import 'package:flutter/material.dart'; import '../services/auth_service.dart'; import '../widgets/custom_input_field.dart'; class LoginScreen extends StatefulWidget { const LoginScreen({super.key}); @override State createState() => _LoginScreenState(); } class _LoginScreenState extends State { final _formKey = GlobalKey(); final _userCodeController = TextEditingController(); final _passwordController = TextEditingController(); final _authService = AuthService(); bool _isLoading = false; String? _errorMessage; @override void dispose() { _userCodeController.dispose(); _passwordController.dispose(); super.dispose(); } Future _handleLogin() async { if (!_formKey.currentState!.validate()) return; setState(() { _isLoading = true; _errorMessage = null; }); try { final input = _userCodeController.text.trim(); final parsedUserCode = int.tryParse(input); if (parsedUserCode == null) { throw Exception('User code must be a number'); } final response = await _authService.login( userCode: parsedUserCode, password: _passwordController.text, ); if (mounted) { // Navigate to daily schedule screen Navigator.of(context).pushReplacementNamed('/schedule'); } } catch (e) { if (mounted) { setState(() { _errorMessage = e.toString().replaceAll('Exception: ', ''); }); } } finally { if (mounted) { setState(() => _isLoading = false); } } } String? _validateUserCode(String? value) { final v = value?.trim(); if (v?.isEmpty ?? true) { return 'User code is required'; } if (int.tryParse(v!) == null) { return 'User code must be a number'; } return null; } String? _validatePassword(String? value) { if (value?.isEmpty ?? true) { return 'Password is required'; } if ((value?.length ?? 0) < 3) { return 'Password must be at least 3 characters'; } return null; } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Bus Terminal Login'), elevation: 0, ), body: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(24.0), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const SizedBox(height: 32), // Title Text( 'Driver Login', style: Theme.of(context).textTheme.headlineMedium?.copyWith( fontWeight: FontWeight.bold, ), ), const SizedBox(height: 12), Text( 'Enter your credentials to continue', style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: Colors.grey[600], ), ), const SizedBox(height: 48), // Error message if (_errorMessage != null) Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.red[50], border: Border.all(color: Colors.red[300]!), borderRadius: BorderRadius.circular(8), ), child: Text( _errorMessage!, style: TextStyle( color: Colors.red[700], fontSize: 14, ), ), ), if (_errorMessage != null) const SizedBox(height: 24), // User Code Field CustomInputField( label: 'User Code', hint: 'Enter your user code', controller: _userCodeController, validator: _validateUserCode, ), const SizedBox(height: 24), // Password Field CustomInputField( label: 'Password', hint: 'Enter your password', controller: _passwordController, obscureText: true, validator: _validatePassword, ), const SizedBox(height: 40), // Login Button - Large for touch accessibility FilledButton( onPressed: _isLoading ? null : _handleLogin, style: FilledButton.styleFrom( minimumSize: const Size.fromHeight(56), // Large touch target disabledBackgroundColor: Colors.grey[400], ), child: _isLoading ? const SizedBox( height: 24, width: 24, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Colors.white), ), ) : const Text( 'Login', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), ), ], ), ), ), ), ); } }