@flowselections/pick-schermen-kwekers 1.0.10 → 1.0.12

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 (45) hide show
  1. package/README.md +24 -24
  2. package/dist-lib/components/PickPublicPage.js +1 -1
  3. package/dist-lib/components/PickstationsPage.d.ts.map +1 -1
  4. package/dist-lib/components/PickstationsPage.js +23 -8
  5. package/dist-lib/components/TemplateModulePage.d.ts +2 -0
  6. package/dist-lib/components/TemplateModulePage.d.ts.map +1 -0
  7. package/dist-lib/components/TemplateModulePage.js +44 -0
  8. package/dist-lib/components/pick/LanguageTiles.d.ts.map +1 -1
  9. package/dist-lib/components/pick/LanguageTiles.js +3 -3
  10. package/dist-lib/components/pick/PickScherm.d.ts.map +1 -1
  11. package/dist-lib/components/pick/PickScherm.js +73 -11
  12. package/dist-lib/components/pick/QueueTable.d.ts.map +1 -1
  13. package/dist-lib/components/pick/QueueTable.js +22 -12
  14. package/dist-lib/hooks/usePickConfig.d.ts +6 -0
  15. package/dist-lib/hooks/usePickConfig.d.ts.map +1 -1
  16. package/dist-lib/hooks/usePickConfig.js +19 -0
  17. package/dist-lib/hooks/usePickQueue.d.ts +4 -0
  18. package/dist-lib/hooks/usePickQueue.d.ts.map +1 -1
  19. package/dist-lib/hooks/usePickQueue.js +38 -7
  20. package/dist-lib/hooks/usePrintJob.d.ts.map +1 -1
  21. package/dist-lib/hooks/usePrintJob.js +13 -2
  22. package/dist-lib/integrations/supabase/auth-middleware.d.ts +2084 -310
  23. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  24. package/dist-lib/integrations/supabase/client.d.ts +2084 -310
  25. package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
  26. package/dist-lib/integrations/supabase/client.js +2 -1
  27. package/dist-lib/integrations/supabase/client.server.d.ts +2084 -310
  28. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  29. package/dist-lib/integrations/supabase/previewAuthStorage.d.ts +6 -0
  30. package/dist-lib/integrations/supabase/previewAuthStorage.d.ts.map +1 -0
  31. package/dist-lib/integrations/supabase/previewAuthStorage.js +92 -0
  32. package/dist-lib/integrations/supabase/types.d.ts +2168 -351
  33. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  34. package/dist-lib/integrations/supabase/types.js +3 -0
  35. package/dist-lib/lib/layoutMaker/pakbonHtml.js +49 -49
  36. package/dist-lib/lib/layoutRenderer.js +17 -17
  37. package/dist-lib/lib/pickApi.d.ts +20 -5
  38. package/dist-lib/lib/pickApi.d.ts.map +1 -1
  39. package/dist-lib/lib/pickApi.js +76 -17
  40. package/dist-lib/lib/pickTypes.d.ts +15 -0
  41. package/dist-lib/lib/pickTypes.d.ts.map +1 -1
  42. package/dist-lib/lib/pickUiText.d.ts +29 -0
  43. package/dist-lib/lib/pickUiText.d.ts.map +1 -0
  44. package/dist-lib/lib/pickUiText.js +71 -0
  45. package/package.json +1 -1
package/README.md CHANGED
@@ -1,24 +1,24 @@
1
- # pick schermen kwekers
2
-
3
- blank project start
4
-
5
- This project was built with [Lovable](https://lovable.dev).
6
-
7
- ## Build with Lovable
8
-
9
- Continue developing this project in the [Lovable editor](https://lovable.dev/projects/f7462658-1d60-42f1-8e22-dbefe36f44ef).
10
-
11
- - **Ship faster**: describe what you want to build and Lovable handles the code.
12
- - **Stay in sync**: every change made in Lovable is committed straight to this repository.
13
- - **Full ownership**: this code is yours. Push to `main` on GitHub and your changes sync back into Lovable, ready for your next prompt.
14
-
15
- ## Development
16
-
17
- Prefer working locally? You need Node.js and npm — [install with nvm](https://github.com/nvm-sh/nvm#installing-and-updating).
18
-
19
- ```sh
20
- git clone <this-repository-url>
21
- cd <repository-name>
22
- npm i
23
- npm run dev
24
- ```
1
+ # pick schermen kwekers
2
+
3
+ blank project start
4
+
5
+ This project was built with [Lovable](https://lovable.dev).
6
+
7
+ ## Build with Lovable
8
+
9
+ Continue developing this project in the [Lovable editor](https://lovable.dev/projects/f7462658-1d60-42f1-8e22-dbefe36f44ef).
10
+
11
+ - **Ship faster**: describe what you want to build and Lovable handles the code.
12
+ - **Stay in sync**: every change made in Lovable is committed straight to this repository.
13
+ - **Full ownership**: this code is yours. Push to `main` on GitHub and your changes sync back into Lovable, ready for your next prompt.
14
+
15
+ ## Development
16
+
17
+ Prefer working locally? You need Node.js and npm — [install with nvm](https://github.com/nvm-sh/nvm#installing-and-updating).
18
+
19
+ ```sh
20
+ git clone <this-repository-url>
21
+ cd <repository-name>
22
+ npm i
23
+ npm run dev
24
+ ```
@@ -15,5 +15,5 @@ export function PickPublicPage({ slug }) {
15
15
  if (!station) {
16
16
  return (_jsx("div", { className: "flex min-h-screen items-center justify-center bg-background", children: _jsx("p", { className: "text-muted-foreground", children: "Pickstation niet gevonden of niet actief." }) }));
17
17
  }
18
- return (_jsx("div", { className: "min-h-screen bg-background p-6", children: _jsx(PickScherm, { station: station }) }));
18
+ return (_jsx("div", { className: "min-h-screen bg-background p-3 sm:p-6", children: _jsx(PickScherm, { station: station }) }));
19
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PickstationsPage.d.ts","sourceRoot":"","sources":["../../src/components/PickstationsPage.tsx"],"names":[],"mappings":"AAmCA,wBAAgB,gBAAgB,gCAkL/B"}
1
+ {"version":3,"file":"PickstationsPage.d.ts","sourceRoot":"","sources":["../../src/components/PickstationsPage.tsx"],"names":[],"mappings":"AAwDA,wBAAgB,gBAAgB,gCA2O/B"}
@@ -1,41 +1,55 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from "react";
3
3
  import { useMutation, useQueryClient } from "@tanstack/react-query";
4
- import { Button, Card, CardContent, Dialog, DialogContent, DialogHeader, DialogTitle, Input, Label, Switch, Textarea, toast, } from "@flowselections/core";
5
- import { Copy, ExternalLink, Loader2, Pencil, Plus, Trash2 } from "lucide-react";
4
+ import { Button, Card, CardContent, Dialog, DialogContent, DialogHeader, DialogTitle, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Switch, Textarea, toast, } from "@flowselections/core";
5
+ import { AlertTriangle, Copy, ExternalLink, Loader2, Pencil, Plus, Printer, Trash2, } from "lucide-react";
6
6
  import { pickApi } from "../lib/pickApi";
7
- import { usePickStations } from "../hooks/usePickConfig";
8
- const emptyDraft = { name: "", description: "", active: true };
7
+ import { usePickPrintPlekken, usePickStations, useStationPrintPlekken, } from "../hooks/usePickConfig";
8
+ const NO_PLEK = "__geen__";
9
+ const emptyDraft = { name: "", description: "", active: true, printPlekId: null };
9
10
  function publicUrl(slug) {
10
11
  const origin = typeof window !== "undefined" ? window.location.origin : "";
11
12
  return `${origin}/pickstation/${slug ?? ""}`;
12
13
  }
13
14
  export function PickstationsPage() {
14
15
  const { data: stations, isLoading } = usePickStations();
16
+ const { data: printPlekken } = usePickPrintPlekken();
17
+ const { data: koppelingen } = useStationPrintPlekken();
15
18
  const queryClient = useQueryClient();
16
19
  const [draft, setDraft] = useState(null);
17
20
  const safeStations = Array.isArray(stations) ? stations : [];
21
+ const safePlekken = Array.isArray(printPlekken) ? printPlekken : [];
22
+ const safeKoppelingen = Array.isArray(koppelingen) ? koppelingen : [];
23
+ const plekOf = (stationId) => safeKoppelingen.find((k) => k.station_id === stationId) ?? null;
18
24
  const save = useMutation({
19
25
  mutationFn: async (d) => {
20
- await pickApi.upsert("pick_stations", {
26
+ const row = await pickApi.upsert("pick_stations", {
21
27
  ...(d.id ? { id: d.id } : {}),
22
28
  name: d.name.trim(),
23
29
  description: d.description.trim() || null,
24
30
  active: d.active,
25
31
  });
32
+ const stationId = d.id ?? row?.["id"] ?? null;
33
+ if (stationId)
34
+ await pickApi.setStationPrintPlek(stationId, d.printPlekId);
26
35
  },
27
36
  onSuccess: () => {
28
37
  toast.success("Pickstation opgeslagen.");
29
38
  setDraft(null);
30
39
  queryClient.invalidateQueries({ queryKey: ["pick", "stations"] });
40
+ queryClient.invalidateQueries({ queryKey: ["pick", "stationPrintPlekken"] });
31
41
  },
32
42
  onError: (e) => toast.error(e instanceof Error ? e.message : "Opslaan mislukt."),
33
43
  });
34
44
  const remove = useMutation({
35
- mutationFn: (id) => pickApi.remove("pick_stations", id),
45
+ mutationFn: async (id) => {
46
+ await pickApi.setStationPrintPlek(id, null);
47
+ await pickApi.remove("pick_stations", id);
48
+ },
36
49
  onSuccess: () => {
37
50
  toast.success("Pickstation verwijderd.");
38
51
  queryClient.invalidateQueries({ queryKey: ["pick", "stations"] });
52
+ queryClient.invalidateQueries({ queryKey: ["pick", "stationPrintPlekken"] });
39
53
  },
40
54
  onError: (e) => toast.error(e instanceof Error ? e.message : "Verwijderen mislukt."),
41
55
  });
@@ -52,10 +66,11 @@ export function PickstationsPage() {
52
66
  return (_jsxs("main", { className: "space-y-6 p-6", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-bold text-foreground", children: "Pickstations" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Beheer je pickstations en hun openbare link. Alle logica komt uit de Logistiek Engine." })] }), _jsxs(Button, { onClick: () => setDraft({ ...emptyDraft }), children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), " Nieuw pickstation"] })] }), isLoading ? (_jsxs("div", { className: "flex items-center gap-2 text-muted-foreground", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), " Laden..."] })) : safeStations.length === 0 ? (_jsx("p", { className: "text-sm text-muted-foreground", children: "Nog geen pickstations." })) : (_jsx("div", { className: "grid gap-4 sm:grid-cols-2 xl:grid-cols-3", children: safeStations.map((station) => (_jsx(Card, { className: "border-2", children: _jsxs(CardContent, { className: "space-y-4 p-6", children: [_jsxs("div", { className: "flex items-start justify-between gap-2", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-lg font-semibold text-foreground", children: station.name }), _jsx("p", { className: "text-sm text-muted-foreground", children: station.description })] }), _jsx("span", { className: "rounded-full px-2 py-1 text-xs font-medium " +
53
67
  (station.active
54
68
  ? "bg-primary/10 text-primary"
55
- : "bg-muted text-muted-foreground"), children: station.active ? "Actief" : "Inactief" })] }), _jsx("code", { className: "block truncate rounded bg-muted px-2 py-1 text-xs text-muted-foreground", children: publicUrl(station.slug) }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Button, { className: "flex-1", asChild: true, children: _jsxs("a", { href: publicUrl(station.slug), target: "_blank", rel: "noreferrer", children: [_jsx(ExternalLink, { className: "mr-2 h-4 w-4" }), " Open pickstation"] }) }), _jsxs(Button, { variant: "outline", onClick: () => copyLink(station), children: [_jsx(Copy, { className: "mr-2 h-4 w-4" }), " Link kopi\u00EBren"] })] }), _jsxs("div", { className: "flex gap-2", children: [_jsxs(Button, { variant: "ghost", size: "sm", onClick: () => setDraft({
69
+ : "bg-muted text-muted-foreground"), children: station.active ? "Actief" : "Inactief" })] }), _jsx("code", { className: "block truncate rounded bg-muted px-2 py-1 text-xs text-muted-foreground", children: publicUrl(station.slug) }), plekOf(station.id) ? (_jsxs("p", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx(Printer, { className: "h-4 w-4 shrink-0" }), _jsxs("span", { className: "truncate", children: ["Printplek: ", plekOf(station.id)?.naam] })] })) : (_jsxs("p", { className: "flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/5 px-2 py-1.5 text-sm text-destructive", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0" }), "Nog geen printplek gekoppeld \u2014 de opdracht blijft in de wachtrij staan."] })), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Button, { className: "flex-1", asChild: true, children: _jsxs("a", { href: publicUrl(station.slug), target: "_blank", rel: "noreferrer", children: [_jsx(ExternalLink, { className: "mr-2 h-4 w-4" }), " Open pickstation"] }) }), _jsxs(Button, { variant: "outline", onClick: () => copyLink(station), children: [_jsx(Copy, { className: "mr-2 h-4 w-4" }), " Link kopi\u00EBren"] })] }), _jsxs("div", { className: "flex gap-2", children: [_jsxs(Button, { variant: "ghost", size: "sm", onClick: () => setDraft({
56
70
  id: station.id,
57
71
  name: station.name,
58
72
  description: station.description ?? "",
59
73
  active: station.active,
60
- }), children: [_jsx(Pencil, { className: "mr-2 h-4 w-4" }), " Wijzigen"] }), _jsxs(Button, { variant: "ghost", size: "sm", className: "text-destructive", onClick: () => remove.mutate(station.id), children: [_jsx(Trash2, { className: "mr-2 h-4 w-4" }), " Verwijderen"] })] })] }) }, station.id))) })), _jsx(Dialog, { open: draft !== null, onOpenChange: (open) => !open && setDraft(null), children: _jsxs(DialogContent, { children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: draft?.id ? "Pickstation wijzigen" : "Nieuw pickstation" }) }), draft && (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "station-name", children: "Naam" }), _jsx(Input, { id: "station-name", value: draft.name, onChange: (e) => setDraft({ ...draft, name: e.target.value }) })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "station-desc", children: "Omschrijving (optioneel)" }), _jsx(Textarea, { id: "station-desc", value: draft.description, onChange: (e) => setDraft({ ...draft, description: e.target.value }) })] }), _jsxs("div", { className: "flex items-center justify-between rounded-md border px-3 py-2", children: [_jsx(Label, { htmlFor: "station-active", children: "Actief" }), _jsx(Switch, { id: "station-active", checked: draft.active, onCheckedChange: (v) => setDraft({ ...draft, active: v }) })] }), _jsxs("div", { className: "flex justify-end gap-2", children: [_jsx(Button, { variant: "outline", onClick: () => setDraft(null), children: "Annuleren" }), _jsxs(Button, { disabled: !draft.name.trim() || save.isPending, onClick: () => save.mutate(draft), children: [save.isPending && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), " Opslaan"] })] })] }))] }) })] }));
74
+ printPlekId: plekOf(station.id)?.print_plek_id ?? null,
75
+ }), children: [_jsx(Pencil, { className: "mr-2 h-4 w-4" }), " Wijzigen"] }), _jsxs(Button, { variant: "ghost", size: "sm", className: "text-destructive", onClick: () => remove.mutate(station.id), children: [_jsx(Trash2, { className: "mr-2 h-4 w-4" }), " Verwijderen"] })] })] }) }, station.id))) })), _jsx(Dialog, { open: draft !== null, onOpenChange: (open) => !open && setDraft(null), children: _jsxs(DialogContent, { children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: draft?.id ? "Pickstation wijzigen" : "Nieuw pickstation" }) }), draft && (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "station-name", children: "Naam" }), _jsx(Input, { id: "station-name", value: draft.name, onChange: (e) => setDraft({ ...draft, name: e.target.value }) })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "station-desc", children: "Omschrijving (optioneel)" }), _jsx(Textarea, { id: "station-desc", value: draft.description, onChange: (e) => setDraft({ ...draft, description: e.target.value }) })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "station-plek", children: "Printplek" }), _jsxs(Select, { value: draft.printPlekId ?? NO_PLEK, onValueChange: (v) => setDraft({ ...draft, printPlekId: v === NO_PLEK ? null : v }), children: [_jsx(SelectTrigger, { id: "station-plek", children: _jsx(SelectValue, { placeholder: "Kies een printplek" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: NO_PLEK, children: "Geen printplek" }), safePlekken.map((plek) => (_jsxs(SelectItem, { value: plek.id, children: [plek.naam, plek.omschrijving ? ` — ${plek.omschrijving}` : ""] }, plek.id)))] })] }), !draft.printPlekId && (_jsx("p", { className: "text-sm text-destructive", children: "Nog geen printplek gekoppeld \u2014 de opdracht blijft in de wachtrij staan." }))] }), _jsxs("div", { className: "flex items-center justify-between rounded-md border px-3 py-2", children: [_jsx(Label, { htmlFor: "station-active", children: "Actief" }), _jsx(Switch, { id: "station-active", checked: draft.active, onCheckedChange: (v) => setDraft({ ...draft, active: v }) })] }), _jsxs("div", { className: "flex justify-end gap-2", children: [_jsx(Button, { variant: "outline", onClick: () => setDraft(null), children: "Annuleren" }), _jsxs(Button, { disabled: !draft.name.trim() || save.isPending, onClick: () => save.mutate(draft), children: [save.isPending && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), " Opslaan"] })] })] }))] }) })] }));
61
76
  }
@@ -0,0 +1,2 @@
1
+ export declare function TemplateModulePage(): import("react").JSX.Element;
2
+ //# sourceMappingURL=TemplateModulePage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TemplateModulePage.d.ts","sourceRoot":"","sources":["../../src/components/TemplateModulePage.tsx"],"names":[],"mappings":"AAsBA,wBAAgB,kBAAkB,gCAmFjC"}
@@ -0,0 +1,44 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ // ============================================================================
3
+ // src/components/TemplateModulePage.tsx — EXAMPLE PAGE COMPONENT
4
+ // ============================================================================
5
+ // Pagina-componenten horen in src/components/, NIET alleen in src/routes/.
6
+ // src/routes/ wordt NIET naar npm gepubliceerd (zie tsconfig.build.json exclude).
7
+ //
8
+ // GEEN <Header /> hier — die zit in _authenticated.tsx via staticData.title
9
+ // ============================================================================
10
+ import { useState, useEffect } from "react";
11
+ import { useAuth, supabase, Button, Card, CardContent, CardHeader, CardTitle, toast, } from "@flowselections/core";
12
+ import { TemplateModuleLogo } from './TemplateModuleLogo';
13
+ export function TemplateModulePage() {
14
+ // Auth is guaranteed — this user is already logged in
15
+ const { user, isAdmin } = useAuth();
16
+ // Example state — replace with your own
17
+ const [items, setItems] = useState([]);
18
+ const [loading, setLoading] = useState(true);
19
+ useEffect(() => {
20
+ loadData();
21
+ }, []);
22
+ const loadData = async () => {
23
+ setLoading(true);
24
+ try {
25
+ // Example query — replace "products" with your table
26
+ const { data, error } = await supabase
27
+ .from("products")
28
+ .select("*")
29
+ .limit(10);
30
+ if (error)
31
+ throw error;
32
+ // ✅ Altijd Array.isArray bewaken op server-function data
33
+ // const safeItems = Array.isArray(data?.items) ? data.items : [];
34
+ setItems(Array.isArray(data) ? data : []);
35
+ }
36
+ catch {
37
+ toast.error("Fout bij het laden van gegevens");
38
+ }
39
+ finally {
40
+ setLoading(false);
41
+ }
42
+ };
43
+ return (_jsxs("main", { className: "p-6 space-y-6", children: [isAdmin && (_jsxs("div", { className: "text-sm text-muted-foreground", children: ["Ingelogd als admin: ", user?.email] })), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(CardTitle, { children: "Overzicht" }) }), _jsxs(CardContent, { children: [loading ? (_jsx("p", { className: "text-sm text-muted-foreground", children: "Laden..." })) : items.length === 0 ? (_jsx("p", { className: "text-sm text-muted-foreground", children: "Geen gegevens gevonden." })) : (_jsxs("p", { className: "text-sm", children: [items.length, " items geladen."] })), _jsx(Button, { onClick: loadData, className: "mt-4", disabled: loading, children: "Vernieuwen" })] })] }), _jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx(TemplateModuleLogo, { className: "w-6 h-6 text-primary" }), _jsx("span", { children: "SVG-component (voorkeur voor vector-logo's)" })] })] }));
44
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"LanguageTiles.d.ts","sourceRoot":"","sources":["../../../src/components/pick/LanguageTiles.tsx"],"names":[],"mappings":"AAGA,UAAU,KAAK;IACb,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,KAAK,+BAuB1D"}
1
+ {"version":3,"file":"LanguageTiles.d.ts","sourceRoot":"","sources":["../../../src/components/pick/LanguageTiles.tsx"],"names":[],"mappings":"AAGA,UAAU,KAAK;IACb,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,KAAK,+BAyB1D"}
@@ -3,9 +3,9 @@ import { Card } from "@flowselections/core";
3
3
  import { PICK_LANGUAGES } from "../../lib/pickI18n";
4
4
  /** Taalkeuze — zelfde tegel-uitstraling en bediening als de oude landselectie. */
5
5
  export function LanguageTiles({ onSelect, selected }) {
6
- return (_jsx("div", { className: "grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5", children: PICK_LANGUAGES.map((l) => (_jsxs(Card, { role: "button", tabIndex: 0, onClick: () => onSelect(l.code), onKeyDown: (e) => {
6
+ return (_jsx("div", { className: "grid grid-cols-2 gap-3 sm:grid-cols-3 sm:gap-4 lg:grid-cols-4 xl:grid-cols-5", children: PICK_LANGUAGES.map((l) => (_jsxs(Card, { role: "button", tabIndex: 0, onClick: () => onSelect(l.code), onKeyDown: (e) => {
7
7
  if (e.key === "Enter" || e.key === " ")
8
8
  onSelect(l.code);
9
- }, className: "cursor-pointer select-none border-2 p-6 text-center transition-all hover:border-primary hover:shadow-lg focus:border-primary focus:outline-none active:scale-[0.98] " +
10
- (selected === l.code ? "border-primary bg-primary/5" : ""), children: [_jsx("div", { className: "text-5xl leading-none", children: l.flag }), _jsx("div", { className: "mt-3 text-lg font-semibold text-foreground", children: l.label })] }, l.code))) }));
9
+ }, className: "flex min-h-22 cursor-pointer select-none flex-col items-center justify-center border-2 p-4 text-center transition-all hover:border-primary hover:shadow-lg focus:border-primary focus:outline-none active:scale-[0.98] sm:p-6 " +
10
+ (selected === l.code ? "border-primary bg-primary/5" : ""), children: [_jsx("div", { className: "text-4xl leading-none sm:text-5xl", children: l.flag }), _jsx("div", { className: "mt-2 text-base font-semibold text-foreground sm:mt-3 sm:text-lg", children: l.label })] }, l.code))) }));
11
11
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PickScherm.d.ts","sourceRoot":"","sources":["../../../src/components/pick/PickScherm.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAiB,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAYtE,UAAU,KAAK;IACb,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAID;;;GAGG;AACH,wBAAgB,UAAU,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,KAAK,+BAuapD"}
1
+ {"version":3,"file":"PickScherm.d.ts","sourceRoot":"","sources":["../../../src/components/pick/PickScherm.tsx"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAiB,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAkBtE,UAAU,KAAK;IACb,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAID;;;GAGG;AACH,wBAAgB,UAAU,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,KAAK,+BAgmBpD"}
@@ -1,15 +1,16 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
- import { Badge, Button, Card, CardContent, Input, toast, } from "@flowselections/core";
4
- import { AlertTriangle, ArrowLeft, CheckCircle2, Globe, Loader2, Printer, RefreshCw, Search, WifiOff, } from "lucide-react";
3
+ import { Badge, Button, Card, CardContent, Input, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, toast, } from "@flowselections/core";
4
+ import { AlertTriangle, ArrowLeft, CheckCircle2, Globe, Loader2, Printer, RefreshCw, ScanLine, Search, WifiOff, Zap, } from "lucide-react";
5
5
  import { LanguageTiles } from "./LanguageTiles";
6
6
  import { QueueTable } from "./QueueTable";
7
7
  import { getSessionId, pickApi } from "../../lib/pickApi";
8
8
  import { completeLogisticsTaskForItem } from "../../lib/pickPrint";
9
9
  import { getPickTranslator } from "../../lib/pickI18n";
10
+ import { friendlyPickError, getPickUiTexts } from "../../lib/pickUiText";
10
11
  import { getPrintJobTexts, printJobStatusLabel } from "../../lib/pickPrintJobText";
11
12
  import { defaultFilters, usePickHeartbeat, usePickQueue, } from "../../hooks/usePickQueue";
12
- import { usePickDocumentTypes, usePickStatuses } from "../../hooks/usePickConfig";
13
+ import { usePickDocumentTypes, usePickStatuses, useStationPrintPlek, } from "../../hooks/usePickConfig";
13
14
  import { usePrintJob } from "../../hooks/usePrintJob";
14
15
  const LANG_STORAGE_KEY = "pick.language";
15
16
  /**
@@ -20,18 +21,23 @@ export function PickScherm({ station, onBack }) {
20
21
  const sessionId = getSessionId();
21
22
  const [lang, setLang] = useState(null);
22
23
  const [filters, setFilters] = useState(defaultFilters);
24
+ const [searchInput, setSearchInput] = useState("");
25
+ const [scanInput, setScanInput] = useState("");
23
26
  const [busyId, setBusyId] = useState(null);
24
27
  const [pending, setPending] = useState(null);
25
28
  const [lastPrinted, setLastPrinted] = useState(null);
26
29
  const [emptyNotice, setEmptyNotice] = useState(null);
27
30
  const resetDone = useRef(null);
28
31
  const autoFetched = useRef(false);
32
+ const retryAfterExpiry = useRef(false);
29
33
  const { data: statuses } = usePickStatuses();
30
34
  const { data: documentTypes } = usePickDocumentTypes();
31
35
  const { online } = usePickHeartbeat(station.id, null, sessionId);
36
+ const { data: printPlek, isLoading: plekLoading } = useStationPrintPlek(station.id);
32
37
  const { tracked, track, clear: clearJob } = usePrintJob();
33
38
  const t = useMemo(() => getPickTranslator(lang ?? "nl"), [lang]);
34
39
  const jobTexts = useMemo(() => getPrintJobTexts(t.lang), [t]);
40
+ const ui = useMemo(() => getPickUiTexts(t.lang), [t]);
35
41
  useEffect(() => {
36
42
  if (typeof window === "undefined")
37
43
  return;
@@ -44,8 +50,15 @@ export function PickScherm({ station, onBack }) {
44
50
  if (typeof window !== "undefined")
45
51
  window.localStorage.setItem(LANG_STORAGE_KEY, code);
46
52
  }, []);
53
+ /** Zoeken pas na een korte pauze, zodat typen geen query per toets afvuurt. */
54
+ useEffect(() => {
55
+ const timer = setTimeout(() => {
56
+ setFilters((f) => (f.search === searchInput ? f : { ...f, search: searchInput, page: 0 }));
57
+ }, 300);
58
+ return () => clearTimeout(timer);
59
+ }, [searchInput]);
47
60
  const effectiveFilters = useMemo(() => ({ ...filters, country: null, sortRules: [] }), [filters]);
48
- const { items, total, loading, lockedIds, refresh, pendingCount, printedCount } = usePickQueue({
61
+ const { items, total, loading, lockedIds, refresh, pendingCount, printedCount, urgentCount, realtimeOk, } = usePickQueue({
49
62
  stationId: station.id,
50
63
  filters: effectiveFilters,
51
64
  enabled: lang !== null,
@@ -89,9 +102,14 @@ export function PickScherm({ station, onBack }) {
89
102
  }
90
103
  })();
91
104
  }, [tracked, sessionId, refresh, jobTexts]);
92
- /** Zet een printfout om in een begrijpelijke melding. */
105
+ /**
106
+ * Zet een printfout om in een begrijpelijke melding en meldt of de claim
107
+ * verlopen was — dan kan het scherm zelf opnieuw ophalen.
108
+ */
93
109
  const showPrintError = useCallback((e) => {
94
- toast.error(e instanceof Error ? e.message : t("notAvailable"));
110
+ const { message, detail, expiredClaim } = friendlyPickError(e, t.lang);
111
+ toast.error(message, detail && detail !== message ? { description: detail } : undefined);
112
+ return expiredClaim;
95
113
  }, [t]);
96
114
  const handlePick = useCallback(async (item) => {
97
115
  setBusyId(item.id);
@@ -162,7 +180,7 @@ export function PickScherm({ station, onBack }) {
162
180
  return claimed;
163
181
  }
164
182
  catch (e) {
165
- const message = e instanceof Error ? e.message : t("noDocument");
183
+ const { message } = friendlyPickError(e, t.lang);
166
184
  if (silent)
167
185
  setEmptyNotice(message);
168
186
  else
@@ -189,7 +207,7 @@ export function PickScherm({ station, onBack }) {
189
207
  await fetchNext();
190
208
  }
191
209
  catch (e) {
192
- showPrintError(e);
210
+ const expired = showPrintError(e);
193
211
  try {
194
212
  await pickApi.releaseLock(item.id);
195
213
  }
@@ -199,8 +217,47 @@ export function PickScherm({ station, onBack }) {
199
217
  setPending(null);
200
218
  refresh();
201
219
  setBusyId(null);
220
+ // Verlopen claim: zelf een verse opdracht ophalen in plaats van blijven hangen.
221
+ if (expired && !retryAfterExpiry.current) {
222
+ retryAfterExpiry.current = true;
223
+ try {
224
+ await fetchNext(true);
225
+ }
226
+ finally {
227
+ retryAfterExpiry.current = false;
228
+ }
229
+ }
202
230
  }
203
231
  }, [pending, runPrint, fetchNext, refresh, showPrintError]);
232
+ /** Scanner: barcode, documentnummer of ordernummer selecteert direct de regel. */
233
+ const handleScan = useCallback(async (raw) => {
234
+ const code = raw.trim();
235
+ if (!code)
236
+ return;
237
+ setBusyId("scan");
238
+ try {
239
+ const found = await pickApi.findByCode(code, station.id);
240
+ if (!found) {
241
+ toast.error(ui.scanNotFound);
242
+ return;
243
+ }
244
+ setScanInput("");
245
+ if (found.printed_at) {
246
+ toast.error(ui.scanAlreadyPrinted);
247
+ setFilters((f) => ({ ...f, search: code, page: 0 }));
248
+ setSearchInput(code);
249
+ return;
250
+ }
251
+ setBusyId(null);
252
+ await handlePick(found);
253
+ }
254
+ catch (e) {
255
+ showPrintError(e);
256
+ }
257
+ finally {
258
+ setBusyId(null);
259
+ }
260
+ }, [station.id, ui, handlePick, showPrintError]);
204
261
  const cancelPending = useCallback(async () => {
205
262
  const item = pending;
206
263
  setPending(null);
@@ -234,13 +291,18 @@ export function PickScherm({ station, onBack }) {
234
291
  }, [pendingCount]);
235
292
  // Stap 1 — taalselectie
236
293
  if (lang === null) {
237
- return (_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-2xl font-bold text-foreground", children: station.name }), _jsx("p", { className: "text-sm text-muted-foreground", children: t("chooseLanguageHint") })] }), onBack && (_jsxs(Button, { variant: "outline", onClick: onBack, children: [_jsx(ArrowLeft, { className: "mr-2 h-4 w-4" }), " ", t("back")] }))] }), _jsx(LanguageTiles, { onSelect: chooseLang })] }));
294
+ return (_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_auto] items-center gap-3 sm:flex sm:flex-wrap sm:justify-between", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("h2", { className: "truncate text-xl font-bold text-foreground sm:text-2xl", children: station.name }), _jsx("p", { className: "text-sm text-muted-foreground", children: t("chooseLanguageHint") })] }), onBack && (_jsxs(Button, { variant: "outline", className: "shrink-0", onClick: onBack, children: [_jsx(ArrowLeft, { className: "mr-2 h-4 w-4" }), " ", t("back")] }))] }), _jsx(LanguageTiles, { onSelect: chooseLang })] }));
238
295
  }
239
296
  const totalPages = Math.max(1, Math.ceil(total / filters.pageSize));
240
297
  const jobStatus = tracked?.job?.status ?? null;
241
298
  const jobFailed = jobStatus === "mislukt" || jobStatus === "geannuleerd";
242
- return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsxs(Button, { variant: "outline", size: "lg", onClick: () => setLang(null), children: [_jsx(Globe, { className: "mr-2 h-5 w-5" }), " ", t("changeLanguage")] }), _jsxs("div", { children: [_jsx("h2", { className: "text-xl font-bold text-foreground", children: station.name }), _jsxs("p", { className: "text-sm text-muted-foreground", children: [pendingCount, " ", t("statusToPrint"), " \u00B7 ", printedCount, " ", t("statusPrinted")] })] })] }), _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", onClick: refresh, "aria-label": t("refresh"), children: _jsx(RefreshCw, { className: "h-4 w-4" }) }), _jsxs(Button, { size: "lg", className: "h-14 px-8 text-lg", onClick: () => (pending ? confirmPending() : fetchNext()), disabled: busyId !== null, children: [busyId !== null ? (_jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" })) : (_jsx(Printer, { className: "mr-2 h-5 w-5" })), t("printNext"), pending?.document_number ? ` · ${pending.document_number}` : ""] })] })] }), !pending && emptyNotice && (_jsx("p", { className: "text-sm text-muted-foreground", children: emptyNotice })), pending && (_jsx(Card, { className: "border-2 border-primary", children: _jsxs(CardContent, { className: "flex flex-wrap items-center justify-between gap-4 p-5", children: [_jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("confirmPrintTitle") }), _jsx("p", { className: "text-2xl font-bold text-foreground", children: pending.document_number ?? t("document") }), _jsx("p", { className: "text-sm text-muted-foreground", children: [pending.order_number, pending.customer_name].filter(Boolean).join(" · ") })] }), _jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { variant: "outline", size: "lg", onClick: cancelPending, disabled: busyId !== null, children: t("cancel") }), _jsxs(Button, { size: "lg", className: "h-14 px-8 text-lg", onClick: confirmPending, disabled: busyId !== null, children: [busyId === "confirm" ? (_jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" })) : (_jsx(Printer, { className: "mr-2 h-5 w-5" })), t("print")] })] })] }) })), tracked && (_jsx(Card, { className: jobFailed ? "border-2 border-destructive" : "border-2 border-primary/40", children: _jsxs(CardContent, { className: "flex flex-wrap items-center justify-between gap-4 p-4", children: [_jsxs("div", { className: "flex items-center gap-3", children: [jobFailed ? (_jsx(AlertTriangle, { className: "h-6 w-6 text-destructive" })) : jobStatus === "voltooid" ? (_jsx(CheckCircle2, { className: "h-6 w-6 text-primary" })) : (_jsx(Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" })), _jsxs("div", { children: [_jsxs("p", { className: "text-sm font-medium text-muted-foreground", children: [jobTexts.jobTitle, " ", tracked.documentNumber ? `· ${tracked.documentNumber}` : ""] }), _jsx("p", { className: "text-lg font-semibold text-foreground", children: printJobStatusLabel(jobStatus, t.lang) }), tracked.job?.printer_naam && (_jsxs("p", { className: "text-sm text-muted-foreground", children: [jobTexts.printerLabel, ": ", tracked.job.printer_naam] })), jobFailed && (_jsxs("p", { className: "text-sm text-destructive", children: [tracked.job?.foutmelding ?? jobTexts.unknown, " \u00B7 ", jobTexts.requeued] }))] })] }), _jsxs("div", { className: "flex gap-2", children: [jobFailed && lastPrinted && (_jsxs(Button, { size: "lg", onClick: () => {
299
+ return (_jsxs("div", { className: "space-y-4 pb-24 md:pb-0", children: [_jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:flex-wrap md:items-center md:justify-between", children: [_jsxs("div", { className: "grid grid-cols-[auto_minmax(0,1fr)] items-center gap-3", children: [_jsxs(Button, { variant: "outline", size: "lg", className: "h-12 shrink-0 px-3 sm:px-4", onClick: () => setLang(null), "aria-label": t("changeLanguage"), children: [_jsx(Globe, { className: "h-5 w-5 sm:mr-2" }), _jsx("span", { className: "hidden sm:inline", children: t("changeLanguage") })] }), _jsxs("div", { className: "min-w-0", children: [_jsx("h2", { className: "truncate text-lg font-bold text-foreground sm:text-xl", children: station.name }), _jsxs("p", { className: "truncate text-sm text-muted-foreground", children: [pendingCount, " ", t("statusToPrint"), " \u00B7 ", printedCount, " ", t("statusPrinted")] })] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [!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, { size: "lg", className: "hidden h-14 px-8 text-lg md:inline-flex", onClick: () => (pending ? confirmPending() : fetchNext()), disabled: busyId !== null, children: [busyId !== null ? (_jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" })) : (_jsx(Printer, { className: "mr-2 h-5 w-5" })), t("printNext"), pending?.document_number ? ` · ${pending.document_number}` : ""] })] })] }), !plekLoading && !printPlek && (_jsxs("div", { className: "flex items-start gap-2 rounded-md border-2 border-destructive/50 bg-destructive/5 p-3 text-sm text-destructive", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0" }), _jsx("span", { children: "Nog geen printplek gekoppeld \u2014 de opdracht blijft in de wachtrij staan." })] })), !pending && emptyNotice && (_jsx("p", { className: "text-sm text-muted-foreground", children: emptyNotice })), pending && (_jsx(Card, { className: "border-2 border-primary", children: _jsxs(CardContent, { className: "flex flex-col gap-4 p-4 sm:flex-row sm:flex-wrap sm:items-center sm:justify-between sm:p-5", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("confirmPrintTitle") }), _jsx("p", { className: "truncate text-xl font-bold text-foreground sm:text-2xl", children: pending.document_number ?? t("document") }), _jsx("p", { className: "truncate text-sm text-muted-foreground", children: [pending.order_number, pending.customer_name].filter(Boolean).join(" · ") })] }), _jsxs("div", { className: "flex flex-col gap-2 sm:flex-row", children: [_jsx(Button, { variant: "outline", size: "lg", className: "h-12 w-full sm:w-auto", onClick: cancelPending, disabled: busyId !== null, children: t("cancel") }), _jsxs(Button, { size: "lg", className: "h-14 w-full px-8 text-lg sm:w-auto", onClick: confirmPending, disabled: busyId !== null, children: [busyId === "confirm" ? (_jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" })) : (_jsx(Printer, { className: "mr-2 h-5 w-5" })), t("print")] })] })] }) })), tracked && (_jsx(Card, { className: jobFailed ? "border-2 border-destructive" : "border-2 border-primary/40", children: _jsxs(CardContent, { className: "flex flex-col gap-4 p-4 sm:flex-row sm:flex-wrap sm:items-center sm:justify-between", children: [_jsxs("div", { className: "flex min-w-0 items-start gap-3", children: [jobFailed ? (_jsx(AlertTriangle, { className: "h-6 w-6 shrink-0 text-destructive" })) : jobStatus === "voltooid" ? (_jsx(CheckCircle2, { className: "h-6 w-6 shrink-0 text-primary" })) : (_jsx(Loader2, { className: "h-6 w-6 shrink-0 animate-spin text-muted-foreground" })), _jsxs("div", { className: "min-w-0", children: [_jsxs("p", { className: "truncate text-sm font-medium text-muted-foreground", children: [jobTexts.jobTitle, " ", tracked.documentNumber ? `· ${tracked.documentNumber}` : ""] }), _jsx("p", { className: "text-lg font-semibold text-foreground", children: printJobStatusLabel(jobStatus, t.lang) }), tracked.job?.printer_naam && (_jsxs("p", { className: "truncate text-sm text-muted-foreground", children: [jobTexts.printerLabel, ": ", tracked.job.printer_naam] })), jobFailed && (_jsxs("p", { className: "text-sm text-destructive", children: [tracked.job?.foutmelding ?? jobTexts.unknown, " \u00B7 ", jobTexts.requeued] }))] })] }), _jsxs("div", { className: "flex flex-col gap-2 sm:flex-row", children: [jobFailed && lastPrinted && (_jsxs(Button, { size: "lg", className: "h-12 w-full sm:w-auto", onClick: () => {
243
300
  clearJob();
244
301
  void handlePick(lastPrinted);
245
- }, disabled: busyId !== null, children: [_jsx(Printer, { className: "mr-2 h-5 w-5" }), " ", jobTexts.retry] })), _jsx(Button, { variant: "outline", size: "lg", onClick: clearJob, children: jobTexts.close })] })] }) })), _jsx(Card, { children: _jsx(CardContent, { className: "flex flex-wrap items-center gap-3 p-4", children: _jsxs("div", { className: "relative min-w-64 flex-1", children: [_jsx(Search, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { className: "pl-9", placeholder: t("search"), value: filters.search, onChange: (e) => setFilters((f) => ({ ...f, search: e.target.value, page: 0 })) })] }) }) }), 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")] })) : (_jsx(QueueTable, { items: items, lockedIds: lockedIds, statuses: Array.isArray(statuses) ? statuses : [], documentTypes: Array.isArray(documentTypes) ? documentTypes : [], busyId: busyId, onPick: handlePick, onReprint: handleReprint, t: t })), _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("span", { className: "text-sm text-muted-foreground", children: [t("page"), " ", filters.page + 1, " ", t("of"), " ", totalPages] }), _jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { variant: "outline", disabled: filters.page === 0, onClick: () => setFilters((f) => ({ ...f, page: Math.max(0, f.page - 1) })), children: t("previous") }), _jsx(Button, { variant: "outline", disabled: filters.page + 1 >= totalPages, onClick: () => setFilters((f) => ({ ...f, page: f.page + 1 })), children: t("next") })] })] })] }));
302
+ }, disabled: busyId !== null, children: [_jsx(Printer, { className: "mr-2 h-5 w-5" }), " ", jobTexts.retry] })), _jsx(Button, { variant: "outline", size: "lg", className: "h-12 w-full sm:w-auto", onClick: clearJob, children: jobTexts.close })] })] }) })), _jsx(Card, { 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("div", { className: "relative w-full min-w-0 sm:w-56", 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: ui.scanPlaceholder, value: scanInput, onChange: (e) => setScanInput(e.target.value), onKeyDown: (e) => {
303
+ if (e.key !== "Enter")
304
+ return;
305
+ e.preventDefault();
306
+ void handleScan(scanInput);
307
+ } })] }), _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 })), 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")] })) : (_jsx(QueueTable, { items: items, lockedIds: lockedIds, statuses: Array.isArray(statuses) ? statuses : [], documentTypes: Array.isArray(documentTypes) ? documentTypes : [], busyId: busyId, onPick: handlePick, onReprint: handleReprint, 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() : fetchNext()), disabled: busyId !== null, children: [busyId !== null ? (_jsx(Loader2, { className: "mr-2 h-5 w-5 animate-spin" })) : (_jsx(Printer, { className: "mr-2 h-5 w-5" })), _jsxs("span", { className: "truncate", children: [t("printNext"), pending?.document_number ? ` · ${pending.document_number}` : ""] })] }) })] }));
246
308
  }
@@ -1 +1 @@
1
- {"version":3,"file":"QueueTable.d.ts","sourceRoot":"","sources":["../../../src/components/pick/QueueTable.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEvF,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,MAAM,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IACtC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,CAAC,EAAE,cAAc,CAAC;CACpB;AASD,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,SAAS,EACT,QAAQ,EACR,aAAa,EACb,MAAM,EACN,MAAM,EACN,SAAS,EACT,QAAQ,EACR,CAAC,EAAE,UAAU,GACd,EAAE,KAAK,+BA8GP"}
1
+ {"version":3,"file":"QueueTable.d.ts","sourceRoot":"","sources":["../../../src/components/pick/QueueTable.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEvF,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,MAAM,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IACtC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,CAAC,EAAE,cAAc,CAAC;CACpB;AASD,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,SAAS,EACT,QAAQ,EACR,aAAa,EACb,MAAM,EACN,MAAM,EACN,SAAS,EACT,QAAQ,EACR,CAAC,EAAE,UAAU,GACd,EAAE,KAAK,+BA4NP"}
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { Badge, Button, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@flowselections/core";
3
3
  import { AlertTriangle, Lock, Printer, RotateCcw } from "lucide-react";
4
4
  import { sinceLabel } from "../../lib/pickTypes";
@@ -16,15 +16,25 @@ export function QueueTable({ items, lockedIds, statuses, documentTypes, busyId,
16
16
  const t = translator ?? getPickTranslator("nl");
17
17
  const safeItems = Array.isArray(items) ? items : [];
18
18
  const docById = new Map((Array.isArray(documentTypes) ? documentTypes : []).map((d) => [d.id, d]));
19
- return (_jsx("div", { className: "overflow-x-auto rounded-lg border", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: t("document") }), _jsx(TableHead, { children: t("order") }), _jsx(TableHead, { children: t("customer") }), _jsx(TableHead, { className: "hidden lg:table-cell", children: t("deliveryAddress") }), _jsx(TableHead, { className: "text-right", children: t("lines") }), _jsx(TableHead, { className: "text-right", children: t("carts") }), _jsx(TableHead, { children: t("status") }), _jsx(TableHead, { children: t("priority") }), _jsx(TableHead, { children: t("announced") }), _jsx(TableHead, { children: t("waiting") }), _jsx(TableHead, { className: "text-right", children: t("action") })] }) }), _jsxs(TableBody, { children: [safeItems.map((item) => {
20
- const printed = !!item.printed_at;
21
- const locked = !printed && lockedIds.has(item.id);
22
- const doc = item.document_type_id ? docById.get(item.document_type_id) : undefined;
23
- const warnings = Array.isArray(item.warnings) ? item.warnings : [];
24
- return (_jsxs(TableRow, { className: locked || printed ? "opacity-60" : undefined, children: [_jsxs(TableCell, { className: "font-medium", children: [_jsxs("div", { className: "flex items-center gap-2", children: [item.document_number, 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: item.order_number }), _jsx(TableCell, { children: item.customer_name }), _jsx(TableCell, { className: "hidden max-w-56 truncate lg:table-cell", children: item.delivery_address }), _jsx(TableCell, { className: "text-right", children: item.line_count }), _jsx(TableCell, { className: "text-right", children: item.cart_count }), _jsx(TableCell, { children: _jsx(Badge, { variant: printed ? "secondary" : "default", children: printed ? t("statusPrinted") : t("statusToPrint") }) }), _jsx(TableCell, { children: _jsx("span", { className: "rounded px-2 py-1 text-xs font-semibold " +
25
- priorityTone(item.priority, item.is_urgent), children: item.is_urgent ? t("urgent") : item.priority }) }), _jsx(TableCell, { className: "whitespace-nowrap text-sm", children: new Date(item.announced_at).toLocaleTimeString(t.locale, {
26
- hour: "2-digit",
27
- minute: "2-digit",
28
- }) }), _jsx(TableCell, { className: "whitespace-nowrap text-sm", children: sinceLabel(item.announced_at) }), _jsx(TableCell, { className: "text-right", children: printed ? (_jsxs(Button, { size: "sm", variant: "ghost", disabled: readOnly || busyId === item.id, onClick: () => (onReprint ?? onPick)(item), children: [_jsx(RotateCcw, { className: "mr-1 h-4 w-4" }), t("print")] })) : 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, onClick: () => onPick(item), children: [_jsx(Printer, { className: "mr-1 h-4 w-4" }), t("print")] })) })] }, item.id));
29
- }), safeItems.length === 0 && (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 11, className: "py-10 text-center text-muted-foreground", children: t("emptyQueue") }) }))] })] }) }));
19
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: "hidden overflow-x-auto rounded-lg border md:block", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: t("document") }), _jsx(TableHead, { children: t("order") }), _jsx(TableHead, { children: t("customer") }), _jsx(TableHead, { className: "hidden lg:table-cell", children: t("deliveryAddress") }), _jsx(TableHead, { className: "text-right", children: t("lines") }), _jsx(TableHead, { className: "text-right", children: t("carts") }), _jsx(TableHead, { children: t("status") }), _jsx(TableHead, { children: t("priority") }), _jsx(TableHead, { children: t("announced") }), _jsx(TableHead, { children: t("waiting") }), _jsx(TableHead, { className: "text-right", children: t("action") })] }) }), _jsxs(TableBody, { children: [safeItems.map((item) => {
20
+ const printed = !!item.printed_at;
21
+ const locked = !printed && lockedIds.has(item.id);
22
+ const doc = item.document_type_id ? docById.get(item.document_type_id) : undefined;
23
+ const warnings = Array.isArray(item.warnings) ? item.warnings : [];
24
+ return (_jsxs(TableRow, { className: locked || printed ? "opacity-60" : undefined, children: [_jsxs(TableCell, { className: "font-medium", children: [_jsxs("div", { className: "flex items-center gap-2", children: [item.document_number, 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: item.order_number }), _jsx(TableCell, { children: item.customer_name }), _jsx(TableCell, { className: "hidden max-w-56 truncate lg:table-cell", children: item.delivery_address }), _jsx(TableCell, { className: "text-right", children: item.line_count }), _jsx(TableCell, { className: "text-right", children: item.cart_count }), _jsx(TableCell, { children: _jsx(Badge, { variant: printed ? "secondary" : "default", children: printed ? t("statusPrinted") : t("statusToPrint") }) }), _jsx(TableCell, { children: _jsx("span", { className: "rounded px-2 py-1 text-xs font-semibold " +
25
+ priorityTone(item.priority, item.is_urgent), children: item.is_urgent ? t("urgent") : item.priority }) }), _jsx(TableCell, { className: "whitespace-nowrap text-sm", children: new Date(item.announced_at).toLocaleTimeString(t.locale, {
26
+ hour: "2-digit",
27
+ minute: "2-digit",
28
+ }) }), _jsx(TableCell, { className: "whitespace-nowrap text-sm", children: sinceLabel(item.announced_at) }), _jsx(TableCell, { className: "text-right", children: printed ? (_jsxs(Button, { size: "sm", variant: "ghost", disabled: readOnly || busyId === item.id, onClick: () => (onReprint ?? onPick)(item), children: [_jsx(RotateCcw, { className: "mr-1 h-4 w-4" }), t("print")] })) : 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, onClick: () => onPick(item), children: [_jsx(Printer, { className: "mr-1 h-4 w-4" }), t("print")] })) })] }, item.id));
29
+ }), safeItems.length === 0 && (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 11, className: "py-10 text-center text-muted-foreground", children: t("emptyQueue") }) }))] })] }) }), _jsxs("div", { className: "space-y-3 md:hidden", children: [safeItems.map((item) => {
30
+ const printed = !!item.printed_at;
31
+ const locked = !printed && lockedIds.has(item.id);
32
+ const doc = item.document_type_id ? docById.get(item.document_type_id) : undefined;
33
+ const warnings = Array.isArray(item.warnings) ? item.warnings : [];
34
+ return (_jsxs("div", { className: "rounded-lg border bg-card p-4 " + (locked || printed ? "opacity-60" : ""), 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: [_jsx("span", { className: "truncate text-lg font-bold text-foreground", children: item.document_number }), 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 flex-col items-end gap-1", children: [_jsx(Badge, { variant: printed ? "secondary" : "default", children: printed ? t("statusPrinted") : t("statusToPrint") }), _jsx("span", { className: "rounded px-2 py-0.5 text-xs font-semibold " +
35
+ priorityTone(item.priority, item.is_urgent), children: item.is_urgent ? t("urgent") : item.priority })] })] }), _jsxs("div", { className: "mt-2 min-w-0 space-y-0.5 text-sm", children: [_jsx("p", { className: "truncate text-foreground", children: item.order_number }), _jsx("p", { className: "truncate text-muted-foreground", children: item.customer_name }), item.delivery_address && (_jsx("p", { className: "truncate text-xs text-muted-foreground", children: item.delivery_address }))] }), _jsxs("div", { className: "mt-2 flex flex-wrap gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [_jsxs("span", { children: [t("lines"), ": ", item.line_count] }), _jsxs("span", { children: [t("carts"), ": ", item.cart_count] }), _jsxs("span", { children: [t("announced"), ":", " ", new Date(item.announced_at).toLocaleTimeString(t.locale, {
36
+ hour: "2-digit",
37
+ minute: "2-digit",
38
+ })] }), _jsxs("span", { children: [t("waiting"), ": ", sinceLabel(item.announced_at)] })] }), _jsx("div", { className: "mt-3", children: printed ? (_jsxs(Button, { size: "lg", variant: "outline", className: "h-12 w-full", disabled: readOnly || busyId === item.id, onClick: () => (onReprint ?? onPick)(item), children: [_jsx(RotateCcw, { className: "mr-2 h-4 w-4" }), t("print")] })) : 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, onClick: () => onPick(item), children: [_jsx(Printer, { className: "mr-2 h-4 w-4" }), t("print")] })) })] }, item.id));
39
+ }), safeItems.length === 0 && (_jsx("div", { className: "rounded-lg border py-10 text-center text-muted-foreground", children: t("emptyQueue") }))] })] }));
30
40
  }
@@ -5,5 +5,11 @@ export declare function usePickDocumentTypes(): import("@tanstack/react-query").
5
5
  export declare function usePickStationTypes(): import("@tanstack/react-query").UseQueryResult<NoInfer<import("..").PickStationType[]>, Error>;
6
6
  export declare function usePickTasks(): import("@tanstack/react-query").UseQueryResult<NoInfer<import("..").PickTask[]>, Error>;
7
7
  export declare function usePickStations(): import("@tanstack/react-query").UseQueryResult<NoInfer<import("..").PickStation[]>, Error>;
8
+ /** Actieve printplekken uit de Layout maker. */
9
+ export declare function usePickPrintPlekken(): import("@tanstack/react-query").UseQueryResult<NoInfer<import("..").PickPrintPlek[]>, Error>;
10
+ /** Koppelingen pickstation → printplek (beheerpagina). */
11
+ export declare function useStationPrintPlekken(): import("@tanstack/react-query").UseQueryResult<NoInfer<import("..").PickStationPrintPlekRow[]>, Error>;
12
+ /** De printplek van één pickstation (ook in openbare pickschermen). */
13
+ export declare function useStationPrintPlek(stationId?: string): import("@tanstack/react-query").UseQueryResult<NoInfer<import("..").PickStationPrintPlek | null>, Error>;
8
14
  export declare function usePickScreens(stationId?: string): import("@tanstack/react-query").UseQueryResult<NoInfer<import("..").PickScreen[]>, Error>;
9
15
  //# sourceMappingURL=usePickConfig.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"usePickConfig.d.ts","sourceRoot":"","sources":["../../src/hooks/usePickConfig.ts"],"names":[],"mappings":"AAGA,wBAAgB,gBAAgB,+FAE/B;AACD,wBAAgB,eAAe,8FAE9B;AACD,wBAAgB,eAAe,+FAE9B;AACD,wBAAgB,oBAAoB,oGAEnC;AACD,wBAAgB,mBAAmB,mGAElC;AACD,wBAAgB,YAAY,4FAE3B;AACD,wBAAgB,eAAe,+FAE9B;AACD,wBAAgB,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,6FAKhD"}
1
+ {"version":3,"file":"usePickConfig.d.ts","sourceRoot":"","sources":["../../src/hooks/usePickConfig.ts"],"names":[],"mappings":"AAGA,wBAAgB,gBAAgB,+FAE/B;AACD,wBAAgB,eAAe,8FAE9B;AACD,wBAAgB,eAAe,+FAE9B;AACD,wBAAgB,oBAAoB,oGAEnC;AACD,wBAAgB,mBAAmB,mGAElC;AACD,wBAAgB,YAAY,4FAE3B;AACD,wBAAgB,eAAe,+FAE9B;AACD,gDAAgD;AAChD,wBAAgB,mBAAmB,iGAElC;AACD,0DAA0D;AAC1D,wBAAgB,sBAAsB,2GAKrC;AACD,uEAAuE;AACvE,wBAAgB,mBAAmB,CAAC,SAAS,CAAC,EAAE,MAAM,4GAMrD;AAED,wBAAgB,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,6FAKhD"}
@@ -21,6 +21,25 @@ export function usePickTasks() {
21
21
  export function usePickStations() {
22
22
  return useQuery({ queryKey: ["pick", "stations"], queryFn: pickApi.stations });
23
23
  }
24
+ /** Actieve printplekken uit de Layout maker. */
25
+ export function usePickPrintPlekken() {
26
+ return useQuery({ queryKey: ["pick", "printPlekken"], queryFn: pickApi.printPlekken });
27
+ }
28
+ /** Koppelingen pickstation → printplek (beheerpagina). */
29
+ export function useStationPrintPlekken() {
30
+ return useQuery({
31
+ queryKey: ["pick", "stationPrintPlekken"],
32
+ queryFn: pickApi.stationPrintPlekken,
33
+ });
34
+ }
35
+ /** De printplek van één pickstation (ook in openbare pickschermen). */
36
+ export function useStationPrintPlek(stationId) {
37
+ return useQuery({
38
+ queryKey: ["pick", "stationPrintPlek", stationId ?? "none"],
39
+ queryFn: () => (stationId ? pickApi.stationPrintPlek(stationId) : null),
40
+ enabled: Boolean(stationId),
41
+ });
42
+ }
24
43
  export function usePickScreens(stationId) {
25
44
  return useQuery({
26
45
  queryKey: ["pick", "screens", stationId ?? "all"],
@@ -4,6 +4,8 @@ export interface QueueFilters {
4
4
  search: string;
5
5
  documentTypeId: string | null;
6
6
  urgentOnly: boolean;
7
+ /** Alleen regels die nog geprint moeten worden. */
8
+ onlyPending: boolean;
7
9
  page: number;
8
10
  pageSize: number;
9
11
  sortRules: PickSortRule[];
@@ -24,9 +26,11 @@ export declare function usePickQueue(args: {
24
26
  pickDay: string | null;
25
27
  pendingCount: number;
26
28
  printedCount: number;
29
+ urgentCount: number;
27
30
  loading: boolean;
28
31
  error: string | null;
29
32
  lockedIds: Set<string>;
33
+ realtimeOk: boolean;
30
34
  refresh: () => void;
31
35
  };
32
36
  /** Houdt bij dat dit scherm online is en ruimt verlopen locks op. */
@@ -1 +1 @@
1
- {"version":3,"file":"usePickQueue.d.ts","sourceRoot":"","sources":["../../src/hooks/usePickQueue.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAY,aAAa,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAG9E,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,YAAY,EAAE,CAAC;CAC3B;AAED,eAAO,MAAM,cAAc,EAAE,YAQ5B,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;CACnB;;;;;;;;;;EA0GA;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,0FAOnF"}
1
+ {"version":3,"file":"usePickQueue.d.ts","sourceRoot":"","sources":["../../src/hooks/usePickQueue.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAY,aAAa,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAG9E,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,mDAAmD;IACnD,WAAW,EAAE,OAAO,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,YAAY,EAAE,CAAC;CAC3B;AAED,eAAO,MAAM,cAAc,EAAE,YAS5B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;;;;;;;;;;;;EA6IA;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,0FAOnF"}