101 lines
3.0 KiB
TypeScript
101 lines
3.0 KiB
TypeScript
import { Button } from '@/components/ui/button';
|
|
import { FileText, Eye, Download } from 'lucide-react';
|
|
import { formatDateTime } from '@/utils/dateFormatter';
|
|
|
|
export interface DocumentData {
|
|
documentId: string;
|
|
name: string;
|
|
fileType: string;
|
|
size: string;
|
|
sizeBytes?: number;
|
|
uploadedBy?: string;
|
|
uploadedAt: string;
|
|
}
|
|
|
|
interface DocumentCardProps {
|
|
document: DocumentData;
|
|
onPreview?: (doc: { fileName: string; fileType: string; documentId: string; fileSize?: number }) => void;
|
|
onDownload?: (documentId: string) => Promise<void>;
|
|
showPreview?: boolean;
|
|
testId?: string;
|
|
}
|
|
|
|
const canPreview = (fileType: string) => {
|
|
const type = (fileType || '').toLowerCase();
|
|
return type.includes('image') || type.includes('pdf') ||
|
|
type.includes('jpg') || type.includes('jpeg') ||
|
|
type.includes('png') || type.includes('gif');
|
|
};
|
|
|
|
export function DocumentCard({
|
|
document,
|
|
onPreview,
|
|
onDownload,
|
|
showPreview = true,
|
|
testId = 'document-card'
|
|
}: DocumentCardProps) {
|
|
return (
|
|
<div
|
|
className="flex items-center justify-between p-4 rounded-lg border border-gray-300 hover:bg-gray-50 transition-colors"
|
|
data-testid={`${testId}-${document.documentId}`}
|
|
>
|
|
<div className="flex items-center gap-3">
|
|
<div className="p-2 bg-blue-100 rounded-lg">
|
|
<FileText className="w-5 h-5 text-blue-600" />
|
|
</div>
|
|
<div>
|
|
<p className="font-medium text-gray-900" data-testid={`${testId}-name`}>
|
|
{document.name}
|
|
</p>
|
|
<p className="text-xs text-gray-500" data-testid={`${testId}-metadata`}>
|
|
{document.size} • Uploaded by {document.uploadedBy} on {formatDateTime(document.uploadedAt)}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
{/* Preview button for images and PDFs */}
|
|
{showPreview && canPreview(document.fileType) && onPreview && (
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
onClick={() => onPreview({
|
|
fileName: document.name,
|
|
fileType: document.fileType,
|
|
documentId: document.documentId,
|
|
fileSize: document.sizeBytes
|
|
})}
|
|
title="Preview file"
|
|
data-testid={`${testId}-preview-btn`}
|
|
>
|
|
<Eye className="w-4 h-4" />
|
|
</Button>
|
|
)}
|
|
|
|
{/* Download button */}
|
|
{onDownload && (
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
onClick={async () => {
|
|
if (!document.documentId) {
|
|
alert('Document ID not available');
|
|
return;
|
|
}
|
|
try {
|
|
await onDownload(document.documentId);
|
|
} catch (error) {
|
|
alert('Failed to download document');
|
|
}
|
|
}}
|
|
title="Download file"
|
|
data-testid={`${testId}-download-btn`}
|
|
>
|
|
<Download className="w-4 h-4" />
|
|
</Button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|