@flowselections/pick-schermen-kwekers 1.0.21 → 1.0.23
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/pick/PickScherm.d.ts.map +1 -1
- package/dist-lib/components/pick/PickScherm.js +56 -27
- package/dist-lib/hooks/usePickConfig.d.ts +11 -11
- package/dist-lib/hooks/usePickConfig.d.ts.map +1 -1
- package/dist-lib/hooks/usePickQueue.d.ts +5 -3
- package/dist-lib/hooks/usePickQueue.d.ts.map +1 -1
- package/dist-lib/hooks/usePickQueue.js +17 -4
- package/dist-lib/hooks/usePickReferenceData.d.ts +1 -1
- package/dist-lib/hooks/usePickReferenceData.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +4754 -230
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.d.ts +4754 -230
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.js +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +4754 -230
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.js +1 -1
- package/dist-lib/integrations/supabase/previewAuthStorage.d.ts +1 -1
- package/dist-lib/integrations/supabase/previewAuthStorage.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/previewAuthStorage.js +8 -1
- package/dist-lib/integrations/supabase/types.d.ts +4795 -203
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/__tests__/pickRobustness.test.d.ts +2 -0
- package/dist-lib/lib/__tests__/pickRobustness.test.d.ts.map +1 -0
- package/dist-lib/lib/__tests__/pickRobustness.test.js +68 -0
- package/dist-lib/lib/pickApi.d.ts +25 -1
- package/dist-lib/lib/pickApi.d.ts.map +1 -1
- package/dist-lib/lib/pickApi.js +56 -3
- package/dist-lib/lib/pickRetry.d.ts +13 -0
- package/dist-lib/lib/pickRetry.d.ts.map +1 -0
- package/dist-lib/lib/pickRetry.js +52 -0
- package/dist-lib/lib/pickUiText.d.ts.map +1 -1
- package/dist-lib/lib/pickUiText.js +5 -3
- package/dist-lib/lib/pickVerify.d.ts +15 -0
- package/dist-lib/lib/pickVerify.d.ts.map +1 -0
- package/dist-lib/lib/pickVerify.js +32 -0
- package/package.json +5 -4
- package/dist-lib/lib/layoutApi.d.ts +0 -23
- package/dist-lib/lib/layoutApi.d.ts.map +0 -1
- package/dist-lib/lib/layoutApi.js +0 -94
- package/dist-lib/lib/layoutMaker/documentProfiles.d.ts +0 -50
- package/dist-lib/lib/layoutMaker/documentProfiles.d.ts.map +0 -1
- package/dist-lib/lib/layoutMaker/documentProfiles.js +0 -458
- package/dist-lib/lib/layoutMaker/documentTypes.d.ts +0 -123
- package/dist-lib/lib/layoutMaker/documentTypes.d.ts.map +0 -1
- package/dist-lib/lib/layoutMaker/documentTypes.js +0 -74
- package/dist-lib/lib/layoutMaker/logoLibrary.d.ts +0 -13
- package/dist-lib/lib/layoutMaker/logoLibrary.d.ts.map +0 -1
- package/dist-lib/lib/layoutMaker/logoLibrary.js +0 -54
- package/dist-lib/lib/layoutMaker/pakbonBuilder.d.ts +0 -196
- package/dist-lib/lib/layoutMaker/pakbonBuilder.d.ts.map +0 -1
- package/dist-lib/lib/layoutMaker/pakbonBuilder.js +0 -813
- package/dist-lib/lib/layoutMaker/pakbonHtml.d.ts +0 -48
- package/dist-lib/lib/layoutMaker/pakbonHtml.d.ts.map +0 -1
- package/dist-lib/lib/layoutMaker/pakbonHtml.js +0 -703
- package/dist-lib/lib/layoutRenderer.d.ts +0 -7
- package/dist-lib/lib/layoutRenderer.d.ts.map +0 -1
- package/dist-lib/lib/layoutRenderer.js +0 -233
- package/dist-lib/lib/layoutTypes.d.ts +0 -84
- package/dist-lib/lib/layoutTypes.d.ts.map +0 -1
- package/dist-lib/lib/layoutTypes.js +0 -25
- package/dist-lib/lib/orderContext.d.ts +0 -50
- package/dist-lib/lib/orderContext.d.ts.map +0 -1
- package/dist-lib/lib/orderContext.js +0 -162
- package/dist-lib/lib/pakbonOrderInput.d.ts +0 -8
- package/dist-lib/lib/pakbonOrderInput.d.ts.map +0 -1
- package/dist-lib/lib/pakbonOrderInput.js +0 -150
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PickScherm.d.ts","sourceRoot":"","sources":["../../../src/components/pick/PickScherm.tsx"],"names":[],"mappings":"AAqCA,OAAO,EAUL,KAAK,WAAW,EACjB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"PickScherm.d.ts","sourceRoot":"","sources":["../../../src/components/pick/PickScherm.tsx"],"names":[],"mappings":"AAqCA,OAAO,EAUL,KAAK,WAAW,EACjB,MAAM,qBAAqB,CAAC;AA2B7B,UAAU,KAAK;IACb,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAeD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,KAAK,+BAotDpD"}
|
|
@@ -11,6 +11,7 @@ import { getSessionId, pickApi } from "../../lib/pickApi";
|
|
|
11
11
|
import { sendLogisticsEvent } from "../../lib/logisticsApi";
|
|
12
12
|
import { completeLogisticsTaskForItem } from "../../lib/pickPrint";
|
|
13
13
|
import { isPdfOnlyFailure, pickReadiness, printedCartIdsOf, pdfSaveWarning, unitRefOf, unitTitleOf, } from "../../lib/pickTypes";
|
|
14
|
+
import { rowFingerprint, rowsToVerify } from "../../lib/pickVerify";
|
|
14
15
|
import { getPickTranslator } from "../../lib/pickI18n";
|
|
15
16
|
import { friendlyPickError, getPickUiTexts } from "../../lib/pickUiText";
|
|
16
17
|
import { getPrintJobTexts, printJobStatusLabel } from "../../lib/pickPrintJobText";
|
|
@@ -139,12 +140,20 @@ export function PickScherm({ station, onBack }) {
|
|
|
139
140
|
return () => clearTimeout(timer);
|
|
140
141
|
}, [searchInput]);
|
|
141
142
|
const effectiveFilters = useMemo(() => ({ ...filters, country: null, sortRules: [] }), [filters]);
|
|
142
|
-
const { items, total, loading, lockedIds, refresh, pendingCount, printedCount, urgentCount, realtimeOk, pickDay, rebuiltAt, } = usePickQueue({
|
|
143
|
+
const { items, total, loading, lockedIds, refresh, pendingCount, printedCount, urgentCount, realtimeOk, pickDay, rebuiltAt, syncError, } = usePickQueue({
|
|
143
144
|
stationId: station.id,
|
|
144
145
|
filters: effectiveFilters,
|
|
145
146
|
enabled: lang !== null,
|
|
146
147
|
pickDayOverride: chosenDay,
|
|
147
148
|
});
|
|
149
|
+
// Eén toast per nieuwe syncfout; de rode balk blijft staan tot hij is opgelost.
|
|
150
|
+
const lastSyncError = useRef(null);
|
|
151
|
+
useEffect(() => {
|
|
152
|
+
if (syncError && syncError !== lastSyncError.current) {
|
|
153
|
+
toast.error(`Pickwachtrij kan niet worden bijgewerkt: ${syncError}`);
|
|
154
|
+
}
|
|
155
|
+
lastSyncError.current = syncError;
|
|
156
|
+
}, [syncError]);
|
|
148
157
|
const { data: pickDays } = usePickDays(lang !== null);
|
|
149
158
|
const safePickDays = Array.isArray(pickDays) ? pickDays : [];
|
|
150
159
|
const dayLabel = useCallback((day) => new Date(`${day}T00:00:00`).toLocaleDateString(t.lang === "en" ? "en-GB" : "nl-NL", {
|
|
@@ -252,37 +261,57 @@ export function PickScherm({ station, onBack }) {
|
|
|
252
261
|
const visibleIdsKey = useMemo(() => (Array.isArray(items) ? items.map((item) => item.id).join(",") : ""), [items]);
|
|
253
262
|
const itemsRef = useRef([]);
|
|
254
263
|
itemsRef.current = Array.isArray(items) ? items : [];
|
|
264
|
+
const verifyMemo = useRef(new Map());
|
|
255
265
|
useEffect(() => {
|
|
256
266
|
let cancelled = false;
|
|
267
|
+
let running = false;
|
|
257
268
|
const verifyVisibleRows = async () => {
|
|
269
|
+
if (running)
|
|
270
|
+
return;
|
|
258
271
|
const visibleItems = itemsRef.current;
|
|
259
|
-
|
|
260
|
-
if (
|
|
272
|
+
const todo = rowsToVerify(visibleItems, verifyMemo.current, Date.now());
|
|
273
|
+
if (todo.length === 0)
|
|
261
274
|
return;
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
275
|
+
// Laadbalk alleen voor regels die nog nooit gecontroleerd zijn.
|
|
276
|
+
const fresh = todo.filter((item) => !verifyMemo.current.has(item.id)).length;
|
|
277
|
+
if (fresh > 0)
|
|
278
|
+
setCheckProgress({ done: 0, total: fresh });
|
|
279
|
+
running = true;
|
|
280
|
+
const next = {};
|
|
281
|
+
try {
|
|
282
|
+
const results = await pickApi.verifyRows(todo.map((item) => ({ id: item.id, ref: unitRefOf(item) || null })));
|
|
283
|
+
const byId = new Map(results.map((r) => [r.id, r]));
|
|
284
|
+
const now = Date.now();
|
|
285
|
+
for (const item of todo) {
|
|
286
|
+
const r = byId.get(item.id);
|
|
287
|
+
let entry = {
|
|
288
|
+
checking: false,
|
|
289
|
+
ready: false,
|
|
290
|
+
reason: "De bron kon de pakbon nog niet bevestigen.",
|
|
291
|
+
};
|
|
292
|
+
if (r && !r.error) {
|
|
293
|
+
const state = pickReadiness(r.plan, r.status, item);
|
|
294
|
+
entry = { checking: false, ready: state.ready, reason: state.reason };
|
|
295
|
+
}
|
|
296
|
+
next[item.id] = entry;
|
|
297
|
+
verifyMemo.current.set(item.id, {
|
|
298
|
+
fingerprint: rowFingerprint(item),
|
|
299
|
+
ready: entry.ready,
|
|
300
|
+
checkedAt: now,
|
|
301
|
+
});
|
|
279
302
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
303
|
+
}
|
|
304
|
+
catch {
|
|
305
|
+
// fail closed: bestaande uitkomst blijft staan; nooit bevestigde regels blijven "Pakbon ophalen"
|
|
306
|
+
}
|
|
307
|
+
finally {
|
|
308
|
+
running = false;
|
|
309
|
+
}
|
|
310
|
+
if (cancelled)
|
|
311
|
+
return;
|
|
312
|
+
if (Object.keys(next).length > 0)
|
|
313
|
+
setReadinessById((prev) => ({ ...prev, ...next }));
|
|
314
|
+
setCheckProgress({ done: 0, total: 0 });
|
|
286
315
|
};
|
|
287
316
|
void verifyVisibleRows();
|
|
288
317
|
const timer = window.setInterval(() => void verifyVisibleRows(), 15000);
|
|
@@ -1001,7 +1030,7 @@ export function PickScherm({ station, onBack }) {
|
|
|
1001
1030
|
: Math.round((checkDone / checkTotal) * 100);
|
|
1002
1031
|
return (_jsxs("div", { className: "space-y-4 pb-24 md:pb-0", children: [busyLoading && (_jsxs("div", { className: "space-y-1", role: "status", "aria-live": "polite", "aria-label": "Gegevens worden geladen", children: [_jsxs("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: [_jsx("span", { children: loading || loadingDay
|
|
1003
1032
|
? "Wachtrij wordt geladen…"
|
|
1004
|
-
: `Pakbonnen controleren bij de bron (${checkDone} van ${checkTotal})` }), _jsxs("span", { className: "tabular-nums", children: [loadPercent, "%"] })] }), _jsx("div", { className: "h-1.5 w-full overflow-hidden rounded-full bg-muted", children: _jsx("div", { className: "h-full rounded-full bg-primary transition-all duration-300", style: { width: `${Math.max(5, loadPercent)}%` } }) })] })), _jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:flex-wrap md:items-center md:justify-between", children: [_jsxs("div", { className: "grid grid-cols-[auto_minmax(0,1fr)] items-center gap-3", children: [_jsxs(Button, { variant: "outline", size: "lg", className: "h-12 shrink-0 px-3 sm:px-4", onClick: () => setLang(null), "aria-label": t("changeLanguage"), children: [_jsx(Globe, { className: "h-5 w-5 sm:mr-2" }), _jsx("span", { className: "hidden sm:inline", children: t("changeLanguage") })] }), _jsxs("div", { className: "min-w-0", children: [_jsx("h2", { className: "truncate text-lg font-bold text-foreground sm:text-xl", children: station.name }), _jsxs("p", { className: "truncate text-sm text-muted-foreground", children: [pendingCount, " ", t("statusToPrint"), " \u00B7 ", printedCount, " ", t("statusPrinted")] })] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Button, { variant: "outline", size: "lg", className: "h-12 px-3", onClick: () => shiftDay(-1), disabled: loadingDay || !(chosenDay ?? pickDay), "aria-label": ui.pickDayPrev, children: [_jsx(ChevronLeft, { className: "h-5 w-5 sm:mr-1" }), _jsx("span", { className: "hidden sm:inline", children: ui.pickDayPrev })] }), _jsx("div", { className: "flex h-12 items-center rounded-md border bg-muted px-4 text-sm font-semibold text-foreground", children: chosenDay ? dayLabel(chosenDay) : ui.pickDayToday }), _jsxs(Button, { variant: "outline", size: "lg", className: "h-12 px-3", onClick: () => shiftDay(1), disabled: loadingDay || !(chosenDay ?? pickDay), "aria-label": ui.pickDayNext, children: [_jsx("span", { className: "hidden sm:inline", children: ui.pickDayNext }), _jsx(ChevronRight, { className: "h-5 w-5 sm:ml-1" })] }), chosenDay && (_jsx(Button, { variant: "secondary", size: "lg", className: "h-12 px-4", onClick: () => void chooseDay("current"), disabled: loadingDay, children: ui.pickDayBackToToday }))] }), _jsxs("div", { className: "flex items-center gap-2", children: [!online && (_jsxs(Badge, { className: "bg-destructive text-destructive-foreground", children: [_jsx(WifiOff, { className: "mr-1 h-3.5 w-3.5" }), " ", t("offline")] })), _jsx(Button, { variant: "outline", size: "icon", className: "h-12 w-12 shrink-0", onClick: refresh, "aria-label": t("refresh"), children: _jsx(RefreshCw, { className: "h-4 w-4" }) }), _jsxs(Button, { variant: "outline", size: "lg", className: "hidden h-14 px-5 md:inline-flex", disabled: fetchingNotes, onClick: () => void fetchShippingNotes(), children: [fetchingNotes ? (_jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" })) : (_jsx(FileDown, { className: "mr-2 h-5 w-5" })), fetchingNotes ? "Ophalen…" : "Verzendbrieven ophalen"] }), cartsPerPrint != null && (_jsxs(Button, { size: "lg", className: "hidden h-14 px-6 text-lg md:inline-flex", disabled: loading || batchPrinting || busyId != null, onClick: () => void printNextCarts(), children: [batchPrinting ? (_jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" })) : (_jsx(Printer, { className: "mr-2 h-5 w-5" })), "Print eerstvolgende ", cartsPerPrint, " karren"] })), _jsxs(Button, { size: "lg", className: "hidden h-14 px-8 text-lg md:inline-flex", onClick: () => (pending ? confirmPending() : fetchNext()), disabled: busyId !== null || fetchingData, children: [busyId !== null || fetchingData ? (_jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" })) : pending && !readiness.ready ? (_jsx(RefreshCw, { className: "mr-2 h-5 w-5" })) : (_jsx(Printer, { className: "mr-2 h-5 w-5" })), pending && !readiness.ready ? "Pakbon ophalen" : t("printNext"), pending?.document_number ? ` · ${pending.document_number}` : ""] })] })] }), !plekLoading && !printPlek && (_jsxs("div", { className: "flex items-start gap-2 rounded-md border-2 border-destructive/50 bg-destructive/5 p-3 text-sm text-destructive", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0" }), _jsx("span", { children: "Nog geen printplek gekoppeld \u2014 de opdracht blijft in de wachtrij staan." })] })), _jsx(ShippingNoteScan, { stationId: station.id }), !pending && emptyNotice && (_jsx("p", { className: "text-sm text-muted-foreground", children: emptyNotice })), pending && (_jsxs(Card, { className: "border-2 border-primary", children: [_jsxs(CardContent, { className: "flex flex-col gap-4 p-4 sm:flex-row sm:flex-wrap sm:items-center sm:justify-between sm:p-5", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("confirmPrintTitle") }), _jsx("p", { className: "truncate text-xl font-bold text-foreground sm:text-2xl", children: pending.document_number ?? t("document") }), _jsx("p", { className: "truncate text-sm text-muted-foreground", children: [pending.order_number, pending.customer_name].filter(Boolean).join(" · ") })] }), _jsxs("div", { className: "flex flex-col gap-2 sm:flex-row", children: [_jsx(Button, { variant: "outline", size: "lg", className: "h-12 w-full sm:w-auto", onClick: cancelPending, disabled: busyId !== null, children: t("cancel") }), _jsxs(Button, { size: "lg", className: "h-14 w-full px-8 text-lg sm:w-auto", onClick: confirmPending, disabled: busyId !== null || fetchingData, variant: readiness.ready ? "default" : "secondary", children: [busyId === "confirm" || fetchingData ? (_jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" })) : readiness.ready ? (_jsx(Printer, { className: "mr-2 h-5 w-5" })) : (_jsx(RefreshCw, { className: "mr-2 h-5 w-5" })), readiness.ready ? t("print") : "Pakbon ophalen"] })] })] }), !readiness.ready && (_jsx(CardContent, { className: "border-t p-4 sm:p-5", children: _jsxs("div", { className: "flex items-start gap-2 rounded-md border bg-muted/30 p-3 text-sm text-muted-foreground", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0" }), _jsx("span", { children: fetchingData
|
|
1033
|
+
: `Pakbonnen controleren bij de bron (${checkDone} van ${checkTotal})` }), _jsxs("span", { className: "tabular-nums", children: [loadPercent, "%"] })] }), _jsx("div", { className: "h-1.5 w-full overflow-hidden rounded-full bg-muted", children: _jsx("div", { className: "h-full rounded-full bg-primary transition-all duration-300", style: { width: `${Math.max(5, loadPercent)}%` } }) })] })), _jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:flex-wrap md:items-center md:justify-between", children: [_jsxs("div", { className: "grid grid-cols-[auto_minmax(0,1fr)] items-center gap-3", children: [_jsxs(Button, { variant: "outline", size: "lg", className: "h-12 shrink-0 px-3 sm:px-4", onClick: () => setLang(null), "aria-label": t("changeLanguage"), children: [_jsx(Globe, { className: "h-5 w-5 sm:mr-2" }), _jsx("span", { className: "hidden sm:inline", children: t("changeLanguage") })] }), _jsxs("div", { className: "min-w-0", children: [_jsx("h2", { className: "truncate text-lg font-bold text-foreground sm:text-xl", children: station.name }), _jsxs("p", { className: "truncate text-sm text-muted-foreground", children: [pendingCount, " ", t("statusToPrint"), " \u00B7 ", printedCount, " ", t("statusPrinted")] })] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Button, { variant: "outline", size: "lg", className: "h-12 px-3", onClick: () => shiftDay(-1), disabled: loadingDay || !(chosenDay ?? pickDay), "aria-label": ui.pickDayPrev, children: [_jsx(ChevronLeft, { className: "h-5 w-5 sm:mr-1" }), _jsx("span", { className: "hidden sm:inline", children: ui.pickDayPrev })] }), _jsx("div", { className: "flex h-12 items-center rounded-md border bg-muted px-4 text-sm font-semibold text-foreground", children: chosenDay ? dayLabel(chosenDay) : ui.pickDayToday }), _jsxs(Button, { variant: "outline", size: "lg", className: "h-12 px-3", onClick: () => shiftDay(1), disabled: loadingDay || !(chosenDay ?? pickDay), "aria-label": ui.pickDayNext, children: [_jsx("span", { className: "hidden sm:inline", children: ui.pickDayNext }), _jsx(ChevronRight, { className: "h-5 w-5 sm:ml-1" })] }), chosenDay && (_jsx(Button, { variant: "secondary", size: "lg", className: "h-12 px-4", onClick: () => void chooseDay("current"), disabled: loadingDay, children: ui.pickDayBackToToday }))] }), _jsxs("div", { className: "flex items-center gap-2", children: [!online && (_jsxs(Badge, { className: "bg-destructive text-destructive-foreground", children: [_jsx(WifiOff, { className: "mr-1 h-3.5 w-3.5" }), " ", t("offline")] })), _jsx(Button, { variant: "outline", size: "icon", className: "h-12 w-12 shrink-0", onClick: refresh, "aria-label": t("refresh"), children: _jsx(RefreshCw, { className: "h-4 w-4" }) }), _jsxs(Button, { variant: "outline", size: "lg", className: "hidden h-14 px-5 md:inline-flex", disabled: fetchingNotes, onClick: () => void fetchShippingNotes(), children: [fetchingNotes ? (_jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" })) : (_jsx(FileDown, { className: "mr-2 h-5 w-5" })), fetchingNotes ? "Ophalen…" : "Verzendbrieven ophalen"] }), cartsPerPrint != null && (_jsxs(Button, { size: "lg", className: "hidden h-14 px-6 text-lg md:inline-flex", disabled: loading || batchPrinting || busyId != null, onClick: () => void printNextCarts(), children: [batchPrinting ? (_jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" })) : (_jsx(Printer, { className: "mr-2 h-5 w-5" })), "Print eerstvolgende ", cartsPerPrint, " karren"] })), _jsxs(Button, { size: "lg", className: "hidden h-14 px-8 text-lg md:inline-flex", onClick: () => (pending ? confirmPending() : fetchNext()), disabled: busyId !== null || fetchingData, children: [busyId !== null || fetchingData ? (_jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" })) : pending && !readiness.ready ? (_jsx(RefreshCw, { className: "mr-2 h-5 w-5" })) : (_jsx(Printer, { className: "mr-2 h-5 w-5" })), pending && !readiness.ready ? "Pakbon ophalen" : t("printNext"), pending?.document_number ? ` · ${pending.document_number}` : ""] })] })] }), syncError && (_jsxs("div", { role: "alert", className: "flex items-start gap-2 rounded-md border-2 border-destructive/50 bg-destructive/5 p-3 text-sm text-destructive", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0" }), _jsxs("span", { children: ["Pickwachtrij kan niet worden bijgewerkt: ", syncError] })] })), !plekLoading && !printPlek && (_jsxs("div", { className: "flex items-start gap-2 rounded-md border-2 border-destructive/50 bg-destructive/5 p-3 text-sm text-destructive", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0" }), _jsx("span", { children: "Nog geen printplek gekoppeld \u2014 de opdracht blijft in de wachtrij staan." })] })), _jsx(ShippingNoteScan, { stationId: station.id }), !pending && emptyNotice && (_jsx("p", { className: "text-sm text-muted-foreground", children: emptyNotice })), pending && (_jsxs(Card, { className: "border-2 border-primary", children: [_jsxs(CardContent, { className: "flex flex-col gap-4 p-4 sm:flex-row sm:flex-wrap sm:items-center sm:justify-between sm:p-5", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("confirmPrintTitle") }), _jsx("p", { className: "truncate text-xl font-bold text-foreground sm:text-2xl", children: pending.document_number ?? t("document") }), _jsx("p", { className: "truncate text-sm text-muted-foreground", children: [pending.order_number, pending.customer_name].filter(Boolean).join(" · ") })] }), _jsxs("div", { className: "flex flex-col gap-2 sm:flex-row", children: [_jsx(Button, { variant: "outline", size: "lg", className: "h-12 w-full sm:w-auto", onClick: cancelPending, disabled: busyId !== null, children: t("cancel") }), _jsxs(Button, { size: "lg", className: "h-14 w-full px-8 text-lg sm:w-auto", onClick: confirmPending, disabled: busyId !== null || fetchingData, variant: readiness.ready ? "default" : "secondary", children: [busyId === "confirm" || fetchingData ? (_jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" })) : readiness.ready ? (_jsx(Printer, { className: "mr-2 h-5 w-5" })) : (_jsx(RefreshCw, { className: "mr-2 h-5 w-5" })), readiness.ready ? t("print") : "Pakbon ophalen"] })] })] }), !readiness.ready && (_jsx(CardContent, { className: "border-t p-4 sm:p-5", children: _jsxs("div", { className: "flex items-start gap-2 rounded-md border bg-muted/30 p-3 text-sm text-muted-foreground", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0" }), _jsx("span", { children: fetchingData
|
|
1005
1034
|
? "De pakbon wordt bij de bron opgevraagd. Zodra alles compleet is, verschijnt de printknop weer."
|
|
1006
1035
|
: planReason
|
|
1007
1036
|
? `${planReason} Klik op "Pakbon ophalen" om hem bij de bron op te vragen.`
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
export declare function usePickCountries(): import("@tanstack/react-query").UseQueryResult<
|
|
2
|
-
export declare function usePickStatuses(): import("@tanstack/react-query").UseQueryResult<
|
|
3
|
-
export declare function usePickPrinters(): import("@tanstack/react-query").UseQueryResult<
|
|
4
|
-
export declare function usePickDocumentTypes(): import("@tanstack/react-query").UseQueryResult<
|
|
5
|
-
export declare function usePickStationTypes(): import("@tanstack/react-query").UseQueryResult<
|
|
6
|
-
export declare function usePickTasks(): import("@tanstack/react-query").UseQueryResult<
|
|
7
|
-
export declare function usePickStations(): import("@tanstack/react-query").UseQueryResult<
|
|
1
|
+
export declare function usePickCountries(): import("@tanstack/react-query").UseQueryResult<import("..").PickCountry[], Error>;
|
|
2
|
+
export declare function usePickStatuses(): import("@tanstack/react-query").UseQueryResult<import("..").PickStatus[], Error>;
|
|
3
|
+
export declare function usePickPrinters(): import("@tanstack/react-query").UseQueryResult<import("..").PickPrinter[], Error>;
|
|
4
|
+
export declare function usePickDocumentTypes(): import("@tanstack/react-query").UseQueryResult<import("..").PickDocumentType[], Error>;
|
|
5
|
+
export declare function usePickStationTypes(): import("@tanstack/react-query").UseQueryResult<import("..").PickStationType[], Error>;
|
|
6
|
+
export declare function usePickTasks(): import("@tanstack/react-query").UseQueryResult<import("..").PickTask[], Error>;
|
|
7
|
+
export declare function usePickStations(): import("@tanstack/react-query").UseQueryResult<import("..").PickStation[], Error>;
|
|
8
8
|
/** Actieve printplekken uit de Layout maker. */
|
|
9
|
-
export declare function usePickPrintPlekken(): import("@tanstack/react-query").UseQueryResult<
|
|
9
|
+
export declare function usePickPrintPlekken(): import("@tanstack/react-query").UseQueryResult<import("..").PickPrintPlek[], Error>;
|
|
10
10
|
/** Koppelingen pickstation → printplek (beheerpagina). */
|
|
11
|
-
export declare function useStationPrintPlekken(): import("@tanstack/react-query").UseQueryResult<
|
|
11
|
+
export declare function useStationPrintPlekken(): import("@tanstack/react-query").UseQueryResult<import("..").PickStationPrintPlekRow[], Error>;
|
|
12
12
|
/** De printplek van één pickstation (ook in openbare pickschermen). */
|
|
13
|
-
export declare function useStationPrintPlek(stationId?: string): import("@tanstack/react-query").UseQueryResult<
|
|
14
|
-
export declare function usePickScreens(stationId?: string): import("@tanstack/react-query").UseQueryResult<
|
|
13
|
+
export declare function useStationPrintPlek(stationId?: string): import("@tanstack/react-query").UseQueryResult<import("..").PickStationPrintPlek | null, Error>;
|
|
14
|
+
export declare function usePickScreens(stationId?: string): import("@tanstack/react-query").UseQueryResult<import("..").PickScreen[], Error>;
|
|
15
15
|
//# sourceMappingURL=usePickConfig.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePickConfig.d.ts","sourceRoot":"","sources":["../../src/hooks/usePickConfig.ts"],"names":[],"mappings":"AAGA,wBAAgB,gBAAgB
|
|
1
|
+
{"version":3,"file":"usePickConfig.d.ts","sourceRoot":"","sources":["../../src/hooks/usePickConfig.ts"],"names":[],"mappings":"AAGA,wBAAgB,gBAAgB,sFAE/B;AACD,wBAAgB,eAAe,qFAE9B;AACD,wBAAgB,eAAe,sFAE9B;AACD,wBAAgB,oBAAoB,2FAEnC;AACD,wBAAgB,mBAAmB,0FAElC;AACD,wBAAgB,YAAY,mFAE3B;AACD,wBAAgB,eAAe,sFAE9B;AACD,gDAAgD;AAChD,wBAAgB,mBAAmB,wFAElC;AACD,0DAA0D;AAC1D,wBAAgB,sBAAsB,kGAKrC;AACD,uEAAuE;AACvE,wBAAgB,mBAAmB,CAAC,SAAS,CAAC,EAAE,MAAM,mGAMrD;AAED,wBAAgB,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,oFAKhD"}
|
|
@@ -33,6 +33,8 @@ export declare function usePickQueue(args: {
|
|
|
33
33
|
error: string | null;
|
|
34
34
|
lockedIds: Set<string>;
|
|
35
35
|
realtimeOk: boolean;
|
|
36
|
+
/** Letterlijke fout uit de wachtrij-synchronisatie, of null. */
|
|
37
|
+
syncError: string | null;
|
|
36
38
|
/** Tijdstip van de laatste heropbouw na een buffer-seintje van de Engine. */
|
|
37
39
|
rebuiltAt: number | null;
|
|
38
40
|
refresh: () => void;
|
|
@@ -44,10 +46,10 @@ export declare function usePickHeartbeat(stationId?: string, screenId?: string |
|
|
|
44
46
|
export declare function usePickCountryCounts(args: {
|
|
45
47
|
stationId?: string;
|
|
46
48
|
screenId?: string;
|
|
47
|
-
}): import("@tanstack/react-query").UseQueryResult<
|
|
49
|
+
}): import("@tanstack/react-query").UseQueryResult<Record<string, number>, Error>;
|
|
48
50
|
/** Pickdagen waarop nog orders klaarstaan (vandaag en later). */
|
|
49
|
-
export declare function usePickDays(enabled?: boolean): import("@tanstack/react-query").UseQueryResult<
|
|
51
|
+
export declare function usePickDays(enabled?: boolean): import("@tanstack/react-query").UseQueryResult<{
|
|
50
52
|
day: string;
|
|
51
53
|
orders: number;
|
|
52
|
-
}[]
|
|
54
|
+
}[], Error>;
|
|
53
55
|
//# sourceMappingURL=usePickQueue.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePickQueue.d.ts","sourceRoot":"","sources":["../../src/hooks/usePickQueue.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAY,aAAa,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAG9E,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,mDAAmD;IACnD,WAAW,EAAE,OAAO,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,YAAY,EAAE,CAAC;CAC3B;AAED,eAAO,MAAM,cAAc,EAAE,YAS5B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2EAA2E;IAC3E,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"usePickQueue.d.ts","sourceRoot":"","sources":["../../src/hooks/usePickQueue.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAY,aAAa,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAG9E,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,mDAAmD;IACnD,WAAW,EAAE,OAAO,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,YAAY,EAAE,CAAC;CAC3B;AAED,eAAO,MAAM,cAAc,EAAE,YAS5B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2EAA2E;IAC3E,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;;;;;;;;;;;IA0LG,gEAAgE;;IAEhE,6EAA6E;;;EAIhF;AAED,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,SAAS,CAAC,EAAE,MAAM;;EAuBhG;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,iFAOnF;AACD,iEAAiE;AACjE,wBAAgB,WAAW,CAAC,OAAO,UAAO;;;YAQzC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
2
|
-
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
2
|
+
import { keepPreviousData, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
3
3
|
import { pickApi, pickDb } from "../lib/pickApi";
|
|
4
4
|
import { safeArray } from "../lib/pickTypes";
|
|
5
5
|
export const defaultFilters = {
|
|
@@ -24,7 +24,15 @@ export function usePickQueue(args) {
|
|
|
24
24
|
queryKey: ["pick", "sync"],
|
|
25
25
|
enabled,
|
|
26
26
|
queryFn: async () => {
|
|
27
|
-
|
|
27
|
+
// Syncfout wordt als waarde teruggegeven zodat de wachtrij blijft laden
|
|
28
|
+
// maar de fout zichtbaar in beeld komt.
|
|
29
|
+
let syncError = null;
|
|
30
|
+
try {
|
|
31
|
+
await pickApi.syncQueue();
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
syncError = e instanceof Error ? e.message : String(e);
|
|
35
|
+
}
|
|
28
36
|
// Bewaking: orders zonder karplan meteen bij de Engine melden. Mislukt
|
|
29
37
|
// dit, dan mag de wachtrij daar niet op stuklopen.
|
|
30
38
|
try {
|
|
@@ -33,7 +41,7 @@ export function usePickQueue(args) {
|
|
|
33
41
|
catch {
|
|
34
42
|
/* bewaking is aanvullend, nooit blokkerend */
|
|
35
43
|
}
|
|
36
|
-
return Date.now();
|
|
44
|
+
return { at: Date.now(), syncError };
|
|
37
45
|
},
|
|
38
46
|
staleTime: 60000,
|
|
39
47
|
refetchInterval: 60000,
|
|
@@ -75,7 +83,8 @@ export function usePickQueue(args) {
|
|
|
75
83
|
useEffect(() => {
|
|
76
84
|
if (rebuildCount <= 0)
|
|
77
85
|
return;
|
|
78
|
-
|
|
86
|
+
// Verouderd markeren en vers ophalen; de oude lijst blijft staan tot de nieuwe binnen is.
|
|
87
|
+
queryClient.invalidateQueries({ queryKey: ["pick", "queue"], refetchType: "all" });
|
|
79
88
|
queryClient.invalidateQueries({ queryKey: ["pick", "pickDay"] });
|
|
80
89
|
queryClient.invalidateQueries({ queryKey: ["pick", "pickDays"] });
|
|
81
90
|
queryClient.invalidateQueries({ queryKey: ["pick", "dayCounts"] });
|
|
@@ -99,11 +108,13 @@ export function usePickQueue(args) {
|
|
|
99
108
|
page: filters.page,
|
|
100
109
|
pageSize: filters.pageSize,
|
|
101
110
|
}),
|
|
111
|
+
placeholderData: keepPreviousData,
|
|
102
112
|
});
|
|
103
113
|
const countsQuery = useQuery({
|
|
104
114
|
queryKey: ["pick", "dayCounts", stationId ?? "-", screenId ?? "-", pickDay ?? "-"],
|
|
105
115
|
enabled: enabled && !pickDayQuery.isLoading,
|
|
106
116
|
queryFn: () => pickApi.dayCounts({ stationId, screenId, pickDay }),
|
|
117
|
+
placeholderData: keepPreviousData,
|
|
107
118
|
});
|
|
108
119
|
// Locks komen primair via realtime binnen; deze poll is alleen terugval.
|
|
109
120
|
const locksQuery = useQuery({
|
|
@@ -170,6 +181,8 @@ export function usePickQueue(args) {
|
|
|
170
181
|
error: queueQuery.error instanceof Error ? queueQuery.error.message : null,
|
|
171
182
|
lockedIds,
|
|
172
183
|
realtimeOk,
|
|
184
|
+
/** Letterlijke fout uit de wachtrij-synchronisatie, of null. */
|
|
185
|
+
syncError: syncQuery.data?.syncError ?? null,
|
|
173
186
|
/** Tijdstip van de laatste heropbouw na een buffer-seintje van de Engine. */
|
|
174
187
|
rebuiltAt,
|
|
175
188
|
refresh: invalidateNow,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export declare const PICK_REFERENCE_QUERY_KEY: readonly ["pick", "referenceData"];
|
|
2
2
|
/** Eén bron voor de instellingenkaart en de waarschuwingsbanner. */
|
|
3
|
-
export declare function usePickReferenceData(): import("@tanstack/react-query").UseQueryResult<
|
|
3
|
+
export declare function usePickReferenceData(): import("@tanstack/react-query").UseQueryResult<import("..").PickReferenceStatus, Error>;
|
|
4
4
|
//# sourceMappingURL=usePickReferenceData.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePickReferenceData.d.ts","sourceRoot":"","sources":["../../src/hooks/usePickReferenceData.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,wBAAwB,oCAAqC,CAAC;AAE3E,oEAAoE;AACpE,wBAAgB,oBAAoB,
|
|
1
|
+
{"version":3,"file":"usePickReferenceData.d.ts","sourceRoot":"","sources":["../../src/hooks/usePickReferenceData.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,wBAAwB,oCAAqC,CAAC;AAE3E,oEAAoE;AACpE,wBAAgB,oBAAoB,4FAKnC"}
|