import { useEffect, useState } from "react"; import { api } from "../api"; import { useConfirm } from "../confirm"; import { useAuth } from "../auth"; import BarcodeList from "../components/BarcodeList"; import Icon from "../components/Icon"; import { fmt } from "../units"; export default function Groups() { const confirm = useConfirm(); const { isAdmin } = useAuth(); const [groups, setGroups] = useState([]); const [units, setUnits] = useState([]); const [form, setForm] = useState({ name: "", min_stock: "", min_stock_unit_id: "" }); const [selectedId, setSelectedId] = useState(null); const [error, setError] = useState(null); async function load() { try { const [gs, us] = await Promise.all([api.listGroups(), api.listUnits()]); setGroups(gs); setUnits(us); } catch (err) { setError(err.message); } } useEffect(() => { load(); }, []); async function add(e) { e.preventDefault(); setError(null); try { await api.createGroup({ name: form.name, min_stock: form.min_stock === "" ? null : Number(form.min_stock), min_stock_unit_id: form.min_stock_unit_id === "" ? null : Number(form.min_stock_unit_id), }); setForm({ name: "", min_stock: "", min_stock_unit_id: form.min_stock_unit_id }); load(); } catch (err) { setError(err.message); } } async function patch(group, body) { setError(null); try { await api.updateGroup(group.id, body); load(); } catch (err) { setError(err.message); } } async function remove(group) { const ok = await confirm({ title: `Gruppe „${group.name}“ löschen?`, message: "Die Produkte bleiben erhalten, verlieren aber ihre Zuordnung zu dieser Gruppe.", confirmLabel: "Löschen", danger: true, }); if (!ok) return; try { await api.deleteGroup(group.id); if (selectedId === group.id) setSelectedId(null); load(); } catch (err) { setError(err.message); } } const selected = groups.find((g) => g.id === selectedId) || null; return (

Gruppen

Bestände mehrerer Marken zusammenzählen – z.B. Mehl von Rewe, Aldi und Migros als „5 kg Mehl“. Mit gemeinsamem Mindestbestand; die EAN-Codes der zugeordneten Artikel erscheinen automatisch hier.
{error &&
{error}
}
{groups.map((g) => { const low = g.min_stock != null && g.stock < g.min_stock; return ( ); })} {groups.length === 0 && }
Gruppe Produkte Bestand Mindestbestand Einheit EAN-Codes
{isAdmin ? ( { const v = e.target.value.trim(); if (v && v !== g.name) patch(g, { name: v }); }} /> ) : {g.name}} {low && niedrig} {g.product_count} {fmt(g.stock)} {g.min_stock_unit_name || ""} {isAdmin ? ( { const v = e.target.value; if (v !== String(g.min_stock ?? "")) { patch(g, { min_stock: v === "" ? null : Number(v) }); } }} /> ) : (g.min_stock != null ? fmt(g.min_stock) : "–")} {isAdmin ? ( ) : (g.min_stock_unit_name || "–")} {isAdmin && ( )}
Noch keine Gruppen.
{selected && (

EAN-Codes der Gruppe: {selected.name}

{ try { await api.addGroupBarcode(selected.id, body); await load(); } catch (err) { setError(err.message); } }} onEditNote={async (code, note) => { try { await api.updateGroupBarcodeNote(selected.id, code, { note }); await load(); } catch (err) { setError(err.message); } }} onDelete={async (code) => { try { await api.deleteGroupBarcode(selected.id, code); await load(); } catch (err) { setError(err.message); } }} />
)} {isAdmin && (

Neue Gruppe

Der Bestand der Gruppe summiert nur Produkte, die zur gewählten Einheit passen. Namen lassen sich in der Tabelle direkt ändern.

)}
); }