/** * BatchProgressBanner — slim banner showing live batch rebuild progress. * Renders on the homepage only when a rebuild is actively in progress * (completed < queue_total). */ "use client"; import { useEffect, useState } from "react"; import Link from "next/link"; interface BatchPayload { status: string; queue_total: number; completed: number; successes: number; failures: number; progress_pct: number; quota_state?: "ok" | "throttled"; quota_resume_eta_minutes?: number | null; } export function BatchProgressBanner() { const [data, setData] = useState(null); useEffect(() => { let alive = true; async function tick() { try { const r = await fetch("/api/admin/batch"); if (!r.ok) return; const j = (await r.json()) as BatchPayload; if (alive && j.status === "ok") setData(j); } catch { /* ignore */ } } tick(); const i = setInterval(tick, 60_000); return () => { alive = false; clearInterval(i); }; }, []); if (!data || data.completed >= data.queue_total) return null; const throttled = data.quota_state === "throttled"; return (
{throttled ? "💸" : "⚙️"}
{throttled ? "Anthropic quota throttled" : "Chunks rebuild em progresso"} {data.completed}/{data.queue_total} docs · {data.progress_pct}% {throttled && data.quota_resume_eta_minutes != null && ( · reset em{" "} {data.quota_resume_eta_minutes >= 60 ? `${(data.quota_resume_eta_minutes / 60).toFixed(1)}h` : `${data.quota_resume_eta_minutes}min`} )} {data.failures > 0 && ( · {data.failures} falhas )} ver detalhes →
); }