@flowselections/floriday-afhandeling-module 1.0.37 → 1.0.39

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 (41) hide show
  1. package/dist-lib/components/afhandeling/ControleLijstPrint.js +54 -54
  2. package/dist-lib/components/afhandeling/ControlePage.d.ts.map +1 -1
  3. package/dist-lib/components/afhandeling/ControlePage.js +1 -3
  4. package/dist-lib/components/afhandeling/DagDetailDialog.d.ts.map +1 -1
  5. package/dist-lib/components/afhandeling/DagDetailDialog.js +5 -38
  6. package/dist-lib/components/afhandeling/LeveringenPage.d.ts.map +1 -1
  7. package/dist-lib/components/afhandeling/LeveringenPage.js +1 -1
  8. package/dist-lib/components/afhandeling/WeekAgendaView.d.ts +1 -3
  9. package/dist-lib/components/afhandeling/WeekAgendaView.d.ts.map +1 -1
  10. package/dist-lib/components/afhandeling/WeekAgendaView.js +6 -57
  11. package/dist-lib/components/pickstation/PakbonTemplate.js +70 -70
  12. package/dist-lib/components/settings/AfhandelingSettingsCard.d.ts.map +1 -1
  13. package/dist-lib/components/settings/AfhandelingSettingsCard.js +4 -55
  14. package/dist-lib/hooks/useOrderPlanning.d.ts.map +1 -1
  15. package/dist-lib/hooks/useOrderPlanning.js +6 -27
  16. package/dist-lib/integrations/supabase/auth-middleware.d.ts +426 -1
  17. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  18. package/dist-lib/integrations/supabase/client.server.d.ts +426 -1
  19. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  20. package/dist-lib/integrations/supabase/moduleClient.d.ts +426 -1
  21. package/dist-lib/integrations/supabase/moduleClient.d.ts.map +1 -1
  22. package/dist-lib/integrations/supabase/previewAuthStorage.d.ts +6 -0
  23. package/dist-lib/integrations/supabase/previewAuthStorage.d.ts.map +1 -0
  24. package/dist-lib/integrations/supabase/previewAuthStorage.js +92 -0
  25. package/dist-lib/integrations/supabase/types.d.ts +436 -1
  26. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  27. package/dist-lib/lib/afhandelingSettings.functions.d.ts +862 -4
  28. package/dist-lib/lib/afhandelingSettings.functions.d.ts.map +1 -1
  29. package/dist-lib/lib/carrierSignupMail.server.js +26 -26
  30. package/dist-lib/lib/carriers.functions.d.ts +2130 -5
  31. package/dist-lib/lib/carriers.functions.d.ts.map +1 -1
  32. package/dist-lib/lib/cartAssignments.functions.d.ts +2130 -5
  33. package/dist-lib/lib/cartAssignments.functions.d.ts.map +1 -1
  34. package/dist-lib/lib/cartControl.functions.d.ts +4290 -20
  35. package/dist-lib/lib/cartControl.functions.d.ts.map +1 -1
  36. package/dist-lib/lib/floriday.functions.d.ts +427 -2
  37. package/dist-lib/lib/floriday.functions.d.ts.map +1 -1
  38. package/dist-lib/lib/printing.d.ts +2 -11
  39. package/dist-lib/lib/printing.d.ts.map +1 -1
  40. package/dist-lib/lib/printing.js +8 -64
  41. package/package.json +1 -1
@@ -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":"AAoHA,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;CAAO,+BA2zBpE"}
1
+ {"version":3,"file":"ControlePage.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/ControlePage.tsx"],"names":[],"mappings":"AAmHA,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;CAAO,+BAyzBpE"}
@@ -9,7 +9,6 @@ import { useServerFn } from "@tanstack/react-start";
9
9
  import { getTodaysControlCarts, getControlRescheduleProposals, submitControlSession, listControlHistory, getControlSessionDetail, getControlDraft, saveControlDraft, } from "../../lib/cartControl.functions";
10
10
  import { renderControleLijstHtml } from "./ControleLijstPrint";
11
11
  import { printHtmlDocument, printFoutMelding } from "../../lib/printing";
12
- import { WerkplekWaarschuwing, useWerkplek } from "./WerkplekWaarschuwing";
13
12
  function fmtDate(iso) {
14
13
  if (!iso)
15
14
  return "—";
@@ -63,7 +62,6 @@ export function ControlePage({ onExit } = {}) {
63
62
  const [checked, setChecked] = useState(new Set());
64
63
  const [cartStates, setCartStates] = useState({});
65
64
  const [printBezig, setPrintBezig] = useState(false);
66
- const werkplek = useWerkplek();
67
65
  const [result, setResult] = useState(null);
68
66
  const [pendingProposal, setPendingProposal] = useState(null);
69
67
  const [confirmApproval, setConfirmApproval] = useState(null);
@@ -416,7 +414,7 @@ export function ControlePage({ onExit } = {}) {
416
414
  supabase.removeChannel(channel);
417
415
  };
418
416
  }, [qc]);
419
- return (_jsxs("main", { className: "p-6 space-y-6", children: [_jsx(WerkplekWaarschuwing, { werkplek: werkplek }), _jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-semibold", children: "Controle karren" }), _jsxs("p", { className: "text-sm text-muted-foreground", children: ["Dagelijkse eindcontrole \u2014 vandaag ", new Date().toLocaleDateString("nl-NL")] })] }), _jsxs("div", { className: "flex gap-2", children: [_jsxs(Button, { variant: "outline", disabled: !werkplek || printBezig || carts.length === 0, onClick: async () => {
417
+ return (_jsxs("main", { className: "p-6 space-y-6", children: [_jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-semibold", children: "Controle karren" }), _jsxs("p", { className: "text-sm text-muted-foreground", children: ["Dagelijkse eindcontrole \u2014 vandaag ", new Date().toLocaleDateString("nl-NL")] })] }), _jsxs("div", { className: "flex gap-2", children: [_jsxs(Button, { variant: "outline", disabled: printBezig || carts.length === 0, onClick: async () => {
420
418
  setPrintBezig(true);
421
419
  try {
422
420
  await printHtmlDocument({
@@ -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;AAwCjE,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;AAWD,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;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,sCAgF1F"}
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useState } from "react";
3
3
  import { useQuery, useQueryClient } from "@tanstack/react-query";
4
4
  import { useServerFn } from "@tanstack/react-start";
@@ -8,8 +8,6 @@ import { ResponsiveDialogBody, ResponsiveDialogContent, ResponsiveDialogFooter,
8
8
  import { isSameDay } from "../../lib/pickDate";
9
9
  import { getOrderLines, } from "../../lib/cartAssignments.functions";
10
10
  import { printLayoutDocument, printFoutMelding } from "../../lib/printing";
11
- import { WerkplekWaarschuwing, useWerkplek } from "./WerkplekWaarschuwing";
12
- import { printDeliveryNotesMerged } from "../../lib/deliveryNotePrint";
13
11
  import { AutoProcessStatus } from "./AutoProcessStatus";
14
12
  import { CapacityWarning } from "./CapacityWarning";
15
13
  import { useCapacityCheck } from "../../hooks/useCapacityCheck";
@@ -18,11 +16,6 @@ import { VerzetOrderDialog } from "./VerzetOrderDialog";
18
16
  import { setPickDay } from "../../lib/logisticsEngine/reschedule";
19
17
  import { clearDayStaffPlan, computeCapacity, getDayStaffPlan, getEngineStaffDefaults, setDayStaffPlan, toDateKey, } from "../../lib/logisticsEngine/staffPlanning";
20
18
  const NL_DATE = new Intl.DateTimeFormat("nl-NL", { dateStyle: "full" });
21
- /** Eén melding per dagdialoog zolang de werkplek niet is ingesteld. */
22
- function DagWerkplekBanner() {
23
- const werkplek = useWerkplek();
24
- return _jsx(WerkplekWaarschuwing, { werkplek: werkplek });
25
- }
26
19
  export function DagDetailDialog({ open, date, planned, onOpenChange }) {
27
20
  if (!date)
28
21
  return null;
@@ -65,7 +58,7 @@ export function DagDetailDialog({ open, date, planned, onOpenChange }) {
65
58
  runningIdx += a.cartCount;
66
59
  }
67
60
  }
68
- return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(ResponsiveDialogContent, { size: "xl", children: [_jsxs(ResponsiveDialogHeader, { children: [_jsxs(DialogTitle, { children: ["Dagdetails \u2014 ", NL_DATE.format(date)] }), _jsxs(DialogDescription, { children: [ordersOnDay.length, " bestellingen \u00B7 ", cartRows.length, " karren"] })] }), _jsxs(ResponsiveDialogBody, { children: [_jsx(DagWerkplekBanner, {}), _jsx(DayCapacityWarning, { date: date }), _jsx(BezettingCard, { date: date, cartsToday: cartRows.length }), _jsxs(Tabs, { defaultValue: "bestellingen", children: [_jsxs(TabsList, { children: [_jsxs(TabsTrigger, { value: "bestellingen", children: ["Bestellingen (", ordersOnDay.length, ")"] }), _jsxs(TabsTrigger, { value: "karren", children: ["Karren (", cartRows.length, ")"] })] }), _jsx(TabsContent, { value: "bestellingen", className: "mt-4", children: _jsx(BestellingenTab, { orders: ordersOnDay, date: date }) }), _jsx(TabsContent, { value: "karren", className: "mt-4", children: _jsx(KarrenTab, { carts: cartRows }) })] })] }), _jsx(ResponsiveDialogFooter, { children: _jsx(Button, { variant: "outline", onClick: () => onOpenChange(false), children: "Sluiten" }) })] }) }));
61
+ return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(ResponsiveDialogContent, { size: "xl", children: [_jsxs(ResponsiveDialogHeader, { children: [_jsxs(DialogTitle, { children: ["Dagdetails \u2014 ", NL_DATE.format(date)] }), _jsxs(DialogDescription, { children: [ordersOnDay.length, " bestellingen \u00B7 ", cartRows.length, " karren"] })] }), _jsxs(ResponsiveDialogBody, { children: [_jsx(DayCapacityWarning, { date: date }), _jsx(BezettingCard, { date: date, cartsToday: cartRows.length }), _jsxs(Tabs, { defaultValue: "bestellingen", children: [_jsxs(TabsList, { children: [_jsxs(TabsTrigger, { value: "bestellingen", children: ["Bestellingen (", ordersOnDay.length, ")"] }), _jsxs(TabsTrigger, { value: "karren", children: ["Karren (", cartRows.length, ")"] })] }), _jsx(TabsContent, { value: "bestellingen", className: "mt-4", children: _jsx(BestellingenTab, { orders: ordersOnDay, date: date }) }), _jsx(TabsContent, { value: "karren", className: "mt-4", children: _jsx(KarrenTab, { carts: cartRows }) })] })] }), _jsx(ResponsiveDialogFooter, { children: _jsx(Button, { variant: "outline", onClick: () => onOpenChange(false), children: "Sluiten" }) })] }) }));
69
62
  }
70
63
  function BezettingCard({ date, cartsToday }) {
71
64
  const queryClient = useQueryClient();
@@ -152,7 +145,6 @@ function OrderRow({ planned: p, cartsToday }) {
152
145
  const [open, setOpen] = useState(false);
153
146
  const [printing, setPrinting] = useState(false);
154
147
  const [verzetOpen, setVerzetOpen] = useState(false);
155
- const werkplek = useWerkplek();
156
148
  const source = p.order.source;
157
149
  const fetchLines = useServerFn(getOrderLines);
158
150
  const linesQuery = useQuery({
@@ -217,37 +209,12 @@ function OrderRow({ planned: p, cartsToday }) {
217
209
  console.warn("[print-all] pakbon mislukt", cartNumber, err);
218
210
  }
219
211
  }
220
- let deliveryOk = 0;
221
- let deliveryFailed = 0;
222
- const salesOrderId = p.order.salesOrderId ?? (source === "floriday" ? p.order.id : null);
223
- if (salesOrderId) {
224
- try {
225
- const res = await printDeliveryNotesMerged([
226
- { id: p.order.id, salesOrderId },
227
- ]);
228
- deliveryOk = res.success;
229
- deliveryFailed = res.failed.length;
230
- if (res.failed.length > 0) {
231
- console.warn("[print-all] afleverbrief mislukt", res.failed);
232
- }
233
- }
234
- catch (err) {
235
- deliveryFailed = 1;
236
- console.warn("[print-all] afleverbrief-fout", err);
237
- }
238
- }
239
- const parts = [`${printed} pakbon${printed === 1 ? "" : "nen"}`];
240
- if (deliveryOk > 0)
241
- parts.push(`${deliveryOk} afleverbrief`);
242
- if (printed > 0 || deliveryOk > 0) {
243
- toast.success(`Documenten geprint — ${parts.join(", ")}.`);
212
+ if (printed > 0) {
213
+ toast.success(`Documenten geprint — ${printed} pakbon${printed === 1 ? "" : "nen"}.`);
244
214
  }
245
215
  if (pakbonFailed > 0) {
246
216
  toast.error(`${pakbonFailed} pakbon kon niet worden geprint.`);
247
217
  }
248
- if (deliveryFailed > 0) {
249
- toast.error(`${deliveryFailed} afleverbrief kon niet worden geprint.`);
250
- }
251
218
  }
252
219
  catch (err) {
253
220
  toast.error(printFoutMelding(err));
@@ -267,7 +234,7 @@ function OrderRow({ planned: p, cartsToday }) {
267
234
  const src = p.order.source === "floriday" ? "floriday" : "manual";
268
235
  const soId = p.order.salesOrderId ?? (src === "floriday" ? p.order.id : null);
269
236
  return soId ? (_jsx(AutoProcessStatus, { salesOrderId: soId })) : null;
270
- })(), _jsxs(Button, { size: "sm", variant: "outline", onClick: handlePrintAll, disabled: printing || !werkplek, title: "Alle pakbonnen en afleverbrieven van deze bestelling afdrukken", children: [_jsx(Printer, { className: "mr-1 h-3.5 w-3.5" }), printing ? "Bezig…" : "Alle documenten afdrukken"] }), _jsxs(Button, { size: "sm", variant: "outline", onClick: (e) => {
237
+ })(), _jsxs(Button, { size: "sm", variant: "outline", onClick: handlePrintAll, disabled: printing, title: "Alle pakbonnen van deze bestelling afdrukken", children: [_jsx(Printer, { className: "mr-1 h-3.5 w-3.5" }), printing ? "Bezig…" : "Alle documenten afdrukken"] }), _jsxs(Button, { size: "sm", variant: "outline", onClick: (e) => {
271
238
  e.stopPropagation();
272
239
  setVerzetOpen(true);
273
240
  }, title: "Ophaaldag of ophaaltijd van deze order wijzigen", children: [_jsx(CalendarClock, { className: "mr-1 h-3.5 w-3.5" }), "Verzetten"] })] })] }), _jsx(VerzetOrderDialog, { open: verzetOpen, orderRef: p.order.orderNumber, carrierTarget: {
@@ -1 +1 @@
1
- {"version":3,"file":"LeveringenPage.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/LeveringenPage.tsx"],"names":[],"mappings":"AAMA,wBAAgB,cAAc,gCA8B7B"}
1
+ {"version":3,"file":"LeveringenPage.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/LeveringenPage.tsx"],"names":[],"mappings":"AAMA,wBAAgB,cAAc,gCA6B7B"}
@@ -8,5 +8,5 @@ export function LeveringenPage() {
8
8
  const [weekStart, setWeekStart] = useState(() => currentWeekStart());
9
9
  const range = useMemo(() => agendaRange(weekStart), [weekStart]);
10
10
  const { planned, nearestDeliveryDate, isLoading, error, warning, refetch } = useOrderPlanning(range);
11
- return (_jsxs("main", { className: "p-6 space-y-6", children: [warning && !error && (_jsxs("div", { className: "rounded-md border border-amber-300 bg-amber-50 p-4 text-sm text-amber-900", children: [warning, " De beschikbare orders blijven zichtbaar."] })), error ? (_jsxs("div", { className: "rounded-md border border-destructive/30 bg-destructive/5 p-4 text-sm text-destructive", children: [error, _jsx(Button, { size: "sm", variant: "outline", className: "ml-3", onClick: () => refetch(), children: "Opnieuw proberen" })] })) : (_jsx(WeekAgendaView, { planned: planned, mode: "delivery", isLoading: isLoading, showPrintButtons: true, onWeekChange: setWeekStart, jumpToDate: nearestDeliveryDate }))] }));
11
+ return (_jsxs("main", { className: "p-6 space-y-6", children: [warning && !error && (_jsxs("div", { className: "rounded-md border border-amber-300 bg-amber-50 p-4 text-sm text-amber-900", children: [warning, " De beschikbare orders blijven zichtbaar."] })), error ? (_jsxs("div", { className: "rounded-md border border-destructive/30 bg-destructive/5 p-4 text-sm text-destructive", children: [error, _jsx(Button, { size: "sm", variant: "outline", className: "ml-3", onClick: () => refetch(), children: "Opnieuw proberen" })] })) : (_jsx(WeekAgendaView, { planned: planned, mode: "delivery", isLoading: isLoading, onWeekChange: setWeekStart, jumpToDate: nearestDeliveryDate }))] }));
12
12
  }
@@ -8,12 +8,10 @@ export interface WeekAgendaViewProps {
8
8
  onOrderClick?: (order: FloridayOrder) => void;
9
9
  onDayClick?: (date: Date) => void;
10
10
  title?: string;
11
- /** Toon "Afleverbrief" print-knoppen (per order + per dag). */
12
- showPrintButtons?: boolean;
13
11
  /** Meld de zichtbare week zodat de pagina alleen die periode ophaalt. */
14
12
  onWeekChange?: (weekStart: Date, weekEnd: Date) => void;
15
13
  /** Dichtstbijzijnde datum met data buiten de zichtbare week (auto-jump). */
16
14
  jumpToDate?: string | null;
17
15
  }
18
- export declare function WeekAgendaView({ planned, mode, isLoading, onOrderClick, onDayClick, title, showPrintButtons, onWeekChange, jumpToDate, }: WeekAgendaViewProps): import("react").JSX.Element;
16
+ export declare function WeekAgendaView({ planned, mode, isLoading, onOrderClick, onDayClick, title, onWeekChange, jumpToDate, }: WeekAgendaViewProps): import("react").JSX.Element;
19
17
  //# sourceMappingURL=WeekAgendaView.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"WeekAgendaView.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/WeekAgendaView.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAIlE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAUjE,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,QAAQ,GAAG,oBAAoB,GAAG,MAAM,CAAC;AAEnF,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,IAAI,EAAE,cAAc,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC9C,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,yEAAyE;IACzE,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,KAAK,IAAI,CAAC;IACxD,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AA+DD,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,IAAI,EACJ,SAAS,EACT,YAAY,EACZ,UAAU,EACV,KAAK,EACL,gBAAgB,EAChB,YAAY,EACZ,UAAU,GACX,EAAE,mBAAmB,+BA0JrB"}
1
+ {"version":3,"file":"WeekAgendaView.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/WeekAgendaView.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAKjE,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,QAAQ,GAAG,oBAAoB,GAAG,MAAM,CAAC;AAEnF,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,IAAI,EAAE,cAAc,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC9C,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,KAAK,IAAI,CAAC;IACxD,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AA+DD,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,IAAI,EACJ,SAAS,EACT,YAAY,EACZ,UAAU,EACV,KAAK,EACL,YAAY,EACZ,UAAU,GACX,EAAE,mBAAmB,+BAwJrB"}
@@ -1,11 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useMemo, useRef, useState } from "react";
3
- import { Button, Badge, toast } from "@flowselections/core";
4
- import { ChevronLeft, ChevronRight, Package, Truck, Sprout, Clock, CheckCircle2, Scale, Printer } from "lucide-react";
5
- import { printFoutMelding } from "../../lib/printing";
6
- import { WerkplekWaarschuwing, useWerkplek } from "./WerkplekWaarschuwing";
3
+ import { Button, Badge } from "@flowselections/core";
4
+ import { ChevronLeft, ChevronRight, Package, Truck, Sprout, Clock, CheckCircle2, Scale } from "lucide-react";
7
5
  import { isSameDay, startOfWeek, addDays } from "../../lib/pickDate";
8
- import { printDeliveryNote, printDeliveryNotesMerged, } from "../../lib/deliveryNotePrint";
9
6
  import { useCapacityCheck } from "../../hooks/useCapacityCheck";
10
7
  import { CapacityWarning } from "./CapacityWarning";
11
8
  import { toDayKey } from "../../lib/logisticsEngine/capacity";
@@ -43,7 +40,7 @@ const MODE_LABELS = {
43
40
  "transport-register": { summary: "Aanmeldingen deze week" },
44
41
  pick: { summary: "Te picken deze week" },
45
42
  };
46
- export function WeekAgendaView({ planned, mode, isLoading, onOrderClick, onDayClick, title, showPrintButtons, onWeekChange, jumpToDate, }) {
43
+ export function WeekAgendaView({ planned, mode, isLoading, onOrderClick, onDayClick, title, onWeekChange, jumpToDate, }) {
47
44
  const [cursor, setCursor] = useState(() => {
48
45
  const d = new Date();
49
46
  d.setHours(0, 0, 0, 0);
@@ -146,66 +143,18 @@ export function WeekAgendaView({ planned, mode, isLoading, onOrderClick, onDayCl
146
143
  d.setHours(0, 0, 0, 0);
147
144
  setCursor(startOfWeek(d));
148
145
  };
149
- return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsx("h2", { className: "text-xl font-semibold tracking-tight", children: title ?? headerLabel }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Button, { variant: "outline", size: "sm", onClick: goPrev, children: [_jsx(ChevronLeft, { className: "mr-1 h-4 w-4" }), " Vorige week"] }), _jsx(Button, { variant: "outline", size: "sm", onClick: goToday, children: "Deze week" }), _jsxs(Button, { variant: "outline", size: "sm", onClick: goNext, children: ["Volgende week ", _jsx(ChevronRight, { className: "ml-1 h-4 w-4" })] })] })] }), _jsxs("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4", children: [_jsx(SummaryCard, { label: MODE_LABELS[mode].summary, value: totals.leveringen, tone: "default" }), _jsx(SummaryCard, { label: "Verzendklaar", value: totals.verzendklaar, tone: "success" }), _jsx(SummaryCard, { label: "In voorbereiding", value: totals.voorbereiding, tone: "muted" }), _jsx(SummaryCard, { label: "Totaal stuks", value: totals.totaalStuks, tone: "default" })] }), _jsxs("div", { className: "max-h-[520px] space-y-2 overflow-y-auto rounded-lg border bg-muted/20 p-2", children: [showPrintButtons && _jsx(AgendaWerkplekBanner, {}), isLoading ? (_jsx("div", { className: "rounded-lg border bg-card p-10 text-center text-sm text-muted-foreground", children: "Laden\u2026" })) : (days.map((day) => (_jsx(DayRow, { day: day, onOrderClick: onOrderClick, onDayClick: onDayClick, showPrintButtons: showPrintButtons, capacity: mode === "delivery" ? undefined : capacity.byDate.get(toDayKey(day.date)) }, day.date.toISOString()))))] })] }));
146
+ return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsx("h2", { className: "text-xl font-semibold tracking-tight", children: title ?? headerLabel }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Button, { variant: "outline", size: "sm", onClick: goPrev, children: [_jsx(ChevronLeft, { className: "mr-1 h-4 w-4" }), " Vorige week"] }), _jsx(Button, { variant: "outline", size: "sm", onClick: goToday, children: "Deze week" }), _jsxs(Button, { variant: "outline", size: "sm", onClick: goNext, children: ["Volgende week ", _jsx(ChevronRight, { className: "ml-1 h-4 w-4" })] })] })] }), _jsxs("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4", children: [_jsx(SummaryCard, { label: MODE_LABELS[mode].summary, value: totals.leveringen, tone: "default" }), _jsx(SummaryCard, { label: "Verzendklaar", value: totals.verzendklaar, tone: "success" }), _jsx(SummaryCard, { label: "In voorbereiding", value: totals.voorbereiding, tone: "muted" }), _jsx(SummaryCard, { label: "Totaal stuks", value: totals.totaalStuks, tone: "default" })] }), _jsx("div", { className: "max-h-[520px] space-y-2 overflow-y-auto rounded-lg border bg-muted/20 p-2", children: isLoading ? (_jsx("div", { className: "rounded-lg border bg-card p-10 text-center text-sm text-muted-foreground", children: "Laden\u2026" })) : (days.map((day) => (_jsx(DayRow, { day: day, onOrderClick: onOrderClick, onDayClick: onDayClick, capacity: mode === "delivery" ? undefined : capacity.byDate.get(toDayKey(day.date)) }, day.date.toISOString())))) })] }));
150
147
  }
151
148
  function SummaryCard({ label, value, tone, }) {
152
149
  const valueClass = tone === "success" ? "text-green-600" : "text-foreground";
153
150
  return (_jsxs("div", { className: "rounded-lg border bg-card p-4", children: [_jsx("div", { className: `text-3xl font-bold ${valueClass}`, children: value }), _jsx("div", { className: "mt-1 text-sm text-muted-foreground", children: label })] }));
154
151
  }
155
- /** Eén melding bovenaan de agenda zolang de werkplek ontbreekt. */
156
- function AgendaWerkplekBanner() {
157
- const werkplek = useWerkplek();
158
- return _jsx(WerkplekWaarschuwing, { werkplek: werkplek });
159
- }
160
- function DayRow({ day, onOrderClick, onDayClick, showPrintButtons, capacity, }) {
152
+ function DayRow({ day, onOrderClick, onDayClick, capacity, }) {
161
153
  const weekdayIdx = (day.date.getDay() + 6) % 7;
162
154
  const today = new Date();
163
155
  today.setHours(0, 0, 0, 0);
164
156
  const isToday = isSameDay(day.date, today);
165
- const [printingDay, setPrintingDay] = useState(false);
166
- const [printingOrderId, setPrintingOrderId] = useState(null);
167
- const printableItems = day.entries
168
- .filter((e) => e.order.source === "floriday" && e.order.salesOrderId)
169
- .map((e) => ({ id: e.order.id, salesOrderId: e.order.salesOrderId ?? undefined }));
170
- const werkplek = useWerkplek();
171
- const handlePrintDay = async () => {
172
- if (printingDay || printableItems.length === 0)
173
- return;
174
- setPrintingDay(true);
175
- try {
176
- const res = await printDeliveryNotesMerged(printableItems);
177
- if (res.success > 0) {
178
- toast.success(`${res.success}/${res.total} afleverbrieven verstuurd naar printer`);
179
- }
180
- for (const f of res.failed.slice(0, 5)) {
181
- toast.error(`Afleverbrief ${f.id} mislukt: ${f.error}`);
182
- }
183
- }
184
- catch (err) {
185
- toast.error(printFoutMelding(err));
186
- }
187
- finally {
188
- setPrintingDay(false);
189
- }
190
- };
191
- const handlePrintOrder = async (order) => {
192
- if (!order.salesOrderId || printingOrderId)
193
- return;
194
- setPrintingOrderId(order.id);
195
- try {
196
- await printDeliveryNote(order.salesOrderId, {
197
- documentnaam: `AFL-${order.orderNumber}`,
198
- });
199
- toast.success(`Afleverbrief ${order.orderNumber} naar de printer gestuurd.`);
200
- }
201
- catch (err) {
202
- toast.error(printFoutMelding(err));
203
- }
204
- finally {
205
- setPrintingOrderId(null);
206
- }
207
- };
208
- return (_jsxs("div", { className: `rounded-lg border bg-card ${isToday ? "ring-1 ring-primary" : ""}`, children: [_jsxs("div", { className: "flex flex-wrap items-center gap-6 px-4 py-4 sm:px-6", children: [_jsxs("div", { className: "w-20 shrink-0", children: [_jsx("div", { className: "text-xs font-medium tracking-wider text-muted-foreground", children: WEEKDAY_LABELS[weekdayIdx] }), _jsx("div", { className: "mt-1 text-3xl font-bold leading-none", children: day.date.getDate() }), _jsxs("div", { className: "text-sm text-muted-foreground", children: [MONTHS_NL_SHORT[day.date.getMonth()], "."] })] }), _jsxs("div", { className: "flex flex-1 flex-wrap items-center gap-6", children: [_jsx(Stat, { icon: _jsx(Package, { className: "h-4 w-4 text-slate-500" }), bg: "bg-slate-100", value: day.bestellingen, label: "bestellingen" }), _jsx(Stat, { icon: _jsx(Truck, { className: "h-4 w-4 text-amber-600" }), bg: "bg-amber-100", value: day.karren, label: "karren" }), _jsx(Stat, { icon: _jsx(Sprout, { className: "h-4 w-4 text-green-600" }), bg: "bg-green-100", value: day.planten, label: "planten" })] }), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [day.movedEarlierOrderIds.size > 0 && (_jsxs(Badge, { className: "bg-purple-500/10 text-purple-700 hover:bg-purple-500/10", variant: "secondary", title: "Aantal orders dat vervroegd is ingepland door Pickverdeling.", children: [_jsx(Scale, { className: "mr-1 h-3.5 w-3.5" }), day.movedEarlierOrderIds.size, " vervroegd"] })), day.verzendklaar > 0 && (_jsxs(Badge, { className: "bg-green-500/15 text-green-700 hover:bg-green-500/15", variant: "secondary", children: [_jsx(CheckCircle2, { className: "mr-1 h-3.5 w-3.5" }), day.verzendklaar, " verzendklaar"] })), day.voorbereiding > 0 && (_jsxs(Badge, { className: "bg-blue-500/10 text-blue-700 hover:bg-blue-500/10", variant: "secondary", children: [_jsx(Clock, { className: "mr-1 h-3.5 w-3.5" }), day.voorbereiding, " in voorbereiding"] })), showPrintButtons && printableItems.length > 0 && (_jsxs(Button, { size: "sm", variant: "outline", onClick: handlePrintDay, disabled: printingDay || !werkplek, children: [_jsx(Printer, { className: "mr-1 h-4 w-4" }), printingDay ? "Printen…" : `Print afleverbrieven (${printableItems.length})`] })), onDayClick && day.bestellingen > 0 && (_jsx(Button, { size: "sm", variant: "outline", onClick: () => onDayClick(day.date), children: "Dagdetails" }))] })] }), _jsx(CapacityWarning, { day: capacity, className: "mx-4 mb-4 sm:mx-6" })] }));
157
+ return (_jsxs("div", { className: `rounded-lg border bg-card ${isToday ? "ring-1 ring-primary" : ""}`, children: [_jsxs("div", { className: "flex flex-wrap items-center gap-6 px-4 py-4 sm:px-6", children: [_jsxs("div", { className: "w-20 shrink-0", children: [_jsx("div", { className: "text-xs font-medium tracking-wider text-muted-foreground", children: WEEKDAY_LABELS[weekdayIdx] }), _jsx("div", { className: "mt-1 text-3xl font-bold leading-none", children: day.date.getDate() }), _jsxs("div", { className: "text-sm text-muted-foreground", children: [MONTHS_NL_SHORT[day.date.getMonth()], "."] })] }), _jsxs("div", { className: "flex flex-1 flex-wrap items-center gap-6", children: [_jsx(Stat, { icon: _jsx(Package, { className: "h-4 w-4 text-slate-500" }), bg: "bg-slate-100", value: day.bestellingen, label: "bestellingen" }), _jsx(Stat, { icon: _jsx(Truck, { className: "h-4 w-4 text-amber-600" }), bg: "bg-amber-100", value: day.karren, label: "karren" }), _jsx(Stat, { icon: _jsx(Sprout, { className: "h-4 w-4 text-green-600" }), bg: "bg-green-100", value: day.planten, label: "planten" })] }), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [day.movedEarlierOrderIds.size > 0 && (_jsxs(Badge, { className: "bg-purple-500/10 text-purple-700 hover:bg-purple-500/10", variant: "secondary", title: "Aantal orders dat vervroegd is ingepland door Pickverdeling.", children: [_jsx(Scale, { className: "mr-1 h-3.5 w-3.5" }), day.movedEarlierOrderIds.size, " vervroegd"] })), day.verzendklaar > 0 && (_jsxs(Badge, { className: "bg-green-500/15 text-green-700 hover:bg-green-500/15", variant: "secondary", children: [_jsx(CheckCircle2, { className: "mr-1 h-3.5 w-3.5" }), day.verzendklaar, " verzendklaar"] })), day.voorbereiding > 0 && (_jsxs(Badge, { className: "bg-blue-500/10 text-blue-700 hover:bg-blue-500/10", variant: "secondary", children: [_jsx(Clock, { className: "mr-1 h-3.5 w-3.5" }), day.voorbereiding, " in voorbereiding"] })), onDayClick && day.bestellingen > 0 && (_jsx(Button, { size: "sm", variant: "outline", onClick: () => onDayClick(day.date), children: "Dagdetails" }))] })] }), _jsx(CapacityWarning, { day: capacity, className: "mx-4 mb-4 sm:mx-6" })] }));
209
158
  }
210
159
  function Stat({ icon, bg, value, label, }) {
211
160
  return (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: `grid h-8 w-8 place-items-center rounded-full ${bg}`, children: icon }), _jsxs("div", { children: [_jsx("div", { className: "text-lg font-bold leading-none", children: value }), _jsx("div", { className: "text-xs text-muted-foreground", children: label })] })] }));
@@ -14,82 +14,82 @@ export function renderPakbonHtml(order, lang = "nl") {
14
14
  };
15
15
  const rows = order.lines.length
16
16
  ? order.lines
17
- .map((l) => `
18
- <tr>
19
- <td>${escapeHtml(l.description)}</td>
20
- <td style="text-align:right">${l.crates ?? ""}</td>
21
- <td>${escapeHtml(l.unit ?? "")}</td>
17
+ .map((l) => `
18
+ <tr>
19
+ <td>${escapeHtml(l.description)}</td>
20
+ <td style="text-align:right">${l.crates ?? ""}</td>
21
+ <td>${escapeHtml(l.unit ?? "")}</td>
22
22
  </tr>`)
23
23
  .join("")
24
24
  : `<tr><td colspan="3" style="text-align:center;color:#666">${escapeHtml(t.noLines)}</td></tr>`;
25
25
  const cartLabel = t.cartOf(order.cartIndex, order.cartTotal);
26
26
  const fustenLabel = order.cratesOnCart != null ? `${order.cratesOnCart}` : "—";
27
27
  const cartNumber = order.cartNumber ?? `${order.orderNumber}-${order.cartIndex}`;
28
- return `<!doctype html>
29
- <html lang="${escapeHtml(htmlLang)}">
30
- <head>
31
- <meta charset="utf-8">
32
- <title>${escapeHtml(t.packingSlip)} ${escapeHtml(order.orderNumber)} · ${escapeHtml(cartNumber)}</title>
33
- <style>
34
- @page {
35
- size: A4;
36
- margin: 16mm;
37
- @top-center { content: element(cartno); }
38
- }
39
- body { font-family: -apple-system, "Segoe UI", Helvetica, Arial, sans-serif; color:#111; }
40
- h1 { margin: 0 0 4px; font-size: 26px; }
41
- .sub { color:#444; margin-bottom: 8px; }
42
-
43
- .cart-number-hero {
44
- position: running(cartno);
45
- font-size: 88px;
46
- font-weight: 900;
47
- letter-spacing: 4px;
48
- line-height: 1;
49
- color: #000;
50
- background: #fff;
51
- border: 4px solid #000;
52
- padding: 12px 20px;
53
- display: inline-block;
54
- margin: 6px 0 20px;
55
- font-family: "Arial Black", "Helvetica Neue", Helvetica, Arial, sans-serif;
56
- }
57
-
58
- .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 24px; margin: 8px 0 22px; }
59
- .grid div { font-size: 14px; }
60
- .label { color:#666; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; }
61
- .value { font-size: 16px; font-weight: 600; }
62
- table { width:100%; border-collapse: collapse; font-size: 14px; }
63
- th, td { padding: 8px 6px; border-bottom: 1px solid #ddd; vertical-align: top; }
64
- th { text-align: left; background:#f5f5f5; }
65
- .barcode-fallback { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 18px; letter-spacing: 4px; padding: 8px 12px; border: 2px solid #111; display: inline-block; margin-top: 18px; }
66
- .footer { margin-top: 28px; font-size: 11px; color:#666; }
67
- </style>
68
- </head>
69
- <body>
70
- <h1>${escapeHtml(t.packingSlip)}</h1>
71
- <div class="sub">${escapeHtml(t.order)} ${escapeHtml(order.orderNumber)} · ${escapeHtml(cartLabel)}</div>
72
-
73
- <div class="cart-number-hero">${escapeHtml(cartNumber)}</div>
74
-
75
- <div class="grid">
76
- <div><div class="label">${escapeHtml(t.customer)}</div><div class="value">${escapeHtml(order.customerName)}</div></div>
77
- <div><div class="label">${escapeHtml(t.country)}</div><div class="value">${escapeHtml(order.country ?? "—")}</div></div>
78
- <div><div class="label">${escapeHtml(t.deliveryDate)}</div><div class="value">${fmt(order.deliveryDate)}</div></div>
79
- <div><div class="label">${escapeHtml(t.pickDate)}</div><div class="value">${fmt(order.pickDate)}</div></div>
80
- <div><div class="label">${escapeHtml(t.cart)}</div><div class="value">${escapeHtml(cartLabel)}</div></div>
81
- <div><div class="label">${escapeHtml(t.cratesOnThisCart)}</div><div class="value">${escapeHtml(fustenLabel)}</div></div>
82
- </div>
83
-
84
- <table>
85
- <thead><tr><th>${escapeHtml(t.description)}</th><th style="text-align:right;width:90px">${escapeHtml(t.crates)}</th><th style="width:90px">${escapeHtml(t.unit)}</th></tr></thead>
86
- <tbody>${rows}</tbody>
87
- </table>
88
-
89
- <div class="barcode-fallback">*${escapeHtml(order.orderNumber)}*</div>
90
-
91
- <div class="footer">${escapeHtml(t.printedVia)} · ${new Date().toLocaleString(locale)}</div>
92
- </body>
28
+ return `<!doctype html>
29
+ <html lang="${escapeHtml(htmlLang)}">
30
+ <head>
31
+ <meta charset="utf-8">
32
+ <title>${escapeHtml(t.packingSlip)} ${escapeHtml(order.orderNumber)} · ${escapeHtml(cartNumber)}</title>
33
+ <style>
34
+ @page {
35
+ size: A4;
36
+ margin: 16mm;
37
+ @top-center { content: element(cartno); }
38
+ }
39
+ body { font-family: -apple-system, "Segoe UI", Helvetica, Arial, sans-serif; color:#111; }
40
+ h1 { margin: 0 0 4px; font-size: 26px; }
41
+ .sub { color:#444; margin-bottom: 8px; }
42
+
43
+ .cart-number-hero {
44
+ position: running(cartno);
45
+ font-size: 88px;
46
+ font-weight: 900;
47
+ letter-spacing: 4px;
48
+ line-height: 1;
49
+ color: #000;
50
+ background: #fff;
51
+ border: 4px solid #000;
52
+ padding: 12px 20px;
53
+ display: inline-block;
54
+ margin: 6px 0 20px;
55
+ font-family: "Arial Black", "Helvetica Neue", Helvetica, Arial, sans-serif;
56
+ }
57
+
58
+ .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 24px; margin: 8px 0 22px; }
59
+ .grid div { font-size: 14px; }
60
+ .label { color:#666; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; }
61
+ .value { font-size: 16px; font-weight: 600; }
62
+ table { width:100%; border-collapse: collapse; font-size: 14px; }
63
+ th, td { padding: 8px 6px; border-bottom: 1px solid #ddd; vertical-align: top; }
64
+ th { text-align: left; background:#f5f5f5; }
65
+ .barcode-fallback { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 18px; letter-spacing: 4px; padding: 8px 12px; border: 2px solid #111; display: inline-block; margin-top: 18px; }
66
+ .footer { margin-top: 28px; font-size: 11px; color:#666; }
67
+ </style>
68
+ </head>
69
+ <body>
70
+ <h1>${escapeHtml(t.packingSlip)}</h1>
71
+ <div class="sub">${escapeHtml(t.order)} ${escapeHtml(order.orderNumber)} · ${escapeHtml(cartLabel)}</div>
72
+
73
+ <div class="cart-number-hero">${escapeHtml(cartNumber)}</div>
74
+
75
+ <div class="grid">
76
+ <div><div class="label">${escapeHtml(t.customer)}</div><div class="value">${escapeHtml(order.customerName)}</div></div>
77
+ <div><div class="label">${escapeHtml(t.country)}</div><div class="value">${escapeHtml(order.country ?? "—")}</div></div>
78
+ <div><div class="label">${escapeHtml(t.deliveryDate)}</div><div class="value">${fmt(order.deliveryDate)}</div></div>
79
+ <div><div class="label">${escapeHtml(t.pickDate)}</div><div class="value">${fmt(order.pickDate)}</div></div>
80
+ <div><div class="label">${escapeHtml(t.cart)}</div><div class="value">${escapeHtml(cartLabel)}</div></div>
81
+ <div><div class="label">${escapeHtml(t.cratesOnThisCart)}</div><div class="value">${escapeHtml(fustenLabel)}</div></div>
82
+ </div>
83
+
84
+ <table>
85
+ <thead><tr><th>${escapeHtml(t.description)}</th><th style="text-align:right;width:90px">${escapeHtml(t.crates)}</th><th style="width:90px">${escapeHtml(t.unit)}</th></tr></thead>
86
+ <tbody>${rows}</tbody>
87
+ </table>
88
+
89
+ <div class="barcode-fallback">*${escapeHtml(order.orderNumber)}*</div>
90
+
91
+ <div class="footer">${escapeHtml(t.printedVia)} · ${new Date().toLocaleString(locale)}</div>
92
+ </body>
93
93
  </html>`;
94
94
  }
95
95
  function escapeHtml(s) {
@@ -1 +1 @@
1
- {"version":3,"file":"AfhandelingSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/AfhandelingSettingsCard.tsx"],"names":[],"mappings":"AAuBA,wBAAgB,uBAAuB,gCAoVtC"}
1
+ {"version":3,"file":"AfhandelingSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/AfhandelingSettingsCard.tsx"],"names":[],"mappings":"AAqBA,wBAAgB,uBAAuB,gCAyHtC"}