From 1fb0091aa20b01a76e70cd6e079c326481610b4d Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Sun, 19 Jul 2026 09:17:12 +0330 Subject: [PATCH] sidebar change --- .cursor/skills/danak-admin/SKILL.md | 10 +- .cursor/skills/danak-admin/add-feature.md | 8 +- src/config/SideBarSubMenu.ts | 66 +- src/shared/SideBar.tsx | 978 +++--------------- src/shared/components/AccessLogsSubMenu.tsx | 62 -- src/shared/components/BlogSubMenu.tsx | 50 - src/shared/components/ContentSubMenu.tsx | 95 ++ src/shared/components/CustomerSubMenu.tsx | 50 - src/shared/components/DkalaSubMenu.tsx | 61 ++ src/shared/components/DmailSubMenu.tsx | 37 + src/shared/components/DmenuSubMenu.tsx | 61 ++ src/shared/components/DpageSubMenu.tsx | 37 + src/shared/components/FinancialSubMenu.tsx | 74 ++ src/shared/components/LearningSubMenu.tsx | 52 - src/shared/components/MenuSubMenu.tsx | 176 ++++ src/shared/components/OtherSubMenu.tsx | 108 ++ src/shared/components/ReceiptSubMenu.tsx | 46 - src/shared/components/ResellerSubMenu.tsx | 43 + src/shared/components/ServicesSubMenu.tsx | 57 - src/shared/components/SubMenuAccordion.tsx | 53 + src/shared/components/SubMenuItem.tsx | 59 +- src/shared/components/SupportSubMenu.tsx | 47 - src/shared/components/TicketSubMenu.tsx | 52 - src/shared/components/TransactionsSubMenu.tsx | 38 - src/shared/components/UsersSubMenu.tsx | 64 -- 25 files changed, 1008 insertions(+), 1376 deletions(-) delete mode 100644 src/shared/components/AccessLogsSubMenu.tsx delete mode 100644 src/shared/components/BlogSubMenu.tsx create mode 100644 src/shared/components/ContentSubMenu.tsx delete mode 100644 src/shared/components/CustomerSubMenu.tsx create mode 100644 src/shared/components/DkalaSubMenu.tsx create mode 100644 src/shared/components/DmailSubMenu.tsx create mode 100644 src/shared/components/DmenuSubMenu.tsx create mode 100644 src/shared/components/DpageSubMenu.tsx create mode 100644 src/shared/components/FinancialSubMenu.tsx delete mode 100644 src/shared/components/LearningSubMenu.tsx create mode 100644 src/shared/components/MenuSubMenu.tsx create mode 100644 src/shared/components/OtherSubMenu.tsx delete mode 100644 src/shared/components/ReceiptSubMenu.tsx create mode 100644 src/shared/components/ResellerSubMenu.tsx delete mode 100644 src/shared/components/ServicesSubMenu.tsx create mode 100644 src/shared/components/SubMenuAccordion.tsx delete mode 100644 src/shared/components/SupportSubMenu.tsx delete mode 100644 src/shared/components/TicketSubMenu.tsx delete mode 100644 src/shared/components/TransactionsSubMenu.tsx delete mode 100644 src/shared/components/UsersSubMenu.tsx diff --git a/.cursor/skills/danak-admin/SKILL.md b/.cursor/skills/danak-admin/SKILL.md index 6a52769..555a9b5 100644 --- a/.cursor/skills/danak-admin/SKILL.md +++ b/.cursor/skills/danak-admin/SKILL.md @@ -87,10 +87,12 @@ Dynamic routes use string concat: `Pages.customer.update + ":id"`. ## Sidebar & submenu -- Main items: `SideBarItem` in `SideBar.tsx` with `link`, `isActive`, `activeName` -- Features with sub-nav: add segment to `SideBarItemHasSubMenu` in `src/config/SideBarSubMenu.ts`, create `{Feature}SubMenu.tsx` in `src/shared/components/`, render it in the `subMenuName === "..."` block at bottom of `SideBar.tsx` -- Submenu items use `SubMenuItem` with `Pages.*` links -- `subMenuName` is derived from first URL segment (`location.pathname.split("/")[1]`) +- Main sidebar shows **group** items (`menu`, `financial`, `other`, `content`, …) via `SideBarItem` with `name` matching the group key +- Each group opens a side panel: `{Group}SubMenu.tsx` in `src/shared/components/` (e.g. `MenuSubMenu.tsx`) +- Map URL → group in `getSubMenuNameFromPath` (`src/config/SideBarSubMenu.ts`) +- Flat links inside a group: `SubMenuItem` +- Nested feature menus inside a group: `SubMenuAccordion` (arrow open/close) wrapping `SubMenuItem` children +- `subMenuName` comes from the group key, not the feature path segment ## Conventions diff --git a/.cursor/skills/danak-admin/add-feature.md b/.cursor/skills/danak-admin/add-feature.md index 2501acd..412295b 100644 --- a/.cursor/skills/danak-admin/add-feature.md +++ b/.cursor/skills/danak-admin/add-feature.md @@ -58,10 +58,10 @@ import CouponsList from "../pages/coupons/List"; **Multi-page feature** — also: -1. Add `"coupons"` to `SideBarItemHasSubMenu` in `src/config/SideBarSubMenu.ts` -2. Create `src/shared/components/CouponsSubMenu.tsx` (copy `CustomerSubMenu.tsx`) -3. Import and add branch in `SideBar.tsx`: `subMenuName === "coupons" ? : ...` -4. Point main sidebar link to list path; first URL segment must match `activeName` / submenu key +1. Add the feature’s URL segment → group mapping in `getSubMenuNameFromPath` / `pathSegmentToSubMenu` (`src/config/SideBarSubMenu.ts`) +2. Add links under the matching group SubMenu (e.g. `MenuSubMenu.tsx`) using `SubMenuItem` +3. If the feature has nested pages, wrap them in `SubMenuAccordion` (arrow open/close) inside that group SubMenu +4. Do not add a new top-level sidebar group unless the feature is a new section (reseller/dmenu-style) ## 5. Translations diff --git a/src/config/SideBarSubMenu.ts b/src/config/SideBarSubMenu.ts index f734f50..c09def2 100644 --- a/src/config/SideBarSubMenu.ts +++ b/src/config/SideBarSubMenu.ts @@ -1,11 +1,59 @@ export const SideBarItemHasSubMenu = [ - "services", - "customers", - "receipts", - "users", - "tickets", - "learning", - "blog", - "support", - "accessLogs", + "menu", + "financial", + "other", + "content", + "reseller", + "dmenu", + "dkala", + "dpage", + "dmail", ]; + +const pathSegmentToSubMenu: Record = { + dashboard: "menu", + services: "menu", + support: "menu", + customers: "menu", + representatives: "menu", + developers: "menu", + payments: "menu", + "referral-code": "menu", + users: "menu", + sliders: "menu", + subscriptions: "financial", + receipts: "financial", + transactions: "financial", + discounts: "financial", + "card-bank": "financial", + tickets: "other", + feedback: "other", + "access-logs": "other", + criticisms: "other", + workspace: "other", + project: "other", + taskmanager: "other", + ads: "content", + announcement: "content", + blog: "content", + learning: "content", + messages: "content", + reseller: "reseller", + dmenu: "dmenu", + dkala: "dkala", + dpage: "dpage", + dmail: "dmail", +}; + +export const getSubMenuNameFromPath = (pathname: string): string => { + if (pathname.startsWith("/customers/subscriptions")) { + return "financial"; + } + + if (pathname.startsWith("/workspace") || pathname.startsWith("/project") || pathname.startsWith("/taskmanager")) { + return "other"; + } + + const segment = pathname.split("/")[1] ?? ""; + return pathSegmentToSubMenu[segment] ?? ""; +}; diff --git a/src/shared/SideBar.tsx b/src/shared/SideBar.tsx index 65b8b4a..c2021db 100644 --- a/src/shared/SideBar.tsx +++ b/src/shared/SideBar.tsx @@ -1,86 +1,51 @@ import { - Activity, - ArrowDown2, - BagTick, Building, - Card, Category, - Chart21, - Code, - CodeCircle, DocumentLike, - DocumentText, Element3, Gallery, Global, - Headphone, - Home2, - Icon, Logout, - Messages3, - Money, Money3, - NotificationStatus, - People, - Profile, - Receipt21, Setting2, - Sms, - SmsTracking, - Task, - Teacher, - TicketDiscount, - UserSquare, UserTick, - Warning2, } from "iconsax-react"; -import { FC, useEffect, useState } from "react"; +import { FC, useEffect } from "react"; import { useTranslation } from "react-i18next"; import { useLocation } from "react-router-dom"; import LogoSmall from "../assets/images/logo-small.svg"; import LogoImage from "../assets/images/logo.svg"; import { Pages } from "../config/Pages"; -import { SideBarItemHasSubMenu } from "../config/SideBarSubMenu"; +import { getSubMenuNameFromPath } from "../config/SideBarSubMenu"; import { clx } from "../helpers/utils"; import { useGetProfile } from "../pages/profile/hooks/useProfileData"; import { useGetAdminPermissions } from "../pages/users/hooks/useUserData"; -import AccessLogsSubMenu from "./components/AccessLogsSubMenu"; -import BlogSubMenu from "./components/BlogSubMenu"; -import CustomerSubMenu from "./components/CustomerSubMenu"; -import LearningSubMenu from "./components/LearningSubMenu"; -import ReceiptSubMenu from "./components/ReceiptSubMenu"; -import ServicesSubMenu from "./components/ServicesSubMenu"; -import SupportSubMenu from "./components/SupportSubMenu"; -import TicketSubMenu from "./components/TicketSubMenu"; -import UsersSubMenu from "./components/UsersSubMenu"; +import ContentSubMenu from "./components/ContentSubMenu"; +import DkalaSubMenu from "./components/DkalaSubMenu"; +import DmailSubMenu from "./components/DmailSubMenu"; +import DmenuSubMenu from "./components/DmenuSubMenu"; +import DpageSubMenu from "./components/DpageSubMenu"; +import FinancialSubMenu from "./components/FinancialSubMenu"; +import MenuSubMenu from "./components/MenuSubMenu"; +import OtherSubMenu from "./components/OtherSubMenu"; +import ResellerSubMenu from "./components/ResellerSubMenu"; import SideBarItem from "./SideBarItem"; import { useSharedStore } from "./store/sharedStore"; + const SideBar: FC = () => { const { t } = useTranslation("global"); const { openSidebar, setOpenSidebar, hasSubMenu, setSubMenuName, setSubtMenu, subMenuName } = useSharedStore(); const location = useLocation(); const { data: profile } = useGetProfile(); const { data: adminPermissions } = useGetAdminPermissions(); - const isActive = (name: string) => { - return location.pathname.includes(name); - }; - const isTaskManagerActive = - location.pathname.startsWith(Pages.taskmanager.workspace) || - location.pathname === Pages.taskmanager.workspaceList || - location.pathname.startsWith(Pages.taskmanager.updateWorkspace) || - location.pathname === Pages.taskmanager.createWorkspace || - location.pathname === Pages.taskmanager.createProject || - location.pathname.startsWith(Pages.taskmanager.updateProject) || - location.pathname.startsWith(Pages.taskmanager.projectList); - - const [openMenu, setOpenMenu] = useState(["menu"]); + const isGroupActive = (name: string) => subMenuName === name || getSubMenuNameFromPath(location.pathname) === name; useEffect(() => { - const split = location.pathname.split("/"); + const groupName = getSubMenuNameFromPath(location.pathname); - if (SideBarItemHasSubMenu.includes(split[1])) { - setSubMenuName(split[1]); + if (groupName) { + setSubMenuName(groupName); setSubtMenu(true); } else { setSubMenuName(""); @@ -92,17 +57,6 @@ const SideBar: FC = () => { const iconSizeSideBar = 20; - const handleOpenMenu = (name: string) => { - const opens = [...openMenu]; - const index = opens.findIndex((o) => o === name); - if (index > -1) { - opens.splice(index, 1); - } else { - opens.push(name); - } - setOpenMenu(opens); - }; - return ( <> {openSidebar && ( @@ -133,771 +87,167 @@ const SideBar: FC = () => {
-
handleOpenMenu("menu")} - className={clx("mt-10 px-12 text-header text-sm font-normal cursor-pointer", hasSubMenu && "px-2 text-center", !hasSubMenu && "flex gap-2 items-center")} - > - {t("sidebar.menu")} - -
- -
-
- -
- - } - title={t("sidebar.mainpage")} - isActive={isActive("dashboard")} - link={Pages.dashboard} - activeName="" - /> +
} - title={t("sidebar.services")} - isActive={isActive("services")} - link={Pages.services.list} - name="services" - activeName="services" - /> - - - } - title={t("sidebar.support")} - isActive={isActive("support")} - link={Pages.support.list} - activeName="support_plan" - /> - - - } - 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" + title={t("sidebar.menu")} + isActive={isGroupActive("menu")} + link={Pages.dashboard} + name="menu" + activeName="" /> } - title={t("sidebar.payments")} - isActive={isActive("payments")} - link={Pages.payment.list} - activeName="payments" + title={t("sidebar.financial")} + isActive={isGroupActive("financial")} + link={Pages.receipts.index} + name="financial" + activeName="" /> - - } - 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" - /> {profile?.data?.user?.roles?.some((role: { name: string }) => role.name === "super_admin") && ( } - title={t("sidebar.sliders")} - isActive={isActive("sliders")} - link={Pages.sliders.list} - activeName="blogs" + title={t("sidebar.other")} + isActive={isGroupActive("other")} + link={Pages.ticket.list} + name="other" + activeName="" + /> + )} + + + } + title={t("sidebar.mnage_content")} + isActive={isGroupActive("content")} + link={Pages.ads.list} + name="content" + activeName="" + /> + + {adminPermissions?.data?.permissions?.some((permission: { name: string }) => permission.name === "reseller") && ( + + } + title={t("sidebar.reseller")} + isActive={isGroupActive("reseller")} + link={Pages.reseller.list} + name="reseller" + activeName="reseller" + /> + )} + + {adminPermissions?.data?.permissions?.some((permission: { name: string }) => permission.name === "dmenu") && ( + + } + title={t("sidebar.dmenu")} + isActive={isGroupActive("dmenu")} + link={Pages.dmenu.icons.list} + name="dmenu" + activeName="dmenu" + /> + )} + + {adminPermissions?.data?.permissions?.some((permission: { name: string }) => permission.name === "dkala") && ( + + } + title={t("sidebar.dkala")} + isActive={isGroupActive("dkala")} + link={Pages.dkala.icons.list} + name="dkala" + activeName="dkala" + /> + )} + + {adminPermissions?.data?.permissions?.some((permission: { name: string }) => permission.name === "dpage") && ( + + } + title={t("sidebar.dpage")} + isActive={isGroupActive("dpage")} + link={Pages.dpage.stickers.list} + name="dpage" + activeName="dpage" + /> + )} + + {adminPermissions?.data?.permissions?.some((permission: { name: string }) => permission.name === "dmail") && ( + + } + title={t("sidebar.dmail")} + isActive={isGroupActive("dmail")} + link={Pages.dmail.list} + name="dmail" + activeName="dmail" /> )}
- { -
handleOpenMenu("financial")} - className={clx("mt-10 px-12 text-header text-sm font-normal cursor-pointer", hasSubMenu && "px-2 text-center", !hasSubMenu && "flex gap-2 items-center")} - > - {t("sidebar.financial")} - -
- -
-
- } -
- - } - title={t("sidebar.subscriptions")} - isActive={isActive("subscriptions")} - link={Pages.subscriptions.list} - activeName="payments" - /> - - - } - 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.discounts")} - isActive={isActive("discounts")} - link={Pages.discount.list} - activeName="discounts" - /> - - - } - title={t("sidebar.card")} - isActive={isActive("card")} - link={Pages.cardBank.list} - activeName="bank_accounts" - /> -
- - {profile?.data?.user?.roles.some((role: { name: string }) => role.name === "super_admin") && ( -
handleOpenMenu("other")} - className={clx("mt-10 px-12 text-header text-sm font-normal cursor-pointer", hasSubMenu && "px-2 text-center", !hasSubMenu && "flex gap-2 items-center")} - > - {t("sidebar.other")} - -
- -
-
- )} - -
- - } - title={t("sidebar.ticket")} - isActive={isActive("tickets")} - link={Pages.ticket.list} - activeName="tickets" - /> - - - } - title={t("sidebar.feedback")} - isActive={isActive("feedback")} - link={Pages.feedback.list} - activeName="services" - /> - -
- - } - title={t("sidebar.accessLogs")} - isActive={isActive("access-logs")} - link={Pages.accessLogs.list} - name="accessLogs" - activeName="logs" - /> -
- -
- - } - title={t("sidebar.criticisms")} - isActive={isActive("criticisms")} - link={Pages.criticisms.list} - activeName="criticisms" - /> -
- -
- - } - title={t("sidebar.taskmanager")} - isActive={isTaskManagerActive} - link={Pages.taskmanager.workspaceList} - activeName="" - /> -
-
- - {profile?.data?.user?.roles?.some((role: { name: string }) => role.name === "super_admin") && ( -
handleOpenMenu("content")} - className={clx("mt-10 px-12 text-header text-sm font-normal cursor-pointer", hasSubMenu && "px-2 text-center text-xs", !hasSubMenu && "flex gap-2 items-center")} - > - {t("sidebar.mnage_content")} - -
- -
-
- )} - - {adminPermissions?.data?.permissions?.some((permission: { name: string }) => permission.name === "reseller") && ( - <> -
handleOpenMenu("reseller")} - className={clx("mt-10 px-12 text-header text-sm font-normal cursor-pointer", hasSubMenu && "px-2 text-center", !hasSubMenu && "flex gap-2 items-center")} - > - {t("sidebar.reseller")} - -
- -
-
-
-
- - } - title={t("sidebar.resellers")} - isActive={isActive("reseller/list")} - link={Pages.reseller.list} - activeName="reseller" - /> -
- -
- - } - title={t("sidebar.withdraw")} - isActive={isActive("reseller/withdraw")} - link={Pages.reseller.withdraw} - activeName="reseller" - /> -
-
- - )} - -
-
- - } - 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")} - isActive={isActive("blog")} - link={Pages.blog.list} - activeName="blogs" - /> -
- -
- - } - title={t("sidebar.learning")} - isActive={isActive("learning")} - link={Pages.learning.list} - activeName="learnings" - /> -
- -
- - } - title={t("sidebar.messages")} - isActive={isActive("messages")} - link={Pages.messages.list} - activeName="contacts_us" - /> -
-
- - {adminPermissions?.data?.permissions?.some((permission: { name: string }) => permission.name === "dmenu") && ( - <> -
handleOpenMenu("dmenu")} - className={clx("mt-10 px-12 text-header text-sm font-normal cursor-pointer", hasSubMenu && "px-2 text-center", !hasSubMenu && "flex gap-2 items-center")} - > - {t("sidebar.dmenu")} - -
- -
-
-
-
- - } - title={t("sidebar.icons")} - isActive={isActive("dmenu/icons/list")} - link={Pages.dmenu.icons.list} - activeName="dmenu" - /> -
- -
- - } - title={t("sidebar.groups_icon")} - isActive={isActive("dmenu/icons/group/list")} - link={Pages.dmenu.icons.groupList} - activeName="dmenu" - /> -
- -
- - } - title={t("sidebar.reports")} - isActive={isActive("dmenu/reports")} - link={Pages.dmenu.warnings.list} - activeName="dmenu" - /> -
- -
- - } - title={t("sidebar.restaurants")} - isActive={isActive("restaurants")} - link={Pages.dmenu.restaurants.list} - activeName="dmenu" - /> -
- -
- - } - title={t("sidebar.sms_count")} - isActive={isActive("sms-count")} - link={Pages.dmenu.restaurants.smsCountList} - activeName="dmenu" - /> -
-
- - )} - - {adminPermissions?.data?.permissions?.some((permission: { name: string }) => permission.name === "dkala") && ( - <> -
handleOpenMenu("dkala")} - className={clx("mt-10 px-12 text-header text-sm font-normal cursor-pointer", hasSubMenu && "px-2 text-center", !hasSubMenu && "flex gap-2 items-center")} - > - {t("sidebar.dkala")} - -
- -
-
-
-
- - } - title={t("sidebar.icons")} - isActive={isActive("dkala/icons/list")} - link={Pages.dkala.icons.list} - activeName="dkala" - /> -
- -
- - } - title={t("sidebar.groups_icon")} - isActive={isActive("dkala/icons/group")} - link={Pages.dkala.icons.groupList} - activeName="dkala" - /> -
- -
- - } - title={t("sidebar.reports")} - isActive={isActive("dkala/reports")} - link={Pages.dkala.warnings.list} - activeName="dkala" - /> -
- -
- - } - title={t("sidebar.shops")} - isActive={isActive("dkala/shops")} - link={Pages.dkala.shops.list} - activeName="dkala" - /> -
- -
- - } - title={t("sidebar.sms_count")} - isActive={isActive("dkala/sms-count")} - link={Pages.dkala.shops.smsCountList} - activeName="dkala" - /> -
-
- - )} - {adminPermissions?.data?.permissions?.some((permission: { name: string }) => permission.name === "dpage") && ( - <> -
handleOpenMenu("dpage")} - className={clx("mt-10 px-12 text-header text-sm font-normal cursor-pointer", hasSubMenu && "px-2 text-center", !hasSubMenu && "flex gap-2 items-center")} - > - {t("sidebar.dpage")} - -
- -
-
-
-
- - } - title={t("sidebar.sticker")} - isActive={isActive("dpage/stickers/list")} - link={Pages.dpage.stickers.list} - activeName="dpage" - /> -
-
- - )} - - {adminPermissions?.data?.permissions?.some((permission: { name: string }) => permission.name === "dmail") && ( - <> -
handleOpenMenu("dmail")} - className={clx("mt-10 px-12 text-header text-sm font-normal cursor-pointer", hasSubMenu && "px-2 text-center", !hasSubMenu && "flex gap-2 items-center")} - > - {t("sidebar.dmail")} - -
- -
-
-
-
- - } - title={t("sidebar.domain")} - isActive={isActive("dmail/domain/list")} - link={Pages.dmail.list} - activeName="dmail" - /> -
-
- - )} -
-
} title={t("sidebar.setting")} - isActive={isActive("setting")} + isActive={location.pathname.includes("setting")} link={Pages.setting} activeName="settings" /> @@ -906,13 +256,13 @@ const SideBar: FC = () => { } title={t("sidebar.logout")} - isActive={isActive("logout")} + isActive={false} link={`#`} isLogout activeName="" @@ -923,25 +273,25 @@ const SideBar: FC = () => {
{hasSubMenu && (openSidebar || window.innerWidth > 1139) && ( -
- {subMenuName === "services" ? ( - - ) : subMenuName === "receipts" ? ( - - ) : subMenuName === "customers" ? ( - - ) : subMenuName === "tickets" ? ( - - ) : subMenuName === "users" ? ( - - ) : subMenuName === "learning" ? ( - - ) : subMenuName === "blog" ? ( - - ) : subMenuName === "support" ? ( - - ) : subMenuName === "accessLogs" ? ( - +
+ {subMenuName === "menu" ? ( + + ) : subMenuName === "financial" ? ( + + ) : subMenuName === "other" ? ( + + ) : subMenuName === "content" ? ( + + ) : subMenuName === "reseller" ? ( + + ) : subMenuName === "dmenu" ? ( + + ) : subMenuName === "dkala" ? ( + + ) : subMenuName === "dpage" ? ( + + ) : subMenuName === "dmail" ? ( + ) : null}
)} diff --git a/src/shared/components/AccessLogsSubMenu.tsx b/src/shared/components/AccessLogsSubMenu.tsx deleted file mode 100644 index cb1085a..0000000 --- a/src/shared/components/AccessLogsSubMenu.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { FC } from 'react' -import { useTranslation } from 'react-i18next' -import { useLocation } from 'react-router-dom' -import { Pages } from '../../config/Pages' -import SideBarItem from '../SideBarItem' -import { DocumentText, Activity, Warning2, Shield } from 'iconsax-react' - -const AccessLogsSubMenu: FC = () => { - const { t } = useTranslation('global') - const location = useLocation() - const iconSizeSideBar = 20 - - const isActive = (name: string) => { - return location.pathname.includes(name) - } - - return ( -
-
- {t('sidebar.accessLogs')} -
- -
-
- } - title="لیست لاگ‌ها" - isActive={isActive('access-logs/list')} - link={Pages.accessLogs.list} - activeName='access_logs_list' - /> - - } - title="آمار لاگ‌ها" - isActive={isActive('access-logs/stats')} - link={Pages.accessLogs.stats} - activeName='access_logs_stats' - /> - - } - title="لاگ‌های خطا" - isActive={isActive('access-logs/errors')} - link={Pages.accessLogs.errors} - activeName='access_logs_errors' - /> - - } - title="لاگ‌های مجوز" - isActive={isActive('access-logs/permissions')} - link={Pages.accessLogs.permissions} - activeName='access_logs_permissions' - /> -
-
-
- ) -} - -export default AccessLogsSubMenu diff --git a/src/shared/components/BlogSubMenu.tsx b/src/shared/components/BlogSubMenu.tsx deleted file mode 100644 index 4f108f7..0000000 --- a/src/shared/components/BlogSubMenu.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { DocumentText } from 'iconsax-react' -import { FC } from 'react' -import { useTranslation } from 'react-i18next' -import SubMenuItem from './SubMenuItem' -import { Pages } from '../../config/Pages' - -const BlogSubMenu: FC = () => { - - const { t } = useTranslation('global') - - const isActive = (name: string) => { - return location.pathname.includes(name) - } - - return ( -
-
- -
- {t('sidebar.blog')} -
-
- -
- - - -
- -
- ) -} - -export default BlogSubMenu \ No newline at end of file diff --git a/src/shared/components/ContentSubMenu.tsx b/src/shared/components/ContentSubMenu.tsx new file mode 100644 index 0000000..c6d218d --- /dev/null +++ b/src/shared/components/ContentSubMenu.tsx @@ -0,0 +1,95 @@ +import { DocumentLike } from "iconsax-react"; +import { FC } from "react"; +import { useTranslation } from "react-i18next"; +import { useLocation } from "react-router-dom"; +import { Pages } from "../../config/Pages"; +import SubMenuAccordion from "./SubMenuAccordion"; +import SubMenuItem from "./SubMenuItem"; + +const ContentSubMenu: FC = () => { + const location = useLocation(); + const { t } = useTranslation("global"); + + const isActive = (name: string) => location.pathname.includes(name); + + return ( +
+
+ +
{t("sidebar.mnage_content")}
+
+ +
+ + + + + + + + + + + + + + + + +
+
+ ); +}; + +export default ContentSubMenu; diff --git a/src/shared/components/CustomerSubMenu.tsx b/src/shared/components/CustomerSubMenu.tsx deleted file mode 100644 index bbb2a54..0000000 --- a/src/shared/components/CustomerSubMenu.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { People } from 'iconsax-react' -import { FC } from 'react' -import { useTranslation } from 'react-i18next' -import SubMenuItem from './SubMenuItem' -import { Pages } from '../../config/Pages' - -const CustomerSubMenu: FC = () => { - - const { t } = useTranslation('global') - - const isActive = (name: string) => { - return location.pathname.includes(name) - } - - return ( -
-
- -
- {t('sidebar.customers')} -
-
- -
- - - -
- -
- ) -} - -export default CustomerSubMenu \ No newline at end of file diff --git a/src/shared/components/DkalaSubMenu.tsx b/src/shared/components/DkalaSubMenu.tsx new file mode 100644 index 0000000..2722120 --- /dev/null +++ b/src/shared/components/DkalaSubMenu.tsx @@ -0,0 +1,61 @@ +import { Building } from "iconsax-react"; +import { FC } from "react"; +import { useTranslation } from "react-i18next"; +import { useLocation } from "react-router-dom"; +import { Pages } from "../../config/Pages"; +import SubMenuItem from "./SubMenuItem"; + +const DkalaSubMenu: FC = () => { + const location = useLocation(); + const { t } = useTranslation("global"); + + const isActive = (name: string) => location.pathname.includes(name); + + return ( +
+
+ +
{t("sidebar.dkala")}
+
+ +
+ + + + + +
+
+ ); +}; + +export default DkalaSubMenu; diff --git a/src/shared/components/DmailSubMenu.tsx b/src/shared/components/DmailSubMenu.tsx new file mode 100644 index 0000000..a231ea0 --- /dev/null +++ b/src/shared/components/DmailSubMenu.tsx @@ -0,0 +1,37 @@ +import { Global } from "iconsax-react"; +import { FC } from "react"; +import { useTranslation } from "react-i18next"; +import { useLocation } from "react-router-dom"; +import { Pages } from "../../config/Pages"; +import SubMenuItem from "./SubMenuItem"; + +const DmailSubMenu: FC = () => { + const location = useLocation(); + const { t } = useTranslation("global"); + + const isActive = (name: string) => location.pathname.includes(name); + + return ( +
+
+ +
{t("sidebar.dmail")}
+
+ +
+ +
+
+ ); +}; + +export default DmailSubMenu; diff --git a/src/shared/components/DmenuSubMenu.tsx b/src/shared/components/DmenuSubMenu.tsx new file mode 100644 index 0000000..743f6df --- /dev/null +++ b/src/shared/components/DmenuSubMenu.tsx @@ -0,0 +1,61 @@ +import { Building } from "iconsax-react"; +import { FC } from "react"; +import { useTranslation } from "react-i18next"; +import { useLocation } from "react-router-dom"; +import { Pages } from "../../config/Pages"; +import SubMenuItem from "./SubMenuItem"; + +const DmenuSubMenu: FC = () => { + const location = useLocation(); + const { t } = useTranslation("global"); + + const isActive = (name: string) => location.pathname.includes(name); + + return ( +
+
+ +
{t("sidebar.dmenu")}
+
+ +
+ + + + + +
+
+ ); +}; + +export default DmenuSubMenu; diff --git a/src/shared/components/DpageSubMenu.tsx b/src/shared/components/DpageSubMenu.tsx new file mode 100644 index 0000000..26d20c5 --- /dev/null +++ b/src/shared/components/DpageSubMenu.tsx @@ -0,0 +1,37 @@ +import { Gallery } from "iconsax-react"; +import { FC } from "react"; +import { useTranslation } from "react-i18next"; +import { useLocation } from "react-router-dom"; +import { Pages } from "../../config/Pages"; +import SubMenuItem from "./SubMenuItem"; + +const DpageSubMenu: FC = () => { + const location = useLocation(); + const { t } = useTranslation("global"); + + const isActive = (name: string) => location.pathname.includes(name); + + return ( +
+
+ +
{t("sidebar.dpage")}
+
+ +
+ +
+
+ ); +}; + +export default DpageSubMenu; diff --git a/src/shared/components/FinancialSubMenu.tsx b/src/shared/components/FinancialSubMenu.tsx new file mode 100644 index 0000000..8714ae7 --- /dev/null +++ b/src/shared/components/FinancialSubMenu.tsx @@ -0,0 +1,74 @@ +import { Money3 } from "iconsax-react"; +import { FC } from "react"; +import { useTranslation } from "react-i18next"; +import { useLocation } from "react-router-dom"; +import { Pages } from "../../config/Pages"; +import SubMenuAccordion from "./SubMenuAccordion"; +import SubMenuItem from "./SubMenuItem"; + +const FinancialSubMenu: FC = () => { + const location = useLocation(); + const { t } = useTranslation("global"); + + const isActive = (name: string) => location.pathname.includes(name); + + return ( +
+
+ +
{t("sidebar.financial")}
+
+ +
+ + + + + + + + + + +
+
+ ); +}; + +export default FinancialSubMenu; diff --git a/src/shared/components/LearningSubMenu.tsx b/src/shared/components/LearningSubMenu.tsx deleted file mode 100644 index 663e74a..0000000 --- a/src/shared/components/LearningSubMenu.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { Teacher } from 'iconsax-react' -import { FC } from 'react' -import { useTranslation } from 'react-i18next' -import SubMenuItem from './SubMenuItem' -import { useLocation } from 'react-router-dom' -import { Pages } from '../../config/Pages' - -const LearningSubMenu: FC = () => { - - const { t } = useTranslation('global') - const location = useLocation() - - const isActive = (name: string) => { - return location.pathname.includes(name) - } - - return ( -
-
- -
- {t('sidebar.learning')} -
-
- -
- - - -
- -
- ) -} - -export default LearningSubMenu \ No newline at end of file diff --git a/src/shared/components/MenuSubMenu.tsx b/src/shared/components/MenuSubMenu.tsx new file mode 100644 index 0000000..cc8c5f6 --- /dev/null +++ b/src/shared/components/MenuSubMenu.tsx @@ -0,0 +1,176 @@ +import { Element3 } from "iconsax-react"; +import { FC } from "react"; +import { useTranslation } from "react-i18next"; +import { useLocation } from "react-router-dom"; +import { Pages } from "../../config/Pages"; +import { useGetProfile } from "../../pages/profile/hooks/useProfileData"; +import SubMenuAccordion from "./SubMenuAccordion"; +import SubMenuItem from "./SubMenuItem"; + +const MenuSubMenu: FC = () => { + const location = useLocation(); + const { t } = useTranslation("global"); + const { data: profile } = useGetProfile(); + + const isActive = (name: string) => location.pathname.includes(name); + + return ( +
+
+ +
{t("sidebar.menu")}
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {profile?.data?.user?.roles?.some((role: { name: string }) => role.name === "super_admin") && ( + + )} +
+
+ ); +}; + +export default MenuSubMenu; diff --git a/src/shared/components/OtherSubMenu.tsx b/src/shared/components/OtherSubMenu.tsx new file mode 100644 index 0000000..1cb69cf --- /dev/null +++ b/src/shared/components/OtherSubMenu.tsx @@ -0,0 +1,108 @@ +import { Category } from "iconsax-react"; +import { FC } from "react"; +import { useTranslation } from "react-i18next"; +import { useLocation } from "react-router-dom"; +import { Pages } from "../../config/Pages"; +import SubMenuAccordion from "./SubMenuAccordion"; +import SubMenuItem from "./SubMenuItem"; + +const OtherSubMenu: FC = () => { + const location = useLocation(); + const { t } = useTranslation("global"); + + const isActive = (name: string) => location.pathname.includes(name); + + const isTaskManagerActive = + location.pathname.startsWith(Pages.taskmanager.workspace) || + location.pathname === Pages.taskmanager.workspaceList || + location.pathname.startsWith(Pages.taskmanager.updateWorkspace) || + location.pathname === Pages.taskmanager.createWorkspace || + location.pathname === Pages.taskmanager.createProject || + location.pathname.startsWith(Pages.taskmanager.updateProject) || + location.pathname.startsWith(Pages.taskmanager.projectList); + + return ( +
+
+ +
{t("sidebar.other")}
+
+ +
+ + + + + + + + + + + + + + + + + +
+
+ ); +}; + +export default OtherSubMenu; diff --git a/src/shared/components/ReceiptSubMenu.tsx b/src/shared/components/ReceiptSubMenu.tsx deleted file mode 100644 index d86c205..0000000 --- a/src/shared/components/ReceiptSubMenu.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { Receipt21 } from 'iconsax-react' -import { FC } from 'react' -import { useTranslation } from 'react-i18next' -import SubMenuItem from './SubMenuItem' -import { useLocation } from 'react-router-dom' -import { Pages } from '../../config/Pages' - -const ReceiptSubMenu: FC = () => { - - const location = useLocation() - const { t } = useTranslation('global') - - const isActive = (name: string) => { - return location.pathname.includes(name) - } - - return ( -
-
- -
- {t('receip.receips')} -
-
- -
- - -
-
- ) -} - -export default ReceiptSubMenu \ No newline at end of file diff --git a/src/shared/components/ResellerSubMenu.tsx b/src/shared/components/ResellerSubMenu.tsx new file mode 100644 index 0000000..cc75675 --- /dev/null +++ b/src/shared/components/ResellerSubMenu.tsx @@ -0,0 +1,43 @@ +import { UserTick } from "iconsax-react"; +import { FC } from "react"; +import { useTranslation } from "react-i18next"; +import { useLocation } from "react-router-dom"; +import { Pages } from "../../config/Pages"; +import SubMenuItem from "./SubMenuItem"; + +const ResellerSubMenu: FC = () => { + const location = useLocation(); + const { t } = useTranslation("global"); + + const isActive = (name: string) => location.pathname.includes(name); + + return ( +
+
+ +
{t("sidebar.reseller")}
+
+ +
+ + +
+
+ ); +}; + +export default ResellerSubMenu; diff --git a/src/shared/components/ServicesSubMenu.tsx b/src/shared/components/ServicesSubMenu.tsx deleted file mode 100644 index 299717a..0000000 --- a/src/shared/components/ServicesSubMenu.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import { Element3 } from 'iconsax-react' -import { FC } from 'react' -import { useTranslation } from 'react-i18next' -import SubMenuItem from './SubMenuItem' -import { useLocation } from 'react-router-dom' -import { Pages } from '../../config/Pages' - -const ServicesSubMenu: FC = () => { - - const location = useLocation() - const { t } = useTranslation('global') - - - const isActive = (name: string) => { - return location.pathname.includes(name) - } - - return ( -
-
- -
- {t('sidebar.services')} -
-
- -
- - - - -
-
- ) -} - -export default ServicesSubMenu \ No newline at end of file diff --git a/src/shared/components/SubMenuAccordion.tsx b/src/shared/components/SubMenuAccordion.tsx new file mode 100644 index 0000000..8509c81 --- /dev/null +++ b/src/shared/components/SubMenuAccordion.tsx @@ -0,0 +1,53 @@ +import { ArrowDown2 } from "iconsax-react"; +import { FC, ReactNode, useEffect, useState } from "react"; +import { clx } from "../../helpers/utils"; +import { useGetAdminPermissions } from "../../pages/users/hooks/useUserData"; + +type Props = { + title: string; + isActive: boolean; + activeName?: string; + children: ReactNode; +}; + +const SubMenuAccordion: FC = ({ title, isActive, activeName = "", children }) => { + const { data: adminPermissions } = useGetAdminPermissions(); + const [open, setOpen] = useState(isActive); + + useEffect(() => { + if (isActive) { + setOpen(true); + } + }, [isActive]); + + if ( + activeName !== "" && + !adminPermissions?.data?.permissions?.some((permission: { name: string }) => permission.name === activeName) + ) { + return null; + } + + return ( +
+ + {open &&
{children}
} +
+ ); +}; + +export default SubMenuAccordion; diff --git a/src/shared/components/SubMenuItem.tsx b/src/shared/components/SubMenuItem.tsx index 59451f4..0f505a1 100644 --- a/src/shared/components/SubMenuItem.tsx +++ b/src/shared/components/SubMenuItem.tsx @@ -1,33 +1,38 @@ -import { FC } from 'react' -import { Link } from 'react-router-dom' -import { clx } from '../../helpers/utils' +import { FC } from "react"; +import { Link } from "react-router-dom"; +import { clx } from "../../helpers/utils"; +import { useGetAdminPermissions } from "../../pages/users/hooks/useUserData"; type Props = { - title: string, - isActive: boolean, - link: string, - isLogout?: boolean, -} + title: string; + isActive: boolean; + link: string; + isLogout?: boolean; + activeName?: string; +}; const SubMenuItem: FC = (props: Props) => { - return ( - -
-
-
- {props.title} -
-
+ const { data: adminPermissions } = useGetAdminPermissions(); - - ) -} + if ( + props.activeName !== undefined && + props.activeName !== "" && + !adminPermissions?.data?.permissions?.some((permission: { name: string }) => permission.name === props.activeName) + ) { + return null; + } -export default SubMenuItem \ No newline at end of file + return ( + +
+
+
{props.title}
+
+ + ); +}; + +export default SubMenuItem; diff --git a/src/shared/components/SupportSubMenu.tsx b/src/shared/components/SupportSubMenu.tsx deleted file mode 100644 index 9e0c9c8..0000000 --- a/src/shared/components/SupportSubMenu.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { Headphone } from 'iconsax-react' -import { FC } from 'react' -import { useTranslation } from 'react-i18next' -import { useLocation } from 'react-router-dom' -import { Pages } from '../../config/Pages' -import SubMenuItem from './SubMenuItem' - -const SupportSubMenu: FC = () => { - - const location = useLocation() - const { t } = useTranslation('global') - - - const isActive = (name: string) => { - return location.pathname.includes(name) - } - - - return
-
- -
- {t('sidebar.support')} -
-
- -
- - -
- -
-} - -export default SupportSubMenu \ No newline at end of file diff --git a/src/shared/components/TicketSubMenu.tsx b/src/shared/components/TicketSubMenu.tsx deleted file mode 100644 index 6d9436d..0000000 --- a/src/shared/components/TicketSubMenu.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { Messages3 } from 'iconsax-react' -import { FC } from 'react' -import { useTranslation } from 'react-i18next' -import SubMenuItem from './SubMenuItem' -import { useLocation } from 'react-router-dom' -import { Pages } from '../../config/Pages' - -const TicketSubMenu: FC = () => { - - const location = useLocation() - const { t } = useTranslation('global') - - - const isActive = (name: string) => { - return location.pathname.includes(name) - } - - return ( -
-
- -
- {t('sidebar.ticket')} -
-
- -
- - - -
-
- ) -} - -export default TicketSubMenu \ No newline at end of file diff --git a/src/shared/components/TransactionsSubMenu.tsx b/src/shared/components/TransactionsSubMenu.tsx deleted file mode 100644 index 20e3f23..0000000 --- a/src/shared/components/TransactionsSubMenu.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { Card } from 'iconsax-react' -import { FC } from 'react' -import { useTranslation } from 'react-i18next' -import SubMenuItem from './SubMenuItem' - -const TransactionsSubMenu: FC = () => { - - const { t } = useTranslation('global') - - const isActive = (name: string) => { - return location.pathname.includes(name) - } - - return ( -
-
- -
- {t('sidebar.transactions')} -
-
- -
- -
-
- ) -} - -export default TransactionsSubMenu \ No newline at end of file diff --git a/src/shared/components/UsersSubMenu.tsx b/src/shared/components/UsersSubMenu.tsx deleted file mode 100644 index 54d1367..0000000 --- a/src/shared/components/UsersSubMenu.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { Profile } from 'iconsax-react' -import { FC } from 'react' -import { useTranslation } from 'react-i18next' -import SubMenuItem from './SubMenuItem' -import { Pages } from '../../config/Pages' - -const UsersSubMenu: FC = () => { - - const { t } = useTranslation('global') - - const isActive = (name: string) => { - return location.pathname.includes(name) - } - - return ( -
-
- -
- {t('sidebar.users')} -
-
- -
- - - - - - -
-
- ) -} - -export default UsersSubMenu \ No newline at end of file