@flowselections/floriday-authenticatie-module 1.0.16 → 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.
Files changed (64) hide show
  1. package/dist-lib/components/floriday/FlorydayConnectionPage.d.ts.map +1 -1
  2. package/dist-lib/components/floriday/FlorydayConnectionPage.js +2 -1
  3. package/dist-lib/components/settings/FloricodeSettingsCard.d.ts +2 -0
  4. package/dist-lib/components/settings/FloricodeSettingsCard.d.ts.map +1 -0
  5. package/dist-lib/components/settings/FloricodeSettingsCard.js +235 -0
  6. package/dist-lib/components/settings/FlorydaySettingsCard.js +1 -1
  7. package/dist-lib/index.d.ts.map +1 -1
  8. package/dist-lib/index.js +2 -0
  9. package/dist-lib/integrations/supabase/auth-middleware.d.ts +484 -3
  10. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  11. package/dist-lib/integrations/supabase/client.d.ts +484 -3
  12. package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
  13. package/dist-lib/integrations/supabase/client.server.d.ts +484 -3
  14. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  15. package/dist-lib/integrations/supabase/types.d.ts +492 -3
  16. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  17. package/dist-lib/lib/floricode-credentials.server.d.ts +21 -0
  18. package/dist-lib/lib/floricode-credentials.server.d.ts.map +1 -0
  19. package/dist-lib/lib/floricode-credentials.server.js +158 -0
  20. package/dist-lib/lib/floricode-product-features.d.ts.map +1 -1
  21. package/dist-lib/lib/floricode-product-features.js +19 -33
  22. package/dist-lib/lib/floricode-regulatory-features.d.ts.map +1 -1
  23. package/dist-lib/lib/floricode-regulatory-features.js +51 -41
  24. package/dist-lib/lib/floricode-sync.server.d.ts +35 -0
  25. package/dist-lib/lib/floricode-sync.server.d.ts.map +1 -0
  26. package/dist-lib/lib/floricode-sync.server.js +211 -0
  27. package/dist-lib/lib/floricode.functions.d.ts +78555 -0
  28. package/dist-lib/lib/floricode.functions.d.ts.map +1 -0
  29. package/dist-lib/lib/floricode.functions.js +178 -0
  30. package/dist-lib/lib/floriday-auction-letters.functions.d.ts +484 -3
  31. package/dist-lib/lib/floriday-auction-letters.functions.d.ts.map +1 -1
  32. package/dist-lib/lib/floriday-auto-process.server.d.ts +34 -0
  33. package/dist-lib/lib/floriday-auto-process.server.d.ts.map +1 -0
  34. package/dist-lib/lib/floriday-auto-process.server.js +365 -0
  35. package/dist-lib/lib/floriday-fulfillment-lookup.server.d.ts +19 -0
  36. package/dist-lib/lib/floriday-fulfillment-lookup.server.d.ts.map +1 -0
  37. package/dist-lib/lib/floriday-fulfillment-lookup.server.js +130 -0
  38. package/dist-lib/lib/floriday-gateway-auth.d.ts +24 -0
  39. package/dist-lib/lib/floriday-gateway-auth.d.ts.map +1 -0
  40. package/dist-lib/lib/floriday-gateway-auth.js +127 -0
  41. package/dist-lib/lib/floriday-labels.functions.d.ts +484 -3
  42. package/dist-lib/lib/floriday-labels.functions.d.ts.map +1 -1
  43. package/dist-lib/lib/floriday-labels.functions.js +3 -2
  44. package/dist-lib/lib/floriday-public.functions.d.ts +2904 -18
  45. package/dist-lib/lib/floriday-public.functions.d.ts.map +1 -1
  46. package/dist-lib/lib/floriday-rate-limit.server.d.ts +21 -0
  47. package/dist-lib/lib/floriday-rate-limit.server.d.ts.map +1 -0
  48. package/dist-lib/lib/floriday-rate-limit.server.js +75 -0
  49. package/dist-lib/lib/floriday-stickers.functions.d.ts +484 -3
  50. package/dist-lib/lib/floriday-stickers.functions.d.ts.map +1 -1
  51. package/dist-lib/lib/floriday-sync.functions.d.ts +15972 -99
  52. package/dist-lib/lib/floriday-sync.functions.d.ts.map +1 -1
  53. package/dist-lib/lib/floriday-writes.functions.d.ts +2952 -42
  54. package/dist-lib/lib/floriday-writes.functions.d.ts.map +1 -1
  55. package/dist-lib/lib/floriday-writes.functions.js +29 -4
  56. package/dist-lib/lib/floriday.functions.d.ts +9054 -198
  57. package/dist-lib/lib/floriday.functions.d.ts.map +1 -1
  58. package/dist-lib/lib/floriday.functions.js +39 -4
  59. package/dist-lib/lib/planning-helpers.d.ts +30 -0
  60. package/dist-lib/lib/planning-helpers.d.ts.map +1 -0
  61. package/dist-lib/lib/planning-helpers.js +62 -0
  62. package/package.json +5 -3
  63. package/public/flowselections-assets/floriday-authenticatie/floricode-logo.png +0 -0
  64. package/public/flowselections-assets/floriday-authenticatie/floriday-logo.png +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"FlorydayConnectionPage.d.ts","sourceRoot":"","sources":["../../../src/components/floriday/FlorydayConnectionPage.tsx"],"names":[],"mappings":"AAEA,wBAAgB,sBAAsB,4CAYrC"}
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,2 @@
1
+ export declare function FloricodeSettingsCard(): import("react/jsx-runtime").JSX.Element;
2
+ //# sourceMappingURL=FloricodeSettingsCard.d.ts.map
@@ -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
+ }
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState, useEffect } from "react";
3
- const florydayLogo = "/flowselections-assets/Floriday Authenticatie/floriday-logo.png";
3
+ const florydayLogo = "/flowselections-assets/floriday-authenticatie/floriday-logo.png";
4
4
  import { ChevronDown } from "lucide-react";
5
5
  import { useServerFn } from "@tanstack/react-start";
6
6
  import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
@@ -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;AAGvD,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,UAczC,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
  };