dart format
This commit is contained in:
@@ -42,57 +42,55 @@ class AuthCubit extends Cubit<AuthState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> login(String customerNo, String password) async {
|
||||
emit(AuthLoading());
|
||||
try {
|
||||
final (users, authToken) = await _authRepository.login(customerNo, password);
|
||||
Future<void> login(String customerNo, String password) async {
|
||||
emit(AuthLoading());
|
||||
try {
|
||||
final (users, authToken) =
|
||||
await _authRepository.login(customerNo, password);
|
||||
|
||||
if (authToken.tnc == false) {
|
||||
emit(ShowTncDialog(authToken, users));
|
||||
} else {
|
||||
await _checkMpinAndNavigate(users);
|
||||
}
|
||||
} catch (e) {
|
||||
emit(AuthError(e is AuthException ? e.message : e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
if (authToken.tnc == false) {
|
||||
emit(ShowTncDialog(authToken, users));
|
||||
} else {
|
||||
await _checkMpinAndNavigate(users);
|
||||
}
|
||||
} catch (e) {
|
||||
emit(AuthError(e is AuthException ? e.message : e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> onTncDialogResult(
|
||||
bool agreed, AuthToken authToken, List<User> users) async {
|
||||
if (agreed) {
|
||||
try {
|
||||
await _authRepository.acceptTnc();
|
||||
// The user is NOT fully authenticated yet. Just check for MPIN.
|
||||
await _checkMpinAndNavigate(users);
|
||||
} catch (e) {
|
||||
emit(AuthError('Failed to accept TNC: $e'));
|
||||
}
|
||||
} else {
|
||||
emit(NavigateToTncRequiredScreen());
|
||||
}
|
||||
}
|
||||
Future<void> onTncDialogResult(
|
||||
bool agreed, AuthToken authToken, List<User> users) async {
|
||||
if (agreed) {
|
||||
try {
|
||||
await _authRepository.acceptTnc();
|
||||
// The user is NOT fully authenticated yet. Just check for MPIN.
|
||||
await _checkMpinAndNavigate(users);
|
||||
} catch (e) {
|
||||
emit(AuthError('Failed to accept TNC: $e'));
|
||||
}
|
||||
} else {
|
||||
emit(NavigateToTncRequiredScreen());
|
||||
}
|
||||
}
|
||||
|
||||
void mpinSetupCompleted() {
|
||||
if (state is NavigateToMpinSetupScreen) {
|
||||
final users = (state as NavigateToMpinSetupScreen).users;
|
||||
emit(Authenticated(users));
|
||||
} else {
|
||||
// Handle unexpected state if necessary
|
||||
emit(AuthError("Invalid state during MPIN setup completion."));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Future<void> _checkMpinAndNavigate(List<User> users) async {
|
||||
final mpin = await _secureStorage.read('mpin');
|
||||
if (mpin == null) {
|
||||
// No MPIN, tell UI to navigate to MPIN setup, carrying user data
|
||||
emit(NavigateToMpinSetupScreen(users));
|
||||
} else {
|
||||
// MPIN exists, user is authenticated
|
||||
emit(Authenticated(users));
|
||||
}
|
||||
}
|
||||
if (state is NavigateToMpinSetupScreen) {
|
||||
final users = (state as NavigateToMpinSetupScreen).users;
|
||||
emit(Authenticated(users));
|
||||
} else {
|
||||
// Handle unexpected state if necessary
|
||||
emit(AuthError("Invalid state during MPIN setup completion."));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _checkMpinAndNavigate(List<User> users) async {
|
||||
final mpin = await _secureStorage.read('mpin');
|
||||
if (mpin == null) {
|
||||
// No MPIN, tell UI to navigate to MPIN setup, carrying user data
|
||||
emit(NavigateToMpinSetupScreen(users));
|
||||
} else {
|
||||
// MPIN exists, user is authenticated
|
||||
emit(Authenticated(users));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,13 +46,13 @@ class ShowTncDialog extends AuthState {
|
||||
// States to trigger specific navigations from the UI
|
||||
class NavigateToTncRequiredScreen extends AuthState {}
|
||||
|
||||
class NavigateToMpinSetupScreen extends AuthState {
|
||||
final List<User> users;
|
||||
class NavigateToMpinSetupScreen extends AuthState {
|
||||
final List<User> users;
|
||||
|
||||
const NavigateToMpinSetupScreen(this.users);
|
||||
const NavigateToMpinSetupScreen(this.users);
|
||||
|
||||
@override
|
||||
List<Object> get props => [users];
|
||||
}
|
||||
@override
|
||||
List<Object> get props => [users];
|
||||
}
|
||||
|
||||
class NavigateToDashboardScreen extends AuthState {}
|
||||
class NavigateToDashboardScreen extends AuthState {}
|
||||
|
||||
@@ -14,24 +14,25 @@ class AuthToken extends Equatable {
|
||||
required this.tnc,
|
||||
});
|
||||
|
||||
factory AuthToken.fromJson(Map<String, dynamic> json) {
|
||||
final token = json['token'];
|
||||
factory AuthToken.fromJson(Map<String, dynamic> json) {
|
||||
final token = json['token'];
|
||||
|
||||
// Safely extract tnc.mobile directly from the outer JSON
|
||||
bool tncMobileValue = false; // Default to false if not found or invalid
|
||||
if (json.containsKey('tnc') && json['tnc'] is Map<String, dynamic>) {
|
||||
final tncMap = json['tnc'] as Map<String, dynamic>;
|
||||
if (tncMap.containsKey('mobile') && tncMap['mobile'] is bool) {
|
||||
tncMobileValue = tncMap['mobile'] as bool;
|
||||
// Safely extract tnc.mobile directly from the outer JSON
|
||||
bool tncMobileValue = false; // Default to false if not found or invalid
|
||||
if (json.containsKey('tnc') && json['tnc'] is Map<String, dynamic>) {
|
||||
final tncMap = json['tnc'] as Map<String, dynamic>;
|
||||
if (tncMap.containsKey('mobile') && tncMap['mobile'] is bool) {
|
||||
tncMobileValue = tncMap['mobile'] as bool;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return AuthToken(
|
||||
accessToken: token,
|
||||
expiresAt: _decodeExpiryFromToken(token), // This method is still valid for JWT expiry
|
||||
tnc: tncMobileValue, // Use the correctly extracted value
|
||||
);
|
||||
}
|
||||
return AuthToken(
|
||||
accessToken: token,
|
||||
expiresAt: _decodeExpiryFromToken(
|
||||
token), // This method is still valid for JWT expiry
|
||||
tnc: tncMobileValue, // Use the correctly extracted value
|
||||
);
|
||||
}
|
||||
|
||||
static DateTime _decodeExpiryFromToken(String token) {
|
||||
try {
|
||||
@@ -55,7 +56,7 @@ class AuthToken extends Equatable {
|
||||
return DateTime.now().add(const Duration(hours: 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// static bool _decodeTncFromToken(String token) {
|
||||
// try {
|
||||
// final parts = token.split('.');
|
||||
|
||||
@@ -41,201 +41,201 @@ class LoginScreenState extends State<LoginScreen>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// return Scaffold(
|
||||
// body: BlocConsumer<AuthCubit, AuthState>(
|
||||
// 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<bool>(
|
||||
// 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<AuthCubit>()
|
||||
// .onTncDialogResult(true, state.authToken, state.users);
|
||||
// },
|
||||
// ),
|
||||
// );
|
||||
// return Scaffold(
|
||||
// body: BlocConsumer<AuthCubit, AuthState>(
|
||||
// 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<bool>(
|
||||
// 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<AuthCubit>()
|
||||
// .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<AuthCubit>()
|
||||
// .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).push( // Use push, NOT pushReplacement
|
||||
// MaterialPageRoute(
|
||||
// builder: (_) => MPinScreen(
|
||||
// mode: MPinMode.set,
|
||||
// onCompleted: (_) {
|
||||
// // This clears the entire stack and pushes the dashboard
|
||||
// Navigator.of(context, rootNavigator: true).pushAndRemoveUntil(
|
||||
// MaterialPageRoute(builder: (_) => const NavigationScaffold()),
|
||||
// (route) => false,
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// } 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),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
// );
|
||||
return Scaffold(
|
||||
// // If 'agreed' is false, it means the user clicked 'Disagree'.
|
||||
// if (agreed == false) {
|
||||
// if (!context.mounted) return;
|
||||
// context
|
||||
// .read<AuthCubit>()
|
||||
// .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).push( // Use push, NOT pushReplacement
|
||||
// MaterialPageRoute(
|
||||
// builder: (_) => MPinScreen(
|
||||
// mode: MPinMode.set,
|
||||
// onCompleted: (_) {
|
||||
// // This clears the entire stack and pushes the dashboard
|
||||
// Navigator.of(context, rootNavigator: true).pushAndRemoveUntil(
|
||||
// MaterialPageRoute(builder: (_) => const NavigationScaffold()),
|
||||
// (route) => false,
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// } 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),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
// );
|
||||
return Scaffold(
|
||||
body: BlocConsumer<AuthCubit, AuthState>(
|
||||
listener: (context, state) {
|
||||
if (state is ShowTncDialog) {
|
||||
@@ -255,7 +255,8 @@ class LoginScreenState extends State<LoginScreen>
|
||||
} else if (state is NavigateToTncRequiredScreen) {
|
||||
Navigator.of(context).pushNamed(TncRequiredScreen.routeName);
|
||||
} else if (state is NavigateToMpinSetupScreen) {
|
||||
Navigator.of(context).push( // Use push, NOT pushReplacement
|
||||
Navigator.of(context).push(
|
||||
// Use push, NOT pushReplacement
|
||||
MaterialPageRoute(
|
||||
builder: (_) => MPinScreen(
|
||||
mode: MPinMode.set,
|
||||
|
||||
@@ -185,16 +185,16 @@ class _MPinScreenState extends State<MPinScreen> with TickerProviderStateMixin {
|
||||
),
|
||||
);
|
||||
break;
|
||||
case MPinMode.confirm:
|
||||
if (widget.initialPin == pin) {
|
||||
// 1) persist the pin
|
||||
await storage.write('mpin', pin);
|
||||
case MPinMode.confirm:
|
||||
if (widget.initialPin == pin) {
|
||||
// 1) persist the pin
|
||||
await storage.write('mpin', pin);
|
||||
|
||||
// 2) Call the onCompleted callback to let the parent handle navigation
|
||||
if (mounted) {
|
||||
widget.onCompleted?.call(pin);
|
||||
}
|
||||
} else {
|
||||
// 2) Call the onCompleted callback to let the parent handle navigation
|
||||
if (mounted) {
|
||||
widget.onCompleted?.call(pin);
|
||||
}
|
||||
} else {
|
||||
setState(() {
|
||||
_isError = true;
|
||||
errorText = AppLocalizations.of(context).pinsDoNotMatch;
|
||||
|
||||
@@ -1,39 +1,40 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class TncRequiredScreen extends StatelessWidget { // Renamed class
|
||||
const TncRequiredScreen({Key? key}) : super(key: key);
|
||||
class TncRequiredScreen extends StatelessWidget {
|
||||
// Renamed class
|
||||
const TncRequiredScreen({Key? key}) : super(key: key);
|
||||
|
||||
static const routeName = '/tnc-required';
|
||||
static const routeName = '/tnc-required';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Terms and Conditions'),
|
||||
),
|
||||
body: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Text(
|
||||
'You must accept the Terms and Conditions to use the application.',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 18),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
// This will take the user back to the previous screen
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: const Text('Go Back'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Terms and Conditions'),
|
||||
),
|
||||
body: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Text(
|
||||
'You must accept the Terms and Conditions to use the application.',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 18),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
// This will take the user back to the previous screen
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: const Text('Go Back'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user