diff --git a/web/src/api.js b/web/src/api.js index aa63329..c04243f 100644 --- a/web/src/api.js +++ b/web/src/api.js @@ -185,9 +185,16 @@ export const api = { updateLot: (id, body) => request(`/lots/${id}`, { method: "PATCH", body }), deleteLot: (id) => request(`/lots/${id}`, { method: "DELETE" }), + // Mindestbestand je Lagerort (ersetzt jeweils die komplette Liste). + setProductLocationMinStock: (id, list) => + request(`/products/${id}/location-min-stock`, { method: "PUT", body: list }), + setGroupLocationMinStock: (id, list) => + request(`/groups/${id}/location-min-stock`, { method: "PUT", body: list }), + // Views shoppingList: () => request("/shopping-list"), groupShoppingList: () => request("/shopping-list/groups"), + shoppingByLocation: () => request("/shopping-list/by-location"), expiring: (days) => request(`/expiring${days != null ? `?days=${days}` : ""}`), listMovements: (limit) => request(`/movements${limit ? `?limit=${limit}` : ""}`), diff --git a/web/src/components/LocationMinStock.jsx b/web/src/components/LocationMinStock.jsx new file mode 100644 index 0000000..f3601ef --- /dev/null +++ b/web/src/components/LocationMinStock.jsx @@ -0,0 +1,85 @@ +import { useState } from "react"; +import Icon from "./Icon"; + +/** + * Editor für Mindestbestände je Lagerort (Bedarfe). Eine Zeile je Ort mit Menge; + * „Bedarfe speichern" ersetzt über onSave die komplette Liste. Menge 0/leer = + * Ort fällt weg. + */ +export default function LocationMinStock({ locations, initial = [], unitLabel = "", onSave, onError }) { + const [rows, setRows] = useState(() => + initial.map((e) => ({ location_id: String(e.location_id), min_stock: String(e.min_stock) })), + ); + const [busy, setBusy] = useState(false); + const [ok, setOk] = useState(false); + + const used = new Set(rows.map((r) => r.location_id)); + const frei = locations.filter((l) => !used.has(String(l.id))); + + function addRow() { + if (!frei.length) return; + setRows([...rows, { location_id: String(frei[0].id), min_stock: "" }]); + setOk(false); + } + function setRow(i, patch) { + setRows(rows.map((r, j) => (j === i ? { ...r, ...patch } : r))); + setOk(false); + } + function removeRow(i) { + setRows(rows.filter((_, j) => j !== i)); + setOk(false); + } + + async function save() { + setBusy(true); + try { + const list = rows + .filter((r) => r.location_id !== "" && Number(r.min_stock) > 0) + .map((r) => ({ location_id: Number(r.location_id), min_stock: Number(r.min_stock) })); + await onSave(list); + setOk(true); + } catch (err) { + onError?.(err.message); + } finally { + setBusy(false); + } + } + + if (!locations.length) { + return
Erst Lagerorte anlegen, dann Bedarfe je Ort möglich.
; + } + + return ( +Kein Bedarf je Lagerort festgelegt.
+ )} + {rows.map((r, i) => ( ++ Bedarf dieser Gruppe je Lagerort (z.B. Ferienhaus, Zuhause), zusätzlich zum + Gesamt-Mindestbestand{selected.min_stock_unit_name ? ` (in ${selected.min_stock_unit_name})` : ""}. +
+