|
|
|
|
@@ -1,5 +1,5 @@
|
|
|
|
|
import React, { useEffect, useState } from 'react';
|
|
|
|
|
import { Box, Typography, Button } from '@mui/material';
|
|
|
|
|
import { useEffect, useState } from 'react';
|
|
|
|
|
import { Box, Typography } from '@mui/material';
|
|
|
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
|
import Logo from '@/components/Logo';
|
|
|
|
|
import { PersonalInfoFields } from './PersonalInfoFields';
|
|
|
|
|
@@ -7,7 +7,7 @@ import { PasswordSection } from './PasswordSection';
|
|
|
|
|
import { EmailSection } from './EmailSection';
|
|
|
|
|
import { SubmitSection } from './SubmitSection';
|
|
|
|
|
import apiClient from '@/lib/apiClient';
|
|
|
|
|
import { sendEmailOtp, fetchAuthToken } from '@/lib/authToken';
|
|
|
|
|
import { Toast } from '@/components/Toast';
|
|
|
|
|
|
|
|
|
|
export function UserCompletionForm() {
|
|
|
|
|
const { t } = useTranslation('completionForm');
|
|
|
|
|
@@ -48,6 +48,15 @@ export function UserCompletionForm() {
|
|
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
|
const [success, setSuccess] = useState(false);
|
|
|
|
|
const [showSuccessToast, setShowSuccessToast] = useState(false);
|
|
|
|
|
const [showErrorToast, setShowErrorToast] = useState(false);
|
|
|
|
|
const [toastMessage, setToastMessage] = useState('');
|
|
|
|
|
|
|
|
|
|
const [showVerifyCodeSectionSuccess, setShowVerifyCodeSectionSuccess] =
|
|
|
|
|
useState(false);
|
|
|
|
|
const [showVerifyCodeSectionError, setShowVerifyCodeSectionError] =
|
|
|
|
|
useState(false);
|
|
|
|
|
const [sentVerificationCode, setSentVerificationCode] = useState('');
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (password) {
|
|
|
|
|
@@ -65,18 +74,16 @@ export function UserCompletionForm() {
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
let timer: NodeJS.Timeout;
|
|
|
|
|
if (buttonState === 'counting' && countdown > 0) {
|
|
|
|
|
timer = setInterval(
|
|
|
|
|
() =>
|
|
|
|
|
setCountdown((prev) => {
|
|
|
|
|
if (prev <= 1) {
|
|
|
|
|
setButtonState('default');
|
|
|
|
|
clearInterval(timer);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return prev - 1;
|
|
|
|
|
}),
|
|
|
|
|
1000,
|
|
|
|
|
);
|
|
|
|
|
timer = setInterval(() => {
|
|
|
|
|
setCountdown((prev) => {
|
|
|
|
|
if (prev <= 1) {
|
|
|
|
|
setButtonState('default');
|
|
|
|
|
clearInterval(timer);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return prev - 1;
|
|
|
|
|
});
|
|
|
|
|
}, 1000);
|
|
|
|
|
}
|
|
|
|
|
return () => clearInterval(timer);
|
|
|
|
|
}, [buttonState, countdown]);
|
|
|
|
|
@@ -97,29 +104,67 @@ export function UserCompletionForm() {
|
|
|
|
|
setError(null);
|
|
|
|
|
setLoading(true);
|
|
|
|
|
setSuccess(false);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
await sendEmailOtp(EMAIL);
|
|
|
|
|
setSuccess(true);
|
|
|
|
|
} catch {
|
|
|
|
|
setError('Failed to send OTP');
|
|
|
|
|
const response = await apiClient.post('/User/SendEmailOtp', { email });
|
|
|
|
|
if (response.data?.success) {
|
|
|
|
|
setSentVerificationCode(response.data.message);
|
|
|
|
|
setShowVerifyCodeSectionSuccess(true);
|
|
|
|
|
setCodeSent(true);
|
|
|
|
|
setButtonState('counting');
|
|
|
|
|
setCountdown(120);
|
|
|
|
|
setSuccess(true);
|
|
|
|
|
setSentVerificationCode(
|
|
|
|
|
response.data.message || 'کد با موفقیت ارسال شد',
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
setShowVerifyCodeSectionError(true);
|
|
|
|
|
setSentVerificationCode(response.data.message || 'مشکلی پیش آمده');
|
|
|
|
|
// setError(
|
|
|
|
|
// response.data?.message || t('completion.verificationCodeError'),
|
|
|
|
|
// );
|
|
|
|
|
}
|
|
|
|
|
} catch (err: any) {
|
|
|
|
|
setShowVerifyCodeSectionError(true);
|
|
|
|
|
setSentVerificationCode(err.response?.data?.message || 'مشکلی پیش آمده');
|
|
|
|
|
// setError(
|
|
|
|
|
// err.response?.data?.message || t('completion.verificationCodeError'),
|
|
|
|
|
// );
|
|
|
|
|
} finally {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleVerifyCode = async () => {
|
|
|
|
|
if (!verificationCode) return;
|
|
|
|
|
if (!verificationCode.trim()) {
|
|
|
|
|
setError('Please enter the verification code');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setIsVerifyingCode(true);
|
|
|
|
|
setError(null);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const tokenRes = await fetchAuthToken(email, verificationCode);
|
|
|
|
|
localStorage.setItem('authToken', tokenRes.access_token);
|
|
|
|
|
apiClient.defaults.headers.common['Authorization'] =
|
|
|
|
|
`Bearer ${tokenRes.access_token}`;
|
|
|
|
|
setEmailVerified(true);
|
|
|
|
|
} catch {
|
|
|
|
|
setError('Invalid verification code');
|
|
|
|
|
const res = await apiClient.post('/User/ConfirmEmailOtp', {
|
|
|
|
|
email,
|
|
|
|
|
otp: verificationCode,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (res.data?.success) {
|
|
|
|
|
setEmailVerified(true);
|
|
|
|
|
setSuccess(true);
|
|
|
|
|
if (res.data.access_token) {
|
|
|
|
|
localStorage.setItem('authToken', res.data.access_token);
|
|
|
|
|
apiClient.defaults.headers.common['Authorization'] =
|
|
|
|
|
`Bearer ${res.data.access_token}`;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
setError(res.data?.message || 'Invalid verification code');
|
|
|
|
|
}
|
|
|
|
|
} catch (err: any) {
|
|
|
|
|
setError(
|
|
|
|
|
err.response?.data?.message ||
|
|
|
|
|
'Something went wrong while verifying the code',
|
|
|
|
|
);
|
|
|
|
|
} finally {
|
|
|
|
|
setIsVerifyingCode(false);
|
|
|
|
|
}
|
|
|
|
|
@@ -143,6 +188,7 @@ export function UserCompletionForm() {
|
|
|
|
|
message: string;
|
|
|
|
|
validations: { property: string; message: string }[];
|
|
|
|
|
}>('/User/CompleteUserInformation', {
|
|
|
|
|
userId: '9cb8ae51-95f9-4f66-99b4-1c7c4d48251b',
|
|
|
|
|
firstName,
|
|
|
|
|
lastName,
|
|
|
|
|
gender: sex === 'female' ? 2 : 1,
|
|
|
|
|
@@ -155,21 +201,22 @@ export function UserCompletionForm() {
|
|
|
|
|
country,
|
|
|
|
|
});
|
|
|
|
|
if (data.success) {
|
|
|
|
|
setSuccess(true);
|
|
|
|
|
setToastMessage(data.message || t('completion.submitSuccess'));
|
|
|
|
|
setShowSuccessToast(true);
|
|
|
|
|
} else {
|
|
|
|
|
setError(data.message || 'Validation error');
|
|
|
|
|
setToastMessage(data.message || t('completion.submitError'));
|
|
|
|
|
setShowErrorToast(true);
|
|
|
|
|
}
|
|
|
|
|
} catch (err: any) {
|
|
|
|
|
setError(
|
|
|
|
|
err.response?.data?.message || err.message || 'An error occurred',
|
|
|
|
|
setToastMessage(
|
|
|
|
|
err.response?.data?.message || err.message || 'خطای ناشناخته',
|
|
|
|
|
);
|
|
|
|
|
setShowErrorToast(true);
|
|
|
|
|
} finally {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const EMAIL = 'klahouti81@gmail.com';
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Box
|
|
|
|
|
sx={{
|
|
|
|
|
@@ -238,6 +285,21 @@ export function UserCompletionForm() {
|
|
|
|
|
showValidations={showPasswordValidations}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<Toast
|
|
|
|
|
color="success"
|
|
|
|
|
open={showVerifyCodeSectionSuccess}
|
|
|
|
|
onClose={() => setShowVerifyCodeSectionSuccess(false)}
|
|
|
|
|
>
|
|
|
|
|
{sentVerificationCode}
|
|
|
|
|
</Toast>
|
|
|
|
|
|
|
|
|
|
<Toast
|
|
|
|
|
color="error"
|
|
|
|
|
open={showVerifyCodeSectionError}
|
|
|
|
|
onClose={() => setShowVerifyCodeSectionError(false)}
|
|
|
|
|
>
|
|
|
|
|
{sentVerificationCode}
|
|
|
|
|
</Toast>
|
|
|
|
|
<EmailSection
|
|
|
|
|
showEmail={showEmail}
|
|
|
|
|
setShowEmail={setShowEmail}
|
|
|
|
|
@@ -255,10 +317,20 @@ export function UserCompletionForm() {
|
|
|
|
|
isVerifyingCode={isVerifyingCode}
|
|
|
|
|
handleEditEmail={handleEditEmail}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<Button onClick={handleSendCode} variant="contained" disabled={loading}>
|
|
|
|
|
{loading ? 'Sending…' : 'Send OTP'}
|
|
|
|
|
</Button>
|
|
|
|
|
<Toast
|
|
|
|
|
color="success"
|
|
|
|
|
open={showSuccessToast}
|
|
|
|
|
onClose={() => setShowSuccessToast(false)}
|
|
|
|
|
>
|
|
|
|
|
{toastMessage}
|
|
|
|
|
</Toast>
|
|
|
|
|
<Toast
|
|
|
|
|
color="error"
|
|
|
|
|
open={showErrorToast}
|
|
|
|
|
onClose={() => setShowErrorToast(false)}
|
|
|
|
|
>
|
|
|
|
|
{toastMessage}
|
|
|
|
|
</Toast>
|
|
|
|
|
|
|
|
|
|
<SubmitSection
|
|
|
|
|
onSubmit={handleSubmit}
|
|
|
|
|
|