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 DataTable from "../components/DataTable"; import LocationMinStock from "../components/LocationMinStock"; import { fmt } from "../units"; export default function Groups() { const confirm = useConfirm(); const { isAdmin } = useAuth(); const [groups, setGroups] = useState([]); const [units, setUnits] = useState([]); const [locations, setLocations] = 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, ls] = await Promise.all([ api.listGroups(), api.listUnits(), api.listLocations(), ]); setGroups(gs); setUnits(us); setLocations(ls); } 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; const columns = [ { key: "name", header: "Gruppe", grow: true, min: 160, filterText: (g) => g.name, sortValue: (g) => g.name, render: (g) => { const low = g.min_stock != null && g.stock < g.min_stock; return ( {isAdmin ? ( { const v = e.target.value.trim(); if (v && v !== g.name) patch(g, { name: v }); }} /> ) : {g.name}} {low && niedrig} ); } }, { key: "products", header: "Produkte", width: 100, align: "num", sortValue: (g) => g.product_count, render: (g) => {g.product_count} }, { key: "stock", header: "Bestand", width: 130, align: "num", sortValue: (g) => g.stock, render: (g) => `${fmt(g.stock)} ${g.min_stock_unit_name || ""}` }, { key: "min", header: "Mindestbestand", width: 150, sortValue: (g) => g.min_stock ?? -1, render: (g) => (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) : "–")) }, { key: "unit", header: "Einheit", width: 150, filterText: (g) => g.min_stock_unit_name || "", render: (g) => (isAdmin ? ( ) : (g.min_stock_unit_name || "–")) }, { key: "codes", header: "EAN-Codes", width: 130, align: "num", render: (g) => ( ) }, { key: "actions", header: "", label: "Aktionen", fixed: true, width: 56, align: "num", render: (g) => isAdmin && ( ) }, ]; return (
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})` : ""}.