@flowselections/floriday-authenticatie-module 1.0.17 → 1.0.18
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/floriday/FlorydayConnectionPage.d.ts.map +1 -1
- package/dist-lib/components/floriday/FlorydayConnectionPage.js +2 -1
- package/dist-lib/components/settings/FloricodeSettingsCard.d.ts +2 -0
- package/dist-lib/components/settings/FloricodeSettingsCard.d.ts.map +1 -0
- package/dist-lib/components/settings/FloricodeSettingsCard.js +235 -0
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +2 -0
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +484 -3
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.d.ts +484 -3
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +484 -3
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +492 -3
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/floricode-credentials.server.d.ts +21 -0
- package/dist-lib/lib/floricode-credentials.server.d.ts.map +1 -0
- package/dist-lib/lib/floricode-credentials.server.js +158 -0
- package/dist-lib/lib/floricode-product-features.d.ts.map +1 -1
- package/dist-lib/lib/floricode-product-features.js +19 -33
- package/dist-lib/lib/floricode-regulatory-features.d.ts.map +1 -1
- package/dist-lib/lib/floricode-regulatory-features.js +51 -41
- package/dist-lib/lib/floricode-sync.server.d.ts +35 -0
- package/dist-lib/lib/floricode-sync.server.d.ts.map +1 -0
- package/dist-lib/lib/floricode-sync.server.js +211 -0
- package/dist-lib/lib/floricode.functions.d.ts +78555 -0
- package/dist-lib/lib/floricode.functions.d.ts.map +1 -0
- package/dist-lib/lib/floricode.functions.js +178 -0
- package/dist-lib/lib/floriday-auction-letters.functions.d.ts +484 -3
- package/dist-lib/lib/floriday-auction-letters.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-auto-process.server.d.ts +34 -0
- package/dist-lib/lib/floriday-auto-process.server.d.ts.map +1 -0
- package/dist-lib/lib/floriday-auto-process.server.js +365 -0
- package/dist-lib/lib/floriday-fulfillment-lookup.server.d.ts +19 -0
- package/dist-lib/lib/floriday-fulfillment-lookup.server.d.ts.map +1 -0
- package/dist-lib/lib/floriday-fulfillment-lookup.server.js +130 -0
- package/dist-lib/lib/floriday-gateway-auth.d.ts +24 -0
- package/dist-lib/lib/floriday-gateway-auth.d.ts.map +1 -0
- package/dist-lib/lib/floriday-gateway-auth.js +127 -0
- package/dist-lib/lib/floriday-labels.functions.d.ts +484 -3
- package/dist-lib/lib/floriday-labels.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-labels.functions.js +3 -2
- package/dist-lib/lib/floriday-public.functions.d.ts +2904 -18
- package/dist-lib/lib/floriday-public.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-rate-limit.server.d.ts +21 -0
- package/dist-lib/lib/floriday-rate-limit.server.d.ts.map +1 -0
- package/dist-lib/lib/floriday-rate-limit.server.js +75 -0
- package/dist-lib/lib/floriday-stickers.functions.d.ts +484 -3
- package/dist-lib/lib/floriday-stickers.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-sync.functions.d.ts +15972 -99
- package/dist-lib/lib/floriday-sync.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-writes.functions.d.ts +2952 -42
- package/dist-lib/lib/floriday-writes.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-writes.functions.js +29 -4
- package/dist-lib/lib/floriday.functions.d.ts +9054 -198
- package/dist-lib/lib/floriday.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday.functions.js +39 -4
- package/dist-lib/lib/planning-helpers.d.ts +30 -0
- package/dist-lib/lib/planning-helpers.d.ts.map +1 -0
- package/dist-lib/lib/planning-helpers.js +62 -0
- package/package.json +3 -2
- package/public/flowselections-assets/floriday-authenticatie/floricode-logo.png +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FlorydayConnectionPage.d.ts","sourceRoot":"","sources":["../../../src/components/floriday/FlorydayConnectionPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FlorydayConnectionPage.d.ts","sourceRoot":"","sources":["../../../src/components/floriday/FlorydayConnectionPage.tsx"],"names":[],"mappings":"AAGA,wBAAgB,sBAAsB,4CAarC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { FlorydaySettingsCard } from "../settings/FlorydaySettingsCard";
|
|
3
|
+
import { FloricodeSettingsCard } from "../settings/FloricodeSettingsCard";
|
|
3
4
|
export function FlorydayConnectionPage() {
|
|
4
|
-
return (_jsxs("main", { className: "p-6 max-w-4xl mx-auto space-y-6", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-bold", children: "Floriday koppeling" }), _jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Verbind je Floriday-account om automatisch gegevens uit te wisselen met het platform." })] }), _jsx(FlorydaySettingsCard, {})] }));
|
|
5
|
+
return (_jsxs("main", { className: "p-6 max-w-4xl mx-auto space-y-6", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-bold", children: "Floriday koppeling" }), _jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Verbind je Floriday-account om automatisch gegevens uit te wisselen met het platform." })] }), _jsx(FlorydaySettingsCard, {}), _jsx(FloricodeSettingsCard, {})] }));
|
|
5
6
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FloricodeSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/FloricodeSettingsCard.tsx"],"names":[],"mappings":"AAuDA,wBAAgB,qBAAqB,4CA4EpC"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { ChevronDown } from "lucide-react";
|
|
4
|
+
import { useServerFn } from "@tanstack/react-start";
|
|
5
|
+
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
6
|
+
import { Card, Button, Input, Label, Badge, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, toast, } from "@flowselections/core";
|
|
7
|
+
import { getFloricodeSettings, saveFloricodeCredentials, clearFloricodeCredentials, testFloricodeConnection, getFloricodeSyncStatus, triggerFloricodeResourceSync, resetFloricodeResourceCursor, } from "../../lib/floricode.functions";
|
|
8
|
+
const floricodeLogo = "/flowselections-assets/floriday-authenticatie/floricode-logo.png";
|
|
9
|
+
function formatDate(iso) {
|
|
10
|
+
if (!iso)
|
|
11
|
+
return "—";
|
|
12
|
+
try {
|
|
13
|
+
return new Date(iso).toLocaleString("nl-NL", { dateStyle: "short", timeStyle: "short" });
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return iso;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function timeAgo(iso) {
|
|
20
|
+
if (!iso)
|
|
21
|
+
return "Nog nooit";
|
|
22
|
+
const diff = Date.now() - new Date(iso).getTime();
|
|
23
|
+
if (Number.isNaN(diff))
|
|
24
|
+
return "—";
|
|
25
|
+
const min = Math.floor(diff / 60000);
|
|
26
|
+
if (min < 1)
|
|
27
|
+
return "Zojuist";
|
|
28
|
+
if (min < 60)
|
|
29
|
+
return `${min} min geleden`;
|
|
30
|
+
const hr = Math.floor(min / 60);
|
|
31
|
+
if (hr < 24)
|
|
32
|
+
return `${hr} uur geleden`;
|
|
33
|
+
const days = Math.floor(hr / 24);
|
|
34
|
+
return `${days} dag${days === 1 ? "" : "en"} geleden`;
|
|
35
|
+
}
|
|
36
|
+
export function FloricodeSettingsCard() {
|
|
37
|
+
const [open, setOpen] = useState(false);
|
|
38
|
+
const getSettings = useServerFn(getFloricodeSettings);
|
|
39
|
+
const { data: settings } = useQuery({
|
|
40
|
+
queryKey: ["floricode-settings"],
|
|
41
|
+
queryFn: () => getSettings(),
|
|
42
|
+
});
|
|
43
|
+
const configured = Boolean(settings?.isConfigured);
|
|
44
|
+
const connected = configured && settings?.lastTokenTestOk !== false;
|
|
45
|
+
return (_jsxs(Card, { className: "overflow-hidden border-border/60", children: [_jsxs("button", { type: "button", onClick: () => setOpen((o) => !o), className: "w-full flex items-center gap-3 px-5 py-4 text-left hover:bg-muted/40 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset", "aria-expanded": open, children: [_jsx("div", { className: "h-9 w-9 rounded-lg bg-muted/60 flex items-center justify-center shrink-0 overflow-hidden", children: _jsx("img", { src: floricodeLogo, alt: "Floricode", className: "h-6 w-6 object-contain", onError: (e) => {
|
|
46
|
+
e.currentTarget.style.display = "none";
|
|
47
|
+
const parent = e.currentTarget.parentElement;
|
|
48
|
+
if (parent && !parent.querySelector("[data-fallback]")) {
|
|
49
|
+
const span = document.createElement("span");
|
|
50
|
+
span.textContent = "Fc";
|
|
51
|
+
span.dataset.fallback = "1";
|
|
52
|
+
span.className = "text-xs font-semibold text-muted-foreground";
|
|
53
|
+
parent.appendChild(span);
|
|
54
|
+
}
|
|
55
|
+
} }) }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("h3", { className: "font-semibold text-sm truncate", children: "Floricode koppeling" }), _jsxs("div", { className: "flex items-center gap-2 flex-wrap mt-1", children: [_jsx(Badge, { variant: configured ? "default" : "secondary", className: "text-[10px] tracking-wide", children: configured ? "Ingesteld" : "Niet ingesteld" }), _jsx(StatusIndicator, { connected: connected, configured: configured })] }), _jsx("p", { className: "text-xs text-muted-foreground mt-1 truncate", children: "Verbind je Floricode-account om automatisch gegevens uit te wisselen met het platform." })] }), _jsx(ChevronDown, { className: `h-4 w-4 text-muted-foreground shrink-0 transition-transform ${open ? "rotate-180" : ""}` })] }), open && (_jsxs("div", { className: "border-t border-border/60 px-5 py-5 space-y-6 bg-muted/20", children: [_jsx(CredentialsBlock, { settings: settings }), _jsx(TestBlock, { settings: settings }), _jsx(SyncBlock, { configured: configured }), _jsx("div", { className: "pt-2 border-t border-border/60", children: _jsx("a", { href: "https://developer.floricode.com/", target: "_blank", rel: "noopener noreferrer", className: "text-xs text-primary hover:underline inline-flex items-center gap-1", children: "Waar vind ik mijn Floricode-inloggegevens?" }) })] }))] }));
|
|
56
|
+
}
|
|
57
|
+
function StatusIndicator({ connected, configured }) {
|
|
58
|
+
const label = !configured ? "Nog niet gekoppeld" : connected ? "Verbonden" : "Fout";
|
|
59
|
+
const color = !configured ? "bg-muted-foreground/40" : connected ? "bg-emerald-500" : "bg-red-500";
|
|
60
|
+
return (_jsxs("span", { className: "inline-flex items-center gap-1.5 text-xs text-muted-foreground", children: [_jsx("span", { "aria-label": label, className: `h-2 w-2 rounded-full ${color}` }), label] }));
|
|
61
|
+
}
|
|
62
|
+
function StepBlock({ number, title, description, children, }) {
|
|
63
|
+
return (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "h-6 w-6 rounded-full bg-primary text-primary-foreground text-xs font-semibold flex items-center justify-center shrink-0", children: number }), _jsx("h4", { className: "font-medium text-sm", children: title })] }), description && _jsx("p", { className: "text-xs text-muted-foreground pl-8", children: description }), _jsx("div", { className: "pl-8", children: children })] }));
|
|
64
|
+
}
|
|
65
|
+
function CredentialsBlock({ settings }) {
|
|
66
|
+
const qc = useQueryClient();
|
|
67
|
+
const saveCreds = useServerFn(saveFloricodeCredentials);
|
|
68
|
+
const clearCreds = useServerFn(clearFloricodeCredentials);
|
|
69
|
+
const [clientId, setClientId] = useState("");
|
|
70
|
+
const [clientSecret, setClientSecret] = useState("");
|
|
71
|
+
const configured = Boolean(settings?.isConfigured);
|
|
72
|
+
const saveMut = useMutation({
|
|
73
|
+
mutationFn: () => saveCreds({
|
|
74
|
+
data: {
|
|
75
|
+
clientId: clientId || settings?.clientId || "",
|
|
76
|
+
clientSecret,
|
|
77
|
+
},
|
|
78
|
+
}),
|
|
79
|
+
onSuccess: () => {
|
|
80
|
+
toast.success("Floricode-inloggegevens opgeslagen");
|
|
81
|
+
setClientId("");
|
|
82
|
+
setClientSecret("");
|
|
83
|
+
qc.invalidateQueries({ queryKey: ["floricode-settings"] });
|
|
84
|
+
},
|
|
85
|
+
onError: (e) => toast.error(String(e?.message ?? e)),
|
|
86
|
+
});
|
|
87
|
+
const clearMut = useMutation({
|
|
88
|
+
mutationFn: () => clearCreds(),
|
|
89
|
+
onSuccess: () => {
|
|
90
|
+
toast.success("Floricode-koppeling verwijderd");
|
|
91
|
+
qc.invalidateQueries({ queryKey: ["floricode-settings"] });
|
|
92
|
+
qc.invalidateQueries({ queryKey: ["floricode-sync-status"] });
|
|
93
|
+
},
|
|
94
|
+
onError: (e) => toast.error(String(e?.message ?? e)),
|
|
95
|
+
});
|
|
96
|
+
return (_jsx(StepBlock, { number: 1, title: "Vul verbindingsgegevens in", children: _jsxs("div", { className: "rounded-lg border border-border/60 bg-card p-4 space-y-4", children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [_jsx("h4", { className: "font-medium text-sm", children: "Verbindingsgegevens" }), configured ? (_jsx(Badge, { variant: "default", className: "text-[10px]", children: "Actief" })) : (_jsx(Badge, { variant: "secondary", className: "text-[10px]", children: "Nog niet gekoppeld" }))] }), configured && (_jsxs(AlertDialog, { children: [_jsx(AlertDialogTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "sm", disabled: clearMut.isPending, children: "Verwijderen" }) }), _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Koppeling verwijderen?" }), _jsx(AlertDialogDescription, { children: "Hiermee worden de opgeslagen Floricode-inloggegevens permanent verwijderd. Andere koppelingen die hiervan afhankelijk zijn werken daarna niet meer totdat je opnieuw verbinding maakt." })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: "Annuleren" }), _jsx(AlertDialogAction, { onClick: () => clearMut.mutate(), children: "Verwijderen" })] })] })] }))] }), _jsxs("div", { className: "grid gap-4", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "floricode-client-id", className: "text-xs", children: "Client ID" }), _jsx(Input, { id: "floricode-client-id", value: clientId, onChange: (e) => setClientId(e.target.value), placeholder: configured ? settings?.clientId ?? "••••••••" : "Floricode Client ID", className: configured ? "font-mono placeholder:font-mono placeholder:text-foreground/60" : undefined, autoComplete: "off" }), _jsx("p", { className: "text-[11px] text-muted-foreground", children: "Te vinden in je Floricode API-instellingen." }), configured && (_jsx("p", { className: "text-[11px] text-muted-foreground", children: "Laat leeg als je deze waarde niet wilt wijzigen." }))] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "floricode-client-secret", className: "text-xs", children: "Client Secret" }), _jsx(Input, { id: "floricode-client-secret", type: "password", value: clientSecret, onChange: (e) => setClientSecret(e.target.value), placeholder: configured
|
|
97
|
+
? settings?.secretLast4
|
|
98
|
+
? `••••••••${settings.secretLast4}`
|
|
99
|
+
: "••••••••"
|
|
100
|
+
: "Floricode Client Secret", className: configured ? "placeholder:text-foreground/60" : undefined, autoComplete: "off" }), _jsx("p", { className: "text-[11px] text-muted-foreground", children: "Houd deze sleutel priv\u00E9." }), configured && (_jsx("p", { className: "text-[11px] text-muted-foreground", children: "Laat leeg als je deze waarde niet wilt wijzigen." }))] })] }), _jsx("div", { children: _jsx(Button, { size: "sm", onClick: () => saveMut.mutate(), disabled: saveMut.isPending ||
|
|
101
|
+
(!clientSecret.trim() && !clientId.trim()), children: saveMut.isPending
|
|
102
|
+
? "Opslaan…"
|
|
103
|
+
: configured
|
|
104
|
+
? "Wijzigingen opslaan"
|
|
105
|
+
: "Koppeling opslaan" }) })] }) }));
|
|
106
|
+
}
|
|
107
|
+
function TestBlock({ settings }) {
|
|
108
|
+
const qc = useQueryClient();
|
|
109
|
+
const testConn = useServerFn(testFloricodeConnection);
|
|
110
|
+
const configured = Boolean(settings?.isConfigured);
|
|
111
|
+
const testMut = useMutation({
|
|
112
|
+
mutationFn: () => testConn(),
|
|
113
|
+
onSuccess: (r) => {
|
|
114
|
+
if (r?.ok)
|
|
115
|
+
toast.success("Verbinding met Floricode geslaagd");
|
|
116
|
+
else
|
|
117
|
+
toast.error(`Verbinding mislukt: ${r?.error ?? "onbekend"}`);
|
|
118
|
+
qc.invalidateQueries({ queryKey: ["floricode-settings"] });
|
|
119
|
+
},
|
|
120
|
+
onError: (e) => toast.error(String(e?.message ?? e)),
|
|
121
|
+
});
|
|
122
|
+
return (_jsx(StepBlock, { number: 2, title: "Test de verbinding", description: "Controleer of je gegevens correct zijn en of de koppeling werkt.", children: _jsxs("div", { className: "space-y-2", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: () => testMut.mutate(), disabled: !configured || testMut.isPending, children: testMut.isPending ? "Testen…" : "Verbinding testen" }), settings?.lastTokenTestAt && (_jsxs("p", { className: "text-[11px] text-muted-foreground", children: ["Laatste test: ", formatDate(settings.lastTokenTestAt), " \u2014", " ", settings.lastTokenTestOk
|
|
123
|
+
? "geslaagd"
|
|
124
|
+
: `mislukt: ${settings.lastTokenTestError ?? "onbekend"}`] }))] }) }));
|
|
125
|
+
}
|
|
126
|
+
function classifyRow(row) {
|
|
127
|
+
const msg = String(row.errorMessage ?? "");
|
|
128
|
+
const notAvailable = /404|niet beschikbaar|niet geautoriseerd|401|403/.test(msg);
|
|
129
|
+
const stale = row.lastSyncAt
|
|
130
|
+
? Date.now() - new Date(row.lastSyncAt).getTime() > 30 * 60000
|
|
131
|
+
: false;
|
|
132
|
+
if (row.status === "error" && notAvailable) {
|
|
133
|
+
return {
|
|
134
|
+
key: "unavailable",
|
|
135
|
+
label: "Niet beschikbaar",
|
|
136
|
+
tone: "text-amber-700 bg-amber-50 border-amber-200",
|
|
137
|
+
dot: "bg-amber-500",
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
if (row.status === "error") {
|
|
141
|
+
return {
|
|
142
|
+
key: "error",
|
|
143
|
+
label: "Fout",
|
|
144
|
+
tone: "text-red-700 bg-red-50 border-red-200",
|
|
145
|
+
dot: "bg-red-500",
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
if (row.status === "running" && stale) {
|
|
149
|
+
return {
|
|
150
|
+
key: "hanging",
|
|
151
|
+
label: "Hangt",
|
|
152
|
+
tone: "text-orange-700 bg-orange-50 border-orange-200",
|
|
153
|
+
dot: "bg-orange-500 animate-pulse",
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
if (row.status === "running") {
|
|
157
|
+
return {
|
|
158
|
+
key: "running",
|
|
159
|
+
label: "Bezig",
|
|
160
|
+
tone: "text-blue-700 bg-blue-50 border-blue-200",
|
|
161
|
+
dot: "bg-blue-500 animate-pulse",
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
if (row.status === "ok") {
|
|
165
|
+
return {
|
|
166
|
+
key: "ok",
|
|
167
|
+
label: "Actueel",
|
|
168
|
+
tone: "text-emerald-700 bg-emerald-50 border-emerald-200",
|
|
169
|
+
dot: "bg-emerald-500",
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
key: "pending",
|
|
174
|
+
label: row.status ?? "In wachtrij",
|
|
175
|
+
tone: "text-muted-foreground bg-muted/60 border-border/60",
|
|
176
|
+
dot: "bg-muted-foreground/50",
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
const STATUS_ORDER = {
|
|
180
|
+
error: 0,
|
|
181
|
+
hanging: 1,
|
|
182
|
+
running: 2,
|
|
183
|
+
pending: 3,
|
|
184
|
+
unavailable: 4,
|
|
185
|
+
ok: 5,
|
|
186
|
+
};
|
|
187
|
+
function SyncBlock({ configured }) {
|
|
188
|
+
const qc = useQueryClient();
|
|
189
|
+
const getStatus = useServerFn(getFloricodeSyncStatus);
|
|
190
|
+
const syncOne = useServerFn(triggerFloricodeResourceSync);
|
|
191
|
+
const resetOne = useServerFn(resetFloricodeResourceCursor);
|
|
192
|
+
const { data: rows = [] } = useQuery({
|
|
193
|
+
queryKey: ["floricode-sync-status"],
|
|
194
|
+
queryFn: () => getStatus(),
|
|
195
|
+
refetchInterval: 10000,
|
|
196
|
+
refetchIntervalInBackground: true,
|
|
197
|
+
});
|
|
198
|
+
const syncMut = useMutation({
|
|
199
|
+
mutationFn: (resource) => syncOne({ data: { resource } }),
|
|
200
|
+
onSuccess: (r) => {
|
|
201
|
+
toast.success(r?.skipped
|
|
202
|
+
? String(r?.message ?? `${r?.resource}: overgeslagen`)
|
|
203
|
+
: `${r?.resource}: ${r?.upserted ?? 0} rijen bijgewerkt`);
|
|
204
|
+
qc.invalidateQueries({ queryKey: ["floricode-sync-status"] });
|
|
205
|
+
},
|
|
206
|
+
onError: (e) => toast.error(String(e?.message ?? e)),
|
|
207
|
+
});
|
|
208
|
+
const resetMut = useMutation({
|
|
209
|
+
mutationFn: (resource) => resetOne({ data: { resource } }),
|
|
210
|
+
onSuccess: (r) => {
|
|
211
|
+
toast.success(`${r?.resource}: volledige scan wordt opnieuw opgestart`);
|
|
212
|
+
qc.invalidateQueries({ queryKey: ["floricode-sync-status"] });
|
|
213
|
+
},
|
|
214
|
+
onError: (e) => toast.error(String(e?.message ?? e)),
|
|
215
|
+
});
|
|
216
|
+
const classified = rows
|
|
217
|
+
.map((r) => ({ row: r, meta: classifyRow(r) }))
|
|
218
|
+
.sort((a, b) => {
|
|
219
|
+
const d = (STATUS_ORDER[a.meta.key] ?? 9) - (STATUS_ORDER[b.meta.key] ?? 9);
|
|
220
|
+
return d !== 0 ? d : a.row.resource.localeCompare(b.row.resource);
|
|
221
|
+
});
|
|
222
|
+
return (_jsx(StepBlock, { number: 3, title: "Gegevens up-to-date houden", description: "We halen je Floricode-gegevens automatisch op en bewaren ze in je werkomgeving. Zo werkt alles effici\u00EBnt & snel.", children: _jsxs("div", { className: "space-y-3", children: [classified.length === 0 && (_jsx("p", { className: "text-xs text-muted-foreground", children: "Nog geen synchronisatiegegevens beschikbaar." })), classified.map(({ row, meta }) => {
|
|
223
|
+
const hasProblem = meta.key === "error" ||
|
|
224
|
+
meta.key === "unavailable" ||
|
|
225
|
+
meta.key === "hanging";
|
|
226
|
+
return (_jsxs("div", { className: "rounded-lg border border-border/60 bg-card p-4", children: [_jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_auto] items-start gap-3 sm:flex sm:items-center sm:justify-between", children: [_jsxs("div", { className: "min-w-0", children: [_jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [_jsx("h5", { className: "font-medium text-sm truncate", children: row.resource }), hasProblem && (_jsxs("span", { className: `inline-flex items-center gap-1.5 rounded-full border px-2 py-0.5 text-[10px] font-medium ${meta.tone}`, children: [_jsx("span", { className: `h-1.5 w-1.5 rounded-full ${meta.dot}` }), meta.label] }))] }), _jsx("p", { className: "text-[11px] text-muted-foreground mt-0.5", children: "Wordt automatisch bijgewerkt op de achtergrond." })] }), _jsx(Button, { variant: "outline", size: "sm", className: "shrink-0", disabled: !configured || syncMut.isPending, onClick: () => syncMut.mutate(row.resource), children: syncMut.isPending && syncMut.variables === row.resource
|
|
227
|
+
? "Bezig…"
|
|
228
|
+
: "Nu bijwerken" })] }), _jsxs("div", { className: "mt-3 grid grid-cols-1 sm:grid-cols-2 gap-2", children: [_jsx(MetricTile, { label: "Laatst bijgewerkt", value: timeAgo(row.lastSyncAt) }), _jsx(MetricTile, { label: "Aantal records", value: (row.rowCount ?? 0).toLocaleString("nl-NL") })] }), hasProblem && (_jsxs("div", { className: "mt-3 flex items-center justify-between gap-3 flex-wrap", children: [row.errorMessage ? (_jsx("p", { className: `text-[11px] break-words ${meta.key === "unavailable"
|
|
229
|
+
? "text-amber-700"
|
|
230
|
+
: "text-red-700"}`, children: row.errorMessage })) : (_jsx("span", {})), _jsxs(AlertDialog, { children: [_jsx(AlertDialogTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "sm", className: "text-xs", disabled: !configured || resetMut.isPending, children: "Opnieuw beginnen" }) }), _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Volledige scan opnieuw uitvoeren?" }), _jsx(AlertDialogDescription, { children: "We beginnen de synchronisatie helemaal opnieuw. Bestaande gegevens blijven zichtbaar en worden ververst zodra ze binnen zijn." })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: "Annuleren" }), _jsx(AlertDialogAction, { onClick: () => resetMut.mutate(row.resource), children: "Opnieuw beginnen" })] })] })] })] }))] }, row.resource));
|
|
231
|
+
})] }) }));
|
|
232
|
+
}
|
|
233
|
+
function MetricTile({ label, value, sub }) {
|
|
234
|
+
return (_jsxs("div", { className: "rounded-md bg-muted/50 px-3 py-2 min-w-0", children: [_jsx("p", { className: "text-[10px] uppercase tracking-wide text-muted-foreground truncate", children: label }), _jsx("p", { className: "text-sm font-semibold mt-0.5 truncate", title: value, children: value }), sub && (_jsx("p", { className: "text-[10px] text-muted-foreground mt-0.5 truncate", title: sub, children: sub }))] }));
|
|
235
|
+
}
|
package/dist-lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAIvD,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,sBAAsB,EAAE,MAAM,8CAA8C,CAAC;AACtF,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAE9C,eAAO,MAAM,2BAA2B,EAAE,UAezC,CAAC"}
|
package/dist-lib/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Plug } from "lucide-react";
|
|
2
2
|
import { FlorydaySettingsCard } from "./components/settings/FlorydaySettingsCard";
|
|
3
|
+
import { FloricodeSettingsCard } from "./components/settings/FloricodeSettingsCard";
|
|
3
4
|
export * from './_core-safelist';
|
|
4
5
|
export { FlorydayConnectionPage } from './components/floriday/FlorydayConnectionPage';
|
|
5
6
|
export * from './lib/floriday.functions';
|
|
@@ -15,5 +16,6 @@ export const floridayAuthenticatieModule = {
|
|
|
15
16
|
},
|
|
16
17
|
settingsCards: [
|
|
17
18
|
{ component: FlorydaySettingsCard, order: 10 },
|
|
19
|
+
{ component: FloricodeSettingsCard, order: 20 },
|
|
18
20
|
],
|
|
19
21
|
};
|