import React, { useCallback, useState } from 'react'; import { useDropzone } from 'react-dropzone'; import { motion, AnimatePresence } from 'framer-motion'; import { CloudArrowUpIcon, DocumentIcon, CheckCircleIcon, XCircleIcon, XMarkIcon } from '@heroicons/react/24/outline'; import { uploadDocument } from '../services/api'; import toast from 'react-hot-toast'; const FileUploader = ({ darkMode, onClose }) => { const [uploading, setUploading] = useState(false); const [uploadedFiles, setUploadedFiles] = useState([]); const onDrop = useCallback(async (acceptedFiles) => { setUploading(true); for (const file of acceptedFiles) { try { console.log(`Starting upload for file: ${file.name}, size: ${file.size} bytes`); const formData = new FormData(); formData.append('file', file); // Check file size limits const maxSize = 100 * 1024 * 1024; // 100MB if (file.size > maxSize) { toast.error(`${file.name} is too large (${formatFileSize(file.size)}). Maximum size is 100MB.`); setUploadedFiles(prev => [...prev, { name: file.name, size: file.size, status: 'error', error: 'File too large (max 100MB)' }]); continue; // Skip this file } else if (file.size > 10 * 1024 * 1024) { toast(`Warning: ${file.name} is large (${formatFileSize(file.size)}). Upload may take time.`, { icon: '⚠️', duration: 6000 }); } await uploadDocument(formData); setUploadedFiles(prev => [...prev, { name: file.name, size: file.size, status: 'success' }]); toast.success(`${file.name} uploaded successfully!`); console.log(`Successfully uploaded: ${file.name}`); } catch (error) { console.error(`Failed to upload ${file.name}:`, error); setUploadedFiles(prev => [...prev, { name: file.name, size: file.size, status: 'error', error: error.message }]); // More specific error messages let errorMessage = `Failed to upload ${file.name}`; if (error.message.includes('Network Error')) { errorMessage += ': Network connection failed. Check if the server is running.'; } else if (error.message.includes('timeout')) { errorMessage += ': Upload timed out. File may be too large.'; } else if (error.message.includes('413')) { errorMessage += ': File too large (max 100MB allowed).'; } else if (error.message.includes('415')) { errorMessage += ': Unsupported file type.'; } else if (error.message.includes('500')) { errorMessage += ': Server error. Check server logs.'; } else { errorMessage += `: ${error.message}`; } toast.error(errorMessage); } } setUploading(false); }, []); const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop, accept: { 'application/pdf': ['.pdf'], 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': ['.docx'], 'text/plain': ['.txt'] }, multiple: true }); const formatFileSize = (bytes) => { 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 removeFile = (index) => { setUploadedFiles(prev => prev.filter((_, i) => i !== index)); }; return (
{/* Dropzone - Mobile optimized */} {/* Upload Icon - Mobile optimized */} {/* Upload Text - Mobile optimized */}

{isDragActive ? 'Drop files here!' : 'Upload study materials'}

{isDragActive ? 'Release to upload your files' : 'Drag & drop files here, or tap to browse' }

{/* File size info - Mobile optimized */}

Maximum file size: 100MB

{/* File type badges - Mobile optimized */}
📄 PDF 📝 DOCX 📋 TXT
{/* Mobile-specific help text */}

💡 Tip: You can select multiple files at once

{/* Upload Progress - Mobile optimized */} {uploading && (
Uploading files...

Please wait while we process your documents

)}
{/* Uploaded Files List - Mobile optimized */} {uploadedFiles.length > 0 && (

Uploaded Files ({uploadedFiles.length})

{uploadedFiles.map((file, index) => (
{/* File Icon */}
{/* File Info */}

{file.name}

{formatFileSize(file.size)}

{file.status === 'error' && file.error && ( <>

{file.error}

)}
{/* Status and Actions */}
{/* Status Icon */} {file.status === 'success' ? ( ) : ( )} {/* Remove Button - Larger touch target */} removeFile(index)} className={`p-2 md:p-2.5 rounded-lg transition-colors touch-manipulation ${ darkMode ? 'hover:bg-gray-700 active:bg-gray-600 text-gray-400 hover:text-gray-200' : 'hover:bg-gray-200 active:bg-gray-300 text-gray-500 hover:text-gray-700' }`} title="Remove file" >
))}
)}
{/* Action Buttons - Mobile optimized */}
{/* Upload More Button */} {uploading ? 'Uploading...' : 'Upload More Files'} {/* Close Button */} {onClose && ( Done )}
); }; export default FileUploader;