import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; import '../../../../core/theme/app_colors.dart'; import '../bloc/auth_bloc.dart'; /// Clean, ADHD-friendly login screen. /// /// Minimal fields, large touch targets, clear labels, calming tone. class LoginScreen extends StatefulWidget { const LoginScreen({super.key}); @override State createState() => _LoginScreenState(); } class _LoginScreenState extends State { final _formKey = GlobalKey(); final _emailController = TextEditingController(); final _passwordController = TextEditingController(); bool _obscurePassword = true; @override void dispose() { _emailController.dispose(); _passwordController.dispose(); super.dispose(); } void _submit() { if (_formKey.currentState?.validate() ?? false) { context.read().add(AuthLoginRequested( email: _emailController.text.trim(), password: _passwordController.text, )); } } @override Widget build(BuildContext context) { final theme = Theme.of(context); return Scaffold( body: BlocListener( listener: (context, state) { if (state is AuthAuthenticated) { context.go('/'); } else if (state is AuthError) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(state.message)), ); } }, child: SafeArea( child: Center( child: SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 24), child: Form( key: _formKey, child: Column( mainAxisSize: MainAxisSize.min, children: [ // ── Logo / Title ───────────────────────────────── Icon(Icons.self_improvement_rounded, size: 64, color: AppColors.primary), const SizedBox(height: 12), Text('FocusFlow', style: theme.textTheme.headlineLarge), const SizedBox(height: 8), Text( 'Welcome back. Let\'s get things done — gently.', style: theme.textTheme.bodyMedium, textAlign: TextAlign.center, ), const SizedBox(height: 40), // ── Email ──────────────────────────────────────── TextFormField( controller: _emailController, keyboardType: TextInputType.emailAddress, textInputAction: TextInputAction.next, decoration: const InputDecoration( labelText: 'Email', prefixIcon: Icon(Icons.email_outlined), ), validator: (v) { if (v == null || v.trim().isEmpty) return 'Email is required'; if (!v.contains('@')) return 'Enter a valid email'; return null; }, ), const SizedBox(height: 16), // ── Password ───────────────────────────────────── TextFormField( controller: _passwordController, obscureText: _obscurePassword, textInputAction: TextInputAction.done, onFieldSubmitted: (_) => _submit(), decoration: InputDecoration( labelText: 'Password', prefixIcon: const Icon(Icons.lock_outline), suffixIcon: IconButton( icon: Icon(_obscurePassword ? Icons.visibility_off_outlined : Icons.visibility_outlined), onPressed: () => setState(() => _obscurePassword = !_obscurePassword), ), ), validator: (v) { if (v == null || v.isEmpty) return 'Password is required'; return null; }, ), const SizedBox(height: 28), // ── Sign in button ─────────────────────────────── BlocBuilder( builder: (context, state) { final loading = state is AuthLoading; return FilledButton( onPressed: loading ? null : _submit, child: loading ? const SizedBox( height: 22, width: 22, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.white, ), ) : const Text('Sign In'), ); }, ), const SizedBox(height: 16), // ── Create account link ────────────────────────── TextButton( onPressed: () => context.go('/signup'), child: const Text('Don\'t have an account? Create one'), ), ], ), ), ), ), ), ), ); } }