"use client"; import { useState } from "react"; import Link from "next/link"; import { usePathname, useRouter } from "next/navigation"; import { useTheme } from "next-themes"; import { Moon, Sun, LogOut, Gauge, SlidersHorizontal, ListMusic, Bluetooth, BarChart3 } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Sheet, SheetContent, SheetDescription, SheetTitle } from "@/components/ui/sheet"; import { ConnectionStatus } from "./ConnectionStatus"; import { BrandMark } from "./BrandMark"; import { cn } from "@/lib/utils"; const LINKS = [ { href: "/", label: "Dashboard", icon: Gauge }, { href: "/control", label: "Control", icon: SlidersHorizontal }, { href: "/sessions", label: "Sessions", icon: ListMusic }, { href: "/devices", label: "Devices", icon: Bluetooth }, { href: "/stats", label: "Stats", icon: BarChart3 }, ]; function isActive(pathname: string, href: string): boolean { return href === "/" ? pathname === "/" : pathname === href || pathname.startsWith(`${href}/`); } /** Desktop tab strip - borderless chips; the active tab lights up with a * primary-tinted fill, matching the drawer rows' active treatment. */ function NavLinks({ onNavigate }: { onNavigate?: () => void }) { const pathname = usePathname(); return ( <> {LINKS.map((link) => { const active = isActive(pathname, link.href); return ( {link.label} ); })} > ); } /** Drawer rows for the mobile menu - icon + label, styled as tappable * console rows rather than the desktop tab strip's underline treatment. */ function MobileNavLinks({ onNavigate }: { onNavigate: () => void }) { const pathname = usePathname(); return ( <> {LINKS.map((link) => { const active = isActive(pathname, link.href); return ( {link.label} ); })} > ); } /** Hamburger that morphs into an X - the top/bottom bars rotate into place * and the middle bar collapses, rather than a straight icon swap. */ function MenuToggleIcon({ open }: { open: boolean }) { return ( ); } export function NavBar() { const { theme, setTheme } = useTheme(); const router = useRouter(); const [menuOpen, setMenuOpen] = useState(false); async function handleLogout() { await fetch("/api/auth/logout", { method: "POST" }); router.push("/login"); router.refresh(); } return ( Sexy setTheme(theme === "dark" ? "light" : "dark")} > setMenuOpen((open) => !open)} > Sexy Jump to another page or manage your session. setMenuOpen(false)} /> setTheme(theme === "dark" ? "light" : "dark")} className="flex items-center gap-3 rounded-lg px-3 py-3 text-sm font-medium text-muted-foreground transition-colors hover:bg-accent/50 hover:text-foreground" > {theme === "dark" ? "Switch to light mode" : "Switch to dark mode"} void handleLogout()} className="flex items-center gap-3 rounded-lg px-3 py-3 text-sm font-medium text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive" > Log out ); }