import React, { useState } from 'react'; import { Box, Typography, Paper } from '@mui/material'; import Swal from 'sweetalert2'; import ImageGallery from './ImageGallery'; /** * Manages image descriptions with save functionality * Wraps ImageGallery and provides batch save for all descriptions * * @param mode - 'manage' (uses token) or 'moderate' (uses groupId) */ function ImageDescriptionManager({ images, token, groupId, enableReordering = false, onReorder, onRefresh, mode = 'manage' }) { const [imageDescriptions, setImageDescriptions] = useState({}); const [originalDescriptions, setOriginalDescriptions] = useState({}); const [isEditMode, setIsEditMode] = useState(false); const [saving, setSaving] = useState(false); // Handle deleting a single image const handleDeleteImage = async (imageId) => { const result = await Swal.fire({ title: 'Bild löschen?', text: 'Möchten Sie dieses Bild wirklich löschen? Diese Aktion kann nicht rückgängig gemacht werden.', icon: 'warning', showCancelButton: true, confirmButtonColor: '#d33', cancelButtonColor: '#3085d6', confirmButtonText: 'Ja, löschen', cancelButtonText: 'Abbrechen' }); if (!result.isConfirmed) return; try { // Different API endpoints for manage vs moderate const endpoint = mode === 'moderate' ? `/groups/${groupId}/images/${imageId}` : `/api/manage/${token}/images/${imageId}`; const res = await fetch(endpoint, { method: 'DELETE' }); if (!res.ok) { const body = await res.json().catch(() => ({})); throw new Error(body.error || 'Fehler beim Löschen des Bildes'); } await Swal.fire({ icon: 'success', title: 'Gelöscht', text: 'Bild wurde erfolgreich gelöscht.', timer: 2000, showConfirmButton: false }); // Refresh data if (onRefresh) { await onRefresh(); } } catch (error) { console.error('Error deleting image:', error); Swal.fire({ icon: 'error', title: 'Fehler', text: error.message || 'Bild konnte nicht gelöscht werden' }); } }; // Initialize descriptions from images React.useEffect(() => { if (images && images.length > 0) { const descriptions = {}; images.forEach(img => { descriptions[img.id] = img.imageDescription || ''; }); setImageDescriptions(descriptions); setOriginalDescriptions(descriptions); } }, [images]); const handleDescriptionChange = (imageId, description) => { setImageDescriptions(prev => ({ ...prev, [imageId]: description })); }; const hasChanges = () => { return JSON.stringify(imageDescriptions) !== JSON.stringify(originalDescriptions); }; const handleSave = async () => { if (!hasChanges()) { Swal.fire({ icon: 'info', title: 'Keine Änderungen', text: 'Es wurden keine Änderungen an den Beschreibungen vorgenommen.' }); return; } try { setSaving(true); // Build descriptions array for API const descriptions = Object.entries(imageDescriptions).map(([imageId, description]) => ({ imageId: parseInt(imageId), description: description || null })); // Different API endpoints for manage vs moderate const endpoint = mode === 'moderate' ? `/groups/${groupId}/images/batch-description` : `/api/manage/${token}/images/descriptions`; const method = mode === 'moderate' ? 'PATCH' : 'PUT'; const res = await fetch(endpoint, { method: method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ descriptions }) }); if (!res.ok) { const body = await res.json().catch(() => ({})); throw new Error(body.error || 'Fehler beim Speichern der Beschreibungen'); } await Swal.fire({ icon: 'success', title: 'Gespeichert', text: 'Bildbeschreibungen wurden erfolgreich aktualisiert.', timer: 2000, showConfirmButton: false }); // Update original descriptions setOriginalDescriptions(imageDescriptions); // Refresh data if callback provided if (onRefresh) { await onRefresh(); } } catch (error) { console.error('Error saving descriptions:', error); Swal.fire({ icon: 'error', title: 'Fehler', text: error.message || 'Beschreibungen konnten nicht gespeichert werden' }); } finally { setSaving(false); } }; const handleDiscard = () => { setImageDescriptions(originalDescriptions); setIsEditMode(false); }; const handleEditToggle = () => { if (isEditMode && hasChanges()) { // Warn user if trying to leave edit mode with unsaved changes Swal.fire({ icon: 'warning', title: 'Ungespeicherte Änderungen', text: 'Du hast ungespeicherte Änderungen. Bitte speichere oder verwerfe sie zuerst.', confirmButtonText: 'OK' }); return; // Don't toggle edit mode } if (isEditMode) { // Discard changes when leaving edit mode without saving setImageDescriptions({ ...originalDescriptions }); } setIsEditMode(!isEditMode); }; return ( {/* Component Header */} Bildbeschreibungen {hasChanges() && ( )} ); } export default ImageDescriptionManager;