@flowselections/floriday-afhandeling-module 1.0.64 → 1.0.66
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/DagDetailDialog.d.ts +4 -0
- package/dist-lib/components/afhandeling/DagDetailDialog.d.ts.map +1 -1
- package/dist-lib/components/afhandeling/DagDetailDialog.js +26 -11
- package/dist-lib/components/afhandeling/LeveringenPage.d.ts.map +1 -1
- package/dist-lib/components/afhandeling/LeveringenPage.js +24 -2
- package/dist-lib/components/afhandeling/SignupMailMoments.js +7 -4
- package/dist-lib/components/afhandeling/VervoerderForm.d.ts.map +1 -1
- package/dist-lib/components/afhandeling/VervoerderForm.js +14 -7
- package/dist-lib/components/settings/AfhandelingSettingsCard.d.ts.map +1 -1
- package/dist-lib/components/settings/AfhandelingSettingsCard.js +1 -1
- package/dist-lib/hooks/useOrderPlanning.d.ts.map +1 -1
- package/dist-lib/hooks/useOrderPlanning.js +20 -5
- package/dist-lib/integrations/supabase/types.d.ts +249 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/carrierPlanning.d.ts +4 -0
- package/dist-lib/lib/carrierPlanning.d.ts.map +1 -1
- package/dist-lib/lib/carrierPlanning.js +14 -8
- package/dist-lib/lib/carrierSignup.functions.d.ts +2 -0
- package/dist-lib/lib/carrierSignup.functions.d.ts.map +1 -1
- package/dist-lib/lib/carrierSignup.functions.js +2 -0
- package/dist-lib/lib/carriers.functions.d.ts.map +1 -1
- package/dist-lib/lib/carriers.functions.js +13 -6
- package/dist-lib/lib/pickWorkdays.d.ts +24 -0
- package/dist-lib/lib/pickWorkdays.d.ts.map +1 -0
- package/dist-lib/lib/pickWorkdays.js +30 -0
- package/dist-lib/lib/pickstationOrders.server.d.ts.map +1 -1
- package/dist-lib/lib/pickstationOrders.server.js +9 -3
- package/dist-lib/lib/planning.d.ts +19 -0
- package/dist-lib/lib/planning.d.ts.map +1 -1
- package/dist-lib/lib/planning.js +58 -11
- package/dist-lib/lib/signupMailText.d.ts.map +1 -1
- package/dist-lib/lib/signupMailText.js +2 -0
- package/package.json +1 -1
|
@@ -4,6 +4,10 @@ export interface DagDetailDialogProps {
|
|
|
4
4
|
date: Date | null;
|
|
5
5
|
planned: PlannedOrder[];
|
|
6
6
|
onOpenChange: (open: boolean) => void;
|
|
7
|
+
/** Waar de dag op telt: leverdag (Planning en leveringen) of pickdag (Pick Agenda). */
|
|
8
|
+
basis?: "lever" | "pick";
|
|
9
|
+
/** Order (id) die uitgelicht wordt, bv. vanuit een link. */
|
|
10
|
+
highlightOrderId?: string | null;
|
|
7
11
|
}
|
|
8
12
|
export declare function DagDetailDialog(props: DagDetailDialogProps): import("react").JSX.Element | null;
|
|
9
13
|
//# sourceMappingURL=DagDetailDialog.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DagDetailDialog.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/DagDetailDialog.tsx"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"DagDetailDialog.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/DagDetailDialog.tsx"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AA8JjE,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;IACtC,uFAAuF;IACvF,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,4DAA4D;IAC5D,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAUD,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,sCAG1D"}
|
|
@@ -9,6 +9,7 @@ import { ResponsiveDialogBody, ResponsiveDialogContent, ResponsiveDialogFooter,
|
|
|
9
9
|
import { usePickAgenda } from "../../hooks/usePickAgenda";
|
|
10
10
|
import { useOrderBuffers, useBufferMembers } from "../../hooks/useOrderBuffers";
|
|
11
11
|
import { isSameDay } from "../../lib/pickDate";
|
|
12
|
+
import { isExcludedOrderStatus } from "../../lib/orderStatus";
|
|
12
13
|
import { getOrderLines, getDayCartContents, getOrderCartIds, getPakbonCartInfo, } from "../../lib/cartAssignments.functions";
|
|
13
14
|
import { printLayoutDocument, printPdfDocument, printFoutMelding } from "../../lib/printing";
|
|
14
15
|
import { NuVersturenButton } from "./NuVersturenButton";
|
|
@@ -79,6 +80,7 @@ function StickerMeldingen({ orderId }) {
|
|
|
79
80
|
return null;
|
|
80
81
|
return (_jsx("ul", { className: "space-y-1", children: q.data.map((m, i) => (_jsxs("li", { className: "flex items-start gap-1 text-xs text-destructive", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-3 w-3 shrink-0" }), _jsx("span", { children: m.melding })] }, (m.stickerId ?? "") + i))) }));
|
|
81
82
|
}
|
|
83
|
+
const HighlightCtx = createContext(null);
|
|
82
84
|
const NL_DATE = new Intl.DateTimeFormat("nl-NL", { dateStyle: "full" });
|
|
83
85
|
function refKey(value) {
|
|
84
86
|
return (value ?? "").trim().toUpperCase();
|
|
@@ -88,7 +90,7 @@ export function DagDetailDialog(props) {
|
|
|
88
90
|
return null;
|
|
89
91
|
return _jsx(DagDetailContent, { ...props, date: props.date });
|
|
90
92
|
}
|
|
91
|
-
function DagDetailContent({ open, date, planned, onOpenChange, }) {
|
|
93
|
+
function DagDetailContent({ open, date, planned, onOpenChange, basis = "pick", highlightOrderId, }) {
|
|
92
94
|
const dayKey = toDayKey(date);
|
|
93
95
|
const agenda = usePickAgenda(dayKey, dayKey);
|
|
94
96
|
const row = agenda.byDate.get(dayKey);
|
|
@@ -102,16 +104,28 @@ function DagDetailContent({ open, date, planned, onOpenChange, }) {
|
|
|
102
104
|
plannedByRef.set(k, p);
|
|
103
105
|
}
|
|
104
106
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
107
|
+
// Leverdag: dezelfde orders als de dagkaart in Planning en leveringen.
|
|
108
|
+
const ordersOnDay = basis === "lever"
|
|
109
|
+
? planned
|
|
110
|
+
.filter((p) => p.planning?.deliveryDate && isSameDay(p.planning.deliveryDate, date))
|
|
111
|
+
.filter((p) => !/annul|cancel/i.test(p.order.status ?? "") && !isExcludedOrderStatus(p.order.status))
|
|
112
|
+
.map((p) => ({
|
|
113
|
+
ref: p.order.orderNumber || p.order.id,
|
|
114
|
+
carts: (p.planning?.pickAssignments ?? []).reduce((s, a) => s + a.cartCount, 0),
|
|
115
|
+
plants: p.order.plantCount ?? 0,
|
|
116
|
+
status: p.order.status ?? "",
|
|
117
|
+
planned: p,
|
|
118
|
+
}))
|
|
119
|
+
: (row?.orders ?? []).map((o) => ({
|
|
120
|
+
ref: o.orderRef,
|
|
121
|
+
carts: o.carts,
|
|
122
|
+
plants: o.plants,
|
|
123
|
+
status: o.status,
|
|
124
|
+
planned: plannedByRef.get(refKey(o.orderRef)) ?? null,
|
|
125
|
+
}));
|
|
112
126
|
// Aanvullen met lokaal ingeplande orders die de Engine-rij (nog) niet noemt.
|
|
113
127
|
const seen = new Set(ordersOnDay.map((o) => refKey(o.ref)));
|
|
114
|
-
for (const p of planned) {
|
|
128
|
+
for (const p of basis === "lever" ? [] : planned) {
|
|
115
129
|
const assigns = p.planning?.pickAssignments ?? [];
|
|
116
130
|
const today = assigns.find((a) => isSameDay(a.date, date));
|
|
117
131
|
if (!today)
|
|
@@ -181,7 +195,7 @@ function DagDetailContent({ open, date, planned, onOpenChange, }) {
|
|
|
181
195
|
}
|
|
182
196
|
// Tel karren op unieke kar-id (gedeelde bufferkar één keer); rijen zonder id tellen los.
|
|
183
197
|
const uniekeKarren = new Set(cartRows.map((c) => c.cartId ?? `zonder-id:${c.key}`)).size;
|
|
184
|
-
return (_jsx(ShipStateCtx.Provider, { value: shipState, children: _jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(ResponsiveDialogContent, { size: "xl", children: [_jsxs(ResponsiveDialogHeader, { children: [_jsxs(DialogTitle, { children: ["Dagdetails \u2014 ", NL_DATE.format(date)] }), _jsxs(DialogDescription, { children: [ordersOnDay.length, " bestellingen \u00B7 ", uniekeKarren, " ", uniekeKarren === 1 ? "kar" : "karren", " \u00B7", " ", ordersOnDay.filter((o) => voortgang(o.status).done).length, " van ", ordersOnDay.length, " ", "bestellingen afgehandeld \u00B7 ", new Set(cartRows.filter((c) => voortgang(c.status).done).map((c) => c.cartId ?? `zonder-id:${c.key}`)).size, " van", " ", uniekeKarren, " karren afgehandeld"] })] }), _jsxs(ResponsiveDialogBody, { children: [_jsx(DayCapacityWarning, { date: date }), _jsx(BezettingCard, { date: date, cartsToday: uniekeKarren }), _jsx(SignupMailMoments, { from: dayKey, to: dayKey }), _jsxs(Tabs, { defaultValue: "bestellingen", children: [_jsxs(TabsList, { children: [_jsxs(TabsTrigger, { value: "bestellingen", children: ["Bestellingen (", ordersOnDay.length, ")"] }), _jsxs(TabsTrigger, { value: "karren", children: ["Karren (", uniekeKarren, ")"] })] }), _jsx(TabsContent, { value: "bestellingen", className: "mt-4", children: _jsx(BestellingenTab, { orders: ordersOnDay, isLoading: agenda.isLoading }) }), _jsx(TabsContent, { value: "karren", className: "mt-4", children: _jsx(KarrenTab, { carts: cartRows }) })] })] }), _jsx(ResponsiveDialogFooter, { children: _jsx(Button, { variant: "outline", onClick: () => onOpenChange(false), children: "Sluiten" }) })] }) }) }));
|
|
198
|
+
return (_jsx(HighlightCtx.Provider, { value: highlightOrderId ?? null, children: _jsx(ShipStateCtx.Provider, { value: shipState, children: _jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(ResponsiveDialogContent, { size: "xl", children: [_jsxs(ResponsiveDialogHeader, { children: [_jsxs(DialogTitle, { children: ["Dagdetails \u2014 ", NL_DATE.format(date), " (", basis === "lever" ? "leverdag" : "pickdag", ")"] }), _jsxs(DialogDescription, { children: [basis === "lever" ? "Bestellingen die op deze dag worden geleverd. " : "Bestellingen die op deze dag worden gepickt. ", ordersOnDay.length, " ", ordersOnDay.length === 1 ? "bestelling" : "bestellingen", " \u00B7 ", uniekeKarren, " ", uniekeKarren === 1 ? "kar" : "karren", " \u00B7", " ", ordersOnDay.filter((o) => voortgang(o.status).done).length, " van ", ordersOnDay.length, " ", ordersOnDay.length === 1 ? "bestelling" : "bestellingen", " afgehandeld \u00B7 ", new Set(cartRows.filter((c) => voortgang(c.status).done).map((c) => c.cartId ?? `zonder-id:${c.key}`)).size, " van", " ", uniekeKarren, " ", uniekeKarren === 1 ? "kar" : "karren", " afgehandeld"] })] }), _jsxs(ResponsiveDialogBody, { children: [_jsx(DayCapacityWarning, { date: date }), _jsx(BezettingCard, { date: date, cartsToday: uniekeKarren }), _jsx(SignupMailMoments, { from: dayKey, to: dayKey }), _jsxs(Tabs, { defaultValue: "bestellingen", children: [_jsxs(TabsList, { children: [_jsxs(TabsTrigger, { value: "bestellingen", children: ["Bestellingen (", ordersOnDay.length, ")"] }), _jsxs(TabsTrigger, { value: "karren", children: ["Karren (", uniekeKarren, ")"] })] }), _jsx(TabsContent, { value: "bestellingen", className: "mt-4", children: _jsx(BestellingenTab, { orders: ordersOnDay, isLoading: agenda.isLoading }) }), _jsx(TabsContent, { value: "karren", className: "mt-4", children: _jsx(KarrenTab, { carts: cartRows }) })] })] }), _jsx(ResponsiveDialogFooter, { children: _jsx(Button, { variant: "outline", onClick: () => onOpenChange(false), children: "Sluiten" }) })] }) }) }) }));
|
|
185
199
|
}
|
|
186
200
|
function BezettingCard({ date, cartsToday }) {
|
|
187
201
|
const queryClient = useQueryClient();
|
|
@@ -647,7 +661,8 @@ function OrderRow({ planned: p, cartsToday, engineStatus, }) {
|
|
|
647
661
|
setPrinting(false);
|
|
648
662
|
}
|
|
649
663
|
};
|
|
650
|
-
|
|
664
|
+
const highlighted = useContext(HighlightCtx) === p.order.id;
|
|
665
|
+
return (_jsxs("div", { className: `rounded-lg border bg-card ${highlighted ? "ring-2 ring-primary" : ""}`, ref: highlighted ? (el) => el?.scrollIntoView({ block: "center" }) : undefined, children: [_jsxs("div", { className: "flex flex-col gap-3 p-3", children: [_jsxs("button", { type: "button", onClick: () => setOpen((o) => !o), className: "-m-1 flex items-start gap-3 rounded-md p-1 text-left hover:bg-muted/50", children: [open ? (_jsx(ChevronDown, { className: "mt-1 h-4 w-4 shrink-0" })) : (_jsx(ChevronRight, { className: "mt-1 h-4 w-4 shrink-0" })), _jsxs("div", { className: "min-w-0 flex-1 space-y-2", children: [_jsxs("div", { className: "flex flex-wrap items-baseline gap-x-6 gap-y-1 text-sm", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "font-medium", children: p.order.orderNumber }), _jsx("div", { className: "truncate text-xs text-muted-foreground", children: p.order.customerName })] }), _jsxs("div", { className: "text-xs text-muted-foreground", children: ["Type ", _jsx("span", { className: "text-foreground", children: p.order.deliveryType })] }), _jsxs("div", { className: "text-xs text-muted-foreground", children: ["Leverdatum", " ", _jsx("span", { className: "text-foreground", children: p.order.deliveryDate
|
|
651
666
|
? new Date(p.order.deliveryDate).toLocaleDateString("nl-NL")
|
|
652
667
|
: "—" })] })] }), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsxs(Badge, { variant: "secondary", children: [cartsToday, " ", cartsToday === 1 ? "kar" : "karren", " vandaag"] }), _jsx(StatusBadge, { vg: vg })] }), _jsx(StickerMeldingen, { orderId: p.order.id })] })] }), _jsxs("div", { className: "flex flex-wrap items-center gap-2 border-t pt-3", children: [p.order.orderNumber && p.order.salesOrderId && !shipStateRow?.floridaySent ? _jsx(NuVersturenButton, { orderRef: p.order.orderNumber }) : null, p.order.salesOrderId ? _jsx(AutoSendStatus, { orderId: p.order.id, orderRef: p.order.orderNumber }) : null, _jsx(AfhandelenButton, { orderRef: p.order.orderNumber, done: vg.done }), _jsxs(Button, { size: "sm", variant: "outline", onClick: handlePrintAll, disabled: printing, title: "Alle documenten van deze bestelling afdrukken (pakbonnen per kar en de verzendbrief)", children: [_jsx(Printer, { className: "mr-1 h-3.5 w-3.5" }), printing ? "In de Printwachtrij…" : "Alle documenten afdrukken"] }), _jsxs(Button, { size: "sm", variant: "outline", onClick: (e) => {
|
|
653
668
|
e.stopPropagation();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LeveringenPage.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/LeveringenPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"LeveringenPage.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/LeveringenPage.tsx"],"names":[],"mappings":"AAmBA,wBAAgB,cAAc,gCAmD7B"}
|
|
@@ -1,14 +1,36 @@
|
|
|
1
1
|
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useMemo, useState } from "react";
|
|
2
|
+
import { useEffect, useMemo, useState } from "react";
|
|
3
3
|
import { Button } from "@flowselections/core";
|
|
4
4
|
import { WeekAgendaView } from "./WeekAgendaView";
|
|
5
5
|
import { DagDetailDialog } from "./DagDetailDialog";
|
|
6
6
|
import { useOrderPlanning } from "../../hooks/useOrderPlanning";
|
|
7
7
|
import { agendaRange, currentWeekStart } from "../../lib/agendaRange";
|
|
8
|
+
import { startOfWeek } from "../../lib/pickDate";
|
|
9
|
+
/** Leest ?dag=JJJJ-MM-DD&order=<order_id> (link vanuit bv. Dashboards). */
|
|
10
|
+
function readLinkParams() {
|
|
11
|
+
const sp = new URLSearchParams(window.location.search);
|
|
12
|
+
const dag = sp.get("dag");
|
|
13
|
+
const order = sp.get("order");
|
|
14
|
+
const m = dag && /^(\d{4})-(\d{2})-(\d{2})$/.exec(dag);
|
|
15
|
+
const day = m ? new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3])) : null;
|
|
16
|
+
const orderId = order && /^[0-9a-f-]{36}$/i.test(order) ? order : null;
|
|
17
|
+
return { day: day && !Number.isNaN(day.getTime()) ? day : null, orderId };
|
|
18
|
+
}
|
|
8
19
|
export function LeveringenPage() {
|
|
9
20
|
const [weekStart, setWeekStart] = useState(() => currentWeekStart());
|
|
10
21
|
const range = useMemo(() => agendaRange(weekStart), [weekStart]);
|
|
11
22
|
const { planned, nearestDeliveryDate, isLoading, error, warning, refetch } = useOrderPlanning(range);
|
|
12
23
|
const [dayDetailDate, setDayDetailDate] = useState(null);
|
|
13
|
-
|
|
24
|
+
const [highlightOrderId, setHighlightOrderId] = useState(null);
|
|
25
|
+
const [linkDay, setLinkDay] = useState(null);
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
const { day, orderId } = readLinkParams();
|
|
28
|
+
if (day) {
|
|
29
|
+
setLinkDay(new URLSearchParams(window.location.search).get("dag"));
|
|
30
|
+
setWeekStart(startOfWeek(day));
|
|
31
|
+
setDayDetailDate(day);
|
|
32
|
+
setHighlightOrderId(orderId);
|
|
33
|
+
}
|
|
34
|
+
}, []);
|
|
35
|
+
return (_jsxs("main", { className: "p-6 space-y-6", children: [warning && !error && (_jsxs("div", { className: "rounded-md border border-amber-300 bg-amber-50 p-4 text-sm text-amber-900", children: [warning, " De beschikbare orders blijven zichtbaar."] })), error ? (_jsxs("div", { className: "rounded-md border border-destructive/30 bg-destructive/5 p-4 text-sm text-destructive", children: [error, _jsx(Button, { size: "sm", variant: "outline", className: "ml-3", onClick: () => refetch(), children: "Opnieuw proberen" })] })) : (_jsx(WeekAgendaView, { planned: planned, mode: "delivery", isLoading: isLoading, onWeekChange: setWeekStart, onDayClick: (d) => { setHighlightOrderId(null); setDayDetailDate(d); }, jumpToDate: linkDay ?? nearestDeliveryDate })), _jsx(DagDetailDialog, { open: !!dayDetailDate, date: dayDetailDate, planned: planned, basis: "lever", highlightOrderId: highlightOrderId, onOpenChange: (o) => !o && setDayDetailDate(null) })] }));
|
|
14
36
|
}
|
|
@@ -29,15 +29,18 @@ export function SignupMailMoments({ from, to, compact }) {
|
|
|
29
29
|
return null;
|
|
30
30
|
return (_jsxs("div", { className: "space-y-2 rounded-md border p-3", children: [_jsxs("div", { className: "flex items-center gap-2 text-sm font-medium", children: [_jsx(Mail, { className: "h-4 w-4 text-primary" }), " Aanmeldmail vervoerders"] }), !ov.enabled ? _jsx("p", { className: "text-xs text-muted-foreground", children: "De aanmeldmail staat uit." }) : null, reason && ov.enabled ? _jsx("p", { className: "text-xs text-destructive", children: reason }) : null, unassigned > 0 ? (_jsxs("p", { className: "text-xs text-destructive", children: [unassigned, " ", unassigned === 1 ? "order heeft" : "orders hebben", " geen vervoerder. Stel een standaardvervoerder in bij Vervoerders."] })) : null, _jsx("ul", { className: "space-y-1", children: ov.groups.map((g) => (_jsx(MomentRow, { g: g, tz: tz, compact: compact, enabled: ov.enabled, onPreview: () => setPreview(g) }, `${g.carrier_id}-${g.pickup_date}-${g.pickup_moment_key}`))) }), preview ? _jsx(PreviewDialog, { g: preview, onClose: () => setPreview(null) }) : null] }));
|
|
31
31
|
}
|
|
32
|
+
const kar = (n) => `${n} ${n === 1 ? "kar" : "karren"}`;
|
|
32
33
|
function statusLine(g, tz, enabled) {
|
|
33
34
|
const moment = compactMoment(g, tz);
|
|
34
35
|
if (g.last) {
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
if (g.last.fingerprint_match) {
|
|
37
|
+
return `${moment} — Al verstuurd om ${fmtTime(g.last.sent_at, tz)} naar ${g.carrier_name} · ${kar(g.last.cart_count)} — er is niets veranderd`;
|
|
38
|
+
}
|
|
39
|
+
return `${moment} — Aanmeldmail verstuurd om ${fmtTime(g.last.sent_at, tz)} naar ${g.carrier_name} · ${kar(g.last.cart_count)} · wijziging volgt: nu ${kar(g.cart_count)}`;
|
|
37
40
|
}
|
|
38
41
|
if (!enabled)
|
|
39
|
-
return `${moment} — ${g.carrier_name} · ${g.cart_count}
|
|
40
|
-
return `${moment} — Aanmeldmail volgt om ${fmtTime(g.send_at, tz)} naar ${g.carrier_name} · ${g.cart_count}
|
|
42
|
+
return `${moment} — ${g.carrier_name} · ${kar(g.cart_count)}`;
|
|
43
|
+
return `${moment} — Aanmeldmail volgt om ${fmtTime(g.send_at, tz)} naar ${g.carrier_name} · ${kar(g.cart_count)}`;
|
|
41
44
|
}
|
|
42
45
|
function compactMoment(g, tz) {
|
|
43
46
|
return `Ophalen ${fmtDayTime(g.pickup_at, tz)}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VervoerderForm.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/VervoerderForm.tsx"],"names":[],"mappings":"AA+CA,UAAU,KAAK;IACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;
|
|
1
|
+
{"version":3,"file":"VervoerderForm.d.ts","sourceRoot":"","sources":["../../../src/components/afhandeling/VervoerderForm.tsx"],"names":[],"mappings":"AA+CA,UAAU,KAAK;IACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAqQD,wBAAgB,cAAc,CAAC,EAAE,SAAS,EAAE,EAAE,KAAK,+BAiblD"}
|
|
@@ -18,7 +18,7 @@ const EMPTY = {
|
|
|
18
18
|
address: "",
|
|
19
19
|
notes: "",
|
|
20
20
|
is_default: false,
|
|
21
|
-
pickup_moments: [DEFAULT_PICKUP_MOMENT],
|
|
21
|
+
pickup_moments: [{ ...DEFAULT_PICKUP_MOMENT }],
|
|
22
22
|
service_countries: [],
|
|
23
23
|
service_provinces: [],
|
|
24
24
|
service_cities: [],
|
|
@@ -45,8 +45,8 @@ function CountryPicker({ value, onChange, excluded, }) {
|
|
|
45
45
|
setQuery("");
|
|
46
46
|
}, className: "flex items-center justify-between w-full px-3 py-2 text-sm text-left hover:bg-muted", children: [_jsx("span", { children: c.name }), _jsx("span", { className: "text-xs text-muted-foreground", children: c.code })] }, c.code)))) })] })] }));
|
|
47
47
|
}
|
|
48
|
-
function PickupMomentRow({ label, days, time, maxDays, onDaysChange, onTimeChange, }) {
|
|
49
|
-
return (_jsxs("div", { className: "grid grid-cols-[110px,1fr,1fr] items-center gap-3", children: [_jsx("div", { className: "text-sm font-medium", children: label }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs text-muted-foreground", children: "Werkdagen v\u00F3\u00F3r levering" }), _jsx(IconInput, { icon: Calendar, type: "number", min: 0, max: maxDays, value: days, onChange: (e) => onDaysChange(Number(e.target.value) || 0) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs text-muted-foreground", children: "Tijdstip" }), _jsx(IconInput, { icon: Clock, type: "time", value: time, onChange: (e) => onTimeChange(e.target.value) })] })] }));
|
|
48
|
+
function PickupMomentRow({ label, days, time, maxDays, onDaysChange, onTimeChange, showError, }) {
|
|
49
|
+
return (_jsxs("div", { className: "grid grid-cols-[110px,1fr,1fr] items-center gap-3", children: [_jsx("div", { className: "text-sm font-medium", children: label }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs text-muted-foreground", children: "Werkdagen v\u00F3\u00F3r levering" }), _jsx(IconInput, { icon: Calendar, type: "number", min: 0, max: maxDays, value: days, onChange: (e) => onDaysChange(Number(e.target.value) || 0) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs text-muted-foreground", children: "Tijdstip" }), _jsx(IconInput, { icon: Clock, type: "time", value: time, required: true, "aria-invalid": showError && !time ? true : undefined, onChange: (e) => onTimeChange(e.target.value) }), showError && !time ? _jsx("p", { className: "text-xs text-destructive", children: "Vul een tijd in." }) : null] })] }));
|
|
50
50
|
}
|
|
51
51
|
// Normaliseer een ophaalmoment: aanmelden moet altijd vóór (of op) ophalen
|
|
52
52
|
// liggen, ophalen vóór (of op) bezorgen. Werkdagen-waardes zijn afstanden tot
|
|
@@ -73,13 +73,13 @@ function normalizeMoment(next, prev) {
|
|
|
73
73
|
}
|
|
74
74
|
return m;
|
|
75
75
|
}
|
|
76
|
-
function PickupMomentEditor({ index, value, canDelete, onChange, onDelete, }) {
|
|
76
|
+
function PickupMomentEditor({ index, value, canDelete, onChange, onDelete, showErrors, }) {
|
|
77
77
|
const update = (patch) => {
|
|
78
78
|
const next = { ...value, ...patch };
|
|
79
79
|
onChange(normalizeMoment(next, value));
|
|
80
80
|
};
|
|
81
81
|
const pickupInvalid = value.pickup_days > value.signup_days;
|
|
82
|
-
return (_jsxs("div", { className: "rounded-md border bg-background p-4 space-y-3", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "text-sm font-semibold", children: ["Ophaalmoment ", index + 1] }), canDelete ? (_jsxs("button", { type: "button", onClick: onDelete, className: "text-xs text-muted-foreground hover:text-destructive inline-flex items-center gap-1", "aria-label": "Ophaalmoment verwijderen", children: [_jsx(Trash2, { className: "w-3.5 h-3.5" }), "Verwijderen"] })) : null] }), _jsxs("div", { className: "space-y-3", children: [_jsx(PickupMomentRow, { label: "Aanmelden", days: value.signup_days, time: value.signup_time, onDaysChange: (n) => update({ signup_days: n }), onTimeChange: (v) => update({ signup_time: v }) }), _jsx(PickupMomentRow, { label: "Ophalen", days: value.pickup_days, time: value.pickup_time, maxDays: value.signup_days, onDaysChange: (n) => update({ pickup_days: Math.min(n, value.signup_days) }), onTimeChange: (v) => update({ pickup_time: v }) }), pickupInvalid ? (_jsx("p", { className: "text-xs text-destructive -mt-1 pl-[122px]", children: "Ophalen kan niet v\u00F3\u00F3r aanmelden plaatsvinden." })) : null, _jsx(PickupMomentRow, { label: "Bezorgen", days: value.delivery_days, time: value.delivery_time, maxDays: value.pickup_days, onDaysChange: (n) => update({ delivery_days: Math.min(n, value.pickup_days) }), onTimeChange: (v) => update({ delivery_time: v }) })] })] }));
|
|
82
|
+
return (_jsxs("div", { className: "rounded-md border bg-background p-4 space-y-3", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "text-sm font-semibold", children: ["Ophaalmoment ", index + 1] }), canDelete ? (_jsxs("button", { type: "button", onClick: onDelete, className: "text-xs text-muted-foreground hover:text-destructive inline-flex items-center gap-1", "aria-label": "Ophaalmoment verwijderen", children: [_jsx(Trash2, { className: "w-3.5 h-3.5" }), "Verwijderen"] })) : null] }), _jsxs("div", { className: "space-y-3", children: [_jsx(PickupMomentRow, { label: "Aanmelden", days: value.signup_days, time: value.signup_time, onDaysChange: (n) => update({ signup_days: n }), onTimeChange: (v) => update({ signup_time: v }), showError: showErrors }), _jsx(PickupMomentRow, { label: "Ophalen", days: value.pickup_days, time: value.pickup_time, maxDays: value.signup_days, onDaysChange: (n) => update({ pickup_days: Math.min(n, value.signup_days) }), onTimeChange: (v) => update({ pickup_time: v }), showError: showErrors }), pickupInvalid ? (_jsx("p", { className: "text-xs text-destructive -mt-1 pl-[122px]", children: "Ophalen kan niet v\u00F3\u00F3r aanmelden plaatsvinden." })) : null, _jsx(PickupMomentRow, { label: "Bezorgen", days: value.delivery_days, time: value.delivery_time, maxDays: value.pickup_days, onDaysChange: (n) => update({ delivery_days: Math.min(n, value.pickup_days) }), onTimeChange: (v) => update({ delivery_time: v }), showError: showErrors })] })] }));
|
|
83
83
|
}
|
|
84
84
|
export function VervoerderForm({ carrierId }) {
|
|
85
85
|
const isEdit = !!carrierId;
|
|
@@ -89,6 +89,7 @@ export function VervoerderForm({ carrierId }) {
|
|
|
89
89
|
const saveCarrier = useServerFn(upsertCarrier);
|
|
90
90
|
const [form, setForm] = useState(EMPTY);
|
|
91
91
|
const [rates, setRates] = useState([]);
|
|
92
|
+
const [showTimeErrors, setShowTimeErrors] = useState(false);
|
|
92
93
|
const [pendingCountry, setPendingCountry] = useState("");
|
|
93
94
|
const [pendingPrice, setPendingPrice] = useState("");
|
|
94
95
|
const { data, isLoading } = useQuery({
|
|
@@ -110,7 +111,7 @@ export function VervoerderForm({ carrierId }) {
|
|
|
110
111
|
is_default: c.is_default ?? false,
|
|
111
112
|
pickup_moments: c.pickup_moments && c.pickup_moments.length > 0
|
|
112
113
|
? c.pickup_moments
|
|
113
|
-
: [DEFAULT_PICKUP_MOMENT],
|
|
114
|
+
: [{ ...DEFAULT_PICKUP_MOMENT }],
|
|
114
115
|
service_countries: c.service_countries ?? [],
|
|
115
116
|
service_provinces: c.service_provinces ?? [],
|
|
116
117
|
service_cities: c.service_cities ?? [],
|
|
@@ -173,6 +174,12 @@ export function VervoerderForm({ carrierId }) {
|
|
|
173
174
|
toast.error("Bedrijfsnaam is verplicht");
|
|
174
175
|
return;
|
|
175
176
|
}
|
|
177
|
+
// Tijden zijn verplicht: er wordt nooit stil een tijd ingevuld.
|
|
178
|
+
if (form.pickup_moments.some((m) => !m.signup_time || !m.pickup_time || !m.delivery_time)) {
|
|
179
|
+
setShowTimeErrors(true);
|
|
180
|
+
toast.error("Vul bij elk ophaalmoment alle tijden in.");
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
176
183
|
mutation.mutate();
|
|
177
184
|
};
|
|
178
185
|
if (isEdit && isLoading) {
|
|
@@ -180,7 +187,7 @@ export function VervoerderForm({ carrierId }) {
|
|
|
180
187
|
}
|
|
181
188
|
return (_jsxs("main", { className: "p-6 space-y-6 max-w-4xl", children: [_jsx(Button, { asChild: true, variant: "ghost", size: "sm", children: _jsxs(Link, { to: "/afhandeling/vervoerders", children: [_jsx(ArrowLeft, { className: "mr-2 h-4 w-4" }), "Terug naar vervoerders"] }) }), _jsxs("div", { className: "flex items-start gap-3", children: [_jsx(FieldIcon, { icon: Truck }), _jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-semibold", children: isEdit ? "Vervoerder bewerken" : "Vervoerder aanmaken" }), _jsx("p", { className: "text-sm text-muted-foreground", children: isEdit
|
|
182
189
|
? "Wijzig de gegevens van de vervoerder."
|
|
183
|
-
: "Voeg een nieuwe vervoerder toe en stel verzendtarieven in." })] })] }), _jsxs("form", { onSubmit: handleSubmit, className: "space-y-6", children: [_jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(CardTitle, { className: "text-base", children: "Algemene gegevens" }) }), _jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { children: ["Bedrijfsnaam ", _jsx("span", { className: "text-destructive", children: "*" })] }), _jsx(IconInput, { icon: Truck, value: form.name, onChange: (e) => setForm({ ...form, name: e.target.value }), placeholder: "Bijv. DHL Freight", required: true })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "Contactpersoon" }), _jsx(IconInput, { icon: User, value: form.contact_person ?? "", onChange: (e) => setForm({ ...form, contact_person: e.target.value }) })] }), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "E-mail" }), _jsx(IconInput, { icon: Mail, type: "email", value: form.email ?? "", onChange: (e) => setForm({ ...form, email: e.target.value }) })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "Telefoonnummer" }), _jsx(IconInput, { icon: Phone, value: form.phone ?? "", onChange: (e) => setForm({ ...form, phone: e.target.value }) })] })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "Adres" }), _jsx(IconInput, { icon: MapPin, value: form.address ?? "", onChange: (e) => setForm({ ...form, address: e.target.value }), placeholder: "Straat, postcode, plaats" })] }), _jsxs("div", { className: "rounded-md border bg-muted/30 p-4 space-y-4", children: [_jsxs("div", { children: [_jsx("div", { className: "text-sm font-medium", children: "Ophaalmomenten (transportplanning)" }), _jsxs("p", { className: "text-xs text-muted-foreground mt-1", children: ["De bezorgdag is ", _jsx("strong", { children: "dag 0" }), ". Per ophaalmoment stel je in op hoeveel werkdagen v\u00F3\u00F3r bezorging \u00E9n op welk tijdstip elke stap plaatsvindt. Bij een nieuwe order kiest het systeem automatisch het eerstvolgende moment waarvan de aanmelddeadline nog niet is verstreken."] })] }), _jsx("div", { className: "space-y-3", children: form.pickup_moments.map((moment, idx) => (_jsx(PickupMomentEditor, { index: idx, value: moment, canDelete: form.pickup_moments.length > 1, onChange: (next) => {
|
|
190
|
+
: "Voeg een nieuwe vervoerder toe en stel verzendtarieven in." })] })] }), _jsxs("form", { onSubmit: handleSubmit, className: "space-y-6", children: [_jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(CardTitle, { className: "text-base", children: "Algemene gegevens" }) }), _jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { children: ["Bedrijfsnaam ", _jsx("span", { className: "text-destructive", children: "*" })] }), _jsx(IconInput, { icon: Truck, value: form.name, onChange: (e) => setForm({ ...form, name: e.target.value }), placeholder: "Bijv. DHL Freight", required: true })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "Contactpersoon" }), _jsx(IconInput, { icon: User, value: form.contact_person ?? "", onChange: (e) => setForm({ ...form, contact_person: e.target.value }) })] }), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "E-mail" }), _jsx(IconInput, { icon: Mail, type: "email", value: form.email ?? "", onChange: (e) => setForm({ ...form, email: e.target.value }) })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "Telefoonnummer" }), _jsx(IconInput, { icon: Phone, value: form.phone ?? "", onChange: (e) => setForm({ ...form, phone: e.target.value }) })] })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "Adres" }), _jsx(IconInput, { icon: MapPin, value: form.address ?? "", onChange: (e) => setForm({ ...form, address: e.target.value }), placeholder: "Straat, postcode, plaats" })] }), _jsxs("div", { className: "rounded-md border bg-muted/30 p-4 space-y-4", children: [_jsxs("div", { children: [_jsx("div", { className: "text-sm font-medium", children: "Ophaalmomenten (transportplanning)" }), _jsxs("p", { className: "text-xs text-muted-foreground mt-1", children: ["De bezorgdag is ", _jsx("strong", { children: "dag 0" }), ". Per ophaalmoment stel je in op hoeveel werkdagen v\u00F3\u00F3r bezorging \u00E9n op welk tijdstip elke stap plaatsvindt. Bij een nieuwe order kiest het systeem automatisch het eerstvolgende moment waarvan de aanmelddeadline nog niet is verstreken."] })] }), _jsx("div", { className: "space-y-3", children: form.pickup_moments.map((moment, idx) => (_jsx(PickupMomentEditor, { showErrors: showTimeErrors, index: idx, value: moment, canDelete: form.pickup_moments.length > 1, onChange: (next) => {
|
|
184
191
|
const copy = [...form.pickup_moments];
|
|
185
192
|
copy[idx] = next;
|
|
186
193
|
setForm({ ...form, pickup_moments: copy });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AfhandelingSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/AfhandelingSettingsCard.tsx"],"names":[],"mappings":"AAuBA,wBAAgB,uBAAuB,
|
|
1
|
+
{"version":3,"file":"AfhandelingSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/AfhandelingSettingsCard.tsx"],"names":[],"mappings":"AAuBA,wBAAgB,uBAAuB,gCAiKtC"}
|
|
@@ -79,7 +79,7 @@ export function AfhandelingSettingsCard() {
|
|
|
79
79
|
toast.error(e instanceof Error ? e.message : "Opslaan mislukt");
|
|
80
80
|
},
|
|
81
81
|
});
|
|
82
|
-
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: "De pickplanning (pickdagen, picktijd en verdeling over de week) wordt volledig bepaald door de planning. Hieronder staan alleen de instellingen van deze module zelf." })] }), _jsxs(CardContent, { className: "space-y-5", children: [_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))) })] }),
|
|
82
|
+
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: "De pickplanning (pickdagen, picktijd en verdeling over de week) wordt volledig bepaald door de planning. Hieronder staan alleen de instellingen van deze module zelf." })] }), _jsxs(CardContent, { className: "space-y-5", children: [_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))) })] }), _jsx("div", { className: "space-y-1 text-sm", children: _jsxs("div", { children: [_jsx("strong", { children: "Verzendadres:" }), " ", cron.data?.senderEmail ? cron.data.senderEmail : _jsx("span", { className: "text-muted-foreground", children: "nog geen verbonden adres" }), " ", _jsx("span", { className: "text-xs text-muted-foreground", children: "(instellen bij E-mailkoppeling)" })] }) }), _jsxs("details", { className: "text-xs text-muted-foreground", children: [_jsx("summary", { className: "cursor-pointer", children: "Details voor beheer" }), _jsxs("div", { className: "mt-2 space-y-2", children: [_jsx(Label, { htmlFor: "mailPurpose", children: "Doeleinde in E-mailkoppeling" }), _jsx(Input, { id: "mailPurpose", value: mailPurpose, disabled: !mailEnabled, onChange: (e) => setMailPurpose(e.target.value) }), _jsxs("p", { children: ["Standaard: ", _jsx("code", { children: "afhandeling_carrier_signup" }), "."] })] })] })] }), _jsx(SignupStatusBlock, { status: cron.data ?? null, loading: cron.isLoading, failed: cron.isError }), _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" })] })] }));
|
|
83
83
|
}
|
|
84
84
|
function SignupStatusBlock({ status, loading, failed, }) {
|
|
85
85
|
if (loading)
|
|
@@ -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;AAK/D,OAAO,
|
|
1
|
+
{"version":3,"file":"useOrderPlanning.d.ts","sourceRoot":"","sources":["../../src/hooks/useOrderPlanning.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAK/D,OAAO,EAEL,KAAK,aAAa,EAEnB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAwC,KAAK,UAAU,EAAE,MAAM,+BAA+B,CAAC;AActG;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GACrB,SAAS,GACT,iBAAiB,GACjB,gBAAgB,GAChB,oBAAoB,CAAC;AAEzB,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,aAAa,CAAC;IACrB,6EAA6E;IAC7E,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IAC/B,qEAAqE;IACrE,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,gFAAgF;IAChF,cAAc,EAAE,OAAO,CAAC;IACxB,iDAAiD;IACjD,KAAK,EAAE,aAAa,CAAC;IACrB,uEAAuE;IACvE,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,iFAAiF;IACjF,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,6EAA6E;IAC7E,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,wEAAwE;IACxE,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,wDAAwD;IACxD,iBAAiB,EAAE,YAAY,EAAE,CAAC;IAClC,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mEAAmE;IACnE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAGD,MAAM,WAAW,uBAAuB;IACtC,8EAA8E;IAC9E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,EAAE,uBAAuB,GAAG,sBAAsB,CAkUxF"}
|
|
@@ -5,12 +5,14 @@ import { getFloridayOrders } from "../lib/floriday.functions";
|
|
|
5
5
|
import { listCarriers } from "../lib/carriers.functions";
|
|
6
6
|
import { safeServerCall } from "../lib/serverFnError";
|
|
7
7
|
import { normalizePickupMoments, sanitizeWeekdays, selectCarrierForTarget } from "../lib/carrierPlanning";
|
|
8
|
-
import { calculateOrderPlanning,
|
|
8
|
+
import { calculateOrderPlanning, } from "../lib/planning";
|
|
9
9
|
import { useEngineTasks } from "./useEngineTasks";
|
|
10
10
|
import { useCartIndex } from "./useCartIndex";
|
|
11
11
|
import { emitEngineEvent, listComposeTaskRefs } from "../lib/logisticsEngine/engine";
|
|
12
12
|
import { orderRefsFor } from "../lib/orderRefs";
|
|
13
13
|
import { isOpenOrderStatus } from "../lib/orderStatus";
|
|
14
|
+
import { loadPickWorkdays } from "../lib/pickWorkdays";
|
|
15
|
+
import { supabase as moduleSupabase } from "../integrations/supabase/moduleClient";
|
|
14
16
|
import { emitQueueStatus, markInFlight, markResult, resetEmitQueue, selectEmitBatch, } from "../lib/logisticsEngine/emitQueue";
|
|
15
17
|
export function useOrderPlanning(range) {
|
|
16
18
|
const from = range?.from ?? null;
|
|
@@ -57,6 +59,15 @@ export function useOrderPlanning(range) {
|
|
|
57
59
|
refetchIntervalInBackground: false,
|
|
58
60
|
refetchOnWindowFocus: true,
|
|
59
61
|
});
|
|
62
|
+
// Werkdagen komen uitsluitend uit de Werktijden; zonder die kalender plannen we niet.
|
|
63
|
+
const workdaysQuery = useQuery({
|
|
64
|
+
queryKey: ["afhandeling", "pick-workdays"],
|
|
65
|
+
queryFn: () => loadPickWorkdays(moduleSupabase),
|
|
66
|
+
retry: 1,
|
|
67
|
+
staleTime: 5 * 60000,
|
|
68
|
+
refetchInterval: 10 * 60000,
|
|
69
|
+
refetchIntervalInBackground: false,
|
|
70
|
+
});
|
|
60
71
|
const carriersQuery = useQuery({
|
|
61
72
|
queryKey: ["carriers"],
|
|
62
73
|
queryFn: () => safeServerCall(() => fetchCarriers(), { carriers: [] }, "listCarriers"),
|
|
@@ -122,7 +133,7 @@ export function useOrderPlanning(range) {
|
|
|
122
133
|
});
|
|
123
134
|
const moments = carrier
|
|
124
135
|
? normalizePickupMoments(carrier.pickup_moments)
|
|
125
|
-
: [
|
|
136
|
+
: [];
|
|
126
137
|
// Transport-/leverdata blijven uit de vervoerdersagenda komen; het
|
|
127
138
|
// pickmoment en de karindeling komen uitsluitend uit de Engine-taak.
|
|
128
139
|
const base = calculateOrderPlanning(order.deliveryDate, {
|
|
@@ -188,7 +199,8 @@ export function useOrderPlanning(range) {
|
|
|
188
199
|
};
|
|
189
200
|
return { order, planning, engineTask: task, awaitingEngine: false, state: "planned", hasComposeTask: true };
|
|
190
201
|
});
|
|
191
|
-
|
|
202
|
+
// workdaysQuery.data: herberekenen zodra de werkdagkalender (opnieuw) geladen is.
|
|
203
|
+
}, [orderList, carriersQuery.data, composeByRef, pickByRef, composeExists, cartsForOrder, workdaysQuery.data]);
|
|
192
204
|
// Alleen echt open orders mogen bij de Logistics Engine worden aangemeld;
|
|
193
205
|
// afgehandelde orders blijven wel zichtbaar maar krijgen geen melding meer.
|
|
194
206
|
const openPlanned = useMemo(() => planned.filter((p) => isOpenOrderStatus(p.order.status)), [planned]);
|
|
@@ -285,12 +297,15 @@ export function useOrderPlanning(range) {
|
|
|
285
297
|
tasksWithoutStart: openPlanned.filter((p) => p.state === "task_without_start"),
|
|
286
298
|
signalError,
|
|
287
299
|
lastEngineRun,
|
|
288
|
-
isLoading: ordersQuery.isLoading || carriersQuery.isLoading || tasksLoading,
|
|
300
|
+
isLoading: ordersQuery.isLoading || carriersQuery.isLoading || tasksLoading || workdaysQuery.isLoading,
|
|
289
301
|
error: ordersQuery.data?.orders?.length ? undefined : ordersQuery.data?.error,
|
|
290
|
-
warning:
|
|
302
|
+
warning: workdaysQuery.isError || (workdaysQuery.data && !workdaysQuery.data.available) || workdaysQuery.data?.count === 0
|
|
303
|
+
? "De werkdagen uit Werktijden zijn niet beschikbaar. Ophaal- en aanmelddagen worden pas getoond als de werkdagen zijn ingesteld."
|
|
304
|
+
: ordersQuery.data?.orders?.length ? ordersQuery.data?.error : undefined,
|
|
291
305
|
refetch: () => {
|
|
292
306
|
void ordersQuery.refetch();
|
|
293
307
|
void carriersQuery.refetch();
|
|
308
|
+
void workdaysQuery.refetch();
|
|
294
309
|
refetchTasks();
|
|
295
310
|
},
|
|
296
311
|
};
|