diff --git a/.env b/.env new file mode 100644 index 0000000..9585291 --- /dev/null +++ b/.env @@ -0,0 +1,3 @@ +VITE_BASE_URL = 'https://api.shinan.ir' +VITE_TOKEN_NAME = 'sh_admin_token' +VITE_REFRESH_TOKEN_NAME = 'sh_admin_token' \ No newline at end of file diff --git a/src/pages/auth/Login.tsx b/src/pages/auth/Login.tsx index e38571a..11d41e0 100644 --- a/src/pages/auth/Login.tsx +++ b/src/pages/auth/Login.tsx @@ -1,15 +1,10 @@ import { type FC } from 'react' import LogoImage from '../../assets/images/logo.svg' import LogoSmallImage from '../../assets/images/logo-small.svg' -import { useAuthStore } from './store/AuthStore' import LoginStep1 from './components/LoginStep1' -import LoginStep2 from './components/LoginStep2' -import LoginStep3 from './components/LoginStep3' const Login: FC = () => { - const { stepLogin, phone, email } = useAuthStore() - return (
@@ -18,21 +13,9 @@ const Login: FC = () => {
- { - stepLogin === 1 ? - - : - stepLogin === 2 && !!phone ? - - : stepLogin === 2 && !!email ? - - : stepLogin === 3 ? - - : null - } +
-
diff --git a/src/pages/auth/Register.tsx b/src/pages/auth/Register.tsx index 2da12a7..75f896b 100644 --- a/src/pages/auth/Register.tsx +++ b/src/pages/auth/Register.tsx @@ -5,16 +5,12 @@ import { useTranslation } from 'react-i18next' import { Link } from 'react-router-dom' import { Pages } from '../../config/Pages' import RegisterStep1 from './components/RegisterStep1' -import { useAuthStore } from './store/AuthStore' -import RegisterStep2 from './components/RegisterStep2' - +// import RegisterStep2 from './components/RegisterStep2' // Not used in current implementation const Register: FC = () => { - const { stepLogin } = useAuthStore() const { t } = useTranslation('global') - return (
@@ -27,15 +23,10 @@ const Register: FC = () => {

{t('auth.enter_information')} -

+

- { - stepLogin === 1 ? - - : - - } +

diff --git a/src/pages/auth/components/LoginStep1.tsx b/src/pages/auth/components/LoginStep1.tsx index c3089cc..473fdce 100644 --- a/src/pages/auth/components/LoginStep1.tsx +++ b/src/pages/auth/components/LoginStep1.tsx @@ -1,55 +1,50 @@ -import { FC } from 'react' +import { type FC } from 'react' import Input from '../../../components/Input' import { useTranslation } from 'react-i18next' -import { LoginType } from '../types/AuthTypes' +import { type LoginWithPasswordType } from '../types/AuthTypes' import { useFormik } from 'formik' import * as Yup from 'yup' import { useAuthStore } from '../store/AuthStore' import Error from '../../../components/Error' import Button from '../../../components/Button' -import { isEmail } from '../../../config/func' -import { useCheckHasAccount, useLoginWithOtp } from '../hooks/useAuthData' +import { useLoginWithPassword } from '../hooks/useAuthData' import { toast } from 'react-toastify' -import { ErrorType } from '../../../helpers/types' +import { type ErrorType } from '../../../helpers/types' +import { setRefreshToken, setToken } from '../../../config/func' +import { Pages } from '../../../config/Pages' const LoginStep1: FC = () => { const { t } = useTranslation('global') - const { setPhone, phone, setStepLogin, setEmail } = useAuthStore() - const loginWithOtp = useLoginWithOtp() - const checkHasAccount = useCheckHasAccount() + const { setEmail } = useAuthStore() + const loginWithPassword = useLoginWithPassword() - const formik = useFormik({ + const formik = useFormik({ initialValues: { - phone_email: phone, + email: '', + password: '', }, validationSchema: Yup.object({ - phone_email: Yup.string() + email: Yup.string() + .email(t('errors.invalid_email')) + .required(t('errors.required')), + password: Yup.string() .required(t('errors.required')) }), onSubmit(values) { - if (isEmail(values.phone_email)) { - setEmail(values.phone_email) - checkHasAccount.mutate({ email: values.phone_email }, { - onSuccess() { - setStepLogin(2) - }, - onError(error: ErrorType) { - toast.error(error?.response?.data?.error?.message[0]) - }, - }) - } else { - setPhone(values.phone_email) - loginWithOtp.mutate({ phone: values.phone_email }, { - onSuccess() { - setStepLogin(2) - toast.success(t('auth.otp_sent')) - }, - onError(error: ErrorType) { - toast.error(error?.response?.data?.error?.message[0]) - }, - }) - } + setEmail(values.email) + loginWithPassword.mutate(values, { + onSuccess(data) { + if (data?.results?.accessToken?.token && data?.results?.refreshToken?.token) { + setToken(data.results.accessToken.token) + setRefreshToken(data.results.refreshToken.token) + window.location.href = Pages.dashboard + } + }, + onError(error: ErrorType) { + toast.error(error?.response?.data?.error?.message[0]) + }, + }) }, }) @@ -64,32 +59,49 @@ const LoginStep1: FC = () => {

-
+
+ + { - formik.touched.phone_email && formik.errors.phone_email && + formik.touched.email && formik.errors.email && } + { + formik.touched.password && formik.errors.password && + + }
-
diff --git a/src/pages/auth/components/LoginStep2.tsx b/src/pages/auth/components/LoginStep2.tsx deleted file mode 100644 index 4fa02a8..0000000 --- a/src/pages/auth/components/LoginStep2.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import { FC } from 'react' -import { useTranslation } from 'react-i18next' -import { OtpVerifyType } from '../types/AuthTypes' -import { useFormik } from 'formik' -import * as Yup from 'yup' -import { useAuthStore } from '../store/AuthStore' -import Button from '../../../components/Button' -import OTPInput from 'react-otp-input' -import { useCountDown } from '../../../hooks/useCountDown' -// import ArrowLeftIcon from '../../../assets/images/arrow-left.svg' -import { Pages } from '../../../config/Pages' -import { useOtpVerify } from '../hooks/useAuthData' -import { ErrorType } from '../../../helpers/types' -import { toast } from 'react-toastify' -import { setToken, setRefreshToken } from '../../../config/func' - -const LoginStep2: FC = () => { - - const { t } = useTranslation('global') - const { phone, setStepLogin } = useAuthStore() - const { value } = useCountDown(2, true) - const otpVerify = useOtpVerify() - - const formik = useFormik({ - initialValues: { - phone: phone, - code: '' - }, - validationSchema: Yup.object({ - code: Yup.string() - .required(t('errors.required')) - }), - onSubmit(values) { - const params: OtpVerifyType = { - phone: phone, - code: values.code - } - otpVerify.mutate(params, { - onSuccess(data) { - setToken(data?.data?.accessToken?.token) - setRefreshToken(data?.data?.refreshToken?.token) - window.location.href = Pages.dashboard - }, - onError(error: ErrorType) { - toast.error(error?.response?.data?.error?.message[0]) - }, - }) - }, - }) - - return ( -
-
-

- {t('auth.enter_otp')} -

-

-

-
{t('auth.verfify_code_text_1')}
-
{phone}
-
- {t('auth.verfify_code_text_2')} -
-
-
setStepLogin(1)} className='text-black cursor-pointer'> - {t('auth.change_number')} -
-

-
- -
-
- {t('auth.verify_code')} -
-
- formik.setFieldValue('code', otp)} - renderInput={(props) => } - /> -
- - { - formik.touched.code && formik.errors.code && -
{formik.errors.code}
- } - -
-
-
{value}
-
{t('auth.counter_otp')}
-
-
- -
- - -
- ) -} - -export default LoginStep2 \ No newline at end of file diff --git a/src/pages/auth/components/LoginStep3.tsx b/src/pages/auth/components/LoginStep3.tsx deleted file mode 100644 index 2c74191..0000000 --- a/src/pages/auth/components/LoginStep3.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import { FC } from 'react' -import Input from '../../../components/Input' -import { useTranslation } from 'react-i18next' -import { LoginWithPasswordType } from '../types/AuthTypes' -import { useFormik } from 'formik' -import * as Yup from 'yup' -import { useAuthStore } from '../store/AuthStore' -import Error from '../../../components/Error' -import Button from '../../../components/Button' -import { Link } from 'react-router-dom' -import { Pages } from '../../../config/Pages' -import ArrowLeftIcon from '../../../assets/images/arrow-left.svg' -import { useLoginWithPassword } from '../hooks/useAuthData' -import { toast } from 'react-toastify' -import { ErrorType } from '../../../helpers/types' -import { setRefreshToken } from '../../../config/func' -import { setToken } from '../../../config/func' - -const LoginStep3: FC = () => { - - const { t } = useTranslation('global') - const { setStepLogin, email } = useAuthStore() - const loginWithPassword = useLoginWithPassword() - - const formik = useFormik({ - initialValues: { - password: '', - email: email - }, - validationSchema: Yup.object({ - password: Yup.string() - .required(t('errors.required')) - }), - onSubmit(values) { - loginWithPassword.mutate(values, { - onSuccess(data) { - setToken(data?.data?.accessToken?.token) - setRefreshToken(data?.data?.refreshToken?.token) - window.location.href = Pages.dashboard - }, - onError(error: ErrorType) { - toast.error(error?.response?.data?.error?.message[0]) - }, - }) - - }, - }) - - return ( -
-
-

- {t('auth.enter_password_step3')} -

-

- {t('auth.enter_your_password')} -

-
- -
- - - { - formik.touched.password && formik.errors.password && - - } - -
- -
- {t('auth.forgot_password')} -
- - -
- ) -} - -export default LoginStep3 \ No newline at end of file diff --git a/src/pages/auth/components/RegisterStep1.tsx b/src/pages/auth/components/RegisterStep1.tsx index 9122f13..6df62dd 100644 --- a/src/pages/auth/components/RegisterStep1.tsx +++ b/src/pages/auth/components/RegisterStep1.tsx @@ -1,36 +1,36 @@ -import { FC } from 'react' +import { type FC } from 'react' import Input from '../../../components/Input' import { useTranslation } from 'react-i18next' -import { CheckHasAccountPhoneType } from '../types/AuthTypes' +import { type CheckHasAccountType } from '../types/AuthTypes' import { useFormik } from 'formik' import * as Yup from 'yup' import { useAuthStore } from '../store/AuthStore' import Error from '../../../components/Error' import Button from '../../../components/Button' -import { useCheckHasAccountRegister, useLoginWithOtp } from '../hooks/useAuthData' +import { useCheckHasAccount } from '../hooks/useAuthData' import { toast } from 'react-toastify' -import { ErrorType } from '../../../helpers/types' +import { type ErrorType } from '../../../helpers/types' const RegisterStep1: FC = () => { const { t } = useTranslation('global') - const { setPhone, setStepLogin } = useAuthStore() - const loginWithOtp = useLoginWithOtp() - const checkHasAccount = useCheckHasAccountRegister() + const { setEmail } = useAuthStore() + const checkHasAccount = useCheckHasAccount() - const formik = useFormik({ + const formik = useFormik({ initialValues: { - phone: '', + email: '', }, validationSchema: Yup.object({ - phone: Yup.string() + email: Yup.string() + .email(t('errors.invalid_email')) .required(t('errors.required')) }), onSubmit(values) { checkHasAccount.mutate(values, { onSuccess() { - setPhone(values.phone) - setStepLogin(2) + setEmail(values.email) + // Redirect to register step 2 or handle as needed }, onError(error: ErrorType) { toast.error(error?.response?.data?.error?.message[0]) @@ -42,33 +42,31 @@ const RegisterStep1: FC = () => { return (
-
{ - formik.touched.phone && formik.errors.phone && + formik.touched.email && formik.errors.email && }
-
) diff --git a/src/pages/auth/components/RegisterStep2.tsx b/src/pages/auth/components/RegisterStep2.tsx index 4cf4c09..04a35e0 100644 --- a/src/pages/auth/components/RegisterStep2.tsx +++ b/src/pages/auth/components/RegisterStep2.tsx @@ -1,21 +1,21 @@ -import { FC, Fragment } from 'react' +import { type FC, Fragment } from 'react' import { useFormik } from 'formik' -import { RegisterType } from '../types/AuthTypes' +import { type RegisterType } from '../types/AuthTypes' import * as Yup from 'yup' -import { useAuthStore } from '../store/AuthStore' +// import { useAuthStore } from '../store/AuthStore' // Not used in current implementation import { useTranslation } from 'react-i18next' import Input from '../../../components/Input' import DatePickerComponent from '../../../components/DatePicker' import Button from '../../../components/Button' import { useRegister } from '../hooks/useAuthData' -import { ErrorType } from '../../../helpers/types' +import { type ErrorType } from '../../../helpers/types' import { toast } from 'react-toastify' import { Pages } from '../../../config/Pages' const RegisterStep2: FC = () => { const { t } = useTranslation('global') - const { phone } = useAuthStore() + // const { email } = useAuthStore() // Not used in current implementation const register = useRegister() const formik = useFormik({ @@ -26,7 +26,7 @@ const RegisterStep2: FC = () => { code: 0, nationalCode: '', password: '', - phone: phone, + phone: '', // We'll need to add phone field to the form }, validationSchema: Yup.object({ firstName: Yup.string() @@ -105,10 +105,12 @@ const RegisterStep2: FC = () => { error_text={formik.touched.password && formik.errors.password ? formik.errors.password : ''} />
diff --git a/src/pages/auth/hooks/useAuthData.tsx b/src/pages/auth/hooks/useAuthData.tsx index 0c480e9..9a1d233 100644 --- a/src/pages/auth/hooks/useAuthData.tsx +++ b/src/pages/auth/hooks/useAuthData.tsx @@ -1,6 +1,6 @@ import { useMutation } from '@tanstack/react-query'; import * as api from '../service/AuthService' -import { CheckHasAccountPhoneType, CheckHasAccountType, LoginWithOtpType, LoginWithPasswordType, OtpVerifyType, RegisterType } from '../types/AuthTypes'; +import { type CheckHasAccountType, type LoginWithPasswordType, type RegisterType } from '../types/AuthTypes'; export const useLoginWithPassword = () => { return useMutation({ @@ -8,30 +8,12 @@ export const useLoginWithPassword = () => { }); }; -export const useLoginWithOtp = () => { - return useMutation({ - mutationFn: (variables: LoginWithOtpType) => api.loginWithOtp(variables), - }); -}; - -export const useOtpVerify = () => { - return useMutation({ - mutationFn: (variables: OtpVerifyType) => api.otpVerify(variables), - }); -}; - export const useCheckHasAccount = () => { return useMutation({ mutationFn: (variables: CheckHasAccountType) => api.checkHasAccount(variables), }); }; -export const useCheckHasAccountRegister = () => { - return useMutation({ - mutationFn: (variables: CheckHasAccountPhoneType) => api.checkHasAccountRegister(variables), - }); -}; - export const useRegister = () => { return useMutation({ mutationFn: (variables: RegisterType) => api.register(variables), diff --git a/src/pages/auth/service/AuthService.ts b/src/pages/auth/service/AuthService.ts index 0ea880e..f08a397 100644 --- a/src/pages/auth/service/AuthService.ts +++ b/src/pages/auth/service/AuthService.ts @@ -1,39 +1,21 @@ import axios from "../../../config/axios"; import { - type CheckHasAccountPhoneType, type CheckHasAccountType, - type LoginWithOtpType, type LoginWithPasswordType, - type OtpVerifyType, type RefreshTokenType, type RegisterType, } from "../types/AuthTypes"; export const loginWithPassword = async (params: LoginWithPasswordType) => { - const { data } = await axios.post(`/auth/login/password/admin`, params); + const { data } = await axios.post(`/admin/login/password`, params); return data; }; -export const loginWithOtp = async (params: LoginWithOtpType) => { - const { data } = await axios.post(`/auth/otp/send`, params); - return data; -}; - -export const otpVerify = async (params: OtpVerifyType) => { - const { data } = await axios.post(`/auth/otp/verify/admin`, params); - return data; -}; export const checkHasAccount = async (params: CheckHasAccountType) => { const { data } = await axios.post(`/auth/check`, params); return data; }; -export const checkHasAccountRegister = async ( - params: CheckHasAccountPhoneType -) => { - const { data } = await axios.post(`/auth/register/initiate`, params); - return data; -}; export const register = async (params: RegisterType) => { const { data } = await axios.post(`/auth/register/complete`, params); return data; diff --git a/src/pages/auth/store/AuthStore.ts b/src/pages/auth/store/AuthStore.ts index de766e3..fc5b18c 100644 --- a/src/pages/auth/store/AuthStore.ts +++ b/src/pages/auth/store/AuthStore.ts @@ -1,17 +1,13 @@ import { create } from "zustand"; -import { AuthStoreType } from "../../auth/types/AuthTypes"; + +export type AuthStoreType = { + email: string; + setEmail: (value: string) => void; +}; export const useAuthStore = create((set) => ({ - phone: "", - setPhone(value) { - set({ phone: value }); - }, email: "", setEmail(value) { set({ email: value }); }, - stepLogin: 1, - setStepLogin(value) { - set({ stepLogin: value }); - }, })); diff --git a/src/pages/auth/types/AuthTypes.ts b/src/pages/auth/types/AuthTypes.ts index 60ef40b..a19fbe2 100644 --- a/src/pages/auth/types/AuthTypes.ts +++ b/src/pages/auth/types/AuthTypes.ts @@ -1,45 +1,12 @@ -import { type XOR } from "../../../helpers/types"; - -export type LoginType = { - phone_email: string; -}; -export type LoginPasswordType = { - password: string; -}; - -export type AuthStoreType = { - phone: string; - setPhone: (value: string) => void; +export type LoginWithPasswordType = { email: string; - setEmail: (value: string) => void; - stepLogin: number; - setStepLogin: (value: number) => void; -}; - -export type LoginWithPasswordType = XOR< - { email: string }, - { phone: number } -> & { password: string; }; -export type LoginWithOtpType = { - phone: string; -}; - -export type OtpVerifyType = { - phone: string; - code: string; -}; - export type CheckHasAccountType = { email: string; }; -export type CheckHasAccountPhoneType = { - phone: string; -}; - export type RegisterType = { phone: string; firstName: string; @@ -49,6 +16,7 @@ export type RegisterType = { password: string; code: number; }; + export type RefreshTokenType = { refreshToken: string; }; diff --git a/src/router/Auth.tsx b/src/router/Auth.tsx index a8ee7b8..60ce041 100644 --- a/src/router/Auth.tsx +++ b/src/router/Auth.tsx @@ -1,8 +1,12 @@ -import React from 'react' +import Login from '../pages/auth/Login' +import { Route, Routes } from 'react-router-dom' +import { Pages } from '../config/Pages' const Auth = () => { return ( -
Auth
+ + } /> + ) } diff --git a/src/shared/SideBar.tsx b/src/shared/SideBar.tsx index 5475b4d..75c2083 100644 --- a/src/shared/SideBar.tsx +++ b/src/shared/SideBar.tsx @@ -2,53 +2,62 @@ import { type FC, useEffect } from 'react' import LogoImage from '../assets/images/logo.svg' import LogoSmall from '../assets/images/logo-small.svg' import { useTranslation } from 'react-i18next' -import { Card, Code, CodeCircle, DocumentLike, DocumentText, Element3, Gallery, Headphone, Home2, Logout, Message, Messages3, Money3, NotificationStatus, People, Profile, Receipt21, Setting2, SmsTracking, Teacher, TicketDiscount, UserSquare } from 'iconsax-react' +import { + Home2, + Element3, + Receipt21, + TicketDiscount, + DocumentText, + Truck, + Money3, + People, + UserSquare, + Profile, + Messages3, + Chart, + Setting2, + Logout, + Briefcase, + Headphone, + SmsTracking +} from 'iconsax-react' import SideBarItem from './SideBarItem' import { useLocation } from 'react-router-dom' -import { Pages } from '../config/Pages' import { useSharedStore } from './store/sharedStore' import { clx } from '../helpers/utils' -import ServicesSubMenu from './components/ServicesSubMenu' -import { SideBarItemHasSubMenu } from '../config/SideBarSubMenu' -import ReceiptSubMenu from './components/ReceiptSubMenu' -import CustomerSubMenu from './components/CustomerSubMenu' -import TicketSubMenu from './components/TicketSubMenu' -import UsersSubMenu from './components/UsersSubMenu' -import LearningSubMenu from './components/LearningSubMenu' import BlogSubMenu from './components/BlogSubMenu' -// import { useGetProfile } from '../pages/profile/hooks/useProfileData' -import SupportSubMenu from './components/SupportSubMenu' +import SubMenuItem from './components/SubMenuItem' + + const SideBar: FC = () => { const { t } = useTranslation('global') const { openSidebar, setOpenSidebar, hasSubMenu, setSubMenuName, setSubtMenu, subMenuName } = useSharedStore() const location = useLocation() - // const { data: profile } = useGetProfile() + const isActive = (name: string) => { return location.pathname.includes(name) } useEffect(() => { - const split = location.pathname.split('/') - - if (SideBarItemHasSubMenu.includes(split[1])) { + if (split[1] === 'dashboard' || split[1] === 'products' || split[1] === 'orders' || + split[1] === 'blog' || split[1] === 'shipping' || split[1] === 'financial' || + split[1] === 'sellers' || split[1] === 'buyers' || split[1] === 'users' || + split[1] === 'tickets' || split[1] === 'reports' || split[1] === 'chat' || + split[1] === 'contact' || split[1] === 'settings' || split[1] === 'pages' || + split[1] === 'jobs') { setSubMenuName(split[1]) setSubtMenu(true) } else { setSubMenuName('') setSubtMenu(false) } - - - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [location.pathname]) - + }, [location.pathname, setSubMenuName, setSubtMenu]) const iconSizeSideBar = 20 - return ( <> { @@ -79,232 +88,165 @@ const SideBar: FC = () => {
+ {/* داشبورد */} } - title={t('sidebar.mainpage')} + title="داشبورد" isActive={isActive('dashboard')} - link={Pages.dashboard} - activeName='' - /> - } - title={t('sidebar.services')} - isActive={isActive('services')} - link={Pages.services.list} - name='services' - activeName='services' + link="/dashboard" + activeName='dashboard' /> + {/* محصولات */} } - title={t('sidebar.support')} - isActive={isActive('support')} - link={Pages.support.list} - activeName='support_plan' + icon={} + title="محصولات" + isActive={isActive('products')} + link="/products" + activeName='products' /> + {/* سفارشات */} } - title={t('sidebar.customers')} - isActive={isActive('customers')} - link={Pages.customers.list} - activeName='customers' - /> - } - title={t('sidebar.representatives')} - isActive={isActive('representatives')} - link={Pages.representative.list} - activeName='agents' - /> - } - title={t('sidebar.developers')} - isActive={isActive('developers')} - link={Pages.developers.list} - activeName='developers' + icon={} + title="سفارشات" + isActive={isActive('orders')} + link="/orders" + activeName='orders' /> - - } - title={t('sidebar.receipt_list')} - isActive={isActive('receipts')} - link={Pages.receipts.index} - activeName='invoices' - /> - } - title={t('sidebar.transactions')} - isActive={isActive('transactions')} - link={Pages.transactions} - activeName='transactions' - /> - } - title={t('sidebar.payments')} - isActive={isActive('payments')} - link={Pages.payment.list} - activeName='payments' - /> + {/* تخفیف ها */} } - title={t('sidebar.discounts')} + title="تخفیف ها" isActive={isActive('discounts')} - link={Pages.discount.list} + link="/discounts" activeName='discounts' /> - } - title={t('sidebar.code_referral')} - isActive={isActive('referral-code')} - link={Pages.referralCode.list} - activeName='referralCode' - /> - } - title={t('sidebar.users')} - isActive={isActive('users')} - link={Pages.users.list} - activeName='admins' - /> - } - title={t('sidebar.sliders')} - isActive={isActive('sliders')} - link={Pages.sliders.list} - activeName='blogs' - /> - } - title={t('sidebar.feedback')} - isActive={isActive('feedback')} - link={Pages.feedback.list} - activeName='services' - /> - -
- - {/* { - profile?.data?.user?.roles.some((role: { name: string }) => role.name === 'super_admin') && -
- {t('sidebar.other')} -
- } */} - - - - -
- } - title={t('sidebar.ticket')} - isActive={isActive('tickets')} - link={Pages.ticket.list} - activeName='tickets' - /> -
- -
- } - title={t('sidebar.criticisms')} - isActive={isActive('criticisms')} - link={Pages.criticisms.list} - activeName='criticisms' - /> -
- - {/* { - profile?.data?.user?.roles?.some((role: { name: string }) => role.name === 'super_admin') && -
- {t('sidebar.mnage_content')} -
- } */} - - -
- } - title={t('sidebar.ads')} - isActive={isActive('ads')} - link={Pages.ads.list} - activeName='advertisements' - /> -
- -
- } - title={t('sidebar.announcement')} - isActive={isActive('announcement')} - link={Pages.announcement.list} - activeName='announcements' - /> -
- -
+ {/* بلاگ */} } - title={t('sidebar.blog')} + title="بلاگ" isActive={isActive('blog')} - link={Pages.blog.list} - activeName='blogs' + link="/blog" + activeName='blog' /> -
-
+ {/* روش های ارسال */} } - title={t('sidebar.learning')} - isActive={isActive('learning')} - link={Pages.learning.list} - activeName='learnings' + icon={} + title="روش های ارسال" + isActive={isActive('shipping')} + link="/shipping" + activeName='shipping' /> -
-
+ {/* مالی */} } - title={t('sidebar.messages')} - isActive={isActive('messages')} - link={Pages.messages.list} - activeName='contacts_us' + icon={} + title="مالی" + isActive={isActive('financial')} + link="/financial" + activeName='financial' + /> + + {/* فروشندگان */} + } + title="فروشندگان" + isActive={isActive('sellers')} + link="/sellers" + activeName='sellers' + /> + + {/* خریداران */} + } + title="خریداران" + isActive={isActive('buyers')} + link="/buyers" + activeName='buyers' + /> + + {/* کاربران */} + } + title="کاربران" + isActive={isActive('users')} + link="/users" + activeName='users' + /> + + {/* تیکت ها */} + } + title="تیکت ها" + isActive={isActive('tickets')} + link="/tickets" + activeName='tickets' + /> + + {/* گزارش ها */} + } + title="گزارش ها" + isActive={isActive('reports')} + link="/reports" + activeName='reports' + /> + + {/* گفت و گو */} + } + title="گفت و گو" + isActive={isActive('chat')} + link="/chat" + activeName='chat' + /> + + {/* ارتباط با ما */} + } + title="ارتباط با ما" + isActive={isActive('contact')} + link="/contact" + activeName='contact' + /> + + {/* تنظیمات */} + } + title="تنظیمات" + isActive={isActive('settings')} + link="/settings" + activeName='settings' + /> + + {/* مدیریت صفحات */} + } + title="مدیریت صفحات" + isActive={isActive('pages')} + link="/pages" + activeName='pages' + /> + + {/* مشاغل */} + } + title="مشاغل" + isActive={isActive('jobs')} + link="/jobs" + activeName='jobs' />
- -
-
- } - title={t('sidebar.card')} - isActive={isActive('card')} - link={Pages.cardBank.list} - activeName='bank_accounts' - /> -
-
- } - title={t('sidebar.setting')} - isActive={isActive('setting')} - link={Pages.setting} - activeName='settings' - /> -
} - title={t('sidebar.logout')} + title="خروج" isActive={isActive('logout')} link={`#`} isLogout @@ -315,27 +257,28 @@ const SideBar: FC = () => {
+ {/* منوی فرعی */} { hasSubMenu && (openSidebar || window.innerWidth > 1139) && -
+
{ - subMenuName === 'services' ? - - : subMenuName === 'receipts' ? - - : subMenuName === 'customers' ? - - : subMenuName === 'tickets' ? - - : subMenuName === 'users' ? - - : subMenuName === 'learning' ? - - : subMenuName === 'blog' ? - - : subMenuName === 'support' ? - - : null + subMenuName === 'blog' ? + : subMenuName === 'dashboard' ? + : subMenuName === 'products' ? + : subMenuName === 'orders' ? + : subMenuName === 'shipping' ? + : subMenuName === 'financial' ? + : subMenuName === 'sellers' ? + : subMenuName === 'buyers' ? + : subMenuName === 'users' ? + : subMenuName === 'tickets' ? + : subMenuName === 'reports' ? + : subMenuName === 'chat' ? + : subMenuName === 'contact' ? + : subMenuName === 'settings' ? + : subMenuName === 'pages' ? + : subMenuName === 'jobs' ? + : null }
} @@ -343,4 +286,615 @@ const SideBar: FC = () => { ) } +// کامپوننت‌های SubMenu برای هر بخش - دقیقاً مثل BlogSubMenu +const DashboardSubMenu: FC = () => { + const isActive = (name: string) => { + return location.pathname.includes(name) + } + + return ( +
+
+ +
+ داشبورد +
+
+ +
+ + + + + +
+
+ ) +} + +const ProductsSubMenu: FC = () => { + const isActive = (name: string) => { + return location.pathname.includes(name) + } + + return ( +
+
+ +
+ محصولات +
+
+ +
+ + + + + +
+
+ ) +} + +const OrdersSubMenu: FC = () => { + const isActive = (name: string) => { + return location.pathname.includes(name) + } + + return ( +
+
+ +
+ سفارشات +
+
+ +
+ + + + + +
+
+ ) +} + +const ShippingSubMenu: FC = () => { + const isActive = (name: string) => { + return location.pathname.includes(name) + } + + return ( +
+
+ +
+ روش های ارسال +
+
+ +
+ + +
+
+ ) +} + +const FinancialSubMenu: FC = () => { + const isActive = (name: string) => { + return location.pathname.includes(name) + } + + return ( +
+
+ +
+ مالی +
+
+ +
+ + +
+
+ ) +} + +const SellersSubMenu: FC = () => { + const isActive = (name: string) => { + return location.pathname.includes(name) + } + + return ( +
+
+ +
+ فروشندگان +
+
+ +
+ + + + + + + + +
+
+ ) +} + +const BuyersSubMenu: FC = () => { + const isActive = (name: string) => { + return location.pathname.includes(name) + } + + return ( +
+
+ +
+ خریداران +
+
+ +
+ +
+
+ ) +} + +const UsersSubMenu: FC = () => { + const isActive = (name: string) => { + return location.pathname.includes(name) + } + + return ( +
+
+ +
+ کاربران +
+
+ +
+ + + +
+
+ ) +} + +const TicketsSubMenu: FC = () => { + const isActive = (name: string) => { + return location.pathname.includes(name) + } + + return ( +
+
+ +
+ تیکت ها +
+
+ +
+ +
+
+ ) +} + +const ReportsSubMenu: FC = () => { + const isActive = (name: string) => { + return location.pathname.includes(name) + } + + return ( +
+
+ +
+ گزارش ها +
+
+ +
+ + +
+
+ ) +} + +const ChatSubMenu: FC = () => { + const isActive = (name: string) => { + return location.pathname.includes(name) + } + + return ( +
+
+ +
+ گفت و گو +
+
+ +
+ + +
+
+ ) +} + +const ContactSubMenu: FC = () => { + const isActive = (name: string) => { + return location.pathname.includes(name) + } + + return ( +
+
+ +
+ ارتباط با ما +
+
+ +
+ +
+
+ ) +} + +const SettingsSubMenu: FC = () => { + const isActive = (name: string) => { + return location.pathname.includes(name) + } + + return ( +
+
+ +
+ تنظیمات +
+
+ +
+ + + +
+
+ ) +} + +const PagesSubMenu: FC = () => { + const isActive = (name: string) => { + return location.pathname.includes(name) + } + + return ( +
+
+ +
+ مدیریت صفحات +
+
+ +
+ + + + + + + + +
+
+ ) +} + +const JobsSubMenu: FC = () => { + const isActive = (name: string) => { + return location.pathname.includes(name) + } + + return ( +
+
+ +
+ مشاغل +
+
+ +
+ + +
+
+ ) +} + export default SideBar \ No newline at end of file diff --git a/src/shared/components/BlogSubMenu.tsx b/src/shared/components/BlogSubMenu.tsx index 4f108f7..7f75728 100644 --- a/src/shared/components/BlogSubMenu.tsx +++ b/src/shared/components/BlogSubMenu.tsx @@ -1,5 +1,5 @@ import { DocumentText } from 'iconsax-react' -import { FC } from 'react' +import { type FC } from 'react' import { useTranslation } from 'react-i18next' import SubMenuItem from './SubMenuItem' import { Pages } from '../../config/Pages' @@ -14,7 +14,7 @@ const BlogSubMenu: FC = () => { return (
-
+