change directory
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
import { ExpandLess, ExpandMore } from "@mui/icons-material";
|
||||
import { Collapse, List, ListItem, ListItemButton, ListItemIcon, ListItemText } from "@mui/material";
|
||||
import Link from "next/link";
|
||||
import SidebarSubitems from "./SidebarSubitems";
|
||||
|
||||
const SidebarListItems = ({ menuItem, dispatch }) => {
|
||||
return (
|
||||
<>
|
||||
<ListItem disablePadding divider>
|
||||
<ListItemButton
|
||||
sx={{ py: 1, px: 0.5 }}
|
||||
disableGutters
|
||||
selected={menuItem.selected}
|
||||
component={menuItem.type === "page" ? Link : null}
|
||||
href={menuItem.type === "page" ? menuItem.route : null}
|
||||
onClick={() => {
|
||||
dispatch({ type: "COLLAPSE_MENU", id: menuItem.id });
|
||||
}}
|
||||
>
|
||||
<ListItemIcon
|
||||
sx={{
|
||||
minWidth: 0,
|
||||
justifyContent: "center",
|
||||
color: "primary.main",
|
||||
width: 40,
|
||||
height: 24,
|
||||
}}
|
||||
>
|
||||
{menuItem.icon}
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={menuItem.label} />
|
||||
{menuItem.hasSubitems ? menuItem.showSubitems ? <ExpandLess /> : <ExpandMore /> : null}
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
<Collapse in={menuItem.showSubitems} timeout="auto" mountOnEnter={true} unmountOnExit={true}>
|
||||
{menuItem.hasSubitems ? (
|
||||
<List
|
||||
disablePadding
|
||||
dense
|
||||
sx={{
|
||||
background: "#00000008",
|
||||
}}
|
||||
>
|
||||
{menuItem.Subitems.map((subitem, index) => {
|
||||
return <SidebarSubitems key={index} dispatch={dispatch} subitem={subitem} />;
|
||||
})}
|
||||
</List>
|
||||
) : null}
|
||||
</Collapse>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default SidebarListItems;
|
||||
@@ -0,0 +1,130 @@
|
||||
"use client";
|
||||
import { usePermissions } from "@/lib/hooks/usePermissions";
|
||||
import { List } from "@mui/material";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useEffect, useReducer, useState } from "react";
|
||||
import Profile from "@/core/components/Profile";
|
||||
import { filterMenuItems } from "@/core/utils/filterMenuItems";
|
||||
import { pageMenu } from "@/core/utils/pageMenu";
|
||||
import SidebarListItems from "./SidebarListItems";
|
||||
|
||||
function selectPage(item, route) {
|
||||
if (item.type === "page") {
|
||||
return {
|
||||
...item,
|
||||
selected: item.route === route,
|
||||
showSubitems: item.route === route,
|
||||
};
|
||||
} else if (item.Subitems && Array.isArray(item.Subitems)) {
|
||||
const updatedSubitems = item.Subitems.map((subitem) => selectPage(subitem, route));
|
||||
return {
|
||||
...item,
|
||||
Subitems: updatedSubitems,
|
||||
showSubitems: updatedSubitems.some((subitem) => subitem.showSubitems || subitem.route === route),
|
||||
};
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
function reducer(state, action) {
|
||||
switch (action.type) {
|
||||
case "UPDATE_MENU":
|
||||
const _permissions = action.permissions || [];
|
||||
const filteredPageMenu = filterMenuItems(state, ["all", ..._permissions]);
|
||||
return filteredPageMenu;
|
||||
case "COLLAPSE_MENU":
|
||||
return state.map((item) =>
|
||||
action.id == item.id
|
||||
? {
|
||||
...item,
|
||||
showSubitems: !item.showSubitems,
|
||||
}
|
||||
: item,
|
||||
);
|
||||
case "COLLAPSE_SUB_ITEMS":
|
||||
return state.map((item) => {
|
||||
return item.hasSubitems
|
||||
? {
|
||||
...item,
|
||||
Subitems: item.Subitems.map((subitem) =>
|
||||
action.id === subitem.id
|
||||
? {
|
||||
...subitem,
|
||||
showSubitems: !subitem.showSubitems,
|
||||
}
|
||||
: subitem,
|
||||
),
|
||||
}
|
||||
: item;
|
||||
});
|
||||
case "COLLAPSE_SUB_SECOND_ITEMS":
|
||||
return state.map((item) => {
|
||||
return item.hasSubitems
|
||||
? {
|
||||
...item,
|
||||
Subitems: item.Subitems.map((subitem) => {
|
||||
return subitem.hasSubitems
|
||||
? {
|
||||
...subitem,
|
||||
Subitems: subitem.Subitems.map((secondSubitem) =>
|
||||
action.id === secondSubitem.id
|
||||
? {
|
||||
...secondSubitem,
|
||||
showSubitems: !secondSubitem.showSubitems,
|
||||
}
|
||||
: secondSubitem,
|
||||
),
|
||||
}
|
||||
: subitem;
|
||||
}),
|
||||
}
|
||||
: item;
|
||||
});
|
||||
case "SELECTED":
|
||||
return state.map((item) => selectPage(item, action.route));
|
||||
|
||||
default:
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
|
||||
const SidebarMenu = () => {
|
||||
const { data: userPermissions } = usePermissions();
|
||||
const [menuItems, dispatch] = useReducer(reducer, pageMenu);
|
||||
const pathname = usePathname();
|
||||
const [selectedKey, setSelectedKey] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch({ type: "SELECTED", route: pathname });
|
||||
setSelectedKey(pathname);
|
||||
}, [userPermissions, pathname]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!userPermissions) return;
|
||||
dispatch({ type: "UPDATE_MENU", permissions: userPermissions });
|
||||
}, [userPermissions]);
|
||||
|
||||
useEffect(() => {
|
||||
selectedKey &&
|
||||
document.querySelector(`[data-route="${selectedKey}"]`)?.scrollIntoView({
|
||||
behavior: "smooth",
|
||||
block: "center",
|
||||
});
|
||||
}, [selectedKey]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Profile />
|
||||
{
|
||||
userPermissions && (
|
||||
<List sx={{ overflow: "auto", flex: 1 }} disablePadding dense>
|
||||
{menuItems.map((menuItem) => {
|
||||
return <SidebarListItems dispatch={dispatch} key={menuItem.id} menuItem={menuItem} />;
|
||||
})}
|
||||
</List>
|
||||
)
|
||||
}
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default SidebarMenu;
|
||||
@@ -0,0 +1,51 @@
|
||||
import { ExpandLess, ExpandMore } from "@mui/icons-material";
|
||||
import { Collapse, List, ListItem, ListItemButton, ListItemIcon, ListItemText } from "@mui/material";
|
||||
import Link from "next/link";
|
||||
|
||||
const SidebarSubitems = ({ subitem, dispatch }) => {
|
||||
return (
|
||||
<>
|
||||
<ListItem disablePadding divider>
|
||||
<ListItemButton
|
||||
disableGutters
|
||||
sx={{ py: 1, px: 0.5, pl: 1 }}
|
||||
selected={subitem.selected}
|
||||
component={subitem.type === "page" ? Link : null}
|
||||
href={subitem.type === "page" ? subitem.route : null}
|
||||
onClick={() => {
|
||||
dispatch({ type: "COLLAPSE_SUB_ITEMS", id: subitem.id });
|
||||
}}
|
||||
>
|
||||
<ListItemIcon
|
||||
sx={{
|
||||
minWidth: 0,
|
||||
justifyContent: "center",
|
||||
width: 40,
|
||||
height: 24,
|
||||
}}
|
||||
>
|
||||
{subitem.icon}
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={subitem.label} />
|
||||
{subitem.hasSubitems ? subitem.showSubitems ? <ExpandLess /> : <ExpandMore /> : null}
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
<Collapse in={subitem.showSubitems} timeout="auto" mountOnEnter={true} unmountOnExit={true}>
|
||||
{subitem.hasSubitems ? (
|
||||
<List
|
||||
disablePadding
|
||||
dense
|
||||
sx={{
|
||||
background: "#00000008",
|
||||
}}
|
||||
>
|
||||
{subitem.Subitems.map((subSubitem, index) => {
|
||||
return <SidebarSubitems key={index} dispatch={dispatch} subitem={subSubitem} />;
|
||||
})}
|
||||
</List>
|
||||
) : null}
|
||||
</Collapse>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default SidebarSubitems;
|
||||
@@ -1,5 +1,4 @@
|
||||
"use client";
|
||||
import SidebarMenu from "@/core/components/SidebarMenu";
|
||||
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
|
||||
import MenuIcon from "@mui/icons-material/Menu";
|
||||
import { Box, Drawer, IconButton, Stack, styled, Toolbar, Typography } from "@mui/material";
|
||||
@@ -8,6 +7,7 @@ import { useState } from "react";
|
||||
import HeaderMenu from "./HeaderMenu";
|
||||
import moment from "jalali-moment";
|
||||
import { headerMenu } from "@/core/utils/headerMenu";
|
||||
import SidebarMenu from "./Sidebar/SidebarMenu";
|
||||
|
||||
const drawerWidth = 300;
|
||||
const headersHeight = 136
|
||||
@@ -57,7 +57,7 @@ const DrawerHeader = styled("div")(({ theme }) => ({
|
||||
|
||||
const HeaderWithSidebar = ({ children }) => {
|
||||
const [open, setOpen] = useState(true);
|
||||
const now = moment().locale("fa").format("HH:mm | YYYY/MM/DD");
|
||||
const now = moment().locale("fa").format("YYYY/MM/DD");
|
||||
|
||||
const handleDrawerOpen = () => {
|
||||
setOpen(true);
|
||||
|
||||
Reference in New Issue
Block a user