@flowselections/mailbox-orders 1.0.2 → 1.0.3
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/MailboxInboxPage.d.ts.map +1 -1
- package/dist-lib/components/MailboxInboxPage.js +78 -19
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +1 -3
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +4935 -1303
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.d.ts +4935 -1303
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +4935 -1303
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +4989 -1258
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.js +18 -1
- package/dist-lib/lib/mailbox-ai.server.d.ts +1 -1
- package/dist-lib/lib/mailbox-ai.server.d.ts.map +1 -1
- package/dist-lib/lib/mailbox-ai.server.js +6 -106
- package/dist-lib/lib/mailbox-template.functions.d.ts +32826 -11034
- package/dist-lib/lib/mailbox-template.functions.d.ts.map +1 -1
- package/dist-lib/lib/mailbox.functions.d.ts +42670 -15922
- package/dist-lib/lib/mailbox.functions.d.ts.map +1 -1
- package/dist-lib/lib/mailbox.functions.js +162 -173
- package/package.json +4 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MailboxInboxPage.d.ts","sourceRoot":"","sources":["../../src/components/MailboxInboxPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MailboxInboxPage.d.ts","sourceRoot":"","sources":["../../src/components/MailboxInboxPage.tsx"],"names":[],"mappings":"AA6BA,wBAAgB,gBAAgB,gCAuO/B"}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef } from "react";
|
|
2
3
|
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
3
4
|
import { useServerFn } from "@tanstack/react-start";
|
|
4
5
|
import { Button, Badge, Card, CardContent, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, toast, } from "@flowselections/core";
|
|
5
|
-
import { Mail,
|
|
6
|
-
import { listMessages,
|
|
6
|
+
import { Mail, Sparkles, AlertCircle, ExternalLink, RefreshCw } from "lucide-react";
|
|
7
|
+
import { listMessages, parseMessage, getActiveOrdersMailbox, ingestEmailEvent, backfillRecentEvents, } from "../lib/mailbox.functions";
|
|
8
|
+
import { supabase } from "../integrations/supabase/client";
|
|
9
|
+
const AUTH_MODULE_URL = "https://auth.flowselections.com/e-mail-authenticatie";
|
|
7
10
|
const STATUS_VARIANT = {
|
|
8
11
|
new: "secondary",
|
|
9
12
|
parsing: "outline",
|
|
@@ -15,33 +18,88 @@ const STATUS_VARIANT = {
|
|
|
15
18
|
export function MailboxInboxPage() {
|
|
16
19
|
const qc = useQueryClient();
|
|
17
20
|
const fetchList = useServerFn(listMessages);
|
|
18
|
-
const fetchPoll = useServerFn(pollMailbox);
|
|
19
21
|
const fetchParse = useServerFn(parseMessage);
|
|
22
|
+
const fetchActive = useServerFn(getActiveOrdersMailbox);
|
|
23
|
+
const fetchIngest = useServerFn(ingestEmailEvent);
|
|
24
|
+
const fetchBackfill = useServerFn(backfillRecentEvents);
|
|
20
25
|
const { data, isLoading } = useQuery({
|
|
21
26
|
queryKey: ["mailbox-messages"],
|
|
22
27
|
queryFn: () => fetchList(),
|
|
23
28
|
});
|
|
24
|
-
const
|
|
25
|
-
|
|
29
|
+
const { data: active, isSuccess: activeLoaded } = useQuery({
|
|
30
|
+
queryKey: ["mailbox-active-account"],
|
|
31
|
+
queryFn: () => fetchActive(),
|
|
32
|
+
refetchInterval: 60000,
|
|
33
|
+
retry: 1,
|
|
34
|
+
});
|
|
35
|
+
// Realtime: nieuwe events uit gedeelde authenticatiemodule
|
|
36
|
+
const activeId = active?.connected ? active.id : null;
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (!activeId)
|
|
39
|
+
return;
|
|
40
|
+
const channel = supabase
|
|
41
|
+
.channel(`email_auth_events:${activeId}`)
|
|
42
|
+
.on("postgres_changes", {
|
|
43
|
+
event: "INSERT",
|
|
44
|
+
schema: "public",
|
|
45
|
+
table: "email_auth_events",
|
|
46
|
+
filter: `connection_id=eq.${activeId}`,
|
|
47
|
+
}, async (payload) => {
|
|
48
|
+
const evId = payload?.new?.id;
|
|
49
|
+
if (!evId)
|
|
50
|
+
return;
|
|
51
|
+
try {
|
|
52
|
+
const res = await fetchIngest({ data: { eventId: evId } });
|
|
53
|
+
if (res?.ok && (res.inserted ?? 0) > 0) {
|
|
54
|
+
const app = res.autoApproved ?? 0;
|
|
55
|
+
if (app > 0)
|
|
56
|
+
toast.success(`Nieuwe e-mail — ${app} automatisch omgezet`);
|
|
57
|
+
else
|
|
58
|
+
toast.success("Nieuwe e-mail ontvangen");
|
|
59
|
+
qc.invalidateQueries({ queryKey: ["mailbox-messages"] });
|
|
60
|
+
qc.invalidateQueries({ queryKey: ["mailbox-proposals"] });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
/* stille fout — backfill vangt het later op */
|
|
65
|
+
}
|
|
66
|
+
})
|
|
67
|
+
.subscribe();
|
|
68
|
+
return () => {
|
|
69
|
+
void supabase.removeChannel(channel);
|
|
70
|
+
};
|
|
71
|
+
}, [activeId, fetchIngest, qc]);
|
|
72
|
+
// Backfill bij eerste mount + iedere 60s (vangt gemiste events op)
|
|
73
|
+
const didInitialBackfill = useRef(false);
|
|
74
|
+
const backfillMut = useMutation({
|
|
75
|
+
mutationFn: async () => {
|
|
76
|
+
try {
|
|
77
|
+
return await fetchBackfill();
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// 401's (token verlopen) en tijdelijke fouten stil opvangen
|
|
81
|
+
return { ok: false, inserted: 0 };
|
|
82
|
+
}
|
|
83
|
+
},
|
|
26
84
|
onSuccess: (res) => {
|
|
27
|
-
if (res?.ok) {
|
|
28
|
-
const ins = res.inserted ?? 0;
|
|
29
|
-
const app = res.autoApproved ?? 0;
|
|
30
|
-
if (ins === 0)
|
|
31
|
-
toast.success("Geen nieuwe e-mails");
|
|
32
|
-
else if (app > 0)
|
|
33
|
-
toast.success(`${ins} nieuwe e-mail(s) — ${app} automatisch omgezet in bestelling`);
|
|
34
|
-
else
|
|
35
|
-
toast.success(`${ins} nieuwe e-mail(s) opgehaald`);
|
|
85
|
+
if (res?.ok && (res.inserted ?? 0) > 0) {
|
|
36
86
|
qc.invalidateQueries({ queryKey: ["mailbox-messages"] });
|
|
37
87
|
qc.invalidateQueries({ queryKey: ["mailbox-proposals"] });
|
|
38
88
|
}
|
|
39
|
-
else {
|
|
40
|
-
toast.error(res?.error ?? "Ophalen mislukt");
|
|
41
|
-
}
|
|
42
89
|
},
|
|
43
|
-
onError: (
|
|
90
|
+
onError: () => {
|
|
91
|
+
/* stille fout — volgende interval probeert opnieuw */
|
|
92
|
+
},
|
|
44
93
|
});
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
if (!activeId || didInitialBackfill.current)
|
|
96
|
+
return;
|
|
97
|
+
didInitialBackfill.current = true;
|
|
98
|
+
backfillMut.mutate();
|
|
99
|
+
const t = setInterval(() => backfillMut.mutate(), 60000);
|
|
100
|
+
return () => clearInterval(t);
|
|
101
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
102
|
+
}, [activeId]);
|
|
45
103
|
const parseMut = useMutation({
|
|
46
104
|
mutationFn: (messageId) => fetchParse({ data: { messageId } }),
|
|
47
105
|
onSuccess: (res) => {
|
|
@@ -57,5 +115,6 @@ export function MailboxInboxPage() {
|
|
|
57
115
|
onError: (e) => toast.error(e?.message ?? "Parsen mislukt"),
|
|
58
116
|
});
|
|
59
117
|
const items = Array.isArray(data?.items) ? data.items : [];
|
|
60
|
-
|
|
118
|
+
const needsReauth = active?.connected && active.needs_reauth;
|
|
119
|
+
return (_jsxs("div", { className: "p-6 space-y-6", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [_jsxs("h1", { className: "text-2xl font-semibold flex items-center gap-2", children: [_jsx(Mail, { className: "h-6 w-6 text-primary" }), " Inbox"] }), _jsx("p", { className: "text-muted-foreground text-sm mt-1", children: "Binnenkomende bestel-e-mails \u2014 geleverd door de E-mail Authenticatie module" })] }), _jsxs(Button, { variant: "outline", onClick: () => backfillMut.mutate(), disabled: backfillMut.isPending || !active?.connected, title: "Haal achterstallige events op", children: [_jsx(RefreshCw, { className: `h-4 w-4 mr-2 ${backfillMut.isPending ? "animate-spin" : ""}` }), "Synchroniseer"] })] }), activeLoaded && !active?.connected ? (_jsx(Card, { children: _jsxs(CardContent, { className: "p-4 flex items-start gap-3 text-sm", children: [_jsx(AlertCircle, { className: "h-4 w-4 text-destructive mt-0.5" }), _jsxs("div", { className: "flex-1", children: [_jsx("div", { className: "font-medium", children: "Nog geen e-mailadres gekoppeld" }), _jsxs("div", { className: "text-muted-foreground", children: ["Koppel in de module ", _jsx("strong", { children: "E-mail Authenticatie" }), " een adres met doeleinde", " ", _jsx("code", { children: "orders" }), " en richting ", _jsx("code", { children: "receive" }), "."] })] }), _jsx(Button, { asChild: true, variant: "outline", size: "sm", children: _jsxs("a", { href: AUTH_MODULE_URL, target: "_blank", rel: "noreferrer", children: ["Open module ", _jsx(ExternalLink, { className: "h-3 w-3 ml-1" })] }) })] }) })) : needsReauth ? (_jsx(Card, { className: "border-destructive", children: _jsxs(CardContent, { className: "p-4 flex items-start gap-3 text-sm", children: [_jsx(AlertCircle, { className: "h-4 w-4 text-destructive mt-0.5" }), _jsxs("div", { className: "flex-1", children: [_jsxs("div", { className: "font-medium", children: ["Heraanmelding vereist voor ", active.account_email] }), _jsx("div", { className: "text-muted-foreground", children: active.last_error ?? "De koppeling is verlopen. Log opnieuw in via de authenticatiemodule." })] }), _jsx(Button, { asChild: true, variant: "destructive", size: "sm", children: _jsxs("a", { href: `${AUTH_MODULE_URL}?focus=${active.id}`, target: "_blank", rel: "noreferrer", children: ["Opnieuw verbinden ", _jsx(ExternalLink, { className: "h-3 w-3 ml-1" })] }) })] }) })) : active?.connected ? (_jsx(Card, { children: _jsxs(CardContent, { className: "p-4 flex items-center gap-3 text-sm", children: [_jsx(Mail, { className: "h-4 w-4 text-primary" }), _jsx("span", { className: "text-muted-foreground", children: "Actieve mailbox:" }), _jsx("span", { className: "font-medium", children: active.account_email }), _jsx(Badge, { variant: "outline", className: "ml-2", children: active.provider }), active.status && active.status !== "ok" && active.status !== "verified" && (_jsx(Badge, { variant: "secondary", className: "ml-2", children: active.status }))] }) })) : null, _jsx(Card, { children: _jsx(CardContent, { className: "p-0", children: isLoading ? (_jsx("div", { className: "p-8 text-center text-muted-foreground", children: "Laden..." })) : items.length === 0 ? (_jsx("div", { className: "p-8 text-center text-muted-foreground", children: "Nog geen e-mails ontvangen. Nieuwe berichten verschijnen automatisch." })) : (_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Status" }), _jsx(TableHead, { children: "Afzender" }), _jsx(TableHead, { children: "Onderwerp" }), _jsx(TableHead, { children: "Ontvangen" }), _jsx(TableHead, { className: "text-right", children: "Actie" })] }) }), _jsx(TableBody, { children: items.map((m) => (_jsxs(TableRow, { children: [_jsx(TableCell, { children: _jsx(Badge, { variant: STATUS_VARIANT[m.status] ?? "secondary", children: m.status }) }), _jsxs(TableCell, { children: [_jsx("div", { className: "text-sm font-medium", children: m.from_name || m.from_email }), m.from_name && _jsx("div", { className: "text-xs text-muted-foreground", children: m.from_email })] }), _jsx(TableCell, { className: "max-w-md truncate", children: m.subject || "(geen onderwerp)" }), _jsx(TableCell, { className: "text-sm text-muted-foreground", children: m.received_at ? new Date(m.received_at).toLocaleString("nl-NL") : "-" }), _jsx(TableCell, { className: "text-right", children: m.status !== "converted" && (_jsxs(Button, { size: "sm", variant: "outline", disabled: parseMut.isPending, onClick: () => parseMut.mutate(m.id), children: [_jsx(Sparkles, { className: "h-3 w-3 mr-1" }), m.status === "parsed" ? "Opnieuw parsen" : "Parse"] })) })] }, m.id))) })] })) }) })] }));
|
|
61
120
|
}
|
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;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGvD,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,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"}
|
package/dist-lib/index.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
// src/index.ts — MODULE CONTRACT (Mailbox bestellingen)
|
|
3
3
|
// ============================================================================
|
|
4
4
|
import { Mail, Inbox, ClipboardCheck, CheckCircle2 } from "lucide-react";
|
|
5
|
-
import { ImapAccountsCard } from "./components/settings/ImapAccountsCard";
|
|
6
5
|
import { MailboxOrderTemplateCard } from "./components/settings/MailboxOrderTemplateCard";
|
|
7
6
|
export * from "./_core-safelist";
|
|
8
7
|
export { MailboxInboxPage } from "./components/MailboxInboxPage";
|
|
@@ -12,7 +11,7 @@ export { MailboxProcessedPage } from "./components/MailboxProcessedPage";
|
|
|
12
11
|
export const mailboxOrdersModule = {
|
|
13
12
|
id: "mailbox_orders",
|
|
14
13
|
name: "Mailbox bestellingen",
|
|
15
|
-
version: "1.
|
|
14
|
+
version: "1.2.0",
|
|
16
15
|
nav: {
|
|
17
16
|
label: "Mailbox",
|
|
18
17
|
href: "/mailbox-orders",
|
|
@@ -24,7 +23,6 @@ export const mailboxOrdersModule = {
|
|
|
24
23
|
],
|
|
25
24
|
},
|
|
26
25
|
settingsCards: [
|
|
27
|
-
{ component: ImapAccountsCard, order: 5 },
|
|
28
26
|
{ component: MailboxOrderTemplateCard, order: 20 },
|
|
29
27
|
],
|
|
30
28
|
};
|