@flowselections/floriday-afhandeling-module 1.0.13 → 1.0.15

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 (74) 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 +41 -63
  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/PakbonTemplate.d.ts +2 -1
  16. package/dist-lib/components/pickstation/PakbonTemplate.d.ts.map +1 -1
  17. package/dist-lib/components/pickstation/PakbonTemplate.js +20 -17
  18. package/dist-lib/components/pickstation/PickstationPage.d.ts.map +1 -1
  19. package/dist-lib/components/pickstation/PickstationPage.js +57 -8
  20. package/dist-lib/components/settings/AfhandelingSettingsCard.d.ts.map +1 -1
  21. package/dist-lib/components/settings/AfhandelingSettingsCard.js +14 -2
  22. package/dist-lib/hooks/useOrderPlanning.d.ts.map +1 -1
  23. package/dist-lib/hooks/useOrderPlanning.js +28 -11
  24. package/dist-lib/index.d.ts +3 -0
  25. package/dist-lib/index.d.ts.map +1 -1
  26. package/dist-lib/index.js +3 -0
  27. package/dist-lib/integrations/supabase/auth-middleware.d.ts +605 -4
  28. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  29. package/dist-lib/integrations/supabase/client.d.ts +605 -4
  30. package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
  31. package/dist-lib/integrations/supabase/client.server.d.ts +605 -4
  32. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  33. package/dist-lib/integrations/supabase/types.d.ts +613 -4
  34. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  35. package/dist-lib/lib/afhandelingSettings.functions.d.ts +1222 -8
  36. package/dist-lib/lib/afhandelingSettings.functions.d.ts.map +1 -1
  37. package/dist-lib/lib/afhandelingSettings.functions.js +28 -1
  38. package/dist-lib/lib/carrierPlanning.d.ts +25 -0
  39. package/dist-lib/lib/carrierPlanning.d.ts.map +1 -0
  40. package/dist-lib/lib/carrierPlanning.js +65 -0
  41. package/dist-lib/lib/carrierSignupMail.server.d.ts +0 -2
  42. package/dist-lib/lib/carrierSignupMail.server.d.ts.map +1 -1
  43. package/dist-lib/lib/carrierSignupMail.server.js +53 -216
  44. package/dist-lib/lib/carriers.functions.d.ts +3025 -20
  45. package/dist-lib/lib/carriers.functions.d.ts.map +1 -1
  46. package/dist-lib/lib/carriers.functions.js +5 -0
  47. package/dist-lib/lib/cartAssignments.functions.d.ts +3025 -20
  48. package/dist-lib/lib/cartAssignments.functions.d.ts.map +1 -1
  49. package/dist-lib/lib/cartControl.functions.d.ts +6050 -40
  50. package/dist-lib/lib/cartControl.functions.d.ts.map +1 -1
  51. package/dist-lib/lib/cartControl.functions.js +1 -1
  52. package/dist-lib/lib/cartRescheduling.d.ts.map +1 -1
  53. package/dist-lib/lib/cartRescheduling.js +8 -6
  54. package/dist-lib/lib/countries.d.ts +2 -0
  55. package/dist-lib/lib/countries.d.ts.map +1 -1
  56. package/dist-lib/lib/countries.js +51 -0
  57. package/dist-lib/lib/deliveryNotePrint.d.ts +26 -0
  58. package/dist-lib/lib/deliveryNotePrint.d.ts.map +1 -0
  59. package/dist-lib/lib/deliveryNotePrint.js +172 -0
  60. package/dist-lib/lib/floriday.functions.d.ts +613 -4
  61. package/dist-lib/lib/floriday.functions.d.ts.map +1 -1
  62. package/dist-lib/lib/floriday.functions.js +126 -8
  63. package/dist-lib/lib/floridayAutoProcess.d.ts +30 -0
  64. package/dist-lib/lib/floridayAutoProcess.d.ts.map +1 -0
  65. package/dist-lib/lib/floridayAutoProcess.js +70 -0
  66. package/dist-lib/lib/pickstationI18n.d.ts +46 -0
  67. package/dist-lib/lib/pickstationI18n.d.ts.map +1 -1
  68. package/dist-lib/lib/pickstationI18n.js +251 -0
  69. package/dist-lib/lib/pickstationOrders.server.d.ts.map +1 -1
  70. package/dist-lib/lib/pickstationOrders.server.js +55 -19
  71. package/dist-lib/lib/planning.d.ts +34 -0
  72. package/dist-lib/lib/planning.d.ts.map +1 -1
  73. package/dist-lib/lib/planning.js +84 -0
  74. package/package.json +2 -2
@@ -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;AAqEnE,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,OAAO,GACR,EAAE;IACD,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,sCAgJA"}
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,84 +3,63 @@ 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 fmtDate(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
- });
17
- }
18
- /** Trek 1 uur af van "HH:MM" en geef terug als "HH:MM". */
19
- function minusOneHour(hhmm) {
20
- const [h, m] = hhmm.split(":").map((n) => parseInt(n, 10));
21
- if (Number.isNaN(h) || Number.isNaN(m))
22
- return hhmm;
23
- const total = h * 60 + m - 60;
24
- const norm = ((total % (24 * 60)) + 24 * 60) % (24 * 60);
25
- const hh = String(Math.floor(norm / 60)).padStart(2, "0");
26
- const mm = String(norm % 60).padStart(2, "0");
27
- return `${hh}:${mm}`;
28
- }
29
- function todayIsoDay() {
30
- const d = new Date();
31
- const y = d.getFullYear();
32
- const m = String(d.getMonth() + 1).padStart(2, "0");
33
- const day = String(d.getDate()).padStart(2, "0");
34
- return `${y}-${m}-${day}`;
35
- }
36
- function tomorrowIsoDay() {
37
- const d = new Date();
38
- d.setDate(d.getDate() + 1);
39
- const y = d.getFullYear();
40
- const m = String(d.getMonth() + 1).padStart(2, "0");
41
- const day = String(d.getDate()).padStart(2, "0");
42
- return `${y}-${m}-${day}`;
43
- }
44
- function computeKlaarzet(cart) {
45
- const today = todayIsoDay();
46
- const tomorrow = tomorrowIsoDay();
47
- if (cart.pickupDate === today) {
48
- const time = cart.pickupTime ? minusOneHour(cart.pickupTime) : null;
49
- if (time) {
50
- const [h, m] = time.split(":").map((n) => parseInt(n, 10));
51
- return { label: time, sortKey: h * 60 + m };
52
- }
53
- // Ophaaldatum vandaag maar geen tijd bekend → einde van vandaag.
54
- return { label: "vandaag", sortKey: 23 * 60 + 59 };
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 };
55
19
  }
56
- if (cart.pickupDate === tomorrow) {
57
- // Moet uiterlijk vandaag klaar → toon datum vandaag.
58
- return { label: fmtDate(today), sortKey: 23 * 60 + 58 };
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 };
59
24
  }
60
- // Overige gevallen: eind van de dag, met datum als label.
61
- return { label: fmtDate(cart.pickupDate), sortKey: 24 * 60 + 999 };
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() };
62
30
  }
63
31
  /** Printbare controlelijst — één regel per kar met checkbox en opmerkingveld. */
64
- 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";
65
35
  useEffect(() => {
66
- const t = setTimeout(() => window.print(), 300);
36
+ const timer = setTimeout(() => window.print(), 300);
67
37
  const handleAfterPrint = () => onClose();
68
38
  window.addEventListener("afterprint", handleAfterPrint);
69
39
  return () => {
70
- clearTimeout(t);
40
+ clearTimeout(timer);
71
41
  window.removeEventListener("afterprint", handleAfterPrint);
72
42
  };
73
43
  }, [onClose]);
74
- 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, {
75
56
  weekday: "long",
76
57
  day: "2-digit",
77
58
  month: "long",
78
59
  year: "numeric",
79
60
  });
80
- // Bereken klaarzet-moment per kar en sorteer op prioriteit
81
- // (vroegste klaarzet bovenaan; daarna land, karnummer).
82
61
  const sortedCarts = carts
83
- .map((cart) => ({ cart, klaarzet: computeKlaarzet(cart) }))
62
+ .map((cart) => ({ cart, klaarzet: computeKlaarzet(cart, lang) }))
84
63
  .sort((a, b) => {
85
64
  if (a.klaarzet.sortKey !== b.klaarzet.sortKey) {
86
65
  return a.klaarzet.sortKey - b.klaarzet.sortKey;
@@ -93,11 +72,10 @@ export function ControleLijstPrint({ carts, onClose, }) {
93
72
  const bn = b.cart.cartNumber ?? "\uFFFF";
94
73
  return an.localeCompare(bn);
95
74
  });
96
- 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-right py-1 pr-2", children: "FUSTEN" }), _jsx("th", { className: "text-left py-1 pr-2", children: "LAND" }), _jsx("th", { className: "text-left py-1 pr-2", children: "KLAARZETTEN" }), _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: [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", children: c.country ?? "—" }), _jsx("td", { className: "py-2 pr-2 whitespace-nowrap font-semibold", children: klaarzet.label }), _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-[35%]", children: _jsx("span", { className: "inline-block w-full border-b border-gray-400 h-4" }) })] }, `${c.orderSource}#${c.orderId}#${c.cartIndex}`))), sortedCarts.length === 0 && (_jsx("tr", { children: _jsx("td", { colSpan: 6, 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: `
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: `
97
76
  @media print {
98
77
  @page { size: A4 portrait; margin: 12mm; }
99
78
  html, body { background: #fff !important; margin: 0 !important; padding: 0 !important; }
100
- /* Hide the entire app; show only the print root */
101
79
  body > *:not(#controle-print-portal) { display: none !important; }
102
80
  #controle-print-portal, #controle-print-root {
103
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"}