331 lines
9.9 KiB
TypeScript
331 lines
9.9 KiB
TypeScript
import {
|
||
Box,
|
||
Typography,
|
||
Button,
|
||
TextField,
|
||
FormControl,
|
||
Select,
|
||
MenuItem,
|
||
Avatar,
|
||
Autocomplete,
|
||
type SelectChangeEvent,
|
||
} from '@mui/material';
|
||
import { useState, type ChangeEvent } from 'react';
|
||
import { CardContainer } from '@/components/CardContainer';
|
||
import { CountryFlag, countryCodeMap } from '@/components/CountryFlag';
|
||
import { useTranslation } from 'react-i18next';
|
||
import { Camera } from 'iconsax-react';
|
||
|
||
export function PersonalInformation() {
|
||
const { t } = useTranslation('profileSetting');
|
||
const [isEditing, setIsEditing] = useState(false);
|
||
const [gender, setGender] = useState('');
|
||
|
||
const initialData = {
|
||
firstName: 'محمد حسین',
|
||
lastName: 'برزهگر',
|
||
country: 'قطر',
|
||
gender: 'مرد',
|
||
nationalCode: '',
|
||
};
|
||
const [data, setData] = useState(initialData);
|
||
const [uploadedImageUrl, setUploadedImageUrl] = useState<string | null>(null);
|
||
|
||
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||
const { name, value } = e.target;
|
||
setData((prev) => ({
|
||
...prev,
|
||
[name]: 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 : 'تعیین نشده';
|
||
};
|
||
|
||
const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||
const file = e.target.files?.[0];
|
||
if (file) {
|
||
const reader = new FileReader();
|
||
reader.onload = () => {
|
||
setUploadedImageUrl(reader.result as string);
|
||
};
|
||
reader.readAsDataURL(file);
|
||
}
|
||
};
|
||
|
||
const initials = `${data.firstName?.trim()[0] || ''}${data.lastName?.trim()[0] || ''}`;
|
||
|
||
return (
|
||
<Box
|
||
sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}
|
||
>
|
||
<CardContainer
|
||
title={t('settingForm.titlePersonalInfo')}
|
||
subtitle={t('settingForm.descriptionPersonalInfo')}
|
||
highlighted={isEditing}
|
||
action={
|
||
<Box sx={{ display: 'flex', gap: 1 }}>
|
||
{isEditing && (
|
||
<Button
|
||
variant="text"
|
||
onClick={() => setIsEditing(false)}
|
||
size="large"
|
||
sx={{
|
||
color: 'primary.main',
|
||
width: '43px',
|
||
textTransform: 'none',
|
||
}}
|
||
>
|
||
{t('settingForm.rejectButton')}
|
||
</Button>
|
||
)}
|
||
<Button
|
||
onClick={toggleEdit}
|
||
size="large"
|
||
variant="outlined"
|
||
sx={{
|
||
textTransform: 'none',
|
||
border: '1px solid',
|
||
borderColor: 'primary.main',
|
||
borderRadius: '4px',
|
||
backgroundColor: isEditing
|
||
? 'primary.main'
|
||
: 'background.paper',
|
||
color: isEditing ? 'primary.contrastText' : 'primary.main',
|
||
px: '22px',
|
||
py: '8px',
|
||
width: isEditing ? '85px' : '93px',
|
||
}}
|
||
>
|
||
{isEditing
|
||
? t('settingForm.saveButton')
|
||
: t('settingForm.editButton')}
|
||
</Button>
|
||
</Box>
|
||
}
|
||
>
|
||
<Box
|
||
sx={{
|
||
px: { xs: 2, sm: 3, md: 4 },
|
||
py: 2,
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 2,
|
||
}}
|
||
>
|
||
{isEditing && (
|
||
<Box
|
||
sx={{
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 2,
|
||
flexWrap: 'wrap',
|
||
}}
|
||
>
|
||
<Avatar
|
||
sx={{
|
||
bgcolor: 'secondary.main',
|
||
width: 88,
|
||
height: 88,
|
||
fontSize: '20px',
|
||
}}
|
||
src={uploadedImageUrl || undefined}
|
||
>
|
||
{initials}
|
||
</Avatar>
|
||
<Box>
|
||
<Typography variant="body1">
|
||
{t('settingForm.profilePicture')}
|
||
</Typography>
|
||
<Typography variant="body2" color="text.secondary">
|
||
{t('settingForm.allowedFormat')}
|
||
</Typography>
|
||
<Box mt={1}>
|
||
<Button
|
||
variant="contained"
|
||
component="label"
|
||
sx={{
|
||
borderRadius: 2,
|
||
textTransform: 'none',
|
||
height: '30px',
|
||
fontSize: '13px',
|
||
}}
|
||
startIcon={<Camera size={18} color="white" />}
|
||
>
|
||
{t('settingForm.uploadPicture')}
|
||
<input
|
||
hidden
|
||
accept="image/png, image/jpeg, image/gif"
|
||
type="file"
|
||
onChange={handleImageChange}
|
||
/>
|
||
</Button>
|
||
</Box>
|
||
</Box>
|
||
</Box>
|
||
)}
|
||
|
||
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 2 }}>
|
||
{[
|
||
{
|
||
name: 'firstName',
|
||
label: t('settingForm.name'),
|
||
value: data.firstName,
|
||
},
|
||
{
|
||
name: 'lastName',
|
||
label: t('settingForm.familyName'),
|
||
value: data.lastName,
|
||
},
|
||
{
|
||
name: 'nationalCode',
|
||
label: t('settingForm.nationalCode'),
|
||
value: data.nationalCode,
|
||
},
|
||
].map((field, index) => (
|
||
<Box
|
||
key={index}
|
||
sx={{
|
||
width: {
|
||
xs: '100%',
|
||
sm: '48%',
|
||
md: 'calc(50% - 8px)',
|
||
},
|
||
}}
|
||
>
|
||
{isEditing ? (
|
||
<TextField
|
||
fullWidth
|
||
name={field.name}
|
||
value={field.value}
|
||
onChange={handleChange}
|
||
label={field.label}
|
||
/>
|
||
) : (
|
||
<Box sx={{ px: 2 }}>
|
||
<Typography variant="caption" color="text.secondary">
|
||
{field.label}
|
||
</Typography>
|
||
<Typography variant="body1" color="text.primary">
|
||
{displayValue(field.value)}
|
||
</Typography>
|
||
</Box>
|
||
)}
|
||
</Box>
|
||
))}
|
||
|
||
<Box
|
||
sx={{
|
||
width: {
|
||
xs: '100%',
|
||
sm: '48%',
|
||
md: 'calc(50% - 8px)',
|
||
},
|
||
}}
|
||
>
|
||
{isEditing ? (
|
||
<FormControl fullWidth>
|
||
<Select
|
||
value={gender}
|
||
onChange={handleChangeGender}
|
||
displayEmpty
|
||
renderValue={(selected) => {
|
||
if (!selected) {
|
||
return (
|
||
<span style={{ color: '#aaa' }}>
|
||
{t('settingForm.genderPlaceholder')}
|
||
</span>
|
||
);
|
||
}
|
||
return selected === 'male'
|
||
? t('settingForm.man')
|
||
: t('settingForm.woman');
|
||
}}
|
||
>
|
||
<MenuItem value="male">{t('settingForm.man')}</MenuItem>
|
||
<MenuItem value="female">{t('settingForm.woman')}</MenuItem>
|
||
</Select>
|
||
</FormControl>
|
||
) : (
|
||
<Box sx={{ px: 2 }}>
|
||
<Typography variant="caption" color="text.secondary">
|
||
{t('settingForm.gender')}
|
||
</Typography>
|
||
<Typography variant="body1" color="text.primary">
|
||
{displayValue(data.gender)}
|
||
</Typography>
|
||
</Box>
|
||
)}
|
||
</Box>
|
||
|
||
{isEditing && (
|
||
<Autocomplete
|
||
sx={{
|
||
width: {
|
||
xs: '100%',
|
||
sm: '48%',
|
||
md: 'calc(50% - 8px)',
|
||
},
|
||
}}
|
||
options={Object.keys(countryCodeMap)}
|
||
value={data.country}
|
||
onChange={(_, newValue) =>
|
||
setData((prev) => ({
|
||
...prev,
|
||
country: newValue || '',
|
||
}))
|
||
}
|
||
renderOption={(props, option) => (
|
||
<Box component="li" {...props}>
|
||
<CountryFlag country={option} />
|
||
</Box>
|
||
)}
|
||
renderInput={(params) => (
|
||
<TextField {...params} label={t('settingForm.country')} />
|
||
)}
|
||
/>
|
||
)}
|
||
|
||
{!isEditing && (
|
||
<Box
|
||
sx={{
|
||
px: 2,
|
||
width: {
|
||
xs: '100%',
|
||
sm: '48%',
|
||
md: 'calc(50% - 8px)',
|
||
},
|
||
}}
|
||
>
|
||
<Typography variant="caption" color="text.secondary">
|
||
{t('settingForm.country')}
|
||
</Typography>
|
||
<CountryFlag country={data.country} />
|
||
</Box>
|
||
)}
|
||
</Box>
|
||
</Box>
|
||
</CardContainer>
|
||
</Box>
|
||
);
|
||
}
|