fix: accounts review
This commit is contained in:
@@ -64,10 +64,8 @@ export function UserCompletionPage() {
|
||||
const correctEmail = isEmail(email);
|
||||
|
||||
const { execute: sendCode, loading: isSendingCode } = useApi(sendEmailOtpApi);
|
||||
|
||||
const { execute: verifyCode, loading: isVerifyingCode } =
|
||||
useApi(confirmEmailOtpApi);
|
||||
|
||||
const { execute: submitForm, loading: isSubmitting } = useApi(
|
||||
completeUserInformationApi,
|
||||
);
|
||||
@@ -89,13 +87,30 @@ export function UserCompletionPage() {
|
||||
return () => clearInterval(timer);
|
||||
}, [buttonState, countdown]);
|
||||
|
||||
useEffect(() => {
|
||||
if (buttonState === 'default') {
|
||||
setCodeSent(false);
|
||||
setVerificationCode('');
|
||||
// setEmailVerified(false);
|
||||
setTouched((prev) => {
|
||||
const n = { ...prev };
|
||||
delete n.verificationCode;
|
||||
return n;
|
||||
});
|
||||
setErrors((prev) => {
|
||||
const n = { ...prev };
|
||||
delete n.verificationCode;
|
||||
return n;
|
||||
});
|
||||
}
|
||||
}, [buttonState]);
|
||||
|
||||
const handleSendCode = async () => {
|
||||
if (!isEmail(email)) {
|
||||
setTouched((prev) => ({ ...prev, email: true }));
|
||||
setErrors((prev) => ({ ...prev, email: t('validation.emailInvalid') }));
|
||||
return;
|
||||
}
|
||||
|
||||
setTouched((prev) => {
|
||||
const newTouched = { ...prev };
|
||||
delete newTouched.verificationCode;
|
||||
@@ -106,13 +121,11 @@ export function UserCompletionPage() {
|
||||
delete newErrors.verificationCode;
|
||||
return newErrors;
|
||||
});
|
||||
|
||||
const res = await sendCode({ email });
|
||||
|
||||
if (res) {
|
||||
if (res.success) {
|
||||
showToast({
|
||||
message: res.message || t('completion.successfulCodeSent'),
|
||||
message: t('completion.successfulCodeSent'),
|
||||
severity: 'success',
|
||||
});
|
||||
setCodeSent(true);
|
||||
@@ -129,8 +142,6 @@ export function UserCompletionPage() {
|
||||
|
||||
const handleVerifyCode = async () => {
|
||||
const trimmedCode = verificationCode.trim();
|
||||
|
||||
// Manually trigger the validation error and stop
|
||||
if (!trimmedCode) {
|
||||
setTouched((prev) => ({ ...prev, verificationCode: true }));
|
||||
setErrors((prev) => ({
|
||||
@@ -146,9 +157,7 @@ export function UserCompletionPage() {
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await verifyCode({ email, otpCode: verificationCode });
|
||||
|
||||
if (res) {
|
||||
if (res.success) {
|
||||
setEmailVerified(true);
|
||||
@@ -178,12 +187,10 @@ export function UserCompletionPage() {
|
||||
confirmPassword: showPasswordSection,
|
||||
sex: true,
|
||||
});
|
||||
|
||||
const isValid = validateForm();
|
||||
if (!isValid) {
|
||||
return; // Stop the submission
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await submitForm({
|
||||
firstName,
|
||||
lastName,
|
||||
@@ -196,16 +203,13 @@ export function UserCompletionPage() {
|
||||
birthDate,
|
||||
countryCode: country,
|
||||
});
|
||||
|
||||
if (res) {
|
||||
if (res.success) {
|
||||
showToast({
|
||||
message: res.message || t('completion.submitSuccess'),
|
||||
severity: 'success',
|
||||
});
|
||||
|
||||
const returnUrl = params.get('returnUrl');
|
||||
|
||||
navigate(
|
||||
returnUrl ? `/account-created?returnUrl=${returnUrl}` : '/setting',
|
||||
);
|
||||
@@ -223,7 +227,6 @@ export function UserCompletionPage() {
|
||||
setCodeSent(false);
|
||||
setEmailVerified(false);
|
||||
setVerificationCode('');
|
||||
// We clear both touched and errors
|
||||
setTouched((prev) => {
|
||||
const newTouched = { ...prev };
|
||||
delete newTouched.email;
|
||||
@@ -240,77 +243,49 @@ export function UserCompletionPage() {
|
||||
|
||||
const validateForm = () => {
|
||||
const newErrors: { [key: string]: string } = {};
|
||||
|
||||
// Rule 1: First Name is required
|
||||
if (!firstName.trim())
|
||||
newErrors.firstName = t('validation.firstNameRequired');
|
||||
|
||||
// Rule 2: Last Name is required
|
||||
if (!lastName.trim()) newErrors.lastName = t('validation.lastNameRequired');
|
||||
|
||||
// Rule 3: Country is required
|
||||
if (!country) newErrors.country = t('validation.countryRequired');
|
||||
|
||||
// Rule 4: Email is required and must be valid IF the section is shown
|
||||
if (showEmail && !isEmail(email)) {
|
||||
newErrors.email = t('validation.emailInvalid');
|
||||
}
|
||||
|
||||
// Rule 5: National ID must be 10 digits IF it's not empty
|
||||
if (nationalId && !nationalIdRegex.test(nationalId)) {
|
||||
newErrors.nationalId = t('validation.nationalIdInvalid');
|
||||
}
|
||||
|
||||
// Rule 6: If verification code sent and email section is active
|
||||
if (showEmail && codeSent && !emailVerified) {
|
||||
const trimmedCode = verificationCode.trim();
|
||||
|
||||
if (!trimmedCode) {
|
||||
// Case 1: The code is required but the field is empty.
|
||||
newErrors.verificationCode = t('validation.verificationCodeRequired');
|
||||
} else if (trimmedCode.length < 4) {
|
||||
// Case 2 : The code is entered but is less than 4 digits.
|
||||
newErrors.verificationCode = t('validation.verificationCodeInvalid');
|
||||
} else {
|
||||
// Case 3: The user has typed a code but hasn't clicked "Verify" yet.
|
||||
newErrors.verificationCode = t('validation.mustVerifyCode');
|
||||
}
|
||||
}
|
||||
|
||||
// Rule 7: Password validation
|
||||
if (showPasswordSection) {
|
||||
// Rule 1: Check if the main password is valid
|
||||
if (!password.trim()) {
|
||||
newErrors.password = t('validation.passwordRequired');
|
||||
} else if (!validPassword) {
|
||||
// 'validPassword' is the boolean you already calculate
|
||||
newErrors.password = t('validation.passwordInvalid');
|
||||
}
|
||||
|
||||
// Rule 2: Check if the confirmation password matches
|
||||
if (!confirmPassword.trim()) {
|
||||
newErrors.confirmPassword = t('validation.confirmPasswordRequired');
|
||||
} else if (!matchPassword) {
|
||||
// 'matchPassword' is the boolean you already calculate
|
||||
newErrors.confirmPassword = t('validation.passwordsDoNotMatch');
|
||||
}
|
||||
}
|
||||
|
||||
if (sex === null) {
|
||||
newErrors.sex = t('validation.genderRequired');
|
||||
}
|
||||
|
||||
setErrors(newErrors);
|
||||
return Object.keys(newErrors).length === 0; // Returns true if form is valid
|
||||
return Object.keys(newErrors).length === 0;
|
||||
};
|
||||
|
||||
const handleBlur = (field: string) => {
|
||||
setTouched((prev) => ({ ...prev, [field]: true }));
|
||||
};
|
||||
const handleBlur = (_field: string) => {};
|
||||
|
||||
useEffect(() => {
|
||||
if (!showPasswordSection) {
|
||||
// We clear both touched and errors to prevent lingering validation messages
|
||||
setTouched((prev) => {
|
||||
const newTouched = { ...prev };
|
||||
delete newTouched.password;
|
||||
@@ -326,10 +301,8 @@ export function UserCompletionPage() {
|
||||
}
|
||||
}, [showPasswordSection]);
|
||||
|
||||
// This effect resets email fields when the section is hidden
|
||||
useEffect(() => {
|
||||
if (!showEmail) {
|
||||
// We clear both touched and errors
|
||||
setTouched((prev) => {
|
||||
const newTouched = { ...prev };
|
||||
delete newTouched.email;
|
||||
@@ -345,9 +318,7 @@ export function UserCompletionPage() {
|
||||
}
|
||||
}, [showEmail]);
|
||||
|
||||
// re-validate whenever a field the user has touched changes value
|
||||
useEffect(() => {
|
||||
// Only run validation if at least one field has been touched
|
||||
if (Object.keys(touched).length > 0) {
|
||||
validateForm();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user