diff --git a/package-lock.json b/package-lock.json index 1204723..fe1023c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "i18next": "^25.3.0", "i18next-browser-languagedetector": "^8.2.0", "i18next-http-backend": "^3.0.2", + "iconsax-react": "^0.0.8", "react": "^19.1.0", "react-dom": "^19.1.0", "react-i18next": "^15.6.0", @@ -3102,6 +3103,18 @@ "cross-fetch": "4.0.0" } }, + "node_modules/iconsax-react": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/iconsax-react/-/iconsax-react-0.0.8.tgz", + "integrity": "sha512-l3dVk4zGtkkJHgvNYqAf0wDKqnKxXykee5/DoESGo2JvSYwaxajJUHSX2YrPRXSov8Hd8ClGFwJxCEaEjrFD1Q==", + "license": "MIT", + "dependencies": { + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": "*" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", diff --git a/package.json b/package.json index 666890c..91571b6 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "i18next": "^25.3.0", "i18next-browser-languagedetector": "^8.2.0", "i18next-http-backend": "^3.0.2", + "iconsax-react": "^0.0.8", "react": "^19.1.0", "react-dom": "^19.1.0", "react-i18next": "^15.6.0", diff --git a/src/App.tsx b/src/App.tsx index 43fe290..b6dffad 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -7,9 +7,12 @@ import { useColorScheme, } from '@mui/material'; import './App.css'; +<<<<<<< HEAD import { useTranslation } from 'react-i18next'; import { LanguageManager } from './components/LanguageManager'; +======= +>>>>>>> 58445fe (feat: add user profile which includes three sections: Personal Information, Phone Number and Email and Social media) function App() { const { t } = useTranslation(); diff --git a/src/features/profile/components/PersonalInformation.tsx b/src/features/profile/components/PersonalInformation.tsx new file mode 100644 index 0000000..21967f1 --- /dev/null +++ b/src/features/profile/components/PersonalInformation.tsx @@ -0,0 +1,229 @@ +import { + Box, + Typography, + Button, + TextField, + Grid, + FormControl, + Select, + MenuItem, + type SelectChangeEvent, +} from '@mui/material'; +import { useState, type ChangeEvent } from 'react'; + +export function PersonalInformation() { + const [isEditing, setIsEditing] = useState(false); + const [gender, setGender] = useState(''); + const [data, setData] = useState({ + firstName: 'محمد حسین', + lastName: 'برزه‌گر', + gender: 'مرد', + nationalCode: '', + }); + + const handleChange = (e: ChangeEvent) => { + 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 ( +
+ + + + + اطلاعات شخصی من + + + این اطلاعات شما صرفا برای احراز هویت شما است و نزد هارمونی باقی + می‌ماند + + + + + {isEditing && ( + + )} + + + + + + + {isEditing ? ( + + ) : ( + + + نام + + + {displayValue(data.firstName)} + + + )} + + + + {isEditing ? ( + + ) : ( + + + نام خانوادگی + + + {displayValue(data.lastName)} + + + )} + + + + {isEditing ? ( + + + + ) : ( + + + جنسیت + + + {displayValue(data.gender)} + + + )} + + + + {isEditing ? ( + + ) : ( + + + کد ملی + + + {displayValue(data.nationalCode)} + + + )} + + + +
+ ); +} diff --git a/src/features/profile/components/PhoneNumber.tsx b/src/features/profile/components/PhoneNumber.tsx new file mode 100644 index 0000000..24a9a50 --- /dev/null +++ b/src/features/profile/components/PhoneNumber.tsx @@ -0,0 +1,306 @@ +import { + Box, + Typography, + Button, + Dialog, + DialogTitle, + DialogContent, + IconButton, + TextField, +} from '@mui/material'; +import { Edit, CloseSquare } from 'iconsax-react'; +import { useState, useEffect } from 'react'; + +export function PhoneNumber() { + const [open, setOpen] = useState(false); + const [dialogStep, setDialogStep] = useState<'enterPhone' | 'verifyCode'>( + 'enterPhone', + ); + const [buttonState, setButtonState] = useState('default'); // default | counting | sent + const [countdown, setCountdown] = useState(120); + + const handleChangePhoneNumber = () => { + setOpen(true); + }; + const handleClose = () => { + setOpen(false); + setDialogStep('enterPhone'); + }; + const handleSendCode = () => { + setDialogStep('verifyCode'); + setButtonState('sent'); + setTimeout(() => { + setButtonState('counting'); + setCountdown(120); + }, 1000); + }; + const handleResendCode = () => { + setButtonState('sent'); + setTimeout(() => { + setButtonState('counting'); + setCountdown(120); + }, 1000); + }; + + useEffect(() => { + if (buttonState === 'counting' && countdown > 0) { + const timer = setInterval(() => { + setCountdown((prev) => prev - 1); + }, 1000); + return () => clearInterval(timer); + } + if (countdown === 0 && buttonState === 'counting') { + setButtonState('default'); + } + }, [buttonState, countdown]); + + 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 = () => { + setDialogStep('enterPhone'); + }; + + return ( +
+ + + + شماره تماس من + + این اطلاعات شما صرفا برای احراز هویت شما است و نزد هارمونی باقی + می‌ماند + + + + + + + + + 09909366045 + + + ۱ ماه پیش + + + + {/* */} + + + + + + ویرایش شماره تماس + + + + + + + {dialogStep === 'enterPhone' ? ( + <> + + شماره تماس جدید + + + شماره تماس جدید جایگزین شماره تماس قبلی شما خواهد شد + + + + + ) : ( + <> + + + + اعتبار سنجی + + + کد تایید 4 رقمی به شماره موبایل شما ارسال شد. لطفا آن را + وارد کنید + + + + + + + + + + + + )} + + + +
+ ); +} diff --git a/src/features/profile/components/SocialMedia.tsx b/src/features/profile/components/SocialMedia.tsx new file mode 100644 index 0000000..8e84bf9 --- /dev/null +++ b/src/features/profile/components/SocialMedia.tsx @@ -0,0 +1,210 @@ +import { Google, Apple, Sms, Trash, CloseSquare } from 'iconsax-react'; +import { + Box, + Button, + Typography, + Dialog, + DialogTitle, + DialogContent, + IconButton, + TextField, +} from '@mui/material'; +import { useState } from 'react'; + +export function SocialMedia() { + const [open, setOpen] = useState(false); + const handleOpen = () => setOpen(true); + const handleClose = () => setOpen(false); + + const emailList = [ + { email: 'emailtemp@email.com', provider: 'email' }, + { email: 'emailtemp@gmail.com', provider: 'google' }, + ]; + + return ( +
+ + + + ایمیل و شبکه‌های اجتماعی من + + این اطلاعات شما صرفاً برای احراز هویت شما است و نزد هارمونی باقی + می‌ماند + + + + + + {emailList.map((item, index) => ( + + + {item.provider === 'google' && ( + + )} + {item.provider === 'apple' && ( + + )} + {item.provider === 'email' && ( + + )} + + + + {item.email} + + ۱ ماه پیش + + + + + + + + ))} + + + + + افزودن ایمیل / سوشال + + + + + + + + + + + + + یا + + + + + + + + + + + +
+ ); +} diff --git a/src/features/profile/components/UserForm.tsx b/src/features/profile/components/UserForm.tsx new file mode 100644 index 0000000..329fc83 --- /dev/null +++ b/src/features/profile/components/UserForm.tsx @@ -0,0 +1,13 @@ +import { PersonalInformation } from './PersonalInformation'; +import { PhoneNumber } from './PhoneNumber'; +import { SocialMedia } from './SocialMedia'; + +export function UserForm() { + return ( + <> + + + + + ); +}