sidebar
This commit is contained in:
Generated
+13
-2
@@ -11,6 +11,7 @@
|
|||||||
"@tanstack/react-query": "^5.62.8",
|
"@tanstack/react-query": "^5.62.8",
|
||||||
"formik": "^2.4.6",
|
"formik": "^2.4.6",
|
||||||
"i18next": "^24.2.0",
|
"i18next": "^24.2.0",
|
||||||
|
"iconsax-react": "^0.0.8",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-i18next": "^15.2.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": {
|
"node_modules/ignore": {
|
||||||
"version": "5.3.2",
|
"version": "5.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
"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",
|
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
"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",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.4.0",
|
"loose-envify": "^1.4.0",
|
||||||
"object-assign": "^4.1.1",
|
"object-assign": "^4.1.1",
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
"@tanstack/react-query": "^5.62.8",
|
"@tanstack/react-query": "^5.62.8",
|
||||||
"formik": "^2.4.6",
|
"formik": "^2.4.6",
|
||||||
"i18next": "^24.2.0",
|
"i18next": "^24.2.0",
|
||||||
|
"iconsax-react": "^0.0.8",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-i18next": "^15.2.0",
|
"react-i18next": "^15.2.0",
|
||||||
|
|||||||
@@ -4,4 +4,18 @@ export const Pages = {
|
|||||||
register: "/auth/register",
|
register: "/auth/register",
|
||||||
forgotPassword: "/auth/forgot",
|
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",
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -53,3 +53,12 @@ textarea::placeholder {
|
|||||||
.otp div {
|
.otp div {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.no-scrollbar::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-scrollbar {
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,5 +39,20 @@
|
|||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"required": "این فیلد اجباری می باشد"
|
"required": "این فیلد اجباری می باشد"
|
||||||
|
},
|
||||||
|
"sidebar": {
|
||||||
|
"menu": "منو",
|
||||||
|
"mainpage": "صفحه اصلی",
|
||||||
|
"myservice": "سرویس های من",
|
||||||
|
"other_service": "سایر سرویس ها",
|
||||||
|
"receipt_list": "لیست صورتحساب",
|
||||||
|
"transactions": "تراکنش ها",
|
||||||
|
"other": "سایر",
|
||||||
|
"ticket": "تیکت ها",
|
||||||
|
"announcement": "اطلاعیه ها",
|
||||||
|
"criticisms": "انتقادات",
|
||||||
|
"learning": "آموزش",
|
||||||
|
"setting": "تنظیمات",
|
||||||
|
"logout": "خروج"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-1
@@ -1,8 +1,13 @@
|
|||||||
import { FC } from 'react'
|
import { FC } from 'react'
|
||||||
|
import SideBar from '../shared/SideBar'
|
||||||
|
import Header from '../shared/Header'
|
||||||
|
|
||||||
const MainRouter: FC = () => {
|
const MainRouter: FC = () => {
|
||||||
return (
|
return (
|
||||||
<div>Main</div>
|
<div className='p-4'>
|
||||||
|
<SideBar />
|
||||||
|
<Header />
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { FC } from 'react'
|
||||||
|
|
||||||
|
const Header: FC = () => {
|
||||||
|
return (
|
||||||
|
<div className='fixed right-[280px] top-4 h-20 bg-white rounded-[32px] w-full'>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Header
|
||||||
@@ -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 (
|
||||||
|
<div className='fixed right-4 top-4 bottom-4 rounded-[32px] w-[250px] bg-white flex flex-col py-12'>
|
||||||
|
<div className='flex justify-center'>
|
||||||
|
<img src={LogoImage} className='w-[140px]' />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex-1 h-full overflow-y-auto no-scrollbar'>
|
||||||
|
<div className='mt-10 px-12 text-header text-sm font-normal'>
|
||||||
|
{t('sidebar.menu')}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='text-xs text-[#8C90A3]'>
|
||||||
|
<SideBarItem
|
||||||
|
icon={<Home2 variant={isActive('dashboard') ? 'Bold' : 'Outline'} color={isActive('dashboard') ? 'black' : '#8C90A3'} size={iconSizeSideBar} />}
|
||||||
|
title={t('sidebar.mainpage')}
|
||||||
|
isActive={isActive('dashboard')}
|
||||||
|
link={Pages.dashboard}
|
||||||
|
/>
|
||||||
|
<SideBarItem
|
||||||
|
icon={<Element3 variant={isActive('services') ? 'Bold' : 'Outline'} color={isActive('services') ? 'black' : '#8C90A3'} size={iconSizeSideBar} />}
|
||||||
|
title={t('sidebar.myservice')}
|
||||||
|
isActive={isActive('services')}
|
||||||
|
link={Pages.services.mine}
|
||||||
|
/>
|
||||||
|
<SideBarItem
|
||||||
|
icon={<Element4 variant={isActive('other-service') ? 'Bold' : 'Outline'} color={isActive('other-service') ? 'black' : '#8C90A3'} size={iconSizeSideBar} />}
|
||||||
|
title={t('sidebar.other_service')}
|
||||||
|
isActive={isActive('other-service')}
|
||||||
|
link={Pages.services.other}
|
||||||
|
/>
|
||||||
|
<SideBarItem
|
||||||
|
icon={<Receipt21 variant={isActive('receipts') ? 'Bold' : 'Outline'} color={isActive('receipts') ? 'black' : '#8C90A3'} size={iconSizeSideBar} />}
|
||||||
|
title={t('sidebar.receipt_list')}
|
||||||
|
isActive={isActive('receipts')}
|
||||||
|
link={Pages.receipts}
|
||||||
|
/>
|
||||||
|
<SideBarItem
|
||||||
|
icon={<Card variant={isActive('transactions') ? 'Bold' : 'Outline'} color={isActive('transactions') ? 'black' : '#8C90A3'} size={iconSizeSideBar} />}
|
||||||
|
title={t('sidebar.transactions')}
|
||||||
|
isActive={isActive('transactions')}
|
||||||
|
link={Pages.transactions}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-10 px-12 text-header text-sm font-normal'>
|
||||||
|
{t('sidebar.other')}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='text-xs text-[#8C90A3]'>
|
||||||
|
<SideBarItem
|
||||||
|
icon={<Messages3 variant={isActive('tickets') ? 'Bold' : 'Outline'} color={isActive('tickets') ? 'black' : '#8C90A3'} size={iconSizeSideBar} />}
|
||||||
|
title={t('sidebar.ticket')}
|
||||||
|
isActive={isActive('tickets')}
|
||||||
|
link={Pages.ticket.list}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='text-xs text-[#8C90A3]'>
|
||||||
|
<SideBarItem
|
||||||
|
icon={<NotificationStatus variant={isActive('announcement') ? 'Bold' : 'Outline'} color={isActive('announcement') ? 'black' : '#8C90A3'} size={iconSizeSideBar} />}
|
||||||
|
title={t('sidebar.announcement')}
|
||||||
|
isActive={isActive('announcement')}
|
||||||
|
link={Pages.announcement}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='text-xs text-[#8C90A3]'>
|
||||||
|
<SideBarItem
|
||||||
|
icon={<DocumentText variant={isActive('criticisms') ? 'Bold' : 'Outline'} color={isActive('criticisms') ? 'black' : '#8C90A3'} size={iconSizeSideBar} />}
|
||||||
|
title={t('sidebar.criticisms')}
|
||||||
|
isActive={isActive('criticisms')}
|
||||||
|
link={Pages.criticisms}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='text-xs text-[#8C90A3]'>
|
||||||
|
<SideBarItem
|
||||||
|
icon={<Teacher variant={isActive('learning') ? 'Bold' : 'Outline'} color={isActive('learning') ? 'black' : '#8C90A3'} size={iconSizeSideBar} />}
|
||||||
|
title={t('sidebar.learning')}
|
||||||
|
isActive={isActive('learning')}
|
||||||
|
link={Pages.learning}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex-1 items-end mt-14'>
|
||||||
|
<div className='text-xs text-[#8C90A3]'>
|
||||||
|
<SideBarItem
|
||||||
|
icon={<Setting2 variant={isActive('setting') ? 'Bold' : 'Outline'} color={isActive('setting') ? 'black' : '#8C90A3'} size={iconSizeSideBar} />}
|
||||||
|
title={t('sidebar.setting')}
|
||||||
|
isActive={isActive('setting')}
|
||||||
|
link={Pages.setting}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='text-xs text-[#8C90A3]'>
|
||||||
|
<SideBarItem
|
||||||
|
icon={<Logout variant={isActive('logout') ? 'Bold' : 'Outline'} color={isActive('logout') ? 'black' : '#8C90A3'} size={iconSizeSideBar} />}
|
||||||
|
title={t('sidebar.logout')}
|
||||||
|
isActive={isActive('logout')}
|
||||||
|
link={`#`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SideBar
|
||||||
@@ -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: Props) => {
|
||||||
|
|
||||||
|
const handleLogout = () => {
|
||||||
|
localStorage.removeItem(import.meta.env.VITE_TOKEN_NAME)
|
||||||
|
window.location.href = Pages.auth.login
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link onClick={props.isLogout ? handleLogout : undefined} to={props.link} className='flex text-xs gap-9 mt-4'>
|
||||||
|
<div className={clx(
|
||||||
|
'w-1 bg-black h-6',
|
||||||
|
!props.isActive && 'invisible'
|
||||||
|
)}></div>
|
||||||
|
<div className='flex gap-3 items-center'>
|
||||||
|
{props.icon}
|
||||||
|
<div className={props.isActive ? 'text-black' : ''}>
|
||||||
|
{props.title}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SideBarItem
|
||||||
+2
-1
@@ -10,7 +10,8 @@ export default {
|
|||||||
primary: 'black',
|
primary: 'black',
|
||||||
secondary: '#F4F5F9',
|
secondary: '#F4F5F9',
|
||||||
border: '#D0D0D0',
|
border: '#D0D0D0',
|
||||||
description: '#888888'
|
description: '#888888',
|
||||||
|
header: "#C3C7DD"
|
||||||
},
|
},
|
||||||
borderRadius: {
|
borderRadius: {
|
||||||
'2.5': '10px'
|
'2.5': '10px'
|
||||||
|
|||||||
Reference in New Issue
Block a user