'use client'; import Link from 'next/link'; import { usePathname } from 'next/navigation'; import { useEffect, useMemo, useState } from 'react'; import { ChevronRight } from 'lucide-react'; import { useTranslations } from 'next-intl'; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from '@/components/ui/collapsible'; import { SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, } from '@/components/ui/sidebar'; import type { OpenFlareNavGroup } from '@/lib/navigation/openflare-nav'; import { matchesNavPath, openflareSidebarNav, isNavGroupActive, } from '@/lib/navigation/openflare-nav'; import { usePublicConfig } from '@/hooks/use-public-config'; function parseMenuDisplayConfig( raw: string | undefined, ): Record { if (!raw) return {}; try { const parsed: unknown = JSON.parse(raw); if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return {}; return Object.entries(parsed).reduce>( (result, [key, value]) => { if (typeof value === 'boolean') { result[key] = value; } return result; }, {}, ); } catch { return {}; } } function SidebarNavGroupMenuItem({ group, pathname, onNavigate, }: { group: OpenFlareNavGroup; pathname: string; onNavigate?: () => void; }) { const t = useTranslations('layout'); const groupTitle = t(`groups.${group.titleKey}`); const groupActive = isNavGroupActive(pathname, group); const [open, setOpen] = useState(groupActive); useEffect(() => { if (groupActive) { setOpen(true); } }, [groupActive]); return ( {groupTitle} {group.items.map((item) => { const title = t(`nav.${item.titleKey}`); return ( {title} ); })} ); } export function OpenFlareSidebarMenu({ onNavigate, }: { onNavigate?: () => void; }) { const pathname = usePathname(); const t = useTranslations('layout'); const { config } = usePublicConfig(); const displayConfig = useMemo( () => parseMenuDisplayConfig(config?.menu_display_config), [config], ); return ( {openflareSidebarNav.map((entry) => { if (entry.kind === 'group') { const filteredItems = entry.items.filter( (item) => displayConfig[item.url] !== false, ); if (filteredItems.length === 0) return null; return ( ); } if (displayConfig[entry.url] === false) { return null; } const title = t(`nav.${entry.titleKey}`); return ( {title} ); })} ); }