"use client"; import { useEffect } from "react"; import { motion, AnimatePresence } from "framer-motion"; import { FileText, X } from "@phosphor-icons/react"; export type PreviewDoc = { doc_id?: string; doc_type?: string; page_count?: number; [key: string]: unknown; }; /** Map CASE-A-001 → INV-A-001 for sample previews before reset. */ export function sampleDocIdForCase(caseId: string): string { const m = caseId.match(/^CASE-([A-E])-(\d{3})$/i); if (m) return `INV-${m[1].toUpperCase()}-${m[2]}`; return "INV-A-001"; } function normType(t: string): string { return t.trim().toLowerCase(); } function extractOcrPreview( lastToolResult: Record | null | undefined, ): string | undefined { if (!lastToolResult) return undefined; const name = typeof lastToolResult.tool_name === "string" ? lastToolResult.tool_name : ""; if (name !== "ocr") return undefined; const top = lastToolResult.text_preview; if (typeof top === "string" && top.trim()) return top.trim(); const out = lastToolResult.output; if (out && typeof out === "object" && "text_preview" in out) { const tp = (out as Record).text_preview; return typeof tp === "string" && tp.trim() ? tp.trim() : undefined; } return undefined; } function InvoiceStub({ docId }: { docId: string }) { return (

Commercial invoice

{docId}

Issued 2026-01-15 · Due NET 30

Bill to

Contoso AP Operations

200 Commerce Way

Vendor

Northwind Industrial Ltd.

vendor_key: northwind-industrial

Description Qty Amount
Industrial fittings — batch 2048-A 1 2,478.00 USD

This is a benchmark fixture for LedgerShield. Use OCR tools in a run to replace this with extracted text from the environment.

); } function EmailStub({ docId }: { docId: string }) { return (

From: accounts@northwind.example.com

To: ap@contoso.example.com

Subject: Invoice {docId} — payment instructions

Please process the attached invoice for Northwind Industrial. Remit to the account on file; contact procurement for any bank detail changes.

); } export function DocumentPreviewModal({ open, onClose, doc, caseId, instruction, lastToolResult, }: { open: boolean; onClose: () => void; doc: PreviewDoc | null; caseId?: string; instruction?: string; lastToolResult?: Record | null; }) { useEffect(() => { if (!open) return; const onKey = (e: KeyboardEvent) => { if (e.key === "Escape") onClose(); }; window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, [open, onClose]); const docId = typeof doc?.doc_id === "string" ? doc.doc_id : "—"; const docType = typeof doc?.doc_type === "string" ? doc.doc_type : "document"; const pages = typeof doc?.page_count === "number" && Number.isFinite(doc.page_count) ? doc.page_count : undefined; const ocr = extractOcrPreview(lastToolResult ?? null); const t = normType(docType); return ( {open && doc && ( e.stopPropagation()} >

{docId}

{docType}

{pages != null && (

{pages} pages

)} {caseId && (

Case {caseId}

)}
{instruction ? (

Task: {instruction}

) : null} {ocr ? (

OCR excerpt (last run)

                    {ocr}
                  
) : t === "invoice" || t === "inv" ? ( ) : t === "email" ? ( ) : (

Document metadata

                    {JSON.stringify(doc, null, 2)}
                  
)}
)}
); }