111 lines
2.9 KiB
TypeScript
111 lines
2.9 KiB
TypeScript
import { useState } from "react";
|
|
import * as TbIcons from "react-icons/tb";
|
|
// import classNames from "./styles/navbarMenuItem.module.css";
|
|
// import dashboardConfig from "../dashboard.config";
|
|
// import { usePathname } from "next/navigation";
|
|
// import areURLsSame from "@/utils/areUrlSame";
|
|
|
|
import { SidebarMenu } from "backend/types";
|
|
import ChildMenu from "./NavbarChildMenu";
|
|
import { Link } from "@tanstack/react-router";
|
|
import { Button } from "@/shadcn/components/ui/button";
|
|
import { ChevronRightIcon} from "lucide-react";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
interface Props {
|
|
menu: SidebarMenu;
|
|
isActive: boolean;
|
|
onClick: (link: string) => void;
|
|
}
|
|
|
|
//TODO: Make bold and collapsed when the item is active
|
|
|
|
/**
|
|
* `MenuItem` is a React functional component that displays an individual menu item.
|
|
* It can optionally include a collapsible sub-menu for items with children.
|
|
*
|
|
* @param props - The component props.
|
|
* @param props.menu - The menu item data to display.
|
|
* @returns A React element representing an individual menu item.
|
|
*/
|
|
export default function MenuItem({ menu, isActive, onClick }: Props) {
|
|
const hasChildren = Array.isArray(menu.children);
|
|
|
|
// const pathname = usePathname();
|
|
|
|
const [opened, setOpened] = useState(
|
|
// menu.children?.some((child) =>
|
|
// areURLsSame(`${dashboardConfig.baseRoute}${child.link}`, pathname)
|
|
// ) ?? false
|
|
false
|
|
);
|
|
|
|
const toggleOpenMenu = () => {
|
|
setOpened((prev) => !prev);
|
|
};
|
|
|
|
const handleClick = () => {
|
|
onClick(menu.link ?? "");
|
|
if (!hasChildren) {
|
|
toggleOpenMenu();
|
|
}
|
|
};
|
|
|
|
// Mapping children menu items if available
|
|
const subItems = (hasChildren ? menu.children! : []).map((child, index) => (
|
|
<ChildMenu key={index} item={child} active={false} />
|
|
));
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
const Icons = TbIcons as any;
|
|
|
|
const Icon =
|
|
typeof menu.icon.tb === "string" ? Icons[menu.icon.tb] : menu.icon.tb;
|
|
|
|
// const isActive = areURLsSame(
|
|
// `${dashboardConfig.baseRoute}${menu.link}`,
|
|
// pathname
|
|
// );
|
|
|
|
return (
|
|
<>
|
|
{/* Main Menu Item */}
|
|
<Button
|
|
variant="ghost"
|
|
className={cn(
|
|
"w-full p-2 rounded-md justify-between focus:outline-none",
|
|
isActive ? "bg-[--primary-color] text-white" : "text-black"
|
|
)}
|
|
onClick={handleClick}
|
|
asChild
|
|
>
|
|
<Link to={menu.link ?? "#"}>
|
|
<div className="flex items-center">
|
|
{/* Icon */}
|
|
<span className="mr-3">
|
|
<Icon className="w-4 h-4" />
|
|
</span>
|
|
{/* Label */}
|
|
<span className="text-xs font-normal whitespace-normal">{menu.label}</span>
|
|
</div>
|
|
{/* Chevron Icon */}
|
|
{hasChildren && (
|
|
<ChevronRightIcon
|
|
className={`w-4 h-4 transition-transform ${
|
|
opened ? "rotate-90" : "rotate-0"
|
|
}`}
|
|
/>
|
|
)}
|
|
</Link>
|
|
</Button>
|
|
|
|
{/* Collapsible Sub-Menu */}
|
|
{hasChildren && (
|
|
<div className={cn("transition-all", opened ? "block" : "hidden")}>
|
|
{subItems}
|
|
</div>
|
|
)}
|
|
</>
|
|
);
|
|
}
|