// Run detail (SD-0002 §5.5) — report card for a completed or in-progress import run. // NO images section this slice (SLICE-7). PUC-4/5/8. import { useEffect, useState } from "react"; import { getRun, type RunDetail as RunDetailType } from "../../productsApi"; import { Banner } from "../../ui/kit"; const STATUS_LABELS: Record = { applying: "Importing…", fetching_images: "Fetching images…", complete: "Complete", complete_with_problems: "Complete with problems", }; export default function RunDetail({ runId }: { runId: number }) { const [run, setRun] = useState(null); const [loadFail, setLoadFail] = useState<"gone" | "failed" | null>(null); async function load() { setLoadFail(null); const resp = await getRun(runId); if (!resp.ok) { setLoadFail(resp.status === 404 ? "gone" : "failed"); return; } setRun(resp.value); } useEffect(() => { void load(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [runId]); if (loadFail === "gone") { return ( ← Products ); } if (loadFail === "failed") { return ( Something went wrong on our side.{" "} ); } if (!run) return

Loading…

; const dialectLabel = run.dialect === "canonical" ? "Canonical format" : run.dialect; return (

← Products

{run.file_name}

Imported {new Date(run.created_at).toLocaleString()} by {run.by} · {dialectLabel}

{run.products_added} added · {run.products_updated} updated · {run.rows_errored} rows in error

{STATUS_LABELS[run.status] ?? run.status}

{run.errors.length > 0 && ( {run.errors.map((e, i) => ( ))}
Line Column Problem
{e.line} {e.column ?? ""} {e.message}
)}
); }