import { useT } from "@agent-native/core/client/i18n"; import { IconActivity, IconArrowUpRight, IconBrain, IconBrandTelegram, IconChartBar, IconFingerprint, IconHistory, IconKey, IconLayersSubtract, IconMail, IconMessages, IconPlugConnected, IconPuzzle, IconSettingsAutomation, IconShield, IconShieldCheck, IconSearch, IconX, } from "@tabler/icons-react"; import { useMemo, useState, type ReactNode } from "react"; import { NavLink } from "react-router"; import { cn } from "../lib/utils"; import { DISPATCH_DOCS, DocsLink } from "./docs-link"; import { useDispatchExtensions, type DispatchNavItem } from "./layout/Layout"; export interface AdminNavGroup { id: string; label: string; labelKey: string; items: readonly DispatchNavItem[]; } const BUILT_IN_ADMIN_NAV_GROUPS: readonly AdminNavGroup[] = [ { id: "workspace", label: "Workspace", labelKey: "dispatch.pages.adminWorkspace", items: [ { id: "admin-overview", to: "/admin", label: "Overview", icon: IconShield, }, { id: "admin-resources", to: "/admin/workspace", label: "Resources", icon: IconLayersSubtract, }, ], }, { id: "operations", label: "Operations", labelKey: "dispatch.pages.adminOperations", items: [ { id: "operations", to: "/admin/operations", label: "Operations", icon: IconActivity, }, { id: "metrics", to: "/admin/metrics", label: "Metrics", icon: IconChartBar, }, { id: "audit", to: "/admin/audit", label: "Audit", icon: IconHistory, }, { id: "thread-debug", to: "/admin/thread-debug", label: "Thread Debug", icon: IconMessages, }, ], }, { id: "automation", label: "Automation & delivery", labelKey: "dispatch.pages.adminAutomation", items: [ { id: "automations", to: "/admin/automations", label: "Automations", icon: IconSettingsAutomation, }, { id: "approvals", to: "/admin/approvals", label: "Approvals", icon: IconShieldCheck, }, { id: "destinations", to: "/admin/destinations", label: "Destinations", icon: IconArrowUpRight, }, { id: "transactional-email", to: "/admin/transactional-email", label: "Transactional email", icon: IconMail, }, ], }, { id: "connections", label: "Connections", labelKey: "dispatch.pages.adminConnections", items: [ { id: "integrations", to: "/admin/integrations", label: "Integrations", icon: IconPuzzle, }, { id: "vault", to: "/admin/vault", label: "Vault", icon: IconKey, }, { id: "messaging", to: "/admin/messaging", label: "Messaging", icon: IconBrandTelegram, }, { id: "identities", to: "/admin/identities", label: "Identities", icon: IconFingerprint, }, ], }, { id: "agent-platform", label: "Agent platform", labelKey: "dispatch.pages.adminAgentPlatform", items: [ { id: "agents", to: "/admin/agents", label: "Agents", icon: IconPlugConnected, }, { id: "dreams", to: "/admin/dreams", label: "Dreams", icon: IconBrain, }, ], }, ]; function itemLabel(t: ReturnType, item: DispatchNavItem) { return t(`dispatch.nav.${item.id}`, { defaultValue: item.label }); } function AdminNavLink({ item, onNavigate, }: { item: DispatchNavItem; onNavigate?: () => void; }) { const t = useT(); const to = item.adminTo ?? item.to; const label = itemLabel(t, item); const Icon = item.icon; return (
  • cn( "flex min-h-8 items-center gap-2 rounded-md px-2 text-sm transition-colors", isActive ? "bg-accent font-medium text-accent-foreground" : "text-muted-foreground hover:bg-accent/60 hover:text-foreground", ) } > {Icon ? : null} {label}
  • ); } export function AdminShell({ children, onNavigate, }: { children: ReactNode; onNavigate?: () => void; }) { const t = useT(); const groups = useAdminNavGroups(); const [query, setQuery] = useState(""); const normalizedQuery = query.trim().toLowerCase(); const visibleGroups = useMemo( () => groups .map((group) => ({ ...group, items: group.items.filter((item) => { if (!normalizedQuery) return true; const label = itemLabel(t, item).toLowerCase(); return `${label} ${group.label.toLowerCase()}`.includes( normalizedQuery, ); }), })) .filter((group) => group.items.length > 0), [groups, normalizedQuery, t], ); return (
    {children}
    ); } export { BUILT_IN_ADMIN_NAV_GROUPS }; export function useAdminNavGroups(): readonly AdminNavGroup[] { const extensions = useDispatchExtensions(); const extensionItems = (extensions?.navItems ?? []).filter( (item) => item.section === "operations", ); return extensionItems.length ? [ ...BUILT_IN_ADMIN_NAV_GROUPS, { id: "workspace-extensions", label: "Workspace extensions", labelKey: "dispatch.pages.adminWorkspaceExtensions", items: extensionItems, }, ] : BUILT_IN_ADMIN_NAV_GROUPS; }