diff --git a/lib/features/auth/provider/user_provider.dart b/lib/features/auth/provider/user_provider.dart index 2b22b5d..253f684 100644 --- a/lib/features/auth/provider/user_provider.dart +++ b/lib/features/auth/provider/user_provider.dart @@ -68,14 +68,17 @@ class UserProvider with ChangeNotifier { } } - Future login({required String email, required String password}) async { + // In the login method of UserProvider + Future login({ + required String credential, + required String password, + }) async { setLoading(true); _errorCode = null; try { - final response = await _userRepository.loginUser({ - 'EMAIL': email, - 'PASSWORD': password, - }); + final loginData = {'IDENTIFIER': credential, 'PASSWORD': password}; + + final response = await _userRepository.loginUser(loginData); _errorCode = response.statusCode; @@ -93,7 +96,6 @@ class UserProvider with ChangeNotifier { await refreshUserData(); return true; } else if (response.statusCode == 403) { - // Khusus untuk error 403 (user belum divalidasi) print('User is not validated: ${response.data['message']}'); return false; } diff --git a/lib/features/auth/screens/signin/signin_screen.dart b/lib/features/auth/screens/signin/signin_screen.dart index fce3178..8c33f79 100644 --- a/lib/features/auth/screens/signin/signin_screen.dart +++ b/lib/features/auth/screens/signin/signin_screen.dart @@ -19,22 +19,29 @@ class SigninScreen extends StatefulWidget { } class _SigninScreenState extends State { - final TextEditingController _emailController = TextEditingController(); + final TextEditingController _loginController = TextEditingController(); final TextEditingController _passwordController = TextEditingController(); - final FocusNode _emailFocus = FocusNode(); + final FocusNode _loginFocus = FocusNode(); final FocusNode _passwordFocus = FocusNode(); final _formKey = GlobalKey(); @override void initState() { super.initState(); + context.read().setController('login', _loginController); + context + .read() + .setController('password', _passwordController); } @override void dispose() { - _emailController.dispose(); + context.read().removeController('login'); + context.read().removeController('password'); + + _loginController.dispose(); _passwordController.dispose(); - _emailFocus.dispose(); + _loginFocus.dispose(); _passwordFocus.dispose(); super.dispose(); } @@ -46,9 +53,12 @@ class _SigninScreenState extends State { final validatorProvider = context.read(); try { + final loginCredential = _loginController.text.trim(); + final password = _passwordController.text; + final isSuccess = await userProvider.login( - email: _emailController.text.trim(), - password: _passwordController.text, + credential: loginCredential, + password: password, ); if (!mounted) return; @@ -73,8 +83,6 @@ class _SigninScreenState extends State { // Reset form validatorProvider.resetFields(); - _emailController.clear(); - _passwordController.clear(); } else { _handleLoginError(context, userProvider.errorCode); } @@ -94,10 +102,10 @@ class _SigninScreenState extends State { switch (errorCode) { case 403: - message = 'Please verify your email first to continue.'; + message = 'Please verify your account first to continue.'; break; case 401: - message = 'Invalid email or password. Please try again.'; + message = 'Invalid credentials. Please try again.'; break; case 429: message = 'Too many attempts. Please try again later.'; @@ -107,6 +115,22 @@ class _SigninScreenState extends State { CustomSnackBar.show(context, message: message, isError: true); } + String? _validateLogin(String? value) { + if (value == null || value.isEmpty) { + return 'Login credential cannot be empty'; + } + + value = value.trim(); + + if (value.contains('@')) { + return context.read().emailValidator(value); + } else if (RegExp(r'^\d{ 10}$').hasMatch(value)) { + return null; // Valid NISN + } else { + return 'Please enter a valid email or NISN (10 digits)'; + } + } + @override Widget build(BuildContext context) { return GestureDetector( @@ -158,26 +182,28 @@ class _SigninScreenState extends State { ), const SizedBox(height: 30), CustomFieldWidget( - fieldName: 'email', - controller: _emailController, - focusNode: _emailFocus, + fieldName: 'login', + controller: _loginController, + focusNode: _loginFocus, isRequired: true, textInputAction: TextInputAction.next, - labelText: 'Email Address', - hintText: 'Enter Your Email Address', + labelText: 'Email or NISN', + hintText: 'Enter Email or NISN Number', keyboardType: TextInputType.emailAddress, - validator: validatorProvider.emailValidator, + validator: _validateLogin, onChanged: (value) => - validatorProvider.validateField( - 'email', - value?.trim(), - validator: validatorProvider.emailValidator, - ), + context.read().validateField( + 'login', + value?.trim(), + validator: _validateLogin, + ), onFieldSubmitted: (_) { FocusScope.of(context) .requestFocus(_passwordFocus); }, - errorText: validatorProvider.getError('email'), + errorText: context + .read() + .getError('login'), ), const SizedBox(height: 14), CustomFieldWidget(