import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../providers/providers.dart'; class LoginPage extends ConsumerStatefulWidget { const LoginPage({super.key}); @override ConsumerState createState() => _LoginPageState(); } class _LoginPageState extends ConsumerState { final _formKey = GlobalKey(); final _usernameController = TextEditingController(); final _passwordController = TextEditingController(); bool _isLoading = false; bool _obscurePassword = true; @override void dispose() { _usernameController.dispose(); _passwordController.dispose(); super.dispose(); } Future _handleLogin() async { if (!_formKey.currentState!.validate()) { return; } setState(() { _isLoading = true; }); final authService = ref.read(authServiceProvider); final result = await authService.login( username: _usernameController.text.trim(), password: _passwordController.text, ); if (!mounted) return; setState(() { _isLoading = false; }); result.when( success: (token) { // ignore: unused_result ref.refresh(isAuthenticatedProvider); }, onError: (error) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(error), backgroundColor: Theme.of(context).colorScheme.error, ), ); }, cancelled: () {}, ); } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: SingleChildScrollView( padding: const EdgeInsets.all(24.0), child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 400), child: Form( key: _formKey, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Icon( Icons.local_shipping, size: 80, color: Theme.of(context).colorScheme.primary, ), const SizedBox(height: 24), Text( 'Plan B Logistics', textAlign: TextAlign.center, style: Theme.of(context).textTheme.displayMedium?.copyWith( color: Theme.of(context).colorScheme.primary, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 8), Text( 'Delivery Management System', textAlign: TextAlign.center, style: Theme.of(context).textTheme.bodyLarge?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), const SizedBox(height: 48), TextFormField( controller: _usernameController, decoration: const InputDecoration( labelText: 'Username', hintText: 'Enter your username', prefixIcon: Icon(Icons.person), border: OutlineInputBorder(), ), textInputAction: TextInputAction.next, enabled: !_isLoading, validator: (value) { if (value == null || value.trim().isEmpty) { return 'Please enter your username'; } return null; }, ), const SizedBox(height: 16), TextFormField( controller: _passwordController, decoration: InputDecoration( labelText: 'Password', hintText: 'Enter your password', prefixIcon: const Icon(Icons.lock), border: const OutlineInputBorder(), suffixIcon: IconButton( icon: Icon( _obscurePassword ? Icons.visibility : Icons.visibility_off, ), onPressed: () { setState(() { _obscurePassword = !_obscurePassword; }); }, ), ), obscureText: _obscurePassword, textInputAction: TextInputAction.done, enabled: !_isLoading, onFieldSubmitted: (_) => _handleLogin(), validator: (value) { if (value == null || value.isEmpty) { return 'Please enter your password'; } return null; }, ), const SizedBox(height: 24), FilledButton( onPressed: _isLoading ? null : _handleLogin, style: FilledButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 16), ), child: _isLoading ? SizedBox( height: 20, width: 20, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( Theme.of(context).colorScheme.primary, ), ), ) : const Text('Login'), ), ], ), ), ), ), ), ); } }