diff --git a/src/langs/fa.json b/src/langs/fa.json
index 7a0cd36..314ee6c 100644
--- a/src/langs/fa.json
+++ b/src/langs/fa.json
@@ -43,7 +43,8 @@
},
"errors": {
"required": "این فیلد اجباری می باشد",
- "password_not_match": "رمز عبور با تکرار آن مطابقت ندارد"
+ "password_not_match": "رمز عبور با تکرار آن مطابقت ندارد",
+ "is_not_image": "فرمت فایل انتخاب شده اشتباه می باشد"
},
"description": "توضیحات",
"sidebar": {
@@ -300,7 +301,9 @@
"image_profile": "تصویر حساب کاربری",
"image_profile_desc": "تصویر خود را در حساب کاربری قرار دهید.",
"upload_image": "آپلود تصویر",
- "format_image": "فرمت های jpg, png,jpeg.حداکثر ۱مگابایت",
+ "formats": "فرمت های",
+ "max_size": "حداکثر ۱مگابایت",
+ "format_image": " jpg, png,jpeg.",
"info_account": "اطلاعات حساب",
"auth_after_change_info": "در صورت تغییر اطلاعات حساب باید مجددا احراز هویت انجام شود.",
"username": "نام کاربری",
@@ -316,7 +319,8 @@
"postal_code": "کد پستی",
"username_available": "نام کاربری موجود",
"username_not_available": "نام کاربری موجود نیست",
- "username_save_success": "نام کاربری با موفقیت ذخیره شد"
+ "username_save_success": "نام کاربری با موفقیت ذخیره شد",
+ "image_uploaded_successfully": "تصویر با موفقیت آپلود شد"
},
"email": "ایمیل",
"save": "ذخیره",
diff --git a/src/pages/annoncement/List.tsx b/src/pages/annoncement/List.tsx
index 1fa9ca6..653b4a5 100644
--- a/src/pages/annoncement/List.tsx
+++ b/src/pages/annoncement/List.tsx
@@ -6,9 +6,11 @@ import StatusWithText from '../../components/StatusWithText'
import { clx } from '../../helpers/utils'
import { useNavigate } from 'react-router-dom'
import { Pages } from '../../config/Pages'
+import { useGetAnnoncement } from './hooks/useAnnoncementData'
const AnnouncementtList: FC = () => {
+ const getAnnoncements = useGetAnnoncement()
const { t } = useTranslation('global')
const navigate = useNavigate()
diff --git a/src/pages/annoncement/hooks/useAnnoncementData.ts b/src/pages/annoncement/hooks/useAnnoncementData.ts
new file mode 100644
index 0000000..4e28797
--- /dev/null
+++ b/src/pages/annoncement/hooks/useAnnoncementData.ts
@@ -0,0 +1,9 @@
+import * as api from "../service/AnnoncementService";
+import { useQuery } from "@tanstack/react-query";
+
+export const useGetAnnoncement = () => {
+ return useQuery({
+ queryKey: ["announcements"],
+ queryFn: () => api.getAnnoncements(),
+ });
+};
diff --git a/src/pages/annoncement/service/AnnoncementService.ts b/src/pages/annoncement/service/AnnoncementService.ts
new file mode 100644
index 0000000..69696b4
--- /dev/null
+++ b/src/pages/annoncement/service/AnnoncementService.ts
@@ -0,0 +1,6 @@
+import axios from "../../../config/axios";
+
+export const getAnnoncements = async () => {
+ const { data } = await axios.get(`/announcements/user`);
+ return data;
+};
diff --git a/src/pages/auth/components/LoginStep2.tsx b/src/pages/auth/components/LoginStep2.tsx
index 0856d98..96bb7b4 100644
--- a/src/pages/auth/components/LoginStep2.tsx
+++ b/src/pages/auth/components/LoginStep2.tsx
@@ -1,4 +1,4 @@
-import { FC } from 'react'
+import { FC, useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import { OtpVerifyType } from '../types/AuthTypes'
import { useFormik } from 'formik'
@@ -47,6 +47,28 @@ const LoginStep2: FC = () => {
},
})
+ useEffect(() => {
+ // بررسی پشتیبانی از Web OTP API
+ if (!("OTPCredential" in window)) return;
+
+ const ac = new AbortController();
+
+ navigator.credentials
+ .get({
+ otp: { transport: ["sms"] },
+ signal: ac.signal,
+ } as CredentialRequestOptions) // اطمینان از تطابق تایپها
+ .then((otpCredential) => {
+ if (otpCredential && "code" in otpCredential) {
+ alert("OTP Received: " + otpCredential.code);
+ formik.setFieldValue("code", (otpCredential).code);
+ }
+ })
+ .catch((err) => console.error("SMS AutoFill Error:", err));
+
+ return () => ac.abort();
+ }, []);
+
return (
@@ -78,7 +100,13 @@ const LoginStep2: FC = () => {
numInputs={5}
inputType='tel'
onChange={(otp: string) => formik.setFieldValue('code', otp)}
- renderInput={(props) => }
+ renderInput={(props) =>
+
+ }
/>
diff --git a/src/pages/financial/components/Legal.tsx b/src/pages/financial/components/Legal.tsx
index 94bb8be..b8678d5 100644
--- a/src/pages/financial/components/Legal.tsx
+++ b/src/pages/financial/components/Legal.tsx
@@ -4,7 +4,7 @@ import Input from '../../../components/Input'
import { useFormik } from 'formik'
import Textarea from '../../../components/Textarea'
import Button from '../../../components/Button'
-import { TickCircle } from 'iconsax-react'
+import { InfoCircle, TickCircle } from 'iconsax-react'
import { CreateLegalUserType, ProvinesItemType } from '../types/FinancialTypes'
import * as Yup from 'yup'
import { useCreateLegalUser, useGetCities, useGetFinancialInfo, useGetProvines } from '../hooks/useFinancialData'
@@ -186,6 +186,14 @@ const Legal: FC = () => {
/>
+
+
+
{t('financial.notice_cannot_edit')}
+
+
{
!isReadOnly &&
diff --git a/src/pages/profile/Profile.tsx b/src/pages/profile/Profile.tsx
index dca82e4..7e2fdb9 100644
--- a/src/pages/profile/Profile.tsx
+++ b/src/pages/profile/Profile.tsx
@@ -1,4 +1,4 @@
-import { FC } from 'react'
+import { FC, useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
import AvatarImage from '../../assets/images/avatar_image.png'
import Button from '../../components/Button'
@@ -7,13 +7,56 @@ import Input from '../../components/Input'
import DatePickerComponent from '../../components/DatePicker'
import Select from '../../components/Select'
import Textarea from '../../components/Textarea'
-import { useGetProfile } from './hooks/useProfileData'
+import { useGetProfile, useUpdateProfile } from './hooks/useProfileData'
import Username from './components/Username'
+import { useDropzone } from 'react-dropzone'
+import { toast } from 'react-toastify'
+import { useSingleUpload } from '../ticket/hooks/useTicketData'
+import { ErrorType } from '../../helpers/types'
+import { UpdateProfileType } from './types/ProfileTypes'
+import PageLoading from '../../components/PageLoading'
const Profile: FC = () => {
const { t } = useTranslation('global')
+ const singleUpload = useSingleUpload()
+ const [file, setFile] = useState
()
const getProfile = useGetProfile()
+ const updateProfile = useUpdateProfile()
+
+ const onDrop = useCallback((acceptedFiles: File[]) => {
+
+ if (acceptedFiles.length > 0) {
+ const file = acceptedFiles[0];
+ if (file.type.startsWith('image/')) {
+ setFile(file);
+ const formData = new FormData()
+ formData.append('file', file)
+ singleUpload.mutate(formData, {
+ onSuccess: (data) => {
+ const params: UpdateProfileType = {
+ profilePic: data.data?.url
+ }
+ updateProfile.mutate(params, {
+ onSuccess: () => {
+ toast.success(t('profile.image_uploaded_successfully'))
+ },
+ onError: (error: ErrorType) => {
+ toast.error(error.response?.data?.error?.message[0])
+ }
+ })
+ },
+ onError: (error: ErrorType) => {
+ toast.error(error.response?.data?.error?.message[0])
+ }
+ })
+ } else {
+ toast.error(t('errors.is_not_image'))
+ }
+ }
+
+ }, [])
+ const { getRootProps, getInputProps } = useDropzone({ onDrop })
return (
@@ -21,151 +64,160 @@ const Profile: FC = () => {
{t('profile.account_user')}
-
-
-
-
- {t('profile.image_profile')}
-
-
- {t('profile.image_profile_desc')}
-
-
-
-
-
-
-
-
-
{t('profile.upload_image')}
-
-
-
- {t('profile.format_image')}
-
-
-
-
-
-
-
-
- {t('profile.info_account')}
-
-
- {t('profile.auth_after_change_info')}
-
-
-
-
-
-
-
-
+ {
+ getProfile.isPending ?
+
+ :
+
+
+
- {t('edit')}
+ {t('profile.image_profile')}
+
+
+ {t('profile.image_profile_desc')}
+
+
+
+
+
+
+
+
+
+
{t('profile.upload_image')}
+
+
+
+ {t('profile.formats')}
+
{t('profile.format_image')}
+
{t('profile.max_size')}
+
-
-
-
-
+
+
+
- {t('edit')}
+ {t('profile.info_account')}
+
+
+ {t('profile.auth_after_change_info')}
+
+
+
-
-
-
-
-
- {t('profile.personal_information')}
-
-
- {t('profile.enter_carefully_your_information')}
-
-
-
-
{ }}
- placeholder=''
- defaulValue={getProfile.data?.data?.user?.birthDate}
- />
+
+
+
+ {t('profile.personal_information')}
+
+
+ {t('profile.enter_carefully_your_information')}
+
+
+
-
-
-
-
-
- {t('profile.address')}
-
-
- {t('profile.address_live')}
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ {t('profile.address')}
+
+
+ {t('profile.address_live')}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
)
diff --git a/src/pages/profile/types/ProfileTypes.ts b/src/pages/profile/types/ProfileTypes.ts
index 7b305f1..f32266d 100644
--- a/src/pages/profile/types/ProfileTypes.ts
+++ b/src/pages/profile/types/ProfileTypes.ts
@@ -8,4 +8,5 @@ export type UpdateProfileType = {
lastName?: string;
birthDate?: string;
userName?: string;
+ profilePic?: string;
};
diff --git a/src/pages/ticket/CreateTicket.tsx b/src/pages/ticket/CreateTicket.tsx
index bab1af9..ac21398 100644
--- a/src/pages/ticket/CreateTicket.tsx
+++ b/src/pages/ticket/CreateTicket.tsx
@@ -224,7 +224,7 @@ const CreateTicket: FC = () => {
- پاسخگویی 24 ساعته تلفنی را تنها از میهن وب هاست می توانید انتظار داشته باشید .بخش پشتیبانی در هر ساعتی حتی در روز های تعطیل آماده پیگیری سریع مشکلات کاربران است.
+ پاسخگویی 24 ساعته تلفنی را تنها از داناک می توانید انتظار داشته باشید .بخش پشتیبانی در هر ساعتی حتی در روز های تعطیل آماده پیگیری سریع مشکلات کاربران است.
diff --git a/src/shared/Footer.tsx b/src/shared/Footer.tsx
index 89e857a..51bdd62 100644
--- a/src/shared/Footer.tsx
+++ b/src/shared/Footer.tsx
@@ -2,72 +2,78 @@ import { Element3, Element4, Home2, Messages3, NotificationStatus } from 'iconsa
import { FC } from 'react'
import { useTranslation } from 'react-i18next'
import { Pages } from '../config/Pages'
-import { Link } from 'react-router-dom'
+import { Link, useLocation } from 'react-router-dom'
const Footer: FC = () => {
-
const { t } = useTranslation('global')
+ const location = useLocation()
+
+ const isActive = (path: string) => location.pathname === path
return (
-
+
-
-
-
+
-
+
{t('footer.other_services')}
-
+
-
+
{t('footer.my_services')}
-
+
-
+
{t('footer.announcements')}
-
-
+
-
@@ -77,4 +83,4 @@ const Footer: FC = () => {
)
}
-export default Footer
\ No newline at end of file
+export default Footer
diff --git a/src/shared/Header.tsx b/src/shared/Header.tsx
index 63e6664..ed0744d 100644
--- a/src/shared/Header.tsx
+++ b/src/shared/Header.tsx
@@ -37,7 +37,9 @@ const Header: FC = () => {
{/*
*/}
-
+
+
+
diff --git a/src/shared/SideBar.tsx b/src/shared/SideBar.tsx
index c483dd3..4f56373 100644
--- a/src/shared/SideBar.tsx
+++ b/src/shared/SideBar.tsx
@@ -48,13 +48,13 @@ const SideBar: FC = () => {
link={Pages.dashboard}
/>
}
+ icon={ }
title={t('sidebar.myservice')}
isActive={isActive('services')}
link={Pages.services.mine}
/>
}
+ icon={ }
title={t('sidebar.other_service')}
isActive={isActive('other-service')}
link={Pages.services.other}