import 'dart:ui'; import 'package:flutter/material.dart'; import '../main.dart'; import '../theme/app_colors.dart'; /// Branded login screen matching the car64 style. class LoginScreen extends StatefulWidget { const LoginScreen({super.key}); @override State createState() => _LoginScreenState(); } class _LoginScreenState extends State with SingleTickerProviderStateMixin { final _emailController = TextEditingController(); final _passwordController = TextEditingController(); bool _isLoading = false; bool _obscurePassword = true; late final AnimationController _fadeController; late final Animation _fadeAnim; @override void initState() { super.initState(); _fadeController = AnimationController( vsync: this, duration: const Duration(milliseconds: 900), ); _fadeAnim = CurvedAnimation( parent: _fadeController, curve: Curves.easeOut, ); _fadeController.forward(); } @override void dispose() { _fadeController.dispose(); _emailController.dispose(); _passwordController.dispose(); super.dispose(); } // ── Auth actions ───────────────────────────────────────────────────── Future _signIn() async { final email = _emailController.text.trim(); final password = _passwordController.text; if (email.isEmpty || password.isEmpty) return; setState(() => _isLoading = true); try { await supabase.auth.signInWithPassword( email: email, password: password, ); } on AuthException catch (e) { if (!mounted) return; showGlobalSnackBar(e.message, isError: true); } finally { if (mounted) setState(() => _isLoading = false); } } Future _forgotPassword() async { final email = _emailController.text.trim(); if (email.isEmpty) { showGlobalSnackBar('Enter your email first.'); return; } try { await supabase.auth.resetPasswordForEmail( email, redirectTo: 'hwcollector://login/recovery', ); showGlobalSnackBar('Password reset email sent! Check your inbox.'); } on AuthException catch (e) { showGlobalSnackBar(e.message, isError: true); } } // ── Build ──────────────────────────────────────────────────────────── @override Widget build(BuildContext context) { final bottom = MediaQuery.of(context).viewInsets.bottom; final topPadding = MediaQuery.of(context).padding.top; return Scaffold( body: Stack( fit: StackFit.expand, children: [ // ── Full-screen background image ── Image.asset( 'assets/img/login_bg.jpg', fit: BoxFit.cover, ), // ── Dark overlay for readability ── Container( color: Colors.black.withValues(alpha: 0.45), ), // ── Scrollable content ── SingleChildScrollView( padding: EdgeInsets.only(bottom: bottom), child: ConstrainedBox( constraints: BoxConstraints( minHeight: MediaQuery.of(context).size.height, ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox(height: topPadding + 40), // ── Brand title ── FadeTransition( opacity: _fadeAnim, child: Column( children: [ Container( width: 80, height: 80, decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.15), shape: BoxShape.circle, border: Border.all( color: Colors.white.withValues(alpha: 0.3), width: 2, ), ), child: Padding( padding: const EdgeInsets.all(14), child: Image.asset( 'assets/img/icon_bg_removed.png', fit: BoxFit.contain, errorBuilder: (context, error, stackTrace) => const Icon( Icons.directions_car_filled, size: 44, color: Colors.white, ), ), ), ), const SizedBox(height: 16), const Text( 'CAR64', style: TextStyle( fontSize: 26, fontWeight: FontWeight.w700, color: Colors.white, letterSpacing: 3, ), ), const SizedBox(height: 6), Text( 'Track your collection', style: TextStyle( fontSize: 14, color: Colors.white.withValues(alpha: 0.8), letterSpacing: 0.5, ), ), ], ), ), const SizedBox(height: 36), // ── Frosted glass form card ── FadeTransition( opacity: _fadeAnim, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: ClipRRect( borderRadius: BorderRadius.circular(24), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 20, sigmaY: 20), child: Container( padding: const EdgeInsets.fromLTRB(24, 32, 24, 24), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.12), borderRadius: BorderRadius.circular(24), border: Border.all( color: Colors.white.withValues(alpha: 0.2), ), ), child: Column( children: [ // Email TextField( controller: _emailController, keyboardType: TextInputType.emailAddress, textInputAction: TextInputAction.next, style: const TextStyle(color: Colors.white), decoration: _glassInputDecoration( label: 'Email', icon: Icons.email_outlined, ), ), const SizedBox(height: 16), // Password TextField( controller: _passwordController, obscureText: _obscurePassword, textInputAction: TextInputAction.done, onSubmitted: (_) => _signIn(), style: const TextStyle(color: Colors.white), decoration: _glassInputDecoration( label: 'Password', icon: Icons.lock_outline, ).copyWith( suffixIcon: IconButton( icon: Icon( _obscurePassword ? Icons.visibility_off_outlined : Icons.visibility_outlined, color: Colors.white70, ), onPressed: () => setState( () => _obscurePassword = !_obscurePassword), ), ), ), const SizedBox(height: 8), // Forgot password Align( alignment: Alignment.centerRight, child: TextButton( onPressed: _forgotPassword, child: Text( 'Forgot Password?', style: TextStyle( color: Colors.white.withValues(alpha: 0.8), fontSize: 13, ), ), ), ), const SizedBox(height: 12), // Sign-in button (gradient) SizedBox( width: double.infinity, height: 52, child: DecoratedBox( decoration: BoxDecoration( gradient: AppColors.brandGradient, borderRadius: BorderRadius.circular(50), boxShadow: [ BoxShadow( color: AppColors.orange .withValues(alpha: 0.4), blurRadius: 16, offset: const Offset(0, 5), ), ], ), child: ElevatedButton( onPressed: _isLoading ? null : _signIn, style: ElevatedButton.styleFrom( backgroundColor: Colors.transparent, shadowColor: Colors.transparent, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50), ), ), child: _isLoading ? const SizedBox( width: 22, height: 22, child: CircularProgressIndicator( strokeWidth: 2.5, color: Colors.white, ), ) : const Text( 'Start Your Engines!', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white, letterSpacing: 0.5, ), ), ), ), ), ], ), ), ), ), ), ), const SizedBox(height: 32), // ── Footer ── Text( '© 2026 car64', style: TextStyle( fontSize: 12, color: Colors.white.withValues(alpha: 0.5), ), ), const SizedBox(height: 24), ], ), ), ), ], ), ); } /// Input decoration styled for the frosted-glass card. InputDecoration _glassInputDecoration({ required String label, required IconData icon, }) { return InputDecoration( labelText: label, labelStyle: TextStyle(color: Colors.white.withValues(alpha: 0.7)), prefixIcon: Icon(icon, color: Colors.white70), filled: true, fillColor: Colors.white.withValues(alpha: 0.08), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(14), borderSide: BorderSide(color: Colors.white.withValues(alpha: 0.15)), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(14), borderSide: const BorderSide(color: AppColors.orange, width: 2), ), ); } } // _GradientHeader is no longer needed — removed.