diff --git a/package-lock.json b/package-lock.json
index 5ecbbfd..19ec2f0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,6 +11,7 @@
"@tanstack/react-query": "^5.62.8",
"formik": "^2.4.6",
"i18next": "^24.2.0",
+ "iconsax-react": "^0.0.8",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-i18next": "^15.2.0",
@@ -2815,6 +2816,18 @@
}
}
},
+ "node_modules/iconsax-react": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/iconsax-react/-/iconsax-react-0.0.8.tgz",
+ "integrity": "sha512-l3dVk4zGtkkJHgvNYqAf0wDKqnKxXykee5/DoESGo2JvSYwaxajJUHSX2YrPRXSov8Hd8ClGFwJxCEaEjrFD1Q==",
+ "license": "MIT",
+ "dependencies": {
+ "prop-types": "^15.7.2"
+ },
+ "peerDependencies": {
+ "react": "*"
+ }
+ },
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -3107,7 +3120,6 @@
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"license": "MIT",
- "peer": true,
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
},
@@ -3589,7 +3601,6 @@
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
"license": "MIT",
- "peer": true,
"dependencies": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
diff --git a/package.json b/package.json
index 0fcb0ec..3856163 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,7 @@
"@tanstack/react-query": "^5.62.8",
"formik": "^2.4.6",
"i18next": "^24.2.0",
+ "iconsax-react": "^0.0.8",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-i18next": "^15.2.0",
diff --git a/src/config/Pages.ts b/src/config/Pages.ts
index ba89ecc..2b904f8 100644
--- a/src/config/Pages.ts
+++ b/src/config/Pages.ts
@@ -4,4 +4,18 @@ export const Pages = {
register: "/auth/register",
forgotPassword: "/auth/forgot",
},
+ dashboard: "/dashboard",
+ services: {
+ mine: "/services",
+ other: "/other-service",
+ },
+ transactions: "/transactions",
+ receipts: "/receipts",
+ ticket: {
+ list: "/tickets",
+ },
+ announcement: "/announcement",
+ criticisms: "/criticisms",
+ learning: "/learning",
+ setting: "/setting",
};
diff --git a/src/index.css b/src/index.css
index fb14904..6290bbd 100644
--- a/src/index.css
+++ b/src/index.css
@@ -53,3 +53,12 @@ textarea::placeholder {
.otp div {
width: 100%;
}
+
+.no-scrollbar::-webkit-scrollbar {
+ display: none;
+}
+
+.no-scrollbar {
+ -ms-overflow-style: none;
+ scrollbar-width: none;
+}
diff --git a/src/langs/fa.json b/src/langs/fa.json
index e6a7379..e92f7d7 100644
--- a/src/langs/fa.json
+++ b/src/langs/fa.json
@@ -39,5 +39,20 @@
},
"errors": {
"required": "این فیلد اجباری می باشد"
+ },
+ "sidebar": {
+ "menu": "منو",
+ "mainpage": "صفحه اصلی",
+ "myservice": "سرویس های من",
+ "other_service": "سایر سرویس ها",
+ "receipt_list": "لیست صورتحساب",
+ "transactions": "تراکنش ها",
+ "other": "سایر",
+ "ticket": "تیکت ها",
+ "announcement": "اطلاعیه ها",
+ "criticisms": "انتقادات",
+ "learning": "آموزش",
+ "setting": "تنظیمات",
+ "logout": "خروج"
}
}
diff --git a/src/router/Main.tsx b/src/router/Main.tsx
index 68617fd..72be757 100644
--- a/src/router/Main.tsx
+++ b/src/router/Main.tsx
@@ -1,8 +1,13 @@
import { FC } from 'react'
+import SideBar from '../shared/SideBar'
+import Header from '../shared/Header'
const MainRouter: FC = () => {
return (
-
Main
+
+
+
+
)
}
diff --git a/src/shared/Header.tsx b/src/shared/Header.tsx
new file mode 100644
index 0000000..ad0998f
--- /dev/null
+++ b/src/shared/Header.tsx
@@ -0,0 +1,11 @@
+import { FC } from 'react'
+
+const Header: FC = () => {
+ return (
+
+
+
+ )
+}
+
+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..388922b
--- /dev/null
+++ b/src/shared/SideBar.tsx
@@ -0,0 +1,124 @@
+import { FC } from 'react'
+import LogoImage from '../assets/images/logo.svg'
+import { useTranslation } from 'react-i18next'
+import { Card, DocumentText, Element3, Element4, Home2, Logout, Messages3, NotificationStatus, Receipt21, Setting2, Teacher } from 'iconsax-react'
+import SideBarItem from './SideBarItem'
+import { useLocation } from 'react-router-dom'
+import { Pages } from '../config/Pages'
+
+const SideBar: FC = () => {
+
+ const { t } = useTranslation('global')
+ const location = useLocation()
+
+ const isActive = (name: string) => {
+ return location.pathname.includes(name)
+ }
+
+ const iconSizeSideBar = 20
+
+ return (
+
+
+

+
+
+
+
+ {t('sidebar.menu')}
+
+
+
+ }
+ title={t('sidebar.mainpage')}
+ isActive={isActive('dashboard')}
+ link={Pages.dashboard}
+ />
+ }
+ title={t('sidebar.myservice')}
+ isActive={isActive('services')}
+ link={Pages.services.mine}
+ />
+ }
+ title={t('sidebar.other_service')}
+ isActive={isActive('other-service')}
+ link={Pages.services.other}
+ />
+ }
+ title={t('sidebar.receipt_list')}
+ isActive={isActive('receipts')}
+ link={Pages.receipts}
+ />
+ }
+ title={t('sidebar.transactions')}
+ isActive={isActive('transactions')}
+ link={Pages.transactions}
+ />
+
+
+
+ {t('sidebar.other')}
+
+
+
+ }
+ title={t('sidebar.ticket')}
+ isActive={isActive('tickets')}
+ link={Pages.ticket.list}
+ />
+
+
+ }
+ title={t('sidebar.announcement')}
+ isActive={isActive('announcement')}
+ link={Pages.announcement}
+ />
+
+
+ }
+ title={t('sidebar.criticisms')}
+ isActive={isActive('criticisms')}
+ link={Pages.criticisms}
+ />
+
+
+ }
+ title={t('sidebar.learning')}
+ isActive={isActive('learning')}
+ link={Pages.learning}
+ />
+
+
+
+
+ }
+ title={t('sidebar.setting')}
+ isActive={isActive('setting')}
+ link={Pages.setting}
+ />
+
+
+ }
+ title={t('sidebar.logout')}
+ isActive={isActive('logout')}
+ link={`#`}
+ />
+
+
+
+
+ )
+}
+
+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..271c00e
--- /dev/null
+++ b/src/shared/SideBarItem.tsx
@@ -0,0 +1,38 @@
+import { FC, ReactNode } from 'react'
+import { Link } from 'react-router-dom'
+import { clx } from '../helpers/utils'
+import { Pages } from '../config/Pages'
+
+type Props = {
+ icon: ReactNode,
+ title: string,
+ isActive: boolean,
+ link: string,
+ isLogout?: boolean,
+}
+
+const SideBarItem: FC = (props: Props) => {
+
+ const handleLogout = () => {
+ localStorage.removeItem(import.meta.env.VITE_TOKEN_NAME)
+ window.location.href = Pages.auth.login
+ }
+
+ return (
+
+
+
+ {props.icon}
+
+ {props.title}
+
+
+
+
+ )
+}
+
+export default SideBarItem
\ No newline at end of file
diff --git a/tailwind.config.js b/tailwind.config.js
index cf9c5e7..3139b0c 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -10,7 +10,8 @@ export default {
primary: 'black',
secondary: '#F4F5F9',
border: '#D0D0D0',
- description: '#888888'
+ description: '#888888',
+ header: "#C3C7DD"
},
borderRadius: {
'2.5': '10px'