import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../providers/auth_provider.dart'; import '../../../core/theme/app_colors.dart'; import '../../../core/theme/app_theme.dart'; import '../../../core/widgets/components/ui_components.dart'; class LoginScreen extends ConsumerStatefulWidget { const LoginScreen({super.key}); @override ConsumerState createState() => _LoginScreenState(); } class _LoginScreenState extends ConsumerState { final _formKey = GlobalKey(); final _usernameController = TextEditingController(); final _passwordController = TextEditingController(); bool _obscurePassword = true; @override void dispose() { _usernameController.dispose(); _passwordController.dispose(); super.dispose(); } Future _handleLogin() async { if (!_formKey.currentState!.validate()) return; final auth = ref.read(authProvider.notifier); final success = await auth.login( _usernameController.text.trim(), _passwordController.text, ); if (success && mounted) { context.go('/playlists'); } } @override Widget build(BuildContext context) { final authState = ref.watch(authProvider); return Scaffold( backgroundColor: AppColors.background, body: Stack( children: [ // Ambient background glow (Subtle) Positioned( top: -100, left: -100, child: Container( width: 500, height: 500, decoration: BoxDecoration( shape: BoxShape.circle, gradient: RadialGradient( colors: [ AppColors.primary.withOpacity(0.15), Colors.transparent, ], radius: 0.6, ), ), ), ), // Main content Center( child: SingleChildScrollView( padding: const EdgeInsets.all(24.0), child: Container( constraints: const BoxConstraints(maxWidth: 400), child: Column( mainAxisSize: MainAxisSize.min, children: [ // Logo and title Container( width: 80, height: 80, decoration: BoxDecoration( color: AppColors.surface, borderRadius: BorderRadius.circular(20), border: Border.all(color: AppColors.border), boxShadow: [ BoxShadow( color: AppColors.primary.withOpacity(0.2), blurRadius: 30, offset: const Offset(0, 10), ), ], ), child: const Icon( Icons.live_tv, color: AppColors.primary, size: 40, ), ), const SizedBox(height: 24), const Text( 'XtremFlow', style: TextStyle( fontSize: 32, fontWeight: FontWeight.w800, color: AppColors.textPrimary, letterSpacing: -0.5, ), ), const SizedBox(height: 8), const Text( 'Cinematic Experience', style: TextStyle( fontSize: 14, color: AppColors.textSecondary, letterSpacing: 2, fontWeight: FontWeight.w500, ), ), const SizedBox(height: 48), // Login form GlassCard( padding: const EdgeInsets.all(32), borderRadius: 16, showBorder: true, child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text( 'Welcome Back', style: Theme.of(context).textTheme.headlineSmall?.copyWith( fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), const SizedBox(height: 32), TextFormField( controller: _usernameController, style: const TextStyle(color: Colors.white), decoration: InputDecoration( labelText: 'Username', labelStyle: const TextStyle(color: Colors.white70), prefixIcon: const Icon(Icons.person_outline, color: Colors.white70), filled: true, fillColor: Colors.white.withOpacity(0.05), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.white.withOpacity(0.1)), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.white.withOpacity(0.1)), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: AppColors.primary), ), ), validator: (value) { if (value == null || value.trim().isEmpty) { return 'Username required'; } return null; }, autofocus: true, textInputAction: TextInputAction.next, ), const SizedBox(height: 16), TextFormField( controller: _passwordController, obscureText: _obscurePassword, style: const TextStyle(color: Colors.white), decoration: InputDecoration( labelText: 'Password', labelStyle: const TextStyle(color: Colors.white70), prefixIcon: const Icon(Icons.lock_outline, color: Colors.white70), filled: true, fillColor: Colors.white.withOpacity(0.05), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.white.withOpacity(0.1)), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.white.withOpacity(0.1)), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: AppColors.primary), ), suffixIcon: IconButton( icon: Icon( _obscurePassword ? Icons.visibility_outlined : Icons.visibility_off_outlined, color: Colors.white70, ), onPressed: () { setState(() { _obscurePassword = !_obscurePassword; }); }, ), ), validator: (value) { if (value == null || value.isEmpty) { return 'Password required'; } return null; }, textInputAction: TextInputAction.done, onFieldSubmitted: (_) => _handleLogin(), ), if (authState.errorMessage != null) ...[ const SizedBox(height: 24), Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: AppColors.error.withOpacity(0.1), borderRadius: BorderRadius.circular(8), border: Border.all( color: AppColors.error.withOpacity(0.3), ), ), child: Row( children: [ Icon( Icons.error_outline, color: AppColors.error, size: 20, ), const SizedBox(height: 8), Expanded( child: Text( authState.errorMessage!, style: const TextStyle( color: AppColors.error, fontSize: 13, ), ), ), ], ), ), ], const SizedBox(height: 32), GradientButton( label: 'Sign In', icon: Icons.arrow_forward, isLoading: authState.isLoading, isExpanded: true, onPressed: _handleLogin, ), ], ), ), ), const SizedBox(height: 24), const Text( 'Default: admin / admin', style: TextStyle( fontSize: 12, color: AppColors.textTertiary, fontStyle: FontStyle.italic, ), textAlign: TextAlign.center, ), ], ), ), ), ), ], ), ); } }