import { useEffect, useState } from "react"; import { api } from "../api"; import Icon from "../components/Icon"; import { useSettings } from "../settings"; import { buildUnitOptions, fmt, isExpired, unitShort } from "../units"; export default function CheckOut() { const { formatBestBefore } = useSettings(); const [barcode, setBarcode] = useState(""); const [search, setSearch] = useState(""); const [results, setResults] = useState([]); const [product, setProduct] = useState(null); const [units, setUnits] = useState([]); const [lots, setLots] = useState([]); const [quantity, setQuantity] = useState(""); const [unit, setUnit] = useState(""); const [lotId, setLotId] = useState(""); // "" = automatisch (FEFO) const [error, setError] = useState(null); const [info, setInfo] = useState(null); const [busy, setBusy] = useState(false); useEffect(() => { api.listUnits().then(setUnits).catch(() => {}); }, []); async function selectProduct(p) { setProduct(p); setResults([]); setLotId(""); setQuantity(""); const opts = buildUnitOptions(p, units); // Gibt es ein Gebinde (Glas, Packung, …), ist das die naheliegende Eingabe. setUnit(p.package_size ? "package" : (p.unit_name || (opts[0] && opts[0].value) || "")); try { setLots(await api.listLots(p.id)); } catch { setLots([]); } } async function doLookup() { setError(null); setInfo(null); if (!barcode) return; try { const res = await api.lookup(barcode.trim()); if (res.found && res.existing_product) { await selectProduct(res.existing_product); } else { setError("Kein bekanntes Produkt zu diesem Barcode im Lager."); } } catch (err) { setError(err.message); } } async function doSearch(e) { e.preventDefault(); try { setResults(await api.listProducts(search)); } catch (err) { setError(err.message); } } async function submit(e) { e.preventDefault(); setError(null); setInfo(null); setBusy(true); try { const res = await api.checkOut({ product_id: product.id, quantity: Number(quantity), unit, lot_id: lotId === "" ? null : Number(lotId), }); setInfo( `Ausgelagert (${res.affected_lots.length} Charge(n)). Neuer Bestand: ` + `${fmt(res.product_stock / (product.unit_factor || 1))} ${product.unit_name}` ); setQuantity(""); const fresh = await api.getProduct(product.id); setProduct(fresh); setLots(await api.listLots(fresh.id)); setLotId(""); } catch (err) { setError(err.message); } finally { setBusy(false); } } const unitOpts = product ? buildUnitOptions(product, units) : []; const selectedLot = lots.find((l) => String(l.id) === String(lotId)) || null; const baseShort = product ? unitShort(product.base_unit) : ""; const pkgSize = product?.package_size || 0; const pkgLabel = product?.package_label || "Packung"; // Chargenmenge in der Artikeleinheit (Gebinde), sonst in der Produkteinheit. function lotAmount(q) { if (pkgSize > 0) return `${fmt(q / pkgSize)} ${pkgLabel}`; return `${fmt(q / (product?.unit_factor || 1))} ${product?.unit_name || baseShort}`; } return (