"use client"; import { useState, useRef, useEffect } from "react"; import Link from "next/link"; import { usePathname, useRouter } from "next/navigation"; import { IconHome2, IconMoon, IconSun, IconChevronsLeft, IconChevronsRight, IconMenu2, IconX, IconCode, IconKey, IconLogout, IconUsers, IconChartLine, IconChevronDown, IconBolt, IconChartBar, IconChartCandle, } from "@tabler/icons-react"; import { useSetTheme } from "@/stores/useThemeStore"; import { useFocusedWindowState, requestViewChange } from "@/stores/windowStore"; import { PANEL_SECTIONS, type PanelId } from "@/app/components/windows/types"; import { SideNavWidgets } from "./SideNavWidgets"; const COLLAPSED_W = 52; const SECTION_ICONS: Record = { "power-analytics": IconBolt, }; const ANALYTICS_ICONS: Record = { dashboard: IconHome2, "analytics-line": IconChartLine, "analytics-bar": IconChartBar, "analytics-candle": IconChartCandle, }; interface SideNavProps { online: boolean; devConsoleOpen: boolean; onToggleDevConsole: () => void; isAuthed?: boolean; } // ── Window nav (only shown on /) ────────────────────────────────────────────── function WindowNav({ collapsed, focusedPanelId }: { collapsed: boolean; focusedPanelId: PanelId | null }) { const [openSections, setOpenSections] = useState>( new Set(PANEL_SECTIONS.map((s) => s.id)) ); const toggleSection = (id: string) => { setOpenSections((prev) => { const next = new Set(prev); next.has(id) ? next.delete(id) : next.add(id); return next; }); }; if (collapsed) { return (
{/* Dashboard icon */} {/* Section items */} {PANEL_SECTIONS.flatMap((s) => s.items.map(({ panelId, label }) => { const Icon = ANALYTICS_ICONS[panelId]; const active = focusedPanelId === panelId; return ( ); }) )}
); } return (
{/* Dashboard standalone */} {/* Power Analytics section */} {PANEL_SECTIONS.map((section) => { const SectionIcon = SECTION_ICONS[section.id] ?? IconBolt; const isOpen = openSections.has(section.id); return (
{isOpen && (
{section.items.map(({ panelId, label }) => { const Icon = ANALYTICS_ICONS[panelId]; const active = focusedPanelId === panelId; return ( ); })}
)}
); })}
); } // ── Desktop sidebar ─────────────────────────────────────────────────────────── const SideNav = ({ online, devConsoleOpen, onToggleDevConsole, isAuthed }: SideNavProps) => { const pathname = usePathname(); const router = useRouter(); const setTheme = useSetTheme(); const [collapsed, setCollapsed] = useState(false); const [sidebarWidth, setSidebarWidth] = useState(220); const [menuOpen, setMenuOpen] = useState(false); const [auth, setAuth] = useState(isAuthed ?? null); const isDragging = useRef(false); const wrapperRef = useRef(null); const { panelId: focusedPanelId } = useFocusedWindowState(); const isHome = pathname === "/"; useEffect(() => { setMenuOpen(false); }, [pathname]); useEffect(() => { if (isAuthed !== undefined) return; fetch("/api/auth/check").then((r) => setAuth(r.ok)).catch(() => setAuth(false)); }, [isAuthed]); useEffect(() => { const onMove = (e: MouseEvent) => { if (!isDragging.current || !wrapperRef.current) return; const left = wrapperRef.current.getBoundingClientRect().left; setSidebarWidth(Math.max(180, Math.min(400, e.clientX - left))); }; const onUp = () => { isDragging.current = false; }; window.addEventListener("mousemove", onMove); window.addEventListener("mouseup", onUp); return () => { window.removeEventListener("mousemove", onMove); window.removeEventListener("mouseup", onUp); }; }, []); async function handleLogout() { await fetch("/api/auth/logout", { method: "POST" }); router.push("/auth"); } const navItemClass = (active: boolean, col: boolean) => "w-full flex items-center rounded-[8px] transition-colors cursor-pointer " + (col ? "justify-center py-[7px] " : "gap-[10px] px-[10px] py-[7px] text-[13px] whitespace-nowrap ") + (active ? "bg-blue/10 text-blue font-semibold" : "text-foreground-sec hover:bg-secondary/50 hover:text-foreground font-medium"); return ( <> {/* Desktop sidebar */}
{/* Logo */}
logo
{/* Auth/users route links */} {/* Window sections — only on home route */} {isHome && ( <> {(auth !== null) &&
} {!collapsed && (

Views

)}
)} {/* Widgets */} {!collapsed && ( <>
)} {/* Online status */}
{!collapsed && (online ? "Online" : "Connecting...")}
{/* Dev console */} {auth && (
)} {/* Logout */} {auth && (
)} {/* Theme toggle */}
{/* Divider + collapse */}
{/* Drag handle */} {!collapsed && (
{ isDragging.current = true; e.preventDefault(); }} className="w-[10px] shrink-0 flex items-center justify-center cursor-col-resize group">
)}
{/* Mobile header */}
setMenuOpen(false)}> logo
{/* Mobile dropdown menu */} {menuOpen && (
{auth === false && ( )} {auth && ( )} {/* Mobile window sections */} {isHome && ( <>

Views

{/* Dashboard */} {/* Sections */} {PANEL_SECTIONS.map((section) => (

{section.label}

{section.items.map(({ panelId, label }) => { const Icon = ANALYTICS_ICONS[panelId]; const active = focusedPanelId === panelId; return ( ); })}
))}
)}
{auth && ( )} {auth && ( )}
)} ); }; export default SideNav;