fix: styles

This commit is contained in:
2025-07-19 17:27:39 +03:30
parent bdf6af0b36
commit ff7b5ce4ac
6 changed files with 658 additions and 513 deletions

View File

@@ -12,6 +12,7 @@ import { LanguageManager } from './components/LanguageManager';
<<<<<<< HEAD <<<<<<< HEAD
<<<<<<< HEAD <<<<<<< HEAD
<<<<<<< HEAD <<<<<<< HEAD
<<<<<<< HEAD
======= =======
>>>>>>> f1620b6 (fix: issue in user profile) >>>>>>> f1620b6 (fix: issue in user profile)
@@ -23,6 +24,9 @@ import { UserProfileForm } from './features/profile/components/UserProfileForm';
>>>>>>> f9815fb (fix: issue in user profile) >>>>>>> f9815fb (fix: issue in user profile)
======= =======
>>>>>>> 2a79376 (fix: merge conflict) >>>>>>> 2a79376 (fix: merge conflict)
=======
import { UserForm } from './features/profile/components/UserForm';
>>>>>>> 60c6dc1 (fix: styles)
function App() { function App() {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -30,6 +34,7 @@ function App() {
<> <>
<CssBaseline /> <CssBaseline />
<LanguageManager /> <LanguageManager />
<UserForm />
<div style={{ padding: '16px' }}> <div style={{ padding: '16px' }}>
<Typography variant="h3">{t('helloWorld')}</Typography> <Typography variant="h3">{t('helloWorld')}</Typography>
<Box <Box

View File

@@ -0,0 +1,56 @@
import { Box, Typography } from '@mui/material';
export function CardContainer({
title,
subtitle,
action,
children,
highlighted,
}: {
title: string;
subtitle: string;
action?: React.ReactNode;
children?: React.ReactNode;
highlighted?: boolean;
}) {
return (
<Box
sx={{
width: '754px',
backgroundColor: 'white',
// boxShadow: 2,
display: 'flex',
flexDirection: 'column',
gap: 2,
}}
>
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
backgroundColor: highlighted ? '#E3F2FD' : '#F5F5F5',
p: 2,
borderRadius: 1,
}}
>
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
<Typography
variant="h6"
color={highlighted ? '#2979FF' : 'text.primary'}
>
{title}
</Typography>
<Typography
color={highlighted ? '#2979FF' : 'text.secondary'}
variant="body2"
>
{subtitle}
</Typography>
</Box>
{action}
</Box>
{children}
</Box>
);
}

View File

@@ -0,0 +1,39 @@
import { useState, useEffect } from 'react';
interface CountdownTimerProps {
initialSeconds: number;
onComplete?: () => void;
}
export function CountDownTimer({
initialSeconds,
onComplete,
}: CountdownTimerProps) {
const [secondsLeft, setSecondsLeft] = useState(initialSeconds);
useEffect(() => {
setSecondsLeft(initialSeconds);
}, [initialSeconds]);
useEffect(() => {
if (secondsLeft <= 0) {
onComplete?.();
return;
}
const timer = setInterval(() => {
setSecondsLeft((prev) => prev - 1);
}, 1000);
return () => clearInterval(timer);
}, [secondsLeft, onComplete]);
const toPersianDigits = (str: string) =>
str.replace(/\d/g, (d: string) => '۰۱۲۳۴۵۶۷۸۹'[parseInt(d)]);
const formatTime = (totalSeconds: number) => {
const minutes = String(Math.floor(totalSeconds / 60)).padStart(2, '0');
const seconds = String(totalSeconds % 60).padStart(2, '0');
return toPersianDigits(`${minutes}:${seconds}`);
};
return <span>{formatTime(secondsLeft)}</span>;
}

View File

@@ -3,13 +3,13 @@ import {
Typography, Typography,
Button, Button,
TextField, TextField,
Grid,
FormControl, FormControl,
Select, Select,
MenuItem, MenuItem,
type SelectChangeEvent, type SelectChangeEvent,
} from '@mui/material'; } from '@mui/material';
import { useState, type ChangeEvent } from 'react'; import { useState, type ChangeEvent } from 'react';
import { CardContainer } from '@/components/CardContainer';
export function PersonalInformation() { export function PersonalInformation() {
const [isEditing, setIsEditing] = useState(false); const [isEditing, setIsEditing] = useState(false);
@@ -51,58 +51,30 @@ export function PersonalInformation() {
}; };
return ( return (
<div <Box
style={{ sx={{
display: 'flex', display: 'flex',
backgroundColor: '#F5F5F5', backgroundColor: '#F5F5F5',
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
}}
>
<Box
sx={{
width: '600px',
backgroundColor: 'white',
display: 'flex',
flexDirection: 'column',
gap: 2,
}}
>
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
backgroundColor: isEditing ? '#ADD8E6' : '#F5F5F5',
p: 2, p: 2,
borderRadius: 1, overflow: 'hidden',
}} }}
> >
<Box sx={{ display: 'flex', flexDirection: 'column' }}> <CardContainer
<Typography title="اطلاعات شخصی من"
variant="h6" subtitle="این اطلاعات شما صرفا برای احراز هویت شما است و نزد هارمونی باقی می‌ماند"
sx={{ color: isEditing ? '#1976d2' : 'black' }} highlighted={isEditing}
> action={
اطلاعات شخصی من
</Typography>
<Typography
variant="subtitle2"
sx={{ color: isEditing ? '#1976d2' : 'gray', fontSize: '13px' }}
>
این اطلاعات شما صرفا برای احراز هویت شما است و نزد هارمونی باقی
میماند
</Typography>
</Box>
<Box sx={{ display: 'flex', gap: 1 }}> <Box sx={{ display: 'flex', gap: 1 }}>
{isEditing && ( {isEditing && (
<Button <Button
variant="text"
onClick={() => setIsEditing(false)} onClick={() => setIsEditing(false)}
size="large"
sx={{ sx={{
backgroundColor: '#ADD8E6', color: '#2979FF',
color: '#1976d2', width: '43px',
width: '80px',
height: '30px',
}} }}
> >
لغو لغو
@@ -110,120 +82,150 @@ export function PersonalInformation() {
)} )}
<Button <Button
onClick={toggleEdit} onClick={toggleEdit}
size="large"
sx={{ sx={{
border: 0.5, border: '1px solid',
borderColor: '#1976d2', borderColor: '#2979FF',
borderRadius: '5px', borderRadius: '4px',
backgroundColor: isEditing ? '#1976d2' : 'white', backgroundColor: isEditing ? '#2979FF' : 'white',
color: isEditing ? 'white' : '#1976d2', color: isEditing ? 'white' : '#2979FF',
width: '80px', px: '22px',
height: '30px', py: '8px',
// minWidth: '93px',
width: isEditing ? '85px' : '93px',
}} }}
> >
{isEditing ? 'ذخیره' : 'ویرایش'} {isEditing ? 'ذخیره' : 'ویرایش'}
</Button> </Button>
</Box> </Box>
</Box> }
>
<Grid container spacing={4}> <Box
<Grid item xs={6}> sx={{
display: 'flex',
flexWrap: 'wrap',
gap: 4,
p: 2,
}}
>
<Box sx={{ width: 'calc(50% - 16px)' }}>
{isEditing ? ( {isEditing ? (
<TextField <TextField
fullWidth fullWidth
name="firstName" name="firstName"
value={data.firstName} value={data.firstName}
onChange={handleChange} onChange={handleChange}
inputProps={{ sx: { height: '12px' } }}
label="نام" label="نام"
/> />
) : ( ) : (
<Box sx={{ width: '250px' }}> <Box
<Typography variant="caption" sx={{ color: 'gray' }}> sx={{
height: '48px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
px: 4,
}}
>
<Typography variant="caption" color="text.secondary">
نام نام
</Typography> </Typography>
<Typography variant="subtitle2"> <Typography variant="body1" color="text.primary">
{displayValue(data.firstName)} {displayValue(data.firstName)}
</Typography> </Typography>
</Box> </Box>
)} )}
</Grid> </Box>
<Grid item xs={6}> <Box sx={{ width: 'calc(50% - 16px)' }}>
{isEditing ? ( {isEditing ? (
<TextField <TextField
fullWidth fullWidth
name="lastName" name="lastName"
value={data.lastName} value={data.lastName}
onChange={handleChange} onChange={handleChange}
inputProps={{ sx: { height: '12px' } }}
label="نام خانوادگی" label="نام خانوادگی"
/> />
) : ( ) : (
<Box sx={{ width: '200px' }}> <Box
<Typography variant="caption" sx={{ color: 'gray' }}> sx={{
height: '48px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
}}
>
<Typography variant="caption" color="text.secondary">
نام خانوادگی نام خانوادگی
</Typography> </Typography>
<Typography variant="subtitle2"> <Typography variant="body1" color="text.primary">
{displayValue(data.lastName)} {displayValue(data.lastName)}
</Typography> </Typography>
</Box> </Box>
)} )}
</Grid> </Box>
<Grid item xs={6}> <Box sx={{ width: 'calc(50% - 16px)' }}>
{isEditing ? ( {isEditing ? (
<FormControl fullWidth> <FormControl fullWidth>
<Select <Select
value={gender} value={gender}
onChange={handleChangeGender} onChange={handleChangeGender}
sx={{ displayEmpty
height: '45px',
width: '210px',
'& .MuiSelect-select': {
paddingY: '10px',
},
}}
label="جنسیت"
> >
<MenuItem value="female">زن</MenuItem> <MenuItem value="female">زن</MenuItem>
<MenuItem value="male">مرد</MenuItem> <MenuItem value="male">مرد</MenuItem>
</Select> </Select>
</FormControl> </FormControl>
) : ( ) : (
<Box sx={{ width: '250px' }}> <Box
<Typography variant="caption" sx={{ color: 'gray' }}> sx={{
height: '48px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
px: 4,
}}
>
<Typography variant="caption" color="text.secondary">
جنسیت جنسیت
</Typography> </Typography>
<Typography variant="subtitle1"> <Typography variant="body1" color="text.primary">
{displayValue(data.gender)} {displayValue(data.gender)}
</Typography> </Typography>
</Box> </Box>
)} )}
</Grid> </Box>
<Grid item xs={6}> <Box sx={{ width: 'calc(50% - 16px)' }}>
{isEditing ? ( {isEditing ? (
<TextField <TextField
fullWidth fullWidth
name="nationalCode" name="nationalCode"
value={data.nationalCode} value={data.nationalCode}
onChange={handleChange} onChange={handleChange}
inputProps={{ sx: { height: '12px' } }} label="کد ملی"
label="کدملی"
/> />
) : ( ) : (
<Box> <Box
<Typography variant="caption" sx={{ color: 'gray' }}> sx={{
height: '48px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
}}
>
<Typography variant="caption" color="text.secondary">
کد ملی کد ملی
</Typography> </Typography>
<Typography variant="subtitle2"> <Typography variant="body1" color="text.primary">
{displayValue(data.nationalCode)} {displayValue(data.nationalCode)}
</Typography> </Typography>
</Box> </Box>
)} )}
</Grid>
</Grid>
</Box> </Box>
</div> </Box>
</CardContainer>
</Box>
); );
} }

View File

@@ -2,305 +2,253 @@ import {
Box, Box,
Typography, Typography,
Button, Button,
Dialog,
DialogTitle,
DialogContent,
IconButton,
TextField, TextField,
IconButton,
GlobalStyles,
} from '@mui/material'; } from '@mui/material';
import { Edit, CloseSquare } from 'iconsax-react'; import { Edit, Refresh, TickCircle } from 'iconsax-react';
import { useState, useEffect } from 'react'; import { useState, useEffect, type ChangeEvent } from 'react';
import { CardContainer } from '@/components/CardContainer';
import { CountDownTimer } from '@/components/CountDownTimer';
export function PhoneNumber() { export function PhoneNumber() {
const [open, setOpen] = useState(false); const [isEditing, setIsEditing] = useState(false);
const [dialogStep, setDialogStep] = useState<'enterPhone' | 'verifyCode'>( const [phoneNumber, setPhoneNumber] = useState('');
'enterPhone', const [verificationCode, setVerificationCode] = useState('');
const [buttonState, setButtonState] = useState<'default' | 'counting'>(
'default',
); );
const [buttonState, setButtonState] = useState('default'); // default | counting | sent const [isVerifying, setIsVerifying] = useState(false);
const [countdown, setCountdown] = useState(120); const [isVerified, setIsVerified] = useState(false);
const handleChangePhoneNumber = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
setDialogStep('enterPhone');
};
const handleSendCode = () => { const handleSendCode = () => {
setDialogStep('verifyCode');
setButtonState('sent');
setTimeout(() => {
setButtonState('counting'); setButtonState('counting');
setCountdown(120); setIsVerified(false);
}, 1000);
};
const handleResendCode = () => {
setButtonState('sent');
setTimeout(() => {
setButtonState('counting');
setCountdown(120);
}, 1000);
}; };
useEffect(() => { const handleVerifyCode = () => {
if (buttonState === 'counting' && countdown > 0) { setIsVerifying(true);
const timer = setInterval(() => { setTimeout(() => {
setCountdown((prev) => prev - 1); setIsVerifying(false);
}, 1000); setIsVerified(true);
return () => clearInterval(timer); }, 1500);
} };
if (countdown === 0 && buttonState === 'counting') {
const toggleEdit = () => {
setIsEditing((prev) => !prev);
setButtonState('default'); setButtonState('default');
} setIsVerified(false);
}, [buttonState, countdown]); setVerificationCode('');
const toPersianDigits = (str: string) =>
str.replace(/\d/g, (d: string) => '۰۱۲۳۴۵۶۷۸۹'[parseInt(d)]);
const getButtonLabel = () => {
if (buttonState === 'sent') return 'ارسال شد!';
if (buttonState === 'counting') {
const minutes = String(Math.floor(countdown / 60)).padStart(2, '0');
const seconds = String(countdown % 60).padStart(2, '0');
const time = `${minutes}:${seconds}`;
return toPersianDigits(time);
}
return 'ارسال دوباره کد';
}; };
const handleEdit = () => { const handlePhoneNumberChange = (e: ChangeEvent<HTMLInputElement>) => {
setDialogStep('enterPhone'); const value = e.target.value.replace(/\D/g, '');
setPhoneNumber(value);
};
const handleVerificationCodeChange = (e: ChangeEvent<HTMLInputElement>) => {
const value = e.target.value.replace(/\D/g, '');
setVerificationCode(value);
}; };
return ( return (
<div <>
style={{ <GlobalStyles
backgroundColor: '#F5F5F5', styles={{
display: 'flex', '@keyframes spin': {
justifyContent: 'center', from: { transform: 'rotate(0deg)' },
alignItems: 'center', to: { transform: 'rotate(360deg)' },
},
}} }}
> />
<Box <Box
sx={{ sx={{
width: '600px',
backgroundColor: 'white',
boxShadow: 2,
display: 'flex', display: 'flex',
flexDirection: 'column', backgroundColor: '#F5F5F5',
justifyContent: 'center',
alignItems: 'center',
p: 2,
}}
>
<CardContainer
title="شماره تماس من"
subtitle="این اطلاعات شما صرفا برای احراز هویت شما است و نزد هارمونی باقی می‌ماند"
highlighted={isEditing}
action={
<Box sx={{ display: 'flex', gap: 1 }}>
{isEditing && (
<Button
variant="text"
onClick={toggleEdit}
size="large"
sx={{ color: '#2979FF', width: '43px' }}
>
لغو
</Button>
)}
<Button
onClick={toggleEdit}
size="large"
variant="outlined"
sx={{
border: '1px solid',
borderColor: '#2979FF',
borderRadius: '4px',
backgroundColor: isEditing ? '#2979FF' : 'white',
color: isEditing ? 'white' : '#2979FF',
width: isEditing ? '85px' : '161px',
}}
>
{isEditing ? 'ذخیره' : 'تغییر شماره تماس'}
</Button>
</Box>
}
>
{isEditing ? (
<Box sx={{ px: 4 }}>
<Box sx={{ width: '668px', mb: 2 }}>
<Typography variant="h6" color="text.primary">
تغییر شماره تماس
</Typography>
<Typography variant="body2" color="text.secondary">
شماره تماس جدید شما جایگزین شماره تماس قبلی(+989123456789)
خواهد شد.
</Typography>
</Box>
<Box
sx={{
display: 'flex',
alignItems: 'center',
width: '700px',
gap: 2, gap: 2,
}} }}
> >
<TextField
name="phoneNumber"
placeholder="09123456789"
label="شماره تماس جدید"
type="tel"
value={phoneNumber}
onChange={handlePhoneNumberChange}
sx={{ width: '100%', maxWidth: '474px' }}
InputProps={{
startAdornment:
buttonState === 'counting' ? (
<IconButton
size="small"
onClick={() => setButtonState('default')}
>
<Edit size="20" color="#2979FF" />
</IconButton>
) : null,
}}
/>
{isVerified ? (
<Box <Box
sx={{ sx={{
width: '100%',
maxWidth: '194px',
display: 'flex', display: 'flex',
justifyContent: 'space-between',
alignItems: 'center', alignItems: 'center',
backgroundColor: '#F5F5F5', justifyContent: 'center',
p: 2, color: 'success.main',
borderRadius: 1, gap: 1,
}} }}
> >
<Box sx={{ display: 'flex', flexDirection: 'column' }}> <TickCircle size="20" color="#2e7d32" variant="Bold" />
<Typography variant="h6">شماره تماس من</Typography> تایید شد
<Typography sx={{ color: 'gray' }} variant="subtitle2">
این اطلاعات شما صرفا برای احراز هویت شما است و نزد هارمونی باقی
میماند
</Typography>
</Box> </Box>
) : (
<Button <Button
onClick={handleChangePhoneNumber} variant="text"
sx={{ sx={{ width: '100%', maxWidth: '194px', color: '#2979FF' }}
border: 0.5, size="large"
borderColor: '#1976d2', onClick={handleSendCode}
borderRadius: '5px', disabled={buttonState === 'counting'}
backgroundColor: 'white',
color: '#1976d2',
width: '150px',
height: '30px',
}}
> >
تغییر شماره تماس {buttonState === 'counting' ? (
<CountDownTimer
initialSeconds={60}
onComplete={() => setButtonState('default')}
/>
) : (
'ارسال کد تایید'
)}
</Button> </Button>
)}
</Box> </Box>
{buttonState === 'counting' && !isVerified && (
<Box <Box
sx={{ sx={{
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
p: 2, width: '700px',
borderRadius: 1, gap: 2,
justifyContent: 'space-between', mt: 2,
}} }}
> >
<TextField
name="verificationCode"
placeholder="کد تایید"
label="کد تایید"
type="tel"
value={verificationCode}
onChange={handleVerificationCodeChange}
sx={{ width: '100%', maxWidth: '474px' }}
/>
<Button
variant="contained"
size="large"
onClick={handleVerifyCode}
disabled={isVerifying || verificationCode.length === 0}
sx={{
width: '100%',
maxWidth: '194px',
display: 'flex',
justifyContent: 'center',
backgroundColor: '#2979FF',
}}
>
{isVerifying ? (
<Box <Box
component="span"
sx={{ sx={{
display: 'flex', display: 'flex',
flexDirection: 'column', animation: 'spin 1s linear infinite',
alignItems: 'flex-end',
}} }}
> >
<Typography variant="h6" sx={{ fontWeight: 'bold' }}> <Refresh size="20" color="white" />
</Box>
) : (
'بررسی کد'
)}
</Button>
</Box>
)}
</Box>
) : (
<Box
sx={{
height: '48px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
px: 4,
}}
>
<Typography variant="h6" color="text.primary">
09909366045 09909366045
</Typography> </Typography>
<Typography variant="caption" sx={{ color: 'gray' }}> <Typography variant="caption" color="text.secondary">
۱ ماه پیش ۱ ماه پیش
</Typography> </Typography>
</Box> </Box>
{/* <IconButton
sx={{
border: '1px solid #1976d2',
color: '#1976d2',
borderRadius: '12px',
width: '40px',
height: '40px',
}}
onClick={handleChangePhoneNumber}
></IconButton> */}
</Box>
</Box>
<Dialog open={open} onClose={handleClose} fullWidth maxWidth="xs">
<DialogTitle
sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
backgroundColor: '#F5F5F5',
}}
>
ویرایش شماره تماس
<IconButton onClick={handleClose}>
<CloseSquare size="24" color="gray" variant="Outline" />
</IconButton>
</DialogTitle>
<DialogContent>
<Box sx={{ width: '100%', display: 'flex', flexDirection: 'column' }}>
{dialogStep === 'enterPhone' ? (
<>
<Typography variant="subtitle1" sx={{ mb: 1 }}>
شماره تماس جدید
</Typography>
<Typography variant="subtitle2" sx={{ color: 'gray', mb: 2 }}>
شماره تماس جدید جایگزین شماره تماس قبلی شما خواهد شد
</Typography>
<TextField
fullWidth
label="شماره تماس"
placeholder="09123456789"
sx={{
mb: 2,
'& .MuiOutlinedInput-root': {
'& fieldset': {
borderColor: '#1976d2',
},
'&:hover fieldset': {
borderColor: '#1976d2',
},
'&.Mui-focused fieldset': {
borderColor: '#1976d2',
},
},
'& label.Mui-focused': {
color: '#1976d2',
},
}}
/>
<Button
onClick={handleSendCode}
variant="contained"
fullWidth
sx={{
borderRadius: '10px',
backgroundColor: '#1976d2',
'&:hover': { backgroundColor: '#115293' },
}}
>
ارسال کد تایید
</Button>
</>
) : (
<>
<Box sx={{ display: 'flex', gap: 1 }}>
<Box>
<Typography variant="subtitle1" sx={{ mb: 1 }}>
اعتبار سنجی
</Typography>
<Typography
variant="subtitle2"
sx={{ color: 'gray', mb: 2 }}
>
کد تایید 4 رقمی به شماره موبایل شما ارسال شد. لطفا آن را
وارد کنید
</Typography>
</Box>
<Button
sx={{
border: 0.5,
borderColor: '#1976d2',
height: '35px',
color: '#1976d2',
width: '150px',
}}
onClick={handleEdit}
>
<Edit />
09123456789
</Button>
</Box>
<TextField
fullWidth
label="کد تایید"
placeholder="کد تایید را وارد کنید"
sx={{
mb: 2,
'& .MuiOutlinedInput-root': {
'& fieldset': {
borderColor: '#1976d2',
},
'&:hover fieldset': {
borderColor: '#1976d2',
},
'&.Mui-focused fieldset': {
borderColor: '#1976d2',
},
},
'& label.Mui-focused': {
color: '#1976d2',
},
}}
/>
<Box sx={{ display: 'flex' }}>
<Button
variant="text"
onClick={handleResendCode}
sx={{ width: '200px' }}
disabled={
buttonState === 'sent' || buttonState === 'counting'
}
>
{getButtonLabel()}
</Button>
<Button
onClick={handleClose}
variant="contained"
fullWidth
sx={{
borderRadius: '10px',
backgroundColor: '#1976d2',
'&:hover': { backgroundColor: '#115293' },
}}
>
بررسی کد
</Button>
</Box>
</>
)} )}
</CardContainer>
</Box> </Box>
</DialogContent> </>
</Dialog>
</div>
); );
} }

View File

@@ -1,4 +1,12 @@
import { Google, Apple, Sms, Trash, CloseSquare } from 'iconsax-react'; import {
Google,
Apple,
Sms,
Trash,
CloseSquare,
Message,
ArrowDown3,
} from 'iconsax-react';
import { import {
Box, Box,
Button, Button,
@@ -8,13 +16,33 @@ import {
DialogContent, DialogContent,
IconButton, IconButton,
TextField, TextField,
Menu,
MenuItem,
ListItemIcon,
ListItemText,
} from '@mui/material'; } from '@mui/material';
import { useState } from 'react'; import React, { useState } from 'react';
import { CardContainer } from '@/components/CardContainer';
export function SocialMedia() { export function SocialMedia() {
const [open, setOpen] = useState(false); const [openDialog, setOpenDialog] = useState(false);
const handleOpen = () => setOpen(true); const [emailInput, setEmailInput] = useState('');
const handleClose = () => setOpen(false); const [emailError, setEmailError] = useState(false);
const [anchor, setAnchor] = useState<null | HTMLElement>(null);
const openMenu = Boolean(anchor);
const handleOpenDialog = () => setOpenDialog(true);
const handleCloseDialog = () => setOpenDialog(false);
const handleClickMenu = (e: React.MouseEvent<HTMLButtonElement>) => {
setAnchor(e.currentTarget);
};
const handleCloseMenu = () => setAnchor(null);
const handleEmailChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
setEmailInput(value);
setEmailError(!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value));
};
const emailList = [ const emailList = [
{ email: 'emailtemp@email.com', provider: 'email' }, { email: 'emailtemp@email.com', provider: 'email' },
@@ -22,57 +50,94 @@ export function SocialMedia() {
]; ];
return ( return (
<div <Box
style={{ sx={{
backgroundColor: '#F5F5F5', backgroundColor: '#F5F5F5',
display: 'flex', display: 'flex',
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', p: 2,
}} }}
> >
<Box <CardContainer
sx={{ title="ایمیل و شبکه های اجتماعی من"
width: '600px', subtitle="این اطلاعات شما صرفاً برای احراز هویت شما است و نزد هارمونی باقی می‌ماند"
backgroundColor: 'white', action={
boxShadow: 2, <Box sx={{ display: 'flex', justifyContent: 'flex-start' }}>
display: 'flex', <Button
flexDirection: 'column', onClick={handleClickMenu}
gap: 2, variant="outlined"
}} size="large"
>
<Box
sx={{ sx={{
maxWidth: '187px',
height: '42px',
border: '1px solid',
borderColor: '#2979FF',
borderRadius: '8px',
color: '#2979FF',
fontSize: '14px',
display: 'flex', display: 'flex',
justifyContent: 'space-between', justifyContent: 'space-between',
alignItems: 'center', px: 2,
backgroundColor: '#F5F5F5',
p: 2,
borderRadius: 1,
}}
>
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
<Typography variant="h6">ایمیل و شبکههای اجتماعی من</Typography>
<Typography sx={{ color: 'gray' }} variant="subtitle2">
این اطلاعات شما صرفاً برای احراز هویت شما است و نزد هارمونی باقی
میماند
</Typography>
</Box>
<Button
onClick={handleOpen}
sx={{
border: 0.5,
borderColor: '#1976d2',
borderRadius: '5px',
backgroundColor: 'white',
color: '#1976d2',
width: '150px',
height: '30px',
}} }}
> >
افزودن ایمیل / سوشال افزودن ایمیل / سوشال
{openMenu && <ArrowDown3 size="20" color="#2979FF" />}
</Button> </Button>
<Menu
anchorEl={anchor}
open={openMenu}
onClose={handleCloseMenu}
PaperProps={{
sx: {
width: anchor ? `${anchor.offsetWidth}px` : undefined,
},
}}
>
<MenuItem
onClick={() => {
handleCloseMenu();
handleOpenDialog();
}}
>
<ListItemIcon>
<Message size={20} color="black" />
</ListItemIcon>
<ListItemText>ایمیل</ListItemText>
</MenuItem>
<MenuItem
onClick={() => {
handleCloseMenu();
handleOpenDialog();
}}
>
<ListItemIcon>
<Google size={20} color="#4285F4" />
</ListItemIcon>
<ListItemText>گوگل</ListItemText>
</MenuItem>
<MenuItem
onClick={() => {
handleCloseMenu();
handleOpenDialog();
}}
>
<ListItemIcon>
<Apple size={20} color="black" />
</ListItemIcon>
<ListItemText>اپل</ListItemText>
</MenuItem>
</Menu>
</Box> </Box>
}
>
<Box
sx={{
width: '100%',
backgroundColor: 'white',
borderRadius: '8px',
p: 2,
}}
>
{emailList.map((item, index) => ( {emailList.map((item, index) => (
<Box <Box
key={index} key={index}
@@ -80,9 +145,9 @@ export function SocialMedia() {
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
justifyContent: 'space-between', justifyContent: 'space-between',
p: 2, p: 1,
borderRadius: 1, borderBottom:
mt: 1, index !== emailList.length - 1 ? '1px solid #eee' : 'none',
}} }}
> >
<Box sx={{ display: 'flex', alignItems: 'center' }}> <Box sx={{ display: 'flex', alignItems: 'center' }}>
@@ -110,60 +175,83 @@ export function SocialMedia() {
style={{ marginLeft: 8 }} style={{ marginLeft: 8 }}
/> />
)} )}
<Box> <Box>
<Typography sx={{ fontWeight: 'bold' }}> <Typography sx={{ fontWeight: 'bold', fontSize: '14px' }}>
{item.email} {item.email}
</Typography> </Typography>
<Typography variant="body2">۱ ماه پیش</Typography> <Typography variant="caption" color="text.secondary">
۱ ماه پیش
</Typography>
</Box> </Box>
</Box> </Box>
<IconButton size="small">
<IconButton>
<Trash size="20" color="gray" variant="Outline" /> <Trash size="20" color="gray" variant="Outline" />
</IconButton> </IconButton>
</Box> </Box>
))} ))}
</Box> </Box>
<Dialog open={open} onClose={handleClose} fullWidth maxWidth="xs"> <Dialog
open={openDialog}
onClose={handleCloseDialog}
fullWidth
maxWidth="xs"
>
<DialogTitle <DialogTitle
sx={{ sx={{
display: 'flex', display: 'flex',
justifyContent: 'space-between', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
backgroundColor: '#F5F5F5', backgroundColor: '#F5F5F5',
fontWeight: 'bold',
fontSize: '16px',
gap: 1,
}} }}
> >
افزودن ایمیل / سوشال <IconButton onClick={handleCloseDialog} size="small">
<IconButton onClick={handleClose}>
<CloseSquare size="24" color="gray" /> <CloseSquare size="24" color="gray" />
</IconButton> </IconButton>
افزودن ایمیل
</DialogTitle> </DialogTitle>
<DialogContent> <DialogContent>
<Box sx={{ width: '100%', display: 'flex', flexDirection: 'column' }}> <Box
sx={{
width: '100%',
display: 'flex',
flexDirection: 'column',
gap: 2,
}}
>
<Box>
<Typography fontWeight="bold">ایمیل جدید</Typography>
<Typography variant="body2" color="text.secondary">
با فعالسازی ایمیل میتوانید در دفعات بعدی ورود برای ورود از
این ایمیل استفاده کنید
</Typography>
</Box>
<TextField <TextField
fullWidth fullWidth
type="email"
value={emailInput}
onChange={handleEmailChange}
error={emailError}
helperText={emailError ? 'لطفا یک ایمیل معتبر وارد کنید' : ''}
label="ایمیل" label="ایمیل"
placeholder="abc@email.com" placeholder="abc@email.com"
sx={{ sx={{
mb: 2,
'& .MuiOutlinedInput-root': { '& .MuiOutlinedInput-root': {
'& fieldset': { borderColor: '#1976d2' }, borderRadius: '8px',
'&:hover fieldset': { borderColor: '#1976d2' },
'&.Mui-focused fieldset': { borderColor: '#1976d2' },
}, },
'& label.Mui-focused': { color: '#1976d2' },
}} }}
/> />
<Button <Button
variant="contained" variant="contained"
fullWidth fullWidth
sx={{ sx={{
borderRadius: '10px', borderRadius: '8px',
backgroundColor: '#1976d2', backgroundColor: '#1976d2',
'&:hover': { backgroundColor: '#115293' },
}} }}
disabled={emailError || emailInput === ''}
> >
ارسال کد تایید ارسال کد تایید
</Button> </Button>
@@ -184,6 +272,9 @@ export function SocialMedia() {
borderColor: '#1976d2', borderColor: '#1976d2',
color: '#1976d2', color: '#1976d2',
borderRadius: '8px', borderRadius: '8px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}} }}
> >
<Google size="20" color="#4285F4" style={{ marginLeft: 8 }} /> <Google size="20" color="#4285F4" style={{ marginLeft: 8 }} />
@@ -196,6 +287,9 @@ export function SocialMedia() {
borderColor: '#1976d2', borderColor: '#1976d2',
color: '#1976d2', color: '#1976d2',
borderRadius: '8px', borderRadius: '8px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}} }}
> >
<Apple size="20" color="black" style={{ marginLeft: 8 }} /> <Apple size="20" color="black" style={{ marginLeft: 8 }} />
@@ -205,6 +299,7 @@ export function SocialMedia() {
</Box> </Box>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
</div> </CardContainer>
</Box>
); );
} }