138 lines
3.7 KiB
TypeScript
138 lines
3.7 KiB
TypeScript
import React from "react";
|
|
import {
|
|
Button,
|
|
Menu,
|
|
MenuItem,
|
|
ListItemText,
|
|
ListItemIcon,
|
|
Divider,
|
|
} from "@mui/material";
|
|
import { useSelector } from "react-redux";
|
|
import { useRouter } from "next/navigation";
|
|
import KeyboardArrowRightIcon from "@mui/icons-material/KeyboardArrowRight";
|
|
import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
|
|
import { selectNavigationSidebar } from "@/app/redux/metadata/selectors";
|
|
import { SidebarLink } from "@/app/redux/metadata/metadataSlice";
|
|
import { resolveIcon } from "@/app/utils/iconMap";
|
|
import "./DropDown.scss";
|
|
|
|
interface Props {
|
|
onChange?: (path: string) => void;
|
|
}
|
|
|
|
export default function SidebarDropdown({ onChange }: Props) {
|
|
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
|
const [openMenus, setOpenMenus] = React.useState<Record<string, boolean>>({});
|
|
const sidebar = useSelector(selectNavigationSidebar);
|
|
const router = useRouter();
|
|
const open = Boolean(anchorEl);
|
|
|
|
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
|
setAnchorEl(event.currentTarget);
|
|
};
|
|
|
|
const handleClose = () => {
|
|
setAnchorEl(null);
|
|
setOpenMenus({});
|
|
};
|
|
|
|
const toggleMenu = (title: string) => {
|
|
setOpenMenus(prev => ({ ...prev, [title]: !prev[title] }));
|
|
};
|
|
|
|
const handleNavigation = (path: string) => {
|
|
router.push(path);
|
|
onChange?.(path);
|
|
handleClose();
|
|
};
|
|
|
|
const renderMenuItem = (
|
|
link: SidebarLink,
|
|
level: number = 0
|
|
): React.ReactNode => {
|
|
const Icon = link.icon ? resolveIcon(link.icon as string) : undefined;
|
|
const hasChildren = link.children && link.children.length > 0;
|
|
const isOpen = openMenus[link.title];
|
|
const indent = level * 24;
|
|
|
|
if (hasChildren) {
|
|
return (
|
|
<React.Fragment key={link.title || link.path}>
|
|
<MenuItem
|
|
onClick={() => toggleMenu(link.title)}
|
|
sx={{
|
|
pl: `${8 + indent}px`,
|
|
}}
|
|
>
|
|
{Icon && (
|
|
<ListItemIcon sx={{ minWidth: 36 }}>
|
|
<Icon fontSize="small" />
|
|
</ListItemIcon>
|
|
)}
|
|
<ListItemText primary={link.title} />
|
|
{isOpen ? (
|
|
<KeyboardArrowDownIcon fontSize="small" />
|
|
) : (
|
|
<KeyboardArrowRightIcon fontSize="small" />
|
|
)}
|
|
</MenuItem>
|
|
{isOpen &&
|
|
link.children?.map(child => renderMenuItem(child, level + 1))}
|
|
</React.Fragment>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<MenuItem
|
|
key={link.path}
|
|
onClick={() => handleNavigation(link.path)}
|
|
sx={{
|
|
pl: `${8 + indent}px`,
|
|
}}
|
|
>
|
|
{Icon && (
|
|
<ListItemIcon sx={{ minWidth: 36 }}>
|
|
<Icon fontSize="small" />
|
|
</ListItemIcon>
|
|
)}
|
|
<ListItemText primary={link.title} />
|
|
</MenuItem>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<div>
|
|
<Button
|
|
variant="outlined"
|
|
onClick={handleClick}
|
|
sx={{ minWidth: 200, justifyContent: "space-between" }}
|
|
>
|
|
Navigate To
|
|
{open ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />}
|
|
</Button>
|
|
<Menu
|
|
anchorEl={anchorEl}
|
|
open={open}
|
|
onClose={handleClose}
|
|
MenuListProps={{
|
|
"aria-labelledby": "sidebar-dropdown-button",
|
|
}}
|
|
PaperProps={{
|
|
style: {
|
|
maxHeight: 400,
|
|
width: "250px",
|
|
},
|
|
}}
|
|
>
|
|
<MenuItem disabled>
|
|
<ListItemText primary="Select a page" />
|
|
</MenuItem>
|
|
<Divider />
|
|
<div className="sidebar-dropdown__container">
|
|
{sidebar?.map(link => renderMenuItem(link))}
|
|
</div>
|
|
</Menu>
|
|
</div>
|
|
);
|
|
}
|