@flowselections/actie-mail-kwekers-erp-mathot 1.0.29 → 1.0.31
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/AanbiedingsmailtjePage.d.ts.map +1 -1
- package/dist-lib/components/AanbiedingsmailtjePage.js +34 -19
- package/dist-lib/components/ActiePage.d.ts.map +1 -1
- package/dist-lib/components/ActiePage.js +17 -8
- package/dist-lib/components/CampagneDetail.d.ts.map +1 -1
- package/dist-lib/components/CampagneDetail.js +3 -2
- package/dist-lib/components/aanbieding/EmailPreview.js +2 -2
- package/dist-lib/components/overzicht/NietGekoppeldeBestellingen.d.ts.map +1 -1
- package/dist-lib/components/overzicht/NietGekoppeldeBestellingen.js +1 -1
- package/dist-lib/components/settings/HuisstijlSettingsCard.d.ts.map +1 -1
- package/dist-lib/components/settings/HuisstijlSettingsCard.js +9 -18
- package/dist-lib/components/settings/StickerSettingsCard.d.ts.map +1 -1
- package/dist-lib/components/settings/StickerSettingsCard.js +3 -7
- package/dist-lib/components/settings/TrackingSettingsCard.d.ts.map +1 -1
- package/dist-lib/components/settings/TrackingSettingsCard.js +3 -4
- package/dist-lib/components/settings/UitsluitingenSettingsCard.d.ts.map +1 -1
- package/dist-lib/components/settings/UitsluitingenSettingsCard.js +3 -4
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +0 -2
- package/dist-lib/integrations/supabase/types.d.ts +334 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/campaigns.functions.d.ts.map +1 -1
- package/dist-lib/lib/campaigns.functions.js +10 -3
- package/dist-lib/lib/offer-settings.functions.d.ts +23 -0
- package/dist-lib/lib/offer-settings.functions.d.ts.map +1 -0
- package/dist-lib/lib/offer-settings.functions.js +59 -0
- package/dist-lib/lib/pricing.d.ts +3 -1
- package/dist-lib/lib/pricing.d.ts.map +1 -1
- package/dist-lib/lib/pricing.js +16 -2
- package/dist-lib/lib/public-offer.functions.d.ts +9 -0
- package/dist-lib/lib/public-offer.functions.d.ts.map +1 -1
- package/dist-lib/lib/public-offer.functions.js +62 -16
- package/dist-lib/lib/stats.functions.d.ts +2 -0
- package/dist-lib/lib/stats.functions.d.ts.map +1 -1
- package/dist-lib/lib/unlinked-offer-orders.functions.d.ts +1 -0
- package/dist-lib/lib/unlinked-offer-orders.functions.d.ts.map +1 -1
- package/dist-lib/lib/unlinked-offer-orders.functions.js +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AanbiedingsmailtjePage.d.ts","sourceRoot":"","sources":["../../src/components/AanbiedingsmailtjePage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AanbiedingsmailtjePage.d.ts","sourceRoot":"","sources":["../../src/components/AanbiedingsmailtjePage.tsx"],"names":[],"mappings":"AAuDA,wBAAgB,sBAAsB,gCA2hCrC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useEffect, useMemo } from "react";
|
|
3
|
-
import { useAuth, supabase, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Input, Label, Textarea, Badge, Separator, Skeleton, Switch, toast, } from "@flowselections/core";
|
|
3
|
+
import { useAuth, supabase, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Input, Label, Textarea, Badge, Separator, Skeleton, Switch, toast, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@flowselections/core";
|
|
4
4
|
import { useServerFn } from "@tanstack/react-start";
|
|
5
5
|
import { useNavigate } from "@tanstack/react-router";
|
|
6
6
|
import { Mail, Send, Search, X, Package, Users, Percent, Tag, BarChart3, Info, ArrowLeft, ArrowRight, CheckCircle2, Check } from "lucide-react";
|
|
@@ -21,7 +21,8 @@ export function AanbiedingsmailtjePage() {
|
|
|
21
21
|
const [busy, setBusy] = useState(false);
|
|
22
22
|
const [step, setStep] = useState(1);
|
|
23
23
|
const [maxStep, setMaxStep] = useState(1);
|
|
24
|
-
const [name, setName] = useState("
|
|
24
|
+
const [name, setName] = useState("");
|
|
25
|
+
const [confirmSend, setConfirmSend] = useState(false);
|
|
25
26
|
const [subject, setSubject] = useState("🌷 Speciale aanbieding voor u!");
|
|
26
27
|
const [fromName, setFromName] = useState("");
|
|
27
28
|
const [fromEmail, setFromEmail] = useState(user?.email ?? "");
|
|
@@ -250,30 +251,35 @@ export function AanbiedingsmailtjePage() {
|
|
|
250
251
|
if (existing) {
|
|
251
252
|
return;
|
|
252
253
|
}
|
|
254
|
+
// Startprijs per fust = stukprijs × planten per fust; alleen als beide bekend en > 0, anders leeg.
|
|
255
|
+
const unit = Number(p.sale_price ?? 0);
|
|
256
|
+
const ppc = Number(p.plants_per_crate ?? 0);
|
|
257
|
+
const startCrate = unit > 0 && ppc > 0 ? round2(unit * ppc) : 0;
|
|
253
258
|
setSelProducts((prev) => [...prev, {
|
|
254
259
|
product_id: p.id ?? `tmp:${p.product}`,
|
|
255
260
|
product_name: p.product ?? "(naamloos)",
|
|
256
261
|
description: "",
|
|
257
262
|
image_url: p.image_url,
|
|
258
|
-
normal_price:
|
|
263
|
+
normal_price: startCrate,
|
|
259
264
|
discount_price: 0,
|
|
260
265
|
available_stock: p.quantity ?? 0,
|
|
261
266
|
plants_per_crate: p.plants_per_crate ?? 0,
|
|
262
267
|
belading: p.belading ?? "",
|
|
263
268
|
barcode: p.barcode ?? "",
|
|
264
|
-
crate_price:
|
|
265
|
-
base_crate_price:
|
|
269
|
+
crate_price: startCrate,
|
|
270
|
+
base_crate_price: startCrate,
|
|
266
271
|
sticker_cost: null,
|
|
267
272
|
sticker_available: true,
|
|
268
|
-
tiers: [
|
|
269
|
-
base_tiers: [
|
|
273
|
+
tiers: [],
|
|
274
|
+
base_tiers: [],
|
|
270
275
|
}]);
|
|
271
276
|
};
|
|
272
277
|
const removeProduct = (id) => setSelProducts((prev) => prev.filter((p) => p.product_id !== id));
|
|
273
278
|
const updateProd = (id, patch) => setSelProducts((prev) => prev.map((p) => (p.product_id === id ? { ...p, ...patch } : p)));
|
|
274
279
|
/** Originele (ongekorte) referenties van een product. */
|
|
275
280
|
const baseOf = (p) => {
|
|
276
|
-
const baseTiers = (p.base_tiers && p.base_tiers.length > 0 ? p.base_tiers : p.tiers) ?? []
|
|
281
|
+
const baseTiers = ((p.base_tiers && p.base_tiers.length > 0 ? p.base_tiers : p.tiers) ?? [])
|
|
282
|
+
.filter((t) => Number.isFinite(Number(t.price_per_crate)) && Number(t.price_per_crate) > 0);
|
|
277
283
|
const baseCrate = p.base_crate_price > 0
|
|
278
284
|
? p.base_crate_price
|
|
279
285
|
: Math.max(p.crate_price, p.normal_price, 0);
|
|
@@ -457,8 +463,14 @@ export function AanbiedingsmailtjePage() {
|
|
|
457
463
|
recipient_email: c.email,
|
|
458
464
|
}));
|
|
459
465
|
// Blokkeer ongeldige staffels (bijv. dubbele "vanaf"-aantallen) vóór opslaan.
|
|
466
|
+
if (!name.trim()) {
|
|
467
|
+
toast.error("Geef de aanbieding een naam");
|
|
468
|
+
setBusy(false);
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
460
471
|
for (const p of selProducts) {
|
|
461
|
-
const
|
|
472
|
+
const filled = p.tiers.filter((t) => Number.isFinite(Number(t.price_per_crate)));
|
|
473
|
+
const blocking = validateTiers(filled, baseOf(p).baseCrate).find((i) => i.level === "error");
|
|
462
474
|
if (blocking) {
|
|
463
475
|
toast.error(`${p.product_name}: ${blocking.message}`);
|
|
464
476
|
setBusy(false);
|
|
@@ -466,11 +478,12 @@ export function AanbiedingsmailtjePage() {
|
|
|
466
478
|
}
|
|
467
479
|
}
|
|
468
480
|
const res = await createFn({ data: {
|
|
469
|
-
name, subject, from_name: fromName || (user?.email ?? "FlowSelections"),
|
|
481
|
+
name: name.trim(), subject, from_name: fromName || (user?.email ?? "FlowSelections"),
|
|
470
482
|
from_email: fromEmail, intro_message: intro,
|
|
471
483
|
products: selProducts.map((p, i) => {
|
|
472
484
|
const { base_tiers: _bt, base_crate_price: _bc, ...rest } = p;
|
|
473
|
-
|
|
485
|
+
// Staffels zonder ingevulde prijs worden niet opgeslagen.
|
|
486
|
+
return { ...rest, tiers: sortTiers(p.tiers.filter((t) => Number.isFinite(Number(t.price_per_crate)))), sort_order: i };
|
|
474
487
|
}),
|
|
475
488
|
recipients,
|
|
476
489
|
} });
|
|
@@ -541,8 +554,8 @@ export function AanbiedingsmailtjePage() {
|
|
|
541
554
|
const sorted = sortTiers(p.tiers);
|
|
542
555
|
const last = sorted[sorted.length - 1];
|
|
543
556
|
const nextMin = last ? last.min_crates + 5 : 1;
|
|
544
|
-
|
|
545
|
-
const newTier = { min_crates: nextMin, price_per_crate:
|
|
557
|
+
// Nieuwe staffel start met een leeg prijsveld (nooit € 0).
|
|
558
|
+
const newTier = { min_crates: nextMin, price_per_crate: Number.NaN };
|
|
546
559
|
updateProd(p.product_id, {
|
|
547
560
|
tiers: [...p.tiers, newTier],
|
|
548
561
|
base_tiers: [...(p.base_tiers ?? p.tiers), newTier],
|
|
@@ -554,9 +567,10 @@ export function AanbiedingsmailtjePage() {
|
|
|
554
567
|
base_tiers: (p.base_tiers ?? p.tiers).filter((_, i) => i !== idx),
|
|
555
568
|
});
|
|
556
569
|
};
|
|
557
|
-
const tierIssues = validateTiers(p.tiers);
|
|
558
|
-
return (_jsxs("div", { className: "border rounded-md p-3 space-y-3 bg-muted/30", children: [_jsxs("div", { className: "flex items-start justify-between gap-2", children: [_jsxs("div", { className: "flex items-start gap-3 min-w-0", children: [_jsx("div", { className: "h-14 w-14 shrink-0 rounded-md border bg-muted overflow-hidden flex items-center justify-center", children: p.image_url ? (_jsx("img", { src: p.image_url, alt: p.product_name, className: "h-full w-full object-cover" })) : (_jsx(Package, { className: "h-6 w-6 text-muted-foreground" })) }), _jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "font-medium text-sm truncate", children: p.product_name }),
|
|
559
|
-
const
|
|
570
|
+
const tierIssues = validateTiers(p.tiers, baseOf(p).baseCrate);
|
|
571
|
+
return (_jsxs("div", { className: "border rounded-md p-3 space-y-3 bg-muted/30", children: [_jsxs("div", { className: "flex items-start justify-between gap-2", children: [_jsxs("div", { className: "flex items-start gap-3 min-w-0", children: [_jsx("div", { className: "h-14 w-14 shrink-0 rounded-md border bg-muted overflow-hidden flex items-center justify-center", children: p.image_url ? (_jsx("img", { src: p.image_url, alt: p.product_name, className: "h-full w-full object-cover" })) : (_jsx(Package, { className: "h-6 w-6 text-muted-foreground" })) }), _jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "font-medium text-sm truncate", children: p.product_name }), _jsx("div", { className: "text-xs text-muted-foreground", children: p.normal_price > 0 ? `Originele prijs: ${fmtEuroNL(p.normal_price)}` : "Geen prijs bekend — vul de fustprijs in" })] })] }), _jsx(Button, { variant: "ghost", size: "icon", onClick: () => removeProduct(p.product_id), children: _jsx(X, { className: "h-4 w-4" }) })] }), _jsxs("div", { className: "grid grid-cols-2 gap-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Label, { className: "text-xs w-24 shrink-0", children: "Planten/fust:" }), _jsx("span", { className: "text-sm font-medium", children: p.plants_per_crate || "—" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Label, { className: "text-xs w-20 shrink-0", children: "Belading:" }), _jsx("span", { className: "text-sm font-medium", children: p.belading || "—" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Label, { className: "text-xs w-24 shrink-0", children: "Barcode:" }), _jsx("span", { className: "text-sm font-medium", children: p.barcode || "—" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Label, { className: "text-xs w-20 shrink-0", children: "Fustprijs: \u20AC" }), _jsx(Input, { type: "number", step: "0.01", min: "0", placeholder: "Vul de fustprijs in", value: p.crate_price > 0 ? p.crate_price : "", onChange: (e) => {
|
|
572
|
+
const raw = Number(e.target.value);
|
|
573
|
+
const newPrice = e.target.value === "" || !Number.isFinite(raw) || raw < 0 ? 0 : round2(raw);
|
|
560
574
|
// Fustprijs is de originele adviesprijs; staffelprijzen blijven ongemoeid.
|
|
561
575
|
updateProd(p.product_id, {
|
|
562
576
|
crate_price: newPrice,
|
|
@@ -566,13 +580,14 @@ export function AanbiedingsmailtjePage() {
|
|
|
566
580
|
});
|
|
567
581
|
} })] })] }), _jsx("p", { className: "text-xs text-muted-foreground -mt-1", children: "Plantgegevens komen automatisch uit het product (voorraad) en zijn hier niet aanpasbaar." }), _jsxs("div", { className: "flex flex-wrap items-center gap-2 border-t pt-2", children: [_jsx("span", { className: "text-xs text-muted-foreground", children: "Korting dit product:" }), [10, 15, 20, 25, 30].map((pct) => (_jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: () => applyProductDiscount(p.product_id, pct), children: [_jsx(Percent, { className: "h-3 w-3 mr-1" }), pct, "%"] }, pct))), _jsx(Input, { type: "number", min: 1, max: 99, placeholder: "%", className: "w-20 h-8", value: prodPct[p.product_id] ?? "", onChange: (e) => setProdPct((prev) => ({ ...prev, [p.product_id]: e.target.value })) }), _jsx(Button, { type: "button", size: "sm", variant: "secondary", onClick: () => applyProductDiscount(p.product_id, Number((prodPct[p.product_id] || "").replace(",", "."))), children: "Toepassen" }), _jsx("span", { className: "text-xs text-muted-foreground ml-1", children: "of \u20AC korting:" }), _jsx(Input, { type: "number", step: "0.01", min: "0.01", placeholder: "\u20AC", className: "w-24 h-8", value: prodEur[p.product_id] ?? "", onChange: (e) => setProdEur((prev) => ({ ...prev, [p.product_id]: e.target.value })) }), _jsx(Button, { type: "button", size: "sm", variant: "secondary", onClick: () => applyProductDiscountAmount(p.product_id, Number((prodEur[p.product_id] || "").replace(",", "."))), children: "Toepassen" })] }), _jsxs("div", { className: "flex items-center gap-2 border-t pt-2", children: [_jsx(Label, { className: "text-xs", children: "Stickeropdruk beschikbaar:" }), _jsx(Button, { type: "button", size: "sm", variant: p.sticker_available ? "default" : "outline", onClick: () => updateProd(p.product_id, { sticker_available: true }), children: "Ja" }), _jsx(Button, { type: "button", size: "sm", variant: !p.sticker_available ? "default" : "outline", onClick: () => updateProd(p.product_id, { sticker_available: false }), children: "Nee" })] }), _jsxs("div", { className: "space-y-2 border-t pt-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx(Label, { className: "text-xs font-medium", children: "Prijs aftuin ex. Fust vanaf .." }), _jsx(Button, { variant: "outline", size: "sm", onClick: addTier, children: "+ Staffel" })] }), p.tiers.map((t, idx) => {
|
|
568
582
|
const pct = discountPercent(p.normal_price, t.price_per_crate);
|
|
569
|
-
return (_jsxs("div", { className: "flex items-center gap-2 text-sm", children: [_jsx("span", { className: "text-xs text-muted-foreground", children: "Vanaf" }), _jsx(Input, { type: "number", className: "w-20", value: t.min_crates, onChange: (e) => updateTier(idx, { min_crates: Number(e.target.value) }) }), _jsx("span", { className: "text-xs text-muted-foreground", children: "fust(en): \u20AC" }), _jsx(Input, { type: "number", step: "0.01", className: "w-24", value: t.price_per_crate, onChange: (e) => updateTier(idx, { price_per_crate: Number(e.target.value) }) }), _jsxs("span", { className: `text-xs font-medium ${pct > 0 ? "text-destructive" : "text-muted-foreground"}`, children: ["(", pct, "%)"] }),
|
|
570
|
-
}), _jsxs("p", { className: "text-[11px] text-muted-foreground", children: ["Percentage t.o.v. de originele fustprijs (
|
|
583
|
+
return (_jsxs("div", { className: "flex items-center gap-2 text-sm", children: [_jsx("span", { className: "text-xs text-muted-foreground", children: "Vanaf" }), _jsx(Input, { type: "number", className: "w-20", value: t.min_crates, onChange: (e) => updateTier(idx, { min_crates: Number(e.target.value) }) }), _jsx("span", { className: "text-xs text-muted-foreground", children: "fust(en): \u20AC" }), _jsx(Input, { type: "number", step: "0.01", min: "0.01", className: "w-24", placeholder: "Prijs", value: Number.isFinite(t.price_per_crate) ? t.price_per_crate : "", onChange: (e) => updateTier(idx, { price_per_crate: e.target.value === "" ? Number.NaN : Number(e.target.value.replace(",", ".")) }) }), _jsxs("span", { className: `text-xs font-medium ${pct > 0 ? "text-destructive" : "text-muted-foreground"}`, children: ["(", pct, "%)"] }), _jsx(Button, { variant: "ghost", size: "icon", className: "h-7 w-7", onClick: () => removeTier(idx), children: _jsx(X, { className: "h-3 w-3" }) })] }, idx));
|
|
584
|
+
}), _jsxs("p", { className: "text-[11px] text-muted-foreground", children: ["Percentage t.o.v. de originele fustprijs (", fmtEuroNL(p.normal_price), "), afgerond op hele procenten. Bij minder fusten dan de laagste staffel geldt de gewone prijs."] }), tierIssues.map((issue, i) => (_jsxs("p", { className: `text-[11px] ${issue.level === "error" ? "text-destructive" : "text-amber-600"}`, children: [issue.level === "error" ? "Fout: " : "Let op: ", issue.message] }, i)))] }), _jsx(Textarea, { placeholder: "Omschrijving (optioneel)", rows: 2, value: p.description, onChange: (e) => updateProd(p.product_id, { description: e.target.value }) })] }, p.product_id));
|
|
571
585
|
}) })] }))] })] })), step === 2 && (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Users, { className: "h-5 w-5" }), _jsx(CardTitle, { children: "Aan wie stuur je het?" })] }), _jsx(CardDescription, { children: "Kies de klanten die deze aanbieding ontvangen." }), _jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground pt-1", children: [_jsx(Info, { className: "h-3.5 w-3.5 shrink-0" }), _jsx("span", { children: "Er worden alleen klanten getoond met een e-mailadres. Klanten zonder e-mailadres zijn niet selecteerbaar." })] })] }), _jsxs(CardContent, { className: "space-y-3", children: [_jsxs("div", { className: "relative", children: [_jsx(Search, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { className: "pl-9", placeholder: "Zoek klant...", value: customerSearch, onChange: (e) => setCustomerSearch(e.target.value) })] }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("label", { className: "flex items-center gap-2 text-sm cursor-pointer", children: [_jsx("input", { type: "checkbox", checked: allVisibleSelected, onChange: toggleAllVisible }), "Selecteer alle klanten met email"] }), _jsxs(Badge, { variant: "secondary", children: [selCustomers.size, " geselecteerd"] })] }), showCustomerClasses && (_jsxs("div", { className: "space-y-2", children: [_jsx("div", { className: "text-xs font-medium text-muted-foreground", children: "Selecteer op klantgroep" }), _jsx("div", { className: "flex flex-wrap gap-2", children: classGroups.map((g) => {
|
|
572
586
|
const allSel = g.customers.length > 0 && g.customers.every((c) => selCustomers.has(c.id));
|
|
573
587
|
return (_jsxs(Button, { type: "button", variant: allSel ? "default" : "outline", size: "sm", onClick: () => toggleClass(g.letter), className: "gap-2", children: ["Klasse ", g.letter, _jsx(Badge, { variant: "secondary", className: "px-1.5 py-0 text-xs", children: g.customers.length })] }, g.letter));
|
|
574
588
|
}) })] })), _jsx(Separator, {}), _jsx("div", { className: "max-h-[500px] overflow-y-auto space-y-2 pr-1", children: filteredCustomers.slice(0, 500).map((c) => {
|
|
575
589
|
const checked = selCustomers.has(c.id);
|
|
576
590
|
return (_jsxs("button", { onClick: () => toggleCustomer(c.id), className: `w-full text-left p-3 rounded-md border hover:bg-muted text-sm flex items-center gap-3 ${checked ? "bg-primary/5 border-primary/40" : ""}`, children: [_jsx("input", { type: "checkbox", checked: checked, readOnly: true }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsxs("div", { className: "font-medium truncate flex items-center gap-2", children: [_jsx("span", { className: "truncate", children: c.company_name }), c.source === "ext" && _jsx(Badge, { variant: "outline", className: "text-[10px] px-1.5 py-0", children: "Floriday" })] }), _jsx("div", { className: "text-xs text-muted-foreground truncate", children: c.email })] }), c.customer_class && _jsx(Badge, { variant: "secondary", children: c.customer_class })] }, c.id));
|
|
577
|
-
}) })] })] })), step === 3 && (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Mail, { className: "h-5 w-5" }), _jsx(CardTitle, { children: "Wat staat er in de mail?" })] }), _jsx(CardDescription, { children: "Pas het onderwerp en de boodschap aan \u2014 je ziet het direct in het voorbeeld." })] }), _jsxs(CardContent, { className: "grid gap-4 md:grid-cols-2", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "Onderwerp" }), _jsx(Input, { value: subject, onChange: (e) => setSubject(e.target.value) })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "Bericht" }), _jsx(Textarea, { value: intro, onChange: (e) => setIntro(e.target.value), rows: 3 })] }), _jsxs("div", { className: "space-y-2 md:col-span-2 hidden", children: [_jsx(Label, { children: "Afzendernaam" }), _jsx(Input, { value: fromName, onChange: (e) => setFromName(e.target.value) }), _jsx(Label, { children: "Afzender e-mail" }), _jsx(Input, { type: "email", value: fromEmail, onChange: (e) => setFromEmail(e.target.value) })] }), _jsxs("div", { className: "md:col-span-2 flex items-start gap-2 rounded-md border bg-muted/40 p-3 text-xs text-muted-foreground", children: [_jsx(Info, { className: "mt-0.5 h-3.5 w-3.5 shrink-0" }), _jsx("span", { children: "Tip: een duidelijk onderwerp en korte samenvatting zorgen voor meer openingen." })] })] })] })), step === 4 && (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CheckCircle2, { className: "h-5 w-5" }), _jsx(CardTitle, { children: "Controleren & versturen" })] }), _jsx(CardDescription, { children: "Controleer je aanbieding en verstuur of bewaar als concept." })] }), _jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { className: "grid gap-3 sm:grid-cols-3", children: [_jsxs("div", { className: "rounded-md border p-3", children: [_jsx("div", { className: "text-xs text-muted-foreground", children: "Producten" }), _jsx("div", { className: "text-xl font-semibold", children: selProducts.length })] }), _jsxs("div", { className: "rounded-md border p-3", children: [_jsx("div", { className: "text-xs text-muted-foreground", children: "Ontvangers" }), _jsx("div", { className: "text-xl font-semibold", children: selCustomers.size })] }), _jsxs("div", { className: "rounded-md border p-3", children: [_jsx("div", { className: "text-xs text-muted-foreground", children: "Onderwerp" }), _jsx("div", { className: "truncate text-sm font-medium", children: subject || "—" })] })] }), _jsxs("div", { className: "space-y-2", children: [_jsx("div", { className: "text-sm font-medium", children: "Producten in deze aanbieding" }), selProducts.length === 0 ? (_jsx("div", { className: "text-sm text-muted-foreground", children: "Nog geen producten geselecteerd." })) : (_jsx("div", { className: "divide-y rounded-md border", children: selProducts.map((p) => (_jsxs("div", { className: "flex items-center justify-between gap-3 p-3 text-sm", children: [_jsx("span", { className: "truncate", children: p.product_name }), _jsxs("span", { className: "shrink-0 font-medium", children: ["\u20AC ", p.crate_price.toFixed(2)] })] }, p.product_id))) }))] }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Button, { variant: "outline", disabled: busy, onClick: () => handleSave(false), children: "Opslaan als concept" }), _jsxs(Button, { disabled: busy || selProducts.length === 0 || selCustomers.size === 0, onClick: () =>
|
|
591
|
+
}) })] })] })), step === 3 && (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Mail, { className: "h-5 w-5" }), _jsx(CardTitle, { children: "Wat staat er in de mail?" })] }), _jsx(CardDescription, { children: "Pas het onderwerp en de boodschap aan \u2014 je ziet het direct in het voorbeeld." })] }), _jsxs(CardContent, { className: "grid gap-4 md:grid-cols-2", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "Onderwerp" }), _jsx(Input, { value: subject, onChange: (e) => setSubject(e.target.value) })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "Bericht" }), _jsx(Textarea, { value: intro, onChange: (e) => setIntro(e.target.value), rows: 3 })] }), _jsxs("div", { className: "space-y-2 md:col-span-2 hidden", children: [_jsx(Label, { children: "Afzendernaam" }), _jsx(Input, { value: fromName, onChange: (e) => setFromName(e.target.value) }), _jsx(Label, { children: "Afzender e-mail" }), _jsx(Input, { type: "email", value: fromEmail, onChange: (e) => setFromEmail(e.target.value) })] }), _jsxs("div", { className: "md:col-span-2 flex items-start gap-2 rounded-md border bg-muted/40 p-3 text-xs text-muted-foreground", children: [_jsx(Info, { className: "mt-0.5 h-3.5 w-3.5 shrink-0" }), _jsx("span", { children: "Tip: een duidelijk onderwerp en korte samenvatting zorgen voor meer openingen." })] })] })] })), step === 4 && (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CheckCircle2, { className: "h-5 w-5" }), _jsx(CardTitle, { children: "Controleren & versturen" })] }), _jsx(CardDescription, { children: "Controleer je aanbieding en verstuur of bewaar als concept." })] }), _jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { className: "grid gap-3 sm:grid-cols-3", children: [_jsxs("div", { className: "rounded-md border p-3", children: [_jsx("div", { className: "text-xs text-muted-foreground", children: "Producten" }), _jsx("div", { className: "text-xl font-semibold", children: selProducts.length })] }), _jsxs("div", { className: "rounded-md border p-3", children: [_jsx("div", { className: "text-xs text-muted-foreground", children: "Ontvangers" }), _jsx("div", { className: "text-xl font-semibold", children: selCustomers.size })] }), _jsxs("div", { className: "rounded-md border p-3", children: [_jsx("div", { className: "text-xs text-muted-foreground", children: "Onderwerp" }), _jsx("div", { className: "truncate text-sm font-medium", children: subject || "—" })] })] }), _jsxs("div", { className: "space-y-2", children: [_jsx("div", { className: "text-sm font-medium", children: "Producten in deze aanbieding" }), selProducts.length === 0 ? (_jsx("div", { className: "text-sm text-muted-foreground", children: "Nog geen producten geselecteerd." })) : (_jsx("div", { className: "divide-y rounded-md border", children: selProducts.map((p) => (_jsxs("div", { className: "flex items-center justify-between gap-3 p-3 text-sm", children: [_jsx("span", { className: "truncate", children: p.product_name }), _jsxs("span", { className: "shrink-0 font-medium", children: ["\u20AC ", p.crate_price.toFixed(2)] })] }, p.product_id))) }))] }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Button, { variant: "outline", disabled: busy, onClick: () => handleSave(false), children: "Opslaan als concept" }), _jsxs(Button, { disabled: busy || selProducts.length === 0 || selCustomers.size === 0, onClick: () => setConfirmSend(true), children: [_jsx(Send, { className: "h-4 w-4 mr-2" }), busy ? "Bezig..." : "Actie Versturen"] })] })] })] }))] }), _jsx(EmailPreview, { subject: subject, intro: intro, fromName: fromName || (user?.email ?? ""), products: selProducts, recipientCount: selCustomers.size, offerName: name, branding: branding })] }), _jsx("div", { className: "sticky bottom-0 z-30 -mx-6 -mb-6 border-t bg-background/95 backdrop-blur px-6 py-3", children: _jsxs("div", { className: "flex items-center justify-between gap-4", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "truncate font-semibold", children: stepDef.title }), _jsxs("div", { className: "truncate text-sm text-muted-foreground", children: [selProducts.length, " product(en) \u2022 ", selCustomers.size, " klant(en)", nextHint ? ` • ${nextHint}` : ""] })] }), _jsxs("div", { className: "flex shrink-0 gap-2", children: [_jsxs(Button, { variant: "outline", onClick: () => (step === 1 ? navigate({ to: "/aanbiedingsmailtje/overzicht" }) : goTo(step - 1)), children: [_jsx(ArrowLeft, { className: "h-4 w-4 mr-2" }), step === 1 ? "Annuleren" : "Vorige"] }), step < 4 ? (_jsxs(Button, { onClick: goNext, disabled: !canNext, children: ["Verder naar ", AANBIEDING_STEPS[step].title.toLowerCase(), _jsx(ArrowRight, { className: "h-4 w-4 ml-2" })] })) : (_jsxs(Button, { disabled: busy || selProducts.length === 0 || selCustomers.size === 0, onClick: () => setConfirmSend(true), children: [_jsx(Send, { className: "h-4 w-4 mr-2" }), busy ? "Bezig..." : "Actie Versturen"] }))] })] }) }), _jsx(AlertDialog, { open: confirmSend, onOpenChange: setConfirmSend, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Actie versturen?" }), _jsxs(AlertDialogDescription, { children: ["Je verstuurt deze actie nu naar ", selCustomers.size, " ", selCustomers.size === 1 ? "ontvanger" : "ontvangers", ". Dit kun je niet terugdraaien."] })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: "Annuleren" }), _jsx(AlertDialogAction, { onClick: () => { setConfirmSend(false); void handleSave(true); }, children: "Ja, versturen" })] })] }) })] }));
|
|
578
592
|
}
|
|
593
|
+
const fmtEuroNL = (n) => new Intl.NumberFormat("nl-NL", { style: "currency", currency: "EUR" }).format(Number(n) || 0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActiePage.d.ts","sourceRoot":"","sources":["../../src/components/ActiePage.tsx"],"names":[],"mappings":"AAuEA,wBAAgB,SAAS,
|
|
1
|
+
{"version":3,"file":"ActiePage.d.ts","sourceRoot":"","sources":["../../src/components/ActiePage.tsx"],"names":[],"mappings":"AAuEA,wBAAgB,SAAS,gCA+sBxB"}
|
|
@@ -6,7 +6,7 @@ import { Button, Input, Label, Textarea, Skeleton, toast } from "@flowselections
|
|
|
6
6
|
import { getOfferByLinkCode, trackOfferClick, placeOfferOrder, getOfferDeliveryOptions, getOfferBranding, } from "../lib/public-offer.functions.js";
|
|
7
7
|
import { ShoppingCart, Check, Package, Truck, Minus, Plus, Send, Leaf, MapPin } from "lucide-react";
|
|
8
8
|
import { resolveBranding } from "../lib/branding.js";
|
|
9
|
-
import {
|
|
9
|
+
import { validTiers, resolveTierPrice, discountPercent } from "../lib/pricing.js";
|
|
10
10
|
// ISO weekday: Ma=1 .. Zo=7
|
|
11
11
|
function isoWeekday(d) {
|
|
12
12
|
const js = d.getDay(); // 0..6, 0=Sun
|
|
@@ -175,18 +175,19 @@ export function ActiePage() {
|
|
|
175
175
|
const plants = crates * ppc;
|
|
176
176
|
// Prijsprioriteit: (1) geldende staffelprijs uit actie-e-mail, (2) discount_price uit
|
|
177
177
|
// e-mail, (3) standaardprijs. Onder de laagste staffel geldt (2)/(3).
|
|
178
|
-
const tiers =
|
|
178
|
+
const tiers = validTiers((Array.isArray(p.tiers) ? p.tiers : []).map((t) => ({
|
|
179
179
|
min_crates: Number(t.min_crates),
|
|
180
180
|
price_per_crate: Number(t.price_per_crate),
|
|
181
181
|
})));
|
|
182
|
-
|
|
182
|
+
// Bij aantal 0 tonen we de prijs voor 1 fust (nooit stukprijs × planten).
|
|
183
|
+
const resolved = resolveTierPrice(tiers, Math.max(1, crates), {
|
|
183
184
|
discount_price: Number(p.discount_price ?? 0),
|
|
184
185
|
normal_price: Number(p.normal_price ?? 0),
|
|
185
186
|
});
|
|
186
187
|
const priceSource = resolved.source;
|
|
187
|
-
//
|
|
188
|
-
const cratePrice =
|
|
189
|
-
const unit =
|
|
188
|
+
// Alle prijzen (staffel, actie, normaal) zijn per fust — gelijk aan de server.
|
|
189
|
+
const cratePrice = resolved.price;
|
|
190
|
+
const unit = Math.round((resolved.price / ppc) * 100) / 100;
|
|
190
191
|
const priceSourceLabel = priceSource === "tier" ? "Prijs uit actie-e-mail"
|
|
191
192
|
: priceSource === "discount" ? "Actieprijs uit e-mail"
|
|
192
193
|
: "Standaardprijs artikelbeheer";
|
|
@@ -262,7 +263,15 @@ export function ActiePage() {
|
|
|
262
263
|
items,
|
|
263
264
|
},
|
|
264
265
|
});
|
|
265
|
-
|
|
266
|
+
if (!r.ok && r.reason === "price_changed") {
|
|
267
|
+
toast.error(r.message ?? "De prijs is gewijzigd. Controleer je bestelling.");
|
|
268
|
+
try {
|
|
269
|
+
setData(await getFn({ data: { code: linkCode } }));
|
|
270
|
+
}
|
|
271
|
+
catch { /* blijft oude weergave */ }
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
setPlaced({ id: r.orderId ?? "", total: r.total, orderNumber: r.orderNumber ?? null, unmatched: !r.ok });
|
|
266
275
|
}
|
|
267
276
|
catch (e) {
|
|
268
277
|
toast.error(e?.message ?? "Fout");
|
|
@@ -276,7 +285,7 @@ export function ActiePage() {
|
|
|
276
285
|
if (placed.unmatched) {
|
|
277
286
|
return (_jsx("div", { className: "min-h-screen bg-[#fffbeb] flex items-center justify-center p-6", children: _jsxs("div", { className: "max-w-md w-full bg-white rounded-2xl shadow-lg border border-amber-200 p-8 text-center", children: [_jsx("h2", { className: "text-2xl font-bold text-slate-900", children: "Bestelling ontvangen \u2014 actie nodig" }), _jsxs("p", { className: "mt-3 text-slate-700", children: ["We hebben je bestelling (referentie ", _jsx("strong", { children: ref }), ") ontvangen, maar konden die niet automatisch aan je klantaccount koppelen."] }), _jsxs("p", { className: "mt-3 text-slate-700", children: ["Neem contact op met ", brandName, " en noem deze referentie, dan verwerken we je bestelling voor je."] })] }) }));
|
|
278
287
|
}
|
|
279
|
-
return (_jsx("div", { className: "min-h-screen bg-[#f0fdf4] flex items-center justify-center p-6", children: _jsxs("div", { className: "max-w-md w-full bg-white rounded-2xl shadow-lg border border-green-100 p-8 text-center", children: [_jsx("div", { className: "mx-auto rounded-full bg-green-100 p-3 w-fit", children: _jsx(Check, { className: "h-8 w-8 text-green-600" }) }), _jsx("h2", { className: "mt-4 text-2xl font-bold text-slate-900", children: "Bedankt
|
|
288
|
+
return (_jsx("div", { className: "min-h-screen bg-[#f0fdf4] flex items-center justify-center p-6", children: _jsxs("div", { className: "max-w-md w-full bg-white rounded-2xl shadow-lg border border-green-100 p-8 text-center", children: [_jsx("div", { className: "mx-auto rounded-full bg-green-100 p-3 w-fit", children: _jsx(Check, { className: "h-8 w-8 text-green-600" }) }), _jsx("h2", { className: "mt-4 text-2xl font-bold text-slate-900", children: "Bedankt, je bestelling is ontvangen" }), _jsxs("p", { className: "mt-2 text-slate-600", children: ["Bestelling ", ref] }), _jsxs("p", { className: "mt-1 text-lg font-semibold text-green-700", children: ["Totaal: ", fmtEuro(placed.total)] }), _jsx("p", { className: "mt-4 text-sm text-slate-500", children: "We gaan er direct mee aan de slag." })] }) }));
|
|
280
289
|
}
|
|
281
290
|
return (_jsxs("div", { className: "min-h-screen bg-[#f0fdf4] flex flex-col", style: brandStyle, children: [_jsx("header", { className: "text-white", style: { backgroundColor: "var(--offer-primary)" }, children: _jsxs("div", { className: "max-w-6xl mx-auto px-4 sm:px-6 py-6 sm:py-10 text-center", children: [_jsxs("div", { className: "mx-auto mb-3 sm:mb-4 inline-flex max-w-full items-center justify-center gap-2 bg-white rounded-md px-3 py-2 shadow-sm", children: [brand.logoUrl ? (_jsx("img", { src: brand.logoUrl, alt: brandName, className: "h-6 sm:h-7 w-auto max-w-[180px] object-contain" })) : (_jsx(Leaf, { className: "h-5 w-5 shrink-0", style: { color: "var(--offer-primary)" } })), _jsx("span", { className: "font-bold text-slate-900 tracking-tight truncate", children: brandName })] }), _jsxs("h1", { className: "text-2xl sm:text-3xl md:text-4xl font-extrabold tracking-tight break-words", children: ["\uD83C\uDF31 ", data?.campaign?.subject ?? "Speciale Aanbieding"] }), data?.campaign?.intro_message ? (_jsx("p", { className: "mt-3 text-white/90 text-sm sm:text-base whitespace-pre-line max-w-2xl mx-auto", children: data.campaign.intro_message })) : (_jsx("p", { className: "mt-3 text-white/90 text-sm sm:text-base", children: "Wij hebben een mooie aanbieding voor u!" }))] }) }), _jsxs("main", { className: "flex-1 max-w-6xl w-full mx-auto px-3 sm:px-6 py-6 sm:py-8 space-y-6 pb-28 lg:pb-8", children: [_jsxs("div", { className: "w-full text-left p-3 rounded-md border border-slate-200 bg-white text-sm flex items-center gap-3", children: [_jsx("div", { className: "h-10 w-10 rounded-md bg-primary text-white grid place-items-center text-sm font-bold shrink-0", children: data?.recipient?.recipient_name
|
|
282
291
|
?.split(" ")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CampagneDetail.d.ts","sourceRoot":"","sources":["../../src/components/CampagneDetail.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CampagneDetail.d.ts","sourceRoot":"","sources":["../../src/components/CampagneDetail.tsx"],"names":[],"mappings":"AAUA,wBAAgB,cAAc,gCA0H7B"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { CampaignStatusBadge, euro } from "./overzicht/campaignStatus.js";
|
|
2
3
|
import { useEffect, useState } from "react";
|
|
3
4
|
import { useParams } from "@tanstack/react-router";
|
|
4
5
|
import { useServerFn } from "@tanstack/react-start";
|
|
@@ -60,7 +61,7 @@ export function CampagneDetail() {
|
|
|
60
61
|
toast.success("Verwijderd");
|
|
61
62
|
navigate({ to: "/aanbiedingsmailtje/overzicht" });
|
|
62
63
|
};
|
|
63
|
-
return (_jsxs("main", { className: "p-6 space-y-6", children: [_jsx(Link, { to: "/aanbiedingsmailtje/overzicht", children: _jsxs(Button, { variant: "ghost", size: "sm", className: "-ml-2", children: [_jsx(ArrowLeft, { className: "h-4 w-4 mr-1" }), "Terug"] }) }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs("div", { className: "flex justify-between items-start", children: [_jsxs("div", { children: [_jsx(CardTitle, { children: c.name }), _jsx(CardDescription, { children: c.subject })] }), _jsx(
|
|
64
|
+
return (_jsxs("main", { className: "p-6 space-y-6", children: [_jsx(Link, { to: "/aanbiedingsmailtje/overzicht", children: _jsxs(Button, { variant: "ghost", size: "sm", className: "-ml-2", children: [_jsx(ArrowLeft, { className: "h-4 w-4 mr-1" }), "Terug"] }) }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs("div", { className: "flex justify-between items-start", children: [_jsxs("div", { children: [_jsx(CardTitle, { children: c.name }), _jsx(CardDescription, { children: c.subject })] }), _jsx(CampaignStatusBadge, { status: c.status })] }) }), _jsxs(CardContent, { className: "space-y-3", children: [_jsxs("div", { className: "text-sm text-muted-foreground", children: ["Van: ", c.from_name, " <", c.from_email, ">"] }), c.intro_message && _jsx("p", { className: "text-sm", children: c.intro_message }), _jsxs("div", { className: "flex gap-2", children: [c.status !== "sent" && (_jsxs(Button, { onClick: handleSend, disabled: busy, children: [_jsx(Send, { className: "h-4 w-4 mr-1" }), "Versturen"] })), _jsxs(Button, { variant: "destructive", onClick: handleDel, children: [_jsx(Trash2, { className: "h-4 w-4 mr-1" }), "Verwijderen"] })] })] })] }), stats && (_jsxs("div", { className: "grid grid-cols-2 md:grid-cols-5 gap-3", children: [_jsx(StatCard, { icon: _jsx(Mail, {}), label: "Verzonden", value: stats.sent }), _jsx(StatCard, { icon: _jsx(Eye, {}), label: "Geopend", value: stats.opened }), _jsx(StatCard, { icon: _jsx(MousePointerClick, {}), label: "Klikken", value: stats.clicked }), _jsx(StatCard, { icon: _jsx(ShoppingCart, {}), label: "Bestellingen", value: stats.ordered }), _jsx(StatCard, { icon: _jsx("span", { children: "\u20AC" }), label: "Omzet", value: euro(Number(stats.revenue)) })] })), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs(CardTitle, { children: ["Producten (", data.products.length, ")"] }) }), _jsx(CardContent, { className: "space-y-2", children: data.products.map((p) => (_jsxs("div", { className: "flex justify-between border-b py-2 text-sm", children: [_jsx("span", { children: p.product_name }), _jsx("span", { children: Number(p.discount_price) > 0 && Number(p.discount_price) < Number(p.normal_price) ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "line-through text-muted-foreground mr-2", children: euro(Number(p.normal_price)) }), _jsx("span", { className: "font-semibold", children: euro(Number(p.discount_price)) })] })) : (_jsx("span", { className: "font-semibold", children: euro(Number(p.normal_price)) })) })] }, p.id))) })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsxs(CardTitle, { children: ["Ontvangers (", data.recipients.length, ")"] }), _jsx(CardDescription, { children: "Klik op een rij om de unieke actie-URL te kopi\u00EBren" })] }), _jsx(CardContent, { children: _jsx("div", { className: "max-h-[400px] overflow-y-auto divide-y text-sm", children: data.recipients.map((r) => {
|
|
64
65
|
const url = `${origin}/actie/${r.link_code}`;
|
|
65
66
|
return (_jsxs("button", { onClick: () => { navigator.clipboard.writeText(url); toast.success("Link gekopieerd"); }, className: "w-full text-left py-2 hover:bg-muted/50 grid grid-cols-12 gap-2 items-center", children: [_jsx("div", { className: "col-span-4 font-medium truncate", children: r.recipient_name }), _jsx("div", { className: "col-span-4 text-muted-foreground truncate", children: r.recipient_email }), _jsxs("div", { className: "col-span-4 flex gap-1 justify-end", children: [r.sent_at && _jsx(Badge, { variant: "outline", children: "verzonden" }), r.opened_at && _jsx(Badge, { variant: "secondary", children: "geopend" }), r.clicked_at && _jsx(Badge, { children: "geklikt" }), r.ordered_at && _jsx(Badge, { variant: "default", children: "besteld" })] })] }, r.id));
|
|
66
67
|
}) }) })] })] }));
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useState } from "react";
|
|
3
3
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle, Button, cn } from "@flowselections/core";
|
|
4
4
|
import { Monitor, Smartphone, Package, Info, Mail, ExternalLink, ShoppingCart } from "lucide-react";
|
|
5
|
-
import {
|
|
5
|
+
import { validTiers, discountPercent } from "../../lib/pricing.js";
|
|
6
6
|
import { resolveBranding } from "../../lib/branding.js";
|
|
7
7
|
const euro = (n) => `€ ${(Number.isFinite(n) ? n : 0).toFixed(2)}`;
|
|
8
8
|
export function EmailPreview({ subject, intro, fromName, products, recipientCount, offerName, branding }) {
|
|
@@ -14,7 +14,7 @@ export function EmailPreview({ subject, intro, fromName, products, recipientCoun
|
|
|
14
14
|
return (_jsxs(Card, { className: "xl:sticky xl:top-6", children: [_jsxs(CardHeader, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { children: [_jsx(CardTitle, { children: "Voorbeeld" }), _jsx(CardDescription, { children: view === "email"
|
|
15
15
|
? "Zo ziet je e-mail eruit voor je ontvangers."
|
|
16
16
|
: "Zo ziet de actiepagina eruit na het klikken op de link." })] }), _jsxs("div", { className: "flex items-center gap-1 rounded-md border p-1", children: [_jsx(Button, { type: "button", size: "icon", variant: device === "desktop" ? "default" : "ghost", className: "h-7 w-7", "aria-label": "Desktopweergave", onClick: () => setDevice("desktop"), children: _jsx(Monitor, { className: "h-4 w-4" }) }), _jsx(Button, { type: "button", size: "icon", variant: isMobile ? "default" : "ghost", className: "h-7 w-7", "aria-label": "Mobiele weergave", onClick: () => setDevice("mobile"), children: _jsx(Smartphone, { className: "h-4 w-4" }) })] })] }), _jsxs("div", { className: "grid grid-cols-2 gap-1 rounded-md border bg-muted/40 p-1", children: [_jsxs(Button, { type: "button", size: "sm", variant: view === "email" ? "default" : "ghost", className: "h-8 gap-1.5", onClick: () => setView("email"), "aria-pressed": view === "email", children: [_jsx(Mail, { className: "h-3.5 w-3.5" }), " E-mail"] }), _jsxs(Button, { type: "button", size: "sm", variant: view === "landing" ? "default" : "ghost", className: "h-8 gap-1.5", onClick: () => setView("landing"), "aria-pressed": view === "landing", children: [_jsx(ExternalLink, { className: "h-3.5 w-3.5" }), " Actiepagina"] })] })] }), _jsxs(CardContent, { className: "space-y-3", children: [_jsx("div", { className: cn("mx-auto transition-all", isMobile ? "max-w-[340px]" : "w-full"), children: view === "email" ? (_jsxs("div", { className: "rounded-lg border bg-card overflow-hidden", children: [_jsxs("div", { className: "border-b bg-muted/40 px-4 py-3", children: [_jsx("div", { className: "text-xs text-muted-foreground", children: "Onderwerpregel" }), _jsx("div", { className: "font-semibold leading-snug break-words", children: subject?.trim() || "Speciale aanbieding voor u!" }), _jsxs("div", { className: "mt-1 text-xs text-muted-foreground truncate", children: ["Van: ", fromName?.trim() || "Aanbiedingsmailtje"] })] }), _jsxs("div", { className: "flex flex-col items-center gap-2 px-4 py-4 text-center", style: { backgroundColor: brand.primary }, children: [brand.logoUrl && (_jsx("img", { src: brand.logoUrl, alt: "", className: "h-8 w-auto max-w-[160px] object-contain" })), _jsx("div", { className: "text-sm font-bold", style: { color: "#ffffff" }, children: subject?.trim() || "Speciale aanbieding voor u!" })] }), _jsxs("div", { className: "space-y-4 px-4 py-4", children: [_jsx("p", { className: "text-sm text-muted-foreground whitespace-pre-wrap", children: intro?.trim() || "Korte samenvatting van je aanbieding..." }), _jsx("button", { className: "w-full rounded-md px-4 py-2 text-sm font-semibold", type: "button", disabled: true, style: { backgroundColor: brand.button, color: brand.buttonText }, children: "\uD83D\uDED2 Direct Bestellen" }), _jsxs("div", { className: "rounded-md border p-3 space-y-3", children: [_jsx("div", { className: "text-sm font-medium", children: "Producten in deze aanbieding" }), safeProducts.length === 0 ? (_jsx("div", { className: cn("grid gap-2", isMobile ? "grid-cols-2" : "grid-cols-3"), children: [0, 1, 2].map((i) => (_jsxs("div", { className: "rounded-md border bg-muted/40 p-3 space-y-2", children: [_jsx("div", { className: "flex h-16 items-center justify-center rounded bg-muted", children: _jsx(Package, { className: "h-5 w-5 text-muted-foreground" }) }), _jsx("div", { className: "h-2 w-3/4 rounded bg-muted" }), _jsx("div", { className: "h-2 w-1/2 rounded bg-muted" })] }, i))) })) : (_jsx("div", { className: cn("grid gap-2", isMobile ? "grid-cols-1" : "grid-cols-2"), children: safeProducts.map((p) => {
|
|
17
|
-
const tiers =
|
|
17
|
+
const tiers = validTiers(Array.isArray(p.tiers) ? p.tiers : []);
|
|
18
18
|
return (_jsxs("div", { className: "rounded-md border p-2 space-y-2", children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("div", { className: "h-14 w-14 shrink-0 overflow-hidden rounded border bg-muted flex items-center justify-center", children: p.image_url ? (_jsx("img", { src: p.image_url, alt: p.product_name, className: "h-full w-full object-cover" })) : (_jsx(Package, { className: "h-5 w-5 text-muted-foreground" })) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "text-sm font-medium leading-tight break-words", children: p.product_name }), _jsxs("div", { className: "mt-0.5 flex flex-wrap items-baseline gap-1.5", children: [_jsx("span", { className: "text-sm font-semibold text-primary", children: euro(p.crate_price) }), p.normal_price > p.crate_price && (_jsx("span", { className: "text-xs text-muted-foreground line-through", children: euro(p.normal_price) }))] })] })] }), p.description?.trim() && (_jsx("p", { className: "text-xs text-muted-foreground break-words", children: p.description })), tiers.length > 0 && (_jsx("ul", { className: "space-y-0.5 text-xs text-muted-foreground", children: tiers.map((t, i) => {
|
|
19
19
|
const pct = discountPercent(p.normal_price, t.price_per_crate);
|
|
20
20
|
return (_jsxs("li", { children: ["Vanaf ", t.min_crates, " fust(en): ", euro(t.price_per_crate), pct > 0 ? ` (-${pct}%)` : ""] }, i));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NietGekoppeldeBestellingen.d.ts","sourceRoot":"","sources":["../../../src/components/overzicht/NietGekoppeldeBestellingen.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"NietGekoppeldeBestellingen.d.ts","sourceRoot":"","sources":["../../../src/components/overzicht/NietGekoppeldeBestellingen.tsx"],"names":[],"mappings":"AAkEA,wBAAgB,0BAA0B,uCAsBzC"}
|
|
@@ -43,7 +43,7 @@ function Row({ o, onDone }) {
|
|
|
43
43
|
setBusy(false);
|
|
44
44
|
}
|
|
45
45
|
};
|
|
46
|
-
return (_jsxs("div", { className: "space-y-2 rounded-lg border p-3", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [_jsxs("div", { children: [_jsxs("p", { className: "font-medium", children: [o.order_number ?? o.id.slice(0, 8), " \u00B7 ", o.customer_name] }), _jsxs("p", { className: "text-xs text-muted-foreground", children: [o.customer_email, " \u00B7 ", new Date(o.created_at).toLocaleString("nl-NL"), " \u00B7 ", euro(Number(o.total_amount ?? 0))] })] }), o.
|
|
46
|
+
return (_jsxs("div", { className: "space-y-2 rounded-lg border p-3", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [_jsxs("div", { children: [_jsxs("p", { className: "font-medium", children: [o.order_number ?? o.id.slice(0, 8), " \u00B7 ", o.customer_name] }), _jsxs("p", { className: "text-xs text-muted-foreground", children: [o.customer_email, " \u00B7 ", new Date(o.created_at).toLocaleString("nl-NL"), " \u00B7 ", euro(Number(o.total_amount ?? 0))] })] }), Number(o.order_creation_attempts ?? 0) >= 10 && _jsx(Badge, { variant: "destructive", children: "Lukt niet automatisch, kijk even na" }), o.order_creation_error && _jsx("span", { className: "text-xs text-muted-foreground", title: "Details voor beheer", children: o.order_creation_error })] }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Input, { className: "max-w-xs", placeholder: "Zoek klant (naam, e-mail, nummer)", value: q, onChange: (e) => setQ(e.target.value) }), _jsxs("select", { className: "rounded-md border bg-background px-2 text-sm", value: choice, onChange: (e) => setChoice(e.target.value), children: [_jsx("option", { value: "", children: "\u2014 kies klant \u2014" }), results.map((c) => (_jsxs("option", { value: c.id, children: [c.company_name ?? "(naamloos)", c.email ? ` · ${c.email}` : "", c.customer_number ? ` · ${c.customer_number}` : ""] }, c.id)))] }), _jsx(Button, { size: "sm", disabled: busy || !choice, onClick: submit, children: "Koppelen en order aanmaken" })] })] }));
|
|
47
47
|
}
|
|
48
48
|
export function NietGekoppeldeBestellingen() {
|
|
49
49
|
const list = useServerFn(listUnlinkedOfferOrders);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HuisstijlSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/HuisstijlSettingsCard.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"HuisstijlSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/HuisstijlSettingsCard.tsx"],"names":[],"mappings":"AAgCA,wBAAgB,qBAAqB,gCA0OpC"}
|
|
@@ -3,6 +3,7 @@ import { useEffect, useRef, useState } from "react";
|
|
|
3
3
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle, Button, Input, Label, supabase, toast, useAuth, } from "@flowselections/core";
|
|
4
4
|
import { Palette, Upload, Trash2, Image as ImageIcon, Loader2 } from "lucide-react";
|
|
5
5
|
import { resolveBranding, isValidHex, DEFAULT_PRIMARY } from "../../lib/branding.js";
|
|
6
|
+
import { saveOfferSettings } from "../../lib/offer-settings.functions.js";
|
|
6
7
|
import { uploadBrandingLogo, deleteBrandingLogo } from "../../lib/branding.functions.js";
|
|
7
8
|
const BUCKET = "offer-branding";
|
|
8
9
|
const MAX_BYTES = 2 * 1024 * 1024;
|
|
@@ -46,12 +47,7 @@ export function HuisstijlSettingsCard() {
|
|
|
46
47
|
const primaryValid = isValidHex(state.primary_color);
|
|
47
48
|
const buttonValid = isValidHex(state.button_color);
|
|
48
49
|
const persistLogoUrl = async (url) => {
|
|
49
|
-
|
|
50
|
-
.from("offer_settings")
|
|
51
|
-
.update({ logo_url: url || null })
|
|
52
|
-
.eq("singleton", true);
|
|
53
|
-
if (error)
|
|
54
|
-
throw error;
|
|
50
|
+
await saveOfferSettings({ data: { logo_url: url || null } });
|
|
55
51
|
};
|
|
56
52
|
const onFile = async (file) => {
|
|
57
53
|
if (!ALLOWED.includes(file.type)) {
|
|
@@ -106,21 +102,16 @@ export function HuisstijlSettingsCard() {
|
|
|
106
102
|
}
|
|
107
103
|
setSaving(true);
|
|
108
104
|
try {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
button_color: brand.button,
|
|
116
|
-
})
|
|
117
|
-
.eq("singleton", true);
|
|
118
|
-
if (error)
|
|
119
|
-
throw error;
|
|
105
|
+
await saveOfferSettings({ data: {
|
|
106
|
+
brand_name: state.brand_name.trim() || null,
|
|
107
|
+
logo_url: state.logo_url.trim() || null,
|
|
108
|
+
primary_color: brand.primary,
|
|
109
|
+
button_color: brand.button,
|
|
110
|
+
} });
|
|
120
111
|
toast.success("Opgeslagen");
|
|
121
112
|
}
|
|
122
113
|
catch (e) {
|
|
123
|
-
toast.error(e?.message ?? "
|
|
114
|
+
toast.error(e?.message ?? "Je instellingen zijn niet opgeslagen.");
|
|
124
115
|
}
|
|
125
116
|
finally {
|
|
126
117
|
setSaving(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StickerSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/StickerSettingsCard.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"StickerSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/StickerSettingsCard.tsx"],"names":[],"mappings":"AAKA,wBAAgB,mBAAmB,gCA0DlC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { saveOfferSettings } from "../../lib/offer-settings.functions.js";
|
|
2
3
|
import { useState, useEffect } from "react";
|
|
3
4
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle, Button, Label, Input, supabase, toast, useAuth } from "@flowselections/core";
|
|
4
5
|
import { Tag } from "lucide-react";
|
|
@@ -22,16 +23,11 @@ export function StickerSettingsCard() {
|
|
|
22
23
|
}
|
|
23
24
|
setSaving(true);
|
|
24
25
|
try {
|
|
25
|
-
|
|
26
|
-
.from("offer_settings")
|
|
27
|
-
.update({ default_sticker_cost: v })
|
|
28
|
-
.eq("singleton", true);
|
|
29
|
-
if (error)
|
|
30
|
-
throw error;
|
|
26
|
+
await saveOfferSettings({ data: { default_sticker_cost: v } });
|
|
31
27
|
toast.success("Opgeslagen");
|
|
32
28
|
}
|
|
33
29
|
catch (e) {
|
|
34
|
-
toast.error(e?.message ?? "
|
|
30
|
+
toast.error(e?.message ?? "Je instellingen zijn niet opgeslagen.");
|
|
35
31
|
}
|
|
36
32
|
finally {
|
|
37
33
|
setSaving(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TrackingSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/TrackingSettingsCard.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TrackingSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/TrackingSettingsCard.tsx"],"names":[],"mappings":"AAKA,wBAAgB,oBAAoB,gCAsDnC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { saveOfferSettings } from "../../lib/offer-settings.functions.js";
|
|
2
3
|
import { useState, useEffect } from "react";
|
|
3
4
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle, Button, Label, Switch, supabase, toast, useAuth, Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@flowselections/core";
|
|
4
5
|
import { Eye } from "lucide-react";
|
|
@@ -14,13 +15,11 @@ export function TrackingSettingsCard() {
|
|
|
14
15
|
const save = async () => {
|
|
15
16
|
setSaving(true);
|
|
16
17
|
try {
|
|
17
|
-
|
|
18
|
-
if (error)
|
|
19
|
-
throw error;
|
|
18
|
+
await saveOfferSettings({ data: state });
|
|
20
19
|
toast.success("Opgeslagen");
|
|
21
20
|
}
|
|
22
21
|
catch (e) {
|
|
23
|
-
toast.error(e?.message ?? "
|
|
22
|
+
toast.error(e?.message ?? "Je instellingen zijn niet opgeslagen.");
|
|
24
23
|
}
|
|
25
24
|
finally {
|
|
26
25
|
setSaving(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UitsluitingenSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/UitsluitingenSettingsCard.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"UitsluitingenSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/UitsluitingenSettingsCard.tsx"],"names":[],"mappings":"AAOA,wBAAgB,yBAAyB,gCA8DxC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { saveOfferSettings } from "../../lib/offer-settings.functions.js";
|
|
2
3
|
import { useState, useEffect } from "react";
|
|
3
4
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle, Button, Label, supabase, toast, useAuth, Badge } from "@flowselections/core";
|
|
4
5
|
import { UserX, X } from "lucide-react";
|
|
@@ -23,13 +24,11 @@ export function UitsluitingenSettingsCard() {
|
|
|
23
24
|
const save = async () => {
|
|
24
25
|
setSaving(true);
|
|
25
26
|
try {
|
|
26
|
-
|
|
27
|
-
if (error)
|
|
28
|
-
throw error;
|
|
27
|
+
await saveOfferSettings({ data: { excluded_customer_ids: excluded } });
|
|
29
28
|
toast.success("Opgeslagen");
|
|
30
29
|
}
|
|
31
30
|
catch (e) {
|
|
32
|
-
toast.error(e?.message ?? "
|
|
31
|
+
toast.error(e?.message ?? "Je instellingen zijn niet opgeslagen.");
|
|
33
32
|
}
|
|
34
33
|
finally {
|
|
35
34
|
setSaving(false);
|
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;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;AACnD,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACxG,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC9F,OAAO,EAAE,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AACnG,OAAO,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,wCAAwC,CAAC;AAC/F,OAAO,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAClG,OAAO,EAAE,0BAA0B,EAAE,MAAM,mDAAmD,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,iBAAiB,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAChK,cAAc,wBAAwB,CAAC;AACvC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;
|
|
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;AACnD,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACxG,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC9F,OAAO,EAAE,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AACnG,OAAO,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,wCAAwC,CAAC;AAC/F,OAAO,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAClG,OAAO,EAAE,0BAA0B,EAAE,MAAM,mDAAmD,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,iBAAiB,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAChK,cAAc,wBAAwB,CAAC;AACvC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAQ/B,eAAO,MAAM,yBAAyB,EAAE,UAevC,CAAC"}
|
package/dist-lib/index.js
CHANGED
|
@@ -19,7 +19,6 @@ import { HuisstijlSettingsCard } from "./components/settings/HuisstijlSettingsCa
|
|
|
19
19
|
import { TrackingSettingsCard } from "./components/settings/TrackingSettingsCard.js";
|
|
20
20
|
import { UitsluitingenSettingsCard } from "./components/settings/UitsluitingenSettingsCard.js";
|
|
21
21
|
import { StickerSettingsCard } from "./components/settings/StickerSettingsCard.js";
|
|
22
|
-
import { TestmailCard } from "./components/settings/TestmailCard.js";
|
|
23
22
|
export const actiemailKwekersErpMathot = {
|
|
24
23
|
id: "aanbiedingsmailtje",
|
|
25
24
|
name: "Aanbiedingsmailtje",
|
|
@@ -34,6 +33,5 @@ export const actiemailKwekersErpMathot = {
|
|
|
34
33
|
{ component: TrackingSettingsCard, order: 30 },
|
|
35
34
|
{ component: StickerSettingsCard, order: 35 },
|
|
36
35
|
{ component: UitsluitingenSettingsCard, order: 40 },
|
|
37
|
-
{ component: TestmailCard, order: 50 },
|
|
38
36
|
],
|
|
39
37
|
};
|