Web: Foto schon beim Anlegen eines Produkts hinterlegen
Bisher ging ein Foto erst nach dem Speichern (Produkt-ID noetig). Jetzt kann man beim Neuanlegen direkt "Foto machen"/"Galerie" nutzen - das Bild wird vorgemerkt, als Vorschau gezeigt und nach dem Anlegen hochgeladen. Nuetzlich, wenn Open Food/ Products Facts kein Bild liefert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -107,6 +107,9 @@ export default function ProductForm() {
|
||||
const [bildVersion, setBildVersion] = useState(0);
|
||||
// Ob gerade ein Bild vorliegt – steuert, ob „Entfernen" angeboten wird.
|
||||
const [hatBild, setHatBild] = useState(false);
|
||||
// Beim Neuanlegen gibt es noch keine Produkt-ID zum Hochladen: Foto zwischen-
|
||||
// speichern und nach dem Anlegen hochladen. { file, url } | null.
|
||||
const [pendingPhoto, setPendingPhoto] = useState(null);
|
||||
|
||||
const selectedUnit = units.find((u) => String(u.id) === String(form.unit_id)) || null;
|
||||
const unitFactor = selectedUnit ? selectedUnit.factor : 1;
|
||||
@@ -198,10 +201,18 @@ export default function ProductForm() {
|
||||
async function onPickPhoto(e) {
|
||||
const file = e.target.files?.[0];
|
||||
e.target.value = ""; // erlaubt, dieselbe Datei erneut zu wählen
|
||||
if (!file || isNew) return;
|
||||
if (!file) return;
|
||||
setError(null);
|
||||
try {
|
||||
const foto = await verkleinereBild(file);
|
||||
if (isNew) {
|
||||
// Noch keine ID – Foto vormerken und erst nach dem Anlegen hochladen.
|
||||
setPendingPhoto((alt) => {
|
||||
if (alt?.url) URL.revokeObjectURL(alt.url);
|
||||
return { file: foto, url: URL.createObjectURL(foto) };
|
||||
});
|
||||
return;
|
||||
}
|
||||
await api.uploadProductImage(id, foto);
|
||||
setBildVersion((v) => v + 1);
|
||||
toast("Foto gespeichert.");
|
||||
@@ -210,6 +221,13 @@ export default function ProductForm() {
|
||||
}
|
||||
}
|
||||
|
||||
function removePendingPhoto() {
|
||||
setPendingPhoto((alt) => {
|
||||
if (alt?.url) URL.revokeObjectURL(alt.url);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
async function removePhoto() {
|
||||
const ok = await confirm({
|
||||
title: "Foto entfernen?", confirmLabel: "Entfernen", danger: true,
|
||||
@@ -507,6 +525,16 @@ export default function ProductForm() {
|
||||
try {
|
||||
if (isNew) {
|
||||
const created = await api.createProduct(buildPayload());
|
||||
// Vorgemerktes Foto jetzt hochladen – ein Fehler dabei darf das Anlegen
|
||||
// nicht zunichte machen, der Artikel existiert bereits.
|
||||
if (pendingPhoto) {
|
||||
try {
|
||||
await api.uploadProductImage(created.id, pendingPhoto.file);
|
||||
} catch (err) {
|
||||
toast(`Artikel angelegt, aber Foto fehlgeschlagen: ${err.message}`, "warn");
|
||||
}
|
||||
removePendingPhoto();
|
||||
}
|
||||
navigate(`/products/${created.id}`);
|
||||
} else {
|
||||
await api.updateProduct(id, buildPayload());
|
||||
@@ -601,9 +629,13 @@ export default function ProductForm() {
|
||||
<input value={form.brand} onChange={(e) => set("brand", e.target.value)} disabled={readOnly} />
|
||||
</label>
|
||||
</div>
|
||||
{!isNew && (
|
||||
{(!isNew || isAdmin) && (
|
||||
<div className="produkt-foto">
|
||||
<ProduktBild productId={id} alt={form.name} version={bildVersion} onLoaded={setHatBild} />
|
||||
{isNew
|
||||
? pendingPhoto && (
|
||||
<img className="produkt-bild" src={pendingPhoto.url} alt={form.name || ""} />
|
||||
)
|
||||
: <ProduktBild productId={id} alt={form.name} version={bildVersion} onLoaded={setHatBild} />}
|
||||
{isAdmin && (
|
||||
<div className="foto-knoepfe">
|
||||
<label className="btn sm" title="Mit der Kamera aufnehmen">
|
||||
@@ -614,9 +646,13 @@ export default function ProductForm() {
|
||||
Galerie
|
||||
<input hidden type="file" accept="image/*" onChange={onPickPhoto} />
|
||||
</label>
|
||||
{hatBild && (
|
||||
<button type="button" className="btn sm" onClick={removePhoto}>Entfernen</button>
|
||||
)}
|
||||
{isNew
|
||||
? pendingPhoto && (
|
||||
<button type="button" className="btn sm" onClick={removePendingPhoto}>Entfernen</button>
|
||||
)
|
||||
: hatBild && (
|
||||
<button type="button" className="btn sm" onClick={removePhoto}>Entfernen</button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user