import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:dio/dio.dart'; import '../../core/theme/app_theme.dart'; import '../../core/widgets/app_widgets.dart'; import '../../core/services/auth_controller.dart'; import '../../core/models/auth_state.dart'; class LoginPage extends ConsumerStatefulWidget { const LoginPage({super.key}); @override ConsumerState createState() => _LoginPageState(); } class _LoginPageState extends ConsumerState { final _formKey = GlobalKey(); final _emailCtrl = TextEditingController(); final _passCtrl = TextEditingController(); bool _obscurePass = true; @override void initState() { super.initState(); ref.listenManual>(authControllerProvider, ( prev, next, ) { if (!mounted) return; if (next is AsyncError) { String errorMessage = 'Ocurrió un error inesperado'; final error = next.error; if (error is DioException) { if (error.response?.data != null && error.response?.data is Map) { errorMessage = error.response!.data['detail'] ?? 'Credenciales inválidas'; } else { errorMessage = 'Error de conexión con el servidor'; } } else { errorMessage = error.toString(); } ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(errorMessage), backgroundColor: AppTheme.danger, behavior: SnackBarBehavior.floating, ), ); } }); } @override void dispose() { _emailCtrl.dispose(); _passCtrl.dispose(); super.dispose(); } Future _submit() async { if (!(_formKey.currentState?.validate() ?? false)) return; await ref .read(authControllerProvider.notifier) .login(email: _emailCtrl.text.trim(), password: _passCtrl.text); } @override Widget build(BuildContext context) { final loading = ref.watch(authControllerProvider).isLoading; return Scaffold( backgroundColor: AppTheme.background, appBar: AppBar( backgroundColor: Colors.transparent, elevation: 0, iconTheme: const IconThemeData(color: AppTheme.textPrimary), title: const Text( 'Iniciar sesión', style: TextStyle(color: AppTheme.textPrimary, fontSize: 16), ), ), body: SafeArea( child: SingleChildScrollView( padding: const EdgeInsets.all(24), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 8), // ── Encabezado ────────────────────────────────────────── Row( children: [ Container( width: 48, height: 48, decoration: BoxDecoration( color: AppTheme.primaryLight, borderRadius: BorderRadius.circular(AppTheme.radiusMd), ), child: const Icon( Icons.delete_outline_rounded, color: AppTheme.primary, size: 26, ), ), const SizedBox(width: 14), const Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Recolecta', style: TextStyle( fontSize: 20, fontWeight: FontWeight.w700, color: AppTheme.textPrimary, ), ), Text( 'Bienvenido de nuevo', style: TextStyle( fontSize: 13, color: AppTheme.textSecondary, ), ), ], ), ], ), const SizedBox(height: 32), // ── Formulario ────────────────────────────────────────── AppFormField( label: 'Correo electrónico', hint: 'tu@correo.com', controller: _emailCtrl, keyboardType: TextInputType.emailAddress, validator: (v) => (v == null || v.trim().isEmpty) ? 'Ingresa tu correo' : null, ), const SizedBox(height: 16), AppFormField( label: 'Contraseña', hint: '••••••••', controller: _passCtrl, obscureText: _obscurePass, validator: (v) => (v == null || v.length < 6) ? 'Mínimo 6 caracteres' : null, suffix: IconButton( icon: Icon( _obscurePass ? Icons.visibility_outlined : Icons.visibility_off_outlined, size: 18, color: AppTheme.textSecondary, ), onPressed: () => setState(() => _obscurePass = !_obscurePass), ), ), const SizedBox(height: 10), Align( alignment: Alignment.centerRight, child: TextButton( onPressed: () {}, style: TextButton.styleFrom( foregroundColor: AppTheme.primary, ), child: const Text( '¿Olvidaste tu contraseña?', style: TextStyle(fontSize: 13), ), ), ), const SizedBox(height: 24), // ── Botón ─────────────────────────────────────────────── SizedBox( width: double.infinity, height: 52, child: ElevatedButton( onPressed: loading ? null : _submit, child: AnimatedSwitcher( duration: const Duration(milliseconds: 200), child: loading ? const SizedBox( key: ValueKey('loading'), width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.white, ), ) : const Text('Ingresar', key: ValueKey('text')), ), ), ), const SizedBox(height: 36), // ── Crear cuenta ──────────────────────────────────────── Center( child: Row( mainAxisSize: MainAxisSize.min, children: [ const Text( '¿No tienes cuenta? ', style: TextStyle( fontSize: 13, color: AppTheme.textSecondary, ), ), GestureDetector( onTap: () => context.go('/register'), child: const Text( 'Regístrate', style: TextStyle( fontSize: 13, fontWeight: FontWeight.w600, color: AppTheme.primary, ), ), ), ], ), ), ], ), ), ), ), ); } }