import React, { useState, useRef } from 'react'; import { Upload, X, Image, Loader2 } from 'lucide-react'; import { Button } from '../common'; import { clsx } from 'clsx'; import { api } from '../../config/api'; import { toast } from 'react-toastify'; import { useQuery } from '@tanstack/react-query'; import { categoriesService } from '../../services/categories.service'; import { useTranslation } from 'react-i18next'; interface PhotoUploadProps { eventId: number; onUploadComplete?: () => void; } export const PhotoUpload: React.FC = ({ eventId, onUploadComplete }) => { const { t } = useTranslation(); const [isUploading, setIsUploading] = useState(false); const [selectedFiles, setSelectedFiles] = useState([]); const [uploadProgress, setUploadProgress] = useState(0); const [selectedCategoryId, setSelectedCategoryId] = useState(null); const fileInputRef = useRef(null); // Fetch categories for this event const { data: categories = [] } = useQuery({ queryKey: ['event-categories', eventId], queryFn: () => categoriesService.getEventCategories(eventId), }); const handleFileSelect = (e: React.ChangeEvent) => { const files = Array.from(e.target.files || []); const imageFiles = files.filter(file => ['image/jpeg', 'image/png', 'image/webp'].includes(file.type) ); setSelectedFiles(prev => [...prev, ...imageFiles]); }; const removeFile = (index: number) => { setSelectedFiles(prev => prev.filter((_, i) => i !== index)); }; const handleUpload = async () => { if (selectedFiles.length === 0) return; setIsUploading(true); setUploadProgress(0); const formData = new FormData(); selectedFiles.forEach((file, index) => { console.log(`Adding file ${index}: ${file.name}, size: ${file.size}`); formData.append('photos', file); }); if (selectedCategoryId) { formData.append('category_id', selectedCategoryId.toString()); } // Debug: Log FormData contents console.log('FormData entries:'); for (let pair of formData.entries()) { console.log(pair[0], pair[1]); } try { const response = await api.post(`/admin/events/${eventId}/upload`, formData, { // Don't set Content-Type header - axios will set it with the boundary onUploadProgress: (progressEvent) => { if (progressEvent.total) { const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total); setUploadProgress(progress); } }, }); console.log('Upload result:', response.data); // Clear selected files setSelectedFiles([]); if (fileInputRef.current) { fileInputRef.current.value = ''; } // Show success message toast.success(t('toast.uploadSuccess')); // Call callback if (onUploadComplete) { onUploadComplete(); } } catch (error: any) { console.error('Upload error:', error); toast.error(error.response?.data?.error || t('toast.uploadError')); } finally { setIsUploading(false); setUploadProgress(0); } }; const formatFileSize = (bytes: number) => { if (bytes < 1024) return bytes + ' B'; if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB'; return (bytes / (1024 * 1024)).toFixed(1) + ' MB'; }; return (
{/* Category Selection */}
{/* File Input Area */}
0 ? "border-primary-400 bg-primary-50/30" : "border-neutral-300" )} onClick={() => fileInputRef.current?.click()} >

{t('upload.clickToUpload')}

{t('upload.fileRequirements')}

{/* Selected Files */} {selectedFiles.length > 0 && (

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

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

{file.name}

{formatFileSize(file.size)}

))}
)} {/* Upload Button */}
{/* Progress Bar */} {isUploading && (
{t('upload.uploading')} {uploadProgress}%
)}
); }; PhotoUpload.displayName = 'PhotoUpload';