Refactor: refactor login functionality to accept credential (email or NISN) instead of email, update UserProvider and SigninScreen accordingly

This commit is contained in:
Naresh Pratista 2024-12-02 10:18:16 +07:00
parent 9f060c1393
commit e886fe6e5d
2 changed files with 56 additions and 28 deletions

View File

@ -68,14 +68,17 @@ class UserProvider with ChangeNotifier {
}
}
Future<bool> login({required String email, required String password}) async {
// In the login method of UserProvider
Future<bool> 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;
}

View File

@ -19,22 +19,29 @@ class SigninScreen extends StatefulWidget {
}
class _SigninScreenState extends State<SigninScreen> {
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<FormState>();
@override
void initState() {
super.initState();
context.read<ValidatorProvider>().setController('login', _loginController);
context
.read<ValidatorProvider>()
.setController('password', _passwordController);
}
@override
void dispose() {
_emailController.dispose();
context.read<ValidatorProvider>().removeController('login');
context.read<ValidatorProvider>().removeController('password');
_loginController.dispose();
_passwordController.dispose();
_emailFocus.dispose();
_loginFocus.dispose();
_passwordFocus.dispose();
super.dispose();
}
@ -46,9 +53,12 @@ class _SigninScreenState extends State<SigninScreen> {
final validatorProvider = context.read<ValidatorProvider>();
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<SigninScreen> {
// Reset form
validatorProvider.resetFields();
_emailController.clear();
_passwordController.clear();
} else {
_handleLoginError(context, userProvider.errorCode);
}
@ -94,10 +102,10 @@ class _SigninScreenState extends State<SigninScreen> {
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<SigninScreen> {
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<ValidatorProvider>().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<SigninScreen> {
),
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<ValidatorProvider>().validateField(
'login',
value?.trim(),
validator: _validateLogin,
),
onFieldSubmitted: (_) {
FocusScope.of(context)
.requestFocus(_passwordFocus);
},
errorText: validatorProvider.getError('email'),
errorText: context
.read<ValidatorProvider>()
.getError('login'),
),
const SizedBox(height: 14),
CustomFieldWidget(