import { Link, useNavigate } from "@tanstack/react-router"; import { useQueryClient } from "@tanstack/react-query"; import { CloudIcon, GearSixIcon, PlugsIcon, ShieldCheckIcon, SignOutIcon, SlidersHorizontalIcon, } from "@phosphor-icons/react"; import { useEffect, useRef, useState } from "react"; import type {ComponentType} from "react"; import type { SessionUser } from "@/lib/api"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { api } from "@/lib/api"; import { cn } from "@/lib/utils"; type IconType = ComponentType<{ className?: string; weight?: "regular" | "fill" | "duotone" }>; interface NavItem { to: string; label: string; icon: IconType; adminOnly?: boolean; } const NAV: Array = [ { to: "/my-settings", label: "My Settings", icon: SlidersHorizontalIcon }, { to: "/cloud-agents", label: "Cloud Agents", icon: CloudIcon }, { to: "/review", label: "Open SWE Review", icon: ShieldCheckIcon }, { to: "/integrations", label: "Integrations", icon: PlugsIcon }, { to: "/admin", label: "Admin", icon: GearSixIcon, adminOnly: true }, ]; export function AppSidebar({ user }: { user: SessionUser }) { const qc = useQueryClient(); const navigate = useNavigate(); const [menuOpen, setMenuOpen] = useState(false); const menuRef = useRef(null); useEffect(() => { if (!menuOpen) return; const onClickOutside = (e: MouseEvent) => { if (menuRef.current && !menuRef.current.contains(e.target as Node)) { setMenuOpen(false); } }; const onKey = (e: KeyboardEvent) => { if (e.key === "Escape") setMenuOpen(false); }; document.addEventListener("mousedown", onClickOutside); document.addEventListener("keydown", onKey); return () => { document.removeEventListener("mousedown", onClickOutside); document.removeEventListener("keydown", onKey); }; }, [menuOpen]); const onLogout = async () => { setMenuOpen(false); await api.logout(); qc.setQueryData(["session"], null); navigate({ to: "/login" }); }; const initials = (user.login || "?").slice(0, 2).toUpperCase(); return ( ); }