@flowselections/floriday-afhandeling-module 1.0.42 → 1.0.43

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 (92) hide show
  1. package/dist-lib/components/afhandeling/AutoProcessStatus.d.ts +3 -1
  2. package/dist-lib/components/afhandeling/AutoProcessStatus.d.ts.map +1 -1
  3. package/dist-lib/components/afhandeling/AutoProcessStatus.js +36 -3
  4. package/dist-lib/components/afhandeling/ControleLijstPrint.js +54 -54
  5. package/dist-lib/components/afhandeling/ControlePage.d.ts.map +1 -1
  6. package/dist-lib/components/afhandeling/ControlePage.js +23 -25
  7. package/dist-lib/components/afhandeling/DagDetailDialog.d.ts +1 -1
  8. package/dist-lib/components/afhandeling/DagDetailDialog.d.ts.map +1 -1
  9. package/dist-lib/components/afhandeling/DagDetailDialog.js +410 -121
  10. package/dist-lib/components/afhandeling/PickAgendaView.d.ts.map +1 -1
  11. package/dist-lib/components/afhandeling/PickAgendaView.js +4 -4
  12. package/dist-lib/components/afhandeling/PickingPage.d.ts.map +1 -1
  13. package/dist-lib/components/afhandeling/PickingPage.js +1 -1
  14. package/dist-lib/components/afhandeling/ScanControleView.d.ts +2 -0
  15. package/dist-lib/components/afhandeling/ScanControleView.d.ts.map +1 -0
  16. package/dist-lib/components/afhandeling/ScanControleView.js +158 -0
  17. package/dist-lib/components/afhandeling/VervoerdersPage.js +1 -1
  18. package/dist-lib/components/afhandeling/VerzetOrderDialog.js +1 -1
  19. package/dist-lib/components/afhandeling/WeekAgendaView.js +1 -1
  20. package/dist-lib/components/pickstation/PakbonTemplate.js +70 -70
  21. package/dist-lib/hooks/useCartIndex.d.ts.map +1 -1
  22. package/dist-lib/hooks/useCartIndex.js +6 -1
  23. package/dist-lib/hooks/useEngineTasks.js +1 -1
  24. package/dist-lib/hooks/useKnownOrders.d.ts +11 -0
  25. package/dist-lib/hooks/useKnownOrders.d.ts.map +1 -0
  26. package/dist-lib/hooks/useKnownOrders.js +54 -0
  27. package/dist-lib/hooks/useOrderBuffers.d.ts +17 -0
  28. package/dist-lib/hooks/useOrderBuffers.d.ts.map +1 -0
  29. package/dist-lib/hooks/useOrderBuffers.js +53 -0
  30. package/dist-lib/hooks/useOrderPickDates.d.ts +10 -0
  31. package/dist-lib/hooks/useOrderPickDates.d.ts.map +1 -0
  32. package/dist-lib/hooks/useOrderPickDates.js +62 -0
  33. package/dist-lib/hooks/useOrderPlanning.d.ts +1 -3
  34. package/dist-lib/hooks/useOrderPlanning.d.ts.map +1 -1
  35. package/dist-lib/hooks/useOrderPlanning.js +9 -13
  36. package/dist-lib/hooks/usePickAgenda.d.ts +0 -5
  37. package/dist-lib/hooks/usePickAgenda.d.ts.map +1 -1
  38. package/dist-lib/hooks/usePickAgenda.js +62 -9
  39. package/dist-lib/hooks/usePickMode.d.ts +10 -0
  40. package/dist-lib/hooks/usePickMode.d.ts.map +1 -0
  41. package/dist-lib/hooks/usePickMode.js +31 -0
  42. package/dist-lib/index.d.ts +2 -0
  43. package/dist-lib/index.d.ts.map +1 -1
  44. package/dist-lib/index.js +19 -6
  45. package/dist-lib/integrations/supabase/auth-middleware.d.ts +2027 -86
  46. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  47. package/dist-lib/integrations/supabase/client.server.d.ts +2027 -86
  48. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  49. package/dist-lib/integrations/supabase/client.server.js +1 -1
  50. package/dist-lib/integrations/supabase/moduleClient.d.ts +2027 -86
  51. package/dist-lib/integrations/supabase/moduleClient.d.ts.map +1 -1
  52. package/dist-lib/integrations/supabase/types.d.ts +2097 -114
  53. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  54. package/dist-lib/integrations/supabase/types.js +1 -0
  55. package/dist-lib/lib/afhandelingSettings.functions.d.ts +4018 -140
  56. package/dist-lib/lib/afhandelingSettings.functions.d.ts.map +1 -1
  57. package/dist-lib/lib/carrierSignupMail.server.js +26 -26
  58. package/dist-lib/lib/carriers.functions.d.ts +10072 -367
  59. package/dist-lib/lib/carriers.functions.d.ts.map +1 -1
  60. package/dist-lib/lib/cartAssignments.functions.d.ts +10072 -367
  61. package/dist-lib/lib/cartAssignments.functions.d.ts.map +1 -1
  62. package/dist-lib/lib/cartControl.functions.d.ts +45879 -579
  63. package/dist-lib/lib/cartControl.functions.d.ts.map +1 -1
  64. package/dist-lib/lib/cartControl.functions.js +134 -10
  65. package/dist-lib/lib/deliveryNote.functions.d.ts +25891 -0
  66. package/dist-lib/lib/deliveryNote.functions.d.ts.map +1 -0
  67. package/dist-lib/lib/deliveryNote.functions.js +32 -0
  68. package/dist-lib/lib/engineLayouts.functions.d.ts +25889 -0
  69. package/dist-lib/lib/engineLayouts.functions.d.ts.map +1 -0
  70. package/dist-lib/lib/engineLayouts.functions.js +42 -0
  71. package/dist-lib/lib/floriday.functions.d.ts +27885 -52
  72. package/dist-lib/lib/floriday.functions.d.ts.map +1 -1
  73. package/dist-lib/lib/floriday.functions.js +118 -343
  74. package/dist-lib/lib/logisticsEngine/reschedule.d.ts +17 -0
  75. package/dist-lib/lib/logisticsEngine/reschedule.d.ts.map +1 -1
  76. package/dist-lib/lib/logisticsEngine/reschedule.js +63 -0
  77. package/dist-lib/lib/orderFulfilment.functions.d.ts +25891 -0
  78. package/dist-lib/lib/orderFulfilment.functions.d.ts.map +1 -0
  79. package/dist-lib/lib/orderFulfilment.functions.js +35 -0
  80. package/dist-lib/lib/orderStatus.d.ts +10 -0
  81. package/dist-lib/lib/orderStatus.d.ts.map +1 -0
  82. package/dist-lib/lib/orderStatus.js +81 -0
  83. package/dist-lib/lib/pickDates.functions.d.ts +25896 -0
  84. package/dist-lib/lib/pickDates.functions.d.ts.map +1 -0
  85. package/dist-lib/lib/pickDates.functions.js +56 -0
  86. package/dist-lib/lib/pickMode.d.ts +14 -0
  87. package/dist-lib/lib/pickMode.d.ts.map +1 -0
  88. package/dist-lib/lib/pickMode.js +103 -0
  89. package/dist-lib/lib/printing.d.ts +3 -1
  90. package/dist-lib/lib/printing.d.ts.map +1 -1
  91. package/dist-lib/lib/printing.js +1 -0
  92. package/package.json +1 -1
@@ -1,5 +1,7 @@
1
1
  interface Props {
2
2
  salesOrderId: string;
3
+ /** Ordernummer (order_ref) — nodig om opnieuw in te plannen via de Engine. */
4
+ orderRef?: string | null;
3
5
  /** Datum waarop de auto-verwerking mag starten (targetPickDate). */
4
6
  autoProcessDate?: Date | null;
5
7
  /** Toon knop "Nu verwerken" ook als datum nog niet bereikt. */
@@ -7,6 +9,6 @@ interface Props {
7
9
  /** Compact = alleen badge, geen knoppen. */
8
10
  compact?: boolean;
9
11
  }
10
- export declare function AutoProcessStatus({ salesOrderId, autoProcessDate, allowManualTrigger, compact, }: Props): import("react").JSX.Element;
12
+ export declare function AutoProcessStatus({ salesOrderId, orderRef, autoProcessDate, allowManualTrigger, compact, }: Props): import("react").JSX.Element;
11
13
  export {};
12
14
  //# sourceMappingURL=AutoProcessStatus.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AutoProcessStatus.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/AutoProcessStatus.tsx"],"names":[],"mappings":"AAUA,UAAU,KAAK;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,eAAe,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAC9B,+DAA+D;IAC/D,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,4CAA4C;IAC5C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAeD,wBAAgB,iBAAiB,CAAC,EAChC,YAAY,EACZ,eAAe,EACf,kBAAyB,EACzB,OAAe,GAChB,EAAE,KAAK,+BAiJP"}
1
+ {"version":3,"file":"AutoProcessStatus.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/AutoProcessStatus.tsx"],"names":[],"mappings":"AAYA,UAAU,KAAK;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,oEAAoE;IACpE,eAAe,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAC9B,+DAA+D;IAC/D,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,4CAA4C;IAC5C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAeD,wBAAgB,iBAAiB,CAAC,EAChC,YAAY,EACZ,QAAQ,EACR,eAAe,EACf,kBAAyB,EACzB,OAAe,GAChB,EAAE,KAAK,+BAiLP"}
@@ -1,9 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useEffect, useState } from "react";
3
+ import { useQueryClient } from "@tanstack/react-query";
3
4
  import { Badge, Button, toast } from "@flowselections/core";
4
5
  import { CheckCircle2, Clock, Loader2, PlayCircle, RefreshCw, AlertTriangle } from "lucide-react";
5
6
  import { autoProcessSalesOrder, fetchAutoProcessStatuses, } from "../../lib/floridayAutoProcess";
6
7
  import { supabase } from "../../integrations/supabase/moduleClient";
8
+ import { replanToNextDeliveryMoment } from "../../lib/logisticsEngine/reschedule";
7
9
  const NL_DATE = new Intl.DateTimeFormat("nl-NL", { day: "2-digit", month: "short" });
8
10
  function formatWaiting(date) {
9
11
  const today = new Date();
@@ -17,17 +19,20 @@ function formatWaiting(date) {
17
19
  return "Verwerkt morgen";
18
20
  return `Wacht tot ${NL_DATE.format(target)} (${diffDays} dagen)`;
19
21
  }
20
- export function AutoProcessStatus({ salesOrderId, autoProcessDate, allowManualTrigger = true, compact = false, }) {
22
+ export function AutoProcessStatus({ salesOrderId, orderRef, autoProcessDate, allowManualTrigger = true, compact = false, }) {
21
23
  const [row, setRow] = useState(null);
22
24
  const [loading, setLoading] = useState(false);
25
+ const queryClient = useQueryClient();
23
26
  useEffect(() => {
24
27
  let cancelled = false;
25
28
  fetchAutoProcessStatuses([salesOrderId]).then((m) => {
26
29
  if (!cancelled)
27
30
  setRow(m.get(salesOrderId) ?? null);
28
31
  });
32
+ // Unieke kanaalnaam per instantie: dezelfde order kan meerdere keren in
33
+ // beeld staan en Supabase hergebruikt anders een al geabonneerd kanaal.
29
34
  const channel = supabase
30
- .channel(`auto-process-${salesOrderId}`)
35
+ .channel(`auto-process-${salesOrderId}-${Math.random().toString(36).slice(2)}`)
31
36
  .on("postgres_changes", {
32
37
  event: "*",
33
38
  schema: "public",
@@ -48,6 +53,34 @@ export function AutoProcessStatus({ salesOrderId, autoProcessDate, allowManualTr
48
53
  const handleProcess = async () => {
49
54
  setLoading(true);
50
55
  try {
56
+ if (orderRef) {
57
+ // Opnieuw inplannen op het eerstvolgende aflevermoment; de Engine
58
+ // bepaalt daarna zelf de pickdag en de bijbehorende taken.
59
+ const res = await replanToNextDeliveryMoment(orderRef);
60
+ if (!res.ok) {
61
+ toast.error(res.error ?? "Opnieuw inplannen mislukt");
62
+ }
63
+ else {
64
+ const d = res.moment
65
+ ? new Date(`${res.moment.date}T00:00:00`).toLocaleDateString("nl-NL")
66
+ : null;
67
+ toast.success(d
68
+ ? `Ingepland op ${d}${res.moment?.time ? ` om ${res.moment.time}` : ""}`
69
+ : "Order opnieuw ingepland");
70
+ // Direct verversen zodat de nieuwe leverdatum en de status meteen
71
+ // in beeld staan, precies zoals bij de andere bestellingen.
72
+ await Promise.all([
73
+ queryClient.invalidateQueries({ queryKey: ["logistics-pick-agenda"] }),
74
+ queryClient.invalidateQueries({ queryKey: ["engine", "tasks"] }),
75
+ queryClient.invalidateQueries({ queryKey: ["order-buffers"] }),
76
+ queryClient.invalidateQueries({ queryKey: ["floriday", "orders"] }),
77
+ queryClient.invalidateQueries({ queryKey: ["logistics-cart-index"] }),
78
+ queryClient.invalidateQueries({ queryKey: ["known-orders"] }),
79
+ ]);
80
+ await queryClient.refetchQueries({ queryKey: ["logistics-pick-agenda"], type: "active" });
81
+ }
82
+ return;
83
+ }
51
84
  const res = await autoProcessSalesOrder(salesOrderId);
52
85
  toast.success(res.status === "done"
53
86
  ? "Verwerkt — afleverbrief wordt aangemaakt"
@@ -99,5 +132,5 @@ export function AutoProcessStatus({ salesOrderId, autoProcessDate, allowManualTr
99
132
  return _jsx(_Fragment, { children: badge });
100
133
  const showRetry = status === "error";
101
134
  const showTrigger = allowManualTrigger && status !== "done" && status !== "acknowledging" && !loading;
102
- return (_jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [badge, showTrigger ? (_jsx(Button, { size: "sm", variant: showRetry ? "outline" : "secondary", onClick: handleProcess, disabled: loading, children: showRetry ? (_jsxs(_Fragment, { children: [_jsx(RefreshCw, { className: "h-3 w-3 mr-1" }), " Opnieuw"] })) : (_jsxs(_Fragment, { children: [_jsx(PlayCircle, { className: "h-3 w-3 mr-1" }), " Nu verwerken"] })) })) : null] }));
135
+ return (_jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [badge, showTrigger ? (_jsx(Button, { size: "sm", variant: showRetry ? "outline" : "secondary", onClick: handleProcess, disabled: loading, children: showRetry ? (_jsxs(_Fragment, { children: [_jsx(RefreshCw, { className: "h-3 w-3 mr-1" }), " Opnieuw"] })) : (_jsxs(_Fragment, { children: [_jsx(PlayCircle, { className: "h-3 w-3 mr-1" }), " ", orderRef ? "Nu inplannen" : "Nu verwerken"] })) })) : null] }));
103
136
  }
@@ -70,62 +70,62 @@ export function renderControleLijstHtml(carts, lang = "nl") {
70
70
  });
71
71
  const rows = sorted.length
72
72
  ? sorted
73
- .map(({ cart: c, klaarzet }) => `
74
- <tr>
75
- <td class="mono bold">${esc(c.cartNumber ?? "—")}</td>
76
- <td class="right">${esc(c.cratesOnCart ?? "—")}</td>
77
- <td class="bold">${esc(countryCode(c.country) ?? c.country ?? "—")}</td>
78
- <td class="bold">${esc(klaarzet.label)}</td>
79
- <td>${esc(statusLabel(c.status, c.printedCount))}</td>
73
+ .map(({ cart: c, klaarzet }) => `
74
+ <tr>
75
+ <td class="mono bold">${esc(c.cartNumber ?? "—")}</td>
76
+ <td class="right">${esc(c.cratesOnCart ?? "—")}</td>
77
+ <td class="bold">${esc(countryCode(c.country) ?? c.country ?? "—")}</td>
78
+ <td class="bold">${esc(klaarzet.label)}</td>
79
+ <td>${esc(statusLabel(c.status, c.printedCount))}</td>
80
80
  </tr>`)
81
81
  .join("")
82
82
  : `<tr><td colspan="5" class="empty">${esc(t.noCartsToday)}</td></tr>`;
83
- return `<!DOCTYPE html>
84
- <html lang="${esc(lang)}">
85
- <head>
86
- <meta charset="utf-8" />
87
- <title>${esc(t.checklistTitle)}</title>
88
- <style>
89
- @page { size: A4 portrait; margin: 12mm; }
90
- body { font-family: Arial, Helvetica, sans-serif; color: #000; margin: 0; }
91
- h1 { font-size: 20px; margin: 0; }
92
- .head { display: flex; align-items: baseline; justify-content: space-between;
93
- border-bottom: 1px solid #000; padding-bottom: 6px; margin-bottom: 12px; }
94
- .total { font-size: 12px; margin-bottom: 10px; }
95
- table { width: 100%; border-collapse: collapse; font-size: 11px; }
96
- th { text-align: left; border-bottom: 1px solid #000; padding: 3px 6px 3px 0; }
97
- td { border-bottom: 1px solid #ccc; padding: 6px 6px 6px 0; white-space: nowrap; }
98
- td.right, th.right { text-align: right; }
99
- .mono { font-family: "Courier New", monospace; }
100
- .bold { font-weight: 700; }
101
- .empty { text-align: center; color: #666; padding: 24px 0; border: none; }
102
- .sign { margin-top: 24px; font-size: 11px; }
103
- .sign div { margin-top: 8px; }
104
- .line { display: inline-block; border-bottom: 1px solid #000; width: 220px; }
105
- tr { page-break-inside: avoid; }
106
- thead { display: table-header-group; }
107
- </style>
108
- </head>
109
- <body>
110
- <div class="head"><h1>${esc(t.checklistTitle)}</h1><div>${esc(today)}</div></div>
111
- <div class="total">${esc(t.totalCarts)}: <strong>${carts.length}</strong></div>
112
- <table>
113
- <thead>
114
- <tr>
115
- <th>${esc(t.colKarnr)}</th>
116
- <th class="right">${esc(t.colFusten)}</th>
117
- <th>${esc(t.colLand)}</th>
118
- <th>${esc(t.colKlaarzetten)}</th>
119
- <th>${esc(t.colStatus)}</th>
120
- </tr>
121
- </thead>
122
- <tbody>${rows}</tbody>
123
- </table>
124
- <div class="sign">
125
- <div>${esc(t.checkedBy)}: <span class="line"></span></div>
126
- <div>${esc(t.dateTime)}: <span class="line"></span></div>
127
- <div>${esc(t.signature)}: <span class="line"></span></div>
128
- </div>
129
- </body>
83
+ return `<!DOCTYPE html>
84
+ <html lang="${esc(lang)}">
85
+ <head>
86
+ <meta charset="utf-8" />
87
+ <title>${esc(t.checklistTitle)}</title>
88
+ <style>
89
+ @page { size: A4 portrait; margin: 12mm; }
90
+ body { font-family: Arial, Helvetica, sans-serif; color: #000; margin: 0; }
91
+ h1 { font-size: 20px; margin: 0; }
92
+ .head { display: flex; align-items: baseline; justify-content: space-between;
93
+ border-bottom: 1px solid #000; padding-bottom: 6px; margin-bottom: 12px; }
94
+ .total { font-size: 12px; margin-bottom: 10px; }
95
+ table { width: 100%; border-collapse: collapse; font-size: 11px; }
96
+ th { text-align: left; border-bottom: 1px solid #000; padding: 3px 6px 3px 0; }
97
+ td { border-bottom: 1px solid #ccc; padding: 6px 6px 6px 0; white-space: nowrap; }
98
+ td.right, th.right { text-align: right; }
99
+ .mono { font-family: "Courier New", monospace; }
100
+ .bold { font-weight: 700; }
101
+ .empty { text-align: center; color: #666; padding: 24px 0; border: none; }
102
+ .sign { margin-top: 24px; font-size: 11px; }
103
+ .sign div { margin-top: 8px; }
104
+ .line { display: inline-block; border-bottom: 1px solid #000; width: 220px; }
105
+ tr { page-break-inside: avoid; }
106
+ thead { display: table-header-group; }
107
+ </style>
108
+ </head>
109
+ <body>
110
+ <div class="head"><h1>${esc(t.checklistTitle)}</h1><div>${esc(today)}</div></div>
111
+ <div class="total">${esc(t.totalCarts)}: <strong>${carts.length}</strong></div>
112
+ <table>
113
+ <thead>
114
+ <tr>
115
+ <th>${esc(t.colKarnr)}</th>
116
+ <th class="right">${esc(t.colFusten)}</th>
117
+ <th>${esc(t.colLand)}</th>
118
+ <th>${esc(t.colKlaarzetten)}</th>
119
+ <th>${esc(t.colStatus)}</th>
120
+ </tr>
121
+ </thead>
122
+ <tbody>${rows}</tbody>
123
+ </table>
124
+ <div class="sign">
125
+ <div>${esc(t.checkedBy)}: <span class="line"></span></div>
126
+ <div>${esc(t.dateTime)}: <span class="line"></span></div>
127
+ <div>${esc(t.signature)}: <span class="line"></span></div>
128
+ </div>
129
+ </body>
130
130
  </html>`;
131
131
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ControlePage.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/ControlePage.tsx"],"names":[],"mappings":"AA+JA,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;CAAO,+BAw1BpE"}
1
+ {"version":3,"file":"ControlePage.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/ControlePage.tsx"],"names":[],"mappings":"AAkJA,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;CAAO,+BAu3BpE"}
@@ -2,11 +2,12 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  import { useEffect, useMemo, useRef, useState } from "react";
3
3
  import { supabase } from "../../integrations/supabase/moduleClient";
4
4
  import { Button, Card, Checkbox, Dialog, DialogDescription, DialogTitle, Input, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Textarea, Badge, toast, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@flowselections/core";
5
- import { Printer, CheckCircle2, AlertTriangle, History, ChevronLeft, ChevronRight } from "lucide-react";
6
- import { ResponsiveDialogBody, ResponsiveDialogContent, ResponsiveDialogFooter, ResponsiveDialogHeader, } from "../ui/responsive-dialog";
5
+ import { Printer, CheckCircle2, AlertTriangle, History, ChevronLeft, ChevronRight, ScanLine } from "lucide-react";
6
+ import { ResponsiveDialogBody, ResponsiveDialogContent, ResponsiveDialogFooter, ResponsiveDialogHeader, } from "../../components/ui/responsive-dialog";
7
7
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
8
8
  import { useServerFn } from "@tanstack/react-start";
9
- import { getTodaysControlCarts, getControlRescheduleProposals, submitControlSession, listControlHistory, getControlSessionDetail, getControlDraft, saveControlDraft, } from "../../lib/cartControl.functions";
9
+ import { getTodaysControlCarts, getControlRescheduleProposals, submitControlSession, listControlHistory, getControlSessionDetail, getControlDraft, listDeliveredToday, saveControlDraft, } from "../../lib/cartControl.functions";
10
+ import { ScanControleView } from "./ScanControleView";
10
11
  import { renderControleLijstHtml } from "./ControleLijstPrint";
11
12
  import { printHtmlDocument, printFoutMelding } from "../../lib/printing";
12
13
  function dayDiffFromToday(iso) {
@@ -36,24 +37,6 @@ function relDayLabel(iso) {
36
37
  return `${Math.abs(diff)} dagen geleden`;
37
38
  return d.toLocaleDateString("nl-NL", { weekday: "short", day: "2-digit", month: "2-digit" });
38
39
  }
39
- function fmtTime(time) {
40
- if (!time)
41
- return null;
42
- const m = /^(\d{1,2}):(\d{2})/.exec(time.trim());
43
- if (!m)
44
- return null;
45
- return `${m[1].padStart(2, "0")}:${m[2]}`;
46
- }
47
- /** "vandaag - 10:00" */
48
- function fmtPickup(iso, time) {
49
- if (!iso)
50
- return "—";
51
- const d = new Date(iso);
52
- if (Number.isNaN(d.getTime()))
53
- return iso;
54
- const t = fmtTime(time);
55
- return t ? `${relDayLabel(iso)} - ${t}` : relDayLabel(iso);
56
- }
57
40
  function fmtDate(iso) {
58
41
  if (!iso)
59
42
  return "—";
@@ -114,6 +97,7 @@ export function ControlePage({ onExit } = {}) {
114
97
  const fetchProposals = useServerFn(getControlRescheduleProposals);
115
98
  const submit = useServerFn(submitControlSession);
116
99
  const fetchDraft = useServerFn(getControlDraft);
100
+ const fetchDelivered = useServerFn(listDeliveredToday);
117
101
  const saveDraft = useServerFn(saveControlDraft);
118
102
  const cartsQ = useQuery({
119
103
  queryKey: ["control", "today"],
@@ -129,6 +113,13 @@ export function ControlePage({ onExit } = {}) {
129
113
  refetchOnMount: "always",
130
114
  refetchOnWindowFocus: true,
131
115
  });
116
+ const deliveredQ = useQuery({
117
+ queryKey: ["control", "delivered"],
118
+ queryFn: () => fetchDelivered(),
119
+ enabled: tab === "afgeleverd",
120
+ refetchOnMount: "always",
121
+ refetchOnWindowFocus: true,
122
+ });
132
123
  const draftQ = useQuery({
133
124
  queryKey: controlDraftQueryKey,
134
125
  queryFn: async () => (await fetchDraft()),
@@ -450,6 +441,7 @@ export function ControlePage({ onExit } = {}) {
450
441
  setPage(pageCount);
451
442
  }, [pageCount, page]);
452
443
  const pagedCarts = useMemo(() => carts.slice((currentPage - 1) * pageSize, currentPage * pageSize), [carts, currentPage, pageSize]);
444
+ // Geen eigen hernummering meer: het karnummer komt uitsluitend uit de Engine.
453
445
  const pendingProposals = pendingProposal?.proposals ?? [];
454
446
  const pendingBlocked = pendingProposal?.blocked ?? [];
455
447
  const pendingNotReadyCount = pendingProposals.length + pendingBlocked.length;
@@ -507,13 +499,13 @@ export function ControlePage({ onExit } = {}) {
507
499
  finally {
508
500
  setPrintBezig(false);
509
501
  }
510
- }, children: [_jsx(Printer, { className: "h-4 w-4 mr-2" }), printBezig ? "Bezig met printen…" : "Controlelijst afdrukken"] }), _jsxs(Button, { onClick: runControl, disabled: submitM.isPending || proposalM.isPending || carts.length === 0 || tab !== "controle", children: [_jsx(CheckCircle2, { className: "h-4 w-4 mr-2" }), proposalM.isPending ? "Controleren…" : "Controle uitvoeren"] })] })] }), _jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { variant: tab === "controle" ? "default" : "outline", onClick: () => setTab("controle"), children: "Controle" }), _jsxs(Button, { variant: tab === "historie" ? "default" : "outline", onClick: () => setTab("historie"), children: [_jsx(History, { className: "h-4 w-4 mr-2" }), "Historie"] })] }), tab === "controle" && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex flex-wrap gap-3 items-center", children: [_jsxs(Card, { className: "p-3", children: [_jsx("div", { className: "text-xs text-muted-foreground", children: "Totaal karren vandaag" }), _jsx("div", { className: "text-2xl font-semibold", children: stats.total })] }), _jsxs(Card, { className: "p-3", children: [_jsx("div", { className: "text-xs text-muted-foreground", children: "Geprint" }), _jsx("div", { className: "text-2xl font-semibold", children: stats.printed })] }), _jsxs(Card, { className: "p-3", children: [_jsx("div", { className: "text-xs text-muted-foreground", children: "Aangevinkt" }), _jsx("div", { className: "text-2xl font-semibold", children: stats.checked })] })] }), _jsxs(Card, { className: "p-0 overflow-hidden", children: [_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { className: "w-12", children: _jsx(Checkbox, { checked: carts.length > 0 && carts.every((c) => checked.has(controlCartKey(c)))
502
+ }, children: [_jsx(Printer, { className: "h-4 w-4 mr-2" }), printBezig ? "Bezig met printen…" : "Controlelijst afdrukken"] }), _jsxs(Button, { onClick: runControl, disabled: submitM.isPending || proposalM.isPending || carts.length === 0 || tab !== "controle", children: [_jsx(CheckCircle2, { className: "h-4 w-4 mr-2" }), proposalM.isPending ? "Controleren…" : "Controle uitvoeren"] })] })] }), _jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { variant: tab === "controle" ? "default" : "outline", onClick: () => setTab("controle"), children: "Controle" }), _jsxs(Button, { variant: tab === "scan" ? "default" : "outline", onClick: () => setTab("scan"), children: [_jsx(ScanLine, { className: "h-4 w-4 mr-2" }), "Scancontrole"] }), _jsxs(Button, { variant: tab === "afgeleverd" ? "default" : "outline", onClick: () => setTab("afgeleverd"), children: [_jsx(CheckCircle2, { className: "h-4 w-4 mr-2" }), "Afgeleverd"] }), _jsxs(Button, { variant: tab === "historie" ? "default" : "outline", onClick: () => setTab("historie"), children: [_jsx(History, { className: "h-4 w-4 mr-2" }), "Historie"] })] }), tab === "controle" && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex flex-wrap gap-3 items-center", children: [_jsxs(Card, { className: "p-3", children: [_jsx("div", { className: "text-xs text-muted-foreground", children: "Totaal karren vandaag" }), _jsx("div", { className: "text-2xl font-semibold", children: stats.total })] }), _jsxs(Card, { className: "p-3", children: [_jsx("div", { className: "text-xs text-muted-foreground", children: "Geprint" }), _jsx("div", { className: "text-2xl font-semibold", children: stats.printed })] }), _jsxs(Card, { className: "p-3", children: [_jsx("div", { className: "text-xs text-muted-foreground", children: "Aangevinkt" }), _jsx("div", { className: "text-2xl font-semibold", children: stats.checked })] })] }), _jsxs(Card, { className: "p-0 overflow-hidden", children: [_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { className: "w-12", children: _jsx(Checkbox, { checked: carts.length > 0 && carts.every((c) => checked.has(controlCartKey(c)))
511
503
  ? true
512
504
  : carts.some((c) => checked.has(controlCartKey(c)))
513
505
  ? "indeterminate"
514
- : false, onCheckedChange: (v) => toggleAll(!!v) }) }), _jsx(TableHead, { children: "Ordernummer" }), _jsx(TableHead, { children: "Ophaaldatum" }), _jsx(TableHead, { children: "Uitgeprint" })] }) }), _jsxs(TableBody, { children: [cartsQ.isLoading && (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 4, className: "text-center text-muted-foreground py-8", children: "Laden\u2026" }) })), !cartsQ.isLoading && carts.length === 0 && (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 4, className: "text-center text-muted-foreground py-8", children: "Geen karren om vandaag te controleren." }) })), pagedCarts.map((c) => {
506
+ : false, onCheckedChange: (v) => toggleAll(!!v) }) }), _jsx(TableHead, { children: "Ordernummer" }), _jsx(TableHead, { children: "Karnummer" }), _jsx(TableHead, { children: "Uitgeprint" })] }) }), _jsxs(TableBody, { children: [cartsQ.isLoading && (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 4, className: "text-center text-muted-foreground py-8", children: "Laden\u2026" }) })), !cartsQ.isLoading && carts.length === 0 && (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 4, className: "text-center text-muted-foreground py-8", children: "Geen karren om vandaag te controleren." }) })), pagedCarts.map((c) => {
515
507
  const k = controlCartKey(c);
516
- return (_jsxs(TableRow, { children: [_jsx(TableCell, { children: _jsx(Checkbox, { checked: checked.has(k), onCheckedChange: (v) => toggle(k, !!v) }) }), _jsx(TableCell, { className: "font-mono font-semibold", children: (c.orderNumbers?.length ?? 0) > 0 ? (_jsx("div", { className: "flex flex-col gap-0.5", children: c.orderNumbers.map((n) => (_jsx("span", { children: n }, n))) })) : (c.orderNumber || "—") }), _jsx(TableCell, { children: fmtPickup(c.pickupDate, c.pickupTime) }), _jsx(TableCell, { children: (c.printedToday ?? (c.printedCount ?? 0) > 0) ? (_jsx(Badge, { variant: "secondary", children: "Ja" })) : (_jsx(Badge, { variant: "outline", children: "Nee" })) })] }, k));
508
+ return (_jsxs(TableRow, { children: [_jsx(TableCell, { children: _jsx(Checkbox, { checked: checked.has(k), onCheckedChange: (v) => toggle(k, !!v) }) }), _jsxs(TableCell, { className: "font-mono font-semibold", children: [c.orderNumber || "—", _jsxs("span", { className: "ml-2 text-muted-foreground font-normal", children: ["[", c.cartSeq, " - ", c.cartTotal ?? c.cartSeq, "]"] })] }), _jsx(TableCell, { className: "font-mono font-semibold", children: c.cartNumber ?? "—" }), _jsx(TableCell, { children: (c.printedToday ?? (c.printedCount ?? 0) > 0) ? (_jsx(Badge, { variant: "secondary", children: "Ja" })) : (_jsx(Badge, { variant: "outline", children: "Nee" })) })] }, k));
517
509
  })] })] }), carts.length > 0 && (_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 border-t bg-muted/20 px-4 py-3 text-sm", children: [_jsxs("span", { className: "text-muted-foreground", children: [carts.length, " resultaten"] }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("span", { className: "text-muted-foreground", children: "Resultaten per pagina" }), _jsxs(Select, { value: String(pageSize), onValueChange: (v) => {
518
510
  setPageSize(Number(v));
519
511
  setPage(1);
@@ -523,7 +515,7 @@ export function ControlePage({ onExit } = {}) {
523
515
  ? "Voortgang automatisch opgeslagen"
524
516
  : lastSavedRef.current && notes === lastSavedRef.current
525
517
  ? "Concept bewaard"
526
- : "" })] }), _jsx(Textarea, { value: notes, onChange: (e) => setNotes(e.target.value), placeholder: "Bijzonderheden, afwijkingen\u2026", rows: 3 }), _jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: "Wordt automatisch bewaard tot de controle definitief is goedgekeurd." })] })] })), tab === "historie" && _jsx(HistorieView, { loading: histQ.isLoading, sessions: histQ.data?.sessions ?? [] }), _jsx(Dialog, { open: !!result, onOpenChange: (v) => !v && setResult(null), children: _jsxs(ResponsiveDialogContent, { size: "md", children: [_jsxs(ResponsiveDialogHeader, { children: [_jsx(DialogTitle, { children: "Resultaat controle" }), _jsxs(DialogDescription, { children: [result?.checkedCount, " klaar \u00B7 ", result?.rescheduledCount, " doorgeschoven \u00B7", " ", result?.blockedCount, " geblokkeerd"] })] }), _jsxs(ResponsiveDialogBody, { className: "space-y-4", children: [result?.blocked && result.blocked.length > 0 && (_jsxs("div", { className: "rounded-md border border-destructive/40 bg-destructive/10 p-3 space-y-2", children: [_jsxs("div", { className: "flex items-start gap-2 text-destructive font-medium", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0" }), _jsx("span", { children: "De volgende karren kunnen niet automatisch worden doorgeschoven omdat hierdoor de planning of levering in gevaar komt." })] }), _jsx(BlockedTable, { blocked: result.blocked })] })), result?.rescheduled && result.rescheduled.length > 0 && (_jsxs("div", { className: "border rounded-md p-3", children: [_jsx("div", { className: "font-medium mb-2", children: "Doorgeschoven karren" }), _jsx("ul", { className: "text-sm space-y-1", children: result.rescheduled.map((r, i) => (_jsxs("li", { children: [_jsx("span", { className: "font-mono", children: r.cartNumber ?? "—" }), " \u2014", " ", r.customerName, " \u2192 nieuwe pickdatum", " ", _jsx("strong", { children: fmtDate(r.newPickDate) })] }, i))) })] }))] }), _jsx(ResponsiveDialogFooter, { children: _jsx(Button, { onClick: () => {
518
+ : "" })] }), _jsx(Textarea, { value: notes, onChange: (e) => setNotes(e.target.value), placeholder: "Bijzonderheden, afwijkingen\u2026", rows: 3 }), _jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: "Wordt automatisch bewaard tot de controle definitief is goedgekeurd." })] })] })), tab === "scan" && _jsx(ScanControleView, {}), tab === "afgeleverd" && (_jsx(AfgeleverdView, { loading: deliveredQ.isLoading, carts: deliveredQ.data?.carts ?? [] })), tab === "historie" && _jsx(HistorieView, { loading: histQ.isLoading, sessions: histQ.data?.sessions ?? [] }), _jsx(Dialog, { open: !!result, onOpenChange: (v) => !v && setResult(null), children: _jsxs(ResponsiveDialogContent, { size: "md", children: [_jsxs(ResponsiveDialogHeader, { children: [_jsx(DialogTitle, { children: "Resultaat controle" }), _jsxs(DialogDescription, { children: [result?.checkedCount, " klaar \u00B7 ", result?.rescheduledCount, " doorgeschoven \u00B7", " ", result?.blockedCount, " geblokkeerd"] })] }), _jsxs(ResponsiveDialogBody, { className: "space-y-4", children: [result?.blocked && result.blocked.length > 0 && (_jsxs("div", { className: "rounded-md border border-destructive/40 bg-destructive/10 p-3 space-y-2", children: [_jsxs("div", { className: "flex items-start gap-2 text-destructive font-medium", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0" }), _jsx("span", { children: "De volgende karren kunnen niet automatisch worden doorgeschoven omdat hierdoor de planning of levering in gevaar komt." })] }), _jsx(BlockedTable, { blocked: result.blocked })] })), result?.rescheduled && result.rescheduled.length > 0 && (_jsxs("div", { className: "border rounded-md p-3", children: [_jsx("div", { className: "font-medium mb-2", children: "Doorgeschoven karren" }), _jsx("ul", { className: "text-sm space-y-1", children: result.rescheduled.map((r, i) => (_jsxs("li", { children: [_jsx("span", { className: "font-mono", children: r.cartNumber ?? "—" }), " \u2014", " ", r.customerName, " \u2192 nieuwe pickdatum", " ", _jsx("strong", { children: fmtDate(r.newPickDate) })] }, i))) })] }))] }), _jsx(ResponsiveDialogFooter, { children: _jsx(Button, { onClick: () => {
527
519
  setResult(null);
528
520
  if (onExit)
529
521
  onExit();
@@ -570,3 +562,9 @@ function SummaryTile({ label, value, tone = "default", }) {
570
562
  }
571
563
  // Silence unused Input import (may be used later); keep tree-shakeable
572
564
  void Input;
565
+ function AfgeleverdView({ loading, carts }) {
566
+ return (_jsx(Card, { className: "p-0 overflow-hidden", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Ordernummer" }), _jsx(TableHead, { children: "Karnummer" }), _jsx(TableHead, { children: "Gecontroleerd om" })] }) }), _jsxs(TableBody, { children: [loading && (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 3, className: "text-center text-muted-foreground py-8", children: "Laden\u2026" }) })), !loading && carts.length === 0 && (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 3, className: "text-center text-muted-foreground py-8", children: "Vandaag zijn er nog geen karren afgeleverd." }) })), carts.map((c, i) => (_jsxs(TableRow, { children: [_jsx(TableCell, { className: "font-mono font-semibold", children: c.orderNumber || "—" }), _jsx(TableCell, { className: "font-mono", children: c.cartNumberLabel || "—" }), _jsx(TableCell, { children: new Date(c.deliveredAt).toLocaleTimeString("nl-NL", {
567
+ hour: "2-digit",
568
+ minute: "2-digit",
569
+ }) })] }, `${c.orderNumber ?? "?"}-${c.cartNumberLabel ?? i}-${i}`)))] })] }) }));
570
+ }
@@ -5,5 +5,5 @@ export interface DagDetailDialogProps {
5
5
  planned: PlannedOrder[];
6
6
  onOpenChange: (open: boolean) => void;
7
7
  }
8
- export declare function DagDetailDialog({ open, date, planned, onOpenChange }: DagDetailDialogProps): import("react").JSX.Element | null;
8
+ export declare function DagDetailDialog(props: DagDetailDialogProps): import("react").JSX.Element | null;
9
9
  //# sourceMappingURL=DagDetailDialog.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DagDetailDialog.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/DagDetailDialog.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAsCjE,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACvC;AAID,wBAAgB,eAAe,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,oBAAoB,sCAiF1F"}
1
+ {"version":3,"file":"DagDetailDialog.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/DagDetailDialog.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAyEjE,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACvC;AAQD,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,sCAG1D"}