LFFE-6 sidebar improvement
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import {Divider, List} from "@mui/material";
|
||||
import {useEffect, useReducer} from "react";
|
||||
import {Fragment, useEffect, useReducer, useRef, useState} from "react";
|
||||
import SidebarListItem from "./SidebarListItem";
|
||||
import sidebarMenu from "@/core/data/sidebarMenu";
|
||||
import {useRouter} from "next/router";
|
||||
@@ -10,18 +10,27 @@ function reducer(state, action) {
|
||||
case "COLLAPSE_MENU":
|
||||
return state.map((itemsArr) =>
|
||||
itemsArr.map((item) =>
|
||||
action.key == item.key
|
||||
? {...item, showSubItem: !item.showSubItem}
|
||||
: item
|
||||
action.key === item.key ? { ...item, showSubItem: !item.showSubItem } : item
|
||||
)
|
||||
);
|
||||
case "SELECTED":
|
||||
return state.map((itemsArr) =>
|
||||
itemsArr.map((item) =>
|
||||
action.route == item.route
|
||||
? {...item, selected: true}
|
||||
: {...item, selected: false}
|
||||
)
|
||||
itemsArr.map((item) => {
|
||||
return item.type === "page"
|
||||
? { ...item, selected: action.route === item.route }
|
||||
: item.subItem && Array.isArray(item.subItem)
|
||||
? {
|
||||
...item,
|
||||
subItem: item.subItem.map((subitem) => ({
|
||||
...subitem,
|
||||
selected: subitem.route === action.route,
|
||||
})),
|
||||
showSubItem: item.subItem.some(
|
||||
(subitem) => subitem.selected
|
||||
),
|
||||
}
|
||||
: item;
|
||||
})
|
||||
);
|
||||
default:
|
||||
throw new Error();
|
||||
@@ -32,26 +41,39 @@ export default function SidebarList({handleDrawerToggle}) {
|
||||
const [itemMenu, dispatch] = useReducer(reducer, sidebarMenu);
|
||||
const {user} = useUser();
|
||||
const router = useRouter();
|
||||
const [selectedKey, setSelectedKey] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch({type: "SELECTED", route: router.pathname});
|
||||
setSelectedKey(router.pathname);
|
||||
}, [router.pathname]);
|
||||
|
||||
const filteredItemMenu = itemMenu[0].filter(
|
||||
(item) => user.permissions.includes(item.permission) || item.permission === "all"
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
selectedKey && document.querySelector(`[data-route="${selectedKey}"]`)?.scrollIntoView({
|
||||
behavior: "smooth",
|
||||
block: "center"
|
||||
});
|
||||
}, [selectedKey]);
|
||||
|
||||
return (
|
||||
<List>
|
||||
{filteredItemMenu.map((item, index) => (
|
||||
<SidebarListItem
|
||||
item={item}
|
||||
dispatch={dispatch}
|
||||
key={item.key}
|
||||
handleDrawerToggle={handleDrawerToggle}
|
||||
/>
|
||||
<List sx={{ overflow: "scroll"}}>
|
||||
{itemMenu.map((itemArr, index) => (
|
||||
<Fragment key={index}>
|
||||
{itemArr.map((item) =>
|
||||
<Fragment key={item.key}>
|
||||
{(user?.permissions?.includes(item.permission) || item.permission === "all") &&
|
||||
<SidebarListItem
|
||||
item={item}
|
||||
dispatch={dispatch}
|
||||
handleDrawerToggle={handleDrawerToggle}
|
||||
/>}
|
||||
</Fragment>
|
||||
)}
|
||||
<Divider/>
|
||||
</Fragment>
|
||||
))}
|
||||
{filteredItemMenu.length > 0 && <Divider/>}
|
||||
</List>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,23 +9,27 @@ import useNotification from "@/lib/app/hooks/useNotification";
|
||||
|
||||
const SidebarListItem = ({item, dispatch, handleDrawerToggle}) => {
|
||||
const t = useTranslations();
|
||||
const {notification_count} = useNotification()
|
||||
const { notification_count } = useNotification();
|
||||
const hasSubItems = item.type === "menu" && item.subItem && item.subItem.length > 0;
|
||||
const renderBadge = () => {
|
||||
return !hasSubItems ? (
|
||||
<IconButton>
|
||||
<Badge
|
||||
badgeContent={notification_count && notification_count.length>0 ? notification_count[item.name] : 0}
|
||||
color="error"
|
||||
variant="standard"
|
||||
anchorOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "right",
|
||||
}}
|
||||
/>
|
||||
</IconButton>
|
||||
) : null;
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment key={item.key}>
|
||||
<ListItem disablePadding secondaryAction={
|
||||
<IconButton>
|
||||
<Badge
|
||||
badgeContent={notification_count ? notification_count[item.name] : 0}
|
||||
color="error"
|
||||
variant="standard"
|
||||
anchorOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "right",
|
||||
}}
|
||||
/>
|
||||
</IconButton>
|
||||
}>
|
||||
<>
|
||||
<ListItem data-route={item.route} disablePadding secondaryAction={renderBadge()}>
|
||||
<ListItemButton
|
||||
selected={item.selected}
|
||||
{...(item.type == "page" && {
|
||||
@@ -35,10 +39,9 @@ const SidebarListItem = ({item, dispatch, handleDrawerToggle}) => {
|
||||
},
|
||||
})}
|
||||
onClick={() => {
|
||||
if (item.type == "menu") {
|
||||
dispatch({type: "COLLAPSE_MENU", key: item.key});
|
||||
if (hasSubItems) {
|
||||
dispatch({ type: "COLLAPSE_MENU", key: item.key });
|
||||
}
|
||||
handleDrawerToggle();
|
||||
}}
|
||||
sx={{
|
||||
minHeight: 48,
|
||||
@@ -66,9 +69,7 @@ const SidebarListItem = ({item, dispatch, handleDrawerToggle}) => {
|
||||
}
|
||||
/>
|
||||
|
||||
|
||||
{item.type == "menu" &&
|
||||
(item.showSubItem ? <ExpandLess/> : <ExpandMore/>)}
|
||||
{hasSubItems && (item.showSubItem ? <ExpandLess /> : <ExpandMore />)}
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
{item.subItem && (
|
||||
@@ -77,7 +78,7 @@ const SidebarListItem = ({item, dispatch, handleDrawerToggle}) => {
|
||||
handleDrawerToggle={handleDrawerToggle}
|
||||
/>
|
||||
)}
|
||||
</Fragment>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,18 +1,43 @@
|
||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||
import InboxIcon from "@mui/icons-material/MoveToInbox";
|
||||
import {Collapse, List, ListItemButton, ListItemIcon, ListItemText,} from "@mui/material";
|
||||
import {
|
||||
Badge,
|
||||
Collapse,
|
||||
IconButton,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import {useTranslations} from "next-intl";
|
||||
import {Fragment} from "react";
|
||||
import useNotification from "@/lib/app/hooks/useNotification";
|
||||
|
||||
const SidebarListSubItem = ({item, handleDrawerToggle}) => {
|
||||
const SidebarListSubItem = ({item, handleDrawerToggle }) => {
|
||||
const t = useTranslations();
|
||||
const {notification_count} = useNotification();
|
||||
const renderBadge = (subitem) => (
|
||||
<IconButton>
|
||||
<Badge
|
||||
badgeContent={notification_count && notification_count.length>0 ? notification_count[subitem.name] : 0}
|
||||
color="error"
|
||||
variant="standard"
|
||||
anchorOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "right",
|
||||
}}
|
||||
/>
|
||||
</IconButton>
|
||||
);
|
||||
|
||||
return (
|
||||
<Collapse in={item.showSubItem} timeout="auto" unmountOnExit>
|
||||
<List component="div" disablePadding sx={{bgcolor: "#f6f6f6"}}>
|
||||
{item.subItem.map((subitem, index) => (
|
||||
<Fragment key={subitem.key}>
|
||||
|
||||
<Collapse in={item.showSubItem} timeout="auto" mountOnEnter={true} unmountOnExit={true}>
|
||||
<List component="div" disablePadding sx={{bgcolor: "#f6f6f6", pr: 0}}>
|
||||
{item.subItem.map((subitem) => (
|
||||
<ListItem key={subitem.key} disablePadding secondaryAction={renderBadge(subitem)}>
|
||||
<ListItemButton
|
||||
selected={subitem.selected}
|
||||
component={NextLinkComposed}
|
||||
to={{
|
||||
pathname: subitem.route,
|
||||
@@ -20,12 +45,6 @@ const SidebarListSubItem = ({item, handleDrawerToggle}) => {
|
||||
sx={{
|
||||
minHeight: 48,
|
||||
}}
|
||||
onClick={(event) => {
|
||||
if (item.type == "menu") {
|
||||
dispatch({type: "COLLAPSE_MENU", key: item.key});
|
||||
}
|
||||
handleDrawerToggle();
|
||||
}}
|
||||
>
|
||||
<ListItemIcon
|
||||
sx={{
|
||||
@@ -34,14 +53,21 @@ const SidebarListSubItem = ({item, handleDrawerToggle}) => {
|
||||
pr: 2,
|
||||
}}
|
||||
>
|
||||
<InboxIcon/>
|
||||
{subitem.icon}
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={t(subitem.key)}/>
|
||||
<ListItemText primary={t(subitem.key)} secondary={
|
||||
subitem.secondary !== undefined ? (
|
||||
<Typography variant="caption" color="textSecondary">
|
||||
{t(subitem.secondary)}
|
||||
</Typography>
|
||||
) : null
|
||||
}/>
|
||||
</ListItemButton>
|
||||
</Fragment>
|
||||
</ListItem>
|
||||
))}
|
||||
</List>
|
||||
</Collapse>
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ const Sidebar = (props) => {
|
||||
"& .MuiDrawer-paper": {
|
||||
boxSizing: "border-box",
|
||||
width: props.drawerWidth,
|
||||
overflow: "hidden",
|
||||
},
|
||||
}}
|
||||
>
|
||||
@@ -33,6 +34,7 @@ const Sidebar = (props) => {
|
||||
"& .MuiDrawer-paper": {
|
||||
boxSizing: "border-box",
|
||||
width: props.drawerWidth,
|
||||
overflow: "hidden",
|
||||
},
|
||||
}}
|
||||
open
|
||||
|
||||
Reference in New Issue
Block a user