"use client"; import Link from "next/link"; import { usePathname } from "next/navigation"; import { clsx } from "clsx"; import { useAuth } from "@/components/AuthProvider"; import { auth } from "@/lib/api"; interface NavItem { href: string; label: string; icon: React.ReactNode; /** Restricted to owner/admin — the roles the backing API requires. */ adminOnly?: boolean; } function ServerIcon() { return ( ); } function KeyIcon() { return ( ); } function SecretIcon() { return ( ); } function WorkflowIcon() { return ( ); } function AuditIcon() { return ( ); } function SettingsIcon() { return ( ); } function MonitorIcon() { return ( ); } function StepsIcon() { return ( ); } function OrgIcon() { return ( ); } const navItems: NavItem[] = [ { href: "/servers", label: "Servers", icon: }, { href: "/monitors", label: "Monitors", icon: }, { href: "/keys", label: "SSH Keys", icon: }, { href: "/secrets", label: "Secrets", icon: }, { href: "/workflows", label: "Workflows", icon: }, { href: "/steps", label: "Steps", icon: }, { href: "/audit", label: "Audit Log", icon: }, { href: "/settings/org", label: "Organization", icon: , adminOnly: true }, { href: "/settings", label: "Settings", icon: , adminOnly: true }, ]; export function Sidebar() { const pathname = usePathname(); const { user, org, isAdmin } = useAuth(); const visibleItems = navItems.filter((item) => !item.adminOnly || isAdmin); // Longest match wins, so /settings/org doesn't also light up /settings. const activeHref = visibleItems.reduce((best, item) => { const matches = pathname === item.href || pathname.startsWith(item.href + "/"); if (!matches) return best; return best === null || item.href.length > best.length ? item.href : best; }, null); async function handleLogout() { // /auth/logout is POST-only on the server. try { await auth.logout(); } catch { // Fall through — clearing the client-side session view is what matters. } window.location.href = "/login"; } return ( ); }