import React, { useState } from 'react'; import { Upload, X, CheckCircle } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import { toast } from 'react-toastify'; import { Button, Card, CardContent } from '../common'; import { api } from '../../config/api'; interface UserPhotoUploadProps { eventId: number; categoryId: number | null | undefined; onUploadComplete: () => void; onClose: () => void; } export const UserPhotoUpload: React.FC = ({ eventId, categoryId, onUploadComplete, onClose, }) => { const { t } = useTranslation(); const [files, setFiles] = useState([]); const [uploading, setUploading] = useState(false); const [uploadProgress, setUploadProgress] = useState<{ [key: string]: number }>({}); const handleFileSelect = (e: React.ChangeEvent) => { const selectedFiles = Array.from(e.target.files || []); // Validate file types const allowedTypes = ['image/jpeg', 'image/png', 'image/webp']; const validFiles = selectedFiles.filter(file => { if (!allowedTypes.includes(file.type)) { toast.error(`Invalid file type: ${file.name}`); return false; } // Check file size (50MB max) if (file.size > 50 * 1024 * 1024) { toast.error(`File too large: ${file.name}`); return false; } return true; }); setFiles(prev => [...prev, ...validFiles]); }; const removeFile = (index: number) => { setFiles(prev => prev.filter((_, i) => i !== index)); }; const handleUpload = async () => { if (files.length === 0) return; setUploading(true); let successCount = 0; let failedCount = 0; for (const file of files) { const formData = new FormData(); formData.append('photos', file); if (categoryId) { formData.append('category_id', categoryId.toString()); } try { await api.post(`/api/gallery/${eventId}/upload`, formData, { headers: { 'Content-Type': 'multipart/form-data', }, onUploadProgress: (progressEvent) => { if (progressEvent.total) { const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total); setUploadProgress(prev => ({ ...prev, [file.name]: progress, })); } }, }); successCount++; } catch (error: any) { console.error(`Failed to upload ${file.name}:`, error); failedCount++; // Show specific error message const errorMessage = error.response?.data?.error || error.message || 'Upload failed'; toast.error(`${file.name}: ${errorMessage}`); } } setUploading(false); if (successCount > 0) { toast.success(t('toast.uploadSuccess') + ` (${successCount} ${t('common.photos')})`); onUploadComplete(); } if (failedCount > 0) { toast.error(`${failedCount} ${t('upload.someFilesFailed')}`); } if (failedCount === 0) { onClose(); } }; const formatBytes = (bytes: number): string => { 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]; }; return (
{/* Header */}

{t('upload.uploadPhotos')}

{/* Content */}
{/* Upload Area */}
{/* Selected Files */} {files.length > 0 && (

{t('upload.selectedFiles')} ({files.length})

{files.map((file, index) => (

{file.name}

{formatBytes(file.size)}

{uploadProgress[file.name] !== undefined ? (
{uploadProgress[file.name] === 100 ? ( ) : (
)}
) : ( )}
))}
)}
{/* Footer */}
); }; UserPhotoUpload.displayName = 'UserPhotoUpload';