import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import '../../services/auth_service.dart'; class LoginScreen extends StatefulWidget { const LoginScreen({super.key}); @override State createState() => _LoginScreenState(); } class _LoginScreenState extends State { final _formKey = GlobalKey(); final _emailCtrl = TextEditingController(); final _passCtrl = TextEditingController(); final _authService = AuthService(); bool _loading = false; bool _obscurePass = true; @override void dispose() { _emailCtrl.dispose(); _passCtrl.dispose(); super.dispose(); } Future _submit() async { if (!_formKey.currentState!.validate()) return; setState(() => _loading = true); final error = await _authService.login( _emailCtrl.text.trim(), _passCtrl.text, ); if (!mounted) return; setState(() => _loading = false); if (error != null) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(error), behavior: SnackBarBehavior.floating, backgroundColor: Theme.of(context).colorScheme.error, ), ); } else { context.go('/dashboard'); } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Theme.of(context).colorScheme.surfaceContainerLowest, body: Center( child: SingleChildScrollView( padding: const EdgeInsets.all(24), child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 420), child: Card( elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(24), side: BorderSide( color: Theme.of(context).colorScheme.outlineVariant, ), ), child: Padding( padding: const EdgeInsets.symmetric( horizontal: 36, vertical: 48, ), child: Form( key: _formKey, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // Logo / título Icon( Icons.sports, size: 56, color: Theme.of(context).colorScheme.primary, ), const SizedBox(height: 16), Text( 'DeporOS', textAlign: TextAlign.center, style: Theme.of(context) .textTheme .headlineMedium ?.copyWith( fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.primary, ), ), const SizedBox(height: 8), Text( 'Panel de administración', textAlign: TextAlign.center, style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: Theme.of(context) .colorScheme .onSurfaceVariant, ), ), const SizedBox(height: 40), // Email TextFormField( controller: _emailCtrl, keyboardType: TextInputType.emailAddress, textInputAction: TextInputAction.next, decoration: const InputDecoration( labelText: 'Email', prefixIcon: Icon(Icons.email_outlined), border: OutlineInputBorder(), ), validator: (v) { if (v == null || v.trim().isEmpty) { return 'Introduce tu email'; } if (!v.contains('@')) return 'Email no válido'; return null; }, ), const SizedBox(height: 16), // Contraseña TextFormField( controller: _passCtrl, obscureText: _obscurePass, textInputAction: TextInputAction.done, onFieldSubmitted: (_) => _submit(), decoration: InputDecoration( labelText: 'Contraseña', prefixIcon: const Icon(Icons.lock_outlined), border: const OutlineInputBorder(), suffixIcon: IconButton( icon: Icon( _obscurePass ? Icons.visibility_outlined : Icons.visibility_off_outlined, ), onPressed: () => setState(() => _obscurePass = !_obscurePass), ), ), validator: (v) { if (v == null || v.isEmpty) { return 'Introduce tu contraseña'; } return null; }, ), const SizedBox(height: 32), // Botón entrar FilledButton( onPressed: _loading ? null : _submit, style: FilledButton.styleFrom( minimumSize: const Size.fromHeight(52), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: _loading ? const SizedBox( height: 22, width: 22, child: CircularProgressIndicator( strokeWidth: 2.5, color: Colors.white, ), ) : const Text( 'Entrar', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, ), ), ), ], ), ), ), ), ), ), ), ); } }