diff --git a/src/admin/ui/SidebarNav.tsx b/src/admin/ui/SidebarNav.tsx new file mode 100644 index 0000000..2120ffa --- /dev/null +++ b/src/admin/ui/SidebarNav.tsx @@ -0,0 +1,172 @@ +import { NavLink, useLocation } from "react-router-dom"; +import Box from "@mui/material/Box"; +import List from "@mui/material/List"; +import ListItemButton from "@mui/material/ListItemButton"; +import ListItemIcon from "@mui/material/ListItemIcon"; +import ListItemText from "@mui/material/ListItemText"; +import Typography from "@mui/material/Typography"; +import Avatar from "@mui/material/Avatar"; +import Button from "@mui/material/Button"; +import { useAuth } from "../context/AuthContext"; +import { useTheme as useAppTheme } from "../../context/ThemeContext"; +import { menuSections, isItemActive, hasItemPermission } from "./navData"; + +interface SidebarNavProps { + /** Closes the mobile drawer on item click (optional — desktop omits it). */ + onNavigate?: () => void; + /** Logout handler, owned by the parent. */ + onLogout: () => void; +} + +export default function SidebarNav({ onNavigate, onLogout }: SidebarNavProps) { + const { user, hasPermission } = useAuth(); + const { theme } = useAppTheme(); + const location = useLocation(); + + const visibleSections = menuSections + .map((section) => ({ + ...section, + items: section.items.filter((item) => + hasItemPermission(item, hasPermission), + ), + })) + .filter((section) => section.items.length > 0); + + return ( + + {/* Logo header */} + + { + e.currentTarget.src = + theme === "dark" + ? "/images/logo-dark.png" + : "/images/logo-light.png"; + }} + sx={{ + maxHeight: 40, + maxWidth: "100%", + objectFit: "contain", + display: "block", + }} + /> + + + {/* Nav */} + + {visibleSections.map((section) => ( + + + {section.label} + + + {section.items.map((item) => ( + + + {item.icon} + + + + ))} + + + ))} + + + {/* Footer */} + + + + {user?.fullName?.charAt(0) || user?.username?.charAt(0) || "U"} + + + + {user?.fullName || user?.username} + + + {user?.roleDisplay} + + + + + + + ); +}