import { Link, useNavigate, useParams } from "@tanstack/react-router"; import { motion, type Variants } from "framer-motion"; import { ArrowLeft, ChevronRight, Clock, Eye, Users } from "lucide-react"; import { useMemo, useState } from "react"; import { usePeers } from "@/api/queries"; import type { components } from "@/api/schema.d.ts"; import { EmptyState } from "@/components/shared/EmptyState"; import { ErrorAlert } from "@/components/shared/ErrorAlert"; import { JsonViewer } from "@/components/shared/JsonViewer"; import { PageLoader } from "@/components/shared/LoadingSpinner"; import { Pagination } from "@/components/shared/Pagination"; import { SortControl, type SortDir } from "@/components/shared/SortControl"; import { MonoCaption, PageTitle } from "@/components/ui/typography"; import { useDemo } from "@/hooks/useDemo"; import { COLOR } from "@/lib/constants"; type Peer = components["schemas"]["Peer"]; type KindStyle = { bg: string; text: string; border: string }; const KIND_STYLES: Record = { agent: { bg: COLOR.warningDim, text: COLOR.warning, border: COLOR.warningBorder }, discord: { bg: "rgba(14,165,233,0.08)", text: "#38bdf8", border: "rgba(14,165,233,0.2)" }, ai: { bg: COLOR.accentDim, text: COLOR.accentText, border: COLOR.accentBorder }, }; function peerKind(id: string): (KindStyle & { label: string }) | null { if (id.startsWith("agent-")) return { label: "agent", ...KIND_STYLES.agent }; if (id.startsWith("discord-")) return { label: "discord", ...KIND_STYLES.discord }; if (["claude", "hermes", "codex"].includes(id)) return { label: "ai", ...KIND_STYLES.ai }; return null; } const SORT_OPTIONS = [ { value: "created_at", label: "Newest" }, { value: "id", label: "ID" }, ]; const container: Variants = { hidden: { opacity: 0 }, show: { opacity: 1, transition: { staggerChildren: 0.06 } }, }; const item: Variants = { hidden: { opacity: 0, y: 10 }, show: { opacity: 1, y: 0, transition: { type: "spring", stiffness: 300, damping: 25 } }, }; export function PeerList() { const { mask } = useDemo(); const { workspaceId } = useParams({ strict: false }) as { workspaceId: string }; const [page, setPage] = useState(1); const [sortField, setSortField] = useState("created_at"); const [sortDir, setSortDir] = useState("desc"); const [expandedMeta, setExpandedMeta] = useState>(new Set()); const [activeFilters, setActiveFilters] = useState>(new Set()); const navigate = useNavigate(); const { data, isLoading, error } = usePeers(workspaceId, page); const peers: Peer[] = (data as { items?: Peer[] } | undefined)?.items ?? []; const totalPages = (data as { pages?: number } | undefined)?.pages ?? 1; const total = (data as { total?: number } | undefined)?.total ?? 0; const availableLabels = useMemo(() => { const labels = new Set(); for (const peer of peers) { const kind = peerKind(peer.id); if (kind) labels.add(kind.label); } return labels; }, [peers]); const sorted = useMemo(() => { return [...peers].sort((a, b) => { let cmp = 0; if (sortField === "created_at") { cmp = new Date(a.created_at).getTime() - new Date(b.created_at).getTime(); } else if (sortField === "id") { cmp = a.id.localeCompare(b.id); } return sortDir === "asc" ? cmp : -cmp; }); }, [peers, sortField, sortDir]); const filtered = useMemo(() => { if (activeFilters.size === 0) return sorted; return sorted.filter((peer) => { const kind = peerKind(peer.id); return kind ? activeFilters.has(kind.label) : false; }); }, [sorted, activeFilters]); function toggleFilter(label: string) { setActiveFilters((prev) => { const next = new Set(prev); next.has(label) ? next.delete(label) : next.add(label); return next; }); } function handleSort(field: string, dir: SortDir) { setSortField(field); setSortDir(dir); } return (
{mask(workspaceId)}
Peers {total > 0 && ( {total} )}
{mask(workspaceId)}
{availableLabels.size > 0 && (
{[...availableLabels].map((label) => { const style = KIND_STYLES[label]; const active = activeFilters.has(label); return ( ); })} {activeFilters.size > 0 && ( )}
)} {isLoading && } {!isLoading && peers.length === 0 && ( )} {!isLoading && peers.length > 0 && filtered.length === 0 && ( )} {!isLoading && filtered.length > 0 && ( <> {filtered.map((peer) => { const kind = peerKind(peer.id); const metaKeys = Object.keys(peer.metadata ?? {}); const hasMeta = metaKeys.length > 0; const metaOpen = expandedMeta.has(peer.id); function toggleMeta(e: React.MouseEvent) { e.stopPropagation(); setExpandedMeta((prev) => { const next = new Set(prev); next.has(peer.id) ? next.delete(peer.id) : next.add(peer.id); return next; }); } return ( {hasMeta && ( <> {metaOpen && (
)} )}
); })}
)}
); }