diff --git a/src/components/CardContainer.tsx b/src/components/CardContainer.tsx
index b83cd82..798b25a 100644
--- a/src/components/CardContainer.tsx
+++ b/src/components/CardContainer.tsx
@@ -1,3 +1,4 @@
+import React from 'react';
import { Box, Typography } from '@mui/material';
export function CardContainer({
@@ -14,27 +15,16 @@ export function CardContainer({
highlighted?: boolean;
}) {
return (
-
+
void;
- severity?: AlertType;
- open: boolean;
- duration?: number;
- delayOnClose?: number;
- rtl?: boolean;
- icon?: React.ReactNode;
-}
-
-const defaultIcons: Record = {
- success: ,
- error: ,
- warning: ,
- info: ,
-};
-
-export const CustomAlert: React.FC = ({
- message,
- severity,
- open,
- onClose,
- duration = 4000,
- delayOnClose = 2000,
- rtl = false,
- icon,
-}) => {
- const [visible, setVisible] = useState(open);
-
- useEffect(() => {
- setVisible(open);
- }, [open]);
-
- useEffect(() => {
- if (visible && duration > 0) {
- const timer = setTimeout(() => {
- setVisible(false);
- onClose();
- }, duration);
- return () => clearTimeout(timer);
- }
- }, [visible, duration, onClose]);
-
- const handleClose = () => {
- setTimeout(() => {
- setVisible(false);
- onClose();
- }, delayOnClose);
- };
-
- if (!visible) return null;
-
- return (
-
-
-
-
- }
- sx={{
- width: '396px',
- flexDirection: 'row-reverse',
- justifyContent: 'space-between',
- alignItems: 'center',
- textAlign: rtl ? 'right' : 'left',
- direction: rtl ? 'rtl' : 'ltr',
- }}
- >
- {message}
-
-
- );
-};
diff --git a/src/components/Toast.tsx b/src/components/Toast.tsx
new file mode 100644
index 0000000..947194f
--- /dev/null
+++ b/src/components/Toast.tsx
@@ -0,0 +1,23 @@
+import { Alert, Snackbar, type AlertColor } from '@mui/material';
+import React, { type PropsWithChildren } from 'react';
+
+export interface ToastProps extends PropsWithChildren {
+ color: AlertColor | undefined;
+ open: boolean;
+ onClose: () => void;
+}
+
+export const Toast = ({ color, open, onClose, children }: ToastProps) => {
+ return (
+
+
+ {children}
+
+
+ );
+};
diff --git a/src/features/profile/components/PersonalInformation.tsx b/src/features/profile/components/PersonalInformation.tsx
index a0ad810..d06b551 100644
--- a/src/features/profile/components/PersonalInformation.tsx
+++ b/src/features/profile/components/PersonalInformation.tsx
@@ -1,5 +1,5 @@
+import React, { useState } from 'react';
import { Box, Button } from '@mui/material';
-import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { CardContainer } from '@/components/CardContainer';
import { ProfileImage } from './personlInformation/ProfileImage';
@@ -38,110 +38,92 @@ export function PersonalInformation() {
};
return (
-
-
- {isEditing && (
-
- )}
+
+ {isEditing && (
-
- }
- >
-
- {isEditing && (
- {
- const file = e.target.files?.[0];
- if (file) {
- const reader = new FileReader();
- reader.onload = () =>
- setUploadedImageUrl(reader.result as string);
- reader.readAsDataURL(file);
- }
- }}
- />
- )}
- {isEditing ? (
-
- ) : (
-
)}
+
-
-
+ }
+ >
+
+ {isEditing && (
+ {
+ const file = e.target.files?.[0];
+ if (file) {
+ const reader = new FileReader();
+ reader.onload = () =>
+ setUploadedImageUrl(reader.result as string);
+ reader.readAsDataURL(file);
+ }
+ }}
+ />
+ )}
+
+ {isEditing ? (
+
+ ) : (
+
+ )}
+
+
);
}
diff --git a/src/features/profile/components/PhoneNumber.tsx b/src/features/profile/components/PhoneNumber.tsx
index 7e08f70..7cf2cff 100644
--- a/src/features/profile/components/PhoneNumber.tsx
+++ b/src/features/profile/components/PhoneNumber.tsx
@@ -1,58 +1,27 @@
+import React, { useState, type ChangeEvent } from 'react';
import { Box, Typography, Button, TextField, IconButton } from '@mui/material';
import { Edit, Refresh, TickCircle } from 'iconsax-react';
-import { useState, type ChangeEvent } from 'react';
+import { useTranslation } from 'react-i18next';
import { CardContainer } from '@/components/CardContainer';
import { CountDownTimer } from '@/components/CountDownTimer';
-import { useTranslation } from 'react-i18next';
-import { CustomAlert } from '@/components/CustomAlert';
+import { Toast } from '@/components/Toast';
export function PhoneNumber() {
const { t } = useTranslation('profileSetting');
const [isEditing, setIsEditing] = useState(false);
const [phoneNumber, setPhoneNumber] = useState('');
const [verificationCode, setVerificationCode] = useState('');
- const [showEmailAlert, setShowEmailAlert] = useState(false);
+ const [showToast, setShowToast] = useState(false);
const [buttonState, setButtonState] = useState<'default' | 'counting'>(
'default',
);
const [isVerifying, setIsVerifying] = useState(false);
const [isVerified, setIsVerified] = useState(false);
- const handleVerifyClick = () => {
- if (!verificationCode || isVerifying) return;
- handleVerifyCode();
- setTimeout(() => {
- setShowEmailAlert(true);
- }, 1600);
- };
-
const [phones, setPhone] = useState([
- {
- phone: '09123456789',
- time: '۱ ماه پیش',
- withCode: '+989123456789',
- },
+ { phone: '09123456789', time: '۱ ماه پیش', withCode: '+989123456789' },
]);
- const handleSendCode = () => {
- setButtonState('counting');
- setIsVerified(false);
- };
-
- const handleVerifyCode = () => {
- setIsVerifying(true);
- setTimeout(() => {
- setIsVerifying(false);
- setIsVerified(true);
- setShowEmailAlert(true);
-
- const newPhone = '+98' + phoneNumber.slice(1);
- setPhone([
- { phone: phoneNumber, time: 'چند ثانیه پیش', withCode: newPhone },
- ]);
- }, 1500);
- };
-
const toggleEdit = () => {
setIsEditing((prev) => {
const enteringEditMode = !prev;
@@ -61,7 +30,7 @@ export function PhoneNumber() {
setVerificationCode('');
setIsVerified(false);
setButtonState('default');
- setShowEmailAlert(false);
+ setShowToast(false);
}
return enteringEditMode;
});
@@ -77,245 +46,241 @@ export function PhoneNumber() {
setVerificationCode(value);
};
+ const handleSendCode = () => {
+ if (!phoneNumber) return;
+ setButtonState('counting');
+ setIsVerified(false);
+ };
+
+ const handleVerifyCode = () => {
+ setIsVerifying(true);
+ setTimeout(() => {
+ setIsVerifying(false);
+ setIsVerified(true);
+ setShowToast(true);
+ const newPhone = '+98' + phoneNumber.slice(1);
+ setPhone([
+ { phone: phoneNumber, time: 'چند ثانیه پیش', withCode: newPhone },
+ ]);
+ }, 1500);
+ };
+
+ const handleVerifyClick = () => {
+ if (!verificationCode || isVerifying) return;
+ handleVerifyCode();
+ setTimeout(() => setShowToast(true), 1600);
+ };
+
return (
-
-
- {isEditing && (
-
- )}
+
+ {isEditing && (
-
- }
- >
- {isEditing ? (
-
-
-
- {t('settingForm.editPhoneNumber')}
-
-
- {t('settingForm.phoneNumberText')}(
- {phones.map((p) => p.withCode)}){t('settingForm.verb')}
-
-
+ {isEditing
+ ? t('settingForm.saveButton')
+ : t('settingForm.editPhoneNumber')}
+
+
+ }
+ >
+ {isEditing ? (
+
+
+
+ {t('settingForm.editPhoneNumber')}
+
+
+ {t('settingForm.phoneNumberText')}({phones.map((p) => p.withCode)}
+ ){t('settingForm.verb')}
+
+
+
+ {
+ setButtonState('default');
+ setPhoneNumber('');
+ }}
+ sx={{ mr: 1 }}
+ >
+
+
+ ) : null,
+ }}
+ />
+
+ {isVerified ? (
+
+
+
+ {t('settingForm.successButton')}
+
+
+ ) : (
+
+ )}
+
+
+ {buttonState === 'counting' && !isVerified && (
{
- setButtonState('default');
- setPhoneNumber('');
- }}
- sx={{ mr: 1 }}
- >
-
-
- ) : null,
- }}
+ value={verificationCode}
+ onChange={handleVerificationCodeChange}
+ sx={{ flex: '1 1 240px', minWidth: 0 }}
+ placeholder={t('settingForm.verificationCode')}
+ inputProps={{ dir: 'rtl', style: { textAlign: 'right' } }}
/>
- {isVerified ? (
-
-
-
- {t('settingForm.successButton')}
-
-
- ) : (
-
-
-
- )}
+
+
+ ) : (
+ t('settingForm.checkCode')
+ )}
+
+ )}
- {buttonState === 'counting' && !isVerified && (
-
-
-
-
-
- )}
- setShowEmailAlert(false)}
- severity="success"
- duration={4000}
- delayOnClose={2000}
- />
-
- ) : (
-
- {phones.map((item, index) => (
-
-
- {item.phone}
-
-
- {item.time}
-
-
- ))}
-
- )}
-
-
+ setShowToast(false)}
+ >
+ {t('settingForm.successfulChangePhone')}
+
+
+ ) : (
+
+ {phones.map((item, index) => (
+
+
+ {item.phone}
+
+
+ {item.time}
+
+
+ ))}
+
+ )}
+
);
}
diff --git a/src/features/profile/components/SocialMedia.tsx b/src/features/profile/components/SocialMedia.tsx
index a053c86..1d8b3ab 100644
--- a/src/features/profile/components/SocialMedia.tsx
+++ b/src/features/profile/components/SocialMedia.tsx
@@ -1,12 +1,4 @@
-import {
- Google,
- Apple,
- Sms,
- Trash,
- CloseSquare,
- Message,
- ArrowDown3,
-} from 'iconsax-react';
+import React, { useState } from 'react';
import {
Box,
Button,
@@ -20,10 +12,21 @@ import {
MenuItem,
ListItemIcon,
ListItemText,
+ useMediaQuery,
} from '@mui/material';
-import React, { useState } from 'react';
-import { CardContainer } from '@/components/CardContainer';
+import type { Theme } from '@mui/material/styles';
import { useTranslation } from 'react-i18next';
+import { CardContainer } from '@/components/CardContainer';
+
+import {
+ Google,
+ Apple,
+ Sms,
+ Trash,
+ CloseSquare,
+ Message,
+ ArrowDown3,
+} from 'iconsax-react';
export function SocialMedia() {
const { t } = useTranslation('profileSetting');
@@ -32,14 +35,17 @@ export function SocialMedia() {
const [emailError, setEmailError] = useState(false);
const [anchor, setAnchor] = useState(null);
const openMenu = Boolean(anchor);
+ const fullScreen = useMediaQuery((theme: Theme) =>
+ theme.breakpoints.down('sm'),
+ );
const handleOpenDialog = () => setOpenDialog(true);
const handleCloseDialog = () => setOpenDialog(false);
- const handleClickMenu = (e: React.MouseEvent) => {
+ const handleClickMenu = (e: React.MouseEvent) =>
setAnchor(e.currentTarget);
- };
const handleCloseMenu = () => setAnchor(null);
+
const handleEmailChange = (e: React.ChangeEvent) => {
const value = e.target.value;
setEmailInput(value);
@@ -49,271 +55,277 @@ export function SocialMedia() {
const emailList = [
{ email: 'emailtemp@email.com', provider: 'email', time: '1 ماه پیش' },
{ email: 'emailtemp@gmail.com', provider: 'google', time: '1 ماه پیش' },
- ];
+ { email: 'emailtemp@icloud.com', provider: 'apple', time: '1 ماه پیش' },
+ ] as const;
return (
-
-
+
+
+
+
+
+ }
+ >
+
+ {emailList.map((item, index) => (
+
-
-
-
-
-
- }
- >
-
- {emailList.map((item, index) => (
-
-
- {item.provider === 'google' && (
-
- )}
- {item.provider === 'apple' && (
-
- )}
- {item.provider === 'email' && (
-
- )}
-
- {item.email}
-
- {item.time}
-
-
-
-
-
-
-
- ))}
-
+ {item.provider === 'google' && (
+
+ )}
+ {item.provider === 'apple' && (
+
+ )}
+ {item.provider === 'email' && (
+
+ )}
-
+
+
+
+
+
+
+ ))}
+
+
+
-
-
+
+
+
+
);
}
diff --git a/src/features/profile/components/UserForm.tsx b/src/features/profile/components/UserForm.tsx
index 329fc83..bcfd593 100644
--- a/src/features/profile/components/UserForm.tsx
+++ b/src/features/profile/components/UserForm.tsx
@@ -1,13 +1,14 @@
+import { Box } from '@mui/material';
import { PersonalInformation } from './PersonalInformation';
import { PhoneNumber } from './PhoneNumber';
import { SocialMedia } from './SocialMedia';
export function UserForm() {
return (
- <>
+
- >
+
);
}