@flowselections/floriday-afhandeling-module 1.0.12 → 1.0.14

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 (80) hide show
  1. package/dist-lib/components/afhandeling/AutoProcessStatus.d.ts +12 -0
  2. package/dist-lib/components/afhandeling/AutoProcessStatus.d.ts.map +1 -0
  3. package/dist-lib/components/afhandeling/AutoProcessStatus.js +103 -0
  4. package/dist-lib/components/afhandeling/ControleLijstPrint.d.ts +3 -1
  5. package/dist-lib/components/afhandeling/ControleLijstPrint.d.ts.map +1 -1
  6. package/dist-lib/components/afhandeling/ControleLijstPrint.js +56 -17
  7. package/dist-lib/components/afhandeling/DagDetailDialog.d.ts.map +1 -1
  8. package/dist-lib/components/afhandeling/DagDetailDialog.js +96 -4
  9. package/dist-lib/components/afhandeling/LeveringenPage.js +1 -1
  10. package/dist-lib/components/afhandeling/VervoerdersPage.d.ts.map +1 -1
  11. package/dist-lib/components/afhandeling/VervoerdersPage.js +2 -1
  12. package/dist-lib/components/afhandeling/WeekAgendaView.d.ts +3 -1
  13. package/dist-lib/components/afhandeling/WeekAgendaView.d.ts.map +1 -1
  14. package/dist-lib/components/afhandeling/WeekAgendaView.js +58 -17
  15. package/dist-lib/components/pickstation/KioskControle.d.ts +2 -0
  16. package/dist-lib/components/pickstation/KioskControle.d.ts.map +1 -0
  17. package/dist-lib/components/pickstation/KioskControle.js +7 -0
  18. package/dist-lib/components/pickstation/PakbonTemplate.d.ts +2 -1
  19. package/dist-lib/components/pickstation/PakbonTemplate.d.ts.map +1 -1
  20. package/dist-lib/components/pickstation/PakbonTemplate.js +20 -17
  21. package/dist-lib/components/pickstation/PickstationPage.d.ts +2 -0
  22. package/dist-lib/components/pickstation/PickstationPage.d.ts.map +1 -0
  23. package/dist-lib/components/pickstation/PickstationPage.js +266 -0
  24. package/dist-lib/components/settings/AfhandelingSettingsCard.d.ts.map +1 -1
  25. package/dist-lib/components/settings/AfhandelingSettingsCard.js +14 -2
  26. package/dist-lib/hooks/useOrderPlanning.d.ts.map +1 -1
  27. package/dist-lib/hooks/useOrderPlanning.js +28 -11
  28. package/dist-lib/index.d.ts +4 -0
  29. package/dist-lib/index.d.ts.map +1 -1
  30. package/dist-lib/index.js +4 -0
  31. package/dist-lib/integrations/supabase/auth-middleware.d.ts +1243 -63
  32. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  33. package/dist-lib/integrations/supabase/client.d.ts +1243 -63
  34. package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
  35. package/dist-lib/integrations/supabase/client.server.d.ts +1243 -63
  36. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  37. package/dist-lib/integrations/supabase/types.d.ts +1264 -56
  38. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  39. package/dist-lib/lib/afhandelingSettings.functions.d.ts +2483 -111
  40. package/dist-lib/lib/afhandelingSettings.functions.d.ts.map +1 -1
  41. package/dist-lib/lib/afhandelingSettings.functions.js +28 -1
  42. package/dist-lib/lib/carrierPlanning.d.ts +25 -0
  43. package/dist-lib/lib/carrierPlanning.d.ts.map +1 -0
  44. package/dist-lib/lib/carrierPlanning.js +65 -0
  45. package/dist-lib/lib/carrierSignupMail.server.d.ts +0 -2
  46. package/dist-lib/lib/carrierSignupMail.server.d.ts.map +1 -1
  47. package/dist-lib/lib/carrierSignupMail.server.js +53 -216
  48. package/dist-lib/lib/carriers.functions.d.ts +5920 -20
  49. package/dist-lib/lib/carriers.functions.d.ts.map +1 -1
  50. package/dist-lib/lib/carriers.functions.js +5 -0
  51. package/dist-lib/lib/cartAssignments.functions.d.ts +5920 -20
  52. package/dist-lib/lib/cartAssignments.functions.d.ts.map +1 -1
  53. package/dist-lib/lib/cartControl.functions.d.ts +11843 -40
  54. package/dist-lib/lib/cartControl.functions.d.ts.map +1 -1
  55. package/dist-lib/lib/cartControl.functions.js +4 -1
  56. package/dist-lib/lib/cartRescheduling.d.ts.map +1 -1
  57. package/dist-lib/lib/cartRescheduling.js +8 -6
  58. package/dist-lib/lib/countries.d.ts +2 -0
  59. package/dist-lib/lib/countries.d.ts.map +1 -1
  60. package/dist-lib/lib/countries.js +51 -0
  61. package/dist-lib/lib/deliveryNotePrint.d.ts +26 -0
  62. package/dist-lib/lib/deliveryNotePrint.d.ts.map +1 -0
  63. package/dist-lib/lib/deliveryNotePrint.js +172 -0
  64. package/dist-lib/lib/floriday.functions.d.ts +1251 -63
  65. package/dist-lib/lib/floriday.functions.d.ts.map +1 -1
  66. package/dist-lib/lib/floriday.functions.js +126 -8
  67. package/dist-lib/lib/floridayAutoProcess.d.ts +30 -0
  68. package/dist-lib/lib/floridayAutoProcess.d.ts.map +1 -0
  69. package/dist-lib/lib/floridayAutoProcess.js +70 -0
  70. package/dist-lib/lib/pickstationI18n.d.ts +46 -0
  71. package/dist-lib/lib/pickstationI18n.d.ts.map +1 -1
  72. package/dist-lib/lib/pickstationI18n.js +251 -0
  73. package/dist-lib/lib/pickstationOrders.server.d.ts.map +1 -1
  74. package/dist-lib/lib/pickstationOrders.server.js +56 -19
  75. package/dist-lib/lib/pickstationTypes.d.ts +2 -0
  76. package/dist-lib/lib/pickstationTypes.d.ts.map +1 -1
  77. package/dist-lib/lib/planning.d.ts +34 -0
  78. package/dist-lib/lib/planning.d.ts.map +1 -1
  79. package/dist-lib/lib/planning.js +84 -0
  80. package/package.json +15 -1
@@ -0,0 +1,12 @@
1
+ interface Props {
2
+ salesOrderId: string;
3
+ /** Datum waarop de auto-verwerking mag starten (targetPickDate). */
4
+ autoProcessDate?: Date | null;
5
+ /** Toon knop "Nu verwerken" ook als datum nog niet bereikt. */
6
+ allowManualTrigger?: boolean;
7
+ /** Compact = alleen badge, geen knoppen. */
8
+ compact?: boolean;
9
+ }
10
+ export declare function AutoProcessStatus({ salesOrderId, autoProcessDate, allowManualTrigger, compact, }: Props): import("react").JSX.Element;
11
+ export {};
12
+ //# sourceMappingURL=AutoProcessStatus.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,103 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ import { Badge, Button, toast } from "@flowselections/core";
4
+ import { CheckCircle2, Clock, Loader2, PlayCircle, RefreshCw, AlertTriangle } from "lucide-react";
5
+ import { autoProcessSalesOrder, fetchAutoProcessStatuses, } from "../../lib/floridayAutoProcess";
6
+ import { supabase } from "../../integrations/supabase/client";
7
+ const NL_DATE = new Intl.DateTimeFormat("nl-NL", { day: "2-digit", month: "short" });
8
+ function formatWaiting(date) {
9
+ const today = new Date();
10
+ today.setHours(0, 0, 0, 0);
11
+ const target = new Date(date);
12
+ target.setHours(0, 0, 0, 0);
13
+ const diffDays = Math.round((target.getTime() - today.getTime()) / 86400000);
14
+ if (diffDays <= 0)
15
+ return "Klaar om te verwerken";
16
+ if (diffDays === 1)
17
+ return "Verwerkt morgen";
18
+ return `Wacht tot ${NL_DATE.format(target)} (${diffDays} dagen)`;
19
+ }
20
+ export function AutoProcessStatus({ salesOrderId, autoProcessDate, allowManualTrigger = true, compact = false, }) {
21
+ const [row, setRow] = useState(null);
22
+ const [loading, setLoading] = useState(false);
23
+ useEffect(() => {
24
+ let cancelled = false;
25
+ fetchAutoProcessStatuses([salesOrderId]).then((m) => {
26
+ if (!cancelled)
27
+ setRow(m.get(salesOrderId) ?? null);
28
+ });
29
+ const channel = supabase
30
+ .channel(`auto-process-${salesOrderId}`)
31
+ .on("postgres_changes", {
32
+ event: "*",
33
+ schema: "public",
34
+ table: "floriday_auto_fulfillment_log",
35
+ filter: `sales_order_id=eq.${salesOrderId}`,
36
+ }, () => {
37
+ fetchAutoProcessStatuses([salesOrderId]).then((m) => {
38
+ if (!cancelled)
39
+ setRow(m.get(salesOrderId) ?? null);
40
+ });
41
+ })
42
+ .subscribe();
43
+ return () => {
44
+ cancelled = true;
45
+ supabase.removeChannel(channel);
46
+ };
47
+ }, [salesOrderId]);
48
+ const handleProcess = async () => {
49
+ setLoading(true);
50
+ try {
51
+ const res = await autoProcessSalesOrder(salesOrderId);
52
+ toast.success(res.status === "done"
53
+ ? "Verwerkt — afleverbrief wordt aangemaakt"
54
+ : "Auto-verwerking gestart");
55
+ }
56
+ catch (e) {
57
+ toast.error(e instanceof Error ? e.message : "Auto-verwerking mislukt");
58
+ }
59
+ finally {
60
+ setLoading(false);
61
+ fetchAutoProcessStatuses([salesOrderId]).then((m) => setRow(m.get(salesOrderId) ?? null));
62
+ }
63
+ };
64
+ const status = row?.status;
65
+ const now = new Date();
66
+ const reached = !autoProcessDate || now >= autoProcessDate;
67
+ let badge;
68
+ if (status === "done") {
69
+ badge = (_jsxs(Badge, { variant: "secondary", className: "gap-1 bg-green-100 text-green-800", children: [_jsx(CheckCircle2, { className: "h-3 w-3" }), " Afleverbrief klaar"] }));
70
+ }
71
+ else if (status === "error") {
72
+ badge = (_jsxs(Badge, { variant: "destructive", className: "gap-1", children: [_jsx(AlertTriangle, { className: "h-3 w-3" }), " Fout \u2014 ", row?.error?.slice(0, 40) ?? "onbekend"] }));
73
+ }
74
+ else if (status === "waiting_for_commit") {
75
+ const deadline = autoProcessDate
76
+ ? new Intl.DateTimeFormat("nl-NL", { hour: "2-digit", minute: "2-digit" }).format(autoProcessDate)
77
+ : null;
78
+ badge = (_jsxs(Badge, { variant: "outline", className: "gap-1", children: [_jsx(Clock, { className: "h-3 w-3" }), " Wacht op commit", deadline ? ` — deadline ${deadline}` : ""] }));
79
+ }
80
+ else if (status === "waiting_for_delivery_order") {
81
+ badge = (_jsxs(Badge, { variant: "outline", className: "gap-1", children: [_jsx(Clock, { className: "h-3 w-3" }), " Wacht op Floriday delivery-order"] }));
82
+ }
83
+ else if (status === "ready_to_fulfill") {
84
+ badge = (_jsxs(Badge, { variant: "secondary", className: "gap-1", children: [_jsx(PlayCircle, { className: "h-3 w-3" }), " Klaar voor fulfillment"] }));
85
+ }
86
+ else if (status === "acknowledging" ||
87
+ status === "creating_delivery_order" ||
88
+ status === "sending_fulfillment" ||
89
+ status === "generating_delivery_note") {
90
+ badge = (_jsxs(Badge, { variant: "secondary", className: "gap-1", children: [_jsx(Loader2, { className: "h-3 w-3 animate-spin" }), " In verwerking"] }));
91
+ }
92
+ else if (!reached && autoProcessDate) {
93
+ badge = (_jsxs(Badge, { variant: "outline", className: "gap-1", children: [_jsx(Clock, { className: "h-3 w-3" }), " ", formatWaiting(autoProcessDate)] }));
94
+ }
95
+ else {
96
+ badge = (_jsxs(Badge, { variant: "outline", className: "gap-1", children: [_jsx(Clock, { className: "h-3 w-3" }), " Klaar om te verwerken"] }));
97
+ }
98
+ if (compact)
99
+ return _jsx(_Fragment, { children: badge });
100
+ const showRetry = status === "error";
101
+ 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] }));
103
+ }
@@ -1,7 +1,9 @@
1
1
  import type { ControlCart } from "../../lib/cartControl.functions";
2
+ import { type PickstationLang } from "../../lib/pickstationI18n";
2
3
  /** Printbare controlelijst — één regel per kar met checkbox en opmerkingveld. */
3
- export declare function ControleLijstPrint({ carts, onClose, }: {
4
+ export declare function ControleLijstPrint({ carts, onClose, lang, }: {
4
5
  carts: ControlCart[];
5
6
  onClose: () => void;
7
+ lang?: PickstationLang;
6
8
  }): import("react").ReactPortal | null;
7
9
  //# sourceMappingURL=ControleLijstPrint.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ControleLijstPrint.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/ControleLijstPrint.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAanE,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,OAAO,GACR,EAAE;IACD,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,sCAkIA"}
1
+ {"version":3,"file":"ControleLijstPrint.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/ControleLijstPrint.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAEnE,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,2BAA2B,CAAC;AAgCnC,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,OAAO,EACP,IAAW,GACZ,EAAE;IACD,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,IAAI,CAAC,EAAE,eAAe,CAAC;CACxB,sCAoJA"}
@@ -3,40 +3,79 @@ import { useEffect } from "react";
3
3
  import { createPortal } from "react-dom";
4
4
  import { Button } from "@flowselections/core";
5
5
  import { X, Printer } from "lucide-react";
6
- function fmt(iso) {
7
- if (!iso)
8
- return "—";
9
- const d = new Date(iso);
10
- if (Number.isNaN(d.getTime()))
11
- return iso;
12
- return d.toLocaleDateString("nl-NL", {
13
- day: "2-digit",
14
- month: "2-digit",
15
- year: "numeric",
16
- });
6
+ import { countryCode } from "../../lib/countries";
7
+ import { getPrintDict, PICKSTATION_LOCALE, } from "../../lib/pickstationI18n";
8
+ const DAY_ABBR_BY_LANG = {
9
+ nl: ["ZO", "MA", "DI", "WO", "DO", "VR", "ZA"],
10
+ en: ["SU", "MO", "TU", "WE", "TH", "FR", "SA"],
11
+ pl: ["ND", "PN", "WT", "ŚR", "CZ", "PT", "SB"],
12
+ ro: ["DU", "LU", "MA", "MI", "JO", "VI", "SÂ"],
13
+ bg: ["НД", "ПН", "ВТ", "СР", "ЧТ", "ПТ", "СБ"],
14
+ uk: ["НД", "ПН", "ВТ", "СР", "ЧТ", "ПТ", "СБ"],
15
+ };
16
+ function computeKlaarzet(cart, lang) {
17
+ if (!cart.pickupDate || !cart.pickupTime) {
18
+ return { label: "—", sortKey: Number.MAX_SAFE_INTEGER };
19
+ }
20
+ const [hh, mm] = cart.pickupTime.split(":").map((n) => parseInt(n, 10));
21
+ const d = new Date(cart.pickupDate);
22
+ if (Number.isNaN(d.getTime()) || Number.isNaN(hh) || Number.isNaN(mm)) {
23
+ return { label: "—", sortKey: Number.MAX_SAFE_INTEGER };
24
+ }
25
+ d.setHours(hh, mm, 0, 0);
26
+ d.setHours(d.getHours() - 1);
27
+ const day = (DAY_ABBR_BY_LANG[lang] ?? DAY_ABBR_BY_LANG.nl)[d.getDay()];
28
+ const time = `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
29
+ return { label: `${day} - ${time}`, sortKey: d.getTime() };
17
30
  }
18
31
  /** Printbare controlelijst — één regel per kar met checkbox en opmerkingveld. */
19
- export function ControleLijstPrint({ carts, onClose, }) {
32
+ export function ControleLijstPrint({ carts, onClose, lang = "nl", }) {
33
+ const t = getPrintDict(lang);
34
+ const locale = PICKSTATION_LOCALE[lang] ?? "nl-NL";
20
35
  useEffect(() => {
21
- const t = setTimeout(() => window.print(), 300);
36
+ const timer = setTimeout(() => window.print(), 300);
22
37
  const handleAfterPrint = () => onClose();
23
38
  window.addEventListener("afterprint", handleAfterPrint);
24
39
  return () => {
25
- clearTimeout(t);
40
+ clearTimeout(timer);
26
41
  window.removeEventListener("afterprint", handleAfterPrint);
27
42
  };
28
43
  }, [onClose]);
29
- const today = new Date().toLocaleDateString("nl-NL", {
44
+ const statusLabel = (status, printedCount) => {
45
+ switch (status) {
46
+ case "not_printed": return t.statusNotPrinted;
47
+ case "printed": return t.statusPrinted(printedCount);
48
+ case "checked": return t.statusChecked;
49
+ case "ready": return t.statusReady;
50
+ case "shipped": return t.statusShipped;
51
+ case "delivered": return t.statusDelivered;
52
+ default: return String(status);
53
+ }
54
+ };
55
+ const today = new Date().toLocaleDateString(locale, {
30
56
  weekday: "long",
31
57
  day: "2-digit",
32
58
  month: "long",
33
59
  year: "numeric",
34
60
  });
35
- const content = (_jsxs("div", { id: "controle-print-root", className: "fixed inset-0 z-[100] bg-white overflow-auto", children: [_jsxs("div", { className: "print:hidden sticky top-0 flex items-center justify-between p-3 border-b bg-white", children: [_jsx("div", { className: "font-semibold", children: "Controlelijst \u2014 printweergave" }), _jsxs("div", { className: "flex gap-2", children: [_jsxs(Button, { size: "sm", variant: "outline", onClick: () => window.print(), children: [_jsx(Printer, { className: "h-4 w-4 mr-2" }), "Opnieuw printen"] }), _jsxs(Button, { size: "sm", variant: "outline", onClick: onClose, children: [_jsx(X, { className: "h-4 w-4 mr-2" }), "Sluiten"] })] })] }), _jsxs("div", { className: "print-sheet p-8 print:p-0 max-w-[210mm] mx-auto text-black", children: [_jsxs("div", { className: "flex items-baseline justify-between border-b border-black pb-2 mb-4", children: [_jsx("h1", { className: "text-2xl font-bold", children: "Controlelijst karren" }), _jsx("div", { className: "text-sm", children: today })] }), _jsxs("div", { className: "text-sm mb-3", children: ["Totaal karren: ", _jsx("strong", { children: carts.length })] }), _jsxs("table", { className: "w-full text-[11px] border-collapse", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b border-black", children: [_jsx("th", { className: "text-left py-1 pr-2", children: "Karnr" }), _jsx("th", { className: "text-left py-1 pr-2", children: "Klant" }), _jsx("th", { className: "text-left py-1 pr-2", children: "Vervoerder" }), _jsx("th", { className: "text-left py-1 pr-2", children: "Lever" }), _jsx("th", { className: "text-left py-1 pr-2", children: "Ophaal" }), _jsx("th", { className: "text-left py-1 pr-2", children: "Print" }), _jsx("th", { className: "text-center py-1 px-2", children: "Klaar" }), _jsx("th", { className: "text-left py-1 pr-2", children: "Opmerkingen" })] }) }), _jsxs("tbody", { children: [carts.map((c) => (_jsxs("tr", { className: "border-b border-gray-300", children: [_jsx("td", { className: "py-2 pr-2 font-mono font-bold whitespace-nowrap", children: c.cartNumber ?? "—" }), _jsx("td", { className: "py-2 pr-2", children: c.customerName }), _jsx("td", { className: "py-2 pr-2", children: c.carrierName ?? "—" }), _jsx("td", { className: "py-2 pr-2 whitespace-nowrap", children: fmt(c.deliveryDate) }), _jsx("td", { className: "py-2 pr-2 whitespace-nowrap", children: fmt(c.pickupDate) }), _jsx("td", { className: "py-2 pr-2 text-center", children: c.printedCount > 0 ? "✓" : "" }), _jsx("td", { className: "py-2 px-2 text-center", children: _jsx("span", { className: "inline-block w-4 h-4 border border-black" }) }), _jsx("td", { className: "py-2 pr-2 w-[30%]", children: _jsx("span", { className: "inline-block w-full border-b border-gray-400 h-4" }) })] }, `${c.orderSource}#${c.orderId}#${c.cartIndex}`))), carts.length === 0 && (_jsx("tr", { children: _jsx("td", { colSpan: 8, className: "py-6 text-center text-gray-500", children: "Geen karren om vandaag te controleren." }) }))] })] }), _jsxs("div", { className: "mt-6 text-[11px]", children: [_jsxs("div", { children: ["Gecontroleerd door: ", _jsx("span", { className: "inline-block border-b border-black w-64" })] }), _jsxs("div", { className: "mt-2", children: ["Datum / tijd: ", _jsx("span", { className: "inline-block border-b border-black w-64" })] }), _jsxs("div", { className: "mt-2", children: ["Handtekening: ", _jsx("span", { className: "inline-block border-b border-black w-64" })] })] })] }), _jsx("style", { children: `
61
+ const sortedCarts = carts
62
+ .map((cart) => ({ cart, klaarzet: computeKlaarzet(cart, lang) }))
63
+ .sort((a, b) => {
64
+ if (a.klaarzet.sortKey !== b.klaarzet.sortKey) {
65
+ return a.klaarzet.sortKey - b.klaarzet.sortKey;
66
+ }
67
+ const ac = a.cart.country ?? "\uFFFF";
68
+ const bc = b.cart.country ?? "\uFFFF";
69
+ if (ac !== bc)
70
+ return ac.localeCompare(bc);
71
+ const an = a.cart.cartNumber ?? "\uFFFF";
72
+ const bn = b.cart.cartNumber ?? "\uFFFF";
73
+ return an.localeCompare(bn);
74
+ });
75
+ const content = (_jsxs("div", { id: "controle-print-root", className: "fixed inset-0 z-[100] bg-white overflow-auto", lang: lang, children: [_jsxs("div", { className: "print:hidden sticky top-0 flex items-center justify-between p-3 border-b bg-white", children: [_jsx("div", { className: "font-semibold", children: t.checklistPrintView }), _jsxs("div", { className: "flex gap-2", children: [_jsxs(Button, { size: "sm", variant: "outline", onClick: () => window.print(), children: [_jsx(Printer, { className: "h-4 w-4 mr-2" }), t.reprint] }), _jsxs(Button, { size: "sm", variant: "outline", onClick: onClose, children: [_jsx(X, { className: "h-4 w-4 mr-2" }), t.close] })] })] }), _jsxs("div", { className: "print-sheet p-8 print:p-0 max-w-[210mm] mx-auto text-black", children: [_jsxs("div", { className: "flex items-baseline justify-between border-b border-black pb-2 mb-4", children: [_jsx("h1", { className: "text-2xl font-bold", children: t.checklistTitle }), _jsx("div", { className: "text-sm", children: today })] }), _jsxs("div", { className: "text-sm mb-3", children: [t.totalCarts, ": ", _jsx("strong", { children: carts.length })] }), _jsxs("table", { className: "w-full text-[11px] border-collapse", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b border-black", children: [_jsx("th", { className: "text-left py-1 pr-2", children: t.colKarnr }), _jsx("th", { className: "text-right py-1 pr-2", children: t.colFusten }), _jsx("th", { className: "text-left py-1 pr-2", children: t.colLand }), _jsx("th", { className: "text-left py-1 pr-2", children: t.colKlaarzetten }), _jsx("th", { className: "text-left py-1 pr-2", children: t.colStatus })] }) }), _jsxs("tbody", { children: [sortedCarts.map(({ cart: c, klaarzet }) => (_jsxs("tr", { className: "border-b border-gray-300", children: [_jsx("td", { className: "py-2 pr-2 font-mono font-bold whitespace-nowrap", children: c.cartNumber ?? "—" }), _jsx("td", { className: "py-2 pr-2 text-right whitespace-nowrap", children: c.cratesOnCart ?? "—" }), _jsx("td", { className: "py-2 pr-2 whitespace-nowrap font-semibold", children: countryCode(c.country) ?? c.country ?? "—" }), _jsx("td", { className: "py-2 pr-2 whitespace-nowrap font-semibold", children: klaarzet.label }), _jsx("td", { className: "py-2 pr-2 whitespace-nowrap", children: statusLabel(c.status, c.printedCount) })] }, `${c.orderSource}#${c.orderId}#${c.cartIndex}`))), sortedCarts.length === 0 && (_jsx("tr", { children: _jsx("td", { colSpan: 5, className: "py-6 text-center text-gray-500", children: t.noCartsToday }) }))] })] }), _jsxs("div", { className: "mt-6 text-[11px]", children: [_jsxs("div", { children: [t.checkedBy, ": ", _jsx("span", { className: "inline-block border-b border-black w-64" })] }), _jsxs("div", { className: "mt-2", children: [t.dateTime, ": ", _jsx("span", { className: "inline-block border-b border-black w-64" })] }), _jsxs("div", { className: "mt-2", children: [t.signature, ": ", _jsx("span", { className: "inline-block border-b border-black w-64" })] })] })] }), _jsx("style", { children: `
36
76
  @media print {
37
77
  @page { size: A4 portrait; margin: 12mm; }
38
78
  html, body { background: #fff !important; margin: 0 !important; padding: 0 !important; }
39
- /* Hide the entire app; show only the print root */
40
79
  body > *:not(#controle-print-portal) { display: none !important; }
41
80
  #controle-print-portal, #controle-print-root {
42
81
  position: static !important;
@@ -1 +1 @@
1
- {"version":3,"file":"DagDetailDialog.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/DagDetailDialog.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAyBjE,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,sCA2E1F"}
1
+ {"version":3,"file":"DagDetailDialog.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/DagDetailDialog.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AA6BjE,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,sCA2E1F"}
@@ -3,11 +3,15 @@ import { useState } from "react";
3
3
  import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
4
4
  import { useServerFn } from "@tanstack/react-start";
5
5
  import { Badge, Button, Dialog, DialogTitle, DialogDescription, Input, Tabs, TabsContent, TabsList, TabsTrigger, toast, } from "@flowselections/core";
6
- import { ChevronDown, ChevronRight, MoveRight, Truck } from "lucide-react";
6
+ import { ChevronDown, ChevronRight, MoveRight, Printer, Truck } from "lucide-react";
7
7
  import { ResponsiveDialogBody, ResponsiveDialogContent, ResponsiveDialogFooter, ResponsiveDialogHeader, } from "../../components/ui/responsive-dialog";
8
8
  import { isSameDay } from "../../lib/pickDate";
9
9
  import { getOrderLines, moveCart as moveCartFn, } from "../../lib/cartAssignments.functions";
10
10
  import { evaluateCartMove } from "../../lib/cartMoveImpact";
11
+ import { renderPakbonHtml } from "../pickstation/PakbonTemplate";
12
+ import { printHtml } from "../pickstation/printDocuments";
13
+ import { printDeliveryNotesMerged } from "../../lib/deliveryNotePrint";
14
+ import { AutoProcessStatus } from "./AutoProcessStatus";
11
15
  const NL_DATE = new Intl.DateTimeFormat("nl-NL", { dateStyle: "full" });
12
16
  export function DagDetailDialog({ open, date, planned, onOpenChange }) {
13
17
  if (!date)
@@ -64,6 +68,7 @@ function BestellingenTab({ orders, date }) {
64
68
  }
65
69
  function OrderRow({ planned: p, cartsToday }) {
66
70
  const [open, setOpen] = useState(false);
71
+ const [printing, setPrinting] = useState(false);
67
72
  const source = p.order.source;
68
73
  const fetchLines = useServerFn(getOrderLines);
69
74
  const linesQuery = useQuery({
@@ -71,9 +76,96 @@ function OrderRow({ planned: p, cartsToday }) {
71
76
  queryFn: () => fetchLines({ data: { orderId: p.order.id, orderSource: source } }),
72
77
  enabled: open,
73
78
  });
74
- return (_jsxs("div", { className: "rounded-lg border bg-card", children: [_jsxs("button", { type: "button", onClick: () => setOpen((o) => !o), className: "flex w-full items-center gap-3 px-4 py-3 text-left hover:bg-muted/50", children: [open ? _jsx(ChevronDown, { className: "h-4 w-4" }) : _jsx(ChevronRight, { className: "h-4 w-4" }), _jsxs("div", { className: "flex-1 grid grid-cols-2 md:grid-cols-4 gap-3 text-sm", children: [_jsxs("div", { children: [_jsx("div", { className: "font-medium", children: p.order.orderNumber }), _jsx("div", { className: "text-xs text-muted-foreground", children: p.order.customerName })] }), _jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: "Type" }), _jsx("div", { children: p.order.deliveryType })] }), _jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: "Leverdatum" }), _jsx("div", { children: p.order.deliveryDate
75
- ? new Date(p.order.deliveryDate).toLocaleDateString("nl-NL")
76
- : "—" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Badge, { variant: "secondary", children: [cartsToday, " karren vandaag"] }), _jsx(Badge, { variant: "outline", children: p.order.status })] })] })] }), open && (_jsxs("div", { className: "border-t px-4 py-3 space-y-3", children: [_jsxs("div", { className: "grid grid-cols-2 md:grid-cols-3 gap-3 text-sm", children: [_jsx(Field, { label: "Afleverlocatie", value: "\u2014" }), _jsx(Field, { label: "Ophaallocatie (tuin)", value: "\u2014" }), _jsx(Field, { label: "Vervoerder", value: "\u2014" })] }), _jsxs("div", { children: [_jsx("div", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Orderregels" }), linesQuery.isLoading && _jsx("p", { className: "text-xs", children: "Regels laden\u2026" }), linesQuery.data && _jsx(OrderLinesTable, { lines: linesQuery.data.lines }), linesQuery.error && _jsx("p", { className: "text-xs text-destructive", children: "Kon regels niet laden" })] })] }))] }));
79
+ const handlePrintAll = async (e) => {
80
+ e.stopPropagation();
81
+ if (printing)
82
+ return;
83
+ setPrinting(true);
84
+ try {
85
+ // Zorg dat we regels hebben — anders eerst ophalen.
86
+ let lines = linesQuery.data?.lines ?? [];
87
+ if (lines.length === 0) {
88
+ try {
89
+ const res = await fetchLines({ data: { orderId: p.order.id, orderSource: source } });
90
+ lines = res.lines;
91
+ }
92
+ catch {
93
+ /* doorgaan met lege regels */
94
+ }
95
+ }
96
+ const cartTotal = Math.max(1, p.order.cartCount ?? 1);
97
+ const pickDateIso = p.planning?.pickAssignments?.[0]?.date?.toISOString?.().slice(0, 10) ??
98
+ new Date().toISOString().slice(0, 10);
99
+ const pakbonLines = lines.map((l) => ({
100
+ description: l.article,
101
+ crates: l.crates,
102
+ unit: null,
103
+ }));
104
+ let printed = 0;
105
+ for (let idx = 0; idx < cartTotal; idx++) {
106
+ const html = renderPakbonHtml({
107
+ id: `${p.order.id}#${idx}`,
108
+ orderNumber: p.order.orderNumber,
109
+ customerName: p.order.customerName,
110
+ country: p.order.country ?? null,
111
+ deliveryDate: p.order.deliveryDate,
112
+ pickDate: pickDateIso,
113
+ cartIndex: idx + 1,
114
+ cartTotal,
115
+ cratesOnCart: null,
116
+ cartNumber: `${p.order.orderNumber}-${String(idx + 1).padStart(2, "0")}`,
117
+ lines: pakbonLines,
118
+ }, "nl");
119
+ await printHtml(html);
120
+ printed++;
121
+ }
122
+ let deliveryOk = 0;
123
+ let deliveryFailed = 0;
124
+ const salesOrderId = p.order.salesOrderId ?? (source === "floriday" ? p.order.id : null);
125
+ if (salesOrderId) {
126
+ try {
127
+ const res = await printDeliveryNotesMerged([
128
+ { id: p.order.id, salesOrderId },
129
+ ]);
130
+ deliveryOk = res.success;
131
+ deliveryFailed = res.failed.length;
132
+ if (res.failed.length > 0) {
133
+ console.warn("[print-all] afleverbrief mislukt", res.failed);
134
+ }
135
+ }
136
+ catch (err) {
137
+ deliveryFailed = 1;
138
+ console.warn("[print-all] afleverbrief-fout", err);
139
+ }
140
+ }
141
+ const parts = [`${printed} pakbon${printed === 1 ? "" : "nen"}`];
142
+ if (deliveryOk > 0)
143
+ parts.push(`${deliveryOk} afleverbrief`);
144
+ toast.success(`Documenten verstuurd naar printer — ${parts.join(", ")}.`);
145
+ if (deliveryFailed > 0) {
146
+ toast.error(`${deliveryFailed} afleverbrief kon niet worden opgehaald.`);
147
+ }
148
+ }
149
+ catch (err) {
150
+ const msg = err instanceof Error ? err.message : "Printen mislukt";
151
+ toast.error(msg);
152
+ console.error("[print-all]", err);
153
+ }
154
+ finally {
155
+ setPrinting(false);
156
+ }
157
+ };
158
+ return (_jsxs("div", { className: "rounded-lg border bg-card", children: [_jsxs("div", { className: "flex items-center gap-2 pr-3", children: [_jsxs("button", { type: "button", onClick: () => setOpen((o) => !o), className: "flex flex-1 items-center gap-3 px-4 py-3 text-left hover:bg-muted/50", children: [open ? _jsx(ChevronDown, { className: "h-4 w-4" }) : _jsx(ChevronRight, { className: "h-4 w-4" }), _jsxs("div", { className: "flex-1 grid grid-cols-2 md:grid-cols-4 gap-3 text-sm", children: [_jsxs("div", { children: [_jsx("div", { className: "font-medium", children: p.order.orderNumber }), _jsx("div", { className: "text-xs text-muted-foreground", children: p.order.customerName })] }), _jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: "Type" }), _jsx("div", { children: p.order.deliveryType })] }), _jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: "Leverdatum" }), _jsx("div", { children: p.order.deliveryDate
159
+ ? new Date(p.order.deliveryDate).toLocaleDateString("nl-NL")
160
+ : "—" })] }), _jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [_jsxs(Badge, { variant: "secondary", children: [cartsToday, " karren vandaag"] }), _jsx(Badge, { variant: "outline", children: p.order.status }), (() => {
161
+ const src = p.order.source === "floriday" ? "floriday" : "manual";
162
+ const soId = p.order.salesOrderId ?? (src === "floriday" ? p.order.id : null);
163
+ return soId ? (_jsx(AutoProcessStatus, { salesOrderId: soId, compact: true, allowManualTrigger: false })) : null;
164
+ })()] })] })] }), _jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [(() => {
165
+ const src = p.order.source === "floriday" ? "floriday" : "manual";
166
+ const soId = p.order.salesOrderId ?? (src === "floriday" ? p.order.id : null);
167
+ return soId ? (_jsx(AutoProcessStatus, { salesOrderId: soId })) : null;
168
+ })(), _jsxs(Button, { size: "sm", variant: "outline", onClick: handlePrintAll, disabled: printing, 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"] })] })] }), open && (_jsxs("div", { className: "border-t px-4 py-3 space-y-3", children: [_jsxs("div", { className: "grid grid-cols-2 md:grid-cols-3 gap-3 text-sm", children: [_jsx(Field, { label: "Afleverlocatie", value: "\u2014" }), _jsx(Field, { label: "Ophaallocatie (tuin)", value: "\u2014" }), _jsx(Field, { label: "Vervoerder", value: "\u2014" })] }), _jsxs("div", { children: [_jsx("div", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Orderregels" }), linesQuery.isLoading && _jsx("p", { className: "text-xs", children: "Regels laden\u2026" }), linesQuery.data && _jsx(OrderLinesTable, { lines: linesQuery.data.lines }), linesQuery.error && _jsx("p", { className: "text-xs text-destructive", children: "Kon regels niet laden" })] })] }))] }));
77
169
  }
78
170
  function Field({ label, value }) {
79
171
  return (_jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: label }), _jsx("div", { children: value })] }));
@@ -33,5 +33,5 @@ export function LeveringenPage() {
33
33
  return true;
34
34
  });
35
35
  }, [planned, customer, deliveryType, dateFrom, dateTo]);
36
- return (_jsx("main", { className: "p-6 space-y-6", children: _jsxs(Tabs, { defaultValue: "overzicht", className: "space-y-6", children: [_jsxs(TabsList, { children: [_jsx(TabsTrigger, { value: "overzicht", children: "Overzicht" }), _jsx(TabsTrigger, { value: "veilbrieven", children: "Veilbrieven" })] }), _jsxs("div", { className: "flex flex-wrap items-end justify-between gap-3", children: [_jsxs("div", { className: "flex flex-wrap items-end gap-3", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("label", { className: "text-xs text-muted-foreground", children: "Datum vanaf" }), _jsx(Input, { type: "date", value: dateFrom, onChange: (e) => setDateFrom(e.target.value), className: "w-40" })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("label", { className: "text-xs text-muted-foreground", children: "Datum t/m" }), _jsx(Input, { type: "date", value: dateTo, onChange: (e) => setDateTo(e.target.value), className: "w-40" })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("label", { className: "text-xs text-muted-foreground", children: "Klant" }), _jsxs(Select, { value: customer, onValueChange: setCustomer, children: [_jsx(SelectTrigger, { className: "w-56", children: _jsx(SelectValue, { placeholder: "Alle klanten" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: ALL, children: "Alle klanten" }), customers.map((c) => _jsx(SelectItem, { value: c, children: c }, c))] })] })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("label", { className: "text-xs text-muted-foreground", children: "Type levering" }), _jsxs(Select, { value: deliveryType, onValueChange: setDeliveryType, children: [_jsx(SelectTrigger, { className: "w-56", children: _jsx(SelectValue, { placeholder: "Alle types" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: ALL, children: "Alle types" }), deliveryTypes.map((t) => _jsx(SelectItem, { value: t, children: t }, t))] })] })] })] }), _jsx("div", { className: "flex items-end gap-2", children: _jsxs(Button, { variant: "outline", onClick: handleRecalc, children: [_jsx(RefreshCw, { className: "mr-2 h-4 w-4" }), "Herbereken planning"] }) })] }), _jsxs(TabsContent, { value: "overzicht", className: "space-y-3", 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: filtered, mode: "delivery", isLoading: isLoading }))] }), _jsx(TabsContent, { value: "veilbrieven", children: _jsx("div", { className: "rounded-md border border-dashed p-10 text-center text-sm text-muted-foreground", children: "Veilbrieven volgen in een volgende iteratie." }) })] }) }));
36
+ return (_jsx("main", { className: "p-6 space-y-6", children: _jsxs(Tabs, { defaultValue: "overzicht", className: "space-y-6", children: [_jsxs(TabsList, { children: [_jsx(TabsTrigger, { value: "overzicht", children: "Overzicht" }), _jsx(TabsTrigger, { value: "veilbrieven", children: "Veilbrieven" })] }), _jsxs("div", { className: "flex flex-wrap items-end justify-between gap-3", children: [_jsxs("div", { className: "flex flex-wrap items-end gap-3", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("label", { className: "text-xs text-muted-foreground", children: "Datum vanaf" }), _jsx(Input, { type: "date", value: dateFrom, onChange: (e) => setDateFrom(e.target.value), className: "w-40" })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("label", { className: "text-xs text-muted-foreground", children: "Datum t/m" }), _jsx(Input, { type: "date", value: dateTo, onChange: (e) => setDateTo(e.target.value), className: "w-40" })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("label", { className: "text-xs text-muted-foreground", children: "Klant" }), _jsxs(Select, { value: customer, onValueChange: setCustomer, children: [_jsx(SelectTrigger, { className: "w-56", children: _jsx(SelectValue, { placeholder: "Alle klanten" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: ALL, children: "Alle klanten" }), customers.map((c) => _jsx(SelectItem, { value: c, children: c }, c))] })] })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("label", { className: "text-xs text-muted-foreground", children: "Type levering" }), _jsxs(Select, { value: deliveryType, onValueChange: setDeliveryType, children: [_jsx(SelectTrigger, { className: "w-56", children: _jsx(SelectValue, { placeholder: "Alle types" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: ALL, children: "Alle types" }), deliveryTypes.map((t) => _jsx(SelectItem, { value: t, children: t }, t))] })] })] })] }), _jsx("div", { className: "flex items-end gap-2", children: _jsxs(Button, { variant: "outline", onClick: handleRecalc, children: [_jsx(RefreshCw, { className: "mr-2 h-4 w-4" }), "Herbereken planning"] }) })] }), _jsxs(TabsContent, { value: "overzicht", className: "space-y-3", 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: filtered, mode: "delivery", isLoading: isLoading, showPrintButtons: true }))] }), _jsx(TabsContent, { value: "veilbrieven", children: _jsx("div", { className: "rounded-md border border-dashed p-10 text-center text-sm text-muted-foreground", children: "Veilbrieven volgen in een volgende iteratie." }) })] }) }));
37
37
  }
@@ -1 +1 @@
1
- {"version":3,"file":"VervoerdersPage.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/VervoerdersPage.tsx"],"names":[],"mappings":"AA4BA,wBAAgB,eAAe,gCA+L9B"}
1
+ {"version":3,"file":"VervoerdersPage.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/VervoerdersPage.tsx"],"names":[],"mappings":"AA6BA,wBAAgB,eAAe,gCA+L9B"}
@@ -7,6 +7,7 @@ import { Link } from "@tanstack/react-router";
7
7
  import { useServerFn } from "@tanstack/react-start";
8
8
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
9
9
  import { listCarriers, deleteCarrier, reorderCarriers } from "../../lib/carriers.functions";
10
+ import { carrierLeadDaysFromMoments } from "../../lib/carrierPlanning";
10
11
  export function VervoerdersPage() {
11
12
  const queryClient = useQueryClient();
12
13
  const fetchList = useServerFn(listCarriers);
@@ -56,5 +57,5 @@ export function VervoerdersPage() {
56
57
  [ids[index], ids[target]] = [ids[target], ids[index]];
57
58
  reorderMutation.mutate(ids);
58
59
  };
59
- return (_jsxs("div", { className: "p-6 space-y-6", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-semibold", children: "Vervoerders" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Beheer vervoerders en hun verzendtarieven per land." })] }), _jsx(Button, { asChild: true, children: _jsxs(Link, { to: "/afhandeling/vervoerders/nieuw", children: [_jsx(Plus, { className: "w-4 h-4 mr-1" }), "Vervoerder toevoegen"] }) })] }), _jsx("div", { className: "border rounded-md bg-card", children: isLoading ? (_jsx("div", { className: "p-12 text-center text-muted-foreground", children: "Laden..." })) : error ? (_jsxs("div", { className: "p-12 text-center space-y-3", children: [_jsxs("div", { className: "text-destructive", children: ["Fout bij laden: ", error.message] }), _jsx(Button, { variant: "outline", onClick: () => refetch(), children: "Opnieuw proberen" })] })) : carriers.length === 0 ? (_jsxs("div", { className: "p-12 text-center space-y-3", children: [_jsx(Truck, { className: "w-10 h-10 mx-auto text-muted-foreground" }), _jsx("div", { className: "font-medium", children: "Nog geen vervoerders" }), _jsx("div", { className: "text-sm text-muted-foreground", children: "Voeg een vervoerder toe om verzendtarieven in te stellen." }), _jsx(Button, { asChild: true, children: _jsxs(Link, { to: "/afhandeling/vervoerders/nieuw", children: [_jsx(Plus, { className: "w-4 h-4 mr-1" }), "Vervoerder toevoegen"] }) })] })) : (_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { className: "w-32", children: "Prioriteit" }), _jsx(TableHead, { children: "Bedrijfsnaam" }), _jsx(TableHead, { children: "Contactpersoon" }), _jsx(TableHead, { children: "E-mail" }), _jsx(TableHead, { children: "Telefoon" }), _jsx(TableHead, { children: "Levertijd" }), _jsx(TableHead, { children: "Landen" }), _jsx(TableHead, { className: "text-right", children: "Acties" })] }) }), _jsx(TableBody, { children: carriers.map((c, index) => (_jsxs(TableRow, { children: [_jsx(TableCell, { children: _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("span", { className: "w-6 text-sm font-medium tabular-nums text-muted-foreground", children: index + 1 }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => move(index, -1), disabled: index === 0 || reorderMutation.isPending, "aria-label": "Hoger", children: _jsx(ArrowUp, { className: "w-4 h-4" }) }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => move(index, 1), disabled: index === carriers.length - 1 || reorderMutation.isPending, "aria-label": "Lager", children: _jsx(ArrowDown, { className: "w-4 h-4" }) })] }) }), _jsx(TableCell, { className: "font-medium", children: c.name }), _jsx(TableCell, { children: c.contact_person ?? "—" }), _jsx(TableCell, { children: c.email ?? "—" }), _jsx(TableCell, { children: c.phone ?? "—" }), _jsx(TableCell, { children: c.delivery_days != null ? `${c.delivery_days} dagen` : "—" }), _jsx(TableCell, { children: c.rate_count }), _jsx(TableCell, { className: "text-right", children: _jsxs("div", { className: "flex justify-end gap-1", children: [_jsx(Button, { asChild: true, variant: "ghost", size: "sm", children: _jsx(Link, { to: "/afhandeling/vervoerders/$id/bewerken", params: { id: c.id }, children: _jsx(Pencil, { className: "w-4 h-4" }) }) }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => setDeletingId(c.id), className: "text-destructive hover:text-destructive", children: _jsx(Trash2, { className: "w-4 h-4" }) })] }) })] }, c.id))) })] })) }), _jsx(AlertDialog, { open: !!deletingId, onOpenChange: (o) => !o && setDeletingId(null), children: _jsxs(ResponsiveAlertDialogContent, { size: "sm", children: [_jsx(ResponsiveAlertDialogHeader, { children: _jsx(AlertDialogTitle, { children: "Vervoerder verwijderen?" }) }), _jsx(ResponsiveAlertDialogBody, { children: _jsx(AlertDialogDescription, { children: "Deze actie kan niet ongedaan gemaakt worden. Alle verzendtarieven worden ook verwijderd." }) }), _jsxs(ResponsiveAlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: "Annuleren" }), _jsx(AlertDialogAction, { onClick: () => deletingId && deleteMutation.mutate(deletingId), className: "bg-destructive text-destructive-foreground hover:bg-destructive/90", children: "Verwijderen" })] })] }) })] }));
60
+ return (_jsxs("div", { className: "p-6 space-y-6", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-semibold", children: "Vervoerders" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Beheer vervoerders en hun verzendtarieven per land." })] }), _jsx(Button, { asChild: true, children: _jsxs(Link, { to: "/afhandeling/vervoerders/nieuw", children: [_jsx(Plus, { className: "w-4 h-4 mr-1" }), "Vervoerder toevoegen"] }) })] }), _jsx("div", { className: "border rounded-md bg-card", children: isLoading ? (_jsx("div", { className: "p-12 text-center text-muted-foreground", children: "Laden..." })) : error ? (_jsxs("div", { className: "p-12 text-center space-y-3", children: [_jsxs("div", { className: "text-destructive", children: ["Fout bij laden: ", error.message] }), _jsx(Button, { variant: "outline", onClick: () => refetch(), children: "Opnieuw proberen" })] })) : carriers.length === 0 ? (_jsxs("div", { className: "p-12 text-center space-y-3", children: [_jsx(Truck, { className: "w-10 h-10 mx-auto text-muted-foreground" }), _jsx("div", { className: "font-medium", children: "Nog geen vervoerders" }), _jsx("div", { className: "text-sm text-muted-foreground", children: "Voeg een vervoerder toe om verzendtarieven in te stellen." }), _jsx(Button, { asChild: true, children: _jsxs(Link, { to: "/afhandeling/vervoerders/nieuw", children: [_jsx(Plus, { className: "w-4 h-4 mr-1" }), "Vervoerder toevoegen"] }) })] })) : (_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { className: "w-32", children: "Prioriteit" }), _jsx(TableHead, { children: "Bedrijfsnaam" }), _jsx(TableHead, { children: "Contactpersoon" }), _jsx(TableHead, { children: "E-mail" }), _jsx(TableHead, { children: "Telefoon" }), _jsx(TableHead, { children: "Levertijd" }), _jsx(TableHead, { children: "Landen" }), _jsx(TableHead, { className: "text-right", children: "Acties" })] }) }), _jsx(TableBody, { children: carriers.map((c, index) => (_jsxs(TableRow, { children: [_jsx(TableCell, { children: _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("span", { className: "w-6 text-sm font-medium tabular-nums text-muted-foreground", children: index + 1 }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => move(index, -1), disabled: index === 0 || reorderMutation.isPending, "aria-label": "Hoger", children: _jsx(ArrowUp, { className: "w-4 h-4" }) }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => move(index, 1), disabled: index === carriers.length - 1 || reorderMutation.isPending, "aria-label": "Lager", children: _jsx(ArrowDown, { className: "w-4 h-4" }) })] }) }), _jsx(TableCell, { className: "font-medium", children: c.name }), _jsx(TableCell, { children: c.contact_person ?? "—" }), _jsx(TableCell, { children: c.email ?? "—" }), _jsx(TableCell, { children: c.phone ?? "—" }), _jsxs(TableCell, { children: [carrierLeadDaysFromMoments(c.pickup_moments), " werkdagen"] }), _jsx(TableCell, { children: c.rate_count }), _jsx(TableCell, { className: "text-right", children: _jsxs("div", { className: "flex justify-end gap-1", children: [_jsx(Button, { asChild: true, variant: "ghost", size: "sm", children: _jsx(Link, { to: "/afhandeling/vervoerders/$id/bewerken", params: { id: c.id }, children: _jsx(Pencil, { className: "w-4 h-4" }) }) }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => setDeletingId(c.id), className: "text-destructive hover:text-destructive", children: _jsx(Trash2, { className: "w-4 h-4" }) })] }) })] }, c.id))) })] })) }), _jsx(AlertDialog, { open: !!deletingId, onOpenChange: (o) => !o && setDeletingId(null), children: _jsxs(ResponsiveAlertDialogContent, { size: "sm", children: [_jsx(ResponsiveAlertDialogHeader, { children: _jsx(AlertDialogTitle, { children: "Vervoerder verwijderen?" }) }), _jsx(ResponsiveAlertDialogBody, { children: _jsx(AlertDialogDescription, { children: "Deze actie kan niet ongedaan gemaakt worden. Alle verzendtarieven worden ook verwijderd." }) }), _jsxs(ResponsiveAlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: "Annuleren" }), _jsx(AlertDialogAction, { onClick: () => deletingId && deleteMutation.mutate(deletingId), className: "bg-destructive text-destructive-foreground hover:bg-destructive/90", children: "Verwijderen" })] })] }) })] }));
60
61
  }
@@ -8,6 +8,8 @@ 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;
11
13
  }
12
- export declare function WeekAgendaView({ planned, mode, isLoading, onOrderClick, onDayClick, title, }: WeekAgendaViewProps): import("react").JSX.Element;
14
+ export declare function WeekAgendaView({ planned, mode, isLoading, onOrderClick, onDayClick, title, showPrintButtons, }: WeekAgendaViewProps): import("react").JSX.Element;
13
15
  //# 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;AAElE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEjE,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;CAChB;AA8DD,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,IAAI,EACJ,SAAS,EACT,YAAY,EACZ,UAAU,EACV,KAAK,GACN,EAAE,mBAAmB,+BA4HrB"}
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;AAOjE,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;CAC5B;AA8DD,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,IAAI,EACJ,SAAS,EACT,YAAY,EACZ,UAAU,EACV,KAAK,EACL,gBAAgB,GACjB,EAAE,mBAAmB,+BAoIrB"}
@@ -1,8 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useMemo, useState } from "react";
3
- import { Button, Badge } from "@flowselections/core";
4
- import { ChevronLeft, ChevronRight, Package, Truck, Sprout, Clock, CheckCircle2, Scale } from "lucide-react";
3
+ import { Button, Badge, toast } from "@flowselections/core";
4
+ import { ChevronLeft, ChevronRight, Package, Truck, Sprout, Clock, CheckCircle2, Scale, Printer } from "lucide-react";
5
5
  import { isSameDay, startOfWeek, addDays } from "../../lib/pickDate";
6
+ import { printDeliveryNote, printDeliveryNotesMerged, } from "../../lib/deliveryNotePrint";
6
7
  const WEEKDAY_LABELS = ["MAANDAG", "DINSDAG", "WOENSDAG", "DONDERDAG", "VRIJDAG", "ZATERDAG", "ZONDAG"];
7
8
  const MONTHS_NL_SHORT = ["jan", "feb", "mrt", "apr", "mei", "jun", "jul", "aug", "sep", "okt", "nov", "dec"];
8
9
  function isOrderReady(o) {
@@ -37,7 +38,7 @@ const MODE_LABELS = {
37
38
  "transport-register": { summary: "Aanmeldingen deze week" },
38
39
  pick: { summary: "Te picken deze week" },
39
40
  };
40
- export function WeekAgendaView({ planned, mode, isLoading, onOrderClick, onDayClick, title, }) {
41
+ export function WeekAgendaView({ planned, mode, isLoading, onOrderClick, onDayClick, title, showPrintButtons, }) {
41
42
  const [cursor, setCursor] = useState(() => {
42
43
  const d = new Date();
43
44
  d.setHours(0, 0, 0, 0);
@@ -120,31 +121,71 @@ export function WeekAgendaView({ planned, mode, isLoading, onOrderClick, onDayCl
120
121
  d.setHours(0, 0, 0, 0);
121
122
  setCursor(startOfWeek(d));
122
123
  };
123
- 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: "space-y-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 }, day.date.toISOString()))) })] }));
124
+ 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: "space-y-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, showPrintButtons: showPrintButtons }, day.date.toISOString())))) })] }));
124
125
  }
125
126
  function SummaryCard({ label, value, tone, }) {
126
127
  const valueClass = tone === "success" ? "text-green-600" : "text-foreground";
127
128
  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 })] }));
128
129
  }
129
- function DayRow({ day, onOrderClick, onDayClick }) {
130
+ function DayRow({ day, onOrderClick, onDayClick, showPrintButtons, }) {
130
131
  const weekdayIdx = (day.date.getDay() + 6) % 7;
131
132
  const today = new Date();
132
133
  today.setHours(0, 0, 0, 0);
133
134
  const isToday = isSameDay(day.date, today);
134
- 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" }))] })] }), onOrderClick && day.entries.length > 0 && (_jsx("div", { className: "border-t px-4 py-2 sm:px-6", children: _jsx("div", { className: "flex flex-wrap gap-2", children: day.entries.map((e, idx) => {
135
+ const [printingDay, setPrintingDay] = useState(false);
136
+ const [printingOrderId, setPrintingOrderId] = useState(null);
137
+ const printableItems = day.entries
138
+ .filter((e) => e.order.source === "floriday" && e.order.salesOrderId)
139
+ .map((e) => ({ id: e.order.id, salesOrderId: e.order.salesOrderId ?? undefined }));
140
+ const handlePrintDay = async () => {
141
+ if (printingDay || printableItems.length === 0)
142
+ return;
143
+ setPrintingDay(true);
144
+ try {
145
+ const res = await printDeliveryNotesMerged(printableItems);
146
+ if (res.success > 0) {
147
+ toast.success(`${res.success}/${res.total} afleverbrieven verstuurd naar printer`);
148
+ }
149
+ for (const f of res.failed.slice(0, 5)) {
150
+ toast.error(`Afleverbrief ${f.id} mislukt: ${f.error}`);
151
+ }
152
+ }
153
+ catch (err) {
154
+ toast.error(err instanceof Error ? err.message : "Printen mislukt");
155
+ }
156
+ finally {
157
+ setPrintingDay(false);
158
+ }
159
+ };
160
+ const handlePrintOrder = async (order) => {
161
+ if (!order.salesOrderId || printingOrderId)
162
+ return;
163
+ setPrintingOrderId(order.id);
164
+ try {
165
+ await printDeliveryNote(order.salesOrderId);
166
+ }
167
+ catch (err) {
168
+ toast.error(err instanceof Error ? err.message : "Afleverbrief printen mislukt");
169
+ }
170
+ finally {
171
+ setPrintingOrderId(null);
172
+ }
173
+ };
174
+ 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, 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" }))] })] }), (onOrderClick || showPrintButtons) && day.entries.length > 0 && (_jsx("div", { className: "border-t px-4 py-2 sm:px-6", children: _jsx("div", { className: "flex flex-wrap gap-2", children: day.entries.map((e, idx) => {
135
175
  const moved = e.movedEarlier;
136
176
  const split = e.splitPart;
137
- return (_jsxs("button", { onClick: () => onOrderClick(e.order), title: [
138
- split
139
- ? `Deel ${split.index}/${split.total} — ${e.cartCount} karren deze dag (verdeeld picken).`
140
- : moved
141
- ? "Deze order is eerder ingepland vanwege Pickverdeling."
142
- : null,
143
- e.carrierName ? `Vervoerder: ${e.carrierName}` : null,
144
- e.reason ? `Planning: ${e.reason}` : null,
145
- ]
146
- .filter(Boolean)
147
- .join("\n") || undefined, className: `flex items-center gap-1 rounded border px-2 py-1 text-xs hover:bg-muted ${moved || split ? "border-purple-300 bg-purple-50" : ""}`, children: [(moved || split) && _jsx(Scale, { className: "h-3 w-3 text-purple-600" }), _jsx("span", { className: "font-medium", children: e.order.orderNumber }), _jsxs("span", { className: "ml-1 text-muted-foreground", children: ["\u00B7 ", e.order.customerName] }), _jsxs("span", { className: "ml-1 text-purple-700", children: ["\u00B7 ", e.cartCount, " karren", split ? ` (deel ${split.index}/${split.total})` : ""] })] }, `${e.order.id}-${idx}`));
177
+ const canPrint = showPrintButtons && e.order.source === "floriday" && !!e.order.salesOrderId;
178
+ return (_jsxs("div", { className: `flex items-center gap-1 rounded border px-2 py-1 text-xs ${moved || split ? "border-purple-300 bg-purple-50" : ""}`, children: [_jsxs("button", { type: "button", onClick: () => onOrderClick?.(e.order), disabled: !onOrderClick, title: [
179
+ split
180
+ ? `Deel ${split.index}/${split.total} — ${e.cartCount} karren deze dag (verdeeld picken).`
181
+ : moved
182
+ ? "Deze order is eerder ingepland vanwege Pickverdeling."
183
+ : null,
184
+ e.carrierName ? `Vervoerder: ${e.carrierName}` : null,
185
+ e.reason ? `Planning: ${e.reason}` : null,
186
+ ]
187
+ .filter(Boolean)
188
+ .join("\n") || undefined, className: `flex items-center gap-1 ${onOrderClick ? "hover:underline" : "cursor-default"}`, children: [(moved || split) && _jsx(Scale, { className: "h-3 w-3 text-purple-600" }), _jsx("span", { className: "font-medium", children: e.order.orderNumber }), _jsxs("span", { className: "ml-1 text-muted-foreground", children: ["\u00B7 ", e.order.customerName] }), _jsxs("span", { className: "ml-1 text-purple-700", children: ["\u00B7 ", e.cartCount, " karren", split ? ` (deel ${split.index}/${split.total})` : ""] })] }), canPrint && (_jsx("button", { type: "button", onClick: () => handlePrintOrder(e.order), disabled: printingOrderId === e.order.id, title: "Afleverbrief printen", className: "ml-1 rounded p-0.5 hover:bg-muted disabled:opacity-50", children: _jsx(Printer, { className: "h-3.5 w-3.5" }) }))] }, `${e.order.id}-${idx}`));
148
189
  }) }) }))] }));
149
190
  }
150
191
  function Stat({ icon, bg, value, label, }) {
@@ -0,0 +1,2 @@
1
+ export declare function KioskControle(): import("react").JSX.Element;
2
+ //# sourceMappingURL=KioskControle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"KioskControle.d.ts","sourceRoot":"","sources":["../../../src/components/pickstation/KioskControle.tsx"],"names":[],"mappings":"AAGA,wBAAgB,aAAa,gCAoB5B"}