Merge branch 'login-fix' into 'master'
Refactor: refactor login functionality to accept credential (email or NISN)... See merge request profile-image/kedaireka/polinema-adapative-learning/mobile-adaptive-learning!21
This commit is contained in:
commit
7fcd5639ae
|
|
@ -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);
|
setLoading(true);
|
||||||
_errorCode = null;
|
_errorCode = null;
|
||||||
try {
|
try {
|
||||||
final response = await _userRepository.loginUser({
|
final loginData = {'IDENTIFIER': credential, 'PASSWORD': password};
|
||||||
'EMAIL': email,
|
|
||||||
'PASSWORD': password,
|
final response = await _userRepository.loginUser(loginData);
|
||||||
});
|
|
||||||
|
|
||||||
_errorCode = response.statusCode;
|
_errorCode = response.statusCode;
|
||||||
|
|
||||||
|
|
@ -93,7 +96,6 @@ class UserProvider with ChangeNotifier {
|
||||||
await refreshUserData();
|
await refreshUserData();
|
||||||
return true;
|
return true;
|
||||||
} else if (response.statusCode == 403) {
|
} else if (response.statusCode == 403) {
|
||||||
// Khusus untuk error 403 (user belum divalidasi)
|
|
||||||
print('User is not validated: ${response.data['message']}');
|
print('User is not validated: ${response.data['message']}');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,22 +19,29 @@ class SigninScreen extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SigninScreenState extends State<SigninScreen> {
|
class _SigninScreenState extends State<SigninScreen> {
|
||||||
final TextEditingController _emailController = TextEditingController();
|
final TextEditingController _loginController = TextEditingController();
|
||||||
final TextEditingController _passwordController = TextEditingController();
|
final TextEditingController _passwordController = TextEditingController();
|
||||||
final FocusNode _emailFocus = FocusNode();
|
final FocusNode _loginFocus = FocusNode();
|
||||||
final FocusNode _passwordFocus = FocusNode();
|
final FocusNode _passwordFocus = FocusNode();
|
||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
context.read<ValidatorProvider>().setController('login', _loginController);
|
||||||
|
context
|
||||||
|
.read<ValidatorProvider>()
|
||||||
|
.setController('password', _passwordController);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_emailController.dispose();
|
context.read<ValidatorProvider>().removeController('login');
|
||||||
|
context.read<ValidatorProvider>().removeController('password');
|
||||||
|
|
||||||
|
_loginController.dispose();
|
||||||
_passwordController.dispose();
|
_passwordController.dispose();
|
||||||
_emailFocus.dispose();
|
_loginFocus.dispose();
|
||||||
_passwordFocus.dispose();
|
_passwordFocus.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
@ -46,9 +53,12 @@ class _SigninScreenState extends State<SigninScreen> {
|
||||||
final validatorProvider = context.read<ValidatorProvider>();
|
final validatorProvider = context.read<ValidatorProvider>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
final loginCredential = _loginController.text.trim();
|
||||||
|
final password = _passwordController.text;
|
||||||
|
|
||||||
final isSuccess = await userProvider.login(
|
final isSuccess = await userProvider.login(
|
||||||
email: _emailController.text.trim(),
|
credential: loginCredential,
|
||||||
password: _passwordController.text,
|
password: password,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
|
|
@ -73,8 +83,6 @@ class _SigninScreenState extends State<SigninScreen> {
|
||||||
|
|
||||||
// Reset form
|
// Reset form
|
||||||
validatorProvider.resetFields();
|
validatorProvider.resetFields();
|
||||||
_emailController.clear();
|
|
||||||
_passwordController.clear();
|
|
||||||
} else {
|
} else {
|
||||||
_handleLoginError(context, userProvider.errorCode);
|
_handleLoginError(context, userProvider.errorCode);
|
||||||
}
|
}
|
||||||
|
|
@ -94,10 +102,10 @@ class _SigninScreenState extends State<SigninScreen> {
|
||||||
|
|
||||||
switch (errorCode) {
|
switch (errorCode) {
|
||||||
case 403:
|
case 403:
|
||||||
message = 'Please verify your email first to continue.';
|
message = 'Please verify your account first to continue.';
|
||||||
break;
|
break;
|
||||||
case 401:
|
case 401:
|
||||||
message = 'Invalid email or password. Please try again.';
|
message = 'Invalid credentials. Please try again.';
|
||||||
break;
|
break;
|
||||||
case 429:
|
case 429:
|
||||||
message = 'Too many attempts. Please try again later.';
|
message = 'Too many attempts. Please try again later.';
|
||||||
|
|
@ -107,6 +115,22 @@ class _SigninScreenState extends State<SigninScreen> {
|
||||||
CustomSnackBar.show(context, message: message, isError: true);
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
|
|
@ -158,26 +182,28 @@ class _SigninScreenState extends State<SigninScreen> {
|
||||||
),
|
),
|
||||||
const SizedBox(height: 30),
|
const SizedBox(height: 30),
|
||||||
CustomFieldWidget(
|
CustomFieldWidget(
|
||||||
fieldName: 'email',
|
fieldName: 'login',
|
||||||
controller: _emailController,
|
controller: _loginController,
|
||||||
focusNode: _emailFocus,
|
focusNode: _loginFocus,
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
textInputAction: TextInputAction.next,
|
textInputAction: TextInputAction.next,
|
||||||
labelText: 'Email Address',
|
labelText: 'Email or NISN',
|
||||||
hintText: 'Enter Your Email Address',
|
hintText: 'Enter Email or NISN Number',
|
||||||
keyboardType: TextInputType.emailAddress,
|
keyboardType: TextInputType.emailAddress,
|
||||||
validator: validatorProvider.emailValidator,
|
validator: _validateLogin,
|
||||||
onChanged: (value) =>
|
onChanged: (value) =>
|
||||||
validatorProvider.validateField(
|
context.read<ValidatorProvider>().validateField(
|
||||||
'email',
|
'login',
|
||||||
value?.trim(),
|
value?.trim(),
|
||||||
validator: validatorProvider.emailValidator,
|
validator: _validateLogin,
|
||||||
),
|
),
|
||||||
onFieldSubmitted: (_) {
|
onFieldSubmitted: (_) {
|
||||||
FocusScope.of(context)
|
FocusScope.of(context)
|
||||||
.requestFocus(_passwordFocus);
|
.requestFocus(_passwordFocus);
|
||||||
},
|
},
|
||||||
errorText: validatorProvider.getError('email'),
|
errorText: context
|
||||||
|
.read<ValidatorProvider>()
|
||||||
|
.getError('login'),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 14),
|
const SizedBox(height: 14),
|
||||||
CustomFieldWidget(
|
CustomFieldWidget(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user