@flowselections/actie-mail-kwekers-erp-mathot 1.0.0

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 (75) hide show
  1. package/dist-lib/_core-safelist.d.ts +2 -0
  2. package/dist-lib/_core-safelist.d.ts.map +1 -0
  3. package/dist-lib/_core-safelist.js +15 -0
  4. package/dist-lib/components/AanbiedingsmailtjePage.d.ts +2 -0
  5. package/dist-lib/components/AanbiedingsmailtjePage.d.ts.map +1 -0
  6. package/dist-lib/components/AanbiedingsmailtjePage.js +239 -0
  7. package/dist-lib/components/ActiePage.d.ts +2 -0
  8. package/dist-lib/components/ActiePage.d.ts.map +1 -0
  9. package/dist-lib/components/ActiePage.js +173 -0
  10. package/dist-lib/components/CampagneDetail.d.ts +2 -0
  11. package/dist-lib/components/CampagneDetail.d.ts.map +1 -0
  12. package/dist-lib/components/CampagneDetail.js +61 -0
  13. package/dist-lib/components/CampagneOverzicht.d.ts +2 -0
  14. package/dist-lib/components/CampagneOverzicht.d.ts.map +1 -0
  15. package/dist-lib/components/CampagneOverzicht.js +16 -0
  16. package/dist-lib/components/DateRangePicker.d.ts +20 -0
  17. package/dist-lib/components/DateRangePicker.d.ts.map +1 -0
  18. package/dist-lib/components/DateRangePicker.js +140 -0
  19. package/dist-lib/components/RapportagePage.d.ts +2 -0
  20. package/dist-lib/components/RapportagePage.d.ts.map +1 -0
  21. package/dist-lib/components/RapportagePage.js +60 -0
  22. package/dist-lib/components/settings/AfzenderSettingsCard.d.ts +2 -0
  23. package/dist-lib/components/settings/AfzenderSettingsCard.d.ts.map +1 -0
  24. package/dist-lib/components/settings/AfzenderSettingsCard.js +30 -0
  25. package/dist-lib/components/settings/HuisstijlSettingsCard.d.ts +2 -0
  26. package/dist-lib/components/settings/HuisstijlSettingsCard.d.ts.map +1 -0
  27. package/dist-lib/components/settings/HuisstijlSettingsCard.js +30 -0
  28. package/dist-lib/components/settings/StickerSettingsCard.d.ts +2 -0
  29. package/dist-lib/components/settings/StickerSettingsCard.d.ts.map +1 -0
  30. package/dist-lib/components/settings/StickerSettingsCard.js +41 -0
  31. package/dist-lib/components/settings/TestmailCard.d.ts +2 -0
  32. package/dist-lib/components/settings/TestmailCard.d.ts.map +1 -0
  33. package/dist-lib/components/settings/TestmailCard.js +21 -0
  34. package/dist-lib/components/settings/TrackingSettingsCard.d.ts +2 -0
  35. package/dist-lib/components/settings/TrackingSettingsCard.d.ts.map +1 -0
  36. package/dist-lib/components/settings/TrackingSettingsCard.js +30 -0
  37. package/dist-lib/components/settings/UitsluitingenSettingsCard.d.ts +2 -0
  38. package/dist-lib/components/settings/UitsluitingenSettingsCard.d.ts.map +1 -0
  39. package/dist-lib/components/settings/UitsluitingenSettingsCard.js +41 -0
  40. package/dist-lib/index.d.ts +17 -0
  41. package/dist-lib/index.d.ts.map +1 -0
  42. package/dist-lib/index.js +34 -0
  43. package/dist-lib/integrations/supabase/auth-attacher.d.ts +2 -0
  44. package/dist-lib/integrations/supabase/auth-attacher.d.ts.map +1 -0
  45. package/dist-lib/integrations/supabase/auth-attacher.js +12 -0
  46. package/dist-lib/integrations/supabase/auth-middleware.d.ts +2555 -0
  47. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -0
  48. package/dist-lib/integrations/supabase/auth-middleware.js +52 -0
  49. package/dist-lib/integrations/supabase/client.d.ts +2551 -0
  50. package/dist-lib/integrations/supabase/client.d.ts.map +1 -0
  51. package/dist-lib/integrations/supabase/client.js +13 -0
  52. package/dist-lib/integrations/supabase/client.server.d.ts +2551 -0
  53. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -0
  54. package/dist-lib/integrations/supabase/client.server.js +30 -0
  55. package/dist-lib/integrations/supabase/types.d.ts +2685 -0
  56. package/dist-lib/integrations/supabase/types.d.ts.map +1 -0
  57. package/dist-lib/integrations/supabase/types.js +8 -0
  58. package/dist-lib/lib/campaigns.functions.d.ts +12881 -0
  59. package/dist-lib/lib/campaigns.functions.d.ts.map +1 -0
  60. package/dist-lib/lib/campaigns.functions.js +358 -0
  61. package/dist-lib/lib/public-offer.functions.d.ts +68 -0
  62. package/dist-lib/lib/public-offer.functions.d.ts.map +1 -0
  63. package/dist-lib/lib/public-offer.functions.js +116 -0
  64. package/dist-lib/lib/stats.functions.d.ts +5180 -0
  65. package/dist-lib/lib/stats.functions.d.ts.map +1 -0
  66. package/dist-lib/lib/stats.functions.js +63 -0
  67. package/dist-lib/lib/utils.d.ts +3 -0
  68. package/dist-lib/lib/utils.d.ts.map +1 -0
  69. package/dist-lib/lib/utils.js +5 -0
  70. package/dist-lib/lib/validationSchemas.d.ts +15 -0
  71. package/dist-lib/lib/validationSchemas.d.ts.map +1 -0
  72. package/dist-lib/lib/validationSchemas.js +25 -0
  73. package/dist-lib/styles.css +1 -0
  74. package/package.json +76 -0
  75. package/public/flowselections-assets/template-module/README.md +15 -0
@@ -0,0 +1,20 @@
1
+ export interface DateRange {
2
+ from: Date | null;
3
+ to: Date | null;
4
+ presetId: string;
5
+ label: string;
6
+ }
7
+ type PresetId = "today" | "yesterday" | "this_week" | "last_week" | "this_month" | "last_month" | "last_30" | "last_60" | "last_90" | "this_quarter" | "last_quarter" | "this_year" | "last_year" | "all" | "custom";
8
+ export declare function computePreset(id: PresetId): {
9
+ from: Date | null;
10
+ to: Date | null;
11
+ label: string;
12
+ };
13
+ export declare function DateRangePicker({ value, onChange }: {
14
+ value: DateRange;
15
+ onChange: (v: DateRange) => void;
16
+ }): import("react").JSX.Element;
17
+ export declare function loadStoredRange(): DateRange;
18
+ export declare function storeRange(r: DateRange): void;
19
+ export {};
20
+ //# sourceMappingURL=DateRangePicker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DateRangePicker.d.ts","sourceRoot":"","sources":["../../src/components/DateRangePicker.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,EAAE,EAAE,IAAI,GAAG,IAAI,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,KAAK,QAAQ,GACT,OAAO,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,GACjD,YAAY,GAAG,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAC/D,cAAc,GAAG,cAAc,GAAG,WAAW,GAAG,WAAW,GAC3D,KAAK,GAAG,QAAQ,CAAC;AA4BrB,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,GAAG;IAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAAC,EAAE,EAAE,IAAI,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAqBjG;AAeD,wBAAgB,eAAe,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,IAAI,CAAA;CAAE,+BA+E1G;AAID,wBAAgB,eAAe,IAAI,SAAS,CAuB3C;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,SAAS,QAQtC"}
@@ -0,0 +1,140 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { Button, Popover, PopoverContent, PopoverTrigger, Label } from "@flowselections/core";
4
+ import { Calendar as CalendarIcon } from "lucide-react";
5
+ const PRESETS = [
6
+ { id: "today", label: "Vandaag" },
7
+ { id: "yesterday", label: "Gisteren" },
8
+ { id: "this_week", label: "Deze week" },
9
+ { id: "last_week", label: "Vorige week" },
10
+ { id: "this_month", label: "Deze maand" },
11
+ { id: "last_month", label: "Vorige maand" },
12
+ { id: "last_30", label: "Laatste 30 dagen" },
13
+ { id: "last_60", label: "Laatste 60 dagen" },
14
+ { id: "last_90", label: "Laatste 90 dagen" },
15
+ { id: "this_quarter", label: "Dit kwartaal" },
16
+ { id: "last_quarter", label: "Vorig kwartaal" },
17
+ { id: "this_year", label: "Dit jaar" },
18
+ { id: "last_year", label: "Vorig jaar" },
19
+ { id: "all", label: "Alles" },
20
+ ];
21
+ function startOfDay(d) { const x = new Date(d); x.setHours(0, 0, 0, 0); return x; }
22
+ function endOfDay(d) { const x = new Date(d); x.setHours(23, 59, 59, 999); return x; }
23
+ function addDays(d, n) { const x = new Date(d); x.setDate(x.getDate() + n); return x; }
24
+ function startOfWeek(d) { const x = startOfDay(d); const day = (x.getDay() + 6) % 7; return addDays(x, -day); } // ma
25
+ function startOfMonth(d) { return new Date(d.getFullYear(), d.getMonth(), 1); }
26
+ function endOfMonth(d) { return endOfDay(new Date(d.getFullYear(), d.getMonth() + 1, 0)); }
27
+ function startOfQuarter(d) { const q = Math.floor(d.getMonth() / 3); return new Date(d.getFullYear(), q * 3, 1); }
28
+ function endOfQuarter(d) { const q = Math.floor(d.getMonth() / 3); return endOfDay(new Date(d.getFullYear(), q * 3 + 3, 0)); }
29
+ export function computePreset(id) {
30
+ const now = new Date();
31
+ const preset = PRESETS.find((p) => p.id === id);
32
+ const label = preset?.label ?? "Aangepast";
33
+ switch (id) {
34
+ case "today": return { from: startOfDay(now), to: endOfDay(now), label };
35
+ case "yesterday": {
36
+ const y = addDays(now, -1);
37
+ return { from: startOfDay(y), to: endOfDay(y), label };
38
+ }
39
+ case "this_week": return { from: startOfWeek(now), to: endOfDay(now), label };
40
+ case "last_week": {
41
+ const s = addDays(startOfWeek(now), -7);
42
+ return { from: s, to: endOfDay(addDays(s, 6)), label };
43
+ }
44
+ case "this_month": return { from: startOfMonth(now), to: endOfDay(now), label };
45
+ case "last_month": {
46
+ const s = startOfMonth(addDays(startOfMonth(now), -1));
47
+ return { from: s, to: endOfMonth(s), label };
48
+ }
49
+ case "last_30": return { from: startOfDay(addDays(now, -29)), to: endOfDay(now), label };
50
+ case "last_60": return { from: startOfDay(addDays(now, -59)), to: endOfDay(now), label };
51
+ case "last_90": return { from: startOfDay(addDays(now, -89)), to: endOfDay(now), label };
52
+ case "this_quarter": return { from: startOfQuarter(now), to: endOfDay(now), label };
53
+ case "last_quarter": {
54
+ const s = startOfQuarter(addDays(startOfQuarter(now), -1));
55
+ return { from: s, to: endOfQuarter(s), label };
56
+ }
57
+ case "this_year": return { from: new Date(now.getFullYear(), 0, 1), to: endOfDay(now), label };
58
+ case "last_year": return { from: new Date(now.getFullYear() - 1, 0, 1), to: endOfDay(new Date(now.getFullYear() - 1, 11, 31)), label };
59
+ case "all": return { from: null, to: null, label };
60
+ default: return { from: null, to: null, label };
61
+ }
62
+ }
63
+ function fmt(d) {
64
+ if (!d)
65
+ return "";
66
+ return d.toLocaleDateString("nl-NL", { day: "2-digit", month: "short", year: "numeric" });
67
+ }
68
+ function toInputDate(d) {
69
+ if (!d)
70
+ return "";
71
+ const y = d.getFullYear();
72
+ const m = String(d.getMonth() + 1).padStart(2, "0");
73
+ const day = String(d.getDate()).padStart(2, "0");
74
+ return `${y}-${m}-${day}`;
75
+ }
76
+ export function DateRangePicker({ value, onChange }) {
77
+ const [open, setOpen] = useState(false);
78
+ const [customFrom, setCustomFrom] = useState(toInputDate(value.from));
79
+ const [customTo, setCustomTo] = useState(toInputDate(value.to));
80
+ const pick = (id) => {
81
+ const r = computePreset(id);
82
+ onChange({ from: r.from, to: r.to, presetId: id, label: r.label });
83
+ setOpen(false);
84
+ };
85
+ const applyCustom = () => {
86
+ if (!customFrom || !customTo)
87
+ return;
88
+ const f = startOfDay(new Date(customFrom));
89
+ const t = endOfDay(new Date(customTo));
90
+ onChange({
91
+ from: f,
92
+ to: t,
93
+ presetId: "custom",
94
+ label: `${fmt(f)} – ${fmt(t)}`,
95
+ });
96
+ setOpen(false);
97
+ };
98
+ const labelText = value.presetId === "all"
99
+ ? "Periode: Alles"
100
+ : value.from && value.to
101
+ ? `${fmt(value.from)} – ${fmt(value.to)}`
102
+ : value.label || "Periode selecteren";
103
+ return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", size: "sm", className: "gap-2", children: [_jsx(CalendarIcon, { className: "h-4 w-4" }), labelText] }) }), _jsx(PopoverContent, { align: "end", className: "w-[420px] p-0", children: _jsxs("div", { className: "grid grid-cols-2 gap-0", children: [_jsx("div", { className: "border-r p-2 max-h-[360px] overflow-y-auto", children: PRESETS.map((p) => (_jsx("button", { onClick: () => pick(p.id), className: `w-full text-left px-3 py-1.5 rounded-md text-sm hover:bg-muted ${value.presetId === p.id ? "bg-muted font-medium" : ""}`, children: p.label }, p.id))) }), _jsxs("div", { className: "p-3 space-y-2", children: [_jsx("div", { className: "text-xs font-semibold text-muted-foreground", children: "Aangepaste periode" }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs", children: "Van" }), _jsx("input", { type: "date", value: customFrom, onChange: (e) => setCustomFrom(e.target.value), className: "w-full border rounded-md px-2 py-1.5 text-sm" })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs", children: "Tot" }), _jsx("input", { type: "date", value: customTo, onChange: (e) => setCustomTo(e.target.value), className: "w-full border rounded-md px-2 py-1.5 text-sm" })] }), _jsx(Button, { size: "sm", className: "w-full", onClick: applyCustom, disabled: !customFrom || !customTo, children: "Toepassen" })] })] }) })] }));
104
+ }
105
+ const STORAGE_KEY = "aanbiedingsmailtje:reportPeriod";
106
+ export function loadStoredRange() {
107
+ if (typeof window === "undefined") {
108
+ const r = computePreset("last_30");
109
+ return { from: r.from, to: r.to, presetId: "last_30", label: r.label };
110
+ }
111
+ try {
112
+ const raw = window.localStorage.getItem(STORAGE_KEY);
113
+ if (raw) {
114
+ const obj = JSON.parse(raw);
115
+ if (obj.presetId && obj.presetId !== "custom") {
116
+ const r = computePreset(obj.presetId);
117
+ return { from: r.from, to: r.to, presetId: obj.presetId, label: r.label };
118
+ }
119
+ return {
120
+ from: obj.from ? new Date(obj.from) : null,
121
+ to: obj.to ? new Date(obj.to) : null,
122
+ presetId: obj.presetId,
123
+ label: obj.label,
124
+ };
125
+ }
126
+ }
127
+ catch { /* noop */ }
128
+ const r = computePreset("last_30");
129
+ return { from: r.from, to: r.to, presetId: "last_30", label: r.label };
130
+ }
131
+ export function storeRange(r) {
132
+ if (typeof window === "undefined")
133
+ return;
134
+ window.localStorage.setItem(STORAGE_KEY, JSON.stringify({
135
+ presetId: r.presetId,
136
+ from: r.from ? r.from.toISOString() : null,
137
+ to: r.to ? r.to.toISOString() : null,
138
+ label: r.label,
139
+ }));
140
+ }
@@ -0,0 +1,2 @@
1
+ export declare function RapportagePage(): import("react").JSX.Element;
2
+ //# sourceMappingURL=RapportagePage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RapportagePage.d.ts","sourceRoot":"","sources":["../../src/components/RapportagePage.tsx"],"names":[],"mappings":"AAQA,wBAAgB,cAAc,gCAiG7B"}
@@ -0,0 +1,60 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useState } from "react";
3
+ import { useServerFn } from "@tanstack/react-start";
4
+ import { Card, CardContent, CardHeader, CardTitle, Skeleton, Badge, Button } from "@flowselections/core";
5
+ import { getOverallStats } from "../lib/stats.functions";
6
+ import { Mail, Eye, MousePointerClick, ShoppingCart, Euro, BarChart3, ArrowLeft } from "lucide-react";
7
+ import { Link } from "@tanstack/react-router";
8
+ import { DateRangePicker, loadStoredRange, storeRange } from "./DateRangePicker";
9
+ export function RapportagePage() {
10
+ const fn = useServerFn(getOverallStats);
11
+ const [range, setRange] = useState(null);
12
+ const [data, setData] = useState(null);
13
+ const [loading, setLoading] = useState(false);
14
+ useEffect(() => { setRange(loadStoredRange()); }, []);
15
+ useEffect(() => {
16
+ if (!range)
17
+ return;
18
+ setLoading(true);
19
+ const payload = {};
20
+ if (range.from)
21
+ payload.from = range.from.toISOString();
22
+ if (range.to)
23
+ payload.to = range.to.toISOString();
24
+ fn({ data: payload }).then((r) => { setData(r); setLoading(false); });
25
+ }, [range]);
26
+ const handleChange = (r) => { storeRange(r); setRange(r); };
27
+ const { topCustomers, topProducts } = useMemo(() => {
28
+ if (!data)
29
+ return { topCustomers: [], topProducts: [] };
30
+ const byCustomer = new Map();
31
+ for (const o of data.orders) {
32
+ const key = o.customer_id ?? o.customer_name;
33
+ const cur = byCustomer.get(key) ?? { name: o.customer_name, orders: 0, revenue: 0 };
34
+ cur.orders += 1;
35
+ cur.revenue += Number(o.total_amount ?? 0);
36
+ byCustomer.set(key, cur);
37
+ }
38
+ const byProduct = new Map();
39
+ for (const o of data.orders) {
40
+ for (const it of (Array.isArray(o.items) ? o.items : [])) {
41
+ const cur = byProduct.get(it.product_name) ?? { name: it.product_name, qty: 0, revenue: 0 };
42
+ cur.qty += Number(it.quantity ?? 0);
43
+ cur.revenue += Number(it.quantity ?? 0) * Number(it.unit_price ?? 0);
44
+ byProduct.set(it.product_name, cur);
45
+ }
46
+ }
47
+ return {
48
+ topCustomers: [...byCustomer.values()].sort((a, b) => b.revenue - a.revenue).slice(0, 10),
49
+ topProducts: [...byProduct.values()].sort((a, b) => b.qty - a.qty).slice(0, 10),
50
+ };
51
+ }, [data]);
52
+ if (!range || !data)
53
+ return _jsx("div", { className: "p-6", children: _jsx(Skeleton, { className: "h-64" }) });
54
+ const t = data.totals;
55
+ const totalRecords = t.sent + t.orders;
56
+ return (_jsxs("main", { className: "p-6 space-y-6", children: [_jsx(Link, { to: "/aanbiedingsmailtje", children: _jsxs(Button, { variant: "ghost", size: "sm", className: "-ml-2", children: [_jsx(ArrowLeft, { className: "h-4 w-4 mr-1" }), "Terug"] }) }), _jsxs("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(BarChart3, { className: "h-6 w-6 text-primary" }), _jsx("h2", { className: "text-2xl font-bold", children: "Rapportage" })] }), range && _jsx(DateRangePicker, { value: range, onChange: handleChange })] }), _jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx("span", { children: "Actieve periode:" }), _jsx(Badge, { variant: "secondary", className: "font-medium", children: range.label }), _jsxs("span", { className: "text-xs", children: ["\u00B7 ", totalRecords, " records ", loading && "(bijwerken…)"] })] }), _jsxs("div", { className: "grid grid-cols-2 md:grid-cols-6 gap-3", children: [_jsx(Stat, { icon: _jsx(Mail, {}), label: "Verzonden", value: t.sent }), _jsx(Stat, { icon: _jsx(Eye, {}), label: "Geopend", value: t.opened }), _jsx(Stat, { icon: _jsx(MousePointerClick, {}), label: "Klikken", value: t.clicked }), _jsx(Stat, { icon: _jsx(ShoppingCart, {}), label: "Bestellingen", value: t.orders }), _jsx(Stat, { icon: _jsx(Euro, {}), label: "Omzet", value: `€ ${t.revenue.toFixed(2)}` }), _jsx(Stat, { icon: _jsx(BarChart3, {}), label: "Campagnes", value: t.campaigns })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(CardTitle, { children: "Top klanten op omzet" }) }), _jsx(CardContent, { children: topCustomers.length === 0 ? _jsx("p", { className: "text-sm text-muted-foreground", children: "Nog geen bestellingen in deze periode" }) : (_jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { className: "text-left text-muted-foreground", children: _jsxs("tr", { children: [_jsx("th", { className: "py-1", children: "Klant" }), _jsx("th", { children: "Bestellingen" }), _jsx("th", { className: "text-right", children: "Omzet" })] }) }), _jsx("tbody", { children: topCustomers.map((c, i) => (_jsxs("tr", { className: "border-t", children: [_jsx("td", { className: "py-2", children: c.name }), _jsx("td", { children: c.orders }), _jsxs("td", { className: "text-right", children: ["\u20AC ", c.revenue.toFixed(2)] })] }, i))) })] })) })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(CardTitle, { children: "Best verkochte actieproducten" }) }), _jsx(CardContent, { children: topProducts.length === 0 ? _jsx("p", { className: "text-sm text-muted-foreground", children: "Nog geen bestellingen in deze periode" }) : (_jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { className: "text-left text-muted-foreground", children: _jsxs("tr", { children: [_jsx("th", { className: "py-1", children: "Product" }), _jsx("th", { children: "Aantal" }), _jsx("th", { className: "text-right", children: "Omzet" })] }) }), _jsx("tbody", { children: topProducts.map((p, i) => (_jsxs("tr", { className: "border-t", children: [_jsx("td", { className: "py-2", children: p.name }), _jsx("td", { children: p.qty }), _jsxs("td", { className: "text-right", children: ["\u20AC ", p.revenue.toFixed(2)] })] }, i))) })] })) })] })] }));
57
+ }
58
+ function Stat({ icon, label, value }) {
59
+ return (_jsx(Card, { children: _jsxs(CardContent, { className: "p-4", children: [_jsxs("div", { className: "flex items-center gap-2 text-muted-foreground text-xs mb-1", children: [icon, _jsx("span", { children: label })] }), _jsx("div", { className: "text-2xl font-bold", children: value })] }) }));
60
+ }
@@ -0,0 +1,2 @@
1
+ export declare function AfzenderSettingsCard(): import("react").JSX.Element;
2
+ //# sourceMappingURL=AfzenderSettingsCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AfzenderSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/AfzenderSettingsCard.tsx"],"names":[],"mappings":"AAIA,wBAAgB,oBAAoB,gCAsCnC"}
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect } from "react";
3
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle, Button, Input, Label, Textarea, supabase, toast, useAuth } from "@flowselections/core";
4
+ import { Mail } from "lucide-react";
5
+ export function AfzenderSettingsCard() {
6
+ const { isAdmin } = useAuth();
7
+ const [state, setState] = useState({ from_name: "", from_email: "", default_subject: "", default_intro: "" });
8
+ const [saving, setSaving] = useState(false);
9
+ useEffect(() => {
10
+ supabase.from("offer_settings").select("from_name, from_email, default_subject, default_intro").maybeSingle()
11
+ .then(({ data }) => { if (data)
12
+ setState(data); });
13
+ }, []);
14
+ const save = async () => {
15
+ setSaving(true);
16
+ try {
17
+ const { error } = await supabase.from("offer_settings").update(state).eq("singleton", true);
18
+ if (error)
19
+ throw error;
20
+ toast.success("Opgeslagen");
21
+ }
22
+ catch (e) {
23
+ toast.error(e?.message ?? "Fout");
24
+ }
25
+ finally {
26
+ setSaving(false);
27
+ }
28
+ };
29
+ return (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Mail, { className: "h-5 w-5 text-primary" }), _jsx(CardTitle, { children: "Afzender" })] }), _jsx(CardDescription, { children: "Standaard afzendergegevens voor aanbiedingsmails" })] }), _jsxs(CardContent, { className: "space-y-3", children: [_jsxs("div", { className: "grid gap-3 md:grid-cols-2", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Afzendernaam" }), _jsx(Input, { value: state.from_name, onChange: (e) => setState({ ...state, from_name: e.target.value }) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Afzender e-mail" }), _jsx(Input, { type: "email", value: state.from_email, onChange: (e) => setState({ ...state, from_email: e.target.value }) })] })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Standaard onderwerp" }), _jsx(Input, { value: state.default_subject, onChange: (e) => setState({ ...state, default_subject: e.target.value }) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Standaard intro" }), _jsx(Textarea, { rows: 3, value: state.default_intro, onChange: (e) => setState({ ...state, default_intro: e.target.value }) })] }), _jsx(Button, { onClick: save, disabled: saving || !isAdmin, children: saving ? "Opslaan..." : "Opslaan" }), !isAdmin && _jsx("p", { className: "text-xs text-muted-foreground", children: "Alleen admins kunnen deze instellingen wijzigen." })] })] }));
30
+ }
@@ -0,0 +1,2 @@
1
+ export declare function HuisstijlSettingsCard(): import("react").JSX.Element;
2
+ //# sourceMappingURL=HuisstijlSettingsCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HuisstijlSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/HuisstijlSettingsCard.tsx"],"names":[],"mappings":"AAIA,wBAAgB,qBAAqB,gCAoCpC"}
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect } from "react";
3
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle, Button, Input, Label, supabase, toast, useAuth } from "@flowselections/core";
4
+ import { Palette } from "lucide-react";
5
+ export function HuisstijlSettingsCard() {
6
+ const { isAdmin } = useAuth();
7
+ const [state, setState] = useState({ logo_url: "", primary_color: "#16a34a", button_color: "#16a34a" });
8
+ const [saving, setSaving] = useState(false);
9
+ useEffect(() => {
10
+ supabase.from("offer_settings").select("logo_url, primary_color, button_color").maybeSingle()
11
+ .then(({ data }) => { if (data)
12
+ setState({ logo_url: data.logo_url ?? "", primary_color: data.primary_color, button_color: data.button_color }); });
13
+ }, []);
14
+ const save = async () => {
15
+ setSaving(true);
16
+ try {
17
+ const { error } = await supabase.from("offer_settings").update(state).eq("singleton", true);
18
+ if (error)
19
+ throw error;
20
+ toast.success("Opgeslagen");
21
+ }
22
+ catch (e) {
23
+ toast.error(e?.message ?? "Fout");
24
+ }
25
+ finally {
26
+ setSaving(false);
27
+ }
28
+ };
29
+ return (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Palette, { className: "h-5 w-5 text-primary" }), _jsx(CardTitle, { children: "Huisstijl" })] }), _jsx(CardDescription, { children: "Logo en kleuren voor de e-mail en actiepagina" })] }), _jsxs(CardContent, { className: "space-y-3", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Logo URL" }), _jsx(Input, { value: state.logo_url, onChange: (e) => setState({ ...state, logo_url: e.target.value }), placeholder: "https://..." })] }), _jsxs("div", { className: "grid gap-3 md:grid-cols-2", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Primaire kleur" }), _jsx(Input, { type: "color", value: state.primary_color, onChange: (e) => setState({ ...state, primary_color: e.target.value }) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Knop kleur" }), _jsx(Input, { type: "color", value: state.button_color, onChange: (e) => setState({ ...state, button_color: e.target.value }) })] })] }), _jsx(Button, { onClick: save, disabled: saving || !isAdmin, children: saving ? "Opslaan..." : "Opslaan" })] })] }));
30
+ }
@@ -0,0 +1,2 @@
1
+ export declare function StickerSettingsCard(): import("react").JSX.Element;
2
+ //# sourceMappingURL=StickerSettingsCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StickerSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/StickerSettingsCard.tsx"],"names":[],"mappings":"AAIA,wBAAgB,mBAAmB,gCA8DlC"}
@@ -0,0 +1,41 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect } from "react";
3
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle, Button, Label, Input, supabase, toast, useAuth } from "@flowselections/core";
4
+ import { Tag } from "lucide-react";
5
+ export function StickerSettingsCard() {
6
+ const { isAdmin } = useAuth();
7
+ const [value, setValue] = useState("0");
8
+ const [saving, setSaving] = useState(false);
9
+ useEffect(() => {
10
+ supabase.from("offer_settings").select("default_sticker_cost").maybeSingle()
11
+ .then(({ data }) => {
12
+ if (data && data.default_sticker_cost != null) {
13
+ setValue(String(data.default_sticker_cost));
14
+ }
15
+ });
16
+ }, []);
17
+ const save = async () => {
18
+ const v = Number(value.replace(",", "."));
19
+ if (!Number.isFinite(v) || v < 0) {
20
+ toast.error("Vul een geldige prijs in");
21
+ return;
22
+ }
23
+ setSaving(true);
24
+ try {
25
+ const { error } = await supabase
26
+ .from("offer_settings")
27
+ .update({ default_sticker_cost: v })
28
+ .eq("singleton", true);
29
+ if (error)
30
+ throw error;
31
+ toast.success("Opgeslagen");
32
+ }
33
+ catch (e) {
34
+ toast.error(e?.message ?? "Fout");
35
+ }
36
+ finally {
37
+ setSaving(false);
38
+ }
39
+ };
40
+ return (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Tag, { className: "h-5 w-5 text-primary" }), _jsx(CardTitle, { children: "Stickers" })] }), _jsx(CardDescription, { children: "Basisprijs voor een sticker (per plant). Wordt automatisch ingevuld bij nieuwe aanbiedingen." })] }), _jsxs(CardContent, { className: "space-y-3", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "default-sticker-cost", children: "Basisprijs sticker (\u20AC per plant)" }), _jsx(Input, { id: "default-sticker-cost", type: "number", step: "0.01", min: "0", inputMode: "decimal", value: value, onChange: (e) => setValue(e.target.value), className: "w-40" })] }), _jsx(Button, { onClick: save, disabled: saving || !isAdmin, children: saving ? "Opslaan..." : "Opslaan" })] })] }));
41
+ }
@@ -0,0 +1,2 @@
1
+ export declare function TestmailCard(): import("react").JSX.Element;
2
+ //# sourceMappingURL=TestmailCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TestmailCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/TestmailCard.tsx"],"names":[],"mappings":"AAIA,wBAAgB,YAAY,gCA0B3B"}
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle, Button, Input, Label, toast } from "@flowselections/core";
4
+ import { TestTube2 } from "lucide-react";
5
+ export function TestmailCard() {
6
+ const [email, setEmail] = useState("");
7
+ const [sending, setSending] = useState(false);
8
+ const send = async () => {
9
+ if (!email) {
10
+ toast.error("Vul een e-mailadres in");
11
+ return;
12
+ }
13
+ setSending(true);
14
+ // Note: actual delivery requires Lovable Emails infrastructure to be configured.
15
+ setTimeout(() => {
16
+ setSending(false);
17
+ toast.success(`Testmail wordt verstuurd naar ${email} (vereist e-mailinfrastructuur)`);
18
+ }, 500);
19
+ };
20
+ return (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(TestTube2, { className: "h-5 w-5 text-primary" }), _jsx(CardTitle, { children: "Testmail" })] }), _jsx(CardDescription, { children: "Verstuur een voorbeeldcampagne naar uzelf" })] }), _jsxs(CardContent, { className: "space-y-3", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Test e-mailadres" }), _jsx(Input, { type: "email", value: email, onChange: (e) => setEmail(e.target.value) })] }), _jsx(Button, { onClick: send, disabled: sending, children: sending ? "Versturen..." : "Verstuur testmail" })] })] }));
21
+ }
@@ -0,0 +1,2 @@
1
+ export declare function TrackingSettingsCard(): import("react").JSX.Element;
2
+ //# sourceMappingURL=TrackingSettingsCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TrackingSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/TrackingSettingsCard.tsx"],"names":[],"mappings":"AAIA,wBAAgB,oBAAoB,gCAuDnC"}
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect } from "react";
3
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle, Button, Label, Switch, supabase, toast, useAuth, Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@flowselections/core";
4
+ import { Eye } from "lucide-react";
5
+ export function TrackingSettingsCard() {
6
+ const { isAdmin } = useAuth();
7
+ const [state, setState] = useState({ tracking_enabled: true, discount_display: "percent", show_customer_classes: true });
8
+ const [saving, setSaving] = useState(false);
9
+ useEffect(() => {
10
+ supabase.from("offer_settings").select("tracking_enabled, discount_display, show_customer_classes").maybeSingle()
11
+ .then(({ data }) => { if (data)
12
+ setState({ tracking_enabled: data.tracking_enabled ?? true, discount_display: data.discount_display ?? "percent", show_customer_classes: data.show_customer_classes ?? true }); });
13
+ }, []);
14
+ const save = async () => {
15
+ setSaving(true);
16
+ try {
17
+ const { error } = await supabase.from("offer_settings").update(state).eq("singleton", true);
18
+ if (error)
19
+ throw error;
20
+ toast.success("Opgeslagen");
21
+ }
22
+ catch (e) {
23
+ toast.error(e?.message ?? "Fout");
24
+ }
25
+ finally {
26
+ setSaving(false);
27
+ }
28
+ };
29
+ return (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Eye, { className: "h-5 w-5 text-primary" }), _jsx(CardTitle, { children: "Tracking & weergave" })] }), _jsx(CardDescription, { children: "Automatische tracking en kortingsweergave" })] }), _jsxs(CardContent, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx(Label, { children: "Automatische tracking" }), _jsx(Switch, { checked: state.tracking_enabled, onCheckedChange: (v) => setState({ ...state, tracking_enabled: v }) })] }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [_jsx(Label, { children: "Klantgroepen tonen" }), _jsx("p", { className: "text-xs text-muted-foreground", children: "Toon de \"Selecteer op klantgroep\" knoppen bij het aanmaken van een aanbieding" })] }), _jsx(Switch, { checked: state.show_customer_classes, onCheckedChange: (v) => setState({ ...state, show_customer_classes: v }) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Kortingsweergave" }), _jsxs(Select, { value: state.discount_display, onValueChange: (v) => setState({ ...state, discount_display: v }), children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "percent", children: "Percentage (-20%)" }), _jsx(SelectItem, { value: "amount", children: "Bedrag (\u20AC5 korting)" }), _jsx(SelectItem, { value: "both", children: "Beide" })] })] })] }), _jsx(Button, { onClick: save, disabled: saving || !isAdmin, children: saving ? "Opslaan..." : "Opslaan" })] })] }));
30
+ }
@@ -0,0 +1,2 @@
1
+ export declare function UitsluitingenSettingsCard(): import("react").JSX.Element;
2
+ //# sourceMappingURL=UitsluitingenSettingsCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UitsluitingenSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/UitsluitingenSettingsCard.tsx"],"names":[],"mappings":"AAMA,wBAAgB,yBAAyB,gCA+DxC"}
@@ -0,0 +1,41 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect } from "react";
3
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle, Button, Label, supabase, toast, useAuth, Badge } from "@flowselections/core";
4
+ import { UserX, X } from "lucide-react";
5
+ export function UitsluitingenSettingsCard() {
6
+ const { isAdmin } = useAuth();
7
+ const [customers, setCustomers] = useState([]);
8
+ const [excluded, setExcluded] = useState([]);
9
+ const [search, setSearch] = useState("");
10
+ const [saving, setSaving] = useState(false);
11
+ useEffect(() => {
12
+ (async () => {
13
+ const [{ data: cs }, { data: s }] = await Promise.all([
14
+ supabase.from("customers").select("id, company_name, email").order("company_name").limit(1000),
15
+ supabase.from("offer_settings").select("excluded_customer_ids").maybeSingle(),
16
+ ]);
17
+ setCustomers((cs ?? []));
18
+ if (s?.excluded_customer_ids)
19
+ setExcluded(s.excluded_customer_ids);
20
+ })();
21
+ }, []);
22
+ const toggle = (id) => setExcluded((p) => p.includes(id) ? p.filter((x) => x !== id) : [...p, id]);
23
+ const save = async () => {
24
+ setSaving(true);
25
+ try {
26
+ const { error } = await supabase.from("offer_settings").update({ excluded_customer_ids: excluded }).eq("singleton", true);
27
+ if (error)
28
+ throw error;
29
+ toast.success("Opgeslagen");
30
+ }
31
+ catch (e) {
32
+ toast.error(e?.message ?? "Fout");
33
+ }
34
+ finally {
35
+ setSaving(false);
36
+ }
37
+ };
38
+ const excludedCustomers = customers.filter((c) => excluded.includes(c.id));
39
+ const filtered = customers.filter((c) => c.company_name?.toLowerCase().includes(search.toLowerCase()) && !excluded.includes(c.id));
40
+ return (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(UserX, { className: "h-5 w-5 text-primary" }), _jsx(CardTitle, { children: "Uitsluitingen" })] }), _jsx(CardDescription, { children: "Klanten die nooit aanbiedingsmails moeten ontvangen" })] }), _jsxs(CardContent, { className: "space-y-3", children: [_jsxs("div", { className: "flex flex-wrap gap-2", children: [excludedCustomers.map((c) => (_jsxs(Badge, { variant: "secondary", className: "cursor-pointer", onClick: () => toggle(c.id), children: [c.company_name, " ", _jsx(X, { className: "h-3 w-3 ml-1" })] }, c.id))), excludedCustomers.length === 0 && _jsx("p", { className: "text-sm text-muted-foreground", children: "Geen uitsluitingen" })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Klant toevoegen" }), _jsx("input", { className: "w-full border rounded-md px-3 py-2 text-sm", placeholder: "Zoek...", value: search, onChange: (e) => setSearch(e.target.value) }), search && (_jsx("div", { className: "max-h-40 overflow-y-auto border rounded-md mt-2", children: filtered.slice(0, 20).map((c) => (_jsx("button", { onClick: () => { toggle(c.id); setSearch(""); }, className: "w-full text-left px-3 py-1.5 hover:bg-muted text-sm", children: c.company_name }, c.id))) }))] }), _jsx(Button, { onClick: save, disabled: saving || !isAdmin, children: saving ? "Opslaan..." : "Opslaan" })] })] }));
41
+ }
@@ -0,0 +1,17 @@
1
+ import type { FlowModule } from "@flowselections/core";
2
+ export * from "./_core-safelist";
3
+ export { AanbiedingsmailtjePage } from "./components/AanbiedingsmailtjePage";
4
+ export { CampagneOverzicht } from "./components/CampagneOverzicht";
5
+ export { CampagneDetail } from "./components/CampagneDetail";
6
+ export { RapportagePage } from "./components/RapportagePage";
7
+ export { ActiePage } from "./components/ActiePage";
8
+ import { AfzenderSettingsCard } from "./components/settings/AfzenderSettingsCard";
9
+ import { HuisstijlSettingsCard } from "./components/settings/HuisstijlSettingsCard";
10
+ import { TrackingSettingsCard } from "./components/settings/TrackingSettingsCard";
11
+ import { UitsluitingenSettingsCard } from "./components/settings/UitsluitingenSettingsCard";
12
+ import { StickerSettingsCard } from "./components/settings/StickerSettingsCard";
13
+ import { TestmailCard } from "./components/settings/TestmailCard";
14
+ export { AfzenderSettingsCard, HuisstijlSettingsCard, TrackingSettingsCard, UitsluitingenSettingsCard, StickerSettingsCard, TestmailCard };
15
+ export declare const aanbiedingsmailtjeModule: FlowModule;
16
+ export declare const myModule: FlowModule;
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,4CAA4C,CAAC;AAClF,OAAO,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAC;AACpF,OAAO,EAAE,oBAAoB,EAAE,MAAM,4CAA4C,CAAC;AAClF,OAAO,EAAE,yBAAyB,EAAE,MAAM,iDAAiD,CAAC;AAC5F,OAAO,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAElE,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,YAAY,EAAE,CAAC;AAE3I,eAAO,MAAM,wBAAwB,EAAE,UAiBtC,CAAC;AAGF,eAAO,MAAM,QAAQ,YAA2B,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { Mail } from "lucide-react";
2
+ export * from "./_core-safelist";
3
+ export { AanbiedingsmailtjePage } from "./components/AanbiedingsmailtjePage";
4
+ export { CampagneOverzicht } from "./components/CampagneOverzicht";
5
+ export { CampagneDetail } from "./components/CampagneDetail";
6
+ export { RapportagePage } from "./components/RapportagePage";
7
+ export { ActiePage } from "./components/ActiePage";
8
+ import { AfzenderSettingsCard } from "./components/settings/AfzenderSettingsCard";
9
+ import { HuisstijlSettingsCard } from "./components/settings/HuisstijlSettingsCard";
10
+ import { TrackingSettingsCard } from "./components/settings/TrackingSettingsCard";
11
+ import { UitsluitingenSettingsCard } from "./components/settings/UitsluitingenSettingsCard";
12
+ import { StickerSettingsCard } from "./components/settings/StickerSettingsCard";
13
+ import { TestmailCard } from "./components/settings/TestmailCard";
14
+ export { AfzenderSettingsCard, HuisstijlSettingsCard, TrackingSettingsCard, UitsluitingenSettingsCard, StickerSettingsCard, TestmailCard };
15
+ export const aanbiedingsmailtjeModule = {
16
+ id: "aanbiedingsmailtje",
17
+ name: "Aanbiedingsmailtje",
18
+ version: "1.0.0",
19
+ nav: {
20
+ label: "Aanbiedingsmailtje",
21
+ href: "/aanbiedingsmailtje",
22
+ icon: Mail,
23
+ },
24
+ settingsCards: [
25
+ { component: AfzenderSettingsCard, order: 10 },
26
+ { component: HuisstijlSettingsCard, order: 20 },
27
+ { component: TrackingSettingsCard, order: 30 },
28
+ { component: StickerSettingsCard, order: 35 },
29
+ { component: UitsluitingenSettingsCard, order: 40 },
30
+ { component: TestmailCard, order: 50 },
31
+ ],
32
+ };
33
+ // Backwards-compatibility alias used by _authenticated.tsx
34
+ export const myModule = aanbiedingsmailtjeModule;
@@ -0,0 +1,2 @@
1
+ export declare const attachSupabaseAuth: import("@tanstack/start-client-core").FunctionMiddlewareAfterClient<{}, unknown, undefined, undefined, undefined>;
2
+ //# sourceMappingURL=auth-attacher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-attacher.d.ts","sourceRoot":"","sources":["../../../src/integrations/supabase/auth-attacher.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,kBAAkB,mHAQ9B,CAAA"}
@@ -0,0 +1,12 @@
1
+ // This file is automatically generated. Do not edit it directly.
2
+ import { createMiddleware } from '@tanstack/react-start';
3
+ import { supabase } from './client';
4
+ // Must be registered as a global `functionMiddleware` in `src/start.ts`; otherwise
5
+ // the browser never attaches the bearer token to serverFn RPCs.
6
+ export const attachSupabaseAuth = createMiddleware({ type: 'function' }).client(async ({ next }) => {
7
+ const { data } = await supabase.auth.getSession();
8
+ const token = data.session?.access_token;
9
+ return next({
10
+ headers: token ? { Authorization: `Bearer ${token}` } : {},
11
+ });
12
+ });