import React, { useState, useEffect } from "react"; import { Card, Group, Text, Stack, Image, Badge, Button, Box, Flex } from "@mantine/core"; import { Dropzone, MIME_TYPES } from "@mantine/dropzone"; import { GlobalWorkerOptions, getDocument } from "pdfjs-dist"; GlobalWorkerOptions.workerSrc = (import.meta as any).env?.PUBLIC_URL ? `${(import.meta as any).env.PUBLIC_URL}/pdf.worker.js` : "/pdf.worker.js"; export interface FileWithUrl extends File { url?: string; file?: File; } function getFileDate(file: File): string { if (file.lastModified) { return new Date(file.lastModified).toLocaleString(); } return "Unknown"; } function getFileSize(file: File): string { if (!file.size) return "Unknown"; if (file.size < 1024) return `${file.size} B`; if (file.size < 1024 * 1024) return `${(file.size / 1024).toFixed(1)} KB`; return `${(file.size / (1024 * 1024)).toFixed(2)} MB`; } function usePdfThumbnail(file: File | undefined | null): string | null { const [thumb, setThumb] = useState(null); useEffect(() => { let cancelled = false; async function generate() { if (!file) return; try { const arrayBuffer = await file.arrayBuffer(); const pdf = await getDocument({ data: arrayBuffer }).promise; const page = await pdf.getPage(1); const viewport = page.getViewport({ scale: 0.5 }); const canvas = document.createElement("canvas"); canvas.width = viewport.width; canvas.height = viewport.height; const context = canvas.getContext("2d"); if (context) { await page.render({ canvasContext: context, viewport }).promise; if (!cancelled) setThumb(canvas.toDataURL()); } } catch { if (!cancelled) setThumb(null); } } generate(); return () => { cancelled = true; }; }, [file]); return thumb; } interface FileCardProps { file: File; onRemove: () => void; onDoubleClick?: () => void; } function FileCard({ file, onRemove, onDoubleClick }: FileCardProps) { const thumb = usePdfThumbnail(file); return ( {thumb ? ( PDF thumbnail ) : ( PDF )} {file.name} {getFileSize(file)} {getFileDate(file)} ); } interface FileManagerProps { files: FileWithUrl[]; setFiles: React.Dispatch>; allowMultiple?: boolean; setPdfFile?: (fileObj: { file: File; url: string }) => void; setCurrentView?: (view: string) => void; } const FileManager: React.FC = ({ files = [], setFiles, allowMultiple = true, setPdfFile, setCurrentView, }) => { const handleDrop = (uploadedFiles: File[]) => { setFiles((prevFiles) => (allowMultiple ? [...prevFiles, ...uploadedFiles] : uploadedFiles)); }; const handleRemoveFile = (index: number) => { setFiles((prevFiles) => prevFiles.filter((_, i) => i !== index)); }; return (
Drag PDF files here or click to select {files.length === 0 ? ( No files uploaded yet. ) : ( {files.map((file, idx) => ( handleRemoveFile(idx)} onDoubleClick={() => { const fileObj = (file as FileWithUrl).file || file; setPdfFile && setPdfFile({ file: fileObj, url: URL.createObjectURL(fileObj), }); setCurrentView && setCurrentView("viewer"); }} /> ))} )}
); }; export default FileManager;