@flowselections/layout-maker 1.3.3 → 1.6.5

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 (112) hide show
  1. package/README.md +24 -24
  2. package/dist-lib/components/AfdrukKnop.d.ts +3 -1
  3. package/dist-lib/components/AfdrukKnop.d.ts.map +1 -1
  4. package/dist-lib/components/AfdrukKnop.js +24 -3
  5. package/dist-lib/components/ComputersLijst.d.ts +23 -0
  6. package/dist-lib/components/ComputersLijst.d.ts.map +1 -0
  7. package/dist-lib/components/ComputersLijst.js +75 -0
  8. package/dist-lib/components/LayoutsPage.d.ts.map +1 -1
  9. package/dist-lib/components/LayoutsPage.js +2 -0
  10. package/dist-lib/components/LogosPage.d.ts.map +1 -1
  11. package/dist-lib/components/LogosPage.js +2 -0
  12. package/dist-lib/components/NetwerkPrintersDialog.d.ts +8 -0
  13. package/dist-lib/components/NetwerkPrintersDialog.d.ts.map +1 -0
  14. package/dist-lib/components/NetwerkPrintersDialog.js +79 -0
  15. package/dist-lib/components/PrintProgrammaUitleg.d.ts +5 -0
  16. package/dist-lib/components/PrintProgrammaUitleg.d.ts.map +1 -0
  17. package/dist-lib/components/PrintProgrammaUitleg.js +19 -0
  18. package/dist-lib/components/PrintQueuePage.d.ts.map +1 -1
  19. package/dist-lib/components/PrintQueuePage.js +37 -3
  20. package/dist-lib/components/PrinterKaart.d.ts +17 -0
  21. package/dist-lib/components/PrinterKaart.d.ts.map +1 -0
  22. package/dist-lib/components/PrinterKaart.js +14 -0
  23. package/dist-lib/components/PrinterSetupWizard.d.ts +11 -1
  24. package/dist-lib/components/PrinterSetupWizard.d.ts.map +1 -1
  25. package/dist-lib/components/PrinterSetupWizard.js +134 -64
  26. package/dist-lib/components/PrinterStatsKaarten.d.ts +11 -0
  27. package/dist-lib/components/PrinterStatsKaarten.d.ts.map +1 -0
  28. package/dist-lib/components/PrinterStatsKaarten.js +8 -0
  29. package/dist-lib/components/PrintersPage.d.ts.map +1 -1
  30. package/dist-lib/components/PrintersPage.js +120 -49
  31. package/dist-lib/components/WerkplekConfiguratiePage.d.ts +2 -0
  32. package/dist-lib/components/WerkplekConfiguratiePage.d.ts.map +1 -0
  33. package/dist-lib/components/WerkplekConfiguratiePage.js +101 -0
  34. package/dist-lib/components/WerkplekkenTabel.d.ts +14 -0
  35. package/dist-lib/components/WerkplekkenTabel.d.ts.map +1 -0
  36. package/dist-lib/components/WerkplekkenTabel.js +16 -0
  37. package/dist-lib/index.d.ts +11 -0
  38. package/dist-lib/index.d.ts.map +1 -1
  39. package/dist-lib/index.js +11 -0
  40. package/dist-lib/integrations/supabase/auth-middleware.d.ts +925 -34
  41. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  42. package/dist-lib/integrations/supabase/client.server.d.ts +925 -34
  43. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  44. package/dist-lib/integrations/supabase/types.d.ts +920 -29
  45. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  46. package/dist-lib/integrations/supabase/types.js +12 -1
  47. package/dist-lib/lib/aiLayout.functions.d.ts +925 -34
  48. package/dist-lib/lib/aiLayout.functions.d.ts.map +1 -1
  49. package/dist-lib/lib/aiLayout.server.js +9 -9
  50. package/dist-lib/lib/browserPrint.d.ts +1 -0
  51. package/dist-lib/lib/browserPrint.d.ts.map +1 -1
  52. package/dist-lib/lib/browserPrint.js +6 -6
  53. package/dist-lib/lib/centralAuth.server.d.ts +13 -0
  54. package/dist-lib/lib/centralAuth.server.d.ts.map +1 -0
  55. package/dist-lib/lib/centralAuth.server.js +60 -0
  56. package/dist-lib/lib/directPrint.d.ts +26 -0
  57. package/dist-lib/lib/directPrint.d.ts.map +1 -0
  58. package/dist-lib/lib/directPrint.js +65 -0
  59. package/dist-lib/lib/documentPdf.d.ts +11 -0
  60. package/dist-lib/lib/documentPdf.d.ts.map +1 -0
  61. package/dist-lib/lib/documentPdf.js +62 -0
  62. package/dist-lib/lib/htmlNaarPdf.server.d.ts +14 -0
  63. package/dist-lib/lib/htmlNaarPdf.server.d.ts.map +1 -0
  64. package/dist-lib/lib/htmlNaarPdf.server.js +34 -0
  65. package/dist-lib/lib/htmlPdf.server.d.ts +29 -0
  66. package/dist-lib/lib/htmlPdf.server.d.ts.map +1 -0
  67. package/dist-lib/lib/htmlPdf.server.js +1009 -0
  68. package/dist-lib/lib/layoutPreview.d.ts +1 -1
  69. package/dist-lib/lib/layoutPreview.d.ts.map +1 -1
  70. package/dist-lib/lib/layoutPreview.js +9 -9
  71. package/dist-lib/lib/logoLibrary.d.ts +1 -1
  72. package/dist-lib/lib/logoLibrary.js +5 -3
  73. package/dist-lib/lib/orderData.server.d.ts +15 -0
  74. package/dist-lib/lib/orderData.server.d.ts.map +1 -0
  75. package/dist-lib/lib/orderData.server.js +194 -0
  76. package/dist-lib/lib/pakbonBuilder.d.ts.map +1 -1
  77. package/dist-lib/lib/pakbonBuilder.js +22 -2
  78. package/dist-lib/lib/pakbonHtml.js +50 -50
  79. package/dist-lib/lib/printQueue.server.d.ts +31 -0
  80. package/dist-lib/lib/printQueue.server.d.ts.map +1 -0
  81. package/dist-lib/lib/printQueue.server.js +435 -0
  82. package/dist-lib/lib/printService.functions.d.ts +103742 -0
  83. package/dist-lib/lib/printService.functions.d.ts.map +1 -0
  84. package/dist-lib/lib/printService.functions.js +94 -0
  85. package/dist-lib/lib/printService.server.d.ts +31 -0
  86. package/dist-lib/lib/printService.server.d.ts.map +1 -0
  87. package/dist-lib/lib/printService.server.js +110 -0
  88. package/dist-lib/lib/productiebonHtml.d.ts +18 -0
  89. package/dist-lib/lib/productiebonHtml.d.ts.map +1 -0
  90. package/dist-lib/lib/productiebonHtml.js +166 -0
  91. package/dist-lib/lib/profielHtml.d.ts +14 -0
  92. package/dist-lib/lib/profielHtml.d.ts.map +1 -0
  93. package/dist-lib/lib/profielHtml.js +256 -0
  94. package/dist-lib/lib/runnerRegistry.server.d.ts +10 -0
  95. package/dist-lib/lib/runnerRegistry.server.d.ts.map +1 -0
  96. package/dist-lib/lib/runnerRegistry.server.js +79 -0
  97. package/dist-lib/lib/supabaseAdmin.server.d.ts +6 -0
  98. package/dist-lib/lib/supabaseAdmin.server.d.ts.map +1 -0
  99. package/dist-lib/lib/supabaseAdmin.server.js +43 -0
  100. package/dist-lib/lib/testpagina.d.ts +2 -0
  101. package/dist-lib/lib/testpagina.d.ts.map +1 -0
  102. package/dist-lib/lib/testpagina.js +31 -0
  103. package/dist-lib/lib/useAutoRefresh.d.ts +8 -0
  104. package/dist-lib/lib/useAutoRefresh.d.ts.map +1 -0
  105. package/dist-lib/lib/useAutoRefresh.js +44 -0
  106. package/dist-lib/lib/useDocumentData.d.ts +4 -3
  107. package/dist-lib/lib/useDocumentData.d.ts.map +1 -1
  108. package/dist-lib/lib/useDocumentData.js +10 -7
  109. package/dist-lib/lib/useNetwerkPrinters.d.ts +12 -0
  110. package/dist-lib/lib/useNetwerkPrinters.d.ts.map +1 -0
  111. package/dist-lib/lib/useNetwerkPrinters.js +26 -0
  112. package/package.json +11 -3
package/README.md CHANGED
@@ -1,24 +1,24 @@
1
- # Layout maker (pakbonnen, verzendbrieven, ectra)
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/4735fccb-b385-4b48-b4f8-ef135f63f4f7).
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
+ # Layout maker (pakbonnen, verzendbrieven, ectra)
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/4735fccb-b385-4b48-b4f8-ef135f63f4f7).
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
+ ```
@@ -8,6 +8,8 @@ export interface AfdrukKnopProps {
8
8
  css?: string;
9
9
  documentnaam?: string;
10
10
  label?: string;
11
+ layoutId?: string | null;
12
+ kopieen?: number;
11
13
  }
12
- export declare function AfdrukKnop({ documenttype, formaatCode, orientatie, getHtml, css, documentnaam, label, }: AfdrukKnopProps): import("react").JSX.Element;
14
+ export declare function AfdrukKnop({ documenttype, formaatCode, orientatie, getHtml, css, documentnaam, label, layoutId, kopieen, }: AfdrukKnopProps): import("react").JSX.Element;
13
15
  //# sourceMappingURL=AfdrukKnop.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AfdrukKnop.d.ts","sourceRoot":"","sources":["../../src/components/AfdrukKnop.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE9D,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,UAAU,CAAC;IACvB,uEAAuE;IACvE,OAAO,EAAE,MAAM,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,UAAU,CAAC,EACzB,YAAY,EACZ,WAAW,EACX,UAAU,EACV,OAAO,EACP,GAAG,EACH,YAAY,EACZ,KAAmB,GACpB,EAAE,eAAe,+BAgCjB"}
1
+ {"version":3,"file":"AfdrukKnop.d.ts","sourceRoot":"","sources":["../../src/components/AfdrukKnop.tsx"],"names":[],"mappings":"AASA,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAG9D,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,UAAU,CAAC;IACvB,uEAAuE;IACvE,OAAO,EAAE,MAAM,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,UAAU,CAAC,EACzB,YAAY,EACZ,WAAW,EACX,UAAU,EACV,OAAO,EACP,GAAG,EACH,YAAY,EACZ,KAAmB,EACnB,QAAQ,EACR,OAAO,GACR,EAAE,eAAe,+BAwDjB"}
@@ -1,22 +1,43 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  // ============================================================================
3
3
  // src/components/AfdrukKnop.tsx — afdrukken met automatisch ingesteld
4
- // papierformaat, stand en de bedoelde printer.
4
+ // papierformaat, stand en de bedoelde printer. Waar mogelijk gaat het
5
+ // document direct naar de printer; anders opent het printvenster.
5
6
  // ============================================================================
6
7
  import { useState } from "react";
7
8
  import { Button, toast } from "@flowselections/core";
8
9
  import { Loader2, Printer } from "lucide-react";
9
10
  import { drukAf } from "../lib/browserPrint";
10
- export function AfdrukKnop({ documenttype, formaatCode, orientatie, getHtml, css, documentnaam, label = "Afdrukken", }) {
11
+ import { printDirect } from "../lib/directPrint";
12
+ export function AfdrukKnop({ documenttype, formaatCode, orientatie, getHtml, css, documentnaam, label = "Afdrukken", layoutId, kopieen, }) {
11
13
  const [bezig, setBezig] = useState(false);
12
14
  const afdrukken = async () => {
13
15
  setBezig(true);
14
16
  try {
17
+ const html = getHtml();
18
+ const direct = await printDirect({
19
+ documenttype,
20
+ formaatCode,
21
+ orientatie,
22
+ html,
23
+ css,
24
+ documentnaam,
25
+ layoutId: layoutId ?? null,
26
+ kopieen,
27
+ });
28
+ if (direct.gelukt) {
29
+ toast.success(direct.printernaam
30
+ ? `Verstuurd naar ${direct.printernaam}`
31
+ : "Het document is naar de printer verstuurd");
32
+ return;
33
+ }
34
+ if (direct.reden)
35
+ toast.error(direct.reden);
15
36
  const { printer } = await drukAf({
16
37
  documenttype,
17
38
  formaatCode,
18
39
  orientatie,
19
- html: getHtml(),
40
+ html,
20
41
  css,
21
42
  documentnaam,
22
43
  });
@@ -0,0 +1,23 @@
1
+ export interface ComputerModel {
2
+ id: string;
3
+ naam: string;
4
+ online: boolean;
5
+ aantalPrinters: number;
6
+ }
7
+ export declare function useComputers(): {
8
+ computers: ComputerModel[];
9
+ loading: boolean;
10
+ fout: string | null;
11
+ reload: (stil?: boolean) => Promise<void>;
12
+ };
13
+ export declare function ComputersLijst({ computers, loading, fout, onVernieuw, onPrintersToevoegen, toevoegenOpen, onToevoegenOpenChange, alleenDialog, }: {
14
+ computers: ComputerModel[];
15
+ loading: boolean;
16
+ fout?: string | null;
17
+ onVernieuw: () => void;
18
+ onPrintersToevoegen: (computer: string) => void;
19
+ toevoegenOpen: boolean;
20
+ onToevoegenOpenChange: (v: boolean) => void;
21
+ alleenDialog?: boolean;
22
+ }): import("react").JSX.Element;
23
+ //# sourceMappingURL=ComputersLijst.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ComputersLijst.d.ts","sourceRoot":"","sources":["../../src/components/ComputersLijst.tsx"],"names":[],"mappings":"AAoBA,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,YAAY;;;;;EA6C3B;AAED,wBAAgB,cAAc,CAAC,EAC7B,SAAS,EACT,OAAO,EACP,IAAI,EACJ,UAAU,EACV,mBAAmB,EACnB,aAAa,EACb,qBAAqB,EACrB,YAAoB,GACrB,EAAE;IACD,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,mBAAmB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,aAAa,EAAE,OAAO,CAAC;IACvB,qBAAqB,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5C,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,+BAuHA"}
@@ -0,0 +1,75 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // ============================================================================
3
+ // src/components/ComputersLijst.tsx — overzicht van computers die het
4
+ // printprogramma draaien, plus een korte stroom om er een toe te voegen.
5
+ // ============================================================================
6
+ import { useCallback, useEffect, useState } from "react";
7
+ import { Button, Card, CardContent, Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@flowselections/core";
8
+ import { Loader2, Monitor, Plus, RefreshCw } from "lucide-react";
9
+ import { netwerkComputers, netwerkPrinters } from "../lib/printService.functions";
10
+ import { PrintProgrammaUitleg, WerktHetNiet } from "./PrintProgrammaUitleg";
11
+ export function useComputers() {
12
+ const [computers, setComputers] = useState([]);
13
+ const [loading, setLoading] = useState(true);
14
+ const [fout, setFout] = useState(null);
15
+ const load = useCallback(async (stil = false) => {
16
+ if (!stil)
17
+ setLoading(true);
18
+ setFout(null);
19
+ try {
20
+ const [c, p] = await Promise.all([
21
+ netwerkComputers({ data: undefined }),
22
+ netwerkPrinters({ data: undefined }),
23
+ ]);
24
+ const printers = p.ok && Array.isArray(p.printers) ? p.printers : [];
25
+ const lijst = c.ok && Array.isArray(c.computers) ? c.computers : [];
26
+ if (!c.ok)
27
+ setFout(c.fout);
28
+ setComputers(lijst.map((comp) => ({
29
+ id: String(comp.id),
30
+ naam: comp.naam,
31
+ online: !!comp.online,
32
+ aantalPrinters: printers.filter((pr) => pr.computer === comp.naam).length,
33
+ })));
34
+ }
35
+ catch (e) {
36
+ const melding = e instanceof Error ? e.message : "";
37
+ setFout(/401|unauthorized|authorization/i.test(melding)
38
+ ? "Je sessie is verlopen. Log opnieuw in en probeer het nog eens."
39
+ : "Er kon geen verbinding worden gemaakt met de printdienst.");
40
+ if (!stil)
41
+ setComputers([]);
42
+ }
43
+ finally {
44
+ setLoading(false);
45
+ }
46
+ }, []);
47
+ useEffect(() => {
48
+ void load();
49
+ }, [load]);
50
+ return { computers, loading, fout, reload: load };
51
+ }
52
+ export function ComputersLijst({ computers, loading, fout, onVernieuw, onPrintersToevoegen, toevoegenOpen, onToevoegenOpenChange, alleenDialog = false, }) {
53
+ const [wachtOp, setWachtOp] = useState([]);
54
+ const [nieuw, setNieuw] = useState(null);
55
+ useEffect(() => {
56
+ if (!toevoegenOpen) {
57
+ setNieuw(null);
58
+ return;
59
+ }
60
+ setWachtOp(computers.map((c) => c.id));
61
+ const timer = setInterval(() => onVernieuw(), 5000);
62
+ return () => clearInterval(timer);
63
+ }, [toevoegenOpen]); // eslint-disable-line react-hooks/exhaustive-deps
64
+ useEffect(() => {
65
+ if (!toevoegenOpen || nieuw)
66
+ return;
67
+ const gevonden = computers.find((c) => !wachtOp.includes(c.id));
68
+ if (gevonden)
69
+ setNieuw(gevonden);
70
+ }, [computers, toevoegenOpen, wachtOp, nieuw]);
71
+ return (_jsxs("div", { className: alleenDialog ? "" : "space-y-3", children: [!alleenDialog && loading && _jsx("p", { className: "text-muted-foreground text-sm", children: "Laden\u2026" }), !alleenDialog && !loading && fout && (_jsx(Card, { children: _jsxs(CardContent, { className: "space-y-3 py-6", children: [_jsx("p", { className: "font-medium", children: "Geen verbinding" }), _jsx("p", { className: "text-muted-foreground text-sm", children: fout }), _jsxs(Button, { variant: "outline", onClick: onVernieuw, children: [_jsx(RefreshCw, { className: "mr-2 h-4 w-4" }), " Opnieuw proberen"] })] }) })), !alleenDialog && !loading && !fout && computers.length === 0 && (_jsx(Card, { children: _jsxs(CardContent, { className: "space-y-4 py-8", children: [_jsx(PrintProgrammaUitleg, {}), _jsxs(Button, { onClick: () => onToevoegenOpenChange(true), children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), " Computer toevoegen"] })] }) })), !alleenDialog && computers.map((c) => (_jsxs("div", { className: "bg-card flex items-center gap-4 rounded-xl border p-4", children: [_jsx("div", { className: "bg-muted rounded-lg p-2.5", children: _jsx(Monitor, { className: "text-muted-foreground h-5 w-5" }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "truncate font-medium", children: c.naam }), _jsxs("p", { className: "text-muted-foreground text-sm", children: [c.aantalPrinters, " ", c.aantalPrinters === 1 ? "printer" : "printers"] })] }), _jsx("span", { className: `rounded-full px-2.5 py-1 text-xs font-medium ${c.online ? "bg-primary/10 text-primary" : "bg-muted text-muted-foreground"}`, children: c.online ? "Aan" : "Uit" }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => onPrintersToevoegen(c.naam), children: "Printers toevoegen" })] }, c.id))), !alleenDialog && computers.length > 0 && _jsx(WerktHetNiet, {}), _jsx(Dialog, { open: toevoegenOpen, onOpenChange: onToevoegenOpenChange, children: _jsxs(DialogContent, { className: "sm:max-w-lg", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Computer toevoegen" }), _jsx(DialogDescription, { children: "Zet het printprogramma klaar op de computer waar de printers aan hangen." })] }), _jsx(PrintProgrammaUitleg, { compact: true }), _jsx("div", { className: "rounded-lg border p-4 text-sm", children: nieuw ? (_jsxs("div", { className: "space-y-3", children: [_jsxs("p", { className: "font-medium", children: ["Computer gevonden: ", nieuw.naam] }), _jsx(Button, { onClick: () => {
72
+ onToevoegenOpenChange(false);
73
+ onPrintersToevoegen(nieuw.naam);
74
+ }, children: "Printers van deze computer toevoegen" })] })) : (_jsxs("p", { className: "text-muted-foreground flex items-center gap-2", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), " We wachten tot de computer zich meldt\u2026"] })) }), _jsx("div", { className: "flex justify-end", children: _jsx(Button, { variant: "outline", onClick: () => onToevoegenOpenChange(false), children: "Sluiten" }) }), _jsx(WerktHetNiet, {})] }) })] }));
75
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"LayoutsPage.d.ts","sourceRoot":"","sources":["../../src/components/LayoutsPage.tsx"],"names":[],"mappings":"AAyDA,wBAAgB,WAAW,gCAijB1B"}
1
+ {"version":3,"file":"LayoutsPage.d.ts","sourceRoot":"","sources":["../../src/components/LayoutsPage.tsx"],"names":[],"mappings":"AA0DA,wBAAgB,WAAW,gCAkjB1B"}
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useMemo, useState } from "react";
3
+ import { useAutoRefresh } from "../lib/useAutoRefresh";
3
4
  import { useNavigate } from "@tanstack/react-router";
4
5
  import { Badge, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Separator, Switch, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Textarea, toast, } from "@flowselections/core";
5
6
  import { Copy, FileText, Images, Pencil, Plus, Search, Settings2, Trash2 } from "lucide-react";
@@ -14,6 +15,7 @@ function klantOntwerpLayout(l) {
14
15
  }
15
16
  export function LayoutsPage() {
16
17
  const { layouts, loading, reload } = useLayouts();
18
+ useAutoRefresh(() => reload(true), 30000);
17
19
  const navigate = useNavigate();
18
20
  const [zoek, setZoek] = useState("");
19
21
  const [typeFilter, setTypeFilter] = useState("alle");
@@ -1 +1 @@
1
- {"version":3,"file":"LogosPage.d.ts","sourceRoot":"","sources":["../../src/components/LogosPage.tsx"],"names":[],"mappings":"AAiCA,OAAO,EAWL,KAAK,SAAS,EACf,MAAM,oBAAoB,CAAC;AAE5B,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,SAAc,EAAE,EAAE;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,+BAY9F;AASD,wBAAgB,SAAS,gCA4KxB"}
1
+ {"version":3,"file":"LogosPage.d.ts","sourceRoot":"","sources":["../../src/components/LogosPage.tsx"],"names":[],"mappings":"AAkCA,OAAO,EAWL,KAAK,SAAS,EACf,MAAM,oBAAoB,CAAC;AAE5B,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,SAAc,EAAE,EAAE;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,+BAY9F;AASD,wBAAgB,SAAS,gCA6KxB"}
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useMemo, useState } from "react";
3
3
  import { Badge, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Switch, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Textarea, toast, } from "@flowselections/core";
4
4
  import { Download, ImagePlus, Pencil, RefreshCw, Trash2, Upload } from "lucide-react";
5
+ import { useAutoRefresh } from "../lib/useAutoRefresh";
5
6
  import { LOGO_CATEGORIEEN, TOEGESTANE_LOGO_TYPES, downloadLogo, formatteerBytes, logoCategorieLabel, maakLogo, useLogos, vervangLogoBestand, verwijderLogo, werkLogoBij, } from "../lib/logoLibrary";
6
7
  export function LogoThumbnail({ logo, className = "" }) {
7
8
  return (_jsx("div", { className: `flex h-12 w-16 items-center justify-center overflow-hidden rounded border bg-[repeating-conic-gradient(#e5e7eb_0%_25%,#fff_0%_50%)] bg-[length:10px_10px] ${className}`, children: logo.viewUrl ? (_jsx("img", { src: logo.viewUrl, alt: logo.naam, className: "max-h-full max-w-full object-contain" })) : (_jsx(ImagePlus, { className: "h-4 w-4 text-muted-foreground" })) }));
@@ -12,6 +13,7 @@ export function LogosPage() {
12
13
  const [categorie, setCategorie] = useState("alle");
13
14
  const [uploadOpen, setUploadOpen] = useState(false);
14
15
  const [bewerk, setBewerk] = useState(null);
16
+ useAutoRefresh(() => reload(true), 30000, uploadOpen || !!bewerk);
15
17
  const zichtbaar = useMemo(() => {
16
18
  const q = zoek.trim().toLowerCase();
17
19
  return logos.filter((l) => (categorie === "alle" || l.categorie === categorie) &&
@@ -0,0 +1,8 @@
1
+ export declare function NetwerkPrintersDialog({ open, onOpenChange, huidigePrinterId, huidigePrinterNaam, onKlaar, }: {
2
+ open: boolean;
3
+ onOpenChange: (v: boolean) => void;
4
+ huidigePrinterId?: string | null;
5
+ huidigePrinterNaam?: string | null;
6
+ onKlaar?: () => void;
7
+ }): import("react").JSX.Element;
8
+ //# sourceMappingURL=NetwerkPrintersDialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NetwerkPrintersDialog.d.ts","sourceRoot":"","sources":["../../src/components/NetwerkPrintersDialog.tsx"],"names":[],"mappings":"AA2BA,wBAAgB,qBAAqB,CAAC,EACpC,IAAI,EACJ,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,OAAO,GACR,EAAE;IACD,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,+BAkHA"}
@@ -0,0 +1,79 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // ============================================================================
3
+ // src/components/NetwerkPrintersDialog.tsx — printers uit het netwerk zoeken,
4
+ // toevoegen of koppelen aan een bestaande printer.
5
+ // ============================================================================
6
+ import { useCallback, useEffect, useState } from "react";
7
+ import { Button, Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, toast, } from "@flowselections/core";
8
+ import { Loader2, Printer, RefreshCw } from "lucide-react";
9
+ import { supabase } from "../lib/supabaseClient";
10
+ import { netwerkPrinters } from "../lib/printService.functions";
11
+ export function NetwerkPrintersDialog({ open, onOpenChange, huidigePrinterId, huidigePrinterNaam, onKlaar, }) {
12
+ const [bezig, setBezig] = useState(false);
13
+ const [fout, setFout] = useState(null);
14
+ const [lijst, setLijst] = useState([]);
15
+ const zoeken = useCallback(async () => {
16
+ setBezig(true);
17
+ setFout(null);
18
+ try {
19
+ const res = await netwerkPrinters({ data: undefined });
20
+ if (!res.ok) {
21
+ setFout(res.fout);
22
+ setLijst([]);
23
+ }
24
+ else {
25
+ setLijst(Array.isArray(res.printers) ? res.printers : []);
26
+ }
27
+ }
28
+ catch {
29
+ setFout("Er kon niet in het netwerk worden gezocht. Probeer het zo opnieuw.");
30
+ }
31
+ finally {
32
+ setBezig(false);
33
+ }
34
+ }, []);
35
+ useEffect(() => {
36
+ if (open)
37
+ void zoeken();
38
+ }, [open, zoeken]);
39
+ const toevoegen = async (p) => {
40
+ try {
41
+ const { error } = await supabase.from("printers").insert({
42
+ naam: p.naam,
43
+ systeemnaam: p.naam,
44
+ locatie: p.computer,
45
+ omschrijving: p.omschrijving,
46
+ online: p.online,
47
+ actief: true,
48
+ extern_printer_id: p.id,
49
+ });
50
+ if (error)
51
+ throw error;
52
+ toast.success(`${p.naam} is toegevoegd`);
53
+ onKlaar?.();
54
+ onOpenChange(false);
55
+ }
56
+ catch {
57
+ toast.error("Toevoegen mislukt");
58
+ }
59
+ };
60
+ const koppelen = async (p) => {
61
+ if (!huidigePrinterId)
62
+ return;
63
+ try {
64
+ const { error } = await supabase
65
+ .from("printers")
66
+ .update({ extern_printer_id: p.id, systeemnaam: p.naam, locatie: p.computer })
67
+ .eq("id", huidigePrinterId);
68
+ if (error)
69
+ throw error;
70
+ toast.success("Printer gekoppeld");
71
+ onKlaar?.();
72
+ onOpenChange(false);
73
+ }
74
+ catch {
75
+ toast.error("Koppelen mislukt");
76
+ }
77
+ };
78
+ return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "max-w-lg", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Printers in het netwerk" }), _jsx(DialogDescription, { children: "Kies een printer om toe te voegen. Staat een printer er niet bij? Zet dan de computer aan waar de printer op is aangesloten." })] }), _jsxs("div", { className: "space-y-2", children: [bezig && (_jsxs("p", { className: "text-muted-foreground flex items-center gap-2 text-sm", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), " Zoeken\u2026"] })), !bezig && fout && _jsx("p", { className: "text-destructive text-sm", children: fout }), !bezig && !fout && lijst.length === 0 && (_jsx("p", { className: "text-muted-foreground text-sm", children: "Er zijn geen printers gevonden." })), lijst.map((p) => (_jsxs("div", { className: "flex items-center gap-3 rounded-lg border p-3", children: [_jsx(Printer, { className: "text-muted-foreground h-5 w-5" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "truncate text-sm font-medium", children: p.naam }), _jsxs("p", { className: "text-muted-foreground truncate text-xs", children: [p.computer || "Onbekende computer", " \u00B7 ", p.online ? "online" : "offline"] })] }), huidigePrinterId && (_jsxs(Button, { variant: "outline", size: "sm", onClick: () => void koppelen(p), children: ["Koppelen aan ", huidigePrinterNaam ?? "printer"] })), _jsx(Button, { size: "sm", onClick: () => void toevoegen(p), children: "Toevoegen" })] }, p.id)))] }), _jsx("div", { className: "flex justify-end", children: _jsxs(Button, { variant: "ghost", onClick: () => void zoeken(), disabled: bezig, children: [_jsx(RefreshCw, { className: "mr-2 h-4 w-4" }), " Opnieuw zoeken"] }) })] }) }));
79
+ }
@@ -0,0 +1,5 @@
1
+ export declare function PrintProgrammaUitleg({ compact }: {
2
+ compact?: boolean;
3
+ }): import("react").JSX.Element;
4
+ export declare function WerktHetNiet(): import("react").JSX.Element;
5
+ //# sourceMappingURL=PrintProgrammaUitleg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PrintProgrammaUitleg.d.ts","sourceRoot":"","sources":["../../src/components/PrintProgrammaUitleg.tsx"],"names":[],"mappings":"AAgBA,wBAAgB,oBAAoB,CAAC,EAAE,OAAe,EAAE,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,+BAmC9E;AAED,wBAAgB,YAAY,gCAa3B"}
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // ============================================================================
3
+ // src/components/PrintProgrammaUitleg.tsx — uitleg over het printprogramma dat
4
+ // op de computer moet draaien voordat printers zichtbaar worden.
5
+ // ============================================================================
6
+ import { Button } from "@flowselections/core";
7
+ import { Download, HelpCircle, MonitorSmartphone } from "lucide-react";
8
+ const DOWNLOAD_URL = "https://www.printnode.com/en/download";
9
+ const STAPPEN = [
10
+ "Download het printprogramma op de computer waar de printer aan hangt.",
11
+ "Installeer het en log in met de gegevens die u van uw beheerder krijgt.",
12
+ "Laat die computer aan staan; de printers verschijnen dan vanzelf in de lijst.",
13
+ ];
14
+ export function PrintProgrammaUitleg({ compact = false }) {
15
+ return (_jsxs("div", { className: "bg-muted/40 space-y-4 rounded-xl border p-5", children: [!compact && (_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "bg-background rounded-lg border p-2", children: _jsx(MonitorSmartphone, { className: "text-muted-foreground h-5 w-5" }) }), _jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium", children: "We zien nog geen printers" }), _jsx("p", { className: "text-muted-foreground text-sm", children: "Zet de computer klaar in drie korte stappen." })] })] })), _jsx("ol", { className: "space-y-3", children: STAPPEN.map((tekst, i) => (_jsxs("li", { className: "flex gap-3", children: [_jsx("span", { className: "bg-background text-foreground flex h-6 w-6 shrink-0 items-center justify-center rounded-full border text-xs font-medium", children: i + 1 }), _jsx("span", { className: "text-sm", children: tekst })] }, tekst))) }), _jsx(Button, { asChild: true, variant: "outline", children: _jsxs("a", { href: DOWNLOAD_URL, target: "_blank", rel: "noreferrer", children: [_jsx(Download, { className: "mr-2 h-4 w-4" }), " Printprogramma downloaden"] }) })] }));
16
+ }
17
+ export function WerktHetNiet() {
18
+ return (_jsxs("details", { className: "group rounded-lg border p-3", children: [_jsxs("summary", { className: "flex cursor-pointer items-center gap-2 text-sm font-medium", children: [_jsx(HelpCircle, { className: "text-muted-foreground h-4 w-4" }), " Werkt het niet?"] }), _jsxs("ul", { className: "text-muted-foreground mt-3 space-y-2 text-sm", children: [_jsx("li", { children: "De computer staat uit of is in slaapstand." }), _jsx("li", { children: "Het printprogramma is nog niet gestart op die computer." }), _jsx("li", { children: "Er is ingelogd met andere gegevens dan die u van uw beheerder kreeg." })] })] }));
19
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"PrintQueuePage.d.ts","sourceRoot":"","sources":["../../src/components/PrintQueuePage.tsx"],"names":[],"mappings":"AAmCA,wBAAgB,cAAc,gCA8K7B"}
1
+ {"version":3,"file":"PrintQueuePage.d.ts","sourceRoot":"","sources":["../../src/components/PrintQueuePage.tsx"],"names":[],"mappings":"AAsCA,wBAAgB,cAAc,gCAuN7B"}
@@ -1,8 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useMemo, useState } from "react";
2
+ import { useMemo, useRef, useState } from "react";
3
3
  import { Badge, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Input, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, toast, } from "@flowselections/core";
4
- import { RefreshCw, RotateCcw, Search, XCircle } from "lucide-react";
4
+ import { RotateCcw, Search, XCircle } from "lucide-react";
5
+ import { bijgewerktTekst, useAutoRefresh } from "../lib/useAutoRefresh";
5
6
  import { maakPrintJob, updateJobStatus, useLayouts, usePrinters, usePrintJobs } from "../lib/useDocumentData";
7
+ import { printStatus, wachtrijTick } from "../lib/printService.functions";
6
8
  import { documentTypeLabel } from "../lib/documentTypes";
7
9
  const STATUS_VARIANT = {
8
10
  wachtend: "outline",
@@ -17,6 +19,7 @@ export function PrintQueuePage() {
17
19
  const { layouts } = useLayouts();
18
20
  const [zoek, setZoek] = useState("");
19
21
  const [status, setStatus] = useState("alle");
22
+ const [tickFout, setTickFout] = useState(null);
20
23
  const printerNaam = useMemo(() => new Map(printers.map((p) => [p.id, p.naam])), [printers]);
21
24
  const layoutNaam = useMemo(() => new Map(layouts.map((l) => [l.id, l.naam])), [layouts]);
22
25
  const gefilterd = jobs.filter((j) => {
@@ -33,7 +36,38 @@ export function PrintQueuePage() {
33
36
  t[j.status] = (t[j.status] ?? 0) + 1;
34
37
  return t;
35
38
  }, [jobs]);
36
- return (_jsxs("main", { className: "space-y-6 p-6", children: [_jsxs("div", { className: "flex flex-wrap items-end justify-between gap-4", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-xl font-semibold", children: "Printwachtrij" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Volg printopdrachten, herstart mislukte prints en print documenten opnieuw." })] }), _jsxs(Button, { variant: "outline", onClick: () => reload(), children: [_jsx(RefreshCw, { className: "mr-2 h-4 w-4" }), " Vernieuwen"] })] }), _jsx("div", { className: "grid gap-4 md:grid-cols-4", children: ["wachtend", "bezig", "voltooid", "mislukt"].map((s) => (_jsx(Card, { children: _jsxs(CardHeader, { className: "pb-2", children: [_jsx(CardDescription, { className: "capitalize", children: s }), _jsx(CardTitle, { className: "text-2xl", children: tellingen[s] ?? 0 })] }) }, s))) }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsx(CardTitle, { className: "text-base", children: "Opdrachten" }), _jsx(CardDescription, { children: loading ? "Laden…" : `${gefilterd.length} opdrachten` })] }), _jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { className: "grid gap-3 md:grid-cols-4", children: [_jsxs("div", { className: "relative md:col-span-2", 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: "Zoek op document of gebruiker", value: zoek, onChange: (e) => setZoek(e.target.value) })] }), _jsxs(Select, { value: status, onValueChange: setStatus, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "alle", children: "Alle statussen" }), ["wachtend", "bezig", "voltooid", "mislukt", "geannuleerd"].map((s) => (_jsx(SelectItem, { value: s, children: s }, s)))] })] })] }), _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Document" }), _jsx(TableHead, { children: "Layout" }), _jsx(TableHead, { children: "Printer" }), _jsx(TableHead, { children: "Status" }), _jsx(TableHead, { children: "Tijdstip" }), _jsx(TableHead, { className: "text-right", children: "Acties" })] }) }), _jsxs(TableBody, { children: [gefilterd.length === 0 && (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 6, className: "py-10 text-center text-sm text-muted-foreground", children: "Geen printopdrachten." }) })), gefilterd.map((j) => (_jsxs(TableRow, { children: [_jsxs(TableCell, { children: [_jsx("span", { className: "font-medium", children: j.documentnaam ?? documentTypeLabel(j.documenttype) }), j.is_herprint && (_jsx(Badge, { variant: "outline", className: "ml-2", children: "herprint" })), j.foutmelding && (_jsx("span", { className: "block text-xs text-destructive", children: j.foutmelding }))] }), _jsx(TableCell, { className: "text-sm text-muted-foreground", children: j.layout_id ? layoutNaam.get(j.layout_id) ?? "—" : "—" }), _jsx(TableCell, { className: "text-sm text-muted-foreground", children: j.printer_id ? printerNaam.get(j.printer_id) ?? "—" : "—" }), _jsx(TableCell, { children: _jsx(Badge, { variant: STATUS_VARIANT[j.status] ?? "outline", children: j.status }) }), _jsx(TableCell, { className: "text-sm text-muted-foreground", children: new Date(j.created_at).toLocaleString("nl-NL") }), _jsx(TableCell, { className: "text-right", children: _jsxs("div", { className: "flex justify-end gap-1", children: [_jsxs(Button, { variant: "ghost", size: "sm", onClick: async () => {
39
+ const jobsRef = useRef(jobs);
40
+ jobsRef.current = jobs;
41
+ const lopende = jobs.some((j) => j.status === "wachtend" || j.status === "bezig");
42
+ const ronde = async () => {
43
+ // Vangnet: laat wachtende opdrachten meteen verwerken, ook als de
44
+ // achtergrondtaak nog niet is langsgekomen in een verse installatie.
45
+ if (jobsRef.current.some((j) => j.status === "wachtend")) {
46
+ try {
47
+ const res = (await wachtrijTick({ data: undefined }));
48
+ setTickFout(res?.ok === false ? res.fout ?? "Verwerken mislukt" : null);
49
+ }
50
+ catch (e) {
51
+ setTickFout(e instanceof Error ? e.message : "Achtergrondprinten werkt nu niet.");
52
+ }
53
+ }
54
+ const open = jobsRef.current.filter((j) => j.extern_job_id && (j.status === "bezig" || j.status === "wachtend"));
55
+ for (const j of open) {
56
+ try {
57
+ const res = await printStatus({ data: { externJobId: String(j.extern_job_id) } });
58
+ if (!res.ok)
59
+ break;
60
+ if (res.status !== j.status)
61
+ await updateJobStatus(j.id, res.status);
62
+ }
63
+ catch {
64
+ break;
65
+ }
66
+ }
67
+ await reload(true);
68
+ };
69
+ const bijgewerkt = useAutoRefresh(ronde, lopende ? 5000 : 20000);
70
+ return (_jsxs("main", { className: "space-y-6 p-6", children: [_jsxs("div", { className: "flex flex-wrap items-end justify-between gap-4", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-xl font-semibold", children: "Printwachtrij" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Volg printopdrachten, herstart mislukte prints en print documenten opnieuw." })] }), _jsx("span", { className: "text-muted-foreground text-xs", children: bijgewerktTekst(bijgewerkt) })] }), tickFout && (_jsx("div", { className: "rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive", children: tickFout })), _jsx("div", { className: "grid gap-4 md:grid-cols-4", children: ["wachtend", "bezig", "voltooid", "mislukt"].map((s) => (_jsx(Card, { children: _jsxs(CardHeader, { className: "pb-2", children: [_jsx(CardDescription, { className: "capitalize", children: s }), _jsx(CardTitle, { className: "text-2xl", children: tellingen[s] ?? 0 })] }) }, s))) }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsx(CardTitle, { className: "text-base", children: "Opdrachten" }), _jsx(CardDescription, { children: loading ? "Laden…" : `${gefilterd.length} opdrachten` })] }), _jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { className: "grid gap-3 md:grid-cols-4", children: [_jsxs("div", { className: "relative md:col-span-2", 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: "Zoek op document of gebruiker", value: zoek, onChange: (e) => setZoek(e.target.value) })] }), _jsxs(Select, { value: status, onValueChange: setStatus, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "alle", children: "Alle statussen" }), ["wachtend", "bezig", "voltooid", "mislukt", "geannuleerd"].map((s) => (_jsx(SelectItem, { value: s, children: s }, s)))] })] })] }), _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Document" }), _jsx(TableHead, { children: "Layout" }), _jsx(TableHead, { children: "Printer" }), _jsx(TableHead, { children: "Status" }), _jsx(TableHead, { children: "Tijdstip" }), _jsx(TableHead, { className: "text-right", children: "Acties" })] }) }), _jsxs(TableBody, { children: [gefilterd.length === 0 && (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 6, className: "py-10 text-center text-sm text-muted-foreground", children: "Geen printopdrachten." }) })), gefilterd.map((j) => (_jsxs(TableRow, { children: [_jsxs(TableCell, { children: [_jsx("span", { className: "font-medium", children: j.documentnaam ?? documentTypeLabel(j.documenttype) }), j.is_herprint && (_jsx(Badge, { variant: "outline", className: "ml-2", children: "herprint" })), j.foutmelding && (_jsx("span", { className: "block text-xs text-destructive", children: j.foutmelding }))] }), _jsx(TableCell, { className: "text-sm text-muted-foreground", children: j.layout_id ? layoutNaam.get(j.layout_id) ?? "—" : "—" }), _jsx(TableCell, { className: "text-sm text-muted-foreground", children: j.printer_id ? printerNaam.get(j.printer_id) ?? "—" : "—" }), _jsx(TableCell, { children: _jsx(Badge, { variant: STATUS_VARIANT[j.status] ?? "outline", children: j.status }) }), _jsx(TableCell, { className: "text-sm text-muted-foreground", children: new Date(j.created_at).toLocaleString("nl-NL") }), _jsx(TableCell, { className: "text-right", children: _jsxs("div", { className: "flex justify-end gap-1", children: [_jsxs(Button, { variant: "ghost", size: "sm", onClick: async () => {
37
71
  if (!j.layout_id)
38
72
  return;
39
73
  try {
@@ -0,0 +1,17 @@
1
+ export interface PrinterKaartData {
2
+ id: string;
3
+ naam: string;
4
+ locatie: string | null;
5
+ systeemnaam?: string | null;
6
+ }
7
+ export declare function PrinterKaart({ printer, computer, beschikbaar, gekozen, onKies, onTest, onBewerk, onVerwijder, }: {
8
+ printer: PrinterKaartData;
9
+ computer?: string | null;
10
+ beschikbaar: boolean | null;
11
+ gekozen: boolean;
12
+ onKies: () => void;
13
+ onTest: () => void;
14
+ onBewerk: () => void;
15
+ onVerwijder: () => void;
16
+ }): import("react").JSX.Element;
17
+ //# sourceMappingURL=PrinterKaart.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PrinterKaart.d.ts","sourceRoot":"","sources":["../../src/components/PrinterKaart.tsx"],"names":[],"mappings":"AAaA,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,QAAQ,EACR,WAAW,EACX,OAAO,EACP,MAAM,EACN,MAAM,EACN,QAAQ,EACR,WAAW,GACZ,EAAE;IACD,OAAO,EAAE,gBAAgB,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB,+BAsDA"}
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // ============================================================================
3
+ // src/components/PrinterKaart.tsx — één printer in de lijst, met status en acties
4
+ // ============================================================================
5
+ import { Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@flowselections/core";
6
+ import { MoreHorizontal, Pencil, Printer, Trash2 } from "lucide-react";
7
+ export function PrinterKaart({ printer, computer, beschikbaar, gekozen, onKies, onTest, onBewerk, onVerwijder, }) {
8
+ return (_jsxs("div", { role: "button", tabIndex: 0, onClick: onKies, onKeyDown: (e) => {
9
+ if (e.key === "Enter" || e.key === " ")
10
+ onKies();
11
+ }, className: `bg-card hover:border-primary/40 flex cursor-pointer items-center gap-4 rounded-xl border p-4 transition ${gekozen ? "border-primary ring-primary/20 ring-2" : ""}`, children: [_jsx("div", { className: "bg-muted rounded-lg p-2.5", children: _jsx(Printer, { className: "text-muted-foreground h-5 w-5" }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "truncate font-medium", children: printer.naam }), _jsx("p", { className: "text-muted-foreground truncate text-sm", children: [printer.locatie, computer].filter(Boolean).join(" · ") || "Geen locatie ingevuld" })] }), _jsx("span", { className: `hidden shrink-0 rounded-full px-2.5 py-1 text-xs font-medium sm:inline ${beschikbaar
12
+ ? "bg-primary/10 text-primary"
13
+ : "bg-muted text-muted-foreground"}`, children: beschikbaar === null ? "Controleren…" : beschikbaar ? "Beschikbaar" : "Niet bereikbaar" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, onClick: (e) => e.stopPropagation(), children: _jsx(Button, { variant: "ghost", size: "sm", "aria-label": "Meer", children: _jsx(MoreHorizontal, { className: "h-4 w-4" }) }) }), _jsxs(DropdownMenuContent, { align: "end", onClick: (e) => e.stopPropagation(), children: [_jsxs(DropdownMenuItem, { onSelect: () => onTest(), children: [_jsx(Printer, { className: "mr-2 h-4 w-4" }), " Testpagina afdrukken"] }), _jsxs(DropdownMenuItem, { onSelect: () => onBewerk(), children: [_jsx(Pencil, { className: "mr-2 h-4 w-4" }), " Naam en locatie wijzigen"] }), _jsxs(DropdownMenuItem, { onSelect: () => onVerwijder(), children: [_jsx(Trash2, { className: "mr-2 h-4 w-4" }), " Verwijderen"] })] })] })] }));
14
+ }
@@ -1,6 +1,16 @@
1
- export declare function PrinterSetupWizard({ open, onOpenChange, onKlaar, }: {
1
+ export interface BewerkPrinter {
2
+ id: string;
3
+ naam: string;
4
+ locatie: string | null;
5
+ papierformaat: string | null;
6
+ }
7
+ export declare function PrinterSetupWizard({ open, onOpenChange, onKlaar, computerFilter, bekendeExterneIds, bekendeLocaties, bewerken, }: {
2
8
  open: boolean;
3
9
  onOpenChange: (v: boolean) => void;
4
10
  onKlaar?: () => void;
11
+ computerFilter?: string | null;
12
+ bekendeExterneIds?: string[];
13
+ bekendeLocaties?: string[];
14
+ bewerken?: BewerkPrinter | null;
5
15
  }): import("react").JSX.Element;
6
16
  //# sourceMappingURL=PrinterSetupWizard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PrinterSetupWizard.d.ts","sourceRoot":"","sources":["../../src/components/PrinterSetupWizard.tsx"],"names":[],"mappings":"AA6DA,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EACJ,YAAY,EACZ,OAAO,GACR,EAAE;IACD,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,+BAuNA"}
1
+ {"version":3,"file":"PrinterSetupWizard.d.ts","sourceRoot":"","sources":["../../src/components/PrinterSetupWizard.tsx"],"names":[],"mappings":"AA6CA,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAoCD,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,cAAc,EACd,iBAAsB,EACtB,eAAoB,EACpB,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;CACjC,+BAiXA"}