import React, { useMemo } from 'react'; import { DownloadIcon, TextScanIcon, AnalyzeIcon, CloseIcon } from '../ui/icons'; import DocumentSummarySection, { buildCorrespondentOptions, sortCorrespondents, } from '../documents/DocumentSummarySection'; import { createDocumentActionState } from '../documents/documentActions'; const formatDateTime = (value) => { if (!value) { return '—'; } const date = new Date(value); return Number.isNaN(date.getTime()) ? '—' : date.toLocaleString(); }; const PreviewWorkspace = ({ document, previewEntry, tagLookupById, tagOptions, onTagAdd, onTagRemove, correspondents, onCorrespondentAdd, onCorrespondentRemove, onUpdateTitle, onUpdateIssued, resolveFolderPath, onFolderNavigate, }) => { const sortedCorrespondents = useMemo( () => sortCorrespondents(document?.correspondents || []), [document], ); const correspondentOptions = useMemo( () => buildCorrespondentOptions(Array.isArray(correspondents) ? correspondents : []), [correspondents], ); const metadataItems = useMemo(() => { if (!document) { return []; } return [ { label: 'Created at', value: formatDateTime(document.created_at) }, { label: 'Updated at', value: formatDateTime(document.updated_at) }, { label: 'Filename', value: document.archive_path || document.filename || '—', }, { label: 'Original filename', value: document.original_name || '—', }, { label: 'SHA-256 checksum', value: document.current_version?.checksum || '—', }, { label: 'Content type', value: document.content_type || '—', }, ]; }, [document]); const metadataPayload = useMemo(() => { if (!document || !document.metadata || Object.keys(document.metadata).length === 0) { return null; } return document.metadata; }, [document]); if (!document) { return null; } return ( Metadata {metadataItems.map(({ label, value }) => ( {label} {value || '—'} ))} {metadataPayload ? ( Show metadata payload {JSON.stringify(metadataPayload, null, 2)} ) : null} {!previewEntry?.url ? ( Loading preview… ) : ( )} ); }; export default PreviewWorkspace; export const createPreviewWorkspaceHeaderActions = ({ document, ensureAssetUrl, ensurePreviewData, getDocumentAsset, resolveApiPath, notifyApiError, onRegenerate, }) => { if (!document) { return null; } const { downloadHref, hasOcr, openOcr } = createDocumentActionState({ document, resolveApiPath, ensurePreviewData, ensureAssetUrl, getDocumentAsset, notifyApiError, ocrErrorMessage: 'Unable to open OCR text.', }); return ( <> {downloadHref ? ( ) : null} {hasOcr ? ( { openOcr().catch(() => {}); }} aria-label="View OCR text" title="View OCR text" > ) : null} onRegenerate(document.id)} aria-label="Re-run analysis" title="Re-run analysis" > > ); }; export const createPreviewSurface = ({ document, previewEntry, ensureAssetUrl, ensurePreviewData, getDocumentAsset, resolveApiPath, notifyApiError, onRegenerate, onClose, renderSidebarToggle, tagLookupById, tagOptions, onTagAdd, onTagRemove, correspondents, onCorrespondentAdd, onCorrespondentRemove, onUpdateTitle, onUpdateIssued, resolveFolderPath, onFolderNavigate, }) => { if (!document) { return null; } const title = document.title; const closeButton = onClose ? ( onClose?.()} aria-label="Close preview" title="Close preview" > ) : null; const sidebarToggle = renderSidebarToggle ? renderSidebarToggle() : null; const leading = closeButton || sidebarToggle ? ( <> {sidebarToggle} {closeButton} > ) : null; const header = { title, subtitle: null, leading, actions: createPreviewWorkspaceHeaderActions({ document, ensureAssetUrl, ensurePreviewData, getDocumentAsset, resolveApiPath, notifyApiError, onRegenerate, }), }; return { key: 'preview', variant: 'preview', header, content: ( ), supportsDetail: false, }; };
{JSON.stringify(metadataPayload, null, 2)}