From 8ed4aab6669d43ba63609e9d86409e2238bbed79 Mon Sep 17 00:00:00 2001 From: Koosha Lahouti Date: Wed, 20 Aug 2025 01:00:20 +0330 Subject: [PATCH 1/6] feat: add navigation to forger password page, show password icon, toasts for different situations and changes of some styles --- public/locales/en/setting.json | 20 +- public/locales/fa/setting.json | 19 +- src/components/CardContainer.tsx | 1 + src/components/Layout/Header.tsx | 4 +- src/components/Layout/Toolbar.tsx | 10 +- src/components/Loading.tsx | 1 - src/components/ThemToggle.tsx | 10 +- .../AccountCreated/AccountCreated.tsx | 4 +- .../AccountCreatedClubBanner.tsx | 4 +- .../AccountCreatedRedirectButton.tsx | 2 +- .../AuthenticationSteps.tsx | 2 +- .../components/security/PasswordDialog.tsx | 50 +++- .../components/security/PasswordSecurity.tsx | 17 +- .../userInformation/PersonalInformation.tsx | 128 ++++----- .../userInformation/PhoneNumber.tsx | 10 +- .../personalInformation/InfoRowDisplay.tsx | 33 ++- .../personalInformation/InfoRowEdit.tsx | 264 +++++++++++------- .../phoneNumber/PhoneEditForm.tsx | 24 +- .../socialMedia/SocialMediaDialog.tsx | 113 ++++---- .../socialMedia/SocialMediaList.tsx | 8 +- .../socialMedia/SocialMediaMenu.tsx | 4 +- .../profile/routes/ActiveDevicesPage.tsx | 11 +- src/features/profile/routes/SettingPage.tsx | 140 ++++++---- 23 files changed, 503 insertions(+), 376 deletions(-) diff --git a/public/locales/en/setting.json b/public/locales/en/setting.json index 458690b..b2162f4 100644 --- a/public/locales/en/setting.json +++ b/public/locales/en/setting.json @@ -16,7 +16,7 @@ "familyName": "Family Name", "country": "Country", "gender": "Gender", - "nationalCode": "National code", + "nationalCode": "National code(Op", "man": "Male", "woman": "Female", "genderPlaceholder": "Male", @@ -62,7 +62,14 @@ "emailIsInvalid": "Email is invalid", "changeEmailFailed": "Change of email failed", "anErrorOccurred": "An error occurred.", - "saving": "Saving..." + "saving": "Saving...", + "successSaveProfile": "Profile saved successfully", + "errorSave": "Saving failed", + "codeSentSuccessfully": "Code sent successfully", + "errorSendCode": "Failed to send code", + "phoneVerified": "Phone number verified", + "errorConfirmCode": "Failed to confirm code", + "errorChangePhone": "Failed to change phone number" }, "active": { @@ -76,7 +83,9 @@ "notLoggedIn": "You are not logged in", "failFetchActiveSessions": "Failed to fetch active sessions.", "errorFetch": "An error occurred while fetching your active sessions.", - "deleting": "Deleting..." + "deleting": "Deleting...", + "successDelete": "Deleted successfully", + "deleteFailed": "Deletion failed" }, "settings": { @@ -123,6 +132,9 @@ "currentDevice": "Current device", "changePassword": "Change password", "currentPassword": "Current password", - "forgetPassword": "Forgot your password?" + "forgetPassword": "Forgot your password?", + "passwordChanged": "Password changed", + "passwordAdded": "Password added", + "error": "Password change failed" } } diff --git a/public/locales/fa/setting.json b/public/locales/fa/setting.json index eec7e03..5a33613 100644 --- a/public/locales/fa/setting.json +++ b/public/locales/fa/setting.json @@ -17,6 +17,7 @@ "country": "کشور", "gender": "جنسیت", "nationalCode": "کد ملی", + "optionalNationalCode": "کد ملی(اختیاری)", "man": "مرد", "woman": "زن", "genderPlaceholder": "مرد", @@ -62,7 +63,14 @@ "emailIsInvalid": "ایمیل نامعتبر است", "changeEmailFailed": "تغییر ایمیل با خطا مواجه شد", "anErrorOccurred": "خطایی رخ داد", - "saving": "در حال ذخیره‌سازی..." + "saving": "در حال ذخیره‌سازی...", + "successSaveProfile": "پروفایل با موفقیت ذخیره شد", + "errorSave": "ذخیره با مشکل مواجه شد", + "codeSentSuccessfully": "کد با موفقیت ارسال شد", + "errorSendCode": "ارسال کد با خطا مواجه شد", + "phoneVerified": "تلفن همراه تایید شد", + "errorConfirmCode": "تایید کد با خطا مواجه شد", + "errorChangePhone": "تغییر تلفن همراه با خطا مواجه شد" }, "active": { @@ -76,7 +84,9 @@ "notLoggedIn": "شما وارد سیستم نشده‌اید", "failFetchActiveSessions": "دریافت نشست های فعال ناموفق بود.", "errorFetch": "هنگام دریافت جلسات فعال شما خطایی روی داد.", - "deleting": "در حال حذف..." + "deleting": "در حال حذف...", + "successDelete": "با موفقیت حذف شد", + "deleteFailed": "حذف با مشکل مواجه شد" }, "settings": { @@ -123,6 +133,9 @@ "currentDevice": "دستگاه فعلی", "changePassword": "تغییر رمز عبور", "currentPassword": "رمز عبور فعلی", - "forgetPassword": "رمز عبور را فراموش کرده اید؟" + "forgetPassword": "رمز عبور را فراموش کرده اید؟", + "passwordChanged": "رمز عبور تعویض شد", + "passwordAdded": "رمز عبور اضافه شد", + "error": "تعویض رمز عبور با مشکل مواجه شد" } } diff --git a/src/components/CardContainer.tsx b/src/components/CardContainer.tsx index 2159df7..24fd92f 100644 --- a/src/components/CardContainer.tsx +++ b/src/components/CardContainer.tsx @@ -25,6 +25,7 @@ export function CardContainer({ display: 'flex', flexDirection: 'column', gap: 2, + borderRadius: 1, }} > = ({ user, loading }) => { +export const Header: React.FC = ({ user }) => { return ( = ({ setSideNavOpen, isMobile, user, - loading, }) => { return ( { return ( diff --git a/src/components/ThemToggle.tsx b/src/components/ThemToggle.tsx index 0149f26..36ef2fd 100644 --- a/src/components/ThemToggle.tsx +++ b/src/components/ThemToggle.tsx @@ -34,7 +34,9 @@ export const ThemeToggleButton = ({ @@ -70,10 +68,6 @@ export const ThemeToggleButton = ({ gap: 1, px: 2, py: 1, - '&.Mui-selected': { - bgcolor: 'primary.light', - color: 'primary.main', - }, }} > diff --git a/src/features/authorization/components/AccountCreated/AccountCreated.tsx b/src/features/authorization/components/AccountCreated/AccountCreated.tsx index ba49095..bee3d4d 100644 --- a/src/features/authorization/components/AccountCreated/AccountCreated.tsx +++ b/src/features/authorization/components/AccountCreated/AccountCreated.tsx @@ -1,6 +1,6 @@ -import React, { useMemo, useState } from 'react'; +import { useMemo } from 'react'; import { AuthenticationCard } from '../AuthenticationCard'; -import { Box, CardHeader, Divider, Stack, Typography } from '@mui/material'; +import { Box, Divider, Stack, Typography } from '@mui/material'; import AccountCreatedIcon from '@/assets/account-created.svg'; import { useTranslation } from 'react-i18next'; import { Link as RouterLink, useSearchParams } from 'react-router-dom'; diff --git a/src/features/authorization/components/AccountCreated/AccountCreatedClubBanner.tsx b/src/features/authorization/components/AccountCreated/AccountCreatedClubBanner.tsx index 213e17c..bc77e4b 100644 --- a/src/features/authorization/components/AccountCreated/AccountCreatedClubBanner.tsx +++ b/src/features/authorization/components/AccountCreated/AccountCreatedClubBanner.tsx @@ -1,7 +1,5 @@ import { Stack, Typography, useTheme } from '@mui/material'; -import { Icon } from '@rkheftan/harmony-ui'; -import { Box, Profile2User } from 'iconsax-react'; -import React from 'react'; +import { Profile2User } from 'iconsax-react'; import { useTranslation } from 'react-i18next'; export const AccountCreatedClubBanner = () => { diff --git a/src/features/authorization/components/AccountCreated/AccountCreatedRedirectButton.tsx b/src/features/authorization/components/AccountCreated/AccountCreatedRedirectButton.tsx index 1cd78cb..199652c 100644 --- a/src/features/authorization/components/AccountCreated/AccountCreatedRedirectButton.tsx +++ b/src/features/authorization/components/AccountCreated/AccountCreatedRedirectButton.tsx @@ -1,6 +1,6 @@ import { useMemo } from 'react'; import type { RequestedApplication } from './AccountCreated'; -import { Box, Button, useTheme } from '@mui/material'; +import { Box, Button } from '@mui/material'; import { useTranslation } from 'react-i18next'; import { CountDownTimer } from '@/components/CountDownTimer'; import type { PalleteColor } from '@/theme/palette'; diff --git a/src/features/authorization/components/AuthenticationSteps/AuthenticationSteps.tsx b/src/features/authorization/components/AuthenticationSteps/AuthenticationSteps.tsx index 344427b..bd5ca98 100644 --- a/src/features/authorization/components/AuthenticationSteps/AuthenticationSteps.tsx +++ b/src/features/authorization/components/AuthenticationSteps/AuthenticationSteps.tsx @@ -6,7 +6,7 @@ import { isNumeric } from '@/utils/regexes/isNumeric'; import { CompleteSignUp } from './CompleteSignUp'; import { EnterPasswordForm } from './EnterPasswordForm'; import { UserStatus } from '../../types/userTypes'; -import type { CountryCode, GUID } from '@/types/commonTypes'; +import type { CountryCode } from '@/types/commonTypes'; import { VerifyPhoneNumber } from './VerifyPhoneNumber'; import { useNavigate, useSearchParams } from 'react-router-dom'; diff --git a/src/features/profile/components/security/PasswordDialog.tsx b/src/features/profile/components/security/PasswordDialog.tsx index a0bdf2d..2aefd9b 100644 --- a/src/features/profile/components/security/PasswordDialog.tsx +++ b/src/features/profile/components/security/PasswordDialog.tsx @@ -10,11 +10,14 @@ import { Link, CircularProgress, Typography, + InputAdornment, } from '@mui/material'; -import { CloseCircle } from 'iconsax-react'; +import { CloseCircle, Eye, EyeSlash } from 'iconsax-react'; import { Icon } from '@rkheftan/harmony-ui'; import { type PasswordDialogProps } from '../../types/settingsType'; import { PasswordValidationItem } from './PasswordValidation'; +import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; export function PasswordDialog({ open, @@ -27,7 +30,6 @@ export function PasswordDialog({ currentPassword, setCurrentPassword, showValidation, - validPassword, matchPassword, loading, handleSubmit, @@ -39,6 +41,11 @@ export function PasswordDialog({ hasUpperAndLower, hasSpecialChar, }: PasswordDialogProps) { + const [showCurrent, setShowCurrent] = useState(false); + const [showNew, setShowNew] = useState(false); + const [showConfirm, setShowConfirm] = useState(false); + const navigate = useNavigate(); + return ( setCurrentPassword(e.target.value)} sx={{ '& .MuiOutlinedInput-root': { borderRadius: 2 }, mt: 2 }} + InputProps={{ + endAdornment: ( + + setShowCurrent(!showCurrent)}> + + + + ), + }} /> - + navigate('/forget-password')} + > {t('securityForm.forgetPassword')} @@ -94,11 +113,20 @@ export function PasswordDialog({ setPassword(e.target.value)} sx={{ '& .MuiOutlinedInput-root': { borderRadius: 2 }, mt: 2 }} + InputProps={{ + endAdornment: ( + + setShowNew(!showNew)}> + + + + ), + }} /> {showValidation && ( @@ -124,7 +152,7 @@ export function PasswordDialog({ setConfirmPassword(e.target.value)} @@ -135,6 +163,15 @@ export function PasswordDialog({ : ' ' } sx={{ '& .MuiOutlinedInput-root': { borderRadius: 2 } }} + InputProps={{ + endAdornment: ( + + setShowConfirm(!showConfirm)}> + + + + ), + }} /> @@ -144,7 +181,6 @@ export function PasswordDialog({ sx={{ height: 48, textTransform: 'none' }} variant="contained" onClick={handleSubmit} - disabled={!validPassword || !matchPassword || loading} > {loading ? ( diff --git a/src/features/profile/components/security/PasswordSecurity.tsx b/src/features/profile/components/security/PasswordSecurity.tsx index 825f2af..4a12176 100644 --- a/src/features/profile/components/security/PasswordSecurity.tsx +++ b/src/features/profile/components/security/PasswordSecurity.tsx @@ -94,23 +94,26 @@ export function PasswordSecurity() { setPassword(''); setConfirmPassword(''); setCurrentPassword(''); - } - }, [addData, changeData, changePasswordUI, showToast, t]); - - useEffect(() => { - if (addError || changeError) { + } else if (addData || changeData) { showToast({ message: - getErrorMessage(addError || changeError) || t('securityForm.general'), + addData?.message || changeData?.message || t('securityForm.error'), severity: 'error', }); } - }, [addError, changeError, t, showToast]); + }, [addData, changeData, changePasswordUI, showToast, t]); const handleOpen = () => setOpen(true); const handleClose = () => setOpen(false); const handlePasswordSubmit = async () => { + if (!matchPassword) { + showToast({ + message: t('securityForm.notCompatibility'), + severity: 'error', + }); + return; + } if (changePasswordUI) { await executeChangePassword({ oldPassword: currentPassword, diff --git a/src/features/profile/components/userInformation/PersonalInformation.tsx b/src/features/profile/components/userInformation/PersonalInformation.tsx index 32e077d..eaf6078 100644 --- a/src/features/profile/components/userInformation/PersonalInformation.tsx +++ b/src/features/profile/components/userInformation/PersonalInformation.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react'; +import { useState, useEffect, useRef } from 'react'; import { Box, Button, Typography, CircularProgress } from '@mui/material'; import { useTranslation } from 'react-i18next'; import { CardContainer } from '@/components/CardContainer'; @@ -25,13 +25,13 @@ export function PersonalInformation() { }); const [originalData, setOriginalData] = useState(null); const showToast = useToast(); + const infoRowEditRef = useRef<{ validateFields: () => boolean }>(null); const { data: profileData, loading: isLoadingProfile, error: fetchProfileError, } = useApi(fetchProfile, { immediate: true }); - const { data: saveData, loading: isSavingProfile, @@ -50,18 +50,14 @@ export function PersonalInformation() { : Gender.None, country: profileData.countryCode ?? '', }; - setData(fetchedData); setOriginalData(fetchedData); - - const imageBaseUrl = process.env.IMAGE_BASE_URL; - - if (profileData.profileImageUrl) { - setUploadedImageUrl(`${imageBaseUrl}${profileData.profileImageUrl}`); - } else { - setUploadedImageUrl(null); - } - + const imageBaseUrl = import.meta.env.IMAGE_BASE_URL; + setUploadedImageUrl( + profileData.profileImageUrl + ? `${imageBaseUrl}${profileData.profileImageUrl}` + : null, + ); setUploadedImageFile(null); } }, [profileData]); @@ -80,21 +76,18 @@ export function PersonalInformation() { const initials = `${data?.firstName?.trim()[0] || ''}‌${data?.lastName?.trim()[0] || ''}`; - const handleEditClick = () => { - setIsEditing(true); - setOriginalData(data); - }; + const handleEditClick = () => setIsEditing(true); const handleCancelClick = () => { setIsEditing(false); - if (originalData) { - setData(originalData); - } + if (originalData) setData(originalData); setUploadedImageFile(null); }; - const handleSaveClick = async () => { + const handleSaveClick = () => { if (!data) return; + const isValid = infoRowEditRef.current?.validateFields?.(); + if (!isValid) return; executeSaveProfile({ data, imageUrl: uploadedImageFile }); }; @@ -105,23 +98,21 @@ export function PersonalInformation() { }; useEffect(() => { - if (saveProfileError) { + if (saveProfileError) showToast({ message: getErrorMessage(saveProfileError) || t('settingForm.errorSave'), severity: 'error', }); - } }, [saveProfileError, showToast, t]); useEffect(() => { - if (fetchProfileError) { + if (fetchProfileError) showToast({ message: getErrorMessage(fetchProfileError) || t('settingForm.errorFetch'), severity: 'error', }); - } }, [fetchProfileError, showToast, t]); return ( @@ -131,12 +122,7 @@ export function PersonalInformation() { subtitle={t('settingForm.descriptionPersonalInfo')} highlighted={isEditing} action={ - + {isEditing ? ( <> @@ -210,46 +194,48 @@ export function PersonalInformation() { ) : ( - <> - - {isEditing && ( - { - setUploadedImageFile(file); - const reader = new FileReader(); - reader.onload = () => - setUploadedImageUrl(reader.result as string); - reader.readAsDataURL(file); - }} - onRemoveImage={() => { - setUploadedImageFile(null); - setUploadedImageUrl(null); - }} + + {isEditing && ( + { + setUploadedImageFile(file); + const reader = new FileReader(); + reader.onload = () => + setUploadedImageUrl(reader.result as string); + reader.readAsDataURL(file); + }} + onRemoveImage={() => { + setUploadedImageFile(null); + setUploadedImageUrl(null); + }} + /> + )} + {data && + (isEditing ? ( + - )} - {data && - (isEditing ? ( - - ) : ( - - ))} - - + ) : ( + + ))} + )} diff --git a/src/features/profile/components/userInformation/PhoneNumber.tsx b/src/features/profile/components/userInformation/PhoneNumber.tsx index 266f64e..2ff5f75 100644 --- a/src/features/profile/components/userInformation/PhoneNumber.tsx +++ b/src/features/profile/components/userInformation/PhoneNumber.tsx @@ -141,12 +141,8 @@ export function PhoneNumber() { }, ]); setIsEditing(false); - toast({ - message: t('settingForm.phoneChangedSuccessfully'), - severity: 'success', - }); } - }, [changePhoneData, countryCode, phoneNumber, t, toast]); + }, [changePhoneData, countryCode, phoneNumber, t]); useEffect(() => { if (changePhoneError) { @@ -203,10 +199,10 @@ export function PhoneNumber() { }); }; - const handleSendCode = () => { + const handleSendCode = async () => { handleBlur(); if (formError || !isPhoneValid(countryCode, phoneNumber)) return; - executeSendCode({ + return executeSendCode({ phoneNumber: countryCode + phoneNumber.replace(/^0/, ''), }); }; diff --git a/src/features/profile/components/userInformation/personalInformation/InfoRowDisplay.tsx b/src/features/profile/components/userInformation/personalInformation/InfoRowDisplay.tsx index 9bb46a2..408f514 100644 --- a/src/features/profile/components/userInformation/personalInformation/InfoRowDisplay.tsx +++ b/src/features/profile/components/userInformation/personalInformation/InfoRowDisplay.tsx @@ -4,15 +4,21 @@ import { DisplayField } from './DisplayField'; import { Gender } from '@/features/profile/types/settingsType'; import { type InfoRowDisplayProps } from '@/features/profile/types/settingsType'; import ReactCountryFlag from 'react-country-flag'; +import { countries } from '@/data/countries'; export function InfoRowDisplay({ data, uploadedImageUrl, initials, }: InfoRowDisplayProps) { - const { t } = useTranslation('setting'); + const { t } = useTranslation(['setting', 'country']); const displayValue = (value: string) => value?.trim() || t('settingForm.notDetermined'); + const countryLabel = + data.country && + t(countries.find((c) => c.code === data.country)?.label || '', { + ns: 'country', + }); const getGenderLabel = (gender: Gender | '') => { switch (gender) { @@ -70,19 +76,20 @@ export function InfoRowDisplay({ {t('settingForm.country')} - + {data.country ? ( - + <> + + + {countryLabel} + + ) : ( {t('settingForm.notDetermined')} diff --git a/src/features/profile/components/userInformation/personalInformation/InfoRowEdit.tsx b/src/features/profile/components/userInformation/personalInformation/InfoRowEdit.tsx index f05dfd6..5bf9d27 100644 --- a/src/features/profile/components/userInformation/personalInformation/InfoRowEdit.tsx +++ b/src/features/profile/components/userInformation/personalInformation/InfoRowEdit.tsx @@ -6,123 +6,175 @@ import { MenuItem, Select, Autocomplete, + FormHelperText, } from '@mui/material'; import { useTranslation } from 'react-i18next'; import { countries } from '@/data/countries'; import { Gender } from '@/features/profile/types/settingsType'; import { type InfoRowEditProps } from '@/features/profile/types/settingsType'; import ReactCountryFlag from 'react-country-flag'; +import { useState, forwardRef, useImperativeHandle } from 'react'; -export function InfoRowEdit({ data, setData }: InfoRowEditProps) { - const { t } = useTranslation(['countries', 'setting']); +export const InfoRowEdit = forwardRef( + ({ data, setData }: InfoRowEditProps, ref) => { + const { t } = useTranslation(['country', 'setting']); + const [touched, setTouched] = useState({ + firstName: false, + lastName: false, + gender: false, + country: false, + }); - const countryOptions = countries.map((c) => ({ - code: c.code, - label: t(c.label, { ns: 'countries' }), - })); + const isValidName = (str: string) => /[A-Za-z\u0600-\u06FF]+/.test(str); - const currentCountry = - countryOptions.find((c) => c.code === data.country) || null; - const fields = [ - { - name: 'firstName' as const, - label: t('settingForm.name', { ns: 'setting' }), - value: data.firstName, - }, - { - name: 'lastName' as const, - label: t('settingForm.familyName', { ns: 'setting' }), - value: data.lastName, - }, - { - name: 'nationalCode' as const, - label: t('settingForm.nationalCode', { ns: 'setting' }), - value: data.nationalCode, - }, - ]; + useImperativeHandle(ref, () => ({ + validateFields: () => { + const newTouched = { + firstName: true, + lastName: true, + gender: true, + country: true, + }; + setTouched(newTouched); - return ( - - {fields.map(({ name, label, value }) => ( - - - setData((prev) => ({ - ...prev, - [name]: e.target.value, - })) - } - label={label} - /> - - ))} + return ( + data.firstName.trim() !== '' && + isValidName(data.firstName) && + data.lastName.trim() !== '' && + isValidName(data.lastName) && + data.gender !== Gender.None && + data.country !== '' + ); + }, + })); - - - - {t('settingForm.genderPlaceholder', { ns: 'setting' })} - - - - - - option.label} - value={currentCountry} - onChange={(_, newValue) => - setData((prev) => ({ - ...prev, - country: newValue?.code || '', - })) - } - renderOption={(props, option) => ( - - + setData((prev) => ({ ...prev, [name]: e.target.value })) + } + label={label} + error={ + name !== 'nationalCode' && + touched[name] && + (value.trim() === '' || !isValidName(value)) + } + helperText={ + name !== 'nationalCode' && + touched[name] && + (value.trim() === '' || !isValidName(value)) + ? t('settingForm.thisFieldIsRequired', { ns: 'setting' }) + : undefined + } /> - {option.label} - )} - renderInput={(params) => ( - - )} - clearOnEscape - /> - - ); -} + ))} + + + + + {t('settingForm.genderPlaceholder', { ns: 'setting' })} + + + + {touched.gender && data.gender === Gender.None + ? t('settingForm.thisFieldIsRequired', { ns: 'setting' }) + : ''} + + + + + option.label} + value={currentCountry} + onChange={(_, newValue) => + setData((prev) => ({ ...prev, country: newValue?.code || '' })) + } + renderOption={(props, option) => ( + + + {option.label} + + )} + renderInput={(params) => ( + + )} + clearOnEscape + /> + + ); + }, +); diff --git a/src/features/profile/components/userInformation/phoneNumber/PhoneEditForm.tsx b/src/features/profile/components/userInformation/phoneNumber/PhoneEditForm.tsx index 081a7ef..2ecf6c1 100644 --- a/src/features/profile/components/userInformation/phoneNumber/PhoneEditForm.tsx +++ b/src/features/profile/components/userInformation/phoneNumber/PhoneEditForm.tsx @@ -45,7 +45,7 @@ export default function PhoneEditForm({ return ( <> - + {t('settingForm.editPhoneNumber')} @@ -59,10 +59,12 @@ export default function PhoneEditForm({ setPhoneNumber(e.target.value)} - sx={{ flex: '1 1 220px' }} placeholder="09123456789" + sx={{ width: { xs: '100%', sm: 474 } }} InputProps={{ endAdornment: buttonState === 'counting' ? ( @@ -142,9 +144,10 @@ export default function PhoneEditForm({ !isValidPhoneNumber(phoneNumber) } sx={{ - minWidth: { xs: '100%', sm: 220 }, + whiteSpace: 'nowrap', color: 'primary.main', textTransform: 'none', + width: { xs: '100%', sm: 210 }, }} > {isSending ? ( @@ -165,11 +168,12 @@ export default function PhoneEditForm({ setVerificationCode(e.target.value.replace(/\D/g, '')) } - sx={{ flex: '1 1 240px', minWidth: 0 }} + sx={{ width: { xs: '100%', sm: 474 } }} placeholder={t('settingForm.verificationCode')} /> @@ -189,7 +193,7 @@ export default function PhoneEditForm({ onClick={handleVerifyClick} disabled={isVerifying || verificationCode.length === 0} sx={{ - minWidth: { xs: '100%', sm: 220 }, + width: { xs: '100%', sm: 210 }, bgcolor: 'primary.main', textTransform: 'none', }} diff --git a/src/features/profile/components/userInformation/socialMedia/SocialMediaDialog.tsx b/src/features/profile/components/userInformation/socialMedia/SocialMediaDialog.tsx index 7d7b48a..7715624 100644 --- a/src/features/profile/components/userInformation/socialMedia/SocialMediaDialog.tsx +++ b/src/features/profile/components/userInformation/socialMedia/SocialMediaDialog.tsx @@ -1,4 +1,4 @@ -import React, { type ReactElement, type ElementType } from 'react'; +import React, { type ReactElement, type ElementType, useState } from 'react'; import { Box, Button, @@ -15,6 +15,7 @@ import type { TransitionProps } from '@mui/material/transitions'; import { CloseCircle } from 'iconsax-react'; import { Icon } from '@rkheftan/harmony-ui'; import { type SocialMediaDialogProps } from '@/features/profile/types/settingsType'; +import { isEmail } from '@/utils/regexes/isEmail'; const MobileSlide = React.forwardRef(function MobileSlide( props: TransitionProps & { children: ReactElement }, @@ -30,57 +31,58 @@ export default function SocialMediaDialog({ emailInput, setEmailInput, fullScreen, - computedMaxWidth, verificationCode, setVerificationCode, - apiError, isLoading, dialogStep, onSendCode, onConfirmEmail, }: SocialMediaDialogProps) { + const [emailError, setEmailError] = useState(); + const [touched, setTouched] = useState(false); + + const validateEmail = (value: string) => { + if (!value) { + setEmailError(t('settingForm.thisFieldIsRequired')); + return false; + } + if (!isEmail(value)) { + setEmailError(t('settingForm.emailIsInvalid')); + return false; + } + setEmailError(undefined); + return true; + }; + return ( - - - - - {t('settingForm.addEmailButton')} + + + + + + + {t('settingForm.addEmailButton')} + + @@ -94,43 +96,46 @@ export default function SocialMediaDialog({ fullWidth type="email" value={emailInput} - onChange={(e) => setEmailInput(e.target.value)} + onChange={(e) => { + setEmailInput(e.target.value); + if (touched) validateEmail(e.target.value); + }} + onBlur={() => { + setTouched(true); + validateEmail(emailInput); + }} label={t('settingForm.email')} placeholder="abc@email.com" autoComplete="email" inputMode="email" - sx={{ '& .MuiOutlinedInput-root': { borderRadius: 2 } }} + sx={{ '& .MuiOutlinedInput-root': { borderRadius: 2 }, mt: 2 }} autoFocus disabled={isLoading || dialogStep === 'enterCode'} + error={touched && !!emailError} + helperText={touched && emailError ? emailError : ' '} /> {dialogStep === 'enterCode' && ( - <> - setVerificationCode(e.target.value)} - label={t('settingForm.verificationCode')} - autoComplete="one-time-code" - inputMode="numeric" - sx={{ '& .MuiOutlinedInput-root': { borderRadius: 2 } }} - autoFocus - disabled={isLoading} - /> - - )} - - {apiError && ( - - {apiError} - + setVerificationCode(e.target.value)} + label={t('settingForm.verificationCode')} + autoComplete="one-time-code" + inputMode="numeric" + sx={{ '& .MuiOutlinedInput-root': { borderRadius: 2 } }} + autoFocus + disabled={isLoading} + /> )} + + - + ); } diff --git a/src/features/profile/components/userInformation/socialMedia/SocialMediaList.tsx b/src/features/profile/components/userInformation/socialMedia/SocialMediaList.tsx index 85782c2..2f0a0e0 100644 --- a/src/features/profile/components/userInformation/socialMedia/SocialMediaList.tsx +++ b/src/features/profile/components/userInformation/socialMedia/SocialMediaList.tsx @@ -1,5 +1,5 @@ -import { Box, Typography, IconButton } from '@mui/material'; -import { Google, Sms, Trash } from 'iconsax-react'; +import { Box, Typography } from '@mui/material'; +import { Google, Sms } from 'iconsax-react'; import { Icon } from '@rkheftan/harmony-ui'; import { type SocialMediaListProps } from '@/features/profile/types/settingsType'; @@ -64,10 +64,6 @@ export default function SocialMediaList({ emailList }: SocialMediaListProps) { - - - - ))} diff --git a/src/features/profile/components/userInformation/socialMedia/SocialMediaMenu.tsx b/src/features/profile/components/userInformation/socialMedia/SocialMediaMenu.tsx index ebc3f9c..0716d57 100644 --- a/src/features/profile/components/userInformation/socialMedia/SocialMediaMenu.tsx +++ b/src/features/profile/components/userInformation/socialMedia/SocialMediaMenu.tsx @@ -74,8 +74,8 @@ export default function SocialMediaMenu({ onClose={handleCloseMenu} PaperProps={{ sx: { - minWidth: 187, - maxWidth: '90vw', + width: anchor ? anchor.offsetWidth : 'auto', + // maxWidth: '90vw', }, }} anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }} diff --git a/src/features/profile/routes/ActiveDevicesPage.tsx b/src/features/profile/routes/ActiveDevicesPage.tsx index 9c6fcca..5ce46d5 100644 --- a/src/features/profile/routes/ActiveDevicesPage.tsx +++ b/src/features/profile/routes/ActiveDevicesPage.tsx @@ -49,7 +49,14 @@ export function ActiveDevicesPage() { ip: session.ipAddress, current: session.key === currentKey, })); - setDevices(formattedDevices); + + const sortedDevices = formattedDevices.sort((a, b) => { + if (a.current && !b.current) return -1; + if (!a.current && b.current) return 1; + return 0; + }); + + setDevices(sortedDevices); } }, [profileData, i18n.language, t]); @@ -66,6 +73,7 @@ export function ActiveDevicesPage() { const { data } = await deleteSessions({ keys: [id] }); if (data.success) { setDevices((prevDevices) => prevDevices.filter((d) => d.id !== id)); + showToast({ message: t('active.successDelete'), severity: 'success' }); } else { showToast({ message: data.message || t('active.deleteFailed'), @@ -73,7 +81,6 @@ export function ActiveDevicesPage() { }); } } catch (error: unknown) { - // console.error('Delete error:', error); showToast({ message: t('active.deleteFailed'), severity: 'error', diff --git a/src/features/profile/routes/SettingPage.tsx b/src/features/profile/routes/SettingPage.tsx index b1da343..7651cbe 100644 --- a/src/features/profile/routes/SettingPage.tsx +++ b/src/features/profile/routes/SettingPage.tsx @@ -59,7 +59,6 @@ export function SettingPage() { } = useApi(fetchProfile); const { - data: saveData, loading: isSaving, error: saveError, execute: executeSaveSettings, @@ -87,15 +86,6 @@ export function SettingPage() { } }, [profileData, setMode, i18n]); - useEffect(() => { - if (saveData?.success) { - setMode(draftSettings.theme); - setSavedSettings(draftSettings); - i18n.changeLanguage(draftSettings.language); - setIsEditing(false); - } - }, [saveData, draftSettings, setMode, i18n]); - useEffect(() => { if (isEditing) { const resolvedMode = mode === 'light' || mode === 'dark' ? mode : 'light'; @@ -109,7 +99,7 @@ export function SettingPage() { setMode(savedSettings.theme); }; - const handleEditToggle = () => { + const handleEditToggle = async () => { if (isEditing) { const languageObj = languageOptions.find( (o) => o.code === draftSettings.language, @@ -119,11 +109,18 @@ export function SettingPage() { ); if (languageObj && calendarObj) { - executeSaveSettings({ + const result = await executeSaveSettings({ theme: themeApiMap[draftSettings.theme], calendarType: calendarObj.apiValue, language: languageObj.apiValue, }); + + if (result?.success) { + setMode(draftSettings.theme); + setSavedSettings(draftSettings); + i18n.changeLanguage(draftSettings.language); + setIsEditing(false); + } } } else { setIsEditing(true); @@ -164,11 +161,13 @@ export function SettingPage() { variant={isEditing ? 'contained' : 'outlined'} disabled={isSaving || isFetching} > - {isSaving - ? t('settings.saving') - : isEditing - ? t('settings.saveButton') - : t('settings.editButton')} + {isSaving ? ( + + ) : isEditing ? ( + t('settings.saveButton') + ) : ( + t('settings.editButton') + )} } @@ -211,40 +210,54 @@ export function SettingPage() { display: 'flex', flexDirection: { xs: 'column', sm: 'row' }, gap: 4, - mt: 2, }} > - - {t('settings.theme')} - {isEditing ? ( - { - setDraftSettings((prev) => ({ - ...prev, - theme: newTheme, - })); + - ) : ( - - - - {t(`settings.${savedSettings.theme}`)} + > + + {t('settings.theme')} + { + if (newTheme) { + setMode(newTheme); + setDraftSettings((prev) => ({ + ...prev, + theme: newTheme, + })); + } + }} + /> + ) : ( + <> + + {t('settings.theme')} + + + + + {t(`settings.${savedSettings.theme}`)} + + + )} - - {t('settings.language')} - {isEditing ? ( } + renderInput={(p) => ( + + )} size="medium" fullWidth disableClearable /> ) : ( - - { - languageOptions.find( - (o) => o.code === savedSettings.language, - )?.label - } - + <> + + {t('settings.language')} + + + { + languageOptions.find( + (o) => o.code === savedSettings.language, + )?.label + } + + )} - - {t('settings.calendar')} - {isEditing ? ( c.key)} @@ -287,18 +304,25 @@ export function SettingPage() { onChange={(_, v) => v && setDraftSettings((prev) => ({ ...prev, calendar: v })) } - renderInput={(params) => } + renderInput={(params) => ( + + )} size="medium" fullWidth disableClearable /> ) : ( - - - - {t(`settings.${savedSettings.calendar}`)} + <> + + {t('settings.calendar')} - + + + + {t(`settings.${savedSettings.calendar}`)} + + + )} From 59032dd285016dd883df933869792834663e1e19 Mon Sep 17 00:00:00 2001 From: Koosha Lahouti Date: Wed, 20 Aug 2025 01:04:17 +0330 Subject: [PATCH 2/6] fix: toast in phone number section --- .../profile/components/userInformation/PhoneNumber.tsx | 4 ++++ .../userInformation/phoneNumber/PhoneEditForm.tsx | 6 ------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/features/profile/components/userInformation/PhoneNumber.tsx b/src/features/profile/components/userInformation/PhoneNumber.tsx index 2ff5f75..aa8c505 100644 --- a/src/features/profile/components/userInformation/PhoneNumber.tsx +++ b/src/features/profile/components/userInformation/PhoneNumber.tsx @@ -174,6 +174,10 @@ export function PhoneNumber() { const handleBlur = () => { setTouched(true); if (!phoneNumber) { + toast({ + message: t('settingForm.phoneNumberIsInvalid'), + severity: 'error', + }); setFormError(t('settingForm.thisFieldIsRequired')); return; } diff --git a/src/features/profile/components/userInformation/phoneNumber/PhoneEditForm.tsx b/src/features/profile/components/userInformation/phoneNumber/PhoneEditForm.tsx index 2ecf6c1..4e20ab5 100644 --- a/src/features/profile/components/userInformation/phoneNumber/PhoneEditForm.tsx +++ b/src/features/profile/components/userInformation/phoneNumber/PhoneEditForm.tsx @@ -137,12 +137,6 @@ export default function PhoneEditForm({ } } }} - disabled={ - isSending || - buttonState === 'counting' || - phoneNumber.length === 0 || - !isValidPhoneNumber(phoneNumber) - } sx={{ whiteSpace: 'nowrap', color: 'primary.main', From 32433c9a2c58cf459d36de40d38f72f09e354a7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D9=85=D9=87=D8=B1=D8=B2=D8=A7=D8=AF=20=D9=82=D8=AF=D8=B1?= =?UTF-8?q?=D8=AA=DB=8C?= Date: Wed, 20 Aug 2025 14:33:15 +0330 Subject: [PATCH 3/6] feat: 404 page redirect with toast added --- public/locales/en/common.json | 1 + public/locales/fa/common.json | 1 + src/components/NavigateWithToast.tsx | 24 ++++++++++++++++++++++++ src/main.tsx | 10 +++++----- src/routes/config.tsx | 12 ++++++++++++ 5 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 src/components/NavigateWithToast.tsx diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 5196be8..2b38d64 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -248,6 +248,7 @@ "zimbabwe": "Zimbabwe" }, "messages": { + "pageNotFound": "Page not found", "noResualtFound": "No result found.", "serverError": "Internal server error" } diff --git a/public/locales/fa/common.json b/public/locales/fa/common.json index 878b22d..bf8918b 100644 --- a/public/locales/fa/common.json +++ b/public/locales/fa/common.json @@ -185,6 +185,7 @@ "zimbabwe": "زیمبابوه" }, "messages": { + "pageNotFound": "صفحه مورد نظر پیدا نشد.", "noResualtFound": "نتیجه ای یافت نشد.", "serverError": "خطای سمت سرور" }, diff --git a/src/components/NavigateWithToast.tsx b/src/components/NavigateWithToast.tsx new file mode 100644 index 0000000..51a133f --- /dev/null +++ b/src/components/NavigateWithToast.tsx @@ -0,0 +1,24 @@ +import { useToast, type ToastOptions } from '@rkheftan/harmony-ui'; +import React, { useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Navigate } from 'react-router-dom'; + +export interface NavigateWithToastProps extends ToastOptions { + to: string; + replace?: boolean; + translator?: string; +} + +export const NavigateWithToast = (props: NavigateWithToastProps) => { + const { t } = useTranslation(props.translator ?? 'common'); + const toast = useToast(); + + useEffect(() => { + toast({ + ...props, + message: t(props.message), + }); + }, []); + + return ; +}; diff --git a/src/main.tsx b/src/main.tsx index be3d73c..2f74b23 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -5,9 +5,9 @@ import App from './App'; import { AppProviders } from './providers/AppProvider'; createRoot(document.getElementById('root')!).render( - - - - - , + // + + + , + // , ); diff --git a/src/routes/config.tsx b/src/routes/config.tsx index 760815d..e1e0e01 100644 --- a/src/routes/config.tsx +++ b/src/routes/config.tsx @@ -1,4 +1,5 @@ import { Layout } from '@/components'; +import { NavigateWithToast } from '@/components/NavigateWithToast'; import { AccountCreatedPage } from '@/features/authorization/routes/AccountCreatedPage'; import { Calendar, @@ -65,6 +66,17 @@ export interface RouteConfig { // can lazy load component if needed (ex. lazy(() => import('@/features/home/routes/HomePage'));) export const appRoutes: RouteConfig[] = [ + { + path: '*', + element: ( + + ), + }, { path: '/', element: , From 8a4509ffd7b012b62dc1dc756b443d167433a45e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D9=85=D9=87=D8=B1=D8=B2=D8=A7=D8=AF=20=D9=82=D8=AF=D8=B1?= =?UTF-8?q?=D8=AA=DB=8C?= Date: Wed, 20 Aug 2025 14:49:24 +0330 Subject: [PATCH 4/6] fix: strict mode uncommented --- src/main.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main.tsx b/src/main.tsx index 2f74b23..be3d73c 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -5,9 +5,9 @@ import App from './App'; import { AppProviders } from './providers/AppProvider'; createRoot(document.getElementById('root')!).render( - // - - - , - // , + + + + + , ); From 882498637b47d0726ac16e16873de6f0292ba437 Mon Sep 17 00:00:00 2001 From: mehrzadghdev Date: Wed, 20 Aug 2025 23:28:18 +0330 Subject: [PATCH 5/6] feat: layout padding and scroll added --- src/components/Layout/Layout.tsx | 10 +++++++++- .../api/authorizationAPI.ts | 0 .../api/identityAPI.ts | 0 .../api/userCompletion.ts | 0 .../components/AccountCreated/AccountCreated.tsx | 0 .../AccountCreated/AccountCreatedClubBanner.tsx | 0 .../AccountCreated/AccountCreatedRedirectButton.tsx | 0 .../components/AuthenticationCard.tsx | 0 .../AuthenticationSteps/AuthenticationSteps.tsx | 0 .../AuthenticationSteps/CompleteSignUp.tsx | 0 .../AuthenticationSteps/EnterPasswordForm.tsx | 0 .../AuthenticationSteps/GoogleAuthentication.tsx | 0 .../AuthenticationSteps/LoginRegiserForm.tsx | 0 .../components/AuthenticationSteps/OtpVerifyForm.tsx | 0 .../AuthenticationSteps/VerifyPhoneNumber.tsx | 0 .../components/CountryCodeSelector.tsx | 0 .../components/ForgetPassword/ChangePassword.tsx | 0 .../ForgetPassword/ForgetPasswordContainer.tsx | 0 .../components/ForgetPassword/ForgetPasswordOtp.tsx | 0 .../ForgetPassword/ForgettedPasswordInfo.tsx | 0 .../components/UserCompletionForm/DateOfBirth.tsx | 0 .../components/UserCompletionForm/EmailSection.tsx | 0 .../UserCompletionForm/PasswordSection.tsx | 0 .../UserCompletionForm/PasswordValidation.tsx | 0 .../UserCompletionForm/PersonalInfoFields.tsx | 0 .../components/UserCompletionForm/SubmitSection.tsx | 0 .../{authorization => authentication}/index.ts | 1 + .../routes/AccountCreatedPage.tsx | 0 .../routes/AuthenticationPage.tsx | 0 .../routes/ForgetPasswordPage.tsx | 0 .../routes/UserCompletionPage.tsx | 0 .../types/authTypes.ts | 0 .../types/completionFormApiTypes.ts | 0 .../types/settingForm.ts | 0 .../types/userTypes.ts | 0 src/providers/AuthProvider.tsx | 2 +- src/routes/config.tsx | 12 ++++++++---- 37 files changed, 19 insertions(+), 6 deletions(-) rename src/features/{authorization => authentication}/api/authorizationAPI.ts (100%) rename src/features/{authorization => authentication}/api/identityAPI.ts (100%) rename src/features/{authorization => authentication}/api/userCompletion.ts (100%) rename src/features/{authorization => authentication}/components/AccountCreated/AccountCreated.tsx (100%) rename src/features/{authorization => authentication}/components/AccountCreated/AccountCreatedClubBanner.tsx (100%) rename src/features/{authorization => authentication}/components/AccountCreated/AccountCreatedRedirectButton.tsx (100%) rename src/features/{authorization => authentication}/components/AuthenticationCard.tsx (100%) rename src/features/{authorization => authentication}/components/AuthenticationSteps/AuthenticationSteps.tsx (100%) rename src/features/{authorization => authentication}/components/AuthenticationSteps/CompleteSignUp.tsx (100%) rename src/features/{authorization => authentication}/components/AuthenticationSteps/EnterPasswordForm.tsx (100%) rename src/features/{authorization => authentication}/components/AuthenticationSteps/GoogleAuthentication.tsx (100%) rename src/features/{authorization => authentication}/components/AuthenticationSteps/LoginRegiserForm.tsx (100%) rename src/features/{authorization => authentication}/components/AuthenticationSteps/OtpVerifyForm.tsx (100%) rename src/features/{authorization => authentication}/components/AuthenticationSteps/VerifyPhoneNumber.tsx (100%) rename src/features/{authorization => authentication}/components/CountryCodeSelector.tsx (100%) rename src/features/{authorization => authentication}/components/ForgetPassword/ChangePassword.tsx (100%) rename src/features/{authorization => authentication}/components/ForgetPassword/ForgetPasswordContainer.tsx (100%) rename src/features/{authorization => authentication}/components/ForgetPassword/ForgetPasswordOtp.tsx (100%) rename src/features/{authorization => authentication}/components/ForgetPassword/ForgettedPasswordInfo.tsx (100%) rename src/features/{authorization => authentication}/components/UserCompletionForm/DateOfBirth.tsx (100%) rename src/features/{authorization => authentication}/components/UserCompletionForm/EmailSection.tsx (100%) rename src/features/{authorization => authentication}/components/UserCompletionForm/PasswordSection.tsx (100%) rename src/features/{authorization => authentication}/components/UserCompletionForm/PasswordValidation.tsx (100%) rename src/features/{authorization => authentication}/components/UserCompletionForm/PersonalInfoFields.tsx (100%) rename src/features/{authorization => authentication}/components/UserCompletionForm/SubmitSection.tsx (100%) rename src/features/{authorization => authentication}/index.ts (75%) rename src/features/{authorization => authentication}/routes/AccountCreatedPage.tsx (100%) rename src/features/{authorization => authentication}/routes/AuthenticationPage.tsx (100%) rename src/features/{authorization => authentication}/routes/ForgetPasswordPage.tsx (100%) rename src/features/{authorization => authentication}/routes/UserCompletionPage.tsx (100%) rename src/features/{authorization => authentication}/types/authTypes.ts (100%) rename src/features/{authorization => authentication}/types/completionFormApiTypes.ts (100%) rename src/features/{authorization => authentication}/types/settingForm.ts (100%) rename src/features/{authorization => authentication}/types/userTypes.ts (100%) diff --git a/src/components/Layout/Layout.tsx b/src/components/Layout/Layout.tsx index 55d15b2..befcc88 100644 --- a/src/components/Layout/Layout.tsx +++ b/src/components/Layout/Layout.tsx @@ -44,7 +44,15 @@ export const Layout = () => { setSideNavOpen={setSideNavOpen} user={userInfo} /> - + diff --git a/src/features/authorization/api/authorizationAPI.ts b/src/features/authentication/api/authorizationAPI.ts similarity index 100% rename from src/features/authorization/api/authorizationAPI.ts rename to src/features/authentication/api/authorizationAPI.ts diff --git a/src/features/authorization/api/identityAPI.ts b/src/features/authentication/api/identityAPI.ts similarity index 100% rename from src/features/authorization/api/identityAPI.ts rename to src/features/authentication/api/identityAPI.ts diff --git a/src/features/authorization/api/userCompletion.ts b/src/features/authentication/api/userCompletion.ts similarity index 100% rename from src/features/authorization/api/userCompletion.ts rename to src/features/authentication/api/userCompletion.ts diff --git a/src/features/authorization/components/AccountCreated/AccountCreated.tsx b/src/features/authentication/components/AccountCreated/AccountCreated.tsx similarity index 100% rename from src/features/authorization/components/AccountCreated/AccountCreated.tsx rename to src/features/authentication/components/AccountCreated/AccountCreated.tsx diff --git a/src/features/authorization/components/AccountCreated/AccountCreatedClubBanner.tsx b/src/features/authentication/components/AccountCreated/AccountCreatedClubBanner.tsx similarity index 100% rename from src/features/authorization/components/AccountCreated/AccountCreatedClubBanner.tsx rename to src/features/authentication/components/AccountCreated/AccountCreatedClubBanner.tsx diff --git a/src/features/authorization/components/AccountCreated/AccountCreatedRedirectButton.tsx b/src/features/authentication/components/AccountCreated/AccountCreatedRedirectButton.tsx similarity index 100% rename from src/features/authorization/components/AccountCreated/AccountCreatedRedirectButton.tsx rename to src/features/authentication/components/AccountCreated/AccountCreatedRedirectButton.tsx diff --git a/src/features/authorization/components/AuthenticationCard.tsx b/src/features/authentication/components/AuthenticationCard.tsx similarity index 100% rename from src/features/authorization/components/AuthenticationCard.tsx rename to src/features/authentication/components/AuthenticationCard.tsx diff --git a/src/features/authorization/components/AuthenticationSteps/AuthenticationSteps.tsx b/src/features/authentication/components/AuthenticationSteps/AuthenticationSteps.tsx similarity index 100% rename from src/features/authorization/components/AuthenticationSteps/AuthenticationSteps.tsx rename to src/features/authentication/components/AuthenticationSteps/AuthenticationSteps.tsx diff --git a/src/features/authorization/components/AuthenticationSteps/CompleteSignUp.tsx b/src/features/authentication/components/AuthenticationSteps/CompleteSignUp.tsx similarity index 100% rename from src/features/authorization/components/AuthenticationSteps/CompleteSignUp.tsx rename to src/features/authentication/components/AuthenticationSteps/CompleteSignUp.tsx diff --git a/src/features/authorization/components/AuthenticationSteps/EnterPasswordForm.tsx b/src/features/authentication/components/AuthenticationSteps/EnterPasswordForm.tsx similarity index 100% rename from src/features/authorization/components/AuthenticationSteps/EnterPasswordForm.tsx rename to src/features/authentication/components/AuthenticationSteps/EnterPasswordForm.tsx diff --git a/src/features/authorization/components/AuthenticationSteps/GoogleAuthentication.tsx b/src/features/authentication/components/AuthenticationSteps/GoogleAuthentication.tsx similarity index 100% rename from src/features/authorization/components/AuthenticationSteps/GoogleAuthentication.tsx rename to src/features/authentication/components/AuthenticationSteps/GoogleAuthentication.tsx diff --git a/src/features/authorization/components/AuthenticationSteps/LoginRegiserForm.tsx b/src/features/authentication/components/AuthenticationSteps/LoginRegiserForm.tsx similarity index 100% rename from src/features/authorization/components/AuthenticationSteps/LoginRegiserForm.tsx rename to src/features/authentication/components/AuthenticationSteps/LoginRegiserForm.tsx diff --git a/src/features/authorization/components/AuthenticationSteps/OtpVerifyForm.tsx b/src/features/authentication/components/AuthenticationSteps/OtpVerifyForm.tsx similarity index 100% rename from src/features/authorization/components/AuthenticationSteps/OtpVerifyForm.tsx rename to src/features/authentication/components/AuthenticationSteps/OtpVerifyForm.tsx diff --git a/src/features/authorization/components/AuthenticationSteps/VerifyPhoneNumber.tsx b/src/features/authentication/components/AuthenticationSteps/VerifyPhoneNumber.tsx similarity index 100% rename from src/features/authorization/components/AuthenticationSteps/VerifyPhoneNumber.tsx rename to src/features/authentication/components/AuthenticationSteps/VerifyPhoneNumber.tsx diff --git a/src/features/authorization/components/CountryCodeSelector.tsx b/src/features/authentication/components/CountryCodeSelector.tsx similarity index 100% rename from src/features/authorization/components/CountryCodeSelector.tsx rename to src/features/authentication/components/CountryCodeSelector.tsx diff --git a/src/features/authorization/components/ForgetPassword/ChangePassword.tsx b/src/features/authentication/components/ForgetPassword/ChangePassword.tsx similarity index 100% rename from src/features/authorization/components/ForgetPassword/ChangePassword.tsx rename to src/features/authentication/components/ForgetPassword/ChangePassword.tsx diff --git a/src/features/authorization/components/ForgetPassword/ForgetPasswordContainer.tsx b/src/features/authentication/components/ForgetPassword/ForgetPasswordContainer.tsx similarity index 100% rename from src/features/authorization/components/ForgetPassword/ForgetPasswordContainer.tsx rename to src/features/authentication/components/ForgetPassword/ForgetPasswordContainer.tsx diff --git a/src/features/authorization/components/ForgetPassword/ForgetPasswordOtp.tsx b/src/features/authentication/components/ForgetPassword/ForgetPasswordOtp.tsx similarity index 100% rename from src/features/authorization/components/ForgetPassword/ForgetPasswordOtp.tsx rename to src/features/authentication/components/ForgetPassword/ForgetPasswordOtp.tsx diff --git a/src/features/authorization/components/ForgetPassword/ForgettedPasswordInfo.tsx b/src/features/authentication/components/ForgetPassword/ForgettedPasswordInfo.tsx similarity index 100% rename from src/features/authorization/components/ForgetPassword/ForgettedPasswordInfo.tsx rename to src/features/authentication/components/ForgetPassword/ForgettedPasswordInfo.tsx diff --git a/src/features/authorization/components/UserCompletionForm/DateOfBirth.tsx b/src/features/authentication/components/UserCompletionForm/DateOfBirth.tsx similarity index 100% rename from src/features/authorization/components/UserCompletionForm/DateOfBirth.tsx rename to src/features/authentication/components/UserCompletionForm/DateOfBirth.tsx diff --git a/src/features/authorization/components/UserCompletionForm/EmailSection.tsx b/src/features/authentication/components/UserCompletionForm/EmailSection.tsx similarity index 100% rename from src/features/authorization/components/UserCompletionForm/EmailSection.tsx rename to src/features/authentication/components/UserCompletionForm/EmailSection.tsx diff --git a/src/features/authorization/components/UserCompletionForm/PasswordSection.tsx b/src/features/authentication/components/UserCompletionForm/PasswordSection.tsx similarity index 100% rename from src/features/authorization/components/UserCompletionForm/PasswordSection.tsx rename to src/features/authentication/components/UserCompletionForm/PasswordSection.tsx diff --git a/src/features/authorization/components/UserCompletionForm/PasswordValidation.tsx b/src/features/authentication/components/UserCompletionForm/PasswordValidation.tsx similarity index 100% rename from src/features/authorization/components/UserCompletionForm/PasswordValidation.tsx rename to src/features/authentication/components/UserCompletionForm/PasswordValidation.tsx diff --git a/src/features/authorization/components/UserCompletionForm/PersonalInfoFields.tsx b/src/features/authentication/components/UserCompletionForm/PersonalInfoFields.tsx similarity index 100% rename from src/features/authorization/components/UserCompletionForm/PersonalInfoFields.tsx rename to src/features/authentication/components/UserCompletionForm/PersonalInfoFields.tsx diff --git a/src/features/authorization/components/UserCompletionForm/SubmitSection.tsx b/src/features/authentication/components/UserCompletionForm/SubmitSection.tsx similarity index 100% rename from src/features/authorization/components/UserCompletionForm/SubmitSection.tsx rename to src/features/authentication/components/UserCompletionForm/SubmitSection.tsx diff --git a/src/features/authorization/index.ts b/src/features/authentication/index.ts similarity index 75% rename from src/features/authorization/index.ts rename to src/features/authentication/index.ts index 7f380b6..ae0aa8e 100644 --- a/src/features/authorization/index.ts +++ b/src/features/authentication/index.ts @@ -1,3 +1,4 @@ export * from './routes/AuthenticationPage'; export * from './routes/ForgetPasswordPage'; export * from './routes/UserCompletionPage'; +export * from './routes/AccountCreatedPage'; diff --git a/src/features/authorization/routes/AccountCreatedPage.tsx b/src/features/authentication/routes/AccountCreatedPage.tsx similarity index 100% rename from src/features/authorization/routes/AccountCreatedPage.tsx rename to src/features/authentication/routes/AccountCreatedPage.tsx diff --git a/src/features/authorization/routes/AuthenticationPage.tsx b/src/features/authentication/routes/AuthenticationPage.tsx similarity index 100% rename from src/features/authorization/routes/AuthenticationPage.tsx rename to src/features/authentication/routes/AuthenticationPage.tsx diff --git a/src/features/authorization/routes/ForgetPasswordPage.tsx b/src/features/authentication/routes/ForgetPasswordPage.tsx similarity index 100% rename from src/features/authorization/routes/ForgetPasswordPage.tsx rename to src/features/authentication/routes/ForgetPasswordPage.tsx diff --git a/src/features/authorization/routes/UserCompletionPage.tsx b/src/features/authentication/routes/UserCompletionPage.tsx similarity index 100% rename from src/features/authorization/routes/UserCompletionPage.tsx rename to src/features/authentication/routes/UserCompletionPage.tsx diff --git a/src/features/authorization/types/authTypes.ts b/src/features/authentication/types/authTypes.ts similarity index 100% rename from src/features/authorization/types/authTypes.ts rename to src/features/authentication/types/authTypes.ts diff --git a/src/features/authorization/types/completionFormApiTypes.ts b/src/features/authentication/types/completionFormApiTypes.ts similarity index 100% rename from src/features/authorization/types/completionFormApiTypes.ts rename to src/features/authentication/types/completionFormApiTypes.ts diff --git a/src/features/authorization/types/settingForm.ts b/src/features/authentication/types/settingForm.ts similarity index 100% rename from src/features/authorization/types/settingForm.ts rename to src/features/authentication/types/settingForm.ts diff --git a/src/features/authorization/types/userTypes.ts b/src/features/authentication/types/userTypes.ts similarity index 100% rename from src/features/authorization/types/userTypes.ts rename to src/features/authentication/types/userTypes.ts diff --git a/src/providers/AuthProvider.tsx b/src/providers/AuthProvider.tsx index 7add190..24bf1e2 100644 --- a/src/providers/AuthProvider.tsx +++ b/src/providers/AuthProvider.tsx @@ -1,6 +1,6 @@ // useAuth.tsx import { AuthContext, type UserInfo } from '@/contexts/AuthContext'; -import type { GenerateTokenResponse } from '@/features/authorization/api/identityAPI'; +import type { GenerateTokenResponse } from '@/features/authentication/api/identityAPI'; import axios from 'axios'; import { useEffect, useState, type ReactNode } from 'react'; import { jwtDecode } from 'jwt-decode'; diff --git a/src/routes/config.tsx b/src/routes/config.tsx index e1e0e01..ca878f5 100644 --- a/src/routes/config.tsx +++ b/src/routes/config.tsx @@ -1,6 +1,5 @@ import { Layout } from '@/components'; import { NavigateWithToast } from '@/components/NavigateWithToast'; -import { AccountCreatedPage } from '@/features/authorization/routes/AccountCreatedPage'; import { Calendar, Devices, @@ -18,17 +17,22 @@ import { lazy, type ReactNode } from 'react'; import { Navigate } from 'react-router-dom'; const AuthenticationPage = lazy(() => - import('@/features/authorization').then((module) => ({ + import('@/features/authentication').then((module) => ({ default: module.AuthenticationPage, })), ); +const AccountCreatedPage = lazy(() => + import('@/features/authentication').then((module) => ({ + default: module.AccountCreatedPage, + })), +); const UserCompletionPage = lazy(() => - import('@/features/authorization').then((module) => ({ + import('@/features/authentication').then((module) => ({ default: module.UserCompletionPage, })), ); const ForgetPasswordPage = lazy(() => - import('@/features/authorization').then((module) => ({ + import('@/features/authentication').then((module) => ({ default: module.ForgetPasswordPage, })), ); From d56eb2e4ffa6a790caddac8c65d2faa84859dc2b Mon Sep 17 00:00:00 2001 From: mehrzadghdev Date: Wed, 20 Aug 2025 23:39:21 +0330 Subject: [PATCH 6/6] fix: recent timer button removed --- .../AuthenticationSteps/OtpVerifyForm.tsx | 24 ++++++++++++------- .../AuthenticationSteps/VerifyPhoneNumber.tsx | 24 ++++++++++++------- .../ForgetPassword/ForgetPasswordOtp.tsx | 24 ++++++++++++------- 3 files changed, 48 insertions(+), 24 deletions(-) diff --git a/src/features/authentication/components/AuthenticationSteps/OtpVerifyForm.tsx b/src/features/authentication/components/AuthenticationSteps/OtpVerifyForm.tsx index 9ea59d9..006e0c5 100644 --- a/src/features/authentication/components/AuthenticationSteps/OtpVerifyForm.tsx +++ b/src/features/authentication/components/AuthenticationSteps/OtpVerifyForm.tsx @@ -213,20 +213,28 @@ export function OtpVerifyForm({ sx={{ justifyContent: 'center', alignItems: 'center', - mt: 1.5, + mt: 2.5, }} > {t('verify.resendCodeIn')} - + + + {canResend && ( + + )} ); diff --git a/src/features/authentication/components/AuthenticationSteps/VerifyPhoneNumber.tsx b/src/features/authentication/components/AuthenticationSteps/VerifyPhoneNumber.tsx index d58553f..c629924 100644 --- a/src/features/authentication/components/AuthenticationSteps/VerifyPhoneNumber.tsx +++ b/src/features/authentication/components/AuthenticationSteps/VerifyPhoneNumber.tsx @@ -140,20 +140,28 @@ export function VerifyPhoneNumber({ sx={{ justifyContent: 'center', alignItems: 'center', - mt: 1.5, + mt: 2.5, }} > {t('verify.resendCodeIn')} - + + + {canResend && ( + + )} ); diff --git a/src/features/authentication/components/ForgetPassword/ForgetPasswordOtp.tsx b/src/features/authentication/components/ForgetPassword/ForgetPasswordOtp.tsx index bd1afea..34596d4 100644 --- a/src/features/authentication/components/ForgetPassword/ForgetPasswordOtp.tsx +++ b/src/features/authentication/components/ForgetPassword/ForgetPasswordOtp.tsx @@ -171,20 +171,28 @@ export function ForgetPasswordOtp({ sx={{ justifyContent: 'center', alignItems: 'center', - mt: 1.5, + mt: 2.5, }} > {t('verify.resendCodeIn')} - + + + {canResend && ( + + )} );