@flowselections/mailbox-orders 1.0.11 → 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.
- package/dist-lib/components/EmailPreview.d.ts +26 -0
- package/dist-lib/components/EmailPreview.d.ts.map +1 -0
- package/dist-lib/components/EmailPreview.js +56 -0
- package/dist-lib/components/MailboxProcessedPage.d.ts.map +1 -1
- package/dist-lib/components/MailboxProcessedPage.js +7 -1
- package/dist-lib/components/MailboxProposalsPage.d.ts.map +1 -1
- package/dist-lib/components/MailboxProposalsPage.js +46 -17
- package/dist-lib/components/TablePagination.d.ts +12 -0
- package/dist-lib/components/TablePagination.d.ts.map +1 -0
- package/dist-lib/components/TablePagination.js +14 -0
- package/dist-lib/index.d.ts +2 -0
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +2 -0
- package/dist-lib/integrations/supabase/client.d.ts +126 -0
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +126 -0
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +126 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/mailbox-body.d.ts +26 -0
- package/dist-lib/lib/mailbox-body.d.ts.map +1 -1
- package/dist-lib/lib/mailbox-body.js +77 -1
- package/dist-lib/lib/mailbox-ingest.server.d.ts.map +1 -1
- package/dist-lib/lib/mailbox-ingest.server.js +5 -0
- package/dist-lib/lib/mailbox.functions.d.ts +10 -0
- package/dist-lib/lib/mailbox.functions.d.ts.map +1 -1
- package/dist-lib/lib/mailbox.functions.js +54 -14
- package/package.json +2 -2
|
@@ -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":"
|
|
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:
|
|
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":"
|
|
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
|
|
270
|
-
const active =
|
|
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:
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
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
|
|
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: [
|
|
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
|
+
}
|
package/dist-lib/index.d.ts
CHANGED
|
@@ -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
|
package/dist-lib/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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;
|