@flowselections/floriday-voorraad 1.0.145 → 1.0.149
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-lib/components/voorraad/ArtikelWizard.d.ts +3 -1
- package/dist-lib/components/voorraad/ArtikelWizard.d.ts.map +1 -1
- package/dist-lib/components/voorraad/ArtikelWizard.js +56 -52
- package/dist-lib/components/voorraad/EditArtikelPage.d.ts.map +1 -1
- package/dist-lib/components/voorraad/EditArtikelPage.js +15 -23
- package/dist-lib/components/voorraad/OrderHistoryCard.d.ts +3 -1
- package/dist-lib/components/voorraad/OrderHistoryCard.d.ts.map +1 -1
- package/dist-lib/components/voorraad/OrderHistoryCard.js +7 -3
- package/dist-lib/components/voorraad/ProductCustomFieldsCard.d.ts +5 -1
- package/dist-lib/components/voorraad/ProductCustomFieldsCard.d.ts.map +1 -1
- package/dist-lib/components/voorraad/ProductCustomFieldsCard.js +37 -18
- package/dist-lib/components/voorraad/ProductSalePriceField.d.ts.map +1 -1
- package/dist-lib/components/voorraad/ProductSalePriceField.js +11 -8
- package/dist-lib/components/voorraad/StepSamenstelling.d.ts.map +1 -1
- package/dist-lib/components/voorraad/StepSamenstelling.js +35 -10
- package/dist-lib/components/voorraad/StockMutationHistoryCard.d.ts +3 -1
- package/dist-lib/components/voorraad/StockMutationHistoryCard.d.ts.map +1 -1
- package/dist-lib/components/voorraad/StockMutationHistoryCard.js +16 -10
- package/dist-lib/components/voorraad/TrayStickerCard.d.ts +5 -1
- package/dist-lib/components/voorraad/TrayStickerCard.d.ts.map +1 -1
- package/dist-lib/components/voorraad/TrayStickerCard.js +64 -66
- package/dist-lib/components/voorraad/ValidationOverviewTable.d.ts +0 -5
- package/dist-lib/components/voorraad/ValidationOverviewTable.d.ts.map +1 -1
- package/dist-lib/components/voorraad/ValidationOverviewTable.js +10 -4
- package/dist-lib/components/voorraad/VoorraadBeheerCard.d.ts +3 -0
- package/dist-lib/components/voorraad/VoorraadBeheerCard.d.ts.map +1 -0
- package/dist-lib/components/voorraad/VoorraadBeheerCard.js +44 -0
- package/dist-lib/components/voorraad/VoorraadPage.d.ts +1 -13
- package/dist-lib/components/voorraad/VoorraadPage.d.ts.map +1 -1
- package/dist-lib/components/voorraad/VoorraadPage.js +102 -140
- package/dist-lib/components/voorraad/VoorraadSturingCard.d.ts +6 -0
- package/dist-lib/components/voorraad/VoorraadSturingCard.d.ts.map +1 -0
- package/dist-lib/components/voorraad/VoorraadSturingCard.js +47 -0
- package/dist-lib/components/voorraad/artikel/ArtikelPagina.d.ts +6 -0
- package/dist-lib/components/voorraad/artikel/ArtikelPagina.d.ts.map +1 -0
- package/dist-lib/components/voorraad/artikel/ArtikelPagina.js +313 -0
- package/dist-lib/components/voorraad/artikel/TwijfelKiezen.d.ts +7 -0
- package/dist-lib/components/voorraad/artikel/TwijfelKiezen.d.ts.map +1 -0
- package/dist-lib/components/voorraad/artikel/TwijfelKiezen.js +54 -0
- package/dist-lib/components/voorraad/artikel/opslaan-context.d.ts +21 -0
- package/dist-lib/components/voorraad/artikel/opslaan-context.d.ts.map +1 -0
- package/dist-lib/components/voorraad/artikel/opslaan-context.js +15 -0
- package/dist-lib/components/voorraad/lijst/ImporteerKnop.d.ts +5 -0
- package/dist-lib/components/voorraad/lijst/ImporteerKnop.d.ts.map +1 -0
- package/dist-lib/components/voorraad/lijst/ImporteerKnop.js +20 -0
- package/dist-lib/components/voorraad/lijst/LijstExportKnop.d.ts +6 -0
- package/dist-lib/components/voorraad/lijst/LijstExportKnop.d.ts.map +1 -0
- package/dist-lib/components/voorraad/lijst/LijstExportKnop.js +43 -0
- package/dist-lib/components/voorraad/lijst/SnelActieDialogen.d.ts +16 -0
- package/dist-lib/components/voorraad/lijst/SnelActieDialogen.d.ts.map +1 -0
- package/dist-lib/components/voorraad/lijst/SnelActieDialogen.js +95 -0
- package/dist-lib/components/voorraad/lijst/VoorraadLijstTabel.d.ts +21 -0
- package/dist-lib/components/voorraad/lijst/VoorraadLijstTabel.d.ts.map +1 -0
- package/dist-lib/components/voorraad/lijst/VoorraadLijstTabel.js +39 -0
- package/dist-lib/hooks/useVoorraadCustomFields.d.ts +2 -1
- package/dist-lib/hooks/useVoorraadCustomFields.d.ts.map +1 -1
- package/dist-lib/hooks/useVoorraadCustomFields.js +8 -4
- package/dist-lib/hooks/useVoorraadLijst.d.ts +21 -0
- package/dist-lib/hooks/useVoorraadLijst.d.ts.map +1 -0
- package/dist-lib/hooks/useVoorraadLijst.js +71 -0
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +4 -0
- package/dist-lib/integrations/supabase/types.d.ts +748 -1
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/artikel-gewijzigd.d.ts +4 -0
- package/dist-lib/lib/artikel-gewijzigd.d.ts.map +1 -0
- package/dist-lib/lib/artikel-gewijzigd.js +7 -0
- package/dist-lib/lib/artikel-pagina.d.ts +68 -0
- package/dist-lib/lib/artikel-pagina.d.ts.map +1 -0
- package/dist-lib/lib/artikel-pagina.js +97 -0
- package/dist-lib/lib/count-stock.d.ts +17 -0
- package/dist-lib/lib/count-stock.d.ts.map +1 -0
- package/dist-lib/lib/count-stock.js +26 -0
- package/dist-lib/lib/floriday-import-validator.d.ts +9 -0
- package/dist-lib/lib/floriday-import-validator.d.ts.map +1 -1
- package/dist-lib/lib/floriday-import-validator.js +13 -0
- package/dist-lib/lib/floriday-versie-ronde.d.ts +59 -0
- package/dist-lib/lib/floriday-versie-ronde.d.ts.map +1 -0
- package/dist-lib/lib/floriday-versie-ronde.functions.d.ts +10 -0
- package/dist-lib/lib/floriday-versie-ronde.functions.d.ts.map +1 -0
- package/dist-lib/lib/floriday-versie-ronde.functions.js +22 -0
- package/dist-lib/lib/floriday-versie-ronde.js +106 -0
- package/dist-lib/lib/pending-photos.d.ts +20 -0
- package/dist-lib/lib/pending-photos.d.ts.map +1 -0
- package/dist-lib/lib/pending-photos.js +90 -0
- package/dist-lib/lib/voorraad-custom-fields.d.ts +16 -1
- package/dist-lib/lib/voorraad-custom-fields.d.ts.map +1 -1
- package/dist-lib/lib/voorraad-custom-fields.js +12 -6
- package/dist-lib/lib/voorraad-lijst.d.ts +92 -0
- package/dist-lib/lib/voorraad-lijst.d.ts.map +1 -0
- package/dist-lib/lib/voorraad-lijst.js +86 -0
- package/dist-lib/server-hooks/floriday-stock-reconcile.d.ts.map +1 -1
- package/dist-lib/server-hooks/floriday-stock-reconcile.js +5 -0
- package/dist-lib/server-hooks/floriday-versieronde.d.ts +2 -0
- package/dist-lib/server-hooks/floriday-versieronde.d.ts.map +1 -0
- package/dist-lib/server-hooks/floriday-versieronde.js +29 -0
- package/dist-lib/server-hooks/guard.js +1 -1
- package/package.json +1 -1
- package/sql/AGENTS.md +6 -0
- package/sql/floriday-voorraad-schema.sql +1355 -22
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { Button, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Textarea, toast, } from "@flowselections/core";
|
|
4
|
+
import { supabase } from "../../../integrations/supabase/client.js";
|
|
5
|
+
import { AFBOEK_REDENEN, afboekFout } from "../../../lib/stock-save.js";
|
|
6
|
+
import { dbFoutTekst } from "../../../lib/db-error-message.js";
|
|
7
|
+
import { aantal } from "../../../lib/voorraad-lijst.js";
|
|
8
|
+
/** Controle vóór "Voorraad aanpassen": aantal ≠ 0, reden verplicht, niet onder 0. */
|
|
9
|
+
export function aanpassenFout(delta, reden, liggend) {
|
|
10
|
+
if (!Number.isInteger(delta) || delta === 0)
|
|
11
|
+
return "Vul een heel aantal in dat niet 0 is (bijv. 10 of -5).";
|
|
12
|
+
if (!reden.trim())
|
|
13
|
+
return "Vul een reden in.";
|
|
14
|
+
if (liggend + delta < 0)
|
|
15
|
+
return `Je kunt niet meer weghalen (${-delta}) dan er ligt (${liggend}).`;
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
/** Directe boeking +/− met reden; los van "Opslaan" zodat een orderafboeking nooit wordt overschreven. */
|
|
19
|
+
export function AanpassenDialog({ rij, onClose, onDone }) {
|
|
20
|
+
const [delta, setDelta] = useState("");
|
|
21
|
+
const [reden, setReden] = useState("");
|
|
22
|
+
const [bezig, setBezig] = useState(false);
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
setDelta("");
|
|
25
|
+
setReden("");
|
|
26
|
+
}, [rij?.id]);
|
|
27
|
+
if (!rij)
|
|
28
|
+
return null;
|
|
29
|
+
const d = Number(delta.replace(",", "."));
|
|
30
|
+
const fout = delta.trim() === "" ? null : aanpassenFout(d, reden || " ", rij.liggend);
|
|
31
|
+
const bevestig = async () => {
|
|
32
|
+
const f = aanpassenFout(d, reden, rij.liggend);
|
|
33
|
+
if (f)
|
|
34
|
+
return toast.error(f);
|
|
35
|
+
setBezig(true);
|
|
36
|
+
try {
|
|
37
|
+
const { error } = await supabase.rpc("voorraad_voorraad_corrigeren", { p_product_id: rij.id, p_delta: d, p_reden: reden.trim() });
|
|
38
|
+
if (error)
|
|
39
|
+
throw error;
|
|
40
|
+
toast.success(`Liggend van ${aantal(rij.liggend)} naar ${aantal(rij.liggend + d)}`);
|
|
41
|
+
onDone();
|
|
42
|
+
onClose();
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
toast.error(`Aanpassen mislukt, niets gewijzigd. ${dbFoutTekst(e, "Opslaan")}`);
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
setBezig(false);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
return (_jsx(Dialog, { open: true, onOpenChange: (o) => !o && onClose(), children: _jsxs(DialogContent, { children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Voorraad aanpassen" }), _jsxs(DialogDescription, { children: [rij.naam, " \u2014 nu liggend ", aantal(rij.liggend), ". Typ een plus- of minaantal; dit wordt direct geboekt."] })] }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "aanpassen-delta", children: "Aantal (+ of \u2212)" }), _jsx(Input, { id: "aanpassen-delta", inputMode: "numeric", autoFocus: true, value: delta, onChange: (e) => setDelta(e.target.value), placeholder: "bijv. 25 of -10" }), delta.trim() !== "" && !fout && Number.isFinite(d) && (_jsxs("p", { className: "text-xs text-muted-foreground", children: ["Wordt liggend ", aantal(rij.liggend + d), "."] })), fout && _jsx("p", { className: "text-xs text-destructive", children: fout })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "aanpassen-reden", children: "Reden" }), _jsx(Textarea, { id: "aanpassen-reden", rows: 2, value: reden, onChange: (e) => setReden(e.target.value), placeholder: "bijv. telling kas 3" })] })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { variant: "outline", onClick: onClose, children: "Annuleren" }), _jsx(Button, { onClick: bevestig, disabled: bezig || !!aanpassenFout(d, reden, rij.liggend), children: "Boeken" })] })] }) }));
|
|
52
|
+
}
|
|
53
|
+
export function AfboekenDialog({ rij, connectionId, onClose, onDone, }) {
|
|
54
|
+
const [hoeveel, setHoeveel] = useState("");
|
|
55
|
+
const [reden, setReden] = useState(null);
|
|
56
|
+
const [notitie, setNotitie] = useState("");
|
|
57
|
+
const [bezig, setBezig] = useState(false);
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
setHoeveel("");
|
|
60
|
+
setReden(null);
|
|
61
|
+
setNotitie("");
|
|
62
|
+
}, [rij?.id]);
|
|
63
|
+
if (!rij)
|
|
64
|
+
return null;
|
|
65
|
+
const n = Number(hoeveel.replace(",", "."));
|
|
66
|
+
const bevestig = async () => {
|
|
67
|
+
const f = afboekFout(n, reden, rij.liggend);
|
|
68
|
+
if (f)
|
|
69
|
+
return toast.error(f);
|
|
70
|
+
if (!rij.voorraad_sleutel)
|
|
71
|
+
return toast.error("Dit artikel heeft nog geen voorraad om af te boeken.");
|
|
72
|
+
setBezig(true);
|
|
73
|
+
try {
|
|
74
|
+
const { error } = await supabase.rpc("voorraad_afboeken", {
|
|
75
|
+
p_connection_id: connectionId,
|
|
76
|
+
p_trade_item_key: rij.voorraad_sleutel,
|
|
77
|
+
p_aantal: n,
|
|
78
|
+
p_reden: reden,
|
|
79
|
+
p_notitie: notitie.trim() || null,
|
|
80
|
+
});
|
|
81
|
+
if (error)
|
|
82
|
+
throw error;
|
|
83
|
+
toast.success(`${aantal(n)} afgeboekt`);
|
|
84
|
+
onDone();
|
|
85
|
+
onClose();
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
toast.error(`Afboeken mislukt, niets gewijzigd. ${dbFoutTekst(e, "Afboeken")}`);
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
setBezig(false);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
return (_jsx(Dialog, { open: true, onOpenChange: (o) => !o && onClose(), children: _jsxs(DialogContent, { children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Afboeken" }), _jsxs(DialogDescription, { children: [rij.naam, " \u2014 haal planten van de liggende voorraad (", aantal(rij.liggend), "). Kies altijd een reden."] })] }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "afboek-aantal", children: "Aantal" }), _jsx(Input, { id: "afboek-aantal", inputMode: "numeric", autoFocus: true, value: hoeveel, onChange: (e) => setHoeveel(e.target.value) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Reden" }), _jsxs(Select, { value: reden ?? undefined, onValueChange: setReden, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: "Kies een reden" }) }), _jsx(SelectContent, { children: AFBOEK_REDENEN.map((r) => (_jsx(SelectItem, { value: r.value, children: r.label }, r.value))) })] })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "afboek-notitie", children: "Notitie (optioneel)" }), _jsx(Textarea, { id: "afboek-notitie", rows: 2, value: notitie, onChange: (e) => setNotitie(e.target.value) })] })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { variant: "outline", onClick: onClose, children: "Annuleren" }), _jsx(Button, { onClick: bevestig, disabled: bezig || !!afboekFout(n, reden, rij.liggend), children: "Afboeken" })] })] }) }));
|
|
95
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type LijstRij, type LijstSort } from "../../../lib/voorraad-lijst.js";
|
|
2
|
+
export type OptioneleKolom = "artikelnummer" | "minimum" | "inkomend" | "prijs";
|
|
3
|
+
export declare const OPTIONELE_KOLOMMEN: Array<{
|
|
4
|
+
key: OptioneleKolom;
|
|
5
|
+
label: string;
|
|
6
|
+
}>;
|
|
7
|
+
export declare function VoorraadLijstTabel({ rijen, loading, sort, oplopend, onSort, kolommen, selected, onToggleSelect, onToggleAll, onAanpassen, onAfboeken, heeftKoppeling, }: {
|
|
8
|
+
heeftKoppeling?: boolean;
|
|
9
|
+
rijen: LijstRij[];
|
|
10
|
+
loading: boolean;
|
|
11
|
+
sort: LijstSort;
|
|
12
|
+
oplopend: boolean;
|
|
13
|
+
onSort: (k: LijstSort) => void;
|
|
14
|
+
kolommen: Set<OptioneleKolom>;
|
|
15
|
+
selected: Set<string>;
|
|
16
|
+
onToggleSelect: (id: string) => void;
|
|
17
|
+
onToggleAll: (ids: string[]) => void;
|
|
18
|
+
onAanpassen: (r: LijstRij) => void;
|
|
19
|
+
onAfboeken: (r: LijstRij) => void;
|
|
20
|
+
}): import("react").JSX.Element;
|
|
21
|
+
//# sourceMappingURL=VoorraadLijstTabel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VoorraadLijstTabel.d.ts","sourceRoot":"","sources":["../../../../src/components/voorraad/lijst/VoorraadLijstTabel.tsx"],"names":[],"mappings":"AAeA,OAAO,EAML,KAAK,QAAQ,EACb,KAAK,SAAS,EAEf,MAAM,6BAA6B,CAAC;AAErC,MAAM,MAAM,cAAc,GAAG,eAAe,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;AAChF,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC;IAAE,GAAG,EAAE,cAAc,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAK5E,CAAC;AA+CF,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,OAAO,EACP,IAAI,EACJ,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,cAAc,EACd,WAAW,EACX,WAAW,EACX,UAAU,EACV,cAAsB,GACvB,EAAE;IACD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,IAAI,CAAC;IAC/B,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IAC9B,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACrC,WAAW,EAAE,CAAC,CAAC,EAAE,QAAQ,KAAK,IAAI,CAAC;IACnC,UAAU,EAAE,CAAC,CAAC,EAAE,QAAQ,KAAK,IAAI,CAAC;CACnC,+BAyFA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Link } from "@tanstack/react-router";
|
|
3
|
+
import { Button, Checkbox } from "@flowselections/core";
|
|
4
|
+
import { ArrowDown, ArrowUp, CheckCircle2, Euro, ExternalLink, Link2Off, Minus, Package, PackageX, SlidersHorizontal, } from "lucide-react";
|
|
5
|
+
import floridayLogo from "../../../assets/floriday-logo.png.asset.json";
|
|
6
|
+
import { aantal, geld, toonFloridayLabel, onderMinimum, STATUS_INFO, } from "../../../lib/voorraad-lijst.js";
|
|
7
|
+
export const OPTIONELE_KOLOMMEN = [
|
|
8
|
+
{ key: "artikelnummer", label: "Artikelnummer" },
|
|
9
|
+
{ key: "minimum", label: "Minimum" },
|
|
10
|
+
{ key: "inkomend", label: "Inkomend" },
|
|
11
|
+
{ key: "prijs", label: "Prijs" },
|
|
12
|
+
];
|
|
13
|
+
function StatusIcoon({ status }) {
|
|
14
|
+
const info = STATUS_INFO[status];
|
|
15
|
+
const titel = info.actie ? `${info.label} — ${info.actie}` : info.label;
|
|
16
|
+
const cls = "h-4 w-4";
|
|
17
|
+
const icon = status === "verpakking" ? _jsx(PackageX, { className: `${cls} text-destructive` }) :
|
|
18
|
+
status === "verwijderd_floriday" ? _jsx(Link2Off, { className: `${cls} text-destructive` }) :
|
|
19
|
+
status === "niet_gekoppeld" ? _jsx(Link2Off, { className: `${cls} text-muted-foreground` }) :
|
|
20
|
+
status === "prijs" ? _jsx(Euro, { className: `${cls} text-destructive` }) :
|
|
21
|
+
status === "gearchiveerd" ? _jsx(Minus, { className: `${cls} text-muted-foreground` }) :
|
|
22
|
+
_jsx(CheckCircle2, { className: `${cls} text-primary` });
|
|
23
|
+
return (_jsxs("span", { title: titel, "aria-label": titel, className: "inline-flex items-center gap-1.5", children: [icon, status !== "ok" && _jsx("span", { className: "text-xs text-muted-foreground hidden xl:inline", children: info.label })] }));
|
|
24
|
+
}
|
|
25
|
+
function Kop({ kolom, label, sort, oplopend, onSort, rechts, }) {
|
|
26
|
+
const actief = sort === kolom;
|
|
27
|
+
return (_jsx("th", { className: `px-3 py-2 font-medium ${rechts ? "text-right" : "text-left"}`, "aria-sort": actief ? (oplopend ? "ascending" : "descending") : "none", children: _jsxs("button", { type: "button", onClick: () => onSort(kolom), className: `inline-flex items-center gap-1 hover:text-foreground ${actief ? "text-foreground" : ""}`, children: [label, actief && (oplopend ? _jsx(ArrowUp, { className: "h-3 w-3" }) : _jsx(ArrowDown, { className: "h-3 w-3" }))] }) }));
|
|
28
|
+
}
|
|
29
|
+
export function VoorraadLijstTabel({ rijen, loading, sort, oplopend, onSort, kolommen, selected, onToggleSelect, onToggleAll, onAanpassen, onAfboeken, heeftKoppeling = false, }) {
|
|
30
|
+
const ids = rijen.map((r) => r.id);
|
|
31
|
+
const allesGekozen = ids.length > 0 && ids.every((id) => selected.has(id));
|
|
32
|
+
const k = (s) => kolommen.has(s);
|
|
33
|
+
return (_jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { className: "border-b bg-muted/40 text-xs text-muted-foreground", children: _jsxs("tr", { children: [_jsx("th", { className: "w-10 px-3 py-2", children: _jsx(Checkbox, { checked: allesGekozen, onCheckedChange: () => onToggleAll(ids), "aria-label": "Alles op deze pagina kiezen" }) }), _jsx(Kop, { kolom: "naam", label: "Artikel", sort: sort, oplopend: oplopend, onSort: onSort }), k("artikelnummer") && _jsx(Kop, { kolom: "artikelnummer", label: "Artikelnummer", sort: sort, oplopend: oplopend, onSort: onSort }), _jsx(Kop, { kolom: "liggend", label: "Liggend", sort: sort, oplopend: oplopend, onSort: onSort, rechts: true }), _jsx(Kop, { kolom: "gereserveerd", label: "Gereserveerd", sort: sort, oplopend: oplopend, onSort: onSort, rechts: true }), _jsx(Kop, { kolom: "vrij", label: "Vrij", sort: sort, oplopend: oplopend, onSort: onSort, rechts: true }), k("minimum") && _jsx("th", { className: "px-3 py-2 text-right font-medium", children: "Minimum" }), k("inkomend") && _jsx(Kop, { kolom: "inkomend", label: "Inkomend", sort: sort, oplopend: oplopend, onSort: onSort, rechts: true }), k("prijs") && _jsx(Kop, { kolom: "prijs", label: "Prijs", sort: sort, oplopend: oplopend, onSort: onSort, rechts: true }), _jsx("th", { className: "px-3 py-2 text-left font-medium", children: "Status" }), _jsx("th", { className: "px-3 py-2 text-right font-medium", children: "Acties" })] }) }), _jsxs("tbody", { children: [loading && rijen.length === 0 &&
|
|
34
|
+
Array.from({ length: 6 }).map((_, i) => (_jsx("tr", { className: "border-b", children: _jsx("td", { colSpan: 12, className: "px-3 py-3", children: _jsx("div", { className: "h-6 animate-pulse rounded bg-muted" }) }) }, `s${i}`))), !loading && rijen.length === 0 && (_jsx("tr", { children: _jsx("td", { colSpan: 12, className: "px-3 py-10 text-center text-muted-foreground", children: "Geen artikelen gevonden." }) })), rijen.map((r) => {
|
|
35
|
+
const rood = onderMinimum(r);
|
|
36
|
+
const gearchiveerd = !!r.gearchiveerd_at;
|
|
37
|
+
return (_jsxs("tr", { className: `border-b hover:bg-muted/30 ${loading ? "opacity-60" : ""}`, children: [_jsx("td", { className: "px-3 py-2", children: _jsx(Checkbox, { checked: selected.has(r.id), onCheckedChange: () => onToggleSelect(r.id), "aria-label": `Kies ${r.naam}` }) }), _jsx("td", { className: "px-3 py-2", children: _jsxs(Link, { to: "/voorraad/$id", params: { id: r.id }, className: "flex items-center gap-3 min-w-0", children: [r.foto ? (_jsx("img", { src: r.foto, alt: "", loading: "lazy", className: "h-9 w-9 shrink-0 rounded object-cover bg-muted" })) : (_jsx("span", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded bg-muted", children: _jsx(Package, { className: "h-4 w-4 text-muted-foreground" }) })), _jsxs("span", { className: "min-w-0", children: [_jsxs("span", { className: "flex items-center gap-1.5 font-medium text-foreground truncate", children: [r.naam, toonFloridayLabel(r, heeftKoppeling) && _jsx("img", { src: floridayLogo.url, alt: "Floriday", title: "Gekoppeld aan Floriday", className: "h-3.5 w-3.5 shrink-0" })] }), _jsxs("span", { className: "block text-xs text-muted-foreground truncate", children: [r.artikelnummer || "Geen artikelnummer", r.soort === "SET" ? " · Samenstelling" : r.soort === "GROUP" ? " · Productgroep" : ""] })] })] }) }), k("artikelnummer") && _jsx("td", { className: "px-3 py-2 text-muted-foreground", children: r.artikelnummer ?? "—" }), _jsx("td", { className: "px-3 py-2 text-right tabular-nums", children: aantal(r.liggend) }), _jsx("td", { className: "px-3 py-2 text-right tabular-nums text-muted-foreground", children: aantal(r.gereserveerd) }), _jsx("td", { className: `px-3 py-2 text-right tabular-nums font-medium ${rood ? "text-destructive" : ""}`, title: rood ? `Onder minimum (${aantal(r.minimum)})` : undefined, children: aantal(r.vrij) }), k("minimum") && _jsx("td", { className: "px-3 py-2 text-right tabular-nums text-muted-foreground", children: aantal(r.minimum) }), k("inkomend") && _jsx("td", { className: "px-3 py-2 text-right tabular-nums text-muted-foreground", children: aantal(r.inkomend) }), k("prijs") && _jsx("td", { className: "px-3 py-2 text-right tabular-nums", children: geld(r.prijs) }), _jsx("td", { className: "px-3 py-2", children: _jsx(StatusIcoon, { status: r.status }) }), _jsx("td", { className: "px-3 py-2", children: _jsxs("div", { className: "flex justify-end gap-1", children: [_jsx(Button, { size: "sm", variant: "ghost", title: "Voorraad aanpassen (+/\u2212)", "aria-label": "Voorraad aanpassen", disabled: gearchiveerd || r.soort === "GROUP", onClick: () => onAanpassen(r), children: _jsx(SlidersHorizontal, { className: "h-4 w-4" }) }), _jsx(Button, { size: "sm", variant: "ghost", title: r.voorraad_sleutel ? "Afboeken" : "Nog geen voorraad om af te boeken", "aria-label": "Afboeken", disabled: gearchiveerd || !r.voorraad_sleutel || r.liggend <= 0, onClick: () => onAfboeken(r), children: _jsx(Minus, { className: "h-4 w-4" }) }), _jsx(Button, { asChild: true, size: "sm", variant: "ghost", title: "Openen", "aria-label": "Openen", children: _jsx(Link, { to: "/voorraad/$id", params: { id: r.id }, children: _jsx(ExternalLink, { className: "h-4 w-4" }) }) })] }) })] }, r.id));
|
|
38
|
+
})] })] }));
|
|
39
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type VoorraadCustomField } from "../lib/voorraad-custom-fields.js";
|
|
2
2
|
/** Laadt de door de gebruiker gedefinieerde voorraadvelden. */
|
|
3
|
-
|
|
3
|
+
/** `begin`: velden die al bekend zijn (uit voorraad_artikel_detail); dan geen eigen aanvraag. */
|
|
4
|
+
export declare function useVoorraadCustomFields(begin?: VoorraadCustomField[]): {
|
|
4
5
|
fields: VoorraadCustomField[];
|
|
5
6
|
loading: boolean;
|
|
6
7
|
error: string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useVoorraadCustomFields.d.ts","sourceRoot":"","sources":["../../src/hooks/useVoorraadCustomFields.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,+BAA+B,CAAC;AAEvC,+DAA+D;AAC/D,wBAAgB,uBAAuB;;;;;
|
|
1
|
+
{"version":3,"file":"useVoorraadCustomFields.d.ts","sourceRoot":"","sources":["../../src/hooks/useVoorraadCustomFields.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,+BAA+B,CAAC;AAEvC,+DAA+D;AAC/D,iGAAiG;AACjG,wBAAgB,uBAAuB,CAAC,KAAK,CAAC,EAAE,mBAAmB,EAAE;;;;;EAyBpE"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { useCallback, useEffect, useState } from "react";
|
|
2
2
|
import { fetchVoorraadCustomFields, } from "../lib/voorraad-custom-fields.js";
|
|
3
3
|
/** Laadt de door de gebruiker gedefinieerde voorraadvelden. */
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const [
|
|
4
|
+
/** `begin`: velden die al bekend zijn (uit voorraad_artikel_detail); dan geen eigen aanvraag. */
|
|
5
|
+
export function useVoorraadCustomFields(begin) {
|
|
6
|
+
const [fields, setFields] = useState(begin ?? []);
|
|
7
|
+
const [loading, setLoading] = useState(!begin);
|
|
7
8
|
const [error, setError] = useState(null);
|
|
8
9
|
const reload = useCallback(async () => {
|
|
9
10
|
setLoading(true);
|
|
@@ -19,8 +20,11 @@ export function useVoorraadCustomFields() {
|
|
|
19
20
|
setLoading(false);
|
|
20
21
|
}
|
|
21
22
|
}, []);
|
|
23
|
+
const heeftBegin = Boolean(begin);
|
|
22
24
|
useEffect(() => {
|
|
25
|
+
if (heeftBegin)
|
|
26
|
+
return;
|
|
23
27
|
void reload();
|
|
24
|
-
}, [reload]);
|
|
28
|
+
}, [reload, heeftBegin]);
|
|
25
29
|
return { fields, loading, error, reload };
|
|
26
30
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { LijstAntwoord, LijstFilter, LijstSort } from "../lib/voorraad-lijst.js";
|
|
2
|
+
export interface LijstVraag {
|
|
3
|
+
zoek: string;
|
|
4
|
+
filter: LijstFilter;
|
|
5
|
+
sort: LijstSort;
|
|
6
|
+
oplopend: boolean;
|
|
7
|
+
pagina: number;
|
|
8
|
+
grootte: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function haalVoorraadLijst(v: LijstVraag): Promise<LijstAntwoord>;
|
|
11
|
+
/**
|
|
12
|
+
* Eén aanvraag per wijziging van zoeken/filter/sortering/pagina. Live-updates
|
|
13
|
+
* gebundeld: één kanaal, hooguit één herlaadactie per 3 s, niet in een verborgen tabblad.
|
|
14
|
+
*/
|
|
15
|
+
export declare function useVoorraadLijst(vraag: LijstVraag): {
|
|
16
|
+
data: LijstAntwoord | null;
|
|
17
|
+
loading: boolean;
|
|
18
|
+
error: string | null;
|
|
19
|
+
reload: () => Promise<void>;
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=useVoorraadLijst.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useVoorraadLijst.d.ts","sourceRoot":"","sources":["../../src/hooks/useVoorraadLijst.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEnF,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,iBAAiB,CAAC,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,CAW7E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU;;;;;EAgDjD"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
import { supabase } from "../integrations/supabase/client.js";
|
|
3
|
+
import { createBundler, pageRequestGuard } from "../lib/request-guard.js";
|
|
4
|
+
export async function haalVoorraadLijst(v) {
|
|
5
|
+
const { data, error } = await supabase.rpc("voorraad_lijst", {
|
|
6
|
+
p_zoek: v.zoek.trim() || null,
|
|
7
|
+
p_filter: v.filter,
|
|
8
|
+
p_sort: v.sort,
|
|
9
|
+
p_oplopend: v.oplopend,
|
|
10
|
+
p_pagina: v.pagina,
|
|
11
|
+
p_grootte: v.grootte,
|
|
12
|
+
});
|
|
13
|
+
if (error)
|
|
14
|
+
throw new Error(error.message);
|
|
15
|
+
return data;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Eén aanvraag per wijziging van zoeken/filter/sortering/pagina. Live-updates
|
|
19
|
+
* gebundeld: één kanaal, hooguit één herlaadactie per 3 s, niet in een verborgen tabblad.
|
|
20
|
+
*/
|
|
21
|
+
export function useVoorraadLijst(vraag) {
|
|
22
|
+
const [data, setData] = useState(null);
|
|
23
|
+
const [loading, setLoading] = useState(true);
|
|
24
|
+
const [error, setError] = useState(null);
|
|
25
|
+
const vraagRef = useRef(vraag);
|
|
26
|
+
vraagRef.current = vraag;
|
|
27
|
+
const seq = useRef(0);
|
|
28
|
+
const laad = useCallback(async () => {
|
|
29
|
+
if (!pageRequestGuard.allow("voorraad_lijst"))
|
|
30
|
+
return;
|
|
31
|
+
const mijn = ++seq.current;
|
|
32
|
+
setLoading(true);
|
|
33
|
+
try {
|
|
34
|
+
const a = await haalVoorraadLijst(vraagRef.current);
|
|
35
|
+
if (mijn !== seq.current)
|
|
36
|
+
return;
|
|
37
|
+
setData(a);
|
|
38
|
+
setError(null);
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
if (mijn !== seq.current)
|
|
42
|
+
return;
|
|
43
|
+
setError(e.message);
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
if (mijn === seq.current)
|
|
47
|
+
setLoading(false);
|
|
48
|
+
}
|
|
49
|
+
}, []);
|
|
50
|
+
const key = `${vraag.zoek}|${vraag.filter}|${vraag.sort}|${vraag.oplopend}|${vraag.pagina}|${vraag.grootte}`;
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
void laad();
|
|
53
|
+
}, [key, laad]);
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
const bundler = createBundler(() => void laad(), 3000);
|
|
56
|
+
const trigger = () => bundler.trigger();
|
|
57
|
+
const channel = supabase
|
|
58
|
+
.channel(`voorraad-lijst-${Math.random().toString(36).slice(2)}`)
|
|
59
|
+
.on("postgres_changes", { event: "*", schema: "public", table: "trade_item_stock" }, trigger)
|
|
60
|
+
.on("postgres_changes", { event: "*", schema: "public", table: "products" }, trigger)
|
|
61
|
+
.subscribe();
|
|
62
|
+
const onVis = () => bundler.flushIfPending();
|
|
63
|
+
document.addEventListener("visibilitychange", onVis);
|
|
64
|
+
return () => {
|
|
65
|
+
bundler.cancel();
|
|
66
|
+
document.removeEventListener("visibilitychange", onVis);
|
|
67
|
+
supabase.removeChannel(channel);
|
|
68
|
+
};
|
|
69
|
+
}, [laad]);
|
|
70
|
+
return { data, loading, error, reload: laad };
|
|
71
|
+
}
|
package/dist-lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AAMpE,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AAExE,eAAO,MAAM,sBAAsB,EAAE,UAkBpC,CAAC"}
|
package/dist-lib/index.js
CHANGED
|
@@ -9,6 +9,8 @@ export { EditArtikelPage } from './components/voorraad/EditArtikelPage.js';
|
|
|
9
9
|
export { ValidationPage } from './components/voorraad/ValidationPage.js';
|
|
10
10
|
export { ArtikelWizard } from './components/voorraad/ArtikelWizard.js';
|
|
11
11
|
import { VoorraadVeldenCard } from './components/voorraad/VoorraadVeldenCard.js';
|
|
12
|
+
import { VoorraadSturingCard } from './components/voorraad/VoorraadSturingCard.js';
|
|
13
|
+
import { VoorraadBeheerCard } from './components/voorraad/VoorraadBeheerCard.js';
|
|
12
14
|
export { FustenPage } from "./components/voorraad/FustenPage.js";
|
|
13
15
|
export { PublicatiesPage } from "./components/voorraad/PublicatiesPage.js";
|
|
14
16
|
export const floridayVoorraadModule = {
|
|
@@ -25,6 +27,8 @@ export const floridayVoorraadModule = {
|
|
|
25
27
|
],
|
|
26
28
|
},
|
|
27
29
|
settingsCards: [
|
|
30
|
+
{ component: VoorraadSturingCard, order: 45 },
|
|
28
31
|
{ component: VoorraadVeldenCard, order: 50 },
|
|
32
|
+
{ component: VoorraadBeheerCard, order: 90 },
|
|
29
33
|
],
|
|
30
34
|
};
|