@flowselections/logistiek-engine 1.0.1
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/README.md +24 -0
- package/dist-lib/_core-safelist.d.ts +2 -0
- package/dist-lib/_core-safelist.d.ts.map +1 -0
- package/dist-lib/_core-safelist.js +15 -0
- package/dist-lib/components/BeladingIndelingCard.d.ts +2 -0
- package/dist-lib/components/BeladingIndelingCard.d.ts.map +1 -0
- package/dist-lib/components/BeladingIndelingCard.js +77 -0
- package/dist-lib/components/BufferDebugCard.d.ts +19 -0
- package/dist-lib/components/BufferDebugCard.d.ts.map +1 -0
- package/dist-lib/components/BufferDebugCard.js +69 -0
- package/dist-lib/components/CapaciteitMeldingenCard.d.ts +2 -0
- package/dist-lib/components/CapaciteitMeldingenCard.d.ts.map +1 -0
- package/dist-lib/components/CapaciteitMeldingenCard.js +40 -0
- package/dist-lib/components/LadingdragersPage.d.ts +2 -0
- package/dist-lib/components/LadingdragersPage.d.ts.map +1 -0
- package/dist-lib/components/LadingdragersPage.js +102 -0
- package/dist-lib/components/LogistiekEngineLogo.d.ts +6 -0
- package/dist-lib/components/LogistiekEngineLogo.d.ts.map +1 -0
- package/dist-lib/components/LogistiekEngineLogo.js +4 -0
- package/dist-lib/components/LogistiekEnginePage.d.ts +2 -0
- package/dist-lib/components/LogistiekEnginePage.d.ts.map +1 -0
- package/dist-lib/components/LogistiekEnginePage.js +53 -0
- package/dist-lib/components/ModulePromptsPage.d.ts +2 -0
- package/dist-lib/components/ModulePromptsPage.d.ts.map +1 -0
- package/dist-lib/components/ModulePromptsPage.js +58 -0
- package/dist-lib/components/RegiePage.d.ts +2 -0
- package/dist-lib/components/RegiePage.d.ts.map +1 -0
- package/dist-lib/components/RegiePage.js +82 -0
- package/dist-lib/components/RuleEnginePage.d.ts +7 -0
- package/dist-lib/components/RuleEnginePage.d.ts.map +1 -0
- package/dist-lib/components/RuleEnginePage.js +114 -0
- package/dist-lib/components/StrategieDialog.d.ts +11 -0
- package/dist-lib/components/StrategieDialog.d.ts.map +1 -0
- package/dist-lib/components/StrategieDialog.js +38 -0
- package/dist-lib/components/VertragingMeldingenCard.d.ts +2 -0
- package/dist-lib/components/VertragingMeldingenCard.d.ts.map +1 -0
- package/dist-lib/components/VertragingMeldingenCard.js +32 -0
- package/dist-lib/components/VoorraadMeldingenCard.d.ts +2 -0
- package/dist-lib/components/VoorraadMeldingenCard.d.ts.map +1 -0
- package/dist-lib/components/VoorraadMeldingenCard.js +26 -0
- package/dist-lib/components/rule-engine/CollapsibleGroup.d.ts +12 -0
- package/dist-lib/components/rule-engine/CollapsibleGroup.d.ts.map +1 -0
- package/dist-lib/components/rule-engine/CollapsibleGroup.js +11 -0
- package/dist-lib/components/rule-engine/ConditionsEditor.d.ts +8 -0
- package/dist-lib/components/rule-engine/ConditionsEditor.d.ts.map +1 -0
- package/dist-lib/components/rule-engine/ConditionsEditor.js +31 -0
- package/dist-lib/components/rule-engine/FieldHelp.d.ts +14 -0
- package/dist-lib/components/rule-engine/FieldHelp.d.ts.map +1 -0
- package/dist-lib/components/rule-engine/FieldHelp.js +18 -0
- package/dist-lib/components/rule-engine/FloridayConnectionBanner.d.ts +2 -0
- package/dist-lib/components/rule-engine/FloridayConnectionBanner.d.ts.map +1 -0
- package/dist-lib/components/rule-engine/FloridayConnectionBanner.js +41 -0
- package/dist-lib/components/rule-engine/ImpactPanel.d.ts +5 -0
- package/dist-lib/components/rule-engine/ImpactPanel.d.ts.map +1 -0
- package/dist-lib/components/rule-engine/ImpactPanel.js +25 -0
- package/dist-lib/components/rule-engine/RuleFieldInput.d.ts +9 -0
- package/dist-lib/components/rule-engine/RuleFieldInput.d.ts.map +1 -0
- package/dist-lib/components/rule-engine/RuleFieldInput.js +80 -0
- package/dist-lib/components/rule-engine/VersionsPanel.d.ts +10 -0
- package/dist-lib/components/rule-engine/VersionsPanel.d.ts.map +1 -0
- package/dist-lib/components/rule-engine/VersionsPanel.js +16 -0
- package/dist-lib/components/settings/LogistiekEngineSettingsCard.d.ts +2 -0
- package/dist-lib/components/settings/LogistiekEngineSettingsCard.d.ts.map +1 -0
- package/dist-lib/components/settings/LogistiekEngineSettingsCard.js +22 -0
- package/dist-lib/hooks/useCapaciteitMeldingen.d.ts +20 -0
- package/dist-lib/hooks/useCapaciteitMeldingen.d.ts.map +1 -0
- package/dist-lib/hooks/useCapaciteitMeldingen.js +46 -0
- package/dist-lib/hooks/useDocumentLayouts.d.ts +13 -0
- package/dist-lib/hooks/useDocumentLayouts.d.ts.map +1 -0
- package/dist-lib/hooks/useDocumentLayouts.js +54 -0
- package/dist-lib/hooks/useLadingdragers.d.ts +16 -0
- package/dist-lib/hooks/useLadingdragers.d.ts.map +1 -0
- package/dist-lib/hooks/useLadingdragers.js +86 -0
- package/dist-lib/hooks/useLogistiekStrategieen.d.ts +29 -0
- package/dist-lib/hooks/useLogistiekStrategieen.d.ts.map +1 -0
- package/dist-lib/hooks/useLogistiekStrategieen.js +111 -0
- package/dist-lib/hooks/useLogistiekTaken.d.ts +89 -0
- package/dist-lib/hooks/useLogistiekTaken.d.ts.map +1 -0
- package/dist-lib/hooks/useLogistiekTaken.js +314 -0
- package/dist-lib/hooks/usePickstations.d.ts +10 -0
- package/dist-lib/hooks/usePickstations.d.ts.map +1 -0
- package/dist-lib/hooks/usePickstations.js +51 -0
- package/dist-lib/hooks/useRecalcJob.d.ts +24 -0
- package/dist-lib/hooks/useRecalcJob.d.ts.map +1 -0
- package/dist-lib/hooks/useRecalcJob.js +83 -0
- package/dist-lib/hooks/useRuleEngine.d.ts +48 -0
- package/dist-lib/hooks/useRuleEngine.d.ts.map +1 -0
- package/dist-lib/hooks/useRuleEngine.js +222 -0
- package/dist-lib/hooks/useVertragingMeldingen.d.ts +29 -0
- package/dist-lib/hooks/useVertragingMeldingen.d.ts.map +1 -0
- package/dist-lib/hooks/useVertragingMeldingen.js +68 -0
- package/dist-lib/hooks/useVoorraadMeldingen.d.ts +30 -0
- package/dist-lib/hooks/useVoorraadMeldingen.d.ts.map +1 -0
- package/dist-lib/hooks/useVoorraadMeldingen.js +70 -0
- package/dist-lib/index.d.ts +36 -0
- package/dist-lib/index.d.ts.map +1 -0
- package/dist-lib/index.js +52 -0
- package/dist-lib/integrations/supabase/auth-attacher.d.ts +2 -0
- package/dist-lib/integrations/supabase/auth-attacher.d.ts.map +1 -0
- package/dist-lib/integrations/supabase/auth-attacher.js +12 -0
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +19781 -0
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -0
- package/dist-lib/integrations/supabase/auth-middleware.js +52 -0
- package/dist-lib/integrations/supabase/client.d.ts +19777 -0
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -0
- package/dist-lib/integrations/supabase/client.js +13 -0
- package/dist-lib/integrations/supabase/client.server.d.ts +19777 -0
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -0
- package/dist-lib/integrations/supabase/client.server.js +30 -0
- package/dist-lib/integrations/supabase/types.d.ts +20355 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -0
- package/dist-lib/integrations/supabase/types.js +78 -0
- package/dist-lib/lib/bufferMatching.d.ts +26 -0
- package/dist-lib/lib/bufferMatching.d.ts.map +1 -0
- package/dist-lib/lib/bufferMatching.js +73 -0
- package/dist-lib/lib/bulkLoadCarrierPlanning.server.d.ts +23 -0
- package/dist-lib/lib/bulkLoadCarrierPlanning.server.d.ts.map +1 -0
- package/dist-lib/lib/bulkLoadCarrierPlanning.server.js +126 -0
- package/dist-lib/lib/floridayDocuments.functions.d.ts +59415 -0
- package/dist-lib/lib/floridayDocuments.functions.d.ts.map +1 -0
- package/dist-lib/lib/floridayDocuments.functions.js +68 -0
- package/dist-lib/lib/floridayDocuments.server.d.ts +51 -0
- package/dist-lib/lib/floridayDocuments.server.d.ts.map +1 -0
- package/dist-lib/lib/floridayDocuments.server.js +109 -0
- package/dist-lib/lib/loadCarrierPlanner.d.ts +71 -0
- package/dist-lib/lib/loadCarrierPlanner.d.ts.map +1 -0
- package/dist-lib/lib/loadCarrierPlanner.js +374 -0
- package/dist-lib/lib/loadCarrierPlanning.functions.d.ts +98984 -0
- package/dist-lib/lib/loadCarrierPlanning.functions.d.ts.map +1 -0
- package/dist-lib/lib/loadCarrierPlanning.functions.js +106 -0
- package/dist-lib/lib/loadCarrierPlanning.server.d.ts +46 -0
- package/dist-lib/lib/loadCarrierPlanning.server.d.ts.map +1 -0
- package/dist-lib/lib/loadCarrierPlanning.server.js +515 -0
- package/dist-lib/lib/loadCarrierTaskSync.server.d.ts +3 -0
- package/dist-lib/lib/loadCarrierTaskSync.server.d.ts.map +1 -0
- package/dist-lib/lib/loadCarrierTaskSync.server.js +56 -0
- package/dist-lib/lib/loadCarrierTypes.d.ts +19 -0
- package/dist-lib/lib/loadCarrierTypes.d.ts.map +1 -0
- package/dist-lib/lib/loadCarrierTypes.js +41 -0
- package/dist-lib/lib/logisticsPlanner.d.ts +56 -0
- package/dist-lib/lib/logisticsPlanner.d.ts.map +1 -0
- package/dist-lib/lib/logisticsPlanner.js +273 -0
- package/dist-lib/lib/logisticsRecalcJob.functions.d.ts +39575 -0
- package/dist-lib/lib/logisticsRecalcJob.functions.d.ts.map +1 -0
- package/dist-lib/lib/logisticsRecalcJob.functions.js +30 -0
- package/dist-lib/lib/logisticsRecalcJob.server.d.ts +32 -0
- package/dist-lib/lib/logisticsRecalcJob.server.d.ts.map +1 -0
- package/dist-lib/lib/logisticsRecalcJob.server.js +116 -0
- package/dist-lib/lib/logisticsRecalculate.functions.d.ts +19792 -0
- package/dist-lib/lib/logisticsRecalculate.functions.d.ts.map +1 -0
- package/dist-lib/lib/logisticsRecalculate.functions.js +35 -0
- package/dist-lib/lib/logisticsTasks.d.ts +23 -0
- package/dist-lib/lib/logisticsTasks.d.ts.map +1 -0
- package/dist-lib/lib/logisticsTasks.js +92 -0
- package/dist-lib/lib/modulePrompts.d.ts +31 -0
- package/dist-lib/lib/modulePrompts.d.ts.map +1 -0
- package/dist-lib/lib/modulePrompts.js +1195 -0
- package/dist-lib/lib/ruleEngineImpact.d.ts +27 -0
- package/dist-lib/lib/ruleEngineImpact.d.ts.map +1 -0
- package/dist-lib/lib/ruleEngineImpact.js +257 -0
- package/dist-lib/lib/ruleEngineSchema.d.ts +69 -0
- package/dist-lib/lib/ruleEngineSchema.d.ts.map +1 -0
- package/dist-lib/lib/ruleEngineSchema.js +899 -0
- package/dist-lib/lib/ruleEngineWizard.d.ts +17 -0
- package/dist-lib/lib/ruleEngineWizard.d.ts.map +1 -0
- package/dist-lib/lib/ruleEngineWizard.js +204 -0
- package/dist-lib/lib/utils.d.ts +3 -0
- package/dist-lib/lib/utils.d.ts.map +1 -0
- package/dist-lib/lib/utils.js +5 -0
- package/dist-lib/lib/validationSchemas.d.ts +15 -0
- package/dist-lib/lib/validationSchemas.d.ts.map +1 -0
- package/dist-lib/lib/validationSchemas.js +25 -0
- package/dist-lib/styles.css +1 -0
- package/package.json +113 -0
- package/public/logo.png +0 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RuleField } from "../../lib/ruleEngineSchema";
|
|
2
|
+
interface Props {
|
|
3
|
+
field: RuleField;
|
|
4
|
+
value: unknown;
|
|
5
|
+
onChange: (value: unknown) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function RuleFieldInput({ field, value, onChange }: Props): import("react").JSX.Element;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=RuleFieldInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RuleFieldInput.d.ts","sourceRoot":"","sources":["../../../src/components/rule-engine/RuleFieldInput.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAM3E,UAAU,KAAK;IACb,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC;AAED,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,KAAK,+BAyP/D"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// ============================================================================
|
|
3
|
+
// src/components/rule-engine/RuleFieldInput.tsx — rendert één schemaveld
|
|
4
|
+
// ============================================================================
|
|
5
|
+
// De uitleg staat niet meer onder het veld maar achter het vraagteken naast
|
|
6
|
+
// het label, zodat het scherm rustig blijft.
|
|
7
|
+
// ============================================================================
|
|
8
|
+
import { Input, Label, Switch, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Textarea, } from "@flowselections/core";
|
|
9
|
+
import { fieldHelp } from "../../lib/ruleEngineWizard";
|
|
10
|
+
import { FieldHelp, FieldLabel } from "./FieldHelp";
|
|
11
|
+
import { usePickstations } from "../../hooks/usePickstations";
|
|
12
|
+
import { useDocumentLayouts } from "../../hooks/useDocumentLayouts";
|
|
13
|
+
export function RuleFieldInput({ field, value, onChange }) {
|
|
14
|
+
const { stations, types, loading } = usePickstations();
|
|
15
|
+
const { layouts: matching, allLayouts, loading: layoutsLoading } = useDocumentLayouts(field.layoutTypes);
|
|
16
|
+
const help = fieldHelp(field);
|
|
17
|
+
if (field.type === "layout") {
|
|
18
|
+
const others = allLayouts.filter((l) => !matching.some((m) => m.id === l.id));
|
|
19
|
+
const options = [...matching, ...others];
|
|
20
|
+
return (_jsxs("div", { className: "space-y-2", children: [_jsx(FieldLabel, { label: field.label, help: help }), _jsxs(Select, { value: String(value ?? ""), onValueChange: (v) => onChange(v === "__none__" ? "" : v), children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: layoutsLoading ? "Laden…" : "Kies een layout" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "__none__", children: "Automatisch kiezen" }), options.map((layout) => (_jsxs(SelectItem, { value: layout.id, children: [layout.name, " \u00B7 ", layout.documentType, " \u00B7 v", layout.version, layout.active ? "" : " (inactief)"] }, layout.id)))] })] }), !layoutsLoading && options.length === 0 && (_jsx("p", { className: "text-xs text-muted-foreground", children: "Er staan nog geen layouts klaar om te kiezen." }))] }));
|
|
21
|
+
}
|
|
22
|
+
if (field.type === "pickstation") {
|
|
23
|
+
const options = field.type === "pickstation" ? stations : types;
|
|
24
|
+
return (_jsxs("div", { className: "space-y-2", children: [_jsx(FieldLabel, { label: field.label, help: help }), _jsxs(Select, { value: String(value ?? ""), onValueChange: (v) => onChange(v === "__none__" ? "" : v), children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: loading ? "Laden…" : "Kies een pickstation" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "__none__", children: "Niet instellen" }), options.map((option) => (_jsx(SelectItem, { value: option.id, children: option.name }, option.id)))] })] }), !loading && options.length === 0 && (_jsx("p", { className: "text-xs text-muted-foreground", children: "Er zijn nog geen pickstations ingericht." }))] }));
|
|
25
|
+
}
|
|
26
|
+
if (field.type === "days") {
|
|
27
|
+
const selected = Array.isArray(value) ? value : [];
|
|
28
|
+
const days = field.options ?? [];
|
|
29
|
+
const toggleDay = (day) => {
|
|
30
|
+
onChange(selected.includes(day) ? selected.filter((d) => d !== day) : [...selected, day]);
|
|
31
|
+
};
|
|
32
|
+
return (_jsxs("div", { className: "space-y-2", children: [_jsx(FieldLabel, { label: field.label, help: help }), _jsx("div", { className: "flex flex-wrap gap-2", children: days.map((day) => {
|
|
33
|
+
const active = selected.includes(day.value);
|
|
34
|
+
return (_jsx("button", { type: "button", onClick: () => toggleDay(day.value), className: `rounded-lg border px-3 py-2 text-sm font-medium transition-colors ${active
|
|
35
|
+
? "border-primary bg-primary/10 text-primary"
|
|
36
|
+
: "border-border text-muted-foreground hover:bg-muted"}`, children: day.label }, day.value));
|
|
37
|
+
}) })] }));
|
|
38
|
+
}
|
|
39
|
+
if (field.type === "toggle") {
|
|
40
|
+
return (_jsxs("div", { className: "flex items-center justify-between gap-4 rounded-lg border border-border p-3", children: [_jsx(FieldLabel, { label: field.label, help: help }), _jsx(Switch, { checked: value === true, onCheckedChange: (checked) => onChange(checked) })] }));
|
|
41
|
+
}
|
|
42
|
+
if (field.type === "radio") {
|
|
43
|
+
const options = Array.isArray(field.options) ? field.options : [];
|
|
44
|
+
return (_jsxs("div", { className: "space-y-2", children: [_jsx(FieldLabel, { label: field.label, help: help }), _jsx("div", { className: "space-y-2", children: options.map((option) => {
|
|
45
|
+
const selected = String(value ?? "") === option.value;
|
|
46
|
+
return (_jsx("button", { type: "button", onClick: () => onChange(option.value), className: `w-full rounded-lg border p-3 text-left transition-colors ${selected ? "border-primary bg-primary/5 ring-1 ring-primary" : "border-border hover:bg-muted/50"}`, children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("span", { className: `flex h-4 w-4 shrink-0 items-center justify-center rounded-full border ${selected ? "border-primary" : "border-muted-foreground/40"}`, children: selected && _jsx("span", { className: "h-2 w-2 rounded-full bg-primary" }) }), _jsxs("span", { className: "flex items-center gap-2 text-sm font-medium", children: [option.label, option.badge && (_jsx("span", { className: "rounded bg-primary/10 px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-primary", children: option.badge })), _jsx(FieldHelp, { text: option.description })] })] }) }, option.value));
|
|
47
|
+
}) })] }));
|
|
48
|
+
}
|
|
49
|
+
if (field.type === "select") {
|
|
50
|
+
const options = Array.isArray(field.options) ? field.options : [];
|
|
51
|
+
return (_jsxs("div", { className: "space-y-2", children: [_jsx(FieldLabel, { label: field.label, help: help }), _jsxs(Select, { value: String(value ?? ""), onValueChange: (v) => onChange(v), children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: "Kies een optie" }) }), _jsx(SelectContent, { children: options.map((option) => (_jsx(SelectItem, { value: option.value, children: option.label }, option.value))) })] })] }));
|
|
52
|
+
}
|
|
53
|
+
if (field.type === "number") {
|
|
54
|
+
return (_jsxs("div", { className: "space-y-2", children: [_jsx(FieldLabel, { label: field.label, help: help, unit: field.unit }), _jsx(Input, { type: "number", min: field.min, max: field.max, value: value === undefined || value === null ? "" : String(value), onChange: (e) => onChange(e.target.value === "" ? "" : Number(e.target.value)) })] }));
|
|
55
|
+
}
|
|
56
|
+
if (field.type === "textarea") {
|
|
57
|
+
return (_jsxs("div", { className: "space-y-2", children: [_jsx(FieldLabel, { label: field.label, help: help }), _jsx(Textarea, { rows: 3, value: String(value ?? ""), onChange: (e) => onChange(e.target.value), placeholder: "naam@bedrijf.nl, inkoop@bedrijf.nl" })] }));
|
|
58
|
+
}
|
|
59
|
+
if (field.type === "time") {
|
|
60
|
+
return (_jsxs("div", { className: "space-y-2", children: [_jsx(FieldLabel, { label: field.label, help: help }), _jsx(Input, { type: "time", value: String(value ?? ""), onChange: (e) => onChange(e.target.value) })] }));
|
|
61
|
+
}
|
|
62
|
+
if (field.type === "priority") {
|
|
63
|
+
const options = Array.isArray(field.options) ? field.options : [];
|
|
64
|
+
const stored = Array.isArray(value) ? value : [];
|
|
65
|
+
// Altijd op de actuele optielijst baseren, zodat nieuwe/hernoemde criteria verschijnen
|
|
66
|
+
const entries = options.map((o) => {
|
|
67
|
+
const found = stored.find((e) => e && e.key === o.value);
|
|
68
|
+
return { key: o.value, enabled: found ? found.enabled : true };
|
|
69
|
+
});
|
|
70
|
+
const toggle = (index) => {
|
|
71
|
+
const next = entries.map((entry, i) => (i === index ? { ...entry, enabled: !entry.enabled } : entry));
|
|
72
|
+
onChange(next);
|
|
73
|
+
};
|
|
74
|
+
return (_jsxs("div", { className: "space-y-2", children: [_jsx(FieldLabel, { label: field.label, help: help }), _jsx("ul", { className: "grid gap-2 sm:grid-cols-2", children: entries.map((entry, index) => {
|
|
75
|
+
const label = options.find((o) => o.value === entry.key)?.label ?? entry.key;
|
|
76
|
+
return (_jsxs("li", { className: "flex items-center gap-3 rounded-lg border border-border p-2.5", children: [_jsx("span", { className: entry.enabled ? "flex-1 text-sm" : "flex-1 text-sm text-muted-foreground line-through", children: label }), _jsx(Switch, { checked: entry.enabled, onCheckedChange: () => toggle(index) })] }, entry.key));
|
|
77
|
+
}) })] }));
|
|
78
|
+
}
|
|
79
|
+
return (_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { className: "text-sm font-medium", children: field.label }), _jsx(Input, { value: String(value ?? ""), onChange: (e) => onChange(e.target.value) })] }));
|
|
80
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RuleEngineSettings } from "../../lib/ruleEngineSchema";
|
|
2
|
+
import type { RuleVersion } from "../../hooks/useRuleEngine";
|
|
3
|
+
interface Props {
|
|
4
|
+
versions: RuleVersion[];
|
|
5
|
+
currentSettings: RuleEngineSettings;
|
|
6
|
+
onRestore: (version: RuleVersion) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function VersionsPanel({ versions, currentSettings, onRestore }: Props): import("react").JSX.Element;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=VersionsPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VersionsPanel.d.ts","sourceRoot":"","sources":["../../../src/components/rule-engine/VersionsPanel.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAErE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE7D,UAAU,KAAK;IACb,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,eAAe,EAAE,kBAAkB,CAAC;IACpC,SAAS,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;CAC3C;AAED,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,SAAS,EAAE,EAAE,KAAK,+BAiF5E"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// ============================================================================
|
|
3
|
+
// src/components/rule-engine/VersionsPanel.tsx — versiebeheer + vergelijking
|
|
4
|
+
// ============================================================================
|
|
5
|
+
import { useState } from "react";
|
|
6
|
+
import { Badge, Button, Card, CardContent, CardHeader, CardTitle, Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@flowselections/core";
|
|
7
|
+
import { GitCompare, History, RotateCcw } from "lucide-react";
|
|
8
|
+
import { diffSettings } from "../../lib/ruleEngineImpact";
|
|
9
|
+
export function VersionsPanel({ versions, currentSettings, onRestore }) {
|
|
10
|
+
const [compare, setCompare] = useState(null);
|
|
11
|
+
const safeVersions = Array.isArray(versions) ? versions : [];
|
|
12
|
+
const diff = compare ? diffSettings(compare.settings, currentSettings) : [];
|
|
13
|
+
return (_jsxs(Card, { children: [_jsx(CardHeader, { className: "pb-3", children: _jsxs(CardTitle, { className: "flex items-center gap-2 text-base", children: [_jsx(History, { className: "h-4 w-4" }), "Versies"] }) }), _jsx(CardContent, { children: safeVersions.length === 0 ? (_jsx("p", { className: "text-sm text-muted-foreground", children: "Nog geen versies opgeslagen. Gebruik \"Versie vastleggen\" om een momentopname te bewaren." })) : (_jsx("ul", { className: "space-y-2", children: safeVersions.map((version) => (_jsxs("li", { className: "flex items-center justify-between gap-2 rounded-lg border border-border p-2.5", children: [_jsxs("div", { className: "min-w-0", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("span", { className: "text-sm font-medium", children: ["Versie ", version.version] }), _jsx(Badge, { variant: "secondary", className: "text-[10px]", children: version.status })] }), _jsx("p", { className: "truncate text-xs text-muted-foreground", children: version.note ?? new Date(version.created_at).toLocaleString("nl-NL") })] }), _jsxs("div", { className: "flex shrink-0 gap-1", children: [_jsx(Button, { size: "icon", variant: "ghost", onClick: () => setCompare(version), "aria-label": "Vergelijken", children: _jsx(GitCompare, { className: "h-4 w-4" }) }), _jsx(Button, { size: "icon", variant: "ghost", onClick: () => onRestore(version), "aria-label": "Herstellen", children: _jsx(RotateCcw, { className: "h-4 w-4" }) })] })] }, version.id))) })) }), _jsx(Dialog, { open: !!compare, onOpenChange: (open) => !open && setCompare(null), children: _jsxs(DialogContent, { className: "max-h-[80vh] overflow-y-auto sm:max-w-2xl", children: [_jsxs(DialogHeader, { children: [_jsxs(DialogTitle, { children: ["Versie ", compare?.version, " vergelijken met huidig"] }), _jsx(DialogDescription, { children: diff.length === 0
|
|
14
|
+
? "Geen verschillen gevonden."
|
|
15
|
+
: `${diff.length} verschil${diff.length === 1 ? "" : "len"} gevonden.` })] }), _jsx("ul", { className: "space-y-2", children: diff.map((line, index) => (_jsxs("li", { className: "rounded-lg border border-border p-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Badge, { variant: "secondary", className: "text-[10px]", children: line.step }), _jsx("span", { className: "text-sm font-medium", children: line.label })] }), _jsxs("p", { className: "mt-1 text-xs", children: [_jsx("span", { className: "text-muted-foreground line-through", children: line.before }), _jsx("span", { className: "mx-2", children: "\u2192" }), _jsx("span", { className: "font-medium", children: line.after })] })] }, index))) })] }) })] }));
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LogistiekEngineSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/LogistiekEngineSettingsCard.tsx"],"names":[],"mappings":"AAcA,wBAAgB,2BAA2B,gCA2C1C"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle, Button, Input, Label, toast, } from "@flowselections/core";
|
|
4
|
+
import { Settings2 } from "lucide-react";
|
|
5
|
+
export function LogistiekEngineSettingsCard() {
|
|
6
|
+
const [standaardVertrektijd, setStandaardVertrektijd] = useState("");
|
|
7
|
+
const [saving, setSaving] = useState(false);
|
|
8
|
+
const handleSave = async () => {
|
|
9
|
+
setSaving(true);
|
|
10
|
+
try {
|
|
11
|
+
// TODO: opslaan naar de instellingen-tabel van deze module
|
|
12
|
+
toast.success("Instellingen opgeslagen");
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
toast.error("Fout bij het opslaan");
|
|
16
|
+
}
|
|
17
|
+
finally {
|
|
18
|
+
setSaving(false);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
return (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Settings2, { className: "h-5 w-5 text-primary" }), _jsx(CardTitle, { children: "Logistiek Engine" })] }), _jsx(CardDescription, { children: "Instellingen voor het logistieke gedeelte van de orderflow" })] }), _jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "vertrektijd", children: "Standaard vertrektijd" }), _jsx(Input, { id: "vertrektijd", type: "time", value: standaardVertrektijd, onChange: (e) => setStandaardVertrektijd(e.target.value) })] }), _jsx(Button, { onClick: handleSave, disabled: saving, children: saving ? "Opslaan..." : "Opslaan" })] })] }));
|
|
22
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface CapaciteitMelding {
|
|
2
|
+
id: string;
|
|
3
|
+
plan_date: string;
|
|
4
|
+
pickup_label: string | null;
|
|
5
|
+
required_minutes: number | null;
|
|
6
|
+
available_minutes: number | null;
|
|
7
|
+
shortage_minutes: number | null;
|
|
8
|
+
carts_total: number | null;
|
|
9
|
+
carts_short: number | null;
|
|
10
|
+
status: string;
|
|
11
|
+
created_at: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function useCapaciteitMeldingen(): {
|
|
14
|
+
meldingen: CapaciteitMelding[];
|
|
15
|
+
staff: number;
|
|
16
|
+
loading: boolean;
|
|
17
|
+
reload: () => Promise<void>;
|
|
18
|
+
controleer: () => Promise<void>;
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=useCapaciteitMeldingen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCapaciteitMeldingen.d.ts","sourceRoot":"","sources":["../../src/hooks/useCapaciteitMeldingen.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAID,wBAAgB,sBAAsB;;;;;;EA4CrC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// src/hooks/useCapaciteitMeldingen.ts — capaciteitswaarschuwingen per pickdag
|
|
3
|
+
// ============================================================================
|
|
4
|
+
import { useCallback, useEffect, useState } from "react";
|
|
5
|
+
import { supabase, toast } from "@flowselections/core";
|
|
6
|
+
const db = () => supabase;
|
|
7
|
+
export function useCapaciteitMeldingen() {
|
|
8
|
+
const [meldingen, setMeldingen] = useState([]);
|
|
9
|
+
const [staff, setStaff] = useState(0);
|
|
10
|
+
const [loading, setLoading] = useState(true);
|
|
11
|
+
const load = useCallback(async () => {
|
|
12
|
+
setLoading(true);
|
|
13
|
+
const { data, error } = await db()
|
|
14
|
+
.from("logistics_capacity_alerts")
|
|
15
|
+
.select("*")
|
|
16
|
+
.eq("status", "open")
|
|
17
|
+
.order("plan_date", { ascending: true })
|
|
18
|
+
.limit(50);
|
|
19
|
+
setMeldingen(error || !Array.isArray(data) ? [] : data);
|
|
20
|
+
const { data: configs } = await db()
|
|
21
|
+
.from("logistics_rule_configs")
|
|
22
|
+
.select("settings, is_active, updated_at")
|
|
23
|
+
.order("is_active", { ascending: false })
|
|
24
|
+
.order("updated_at", { ascending: false })
|
|
25
|
+
.limit(1);
|
|
26
|
+
const settings = Array.isArray(configs) && configs[0] ? configs[0].settings : null;
|
|
27
|
+
const value = Number(settings?.order_picken?.fields?.avg_staff ?? 0);
|
|
28
|
+
setStaff(Number.isFinite(value) && value > 0 ? value : 0);
|
|
29
|
+
setLoading(false);
|
|
30
|
+
}, []);
|
|
31
|
+
const controleer = useCallback(async () => {
|
|
32
|
+
const today = new Date();
|
|
33
|
+
const from = today.toISOString().slice(0, 10);
|
|
34
|
+
const to = new Date(today.getTime() + 21 * 86400000).toISOString().slice(0, 10);
|
|
35
|
+
const { error } = await db().rpc("logistics_capacity_day_check", { p_from: from, p_to: to });
|
|
36
|
+
if (error)
|
|
37
|
+
toast.error(`Capaciteitscontrole mislukt: ${error.message}`);
|
|
38
|
+
else
|
|
39
|
+
toast.success("Capaciteit opnieuw berekend");
|
|
40
|
+
await load();
|
|
41
|
+
}, [load]);
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
void load();
|
|
44
|
+
}, [load]);
|
|
45
|
+
return { meldingen, staff, loading, reload: load, controleer };
|
|
46
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface DocumentLayoutOption {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
documentType: string;
|
|
5
|
+
version: number;
|
|
6
|
+
active: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function useDocumentLayouts(documentTypes?: string[]): {
|
|
9
|
+
layouts: DocumentLayoutOption[];
|
|
10
|
+
allLayouts: DocumentLayoutOption[];
|
|
11
|
+
loading: boolean;
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=useDocumentLayouts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDocumentLayouts.d.ts","sourceRoot":"","sources":["../../src/hooks/useDocumentLayouts.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CACjB;AA4BD,wBAAgB,kBAAkB,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE;;;;EAyB1D"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// src/hooks/useDocumentLayouts.ts — layouts uit de Layout maker, zodat je per
|
|
3
|
+
// documentsoort in de Logistiek Engine een layout kunt koppelen.
|
|
4
|
+
// ============================================================================
|
|
5
|
+
import { useEffect, useState } from "react";
|
|
6
|
+
import { supabase } from "@flowselections/core";
|
|
7
|
+
const db = () => supabase;
|
|
8
|
+
let cache = null;
|
|
9
|
+
let inflight = null;
|
|
10
|
+
async function load() {
|
|
11
|
+
if (cache)
|
|
12
|
+
return cache;
|
|
13
|
+
if (!inflight) {
|
|
14
|
+
inflight = (async () => {
|
|
15
|
+
const { data } = await db()
|
|
16
|
+
.from("document_layouts")
|
|
17
|
+
.select("id, naam, documenttype, huidige_versie, actief")
|
|
18
|
+
.order("naam", { ascending: true });
|
|
19
|
+
cache = (Array.isArray(data) ? data : []).map((r) => ({
|
|
20
|
+
id: String(r.id),
|
|
21
|
+
name: String(r.naam ?? r.id),
|
|
22
|
+
documentType: String(r.documenttype ?? ""),
|
|
23
|
+
version: Number(r.huidige_versie ?? 1),
|
|
24
|
+
active: r.actief !== false,
|
|
25
|
+
}));
|
|
26
|
+
return cache;
|
|
27
|
+
})();
|
|
28
|
+
}
|
|
29
|
+
return inflight;
|
|
30
|
+
}
|
|
31
|
+
export function useDocumentLayouts(documentTypes) {
|
|
32
|
+
const [layouts, setLayouts] = useState(cache ?? []);
|
|
33
|
+
const [loading, setLoading] = useState(!cache);
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
let active = true;
|
|
36
|
+
load()
|
|
37
|
+
.then((rows) => {
|
|
38
|
+
if (active)
|
|
39
|
+
setLayouts(rows);
|
|
40
|
+
})
|
|
41
|
+
.catch(() => undefined)
|
|
42
|
+
.finally(() => {
|
|
43
|
+
if (active)
|
|
44
|
+
setLoading(false);
|
|
45
|
+
});
|
|
46
|
+
return () => {
|
|
47
|
+
active = false;
|
|
48
|
+
};
|
|
49
|
+
}, []);
|
|
50
|
+
const filtered = documentTypes && documentTypes.length > 0
|
|
51
|
+
? layouts.filter((l) => documentTypes.includes(l.documentType))
|
|
52
|
+
: layouts;
|
|
53
|
+
return { layouts: filtered, allLayouts: layouts, loading };
|
|
54
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { LoadCarrierTypeRow } from "../lib/loadCarrierTypes";
|
|
2
|
+
export type LadingdragerInput = Partial<Omit<LoadCarrierTypeRow, "id">> & {
|
|
3
|
+
code: string;
|
|
4
|
+
name: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function useLadingdragers(): {
|
|
7
|
+
items: LoadCarrierTypeRow[];
|
|
8
|
+
loading: boolean;
|
|
9
|
+
saving: boolean;
|
|
10
|
+
error: string | null;
|
|
11
|
+
reload: () => Promise<void>;
|
|
12
|
+
create: (input: LadingdragerInput) => Promise<boolean>;
|
|
13
|
+
update: (id: string, input: Partial<LoadCarrierTypeRow>) => Promise<boolean>;
|
|
14
|
+
remove: (id: string) => Promise<boolean>;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=useLadingdragers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useLadingdragers.d.ts","sourceRoot":"","sources":["../../src/hooks/useLadingdragers.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAIlE,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzG,wBAAgB,gBAAgB;;;;;;oBAkDW,iBAAiB;iBArBpB,MAAM,SAAS,OAAO,CAAC,kBAAkB,CAAC;iBAuC1C,MAAM;EAY7C"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// src/hooks/useLadingdragers.ts — beheer van ladingdragertypen
|
|
2
|
+
import { useCallback, useEffect, useState } from "react";
|
|
3
|
+
import { supabase, toast } from "@flowselections/core";
|
|
4
|
+
const db = () => supabase;
|
|
5
|
+
export function useLadingdragers() {
|
|
6
|
+
const [items, setItems] = useState([]);
|
|
7
|
+
const [loading, setLoading] = useState(true);
|
|
8
|
+
const [saving, setSaving] = useState(false);
|
|
9
|
+
const [error, setError] = useState(null);
|
|
10
|
+
const load = useCallback(async () => {
|
|
11
|
+
setLoading(true);
|
|
12
|
+
setError(null);
|
|
13
|
+
try {
|
|
14
|
+
const { data, error } = await db()
|
|
15
|
+
.from("load_carrier_types")
|
|
16
|
+
.select("*")
|
|
17
|
+
.order("sort_order", { ascending: true })
|
|
18
|
+
.limit(100);
|
|
19
|
+
if (error)
|
|
20
|
+
throw error;
|
|
21
|
+
setItems(Array.isArray(data) ? data : []);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
setError("Fout bij het laden van ladingdragers");
|
|
25
|
+
toast.error("Fout bij het laden van ladingdragers");
|
|
26
|
+
}
|
|
27
|
+
finally {
|
|
28
|
+
setLoading(false);
|
|
29
|
+
}
|
|
30
|
+
}, []);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
load();
|
|
33
|
+
}, [load]);
|
|
34
|
+
const update = useCallback(async (id, input) => {
|
|
35
|
+
setSaving(true);
|
|
36
|
+
try {
|
|
37
|
+
const { data, error } = await db()
|
|
38
|
+
.from("load_carrier_types")
|
|
39
|
+
.update(input)
|
|
40
|
+
.eq("id", id)
|
|
41
|
+
.select()
|
|
42
|
+
.single();
|
|
43
|
+
if (error)
|
|
44
|
+
throw error;
|
|
45
|
+
setItems((prev) => prev.map((i) => (i.id === id ? data : i)));
|
|
46
|
+
toast.success("Ladingdrager bijgewerkt");
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
toast.error(e?.message ?? "Bijwerken mislukt");
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
setSaving(false);
|
|
55
|
+
}
|
|
56
|
+
}, []);
|
|
57
|
+
const create = useCallback(async (input) => {
|
|
58
|
+
setSaving(true);
|
|
59
|
+
try {
|
|
60
|
+
const { data, error } = await db().from("load_carrier_types").insert(input).select().single();
|
|
61
|
+
if (error)
|
|
62
|
+
throw error;
|
|
63
|
+
setItems((prev) => [...prev, data].sort((a, b) => a.sort_order - b.sort_order));
|
|
64
|
+
toast.success("Ladingdrager toegevoegd");
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
toast.error(e?.message ?? "Toevoegen mislukt");
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
setSaving(false);
|
|
73
|
+
}
|
|
74
|
+
}, []);
|
|
75
|
+
const remove = useCallback(async (id) => {
|
|
76
|
+
const { error } = await db().from("load_carrier_types").delete().eq("id", id);
|
|
77
|
+
if (error) {
|
|
78
|
+
toast.error("Verwijderen mislukt");
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
setItems((prev) => prev.filter((i) => i.id !== id));
|
|
82
|
+
toast.success("Ladingdrager verwijderd");
|
|
83
|
+
return true;
|
|
84
|
+
}, []);
|
|
85
|
+
return { items, loading, saving, error, reload: load, create, update, remove };
|
|
86
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface LogistiekStrategie {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
description: string | null;
|
|
5
|
+
priority: number;
|
|
6
|
+
color: string;
|
|
7
|
+
is_active: boolean;
|
|
8
|
+
version: number;
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
}
|
|
11
|
+
export interface StrategieInput {
|
|
12
|
+
name: string;
|
|
13
|
+
description: string;
|
|
14
|
+
priority: number;
|
|
15
|
+
color: string;
|
|
16
|
+
is_active: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function useLogistiekStrategieen(): {
|
|
19
|
+
items: LogistiekStrategie[];
|
|
20
|
+
loading: boolean;
|
|
21
|
+
saving: boolean;
|
|
22
|
+
error: string | null;
|
|
23
|
+
reload: () => Promise<void>;
|
|
24
|
+
create: (input: StrategieInput) => Promise<boolean>;
|
|
25
|
+
update: (id: string, input: Partial<StrategieInput>) => Promise<boolean>;
|
|
26
|
+
remove: (id: string) => Promise<boolean>;
|
|
27
|
+
toggleActive: (item: LogistiekStrategie) => Promise<boolean>;
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=useLogistiekStrategieen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useLogistiekStrategieen.d.ts","sourceRoot":"","sources":["../../src/hooks/useLogistiekStrategieen.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;CACpB;AAID,wBAAgB,uBAAuB;;;;;;oBA6CI,cAAc;iBA0BjB,MAAM,SAAS,OAAO,CAAC,cAAc,CAAC;iBA2BtC,MAAM;yBAYnC,kBAAkB;EAK5B"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// src/hooks/useLogistiekStrategieen.ts — data hook voor logistieke strategieën
|
|
2
|
+
import { useState, useEffect, useCallback } from "react";
|
|
3
|
+
import { supabase, toast } from "@flowselections/core";
|
|
4
|
+
const db = () => supabase;
|
|
5
|
+
export function useLogistiekStrategieen() {
|
|
6
|
+
const [items, setItems] = useState([]);
|
|
7
|
+
const [loading, setLoading] = useState(true);
|
|
8
|
+
const [saving, setSaving] = useState(false);
|
|
9
|
+
const [error, setError] = useState(null);
|
|
10
|
+
const load = useCallback(async () => {
|
|
11
|
+
setLoading(true);
|
|
12
|
+
setError(null);
|
|
13
|
+
try {
|
|
14
|
+
const { data, error } = await db()
|
|
15
|
+
.from("logistics_strategies")
|
|
16
|
+
.select("*")
|
|
17
|
+
.order("priority", { ascending: true })
|
|
18
|
+
.limit(100);
|
|
19
|
+
if (error)
|
|
20
|
+
throw error;
|
|
21
|
+
setItems(Array.isArray(data) ? data : []);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
setError("Fout bij het laden van logistieke strategieën");
|
|
25
|
+
toast.error("Fout bij het laden van gegevens");
|
|
26
|
+
}
|
|
27
|
+
finally {
|
|
28
|
+
setLoading(false);
|
|
29
|
+
}
|
|
30
|
+
}, []);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
load();
|
|
33
|
+
const channel = supabase
|
|
34
|
+
.channel("logistics_strategies_changes")
|
|
35
|
+
.on("postgres_changes", { event: "*", schema: "public", table: "logistics_strategies" }, () => {
|
|
36
|
+
load();
|
|
37
|
+
})
|
|
38
|
+
.subscribe();
|
|
39
|
+
return () => {
|
|
40
|
+
supabase.removeChannel(channel);
|
|
41
|
+
};
|
|
42
|
+
}, [load]);
|
|
43
|
+
const create = useCallback(async (input) => {
|
|
44
|
+
setSaving(true);
|
|
45
|
+
try {
|
|
46
|
+
const { data: userData } = await supabase.auth.getUser();
|
|
47
|
+
const userId = userData?.user?.id;
|
|
48
|
+
if (!userId) {
|
|
49
|
+
toast.error("Je bent niet ingelogd");
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
const { data, error } = await db()
|
|
53
|
+
.from("logistics_strategies")
|
|
54
|
+
.insert({ ...input, description: input.description || null, user_id: userId })
|
|
55
|
+
.select()
|
|
56
|
+
.single();
|
|
57
|
+
if (error)
|
|
58
|
+
throw error;
|
|
59
|
+
setItems((prev) => [...prev, data].sort((a, b) => a.priority - b.priority));
|
|
60
|
+
toast.success("Strategie aangemaakt");
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
toast.error(e?.message ?? "Aanmaken mislukt");
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
setSaving(false);
|
|
69
|
+
}
|
|
70
|
+
}, []);
|
|
71
|
+
const update = useCallback(async (id, input) => {
|
|
72
|
+
setSaving(true);
|
|
73
|
+
try {
|
|
74
|
+
const payload = { ...input };
|
|
75
|
+
if ("description" in payload)
|
|
76
|
+
payload.description = input.description || null;
|
|
77
|
+
const { data, error } = await db()
|
|
78
|
+
.from("logistics_strategies")
|
|
79
|
+
.update(payload)
|
|
80
|
+
.eq("id", id)
|
|
81
|
+
.select()
|
|
82
|
+
.single();
|
|
83
|
+
if (error)
|
|
84
|
+
throw error;
|
|
85
|
+
setItems((prev) => prev
|
|
86
|
+
.map((item) => (item.id === id ? data : item))
|
|
87
|
+
.sort((a, b) => a.priority - b.priority));
|
|
88
|
+
toast.success("Strategie bijgewerkt");
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
catch (e) {
|
|
92
|
+
toast.error(e?.message ?? "Bijwerken mislukt");
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
setSaving(false);
|
|
97
|
+
}
|
|
98
|
+
}, []);
|
|
99
|
+
const remove = useCallback(async (id) => {
|
|
100
|
+
const { error } = await db().from("logistics_strategies").delete().eq("id", id);
|
|
101
|
+
if (error) {
|
|
102
|
+
toast.error("Verwijderen mislukt");
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
setItems((prev) => prev.filter((item) => item.id !== id));
|
|
106
|
+
toast.success("Strategie verwijderd");
|
|
107
|
+
return true;
|
|
108
|
+
}, []);
|
|
109
|
+
const toggleActive = useCallback((item) => update(item.id, { is_active: !item.is_active }), [update]);
|
|
110
|
+
return { items, loading, saving, error, reload: load, create, update, remove, toggleActive };
|
|
111
|
+
}
|