184 lines
5.7 KiB
TypeScript
184 lines
5.7 KiB
TypeScript
import { Box, Typography } from '@mui/material';
|
|
import { useEffect, useState } from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { PersonalInfoFields } from './PersonalInfoFields';
|
|
import { PasswordSection } from './PasswordSection';
|
|
import { EmailSection } from './EmailSection';
|
|
import { SubmitSection } from './SubmitSection';
|
|
|
|
export function UserCompletionForm() {
|
|
const { t } = useTranslation('completionForm');
|
|
const [sex, setSex] = useState('');
|
|
const [country, setCountry] = useState('');
|
|
const [showPasswordSection, setShowPasswordSection] = useState(false);
|
|
const [password, setPassword] = useState('');
|
|
const [confirmPassword, setConfirmPassword] = useState('');
|
|
const [showEmail, setShowEmail] = useState(false);
|
|
const [email, setEmail] = useState('');
|
|
const [codeSent, setCodeSent] = useState(false);
|
|
const [verificationCode, setVerificationCode] = useState('');
|
|
const [buttonState, setButtonState] = useState<
|
|
'default' | 'counting' | 'sent'
|
|
>('default');
|
|
const [countdown, setCountdown] = useState(60);
|
|
const [emailVerified, setEmailVerified] = useState(false);
|
|
const [isVerifyingCode, setIsVerifyingCode] = useState(false);
|
|
|
|
const matchPassword = password === confirmPassword;
|
|
const hasNumber = /\d/.test(password);
|
|
const hasMinLength = password.length >= 8;
|
|
const hasUpperAndLower = /[A-Z]/.test(password) && /[a-z]/.test(password);
|
|
const hasSpecialChar = /[!@#$%^&*]/.test(password);
|
|
const validPassword =
|
|
hasNumber && hasMinLength && hasUpperAndLower && hasSpecialChar;
|
|
const [showPasswordValidations, setShowPasswordValidations] = useState(false);
|
|
const correctEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
|
|
|
|
useEffect(() => {
|
|
if (password) {
|
|
if (!validPassword) {
|
|
setShowPasswordValidations(true);
|
|
} else {
|
|
const timer = setTimeout(() => setShowPasswordValidations(false), 1000);
|
|
return () => clearTimeout(timer);
|
|
}
|
|
} else {
|
|
setShowPasswordValidations(false);
|
|
}
|
|
}, [password, validPassword]);
|
|
|
|
useEffect(() => {
|
|
let timer: ReturnType<typeof setInterval>;
|
|
if (buttonState === 'counting' && countdown > 0) {
|
|
timer = setInterval(() => {
|
|
setCountdown((prev) => prev - 1);
|
|
}, 1000);
|
|
}
|
|
if (countdown === 0) {
|
|
setButtonState('default');
|
|
}
|
|
return () => clearInterval(timer);
|
|
}, [buttonState, countdown]);
|
|
|
|
const toPersianDigits = (str: string) =>
|
|
str.replace(/\d/g, (d: string) => '۰۱۲۳۴۵۶۷۸۹'[parseInt(d)]);
|
|
|
|
const getButtonLabel = () => {
|
|
if (buttonState === 'sent') return t('completion.sent');
|
|
if (buttonState === 'counting') {
|
|
const minutes = String(Math.floor(countdown / 60)).padStart(2, '0');
|
|
const seconds = String(countdown % 60).padStart(2, '0');
|
|
return toPersianDigits(`${minutes}:${seconds}`);
|
|
}
|
|
return t('completion.vericationCodeButton');
|
|
};
|
|
|
|
const handleSendCode = () => {
|
|
setCodeSent(true);
|
|
setButtonState('sent');
|
|
setTimeout(() => {
|
|
setButtonState('counting');
|
|
setCountdown(60);
|
|
}, 500);
|
|
};
|
|
|
|
const handleVerifyCode = () => {
|
|
setIsVerifyingCode(true);
|
|
setTimeout(() => {
|
|
setIsVerifyingCode(false);
|
|
setEmailVerified(true);
|
|
}, 500);
|
|
};
|
|
|
|
const handleEditEmail = () => {
|
|
setButtonState('default');
|
|
setCodeSent(false);
|
|
setEmailVerified(false);
|
|
};
|
|
|
|
return (
|
|
<Box
|
|
sx={{
|
|
backgroundColor: 'background.default',
|
|
display: 'flex',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
p: { xs: 1, sm: 2, md: 3 },
|
|
}}
|
|
>
|
|
<Box
|
|
sx={{
|
|
width: '100%',
|
|
maxWidth: '730px',
|
|
backgroundColor: 'background.paper',
|
|
border: '1px solid #ccc',
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
gap: 2,
|
|
px: { xs: 2, sm: 4, md: 6 },
|
|
py: { xs: 3, sm: 4 },
|
|
}}
|
|
>
|
|
<Box
|
|
sx={{
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
width: '100%',
|
|
gap: 1,
|
|
}}
|
|
>
|
|
<Typography variant="h5" color="text.primary">
|
|
{t('completion.title')}
|
|
</Typography>
|
|
<Typography variant="body2" color="text.secondary">
|
|
{t('completion.description')}
|
|
</Typography>
|
|
</Box>
|
|
|
|
<PersonalInfoFields
|
|
sex={sex}
|
|
setSex={setSex}
|
|
country={country}
|
|
setCountry={setCountry}
|
|
/>
|
|
|
|
<PasswordSection
|
|
showPasswordSection={showPasswordSection}
|
|
setShowPasswordSection={setShowPasswordSection}
|
|
password={password}
|
|
setPassword={setPassword}
|
|
confirmPassword={confirmPassword}
|
|
setConfirmPassword={setConfirmPassword}
|
|
matchPassword={matchPassword}
|
|
hasNumber={hasNumber}
|
|
hasMinLength={hasMinLength}
|
|
hasUpperAndLower={hasUpperAndLower}
|
|
hasSpecialChar={hasSpecialChar}
|
|
validPassword={validPassword}
|
|
showValidations={showPasswordValidations}
|
|
/>
|
|
|
|
<EmailSection
|
|
showEmail={showEmail}
|
|
setShowEmail={setShowEmail}
|
|
email={email}
|
|
setEmail={setEmail}
|
|
correctEmail={correctEmail}
|
|
codeSent={codeSent}
|
|
verificationCode={verificationCode}
|
|
setVerificationCode={setVerificationCode}
|
|
buttonState={buttonState}
|
|
getButtonLabel={getButtonLabel}
|
|
handleSendCode={handleSendCode}
|
|
handleVerifyCode={handleVerifyCode}
|
|
emailVerified={emailVerified}
|
|
isVerifyingCode={isVerifyingCode}
|
|
handleEditEmail={handleEditEmail}
|
|
/>
|
|
|
|
<SubmitSection />
|
|
</Box>
|
|
</Box>
|
|
);
|
|
}
|