import { CircleDotDashed, Settings, Tags } from "lucide-react"; import { useEffect, useState } from "react"; import { Link, useLocation, useNavigate, useParams } from "react-router-dom"; import { useBoardMaintainers, useBoards } from "../hooks/useBoard"; import { api } from "../lib/api"; import { clearAuthToken, signOut, useSession } from "../lib/auth-client"; import { getTheme, setTheme, type Theme } from "../lib/theme"; import { AgentIdenticon } from "./AgentIdenticon"; import { BoardMaintainerDialog } from "./BoardMaintainerDialog"; import { BoardSwitcher } from "./BoardSwitcher"; import { Avatar, AvatarFallback, AvatarImage } from "./ui/avatar"; import { Button, buttonVariants } from "./ui/button"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from "./ui/dropdown-menu"; import { Tooltip, TooltipContent, TooltipTrigger } from "./ui/tooltip"; const _navLinks = [ { to: "/projects", label: "Dự án" }, { to: "/agents", label: "Agents" }, { to: "/machines", label: "Machines" }, ]; function ThemeIcon({ theme }: { theme: Theme }) { if (theme === "light") { return ( ); } if (theme === "dark") { return ( ); } return ( ); } export function Header() { const { data: session } = useSession(); const user = session?.user as { name?: string; email?: string; image?: string; role?: string } | undefined; const isAdmin = user?.role === "admin"; const { boards, refresh: refreshBoards } = useBoards(); const { boardId } = useParams<{ boardId: string }>(); const [theme, setThemeState] = useState(getTheme()); const [switcherOpen, setSwitcherOpen] = useState(false); const _location = useLocation(); const navigate = useNavigate(); const activeBoard = boards.find((b: any) => b.id === boardId); function cycleTheme() { const next: Theme = theme === "dark" ? "light" : theme === "light" ? "system" : "dark"; setTheme(next); setThemeState(next); } function handleBoardSelect(id: string) { navigate(`/boards/${id}`); } async function handleBoardCreate(name: string, type: "dev" | "ops") { const created = await api.boards.create({ name, type }); refreshBoards(); if (created?.id) navigate(`/boards/${created.id}`); } async function handleSignOut() { await signOut(); clearAuthToken(); navigate("/auth"); } return ( <>
{/* Left: Logo + Board name */}
VTIT Agent Coding {activeBoard && ( <> / } /> Board settings } /> Labels )}
{/* Right: Nav + Theme + Avatar */}
{/* Navigation Links Removed per user request */} {/* Avatar + Dropdown */} }> {user?.image && } {(user?.name || "?")[0].toUpperCase()} {user && ( <>

{user.name || user.email}

{user.name && user.email &&

{user.email}

}
)} navigate("/settings/profile")}> Settings navigate("/repositories")}> Repositories {isAdmin && ( navigate("/admin")}> Admin )} Sign out
{/* Theme toggle */} }> Theme: {theme}
{switcherOpen && ( setSwitcherOpen(false)} /> )} ); } function MaintainerControl({ boardId }: { boardId: string }) { const navigate = useNavigate(); const [dialogOpen, setDialogOpen] = useState(false); const [agent, setAgent] = useState(null); const { maintainers } = useBoardMaintainers(boardId); const maintainer = maintainers[0] as { id: string; agent_id?: string; status?: string } | undefined; useEffect(() => { let cancelled = false; if (!maintainer?.agent_id) { setAgent(null); return; } api.agents .list() .then((agents) => { if (!cancelled) setAgent((agents ?? []).find((candidate: any) => candidate.id === maintainer.agent_id) ?? null); }) .catch(() => { if (!cancelled) setAgent(null); }); return () => { cancelled = true; }; }, [maintainer?.agent_id]); if (!maintainer) { return ( <> setDialogOpen(true)}> } /> Add maintainer ); } const maintainerLabel = agent?.name ?? agent?.username ?? maintainer.agent_id ?? maintainer.id; return ( navigate(`/boards/${boardId}/maintainers/${maintainer.id}`)} > {agent?.public_key ? ( ) : ( {maintainerLabel[0]?.toUpperCase() ?? "?"} )} } /> {maintainerLabel} ); }