@flowselections/pick-schermen-kwekers 1.0.14 → 1.0.16

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 (46) hide show
  1. package/README.md +24 -24
  2. package/dist-lib/components/PickstationsPage.d.ts.map +1 -1
  3. package/dist-lib/components/PickstationsPage.js +2 -1
  4. package/dist-lib/components/pick/PickScherm.d.ts.map +1 -1
  5. package/dist-lib/components/pick/PickScherm.js +3 -1
  6. package/dist-lib/components/pick/PreviewDialog.d.ts +13 -0
  7. package/dist-lib/components/pick/PreviewDialog.d.ts.map +1 -0
  8. package/dist-lib/components/pick/PreviewDialog.js +52 -0
  9. package/dist-lib/components/pick/QueueTable.d.ts +2 -1
  10. package/dist-lib/components/pick/QueueTable.d.ts.map +1 -1
  11. package/dist-lib/components/pick/QueueTable.js +11 -5
  12. package/dist-lib/components/pick/ReferentiedataBanner.d.ts +6 -0
  13. package/dist-lib/components/pick/ReferentiedataBanner.d.ts.map +1 -0
  14. package/dist-lib/components/pick/ReferentiedataBanner.js +17 -0
  15. package/dist-lib/components/settings/ReferentiedataPickdocumentenCard.d.ts +2 -0
  16. package/dist-lib/components/settings/ReferentiedataPickdocumentenCard.d.ts.map +1 -0
  17. package/dist-lib/components/settings/ReferentiedataPickdocumentenCard.js +84 -0
  18. package/dist-lib/hooks/usePickReferenceData.d.ts +4 -0
  19. package/dist-lib/hooks/usePickReferenceData.d.ts.map +1 -0
  20. package/dist-lib/hooks/usePickReferenceData.js +10 -0
  21. package/dist-lib/index.d.ts +5 -0
  22. package/dist-lib/index.d.ts.map +1 -1
  23. package/dist-lib/index.js +6 -5
  24. package/dist-lib/integrations/supabase/auth-middleware.d.ts +370 -0
  25. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  26. package/dist-lib/integrations/supabase/client.d.ts +370 -0
  27. package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
  28. package/dist-lib/integrations/supabase/client.server.d.ts +370 -0
  29. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  30. package/dist-lib/integrations/supabase/types.d.ts +373 -0
  31. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  32. package/dist-lib/lib/layoutMaker/pakbonHtml.js +49 -49
  33. package/dist-lib/lib/layoutRenderer.js +17 -17
  34. package/dist-lib/lib/pickPreview.d.ts +19 -0
  35. package/dist-lib/lib/pickPreview.d.ts.map +1 -0
  36. package/dist-lib/lib/pickPreview.js +75 -0
  37. package/dist-lib/lib/pickReferenceApi.d.ts +37 -0
  38. package/dist-lib/lib/pickReferenceApi.d.ts.map +1 -0
  39. package/dist-lib/lib/pickReferenceApi.js +98 -0
  40. package/dist-lib/lib/pickUiText.d.ts +1 -0
  41. package/dist-lib/lib/pickUiText.d.ts.map +1 -1
  42. package/dist-lib/lib/pickUiText.js +11 -1
  43. package/package.json +1 -1
  44. package/dist-lib/components/TemplateModulePage.d.ts +0 -2
  45. package/dist-lib/components/TemplateModulePage.d.ts.map +0 -1
  46. package/dist-lib/components/TemplateModulePage.js +0 -44
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
+ ```
@@ -1 +1 @@
1
- {"version":3,"file":"PickstationsPage.d.ts","sourceRoot":"","sources":["../../src/components/PickstationsPage.tsx"],"names":[],"mappings":"AA+FA,wBAAgB,gBAAgB,gCAuL/B"}
1
+ {"version":3,"file":"PickstationsPage.d.ts","sourceRoot":"","sources":["../../src/components/PickstationsPage.tsx"],"names":[],"mappings":"AAiGA,wBAAgB,gBAAgB,gCA2L/B"}
@@ -6,6 +6,7 @@ import { AlertTriangle, Copy, ExternalLink, Loader2, Pencil, Plus, Printer, Tras
6
6
  import { pickApi } from "../lib/pickApi";
7
7
  import { usePickStations } from "../hooks/usePickConfig";
8
8
  import { useKoppelingVoorBron } from "../hooks/useKoppelingVoorBron";
9
+ import { ReferentiedataBanner } from "./pick/ReferentiedataBanner";
9
10
  const emptyDraft = { name: "", description: "", active: true };
10
11
  function publicUrl(slug) {
11
12
  const origin = typeof window !== "undefined" ? window.location.origin : "";
@@ -56,7 +57,7 @@ export function PickstationsPage() {
56
57
  toast.error(url);
57
58
  }
58
59
  };
59
- 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 " +
60
+ 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"] })] }), _jsx(ReferentiedataBanner, {}), 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 " +
60
61
  (station.active
61
62
  ? "bg-primary/10 text-primary"
62
63
  : "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) }), _jsx(StationPrintplek, { station: station }), _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({
@@ -1 +1 @@
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
+ {"version":3,"file":"PickScherm.d.ts","sourceRoot":"","sources":["../../../src/components/pick/PickScherm.tsx"],"names":[],"mappings":"AAgCA,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,+BAwmBpD"}
@@ -4,6 +4,7 @@ import { Badge, Button, Card, CardContent, Input, Select, SelectContent, SelectI
4
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
+ import { PreviewDialog } from "./PreviewDialog";
7
8
  import { getSessionId, pickApi } from "../../lib/pickApi";
8
9
  import { completeLogisticsTaskForItem } from "../../lib/pickPrint";
9
10
  import { getPickTranslator } from "../../lib/pickI18n";
@@ -26,6 +27,7 @@ export function PickScherm({ station, onBack }) {
26
27
  const [busyId, setBusyId] = useState(null);
27
28
  const [pending, setPending] = useState(null);
28
29
  const [lastPrinted, setLastPrinted] = useState(null);
30
+ const [previewItem, setPreviewItem] = useState(null);
29
31
  const [emptyNotice, setEmptyNotice] = useState(null);
30
32
  const resetDone = useRef(null);
31
33
  const autoFetched = useRef(false);
@@ -304,5 +306,5 @@ export function PickScherm({ station, onBack }) {
304
306
  return;
305
307
  e.preventDefault();
306
308
  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}` : ""] })] }) })] }));
309
+ } })] }), _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, 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() : 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}` : ""] })] }) }), _jsx(PreviewDialog, { item: previewItem, stationSlug: station.slug, onClose: () => setPreviewItem(null) })] }));
308
310
  }
@@ -0,0 +1,13 @@
1
+ import type { PickQueueItem } from "../../lib/pickTypes";
2
+ interface Props {
3
+ item: PickQueueItem | null;
4
+ stationSlug: string | null;
5
+ onClose: () => void;
6
+ }
7
+ /**
8
+ * Toont het PDF-voorbeeld zoals de printketen het opbouwt. Bewust zonder
9
+ * printknop: printen loopt uitsluitend via de wachtrijknoppen.
10
+ */
11
+ export declare function PreviewDialog({ item, stationSlug, onClose }: Props): import("react").JSX.Element;
12
+ export {};
13
+ //# sourceMappingURL=PreviewDialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreviewDialog.d.ts","sourceRoot":"","sources":["../../../src/components/pick/PreviewDialog.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,UAAU,KAAK;IACb,IAAI,EAAE,aAAa,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,KAAK,+BAqFlE"}
@@ -0,0 +1,52 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@flowselections/core";
4
+ import { AlertTriangle, Loader2 } from "lucide-react";
5
+ import { fetchPickPreview, PickPreviewError } from "../../lib/pickPreview";
6
+ /**
7
+ * Toont het PDF-voorbeeld zoals de printketen het opbouwt. Bewust zonder
8
+ * printknop: printen loopt uitsluitend via de wachtrijknoppen.
9
+ */
10
+ export function PreviewDialog({ item, stationSlug, onClose }) {
11
+ const [url, setUrl] = useState(null);
12
+ const [bron, setBron] = useState(null);
13
+ const [error, setError] = useState(null);
14
+ const [loading, setLoading] = useState(false);
15
+ useEffect(() => {
16
+ if (!item)
17
+ return;
18
+ if (!stationSlug) {
19
+ setError("Dit pickstation heeft geen openbare verwijzing; een voorbeeld is niet mogelijk.");
20
+ return;
21
+ }
22
+ const controller = new AbortController();
23
+ let objectUrl = null;
24
+ setLoading(true);
25
+ setError(null);
26
+ setUrl(null);
27
+ setBron(null);
28
+ fetchPickPreview({ stationSlug, queueItemId: item.id, signal: controller.signal })
29
+ .then((result) => {
30
+ objectUrl = result.url;
31
+ setUrl(result.url);
32
+ setBron(result.bron);
33
+ })
34
+ .catch((err) => {
35
+ if (controller.signal.aborted)
36
+ return;
37
+ setError(err instanceof PickPreviewError
38
+ ? err.message
39
+ : "Het voorbeeld kon niet worden opgehaald.");
40
+ })
41
+ .finally(() => {
42
+ if (!controller.signal.aborted)
43
+ setLoading(false);
44
+ });
45
+ return () => {
46
+ controller.abort();
47
+ if (objectUrl)
48
+ URL.revokeObjectURL(objectUrl);
49
+ };
50
+ }, [item, stationSlug]);
51
+ return (_jsx(Dialog, { open: !!item, onOpenChange: (open) => !open && onClose(), children: _jsxs(DialogContent, { className: "max-w-3xl", children: [_jsxs(DialogHeader, { children: [_jsxs(DialogTitle, { children: ["Voorbeeld ", item?.document_number ?? ""] }), _jsx(DialogDescription, { children: bron ? `Bron: ${bron}` : "Zo komt dit document uit de printer." })] }), loading && (_jsx("div", { className: "flex h-96 items-center justify-center", children: _jsx(Loader2, { className: "h-8 w-8 animate-spin text-primary" }) })), !loading && error && (_jsxs("div", { className: "flex items-start gap-3 rounded-lg border border-destructive/40 bg-destructive/10 p-4", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-5 w-5 shrink-0 text-destructive" }), _jsx("p", { className: "text-sm text-foreground", children: error })] })), !loading && !error && url && (_jsx("object", { data: url, type: "application/pdf", className: "h-[70vh] max-h-[70vh] w-full rounded-lg border", "aria-label": `Voorbeeld van ${item?.document_number ?? "document"}`, children: _jsxs("p", { className: "p-4 text-sm text-muted-foreground", children: ["Deze browser kan de PDF niet tonen.", " ", _jsx("a", { className: "underline", href: url, target: "_blank", rel: "noreferrer", children: "Openen in een nieuw tabblad" })] }) }))] }) }));
52
+ }
@@ -8,9 +8,10 @@ interface Props {
8
8
  busyId: string | null;
9
9
  onPick: (item: PickQueueItem) => void;
10
10
  onReprint?: (item: PickQueueItem) => void;
11
+ onPreview?: (item: PickQueueItem) => void;
11
12
  readOnly?: boolean;
12
13
  t?: PickTranslator;
13
14
  }
14
- export declare function QueueTable({ items, lockedIds, statuses, documentTypes, busyId, onPick, onReprint, readOnly, t: translator, }: Props): import("react").JSX.Element;
15
+ export declare function QueueTable({ items, lockedIds, statuses, documentTypes, busyId, onPick, onReprint, onPreview, readOnly, t: translator, }: Props): import("react").JSX.Element;
15
16
  export {};
16
17
  //# sourceMappingURL=QueueTable.d.ts.map
@@ -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,+BA4NP"}
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,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,SAAS,EACT,QAAQ,EACR,CAAC,EAAE,UAAU,GACd,EAAE,KAAK,+BA4PP"}
@@ -1,6 +1,6 @@
1
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
- import { AlertTriangle, Lock, Printer, RotateCcw } from "lucide-react";
3
+ import { AlertTriangle, Eye, Lock, Printer, RotateCcw } from "lucide-react";
4
4
  import { sinceLabel } from "../../lib/pickTypes";
5
5
  import { getPickTranslator } from "../../lib/pickI18n";
6
6
  function priorityTone(priority, urgent) {
@@ -12,7 +12,7 @@ function priorityTone(priority, urgent) {
12
12
  return "bg-secondary text-secondary-foreground";
13
13
  return "bg-muted text-muted-foreground";
14
14
  }
15
- export function QueueTable({ items, lockedIds, statuses, documentTypes, busyId, onPick, onReprint, readOnly, t: translator, }) {
15
+ export function QueueTable({ items, lockedIds, statuses, documentTypes, busyId, onPick, onReprint, onPreview, readOnly, t: translator, }) {
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]));
@@ -25,14 +25,20 @@ export function QueueTable({ items, lockedIds, statuses, documentTypes, busyId,
25
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
26
  hour: "2-digit",
27
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));
28
+ }) }), _jsx(TableCell, { className: "whitespace-nowrap text-sm", children: sinceLabel(item.announced_at) }), _jsx(TableCell, { className: "text-right", children: _jsxs("div", { className: "flex items-center justify-end 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) => {
29
+ e.stopPropagation();
30
+ onPreview(item);
31
+ }, children: _jsx(Eye, { className: "h-5 w-5" }) })), 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
32
  }), 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
33
  const printed = !!item.printed_at;
31
34
  const locked = !printed && lockedIds.has(item.id);
32
35
  const doc = item.document_type_id ? docById.get(item.document_type_id) : undefined;
33
36
  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, {
37
+ 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 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) => {
38
+ e.stopPropagation();
39
+ onPreview(item);
40
+ }, children: _jsx(Eye, { className: "h-5 w-5" }) })), _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 " +
41
+ 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
42
  hour: "2-digit",
37
43
  minute: "2-digit",
38
44
  })] }), _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));
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Waarschuwing als verplichte referentiedata ontbreekt of uitgezet is.
3
+ * Rendert niets zodra alles aanwezig en actief is — geen groene bevestiging.
4
+ */
5
+ export declare function ReferentiedataBanner(): import("react").JSX.Element | null;
6
+ //# sourceMappingURL=ReferentiedataBanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReferentiedataBanner.d.ts","sourceRoot":"","sources":["../../../src/components/pick/ReferentiedataBanner.tsx"],"names":[],"mappings":"AAMA;;;GAGG;AACH,wBAAgB,oBAAoB,uCA4BnC"}
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button } from "@flowselections/core";
3
+ import { Link } from "@tanstack/react-router";
4
+ import { AlertTriangle } from "lucide-react";
5
+ import { usePickReferenceData } from "../../hooks/usePickReferenceData";
6
+ import { referentieProblemen } from "../../lib/pickReferenceApi";
7
+ /**
8
+ * Waarschuwing als verplichte referentiedata ontbreekt of uitgezet is.
9
+ * Rendert niets zodra alles aanwezig en actief is — geen groene bevestiging.
10
+ */
11
+ export function ReferentiedataBanner() {
12
+ const { data } = usePickReferenceData();
13
+ const problemen = referentieProblemen(data);
14
+ if (problemen.length === 0)
15
+ return null;
16
+ return (_jsxs("div", { className: "space-y-3 rounded-lg border border-destructive/50 bg-destructive/5 p-4", children: [_jsxs("div", { className: "flex items-start gap-3", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-5 w-5 shrink-0 text-destructive" }), _jsxs("div", { className: "space-y-1", children: [_jsx("h2", { className: "font-semibold text-destructive", children: "Referentiedata ontbreekt \u2014 er komt niets in de pickwachtrij" }), _jsx("ul", { className: "list-inside list-disc text-sm text-destructive", children: problemen.map((p) => (_jsx("li", { children: p }, p))) }), _jsx("p", { className: "text-sm text-muted-foreground", children: "De synchronisatie stopt hierop en pickstations blijven leeg." })] })] }), _jsx(Button, { variant: "outline", size: "sm", asChild: true, children: _jsx(Link, { to: "/instellingen", children: "Naar referentiedata-instellingen" }) })] }));
17
+ }
@@ -0,0 +1,2 @@
1
+ export declare function ReferentiedataPickdocumentenCard(): import("react").JSX.Element;
2
+ //# sourceMappingURL=ReferentiedataPickdocumentenCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReferentiedataPickdocumentenCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/ReferentiedataPickdocumentenCard.tsx"],"names":[],"mappings":"AAwEA,wBAAgB,gCAAgC,gCAyT/C"}
@@ -0,0 +1,84 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { useMutation, useQueryClient } from "@tanstack/react-query";
4
+ import { Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Input, Label, Switch, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, toast, } from "@flowselections/core";
5
+ import { FileText, Loader2, Plus, RotateCcw } from "lucide-react";
6
+ import { pickReferenceApi } from "../../lib/pickReferenceApi";
7
+ import { usePickReferenceData, PICK_REFERENCE_QUERY_KEY } from "../../hooks/usePickReferenceData";
8
+ function NumberCell({ value, onSave, }) {
9
+ const [local, setLocal] = useState(String(value ?? 0));
10
+ return (_jsx(Input, { className: "h-8 w-20", inputMode: "numeric", value: local, onChange: (e) => setLocal(e.target.value), onBlur: () => {
11
+ const n = Number(local);
12
+ if (Number.isFinite(n) && n !== value)
13
+ onSave(n);
14
+ else
15
+ setLocal(String(value ?? 0));
16
+ } }));
17
+ }
18
+ function TextCell({ value, onSave, className, }) {
19
+ const [local, setLocal] = useState(value ?? "");
20
+ return (_jsx(Input, { className: "h-8 " + (className ?? ""), value: local, onChange: (e) => setLocal(e.target.value), onBlur: () => {
21
+ const v = local.trim();
22
+ if (v && v !== value)
23
+ onSave(v);
24
+ else
25
+ setLocal(value ?? "");
26
+ } }));
27
+ }
28
+ export function ReferentiedataPickdocumentenCard() {
29
+ const { data, isLoading } = usePickReferenceData();
30
+ const queryClient = useQueryClient();
31
+ const [nieuw, setNieuw] = useState(null);
32
+ const types = Array.isArray(data?.types) ? data.types : [];
33
+ const statussen = Array.isArray(data?.statussen) ? data.statussen : [];
34
+ const verplichteTypes = Array.isArray(data?.verplichte_types) ? data.verplichte_types : [];
35
+ const verplichteStatussen = Array.isArray(data?.verplichte_statussen)
36
+ ? data.verplichte_statussen
37
+ : [];
38
+ const invalidate = () => queryClient.invalidateQueries({ queryKey: PICK_REFERENCE_QUERY_KEY });
39
+ const saveType = useMutation({
40
+ mutationFn: ({ id, patch }) => pickReferenceApi.updateType(id, patch),
41
+ onSuccess: invalidate,
42
+ onError: (e) => toast.error(e instanceof Error ? e.message : "Opslaan mislukt."),
43
+ });
44
+ const saveStatus = useMutation({
45
+ mutationFn: ({ id, patch }) => pickReferenceApi.updateStatus(id, patch),
46
+ onSuccess: invalidate,
47
+ onError: (e) => toast.error(e instanceof Error ? e.message : "Opslaan mislukt."),
48
+ });
49
+ const addRow = useMutation({
50
+ mutationFn: async (d) => {
51
+ const row = { code: d.code.trim(), name: d.naam.trim() };
52
+ if (d.tabel === "types")
53
+ await pickReferenceApi.insertType(row);
54
+ else
55
+ await pickReferenceApi.insertStatus(row);
56
+ },
57
+ onSuccess: () => {
58
+ toast.success("Rij toegevoegd.");
59
+ setNieuw(null);
60
+ invalidate();
61
+ },
62
+ onError: (e) => toast.error(e instanceof Error ? e.message : "Toevoegen mislukt."),
63
+ });
64
+ const seed = useMutation({
65
+ mutationFn: pickReferenceApi.seed,
66
+ onSuccess: (r) => {
67
+ const totaal = r.statuses_toegevoegd + r.types_toegevoegd;
68
+ const tekst = `${r.statuses_toegevoegd} statussen toegevoegd, ${r.types_toegevoegd} types toegevoegd`;
69
+ if (totaal === 0)
70
+ toast.message("Alle standaardwaarden waren al aanwezig.", { description: tekst });
71
+ else
72
+ toast.success(tekst);
73
+ invalidate();
74
+ },
75
+ onError: (e) => toast.error(e instanceof Error ? e.message : "Herstellen mislukt."),
76
+ });
77
+ return (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(FileText, { className: "h-5 w-5 text-primary" }), _jsx(CardTitle, { children: "Referentiedata pickdocumenten" })] }), _jsx(CardDescription, { children: "De synchronisatie zoekt hardcoded op deze codes: zonder documenttype 'pakbon' komt er niets in de pickwachtrij. De kolom code is daarom niet te wijzigen." })] }), _jsxs(CardContent, { className: "space-y-8", children: [_jsx("div", { className: "flex flex-wrap gap-2", children: _jsxs(Button, { variant: "outline", onClick: () => seed.mutate(), disabled: seed.isPending, children: [seed.isPending ? (_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" })) : (_jsx(RotateCcw, { className: "mr-2 h-4 w-4" })), "Standaardwaarden herstellen"] }) }), isLoading ? (_jsxs("div", { className: "flex items-center gap-2 text-muted-foreground", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), " Laden..."] })) : (_jsxs(_Fragment, { children: [_jsxs("section", { className: "space-y-3", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [_jsxs("h3", { className: "font-semibold text-foreground", children: ["Documenttypes (", types.length, ")"] }), _jsxs(Button, { variant: "ghost", size: "sm", onClick: () => setNieuw({ tabel: "types", code: "", naam: "" }), children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), " Type toevoegen"] })] }), _jsx("div", { className: "overflow-x-auto", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Code" }), _jsx(TableHead, { children: "Naam" }), _jsx(TableHead, { children: "Kleur" }), _jsx(TableHead, { children: "Icoon" }), _jsx(TableHead, { children: "Prioriteit" }), _jsx(TableHead, { children: "Sortering" }), _jsx(TableHead, { children: "Actief" })] }) }), _jsx(TableBody, { children: types.map((t) => {
78
+ const verplicht = verplichteTypes.includes(t.code);
79
+ return (_jsxs(TableRow, { children: [_jsx(TableCell, { className: "font-mono text-xs", children: t.code }), _jsx(TableCell, { children: _jsx(TextCell, { value: t.name, className: "w-40", onSave: (name) => saveType.mutate({ id: t.id, patch: { name } }) }) }), _jsx(TableCell, { children: _jsx(TextCell, { value: t.color ?? "", className: "w-28 font-mono text-xs", onSave: (color) => saveType.mutate({ id: t.id, patch: { color } }) }) }), _jsx(TableCell, { children: _jsx(TextCell, { value: t.icon ?? "", className: "w-32", onSave: (icon) => saveType.mutate({ id: t.id, patch: { icon } }) }) }), _jsx(TableCell, { children: _jsx(NumberCell, { value: t.priority, onSave: (priority) => saveType.mutate({ id: t.id, patch: { priority } }) }) }), _jsx(TableCell, { children: _jsx(NumberCell, { value: t.sort_order, onSave: (sort_order) => saveType.mutate({ id: t.id, patch: { sort_order } }) }) }), _jsx(TableCell, { children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Switch, { checked: t.active, disabled: verplicht && t.active, onCheckedChange: (active) => saveType.mutate({ id: t.id, patch: { active } }) }), verplicht && (_jsx("span", { className: "text-xs text-muted-foreground", children: "Verplicht \u2014 kan niet uit" }))] }) })] }, t.id));
80
+ }) })] }) })] }), _jsxs("section", { className: "space-y-3", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [_jsxs("h3", { className: "font-semibold text-foreground", children: ["Documentstatussen (", statussen.length, ")"] }), _jsxs(Button, { variant: "ghost", size: "sm", onClick: () => setNieuw({ tabel: "statussen", code: "", naam: "" }), children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), " Status toevoegen"] })] }), _jsx("div", { className: "overflow-x-auto", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Code" }), _jsx(TableHead, { children: "Naam" }), _jsx(TableHead, { children: "Kleur" }), _jsx(TableHead, { children: "Sortering" }), _jsx(TableHead, { children: "Open" }), _jsx(TableHead, { children: "Eindstatus" }), _jsx(TableHead, { children: "Actief" })] }) }), _jsx(TableBody, { children: statussen.map((s) => {
81
+ const verplicht = verplichteStatussen.includes(s.code);
82
+ return (_jsxs(TableRow, { children: [_jsx(TableCell, { className: "font-mono text-xs", children: s.code }), _jsx(TableCell, { children: _jsx(TextCell, { value: s.name, className: "w-40", onSave: (name) => saveStatus.mutate({ id: s.id, patch: { name } }) }) }), _jsx(TableCell, { children: _jsx(TextCell, { value: s.color ?? "", className: "w-28 font-mono text-xs", onSave: (color) => saveStatus.mutate({ id: s.id, patch: { color } }) }) }), _jsx(TableCell, { children: _jsx(NumberCell, { value: s.sort_order, onSave: (sort_order) => saveStatus.mutate({ id: s.id, patch: { sort_order } }) }) }), _jsx(TableCell, { children: _jsx(Switch, { checked: s.is_open, onCheckedChange: (is_open) => saveStatus.mutate({ id: s.id, patch: { is_open } }) }) }), _jsx(TableCell, { children: _jsx(Switch, { checked: s.is_terminal, onCheckedChange: (is_terminal) => saveStatus.mutate({ id: s.id, patch: { is_terminal } }) }) }), _jsx(TableCell, { children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Switch, { checked: s.active, disabled: verplicht && s.active, onCheckedChange: (active) => saveStatus.mutate({ id: s.id, patch: { active } }) }), verplicht && (_jsx("span", { className: "text-xs text-muted-foreground", children: "Verplicht \u2014 kan niet uit" }))] }) })] }, s.id));
83
+ }) })] }) })] })] })), nieuw && (_jsxs("div", { className: "space-y-3 rounded-md border p-4", children: [_jsxs("p", { className: "text-sm font-medium text-foreground", children: ["Nieuwe ", nieuw.tabel === "types" ? "documenttype" : "documentstatus"] }), _jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "ref-code", children: "Code" }), _jsx(Input, { id: "ref-code", value: nieuw.code, onChange: (e) => setNieuw({ ...nieuw, code: e.target.value }), placeholder: "bijv. wagenlijst" })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "ref-naam", children: "Naam" }), _jsx(Input, { id: "ref-naam", value: nieuw.naam, onChange: (e) => setNieuw({ ...nieuw, naam: e.target.value }) })] })] }), _jsxs("div", { className: "flex justify-end gap-2", children: [_jsx(Button, { variant: "outline", onClick: () => setNieuw(null), children: "Annuleren" }), _jsxs(Button, { disabled: !nieuw.code.trim() || !nieuw.naam.trim() || addRow.isPending, onClick: () => addRow.mutate(nieuw), children: [addRow.isPending && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), " Toevoegen"] })] })] }))] })] }));
84
+ }
@@ -0,0 +1,4 @@
1
+ export declare const PICK_REFERENCE_QUERY_KEY: readonly ["pick", "referenceData"];
2
+ /** Eén bron voor de instellingenkaart en de waarschuwingsbanner. */
3
+ export declare function usePickReferenceData(): import("@tanstack/react-query").UseQueryResult<NoInfer<import("..").PickReferenceStatus>, Error>;
4
+ //# sourceMappingURL=usePickReferenceData.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePickReferenceData.d.ts","sourceRoot":"","sources":["../../src/hooks/usePickReferenceData.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,wBAAwB,oCAAqC,CAAC;AAE3E,oEAAoE;AACpE,wBAAgB,oBAAoB,qGAKnC"}
@@ -0,0 +1,10 @@
1
+ import { useQuery } from "@tanstack/react-query";
2
+ import { pickReferenceApi } from "../lib/pickReferenceApi";
3
+ export const PICK_REFERENCE_QUERY_KEY = ["pick", "referenceData"];
4
+ /** Eén bron voor de instellingenkaart en de waarschuwingsbanner. */
5
+ export function usePickReferenceData() {
6
+ return useQuery({
7
+ queryKey: PICK_REFERENCE_QUERY_KEY,
8
+ queryFn: pickReferenceApi.status,
9
+ });
10
+ }
@@ -16,5 +16,10 @@ export { PickScherm } from './components/pick/PickScherm';
16
16
  export { PickstationsPage } from './components/PickstationsPage';
17
17
  export { PickPublicPage } from './components/PickPublicPage';
18
18
  export { PublicPickRoute } from './components/pick/PublicPickRoute';
19
+ export { pickReferenceApi, referentieProblemen, VERPLICHTE_TYPE_CODES, VERPLICHTE_STATUS_CODES, } from './lib/pickReferenceApi';
20
+ export type { PickReferenceStatus } from './lib/pickReferenceApi';
21
+ export { usePickReferenceData, PICK_REFERENCE_QUERY_KEY } from './hooks/usePickReferenceData';
22
+ export { ReferentiedataPickdocumentenCard } from './components/settings/ReferentiedataPickdocumentenCard';
23
+ export { ReferentiedataBanner } from './components/pick/ReferentiedataBanner';
19
24
  export declare const pickSchermenModule: FlowModule;
20
25
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAErE,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAOpE,eAAO,MAAM,kBAAkB,EAAE,UAYhC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGvD,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAErE,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AAC9F,OAAO,EAAE,gCAAgC,EAAE,MAAM,wDAAwD,CAAC;AAC1G,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAE9E,eAAO,MAAM,kBAAkB,EAAE,UAYhC,CAAC"}
package/dist-lib/index.js CHANGED
@@ -14,6 +14,7 @@
14
14
  // 4. Done! You don't need to touch any other file for registration.
15
15
  // ============================================================================
16
16
  import { Warehouse } from "lucide-react";
17
+ import { ReferentiedataPickdocumentenCard } from "./components/settings/ReferentiedataPickdocumentenCard";
17
18
  export * from './_core-safelist';
18
19
  export * from './components/TemplatePage';
19
20
  export { TemplateModuleLogo } from './components/TemplateModuleLogo';
@@ -31,10 +32,10 @@ export { PickScherm } from './components/pick/PickScherm';
31
32
  export { PickstationsPage } from './components/PickstationsPage';
32
33
  export { PickPublicPage } from './components/PickPublicPage';
33
34
  export { PublicPickRoute } from './components/pick/PublicPickRoute';
34
- // Import your settings cards here (delete if you have none)
35
- // import { MySettingsCard } from "./components/settings/MySettingsCard";
36
- // ⚠️ HERNOEM naar een unieke naam, bijv. floridayVerkoopModule
37
- // De naam 'myModule' veroorzaakt een duplicate identifier bij meerdere modules in één shell.
35
+ export { pickReferenceApi, referentieProblemen, VERPLICHTE_TYPE_CODES, VERPLICHTE_STATUS_CODES, } from './lib/pickReferenceApi';
36
+ export { usePickReferenceData, PICK_REFERENCE_QUERY_KEY } from './hooks/usePickReferenceData';
37
+ export { ReferentiedataPickdocumentenCard } from './components/settings/ReferentiedataPickdocumentenCard';
38
+ export { ReferentiedataBanner } from './components/pick/ReferentiedataBanner';
38
39
  export const pickSchermenModule = {
39
40
  id: "pick-schermen",
40
41
  name: "Pickstations",
@@ -44,5 +45,5 @@ export const pickSchermenModule = {
44
45
  href: "/pickstations",
45
46
  icon: Warehouse,
46
47
  },
47
- settingsCards: [],
48
+ settingsCards: [{ component: ReferentiedataPickdocumentenCard, order: 10 }],
48
49
  };