"use client"; import React, { useEffect, useRef, useState, useCallback } from "react"; import Link from "next/link"; import Image from "next/image"; import { usePathname } from "next/navigation"; import { useSidebar } from "../context/SidebarContext"; import { BoxCubeIcon, CalenderIcon, ChevronDownIcon, FileIcon, GridIcon, HorizontaLDots, ListIcon, PageIcon, PieChartIcon, PlugInIcon, TableIcon, UserCircleIcon, } from "../icons/index"; type NavItem = { name: string; icon: React.ReactNode; path?: string; subItems?: { name: string; path: string; pro?: boolean; new?: boolean; }[]; }; const ALL_NAV_ITEMS: NavItem[] = [ { icon: , name: "Trang Chủ", // subItems: [{ name: "Ecommerce", path: "/", pro: false }], path: "/", }, { icon: , name: "Dự Án", path: "/user/projects", }, { icon: , name: "Thư Viện", path: "/user/library", }, { icon: , name: "Tài Khoản", path: "/user/account", }, ]; const OTHERS_ITEMS: NavItem[] = [ { icon: , name: "Charts", subItems: [ { name: "Line Chart", path: "/line-chart", pro: false }, { name: "Bar Chart", path: "/bar-chart", pro: false }, ], }, { icon: , name: "UI Elements", subItems: [ { name: "Alerts", path: "/alerts", pro: false }, { name: "Avatar", path: "/avatars", pro: false }, { name: "Badge", path: "/badge", pro: false }, { name: "Buttons", path: "/buttons", pro: false }, { name: "Images", path: "/images", pro: false }, { name: "Videos", path: "/videos", pro: false }, ], }, { icon: , name: "Authentication", subItems: [ { name: "Sign In", path: "/signin", pro: false }, { name: "Sign Up", path: "/signup", pro: false }, ], }, ]; const AppSidebar: React.FC = () => { const { isExpanded, isMobileOpen, isHovered, setIsHovered } = useSidebar(); const pathname = usePathname(); const [openSubmenu, setOpenSubmenu] = useState<{ type: "main" | "others"; index: number; } | null>(null); const [subMenuHeight, setSubMenuHeight] = useState>( {}, ); const subMenuRefs = useRef>({}); const isActive = useCallback((path: string) => path === pathname, [pathname]); const handleSubmenuToggle = (index: number, menuType: "main" | "others") => { setOpenSubmenu((prev) => prev?.type === menuType && prev?.index === index ? null : { type: menuType, index }, ); }; useEffect(() => { let submenuMatched = false; [ { items: ALL_NAV_ITEMS, type: "main" }, { items: OTHERS_ITEMS, type: "others" }, ].forEach(({ items, type }) => { items.forEach((nav, index) => { nav.subItems?.forEach((sub) => { if (isActive(sub.path)) { setOpenSubmenu((prev) => { if (prev?.type === type && prev?.index === index) return prev; return { type: type as "main" | "others", index }; }); submenuMatched = true; } }); }); }); if (!submenuMatched) { setOpenSubmenu((prev) => (prev !== null ? null : prev)); } }, [pathname, isActive]); useEffect(() => { if (openSubmenu !== null) { const key = `${openSubmenu.type}-${openSubmenu.index}`; if (subMenuRefs.current[key]) { setSubMenuHeight((prev) => ({ ...prev, [key]: subMenuRefs.current[key]?.scrollHeight || 0, })); } } }, [openSubmenu]); const renderMenuItems = (items: NavItem[], menuType: "main" | "others") => (
    {items.map((nav, index) => (
  • {nav.subItems ? ( ) : ( nav.path && ( {nav.icon} {(isExpanded || isHovered || isMobileOpen) && ( {nav.name} )} ) )} {nav.subItems && (isExpanded || isHovered || isMobileOpen) && (
    { subMenuRefs.current[`${menuType}-${index}`] = el; }} className="overflow-hidden transition-all duration-300" style={{ height: openSubmenu?.type === menuType && openSubmenu?.index === index ? `${subMenuHeight[`${menuType}-${index}`]}px` : "0px", }} >
      {nav.subItems.map((subItem) => (
    • {subItem.name} {subItem.new && ( new )} {subItem.pro && ( pro )}
    • ))}
    )}
  • ))}
); return ( ); }; export default AppSidebar;