feat: Published-Bilder ausblenden + Bild-Lösch-Button in Content Erstellen

Die Blätter-Ansicht lädt veröffentlichte Bilder nicht mehr (Filter beim
Laden/Reload, Entfernen beim manuellen Publish). Neuer 🗑-Button löscht
ein Bild komplett (S3 + DB inkl. Objekte und Pairs via API-Kaskade).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 21:27:57 +02:00
parent e383cacd45
commit 96c436e0e9

View File

@@ -1606,6 +1606,7 @@ export default function ContentCreation() {
const [loadingPairs, setLoadingPairs] = useState(false);
const [markingDone, setMarkingDone] = useState(false);
const [deletingPicture, setDeletingPicture] = useState(false);
const currentPicture = pictures[pictureIndex] || null;
const selectedObjectId = typeof mode === 'string' && mode !== 'add' ? mode : null;
@@ -1614,15 +1615,21 @@ export default function ContentCreation() {
? { ...selectedObject, _index: objects.indexOf(selectedObject) }
: null;
// Load all pictures
// Load all pictures (published sind fertig und werden hier nicht mehr bearbeitet)
useEffect(() => {
setLoadingPictures(true);
apiFetch('/pictures?limit=500')
.then(data => setPictures(Array.isArray(data) ? data : []))
.then(data => setPictures(Array.isArray(data) ? data.filter(p => p.status !== 'published') : []))
.catch(() => setPictures([]))
.finally(() => setLoadingPictures(false));
}, []);
// Index im gültigen Bereich halten, wenn die Liste schrumpft
useEffect(() => {
if (pictureIndex > 0 && pictureIndex >= pictures.length)
setPictureIndex(Math.max(0, pictures.length - 1));
}, [pictures.length, pictureIndex]);
// Load objects when picture changes
useEffect(() => {
if (!currentPicture) return;
@@ -1720,10 +1727,27 @@ export default function ContentCreation() {
if (!currentPicture) return;
try {
await apiPatch('/pictures', currentPicture.id, { status: newStatus });
setPictures(prev => prev.map((p, i) => i === pictureIndex ? { ...p, status: newStatus } : p));
if (newStatus === 'published') {
// Veröffentlichte Bilder verschwinden aus der Bearbeitungs-Ansicht
setPictures(prev => prev.filter((_, i) => i !== pictureIndex));
} else {
setPictures(prev => prev.map((p, i) => i === pictureIndex ? { ...p, status: newStatus } : p));
}
} catch (e) { alert('Fehler: ' + e.message); }
}
async function handleDeletePicture() {
if (!currentPicture) return;
const ok = window.confirm('Bild endgültig löschen? Entfernt das Bild (S3 + Datenbank) inklusive aller Objekte und Pairs.');
if (!ok) return;
setDeletingPicture(true);
try {
await apiDelete('/pictures', currentPicture.id);
setPictures(prev => prev.filter((_, i) => i !== pictureIndex));
} catch (e) { alert('Fehler: ' + e.message); }
finally { setDeletingPicture(false); }
}
async function handleObjectStatusChange(objectId, newStatus) {
try {
await apiPatch('/objects', objectId, { status: newStatus });
@@ -1756,7 +1780,7 @@ export default function ContentCreation() {
function reloadPictures() {
apiFetch('/pictures?limit=500')
.then(data => setPictures(Array.isArray(data) ? data : []))
.then(data => setPictures(Array.isArray(data) ? data.filter(p => p.status !== 'published') : []))
.catch(() => {});
}
@@ -1800,6 +1824,12 @@ export default function ContentCreation() {
{currentPicture.objects_created && (
<span className="px-2 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-700"> Objekte</span>
)}
<button onClick={handleDeletePicture}
disabled={deletingPicture}
title="Bild löschen (S3 + Datenbank, inkl. Objekte und Pairs)"
className="px-2 py-1 text-xs rounded-lg border border-red-200 text-red-600 hover:bg-red-50 disabled:opacity-40 transition-colors">
{deletingPicture ? 'Lösche…' : '🗑'}
</button>
</>
)}
<button onClick={handleMarkDone}