@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.
- 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 +41 -63
- 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/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.map +1 -1
- package/dist-lib/components/pickstation/PickstationPage.js +57 -8
- 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 +3 -0
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +3 -0
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +605 -4
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.d.ts +605 -4
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +605 -4
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +613 -4
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/afhandelingSettings.functions.d.ts +1222 -8
- 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 +3025 -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 +3025 -20
- package/dist-lib/lib/cartAssignments.functions.d.ts.map +1 -1
- package/dist-lib/lib/cartControl.functions.d.ts +6050 -40
- package/dist-lib/lib/cartControl.functions.d.ts.map +1 -1
- package/dist-lib/lib/cartControl.functions.js +1 -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 +613 -4
- 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 +55 -19
- 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 +2 -2
|
@@ -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, }) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PickstationOrder } from "../../lib/pickstationTypes";
|
|
2
|
+
import { type PickstationLang } from "../../lib/pickstationI18n";
|
|
2
3
|
/** Returns a fully self-contained printable HTML document for one packing slip per cart. */
|
|
3
4
|
export declare function renderPakbonHtml(order: {
|
|
4
5
|
id: string;
|
|
@@ -16,6 +17,6 @@ export declare function renderPakbonHtml(order: {
|
|
|
16
17
|
crates: number | null;
|
|
17
18
|
unit: string | null;
|
|
18
19
|
}[];
|
|
19
|
-
}): string;
|
|
20
|
+
}, lang?: PickstationLang | null | undefined): string;
|
|
20
21
|
export type { PickstationOrder };
|
|
21
22
|
//# sourceMappingURL=PakbonTemplate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PakbonTemplate.d.ts","sourceRoot":"","sources":["../../../src/components/pickstation/PakbonTemplate.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"PakbonTemplate.d.ts","sourceRoot":"","sources":["../../../src/components/pickstation/PakbonTemplate.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,2BAA2B,CAAC;AAEnC,4FAA4F;AAC5F,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE;IACL,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,EAAE,CAAC;CAC9E,EACD,IAAI,GAAE,eAAe,GAAG,IAAI,GAAG,SAAgB,GAC9C,MAAM,CA+FR;AAWD,YAAY,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
+
import { getPrintDict, PICKSTATION_LOCALE, } from "../../lib/pickstationI18n";
|
|
1
2
|
/** Returns a fully self-contained printable HTML document for one packing slip per cart. */
|
|
2
|
-
export function renderPakbonHtml(order) {
|
|
3
|
+
export function renderPakbonHtml(order, lang = "nl") {
|
|
4
|
+
const t = getPrintDict(lang);
|
|
5
|
+
const locale = PICKSTATION_LOCALE[lang ?? "nl"] ?? "nl-NL";
|
|
6
|
+
const htmlLang = lang ?? "nl";
|
|
3
7
|
const fmt = (d) => {
|
|
4
8
|
if (!d)
|
|
5
9
|
return "—";
|
|
6
10
|
const dt = new Date(d);
|
|
7
11
|
if (Number.isNaN(dt.getTime()))
|
|
8
12
|
return d;
|
|
9
|
-
return dt.toLocaleDateString(
|
|
13
|
+
return dt.toLocaleDateString(locale, { day: "2-digit", month: "2-digit", year: "numeric" });
|
|
10
14
|
};
|
|
11
15
|
const rows = order.lines.length
|
|
12
16
|
? order.lines
|
|
@@ -17,15 +21,15 @@ export function renderPakbonHtml(order) {
|
|
|
17
21
|
<td>${escapeHtml(l.unit ?? "")}</td>
|
|
18
22
|
</tr>`)
|
|
19
23
|
.join("")
|
|
20
|
-
: `<tr><td colspan="3" style="text-align:center;color:#666"
|
|
21
|
-
const cartLabel =
|
|
24
|
+
: `<tr><td colspan="3" style="text-align:center;color:#666">${escapeHtml(t.noLines)}</td></tr>`;
|
|
25
|
+
const cartLabel = t.cartOf(order.cartIndex, order.cartTotal);
|
|
22
26
|
const fustenLabel = order.cratesOnCart != null ? `${order.cratesOnCart}` : "—";
|
|
23
27
|
const cartNumber = order.cartNumber ?? `${order.orderNumber}-${order.cartIndex}`;
|
|
24
28
|
return `<!doctype html>
|
|
25
|
-
<html lang="
|
|
29
|
+
<html lang="${escapeHtml(htmlLang)}">
|
|
26
30
|
<head>
|
|
27
31
|
<meta charset="utf-8">
|
|
28
|
-
<title
|
|
32
|
+
<title>${escapeHtml(t.packingSlip)} ${escapeHtml(order.orderNumber)} · ${escapeHtml(cartNumber)}</title>
|
|
29
33
|
<style>
|
|
30
34
|
@page {
|
|
31
35
|
size: A4;
|
|
@@ -36,7 +40,6 @@ export function renderPakbonHtml(order) {
|
|
|
36
40
|
h1 { margin: 0 0 4px; font-size: 26px; }
|
|
37
41
|
.sub { color:#444; margin-bottom: 8px; }
|
|
38
42
|
|
|
39
|
-
/* Groot, vetgedrukt karnummer direct onder de titel — ook running header op elke pagina. */
|
|
40
43
|
.cart-number-hero {
|
|
41
44
|
position: running(cartno);
|
|
42
45
|
font-size: 88px;
|
|
@@ -64,28 +67,28 @@ export function renderPakbonHtml(order) {
|
|
|
64
67
|
</style>
|
|
65
68
|
</head>
|
|
66
69
|
<body>
|
|
67
|
-
<h1
|
|
68
|
-
<div class="sub"
|
|
70
|
+
<h1>${escapeHtml(t.packingSlip)}</h1>
|
|
71
|
+
<div class="sub">${escapeHtml(t.order)} ${escapeHtml(order.orderNumber)} · ${escapeHtml(cartLabel)}</div>
|
|
69
72
|
|
|
70
73
|
<div class="cart-number-hero">${escapeHtml(cartNumber)}</div>
|
|
71
74
|
|
|
72
75
|
<div class="grid">
|
|
73
|
-
<div><div class="label"
|
|
74
|
-
<div><div class="label"
|
|
75
|
-
<div><div class="label"
|
|
76
|
-
<div><div class="label"
|
|
77
|
-
<div><div class="label"
|
|
78
|
-
<div><div class="label"
|
|
76
|
+
<div><div class="label">${escapeHtml(t.customer)}</div><div class="value">${escapeHtml(order.customerName)}</div></div>
|
|
77
|
+
<div><div class="label">${escapeHtml(t.country)}</div><div class="value">${escapeHtml(order.country ?? "—")}</div></div>
|
|
78
|
+
<div><div class="label">${escapeHtml(t.deliveryDate)}</div><div class="value">${fmt(order.deliveryDate)}</div></div>
|
|
79
|
+
<div><div class="label">${escapeHtml(t.pickDate)}</div><div class="value">${fmt(order.pickDate)}</div></div>
|
|
80
|
+
<div><div class="label">${escapeHtml(t.cart)}</div><div class="value">${escapeHtml(cartLabel)}</div></div>
|
|
81
|
+
<div><div class="label">${escapeHtml(t.cratesOnThisCart)}</div><div class="value">${escapeHtml(fustenLabel)}</div></div>
|
|
79
82
|
</div>
|
|
80
83
|
|
|
81
84
|
<table>
|
|
82
|
-
<thead><tr><th
|
|
85
|
+
<thead><tr><th>${escapeHtml(t.description)}</th><th style="text-align:right;width:90px">${escapeHtml(t.crates)}</th><th style="width:90px">${escapeHtml(t.unit)}</th></tr></thead>
|
|
83
86
|
<tbody>${rows}</tbody>
|
|
84
87
|
</table>
|
|
85
88
|
|
|
86
89
|
<div class="barcode-fallback">*${escapeHtml(order.orderNumber)}*</div>
|
|
87
90
|
|
|
88
|
-
<div class="footer"
|
|
91
|
+
<div class="footer">${escapeHtml(t.printedVia)} · ${new Date().toLocaleString(locale)}</div>
|
|
89
92
|
</body>
|
|
90
93
|
</html>`;
|
|
91
94
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PickstationPage.d.ts","sourceRoot":"","sources":["../../../src/components/pickstation/PickstationPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PickstationPage.d.ts","sourceRoot":"","sources":["../../../src/components/pickstation/PickstationPage.tsx"],"names":[],"mappings":"AA2EA,wBAAgB,eAAe,gCA+X9B"}
|
|
@@ -6,6 +6,7 @@ import { LanguagePicker } from "./LanguagePicker";
|
|
|
6
6
|
import { renderPakbonHtml } from "./PakbonTemplate";
|
|
7
7
|
import { printHtml, printPdfBase64 } from "./printDocuments";
|
|
8
8
|
import { ControleLijstPrint } from "../afhandeling/ControleLijstPrint";
|
|
9
|
+
import { countryCode } from "../../lib/countries";
|
|
9
10
|
import { PICKSTATION_DICT, PICKSTATION_LANGUAGES, } from "../../lib/pickstationI18n";
|
|
10
11
|
const LANG_KEY = "pickstation.lang";
|
|
11
12
|
const LAST_GOOD_ORDERS_KEY = "pickstation.lastGoodOrders";
|
|
@@ -28,6 +29,30 @@ function statusBadge(status, t, printedCount) {
|
|
|
28
29
|
return { label: `✓ ${t.statusDelivered}`, className: "bg-emerald-600 text-white" };
|
|
29
30
|
}
|
|
30
31
|
}
|
|
32
|
+
const DAY_ABBR_BY_LANG = {
|
|
33
|
+
nl: ["ZO", "MA", "DI", "WO", "DO", "VR", "ZA"],
|
|
34
|
+
en: ["SU", "MO", "TU", "WE", "TH", "FR", "SA"],
|
|
35
|
+
pl: ["ND", "PN", "WT", "ŚR", "CZ", "PT", "SB"],
|
|
36
|
+
ro: ["DU", "LU", "MA", "MI", "JO", "VI", "SÂ"],
|
|
37
|
+
bg: ["НД", "ПН", "ВТ", "СР", "ЧТ", "ПТ", "СБ"],
|
|
38
|
+
uk: ["НД", "ПН", "ВТ", "СР", "ЧТ", "ПТ", "СБ"],
|
|
39
|
+
};
|
|
40
|
+
function computeKlaarzet(o, lang) {
|
|
41
|
+
if (!o.pickupDate || !o.pickupTime) {
|
|
42
|
+
return { label: "—", sortKey: Number.MAX_SAFE_INTEGER };
|
|
43
|
+
}
|
|
44
|
+
const [hh, mm] = o.pickupTime.split(":").map((n) => parseInt(n, 10));
|
|
45
|
+
const d = new Date(o.pickupDate);
|
|
46
|
+
if (Number.isNaN(d.getTime()) || Number.isNaN(hh) || Number.isNaN(mm)) {
|
|
47
|
+
return { label: "—", sortKey: Number.MAX_SAFE_INTEGER };
|
|
48
|
+
}
|
|
49
|
+
d.setHours(hh, mm, 0, 0);
|
|
50
|
+
// Klaarzet = ophaaltijd minus 1 uur.
|
|
51
|
+
d.setHours(d.getHours() - 1);
|
|
52
|
+
const day = (DAY_ABBR_BY_LANG[lang] ?? DAY_ABBR_BY_LANG.nl)[d.getDay()];
|
|
53
|
+
const time = `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
|
|
54
|
+
return { label: `${day} - ${time}`, sortKey: d.getTime() };
|
|
55
|
+
}
|
|
31
56
|
export function PickstationPage() {
|
|
32
57
|
const navigate = useNavigate();
|
|
33
58
|
const [lang, setLang] = useState(null);
|
|
@@ -100,7 +125,23 @@ export function PickstationPage() {
|
|
|
100
125
|
const queryError = ordersQuery.data?.error ??
|
|
101
126
|
(ordersQuery.error instanceof Error ? ordersQuery.error.message : undefined);
|
|
102
127
|
const freshOrders = ordersQuery.data?.orders ?? [];
|
|
103
|
-
const
|
|
128
|
+
const unsortedOrders = queryError ? lastGoodOrders : freshOrders;
|
|
129
|
+
const orders = useMemo(() => {
|
|
130
|
+
return unsortedOrders
|
|
131
|
+
.map((o) => ({ o, k: computeKlaarzet(o, lang ?? "nl") }))
|
|
132
|
+
.sort((a, b) => {
|
|
133
|
+
if (a.k.sortKey !== b.k.sortKey)
|
|
134
|
+
return a.k.sortKey - b.k.sortKey;
|
|
135
|
+
const ac = a.o.country ?? "\uFFFF";
|
|
136
|
+
const bc = b.o.country ?? "\uFFFF";
|
|
137
|
+
if (ac !== bc)
|
|
138
|
+
return ac.localeCompare(bc);
|
|
139
|
+
const an = a.o.cartNumber ?? "\uFFFF";
|
|
140
|
+
const bn = b.o.cartNumber ?? "\uFFFF";
|
|
141
|
+
return an.localeCompare(bn);
|
|
142
|
+
})
|
|
143
|
+
.map((x) => x.o);
|
|
144
|
+
}, [unsortedOrders]);
|
|
104
145
|
const printedCount = orders.filter((o) => o.printedCount > 0).length;
|
|
105
146
|
const handlePrint = useCallback(async (order) => {
|
|
106
147
|
if (printingId || pendingConfirm)
|
|
@@ -130,7 +171,7 @@ export function PickstationPage() {
|
|
|
130
171
|
catch {
|
|
131
172
|
/* network error – continue with pakbon only */
|
|
132
173
|
}
|
|
133
|
-
const html = renderPakbonHtml(order);
|
|
174
|
+
const html = renderPakbonHtml(order, lang ?? "nl");
|
|
134
175
|
await printHtml(html);
|
|
135
176
|
if (auctionLetter) {
|
|
136
177
|
await printPdfBase64(auctionLetter.base64, auctionLetter.mime);
|
|
@@ -168,6 +209,14 @@ export function PickstationPage() {
|
|
|
168
209
|
const body = (await res.json());
|
|
169
210
|
if (body.warning)
|
|
170
211
|
setPrintWarning(body.warning);
|
|
212
|
+
setLang(null);
|
|
213
|
+
setPickerOpen(true);
|
|
214
|
+
try {
|
|
215
|
+
localStorage.removeItem(LANG_KEY);
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
/* ignore */
|
|
219
|
+
}
|
|
171
220
|
}
|
|
172
221
|
else {
|
|
173
222
|
setPrintWarning(`Bevestigen mislukt (HTTP ${res.status}).`);
|
|
@@ -183,20 +232,20 @@ export function PickstationPage() {
|
|
|
183
232
|
}
|
|
184
233
|
}, [pendingConfirm, ordersQuery]);
|
|
185
234
|
const printNext = useCallback(() => {
|
|
186
|
-
const next = orders
|
|
235
|
+
const next = orders.find((o) => o.status === "not_printed" && o.printedCount === 0) ??
|
|
236
|
+
orders.find((o) => o.printedCount === 0);
|
|
187
237
|
if (next)
|
|
188
238
|
void handlePrint(next);
|
|
189
239
|
}, [orders, handlePrint]);
|
|
190
240
|
if (!lang || pickerOpen) {
|
|
191
241
|
return _jsx(LanguagePicker, { onPick: pickLang });
|
|
192
242
|
}
|
|
193
|
-
return (_jsxs("div", { className: "min-h-screen bg-slate-50 text-slate-900", children: [_jsx("header", { className: "bg-white border-b sticky top-0 z-10", children: _jsxs("div", { className: "max-w-6xl mx-auto px-4 py-4 flex items-center gap-3 flex-wrap", children: [_jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("h1", { className: "text-2xl font-semibold leading-tight", children: t.title }), _jsxs("p", { className: "text-sm text-slate-500", children: [t.subtitle, " \u00B7 ", t.ofTotal(printedCount, orders.length)] })] }), _jsxs("button", { onClick: () => setPickerOpen(true), className: "h-14 px-5 rounded-xl bg-white border-2 border-slate-300 hover:bg-slate-100 font-semibold text-lg", children: ["\uD83C\uDF10 ", t.changeLang] }), _jsxs("button", { onClick: () => setShowChecklist(true), className: "h-14 px-5 rounded-xl bg-white border-2 border-slate-300 hover:bg-slate-100 font-semibold text-lg", children: ["\uD83D\uDCCB ", t.printChecklist] }), _jsxs("button", { onClick: () => navigate({ to: "/controle" }), className: "h-14 px-5 rounded-xl bg-sky-600 hover:bg-sky-700 text-white font-semibold text-lg shadow", children: ["\u2713 ", t.runControl] }), _jsxs("button", { onClick: printNext, disabled: printingId !== null || orders.length === 0, className: "h-14 px-6 rounded-xl bg-emerald-600 hover:bg-emerald-700 disabled:bg-slate-300 text-white font-bold text-lg shadow", children: ["\uD83D\uDDA8 ", t.printNext] })] }) }), _jsxs("main", { className: "max-w-6xl mx-auto px-4 py-6", children: [ordersQuery.isLoading && _jsx("p", { className: "text-xl text-center py-12", children: t.loading }), queryError && orders.length > 0 && (_jsxs("div", { className: "bg-amber-50 border-2 border-amber-300 text-amber-900 rounded-xl p-4 mb-4", children: [_jsx("strong", { children: "Let op:" }), " verversen is niet gelukt, daarom blijven de laatst bekende pakbonnen zichtbaar. ", queryError] })), printWarning && (_jsxs("div", { className: "bg-amber-50 border-2 border-amber-300 text-amber-900 rounded-xl p-4 mb-4", children: [_jsx("strong", { children: "Let op:" }), " ", printWarning] })), queryError && orders.length === 0 && (_jsxs("div", { className: "bg-rose-50 border-2 border-rose-300 text-rose-900 rounded-xl p-4 mb-4", children: [_jsx("strong", { children: "Picklijst niet bijgewerkt:" }), " ", queryError, " De orders zijn hierdoor niet verwijderd; controleer de Pickagenda of probeer opnieuw."] })), !ordersQuery.isLoading && orders.length === 0 && !queryError && (_jsx("p", { className: "text-2xl text-center py-16 text-slate-500", children: t.empty })), orders.length > 0 && (_jsx("div", { className: "bg-white rounded-2xl border border-slate-200 overflow-hidden shadow-sm", children: _jsxs("table", { className: "w-full text-lg", children: [_jsx("thead", { className: "bg-slate-100 text-slate-600 text-sm uppercase tracking-wide", children: _jsxs("tr", { children: [_jsx("th", { className: "text-left px-5 py-3", children: "Karnr" }), _jsx("th", { className: "text-left px-5 py-3", children: t.orderNumber }), _jsx("th", { className: "text-
|
|
243
|
+
return (_jsxs("div", { className: "min-h-screen bg-slate-50 text-slate-900", children: [_jsx("header", { className: "bg-white border-b sticky top-0 z-10", children: _jsxs("div", { className: "max-w-6xl mx-auto px-4 py-4 flex items-center gap-3 flex-wrap", children: [_jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("h1", { className: "text-2xl font-semibold leading-tight", children: t.title }), _jsxs("p", { className: "text-sm text-slate-500", children: [t.subtitle, " \u00B7 ", t.ofTotal(printedCount, orders.length)] })] }), _jsxs("button", { onClick: () => setPickerOpen(true), className: "h-14 px-5 rounded-xl bg-white border-2 border-slate-300 hover:bg-slate-100 font-semibold text-lg", children: ["\uD83C\uDF10 ", t.changeLang] }), _jsxs("button", { onClick: () => setShowChecklist(true), className: "h-14 px-5 rounded-xl bg-white border-2 border-slate-300 hover:bg-slate-100 font-semibold text-lg", children: ["\uD83D\uDCCB ", t.printChecklist] }), _jsxs("button", { onClick: () => navigate({ to: "/controle" }), className: "h-14 px-5 rounded-xl bg-sky-600 hover:bg-sky-700 text-white font-semibold text-lg shadow", children: ["\u2713 ", t.runControl] }), _jsxs("button", { onClick: printNext, disabled: printingId !== null || orders.length === 0, className: "h-14 px-6 rounded-xl bg-emerald-600 hover:bg-emerald-700 disabled:bg-slate-300 text-white font-bold text-lg shadow", children: ["\uD83D\uDDA8 ", t.printNext] })] }) }), _jsxs("main", { className: "max-w-6xl mx-auto px-4 py-6", children: [ordersQuery.isLoading && _jsx("p", { className: "text-xl text-center py-12", children: t.loading }), queryError && orders.length > 0 && (_jsxs("div", { className: "bg-amber-50 border-2 border-amber-300 text-amber-900 rounded-xl p-4 mb-4", children: [_jsx("strong", { children: "Let op:" }), " verversen is niet gelukt, daarom blijven de laatst bekende pakbonnen zichtbaar. ", queryError] })), printWarning && (_jsxs("div", { className: "bg-amber-50 border-2 border-amber-300 text-amber-900 rounded-xl p-4 mb-4", children: [_jsx("strong", { children: "Let op:" }), " ", printWarning] })), queryError && orders.length === 0 && (_jsxs("div", { className: "bg-rose-50 border-2 border-rose-300 text-rose-900 rounded-xl p-4 mb-4", children: [_jsx("strong", { children: "Picklijst niet bijgewerkt:" }), " ", queryError, " De orders zijn hierdoor niet verwijderd; controleer de Pickagenda of probeer opnieuw."] })), !ordersQuery.isLoading && orders.length === 0 && !queryError && (_jsx("p", { className: "text-2xl text-center py-16 text-slate-500", children: t.empty })), orders.length > 0 && (_jsx("div", { className: "bg-white rounded-2xl border border-slate-200 overflow-hidden shadow-sm", children: _jsxs("table", { className: "w-full text-lg", children: [_jsx("thead", { className: "bg-slate-100 text-slate-600 text-sm uppercase tracking-wide", children: _jsxs("tr", { children: [_jsx("th", { className: "text-left px-5 py-3", children: "Karnr" }), _jsx("th", { className: "text-left px-5 py-3", children: t.orderNumber }), _jsx("th", { className: "text-right px-5 py-3", children: "Fusten" }), _jsx("th", { className: "text-left px-5 py-3", children: "Land" }), _jsx("th", { className: "text-left px-5 py-3", children: "Klaarzetten" }), _jsx("th", { className: "text-left px-5 py-3", children: t.status })] }) }), _jsx("tbody", { children: orders.map((o) => {
|
|
194
244
|
const isPrinting = printingId === o.id;
|
|
195
245
|
const badge = statusBadge(o.status, t, o.printedCount);
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}) })] }) })), _jsx("p", { className: "text-xs text-slate-400 mt-6 text-center", children: t.printDialogHint })] }), pendingConfirm && (_jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4", children: _jsxs("div", { className: "bg-white rounded-2xl shadow-2xl max-w-md w-full p-6", children: [_jsx("h2", { className: "text-2xl font-bold mb-2", children: t.confirmPrintedTitle }), _jsx("p", { className: "text-slate-600 mb-2", children: t.confirmPrintedBody }), _jsx("div", { className: "mb-4 inline-block px-4 py-2 rounded-md bg-black text-white font-black text-3xl tracking-widest font-mono", children: pendingConfirm.cartNumber ?? "—" }), _jsxs("p", { className: "text-slate-800 font-semibold mb-6", children: [pendingConfirm.orderNumber, " \u00B7 kar ", pendingConfirm.cartIndex, "/", pendingConfirm.cartTotal] }), _jsxs("div", { className: "flex flex-col gap-3", children: [_jsxs("button", { onClick: () => void confirmPrinted(true), disabled: confirming, className: "h-14 rounded-xl bg-emerald-600 hover:bg-emerald-700 disabled:bg-slate-300 text-white font-bold text-lg shadow", children: ["\u2713 ", t.confirmYes] }), _jsxs("button", { onClick: () => void confirmPrinted(false), disabled: confirming, className: "h-14 rounded-xl bg-white border-2 border-slate-300 hover:bg-slate-100 disabled:opacity-60 font-semibold text-lg", children: ["\u2715 ", t.confirmNo] })] })] }) })), showChecklist && (_jsx(ControleLijstPrint, { carts: orders.map((o) => ({
|
|
246
|
+
const klaarzet = computeKlaarzet(o, lang ?? "nl");
|
|
247
|
+
return (_jsxs("tr", { className: `border-t border-slate-100 transition select-none ${isPrinting ? "bg-emerald-50" : "hover:bg-slate-50"}`, style: { minHeight: 64 }, children: [_jsx("td", { className: "px-5 py-4 whitespace-nowrap cursor-pointer", onClick: () => void handlePrint(o), children: _jsx("span", { className: "inline-block px-3 py-1.5 rounded-md bg-black text-white font-black text-xl tracking-widest font-mono whitespace-nowrap", children: o.cartNumber ?? "—" }) }), _jsx("td", { className: "px-5 py-4 font-semibold whitespace-nowrap cursor-pointer", onClick: () => void handlePrint(o), children: o.orderNumber ?? "—" }), _jsx("td", { className: "px-5 py-4 text-right font-semibold", children: o.cratesOnCart != null ? o.cratesOnCart : "—" }), _jsx("td", { className: "px-5 py-4 font-semibold whitespace-nowrap", children: countryCode(o.country) ?? o.country ?? "—" }), _jsx("td", { className: "px-5 py-4 font-semibold whitespace-nowrap", children: klaarzet.label }), _jsx("td", { className: "px-5 py-4", children: isPrinting ? (_jsx("span", { className: "inline-flex items-center gap-2 px-3 py-1 rounded-full bg-emerald-600 text-white font-semibold", children: t.printingNow })) : (_jsx("span", { className: `inline-flex items-center gap-2 px-3 py-1 rounded-full font-semibold ${badge.className}`, children: badge.label })) })] }, o.id));
|
|
248
|
+
}) })] }) })), _jsx("p", { className: "text-xs text-slate-400 mt-6 text-center", children: t.printDialogHint })] }), pendingConfirm && (_jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4", children: _jsxs("div", { className: "bg-white rounded-2xl shadow-2xl max-w-md w-full p-6", children: [_jsx("h2", { className: "text-2xl font-bold mb-2", children: t.confirmPrintedTitle }), _jsx("p", { className: "text-slate-600 mb-2", children: t.confirmPrintedBody }), _jsx("div", { className: "mb-4 inline-block px-4 py-2 rounded-md bg-black text-white font-black text-3xl tracking-widest font-mono", children: pendingConfirm.cartNumber ?? "—" }), _jsxs("p", { className: "text-slate-800 font-semibold mb-6", children: [pendingConfirm.orderNumber, " \u00B7 kar ", pendingConfirm.cartIndex, "/", pendingConfirm.cartTotal] }), _jsxs("div", { className: "flex flex-col gap-3", children: [_jsxs("button", { onClick: () => void confirmPrinted(true), disabled: confirming, className: "h-14 rounded-xl bg-emerald-600 hover:bg-emerald-700 disabled:bg-slate-300 text-white font-bold text-lg shadow", children: ["\u2713 ", t.confirmYes] }), _jsxs("button", { onClick: () => void confirmPrinted(false), disabled: confirming, className: "h-14 rounded-xl bg-white border-2 border-slate-300 hover:bg-slate-100 disabled:opacity-60 font-semibold text-lg", children: ["\u2715 ", t.confirmNo] })] })] }) })), showChecklist && (_jsx(ControleLijstPrint, { lang: lang ?? "nl", carts: orders.map((o) => ({
|
|
200
249
|
cartNumberId: null,
|
|
201
250
|
cartNumber: o.cartNumber,
|
|
202
251
|
orderId: o.orderId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AfhandelingSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/AfhandelingSettingsCard.tsx"],"names":[],"mappings":"AAsBA,wBAAgB,uBAAuB,
|
|
1
|
+
{"version":3,"file":"AfhandelingSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/AfhandelingSettingsCard.tsx"],"names":[],"mappings":"AAsBA,wBAAgB,uBAAuB,gCA4TtC"}
|
|
@@ -3,7 +3,7 @@ import { useEffect, useState } from "react";
|
|
|
3
3
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
4
4
|
import { useServerFn } from "@tanstack/react-start";
|
|
5
5
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle, Button, Input, Label, Switch, toast, } from "@flowselections/core";
|
|
6
|
-
import { CalendarClock, CalendarDays, Mail, Scale } from "lucide-react";
|
|
6
|
+
import { CalendarClock, CalendarDays, Mail, Pause, Printer, Scale, Sticker } from "lucide-react";
|
|
7
7
|
import { getAfhandelingSettings, updateAfhandelingSettings, } from "../../lib/afhandelingSettings.functions";
|
|
8
8
|
import { WeekdayPicker } from "../afhandeling/WeekdayPicker";
|
|
9
9
|
export function AfhandelingSettingsCard() {
|
|
@@ -26,6 +26,9 @@ export function AfhandelingSettingsCard() {
|
|
|
26
26
|
signupMailLeadMinutes: 60,
|
|
27
27
|
signupMailPurpose: "afhandeling_carrier_signup",
|
|
28
28
|
pickWeekdays: [1, 2, 3, 4, 5],
|
|
29
|
+
extraPickDaysWithStickers: 0,
|
|
30
|
+
autoProcessPaused: false,
|
|
31
|
+
autoPrintDeliveryNote: false,
|
|
29
32
|
};
|
|
30
33
|
}
|
|
31
34
|
},
|
|
@@ -38,6 +41,9 @@ export function AfhandelingSettingsCard() {
|
|
|
38
41
|
const [mailLead, setMailLead] = useState(60);
|
|
39
42
|
const [mailPurpose, setMailPurpose] = useState("afhandeling_carrier_signup");
|
|
40
43
|
const [pickWeekdays, setPickWeekdays] = useState([1, 2, 3, 4, 5]);
|
|
44
|
+
const [extraStickerDays, setExtraStickerDays] = useState(0);
|
|
45
|
+
const [autoProcessPaused, setAutoProcessPaused] = useState(false);
|
|
46
|
+
const [autoPrintDelivery, setAutoPrintDelivery] = useState(false);
|
|
41
47
|
useEffect(() => {
|
|
42
48
|
if (data) {
|
|
43
49
|
setPickDays(data.pickDaysBeforeTransport);
|
|
@@ -50,6 +56,9 @@ export function AfhandelingSettingsCard() {
|
|
|
50
56
|
setPickWeekdays(Array.isArray(data.pickWeekdays) && data.pickWeekdays.length > 0
|
|
51
57
|
? data.pickWeekdays
|
|
52
58
|
: [1, 2, 3, 4, 5]);
|
|
59
|
+
setExtraStickerDays(data.extraPickDaysWithStickers ?? 0);
|
|
60
|
+
setAutoProcessPaused(Boolean(data.autoProcessPaused));
|
|
61
|
+
setAutoPrintDelivery(Boolean(data.autoPrintDeliveryNote));
|
|
53
62
|
}
|
|
54
63
|
}, [data]);
|
|
55
64
|
const mutation = useMutation({
|
|
@@ -63,6 +72,9 @@ export function AfhandelingSettingsCard() {
|
|
|
63
72
|
signupMailLeadMinutes: mailLead,
|
|
64
73
|
signupMailPurpose: mailPurpose,
|
|
65
74
|
pickWeekdays,
|
|
75
|
+
extraPickDaysWithStickers: extraStickerDays,
|
|
76
|
+
autoProcessPaused,
|
|
77
|
+
autoPrintDeliveryNote: autoPrintDelivery,
|
|
66
78
|
},
|
|
67
79
|
}),
|
|
68
80
|
onSuccess: async () => {
|
|
@@ -75,5 +87,5 @@ export function AfhandelingSettingsCard() {
|
|
|
75
87
|
},
|
|
76
88
|
});
|
|
77
89
|
const clamp = (n) => Math.max(0, Math.min(30, Math.floor(n) || 0));
|
|
78
|
-
return (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CalendarClock, { className: "h-5 w-5 text-primary" }), _jsx(CardTitle, { children: "Afhandeling \u2014 Planning" })] }), _jsx(CardDescription, { children: "Centrale werkdag-instellingen voor de automatische order\u00ADplanning. Alle berekeningen tellen alleen werkdagen (ma\u2013vr)." })] }), _jsxs(CardContent, { className: "space-y-5", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "pickDays", children: "Aantal pickdagen (werkdagen v\u00F3\u00F3r ophaaldag)" }), _jsx(Input, { id: "pickDays", type: "number", min: 0, max: 30, value: pickDays, onChange: (e) => setPickDays(clamp(Number(e.target.value))) }), _jsx("p", { className: "text-xs text-muted-foreground", children: "Wordt vanaf de berekende ophaaldag teruggeteld om de uiterste pickdatum te bepalen." })] }), _jsxs("div", { className: "rounded-md border p-4 space-y-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CalendarDays, { className: "h-4 w-4 text-primary" }), _jsx(Label, { className: "font-semibold", children: "Orderpickdagen" })] }), _jsx("p", { className: "text-xs text-muted-foreground", children: "Selecteer de dagen waarop het systeem orders mag inplannen om te picken. Andere dagen worden automatisch overgeslagen." }), _jsx(WeekdayPicker, { value: pickWeekdays, onChange: setPickWeekdays, idPrefix: "pick-wd" }), pickWeekdays.length === 0 ? (_jsx("p", { className: "text-xs text-destructive", children: "Kies minimaal \u00E9\u00E9n pickdag; anders kan het systeem geen orders inplannen." })) : null] }), _jsxs("div", { className: "rounded-md border p-4 space-y-4", children: [_jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Scale, { className: "h-4 w-4 text-primary" }), _jsx(Label, { htmlFor: "pickDistribution", className: "font-semibold", children: "Pickverdeling" })] }), _jsx("p", { className: "text-xs text-muted-foreground max-w-prose", children: "Verdeelt de pickbelasting automatisch over werkdagen. Orders mogen eerder ingepland worden, maar nooit later dan de berekende uiterste pickdatum \u2014 leverbetrouwbaarheid blijft gegarandeerd." })] }), _jsx(Switch, { id: "pickDistribution", checked: distributionEnabled, onCheckedChange: setDistributionEnabled })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "maxEarlier", children: "Maximaal aantal werkdagen eerder picken" }), _jsx(Input, { id: "maxEarlier", type: "number", min: 0, max: 30, value: maxEarlier, disabled: !distributionEnabled, onChange: (e) => setMaxEarlier(clamp(Number(e.target.value))) }), _jsx("p", { className: "text-xs text-muted-foreground", children: "0 = geen vervroeging. Bijv. 2 = orders mogen maximaal 2 werkdagen voor hun uiterste pickdatum ingepland worden." })] })] }), _jsxs("div", { className: "rounded-md border p-4 space-y-4", children: [_jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Mail, { className: "h-4 w-4 text-primary" }), _jsx(Label, { htmlFor: "mailEnabled", className: "font-semibold", children: "Aanmeldmail vervoerders" })] }), _jsx("p", { className: "text-xs text-muted-foreground max-w-prose", children: "Verstuurt automatisch een mail met de te verwachten karren naar de vervoerder v\u00F3\u00F3r de aanmelddeadline van het ophaalmoment. E\u00E9n mail per ophaaldag/-moment per vervoerder." })] }), _jsx(Switch, { id: "mailEnabled", checked: mailEnabled, onCheckedChange: setMailEnabled })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "mailLead", children: "Minuten v\u00F3\u00F3r aanmelddeadline versturen" }), _jsx(Input, { id: "mailLead", type: "number", min: 0, max: 1440, value: mailLead, disabled: !mailEnabled, onChange: (e) => setMailLead(Math.max(0, Math.min(1440, Math.floor(Number(e.target.value)) || 0))) })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "mailPurpose", children: "E-mail-doeleinde (purpose)" }), _jsx(Input, { id: "mailPurpose", value: mailPurpose, disabled: !mailEnabled, onChange: (e) => setMailPurpose(e.target.value) }), _jsxs("p", { className: "text-xs text-muted-foreground", children: ["Koppel dit doeleinde in de module ", _jsx("strong", { children: "E-mailkoppeling" }), " aan een actief send-adres. Standaard: ", _jsx("code", { children: "afhandeling_carrier_signup" }), "."] })] })] }), _jsxs("div", { className: "rounded-md bg-muted/50 p-3 text-xs text-muted-foreground", children: [_jsx("strong", { children: "Ophaaltijd" }), " en ", _jsx("strong", { children: "Aanmeldtijd" }), " stel je per vervoerder in (werkdagen v\u00F3\u00F3r bezorgdag). De vervoerder die als ", _jsx("strong", { children: "standaard" }), " is gemarkeerd, wordt gebruikt voor orders zonder eigen vervoerder."] }), _jsx(Button, { onClick: () => mutation.mutate(), disabled: mutation.isPending, children: mutation.isPending ? "Opslaan…" : "Opslaan" })] })] }));
|
|
90
|
+
return (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CalendarClock, { className: "h-5 w-5 text-primary" }), _jsx(CardTitle, { children: "Afhandeling \u2014 Planning" })] }), _jsx(CardDescription, { children: "Centrale werkdag-instellingen voor de automatische order\u00ADplanning. Alle berekeningen tellen alleen werkdagen (ma\u2013vr)." })] }), _jsxs(CardContent, { className: "space-y-5", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "pickDays", children: "Aantal pickdagen (werkdagen v\u00F3\u00F3r ophaaldag)" }), _jsx(Input, { id: "pickDays", type: "number", min: 0, max: 30, value: pickDays, onChange: (e) => setPickDays(clamp(Number(e.target.value))) }), _jsx("p", { className: "text-xs text-muted-foreground", children: "Wordt vanaf de berekende ophaaldag teruggeteld om de uiterste pickdatum te bepalen." })] }), _jsxs("div", { className: "rounded-md border p-4 space-y-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Sticker, { className: "h-4 w-4 text-primary" }), _jsx(Label, { htmlFor: "extraStickerDays", className: "font-semibold", children: "Extra pickdagen bij stickers" })] }), _jsx("p", { className: "text-xs text-muted-foreground max-w-prose", children: "Wanneer een order stickers bevat, mag het picken langer duren. Deze werkdagen worden bovenop het standaard aantal pickdagen opgeteld, zodat de uiterste pickdatum vroeger valt." }), _jsx(Input, { id: "extraStickerDays", type: "number", min: 0, max: 30, value: extraStickerDays, onChange: (e) => setExtraStickerDays(clamp(Number(e.target.value))) }), _jsx("p", { className: "text-xs text-muted-foreground", children: "Voorbeeld: standaard 1 pickdag + 2 extra = 3 werkdagen picktijd voor orders met stickers." })] }), _jsxs("div", { className: "rounded-md border p-4 space-y-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CalendarDays, { className: "h-4 w-4 text-primary" }), _jsx(Label, { className: "font-semibold", children: "Orderpickdagen" })] }), _jsx("p", { className: "text-xs text-muted-foreground", children: "Selecteer de dagen waarop het systeem orders mag inplannen om te picken. Andere dagen worden automatisch overgeslagen." }), _jsx(WeekdayPicker, { value: pickWeekdays, onChange: setPickWeekdays, idPrefix: "pick-wd" }), pickWeekdays.length === 0 ? (_jsx("p", { className: "text-xs text-destructive", children: "Kies minimaal \u00E9\u00E9n pickdag; anders kan het systeem geen orders inplannen." })) : null] }), _jsxs("div", { className: "rounded-md border p-4 space-y-4", children: [_jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Scale, { className: "h-4 w-4 text-primary" }), _jsx(Label, { htmlFor: "pickDistribution", className: "font-semibold", children: "Pickverdeling" })] }), _jsx("p", { className: "text-xs text-muted-foreground max-w-prose", children: "Verdeelt de pickbelasting automatisch over werkdagen. Orders mogen eerder ingepland worden, maar nooit later dan de berekende uiterste pickdatum \u2014 leverbetrouwbaarheid blijft gegarandeerd." })] }), _jsx(Switch, { id: "pickDistribution", checked: distributionEnabled, onCheckedChange: setDistributionEnabled })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "maxEarlier", children: "Maximaal aantal werkdagen eerder picken" }), _jsx(Input, { id: "maxEarlier", type: "number", min: 0, max: 30, value: maxEarlier, disabled: !distributionEnabled, onChange: (e) => setMaxEarlier(clamp(Number(e.target.value))) }), _jsx("p", { className: "text-xs text-muted-foreground", children: "0 = geen vervroeging. Bijv. 2 = orders mogen maximaal 2 werkdagen voor hun uiterste pickdatum ingepland worden." })] })] }), _jsxs("div", { className: "rounded-md border p-4 space-y-4", children: [_jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Mail, { className: "h-4 w-4 text-primary" }), _jsx(Label, { htmlFor: "mailEnabled", className: "font-semibold", children: "Aanmeldmail vervoerders" })] }), _jsx("p", { className: "text-xs text-muted-foreground max-w-prose", children: "Verstuurt automatisch een mail met de te verwachten karren naar de vervoerder v\u00F3\u00F3r de aanmelddeadline van het ophaalmoment. E\u00E9n mail per ophaaldag/-moment per vervoerder." })] }), _jsx(Switch, { id: "mailEnabled", checked: mailEnabled, onCheckedChange: setMailEnabled })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "mailLead", children: "Minuten v\u00F3\u00F3r aanmelddeadline versturen" }), _jsx(Input, { id: "mailLead", type: "number", min: 0, max: 1440, value: mailLead, disabled: !mailEnabled, onChange: (e) => setMailLead(Math.max(0, Math.min(1440, Math.floor(Number(e.target.value)) || 0))) })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "mailPurpose", children: "E-mail-doeleinde (purpose)" }), _jsx(Input, { id: "mailPurpose", value: mailPurpose, disabled: !mailEnabled, onChange: (e) => setMailPurpose(e.target.value) }), _jsxs("p", { className: "text-xs text-muted-foreground", children: ["Koppel dit doeleinde in de module ", _jsx("strong", { children: "E-mailkoppeling" }), " aan een actief send-adres. Standaard: ", _jsx("code", { children: "afhandeling_carrier_signup" }), "."] })] })] }), _jsxs("div", { className: "rounded-md border p-4 space-y-4", children: [_jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Pause, { className: "h-4 w-4 text-primary" }), _jsx(Label, { htmlFor: "autoPause", className: "font-semibold", children: "Automatische Floriday-verwerking pauzeren" })] }), _jsxs("p", { className: "text-xs text-muted-foreground max-w-prose", children: ["Zet dit aan om ", _jsx("strong", { children: "tijdelijk" }), " te stoppen met automatisch Sales Orders acknowledgen, delivery orders aanmaken en fulfillment orders versturen. Bestaande orders in de wachtrij blijven staan."] })] }), _jsx(Switch, { id: "autoPause", checked: autoProcessPaused, onCheckedChange: setAutoProcessPaused })] }), _jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Printer, { className: "h-4 w-4 text-primary" }), _jsx(Label, { htmlFor: "autoPrint", className: "font-semibold", children: "Afleverbrief automatisch printen" })] }), _jsx("p", { className: "text-xs text-muted-foreground max-w-prose", children: "Wanneer een afleverbrief beschikbaar komt, wordt hij direct naar de standaardprinter gestuurd. Handig voor onbemande balies." })] }), _jsx(Switch, { id: "autoPrint", checked: autoPrintDelivery, onCheckedChange: setAutoPrintDelivery })] }), _jsxs("p", { className: "text-xs text-muted-foreground", children: ["Timing van de automatische verwerking wordt bepaald door", " ", _jsx("strong", { children: "Maximaal aantal werkdagen eerder picken" }), ",", " ", _jsx("strong", { children: "Orderpickdagen" }), " en", " ", _jsx("strong", { children: "Extra pickdagen bij stickers" }), " hierboven."] })] }), _jsxs("div", { className: "rounded-md bg-muted/50 p-3 text-xs text-muted-foreground", children: [_jsx("strong", { children: "Ophaaltijd" }), " en ", _jsx("strong", { children: "Aanmeldtijd" }), " stel je per vervoerder in (werkdagen v\u00F3\u00F3r bezorgdag). De vervoerder die als ", _jsx("strong", { children: "standaard" }), " is gemarkeerd, wordt gebruikt voor orders zonder eigen vervoerder."] }), _jsx(Button, { onClick: () => mutation.mutate(), disabled: mutation.isPending, children: mutation.isPending ? "Opslaan…" : "Opslaan" })] })] }));
|
|
79
91
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useOrderPlanning.d.ts","sourceRoot":"","sources":["../../src/hooks/useOrderPlanning.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAI/D,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"useOrderPlanning.d.ts","sourceRoot":"","sources":["../../src/hooks/useOrderPlanning.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAI/D,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAExF,OAAO,EAIL,KAAK,aAAa,EAEnB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,gBAAgB,IAAI,sBAAsB,CAkJzD"}
|
|
@@ -5,6 +5,7 @@ import { getFloridayOrders } from "../lib/floriday.functions";
|
|
|
5
5
|
import { getAfhandelingSettings } from "../lib/afhandelingSettings.functions";
|
|
6
6
|
import { listCarriers } from "../lib/carriers.functions";
|
|
7
7
|
import { listCartOverrides } from "../lib/cartAssignments.functions";
|
|
8
|
+
import { normalizePickupMoments, sanitizeWeekdays, selectCarrierForTarget } from "../lib/carrierPlanning";
|
|
8
9
|
import { calculateOrderPlanning, distributePickDates, DEFAULT_PICKUP_MOMENT, } from "../lib/planning";
|
|
9
10
|
export function useOrderPlanning() {
|
|
10
11
|
const fetchOrders = useServerFn(getFloridayOrders);
|
|
@@ -52,7 +53,7 @@ export function useOrderPlanning() {
|
|
|
52
53
|
return await fetchSettings();
|
|
53
54
|
}
|
|
54
55
|
catch {
|
|
55
|
-
return { pickDaysBeforeTransport: 1, transportRegisterDaysBefore: 1, pickDistributionEnabled: false, maxWorkdaysEarlierPick: 2, signupMailEnabled: false, signupMailLeadMinutes: 60, signupMailPurpose: "afhandeling_carrier_signup", pickWeekdays: [1, 2, 3, 4, 5] };
|
|
56
|
+
return { pickDaysBeforeTransport: 1, transportRegisterDaysBefore: 1, pickDistributionEnabled: false, maxWorkdaysEarlierPick: 2, signupMailEnabled: false, signupMailLeadMinutes: 60, signupMailPurpose: "afhandeling_carrier_signup", pickWeekdays: [1, 2, 3, 4, 5], extraPickDaysWithStickers: 0 };
|
|
56
57
|
}
|
|
57
58
|
},
|
|
58
59
|
});
|
|
@@ -88,15 +89,10 @@ export function useOrderPlanning() {
|
|
|
88
89
|
pickDistributionEnabled: false,
|
|
89
90
|
maxWorkdaysEarlierPick: 2,
|
|
90
91
|
pickWeekdays: [1, 2, 3, 4, 5],
|
|
92
|
+
extraPickDaysWithStickers: 0,
|
|
91
93
|
};
|
|
92
94
|
const carriers = carriersQuery.data?.carriers ?? [];
|
|
93
95
|
const overrides = overridesQuery.data?.overrides ?? [];
|
|
94
|
-
const defaultCarrier = carriers.find((c) => c.is_default);
|
|
95
|
-
const moments = defaultCarrier && defaultCarrier.pickup_moments.length > 0
|
|
96
|
-
? defaultCarrier.pickup_moments
|
|
97
|
-
: [DEFAULT_PICKUP_MOMENT];
|
|
98
|
-
const carrierPickupWeekdays = defaultCarrier?.pickup_weekdays ?? [1, 2, 3, 4, 5];
|
|
99
|
-
const carrierDeliveryWeekdays = defaultCarrier?.delivery_weekdays ?? [1, 2, 3, 4, 5];
|
|
100
96
|
const pickWeekdays = settings.pickWeekdays ?? [1, 2, 3, 4, 5];
|
|
101
97
|
const overrideMap = new Map();
|
|
102
98
|
for (const o of overrides) {
|
|
@@ -106,16 +102,32 @@ export function useOrderPlanning() {
|
|
|
106
102
|
});
|
|
107
103
|
}
|
|
108
104
|
const initial = orders.map((order) => {
|
|
105
|
+
const carrier = selectCarrierForTarget(carriers, {
|
|
106
|
+
carrierId: order.carrierId,
|
|
107
|
+
country: order.country,
|
|
108
|
+
province: order.province,
|
|
109
|
+
city: order.city,
|
|
110
|
+
});
|
|
111
|
+
const moments = carrier
|
|
112
|
+
? normalizePickupMoments(carrier.pickup_moments)
|
|
113
|
+
: [DEFAULT_PICKUP_MOMENT];
|
|
114
|
+
const carrierPickupWeekdays = sanitizeWeekdays(carrier?.pickup_weekdays);
|
|
115
|
+
const carrierDeliveryWeekdays = sanitizeWeekdays(carrier?.delivery_weekdays);
|
|
116
|
+
const extraStickerDays = Math.max(0, Math.floor(settings.extraPickDaysWithStickers ?? 0));
|
|
117
|
+
const pickDuration = settings.pickDaysBeforeTransport + (order.hasStickers ? extraStickerDays : 0);
|
|
109
118
|
const planning = calculateOrderPlanning(order.deliveryDate, {
|
|
110
119
|
pickupMoments: moments,
|
|
111
|
-
pickDurationWorkdays:
|
|
120
|
+
pickDurationWorkdays: pickDuration,
|
|
112
121
|
orderCreatedAt: order.createdAt,
|
|
113
122
|
pickWeekdays,
|
|
114
123
|
carrierPickupWeekdays,
|
|
115
124
|
carrierDeliveryWeekdays,
|
|
125
|
+
carrierId: carrier?.id ?? null,
|
|
126
|
+
carrierName: carrier?.name ?? null,
|
|
127
|
+
orderId: order.id,
|
|
116
128
|
});
|
|
117
|
-
if (planning &&
|
|
118
|
-
planning.carrierName =
|
|
129
|
+
if (planning && carrier) {
|
|
130
|
+
planning.carrierName = carrier.name;
|
|
119
131
|
}
|
|
120
132
|
return { order, planning };
|
|
121
133
|
});
|
|
@@ -137,6 +149,11 @@ export function useOrderPlanning() {
|
|
|
137
149
|
isLoading: ordersQuery.isLoading || settingsQuery.isLoading || carriersQuery.isLoading || overridesQuery.isLoading,
|
|
138
150
|
error: ordersQuery.data?.orders?.length ? undefined : ordersQuery.data?.error,
|
|
139
151
|
warning: ordersQuery.data?.orders?.length ? ordersQuery.data?.error : undefined,
|
|
140
|
-
refetch: () => {
|
|
152
|
+
refetch: () => {
|
|
153
|
+
void ordersQuery.refetch();
|
|
154
|
+
void settingsQuery.refetch();
|
|
155
|
+
void carriersQuery.refetch();
|
|
156
|
+
void overridesQuery.refetch();
|
|
157
|
+
},
|
|
141
158
|
};
|
|
142
159
|
}
|
package/dist-lib/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { FlowModule } from "@flowselections/core";
|
|
|
2
2
|
export * from "./_core-safelist";
|
|
3
3
|
export { LeveringenPage } from "./components/afhandeling/LeveringenPage";
|
|
4
4
|
export { VervoerdersPage } from "./components/afhandeling/VervoerdersPage";
|
|
5
|
+
export { VervoerderForm } from "./components/afhandeling/VervoerderForm";
|
|
5
6
|
export { NieuweLeveringPage } from "./components/afhandeling/NieuweLeveringPage";
|
|
6
7
|
export { PickAgendaView } from "./components/afhandeling/PickAgendaView";
|
|
7
8
|
export { PickingPage } from "./components/afhandeling/PickingPage";
|
|
@@ -11,5 +12,7 @@ export { AfhandelingSettingsCard } from "./components/settings/AfhandelingSettin
|
|
|
11
12
|
export { VervoerdersSettingsCard } from "./components/settings/VervoerdersSettingsCard";
|
|
12
13
|
export { PickstationPage } from "./components/pickstation/PickstationPage";
|
|
13
14
|
export { KioskControle } from "./components/pickstation/KioskControle";
|
|
15
|
+
export { calculateEarliestDeliveryDate, calculateOrderPlanning, DEFAULT_PICKUP_MOMENT, type EarliestDeliveryRules, type OrderPlanning, type PickupMoment, } from "./lib/planning";
|
|
16
|
+
export { carrierLeadDaysFromMoments, normalizePickupMoments, sanitizeWeekdays, selectCarrierForTarget, type CarrierOrderTarget, type CarrierPlanningInfo, } from "./lib/carrierPlanning";
|
|
14
17
|
export declare const floridayAfhandelingModule: FlowModule;
|
|
15
18
|
//# sourceMappingURL=index.d.ts.map
|
package/dist-lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,0CAA0C,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,MAAM,+CAA+C,CAAC;AACxF,OAAO,EAAE,uBAAuB,EAAE,MAAM,+CAA+C,CAAC;AACxF,OAAO,EAAE,eAAe,EAAE,MAAM,0CAA0C,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,0CAA0C,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,MAAM,+CAA+C,CAAC;AACxF,OAAO,EAAE,uBAAuB,EAAE,MAAM,+CAA+C,CAAC;AACxF,OAAO,EAAE,eAAe,EAAE,MAAM,0CAA0C,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AACvE,OAAO,EACL,6BAA6B,EAC7B,sBAAsB,EACtB,qBAAqB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,YAAY,GAClB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,0BAA0B,EAC1B,sBAAsB,EACtB,gBAAgB,EAChB,sBAAsB,EACtB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,GACzB,MAAM,uBAAuB,CAAC;AAK/B,eAAO,MAAM,yBAAyB,EAAE,UAkBvC,CAAC"}
|
package/dist-lib/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import { PackageCheck, CalendarCheck, CalendarRange, ClipboardCheck } from "luci
|
|
|
2
2
|
export * from "./_core-safelist";
|
|
3
3
|
export { LeveringenPage } from "./components/afhandeling/LeveringenPage";
|
|
4
4
|
export { VervoerdersPage } from "./components/afhandeling/VervoerdersPage";
|
|
5
|
+
export { VervoerderForm } from "./components/afhandeling/VervoerderForm";
|
|
5
6
|
export { NieuweLeveringPage } from "./components/afhandeling/NieuweLeveringPage";
|
|
6
7
|
export { PickAgendaView } from "./components/afhandeling/PickAgendaView";
|
|
7
8
|
export { PickingPage } from "./components/afhandeling/PickingPage";
|
|
@@ -11,6 +12,8 @@ export { AfhandelingSettingsCard } from "./components/settings/AfhandelingSettin
|
|
|
11
12
|
export { VervoerdersSettingsCard } from "./components/settings/VervoerdersSettingsCard";
|
|
12
13
|
export { PickstationPage } from "./components/pickstation/PickstationPage";
|
|
13
14
|
export { KioskControle } from "./components/pickstation/KioskControle";
|
|
15
|
+
export { calculateEarliestDeliveryDate, calculateOrderPlanning, DEFAULT_PICKUP_MOMENT, } from "./lib/planning";
|
|
16
|
+
export { carrierLeadDaysFromMoments, normalizePickupMoments, sanitizeWeekdays, selectCarrierForTarget, } from "./lib/carrierPlanning";
|
|
14
17
|
import { AfhandelingSettingsCard } from "./components/settings/AfhandelingSettingsCard";
|
|
15
18
|
import { VervoerdersSettingsCard } from "./components/settings/VervoerdersSettingsCard";
|
|
16
19
|
export const floridayAfhandelingModule = {
|