@flowselections/layout-maker 1.62.3 → 1.63.2

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 (49) hide show
  1. package/dist-lib/components/BevestigDialog.d.ts +9 -0
  2. package/dist-lib/components/BevestigDialog.d.ts.map +1 -0
  3. package/dist-lib/components/BevestigDialog.js +24 -0
  4. package/dist-lib/components/LogosPage.d.ts.map +1 -1
  5. package/dist-lib/components/LogosPage.js +27 -5
  6. package/dist-lib/components/PrintenInstellenWizard.js +1 -1
  7. package/dist-lib/components/PrinterSetupWizard.d.ts.map +1 -1
  8. package/dist-lib/components/PrinterSetupWizard.js +3 -1
  9. package/dist-lib/components/PrintplekDetailPage.d.ts.map +1 -1
  10. package/dist-lib/components/PrintplekDetailPage.js +42 -4
  11. package/dist-lib/components/TestprintDialog.d.ts.map +1 -1
  12. package/dist-lib/components/TestprintDialog.js +15 -1
  13. package/dist-lib/components/WerkplekConfiguratiePage.js +2 -2
  14. package/dist-lib/components/WerkplekkenTab.d.ts.map +1 -1
  15. package/dist-lib/components/WerkplekkenTab.js +13 -6
  16. package/dist-lib/integrations/supabase/types.d.ts +125 -0
  17. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  18. package/dist-lib/lib/afbeeldingMaat.d.ts +10 -0
  19. package/dist-lib/lib/afbeeldingMaat.d.ts.map +1 -0
  20. package/dist-lib/lib/afbeeldingMaat.js +39 -0
  21. package/dist-lib/lib/etiketControle.d.ts +9 -1
  22. package/dist-lib/lib/etiketControle.d.ts.map +1 -1
  23. package/dist-lib/lib/etiketControle.js +21 -4
  24. package/dist-lib/lib/htmlNaarPdf.server.d.ts +4 -0
  25. package/dist-lib/lib/htmlNaarPdf.server.d.ts.map +1 -1
  26. package/dist-lib/lib/htmlNaarPdf.server.js +5 -1
  27. package/dist-lib/lib/htmlPdf.server.d.ts +6 -0
  28. package/dist-lib/lib/htmlPdf.server.d.ts.map +1 -1
  29. package/dist-lib/lib/htmlPdf.server.js +46 -10
  30. package/dist-lib/lib/logoLibrary.d.ts +25 -0
  31. package/dist-lib/lib/logoLibrary.d.ts.map +1 -1
  32. package/dist-lib/lib/logoLibrary.js +73 -1
  33. package/dist-lib/lib/opmaakLimiet.d.ts +8 -0
  34. package/dist-lib/lib/opmaakLimiet.d.ts.map +1 -0
  35. package/dist-lib/lib/opmaakLimiet.js +25 -0
  36. package/dist-lib/lib/printQueue.server.d.ts.map +1 -1
  37. package/dist-lib/lib/printQueue.server.js +81 -20
  38. package/dist-lib/lib/printService.functions.js +2 -2
  39. package/dist-lib/lib/printplekken.d.ts +17 -1
  40. package/dist-lib/lib/printplekken.d.ts.map +1 -1
  41. package/dist-lib/lib/printplekken.js +42 -3
  42. package/dist-lib/lib/profielHtml.js +1 -1
  43. package/dist-lib/lib/shellPoort.d.ts +1 -1
  44. package/dist-lib/lib/shellPoort.js +1 -1
  45. package/dist-lib/lib/stickerFormaat.d.ts +21 -0
  46. package/dist-lib/lib/stickerFormaat.d.ts.map +1 -0
  47. package/dist-lib/lib/stickerFormaat.js +39 -0
  48. package/dist-lib/lib/testprint.js +1 -1
  49. package/package.json +1 -1
@@ -0,0 +1,9 @@
1
+ import { type ReactNode } from "react";
2
+ export interface BevestigVraag {
3
+ titel: string;
4
+ tekst?: ReactNode;
5
+ knop?: string;
6
+ gevaarlijk?: boolean;
7
+ }
8
+ export declare function useBevestig(): [ReactNode, (v: BevestigVraag) => Promise<boolean>];
9
+ //# sourceMappingURL=BevestigDialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BevestigDialog.d.ts","sourceRoot":"","sources":["../../src/components/BevestigDialog.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAiC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAUtE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,wBAAgB,WAAW,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,aAAa,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAwCjF"}
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // ============================================================================
3
+ // src/components/BevestigDialog.tsx — eigen bevestigvenster in plaats van het
4
+ // standaard browservenster (dat in sommige omgevingen stil wordt geblokkeerd).
5
+ // Gebruik: const [venster, bevestig] = useBevestig(); if (!(await bevestig({...}))) return;
6
+ // ============================================================================
7
+ import { useCallback, useRef, useState } from "react";
8
+ import { Button, Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@flowselections/core";
9
+ export function useBevestig() {
10
+ const [vraag, setVraag] = useState(null);
11
+ const antwoord = useRef(null);
12
+ const sluit = (ja) => {
13
+ antwoord.current?.(ja);
14
+ antwoord.current = null;
15
+ setVraag(null);
16
+ };
17
+ const bevestig = useCallback((v) => new Promise((resolve) => {
18
+ antwoord.current?.(false);
19
+ antwoord.current = resolve;
20
+ setVraag(v);
21
+ }), []);
22
+ const venster = (_jsx(Dialog, { open: !!vraag, onOpenChange: (open) => !open && sluit(false), children: _jsxs(DialogContent, { className: "sm:max-w-lg", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: vraag?.titel }), vraag?.tekst ? _jsx(DialogDescription, { asChild: true, children: _jsx("div", { children: vraag.tekst }) }) : null] }), _jsxs("div", { className: "flex justify-end gap-2", children: [_jsx(Button, { variant: "outline", onClick: () => sluit(false), children: "Annuleren" }), _jsx(Button, { variant: vraag?.gevaarlijk ? "destructive" : "default", onClick: () => sluit(true), children: vraag?.knop ?? "Doorgaan" })] })] }) }));
23
+ return [venster, bevestig];
24
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"LogosPage.d.ts","sourceRoot":"","sources":["../../src/components/LogosPage.tsx"],"names":[],"mappings":"AAkCA,OAAO,EAaL,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,CAAC,EAAE,OAAe,EAAE,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,+BA8LxE"}
1
+ {"version":3,"file":"LogosPage.d.ts","sourceRoot":"","sources":["../../src/components/LogosPage.tsx"],"names":[],"mappings":"AAkCA,OAAO,EAcL,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,CAAC,EAAE,OAAe,EAAE,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,+BAwNxE"}
@@ -1,9 +1,9 @@
1
1
  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
- import { Download, ImagePlus, Pencil, RefreshCw, Trash2, Upload } from "lucide-react";
4
+ import { Download, ImagePlus, Pencil, RefreshCw, Trash2, Undo2, Upload } from "lucide-react";
5
5
  import { useAutoRefresh } from "../lib/useAutoRefresh.js";
6
- import { LOGO_CATEGORIEEN, TOEGESTANE_LOGO_TYPES, downloadLogo, formatteerBytes, logoCategorieLabel, maakLogo, useLogoOpslag, useLogos, vervangLogoBestand, verwijderLogo, werkLogoBij, } from "../lib/logoLibrary.js";
6
+ import { LOGO_CATEGORIEEN, TOEGESTANE_LOGO_TYPES, downloadLogo, formatteerBytes, logoCategorieLabel, maakLogo, useLogoOpslag, useLogos, verkleinLogoVoorUpload, zetOrigineelTerug, vervangLogoBestand, verwijderLogo, werkLogoBij, } from "../lib/logoLibrary.js";
7
7
  export function LogoThumbnail({ logo, className = "" }) {
8
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" })) }));
9
9
  }
@@ -22,14 +22,30 @@ export function LogosPage({ ingebed = false } = {}) {
22
22
  }, [logos, zoek, categorie]);
23
23
  const vervang = async (logo, file) => {
24
24
  try {
25
- await vervangLogoBestand(logo, file);
25
+ const v = await verkleinLogoVoorUpload(file);
26
+ await vervangLogoBestand(logo, v.bestand);
26
27
  toast.success("Logo vervangen — alle layouts zijn bijgewerkt");
28
+ if (v.verkleind && v.van && v.naar) {
29
+ toast.info("Logo verkleind voor snel printen", {
30
+ description: `${v.van.breedte} × ${v.van.hoogte} → ${v.naar.breedte} × ${v.naar.hoogte} pixels`,
31
+ });
32
+ }
27
33
  await reload();
28
34
  }
29
35
  catch (e) {
30
36
  toast.error(e instanceof Error ? e.message : "Vervangen mislukt");
31
37
  }
32
38
  };
39
+ const terugzetten = async (logo) => {
40
+ try {
41
+ await zetOrigineelTerug(logo);
42
+ toast.success("Origineel logo teruggezet");
43
+ await reload();
44
+ }
45
+ catch (e) {
46
+ toast.error(e instanceof Error ? e.message : "Terugzetten mislukt");
47
+ }
48
+ };
33
49
  const wis = async (logo) => {
34
50
  if (!window.confirm(`Logo "${logo.naam}" verwijderen?`))
35
51
  return;
@@ -48,7 +64,7 @@ export function LogosPage({ ingebed = false } = {}) {
48
64
  if (f)
49
65
  void vervang(l, f);
50
66
  e.target.value = "";
51
- } }), _jsx("span", { className: "inline-flex h-9 w-9 cursor-pointer items-center justify-center rounded-md hover:bg-accent", children: _jsx(RefreshCw, { className: "h-4 w-4" }) })] }), _jsx(Button, { variant: "ghost", size: "icon", title: "Downloaden", onClick: () => void downloadLogo(l), children: _jsx(Download, { className: "h-4 w-4" }) }), _jsx(Button, { variant: "ghost", size: "icon", title: "Verwijderen", onClick: () => void wis(l), children: _jsx(Trash2, { className: "h-4 w-4" }) })] }) })] }, l.id)))] })] }) })] })] }), _jsx(LogoUploadDialog, { open: uploadOpen, onOpenChange: setUploadOpen, onKlaar: reload }), _jsx(LogoBewerkDialog, { logo: bewerk, onOpenChange: () => setBewerk(null), onKlaar: reload })] }));
67
+ } }), _jsx("span", { className: "inline-flex h-9 w-9 cursor-pointer items-center justify-center rounded-md hover:bg-accent", children: _jsx(RefreshCw, { className: "h-4 w-4" }) })] }), _jsx(Button, { variant: "ghost", size: "icon", title: "Downloaden", onClick: () => void downloadLogo(l), children: _jsx(Download, { className: "h-4 w-4" }) }), l.origineel_pad && (_jsx(Button, { variant: "ghost", size: "icon", title: "Origineel terugzetten", onClick: () => void terugzetten(l), children: _jsx(Undo2, { className: "h-4 w-4" }) })), _jsx(Button, { variant: "ghost", size: "icon", title: "Verwijderen", onClick: () => void wis(l), children: _jsx(Trash2, { className: "h-4 w-4" }) })] }) })] }, l.id)))] })] }) })] })] }), _jsx(LogoUploadDialog, { open: uploadOpen, onOpenChange: setUploadOpen, onKlaar: reload }), _jsx(LogoBewerkDialog, { logo: bewerk, onOpenChange: () => setBewerk(null), onKlaar: reload })] }));
52
68
  }
53
69
  function LogoUploadDialog({ open, onOpenChange, onKlaar, }) {
54
70
  const [bestanden, setBestanden] = useState([]);
@@ -75,13 +91,19 @@ function LogoUploadDialog({ open, onOpenChange, onKlaar, }) {
75
91
  ? form.naam.trim() || file.name.replace(/\.[^.]+$/, "")
76
92
  : `${form.naam.trim() ? `${form.naam.trim()} — ` : ""}${file.name.replace(/\.[^.]+$/, "")}`;
77
93
  try {
94
+ const v = await verkleinLogoVoorUpload(file);
78
95
  await maakLogo({
79
- file,
96
+ file: v.bestand,
80
97
  naam,
81
98
  omschrijving: form.omschrijving,
82
99
  categorie: form.categorie,
83
100
  is_standaard: form.is_standaard && i === 0,
84
101
  });
102
+ if (v.verkleind && v.van && v.naar) {
103
+ toast.info("Logo verkleind voor snel printen", {
104
+ description: `${v.van.breedte} × ${v.van.hoogte} → ${v.naar.breedte} × ${v.naar.hoogte} pixels`,
105
+ });
106
+ }
85
107
  gelukt += 1;
86
108
  }
87
109
  catch (e) {
@@ -60,7 +60,7 @@ export function PrintenInstellenWizard({ open, onOpenChange, onKlaar, }) {
60
60
  Tijdstip: new Date().toLocaleString("nl-NL"),
61
61
  }),
62
62
  printerId,
63
- payload: { is_testprint: true },
63
+ payload: { is_testprint: true, is_test: true },
64
64
  });
65
65
  volgJobStatus(jobId, (j) => setStatus((s) => ({ ...s, [printerId]: j.foutmelding ? `mislukt: ${j.foutmelding}` : j.status })));
66
66
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PrinterSetupWizard.d.ts","sourceRoot":"","sources":["../../src/components/PrinterSetupWizard.tsx"],"names":[],"mappings":"AAoDA,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;AAwCD,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,cAAc,EACd,iBAAsB,EACtB,eAAoB,EACpB,QAAQ,EACR,WAAW,GACZ,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,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;CACjC,+BAodA"}
1
+ {"version":3,"file":"PrinterSetupWizard.d.ts","sourceRoot":"","sources":["../../src/components/PrinterSetupWizard.tsx"],"names":[],"mappings":"AAoDA,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;AAwCD,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,cAAc,EACd,iBAAsB,EACtB,eAAoB,EACpB,QAAQ,EACR,WAAW,GACZ,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,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;CACjC,+BAsdA"}
@@ -240,6 +240,8 @@ export function PrinterSetupWizard({ open, onOpenChange, onKlaar, computerFilter
240
240
  }) })), !zoekt && zichtbaar.length === 0 && _jsx(PrintProgrammaUitleg, {}), !zoekt && zichtbaar.length > 0 && (_jsxs("div", { className: "space-y-3", children: [_jsx("button", { type: "button", className: "text-muted-foreground hover:text-foreground text-sm underline", onClick: () => setUitlegOpen((v) => !v), children: "Ik zie mijn printer niet" }), uitlegOpen && _jsx(PrintProgrammaUitleg, { compact: true })] })), _jsx("div", { className: "flex justify-between", children: _jsxs(Button, { variant: "ghost", onClick: () => void zoeken(), disabled: zoekt, children: [_jsx(RefreshCw, { className: "mr-2 h-4 w-4" }), " Opnieuw zoeken"] }) })] })), stap === 1 && (_jsxs("div", { className: "grid gap-5 sm:grid-cols-[1fr_200px]", children: [_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "Weergavenaam" }), _jsx(Input, { value: naam, placeholder: "Bijvoorbeeld: pakbonprinter voorin", onChange: (e) => setNaam(e.target.value) })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "Omschrijving (optioneel)" }), _jsx("p", { className: "text-muted-foreground text-xs", children: "Waar staat deze printer? Bijvoorbeeld: magazijn achter." }), _jsx(Input, { value: locatie, placeholder: "Bijvoorbeeld: magazijn achter", onChange: (e) => setLocatie(e.target.value) }), bekendeLocaties.length > 0 && (_jsx("div", { className: "flex flex-wrap gap-2 pt-1", children: bekendeLocaties.slice(0, 6).map((l) => (_jsx("button", { type: "button", onClick: () => setLocatie(l), className: "hover:bg-accent rounded-full border px-3 py-1 text-xs", children: l }, l))) }))] }), formaatOpties.length > 0 ? (_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "Standaardformaat van deze printer" }), _jsxs("p", { className: "text-muted-foreground text-xs", children: ["Deze printer kan: ", formaatOpties.map((o) => o.label.split(" (")[0]).join(", "), "."] }), formaatOpties.length === 1 ? (_jsx("p", { className: "text-sm", children: formaatOpties[0].label })) : (_jsx("div", { className: "grid gap-2 sm:grid-cols-2", children: formaatOpties.map((o) => (_jsxs("button", { type: "button", onClick: () => setFormaatCode(o.code), className: `hover:bg-accent rounded-lg border p-3 text-left transition ${formaatCode === o.code ? "border-primary bg-accent" : ""}`, children: [o.breedte <= 120 && o.hoogte <= 220 ? (_jsx(Tag, { className: "text-muted-foreground mb-1 h-4 w-4" })) : (_jsx(FileText, { className: "text-muted-foreground mb-1 h-4 w-4" })), _jsx("p", { className: "text-sm font-medium", children: o.label.split(" (")[0] }), _jsxs("p", { className: "text-muted-foreground text-xs", children: [o.breedte, " \u00D7 ", o.hoogte, " mm"] })] }, o.code))) }))] })) : (_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "Wat gaat deze printer afdrukken?" }), _jsx("p", { className: "text-muted-foreground text-xs", children: "De formaten van deze printer konden niet worden opgehaald." }), _jsx("div", { className: "grid grid-cols-2 gap-3", children: [
241
241
  { code: "papier", label: "Papier (A4)", sub: "Gewone documenten", Icon: FileText },
242
242
  { code: "etiket", label: "Etiketten", sub: "Stickers en labels", Icon: Tag },
243
- ].map((o) => (_jsxs("button", { type: "button", onClick: () => setGebruik(o.code), className: `hover:bg-accent rounded-lg border p-4 text-left transition ${gebruik === o.code ? "border-primary bg-accent" : ""}`, children: [_jsx(o.Icon, { className: "text-muted-foreground mb-2 h-5 w-5" }), _jsx("p", { className: "text-sm font-medium", children: o.label }), _jsx("p", { className: "text-muted-foreground text-xs", children: o.sub })] }, o.code))) })] })), _jsxs("div", { className: "flex justify-between", children: [!bewerken ? (_jsx(Button, { variant: "ghost", onClick: () => setStap(0), children: "Terug" })) : (_jsx("span", {})), _jsx(Button, { disabled: bezig, onClick: () => void opslaan(), children: bewerken ? "Opslaan" : "Opslaan en verder" })] })] }), _jsxs("div", { className: "hidden sm:block", children: [_jsx("p", { className: "text-muted-foreground mb-2 text-xs", children: "Zo komt hij in de lijst:" }), _jsxs("div", { className: "bg-card rounded-xl border p-3", children: [_jsx(Printer, { className: "text-muted-foreground mb-2 h-4 w-4" }), _jsx("p", { className: "truncate text-sm font-medium", children: naam || "Naam van de printer" }), _jsx("p", { className: "text-muted-foreground truncate text-xs", children: locatie || gekozen?.computer || "Geen omschrijving" })] })] })] })), stap === 2 && (_jsxs("div", { className: "space-y-4 text-center", children: [_jsx(CheckCircle2, { className: "text-primary mx-auto h-10 w-10" }), _jsxs("div", { children: [_jsx("p", { className: "font-medium", children: "De printer is klaar voor gebruik" }), _jsxs("p", { className: "text-muted-foreground text-sm", children: [naam, " ", locatie ? `bij ${locatie}` : "", " drukt voortaan automatisch af."] })] }), testStatus !== "leeg" && (_jsxs("p", { className: "text-muted-foreground text-sm", children: [testStatus === "bezig" && "Onderweg naar de printer…", testStatus === "gelukt" && (testMelding || "De testpagina is afgedrukt."), testStatus === "fout" &&
243
+ ].map((o) => (_jsxs("button", { type: "button", onClick: () => setGebruik(o.code), className: `hover:bg-accent rounded-lg border p-4 text-left transition ${gebruik === o.code ? "border-primary bg-accent" : ""}`, children: [_jsx(o.Icon, { className: "text-muted-foreground mb-2 h-5 w-5" }), _jsx("p", { className: "text-sm font-medium", children: o.label }), _jsx("p", { className: "text-muted-foreground text-xs", children: o.sub })] }, o.code))) })] })), _jsxs("div", { className: "flex justify-between", children: [!bewerken ? (_jsx(Button, { variant: "ghost", onClick: () => setStap(0), children: "Terug" })) : (_jsx("span", {})), _jsx(Button, { disabled: bezig, onClick: () => void opslaan(), children: bewerken ? "Opslaan" : "Opslaan en verder" })] })] }), _jsxs("div", { className: "hidden sm:block", children: [_jsx("p", { className: "text-muted-foreground mb-2 text-xs", children: "Zo komt hij in de lijst:" }), _jsxs("div", { className: "bg-card rounded-xl border p-3", children: [_jsx(Printer, { className: "text-muted-foreground mb-2 h-4 w-4" }), _jsx("p", { className: "truncate text-sm font-medium", children: naam || "Naam van de printer" }), _jsx("p", { className: "text-muted-foreground truncate text-xs", children: locatie || gekozen?.computer || "Geen omschrijving" })] })] })] })), stap === 2 && (_jsxs("div", { className: "space-y-4 text-center", children: [_jsx(CheckCircle2, { className: "text-primary mx-auto h-10 w-10" }), _jsxs("div", { children: [_jsx("p", { className: "font-medium", children: "De printer is klaar voor gebruik" }), _jsx("p", { className: "text-muted-foreground text-sm", children: printPlekId
244
+ ? `${naam} ${locatie ? `bij ${locatie} ` : ""}hoort nu bij deze printplek. Kies onder Documentroutering welke documenten hierheen gaan.`
245
+ : `${naam} is opgeslagen, maar hoort nog bij geen printplek. Er wordt pas afgedrukt als je hem aan een printplek koppelt.` })] }), testStatus !== "leeg" && (_jsxs("p", { className: "text-muted-foreground text-sm", children: [testStatus === "bezig" && "Onderweg naar de printer…", testStatus === "gelukt" && (testMelding || "De testpagina is afgedrukt."), testStatus === "fout" &&
244
246
  `De testpagina kon niet worden afgedrukt.${testMelding ? ` ${testMelding}` : ""}`] })), _jsxs("div", { className: "flex flex-wrap justify-center gap-2", children: [_jsx(Button, { variant: "outline", onClick: () => void testpagina(), children: "Testpagina afdrukken" }), _jsx(Button, { variant: "ghost", onClick: opnieuw, children: "Nog een printer toevoegen" }), _jsx(Button, { onClick: () => onOpenChange(false), children: "Klaar" })] }), _jsx(WerktHetNiet, {})] }))] }) }));
245
247
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PrintplekDetailPage.d.ts","sourceRoot":"","sources":["../../src/components/PrintplekDetailPage.tsx"],"names":[],"mappings":"AAoEA,wBAAgB,mBAAmB,gCAqqBlC"}
1
+ {"version":3,"file":"PrintplekDetailPage.d.ts","sourceRoot":"","sources":["../../src/components/PrintplekDetailPage.tsx"],"names":[],"mappings":"AAwEA,wBAAgB,mBAAmB,gCA4uBlC"}
@@ -8,8 +8,9 @@ import { useEffect, useMemo, useState } from "react";
8
8
  import { Badge, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Input, toast, } from "@flowselections/core";
9
9
  import { Link, useNavigate, useParams } from "@tanstack/react-router";
10
10
  import { PrintplekVerwijderenDialog } from "./PrintplekVerwijderenDialog.js";
11
+ import { useBevestig } from "./BevestigDialog.js";
11
12
  import { AlertTriangle, ArrowLeft, Check, Link2, Monitor, Plus, Printer, Trash2, X, } from "lucide-react";
12
- import { bewerkPrintplek, koppelComputerAanPrintplek, koppelPrinterLosVanPrintplek, ontkoppelBron, usePrintplekken, verplaatsPrinterNaarPrintplek, wijsPrinterToeAanPrintplek, zetPrintplekPrinter, } from "../lib/printplekken.js";
13
+ import { bewerkPrintplek, koppelComputerAanPrintplek, koppelPrinterLosVanPrintplek, ontkoppelBron, printerHerstelUitvoeren, printerHerstelVoorstel, printerVerwijzingen, usePrintplekken, verplaatsPrinterNaarPrintplek, wijsPrinterToeAanPrintplek, zetPrintplekPrinter, } from "../lib/printplekken.js";
13
14
  import { PrinterVervangenDialog } from "./PrinterVervangenDialog.js";
14
15
  import { ComputerVerwijderenDialog } from "./ComputerVerwijderenDialog.js";
15
16
  import { usePrinters } from "../lib/useDocumentData.js";
@@ -105,6 +106,27 @@ export function PrintplekDetailPage() {
105
106
  .filter((t) => t.print_plek_id === plekId)
106
107
  .map((t) => t.printer_id));
107
108
  const eigenPrinters = printers.filter((p) => toegewezenIds.has(p.id));
109
+ const eigenPrinterSleutel = eigenPrinters.map((p) => p.id).join(",");
110
+ const [venster, bevestig] = useBevestig();
111
+ // Dezelfde printer opnieuw toegevoegd? Dan de leeggemaakte regels aanbieden.
112
+ const [herstel, setHerstel] = useState([]);
113
+ useEffect(() => {
114
+ let weg = false;
115
+ void (async () => {
116
+ const uit = [];
117
+ for (const p of eigenPrinters) {
118
+ const aantal = await printerHerstelVoorstel(plekId, p.id).catch(() => 0);
119
+ if (aantal > 0)
120
+ uit.push({ id: p.id, naam: p.naam, aantal });
121
+ }
122
+ if (!weg)
123
+ setHerstel(uit);
124
+ })();
125
+ return () => {
126
+ weg = true;
127
+ };
128
+ // eslint-disable-next-line react-hooks/exhaustive-deps
129
+ }, [plekId, eigenPrinterSleutel, regels.length]);
108
130
  const nietToegewezen = printers.filter((p) => !toegewezenIds.has(p.id));
109
131
  const eigenNamen = new Set(eigenComputers.map((c) => c.computer_naam));
110
132
  const printersPerComputer = eigenComputers.map((c) => ({
@@ -178,8 +200,15 @@ export function PrintplekDetailPage() {
178
200
  }
179
201
  };
180
202
  const loskoppelen = async (p) => {
181
- const n = regels.filter((r) => r.print_plek_id === plekId && r.printer_id === p.id).length;
182
- if (n > 0 && !window.confirm(`${n} regel(s) wijzen naar ${p.naam}. Die worden leeg en gemarkeerd. Doorgaan?`))
203
+ const v = await printerVerwijzingen(plekId, p.id).catch(() => null);
204
+ const n = v?.printplek_regels ?? regels.filter((r) => r.print_plek_id === plekId && r.printer_id === p.id).length;
205
+ const ja = await bevestig({
206
+ titel: `${p.naam} van deze plek verwijderen?`,
207
+ knop: "Verwijderen",
208
+ gevaarlijk: true,
209
+ tekst: (_jsxs("div", { className: "space-y-2 text-sm", children: [n > 0 ? _jsxs("p", { children: [n, " regel(s) van deze plek wijzen naar deze printer. Die worden leeg en vallen terug op de bedrijfsstandaard."] }) : _jsx("p", { children: "Er wijzen geen regels van deze plek naar deze printer." }), v && v.werkplek_regels.length > 0 ? (_jsxs("div", { children: [_jsx("p", { children: "Ook deze uitzonderingen worden leeg:" }), _jsx("ul", { className: "list-disc pl-5", children: v.werkplek_regels.map((w, i) => (_jsxs("li", { children: [w.werkplek, " \u2192 ", documentTypeLabel(w.documenttype)] }, i))) })] })) : null, v && v.werkplekken.length > 0 ? (_jsxs("div", { children: [_jsx("p", { children: "Deze werkplekken gebruiken de printer nog en blijven ernaar wijzen tot je ze aanpast:" }), _jsx("ul", { className: "list-disc pl-5", children: v.werkplekken.map((w, i) => (_jsxs("li", { children: [w.naam, " (", w.rol, "-printer)"] }, i))) })] })) : null, _jsx("p", { children: "Voeg je dezelfde printer later opnieuw toe, dan bieden we aan de regels terug te zetten." })] })),
210
+ });
211
+ if (!ja)
183
212
  return;
184
213
  try {
185
214
  await koppelPrinterLosVanPrintplek(plekId, p.id);
@@ -215,7 +244,16 @@ export function PrintplekDetailPage() {
215
244
  const teVerwijderenPrinters = teVerwijderen
216
245
  ? eigenPrinters.filter((p) => computerVan(p) === teVerwijderen).map((p) => ({ id: p.id, naam: p.naam }))
217
246
  : [];
218
- return (_jsxs("main", { className: "space-y-6 p-6", children: [_jsxs("div", { className: "flex flex-wrap items-start justify-between gap-4", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Button, { variant: "ghost", size: "sm", asChild: true, className: "-ml-2", children: _jsxs(Link, { to: "/layouts-printers/printplekken", children: [_jsx(ArrowLeft, { className: "mr-2 h-4 w-4" }), " Alle printplekken"] }) }), naamBewerken ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Input, { value: naam, onChange: (e) => setNaam(e.target.value), className: "w-64" }), _jsx(Button, { size: "icon", onClick: async () => {
247
+ return (_jsxs("main", { className: "space-y-6 p-6", children: [venster, herstel.map((h) => (_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 rounded-lg border p-3 text-sm", children: [_jsxs("span", { children: ["Zet de ", h.aantal, " regels terug naar ", h.naam, "?"] }), _jsx(Button, { size: "sm", onClick: async () => {
248
+ try {
249
+ const n = await printerHerstelUitvoeren(plekId, h.id);
250
+ toast.success(`${n} regel(s) teruggezet naar ${h.naam}`);
251
+ await vernieuw();
252
+ }
253
+ catch (e) {
254
+ toast.error(leesbareFout(e, "Terugzetten mislukt"));
255
+ }
256
+ }, children: "Terugzetten" })] }, h.id))), _jsxs("div", { className: "flex flex-wrap items-start justify-between gap-4", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Button, { variant: "ghost", size: "sm", asChild: true, className: "-ml-2", children: _jsxs(Link, { to: "/layouts-printers/printplekken", children: [_jsx(ArrowLeft, { className: "mr-2 h-4 w-4" }), " Alle printplekken"] }) }), naamBewerken ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Input, { value: naam, onChange: (e) => setNaam(e.target.value), className: "w-64" }), _jsx(Button, { size: "icon", onClick: async () => {
219
257
  await bewerkPrintplek(plek.id, { naam: naam.trim() });
220
258
  setNaamBewerken(false);
221
259
  await reload(true);
@@ -1 +1 @@
1
- {"version":3,"file":"TestprintDialog.d.ts","sourceRoot":"","sources":["../../src/components/TestprintDialog.tsx"],"names":[],"mappings":"AAsCA,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,YAAY,EACZ,WAAW,EACX,aAAa,EACb,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,+BAwKA"}
1
+ {"version":3,"file":"TestprintDialog.d.ts","sourceRoot":"","sources":["../../src/components/TestprintDialog.tsx"],"names":[],"mappings":"AA0DA,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,YAAY,EACZ,WAAW,EACX,aAAa,EACb,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,+BA2KA"}
@@ -9,6 +9,20 @@ import { Badge, Button, Dialog, DialogContent, DialogDescription, DialogHeader,
9
9
  import { AlertTriangle, Check, Loader2, Printer, X } from "lucide-react";
10
10
  import { volgJobStatus } from "../lib/printApi.js";
11
11
  import { bepaalTestOverzicht, verstuurTestprint, } from "../lib/testprint.js";
12
+ import { supabase } from "../lib/supabaseClient.js";
13
+ import { GeladenEtiketKeuze } from "./WerkplekkenTab.js";
14
+ function EtiketWijzigen({ printerId }) {
15
+ const [open, setOpen] = useState(false);
16
+ const [printer, setPrinter] = useState(null);
17
+ const laad = useCallback(async () => {
18
+ const { data } = await supabase.from("printers").select("*").eq("id", printerId).maybeSingle();
19
+ setPrinter(data ?? null);
20
+ }, [printerId]);
21
+ if (!open) {
22
+ return (_jsx(Button, { size: "sm", variant: "link", className: "h-auto p-0 text-xs", onClick: () => { setOpen(true); void laad(); }, children: "Geladen etiket wijzigen" }));
23
+ }
24
+ return printer ? _jsx("div", { className: "mt-2", children: _jsx(GeladenEtiketKeuze, { printer: printer, onGewijzigd: () => void laad() }) }) : null;
25
+ }
12
26
  const STATUS_LABEL = {
13
27
  wachtend: "In de wachtrij",
14
28
  bezig: "Naar de printer",
@@ -85,7 +99,7 @@ export function TestprintDialog({ open, onOpenChange, printplekId, printplekNaam
85
99
  const ontbreekt = regels.filter((r) => !r.printerId);
86
100
  return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "max-h-[85vh] max-w-2xl overflow-y-auto", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Testprint controleren" }), _jsxs(DialogDescription, { children: ["Elke testprint volgt precies dezelfde weg als een echt document", printplekNaam ? ` vanaf ${printplekNaam}` : werkplek ? ` vanaf ${werkplek}` : "", ". Op het vel staat welke documentsoort, plek en printer bedoeld waren."] })] }), _jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsxs("p", { className: "text-muted-foreground text-sm", children: [ingesteld.length, " documentsoort", ingesteld.length === 1 ? "" : "en", " ingesteld", ontbreekt.length ? `, ${ontbreekt.length} zonder printer` : "", "."] }), _jsxs(Button, { size: "sm", disabled: laden || alles || !ingesteld.length, onClick: () => void testAlles(), children: [alles ? (_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" })) : (_jsx(Printer, { className: "mr-2 h-4 w-4" })), "Alles testen"] })] }), laden ? (_jsxs("div", { className: "text-muted-foreground flex items-center gap-2 py-8 text-sm", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), " Instellingen ophalen\u2026"] })) : (_jsx("div", { className: "space-y-2", children: [...ingesteld, ...ontbreekt].map((r) => {
87
101
  const st = statussen[r.documenttype];
88
- return (_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2 rounded-lg border p-3", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-sm font-medium", children: r.label }), r.printerId ? (_jsxs("div", { className: "text-muted-foreground text-xs", children: ["Gaat naar ", _jsx("span", { className: "font-medium", children: r.printerNaam })] })) : (_jsxs("div", { className: "text-muted-foreground flex items-center gap-1 text-xs", children: [_jsx(AlertTriangle, { className: "h-3 w-3" }), " ", r.reden] })), st?.fout ? (_jsx("div", { className: "text-destructive mt-1 text-xs", children: st.fout })) : null] }), _jsxs("div", { className: "flex items-center gap-2", children: [st?.status ? (_jsxs(Badge, { variant: st.status === "voltooid"
102
+ return (_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2 rounded-lg border p-3", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-sm font-medium", children: r.label }), r.printerId ? (_jsxs("div", { className: "text-muted-foreground text-xs", children: ["Gaat naar ", _jsx("span", { className: "font-medium", children: r.printerNaam })] })) : (_jsxs("div", { className: "text-muted-foreground flex items-center gap-1 text-xs", children: [_jsx(AlertTriangle, { className: "h-3 w-3" }), " ", r.reden] })), st?.fout ? (_jsx("div", { className: "text-destructive mt-1 text-xs", children: st.fout })) : null, r.printerId && st?.status === "mislukt" && /^(FORMAAT_PAST_NIET|GEEN_GELADEN_ETIKET)|past niet|geen etiket/i.test(st.fout ?? "") ? (_jsx(EtiketWijzigen, { printerId: r.printerId })) : null] }), _jsxs("div", { className: "flex items-center gap-2", children: [st?.status ? (_jsxs(Badge, { variant: st.status === "voltooid"
89
103
  ? "default"
90
104
  : st.status === "mislukt" || st.status === "geannuleerd"
91
105
  ? "destructive"
@@ -61,7 +61,7 @@ export function WerkplekConfiguratiePage() {
61
61
  setGekoppeld(new Set());
62
62
  return;
63
63
  }
64
- const id = await printplekVoorComputer(werkplekNaam);
64
+ const id = await printplekVoorComputer(werkplekNaam, computer?.id ?? null);
65
65
  setPlekId(id);
66
66
  if (!id) {
67
67
  setGekoppeld(new Set());
@@ -73,7 +73,7 @@ export function WerkplekConfiguratiePage() {
73
73
  .eq("print_plek_id", id);
74
74
  const lijst = Array.isArray(data) ? data : [];
75
75
  setGekoppeld(new Set(lijst.map((r) => r.printer_id)));
76
- }, [werkplekNaam]);
76
+ }, [werkplekNaam, computer?.id]);
77
77
  useEffect(() => {
78
78
  void laadKoppeling();
79
79
  }, [laadKoppeling, printers]);
@@ -1 +1 @@
1
- {"version":3,"file":"WerkplekkenTab.d.ts","sourceRoot":"","sources":["../../src/components/WerkplekkenTab.tsx"],"names":[],"mappings":"AAcA,OAAO,EAUL,KAAK,UAAU,EAEhB,MAAM,oBAAoB,CAAC;AAM5B,wBAAgB,kBAAkB,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE;IAAE,OAAO,EAAE,UAAU,CAAC;IAAC,WAAW,EAAE,MAAM,IAAI,CAAA;CAAE,+BAyE5G;AAqPD,wBAAgB,cAAc,gCA4E7B"}
1
+ {"version":3,"file":"WerkplekkenTab.d.ts","sourceRoot":"","sources":["../../src/components/WerkplekkenTab.tsx"],"names":[],"mappings":"AAcA,OAAO,EAUL,KAAK,UAAU,EAEhB,MAAM,oBAAoB,CAAC;AAO5B,wBAAgB,kBAAkB,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE;IAAE,OAAO,EAAE,UAAU,CAAC;IAAC,WAAW,EAAE,MAAM,IAAI,CAAA;CAAE,+BAyE5G;AA0PD,wBAAgB,cAAc,gCA4E7B"}
@@ -11,13 +11,14 @@ import { AlertTriangle, Plus, Printer, Trash2, Wand2 } from "lucide-react";
11
11
  import { supabase } from "../lib/supabaseClient.js";
12
12
  import { DOCUMENT_TYPES, documentTypeLabel } from "../lib/documentTypes.js";
13
13
  import { leesbareFout } from "../lib/foutTekst.js";
14
- import { etiketOpties, etiketTekst, maatNl } from "../lib/etiketControle.js";
14
+ import { etiketOptiesMetStandaard, etiketTekst, maatNl } from "../lib/etiketControle.js";
15
15
  import { formaatKlasse, printerTitel, slaWerkplekOp, soortPastBijFormaat, usePrinterLijst, useWerkplekken, verwijderWerkplek, zetAfwijking, zetPrinterVelden, } from "../lib/werkplekken.js";
16
16
  import { PrintenInstellenWizard } from "./PrintenInstellenWizard.js";
17
+ import { useBevestig } from "./BevestigDialog.js";
17
18
  const selectKlasse = "border-input bg-background rounded-md border px-2 py-1 text-sm";
18
19
  const db = supabase;
19
20
  export function GeladenEtiketKeuze({ printer, onGewijzigd }) {
20
- const opties = useMemo(() => etiketOpties(printer.ondersteunde_formaten), [printer.ondersteunde_formaten]);
21
+ const opties = useMemo(() => etiketOptiesMetStandaard(printer.ondersteunde_formaten), [printer.ondersteunde_formaten]);
21
22
  // Namen uit PrintNode kunnen spaties aan begin of eind hebben: vergelijk getrimd.
22
23
  const huidig = (printer.geladen_etiket?.naam ?? "").trim();
23
24
  const [zoek, setZoek] = useState("");
@@ -60,6 +61,7 @@ function PrinterSelect({ printers, value, onChange, leeg = "— geen —", }) {
60
61
  return (_jsxs("select", { className: selectKlasse, value: value ?? "", onChange: (e) => onChange(e.target.value || null), children: [_jsx("option", { value: "", children: leeg }), printers.map((p) => (_jsxs("option", { value: p.id, children: [printerTitel(p), p.locatie ? ` · ${p.locatie}` : "", p.online === false ? " (offline)" : ""] }, p.id)))] }));
61
62
  }
62
63
  function WerkplekKaart({ w, printers, plekken, afwijkingen, onGewijzigd, }) {
64
+ const [venster, bevestig] = useBevestig();
63
65
  const bewaar = async (velden) => {
64
66
  try {
65
67
  await slaWerkplekOp({ ...w, ...velden });
@@ -70,8 +72,8 @@ function WerkplekKaart({ w, printers, plekken, afwijkingen, onGewijzigd, }) {
70
72
  }
71
73
  };
72
74
  const label = printers.find((p) => p.id === w.label_printer_id) ?? null;
73
- return (_jsxs(Card, { children: [_jsxs(CardHeader, { className: "flex flex-row items-start justify-between gap-2", children: [_jsxs("div", { children: [_jsx(CardTitle, { className: "text-base", children: w.naam }), _jsx(CardDescription, { children: "A4 en A5 gaan naar de A4-printer, etiketten en stickers naar de labelprinter." })] }), _jsx(Button, { size: "sm", variant: "ghost", onClick: async () => {
74
- if (!confirm(`Werkplek ${w.naam} verwijderen? Printers blijven bestaan.`))
75
+ return (_jsxs(Card, { children: [venster, _jsxs(CardHeader, { className: "flex flex-row items-start justify-between gap-2", children: [_jsxs("div", { children: [_jsx(CardTitle, { className: "text-base", children: w.naam }), _jsx(CardDescription, { children: "A4 en A5 gaan naar de A4-printer, etiketten en stickers naar de labelprinter." })] }), _jsx(Button, { size: "sm", variant: "ghost", onClick: async () => {
76
+ if (!(await bevestig({ titel: `Werkplek ${w.naam} verwijderen?`, tekst: "De printers blijven bestaan.", knop: "Verwijderen", gevaarlijk: true })))
75
77
  return;
76
78
  await verwijderWerkplek(w.id).catch((e) => toast.error(leesbareFout(e, "Verwijderen mislukt")));
77
79
  onGewijzigd();
@@ -106,10 +108,15 @@ function AfwijkendeLayouts({ printers }) {
106
108
  }, []);
107
109
  const fout = layouts.filter((l) => !soortPastBijFormaat(l.documenttype, l.papierformaat));
108
110
  const labelPrinters = printers.filter((p) => p.geladen_etiket);
109
- return (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { className: "text-base", children: "Layouts en papier" }), _jsx(CardDescription, { children: "Layouts waarvan de documentsoort niet bij het papierformaat past, en op welke labelprinters een etiketlayout past." })] }), _jsxs(CardContent, { className: "space-y-2 text-sm", children: [fout.length === 0 ? _jsx("p", { className: "text-muted-foreground", children: "Alle actieve layouts passen bij hun papierformaat." }) : null, fout.map((l) => (_jsxs("div", { className: "flex flex-wrap items-center gap-2 rounded-lg border p-2", children: [_jsx(AlertTriangle, { className: "text-destructive h-4 w-4" }), _jsx("span", { className: "font-medium", children: l.naam }), _jsxs("span", { className: "text-muted-foreground", children: ["is ", documentTypeLabel(l.documenttype), " maar heeft papier ", l.papierformaat ?? "A4"] }), _jsxs("select", { className: `${selectKlasse} ml-auto`, defaultValue: "", onChange: async (e) => {
111
+ const [venster, bevestig] = useBevestig();
112
+ return (_jsxs(Card, { children: [venster, _jsxs(CardHeader, { children: [_jsx(CardTitle, { className: "text-base", children: "Layouts en papier" }), _jsx(CardDescription, { children: "Layouts waarvan de documentsoort niet bij het papierformaat past, en op welke labelprinters een etiketlayout past." })] }), _jsxs(CardContent, { className: "space-y-2 text-sm", children: [fout.length === 0 ? _jsx("p", { className: "text-muted-foreground", children: "Alle actieve layouts passen bij hun papierformaat." }) : null, fout.map((l) => (_jsxs("div", { className: "flex flex-wrap items-center gap-2 rounded-lg border p-2", children: [_jsx(AlertTriangle, { className: "text-destructive h-4 w-4" }), _jsx("span", { className: "font-medium", children: l.naam }), _jsxs("span", { className: "text-muted-foreground", children: ["is ", documentTypeLabel(l.documenttype), " maar heeft papier ", l.papierformaat ?? "A4"] }), _jsxs("select", { className: `${selectKlasse} ml-auto`, defaultValue: "", onChange: async (e) => {
110
113
  const soort = e.target.value;
111
- if (!soort || !confirm(`Soort van "${l.naam}" wijzigen naar ${documentTypeLabel(soort)}?`))
114
+ if (!soort)
112
115
  return;
116
+ if (!(await bevestig({ titel: `Soort van "${l.naam}" wijzigen naar ${documentTypeLabel(soort)}?`, knop: "Wijzigen" }))) {
117
+ e.target.value = "";
118
+ return;
119
+ }
113
120
  const { error } = await db.from("document_layouts").update({ documenttype: soort }).eq("id", l.id);
114
121
  if (error)
115
122
  toast.error(leesbareFout(error, "Soort aanpassen mislukt"));