'use client'; import { navs } from '@/config/navs'; import useGlobalStore from '@/config/use-global'; import { HoverCard, HoverCardContent, HoverCardTrigger } from '@workspace/ui/components/hover-card'; import { Sidebar, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarHeader, SidebarMenu, SidebarMenuButton, SidebarMenuItem, useSidebar, } from '@workspace/ui/components/sidebar'; import { Icon } from '@workspace/ui/custom-components/icon'; import { cn } from '@workspace/ui/lib/utils'; import { useTranslations } from 'next-intl'; import Image from 'next/legacy/image'; import Link from 'next/link'; import { usePathname } from 'next/navigation'; import React, { useState } from 'react'; type Nav = (typeof navs)[number]; function hasChildren(obj: any): obj is { items: any[] } { return obj && Array.isArray((obj as any).items) && (obj as any).items.length > 0; } export function SidebarLeft({ ...props }: React.ComponentProps) { const { common } = useGlobalStore(); const { site } = common; const t = useTranslations('menu'); const pathname = usePathname(); const { state, isMobile } = useSidebar(); const logsGroupTitle = 'Logs & Analytics'; const systemGroupTitle = 'System'; const [openGroups, setOpenGroups] = useState>(() => { const groups: Record = {}; (navs as typeof navs).forEach((nav) => { if (hasChildren(nav)) { // Default: open all groups except Logs & Analytics and System groups[nav.title] = nav.title !== logsGroupTitle && nav.title !== systemGroupTitle; } }); return groups; }); const handleToggleGroup = (title: string) => { setOpenGroups((prev) => ({ ...prev, [title]: !prev[title] })); }; const normalize = (p: string) => (p.endsWith('/') && p !== '/' ? p.replace(/\/+$/, '') : p); const isActiveUrl = (url: string) => { const path = normalize(pathname); const target = normalize(url); if (target === '/dashboard') return path === target; if (path === target) return true; // Only treat as active if next char is a path boundary '/' return path.startsWith(target + '/'); }; const isGroupActive = (nav: Nav) => (hasChildren(nav) && nav.items.some((i: any) => isActiveUrl(i.url))) || ('url' in nav && nav.url ? isActiveUrl(nav.url as string) : false); // Ensure the group containing the active route is open, without closing others React.useEffect(() => { setOpenGroups((prev) => { const next: Record = { ...prev }; (navs as typeof navs).forEach((nav) => { if (hasChildren(nav) && isGroupActive(nav)) next[nav.title] = true; }); return next; }); }, [pathname]); const renderCollapsedFlyout = (nav: Nav) => { const ParentButton = ( {'url' in nav && nav.url ? ( {'icon' in nav && (nav as any).icon ? ( ) : null} ) : ( <> {'icon' in nav && (nav as any).icon ? ( ) : null} )} ); if (!hasChildren(nav)) return ParentButton; return ( {ParentButton}
{'icon' in nav && (nav as any).icon ? ( ) : null} {t(nav.title)}
    {nav.items.map((item: any) => (
  • {item.icon && } {t(item.title)}
  • ))}
); }; return (
logo
{site.site_name} {site.site_desc}
{!isMobile && state === 'collapsed' ? (navs as typeof navs).map((nav) => ( {renderCollapsedFlyout(nav)} )) : (navs as typeof navs).map((nav) => { if (hasChildren(nav)) { const isOpen = openGroups[nav.title] ?? false; const groupActive = isGroupActive(nav); return ( handleToggleGroup(nav.title)} tabIndex={0} style={{ fontWeight: 500 }} isActive={false} > {'icon' in nav && (nav as any).icon ? ( ) : null} {t(nav.title)} {isOpen && ( {nav.items.map((item: any) => ( {item.icon && } {t(item.title)} ))} )} ); } return ( {'url' in nav && (nav as any).url ? ( {'icon' in nav && (nav as any).icon ? ( ) : null} {t(nav.title)} ) : ( <> {'icon' in nav && (nav as any).icon ? ( ) : null} {t(nav.title)} )} ); })}
); }