import { useCallback, useState } from 'react'; import { useDropzone } from 'react-dropzone'; import { Upload, X, Image, File } from 'lucide-react'; interface EnhancedFileUploadProps { onFilesChange: (files: File[]) => void; maxFiles?: number; maxSize?: number; // in bytes accept?: { [key: string]: string[] }; className?: string; } const EnhancedFileUpload: React.FC = ({ onFilesChange, maxFiles = 5, maxSize = 10 * 1024 * 1024, // 10MB accept = { 'image/*': ['.jpeg', '.jpg', '.png', '.gif', '.webp'], 'application/pdf': ['.pdf'], 'text/*': ['.txt', '.doc', '.docx'] }, className = '' }) => { const [uploadedFiles, setUploadedFiles] = useState([]); const [uploading, setUploading] = useState(false); const [uploadProgress, setUploadProgress] = useState<{ [key: string]: number }>({}); const onDrop = useCallback(async (acceptedFiles: File[]) => { setUploading(true); const newFiles = [...uploadedFiles, ...acceptedFiles].slice(0, maxFiles); setUploadedFiles(newFiles); onFilesChange(newFiles); // Simulate upload progress for (const file of acceptedFiles) { for (let progress = 0; progress <= 100; progress += 10) { setUploadProgress(prev => ({ ...prev, [file.name]: progress })); await new Promise(resolve => setTimeout(resolve, 100)); } } setUploading(false); setUploadProgress({}); }, [uploadedFiles, maxFiles, onFilesChange]); const removeFile = (fileToRemove: File) => { const newFiles = uploadedFiles.filter(file => file !== fileToRemove); setUploadedFiles(newFiles); onFilesChange(newFiles); }; const { getRootProps, getInputProps, isDragActive, fileRejections } = useDropzone({ onDrop, accept, maxSize, maxFiles: maxFiles - uploadedFiles.length, disabled: uploading }); const formatFileSize = (bytes: number) => { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; }; const getFileIcon = (file: File) => { if (file.type.startsWith('image/')) { return ; } return ; }; return (
{/* Dropzone */}
{isDragActive ? 'Drop files here' : 'Drag & drop files here'}

or browse files

Max {maxFiles} files, up to {formatFileSize(maxSize)} each

{/* File Rejections */} {fileRejections.length > 0 && (
Upload Errors:
{fileRejections.map(({ file, errors }) => (
{file.name}: {errors.map(e => e.message).join(', ')}
))}
)} {/* Uploaded Files List */} {uploadedFiles.length > 0 && (
Uploaded Files ({uploadedFiles.length})
{uploadedFiles.map((file, index) => (
{getFileIcon(file)}

{file.name}

{formatFileSize(file.size)}

{uploadProgress[file.name] !== undefined && (
)}
))}
)}
); }; export default EnhancedFileUpload;