// PURPOSE: Export bundle flow (spec §3.4, §8). Request an export of the whole // estate or one corpus; the app polls getExport and feeds jobs back in // (the timer lives in the app, per the polling contract). Download on // ready, error verbatim on failure. Props in, callbacks out. // =========================================================================== import { useState, type FC, type ReactNode } from "react"; import { Archive, CheckCircle2, Download, Loader2, XCircle } from "lucide-react"; import type { Collection, ExportJob, ExportScope } from "./types"; import { Spinner, cn, formatBytes, formatRelative } from "./_internal"; // ---- ExportJobRow --------------------------------------------------------- export const ExportJobRow: FC<{ job: ExportJob; onDownload?: (job: ExportJob) => void; className?: string }> = ({ job, onDownload, className, }) => { const running = job.status === "pending" || job.status === "running"; return (
{job.scope === "all" ? "Whole knowledge base" : job.scope}
{running ? "Building…" : job.status === "ready" ? `${job.object_count ?? 0} items · ${formatBytes(job.byte_size)} · ${formatRelative(job.updated_at)}` : job.error || "Failed"}
{intro ?? ( <> A self-contained zip — your originals, extracted text, catalog cards, and claims, in open formats. Citations resolve inside the bundle, so it stays readable with no service in the loop. It's yours to keep. > )}