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'; import { PasswordSection } from './PasswordSection'; import { EmailSection } from './EmailSection'; import { SubmitSection } from './SubmitSection'; import { useToast } from '@rkheftan/harmony-ui'; import { regex } from '../../../utils/regex'; import { toLocaleDigits } from '../../../utils/persianDigit'; import i18n from '@/config/i18n'; import { Gender } from '../types/settingForm'; import { useApi } from '@/hooks/useApi'; import { sendEmailOtpApi, confirmEmailOtpApi, completeUserInformationApi, } from '../api/userCompletion'; import { type SendEmailOtpPayload, type ConfirmEmailOtpPayload, type CompleteUserInfoPayload, } from '../types/completionFormApiTypes'; import { type ApiResponse } from '@/types/apiResponse'; export function UserCompletionForm() { const { t } = useTranslation('completionForm'); const showToast = useToast(); const [firstName, setFirstName] = useState(''); const [lastName, setLastName] = useState(''); const [nationalId, setNationalId] = useState(''); const [birthDate, setBirthDate] = useState(null); const [sex, setSex] = useState(Gender.Female); 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 [verificationCode, setVerificationCode] = useState(''); const [codeSent, setCodeSent] = useState(false); const [buttonState, setButtonState] = useState<'default' | 'counting'>( 'default', ); const [countdown, setCountdown] = useState(0); const [emailVerified, setEmailVerified] = useState(false); const [showPasswordValidations, setShowPasswordValidations] = useState(false); const { hasNumber, hasMinLength, hasUpperAndLower, hasSpecialChar, validPassword, correctEmail, } = regex(password, email); const matchPassword = password === confirmPassword; const { execute: sendCode, data: sendCodeData } = useApi( async (payload: SendEmailOtpPayload) => { const result = await sendEmailOtpApi(payload); const conformingResult: ApiResponse = { ...result, errorCode: result.errorCode || 0, validations: [], }; return { data: conformingResult }; }, ); const { execute: verifyCode, loading: isVerifyingCode, data: verifyCodeData, } = useApi(async (payload: ConfirmEmailOtpPayload) => { const result = await confirmEmailOtpApi(payload); const conformingResult: ApiResponse = { ...result, errorCode: result.errorCode || 0, validations: [], }; return { data: conformingResult }; }); const { execute: submitForm, loading: isSubmitting, error: submitError, data: submitData, } = useApi(async (payload: CompleteUserInfoPayload) => { const result = await completeUserInformationApi(payload); const conformingResult: ApiResponse = { ...result, errorCode: result.errorCode || 0, validations: [], }; return { data: conformingResult }; }); const getErrorMessage = (error: unknown): string | null => { if (!error) return null; if (error instanceof Error) return error.message; return String(error); }; useEffect(() => { if (sendCodeData) { if (sendCodeData.success) { showToast({ message: sendCodeData.message || t('completion.successfullCodeSent'), severity: 'success', }); setCodeSent(true); setButtonState('counting'); setCountdown(120); } else { showToast({ message: sendCodeData.message || t('completion.problem'), severity: 'error', }); } } }, [sendCodeData, showToast, t]); useEffect(() => { if (verifyCodeData) { if (verifyCodeData.success) { setEmailVerified(true); showToast({ message: verifyCodeData.message || t('completion.codeVerified'), severity: 'success', }); } else { showToast({ message: verifyCodeData.message || t('completion.invalidCode'), severity: 'error', }); setEmailVerified(false); } } }, [verifyCodeData, showToast, t]); useEffect(() => { if (submitData) { showToast({ message: submitData.message || t( submitData.success ? 'completion.submitSuccess' : 'completion.submitError', ), severity: submitData.success ? 'success' : 'error', }); } else if (submitError) { showToast({ message: getErrorMessage(submitError) || t('completion.problem'), severity: 'error', }); } }, [submitData, submitError, showToast, t]); useEffect(() => { setShowPasswordValidations(password ? !validPassword : false); }, [password, validPassword]); 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); } return () => clearInterval(timer); }, [buttonState, countdown]); const handleSendCode = () => { sendCode({ email }); }; const handleVerifyCode = () => { if (!verificationCode.trim()) { showToast({ message: 'Please enter the verification code', severity: 'warning', }); return; } verifyCode({ email, otpCode: verificationCode }); }; const handleSubmit = () => { submitForm({ userId: '3fa85f64-5717-4562-b3fc-2c963f66afa6', firstName, lastName, gender: sex, nationalId, savePassword: showPasswordSection, password: showPasswordSection ? password : undefined, saveEmail: showEmail, email: showEmail ? email : undefined, birthDate, country, }); }; const getButtonLabel = () => { if (buttonState === 'counting') { const m = String(Math.floor(countdown / 60)).padStart(2, '0'); const s = String(countdown % 60).padStart(2, '0'); return toLocaleDigits(`${m}:${s}`, i18n.language); } return t('completion.vericationCodeButton'); }; const handleEditEmail = () => { setButtonState('default'); setCodeSent(false); setEmailVerified(false); setVerificationCode(''); }; return ( {t('completion.title')} {t('completion.description')} ); }