/** * dashboard-client/src/components/RepoDetailModal.tsx — repo drill-down. * * Full detail from an /api/index row: token breakdown (kept/dropped), model * info, context window, dedup rate, reasoning flag. Click backdrop to close. */ import type React from "react"; import { useEffect } from "react"; import type { IndexesIndexRow } from "@contracts"; export interface RepoDetailModalProps { repo: IndexesIndexRow; onClose: () => void; } function fmt(n: number): string { if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`; if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`; return String(n); } /** Format bytes → MiB/KiB/B (matches html.ts fmtBytesTop). */ function fmtBytesTop(b: number): string { if (b >= 1_048_576) return `${(b / 1_048_576).toFixed(1)} MiB`; if (b >= 1024) return `${(b / 1024).toFixed(1)} KiB`; return `${b} B`; } function formatTs(ts: number | null): string { if (ts === null || ts === undefined) return "never"; try { return new Date(ts).toLocaleString(); } catch { return String(ts); } } export function RepoDetailModal({ repo, onClose, }: RepoDetailModalProps): React.ReactElement { // Close on Escape key. useEffect(() => { const handler = (e: KeyboardEvent): void => { if (e.key === "Escape") onClose(); }; window.addEventListener("keydown", handler); return () => window.removeEventListener("keydown", handler); }, [onClose]); return (
{repo.repoRoot}