import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:kmobile/app.dart'; import 'package:kmobile/features/auth/screens/mpin_screen.dart'; import 'package:kmobile/features/auth/screens/set_password_screen.dart'; import 'package:kmobile/features/auth/screens/tnc_required_screen.dart'; import 'package:kmobile/widgets/tnc_dialog.dart'; import '../../../l10n/app_localizations.dart'; import 'package:flutter/material.dart'; import '../controllers/auth_cubit.dart'; import '../controllers/auth_state.dart'; class LoginScreen extends StatefulWidget { const LoginScreen({super.key}); @override LoginScreenState createState() => LoginScreenState(); } class LoginScreenState extends State with SingleTickerProviderStateMixin { final _formKey = GlobalKey(); final _customerNumberController = TextEditingController(); final _passwordController = TextEditingController(); bool _obscurePassword = true; @override void dispose() { _customerNumberController.dispose(); _passwordController.dispose(); super.dispose(); } void _submitForm() { if (_formKey.currentState!.validate()) { context.read().login( _customerNumberController.text.trim(), _passwordController.text, ); } } @override Widget build(BuildContext context) { return Scaffold( body: BlocConsumer( listener: (context, state) async { if (state is ShowTncDialog) { // The dialog now returns a boolean for the 'disagree' case, // or it completes when the 'proceed' action is finished. final agreed = await showDialog( context: context, barrierDismissible: false, builder: (dialogContext) => TncDialog( onProceed: () async { // This function is passed to the dialog. // It calls the cubit and completes when the cubit's work is done. await context .read() .onTncDialogResult(true, state.authToken, state.users); }, ), ); // If 'agreed' is false, it means the user clicked 'Disagree'. if (agreed == false) { if (!context.mounted) return; context .read() .onTncDialogResult(false, state.authToken, state.users); } } else if (state is NavigateToTncRequiredScreen) { Navigator.of(context).pushNamed(TncRequiredScreen.routeName); } else if (state is NavigateToMpinSetupScreen) { Navigator.of(context).pushReplacement( MaterialPageRoute( builder: (_) => MPinScreen( mode: MPinMode.set, onCompleted: (_) { Navigator.of(context, rootNavigator: true).pushReplacement( MaterialPageRoute(builder: (_) => const NavigationScaffold()), ); }, ), ), ); } else if (state is NavigateToDashboardScreen) { Navigator.of(context).pushReplacement( MaterialPageRoute(builder: (_) => const NavigationScaffold()), ); } else if (state is AuthError) { if (state.message == 'MIGRATED_USER_HAS_NO_PASSWORD') { Navigator.of(context).push(MaterialPageRoute( builder: (_) => SetPasswordScreen( customerNo: _customerNumberController.text.trim(), ))); } else { ScaffoldMessenger.of(context) .showSnackBar(SnackBar(content: Text(state.message))); } } }, builder: (context, state) { // The commented out section is removed for clarity, the logic is now above. return Padding( padding: const EdgeInsets.all(24.0), child: Form( key: _formKey, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset( 'assets/images/logo.png', width: 150, height: 150, errorBuilder: (context, error, stackTrace) { return Icon( Icons.account_balance, size: 100, color: Theme.of(context).primaryColor, ); }, ), const SizedBox(height: 16), Text( AppLocalizations.of(context).kccb, style: TextStyle( fontSize: 32, fontWeight: FontWeight.bold, color: Theme.of(context).primaryColor, ), ), const SizedBox(height: 48), TextFormField( controller: _customerNumberController, decoration: InputDecoration( labelText: AppLocalizations.of(context).customerNumber, border: const OutlineInputBorder(), isDense: true, filled: true, fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide( color: Theme.of(context).colorScheme.outline), ), focusedBorder: OutlineInputBorder( borderSide: BorderSide( color: Theme.of(context).colorScheme.primary, width: 2), ), ), keyboardType: TextInputType.number, textInputAction: TextInputAction.next, validator: (value) { if (value == null || value.isEmpty) { return AppLocalizations.of(context).pleaseEnterUsername; } return null; }, ), const SizedBox(height: 24), TextFormField( controller: _passwordController, obscureText: _obscurePassword, textInputAction: TextInputAction.done, onFieldSubmitted: (_) => _submitForm(), decoration: InputDecoration( labelText: AppLocalizations.of(context).password, border: const OutlineInputBorder(), isDense: true, filled: true, fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide( color: Theme.of(context).colorScheme.outline), ), focusedBorder: OutlineInputBorder( borderSide: BorderSide( color: Theme.of(context).colorScheme.primary, width: 2), ), suffixIcon: IconButton( icon: Icon( _obscurePassword ? Icons.visibility : Icons.visibility_off, ), onPressed: () { setState(() { _obscurePassword = !_obscurePassword; }); }, ), ), validator: (value) { if (value == null || value.isEmpty) { return AppLocalizations.of(context).pleaseEnterPassword; } return null; }, ), const SizedBox(height: 24), SizedBox( width: 250, child: ElevatedButton( onPressed: state is AuthLoading ? null : _submitForm, style: ElevatedButton.styleFrom( shape: const StadiumBorder(), padding: const EdgeInsets.symmetric(vertical: 16), backgroundColor: Theme.of(context).scaffoldBackgroundColor, foregroundColor: Theme.of(context).primaryColorDark, side: BorderSide( color: Theme.of(context).colorScheme.outline, width: 1), elevation: 0, ), child: state is AuthLoading ? const CircularProgressIndicator() : Text( AppLocalizations.of(context).login, style: TextStyle( color: Theme.of(context) .colorScheme .onPrimaryContainer), ), ), ), const SizedBox(height: 25), ], ), ), ); }, ), ); } }