@flowselections/mailbox-orders 1.0.12 → 1.0.13

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 (28) hide show
  1. package/dist-lib/components/EmailPreview.d.ts +26 -0
  2. package/dist-lib/components/EmailPreview.d.ts.map +1 -0
  3. package/dist-lib/components/EmailPreview.js +56 -0
  4. package/dist-lib/components/MailboxProcessedPage.d.ts.map +1 -1
  5. package/dist-lib/components/MailboxProcessedPage.js +7 -1
  6. package/dist-lib/components/MailboxProposalsPage.d.ts.map +1 -1
  7. package/dist-lib/components/MailboxProposalsPage.js +46 -17
  8. package/dist-lib/components/TablePagination.d.ts +12 -0
  9. package/dist-lib/components/TablePagination.d.ts.map +1 -0
  10. package/dist-lib/components/TablePagination.js +14 -0
  11. package/dist-lib/index.d.ts +2 -0
  12. package/dist-lib/index.d.ts.map +1 -1
  13. package/dist-lib/index.js +2 -0
  14. package/dist-lib/integrations/supabase/client.d.ts +126 -0
  15. package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
  16. package/dist-lib/integrations/supabase/client.server.d.ts +126 -0
  17. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  18. package/dist-lib/integrations/supabase/types.d.ts +126 -0
  19. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  20. package/dist-lib/lib/mailbox-body.d.ts +26 -0
  21. package/dist-lib/lib/mailbox-body.d.ts.map +1 -1
  22. package/dist-lib/lib/mailbox-body.js +77 -1
  23. package/dist-lib/lib/mailbox-ingest.server.d.ts.map +1 -1
  24. package/dist-lib/lib/mailbox-ingest.server.js +5 -0
  25. package/dist-lib/lib/mailbox.functions.d.ts +10 -0
  26. package/dist-lib/lib/mailbox.functions.d.ts.map +1 -1
  27. package/dist-lib/lib/mailbox.functions.js +54 -14
  28. package/package.json +1 -1
@@ -0,0 +1,26 @@
1
+ export type PreviewAddress = {
2
+ name?: string | null;
3
+ email?: string | null;
4
+ };
5
+ export type PreviewAttachment = {
6
+ name: string;
7
+ contentType?: string | null;
8
+ size?: number | null;
9
+ contentId?: string | null;
10
+ url?: string | null;
11
+ };
12
+ type Props = {
13
+ subject?: string | null;
14
+ fromName?: string | null;
15
+ fromEmail?: string | null;
16
+ receivedAt?: string | null;
17
+ to?: PreviewAddress[];
18
+ cc?: PreviewAddress[];
19
+ bodyHtml?: string | null;
20
+ bodyText?: string | null;
21
+ attachments?: PreviewAttachment[];
22
+ hasAttachments?: boolean;
23
+ };
24
+ export declare function EmailPreview({ subject, fromName, fromEmail, receivedAt, to, cc, bodyHtml, bodyText, attachments, hasAttachments, }: Props): import("react").JSX.Element;
25
+ export {};
26
+ //# sourceMappingURL=EmailPreview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EmailPreview.d.ts","sourceRoot":"","sources":["../../src/components/EmailPreview.tsx"],"names":[],"mappings":"AAIA,MAAM,MAAM,cAAc,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAC7E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB,CAAC;AAEF,KAAK,KAAK,GAAG;IACX,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC;IACtB,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAClC,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAsEF,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,QAAQ,EACR,SAAS,EACT,UAAU,EACV,EAAO,EACP,EAAO,EACP,QAAQ,EACR,QAAQ,EACR,WAAgB,EAChB,cAAc,GACf,EAAE,KAAK,+BAsHP"}
@@ -0,0 +1,56 @@
1
+ import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useState } from "react";
3
+ import { Button, Badge } from "@flowselections/core";
4
+ import { Paperclip, Download, Code, FileText, ShieldOff, Shield } from "lucide-react";
5
+ function addrLabel(a) {
6
+ if (a.name && a.email && a.name !== a.email)
7
+ return `${a.name} <${a.email}>`;
8
+ return a.email || a.name || "";
9
+ }
10
+ function AddressLine({ label, list }) {
11
+ const [expanded, setExpanded] = useState(false);
12
+ if (!list.length)
13
+ return null;
14
+ const shown = expanded ? list : list.slice(0, 3);
15
+ return (_jsxs("div", { className: "flex gap-1 text-xs text-muted-foreground", children: [_jsxs("span", { className: "shrink-0 font-medium", children: [label, ":"] }), _jsxs("span", { className: "break-all", children: [shown.map(addrLabel).filter(Boolean).join(", "), !expanded && list.length > 3 && (_jsxs("button", { type: "button", className: "ml-1 underline", onClick: () => setExpanded(true), children: ["en ", list.length - 3, " meer"] }))] })] }));
16
+ }
17
+ function formatSize(n) {
18
+ if (!n || n <= 0)
19
+ return "";
20
+ if (n < 1024)
21
+ return `${n} B`;
22
+ if (n < 1024 * 1024)
23
+ return `${Math.round(n / 1024)} kB`;
24
+ return `${(n / (1024 * 1024)).toFixed(1)} MB`;
25
+ }
26
+ /** Blokkeert externe requests door remote src/href-bronnen te neutraliseren. */
27
+ function blockRemote(html) {
28
+ return html
29
+ .replace(/\ssrc\s*=\s*(["'])https?:\/\/[^"']*\1/gi, ' data-blocked-src=""')
30
+ .replace(/\sbackground\s*=\s*(["'])https?:\/\/[^"']*\1/gi, "")
31
+ .replace(/url\((["']?)https?:\/\/[^)]*\)/gi, "none");
32
+ }
33
+ function EmailFrame({ html }) {
34
+ const doc = useMemo(() => `<!doctype html><html><head><meta charset="utf-8">` +
35
+ `<base target="_blank">` +
36
+ `<style>html,body{margin:0;padding:12px;background:#fff;color:#111;` +
37
+ `font-family:-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif;font-size:14px;line-height:1.5;}` +
38
+ `img{max-width:100%;height:auto;}table{max-width:100%;}` +
39
+ `*{word-break:break-word;}</style></head><body>${html}</body></html>`, [html]);
40
+ return (_jsx("iframe", { title: "E-mailweergave", srcDoc: doc,
41
+ // Geen allow-scripts en geen allow-same-origin: de mail kan niets uitvoeren
42
+ // en niet bij de applicatie. Popups blijven werken voor links.
43
+ sandbox: "allow-popups allow-popups-to-escape-sandbox", referrerPolicy: "no-referrer", className: "h-full w-full rounded border bg-white" }));
44
+ }
45
+ export function EmailPreview({ subject, fromName, fromEmail, receivedAt, to = [], cc = [], bodyHtml, bodyText, attachments = [], hasAttachments, }) {
46
+ const html = (bodyHtml ?? "").trim();
47
+ const [mode, setMode] = useState(html ? "html" : "text");
48
+ const [blockRemoteContent, setBlockRemoteContent] = useState(false);
49
+ useEffect(() => {
50
+ setMode(html ? "html" : "text");
51
+ }, [html]);
52
+ const rendered = blockRemoteContent ? blockRemote(html) : html;
53
+ const safeAttachments = Array.isArray(attachments) ? attachments : [];
54
+ const inlineOnly = safeAttachments.every((a) => !!a.contentId);
55
+ return (_jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [_jsxs("div", { className: "shrink-0 space-y-1 border-b pb-3", children: [_jsx("div", { className: "text-base font-semibold leading-snug", children: subject || "(geen onderwerp)" }), _jsxs("div", { className: "text-xs text-muted-foreground", children: [_jsx("span", { className: "font-medium text-foreground", children: fromName || fromEmail }), fromName && fromEmail ? ` <${fromEmail}>` : "", receivedAt ? ` · ${new Date(receivedAt).toLocaleString("nl-NL")}` : ""] }), _jsx(AddressLine, { label: "Aan", list: to }), _jsx(AddressLine, { label: "CC", list: cc }), (safeAttachments.length > 0 || hasAttachments) && (_jsxs("div", { className: "flex flex-wrap items-center gap-2 pt-2", children: [safeAttachments.length === 0 ? (_jsxs(Badge, { variant: "outline", className: "gap-1 font-normal", children: [_jsx(Paperclip, { className: "h-3 w-3" }), " Deze mail bevat bijlagen (nog niet opgehaald)"] })) : (safeAttachments.map((a, i) => (_jsxs("span", { className: "inline-flex items-center gap-1 rounded border bg-muted/40 px-2 py-1 text-xs", children: [_jsx(Paperclip, { className: "h-3 w-3 shrink-0" }), _jsx("span", { className: "max-w-[16rem] truncate", children: a.name }), formatSize(a.size) && (_jsx("span", { className: "text-muted-foreground", children: formatSize(a.size) })), a.url && (_jsx("a", { href: a.url, target: "_blank", rel: "noopener noreferrer", className: "text-primary", "aria-label": `Download ${a.name}`, children: _jsx(Download, { className: "h-3 w-3" }) }))] }, `${a.name}-${i}`)))), safeAttachments.length > 0 && inlineOnly && (_jsx("span", { className: "text-[11px] text-muted-foreground", children: "(in de mail ingesloten afbeeldingen)" }))] })), _jsxs("div", { className: "flex flex-wrap items-center gap-2 pt-2", children: [_jsx(Button, { type: "button", size: "sm", variant: "outline", onClick: () => setMode(mode === "html" ? "text" : "html"), disabled: !html, children: mode === "html" ? (_jsxs(_Fragment, { children: [_jsx(FileText, { className: "mr-1 h-3.5 w-3.5" }), " Platte tekst"] })) : (_jsxs(_Fragment, { children: [_jsx(Code, { className: "mr-1 h-3.5 w-3.5" }), " Opgemaakte mail"] })) }), _jsx(Button, { type: "button", size: "sm", variant: "ghost", disabled: mode !== "html" || !html, onClick: () => setBlockRemoteContent((v) => !v), children: blockRemoteContent ? (_jsxs(_Fragment, { children: [_jsx(Shield, { className: "mr-1 h-3.5 w-3.5" }), " Externe inhoud tonen"] })) : (_jsxs(_Fragment, { children: [_jsx(ShieldOff, { className: "mr-1 h-3.5 w-3.5" }), " Externe inhoud blokkeren"] })) })] })] }), _jsx("div", { className: "min-h-0 flex-1 overflow-hidden pt-3", children: mode === "html" && html ? (_jsx(EmailFrame, { html: rendered })) : (_jsx("div", { className: "h-full w-full overflow-y-auto overscroll-contain rounded border bg-white p-3", children: _jsx("pre", { className: "whitespace-pre-wrap break-words font-sans text-sm leading-relaxed text-[#111]", children: bodyText || "(geen tekst)" }) })) })] }));
56
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"MailboxProcessedPage.d.ts","sourceRoot":"","sources":["../../src/components/MailboxProcessedPage.tsx"],"names":[],"mappings":"AAWA,wBAAgB,oBAAoB,gCA+FnC"}
1
+ {"version":3,"file":"MailboxProcessedPage.d.ts","sourceRoot":"","sources":["../../src/components/MailboxProcessedPage.tsx"],"names":[],"mappings":"AAYA,wBAAgB,oBAAoB,gCA6GnC"}
@@ -6,6 +6,7 @@ import { toast } from "sonner";
6
6
  import { Badge, Button, Card, CardContent, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@flowselections/core";
7
7
  import { listProposals, reopenProposal, getActiveOrdersMailbox } from "../lib/mailbox.functions";
8
8
  import { MailboxAuthBanner } from "./MailboxAuthBanner";
9
+ import { TablePagination } from "./TablePagination";
9
10
  export function MailboxProcessedPage() {
10
11
  const fetchList = useServerFn(listProposals);
11
12
  const reopen = useServerFn(reopenProposal);
@@ -30,6 +31,11 @@ export function MailboxProcessedPage() {
30
31
  ...(Array.isArray(rejected.data?.items) ? rejected.data.items : []),
31
32
  ].sort((a, b) => (b.reviewed_at ?? "").localeCompare(a.reviewed_at ?? ""));
32
33
  const [busyId, setBusyId] = useState(null);
34
+ const [page, setPage] = useState(1);
35
+ const [pageSize, setPageSize] = useState(25);
36
+ const pageCount = Math.max(1, Math.ceil(items.length / pageSize));
37
+ const currentPage = Math.min(page, pageCount);
38
+ const pagedItems = items.slice((currentPage - 1) * pageSize, currentPage * pageSize);
33
39
  const handleReopen = async (proposalId) => {
34
40
  setBusyId(proposalId);
35
41
  try {
@@ -44,5 +50,5 @@ export function MailboxProcessedPage() {
44
50
  setBusyId(null);
45
51
  }
46
52
  };
47
- return (_jsxs("div", { className: "p-6 flex flex-col gap-4 flex-1 min-h-0 overflow-hidden", children: [_jsx(MailboxAuthBanner, { active: activeMailbox }), _jsx("h1", { className: "text-2xl font-semibold shrink-0", children: "Verwerkt" }), _jsx("div", { className: "flex-1 min-h-0 overflow-y-auto overscroll-contain [scrollbar-gutter:stable]", children: _jsx(Card, { children: _jsx(CardContent, { className: "p-0", children: items.length === 0 ? (_jsx("div", { className: "p-8 text-center text-muted-foreground", children: "Nog geen verwerkte voorstellen." })) : (_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Status" }), _jsx(TableHead, { children: "Afzender" }), _jsx(TableHead, { children: "Onderwerp" }), _jsx(TableHead, { children: "Verwerkt op" }), _jsx(TableHead, { className: "text-right", children: "Acties" })] }) }), _jsx(TableBody, { children: items.map((p) => (_jsxs(TableRow, { children: [_jsx(TableCell, { children: _jsx(Badge, { variant: p.status === "approved" ? "default" : "destructive", children: p.status === "approved" ? "Goedgekeurd" : "Afgewezen" }) }), _jsx(TableCell, { children: p.mailbox_messages?.from_email ?? "-" }), _jsx(TableCell, { className: "max-w-md truncate", children: p.mailbox_messages?.subject ?? "-" }), _jsx(TableCell, { className: "text-sm text-muted-foreground", children: p.reviewed_at ? new Date(p.reviewed_at).toLocaleString("nl-NL") : "-" }), _jsx(TableCell, { className: "text-right space-x-2", children: p.status === "rejected" && (_jsx(Button, { size: "sm", variant: "outline", disabled: busyId === p.id, onClick: () => handleReopen(p.id), children: busyId === p.id ? "Bezig..." : "Terugzetten" })) })] }, p.id))) })] })) }) }) })] }));
53
+ return (_jsxs("div", { className: "p-6 flex flex-col gap-4 flex-1 min-h-0 overflow-hidden", children: [_jsx(MailboxAuthBanner, { active: activeMailbox }), _jsx("h1", { className: "text-2xl font-semibold shrink-0", children: "Verwerkt" }), _jsx("div", { className: "flex-1 min-h-0 overflow-y-auto overscroll-contain [scrollbar-gutter:stable]", children: _jsx(Card, { children: _jsxs(CardContent, { className: "p-0", children: [items.length === 0 ? (_jsx("div", { className: "p-8 text-center text-muted-foreground", children: "Nog geen verwerkte voorstellen." })) : (_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Status" }), _jsx(TableHead, { children: "Afzender" }), _jsx(TableHead, { children: "Onderwerp" }), _jsx(TableHead, { children: "Verwerkt op" }), _jsx(TableHead, { className: "text-right", children: "Acties" })] }) }), _jsx(TableBody, { children: pagedItems.map((p) => (_jsxs(TableRow, { children: [_jsx(TableCell, { children: _jsx(Badge, { variant: p.status === "approved" ? "default" : "destructive", children: p.status === "approved" ? "Goedgekeurd" : "Afgewezen" }) }), _jsx(TableCell, { children: p.mailbox_messages?.from_email ?? "-" }), _jsx(TableCell, { className: "max-w-md truncate", children: p.mailbox_messages?.subject ?? "-" }), _jsx(TableCell, { className: "text-sm text-muted-foreground", children: p.reviewed_at ? new Date(p.reviewed_at).toLocaleString("nl-NL") : "-" }), _jsx(TableCell, { className: "text-right space-x-2", children: p.status === "rejected" && (_jsx(Button, { size: "sm", variant: "outline", disabled: busyId === p.id, onClick: () => handleReopen(p.id), children: busyId === p.id ? "Bezig..." : "Terugzetten" })) })] }, p.id))) })] })), items.length > 0 && (_jsx(TablePagination, { total: items.length, page: currentPage, pageSize: pageSize, onPageChange: setPage, onPageSizeChange: setPageSize }))] }) }) })] }));
48
54
  }
@@ -1 +1 @@
1
- {"version":3,"file":"MailboxProposalsPage.d.ts","sourceRoot":"","sources":["../../src/components/MailboxProposalsPage.tsx"],"names":[],"mappings":"AAyFA,6EAA6E;AAC7E,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AA2CD,wBAAgB,oBAAoB,gCAwYnC"}
1
+ {"version":3,"file":"MailboxProposalsPage.d.ts","sourceRoot":"","sources":["../../src/components/MailboxProposalsPage.tsx"],"names":[],"mappings":"AA2FA,6EAA6E;AAC7E,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AA2CD,wBAAgB,oBAAoB,gCAqbnC"}
@@ -5,11 +5,13 @@ import { useServerFn } from "@tanstack/react-start";
5
5
  import { Button, Badge, Card, CardContent, CardHeader, CardTitle, Input, Label, Textarea, Switch, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Dialog, DialogContent, DialogHeader, DialogTitle, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, toast, } from "@flowselections/core";
6
6
  import { Check, X, Trash2, Plus, AlertTriangle, RefreshCw } from "lucide-react";
7
7
  import { computeEarliestDelivery, isValidDeliveryDate } from "../lib/delivery-date";
8
- import { listProposals, approveProposal, rejectProposal, listCustomersForPicker, createCustomerFromGroup, listProductsForPicker, listDeliveryLocationsForCustomer, listPickupLocations, listCarriersForPicker, getOrderPickDays, getActiveOrdersMailbox, syncMailboxNow, getLastIngestRun, refreshProposalsForAgentChange, reparseProposalNow, listBeladingOptionsForProducts, listAllowedLoadCarriers, } from "../lib/mailbox.functions";
8
+ import { listProposals, getProposalDetail, approveProposal, rejectProposal, listCustomersForPicker, createCustomerFromGroup, listProductsForPicker, listDeliveryLocationsForCustomer, listPickupLocations, listCarriersForPicker, getOrderPickDays, getActiveOrdersMailbox, syncMailboxNow, getLastIngestRun, refreshProposalsForAgentChange, reparseProposalNow, listBeladingOptionsForProducts, listAllowedLoadCarriers, } from "../lib/mailbox.functions";
9
9
  import { enabledLoadCarriers, normalizeAllowedLoadCarriers, EMPTY_LOAD_CARRIERS } from "../lib/load-carriers";
10
10
  import { listTemplateFields, listPlantTypesForPicker, listSuppliersForPicker, } from "../lib/mailbox-template.functions";
11
11
  import { SearchableSelect } from "./SearchableSelect";
12
12
  import { MailboxAuthBanner } from "./MailboxAuthBanner";
13
+ import { EmailPreview } from "./EmailPreview";
14
+ import { TablePagination } from "./TablePagination";
13
15
  import { supabase } from "../integrations/supabase/client";
14
16
  const beladingKey = (b) => `${b.plants_per_crate}x${b.crates_per_layer}x${b.layers_per_cart}|${b.crate_code ?? ""}|${b.carrier_code ?? ""}`;
15
17
  const beladingLabel = (b) => `${b.plants_per_crate} planten/fust · ${b.crates_per_layer} fusten/laag · ${b.layers_per_cart} lagen`;
@@ -98,6 +100,20 @@ export function MailboxProposalsPage() {
98
100
  return { items: [] };
99
101
  }
100
102
  };
103
+ // Welk voorstel staat open? De zware referentielijsten worden pas geladen
104
+ // zodra de dialoog voor het eerst opengaat, en blijven daarna gecachet.
105
+ const [activeId, setActiveId] = useState(null);
106
+ const [page, setPage] = useState(1);
107
+ const [pageSize, setPageSize] = useState(25);
108
+ const [refsEnabled, setRefsEnabled] = useState(false);
109
+ useEffect(() => { if (activeId)
110
+ setRefsEnabled(true); }, [activeId]);
111
+ const refOpts = {
112
+ enabled: refsEnabled,
113
+ staleTime: 5 * 60000,
114
+ gcTime: 30 * 60000,
115
+ refetchOnWindowFocus: false,
116
+ };
101
117
  // Bestelvoorstellen toont uitsluitend nieuwe, nog niet gecontroleerde
102
118
  // bestellingen ("Te controleren"). Goedgekeurd/afgewezen verschijnt in
103
119
  // de module Verwerkt.
@@ -111,16 +127,25 @@ export function MailboxProposalsPage() {
111
127
  refetchInterval: 60000,
112
128
  refetchOnWindowFocus: true,
113
129
  });
130
+ // Detail (mailtekst, bestelregels, veldwaarden) pas ophalen bij openen.
131
+ const fetchDetail = useServerFn(getProposalDetail);
132
+ const { data: detailData, isFetching: detailLoading } = useQuery({
133
+ queryKey: ["mailbox-proposal-detail", activeId],
134
+ enabled: !!activeId,
135
+ staleTime: 60000,
136
+ queryFn: () => fetchDetail({ data: { proposalId: activeId } }),
137
+ });
114
138
  const { data: templateData } = useQuery({
115
139
  queryKey: ["mailbox-template-fields"],
116
140
  queryFn: () => safe(() => fetchTemplate()),
141
+ ...refOpts,
117
142
  });
118
- const { data: customersData } = useQuery({ queryKey: ["mailbox-customers"], queryFn: () => safe(() => fetchCustomers()) });
119
- const { data: productsData } = useQuery({ queryKey: ["mailbox-products"], queryFn: () => safe(() => fetchProducts()) });
120
- const { data: plantData } = useQuery({ queryKey: ["mailbox-plant-types"], queryFn: () => safe(() => fetchPlantTypes()) });
121
- const { data: supplierData } = useQuery({ queryKey: ["mailbox-suppliers"], queryFn: () => safe(() => fetchSuppliers()) });
122
- const { data: carriersData } = useQuery({ queryKey: ["mailbox-carriers"], queryFn: () => safe(() => fetchCarriers()) });
123
- const { data: pickupLocData } = useQuery({ queryKey: ["mailbox-pickup-locations"], queryFn: () => safe(() => fetchPickupLocations()) });
143
+ const { data: customersData } = useQuery({ queryKey: ["mailbox-customers"], queryFn: () => safe(() => fetchCustomers()), ...refOpts });
144
+ const { data: productsData } = useQuery({ queryKey: ["mailbox-products"], queryFn: () => safe(() => fetchProducts()), ...refOpts });
145
+ const { data: plantData } = useQuery({ queryKey: ["mailbox-plant-types"], queryFn: () => safe(() => fetchPlantTypes()), ...refOpts });
146
+ const { data: supplierData } = useQuery({ queryKey: ["mailbox-suppliers"], queryFn: () => safe(() => fetchSuppliers()), ...refOpts });
147
+ const { data: carriersData } = useQuery({ queryKey: ["mailbox-carriers"], queryFn: () => safe(() => fetchCarriers()), ...refOpts });
148
+ const { data: pickupLocData } = useQuery({ queryKey: ["mailbox-pickup-locations"], queryFn: () => safe(() => fetchPickupLocations()), ...refOpts });
124
149
  const { data: activeMailbox } = useQuery({
125
150
  queryKey: ["mailbox-active-account"],
126
151
  queryFn: () => fetchActive(),
@@ -226,6 +251,7 @@ export function MailboxProposalsPage() {
226
251
  if (res?.ok) {
227
252
  setReparseError(null);
228
253
  qc.invalidateQueries({ queryKey: ["mailbox-proposals"] });
254
+ qc.invalidateQueries({ queryKey: ["mailbox-proposal-detail"] });
229
255
  toast.success("E-mail opnieuw geanalyseerd — bestelgegevens bijgewerkt");
230
256
  }
231
257
  else {
@@ -257,6 +283,9 @@ export function MailboxProposalsPage() {
257
283
  // eslint-disable-next-line react-hooks/exhaustive-deps
258
284
  }, []);
259
285
  const items = Array.isArray(data?.items) ? data.items : [];
286
+ const pageCount = Math.max(1, Math.ceil(items.length / pageSize));
287
+ const currentPage = Math.min(page, pageCount);
288
+ const pagedItems = items.slice((currentPage - 1) * pageSize, currentPage * pageSize);
260
289
  const template = Array.isArray(templateData?.items) ? templateData.items : [];
261
290
  const customers = Array.isArray(customersData?.items) ? customersData.items : [];
262
291
  const products = Array.isArray(productsData?.items) ? productsData.items : [];
@@ -266,8 +295,8 @@ export function MailboxProposalsPage() {
266
295
  const suppliers = Array.isArray(supplierData?.items) ? supplierData.items : [];
267
296
  const carriers = Array.isArray(carriersData?.items) ? carriersData.items : [];
268
297
  const pickupLocations = Array.isArray(pickupLocData?.items) ? pickupLocData.items : [];
269
- const [activeId, setActiveId] = useState(null);
270
- const active = items.find((p) => p.id === activeId) ?? null;
298
+ const activeSummary = items.find((p) => p.id === activeId) ?? null;
299
+ const active = (detailData?.item ?? null);
271
300
  const statusLabel = (_s) => "Te controleren";
272
301
  const statusVariant = (_s) => "secondary";
273
302
  const customerNameFor = (p) => {
@@ -281,15 +310,15 @@ export function MailboxProposalsPage() {
281
310
  }
282
311
  return p.mailbox_messages?.from_name || p.mailbox_messages?.from_email || "Onbekend";
283
312
  };
284
- return (_jsxs("div", { className: "p-6 flex flex-col gap-4 flex-1 min-h-0 overflow-hidden", children: [_jsx(MailboxAuthBanner, { active: activeMailbox }), _jsxs("div", { className: "flex items-center justify-between shrink-0", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-semibold", children: "Bestelvoorstellen" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Nieuw binnengekomen bestellingen die nog handmatig gecontroleerd moeten worden." })] }), _jsxs("div", { className: "flex items-center gap-3", children: [lastRun?.finished_at && (_jsxs("span", { className: "text-xs text-muted-foreground", children: ["Laatste sync: ", new Date(lastRun.finished_at).toLocaleTimeString("nl-NL"), " \u2014 ", lastRun.processed, " verwerkt", lastRun.errors > 0 ? `, ${lastRun.errors} fouten` : ""] })), _jsxs(Button, { onClick: handleManualSync, disabled: syncMut.isPending, variant: "outline", children: [_jsx(RefreshCw, { className: `h-4 w-4 mr-2 ${syncMut.isPending ? "animate-spin" : ""}` }), "Sync nu"] })] })] }), _jsx("div", { className: "flex-1 min-h-0 overflow-y-auto overscroll-contain [scrollbar-gutter:stable]", children: isLoading ? (_jsx("div", { className: "text-muted-foreground", children: "Laden..." })) : listError ? (_jsxs("div", { className: "rounded-md border border-destructive/40 bg-destructive/5 p-4 text-sm", children: [_jsx("p", { className: "font-medium text-destructive", children: "Bestellingen konden niet worden opgehaald." }), _jsxs("p", { className: "text-muted-foreground mt-1", children: [listError?.message ?? "Onbekende fout", " \u2014 de lijst is niet leeg, alleen niet geladen."] }), _jsx(Button, { size: "sm", variant: "outline", className: "mt-3", onClick: () => void refetchList(), children: "Opnieuw proberen" })] })) : items.length === 0 ? (_jsx("p", { className: "text-muted-foreground", children: "Geen bestellingen te controleren." })) : (_jsx(Card, { children: _jsx(CardContent, { className: "p-0", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Klantnaam" }), _jsx(TableHead, { children: "Orderdatum" }), _jsx(TableHead, { children: "Status" }), _jsx(TableHead, { className: "text-right", children: "Orderwaarde" })] }) }), _jsx(TableBody, { children: items.map((p) => {
285
- const fvs = Array.isArray(p.mailbox_proposal_field_values) ? p.mailbox_proposal_field_values : [];
286
- const needsReview = fvs.some((v) => v.needs_review);
287
- const date = p.mailbox_messages?.received_at ?? p.created_at;
288
- return (_jsxs(TableRow, { className: "cursor-pointer hover:bg-muted/50", onClick: () => setActiveId(p.id), children: [_jsx(TableCell, { className: "font-medium", children: customerNameFor(p) }), _jsx(TableCell, { className: "text-sm text-muted-foreground", children: date ? new Date(date).toLocaleDateString("nl-NL") : "-" }), _jsx(TableCell, { children: _jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Badge, { variant: statusVariant(p.status), children: statusLabel(p.status) }), p.parsed_payload?.ai?.ok === true && (_jsx(Badge, { variant: "outline", className: "text-xs border-sky-500 text-sky-700", children: "AI" })), needsReview && (_jsxs(Badge, { variant: "outline", className: "text-xs border-yellow-500 text-yellow-700", children: [_jsx(AlertTriangle, { className: "h-3 w-3 mr-1" }), "Controleren"] }))] }) }), _jsx(TableCell, { className: "text-right text-sm text-muted-foreground", children: "\u2014" })] }, p.id));
289
- }) })] }) }) })) }), _jsx(Dialog, { open: !!active, onOpenChange: (o) => { if (!o) {
313
+ return (_jsxs("div", { className: "p-6 flex flex-col gap-4 flex-1 min-h-0 overflow-hidden", children: [_jsx(MailboxAuthBanner, { active: activeMailbox }), _jsxs("div", { className: "flex items-center justify-between shrink-0", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-semibold", children: "Bestelvoorstellen" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Nieuw binnengekomen bestellingen die nog handmatig gecontroleerd moeten worden." })] }), _jsxs("div", { className: "flex items-center gap-3", children: [lastRun?.finished_at && (_jsxs("span", { className: "text-xs text-muted-foreground", children: ["Laatste sync: ", new Date(lastRun.finished_at).toLocaleTimeString("nl-NL"), " \u2014 ", lastRun.processed, " verwerkt", lastRun.errors > 0 ? `, ${lastRun.errors} fouten` : ""] })), _jsxs(Button, { onClick: handleManualSync, disabled: syncMut.isPending, variant: "outline", children: [_jsx(RefreshCw, { className: `h-4 w-4 mr-2 ${syncMut.isPending ? "animate-spin" : ""}` }), "Sync nu"] })] })] }), _jsx("div", { className: "flex-1 min-h-0 overflow-y-auto overscroll-contain [scrollbar-gutter:stable]", children: isLoading ? (_jsx("div", { className: "text-muted-foreground", children: "Laden..." })) : listError ? (_jsxs("div", { className: "rounded-md border border-destructive/40 bg-destructive/5 p-4 text-sm", children: [_jsx("p", { className: "font-medium text-destructive", children: "Bestellingen konden niet worden opgehaald." }), _jsxs("p", { className: "text-muted-foreground mt-1", children: [listError?.message ?? "Onbekende fout", " \u2014 de lijst is niet leeg, alleen niet geladen."] }), _jsx(Button, { size: "sm", variant: "outline", className: "mt-3", onClick: () => void refetchList(), children: "Opnieuw proberen" })] })) : items.length === 0 ? (_jsx("p", { className: "text-muted-foreground", children: "Geen bestellingen te controleren." })) : (_jsx(Card, { children: _jsxs(CardContent, { className: "p-0", children: [_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Klantnaam" }), _jsx(TableHead, { children: "Orderdatum" }), _jsx(TableHead, { children: "Status" }), _jsx(TableHead, { className: "text-right", children: "Orderwaarde" })] }) }), _jsx(TableBody, { children: pagedItems.map((p) => {
314
+ const fvs = Array.isArray(p.mailbox_proposal_field_values) ? p.mailbox_proposal_field_values : [];
315
+ const needsReview = fvs.some((v) => v.needs_review);
316
+ const date = p.mailbox_messages?.received_at ?? p.created_at;
317
+ return (_jsxs(TableRow, { className: "cursor-pointer hover:bg-muted/50", onClick: () => setActiveId(p.id), children: [_jsx(TableCell, { className: "font-medium", children: customerNameFor(p) }), _jsx(TableCell, { className: "text-sm text-muted-foreground", children: date ? new Date(date).toLocaleDateString("nl-NL") : "-" }), _jsx(TableCell, { children: _jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Badge, { variant: statusVariant(p.status), children: statusLabel(p.status) }), String(p.ai_ok) === "true" && (_jsx(Badge, { variant: "outline", className: "text-xs border-sky-500 text-sky-700", children: "AI" })), needsReview && (_jsxs(Badge, { variant: "outline", className: "text-xs border-yellow-500 text-yellow-700", children: [_jsx(AlertTriangle, { className: "h-3 w-3 mr-1" }), "Controleren"] }))] }) }), _jsx(TableCell, { className: "text-right text-sm text-muted-foreground", children: "\u2014" })] }, p.id));
318
+ }) })] }), _jsx(TablePagination, { total: items.length, page: currentPage, pageSize: pageSize, onPageChange: setPage, onPageSizeChange: setPageSize })] }) })) }), _jsx(Dialog, { open: !!activeId, onOpenChange: (o) => { if (!o) {
290
319
  setActiveId(null);
291
320
  setReparseError(null);
292
- } }, children: _jsx(DialogContent, { className: "max-w-[95vw] w-[95vw] h-[92vh] max-h-[92vh] p-0 flex flex-col overflow-hidden", children: active && (_jsxs(_Fragment, { children: [_jsxs(DialogHeader, { className: "px-6 pt-6 pb-3 shrink-0 border-b", children: [_jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsx(DialogTitle, { children: customerNameFor(active) }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", className: "mr-8", disabled: reparseMutation.isPending, onClick: () => reparseMutation.mutate(active.id), children: [_jsx(RefreshCw, { className: `h-4 w-4 mr-2 ${reparseMutation.isPending ? "animate-spin" : ""}` }), reparseMutation.isPending ? "Analyseren…" : "Mail opnieuw analyseren"] })] }), reparseError && (_jsxs("div", { className: "mt-2 flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive", children: [_jsx(AlertTriangle, { className: "h-4 w-4 mt-0.5 shrink-0" }), _jsx("span", { children: reparseError })] }))] }), _jsx("div", { className: "flex-1 min-h-0 overflow-hidden p-6", children: _jsx(ProposalEditor, { proposal: active, template: template, customers: customers, products: products, allowBackorder: allowBackorder, plantTypes: plantTypes, suppliers: suppliers, carriers: carriers, pickupLocations: pickupLocations, onApprove: async (payload) => {
321
+ } }, children: _jsx(DialogContent, { className: "max-w-[95vw] w-[95vw] h-[92vh] max-h-[92vh] p-0 flex flex-col overflow-hidden", children: !active ? (_jsxs("div", { className: "flex-1 flex flex-col items-center justify-center gap-2 text-sm text-muted-foreground", children: [_jsx(DialogTitle, { className: "text-base", children: "Bestelling" }), detailLoading ? "Bestelling laden…" : "Bestelling niet gevonden."] })) : (_jsxs(_Fragment, { children: [_jsxs(DialogHeader, { className: "px-6 pt-6 pb-3 shrink-0 border-b", children: [_jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsx(DialogTitle, { children: customerNameFor(activeSummary ?? active) }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", className: "mr-8", disabled: reparseMutation.isPending, onClick: () => reparseMutation.mutate(active.id), children: [_jsx(RefreshCw, { className: `h-4 w-4 mr-2 ${reparseMutation.isPending ? "animate-spin" : ""}` }), reparseMutation.isPending ? "Analyseren…" : "Mail opnieuw analyseren"] })] }), reparseError && (_jsxs("div", { className: "mt-2 flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive", children: [_jsx(AlertTriangle, { className: "h-4 w-4 mt-0.5 shrink-0" }), _jsx("span", { children: reparseError })] }))] }), _jsx("div", { className: "flex-1 min-h-0 overflow-hidden p-6", children: _jsx(ProposalEditor, { proposal: active, template: template, customers: customers, products: products, allowBackorder: allowBackorder, plantTypes: plantTypes, suppliers: suppliers, carriers: carriers, pickupLocations: pickupLocations, onApprove: async (payload) => {
293
322
  try {
294
323
  const res = await fetchApprove({ data: payload });
295
324
  const shortages = Array.isArray(res?.shortages) ? res.shortages : [];
@@ -613,7 +642,7 @@ function ProposalEditor({ proposal, template, customers, products, allowBackorde
613
642
  setSubmitting(false);
614
643
  }
615
644
  };
616
- return (_jsxs("div", { className: "grid grid-cols-2 gap-4 h-full min-h-0", children: [_jsxs(Card, { className: "flex flex-col min-h-0 overflow-hidden", children: [_jsxs(CardHeader, { className: "shrink-0", children: [_jsx(CardTitle, { className: "text-base", children: msg.subject || "(geen onderwerp)" }), _jsxs("div", { className: "text-xs text-muted-foreground", children: [msg.from_name, " <", msg.from_email, "> \u00B7", " ", msg.received_at ? new Date(msg.received_at).toLocaleString("nl-NL") : ""] })] }), _jsx(CardContent, { className: "flex-1 min-h-0 overflow-y-auto overscroll-contain", children: _jsx("pre", { className: "text-sm whitespace-pre-wrap font-sans", children: msg.body_text || "(geen tekst)" }) })] }), _jsxs(Card, { className: "flex flex-col min-h-0 overflow-hidden", children: [_jsx(CardHeader, { className: "shrink-0", children: _jsx(CardTitle, { className: "text-base", children: "Bestelvoorstel" }) }), _jsxs(CardContent, { className: "space-y-4 flex-1 min-h-0 overflow-y-auto overscroll-contain", children: [(() => {
645
+ return (_jsxs("div", { className: "grid grid-cols-2 gap-4 h-full min-h-0", children: [_jsx(Card, { className: "flex flex-col min-h-0 overflow-hidden", children: _jsx(CardContent, { className: "flex-1 min-h-0 p-4", children: _jsx(EmailPreview, { subject: msg.subject, fromName: msg.from_name, fromEmail: msg.from_email, receivedAt: msg.received_at, to: Array.isArray(msg.to_recipients) ? msg.to_recipients : [], cc: Array.isArray(msg.cc_recipients) ? msg.cc_recipients : [], bodyHtml: msg.body_html, bodyText: msg.body_text, attachments: Array.isArray(msg.attachments) ? msg.attachments : [], hasAttachments: msg.has_attachments === true }) }) }), _jsxs(Card, { className: "flex flex-col min-h-0 overflow-hidden", children: [_jsx(CardHeader, { className: "shrink-0", children: _jsx(CardTitle, { className: "text-base", children: "Bestelvoorstel" }) }), _jsxs(CardContent, { className: "space-y-4 flex-1 min-h-0 overflow-y-auto overscroll-contain", children: [(() => {
617
646
  // Klantveld staat altijd bovenaan, ook als het template (nog) leeg is.
618
647
  const customerField = visibleFields.find((f) => f.key === "customer") ?? {
619
648
  id: "customer",
@@ -0,0 +1,12 @@
1
+ export declare const PAGE_SIZE_OPTIONS: number[];
2
+ type Props = {
3
+ total: number;
4
+ page: number;
5
+ pageSize: number;
6
+ onPageChange: (page: number) => void;
7
+ onPageSizeChange: (size: number) => void;
8
+ };
9
+ /** Paginering onderaan een tabel: "1–14 van 14 · Per pagina · Vorige/Volgende". */
10
+ export declare function TablePagination({ total, page, pageSize, onPageChange, onPageSizeChange, }: Props): import("react").JSX.Element;
11
+ export {};
12
+ //# sourceMappingURL=TablePagination.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TablePagination.d.ts","sourceRoot":"","sources":["../../src/components/TablePagination.tsx"],"names":[],"mappings":"AASA,eAAO,MAAM,iBAAiB,UAAoB,CAAC;AAEnD,KAAK,KAAK,GAAG;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C,CAAC;AAEF,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,YAAY,EACZ,gBAAgB,GACjB,EAAE,KAAK,+BAqDP"}
@@ -0,0 +1,14 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { Button, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@flowselections/core";
3
+ export const PAGE_SIZE_OPTIONS = [10, 25, 50, 100];
4
+ /** Paginering onderaan een tabel: "1–14 van 14 · Per pagina · Vorige/Volgende". */
5
+ export function TablePagination({ total, page, pageSize, onPageChange, onPageSizeChange, }) {
6
+ const pageCount = Math.max(1, Math.ceil(total / pageSize));
7
+ const current = Math.min(Math.max(1, page), pageCount);
8
+ const from = total === 0 ? 0 : (current - 1) * pageSize + 1;
9
+ const to = Math.min(current * pageSize, total);
10
+ return (_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 border-t px-4 py-2 text-sm", children: [_jsxs("span", { className: "text-muted-foreground", children: [from, "\u2013", to, " van ", total] }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("span", { className: "text-muted-foreground", children: "Per pagina" }), _jsxs(Select, { value: String(pageSize), onValueChange: (v) => {
11
+ onPageSizeChange(Number(v));
12
+ onPageChange(1);
13
+ }, children: [_jsx(SelectTrigger, { className: "h-8 w-[80px]", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: PAGE_SIZE_OPTIONS.map((n) => (_jsx(SelectItem, { value: String(n), children: n }, n))) })] }), _jsx(Button, { size: "sm", variant: "outline", disabled: current <= 1, onClick: () => onPageChange(current - 1), children: "Vorige" }), _jsxs("span", { className: "text-muted-foreground", children: [current, " / ", pageCount] }), _jsx(Button, { size: "sm", variant: "outline", disabled: current >= pageCount, onClick: () => onPageChange(current + 1), children: "Volgende" })] })] }));
14
+ }
@@ -3,5 +3,7 @@ export * from "./_core-safelist";
3
3
  export { MailboxProposalsPage } from "./components/MailboxProposalsPage";
4
4
  export { SearchableSelect } from "./components/SearchableSelect";
5
5
  export { MailboxProcessedPage } from "./components/MailboxProcessedPage";
6
+ export { EmailPreview } from "./components/EmailPreview";
7
+ export { TablePagination } from "./components/TablePagination";
6
8
  export declare const mailboxOrdersModule: FlowModule;
7
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAIvD,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAEzE,eAAO,MAAM,mBAAmB,EAAE,UAmBjC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAIvD,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAE/D,eAAO,MAAM,mBAAmB,EAAE,UAmBjC,CAAC"}
package/dist-lib/index.js CHANGED
@@ -8,6 +8,8 @@ export * from "./_core-safelist";
8
8
  export { MailboxProposalsPage } from "./components/MailboxProposalsPage";
9
9
  export { SearchableSelect } from "./components/SearchableSelect";
10
10
  export { MailboxProcessedPage } from "./components/MailboxProcessedPage";
11
+ export { EmailPreview } from "./components/EmailPreview";
12
+ export { TablePagination } from "./components/TablePagination";
11
13
  export const mailboxOrdersModule = {
12
14
  id: "mailbox_orders",
13
15
  name: "Mailbox bestellingen",
@@ -9417,14 +9417,17 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
9417
9417
  };
9418
9418
  mailbox_messages: {
9419
9419
  Row: {
9420
+ attachments: import("./types").Json;
9420
9421
  body_html: string | null;
9421
9422
  body_text: string | null;
9423
+ cc_recipients: import("./types").Json;
9422
9424
  connection_id: string | null;
9423
9425
  created_at: string;
9424
9426
  error_message: string | null;
9425
9427
  external_id: string | null;
9426
9428
  from_email: string | null;
9427
9429
  from_name: string | null;
9430
+ has_attachments: boolean;
9428
9431
  id: string;
9429
9432
  message_id: string | null;
9430
9433
  profile_id: string | null;
@@ -9432,18 +9435,22 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
9432
9435
  received_at: string | null;
9433
9436
  status: string;
9434
9437
  subject: string | null;
9438
+ to_recipients: import("./types").Json;
9435
9439
  uid: number | null;
9436
9440
  updated_at: string;
9437
9441
  };
9438
9442
  Insert: {
9443
+ attachments?: import("./types").Json;
9439
9444
  body_html?: string | null;
9440
9445
  body_text?: string | null;
9446
+ cc_recipients?: import("./types").Json;
9441
9447
  connection_id?: string | null;
9442
9448
  created_at?: string;
9443
9449
  error_message?: string | null;
9444
9450
  external_id?: string | null;
9445
9451
  from_email?: string | null;
9446
9452
  from_name?: string | null;
9453
+ has_attachments?: boolean;
9447
9454
  id?: string;
9448
9455
  message_id?: string | null;
9449
9456
  profile_id?: string | null;
@@ -9451,18 +9458,22 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
9451
9458
  received_at?: string | null;
9452
9459
  status?: string;
9453
9460
  subject?: string | null;
9461
+ to_recipients?: import("./types").Json;
9454
9462
  uid?: number | null;
9455
9463
  updated_at?: string;
9456
9464
  };
9457
9465
  Update: {
9466
+ attachments?: import("./types").Json;
9458
9467
  body_html?: string | null;
9459
9468
  body_text?: string | null;
9469
+ cc_recipients?: import("./types").Json;
9460
9470
  connection_id?: string | null;
9461
9471
  created_at?: string;
9462
9472
  error_message?: string | null;
9463
9473
  external_id?: string | null;
9464
9474
  from_email?: string | null;
9465
9475
  from_name?: string | null;
9476
+ has_attachments?: boolean;
9466
9477
  id?: string;
9467
9478
  message_id?: string | null;
9468
9479
  profile_id?: string | null;
@@ -9470,6 +9481,7 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
9470
9481
  received_at?: string | null;
9471
9482
  status?: string;
9472
9483
  subject?: string | null;
9484
+ to_recipients?: import("./types").Json;
9473
9485
  uid?: number | null;
9474
9486
  updated_at?: string;
9475
9487
  };
@@ -9877,6 +9889,36 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
9877
9889
  };
9878
9890
  Relationships: [];
9879
9891
  };
9892
+ module_registry: {
9893
+ Row: {
9894
+ created_at: string;
9895
+ is_active: boolean;
9896
+ last_seen_at: string;
9897
+ module_id: string;
9898
+ name: string;
9899
+ shell_id: string | null;
9900
+ sort_order: number | null;
9901
+ };
9902
+ Insert: {
9903
+ created_at?: string;
9904
+ is_active?: boolean;
9905
+ last_seen_at?: string;
9906
+ module_id: string;
9907
+ name: string;
9908
+ shell_id?: string | null;
9909
+ sort_order?: number | null;
9910
+ };
9911
+ Update: {
9912
+ created_at?: string;
9913
+ is_active?: boolean;
9914
+ last_seen_at?: string;
9915
+ module_id?: string;
9916
+ name?: string;
9917
+ shell_id?: string | null;
9918
+ sort_order?: number | null;
9919
+ };
9920
+ Relationships: [];
9921
+ };
9880
9922
  module_runtime_config: {
9881
9923
  Row: {
9882
9924
  key: string;
@@ -12487,6 +12529,33 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
12487
12529
  };
12488
12530
  Relationships: [];
12489
12531
  };
12532
+ print_queue_settings: {
12533
+ Row: {
12534
+ bewaar_bestanden_dagen: number;
12535
+ bewaar_opdrachten_dagen: number;
12536
+ created_at: string;
12537
+ dubbel_venster_minuten: number;
12538
+ id: string;
12539
+ updated_at: string;
12540
+ };
12541
+ Insert: {
12542
+ bewaar_bestanden_dagen?: number;
12543
+ bewaar_opdrachten_dagen?: number;
12544
+ created_at?: string;
12545
+ dubbel_venster_minuten?: number;
12546
+ id?: string;
12547
+ updated_at?: string;
12548
+ };
12549
+ Update: {
12550
+ bewaar_bestanden_dagen?: number;
12551
+ bewaar_opdrachten_dagen?: number;
12552
+ created_at?: string;
12553
+ dubbel_venster_minuten?: number;
12554
+ id?: string;
12555
+ updated_at?: string;
12556
+ };
12557
+ Relationships: [];
12558
+ };
12490
12559
  print_rules: {
12491
12560
  Row: {
12492
12561
  actief: boolean;
@@ -16429,6 +16498,33 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
16429
16498
  referencedColumns: ["id"];
16430
16499
  }];
16431
16500
  };
16501
+ user_module_permissions: {
16502
+ Row: {
16503
+ created_at: string;
16504
+ id: string;
16505
+ module_id: string;
16506
+ permission: string;
16507
+ updated_at: string;
16508
+ user_id: string;
16509
+ };
16510
+ Insert: {
16511
+ created_at?: string;
16512
+ id?: string;
16513
+ module_id: string;
16514
+ permission: string;
16515
+ updated_at?: string;
16516
+ user_id: string;
16517
+ };
16518
+ Update: {
16519
+ created_at?: string;
16520
+ id?: string;
16521
+ module_id?: string;
16522
+ permission?: string;
16523
+ updated_at?: string;
16524
+ user_id?: string;
16525
+ };
16526
+ Relationships: [];
16527
+ };
16432
16528
  user_roles: {
16433
16529
  Row: {
16434
16530
  created_at: string;
@@ -18613,6 +18709,13 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
18613
18709
  };
18614
18710
  Returns: import("./types").Json;
18615
18711
  };
18712
+ effective_module_permission: {
18713
+ Args: {
18714
+ _module_id: string;
18715
+ _user_id: string;
18716
+ };
18717
+ Returns: string;
18718
+ };
18616
18719
  email_auth_decrypt: {
18617
18720
  Args: {
18618
18721
  cipher: string;
@@ -19751,6 +19854,13 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
19751
19854
  };
19752
19855
  Returns: undefined;
19753
19856
  };
19857
+ my_module_permissions: {
19858
+ Args: never;
19859
+ Returns: {
19860
+ module_id: string;
19861
+ permission: string;
19862
+ }[];
19863
+ };
19754
19864
  next_manufacture_partij: {
19755
19865
  Args: {
19756
19866
  _tenant_id: string;
@@ -19801,6 +19911,13 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
19801
19911
  };
19802
19912
  Returns: boolean;
19803
19913
  };
19914
+ opruim_print_historie: {
19915
+ Args: never;
19916
+ Returns: {
19917
+ ontdaan: number;
19918
+ verwijderd: number;
19919
+ }[];
19920
+ };
19804
19921
  order_number_prefix: {
19805
19922
  Args: {
19806
19923
  p_custom_fields?: import("./types").Json;
@@ -20644,6 +20761,15 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
20644
20761
  };
20645
20762
  Returns: undefined;
20646
20763
  };
20764
+ trade_item_stock_duplicates: {
20765
+ Args: never;
20766
+ Returns: {
20767
+ keys: string[];
20768
+ product_id: string;
20769
+ product_name: string;
20770
+ row_count: number;
20771
+ }[];
20772
+ };
20647
20773
  try_debtor_lock: {
20648
20774
  Args: {
20649
20775
  _group_key: string;