@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.
- package/dist-lib/components/afhandeling/AutoProcessStatus.d.ts +12 -0
- package/dist-lib/components/afhandeling/AutoProcessStatus.d.ts.map +1 -0
- package/dist-lib/components/afhandeling/AutoProcessStatus.js +103 -0
- package/dist-lib/components/afhandeling/ControleLijstPrint.d.ts +3 -1
- package/dist-lib/components/afhandeling/ControleLijstPrint.d.ts.map +1 -1
- package/dist-lib/components/afhandeling/ControleLijstPrint.js +56 -17
- package/dist-lib/components/afhandeling/DagDetailDialog.d.ts.map +1 -1
- package/dist-lib/components/afhandeling/DagDetailDialog.js +96 -4
- package/dist-lib/components/afhandeling/LeveringenPage.js +1 -1
- package/dist-lib/components/afhandeling/VervoerdersPage.d.ts.map +1 -1
- package/dist-lib/components/afhandeling/VervoerdersPage.js +2 -1
- package/dist-lib/components/afhandeling/WeekAgendaView.d.ts +3 -1
- package/dist-lib/components/afhandeling/WeekAgendaView.d.ts.map +1 -1
- package/dist-lib/components/afhandeling/WeekAgendaView.js +58 -17
- package/dist-lib/components/pickstation/KioskControle.d.ts +2 -0
- package/dist-lib/components/pickstation/KioskControle.d.ts.map +1 -0
- package/dist-lib/components/pickstation/KioskControle.js +7 -0
- package/dist-lib/components/pickstation/PakbonTemplate.d.ts +2 -1
- package/dist-lib/components/pickstation/PakbonTemplate.d.ts.map +1 -1
- package/dist-lib/components/pickstation/PakbonTemplate.js +20 -17
- package/dist-lib/components/pickstation/PickstationPage.d.ts +2 -0
- package/dist-lib/components/pickstation/PickstationPage.d.ts.map +1 -0
- package/dist-lib/components/pickstation/PickstationPage.js +266 -0
- package/dist-lib/components/settings/AfhandelingSettingsCard.d.ts.map +1 -1
- package/dist-lib/components/settings/AfhandelingSettingsCard.js +14 -2
- package/dist-lib/hooks/useOrderPlanning.d.ts.map +1 -1
- package/dist-lib/hooks/useOrderPlanning.js +28 -11
- package/dist-lib/index.d.ts +4 -0
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +4 -0
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +1243 -63
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.d.ts +1243 -63
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +1243 -63
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +1264 -56
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/afhandelingSettings.functions.d.ts +2483 -111
- package/dist-lib/lib/afhandelingSettings.functions.d.ts.map +1 -1
- package/dist-lib/lib/afhandelingSettings.functions.js +28 -1
- package/dist-lib/lib/carrierPlanning.d.ts +25 -0
- package/dist-lib/lib/carrierPlanning.d.ts.map +1 -0
- package/dist-lib/lib/carrierPlanning.js +65 -0
- package/dist-lib/lib/carrierSignupMail.server.d.ts +0 -2
- package/dist-lib/lib/carrierSignupMail.server.d.ts.map +1 -1
- package/dist-lib/lib/carrierSignupMail.server.js +53 -216
- package/dist-lib/lib/carriers.functions.d.ts +5920 -20
- package/dist-lib/lib/carriers.functions.d.ts.map +1 -1
- package/dist-lib/lib/carriers.functions.js +5 -0
- package/dist-lib/lib/cartAssignments.functions.d.ts +5920 -20
- package/dist-lib/lib/cartAssignments.functions.d.ts.map +1 -1
- package/dist-lib/lib/cartControl.functions.d.ts +11843 -40
- package/dist-lib/lib/cartControl.functions.d.ts.map +1 -1
- package/dist-lib/lib/cartControl.functions.js +4 -1
- package/dist-lib/lib/cartRescheduling.d.ts.map +1 -1
- package/dist-lib/lib/cartRescheduling.js +8 -6
- package/dist-lib/lib/countries.d.ts +2 -0
- package/dist-lib/lib/countries.d.ts.map +1 -1
- package/dist-lib/lib/countries.js +51 -0
- package/dist-lib/lib/deliveryNotePrint.d.ts +26 -0
- package/dist-lib/lib/deliveryNotePrint.d.ts.map +1 -0
- package/dist-lib/lib/deliveryNotePrint.js +172 -0
- package/dist-lib/lib/floriday.functions.d.ts +1251 -63
- package/dist-lib/lib/floriday.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday.functions.js +126 -8
- package/dist-lib/lib/floridayAutoProcess.d.ts +30 -0
- package/dist-lib/lib/floridayAutoProcess.d.ts.map +1 -0
- package/dist-lib/lib/floridayAutoProcess.js +70 -0
- package/dist-lib/lib/pickstationI18n.d.ts +46 -0
- package/dist-lib/lib/pickstationI18n.d.ts.map +1 -1
- package/dist-lib/lib/pickstationI18n.js +251 -0
- package/dist-lib/lib/pickstationOrders.server.d.ts.map +1 -1
- package/dist-lib/lib/pickstationOrders.server.js +56 -19
- package/dist-lib/lib/pickstationTypes.d.ts +2 -0
- package/dist-lib/lib/pickstationTypes.d.ts.map +1 -1
- package/dist-lib/lib/planning.d.ts +34 -0
- package/dist-lib/lib/planning.d.ts.map +1 -1
- package/dist-lib/lib/planning.js +84 -0
- 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;
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
|
36
|
+
const timer = setTimeout(() => window.print(), 300);
|
|
22
37
|
const handleAfterPrint = () => onClose();
|
|
23
38
|
window.addEventListener("afterprint", handleAfterPrint);
|
|
24
39
|
return () => {
|
|
25
|
-
clearTimeout(
|
|
40
|
+
clearTimeout(timer);
|
|
26
41
|
window.removeEventListener("afterprint", handleAfterPrint);
|
|
27
42
|
};
|
|
28
43
|
}, [onClose]);
|
|
29
|
-
const
|
|
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
|
|
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;
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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":"
|
|
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 ?? "—" }),
|
|
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;
|
|
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
|
-
|
|
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
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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 @@
|
|
|
1
|
+
{"version":3,"file":"KioskControle.d.ts","sourceRoot":"","sources":["../../../src/components/pickstation/KioskControle.tsx"],"names":[],"mappings":"AAGA,wBAAgB,aAAa,gCAoB5B"}
|