fix/ styles and seperate the main file to different components

This commit is contained in:
2025-07-21 16:55:25 +03:30
committed by Koosha Lahouti
parent 31be893d0b
commit 20187c6cbc
8 changed files with 619 additions and 520 deletions

View File

@@ -0,0 +1,30 @@
{
"completion": {
"title": "تکمیل اطلاعات حساب کاربری",
"description": "اطلاعات کسب و کار خود را وارد کنید",
"name": "نام",
"familyName": "نام خانوادگی",
"gender": "جنسیت",
"optionalNationalCode": "کدملی(اختیاری)",
"determinePassword": "تعیین رمز عبور",
"password": "رمز عبور",
"passwordRepetition": "تکرار رمز عبور",
"determineEmail": "اتصال ایمیل خود",
"email": "ایمیل",
"vericationCodeButton": "ارسال کد تایید",
"verificationCode": "کد تایید",
"checkCodeButton": "بررسی کد",
"registerButton": "تایید و ثبت نام",
"man": "مرد",
"woman": "زن",
"hasNumber": "شامل عدد",
"hasMinLength": "حداقل 8 کاراکتر",
"hasUpperAndLower": "شامل یک حرف کوچک و بزرگ",
"hasSpecialChar": "شامل علامت (!@#$%^&*)",
"notCompatibility": "مطابقت ندارد",
"emailCorrectForm": "فرم درست ایمیل را وارد کنید",
"agreementPart1": " ادامه فرایند ثبت نام به منزله تایید و قبول",
"agreementLinkText": " قوانین و مقررات هارمونی",
"agreementPart2": "می باشد."
}
}

View File

@@ -0,0 +1,175 @@
import React from 'react';
import {
TextField,
Box,
Button,
Switch,
FormGroup,
Typography,
InputAdornment,
IconButton,
} from '@mui/material';
import { useTranslation } from 'react-i18next';
import { TickCircle, Edit, Refresh } from 'iconsax-react';
interface EmailSectionProps {
showEmail: boolean;
setShowEmail: (checked: boolean) => void;
email: string;
setEmail: (email: string) => void;
correctEmail: boolean;
codeSent: boolean;
verificationCode: string;
setVerificationCode: (code: string) => void;
buttonState: 'default' | 'counting' | 'sent';
getButtonLabel: () => string;
handleSendCode: () => void;
handleVerifyCode: () => void;
emailVerified: boolean;
isVerifyingCode: boolean;
handleEditEmail: () => void;
}
export function EmailSection({
showEmail,
setShowEmail,
email,
setEmail,
correctEmail,
codeSent,
verificationCode,
setVerificationCode,
buttonState,
getButtonLabel,
handleSendCode,
handleVerifyCode,
emailVerified,
isVerifyingCode,
handleEditEmail,
}: EmailSectionProps) {
const { t } = useTranslation('completionForm');
const handleToggleEmail = (e: React.ChangeEvent<HTMLInputElement>) => {
setShowEmail(e.target.checked);
};
return (
<>
<FormGroup>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, px: 6 }}>
<Switch
checked={showEmail}
onChange={handleToggleEmail}
sx={{
'& .MuiSwitch-switchBase.Mui-checked': {
color: '#2979FF',
},
'& .MuiSwitch-switchBase.Mui-checked + .MuiSwitch-track': {
backgroundColor: '#2979FF',
},
}}
/>
<Typography sx={{ color: showEmail ? '#2979FF' : 'black' }}>
{t('completion.determineEmail')}
</Typography>
</Box>
</FormGroup>
{showEmail && (
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2, px: 6 }}>
<Box sx={{ display: 'flex', gap: 4 }}>
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
<TextField
label={t('completion.email')}
variant="outlined"
value={email}
onChange={(e) => setEmail(e.target.value)}
sx={{
width: !isVerifyingCode && !emailVerified ? '446px' : '634px',
transition: 'width 0.3s',
}}
InputProps={{
startAdornment:
buttonState === 'counting' ? (
<InputAdornment position="start">
<IconButton size="small" onClick={handleEditEmail}>
<Edit size="20" color="#2979FF" />
</IconButton>
</InputAdornment>
) : null,
endAdornment:
!isVerifyingCode && emailVerified ? (
<TickCircle size="16" color="#2e7d32" variant="Bold" />
) : null,
}}
/>
{email && (
<Typography
sx={{ color: correctEmail ? 'green' : 'red' }}
variant="caption"
>
{correctEmail ? '' : t('completion.emailCorrectForm')}
</Typography>
)}
</Box>
{!isVerifyingCode && !emailVerified && (
<Button
variant="text"
onClick={handleSendCode}
sx={{ width: '200px', color: '#2979FF' }}
disabled={
buttonState === 'sent' ||
buttonState === 'counting' ||
!correctEmail
}
>
{getButtonLabel()}
</Button>
)}
</Box>
{!emailVerified && codeSent && (
<Box sx={{ display: 'flex', gap: 4 }}>
<TextField
label={t('completion.verificationCode')}
variant="outlined"
value={verificationCode}
onChange={(e) => setVerificationCode(e.target.value)}
sx={{ width: '446px' }}
disabled={isVerifyingCode}
/>
<Button
variant="contained"
sx={{
width: '156px',
backgroundColor: 'white',
border: 0.5,
borderColor: '#2979FF',
color: '#2979FF',
}}
onClick={handleVerifyCode}
disabled={isVerifyingCode}
>
{isVerifyingCode ? (
<Box
component="span"
sx={{
display: 'flex',
animation: 'spin 1s linear infinite',
'@keyframes spin': {
'0%': { transform: 'rotate(0deg)' },
'100%': { transform: 'rotate(360deg)' },
},
}}
>
<Refresh size="20" color="text.secondary" />
</Box>
) : (
t('completion.checkCodeButton')
)}
</Button>
</Box>
)}
</Box>
)}
</>
);
}

View File

@@ -0,0 +1,177 @@
import React, { useState } from 'react';
import {
TextField,
Box,
IconButton,
Switch,
FormGroup,
Typography,
InputAdornment,
} from '@mui/material';
import { useTranslation } from 'react-i18next';
import { TickCircle, Eye, EyeSlash } from 'iconsax-react';
import { PasswordValidationItem } from './PasswordValidation';
interface PasswordSectionProps {
showPasswordSection: boolean;
setShowPasswordSection: (checked: boolean) => void;
password: string;
setPassword: (password: string) => void;
confirmPassword: string;
setConfirmPassword: (confirmPassword: string) => void;
matchPassword: boolean;
hasNumber: boolean;
hasMinLength: boolean;
hasUpperAndLower: boolean;
hasSpecialChar: boolean;
validPassword: boolean;
showValidations: boolean;
}
export function PasswordSection({
showPasswordSection,
setShowPasswordSection,
password,
setPassword,
confirmPassword,
setConfirmPassword,
matchPassword,
hasNumber,
hasMinLength,
hasUpperAndLower,
hasSpecialChar,
validPassword,
showValidations,
}: PasswordSectionProps) {
const { t } = useTranslation('completionForm');
const [showPasswordText, setShowPasswordText] = useState(false);
const handleTogglePasswordSection = (
e: React.ChangeEvent<HTMLInputElement>,
) => {
setShowPasswordSection(e.target.checked);
};
const handleTogglePasswordEye = () => {
setShowPasswordText((prev) => !prev);
};
return (
<>
<FormGroup>
<Box sx={{ display: 'flex', gap: 0.5, px: 6, alignItems: 'center' }}>
<Switch
checked={showPasswordSection}
onChange={handleTogglePasswordSection}
sx={{
'& .MuiSwitch-switchBase.Mui-checked': { color: '#2979FF' },
'& .MuiSwitch-switchBase.Mui-checked + .MuiSwitch-track': {
backgroundColor: '#2979FF',
},
}}
/>
<Typography sx={{ color: showPasswordSection ? '#2979FF' : 'black' }}>
{t('completion.determinePassword')}
</Typography>
</Box>
</FormGroup>
{showPasswordSection && (
<Box sx={{ display: 'flex', gap: 2, px: 6 }}>
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
<TextField
label={t('completion.password')}
value={password}
onChange={(e) => setPassword(e.target.value)}
variant="outlined"
type={showPasswordText ? 'text' : 'password'}
sx={{ width: '309px' }}
InputProps={{
endAdornment: (
<InputAdornment position="end">
{validPassword && (
<TickCircle
size="16"
color="#2e7d32"
variant="Bold"
style={{ marginRight: '8px' }}
/>
)}
<IconButton onClick={handleTogglePasswordEye}>
{showPasswordText ? (
<EyeSlash size="20" color="#000" />
) : (
<Eye size="20" color="#000" />
)}
</IconButton>
</InputAdornment>
),
}}
/>
{password && (
<Box sx={{ mt: 1 }}>
{showValidations && (
<Box sx={{ mt: 1 }}>
<PasswordValidationItem
isValid={hasNumber}
label={t('completion.hasNumber')}
/>
<PasswordValidationItem
isValid={hasMinLength}
label={t('completion.hasMinLength')}
/>
<PasswordValidationItem
isValid={hasUpperAndLower}
label={t('completion.hasUpperAndLower')}
/>
<PasswordValidationItem
isValid={hasSpecialChar}
label={t('completion.hasSpecialChar')}
/>
</Box>
)}
</Box>
)}
</Box>
<TextField
label={t('completion.passwordRepetition')}
variant="outlined"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
error={confirmPassword.length > 0 && !matchPassword}
helperText={
confirmPassword.length > 0 && !matchPassword
? t('completion.notCompatibility')
: ' '
}
sx={{ width: '309px' }}
type={showPasswordText ? 'text' : 'password'}
InputProps={{
endAdornment: (
<InputAdornment position="end">
{confirmPassword.length > 0 && matchPassword && (
<TickCircle
size="16"
color="#2e7d32"
variant="Bold"
style={{ marginRight: '8px' }}
/>
)}
<IconButton onClick={handleTogglePasswordEye}>
{showPasswordText ? (
<EyeSlash size="20" color="#000" />
) : (
<Eye size="20" color="#000" />
)}
</IconButton>
</InputAdornment>
),
}}
/>
</Box>
)}
</>
);
}

View File

@@ -0,0 +1,25 @@
import { Box, Typography } from '@mui/material';
import { TickCircle } from 'iconsax-react';
interface ValidationItemProps {
isValid: boolean;
label: string;
}
export function PasswordValidationItem({
isValid,
label,
}: ValidationItemProps) {
return (
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 0.5 }}>
<TickCircle
size="16"
color={isValid ? '#2e7d32' : '#2979FF'}
variant={isValid ? 'Bold' : 'Outline'}
/>
<Typography variant="body2" color="text.primary">
{label}
</Typography>
</Box>
);
}

View File

@@ -0,0 +1,71 @@
import {
TextField,
FormControl,
InputLabel,
MenuItem,
Select,
Box,
type SelectChangeEvent,
} from '@mui/material';
import { useTranslation } from 'react-i18next';
interface PersonalInfoFieldsProps {
sex: string;
setSex: (sex: string) => void;
}
export function PersonalInfoFields({ sex, setSex }: PersonalInfoFieldsProps) {
const { t } = useTranslation('completionForm');
const handleChange = (e: SelectChangeEvent) => {
setSex(e.target.value);
};
return (
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2, px: 6 }}>
<Box sx={{ display: 'flex', gap: 2 }}>
<TextField
label={t('completion.name')}
placeholder={t('completion.name')}
variant="outlined"
sx={{
width: '309px',
}}
/>
<TextField
label={t('completion.familyName')}
placeholder={t('completion.familyName')}
variant="outlined"
sx={{
width: '309px',
}}
/>
</Box>
<Box sx={{ display: 'flex', gap: 2 }}>
<FormControl sx={{ width: '309px' }}>
<InputLabel id="sex-label">{t('completion.gender')}</InputLabel>
<Select
labelId="sex-label"
id="sex"
value={sex}
label={t('completion.gender')}
onChange={handleChange}
>
<MenuItem value="female">{t('completion.man')}</MenuItem>
<MenuItem value="male">{t('completion.woman')}</MenuItem>
</Select>
</FormControl>
<TextField
label={t('completion.optionalNationalCode')}
placeholder={t('completion.optionalNationalCode')}
variant="outlined"
sx={{
width: '309px',
}}
/>
</Box>
</Box>
);
}

View File

@@ -0,0 +1,24 @@
import { Box, Button, Typography, Link } from '@mui/material';
import { useTranslation } from 'react-i18next';
export function SubmitSection() {
const { t } = useTranslation('completionForm');
return (
<Box sx={{ display: 'flex', gap: 2, px: 6, mb: '17px' }}>
<Typography variant="body2" sx={{ flex: 1 }}>
{t('completion.agreementPart1')}
<Link target="_blank" sx={{ color: '#2979FF' }}>
{t('completion.agreementLinkText')}
</Link>{' '}
{t('completion.agreementPart2')}
</Typography>
<Button
variant="contained"
sx={{ width: '247px', backgroundColor: '#2979FF' }}
>
{t('completion.registerButton')}
</Button>
</Box>
);
}

View File

@@ -1,56 +1,53 @@
import {
TextField,
FormControl,
InputLabel,
MenuItem,
Select,
Box,
type SelectChangeEvent,
Switch,
FormGroup,
Button,
Typography,
Link,
} from '@mui/material';
import React, { useEffect, useState } from 'react';
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 [showPassword, setShowPassword] = useState(false);
const [showEmail, setShowEmail] = useState(false);
const [showPasswordSection, setShowPasswordSection] = useState(false);
const [password, setPassword] = useState('');
const [email, setEmail] = 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'); // default | counting | sent
const [buttonState, setButtonState] = useState<
'default' | 'counting' | 'sent'
>('default'); // default | counting | sent
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);
const handleTogglePassword = (e: React.ChangeEvent<HTMLInputElement>) => {
setShowPassword(e.target.checked);
};
const handleToggleEmail = (e: React.ChangeEvent<HTMLInputElement>) => {
setShowEmail(e.target.checked);
};
const handleChange = (e: SelectChangeEvent) => {
setSex(e.target.value);
};
const onClickCodeSent = () => {
setCodeSent(true);
setButtonState('sent');
setTimeout(() => {
setButtonState('counting');
setCountdown(60);
}, 1000);
};
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>;
@@ -76,282 +73,112 @@ export function UserCompletionForm() {
const time = `${minutes}:${seconds}`;
return toPersianDigits(time);
}
return 'ارسال کد تایید';
return t('completion.vericationCodeButton');
};
const handleSendCode = () => {
setCodeSent(true);
setButtonState('sent');
setTimeout(() => {
setButtonState('counting');
setCountdown(60);
}, 1000);
};
const handleVerifyCode = () => {
setIsVerifyingCode(true);
setTimeout(() => {
setIsVerifyingCode(false);
setEmailVerified(true);
}, 1000);
};
const handleEditEmail = () => {
setButtonState('default');
setCodeSent(false);
setEmailVerified(false);
};
return (
<div
dir="rtl"
style={{
<Box
sx={{
backgroundColor: '#F5F5F5',
minHeight: '100vh',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
p: 2,
}}
>
<Box
sx={{
width: '500px',
width: '730px',
backgroundColor: 'white',
border: '1px solid #ccc',
borderRadius: 2,
padding: 5,
margin: '40px auto',
boxShadow: 2,
display: 'flex',
flexDirection: 'column',
gap: 2,
}}
>
<Box sx={{ flexDirection: 'column', mb: 2 }}>
<Typography variant="h5" sx={{ mb: 0.5 }}>
تکمیل اطلاعات حساب کاربری
</Typography>
<Typography sx={{ color: 'gray', fontSize: '14px' }}>
اطلاعات کسب و کار خود را وارد کنید
</Typography>
</Box>
<Box
sx={{
display: 'flex',
gap: 2,
flexDirection: 'column',
px: 4,
width: '100%',
maxWidth: '666px',
height: '92px',
mt: '32px',
}}
>
<TextField
label="نام"
placeholder="نام"
variant="outlined"
sx={{
width: '330px',
'& .MuiOutlinedInput-root': {
height: 45,
},
}}
/>
<TextField
label="نام خانوادگی"
placeholder="نام خانوادگی"
variant="outlined"
sx={{
width: '330px',
'& .MuiOutlinedInput-root': {
height: 45,
},
}}
/>
</Box>
<Box sx={{ display: 'flex', gap: 2 }}>
<FormControl sx={{ width: '330px' }}>
<InputLabel id="sex-label">جنسیت</InputLabel>
<Select
labelId="sex-label"
id="sex"
value={sex}
label="جنسیت"
onChange={handleChange}
sx={{
height: '45px',
'& .MuiSelect-select': {
paddingY: '10px',
},
}}
>
<MenuItem value="female">زن</MenuItem>
<MenuItem value="male">مرد</MenuItem>
</Select>
</FormControl>
<TextField
label="کدملی(اختیاری)"
placeholder="کدملی(اختیاری)"
variant="outlined"
sx={{
width: '330px',
'& .MuiOutlinedInput-root': {
height: 45,
},
}}
/>
</Box>
<FormGroup>
<Box sx={{ display: 'flex', gap: 0.5, alignItems: 'center' }}>
<Switch
checked={showPassword}
onChange={handleTogglePassword}
sx={{
color: '#2979FF',
transform: 'scaleX(-1)',
'& .MuiSwitch-thumb': {
transform: 'scaleX(-1)',
},
}}
/>
<Typography> تعیین رمز عبور</Typography>
</Box>
</FormGroup>
{showPassword && (
<Box sx={{ display: 'flex', gap: 2 }}>
<Box
sx={{ display: 'flex', flexDirection: 'column', width: '330px' }}
>
<TextField
label="رمز عبور"
value={password}
onChange={(e) => setPassword(e.target.value)}
variant="outlined"
sx={{
'& .MuiOutlinedInput-root': {
height: 45,
},
}}
/>
{password && (
<Box sx={{ mt: 1 }}>
<Typography
variant="caption"
sx={{ color: hasNumber ? 'green' : 'red' }}
>
شامل عدد
</Typography>
<br />
<Typography
variant="caption"
sx={{ color: hasMinLength ? 'green' : 'red' }}
>
حداقل 8 کاراکتر
</Typography>
<br />
<Typography
variant="caption"
sx={{ color: hasUpperAndLower ? 'green' : 'red' }}
>
شامل یک حرف بزرگ و کوچک
</Typography>
<br />
<Typography
variant="caption"
sx={{ color: hasSpecialChar ? 'green' : 'red' }}
>
شامل علامت(!@#$%^&*)
</Typography>
</Box>
)}
</Box>
{showPassword && (
<TextField
label="تکرار رمز عبور"
variant="outlined"
onChange={(e) => setConfirmPassword(e.target.value)}
error={confirmPassword.length > 0 && !matchPassword}
helperText={
confirmPassword.length > 0 && !matchPassword
? 'مطابقت ندارد'
: ' '
}
sx={{
width: '330px',
'& .MuiOutlinedInput-root': {
height: 45,
},
}}
/>
)}
</Box>
)}
<FormGroup>
<Box sx={{ display: 'flex', gap: 0.5, alignItems: 'center' }}>
<Switch
checked={showEmail}
onChange={handleToggleEmail}
sx={{
transform: 'scaleX(-1)',
'& .MuiSwitch-thumb': {
transform: 'scaleX(-1)',
},
}}
/>
<Typography> اتصال ایمیل خود</Typography>
</Box>
</FormGroup>
{showEmail && (
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
<Box sx={{ display: 'flex', gap: 2 }}>
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
<TextField
label="ایمیل"
variant="outlined"
value={email}
onChange={(e) => setEmail(e.target.value)}
sx={{
width: '330px',
'& .MuiOutlinedInput-root': {
height: 45,
},
}}
/>
{email && (
<Typography sx={{ color: correctEmail ? 'green' : 'red' }}>
فرم درست ایمیل وارد کنید
</Typography>
)}
</Box>
<Button
variant="text"
onClick={onClickCodeSent}
sx={{ width: '200px', color: '#2979FF' }}
disabled={buttonState === 'sent' || buttonState === 'counting'}
>
{getButtonLabel()}
</Button>
</Box>
{codeSent && (
<Box sx={{ display: 'flex', gap: 2 }}>
<TextField
label="کد تایید"
variant="outlined"
value={verificationCode}
onChange={(e) => setVerificationCode(e.target.value)}
sx={{
width: '330px',
'& .MuiOutlinedInput-root': {
height: 45,
},
}}
/>
<Button
variant="contained"
sx={{
width: '150px',
backgroundColor: 'white',
border: 0.5,
borderColor: '#1976d2',
color: '#1976d2',
}}
>
بررسی کد
</Button>
</Box>
)}
</Box>
)}
<Box sx={{ display: 'flex', gap: 2 }}>
<Typography variant="body2" sx={{ flex: 1 }}>
ادامه فرایند ثبت نام به منزله تایید و قبول{' '}
<Link href="" target="_blank" rel="">
قوانین و مقررات هارمونی
</Link>{' '}
می باشد.
</Typography>
<Button
variant="contained"
sx={{ width: '250px', height: '40px', backgroundColor: '#2979FF' }}
<Typography
variant="h5"
color="text.primary"
sx={{ mt: '16px', px: 2 }}
>
تایید و ثبت نام
</Button>
{t('completion.title')}
</Typography>
<Typography variant="body2" color="text.secondary" sx={{ px: 2 }}>
{t('completion.description')}
</Typography>
</Box>
<PersonalInfoFields sex={sex} setSex={setSex} />
<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>
</div>
</Box>
);
}

View File

@@ -1,230 +0,0 @@
import {
Box,
Typography,
Button,
TextField,
FormControl,
Select,
MenuItem,
type SelectChangeEvent,
} from '@mui/material';
import { useState, type ChangeEvent } from 'react';
import { CardContainer } from '@/components/CardContainer';
export function PersonalInformation() {
const [isEditing, setIsEditing] = useState(false);
const [gender, setGender] = useState('');
const [data, setData] = useState({
firstName: 'محمد حسین',
lastName: 'برزه‌گر',
gender: 'مرد',
nationalCode: '',
});
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
setData((prev) => ({
...prev,
[e.target.name]: e.target.value,
}));
};
const toggleEdit = () => {
setIsEditing((prev) => !prev);
if (isEditing) {
setData((prev) => ({
...prev,
gender: gender === 'male' ? 'مرد' : gender === 'female' ? 'زن' : '',
}));
} else {
setGender(
data.gender === 'مرد' ? 'male' : data.gender === 'زن' ? 'female' : '',
);
}
};
const handleChangeGender = (e: SelectChangeEvent) => {
setGender(e.target.value);
};
const displayValue = (value: string | null | undefined) => {
return value && value.trim() !== '' ? value : 'تعیین نشده';
};
return (
<Box
sx={{
display: 'flex',
backgroundColor: '#F5F5F5',
justifyContent: 'center',
alignItems: 'center',
p: 2,
overflow: 'hidden',
}}
>
<CardContainer
title="اطلاعات شخصی من"
subtitle="این اطلاعات شما صرفا برای احراز هویت شما است و نزد هارمونی باقی می‌ماند"
highlighted={isEditing}
action={
<Box sx={{ display: 'flex', gap: 1 }}>
{isEditing && (
<Button
variant="text"
onClick={() => setIsEditing(false)}
size="large"
sx={{
color: '#2979FF',
width: '43px',
}}
>
لغو
</Button>
)}
<Button
onClick={toggleEdit}
size="large"
sx={{
border: '1px solid',
borderColor: '#2979FF',
borderRadius: '4px',
backgroundColor: isEditing ? '#2979FF' : 'white',
color: isEditing ? 'white' : '#2979FF',
px: '22px',
py: '8px',
width: isEditing ? '85px' : '93px',
}}
>
{isEditing ? 'ذخیره' : 'ویرایش'}
</Button>
</Box>
}
>
<Box
sx={{
display: 'flex',
flexWrap: 'wrap',
gap: 4,
p: 2,
}}
>
<Box sx={{ width: 'calc(50% - 16px)' }}>
{isEditing ? (
<TextField
fullWidth
name="firstName"
value={data.firstName}
onChange={handleChange}
label="نام"
/>
) : (
<Box
sx={{
height: '48px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
px: 4,
}}
>
<Typography variant="caption" color="text.secondary">
نام
</Typography>
<Typography variant="body1" color="text.primary">
{displayValue(data.firstName)}
</Typography>
</Box>
)}
</Box>
<Box sx={{ width: 'calc(50% - 16px)' }}>
{isEditing ? (
<TextField
fullWidth
name="lastName"
value={data.lastName}
onChange={handleChange}
label="نام خانوادگی"
/>
) : (
<Box
sx={{
height: '48px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
}}
>
<Typography variant="caption" color="text.secondary">
نام خانوادگی
</Typography>
<Typography variant="body1" color="text.primary">
{displayValue(data.lastName)}
</Typography>
</Box>
)}
</Box>
<Box sx={{ width: 'calc(50% - 16px)' }}>
{isEditing ? (
<FormControl fullWidth>
<Select
value={gender}
onChange={handleChangeGender}
displayEmpty
>
<MenuItem value="female">زن</MenuItem>
<MenuItem value="male">مرد</MenuItem>
</Select>
</FormControl>
) : (
<Box
sx={{
height: '48px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
px: 4,
}}
>
<Typography variant="caption" color="text.secondary">
جنسیت
</Typography>
<Typography variant="body1" color="text.primary">
{displayValue(data.gender)}
</Typography>
</Box>
)}
</Box>
<Box sx={{ width: 'calc(50% - 16px)' }}>
{isEditing ? (
<TextField
fullWidth
name="nationalCode"
value={data.nationalCode}
onChange={handleChange}
label="کد ملی"
/>
) : (
<Box
sx={{
height: '48px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
}}
>
<Typography variant="caption" color="text.secondary">
کد ملی
</Typography>
<Typography variant="body1" color="text.primary">
{displayValue(data.nationalCode)}
</Typography>
</Box>
)}
</Box>
</Box>
</CardContainer>
</Box>
);
}