'use client' import Link from 'next/link' import { useMemo, useState } from 'react' import type { SidebarRoute } from '@/types' import Button from '@/components/formElements/Button' import AngleDownIcon from '@/components/icons/AngleDownIcon' import { isSidebarGroupOpen, isSidebarRouteActive } from '@/helpers/sidebarRoute' interface SidebarNavProps { items: SidebarRoute[] pathname: string onLinkClick?: () => void compact?: boolean } const iconClass = (active: boolean, size: 'md' | 'sm' = 'md') => `${size === 'sm' ? 'size-4' : 'size-5'} ${active ? 'text-white' : 'text-secondary-30'}` const SidebarNavIcon = ({ active, item, size = 'md' }: { item: SidebarRoute; active: boolean; size?: 'md' | 'sm' }) => { const boxClass = size === 'sm' ? 'size-6' : 'size-8' if (!item.icon) { return ( ) } return ( {item.icon(iconClass(active, size))} ) } const SidebarNavLink = ({ active, href, item, onLinkClick, size = 'md', compact = false, }: { item: SidebarRoute href: string active: boolean onLinkClick?: () => void size?: 'md' | 'sm' compact?: boolean }) => { const isChild = size === 'sm' return ( {!isChild && (compact && item.icon ? ( item.icon(`size-6 ${active ? 'text-primary-700' : 'text-secondary-20'}`) ) : ( ))} {isChild && (item.icon ? ( ) : null)} {item.title} ) } const SidebarNavGroup = ({ groupKey, isOpen, item, onLinkClick, onToggle, pathname, }: { item: SidebarRoute groupKey: string pathname: string isOpen: boolean onToggle: (key: string) => void onLinkClick?: () => void }) => { const active = isSidebarRouteActive(pathname, item) return (
{isOpen && item.children ? (
{item.children.map((child, childIndex) => { if (!child.link) { return null } const childActive = isSidebarRouteActive(pathname, child) return ( ) })}
) : null}
) } const SidebarNav = ({ compact = false, items, onLinkClick, pathname }: SidebarNavProps) => { const autoOpenKeys = useMemo(() => { const keys = new Set() items.forEach((item, index) => { if (item.children && isSidebarGroupOpen(pathname, item)) { keys.add(String(index)) } }) return keys }, [pathname, items]) const [prevPathname, setPrevPathname] = useState(pathname) const [manualClosed, setManualClosed] = useState>(() => new Set()) const [manualOpen, setManualOpen] = useState>(() => new Set()) if (pathname !== prevPathname) { setPrevPathname(pathname) setManualClosed(new Set()) setManualOpen(new Set()) } const isGroupOpen = (key: string) => { if (manualClosed.has(key)) { return false } if (manualOpen.has(key)) { return true } return autoOpenKeys.has(key) } const toggleGroup = (key: string) => { if (isGroupOpen(key)) { setManualClosed((prev) => new Set(prev).add(key)) setManualOpen((prev) => { const next = new Set(prev) next.delete(key) return next }) } else { setManualOpen((prev) => new Set(prev).add(key)) setManualClosed((prev) => { const next = new Set(prev) next.delete(key) return next }) } } return ( ) } export default SidebarNav