@flowselections/pick-schermen-kwekers 1.0.60 → 1.0.64

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.
Files changed (57) hide show
  1. package/dist-lib/components/pick/PickScherm.d.ts.map +1 -1
  2. package/dist-lib/components/pick/PickScherm.js +28 -10
  3. package/dist-lib/components/pick/QueueTable.d.ts +5 -1
  4. package/dist-lib/components/pick/QueueTable.d.ts.map +1 -1
  5. package/dist-lib/components/pick/QueueTable.js +14 -31
  6. package/dist-lib/components/pick/ShippingNoteScan.d.ts.map +1 -1
  7. package/dist-lib/components/pick/ShippingNoteScan.js +52 -13
  8. package/dist-lib/components/pick/StickerState.d.ts +4 -0
  9. package/dist-lib/components/pick/StickerState.d.ts.map +1 -1
  10. package/dist-lib/components/pick/StickerState.js +30 -4
  11. package/dist-lib/hooks/usePickPrintStatus.d.ts +14 -0
  12. package/dist-lib/hooks/usePickPrintStatus.d.ts.map +1 -0
  13. package/dist-lib/hooks/usePickPrintStatus.js +47 -0
  14. package/dist-lib/hooks/usePickQueue.d.ts +2 -0
  15. package/dist-lib/hooks/usePickQueue.d.ts.map +1 -1
  16. package/dist-lib/hooks/usePickQueue.js +29 -8
  17. package/dist-lib/integrations/supabase/types.d.ts +937 -7
  18. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  19. package/dist-lib/integrations/supabase/types.js +1 -0
  20. package/dist-lib/lib/__tests__/pick143.test.js +1 -1
  21. package/dist-lib/lib/__tests__/pick161.test.d.ts +2 -0
  22. package/dist-lib/lib/__tests__/pick161.test.d.ts.map +1 -0
  23. package/dist-lib/lib/__tests__/pick161.test.js +29 -0
  24. package/dist-lib/lib/__tests__/pick163.test.d.ts +2 -0
  25. package/dist-lib/lib/__tests__/pick163.test.d.ts.map +1 -0
  26. package/dist-lib/lib/__tests__/pick163.test.js +68 -0
  27. package/dist-lib/lib/__tests__/pickUitwijk.test.d.ts +2 -0
  28. package/dist-lib/lib/__tests__/pickUitwijk.test.d.ts.map +1 -0
  29. package/dist-lib/lib/__tests__/pickUitwijk.test.js +36 -0
  30. package/dist-lib/lib/pick143.d.ts +7 -2
  31. package/dist-lib/lib/pick143.d.ts.map +1 -1
  32. package/dist-lib/lib/pick143.js +24 -5
  33. package/dist-lib/lib/pick159.js +2 -2
  34. package/dist-lib/lib/pick161.d.ts +27 -0
  35. package/dist-lib/lib/pick161.d.ts.map +1 -0
  36. package/dist-lib/lib/pick161.js +86 -0
  37. package/dist-lib/lib/pickPerf.d.ts +11 -0
  38. package/dist-lib/lib/pickPerf.d.ts.map +1 -0
  39. package/dist-lib/lib/pickPerf.js +35 -0
  40. package/dist-lib/lib/pickPreview.d.ts.map +1 -1
  41. package/dist-lib/lib/pickPreview.js +2 -1
  42. package/dist-lib/lib/pickPrintStatus.d.ts +36 -0
  43. package/dist-lib/lib/pickPrintStatus.d.ts.map +1 -0
  44. package/dist-lib/lib/pickPrintStatus.js +98 -0
  45. package/dist-lib/lib/pickRowState.d.ts +2 -1
  46. package/dist-lib/lib/pickRowState.d.ts.map +1 -1
  47. package/dist-lib/lib/pickRowState.js +4 -2
  48. package/dist-lib/lib/pickStickers.d.ts +5 -0
  49. package/dist-lib/lib/pickStickers.d.ts.map +1 -1
  50. package/dist-lib/lib/pickStickers.js +3 -0
  51. package/dist-lib/lib/pickUitwijk.d.ts +25 -0
  52. package/dist-lib/lib/pickUitwijk.d.ts.map +1 -0
  53. package/dist-lib/lib/pickUitwijk.js +93 -0
  54. package/dist-lib/lib/shippingNote.d.ts +2 -0
  55. package/dist-lib/lib/shippingNote.d.ts.map +1 -1
  56. package/dist-lib/lib/shippingNote.js +2 -1
  57. package/package.json +1 -1
@@ -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;AA2D7B,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,+BAkqEpD"}
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;AA6D7B,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,+BA0rEpD"}
@@ -21,12 +21,14 @@ 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 { activeDeviceKey } from "../../lib/pick159.js";
24
26
  import { usePickDocumentTypes, usePickStatuses, useStationPrintPlek, } from "../../hooks/usePickConfig.js";
25
27
  import { usePrintBatch, usePrintJob } from "../../hooks/usePrintJob.js";
26
28
  import { useShippingNoteStatus } from "../../hooks/useShippingNoteStatus.js";
27
29
  import { firstVisibleTarget, isJobFinished, isRowGoneError, NO_ROW_IN_FILTER_MESSAGE, RELEASE_PENDING_MESSAGE, ROW_GONE_MESSAGE, stuckMessage, stuckMinutesOf, } from "../../lib/pickRowState.js";
28
30
  import { CartItemRows, PlanWarnings } from "./CartItemRows.js";
29
- import { CartStickerState, OrderStickerMeldingen, StickerFitMeldingen } from "./StickerState.js";
31
+ import { CartStickerState, OrderStickerMeldingen, StickerFitMeldingen, VroegeStickerWaarschuwing } from "./StickerState.js";
30
32
  import { StickerReprintButton } from "./StickerReprintButton.js";
31
33
  import { isJobFailed } from "../../lib/pick142.js";
32
34
  import { isPrintBlocked } from "../../lib/pick156.js";
@@ -144,15 +146,22 @@ export function PickScherm({ station, onBack }) {
144
146
  if (fetchingNotes)
145
147
  return;
146
148
  setFetchingNotes(true);
149
+ const id = toast.loading("Verzendbrieven ophalen…");
147
150
  try {
148
151
  const result = await refreshShippingNotesNow();
149
152
  if (result.ok) {
150
- toast.success(result.message ?? "Verzendbrieven worden opgehaald.");
153
+ toast.success(result.message ?? "Verzendbrieven worden opgehaald.", { id });
151
154
  }
152
155
  else {
153
- toast.info("De verzendbrieven worden zo vanzelf opgehaald. Je hoeft niets te doen.");
156
+ toast.info("De verzendbrieven worden zo vanzelf opgehaald. Je hoeft niets te doen.", { id });
154
157
  }
155
158
  }
159
+ catch (e) {
160
+ toast.error("Verzendbrieven ophalen lukte niet. Probeer het over een minuut opnieuw.", {
161
+ id,
162
+ description: e instanceof Error ? `Details voor beheer: ${e.message}` : undefined,
163
+ });
164
+ }
156
165
  finally {
157
166
  setFetchingNotes(false);
158
167
  }
@@ -212,12 +221,17 @@ export function PickScherm({ station, onBack }) {
212
221
  return () => clearTimeout(timer);
213
222
  }, [searchInput]);
214
223
  const effectiveFilters = useMemo(() => ({ ...filters, country: null, sortRules: [] }), [filters]);
215
- const { items, total, loading, lockedIds, refresh, pendingCount, printedCount, urgentCount, realtimeOk, pickDay, rebuiltAt, syncError, } = usePickQueue({
224
+ const { items, total, loading, lockedIds, refresh, pendingCount, printedCount, countsLoading, urgentCount, realtimeOk, pickDay, rebuiltAt, syncError, } = usePickQueue({
216
225
  stationId: station.id,
217
226
  filters: effectiveFilters,
218
227
  enabled: lang !== null,
219
228
  pickDayOverride: chosenDay,
220
229
  });
230
+ // 1.0.63: printstatus uit de Engine, één aanroep voor alle regels in beeld.
231
+ const printStatusIds = useMemo(() => (Array.isArray(items) ? items : []).map((i) => i.id), [items]);
232
+ const { result: printStatus, loading: printStatusLoading, inPrint, } = usePickPrintStatus(printStatusIds, activeDeviceKey() ? station.slug ?? null : null, lang !== null);
233
+ const inPrintRef = useRef(inPrint);
234
+ inPrintRef.current = inPrint;
221
235
  /** Geprint maar nog niet gescand, van een eerdere pickdag (blijft open tot de scan). */
222
236
  const viewDay = chosenDay ?? pickDay ?? null;
223
237
  const { data: earlierRaw, refetch: refetchEarlier } = useQuery({
@@ -660,6 +674,10 @@ export function PickScherm({ station, onBack }) {
660
674
  toast.warning(block);
661
675
  return;
662
676
  }
677
+ if (inPrintRef.current.has(item.id)) {
678
+ toast.info("Deze pakbon wordt al geprint. Wacht tot de printer klaar is.");
679
+ return;
680
+ }
663
681
  setBusyId(item.id);
664
682
  try {
665
683
  const claimed = await pickApi.claim({
@@ -911,7 +929,7 @@ export function PickScherm({ station, onBack }) {
911
929
  return;
912
930
  setBatchPrinting(true);
913
931
  try {
914
- const visible = (Array.isArray(items) ? items : []).filter((item) => !item.printed_at);
932
+ const visible = (Array.isArray(items) ? items : []).filter((item) => !item.printed_at && !inPrintRef.current.has(item.id));
915
933
  const targets = [];
916
934
  const skipped = [];
917
935
  for (const item of visible) {
@@ -965,7 +983,7 @@ export function PickScherm({ station, onBack }) {
965
983
  setBusyId("next");
966
984
  let claimed = null;
967
985
  try {
968
- const target = firstVisibleTarget(itemsRef.current, lockedIds);
986
+ const target = firstVisibleTarget(itemsRef.current, lockedIds, inPrintRef.current);
969
987
  const filtered = !!filters.search.trim() || !!filters.documentTypeId || filters.urgentOnly || !!filters.country;
970
988
  if (target) {
971
989
  // De rij die in beeld staat (ook met zoekfilter), niet de bovenste van de hele wachtrij.
@@ -1359,7 +1377,7 @@ export function PickScherm({ station, onBack }) {
1359
1377
  ? "Pickwachtrij laden…"
1360
1378
  : checkDone > 0
1361
1379
  ? `Pakbonnen controleren (${checkDone} van ${checkTotal})…`
1362
- : `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: () => {
1380
+ : `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: () => {
1363
1381
  setCartMissing(false);
1364
1382
  setRowGone(false);
1365
1383
  setPending(null);
@@ -1371,7 +1389,7 @@ export function PickScherm({ station, onBack }) {
1371
1389
  const cart = plannedCart ?? { cartId: r.cartId, cartLabel: r.cartLabel ?? r.cartId };
1372
1390
  setLastCartResults((prev) => prev.filter((x) => x.cartId !== r.cartId));
1373
1391
  void reprintCart(lastPrinted, cart);
1374
- }, 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(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
1392
+ }, 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
1375
1393
  ? "De pakbon wordt opgevraagd. Zodra alles compleet is, verschijnt de printknop weer."
1376
1394
  : planReason
1377
1395
  ? `${planReason} Klik op "Pakbon ophalen" om hem op te vragen.`
@@ -1427,8 +1445,8 @@ export function PickScherm({ station, onBack }) {
1427
1445
  (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
1428
1446
  ? `Volgende poging: ${formatSiteTime(note.state.nextAttemptAt, siteTz)}`
1429
1447
  : ""] }))] })] }, note.jobId));
1430
- })] }) })), _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 () => {
1448
+ })] }) })), _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 () => {
1431
1449
  await printAllForItem(row);
1432
1450
  void refetchEarlier();
1433
- }, 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) })] }));
1451
+ }, 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) })] }));
1434
1452
  }
@@ -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;AAUvF,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,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,MAAM,EACN,SAAS,EACT,UAAU,EACV,eAAe,EACf,aAAa,EACb,SAAS,EAGT,QAAQ,EACR,CAAC,EAAE,UAAU,EACb,YAAmB,EACnB,OAAc,GACf,EAAE,KAAK,+BAggBP"}
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 { useQuery } from "@tanstack/react-query";
9
- import { pickApi } from "../../lib/pickApi.js";
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(RowPrintBadge, { printed: printed, hasJob: !!item.print_job_id, job: item.print_job_id ? jobsById.get(item.print_job_id) : undefined, jobsLoaded: jobsLoaded, toPrintLabel: t("statusToPrint") }), printed && (_jsx("div", { className: "mt-1 text-xs text-muted-foreground", children: new Date(item.printed_at).toLocaleTimeString([], {
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(RowPrintBadge, { printed: printed, hasJob: !!item.print_job_id, job: item.print_job_id ? jobsById.get(item.print_job_id) : undefined, jobsLoaded: jobsLoaded, toPrintLabel: t("statusToPrint") }), printed && (_jsx("span", { className: "text-xs text-muted-foreground", children: new Date(item.printed_at).toLocaleTimeString([], {
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 RowPrintBadge({ printed, hasJob, job, jobsLoaded, toPrintLabel }) {
200
- if (!printed)
201
- return _jsx(Badge, { variant: "default", children: toPrintLabel });
202
- if (!hasJob)
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
- return (_jsx(Badge, { variant: stage === "failed" ? "destructive" : "secondary", children: printStageLabel(job) }));
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":"ShippingNoteScan.d.ts","sourceRoot":"","sources":["../../../src/components/pick/ShippingNoteScan.tsx"],"names":[],"mappings":"AASA,UAAU,KAAK;IACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,yEAAyE;IACzE,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,KAAK,IAAI,CAAC;CACxE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE,KAAK,+BA0LlE"}
1
+ {"version":3,"file":"ShippingNoteScan.d.ts","sourceRoot":"","sources":["../../../src/components/pick/ShippingNoteScan.tsx"],"names":[],"mappings":"AAkBA,UAAU,KAAK;IACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,yEAAyE;IACzE,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,KAAK,IAAI,CAAC;CACxE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE,KAAK,+BA0NlE"}
@@ -3,6 +3,16 @@ import { useCallback, useState } from "react";
3
3
  import { Badge, Button, Card, CardContent, Input, toast } from "@flowselections/core";
4
4
  import { AlertTriangle, CheckCircle2, Loader2, ScanLine } from "lucide-react";
5
5
  import { createShippingNote, lookupBarcode, } from "../../lib/shippingNote.js";
6
+ import { friendlyEngineMessage, isPakbonNumber, quantityText, SCAN_UNKNOWN, slipVariantText } from "../../lib/pick161.js";
7
+ import { pickDb } from "../../lib/pickApi.js";
8
+ async function toCartBarcode(code) {
9
+ if (!isPakbonNumber(code))
10
+ return code;
11
+ const { data, error } = await pickDb.rpc("pick_resolve_scan_code", { p_code: code });
12
+ if (error)
13
+ throw new Error(error.message);
14
+ return typeof data === "string" && data ? data : null;
15
+ }
6
16
  /**
7
17
  * Pakbon scannen -> verzendbrief. De module zoekt eerst op (leest alleen) en
8
18
  * maakt pas na een expliciete bevestiging een verzendbrief aan via de Engine.
@@ -11,7 +21,19 @@ export function ShippingNoteScan({ stationId, onJobCreated }) {
11
21
  const [code, setCode] = useState("");
12
22
  const [busy, setBusy] = useState(false);
13
23
  const [found, setFound] = useState(null);
14
- const [notice, setNotice] = useState(null);
24
+ const [notice, setNoticeRaw] = useState(null);
25
+ const [detail, setDetail] = useState(null);
26
+ const [status, setStatus] = useState(null);
27
+ const setNotice = useCallback((raw, fallback = SCAN_UNKNOWN) => {
28
+ if (raw == null) {
29
+ setNoticeRaw(null);
30
+ setDetail(null);
31
+ return;
32
+ }
33
+ const f = friendlyEngineMessage(raw, fallback);
34
+ setNoticeRaw(f.message);
35
+ setDetail(f.detail);
36
+ }, []);
15
37
  const [reprintNotice, setReprintNotice] = useState(null);
16
38
  const [warning, setWarning] = useState(null);
17
39
  const reset = useCallback(() => {
@@ -23,31 +45,43 @@ export function ShippingNoteScan({ stationId, onJobCreated }) {
23
45
  const barcode = raw.trim();
24
46
  if (!barcode)
25
47
  return;
48
+ let found_barcode = barcode;
26
49
  setBusy(true);
27
50
  reset();
28
51
  setNotice(null);
52
+ setStatus("Pakbon opzoeken…");
29
53
  try {
30
- const lookup = await lookupBarcode(barcode);
54
+ const cartBarcode = await toCartBarcode(barcode);
55
+ if (!cartBarcode) {
56
+ setNotice(null);
57
+ setNoticeRaw(SCAN_UNKNOWN);
58
+ return;
59
+ }
60
+ const lookup = await lookupBarcode(cartBarcode);
31
61
  if (!lookup.ok) {
32
- // De RPC levert een kant-en-klare melding; die tonen we letterlijk.
33
- setNotice(lookup.error ?? "De barcode kon niet worden opgezocht.");
62
+ setNoticeRaw(SCAN_UNKNOWN);
63
+ setDetail(lookup.error);
34
64
  return;
35
65
  }
36
- setFound({ barcode, lookup });
66
+ found_barcode = cartBarcode;
67
+ setFound({ barcode: found_barcode, lookup });
37
68
  setCode("");
38
69
  }
39
70
  catch (e) {
40
- setNotice(e instanceof Error ? e.message : "De barcode kon niet worden opgezocht.");
71
+ setNoticeRaw("De pakbon kon niet worden opgezocht. Probeer het opnieuw.");
72
+ setDetail(e instanceof Error ? e.message : null);
41
73
  }
42
74
  finally {
43
75
  setBusy(false);
76
+ setStatus(null);
44
77
  }
45
- }, [reset]);
78
+ }, [reset, setNotice]);
46
79
  const handleConfirm = useCallback(async (allowReprint) => {
47
80
  if (!found)
48
81
  return;
49
82
  setBusy(true);
50
83
  setWarning(null);
84
+ setStatus("Verzendbrief klaarzetten…");
51
85
  try {
52
86
  const result = await createShippingNote({
53
87
  barcode: found.barcode,
@@ -56,10 +90,12 @@ export function ShippingNoteScan({ stationId, onJobCreated }) {
56
90
  });
57
91
  if (!result.ok) {
58
92
  if (result.errorCode === "al_geprint") {
59
- setReprintNotice(result.error ?? "Er is al een verzendbrief voor deze kar gemaakt.");
93
+ setReprintNotice("Er is al een verzendbrief voor deze kar gemaakt.");
60
94
  return;
61
95
  }
62
- setNotice(result.error ?? "De verzendbrief kon niet worden klaargezet.");
96
+ setNotice(result.error ?? result.errorCode ?? null, "De verzendbrief kon niet worden klaargezet. Meld dit bij kantoor.");
97
+ if (!result.error && !result.errorCode)
98
+ setNoticeRaw("De verzendbrief kon niet worden klaargezet. Meld dit bij kantoor.");
63
99
  reset();
64
100
  return;
65
101
  }
@@ -73,17 +109,20 @@ export function ShippingNoteScan({ stationId, onJobCreated }) {
73
109
  setReprintNotice(null);
74
110
  }
75
111
  catch (e) {
76
- setNotice(e instanceof Error ? e.message : "De verzendbrief kon niet worden klaargezet.");
112
+ setNotice(e instanceof Error ? e.message : null, "De verzendbrief kon niet worden klaargezet. Probeer het opnieuw.");
113
+ if (!(e instanceof Error))
114
+ setNoticeRaw("De verzendbrief kon niet worden klaargezet. Probeer het opnieuw.");
77
115
  }
78
116
  finally {
79
117
  setBusy(false);
118
+ setStatus(null);
80
119
  }
81
- }, [found, stationId, onJobCreated, reset]);
120
+ }, [found, stationId, onJobCreated, reset, setNotice]);
82
121
  const cart = found?.lookup.cart ?? null;
83
- return (_jsx(Card, { children: _jsxs(CardContent, { className: "space-y-3 p-3 sm:p-4", children: [_jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between", children: [_jsx("p", { className: "text-sm font-semibold text-foreground", children: "Pakbon scannen" }), _jsxs("div", { className: "relative w-full min-w-0 sm:w-72", children: [_jsx(ScanLine, { 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: "Barcode van de pakbon", value: code, disabled: busy, onChange: (e) => setCode(e.target.value), onKeyDown: (e) => {
122
+ return (_jsx(Card, { children: _jsxs(CardContent, { className: "space-y-3 p-3 sm:p-4", children: [_jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between", children: [_jsx("p", { className: "text-sm font-semibold text-foreground", children: "Pakbon scannen" }), _jsxs("div", { className: "relative w-full min-w-0 sm:w-72", children: [_jsx(ScanLine, { 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: "Pakbonnummer of barcode onderaan de pakbon", value: code, disabled: busy, onChange: (e) => setCode(e.target.value), onKeyDown: (e) => {
84
123
  if (e.key !== "Enter")
85
124
  return;
86
125
  e.preventDefault();
87
126
  void handleLookup(code);
88
- } })] })] }), notice && (_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: notice })] })), warning && (_jsxs("div", { className: "flex items-start gap-2 rounded-md border p-3 text-sm text-muted-foreground", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0" }), _jsx("span", { children: warning })] })), found && (_jsxs("div", { className: "rounded-md border-2 border-primary/40 bg-muted/20 p-3 sm:p-4", children: [_jsxs("div", { className: "flex flex-wrap items-start justify-between gap-2", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "truncate text-lg font-bold text-foreground", children: found.lookup.orderNumber ?? "Order" }), _jsx("p", { className: "truncate text-sm text-muted-foreground", children: [found.lookup.customerName, cart?.cartLabel].filter(Boolean).join(" · ") })] }), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [cart?.slipVariant && _jsx(Badge, { variant: "outline", children: cart.slipVariant }), cart?.barcode && _jsx(Badge, { variant: "outline", children: cart.barcode }), found.lookup.alreadyPrinted && (_jsxs(Badge, { className: "bg-destructive text-destructive-foreground", children: ["Al geprint (", found.lookup.printCount, ")"] }))] })] }), _jsx("div", { className: "mt-3 divide-y rounded-md border bg-background", children: cart && cart.items.length > 0 ? (cart.items.map((item, index) => (_jsxs("div", { className: "flex items-center justify-between gap-3 p-3", children: [_jsx("span", { className: "min-w-0 truncate text-sm text-foreground", children: item.productName }), _jsx("span", { className: "shrink-0 text-sm font-semibold text-foreground", children: item.quantity ?? 0 })] }, `${item.productName}-${index}`)))) : (_jsx("p", { className: "p-3 text-sm text-muted-foreground", children: "Geen regels bij deze kar." })) }), reprintNotice && (_jsxs("div", { className: "mt-3 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: reprintNotice })] })), _jsxs("div", { className: "mt-3 flex flex-col gap-2 sm:flex-row sm:justify-end", children: [_jsx(Button, { variant: "outline", size: "lg", className: "h-12 w-full sm:w-auto", onClick: reset, disabled: busy, children: "Annuleren" }), _jsxs(Button, { size: "lg", className: "h-12 w-full sm:w-auto", onClick: () => void handleConfirm(reprintNotice !== null), disabled: busy, children: [busy ? (_jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" })) : (_jsx(CheckCircle2, { className: "mr-2 h-5 w-5" })), reprintNotice ? "Toch opnieuw printen" : "Verzendbrief klaarzetten"] })] })] }))] }) }));
127
+ } })] })] }), notice && (_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: notice })] })), status && (_jsxs("p", { role: "status", className: "flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), " ", status] })), detail && notice && (_jsxs("details", { className: "text-xs text-muted-foreground", children: [_jsx("summary", { className: "cursor-pointer", children: "Details voor beheer" }), _jsx("p", { children: detail })] })), warning && (_jsxs("div", { className: "flex items-start gap-2 rounded-md border p-3 text-sm text-muted-foreground", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0" }), _jsx("span", { children: warning })] })), found && (_jsxs("div", { className: "rounded-md border-2 border-primary/40 bg-muted/20 p-3 sm:p-4", children: [_jsxs("div", { className: "flex flex-wrap items-start justify-between gap-2", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "truncate text-lg font-bold text-foreground", children: found.lookup.orderNumber ?? "Order" }), _jsx("p", { className: "truncate text-sm text-muted-foreground", children: [found.lookup.customerName, cart?.cartLabel].filter(Boolean).join(" · ") })] }), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [slipVariantText(cart?.slipVariant) && _jsx(Badge, { variant: "outline", children: slipVariantText(cart?.slipVariant) }), cart?.barcode && _jsx(Badge, { variant: "outline", children: cart.barcode }), found.lookup.alreadyPrinted && (_jsxs(Badge, { className: "bg-destructive text-destructive-foreground", children: ["Al geprint (", found.lookup.printCount, ")"] }))] })] }), _jsx("div", { className: "mt-3 divide-y rounded-md border bg-background", children: cart && cart.items.length > 0 ? (cart.items.map((item, index) => (_jsxs("div", { className: "flex items-center justify-between gap-3 p-3", children: [_jsx("span", { className: "min-w-0 truncate text-sm text-foreground", children: item.productName }), _jsx("span", { className: "shrink-0 text-sm font-semibold text-foreground", children: quantityText(item.quantity, item.crates) })] }, `${item.productName}-${index}`)))) : (_jsx("p", { className: "p-3 text-sm text-muted-foreground", children: "Geen regels bij deze kar." })) }), reprintNotice && (_jsxs("div", { className: "mt-3 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: reprintNotice })] })), _jsxs("div", { className: "mt-3 flex flex-col gap-2 sm:flex-row sm:justify-end", children: [_jsx(Button, { variant: "outline", size: "lg", className: "h-12 w-full sm:w-auto", onClick: reset, disabled: busy, children: "Annuleren" }), _jsxs(Button, { size: "lg", className: "h-12 w-full sm:w-auto", onClick: () => void handleConfirm(reprintNotice !== null), disabled: busy, children: [busy ? (_jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" })) : (_jsx(CheckCircle2, { className: "mr-2 h-5 w-5" })), reprintNotice ? "Toch opnieuw printen" : "Verzendbrief klaarzetten"] })] })] }))] }) }));
89
128
  }
@@ -13,4 +13,8 @@ export declare function CartStickerState({ cartId, slug }: {
13
13
  cartId: string;
14
14
  slug: string | null;
15
15
  }): import("react").JSX.Element | null;
16
+ /** Bovenaan het pickstation: stickers die vandaag/morgen via A4 of verkleind gaan. Niets als Layouts het nog niet levert. */
17
+ export declare function VroegeStickerWaarschuwing({ stationId }: {
18
+ stationId: string | null;
19
+ }): import("react").JSX.Element | null;
16
20
  //# sourceMappingURL=StickerState.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"StickerState.d.ts","sourceRoot":"","sources":["../../../src/components/pick/StickerState.tsx"],"names":[],"mappings":"AAaA,+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,sCAuC5F;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,sCAqCzF"}
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,sCAuC5F;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,sCA8CzF;AAED,6HAA6H;AAC7H,wBAAgB,yBAAyB,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,sCAiBpF"}
@@ -1,6 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useQuery } from "@tanstack/react-query";
3
- import { fetchCartStickerState, fetchOrderStickerMeldingen, STICKER_UNKNOWN, stickerStatusLabel, stickerSummary, } from "../../lib/pickStickers.js";
3
+ import { fetchCartStickerState, fetchOrderStickerMeldingen, STICKER_UNKNOWN, stickerStatusLabel, } from "../../lib/pickStickers.js";
4
+ import { stickerLine } from "../../lib/pick161.js";
5
+ import { fetchUitwijk, fetchVroegeWaarschuwing, vroegeWaarschuwingText } from "../../lib/pickUitwijk.js";
4
6
  import { fetchStickerFit, STICKER_FIT_UNKNOWN, stickerFitTone } from "../../lib/pick150.js";
5
7
  const POLL = 15000;
6
8
  /** Controle vooraf of de klantstickers van de kar passen; vóór het printen. */
@@ -59,15 +61,39 @@ export function CartStickerState({ cartId, slug }) {
59
61
  placeholderData: (prev) => prev,
60
62
  retry: 1,
61
63
  });
64
+ const jobIds = Array.isArray(q.data?.regels) ? q.data.regels.map((r) => r.printJobId).filter((x) => !!x).sort() : [];
65
+ const u = useQuery({
66
+ queryKey: ["pick", "uitwijk", jobIds.join(",")],
67
+ queryFn: () => fetchUitwijk(jobIds),
68
+ enabled: jobIds.length > 0,
69
+ refetchInterval: POLL,
70
+ placeholderData: (prev) => prev,
71
+ retry: 1,
72
+ });
62
73
  if (q.isLoading)
63
74
  return null;
64
75
  if (q.isError || !q.data) {
65
76
  return _jsx("p", { className: "mt-3 text-xs text-muted-foreground", children: STICKER_UNKNOWN });
66
77
  }
67
78
  const s = q.data;
79
+ const line = stickerLine(s, u.data);
68
80
  const regels = Array.isArray(s.regels) ? s.regels : [];
69
- const summary = stickerSummary(s);
70
81
  if (s.totaal === 0)
71
- return _jsx("p", { className: "mt-3 text-xs text-muted-foreground", children: summary });
72
- return (_jsxs("details", { className: "mt-3 rounded-md border bg-background p-3 text-sm", children: [_jsxs("summary", { className: "cursor-pointer font-medium text-foreground", children: ["Stickers: ", s.totaal ?? regels.length, " \u00B7 in de printwachtrij ", s.inPrintwachtrij ?? "—", " \u00B7 wachtend ", s.wachtend ?? "—", " \u00B7 geblokkeerd ", s.geblokkeerd ?? "—"] }), _jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: "In de printwachtrij betekent nog niet fysiek geprint." }), _jsx("ul", { className: "mt-2 divide-y", children: regels.map((r, i) => (_jsxs("li", { className: "flex flex-wrap justify-between gap-2 py-1.5 text-xs", children: [_jsxs("span", { className: "text-foreground", children: [r.soort ?? "sticker", " \u00B7 ", r.kopieen ?? "—", "x", r.breedteMm && r.hoogteMm ? ` · ${r.breedteMm}x${r.hoogteMm} mm` : ""] }), _jsxs("span", { className: "text-muted-foreground", children: [stickerStatusLabel(r.status), r.reden ? ` — ${r.reden}` : ""] })] }, r.stickerId ?? i))) })] }));
82
+ return _jsx("p", { className: "mt-3 text-sm text-muted-foreground", children: line });
83
+ return (_jsxs("details", { className: "mt-3 rounded-md border bg-background p-3 text-sm", children: [_jsxs("summary", { className: "cursor-pointer font-medium text-foreground", children: ["Stickers: ", line] }), _jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: "In de printwachtrij betekent nog niet fysiek geprint." }), _jsx("ul", { className: "mt-2 divide-y", children: regels.map((r, i) => (_jsxs("li", { className: "flex flex-wrap justify-between gap-2 py-1.5 text-xs", children: [_jsxs("span", { className: "text-foreground", children: [r.soort ?? "sticker", " \u00B7 ", r.kopieen ?? "—", "x", r.breedteMm && r.hoogteMm ? ` · ${r.breedteMm}x${r.hoogteMm} mm` : ""] }), _jsxs("span", { className: "text-muted-foreground", children: [stickerStatusLabel(r.status), r.reden ? ` — ${r.reden}` : ""] })] }, r.stickerId ?? i))) })] }));
84
+ }
85
+ /** Bovenaan het pickstation: stickers die vandaag/morgen via A4 of verkleind gaan. Niets als Layouts het nog niet levert. */
86
+ export function VroegeStickerWaarschuwing({ stationId }) {
87
+ const q = useQuery({
88
+ queryKey: ["pick", "vroege-sticker", stationId],
89
+ queryFn: () => fetchVroegeWaarschuwing(stationId),
90
+ refetchInterval: 5 * 60000,
91
+ placeholderData: (prev) => prev,
92
+ retry: 1,
93
+ });
94
+ const list = Array.isArray(q.data) ? q.data : [];
95
+ if (list.length === 0)
96
+ return null;
97
+ const today = new Date().toLocaleDateString("sv-SE");
98
+ return (_jsxs("div", { role: "status", className: "mb-3 space-y-1 rounded-md border-2 border-primary/40 bg-primary/5 p-3 text-sm text-foreground", children: [_jsx("p", { className: "font-medium", children: "Let op: stickers passen niet op het gewone etiket" }), list.map((w, i) => _jsx("p", { children: vroegeWaarschuwingText(w, today) }, i))] }));
73
99
  }
@@ -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"}