From 2a507851d94ada5e0fd78e3856464e32354880f8 Mon Sep 17 00:00:00 2001 From: Scarriffle Date: Sun, 26 Jul 2026 12:28:02 +0200 Subject: [PATCH] Web: "Entfernen" nur zeigen, wenn ein Artikelbild vorliegt Der Entfernen-Knopf stand auch ohne Bild da. ProduktBild meldet jetzt via onLoaded, ob ein Bild geladen wurde; das Produktformular blendet "Entfernen" entsprechend ein oder aus. "Foto machen" und "Galerie" bleiben immer sichtbar. Co-Authored-By: Claude Opus 4.8 --- web/src/components/ProduktBild.jsx | 27 ++++++++++++++++++++------- web/src/pages/ProductForm.jsx | 8 ++++++-- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/web/src/components/ProduktBild.jsx b/web/src/components/ProduktBild.jsx index 7104832..3a9cdcf 100644 --- a/web/src/components/ProduktBild.jsx +++ b/web/src/components/ProduktBild.jsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import { authorizedObjectUrl } from "../api"; import Icon from "./Icon"; @@ -7,9 +7,16 @@ import Icon from "./Icon"; * * Die Objekt-URL wird beim Verlassen wieder freigegeben, sonst hält der Browser * jedes angesehene Bild bis zum Neuladen der Seite im Speicher. + * + * ``onLoaded`` meldet, ob ein Bild vorliegt – so kann die Artikelseite z.B. den + * „Entfernen"-Knopf ausblenden, wenn es nichts zu entfernen gibt. */ -function useBildUrl(productId, version = 0) { +function useBildUrl(productId, version = 0, onLoaded) { const [url, setUrl] = useState(null); + // Über einen Ref, damit ein bei jedem Render neu erzeugtes onLoaded den Effekt + // nicht erneut auslöst. + const onLoadedRef = useRef(onLoaded); + onLoadedRef.current = onLoaded; useEffect(() => { if (!productId) return undefined; @@ -20,15 +27,21 @@ function useBildUrl(productId, version = 0) { // Speichern nicht seine zwischengespeicherte Fassung ausliefert. authorizedObjectUrl(`/products/${productId}/image${version ? `?v=${version}` : ""}`) .then((neu) => { - if (!neu) return; if (abgebrochen) { - URL.revokeObjectURL(neu); + if (neu) URL.revokeObjectURL(neu); + return; + } + onLoadedRef.current?.(Boolean(neu)); + if (!neu) { + setUrl(null); return; } erzeugt = neu; setUrl(neu); }) - .catch(() => {}); + .catch(() => { + if (!abgebrochen) onLoadedRef.current?.(false); + }); return () => { abgebrochen = true; @@ -46,8 +59,8 @@ function useBildUrl(productId, version = 0) { * Rendert nichts, solange kein Bild vorliegt – ein leerer Rahmen neben einem * Artikel, der nie ein Bild bekommen wird, wäre nur Lärm. */ -export default function ProduktBild({ productId, alt, className = "", version = 0 }) { - const url = useBildUrl(productId, version); +export default function ProduktBild({ productId, alt, className = "", version = 0, onLoaded }) { + const url = useBildUrl(productId, version, onLoaded); if (!url) return null; return {alt; } diff --git a/web/src/pages/ProductForm.jsx b/web/src/pages/ProductForm.jsx index f97e5dd..8969d15 100644 --- a/web/src/pages/ProductForm.jsx +++ b/web/src/pages/ProductForm.jsx @@ -96,6 +96,8 @@ export default function ProductForm() { const [offDaten, setOffDaten] = useState(null); const [offBusy, setOffBusy] = useState(false); const [bildVersion, setBildVersion] = useState(0); + // Ob gerade ein Bild vorliegt – steuert, ob „Entfernen" angeboten wird. + const [hatBild, setHatBild] = useState(false); const selectedUnit = units.find((u) => String(u.id) === String(form.unit_id)) || null; const unitFactor = selectedUnit ? selectedUnit.factor : 1; @@ -561,7 +563,7 @@ export default function ProductForm() { {!isNew && (
- + {isAdmin && (
- + {hatBild && ( + + )}
)}