@flowselections/floriday-verkoop-module 1.0.40 → 1.0.41

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.
Files changed (93) hide show
  1. package/dist-lib/components/verkoop/EngineBufferCard.d.ts.map +1 -1
  2. package/dist-lib/components/verkoop/EngineBufferCard.js +2 -2
  3. package/dist-lib/components/verkoop/InvoiceTimingSettings.d.ts +3 -0
  4. package/dist-lib/components/verkoop/InvoiceTimingSettings.d.ts.map +1 -0
  5. package/dist-lib/components/verkoop/InvoiceTimingSettings.js +54 -0
  6. package/dist-lib/components/verkoop/SalesOrdersTable.d.ts.map +1 -1
  7. package/dist-lib/components/verkoop/SalesOrdersTable.js +44 -91
  8. package/dist-lib/components/verkoop/VerkoopOrdersPage.d.ts.map +1 -1
  9. package/dist-lib/components/verkoop/VerkoopOrdersPage.js +9 -8
  10. package/dist-lib/index.d.ts +1 -0
  11. package/dist-lib/index.d.ts.map +1 -1
  12. package/dist-lib/index.js +3 -1
  13. package/dist-lib/integrations/supabase/auth-middleware.d.ts +577 -4
  14. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  15. package/dist-lib/integrations/supabase/client.d.ts +577 -4
  16. package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
  17. package/dist-lib/integrations/supabase/client.server.d.ts +577 -4
  18. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  19. package/dist-lib/integrations/supabase/types.d.ts +578 -5
  20. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  21. package/dist-lib/integrations/supabase/types.js +12 -1
  22. package/dist-lib/lib/cart-lock.functions.d.ts +577 -4
  23. package/dist-lib/lib/cart-lock.functions.d.ts.map +1 -1
  24. package/dist-lib/lib/cart-planning-settings.functions.d.ts +6347 -44
  25. package/dist-lib/lib/cart-planning-settings.functions.d.ts.map +1 -1
  26. package/dist-lib/lib/cart-replan.functions.d.ts +1731 -12
  27. package/dist-lib/lib/cart-replan.functions.d.ts.map +1 -1
  28. package/dist-lib/lib/create-order.functions.d.ts +8655 -60
  29. package/dist-lib/lib/create-order.functions.d.ts.map +1 -1
  30. package/dist-lib/lib/cron/index.d.ts +1 -0
  31. package/dist-lib/lib/cron/index.d.ts.map +1 -1
  32. package/dist-lib/lib/cron/index.js +1 -0
  33. package/dist-lib/lib/cron/invoice-due.d.ts +4 -0
  34. package/dist-lib/lib/cron/invoice-due.d.ts.map +1 -0
  35. package/dist-lib/lib/cron/invoice-due.js +21 -0
  36. package/dist-lib/lib/floriday-auto-fulfillment.functions.d.ts +1731 -12
  37. package/dist-lib/lib/floriday-auto-fulfillment.functions.d.ts.map +1 -1
  38. package/dist-lib/lib/floriday-fulfillment-status.server.d.ts +28 -0
  39. package/dist-lib/lib/floriday-fulfillment-status.server.d.ts.map +1 -0
  40. package/dist-lib/lib/floriday-fulfillment-status.server.js +91 -0
  41. package/dist-lib/lib/floriday-logistic-labels.functions.d.ts +577 -4
  42. package/dist-lib/lib/floriday-logistic-labels.functions.d.ts.map +1 -1
  43. package/dist-lib/lib/floriday-mirror.functions.d.ts +577 -4
  44. package/dist-lib/lib/floriday-mirror.functions.d.ts.map +1 -1
  45. package/dist-lib/lib/floriday-mirror.functions.js +27 -4
  46. package/dist-lib/lib/floriday-public.functions.d.ts +4039 -28
  47. package/dist-lib/lib/floriday-public.functions.d.ts.map +1 -1
  48. package/dist-lib/lib/floriday-writes.functions.d.ts +2885 -20
  49. package/dist-lib/lib/floriday-writes.functions.d.ts.map +1 -1
  50. package/dist-lib/lib/invoice-timing.d.ts +38 -0
  51. package/dist-lib/lib/invoice-timing.d.ts.map +1 -0
  52. package/dist-lib/lib/invoice-timing.functions.d.ts +83845 -0
  53. package/dist-lib/lib/invoice-timing.functions.d.ts.map +1 -0
  54. package/dist-lib/lib/invoice-timing.functions.js +88 -0
  55. package/dist-lib/lib/invoice-timing.js +139 -0
  56. package/dist-lib/lib/invoice-timing.server.d.ts +22 -0
  57. package/dist-lib/lib/invoice-timing.server.d.ts.map +1 -0
  58. package/dist-lib/lib/invoice-timing.server.js +154 -0
  59. package/dist-lib/lib/load-carriers.functions.d.ts +577 -4
  60. package/dist-lib/lib/load-carriers.functions.d.ts.map +1 -1
  61. package/dist-lib/lib/logistics-engine.functions.d.ts +2887 -22
  62. package/dist-lib/lib/logistics-engine.functions.d.ts.map +1 -1
  63. package/dist-lib/lib/logistics-stock.functions.d.ts +1154 -8
  64. package/dist-lib/lib/logistics-stock.functions.d.ts.map +1 -1
  65. package/dist-lib/lib/order-addresses.functions.d.ts +577 -4
  66. package/dist-lib/lib/order-addresses.functions.d.ts.map +1 -1
  67. package/dist-lib/lib/order-buffers.functions.d.ts +1731 -12
  68. package/dist-lib/lib/order-buffers.functions.d.ts.map +1 -1
  69. package/dist-lib/lib/order-carrier.functions.d.ts +1154 -8
  70. package/dist-lib/lib/order-carrier.functions.d.ts.map +1 -1
  71. package/dist-lib/lib/order-pickup.functions.d.ts +1154 -8
  72. package/dist-lib/lib/order-pickup.functions.d.ts.map +1 -1
  73. package/dist-lib/lib/order-shipments.functions.d.ts +2308 -16
  74. package/dist-lib/lib/order-shipments.functions.d.ts.map +1 -1
  75. package/dist-lib/lib/order-status.d.ts +33 -0
  76. package/dist-lib/lib/order-status.d.ts.map +1 -0
  77. package/dist-lib/lib/order-status.js +77 -0
  78. package/dist-lib/lib/salesorders-list.functions.d.ts +578 -5
  79. package/dist-lib/lib/salesorders-list.functions.d.ts.map +1 -1
  80. package/dist-lib/lib/salesorders-list.functions.js +1 -1
  81. package/dist-lib/lib/salesorders-list.server.d.ts +2 -1
  82. package/dist-lib/lib/salesorders-list.server.d.ts.map +1 -1
  83. package/dist-lib/lib/salesorders-list.server.js +145 -58
  84. package/dist-lib/lib/salesorders-mapping.d.ts +13 -0
  85. package/dist-lib/lib/salesorders-mapping.d.ts.map +1 -1
  86. package/dist-lib/lib/salesorders-mapping.js +2 -7
  87. package/dist-lib/lib/salesorders.functions.d.ts +2885 -20
  88. package/dist-lib/lib/salesorders.functions.d.ts.map +1 -1
  89. package/dist-lib/lib/tradeitems.functions.d.ts +577 -4
  90. package/dist-lib/lib/tradeitems.functions.d.ts.map +1 -1
  91. package/dist-lib/lib/useSalesOrdersQuery.d.ts +2 -1
  92. package/dist-lib/lib/useSalesOrdersQuery.d.ts.map +1 -1
  93. package/package.json +10 -2
@@ -1 +1 @@
1
- {"version":3,"file":"EngineBufferCard.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/EngineBufferCard.tsx"],"names":[],"mappings":"AAiBA;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,sCA+HvE"}
1
+ {"version":3,"file":"EngineBufferCard.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/EngineBufferCard.tsx"],"names":[],"mappings":"AAiBA;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,sCA6IvE"}
@@ -34,7 +34,7 @@ export function EngineBufferCard({ orderId }) {
34
34
  });
35
35
  if (!orderId)
36
36
  return null;
37
- return (_jsxs("div", { className: "rounded-lg border border-border bg-card p-4", children: [_jsxs("div", { className: "mb-3 flex items-center gap-2", children: [_jsx(Cpu, { className: "h-4 w-4 text-primary" }), _jsx("span", { className: "text-sm font-semibold text-foreground", children: "Logistics Engine" }), data?.shadow && (_jsx(Badge, { variant: "outline", className: "text-[10px]", children: "Schaduwmodus" })), data?.task?.ruleVersion && (_jsxs(Badge, { variant: "outline", className: "text-[10px]", children: ["rule ", data.task.ruleVersion] }))] }), isLoading && _jsx("div", { className: "text-sm text-muted-foreground", children: "Engine raadplegen\u2026" }), error && (_jsxs("div", { className: "flex items-start gap-2 text-sm text-destructive", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0" }), _jsx("span", { children: error.message })] })), data && !data.engineAvailable && (_jsxs("div", { className: "flex items-start gap-2 text-sm text-muted-foreground", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-500" }), _jsxs("span", { children: ["Engine niet bereikbaar", data.engineError ? `: ${data.engineError}` : "", " \u2014 order gaat los door."] })] })), data && data.engineAvailable && !data.buffer && (_jsxs("div", { className: "text-sm text-muted-foreground", children: ["De Engine buffert deze order niet", data.reason ? ` (${data.reason})` : "", " \u2014 de order gaat los door."] })), data && data.engineAvailable && data.buffer && (_jsxs("div", { className: "space-y-3 text-sm", children: [_jsxs("div", { className: "grid grid-cols-2 gap-3", children: [_jsxs("div", { children: [_jsx("div", { className: "text-muted-foreground", children: "Buffer sluit" }), _jsx("div", { className: "font-semibold text-foreground", children: fmt(data.closeAt) })] }), _jsxs("div", { children: [_jsx("div", { className: "text-muted-foreground", children: "Vrijgave" }), _jsx("div", { className: "font-semibold text-foreground", children: data.release })] }), _jsxs("div", { children: [_jsx("div", { className: "text-muted-foreground", children: "Buffersleutel" }), _jsx("div", { className: "font-mono text-xs text-foreground", children: data.bufferKey ?? data.bufferRef ?? "—" })] }), _jsxs("div", { children: [_jsx("div", { className: "text-muted-foreground", children: "Orders in buffer" }), _jsx("div", { className: "font-semibold text-foreground", children: data.orderCount })] })] }), data.matchCriteria && Object.keys(data.matchCriteria).length > 0 && (_jsxs("div", { children: [_jsx("div", { className: "mb-1 text-muted-foreground", children: "Samenstelling (matchCriteria)" }), _jsx("div", { className: "flex flex-wrap gap-1.5", children: Object.entries(data.matchCriteria).map(([k, v]) => (_jsxs(Badge, { variant: "outline", className: "text-[11px]", children: [k, ": ", typeof v === "object" ? JSON.stringify(v) : String(v)] }, k))) })] })), data.release === "manual" && data.task && (_jsx(Button, { size: "sm", disabled: releasing, onClick: async () => {
37
+ return (_jsxs("div", { className: "rounded-lg border border-border bg-card p-4", children: [_jsxs("div", { className: "mb-3 flex items-center gap-2", children: [_jsx(Cpu, { className: "h-4 w-4 text-primary" }), _jsx("span", { className: "text-sm font-semibold text-foreground", children: "Samenvoegen van orders" }), data?.shadow && (_jsx(Badge, { variant: "outline", className: "text-[10px]", children: "Schaduwmodus" }))] }), isLoading && _jsx("div", { className: "text-sm text-muted-foreground", children: "Bezig met controleren\u2026" }), error && (_jsxs("div", { className: "flex items-start gap-2 text-sm text-destructive", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0" }), _jsx("span", { children: error.message })] })), data && !data.engineAvailable && (_jsxs("div", { className: "flex items-start gap-2 text-sm text-muted-foreground", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-500" }), _jsxs("span", { children: ["De planning kon niet worden opgehaald \u2014 deze order wordt los verwerkt.", data.engineError ? ` (${data.engineError})` : ""] })] })), data && data.engineAvailable && !data.buffer && (_jsxs("div", { className: "text-sm text-muted-foreground", children: ["Deze order wordt niet samengevoegd met andere orders en gaat los door.", data.reason ? ` (${data.reason})` : ""] })), data && data.engineAvailable && data.buffer && (_jsxs("div", { className: "space-y-3 text-sm", children: [_jsxs("div", { className: "text-foreground", children: ["Deze order wordt samengevoegd met", " ", _jsx("span", { className: "font-semibold", children: Math.max((data.orderCount ?? 1) - 1, 0) }), " ", "andere order(s) voor dezelfde levering."] }), _jsxs("div", { className: "grid grid-cols-2 gap-3", children: [_jsxs("div", { children: [_jsx("div", { className: "text-muted-foreground", children: "Verzamelen tot" }), _jsx("div", { className: "font-semibold text-foreground", children: fmt(data.closeAt) })] }), _jsxs("div", { children: [_jsx("div", { className: "text-muted-foreground", children: "Orders in deze groep" }), _jsx("div", { className: "font-semibold text-foreground", children: data.orderCount })] })] }), _jsxs("details", { className: "rounded-md border border-border/60 bg-muted/20 p-2", children: [_jsx("summary", { className: "cursor-pointer text-xs text-muted-foreground", children: "Technische details" }), _jsxs("div", { className: "mt-2 space-y-2 text-xs", children: [_jsxs("div", { children: [_jsx("span", { className: "text-muted-foreground", children: "Vrijgave: " }), _jsx("span", { className: "text-foreground", children: data.release })] }), _jsxs("div", { children: [_jsx("span", { className: "text-muted-foreground", children: "Buffersleutel: " }), _jsx("span", { className: "font-mono text-foreground", children: data.bufferKey ?? data.bufferRef ?? "—" })] }), data.task?.ruleVersion && (_jsxs("div", { children: [_jsx("span", { className: "text-muted-foreground", children: "Regelversie: " }), _jsx("span", { className: "text-foreground", children: data.task.ruleVersion })] })), data.matchCriteria && Object.keys(data.matchCriteria).length > 0 && (_jsx("div", { className: "flex flex-wrap gap-1.5", children: Object.entries(data.matchCriteria).map(([k, v]) => (_jsxs(Badge, { variant: "outline", className: "text-[11px]", children: [k, ": ", typeof v === "object" ? JSON.stringify(v) : String(v)] }, k))) }))] })] }), data.release === "manual" && data.task && (_jsx(Button, { size: "sm", disabled: releasing, onClick: async () => {
38
38
  try {
39
39
  setReleasing(true);
40
40
  await doRelease({ data: { taskId: data.task.taskId } });
@@ -49,5 +49,5 @@ export function EngineBufferCard({ orderId }) {
49
49
  finally {
50
50
  setReleasing(false);
51
51
  }
52
- }, children: releasing ? "Bezig…" : "Vrijgeven" })), data.release !== "manual" && (_jsxs("div", { className: "text-xs text-muted-foreground", children: ["Vrijgave \u201C", data.release, "\u201D \u2014 de Engine bepaalt dit, hier is geen actie nodig."] }))] }))] }));
52
+ }, children: releasing ? "Bezig…" : "Vrijgeven" })), data.release !== "manual" && (_jsx("div", { className: "text-xs text-muted-foreground", children: "De vrijgave gebeurt automatisch \u2014 hier is geen actie nodig." }))] }))] }));
53
53
  }
@@ -0,0 +1,3 @@
1
+ export declare function InvoiceTimingSettingsCard(): import("react").JSX.Element;
2
+ export default InvoiceTimingSettingsCard;
3
+ //# sourceMappingURL=InvoiceTimingSettings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InvoiceTimingSettings.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/InvoiceTimingSettings.tsx"],"names":[],"mappings":"AA+GA,wBAAgB,yBAAyB,gCA2GxC;AAED,eAAe,yBAAyB,CAAC"}
@@ -0,0 +1,54 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // Instellingenkaart: wanneer mag een order gefactureerd worden?
3
+ // Formule: ijkpunt + X dagen, op een vast tijdstip. Zelfafhalers apart.
4
+ import { useEffect, useState } from "react";
5
+ import { useQuery } from "@tanstack/react-query";
6
+ import { useServerFn } from "@tanstack/react-start";
7
+ import { Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Separator, Switch, toast, } from "@flowselections/core";
8
+ import { DEFAULT_INVOICE_TIMING, INVOICE_ANCHORS, describeInvoiceTiming, } from "../../lib/invoice-timing";
9
+ import { getInvoiceTimingSettings, saveInvoiceTimingSettings, } from "../../lib/invoice-timing.functions";
10
+ function Formula({ anchor, offset, businessOnly, time, onChange, idPrefix, }) {
11
+ return (_jsxs("div", { className: "grid gap-4 md:grid-cols-4", children: [_jsxs("div", { className: "md:col-span-2 space-y-1.5", children: [_jsx(Label, { htmlFor: `${idPrefix}-anchor`, children: "IJkpunt" }), _jsxs(Select, { value: anchor, onValueChange: (v) => onChange({ anchor: v }), children: [_jsx(SelectTrigger, { id: `${idPrefix}-anchor`, children: _jsx(SelectValue, { placeholder: "Kies een ijkpunt" }) }), _jsx(SelectContent, { children: INVOICE_ANCHORS.map((a) => (_jsx(SelectItem, { value: a.id, children: a.label }, a.id))) })] }), _jsx("p", { className: "text-xs text-muted-foreground", children: INVOICE_ANCHORS.find((a) => a.id === anchor)?.hint })] }), _jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { htmlFor: `${idPrefix}-offset`, children: "Extra dagen" }), _jsx(Input, { id: `${idPrefix}-offset`, type: "number", min: -60, max: 60, value: offset, onChange: (e) => onChange({ offset: Number(e.target.value) || 0 }) }), _jsxs("div", { className: "flex items-center gap-2 pt-1", children: [_jsx(Switch, { id: `${idPrefix}-business`, checked: businessOnly, onCheckedChange: (v) => onChange({ businessOnly: v }) }), _jsx(Label, { htmlFor: `${idPrefix}-business`, className: "text-xs font-normal", children: "Alleen werkdagen tellen" })] })] }), _jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { htmlFor: `${idPrefix}-time`, children: "Tijdstip" }), _jsx(Input, { id: `${idPrefix}-time`, type: "time", value: time, onChange: (e) => onChange({ time: e.target.value }) })] })] }));
12
+ }
13
+ export function InvoiceTimingSettingsCard() {
14
+ const load = useServerFn(getInvoiceTimingSettings);
15
+ const save = useServerFn(saveInvoiceTimingSettings);
16
+ const [form, setForm] = useState(DEFAULT_INVOICE_TIMING);
17
+ const [saving, setSaving] = useState(false);
18
+ const { data, isLoading } = useQuery({
19
+ queryKey: ["invoice-timing-settings"],
20
+ queryFn: () => load(),
21
+ });
22
+ useEffect(() => {
23
+ if (data)
24
+ setForm(data);
25
+ }, [data]);
26
+ const patch = (p) => setForm((f) => ({ ...f, ...p }));
27
+ async function onSave() {
28
+ setSaving(true);
29
+ try {
30
+ const res = await save({ data: form });
31
+ toast.success(`Factuurmoment opgeslagen — ${res?.recomputed ?? 0} orders herberekend`);
32
+ }
33
+ catch (e) {
34
+ toast.error(e?.message ?? "Opslaan mislukt");
35
+ }
36
+ finally {
37
+ setSaving(false);
38
+ }
39
+ }
40
+ return (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { children: "Factuurmoment" }), _jsx(CardDescription, { children: "Bepaal wanneer een order automatisch klaargezet wordt voor facturatie. De formule is: ijkpunt + extra dagen, op een vast tijdstip." })] }), _jsxs(CardContent, { className: "space-y-6", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Switch, { id: "invoice-timing-enabled", checked: form.enabled, onCheckedChange: (v) => patch({ enabled: v }), disabled: isLoading }), _jsx(Label, { htmlFor: "invoice-timing-enabled", children: "Automatisch factureren inschakelen" })] }), _jsxs("div", { className: "space-y-3", children: [_jsx("h4", { className: "text-sm font-medium", children: "Orders die bezorgd worden" }), _jsx(Formula, { idPrefix: "inv", anchor: form.anchor, offset: form.offsetDays, businessOnly: form.businessDaysOnly, time: form.timeOfDay, onChange: (p) => patch({
41
+ ...(p.anchor ? { anchor: p.anchor } : {}),
42
+ ...(p.offset !== undefined ? { offsetDays: p.offset } : {}),
43
+ ...(p.businessOnly !== undefined ? { businessDaysOnly: p.businessOnly } : {}),
44
+ ...(p.time ? { timeOfDay: p.time } : {}),
45
+ }) }), _jsxs("p", { className: "text-xs text-muted-foreground", children: ["Factureren op: ", describeInvoiceTiming(form, false)] })] }), _jsx(Separator, {}), _jsxs("div", { className: "space-y-3", children: [_jsx("h4", { className: "text-sm font-medium", children: "Orders die de klant zelf ophaalt" }), _jsx(Formula, { idPrefix: "inv-pickup", anchor: form.pickupAnchor, offset: form.pickupOffsetDays, businessOnly: form.pickupBusinessDaysOnly, time: form.pickupTimeOfDay, onChange: (p) => patch({
46
+ ...(p.anchor ? { pickupAnchor: p.anchor } : {}),
47
+ ...(p.offset !== undefined ? { pickupOffsetDays: p.offset } : {}),
48
+ ...(p.businessOnly !== undefined
49
+ ? { pickupBusinessDaysOnly: p.businessOnly }
50
+ : {}),
51
+ ...(p.time ? { pickupTimeOfDay: p.time } : {}),
52
+ }) }), _jsxs("p", { className: "text-xs text-muted-foreground", children: ["Factureren op: ", describeInvoiceTiming(form, true)] })] }), _jsx("div", { className: "flex justify-end", children: _jsx(Button, { onClick: onSave, disabled: saving || isLoading, children: saving ? "Opslaan…" : "Opslaan" }) })] })] }));
53
+ }
54
+ export default InvoiceTimingSettingsCard;
@@ -1 +1 @@
1
- {"version":3,"file":"SalesOrdersTable.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/SalesOrdersTable.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAsBxC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAgFnE,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,OAAO,EACP,aAAa,EACb,aAAa,EACb,WAAW,EACX,cAAc,GACf,EAAE;IACD,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7C,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CACjD,qBAgQA"}
1
+ {"version":3,"file":"SalesOrdersTable.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/SalesOrdersTable.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAuBxC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAmCnE,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,OAAO,EACP,aAAa,EACb,aAAa,EACb,WAAW,EACX,cAAc,GACf,EAAE;IACD,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7C,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CACjD,qBAwOA"}
@@ -1,10 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from "react";
3
3
  import { Badge, Checkbox, Skeleton, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@flowselections/core";
4
- import { formatLoadUnits, mergeTypeNames } from "../../lib/load-carrier-labels";
4
+ import { formatLoadUnits } from "../../lib/load-carrier-labels";
5
5
  import { useAllowedLoadCarriers } from "../../lib/useAllowedLoadCarriers";
6
+ import { orderStageBadgeClass, orderStageLabel } from "../../lib/order-status";
6
7
  import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@flowselections/core";
7
- import { MoreVertical, Package, ArrowDown } from "lucide-react";
8
+ import { MoreVertical, AlertTriangle, ArrowDown } from "lucide-react";
8
9
  function formatDateShort(iso) {
9
10
  if (!iso)
10
11
  return { date: "—", time: "" };
@@ -17,108 +18,60 @@ function formatDateShort(iso) {
17
18
  const time = d.toLocaleTimeString("nl-NL", { hour: "2-digit", minute: "2-digit" });
18
19
  return { date, time };
19
20
  }
20
- function formatDateLong(iso) {
21
+ function formatDelivery(iso) {
21
22
  if (!iso)
22
- return "—";
23
- // Kale datum (zonder tijd): geen verzonnen tijdstip tonen. new Date("2026-07-31")
24
- // is UTC-middernacht en werd eerder als "02:00" weergegeven.
23
+ return { date: "—", time: "" };
25
24
  const dateOnly = /^\d{4}-\d{2}-\d{2}$/.test(iso.trim());
26
25
  const d = new Date(dateOnly ? `${iso.trim()}T00:00:00` : iso);
27
26
  if (Number.isNaN(d.getTime()))
28
- return iso;
29
- return d.toLocaleString("nl-NL", {
30
- day: "numeric",
31
- month: "short",
32
- year: "numeric",
33
- ...(dateOnly ? {} : { hour: "2-digit", minute: "2-digit" }),
34
- });
27
+ return { date: iso, time: "" };
28
+ return {
29
+ date: d.toLocaleDateString("nl-NL", { day: "numeric", month: "short", year: "numeric" }),
30
+ time: dateOnly
31
+ ? ""
32
+ : d.toLocaleTimeString("nl-NL", { hour: "2-digit", minute: "2-digit" }),
33
+ };
35
34
  }
36
- function StatusTag({ status, rawOrder, }) {
37
- const rawStatus = String(rawOrder?.status ?? "").toUpperCase();
38
- if (status.isCancelled || rawStatus === "CANCELLED") {
39
- return (_jsx(Badge, { variant: "outline", className: "border-destructive/30 bg-destructive/10 text-destructive", children: "Geannuleerd" }));
40
- }
41
- if (rawStatus === "DELIVERED" || (status.isShipped && status.isInvoiced)) {
42
- return (_jsx(Badge, { variant: "outline", className: "border-emerald-500/30 bg-emerald-500/10 text-emerald-600 dark:text-emerald-400", children: "Geleverd" }));
43
- }
44
- if (rawStatus === "SHIPPED" || status.isShipped) {
45
- return (_jsx(Badge, { variant: "outline", className: "border-blue-500/30 bg-blue-500/10 text-blue-600 dark:text-blue-400", children: "Onderweg" }));
46
- }
47
- if (status.isControlled) {
48
- return (_jsx(Badge, { variant: "outline", className: "border-amber-500/30 bg-amber-500/10 text-amber-600 dark:text-amber-400", children: "Verzend klaar" }));
49
- }
50
- if (rawStatus === "COMMITTED" || status.isConfirmed) {
51
- return (_jsx(Badge, { variant: "outline", className: "border-sky-500/30 bg-sky-500/10 text-sky-600 dark:text-sky-400", children: "Nog niet gepakt" }));
52
- }
53
- return (_jsx(Badge, { variant: "outline", className: "border-muted-foreground/30 bg-muted text-muted-foreground", children: "Nog picken" }));
35
+ function StatusTag({ order }) {
36
+ const stage = order.stage ?? "incoming";
37
+ return (_jsx(Badge, { variant: "outline", className: `border-transparent ${orderStageBadgeClass(stage)}`, children: orderStageLabel(stage) }));
54
38
  }
55
39
  export function SalesOrdersTable({ orders, loading, onSelectOrder, onDeleteOrder, onEditOrder, onConfirmOrder, }) {
56
40
  const [selected, setSelected] = useState(new Set());
57
41
  const allowedCarrierCodes = useAllowedLoadCarriers().allowed;
58
42
  const allChecked = orders.length > 0 && selected.size === orders.length;
43
+ // Omzetkolom alleen tonen wanneer er daadwerkelijk bedragen bekend zijn.
44
+ const showRevenue = orders.some((o) => (o.revenue ?? 0) > 0);
45
+ const columnCount = showRevenue ? 10 : 9;
59
46
  const toggle = (id) => setSelected((s) => {
60
47
  const n = new Set(s);
61
48
  n.has(id) ? n.delete(id) : n.add(id);
62
49
  return n;
63
50
  });
64
- return (_jsx("div", { className: "rounded-lg border border-border bg-card", children: _jsx("div", { className: "max-h-[70vh] overflow-y-auto overflow-x-auto overscroll-contain [scrollbar-gutter:stable]", style: { WebkitOverflowScrolling: "touch" }, children: _jsxs(Table, { className: "min-w-[950px] [&_thead_th]:sticky [&_thead_th]:top-0 [&_thead_th]:z-10 [&_thead_th]:bg-card", children: [_jsx(TableHeader, { children: _jsxs(TableRow, { className: "hover:bg-transparent", children: [_jsx(TableHead, { className: "w-10", children: _jsx(Checkbox, { checked: allChecked, onCheckedChange: (v) => setSelected(v === true ? new Set(orders.map((o) => o.id)) : new Set()) }) }), _jsx(TableHead, { children: "Omzet" }), _jsx(TableHead, { children: _jsxs("span", { className: "inline-flex items-center gap-1", children: ["Bestelmoment ", _jsx(ArrowDown, { className: "h-3 w-3" })] }) }), _jsx(TableHead, { children: "Karren" }), _jsx(TableHead, { children: "Fusten" }), _jsx(TableHead, { children: "Klant" }), _jsx(TableHead, { children: "Levering" }), _jsx(TableHead, { children: "Status" }), _jsx(TableHead, { className: "w-10" })] }) }), _jsxs(TableBody, { children: [loading &&
65
- Array.from({ length: 6 }).map((_, i) => (_jsx(TableRow, { children: Array.from({ length: 9 }).map((__, j) => (_jsx(TableCell, { children: _jsx(Skeleton, { className: "h-6 w-full" }) }, j))) }, `s-${i}`))), !loading && orders.length === 0 && (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 9, className: "py-12 text-center text-muted-foreground", children: "Geen verkooporders gevonden." }) })), !loading &&
66
- (() => {
67
- // Groepeer orders met dezelfde bufferId volledig tot één rij.
68
- // Orders zonder buffer (of buffer met 1 order) blijven staan.
69
- const groupsMap = new Map();
70
- const order = [];
71
- for (const o of orders) {
72
- const key = o.bufferId && (o.bufferSize ?? 1) > 1 ? `buf:${o.bufferId}` : `one:${o.id}`;
73
- if (!groupsMap.has(key)) {
74
- groupsMap.set(key, []);
75
- order.push(key);
76
- }
77
- groupsMap.get(key).push(o);
78
- }
79
- const groups = order.map((k) => groupsMap.get(k));
80
- // Sorteer groepen op meest recente bestelmoment binnen de groep (desc).
81
- groups.sort((a, b) => {
82
- const ta = a.reduce((m, o) => (o.orderedAt > m ? o.orderedAt : m), "");
83
- const tb = b.reduce((m, o) => (o.orderedAt > m ? o.orderedAt : m), "");
84
- return tb.localeCompare(ta);
85
- });
86
- const nodes = [];
87
- for (const group of groups) {
88
- const isBuffer = group.length > 1;
89
- const first = group[0];
90
- const revenue = group.reduce((s, o) => s + o.revenue, 0);
91
- const karren = group.reduce((s, o) => s + o.karCount, 0);
92
- const fusten = group.reduce((s, o) => s + o.fustCount, 0);
93
- const cartType = mergeTypeNames(group.map((o) => o.cartTypeName));
94
- const crateType = mergeTypeNames(group.map((o) => o.crateTypeName));
95
- const orderedAt = group.reduce((m, o) => (o.orderedAt > m ? o.orderedAt : m), "");
96
- const deliveryAt = group.reduce((m, o) => (o.deliveryAt > m ? o.deliveryAt : m), "");
97
- const ordered = formatDateShort(orderedAt || first.orderedAt);
98
- const rowId = isBuffer ? `buf-${first.bufferId}` : first.id;
99
- const orderNumbers = Array.from(new Set(group.map((o) => o.orderNumber).filter(Boolean)));
100
- nodes.push(_jsxs(TableRow, { className: `align-top cursor-pointer ${isBuffer ? "bg-muted/20 border-l-2 border-primary/40" : ""}`, onClick: () => onSelectOrder?.(first), children: [_jsx(TableCell, { onClick: (e) => e.stopPropagation(), children: _jsx(Checkbox, { checked: selected.has(rowId), onCheckedChange: () => toggle(rowId) }) }), _jsxs(TableCell, { children: [_jsxs("div", { className: "font-medium text-foreground", children: ["\u20AC ", revenue.toFixed(2)] }), isBuffer ? (_jsx("div", { className: "text-xs text-muted-foreground", children: first.isLocal ? "BVO-order" : "FO-order" })) : (first.orderNumber && (_jsx("div", { className: "text-xs text-muted-foreground", children: first.orderNumber })))] }), _jsx(TableCell, { children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Package, { className: "h-4 w-4 text-primary" }), _jsxs("div", { children: [_jsx("div", { className: "font-medium text-foreground", children: ordered.date }), _jsx("div", { className: "text-xs text-muted-foreground", children: ordered.time })] })] }) }), _jsx(TableCell, { children: _jsx("div", { className: "font-medium text-foreground", children: formatLoadUnits(karren, cartType) }) }), _jsx(TableCell, { children: _jsx("div", { className: "font-medium text-foreground", children: formatLoadUnits(fusten, crateType) }) }), _jsxs(TableCell, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "font-medium text-foreground", children: first.customer.name }), isBuffer && (_jsxs(Badge, { variant: "outline", className: "border-primary/30 text-primary", children: ["Buffer \u00B7 ", group.length] })), !isBuffer && first.isLocal && (_jsx(Badge, { variant: "outline", className: "border-primary/30 text-primary", children: "Lokaal" })), (() => {
101
- // Ook bij buffers tonen: alle orders = "Reservering",
102
- // deels = "Reservering · n van m".
103
- const reserved = group.filter((o) => o.isReservation).length;
104
- if (reserved === 0)
105
- return null;
106
- return (_jsx(Badge, { variant: "outline", className: "border-amber-400/40 text-amber-600", children: reserved === group.length
107
- ? "Reservering"
108
- : `Reservering · ${reserved} van ${group.length}` }));
109
- })(), (() => {
110
- // Orders met een inmiddels uitgeschakelde ladingdrager
111
- // markeren, zodat een medewerker een andere kiest.
112
- if (allowedCarrierCodes.length === 0)
113
- return null;
114
- const bad = group.filter((o) => o.loadCarrierType && !allowedCarrierCodes.includes(o.loadCarrierType)).length;
115
- if (bad === 0)
116
- return null;
117
- return (_jsx(Badge, { variant: "outline", className: "border-destructive/40 text-destructive", title: "Deze ladingdrager is uitgeschakeld in de Logistics Engine.", children: bad === group.length
118
- ? "Ladingdrager uitgeschakeld"
119
- : `Ladingdrager uitgeschakeld · ${bad} van ${group.length}` }));
120
- })()] }), _jsx("div", { className: "text-xs text-muted-foreground", children: [first.customer.postalCode, first.customer.city].filter(Boolean).join(" ") })] }), _jsx(TableCell, { className: "text-sm text-foreground", children: formatDateLong(deliveryAt || first.deliveryAt) }), _jsx(TableCell, { children: _jsx(StatusTag, { status: first.status, rawOrder: first.raw?.order }) }), _jsx(TableCell, { onClick: (e) => e.stopPropagation(), children: _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { className: "inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground", children: _jsx(MoreVertical, { className: "h-4 w-4" }) }), _jsxs(DropdownMenuContent, { align: "end", children: [_jsx(DropdownMenuItem, { disabled: isBuffer || !first.isLocal, onClick: () => !isBuffer && first.isLocal && onEditOrder?.(first), title: isBuffer ? "Buffer-orders kunnen niet gebundeld bewerkt worden." : first.isLocal ? undefined : "FO-orders kunnen niet bewerkt worden.", children: "Bewerken" }), _jsx(DropdownMenuItem, { onClick: () => onSelectOrder?.(first), children: "Details bekijken" }), _jsx(DropdownMenuItem, { onClick: () => onConfirmOrder?.(first), children: "Bevestigen" }), !isBuffer && first.isLocal ? (_jsx(DropdownMenuItem, { className: "text-destructive focus:text-destructive", onClick: () => onDeleteOrder?.(first), children: "Verwijderen" })) : (_jsxs(DropdownMenuItem, { disabled: true, title: isBuffer ? "Buffer-orders kunnen niet gebundeld verwijderd worden." : "FO-orders kunnen niet verwijderd worden.", children: ["Verwijderen", isBuffer ? "" : " (FO)"] }))] })] }) })] }, rowId));
121
- }
122
- return nodes;
123
- })()] })] }) }) }));
51
+ return (_jsx("div", { className: "rounded-lg border border-border bg-card", children: _jsx("div", { className: "max-h-[70vh] overflow-y-auto overflow-x-auto overscroll-contain [scrollbar-gutter:stable]", style: { WebkitOverflowScrolling: "touch" }, children: _jsxs(Table, { className: "min-w-[950px] [&_thead_th]:sticky [&_thead_th]:top-0 [&_thead_th]:z-10 [&_thead_th]:bg-card", children: [_jsx(TableHeader, { children: _jsxs(TableRow, { className: "hover:bg-transparent", children: [_jsx(TableHead, { className: "w-10", children: _jsx(Checkbox, { checked: allChecked, onCheckedChange: (v) => setSelected(v === true ? new Set(orders.map((o) => o.id)) : new Set()) }) }), _jsx(TableHead, { children: "Levering" }), _jsx(TableHead, { children: "Klant" }), _jsx(TableHead, { children: "Product" }), _jsx(TableHead, { children: "Karren" }), _jsx(TableHead, { children: "Fusten" }), _jsx(TableHead, { children: "Vervoerder" }), _jsx(TableHead, { children: "Status" }), showRevenue && _jsx(TableHead, { children: "Omzet" }), _jsx(TableHead, { children: _jsxs("span", { className: "inline-flex items-center gap-1", children: ["Besteld ", _jsx(ArrowDown, { className: "h-3 w-3" })] }) }), _jsx(TableHead, { className: "w-10" })] }) }), _jsxs(TableBody, { children: [loading &&
52
+ Array.from({ length: 6 }).map((_, i) => (_jsx(TableRow, { children: Array.from({ length: columnCount + 1 }).map((__, j) => (_jsx(TableCell, { children: _jsx(Skeleton, { className: "h-6 w-full" }) }, j))) }, `s-${i}`))), !loading && orders.length === 0 && (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: columnCount + 1, className: "py-12 text-center text-muted-foreground", children: "Geen verkooporders gevonden." }) })), !loading &&
53
+ orders.map((row) => {
54
+ // Buffers zijn serverside al samengevouwen tot één rij.
55
+ const bufferSize = row.bufferSize ?? 1;
56
+ const isBuffer = !!row.bufferId && bufferSize > 1;
57
+ const rowId = isBuffer ? `buf-${row.bufferId}` : row.id;
58
+ const ordered = formatDateShort(row.orderedAt);
59
+ const delivery = formatDelivery(row.deliveryAt);
60
+ const reserved = row.reservationCount ?? (row.isReservation ? 1 : 0);
61
+ const carrierDisabled = allowedCarrierCodes.length > 0 &&
62
+ !!row.loadCarrierType &&
63
+ !allowedCarrierCodes.includes(row.loadCarrierType);
64
+ const incomplete = row.incomplete ?? [];
65
+ return (_jsxs(TableRow, { className: `align-top cursor-pointer ${isBuffer ? "bg-muted/20 border-l-2 border-primary/40" : ""}`, onClick: () => onSelectOrder?.(row), children: [_jsx(TableCell, { onClick: (e) => e.stopPropagation(), children: _jsx(Checkbox, { checked: selected.has(rowId), onCheckedChange: () => toggle(rowId) }) }), _jsxs(TableCell, { children: [_jsx("div", { className: "font-medium text-foreground", children: delivery.date }), delivery.time && (_jsx("div", { className: "text-xs text-muted-foreground", children: delivery.time }))] }), _jsxs(TableCell, { children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("span", { className: "font-medium text-foreground", children: row.customer.name }), isBuffer && (_jsxs(Badge, { variant: "outline", className: "border-primary/30 text-primary", children: ["Buffer \u00B7 ", bufferSize] })), reserved > 0 && (_jsx(Badge, { variant: "outline", className: "border-amber-400/40 text-amber-600", children: reserved === bufferSize
66
+ ? "Reservering"
67
+ : `Reservering · ${reserved} van ${bufferSize}` })), carrierDisabled && (_jsx(Badge, { variant: "outline", className: "border-destructive/40 text-destructive", title: "Deze ladingdrager is uitgeschakeld in de Logistiek Engine.", children: "Ladingdrager uitgeschakeld" }))] }), _jsx("div", { className: "text-xs text-muted-foreground", children: [row.customer.postalCode, row.customer.city].filter(Boolean).join(" ") }), incomplete.length > 0 && (_jsxs("div", { className: "mt-1 inline-flex items-center gap-1 text-xs text-amber-600", children: [_jsx(AlertTriangle, { className: "h-3 w-3" }), incomplete.join(" · ")] }))] }), _jsxs(TableCell, { children: [_jsx("div", { className: "font-medium text-foreground", children: row.productName || "—" }), _jsx("div", { className: "text-xs text-muted-foreground", children: row.totalPieces > 0 ? `${row.totalPieces} stuks` : "" })] }), _jsx(TableCell, { children: _jsx("div", { className: "font-medium text-foreground", children: formatLoadUnits(row.karCount, row.cartTypeName) }) }), _jsx(TableCell, { children: _jsx("div", { className: "font-medium text-foreground", children: formatLoadUnits(row.fustCount, row.crateTypeName) }) }), _jsx(TableCell, { className: "text-sm text-foreground", children: row.carrierName || _jsx("span", { className: "text-muted-foreground", children: "\u2014" }) }), _jsx(TableCell, { children: _jsx(StatusTag, { order: row }) }), showRevenue && (_jsxs(TableCell, { className: "font-medium text-foreground", children: ["\u20AC ", (row.revenue ?? 0).toFixed(2)] })), _jsxs(TableCell, { children: [_jsx("div", { className: "text-sm text-foreground", children: ordered.date }), _jsx("div", { className: "text-xs text-muted-foreground", children: isBuffer
68
+ ? `${bufferSize} orders`
69
+ : row.orderNumber || ordered.time })] }), _jsx(TableCell, { onClick: (e) => e.stopPropagation(), children: _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { className: "inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground", children: _jsx(MoreVertical, { className: "h-4 w-4" }) }), _jsxs(DropdownMenuContent, { align: "end", children: [_jsx(DropdownMenuItem, { disabled: isBuffer || !row.isLocal, onClick: () => !isBuffer && row.isLocal && onEditOrder?.(row), title: isBuffer
70
+ ? "Buffer-orders kunnen niet gebundeld bewerkt worden."
71
+ : row.isLocal
72
+ ? undefined
73
+ : "FO-orders kunnen niet bewerkt worden.", children: "Bewerken" }), _jsx(DropdownMenuItem, { onClick: () => onSelectOrder?.(row), children: "Details bekijken" }), _jsx(DropdownMenuItem, { onClick: () => onConfirmOrder?.(row), children: "Bevestigen" }), !isBuffer && row.isLocal ? (_jsx(DropdownMenuItem, { className: "text-destructive focus:text-destructive", onClick: () => onDeleteOrder?.(row), children: "Verwijderen" })) : (_jsxs(DropdownMenuItem, { disabled: true, title: isBuffer
74
+ ? "Buffer-orders kunnen niet gebundeld verwijderd worden."
75
+ : "FO-orders kunnen niet verwijderd worden.", children: ["Verwijderen", isBuffer ? "" : " (FO)"] }))] })] }) })] }, rowId));
76
+ })] })] }) }) }));
124
77
  }
@@ -1 +1 @@
1
- {"version":3,"file":"VerkoopOrdersPage.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/VerkoopOrdersPage.tsx"],"names":[],"mappings":"AA8DA,wBAAgB,iBAAiB,gCA+YhC"}
1
+ {"version":3,"file":"VerkoopOrdersPage.d.ts","sourceRoot":"","sources":["../../../src/components/verkoop/VerkoopOrdersPage.tsx"],"names":[],"mappings":"AA4DA,wBAAgB,iBAAiB,gCAoahC"}
@@ -17,12 +17,10 @@ import { SalesOrdersFilters } from "./SalesOrdersFilters";
17
17
  import { SalesOrdersFilterPanel, countActiveFilters, } from "./SalesOrdersFilterPanel";
18
18
  import { SalesOrdersTable } from "./SalesOrdersTable";
19
19
  import { EditLocalOrderDialog } from "./EditLocalOrderDialog";
20
+ import { ORDER_STAGES } from "../../lib/order-status";
20
21
  const STATUS_TABS = [
21
22
  { id: "all", label: "Alle" },
22
- { id: "open", label: "Open" },
23
- { id: "shipped", label: "Verzonden" },
24
- { id: "invoiced", label: "Gefactureerd" },
25
- { id: "cancelled", label: "Geannuleerd" },
23
+ ...ORDER_STAGES.map((s) => ({ id: s.id, label: s.label, hint: s.hint })),
26
24
  ];
27
25
  // Statusfiltering, buffer-groepering en totalen gebeuren serverside
28
26
  // (zie src/lib/salesorders-list.server.ts).
@@ -93,11 +91,14 @@ export function VerkoopOrdersPage() {
93
91
  };
94
92
  const statusCounts = data?.statusCounts ?? {
95
93
  all: 0,
96
- open: 0,
94
+ incoming: 0,
95
+ topick: 0,
96
+ picked: 0,
97
97
  shipped: 0,
98
- invoiced: 0,
99
98
  cancelled: 0,
100
99
  };
100
+ const warnings = data?.warnings ?? [];
101
+ const truncated = data?.truncated ?? false;
101
102
  const totalCount = data?.totalCount ?? 0;
102
103
  const fetchListForExport = useServerFn(listSalesOrders);
103
104
  // Automatisch verversen wanneer de Authenticatie-module de omgeving wijzigt.
@@ -174,14 +175,14 @@ export function VerkoopOrdersPage() {
174
175
  return (_jsxs("main", { className: "space-y-5 p-6", children: [_jsx("div", { className: "flex items-center justify-between border-b border-border", children: _jsx("div", { className: "flex items-center gap-6 overflow-x-auto", children: STATUS_TABS.map((t) => {
175
176
  const active = tab === t.id;
176
177
  const count = statusCounts[t.id];
177
- return (_jsxs("button", { type: "button", onClick: () => setTab(t.id), className: "relative -mb-px flex items-center gap-2 whitespace-nowrap border-b-2 px-1 pb-3 pt-1 text-sm transition-colors " +
178
+ return (_jsxs("button", { type: "button", onClick: () => setTab(t.id), title: t.hint, className: "relative -mb-px flex items-center gap-2 whitespace-nowrap border-b-2 px-1 pb-3 pt-1 text-sm transition-colors " +
178
179
  (active
179
180
  ? "border-primary font-semibold text-foreground"
180
181
  : "border-transparent text-muted-foreground hover:text-foreground"), children: [_jsx("span", { children: t.label }), _jsx("span", { className: "inline-flex h-5 min-w-5 items-center justify-center rounded-full px-1.5 text-[11px] font-semibold " +
181
182
  (active
182
183
  ? "bg-primary text-primary-foreground"
183
184
  : "bg-muted text-muted-foreground"), children: count })] }, t.id));
184
- }) }) }), _jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsx(SalesOrdersFilters, { value: filters, onChange: setFilters }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Button, { variant: "outline", size: "sm", onClick: () => setFilterPanelOpen(true), "aria-label": "Filters", children: [_jsx(Filter, { className: "mr-2 h-4 w-4" }), "Filters", activeFilterCount > 0 && (_jsx("span", { className: "ml-2 inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-primary px-1.5 text-[11px] font-semibold text-primary-foreground", children: activeFilterCount }))] }), _jsx(Button, { variant: "outline", size: "icon", onClick: handleSync, disabled: syncing, "aria-label": "Synchroniseren", title: "Synchroniseren", children: _jsx(RefreshCw, { className: "h-4 w-4 " + (syncing ? "animate-spin" : "") }) }), _jsxs(Button, { variant: "outline", size: "sm", onClick: handleExport, children: [_jsx(Download, { className: "mr-2 h-4 w-4" }), " Exporteren"] }), _jsxs(Button, { size: "sm", onClick: () => navigate({ to: "/floriday-verkoop/verkooporders/nieuw" }), children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), " Bestelling aanmaken"] })] })] }), _jsx(AnalyticsCards, { totals: totals, loading: isLoading }), error && (_jsxs("div", { className: "flex items-start gap-3 rounded-lg border border-destructive/30 bg-destructive/5 p-4 text-sm", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-5 w-5 shrink-0 text-destructive" }), _jsxs("div", { className: "flex-1", children: [_jsx("div", { className: "font-medium text-destructive", children: "Floriday gegevens konden niet geladen worden" }), _jsx("div", { className: "mt-1 text-muted-foreground", children: error.message })] }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => refetch(), disabled: isFetching, children: "Opnieuw proberen" })] })), _jsx(SalesOrdersTable, { orders: paged, loading: isLoading, onSelectOrder: (o) => navigate({
185
+ }) }) }), _jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsx(SalesOrdersFilters, { value: filters, onChange: setFilters }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Button, { variant: "outline", size: "sm", onClick: () => setFilterPanelOpen(true), "aria-label": "Filters", children: [_jsx(Filter, { className: "mr-2 h-4 w-4" }), "Filters", activeFilterCount > 0 && (_jsx("span", { className: "ml-2 inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-primary px-1.5 text-[11px] font-semibold text-primary-foreground", children: activeFilterCount }))] }), _jsx(Button, { variant: "outline", size: "icon", onClick: handleSync, disabled: syncing, "aria-label": "Synchroniseren", title: "Synchroniseren", children: _jsx(RefreshCw, { className: "h-4 w-4 " + (syncing ? "animate-spin" : "") }) }), _jsxs(Button, { variant: "outline", size: "sm", onClick: handleExport, children: [_jsx(Download, { className: "mr-2 h-4 w-4" }), " Exporteren"] }), _jsxs(Button, { size: "sm", onClick: () => navigate({ to: "/floriday-verkoop/verkooporders/nieuw" }), children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), " Bestelling aanmaken"] })] })] }), _jsx(AnalyticsCards, { totals: totals, loading: isLoading }), error && (_jsxs("div", { className: "flex items-start gap-3 rounded-lg border border-destructive/30 bg-destructive/5 p-4 text-sm", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-5 w-5 shrink-0 text-destructive" }), _jsxs("div", { className: "flex-1", children: [_jsx("div", { className: "font-medium text-destructive", children: "Floriday gegevens konden niet geladen worden" }), _jsx("div", { className: "mt-1 text-muted-foreground", children: error.message })] }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => refetch(), disabled: isFetching, children: "Opnieuw proberen" })] })), (warnings.length > 0 || truncated) && (_jsxs("div", { className: "flex items-start gap-3 rounded-lg border border-amber-500/30 bg-amber-500/5 p-3 text-sm", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-600" }), _jsxs("div", { className: "space-y-1 text-muted-foreground", children: [warnings.map((w) => (_jsx("div", { children: w }, w))), truncated && (_jsx("div", { children: "Niet alle orders konden worden meegenomen. Kies een kortere periode voor een volledig overzicht." }))] })] })), _jsx(SalesOrdersTable, { orders: paged, loading: isLoading, onSelectOrder: (o) => navigate({
185
186
  to: "/floriday-verkoop/verkooporders/$salesOrderId",
186
187
  params: { salesOrderId: o.id },
187
188
  }), onDeleteOrder: (o) => {
@@ -3,5 +3,6 @@ export * from "./_core-safelist";
3
3
  export { VerkoopOrdersPage } from "./components/verkoop/VerkoopOrdersPage";
4
4
  export { SalesOrderDetailPage } from "./components/verkoop/SalesOrderDetailPage";
5
5
  export { CreateOrderPage } from "./components/verkoop/CreateOrderPage";
6
+ export { InvoiceTimingSettingsCard } from "./components/verkoop/InvoiceTimingSettings";
6
7
  export declare const floridayVerkoopModule: FlowModule;
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAGvE,eAAO,MAAM,qBAAqB,EAAE,UAiBnC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGvD,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,4CAA4C,CAAC;AAGvF,eAAO,MAAM,qBAAqB,EAAE,UAiBnC,CAAC"}
package/dist-lib/index.js CHANGED
@@ -1,8 +1,10 @@
1
1
  import { ShoppingCart, ListOrdered } from "lucide-react";
2
+ import { InvoiceTimingSettingsCard } from "./components/verkoop/InvoiceTimingSettings";
2
3
  export * from "./_core-safelist";
3
4
  export { VerkoopOrdersPage } from "./components/verkoop/VerkoopOrdersPage";
4
5
  export { SalesOrderDetailPage } from "./components/verkoop/SalesOrderDetailPage";
5
6
  export { CreateOrderPage } from "./components/verkoop/CreateOrderPage";
7
+ export { InvoiceTimingSettingsCard } from "./components/verkoop/InvoiceTimingSettings";
6
8
  export const floridayVerkoopModule = {
7
9
  id: "verkoop",
8
10
  name: "Orders",
@@ -19,5 +21,5 @@ export const floridayVerkoopModule = {
19
21
  },
20
22
  ],
21
23
  },
22
- settingsCards: [],
24
+ settingsCards: [{ component: InvoiceTimingSettingsCard, order: 10 }],
23
25
  };