import React, { useState, useEffect } from 'react'; import { Button, Card, CardContent, Typography, Container, Box } from '@mui/material'; import Swal from 'sweetalert2/dist/sweetalert2.js'; import 'sweetalert2/src/sweetalert2.scss'; // Components import Navbar from '../ComponentUtils/Headers/Navbar'; import Footer from '../ComponentUtils/Footer'; import MultiImageDropzone from '../ComponentUtils/MultiUpload/MultiImageDropzone'; import ImageGallery from '../ComponentUtils/ImageGallery'; import DescriptionInput from '../ComponentUtils/MultiUpload/DescriptionInput'; import UploadProgress from '../ComponentUtils/MultiUpload/UploadProgress'; import Loading from '../ComponentUtils/LoadingAnimation/Loading'; import ConsentCheckboxes from '../ComponentUtils/MultiUpload/ConsentCheckboxes'; // Utils import { uploadImageBatch } from '../../Utils/batchUpload'; // Styles import '../../App.css'; // Background.css is now globally imported in src/index.js // Styles migrated to MUI sx props in-place below function MultiUploadPage() { const [selectedImages, setSelectedImages] = useState([]); const [metadata, setMetadata] = useState({ year: new Date().getFullYear(), title: '', description: '', name: '' }); const [consents, setConsents] = useState({ workshopConsent: false, socialMediaConsents: [] }); const [uploading, setUploading] = useState(false); const [uploadProgress, setUploadProgress] = useState(0); const [uploadComplete, setUploadComplete] = useState(false); const [uploadResult, setUploadResult] = useState(null); const [isEditMode, setIsEditMode] = useState(false); const [imageDescriptions, setImageDescriptions] = useState({}); // Cleanup object URLs when component unmounts useEffect(() => { return () => { selectedImages.forEach(img => { if (img.url && img.url.startsWith('blob:')) { URL.revokeObjectURL(img.url); } }); }; }, [selectedImages]); const handleImagesSelected = (newImages) => { console.log('handleImagesSelected called with:', newImages); // Convert File objects to preview objects with URLs const imageObjects = newImages.map((file, index) => ({ id: `preview-${Date.now()}-${index}`, // Unique ID für Preview-Modus file: file, // Original File object for upload url: URL.createObjectURL(file), // Preview URL name: file.name, originalName: file.name, size: file.size, type: file.type })); setSelectedImages(prev => { const updated = [...prev, ...imageObjects]; return updated; }); }; const handleRemoveImage = (indexToRemove) => { setSelectedImages(prev => { const imageToRemove = prev[indexToRemove]; // Clean up the object URL to avoid memory leaks if (imageToRemove && imageToRemove.url && imageToRemove.url.startsWith('blob:')) { URL.revokeObjectURL(imageToRemove.url); } return prev.filter((_, index) => index !== indexToRemove); }); }; const handleClearAll = () => { // Clean up all object URLs selectedImages.forEach(img => { if (img.url && img.url.startsWith('blob:')) { URL.revokeObjectURL(img.url); } }); setSelectedImages([]); setMetadata({ year: new Date().getFullYear(), title: '', description: '', name: '' }); setConsents({ workshopConsent: false, socialMediaConsents: [] }); setImageDescriptions({}); setIsEditMode(false); }; // Handle drag-and-drop reordering (only updates local state, no API call) const handleReorder = (reorderedItems) => { console.log('Reordering images in preview:', reorderedItems); setSelectedImages(reorderedItems); }; // Handle edit mode toggle const handleEditMode = (enabled) => { setIsEditMode(enabled); }; // Handle description changes const handleDescriptionChange = (imageId, description) => { setImageDescriptions(prev => ({ ...prev, [imageId]: description.slice(0, 200) // Enforce max length })); }; const handleUpload = async () => { if (selectedImages.length === 0) { Swal.fire({ icon: 'warning', title: 'Keine Bilder ausgewählt', text: 'Bitte wählen Sie mindestens ein Bild zum Upload aus.', confirmButtonColor: '#4CAF50' }); return; } if (!metadata.year || !metadata.title.trim()) { Swal.fire({ icon: 'warning', title: 'Pflichtfelder fehlen', text: 'Bitte gebe das Jahr und den Titel an.', confirmButtonColor: '#4CAF50' }); return; } // GDPR: Validate workshop consent (mandatory) if (!consents.workshopConsent) { Swal.fire({ icon: 'error', title: 'Einwilligung erforderlich', text: 'Die Zustimmung zur Anzeige in der Werkstatt ist erforderlich.', confirmButtonColor: '#f44336' }); return; } setUploading(true); setUploadProgress(0); try { // Simuliere Progress (da wir noch keinen echten Progress haben) const progressInterval = setInterval(() => { setUploadProgress(prev => { if (prev >= 90) { clearInterval(progressInterval); return 90; } return prev + 10; }); }, 200); // Extract the actual File objects from our image objects const filesToUpload = selectedImages.map(img => img.file || img); // Prepare descriptions array for backend const descriptionsArray = selectedImages.map(img => ({ fileName: img.name, description: imageDescriptions[img.id] || '' })); const result = await uploadImageBatch(filesToUpload, metadata, descriptionsArray, consents); clearInterval(progressInterval); setUploadProgress(100); // Show success content setTimeout(() => { setUploadComplete(true); setUploadResult(result); }, 500); } catch (error) { setUploading(false); console.error('Upload error:', error); Swal.fire({ icon: 'error', title: 'Upload fehlgeschlagen', text: error.message || 'Ein Fehler ist beim Upload aufgetreten.', confirmButtonColor: '#f44336' }); } }; return (
Project Image Uploader Lade ein oder mehrere Bilder von deinem Projekt hoch und beschreibe dein Projekt in wenigen Worten.
Die Bilder werden nur hier im Hobbyhimmel auf dem Monitor gezeigt, es wird an keine Dritten weiter gegeben.
{!uploading ? ( <> {selectedImages.length > 0 && ( <> )} ) : (
{!uploadComplete ? ( <> ) : ( {/* Success Icon & Title */} Upload erfolgreich! {/* Upload Count */} {uploadResult?.imageCount || 0} {uploadResult?.imageCount === 1 ? 'Bild wurde' : 'Bilder wurden'} erfolgreich hochgeladen und {uploadResult?.imageCount === 1 ? 'wird' : 'werden'} nach der Prüfung durch das Hobbyhimmel-Team angezeigt. {/* Group ID Box */} Ihre Referenz-Nummer: {uploadResult?.groupId} Notieren Sie sich diese Nummer für spätere Anfragen {/* Next Steps */} Was passiert jetzt? Ihre Bilder werden vom Team geprüft Nach Freigabe erscheinen sie auf dem Werkstatt-Monitor Bei gewählter Social Media Einwilligung werden sie entsprechend veröffentlicht {/* GDPR Contact */} Fragen oder Widerruf? Kontaktieren Sie uns mit Ihrer Referenz-Nummer unter: it@hobbyhimmel.de {/* Action Button */} )}
)}
); } export default MultiUploadPage;