/** * Card view for displaying document summary, preview, and metadata. */ import { useState } from 'react'; import { Download, FileText, Trash2 } from 'lucide-react'; import type { DmsDocument } from '../types'; import { contentMarkdownUrl, downloadUrl, thumbnailUrl } from '../lib/api'; /** * Defines properties accepted by the document card component. */ interface DocumentCardProps { document: DmsDocument; isSelected: boolean; isChecked: boolean; isTrashView: boolean; onSelect: (document: DmsDocument) => void; onToggleChecked: (documentId: string, checked: boolean) => void; onTrashDocument: (documentId: string) => Promise; onFilterPath: (path: string) => void; onFilterTag: (tag: string) => void; } /** * Defines visual processing status variants rendered in the card header indicator. */ type StatusTone = 'success' | 'progress' | 'failed'; /** * Resolves status tone and tooltip text from backend document status values. */ function statusPresentation(status: DmsDocument['status']): { tone: StatusTone; tooltip: string } { if (status === 'processed') { return { tone: 'success', tooltip: 'Processing status: success' }; } if (status === 'queued') { return { tone: 'progress', tooltip: 'Processing status: in progress' }; } if (status === 'error') { return { tone: 'failed', tooltip: 'Processing status: failed' }; } if (status === 'unsupported') { return { tone: 'failed', tooltip: 'Processing status: failed (unsupported type)' }; } return { tone: 'success', tooltip: 'Processing status: success (moved to trash)' }; } /** * Limits logical-path length while preserving start and end context with middle ellipsis. */ function compactLogicalPath(path: string, maxChars = 180): string { const normalized = path.trim(); if (!normalized) { return ''; } if (normalized.length <= maxChars) { return normalized; } const keepChars = Math.max(12, maxChars - 3); const headChars = Math.ceil(keepChars * 0.6); const tailChars = keepChars - headChars; return `${normalized.slice(0, headChars)}...${normalized.slice(-tailChars)}`; } /** * Renders one document card with optional image preview and searchable metadata. */ export default function DocumentCard({ document, isSelected, isChecked, isTrashView, onSelect, onToggleChecked, onTrashDocument, onFilterPath, onFilterTag, }: DocumentCardProps): JSX.Element { const [isTrashing, setIsTrashing] = useState(false); const createdDate = new Date(document.created_at).toLocaleString(); const status = statusPresentation(document.status); const compactPath = compactLogicalPath(document.logical_path, 180); const trashDisabled = isTrashView || document.status === 'trashed' || isTrashing; const trashTitle = trashDisabled ? 'Already in trash' : 'Move to trash'; return (
onSelect(document)} onKeyDown={(event) => { if (event.currentTarget !== event.target) { return; } if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); onSelect(document); } }} >
{document.preview_available ? ( {document.original_filename} ) : (
{document.extension || 'file'}
)}

{compactPath}/ {document.original_filename}

{createdDate}

); }