import React, { useState } from 'react'; import { Text, Checkbox, Tooltip, ActionIcon, Badge, Modal } from '@mantine/core'; import { useTranslation } from 'react-i18next'; import CloseIcon from '@mui/icons-material/Close'; import VisibilityIcon from '@mui/icons-material/Visibility'; import HistoryIcon from '@mui/icons-material/History'; import DragIndicatorIcon from '@mui/icons-material/DragIndicator'; import styles from './PageEditor.module.css'; import FileOperationHistory from '../history/FileOperationHistory'; interface FileItem { id: string; name: string; pageCount: number; thumbnail: string; size: number; splitBefore?: boolean; } interface FileThumbnailProps { file: FileItem; index: number; totalFiles: number; selectedFiles: string[]; selectionMode: boolean; draggedFile: string | null; dropTarget: string | null; isAnimating: boolean; fileRefs: React.MutableRefObject>; onDragStart: (fileId: string) => void; onDragEnd: () => void; onDragOver: (e: React.DragEvent) => void; onDragEnter: (fileId: string) => void; onDragLeave: () => void; onDrop: (e: React.DragEvent, fileId: string) => void; onToggleFile: (fileId: string) => void; onDeleteFile: (fileId: string) => void; onViewFile: (fileId: string) => void; onSetStatus: (status: string) => void; toolMode?: boolean; isSupported?: boolean; } const FileThumbnail = ({ file, index, totalFiles, selectedFiles, selectionMode, draggedFile, dropTarget, isAnimating, fileRefs, onDragStart, onDragEnd, onDragOver, onDragEnter, onDragLeave, onDrop, onToggleFile, onDeleteFile, onViewFile, onSetStatus, toolMode = false, isSupported = true, }: FileThumbnailProps) => { const { t } = useTranslation(); const [showHistory, setShowHistory] = useState(false); const formatFileSize = (bytes: number) => { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]; }; return (
{ if (el) { fileRefs.current.set(file.id, el); } else { fileRefs.current.delete(file.id); } }} data-file-id={file.id} data-testid="file-thumbnail" className={` ${styles.pageContainer} !rounded-lg cursor-grab select-none w-[20rem] h-[24rem] flex flex-col items-center justify-center flex-shrink-0 shadow-sm hover:shadow-md transition-all relative ${selectionMode ? 'bg-white hover:bg-gray-50' : 'bg-white hover:bg-gray-50'} ${draggedFile === file.id ? 'opacity-50 scale-95' : ''} `} style={{ transform: (() => { if (!isAnimating && draggedFile && file.id !== draggedFile && dropTarget === file.id) { return 'translateX(20px)'; } return 'translateX(0)'; })(), transition: isAnimating ? 'none' : 'transform 0.2s ease-in-out', opacity: isSupported ? 1 : 0.5, filter: isSupported ? 'none' : 'grayscale(50%)' }} draggable onDragStart={() => onDragStart(file.id)} onDragEnd={onDragEnd} onDragOver={onDragOver} onDragEnter={() => onDragEnter(file.id)} onDragLeave={onDragLeave} onDrop={(e) => onDrop(e, file.id)} > {selectionMode && (
e.stopPropagation()} onDragStart={(e) => { e.preventDefault(); e.stopPropagation(); }} > { event.stopPropagation(); if (isSupported) { onToggleFile(file.id); } }} onClick={(e) => e.stopPropagation()} disabled={!isSupported} size="sm" />
)} {/* File content area */}
{/* Stacked file effect - multiple shadows to simulate pages */}
{file.name}
{/* Page count badge */} {file.pageCount} pages {/* Unsupported badge */} {!isSupported && ( {t("fileManager.unsupported", "Unsupported")} )} {/* File name overlay */} {file.name} {/* Hover controls */}
{!toolMode && isSupported && ( <> { e.stopPropagation(); onViewFile(file.id); onSetStatus(`Opened ${file.name}`); }} > )} { e.stopPropagation(); setShowHistory(true); onSetStatus(`Viewing history for ${file.name}`); }} > { e.stopPropagation(); onDeleteFile(file.id); onSetStatus(`Closed ${file.name}`); }} >
{/* File info */}
{file.name} {formatFileSize(file.size)}
{/* History Modal */} setShowHistory(false)} title={`Operation History - ${file.name}`} size="lg" scrollAreaComponent="div" >
); }; export default FileThumbnail;