@flowselections/pick-schermen-kwekers 1.0.62 → 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/pick/PickScherm.d.ts.map +1 -1
- package/dist-lib/components/pick/PickScherm.js +22 -7
- package/dist-lib/components/pick/QueueTable.d.ts +5 -1
- package/dist-lib/components/pick/QueueTable.d.ts.map +1 -1
- package/dist-lib/components/pick/QueueTable.js +14 -31
- package/dist-lib/components/pick/StickerReprintButton.d.ts.map +1 -1
- package/dist-lib/components/pick/StickerReprintButton.js +2 -1
- package/dist-lib/components/pick/StickerState.d.ts.map +1 -1
- package/dist-lib/components/pick/StickerState.js +7 -5
- package/dist-lib/hooks/useCartStickerStates.d.ts +8 -0
- package/dist-lib/hooks/useCartStickerStates.d.ts.map +1 -0
- package/dist-lib/hooks/useCartStickerStates.js +41 -0
- package/dist-lib/hooks/usePickPrintStatus.d.ts +14 -0
- package/dist-lib/hooks/usePickPrintStatus.d.ts.map +1 -0
- package/dist-lib/hooks/usePickPrintStatus.js +47 -0
- package/dist-lib/hooks/usePickQueue.d.ts +2 -0
- package/dist-lib/hooks/usePickQueue.d.ts.map +1 -1
- package/dist-lib/hooks/usePickQueue.js +29 -8
- package/dist-lib/integrations/supabase/types.d.ts +585 -2
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.js +1 -0
- package/dist-lib/lib/__tests__/pick143.test.js +1 -1
- package/dist-lib/lib/__tests__/pick163.test.d.ts +2 -0
- package/dist-lib/lib/__tests__/pick163.test.d.ts.map +1 -0
- package/dist-lib/lib/__tests__/pick163.test.js +68 -0
- package/dist-lib/lib/__tests__/pickStickerBundle.test.d.ts +2 -0
- package/dist-lib/lib/__tests__/pickStickerBundle.test.d.ts.map +1 -0
- package/dist-lib/lib/__tests__/pickStickerBundle.test.js +27 -0
- package/dist-lib/lib/pick143.d.ts +7 -2
- package/dist-lib/lib/pick143.d.ts.map +1 -1
- package/dist-lib/lib/pick143.js +24 -5
- package/dist-lib/lib/pick159.js +1 -1
- package/dist-lib/lib/pickPerf.d.ts +11 -0
- package/dist-lib/lib/pickPerf.d.ts.map +1 -0
- package/dist-lib/lib/pickPerf.js +35 -0
- package/dist-lib/lib/pickPrintStatus.d.ts +36 -0
- package/dist-lib/lib/pickPrintStatus.d.ts.map +1 -0
- package/dist-lib/lib/pickPrintStatus.js +98 -0
- package/dist-lib/lib/pickRowState.d.ts +2 -1
- package/dist-lib/lib/pickRowState.d.ts.map +1 -1
- package/dist-lib/lib/pickRowState.js +4 -2
- package/dist-lib/lib/pickStickerBundle.d.ts +16 -0
- package/dist-lib/lib/pickStickerBundle.d.ts.map +1 -0
- package/dist-lib/lib/pickStickerBundle.js +36 -0
- package/package.json +7 -2
- package/schema/pickschermen.sql +5315 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PickScherm.d.ts","sourceRoot":"","sources":["../../../src/components/pick/PickScherm.tsx"],"names":[],"mappings":"AA0DA,OAAO,EAaL,KAAK,WAAW,EACjB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"PickScherm.d.ts","sourceRoot":"","sources":["../../../src/components/pick/PickScherm.tsx"],"names":[],"mappings":"AA0DA,OAAO,EAaL,KAAK,WAAW,EACjB,MAAM,qBAAqB,CAAC;AA8D7B,UAAU,KAAK;IACb,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAwBD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,KAAK,+BAgsEpD"}
|
|
@@ -21,6 +21,9 @@ import { getPickTranslator } from "../../lib/pickI18n.js";
|
|
|
21
21
|
import { friendlyPickError, getPickUiTexts } from "../../lib/pickUiText.js";
|
|
22
22
|
import { getPrintJobTexts } from "../../lib/pickPrintJobText.js";
|
|
23
23
|
import { defaultFilters, usePickDays, usePickHeartbeat, usePickQueue, } from "../../hooks/usePickQueue.js";
|
|
24
|
+
import { usePickPrintStatus } from "../../hooks/usePickPrintStatus.js";
|
|
25
|
+
import { useCartStickerStates } from "../../hooks/useCartStickerStates.js";
|
|
26
|
+
import { activeDeviceKey } from "../../lib/pick159.js";
|
|
24
27
|
import { usePickDocumentTypes, usePickStatuses, useStationPrintPlek, } from "../../hooks/usePickConfig.js";
|
|
25
28
|
import { usePrintBatch, usePrintJob } from "../../hooks/usePrintJob.js";
|
|
26
29
|
import { useShippingNoteStatus } from "../../hooks/useShippingNoteStatus.js";
|
|
@@ -219,12 +222,20 @@ export function PickScherm({ station, onBack }) {
|
|
|
219
222
|
return () => clearTimeout(timer);
|
|
220
223
|
}, [searchInput]);
|
|
221
224
|
const effectiveFilters = useMemo(() => ({ ...filters, country: null, sortRules: [] }), [filters]);
|
|
222
|
-
const { items, total, loading, lockedIds, refresh, pendingCount, printedCount, urgentCount, realtimeOk, pickDay, rebuiltAt, syncError, } = usePickQueue({
|
|
225
|
+
const { items, total, loading, lockedIds, refresh, pendingCount, printedCount, countsLoading, urgentCount, realtimeOk, pickDay, rebuiltAt, syncError, } = usePickQueue({
|
|
223
226
|
stationId: station.id,
|
|
224
227
|
filters: effectiveFilters,
|
|
225
228
|
enabled: lang !== null,
|
|
226
229
|
pickDayOverride: chosenDay,
|
|
227
230
|
});
|
|
231
|
+
// 1.0.63: printstatus uit de Engine, één aanroep voor alle regels in beeld.
|
|
232
|
+
const printStatusIds = useMemo(() => (Array.isArray(items) ? items : []).map((i) => i.id), [items]);
|
|
233
|
+
const { result: printStatus, loading: printStatusLoading, inPrint, } = usePickPrintStatus(printStatusIds, activeDeviceKey() ? station.slug ?? null : null, lang !== null);
|
|
234
|
+
const inPrintRef = useRef(inPrint);
|
|
235
|
+
inPrintRef.current = inPrint;
|
|
236
|
+
// 1.0.65: stickerstand van alle karren van de order in één aanroep (openbaar station).
|
|
237
|
+
const stickerCartIds = useMemo(() => (Array.isArray(cartPlan?.carts) ? cartPlan.carts.map((c) => c.cartId).filter((x) => !!x) : []), [cartPlan]);
|
|
238
|
+
useCartStickerStates(stickerCartIds, station.slug ?? null);
|
|
228
239
|
/** Geprint maar nog niet gescand, van een eerdere pickdag (blijft open tot de scan). */
|
|
229
240
|
const viewDay = chosenDay ?? pickDay ?? null;
|
|
230
241
|
const { data: earlierRaw, refetch: refetchEarlier } = useQuery({
|
|
@@ -667,6 +678,10 @@ export function PickScherm({ station, onBack }) {
|
|
|
667
678
|
toast.warning(block);
|
|
668
679
|
return;
|
|
669
680
|
}
|
|
681
|
+
if (inPrintRef.current.has(item.id)) {
|
|
682
|
+
toast.info("Deze pakbon wordt al geprint. Wacht tot de printer klaar is.");
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
670
685
|
setBusyId(item.id);
|
|
671
686
|
try {
|
|
672
687
|
const claimed = await pickApi.claim({
|
|
@@ -918,7 +933,7 @@ export function PickScherm({ station, onBack }) {
|
|
|
918
933
|
return;
|
|
919
934
|
setBatchPrinting(true);
|
|
920
935
|
try {
|
|
921
|
-
const visible = (Array.isArray(items) ? items : []).filter((item) => !item.printed_at);
|
|
936
|
+
const visible = (Array.isArray(items) ? items : []).filter((item) => !item.printed_at && !inPrintRef.current.has(item.id));
|
|
922
937
|
const targets = [];
|
|
923
938
|
const skipped = [];
|
|
924
939
|
for (const item of visible) {
|
|
@@ -972,7 +987,7 @@ export function PickScherm({ station, onBack }) {
|
|
|
972
987
|
setBusyId("next");
|
|
973
988
|
let claimed = null;
|
|
974
989
|
try {
|
|
975
|
-
const target = firstVisibleTarget(itemsRef.current, lockedIds);
|
|
990
|
+
const target = firstVisibleTarget(itemsRef.current, lockedIds, inPrintRef.current);
|
|
976
991
|
const filtered = !!filters.search.trim() || !!filters.documentTypeId || filters.urgentOnly || !!filters.country;
|
|
977
992
|
if (target) {
|
|
978
993
|
// De rij die in beeld staat (ook met zoekfilter), niet de bovenste van de hele wachtrij.
|
|
@@ -1366,7 +1381,7 @@ export function PickScherm({ station, onBack }) {
|
|
|
1366
1381
|
? "Pickwachtrij laden…"
|
|
1367
1382
|
: checkDone > 0
|
|
1368
1383
|
? `Pakbonnen controleren (${checkDone} van ${checkTotal})…`
|
|
1369
|
-
: `Pakbonnen controleren (${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"), openJobIds.length > 0 ? ` · ${openJobIds.length} wacht op printer` : ""] })] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Button, { variant: "outline", size: "lg", className: "h-12 px-3", onClick: () => void 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: () => void 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 || actionBusy), 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" })), "Volgende printen (", cartsPerPrint, " karren)"] })), _jsxs(Button, { size: "lg", className: "hidden h-14 px-8 text-lg md:inline-flex", onClick: () => (pending ? confirmPending() : fetchNextLocked()), disabled: (busyId !== null || actionBusy) || fetchingData, children: [(busyId !== null || actionBusy) || 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")] })] })] }), 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: [SYNC_ERROR_MESSAGE, _jsxs("details", { className: "mt-1 text-xs text-muted-foreground", children: [_jsx("summary", { children: "Details voor beheer" }), 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." })] })), (cartMissing || rowGone) && (_jsxs("div", { role: "alert", className: "flex flex-col gap-2 rounded-md border-2 border-destructive/50 bg-destructive/5 p-3 text-sm text-destructive sm:flex-row sm:items-center sm:justify-between", children: [_jsxs("span", { className: "flex items-start gap-2", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0" }), rowGone ? ROW_GONE_MESSAGE : CART_MISSING_MESSAGE] }), _jsx(Button, { variant: "outline", size: "sm", onClick: () => {
|
|
1384
|
+
: `Pakbonnen controleren (${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: [countsLoading ? "…" : pendingCount, " ", t("statusToPrint"), " \u00B7 ", countsLoading ? "…" : printedCount, " ", t("statusPrinted"), openJobIds.length > 0 ? ` · ${openJobIds.length} wacht op printer` : ""] })] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Button, { variant: "outline", size: "lg", className: "h-12 px-3", onClick: () => void 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: () => void 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 || printStatusLoading || batchPrinting || (busyId != null || actionBusy), 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" })), "Volgende printen (", cartsPerPrint, " karren)"] })), _jsxs(Button, { size: "lg", className: "hidden h-14 px-8 text-lg md:inline-flex", onClick: () => (pending ? confirmPending() : fetchNextLocked()), disabled: (busyId !== null || actionBusy) || fetchingData || (!pending && printStatusLoading), children: [(busyId !== null || actionBusy) || 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")] })] })] }), 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: [SYNC_ERROR_MESSAGE, _jsxs("details", { className: "mt-1 text-xs text-muted-foreground", children: [_jsx("summary", { children: "Details voor beheer" }), 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." })] })), (cartMissing || rowGone) && (_jsxs("div", { role: "alert", className: "flex flex-col gap-2 rounded-md border-2 border-destructive/50 bg-destructive/5 p-3 text-sm text-destructive sm:flex-row sm:items-center sm:justify-between", children: [_jsxs("span", { className: "flex items-start gap-2", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0" }), rowGone ? ROW_GONE_MESSAGE : CART_MISSING_MESSAGE] }), _jsx(Button, { variant: "outline", size: "sm", onClick: () => {
|
|
1370
1385
|
setCartMissing(false);
|
|
1371
1386
|
setRowGone(false);
|
|
1372
1387
|
setPending(null);
|
|
@@ -1378,7 +1393,7 @@ export function PickScherm({ station, onBack }) {
|
|
|
1378
1393
|
const cart = plannedCart ?? { cartId: r.cartId, cartLabel: r.cartLabel ?? r.cartId };
|
|
1379
1394
|
setLastCartResults((prev) => prev.filter((x) => x.cartId !== r.cartId));
|
|
1380
1395
|
void reprintCart(lastPrinted, cart);
|
|
1381
|
-
}, children: "Opnieuw printen" })] }, r.cartId))) }) })), lastCartResults.length > 1 && (_jsxs("div", { className: "rounded-md border p-3 text-sm", "aria-label": "Resultaat per kar", children: [_jsx("p", { className: "mb-1 font-semibold text-foreground", children: "Resultaat per kar" }), _jsx("ul", { className: "space-y-0.5 text-muted-foreground", children: lastCartResults.map((r) => (_jsx("li", { className: r.outcome === "created" ? "text-foreground" : r.outcome === "error" ? "text-destructive" : "", children: cartResultLine(r) }, r.cartId))) })] })), _jsx(VroegeStickerWaarschuwing, { stationId: station.id }), _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 || actionBusy), children: t("cancel") }), _jsxs(Button, { size: "lg", className: "h-14 w-full px-8 text-lg sm:w-auto", onClick: confirmPending, disabled: (busyId !== null || actionBusy) || 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
|
|
1396
|
+
}, children: "Opnieuw printen" })] }, r.cartId))) }) })), lastCartResults.length > 1 && (_jsxs("div", { className: "rounded-md border p-3 text-sm", "aria-label": "Resultaat per kar", children: [_jsx("p", { className: "mb-1 font-semibold text-foreground", children: "Resultaat per kar" }), _jsx("ul", { className: "space-y-0.5 text-muted-foreground", children: lastCartResults.map((r) => (_jsx("li", { className: r.outcome === "created" ? "text-foreground" : r.outcome === "error" ? "text-destructive" : "", children: cartResultLine(r) }, r.cartId))) })] })), _jsx(VroegeStickerWaarschuwing, { stationId: station.id }), _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 || actionBusy), children: t("cancel") }), _jsxs(Button, { size: "lg", className: "h-14 w-full px-8 text-lg sm:w-auto", onClick: confirmPending, disabled: (busyId !== null || actionBusy) || fetchingData || (!pending && printStatusLoading), 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
|
|
1382
1397
|
? "De pakbon wordt opgevraagd. Zodra alles compleet is, verschijnt de printknop weer."
|
|
1383
1398
|
: planReason
|
|
1384
1399
|
? `${planReason} Klik op "Pakbon ophalen" om hem op te vragen.`
|
|
@@ -1434,8 +1449,8 @@ export function PickScherm({ station, onBack }) {
|
|
|
1434
1449
|
(message ?? "Verzendbriefstatus wordt opgehaald.") }), waiting && (note.state.attempts !== null || note.state.nextAttemptAt) && (_jsxs("p", { className: "text-xs text-muted-foreground", children: [note.state.attempts !== null ? `Pogingen: ${note.state.attempts}` : "", note.state.attempts !== null && note.state.nextAttemptAt ? " · " : "", note.state.nextAttemptAt
|
|
1435
1450
|
? `Volgende poging: ${formatSiteTime(note.state.nextAttemptAt, siteTz)}`
|
|
1436
1451
|
: ""] }))] })] }, note.jobId));
|
|
1437
|
-
})] }) })), _jsxs(Button, { variant: "outline", size: "lg", className: "h-12 w-full sm:hidden", "aria-expanded": filtersOpen, onClick: () => setFiltersOpen((v) => !v), children: [_jsx(Search, { className: "mr-2 h-4 w-4" }), " ", ui.filters] }), _jsx(Card, { className: filtersOpen ? "" : "hidden sm:block", children: _jsxs(CardContent, { className: "flex flex-wrap items-center gap-3 p-3 sm:p-4", children: [_jsxs("div", { className: "relative w-full min-w-0 flex-1 sm:min-w-64", children: [_jsx(Search, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { className: "h-12 pl-9 text-base", placeholder: t("search"), value: searchInput, onChange: (e) => setSearchInput(e.target.value) })] }), _jsxs(Select, { value: chosenDay ?? "current", onValueChange: (v) => void chooseDay(v), children: [_jsx(SelectTrigger, { className: "h-12 w-full sm:w-56", disabled: loadingDay, children: _jsx(SelectValue, { placeholder: ui.pickDay }) }), _jsxs(SelectContent, { className: "z-[100] bg-popover opacity-100", children: [_jsx(SelectItem, { value: "current", children: ui.pickDayToday }), safePickDays.map((d) => (_jsxs(SelectItem, { value: d.day, children: [dayLabel(d.day), d.orders > 0 ? ` (${d.orders})` : ""] }, d.day)))] })] }), _jsxs(Select, { value: filters.documentTypeId ?? "all", onValueChange: (v) => setFilters((f) => ({ ...f, documentTypeId: v === "all" ? null : v, page: 0 })), children: [_jsx(SelectTrigger, { className: "h-12 w-full sm:w-52", children: _jsx(SelectValue, { placeholder: ui.allDocumentTypes }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "all", children: ui.allDocumentTypes }), (Array.isArray(documentTypes) ? documentTypes : []).map((dt) => (_jsx(SelectItem, { value: dt.id, children: dt.name }, dt.id)))] })] }), _jsx(Button, { variant: filters.onlyPending ? "default" : "outline", className: "h-12", onClick: () => setFilters((f) => ({ ...f, onlyPending: !f.onlyPending, page: 0 })), children: ui.onlyPending }), _jsxs(Button, { variant: filters.urgentOnly ? "default" : "outline", className: "h-12", onClick: () => setFilters((f) => ({ ...f, urgentOnly: !f.urgentOnly, page: 0 })), children: [_jsx(Zap, { className: "mr-2 h-4 w-4" }), ui.onlyUrgent, urgentCount > 0 ? ` (${urgentCount})` : ""] })] }) }), !realtimeOk && (_jsx("p", { className: "text-sm text-muted-foreground", children: ui.connectionLost })), cartsPerPrint != null && (_jsx("div", { className: "flex justify-end md:hidden", children: _jsxs(Button, { className: "h-12", disabled: loading || batchPrinting || (busyId != null || actionBusy), onClick: () => void printNextCarts(), children: [batchPrinting ? (_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" })) : (_jsx(Printer, { className: "mr-2 h-4 w-4" })), "Volgende printen (", cartsPerPrint, " karren)"] }) })), _jsx("div", { className: "md:hidden", children: _jsxs(Button, { variant: "outline", className: "h-12 w-full", disabled: fetchingNotes, onClick: () => void fetchShippingNotes(), children: [fetchingNotes ? (_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" })) : (_jsx(FileDown, { className: "mr-2 h-4 w-4" })), fetchingNotes ? "Ophalen…" : "Verzendbrieven ophalen"] }) }), loading ? (_jsxs("div", { className: "flex items-center justify-center py-16 text-muted-foreground", children: [_jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" }), " ", t("loadingQueue")] })) : (_jsxs(_Fragment, { children: [earlierRows.length > 0 && (_jsxs("section", { className: "mb-4 rounded-lg border border-primary/40 bg-muted/40 p-3", "aria-label": "Nog niet gescand van eerdere dagen", children: [_jsxs("h3", { className: "mb-2 text-sm font-semibold text-foreground", children: ["Nog niet gescand van eerdere dagen (", earlierRows.length, ")"] }), _jsx("ul", { className: "divide-y divide-border", children: earlierRows.map((row) => (_jsxs("li", { className: "flex flex-wrap items-center justify-between gap-2 py-2", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "truncate font-medium", children: row.document_number ?? row.order_number ?? "Pakbon" }), _jsxs("div", { className: "text-xs text-muted-foreground", children: [pickDayShortLabel(pickDayOf(row)), row.customer_name ? ` · ${row.customer_name}` : ""] })] }), _jsx(Button, { size: "sm", variant: "outline", disabled: busyId !== null || actionBusy, onClick: async () => {
|
|
1452
|
+
})] }) })), _jsxs(Button, { variant: "outline", size: "lg", className: "h-12 w-full sm:hidden", "aria-expanded": filtersOpen, onClick: () => setFiltersOpen((v) => !v), children: [_jsx(Search, { className: "mr-2 h-4 w-4" }), " ", ui.filters] }), _jsx(Card, { className: filtersOpen ? "" : "hidden sm:block", children: _jsxs(CardContent, { className: "flex flex-wrap items-center gap-3 p-3 sm:p-4", children: [_jsxs("div", { className: "relative w-full min-w-0 flex-1 sm:min-w-64", children: [_jsx(Search, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { className: "h-12 pl-9 text-base", placeholder: t("search"), value: searchInput, onChange: (e) => setSearchInput(e.target.value) })] }), _jsxs(Select, { value: chosenDay ?? "current", onValueChange: (v) => void chooseDay(v), children: [_jsx(SelectTrigger, { className: "h-12 w-full sm:w-56", disabled: loadingDay, children: _jsx(SelectValue, { placeholder: ui.pickDay }) }), _jsxs(SelectContent, { className: "z-[100] bg-popover opacity-100", children: [_jsx(SelectItem, { value: "current", children: ui.pickDayToday }), safePickDays.map((d) => (_jsxs(SelectItem, { value: d.day, children: [dayLabel(d.day), d.orders > 0 ? ` (${d.orders})` : ""] }, d.day)))] })] }), _jsxs(Select, { value: filters.documentTypeId ?? "all", onValueChange: (v) => setFilters((f) => ({ ...f, documentTypeId: v === "all" ? null : v, page: 0 })), children: [_jsx(SelectTrigger, { className: "h-12 w-full sm:w-52", children: _jsx(SelectValue, { placeholder: ui.allDocumentTypes }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "all", children: ui.allDocumentTypes }), (Array.isArray(documentTypes) ? documentTypes : []).map((dt) => (_jsx(SelectItem, { value: dt.id, children: dt.name }, dt.id)))] })] }), _jsx(Button, { variant: filters.onlyPending ? "default" : "outline", className: "h-12", onClick: () => setFilters((f) => ({ ...f, onlyPending: !f.onlyPending, page: 0 })), children: ui.onlyPending }), _jsxs(Button, { variant: filters.urgentOnly ? "default" : "outline", className: "h-12", onClick: () => setFilters((f) => ({ ...f, urgentOnly: !f.urgentOnly, page: 0 })), children: [_jsx(Zap, { className: "mr-2 h-4 w-4" }), ui.onlyUrgent, urgentCount > 0 ? ` (${urgentCount})` : ""] })] }) }), !realtimeOk && (_jsx("p", { className: "text-sm text-muted-foreground", children: ui.connectionLost })), cartsPerPrint != null && (_jsx("div", { className: "flex justify-end md:hidden", children: _jsxs(Button, { className: "h-12", disabled: loading || printStatusLoading || batchPrinting || (busyId != null || actionBusy), onClick: () => void printNextCarts(), children: [batchPrinting ? (_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" })) : (_jsx(Printer, { className: "mr-2 h-4 w-4" })), "Volgende printen (", cartsPerPrint, " karren)"] }) })), _jsx("div", { className: "md:hidden", children: _jsxs(Button, { variant: "outline", className: "h-12 w-full", disabled: fetchingNotes, onClick: () => void fetchShippingNotes(), children: [fetchingNotes ? (_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" })) : (_jsx(FileDown, { className: "mr-2 h-4 w-4" })), fetchingNotes ? "Ophalen…" : "Verzendbrieven ophalen"] }) }), loading ? (_jsxs("div", { className: "flex items-center justify-center py-16 text-muted-foreground", children: [_jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" }), " ", t("loadingQueue")] })) : (_jsxs(_Fragment, { children: [earlierRows.length > 0 && (_jsxs("section", { className: "mb-4 rounded-lg border border-primary/40 bg-muted/40 p-3", "aria-label": "Nog niet gescand van eerdere dagen", children: [_jsxs("h3", { className: "mb-2 text-sm font-semibold text-foreground", children: ["Nog niet gescand van eerdere dagen (", earlierRows.length, ")"] }), _jsx("ul", { className: "divide-y divide-border", children: earlierRows.map((row) => (_jsxs("li", { className: "flex flex-wrap items-center justify-between gap-2 py-2", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "truncate font-medium", children: row.document_number ?? row.order_number ?? "Pakbon" }), _jsxs("div", { className: "text-xs text-muted-foreground", children: [pickDayShortLabel(pickDayOf(row)), row.customer_name ? ` · ${row.customer_name}` : ""] })] }), _jsx(Button, { size: "sm", variant: "outline", disabled: busyId !== null || actionBusy, onClick: async () => {
|
|
1438
1453
|
await printAllForItem(row);
|
|
1439
1454
|
void refetchEarlier();
|
|
1440
|
-
}, children: "Opnieuw printen" })] }, row.id))) })] })), _jsx(QueueTable, { items: items.filter((item) => readinessById[item.id]?.replaced !== true), lockedIds: lockedIds, statuses: Array.isArray(statuses) ? statuses : [], documentTypes: Array.isArray(documentTypes) ? documentTypes : [], busyId: busyId, readinessById: readinessById, siteTimeZone: siteTz, pickDay: chosenDay ?? pickDay ?? null, waitingIds: waitingQueueIds, onPick: handlePick, onReprint: handleReprintLocked, onPrintAll: printAllForItem, onSelectPrinted: selectPrintedForReprint, onMarkPrinted: markPrinted, onPreview: setPreviewItem, t: t })] })), _jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between", children: [_jsxs("span", { className: "text-center text-sm text-muted-foreground sm:text-left", children: [t("page"), " ", filters.page + 1, " ", t("of"), " ", totalPages] }), _jsxs("div", { className: "grid grid-cols-2 gap-2 sm:flex", children: [_jsx(Button, { variant: "outline", className: "h-12 w-full sm:w-auto", disabled: filters.page === 0, onClick: () => setFilters((f) => ({ ...f, page: Math.max(0, f.page - 1) })), children: t("previous") }), _jsx(Button, { variant: "outline", className: "h-12 w-full sm:w-auto", disabled: filters.page + 1 >= totalPages, onClick: () => setFilters((f) => ({ ...f, page: f.page + 1 })), children: t("next") })] })] }), _jsx("div", { className: "fixed inset-x-0 bottom-0 z-40 border-t bg-background/95 p-3 pb-[max(0.75rem,env(safe-area-inset-bottom))] backdrop-blur md:hidden", children: _jsxs(Button, { size: "lg", className: "h-14 w-full text-lg", onClick: () => (pending ? confirmPending() : fetchNextLocked()), disabled: (busyId !== null || actionBusy) || fetchingData, children: [(busyId !== null || actionBusy) || 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" })), _jsxs("span", { className: "truncate", children: [pending && !readiness.ready ? "Pakbon ophalen" : t("printNext"), pending?.document_number ? ` · ${pending.document_number}` : ""] })] }) }), _jsx(PreviewDialog, { item: previewItem, stationSlug: station.slug, onClose: () => setPreviewItem(null) })] }));
|
|
1455
|
+
}, children: "Opnieuw printen" })] }, row.id))) })] })), _jsx(QueueTable, { items: items.filter((item) => readinessById[item.id]?.replaced !== true), lockedIds: lockedIds, statuses: Array.isArray(statuses) ? statuses : [], documentTypes: Array.isArray(documentTypes) ? documentTypes : [], busyId: busyId, readinessById: readinessById, siteTimeZone: siteTz, pickDay: chosenDay ?? pickDay ?? null, waitingIds: waitingQueueIds, printStatus: printStatus, printStatusLoading: printStatusLoading, onPick: handlePick, onReprint: handleReprintLocked, onPrintAll: printAllForItem, onSelectPrinted: selectPrintedForReprint, onMarkPrinted: markPrinted, onPreview: setPreviewItem, t: t })] })), _jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between", children: [_jsxs("span", { className: "text-center text-sm text-muted-foreground sm:text-left", children: [t("page"), " ", filters.page + 1, " ", t("of"), " ", totalPages] }), _jsxs("div", { className: "grid grid-cols-2 gap-2 sm:flex", children: [_jsx(Button, { variant: "outline", className: "h-12 w-full sm:w-auto", disabled: filters.page === 0, onClick: () => setFilters((f) => ({ ...f, page: Math.max(0, f.page - 1) })), children: t("previous") }), _jsx(Button, { variant: "outline", className: "h-12 w-full sm:w-auto", disabled: filters.page + 1 >= totalPages, onClick: () => setFilters((f) => ({ ...f, page: f.page + 1 })), children: t("next") })] })] }), _jsx("div", { className: "fixed inset-x-0 bottom-0 z-40 border-t bg-background/95 p-3 pb-[max(0.75rem,env(safe-area-inset-bottom))] backdrop-blur md:hidden", children: _jsxs(Button, { size: "lg", className: "h-14 w-full text-lg", onClick: () => (pending ? confirmPending() : fetchNextLocked()), disabled: (busyId !== null || actionBusy) || fetchingData || (!pending && printStatusLoading), children: [(busyId !== null || actionBusy) || 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" })), _jsxs("span", { className: "truncate", children: [pending && !readiness.ready ? "Pakbon ophalen" : t("printNext"), pending?.document_number ? ` · ${pending.document_number}` : ""] })] }) }), _jsx(PreviewDialog, { item: previewItem, stationSlug: station.slug, onClose: () => setPreviewItem(null) })] }));
|
|
1441
1456
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PickDocumentType, PickQueueItem, PickStatus } from "../../lib/pickTypes.js";
|
|
2
|
+
import { type PrintStatusResult } from "../../lib/pickPrintStatus.js";
|
|
2
3
|
import { type PickTranslator } from "../../lib/pickI18n.js";
|
|
3
4
|
interface Props {
|
|
4
5
|
items: PickQueueItem[];
|
|
@@ -23,6 +24,9 @@ interface Props {
|
|
|
23
24
|
siteTimeZone?: string | null;
|
|
24
25
|
/** Rijen met een printopdracht die nog niet voltooid is. */
|
|
25
26
|
waitingIds?: Set<string>;
|
|
27
|
+
/** 1.0.63: printstatus uit de Engine (één aanroep per scherm). */
|
|
28
|
+
printStatus?: PrintStatusResult | null;
|
|
29
|
+
printStatusLoading?: boolean;
|
|
26
30
|
onPick: (item: PickQueueItem) => void;
|
|
27
31
|
onReprint?: (item: PickQueueItem) => void;
|
|
28
32
|
onPrintAll?: (item: PickQueueItem) => void;
|
|
@@ -32,6 +36,6 @@ interface Props {
|
|
|
32
36
|
readOnly?: boolean;
|
|
33
37
|
t?: PickTranslator;
|
|
34
38
|
}
|
|
35
|
-
export declare function QueueTable({ items, lockedIds, statuses, documentTypes, busyId, readinessById, waitingIds, onPick, onReprint, onPrintAll, onSelectPrinted, onMarkPrinted, onPreview, readOnly, t: translator, siteTimeZone, pickDay, }: Props): import("react").JSX.Element;
|
|
39
|
+
export declare function QueueTable({ items, lockedIds, statuses, documentTypes, busyId, readinessById, waitingIds, printStatus, printStatusLoading, onPick, onReprint, onPrintAll, onSelectPrinted, onMarkPrinted, onPreview, readOnly, t: translator, siteTimeZone, pickDay, }: Props): import("react").JSX.Element;
|
|
36
40
|
export {};
|
|
37
41
|
//# sourceMappingURL=QueueTable.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueueTable.d.ts","sourceRoot":"","sources":["../../../src/components/pick/QueueTable.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"QueueTable.d.ts","sourceRoot":"","sources":["../../../src/components/pick/QueueTable.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAKvF,OAAO,EAA+B,KAAK,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAGhG,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAe5E,UAAU,KAAK;IACb,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACvB,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,aAAa,EAAE,gBAAgB,EAAE,CAAC;IAClC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,YAAY,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,UAAU,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACzO,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,4DAA4D;IAC5D,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,kEAAkE;IAClE,WAAW,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACvC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,MAAM,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IACtC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IAC1C,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IAC3C,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IAChD,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IAC9C,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,CAAC,EAAE,cAAc,CAAC;CACpB;AA8DD,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,SAAS,EACT,QAAQ,EACR,aAAa,EACb,MAAM,EACN,aAAa,EACb,UAAU,EACV,WAAkB,EAClB,kBAA0B,EAC1B,MAAM,EACN,SAAS,EACT,UAAU,EACV,eAAe,EACf,aAAa,EACb,SAAS,EAGT,QAAQ,EACR,CAAC,EAAE,UAAU,EACb,YAAmB,EACnB,OAAc,GACf,EAAE,KAAK,+BA2fP"}
|
|
@@ -5,9 +5,8 @@ import { Badge, Button, Table, TableBody, TableCell, TableHead, TableHeader, Tab
|
|
|
5
5
|
import { AlertTriangle, Check, Eye, Loader2, Lock, Printer, RefreshCw, RotateCcw } from "lucide-react";
|
|
6
6
|
import { cartColumnInfo, comparePickQueue, dedupeByUnit, displayCartCount, displayPageCount, sinceLabel, unitTitleOf } from "../../lib/pickTypes.js";
|
|
7
7
|
import { duplicateNameTag } from "../../lib/pickRowState.js";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { PRINT_MANUAL, PRINT_NOT_NEEDED_HINT, printStage, printStageLabel } from "../../lib/pick142.js";
|
|
8
|
+
import { PRINT_MANUAL } from "../../lib/pick142.js";
|
|
9
|
+
import { isInPrint, printStatusLabel } from "../../lib/pickPrintStatus.js";
|
|
11
10
|
import { CART_PLAN_MISMATCH_MESSAGE, orderNumbersLabel } from "../../lib/pick142.js";
|
|
12
11
|
import { isRowPrintable, rowWaitMessage, rowWaitOf } from "../../lib/pick143.js";
|
|
13
12
|
import { getPickTranslator } from "../../lib/pickI18n.js";
|
|
@@ -70,21 +69,8 @@ function priorityTone(priority, urgent) {
|
|
|
70
69
|
return "bg-secondary text-secondary-foreground";
|
|
71
70
|
return "bg-muted text-muted-foreground";
|
|
72
71
|
}
|
|
73
|
-
export function QueueTable({ items, lockedIds, statuses, documentTypes, busyId, readinessById, waitingIds, onPick, onReprint, onPrintAll, onSelectPrinted, onMarkPrinted, onPreview, readOnly, t: translator, siteTimeZone = null, pickDay = null, }) {
|
|
72
|
+
export function QueueTable({ items, lockedIds, statuses, documentTypes, busyId, readinessById, waitingIds, printStatus = null, printStatusLoading = false, onPick, onReprint, onPrintAll, onSelectPrinted, onMarkPrinted, onPreview, readOnly, t: translator, siteTimeZone = null, pickDay = null, }) {
|
|
74
73
|
const t = translator ?? getPickTranslator("nl");
|
|
75
|
-
// Echte printstatus per regel uit de printopdrachten (één aanvraag, ververst mee).
|
|
76
|
-
const jobIds = Array.from(new Set((Array.isArray(items) ? items : []).filter((i) => i.printed_at && i.print_job_id).map((i) => i.print_job_id))).sort();
|
|
77
|
-
const jobsQuery = useQuery({
|
|
78
|
-
queryKey: ["pick", "rowPrintJobs", jobIds.join(",")],
|
|
79
|
-
enabled: jobIds.length > 0,
|
|
80
|
-
queryFn: () => pickApi.printJobsStatus(jobIds),
|
|
81
|
-
refetchInterval: (q) => {
|
|
82
|
-
const data = Array.isArray(q.state.data) ? q.state.data : [];
|
|
83
|
-
return data.some((j) => printStage(j) === "rendering") ? 5000 : 30000;
|
|
84
|
-
},
|
|
85
|
-
});
|
|
86
|
-
const jobsLoaded = jobsQuery.isSuccess;
|
|
87
|
-
const jobsById = new Map((Array.isArray(jobsQuery.data) ? jobsQuery.data : []).map((j) => [j.id, j]));
|
|
88
74
|
// Volgorde identiek aan de keuze van "volgende uitprinten" (zie
|
|
89
75
|
// comparePickQueue): niet-geprinte regels bovenaan, en bij gelijke stand op
|
|
90
76
|
// kar-nummer, zodat K1 boven K2 boven K3 staat en het printen van boven naar
|
|
@@ -117,7 +103,7 @@ export function QueueTable({ items, lockedIds, statuses, documentTypes, busyId,
|
|
|
117
103
|
}, children: [_jsxs(TableCell, { className: "font-medium", children: [_jsxs("div", { className: "flex items-center gap-2", children: [unitTitleOf(item), dupTag && _jsxs("span", { className: "text-xs font-normal text-muted-foreground", children: ["(", dupTag, ")"] }), replaced && (_jsx("span", { className: "rounded bg-destructive/10 px-1.5 py-0.5 text-xs font-semibold text-destructive", title: readiness?.reason ?? undefined, children: "Vervangen" })), replaced && readiness?.reason && (_jsx("span", { className: "text-xs font-normal text-destructive", children: readiness.reason })), waiting && (_jsx("span", { className: "rounded bg-muted px-1.5 py-0.5 text-xs font-semibold text-muted-foreground", children: "Wacht op printer" })), sentElsewhereLines(item).map((line) => (_jsx("span", { className: "text-xs font-normal text-muted-foreground", children: line }, line))), warnings.length > 0 && (_jsx(AlertTriangle, { className: "h-4 w-4 text-destructive", "aria-label": t("warning") }))] }), _jsx("div", { className: "text-xs text-muted-foreground", children: doc?.name ?? "-" })] }), _jsx(TableCell, { children: orderNumbersLabel(item) }), _jsx(TableCell, { children: item.customer_name }), _jsx(TableCell, { className: "text-right", children: item.line_count }), _jsx(TableCell, { className: "text-right", children: (() => {
|
|
118
104
|
const info = cartColumnInfo(item);
|
|
119
105
|
return (_jsxs("div", { className: "flex flex-col items-end", children: [_jsx("span", { children: info.carts }), info.cartLabel && (_jsx("span", { className: "text-xs text-muted-foreground", children: info.cartLabel })), info.reason && (_jsx("span", { className: "text-xs text-muted-foreground", children: info.reason }))] }));
|
|
120
|
-
})() }), _jsx(TableCell, { className: "text-right", children: printedSlipCount(item) ?? "—" }), _jsx(TableCell, { className: "text-right", children: displayPageCount(item.line_count) }), _jsxs(TableCell, { children: [_jsx(
|
|
106
|
+
})() }), _jsx(TableCell, { className: "text-right", children: printedSlipCount(item) ?? "—" }), _jsx(TableCell, { className: "text-right", children: displayPageCount(item.line_count) }), _jsxs(TableCell, { children: [_jsx(EnginePrintBadge, { item: item, result: printStatus, loading: printStatusLoading }), printed && (_jsx("div", { className: "mt-1 text-xs text-muted-foreground", children: new Date(item.printed_at).toLocaleTimeString([], {
|
|
121
107
|
hour: "2-digit",
|
|
122
108
|
minute: "2-digit",
|
|
123
109
|
}) }))] }), _jsx(TableCell, { children: _jsx("span", { className: "rounded px-2 py-1 text-xs font-semibold " +
|
|
@@ -134,7 +120,7 @@ export function QueueTable({ items, lockedIds, statuses, documentTypes, busyId,
|
|
|
134
120
|
}, children: _jsx(Check, { className: "h-5 w-5" }) })), blockedMessage(readinessById[item.id], siteTimeZone, item) && !printed ? (_jsx("span", { className: "max-w-56 text-right text-xs font-medium text-destructive", children: blockedMessage(readinessById[item.id], siteTimeZone, item) })) : printed ? (_jsxs(Button, { size: "sm", variant: "ghost", disabled: readOnly || busyId === item.id || checking || replaced, onClick: (e) => {
|
|
135
121
|
e.stopPropagation();
|
|
136
122
|
(onPrintAll ?? onReprint ?? onPick)(item);
|
|
137
|
-
}, children: [checking ? (_jsx(Loader2, { className: "mr-1 h-4 w-4 animate-spin" })) : ready ? (_jsx(RotateCcw, { className: "mr-1 h-4 w-4" })) : (_jsx(RefreshCw, { className: "mr-1 h-4 w-4" })), replaced ? "Vervangen" : checking ? "Pakbon controleren" : ready ? t("print") : "Pakbon ophalen"] })) : locked ? (_jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-muted-foreground", children: [_jsx(Lock, { className: "h-3.5 w-3.5" }), " ", t("inProgress")] })) : (_jsxs(Button, { size: "sm", variant: "outline", disabled: readOnly || busyId === item.id || checking || replaced, onClick: (e) => {
|
|
123
|
+
}, children: [checking ? (_jsx(Loader2, { className: "mr-1 h-4 w-4 animate-spin" })) : ready ? (_jsx(RotateCcw, { className: "mr-1 h-4 w-4" })) : (_jsx(RefreshCw, { className: "mr-1 h-4 w-4" })), replaced ? "Vervangen" : checking ? "Pakbon controleren" : ready ? t("print") : "Pakbon ophalen"] })) : isInPrint(printStatus?.byId.get(item.id)) || (printStatusLoading && !printed) ? (_jsxs(Button, { size: "sm", variant: "outline", disabled: true, onClick: (e) => e.stopPropagation(), children: [_jsx(Loader2, { className: "mr-1 h-4 w-4 animate-spin" }), printStatusLoading ? "…" : "Wordt geprint"] })) : locked ? (_jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-muted-foreground", children: [_jsx(Lock, { className: "h-3.5 w-3.5" }), " ", t("inProgress")] })) : (_jsxs(Button, { size: "sm", variant: "outline", disabled: readOnly || busyId === item.id || checking || replaced, onClick: (e) => {
|
|
138
124
|
e.stopPropagation();
|
|
139
125
|
(onPrintAll ?? onPick)(item);
|
|
140
126
|
}, children: [checking ? (_jsx(Loader2, { className: "mr-1 h-4 w-4 animate-spin" })) : !ready ? (_jsx(RefreshCw, { className: "mr-1 h-4 w-4" })) : (_jsx(Printer, { className: "mr-1 h-4 w-4" })), replaced ? "Vervangen" : checking ? "Pakbon controleren" : ready ? t("print") : "Pakbon ophalen"] }))] }) })] }, item.id));
|
|
@@ -161,7 +147,7 @@ export function QueueTable({ items, lockedIds, statuses, documentTypes, busyId,
|
|
|
161
147
|
}, children: [_jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_auto] items-start gap-3", children: [_jsxs("div", { className: "min-w-0", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsxs("span", { className: "truncate text-lg font-bold text-foreground", children: [unitTitleOf(item), dupTag && _jsxs("span", { className: "text-xs font-normal text-muted-foreground", children: ["(", dupTag, ")"] }), replaced && (_jsx("span", { className: "rounded bg-destructive/10 px-1.5 py-0.5 text-xs font-semibold text-destructive", title: readiness?.reason ?? undefined, children: "Vervangen" })), replaced && readiness?.reason && (_jsx("span", { className: "text-xs font-normal text-destructive", children: readiness.reason })), waiting && (_jsx("span", { className: "rounded bg-muted px-1.5 py-0.5 text-xs font-semibold text-muted-foreground", children: "Wacht op printer" }))] }), warnings.length > 0 && (_jsx(AlertTriangle, { className: "h-4 w-4 shrink-0 text-destructive", "aria-label": t("warning") }))] }), _jsx("p", { className: "truncate text-xs text-muted-foreground", children: doc?.name ?? "-" })] }), _jsxs("div", { className: "flex shrink-0 items-start gap-1", children: [onPreview && (_jsx("button", { type: "button", "aria-label": "Voorbeeld " + item.document_number, title: "Voorbeeld " + item.document_number, className: "inline-flex h-11 w-11 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-muted hover:text-foreground", onClick: (e) => {
|
|
162
148
|
e.stopPropagation();
|
|
163
149
|
onPreview(item);
|
|
164
|
-
}, children: _jsx(Eye, { className: "h-5 w-5" }) })), _jsxs("div", { className: "flex shrink-0 flex-col items-end gap-1", children: [_jsx(
|
|
150
|
+
}, children: _jsx(Eye, { className: "h-5 w-5" }) })), _jsxs("div", { className: "flex shrink-0 flex-col items-end gap-1", children: [_jsx(EnginePrintBadge, { item: item, result: printStatus, loading: printStatusLoading }), printed && (_jsx("span", { className: "text-xs text-muted-foreground", children: new Date(item.printed_at).toLocaleTimeString([], {
|
|
165
151
|
hour: "2-digit",
|
|
166
152
|
minute: "2-digit",
|
|
167
153
|
}) })), _jsx("span", { className: "rounded px-2 py-0.5 text-xs font-semibold " +
|
|
@@ -185,7 +171,7 @@ export function QueueTable({ items, lockedIds, statuses, documentTypes, busyId,
|
|
|
185
171
|
})(), _jsx(CartSteps, { printed: printed, waiting: waiting }), _jsxs("div", { className: "mt-3", children: [blockedMessage(readiness, siteTimeZone, item) && !printed ? (_jsx("p", { className: "rounded-md border border-destructive/40 bg-destructive/5 p-3 text-sm font-medium text-destructive", children: blockedMessage(readiness, siteTimeZone, item) })) : printed ? (_jsxs(Button, { size: "lg", variant: "outline", className: "h-12 w-full", disabled: readOnly || busyId === item.id || checking || replaced, onClick: (e) => {
|
|
186
172
|
e.stopPropagation();
|
|
187
173
|
(onPrintAll ?? onReprint ?? onPick)(item);
|
|
188
|
-
}, children: [checking ? (_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" })) : ready ? (_jsx(RotateCcw, { className: "mr-2 h-4 w-4" })) : (_jsx(RefreshCw, { className: "mr-2 h-4 w-4" })), replaced ? "Vervangen" : checking ? "Pakbon controleren" : ready ? t("print") : "Pakbon ophalen"] })) : locked ? (_jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-muted-foreground", children: [_jsx(Lock, { className: "h-3.5 w-3.5" }), " ", t("inProgress")] })) : (_jsxs(Button, { size: "lg", className: "h-12 w-full", disabled: readOnly || busyId === item.id || checking || replaced, onClick: (e) => {
|
|
174
|
+
}, children: [checking ? (_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" })) : ready ? (_jsx(RotateCcw, { className: "mr-2 h-4 w-4" })) : (_jsx(RefreshCw, { className: "mr-2 h-4 w-4" })), replaced ? "Vervangen" : checking ? "Pakbon controleren" : ready ? t("print") : "Pakbon ophalen"] })) : isInPrint(printStatus?.byId.get(item.id)) || (printStatusLoading && !printed) ? (_jsxs(Button, { size: "sm", variant: "outline", disabled: true, onClick: (e) => e.stopPropagation(), children: [_jsx(Loader2, { className: "mr-1 h-4 w-4 animate-spin" }), printStatusLoading ? "…" : "Wordt geprint"] })) : locked ? (_jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-muted-foreground", children: [_jsx(Lock, { className: "h-3.5 w-3.5" }), " ", t("inProgress")] })) : (_jsxs(Button, { size: "lg", className: "h-12 w-full", disabled: readOnly || busyId === item.id || checking || replaced, onClick: (e) => {
|
|
189
175
|
e.stopPropagation();
|
|
190
176
|
(onPrintAll ?? onPick)(item);
|
|
191
177
|
}, children: [checking ? (_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" })) : !ready ? (_jsx(RefreshCw, { className: "mr-2 h-4 w-4" })) : (_jsx(Printer, { className: "mr-2 h-4 w-4" })), replaced ? "Vervangen" : checking ? "Pakbon controleren" : ready ? t("print") : "Pakbon ophalen"] })), !printed && onMarkPrinted && (_jsxs("details", { className: "mt-2 text-sm", onClick: (e) => e.stopPropagation(), children: [_jsx("summary", { className: "cursor-pointer select-none text-muted-foreground", children: "Meer" }), _jsxs(Button, { size: "sm", variant: "ghost", className: "mt-1 w-full", disabled: readOnly || busyId === item.id, onClick: (e) => {
|
|
@@ -196,16 +182,13 @@ export function QueueTable({ items, lockedIds, statuses, documentTypes, busyId,
|
|
|
196
182
|
}), safeItems.length === 0 && (_jsx("div", { className: "rounded-lg border py-10 text-center text-muted-foreground", children: t("emptyQueue") }))] })] }));
|
|
197
183
|
}
|
|
198
184
|
/** Statuslabel van een regel: alleen de echte stand uit de printopdracht, nooit een aanname. */
|
|
199
|
-
function
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
if (!
|
|
185
|
+
function EnginePrintBadge({ item, result, loading }) {
|
|
186
|
+
const status = result?.byId.get(item.id);
|
|
187
|
+
// Handmatig gemarkeerd: geprint zonder printopdracht.
|
|
188
|
+
if (!loading && status?.code === "geen" && item.printed_at && !item.print_job_id) {
|
|
203
189
|
return _jsx(Badge, { variant: "secondary", children: PRINT_MANUAL });
|
|
204
|
-
if (!job && !jobsLoaded)
|
|
205
|
-
return _jsx(Badge, { variant: "secondary", children: "Status laden\u2026" });
|
|
206
|
-
const stage = printStage(job);
|
|
207
|
-
if (stage === "not_needed") {
|
|
208
|
-
return _jsx(Badge, { variant: "outline", className: "text-muted-foreground", title: PRINT_NOT_NEEDED_HINT, children: printStageLabel(job) });
|
|
209
190
|
}
|
|
210
|
-
|
|
191
|
+
const l = printStatusLabel({ status, loading: loading && !result, beschikbaar: result ? result.beschikbaar : true, reden: result?.reden ?? null });
|
|
192
|
+
const variant = l.tone === "failed" ? "destructive" : l.tone === "todo" ? "default" : l.tone === "unknown" ? "outline" : "secondary";
|
|
193
|
+
return (_jsxs("div", { className: "flex flex-col items-start gap-0.5", children: [_jsx(Badge, { variant: variant, title: l.reason ?? undefined, children: l.label }), l.reason && _jsx("span", { className: "max-w-56 text-xs text-muted-foreground", children: l.reason })] }));
|
|
211
194
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StickerReprintButton.d.ts","sourceRoot":"","sources":["../../../src/components/pick/StickerReprintButton.tsx"],"names":[],"mappings":"AAMA,2EAA2E;AAC3E,wBAAgB,oBAAoB,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"StickerReprintButton.d.ts","sourceRoot":"","sources":["../../../src/components/pick/StickerReprintButton.tsx"],"names":[],"mappings":"AAMA,2EAA2E;AAC3E,wBAAgB,oBAAoB,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,sCAsE7F"}
|
|
@@ -17,7 +17,7 @@ export function StickerReprintButton({ cartId, slug }) {
|
|
|
17
17
|
refetchInterval: 15000,
|
|
18
18
|
placeholderData: (prev) => prev,
|
|
19
19
|
retry: 1,
|
|
20
|
-
enabled:
|
|
20
|
+
enabled: false, // gevuld door useCartStickerStates
|
|
21
21
|
});
|
|
22
22
|
if (!slug || !hasPrintedSticker(q.data))
|
|
23
23
|
return null;
|
|
@@ -41,6 +41,7 @@ export function StickerReprintButton({ cartId, slug }) {
|
|
|
41
41
|
finally {
|
|
42
42
|
setBusy(false);
|
|
43
43
|
qc.invalidateQueries({ queryKey: ["pick", "sticker-state", cartId] });
|
|
44
|
+
qc.invalidateQueries({ queryKey: ["pick", "sticker-bundle"] });
|
|
44
45
|
}
|
|
45
46
|
};
|
|
46
47
|
return (_jsxs("div", { className: "mt-3", children: [_jsx("button", { type: "button", onClick: () => setOpen(true), className: "rounded-md border bg-background px-3 py-2 text-sm font-medium text-foreground hover:bg-muted", children: "Stickers opnieuw printen" }), open && (_jsx("div", { role: "dialog", "aria-modal": "true", className: "fixed inset-0 z-50 flex items-center justify-center bg-foreground/40 p-4", children: _jsxs("div", { className: "w-full max-w-sm rounded-lg border bg-background p-4 shadow-lg", children: [_jsx("p", { className: "font-medium text-foreground", children: "Stickers van deze kar opnieuw printen?" }), _jsxs("label", { className: "mt-3 block text-sm text-muted-foreground", children: ["Reden (optioneel)", _jsx("input", { value: reden, onChange: (e) => setReden(e.target.value), disabled: busy, className: "mt-1 w-full rounded-md border bg-background px-2 py-1.5 text-sm text-foreground" })] }), detail && (_jsxs("details", { className: "mt-2 text-xs text-muted-foreground", children: [_jsx("summary", { className: "cursor-pointer", children: "Details voor beheer" }), _jsx("p", { children: detail })] })), _jsxs("div", { className: "mt-4 flex justify-end gap-2", children: [_jsx("button", { type: "button", disabled: busy, onClick: () => setOpen(false), className: "rounded-md border px-3 py-1.5 text-sm text-foreground", children: "Annuleren" }), _jsx("button", { type: "button", disabled: busy, onClick: run, className: "rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground disabled:opacity-60", children: busy ? "Bezig…" : "Opnieuw printen" })] })] }) }))] }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StickerState.d.ts","sourceRoot":"","sources":["../../../src/components/pick/StickerState.tsx"],"names":[],"mappings":"AAcA,+EAA+E;AAC/E,wBAAgB,mBAAmB,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"StickerState.d.ts","sourceRoot":"","sources":["../../../src/components/pick/StickerState.tsx"],"names":[],"mappings":"AAcA,+EAA+E;AAC/E,wBAAgB,mBAAmB,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,sCAwC5F;AAED,6EAA6E;AAC7E,wBAAgB,qBAAqB,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;IAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,sCAoBvG;AAED,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,sCA+CzF;AAED,6HAA6H;AAC7H,wBAAgB,yBAAyB,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,sCAiBpF"}
|
|
@@ -10,11 +10,12 @@ export function StickerFitMeldingen({ cartId, slug }) {
|
|
|
10
10
|
const q = useQuery({
|
|
11
11
|
queryKey: ["pick", "sticker-fit", cartId, slug],
|
|
12
12
|
queryFn: () => fetchStickerFit(cartId, slug),
|
|
13
|
+
enabled: !slug, // openbaar station: gevuld door useCartStickerStates
|
|
13
14
|
refetchInterval: POLL,
|
|
14
15
|
placeholderData: (prev) => prev,
|
|
15
16
|
retry: 1,
|
|
16
17
|
});
|
|
17
|
-
if (q.
|
|
18
|
+
if (q.data === undefined && !q.isError)
|
|
18
19
|
return null;
|
|
19
20
|
if (q.isError || q.data == null) {
|
|
20
21
|
return _jsx("p", { className: "mt-3 text-xs text-muted-foreground", children: STICKER_FIT_UNKNOWN });
|
|
@@ -37,12 +38,12 @@ export function OrderStickerMeldingen({ orderId, slug }) {
|
|
|
37
38
|
const q = useQuery({
|
|
38
39
|
queryKey: ["pick", "sticker-meldingen", orderId, slug],
|
|
39
40
|
queryFn: () => fetchOrderStickerMeldingen(orderId, slug),
|
|
40
|
-
enabled: !!orderId,
|
|
41
|
+
enabled: !!orderId && !slug,
|
|
41
42
|
refetchInterval: POLL,
|
|
42
43
|
placeholderData: (prev) => prev,
|
|
43
44
|
retry: 1,
|
|
44
45
|
});
|
|
45
|
-
if (!orderId || q.
|
|
46
|
+
if (!orderId || (q.data === undefined && !q.isError))
|
|
46
47
|
return null;
|
|
47
48
|
if (q.isError || q.data == null) {
|
|
48
49
|
return _jsxs("p", { className: "mb-3 text-xs text-muted-foreground", children: ["Stickermeldingen: ", STICKER_UNKNOWN] });
|
|
@@ -57,6 +58,7 @@ export function CartStickerState({ cartId, slug }) {
|
|
|
57
58
|
const q = useQuery({
|
|
58
59
|
queryKey: ["pick", "sticker-state", cartId, slug],
|
|
59
60
|
queryFn: () => fetchCartStickerState(cartId, slug),
|
|
61
|
+
enabled: !slug,
|
|
60
62
|
refetchInterval: POLL,
|
|
61
63
|
placeholderData: (prev) => prev,
|
|
62
64
|
retry: 1,
|
|
@@ -65,12 +67,12 @@ export function CartStickerState({ cartId, slug }) {
|
|
|
65
67
|
const u = useQuery({
|
|
66
68
|
queryKey: ["pick", "uitwijk", jobIds.join(",")],
|
|
67
69
|
queryFn: () => fetchUitwijk(jobIds),
|
|
68
|
-
enabled: jobIds.length > 0,
|
|
70
|
+
enabled: !slug && jobIds.length > 0,
|
|
69
71
|
refetchInterval: POLL,
|
|
70
72
|
placeholderData: (prev) => prev,
|
|
71
73
|
retry: 1,
|
|
72
74
|
});
|
|
73
|
-
if (q.
|
|
75
|
+
if (q.data === undefined && !q.isError)
|
|
74
76
|
return null;
|
|
75
77
|
if (q.isError || !q.data) {
|
|
76
78
|
return _jsx("p", { className: "mt-3 text-xs text-muted-foreground", children: STICKER_UNKNOWN });
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const STICKER_POLL = 15000;
|
|
2
|
+
/**
|
|
3
|
+
* Openbaar pickstation: stickerstand, controle, meldingen en uitwijk voor alle
|
|
4
|
+
* karren van de order in één aanroep. Vult de cache van de losse onderdelen,
|
|
5
|
+
* die met een slug zelf niet meer opvragen.
|
|
6
|
+
*/
|
|
7
|
+
export declare function useCartStickerStates(cartIds: string[], slug: string | null): import("@tanstack/react-query").UseQueryResult<import("../lib/pickStickerBundle.js").CartStickerBundleItem[], Error>;
|
|
8
|
+
//# sourceMappingURL=useCartStickerStates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCartStickerStates.d.ts","sourceRoot":"","sources":["../../src/hooks/useCartStickerStates.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,YAAY,QAAS,CAAC;AAEnC;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,qHA0B1E"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useEffect, useMemo } from "react";
|
|
2
|
+
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
3
|
+
import { supabase } from "@flowselections/core";
|
|
4
|
+
import { keyedRpc } from "../lib/pick159.js";
|
|
5
|
+
import { parseCartStickerBundle } from "../lib/pickStickerBundle.js";
|
|
6
|
+
import { pickMeasure } from "../lib/pickPerf.js";
|
|
7
|
+
const db = keyedRpc(supabase);
|
|
8
|
+
export const STICKER_POLL = 15000;
|
|
9
|
+
/**
|
|
10
|
+
* Openbaar pickstation: stickerstand, controle, meldingen en uitwijk voor alle
|
|
11
|
+
* karren van de order in één aanroep. Vult de cache van de losse onderdelen,
|
|
12
|
+
* die met een slug zelf niet meer opvragen.
|
|
13
|
+
*/
|
|
14
|
+
export function useCartStickerStates(cartIds, slug) {
|
|
15
|
+
const qc = useQueryClient();
|
|
16
|
+
const ids = useMemo(() => Array.from(new Set(cartIds.filter(Boolean))).sort(), [cartIds]);
|
|
17
|
+
const q = useQuery({
|
|
18
|
+
queryKey: ["pick", "sticker-bundle", slug, ids.join(",")],
|
|
19
|
+
enabled: !!slug && ids.length > 0,
|
|
20
|
+
refetchInterval: STICKER_POLL,
|
|
21
|
+
retry: 1,
|
|
22
|
+
queryFn: async () => {
|
|
23
|
+
const { data, error } = await pickMeasure("stickerstand", () => db.rpc("pickstation_cart_sticker_states", { p_slug: slug, p_cart_ids: ids }));
|
|
24
|
+
if (error)
|
|
25
|
+
throw new Error(error.message);
|
|
26
|
+
return parseCartStickerBundle(data);
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (!q.data)
|
|
31
|
+
return;
|
|
32
|
+
for (const k of q.data) {
|
|
33
|
+
qc.setQueryData(["pick", "sticker-state", k.cartId, slug], k.stand);
|
|
34
|
+
qc.setQueryData(["pick", "sticker-fit", k.cartId, slug], k.controle);
|
|
35
|
+
if (k.orderId)
|
|
36
|
+
qc.setQueryData(["pick", "sticker-meldingen", k.orderId, slug], k.meldingen);
|
|
37
|
+
qc.setQueryData(["pick", "uitwijk", k.jobIds.join(",")], k.uitwijk);
|
|
38
|
+
}
|
|
39
|
+
}, [q.data, qc, slug]);
|
|
40
|
+
return q;
|
|
41
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type PrintStatusResult } from "../lib/pickPrintStatus.js";
|
|
2
|
+
/**
|
|
3
|
+
* Eén aanroep voor alle zichtbare regels. Openbaar station (slug):
|
|
4
|
+
* pickstation_print_status; ingelogd scherm: logistics_print_status direct.
|
|
5
|
+
* Fout: "niet beschikbaar" met reden, nooit terugvallen op printed_at.
|
|
6
|
+
*/
|
|
7
|
+
export declare function fetchPrintStatus(ids: string[], slug: string | null): Promise<PrintStatusResult>;
|
|
8
|
+
export declare function usePickPrintStatus(ids: string[], slug: string | null, enabled?: boolean): {
|
|
9
|
+
result: PrintStatusResult | null;
|
|
10
|
+
loading: boolean;
|
|
11
|
+
inPrint: Set<string>;
|
|
12
|
+
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<PrintStatusResult, Error>>;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=usePickPrintStatus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePickPrintStatus.d.ts","sourceRoot":"","sources":["../../src/hooks/usePickPrintStatus.ts"],"names":[],"mappings":"AAIA,OAAO,EAAgC,KAAK,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAQ9F;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAgBrG;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,UAAO;;;;;EAkBpF"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
import { useQuery } from "@tanstack/react-query";
|
|
3
|
+
import { supabase } from "@flowselections/core";
|
|
4
|
+
import { keyedRpc } from "../lib/pick159.js";
|
|
5
|
+
import { inPrintIds, parsePrintStatus } from "../lib/pickPrintStatus.js";
|
|
6
|
+
import { pickMeasure } from "../lib/pickPerf.js";
|
|
7
|
+
const db = keyedRpc(supabase);
|
|
8
|
+
const MAX_IDS = 500;
|
|
9
|
+
/**
|
|
10
|
+
* Eén aanroep voor alle zichtbare regels. Openbaar station (slug):
|
|
11
|
+
* pickstation_print_status; ingelogd scherm: logistics_print_status direct.
|
|
12
|
+
* Fout: "niet beschikbaar" met reden, nooit terugvallen op printed_at.
|
|
13
|
+
*/
|
|
14
|
+
export async function fetchPrintStatus(ids, slug) {
|
|
15
|
+
const list = ids.slice(0, MAX_IDS);
|
|
16
|
+
const { data, error } = await pickMeasure("printstatus", () => slug
|
|
17
|
+
? db.rpc("pickstation_print_status", { p_slug: slug, p_queue_item_ids: list })
|
|
18
|
+
: db.rpc("logistics_print_status", { p_queue_item_ids: list }));
|
|
19
|
+
if (error) {
|
|
20
|
+
const missing = /could not find|does not exist|PGRST202/i.test(error.message);
|
|
21
|
+
return {
|
|
22
|
+
beschikbaar: false,
|
|
23
|
+
reden: missing ? "Printstatus nog niet beschikbaar: de Logistiek Engine is te oud." : "Printstatus kon niet worden opgehaald.",
|
|
24
|
+
byId: new Map(),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
return parsePrintStatus(data);
|
|
28
|
+
}
|
|
29
|
+
export function usePickPrintStatus(ids, slug, enabled = true) {
|
|
30
|
+
const sorted = useMemo(() => Array.from(new Set(ids)).sort(), [ids]);
|
|
31
|
+
const q = useQuery({
|
|
32
|
+
queryKey: ["pick", "printStatus", slug ?? "-", sorted.join(",")],
|
|
33
|
+
enabled: enabled && sorted.length > 0,
|
|
34
|
+
queryFn: () => fetchPrintStatus(sorted, slug),
|
|
35
|
+
refetchInterval: (query) => {
|
|
36
|
+
const d = query.state.data;
|
|
37
|
+
return d && inPrintIds(d).size > 0 ? 3000 : 20000;
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
const inPrint = useMemo(() => inPrintIds(q.data), [q.data]);
|
|
41
|
+
return {
|
|
42
|
+
result: q.data ?? null,
|
|
43
|
+
loading: sorted.length > 0 && q.data === undefined,
|
|
44
|
+
inPrint,
|
|
45
|
+
refetch: q.refetch,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -29,6 +29,8 @@ export declare function usePickQueue(args: {
|
|
|
29
29
|
pendingCount: number;
|
|
30
30
|
printedCount: number;
|
|
31
31
|
urgentCount: number;
|
|
32
|
+
/** Tellingen nog niet geladen: kopregel toont "…". */
|
|
33
|
+
countsLoading: boolean;
|
|
32
34
|
loading: boolean;
|
|
33
35
|
error: string | null;
|
|
34
36
|
lockedIds: Set<string>;
|
|
@@ -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;
|
|
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;AAK9E,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;;;;;;;IAqNG,sDAAsD;;;;;;IAMtD,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;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,CAAC,EAAE,SAAS,OAAO,EAAE,EAAE,CAAC,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAEpF"}
|