setOpenSidebar(false)} />
+ ) : null}
+
+ >
+ );
+};
+
+export default EditorSidebar;
+
diff --git a/src/pages/home/Home.tsx b/src/pages/home/Home.tsx
new file mode 100644
index 0000000..b52e216
--- /dev/null
+++ b/src/pages/home/Home.tsx
@@ -0,0 +1,9 @@
+import React from 'react'
+
+const Home = () => {
+ return (
+
Home
+ )
+}
+
+export default Home
\ No newline at end of file
diff --git a/src/router/MainRouter.tsx b/src/router/MainRouter.tsx
new file mode 100644
index 0000000..f1b57bf
--- /dev/null
+++ b/src/router/MainRouter.tsx
@@ -0,0 +1,42 @@
+import SideBar from '@/shared/SideBar'
+import Header from '@/shared/Header'
+import { Route, Routes, useLocation } from 'react-router-dom'
+import { Paths } from '@/config/Paths'
+import { clx } from '@/helpers/utils'
+import { useSharedStore } from '@/shared/store/sharedStore'
+import Home from '@/pages/home/Home'
+import Editor from '@/pages/editor/Editor'
+
+const MainRouter = () => {
+ const { hasSubMenu } = useSharedStore()
+ const location = useLocation()
+ const hiddenSideBarRoutes = [Paths.editor]
+ const shouldRenderSideBar = !hiddenSideBarRoutes.includes(location.pathname)
+ const routeHasLocalSidebar = location.pathname === Paths.editor
+ const hasSidebarSpace = shouldRenderSideBar || routeHasLocalSidebar
+ const headerSidebarSize = routeHasLocalSidebar ? 'wide' : 'default'
+
+ return (
+
+ {shouldRenderSideBar ?
: null}
+
+
+
+ )
+}
+
+export default MainRouter
\ No newline at end of file
diff --git a/src/shared/Header.tsx b/src/shared/Header.tsx
new file mode 100644
index 0000000..c874609
--- /dev/null
+++ b/src/shared/Header.tsx
@@ -0,0 +1,130 @@
+import { type FC, useEffect } from 'react'
+import Input from '@/components/Input'
+// import { ArrowDown2, CloseCircle, HambergerMenu, Logout, Wallet } from 'iconsax-react'
+// import AvatarImage from '../assets/images/avatar_image.png'
+import { useTranslation } from 'react-i18next'
+import { useLocation } from 'react-router-dom'
+import { useSharedStore } from '@/shared/store/sharedStore'
+import { HambergerMenu } from 'iconsax-react'
+import { clx } from '@/helpers/utils'
+
+type SidebarSize = 'default' | 'wide'
+
+type HeaderProps = {
+ hasMainSidebar?: boolean
+ sidebarSize?: SidebarSize
+}
+
+const sidebarSizeClasses: Record
= {
+ default: {
+ base: 'xl:right-[285px] xl:w-[calc(100%-305px)]',
+ withSub: 'xl:right-[320px] xl:w-[calc(100%-340px)]',
+ },
+ wide: {
+ base: 'xl:right-[390px] xl:w-[calc(100%-406px)]',
+ withSub: 'xl:right-[425px] xl:w-[calc(100%-441px)]',
+ },
+}
+
+const Header: FC = ({ hasMainSidebar = true, sidebarSize = 'default' }) => {
+
+ // const location = useLocation();
+ // const [popoverKey, setPopoverKey] = useState(0);
+ const { t } = useTranslation('global')
+ const { setOpenSidebar, openSidebar, hasSubMenu, setSearch } = useSharedStore()
+ const location = useLocation()
+
+ // useEffect(() => {
+ // setPopoverKey((prevKey) => prevKey + 1);
+ // }, [location.pathname]);
+
+ // const handleLogout = () => {
+ // removeToken()
+ // removeRefreshToken()
+ // window.location.href = Pages.auth.login
+ // }
+
+ useEffect(() => {
+ setSearch('')
+ }, [location.pathname])
+
+ return (
+
+
+
+ setSearch(value)}
+ />
+
+
setOpenSidebar(!openSidebar)} className='xl:hidden block'>
+
+
+ {/*

*/}
+
+ {/*
+
+ */}
+ {/*
*/}
+ {/* {
+ data && (
+
+
+
+
+

+
+
+
+ {data?.data?.user?.firstName + ' ' + data?.data?.user?.lastName}
+
+
+
+
+
+
+
+
+ setPopoverKey((prevKey) => prevKey + 1)} size={20} color='#da2129' />
+
+
+
+

+
+
+
+ {data?.data?.user?.firstName + ' ' + data?.data?.user?.lastName}
+
+
+
+ {data?.data?.user?.email}
+
+
+
+
+
handleLogout()} className='flex gap-2 items-center cursor-pointer'>
+
+
+ {t('sidebar.logout')}
+
+
+
+
+
+
+ )
+ } */}
+
+
+ )
+}
+
+export default Header
\ No newline at end of file
diff --git a/src/shared/SideBar.tsx b/src/shared/SideBar.tsx
new file mode 100644
index 0000000..86f29f6
--- /dev/null
+++ b/src/shared/SideBar.tsx
@@ -0,0 +1,110 @@
+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 {
+ Home2,
+ Logout,
+} from 'iconsax-react'
+import SideBarItem from './SideBarItem'
+import { useLocation } from 'react-router-dom'
+import { useSharedStore } from './store/sharedStore'
+import { clx } from '../helpers/utils'
+import { Paths } from '../config/Paths'
+
+
+const SideBar: FC = () => {
+
+ const { t } = useTranslation('global')
+ const { openSidebar, setOpenSidebar, hasSubMenu, setSubMenuName, setSubtMenu, subMenuName } = useSharedStore()
+ const location = useLocation()
+
+ const isActive = (name: string) => {
+ return window.location.href.includes(name)
+ }
+
+ useEffect(() => {
+ const split = location.pathname.split('/')
+
+ if (split[1] === 'dashboard' || split[1] === 'products') {
+ setSubMenuName(split[1])
+ setSubtMenu(true)
+ } else {
+ setSubMenuName('')
+ setSubtMenu(false)
+ }
+ }, [location.pathname, setSubMenuName, setSubtMenu])
+
+ const iconSizeSideBar = 20
+
+ return (
+ <>
+ {
+ openSidebar && setOpenSidebar(false)} />
+ }
+
+
+ {
+ !hasSubMenu ?
+

+ :
+

+ }
+
+
+
+
+ {t('sidebar.menu')}
+
+
+
+ }
+ title={t('sidebar.home_page')}
+ isActive={isActive(Paths.home)}
+ link={Paths.home}
+ activeName={Paths.home}
+ />
+
+
+
+
+ }
+ title="خروج"
+ isActive={isActive('logout')}
+ link={`#`}
+ isLogout
+ activeName=''
+ />
+
+
+
+
+
+ {/* منوی فرعی */}
+ {
+ hasSubMenu && (openSidebar || window.innerWidth > 1139) &&
+
+ {
+ subMenuName === 'dashboard' ? null
+ //
+ : null
+ }
+
+ }
+ >
+ )
+}
+
+
+export default SideBar
\ No newline at end of file
diff --git a/src/shared/SideBarItem.tsx b/src/shared/SideBarItem.tsx
new file mode 100644
index 0000000..dbf3042
--- /dev/null
+++ b/src/shared/SideBarItem.tsx
@@ -0,0 +1,61 @@
+import { type FC, type ReactNode } from 'react'
+import { Link } from 'react-router-dom'
+import { clx } from '../helpers/utils'
+import { useSharedStore } from './store/sharedStore'
+// import { useGetAdminPermissions } from '../pages/users/hooks/useUserData'
+
+type Props = {
+ icon: ReactNode,
+ title: string,
+ isActive: boolean,
+ link: string,
+ isLogout?: boolean,
+ name?: string,
+ activeName?: string
+}
+
+const SideBarItem: FC
= (props: Props) => {
+
+ const { hasSubMenu, setSubMenuName, setSubtMenu } = useSharedStore()
+ // const { data: adminPermissions } = useGetAdminPermissions()
+ const handleLogout = () => {
+ // removeToken()
+ // removeRefreshToken()
+ // window.location.href = Pages.auth.login
+ }
+
+ const handleClick = () => {
+ if (props.name) {
+ setSubMenuName(props.name)
+ setSubtMenu(true)
+ }
+ }
+ // if (props.activeName === '' || props.activeName && adminPermissions?.data?.permissions?.some((permission: { name: string }) => permission.name === props.activeName)) {
+ if (true) {
+ return (
+
+
+
+ {props.icon}
+
+ {props.title}
+
+
+
+
+ )
+ }
+
+}
+
+export default SideBarItem
\ No newline at end of file
diff --git a/src/shared/store/sharedStore.ts b/src/shared/store/sharedStore.ts
new file mode 100644
index 0000000..bd93a94
--- /dev/null
+++ b/src/shared/store/sharedStore.ts
@@ -0,0 +1,13 @@
+import { create } from "zustand";
+import { type SharedStoreType } from "../types/SharedTypes";
+
+export const useSharedStore = create((set) => ({
+ openSidebar: false,
+ setOpenSidebar: (value) => set({ openSidebar: value }),
+ hasSubMenu: false,
+ setSubtMenu: (value: boolean) => set({ hasSubMenu: value }),
+ subMenuName: "",
+ setSubMenuName: (value: string) => set({ subMenuName: value }),
+ search: "",
+ setSearch: (value: string) => set({ search: value }),
+}));
diff --git a/src/shared/types/SharedTypes.ts b/src/shared/types/SharedTypes.ts
new file mode 100644
index 0000000..8eb851c
--- /dev/null
+++ b/src/shared/types/SharedTypes.ts
@@ -0,0 +1,19 @@
+export type SharedStoreType = {
+ openSidebar: boolean;
+ setOpenSidebar: (value: boolean) => void;
+ hasSubMenu: boolean;
+ setSubtMenu: (value: boolean) => void;
+ subMenuName: string;
+ setSubMenuName: (value: string) => void;
+ search: string;
+ setSearch: (value: string) => void;
+};
+
+export type PagerType = {
+ page: number;
+ limit: number;
+ totalItems: number;
+ totalPages: number;
+ prevPage: boolean | null;
+ nextPage: string | null;
+};
diff --git a/tsconfig.app.json b/tsconfig.app.json
index a9b5a59..4d8c378 100644
--- a/tsconfig.app.json
+++ b/tsconfig.app.json
@@ -15,6 +15,10 @@
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["src/*"]
+ },
/* Linting */
"strict": true,
diff --git a/vite.config.ts b/vite.config.ts
index adeab7d..db3fc25 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,6 +1,7 @@
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";
+import { fileURLToPath, URL } from "node:url";
// https://vite.dev/config/
export default defineConfig({
@@ -12,4 +13,9 @@ export default defineConfig({
}),
tailwindcss(),
],
+ resolve: {
+ alias: {
+ "@": fileURLToPath(new URL("./src", import.meta.url)),
+ },
+ },
});