@flowselections/actie-mail-kwekers-erp-mathot 1.0.23 → 1.0.25
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.js +6 -6
- package/dist-lib/components/ActiePage.d.ts.map +1 -1
- package/dist-lib/components/ActiePage.js +9 -5
- package/dist-lib/components/CampagneDetail.js +2 -2
- package/dist-lib/components/CampagneOverzicht.d.ts.map +1 -1
- package/dist-lib/components/CampagneOverzicht.js +3 -2
- package/dist-lib/components/aanbieding/EmailPreview.d.ts +1 -1
- package/dist-lib/components/aanbieding/EmailPreview.js +2 -2
- package/dist-lib/components/overzicht/NietGekoppeldeBestellingen.d.ts +2 -0
- package/dist-lib/components/overzicht/NietGekoppeldeBestellingen.d.ts.map +1 -0
- package/dist-lib/components/overzicht/NietGekoppeldeBestellingen.js +58 -0
- package/dist-lib/components/settings/HuisstijlSettingsCard.js +2 -2
- package/dist-lib/index.d.ts +1 -0
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +1 -0
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +18022 -9825
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.d.ts +2 -22013
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.js +6 -13
- package/dist-lib/integrations/supabase/client.server.d.ts +18022 -9825
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.js +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +18402 -10109
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.js +1 -0
- package/dist-lib/lib/branding.functions.d.ts +57417 -32826
- package/dist-lib/lib/branding.functions.d.ts.map +1 -1
- package/dist-lib/lib/branding.functions.js +1 -1
- package/dist-lib/lib/campaigns.functions.d.ts +108258 -67273
- package/dist-lib/lib/campaigns.functions.d.ts.map +1 -1
- package/dist-lib/lib/campaigns.functions.js +3 -3
- package/dist-lib/lib/public-offer.functions.d.ts +9 -2
- package/dist-lib/lib/public-offer.functions.d.ts.map +1 -1
- package/dist-lib/lib/public-offer.functions.js +25 -3
- package/dist-lib/lib/soft-auth.server.d.ts +1 -1
- package/dist-lib/lib/stats.functions.d.ts +18025 -9825
- package/dist-lib/lib/stats.functions.d.ts.map +1 -1
- package/dist-lib/lib/stats.functions.js +2 -2
- package/dist-lib/lib/unlinked-offer-orders.functions.d.ts +90667 -0
- package/dist-lib/lib/unlinked-offer-orders.functions.d.ts.map +1 -0
- package/dist-lib/lib/unlinked-offer-orders.functions.js +70 -0
- package/package.json +3 -3
- package/dist-lib/components/settings/AfzenderSettingsCard.d.ts +0 -2
- package/dist-lib/components/settings/AfzenderSettingsCard.d.ts.map +0 -1
- package/dist-lib/components/settings/AfzenderSettingsCard.js +0 -30
|
@@ -4,12 +4,12 @@ import { useAuth, supabase, Button, Card, CardContent, CardDescription, CardHead
|
|
|
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";
|
|
7
|
-
import { createCampaign, sendCampaign } from "../lib/campaigns.functions";
|
|
8
|
-
import { createVoorraadStockMap, voorraadAvailableStock } from "../lib/voorraad-service";
|
|
9
|
-
import { WizardSteps, AANBIEDING_STEPS } from "
|
|
10
|
-
import { EmailPreview } from "
|
|
11
|
-
import { resolveBranding } from "../lib/branding";
|
|
12
|
-
import { round2, sortTiers, validateTiers, discountPercent, applyPercentDiscount, applyAmountDiscount, discountTiersByPercent, discountTiersByAmount, } from "../lib/pricing";
|
|
7
|
+
import { createCampaign, sendCampaign } from "../lib/campaigns.functions.js";
|
|
8
|
+
import { createVoorraadStockMap, voorraadAvailableStock } from "../lib/voorraad-service.js";
|
|
9
|
+
import { WizardSteps, AANBIEDING_STEPS } from "./aanbieding/WizardSteps.js";
|
|
10
|
+
import { EmailPreview } from "./aanbieding/EmailPreview.js";
|
|
11
|
+
import { resolveBranding } from "../lib/branding.js";
|
|
12
|
+
import { round2, sortTiers, validateTiers, discountPercent, applyPercentDiscount, applyAmountDiscount, discountTiersByPercent, discountTiersByAmount, } from "../lib/pricing.js";
|
|
13
13
|
export function AanbiedingsmailtjePage() {
|
|
14
14
|
const { user } = useAuth();
|
|
15
15
|
const navigate = useNavigate();
|
|
@@ -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,gCAysBxB"}
|
|
@@ -3,10 +3,10 @@ import { useEffect, useMemo, useState } from "react";
|
|
|
3
3
|
import { useParams } from "@tanstack/react-router";
|
|
4
4
|
import { useServerFn } from "@tanstack/react-start";
|
|
5
5
|
import { Button, Input, Label, Textarea, Skeleton, toast } from "@flowselections/core";
|
|
6
|
-
import { getOfferByLinkCode, trackOfferClick, placeOfferOrder, getOfferDeliveryOptions, getOfferBranding, } from "../lib/public-offer.functions";
|
|
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
|
-
import { resolveBranding } from "../lib/branding";
|
|
9
|
-
import { sortTiers, resolveTierPrice, discountPercent } from "../lib/pricing";
|
|
8
|
+
import { resolveBranding } from "../lib/branding.js";
|
|
9
|
+
import { sortTiers, 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
|
|
@@ -262,7 +262,7 @@ export function ActiePage() {
|
|
|
262
262
|
items,
|
|
263
263
|
},
|
|
264
264
|
});
|
|
265
|
-
setPlaced({ id: r.orderId, total: r.total, orderNumber: r.orderNumber ?? null });
|
|
265
|
+
setPlaced({ id: r.orderId, total: r.total, orderNumber: r.orderNumber ?? null, unmatched: !r.ok });
|
|
266
266
|
}
|
|
267
267
|
catch (e) {
|
|
268
268
|
toast.error(e?.message ?? "Fout");
|
|
@@ -272,7 +272,11 @@ export function ActiePage() {
|
|
|
272
272
|
}
|
|
273
273
|
};
|
|
274
274
|
if (placed) {
|
|
275
|
-
|
|
275
|
+
const ref = placed.orderNumber ? placed.orderNumber : `#${placed.id.slice(0, 8)}`;
|
|
276
|
+
if (placed.unmatched) {
|
|
277
|
+
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
|
+
}
|
|
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 voor uw bestelling!" }), _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 nemen zo spoedig mogelijk contact met u op." })] }) }));
|
|
276
280
|
}
|
|
277
281
|
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
|
|
278
282
|
?.split(" ")
|
|
@@ -3,8 +3,8 @@ import { useEffect, useState } from "react";
|
|
|
3
3
|
import { useParams } from "@tanstack/react-router";
|
|
4
4
|
import { useServerFn } from "@tanstack/react-start";
|
|
5
5
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle, Badge, Button, Skeleton, toast } from "@flowselections/core";
|
|
6
|
-
import { getCampaign, sendCampaign, deleteCampaign } from "../lib/campaigns.functions";
|
|
7
|
-
import { getCampaignStats } from "../lib/stats.functions";
|
|
6
|
+
import { getCampaign, sendCampaign, deleteCampaign } from "../lib/campaigns.functions.js";
|
|
7
|
+
import { getCampaignStats } from "../lib/stats.functions.js";
|
|
8
8
|
import { Send, Trash2, Mail, MousePointerClick, ShoppingCart, Eye, ArrowLeft } from "lucide-react";
|
|
9
9
|
import { useNavigate, Link } from "@tanstack/react-router";
|
|
10
10
|
export function CampagneDetail() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CampagneOverzicht.d.ts","sourceRoot":"","sources":["../../src/components/CampagneOverzicht.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CampagneOverzicht.d.ts","sourceRoot":"","sources":["../../src/components/CampagneOverzicht.tsx"],"names":[],"mappings":"AAoBA,wBAAgB,iBAAiB,gCA0PhC"}
|
|
@@ -3,12 +3,13 @@ import { useEffect, useMemo, useState } from "react";
|
|
|
3
3
|
import { Card, CardContent, Badge, Button, Skeleton, Input } from "@flowselections/core";
|
|
4
4
|
import { Link } from "@tanstack/react-router";
|
|
5
5
|
import { useServerFn } from "@tanstack/react-start";
|
|
6
|
-
import { getOverallStats } from "../lib/stats.functions";
|
|
6
|
+
import { getOverallStats } from "../lib/stats.functions.js";
|
|
7
7
|
import { Plus, ArrowLeft, Search, BarChart3, Mail } from "lucide-react";
|
|
8
8
|
import { DateRangePicker, loadStoredRange, storeRange } from "./DateRangePicker";
|
|
9
9
|
import { PrestatieTegels } from "./overzicht/PrestatieTegels";
|
|
10
10
|
import { RecenteCampagnes } from "./overzicht/RecenteCampagnes";
|
|
11
11
|
import { TopLijsten } from "./overzicht/TopLijsten";
|
|
12
|
+
import { NietGekoppeldeBestellingen } from "./overzicht/NietGekoppeldeBestellingen";
|
|
12
13
|
import { CampaignStatusBadge, campaignStatus, campaignTimeLabel, euro } from "./overzicht/campaignStatus";
|
|
13
14
|
const STATUS_FILTERS = [
|
|
14
15
|
{ id: "all", label: "Alle" },
|
|
@@ -116,7 +117,7 @@ export function CampagneOverzicht() {
|
|
|
116
117
|
return (_jsxs("main", { className: "space-y-4 p-6", children: [_jsx(Skeleton, { className: "h-10 w-64" }), _jsx(Skeleton, { className: "h-48 w-full" }), _jsx("div", { className: "grid grid-cols-2 gap-3 md:grid-cols-6", children: Array.from({ length: 6 }).map((_, i) => _jsx(Skeleton, { className: "h-24" }, i)) }), _jsxs("div", { className: "grid gap-4 lg:grid-cols-2", children: [_jsx(Skeleton, { className: "h-56" }), _jsx(Skeleton, { className: "h-56" })] })] }));
|
|
117
118
|
}
|
|
118
119
|
const hasCampaigns = campaigns.length > 0;
|
|
119
|
-
return (_jsxs("main", { className: "space-y-6 p-6", children: [_jsx(Link, { to: "/aanbiedingsmailtje", children: _jsxs(Button, { variant: "ghost", size: "sm", className: "-ml-2", children: [_jsx(ArrowLeft, { className: "mr-1 h-4 w-4" }), "Terug"] }) }), _jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [_jsxs("div", { 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: "Campagne overzicht" })] }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Bekijk recente campagnes en prestaties op \u00E9\u00E9n plek" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(DateRangePicker, { value: range, onChange: handleChange }), _jsx(Link, { to: "/aanbiedingsmailtje", children: _jsxs(Button, { children: [_jsx(Plus, { className: "mr-1 h-4 w-4" }), "Nieuwe campagne"] }) })] })] }), _jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx("span", { children: "Periode:" }), _jsx(Badge, { variant: "secondary", className: "font-medium", children: range.label }), loading && _jsx("span", { className: "text-xs", children: "bijwerken\u2026" })] }), !hasCampaigns ? (_jsx(Card, { children: _jsxs(CardContent, { className: "p-10 text-center", children: [_jsx(Mail, { className: "mx-auto mb-3 h-10 w-10 text-muted-foreground" }), _jsx("p", { className: "text-lg font-semibold", children: "Nog geen campagnes in deze periode" }), _jsx("p", { className: "mb-4 text-sm text-muted-foreground", children: "Verruim de periode of maak direct je eerste aanbieding aan." }), _jsx(Link, { to: "/aanbiedingsmailtje", children: _jsxs(Button, { children: [_jsx(Plus, { className: "mr-1 h-4 w-4" }), "Maak je eerste aanbieding"] }) })] }) })) : (_jsx(RecenteCampagnes, { campaigns: campaigns.slice(0, 5), showingAll: showAll, onShowAll: () => setShowAll((v) => !v) })), showAll && hasCampaigns && (_jsx(Card, { children: _jsxs(CardContent, { className: "space-y-3 p-4", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsxs("div", { className: "relative min-w-[220px] flex-1", children: [_jsx(Search, { className: "absolute left-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { className: "pl-8", placeholder: "Zoek op naam of onderwerp", value: search, onChange: (e) => setSearch(e.target.value) })] }), _jsx("div", { className: "flex flex-wrap gap-1", children: STATUS_FILTERS.map((f) => (_jsx(Button, { size: "sm", variant: statusFilter === f.id ? "default" : "outline", onClick: () => setStatusFilter(f.id), children: f.label }, f.id))) })] }), filteredCampaigns.length === 0 ? (_jsx("p", { className: "py-6 text-center text-sm text-muted-foreground", children: "Geen campagnes gevonden" })) : (_jsx("div", { className: "divide-y", children: filteredCampaigns.map((c) => {
|
|
120
|
+
return (_jsxs("main", { className: "space-y-6 p-6", children: [_jsx(Link, { to: "/aanbiedingsmailtje", children: _jsxs(Button, { variant: "ghost", size: "sm", className: "-ml-2", children: [_jsx(ArrowLeft, { className: "mr-1 h-4 w-4" }), "Terug"] }) }), _jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [_jsxs("div", { 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: "Campagne overzicht" })] }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Bekijk recente campagnes en prestaties op \u00E9\u00E9n plek" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(DateRangePicker, { value: range, onChange: handleChange }), _jsx(Link, { to: "/aanbiedingsmailtje", children: _jsxs(Button, { children: [_jsx(Plus, { className: "mr-1 h-4 w-4" }), "Nieuwe campagne"] }) })] })] }), _jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx("span", { children: "Periode:" }), _jsx(Badge, { variant: "secondary", className: "font-medium", children: range.label }), loading && _jsx("span", { className: "text-xs", children: "bijwerken\u2026" })] }), _jsx(NietGekoppeldeBestellingen, {}), !hasCampaigns ? (_jsx(Card, { children: _jsxs(CardContent, { className: "p-10 text-center", children: [_jsx(Mail, { className: "mx-auto mb-3 h-10 w-10 text-muted-foreground" }), _jsx("p", { className: "text-lg font-semibold", children: "Nog geen campagnes in deze periode" }), _jsx("p", { className: "mb-4 text-sm text-muted-foreground", children: "Verruim de periode of maak direct je eerste aanbieding aan." }), _jsx(Link, { to: "/aanbiedingsmailtje", children: _jsxs(Button, { children: [_jsx(Plus, { className: "mr-1 h-4 w-4" }), "Maak je eerste aanbieding"] }) })] }) })) : (_jsx(RecenteCampagnes, { campaigns: campaigns.slice(0, 5), showingAll: showAll, onShowAll: () => setShowAll((v) => !v) })), showAll && hasCampaigns && (_jsx(Card, { children: _jsxs(CardContent, { className: "space-y-3 p-4", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsxs("div", { className: "relative min-w-[220px] flex-1", children: [_jsx(Search, { className: "absolute left-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { className: "pl-8", placeholder: "Zoek op naam of onderwerp", value: search, onChange: (e) => setSearch(e.target.value) })] }), _jsx("div", { className: "flex flex-wrap gap-1", children: STATUS_FILTERS.map((f) => (_jsx(Button, { size: "sm", variant: statusFilter === f.id ? "default" : "outline", onClick: () => setStatusFilter(f.id), children: f.label }, f.id))) })] }), filteredCampaigns.length === 0 ? (_jsx("p", { className: "py-6 text-center text-sm text-muted-foreground", children: "Geen campagnes gevonden" })) : (_jsx("div", { className: "divide-y", children: filteredCampaigns.map((c) => {
|
|
120
121
|
const s = c.stats ?? { sent: 0, opened: 0, clicked: 0, orders: 0, revenue: 0 };
|
|
121
122
|
return (_jsxs(Link, { to: "/aanbiedingsmailtje/$campaignId", params: { campaignId: c.id }, className: "flex flex-wrap items-center gap-3 py-3 hover:bg-muted/40", children: [_jsxs("div", { className: "min-w-[200px] flex-1", children: [_jsx("div", { className: "truncate font-medium", children: c.name }), _jsx("div", { className: "truncate text-xs text-muted-foreground", children: c.subject ?? "" })] }), _jsx("span", { className: "text-xs text-muted-foreground", children: campaignTimeLabel(c) }), _jsx(CampaignStatusBadge, { status: c.status }), _jsxs("span", { className: "text-sm text-muted-foreground", children: [s.sent, " verzonden \u00B7 ", s.opened, " geopend \u00B7 ", s.orders, " bestellingen \u00B7 ", euro(s.revenue)] })] }, c.id));
|
|
122
123
|
}) }))] }) })), _jsxs("div", { className: "space-y-2", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Prestatieoverzicht" }), _jsx(PrestatieTegels, { totals: data?.totals, previousTotals: data?.previousTotals })] }), _jsx(TopLijsten, { customers: topCustomers, products: topProducts })] }));
|
|
@@ -2,8 +2,8 @@ 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 { sortTiers, discountPercent } from "../../lib/pricing";
|
|
6
|
-
import { resolveBranding } from "../../lib/branding";
|
|
5
|
+
import { sortTiers, discountPercent } from "../../lib/pricing.js";
|
|
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 }) {
|
|
9
9
|
const [device, setDevice] = useState("desktop");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NietGekoppeldeBestellingen.d.ts","sourceRoot":"","sources":["../../../src/components/overzicht/NietGekoppeldeBestellingen.tsx"],"names":[],"mappings":"AAiEA,wBAAgB,0BAA0B,uCAsBzC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { Card, CardContent, Button, Input, Badge } from "@flowselections/core";
|
|
4
|
+
import { useServerFn } from "@tanstack/react-start";
|
|
5
|
+
import { toast } from "sonner";
|
|
6
|
+
import { AlertTriangle } from "lucide-react";
|
|
7
|
+
import { listUnlinkedOfferOrders, searchCustomersForLink, relinkOfferOrder, } from "../../lib/unlinked-offer-orders.functions.js";
|
|
8
|
+
import { euro } from "./campaignStatus";
|
|
9
|
+
function Row({ o, onDone }) {
|
|
10
|
+
const search = useServerFn(searchCustomersForLink);
|
|
11
|
+
const relink = useServerFn(relinkOfferOrder);
|
|
12
|
+
const [q, setQ] = useState(o.customer_email ?? "");
|
|
13
|
+
const [results, setResults] = useState([]);
|
|
14
|
+
const [choice, setChoice] = useState("");
|
|
15
|
+
const [busy, setBusy] = useState(false);
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const t = setTimeout(async () => {
|
|
18
|
+
try {
|
|
19
|
+
const r = await search({ data: { q } });
|
|
20
|
+
setResults(Array.isArray(r?.items) ? r.items : []);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
setResults([]);
|
|
24
|
+
}
|
|
25
|
+
}, 250);
|
|
26
|
+
return () => clearTimeout(t);
|
|
27
|
+
}, [q]);
|
|
28
|
+
const submit = async () => {
|
|
29
|
+
if (!choice) {
|
|
30
|
+
toast.error("Kies eerst een klant");
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
setBusy(true);
|
|
34
|
+
try {
|
|
35
|
+
const r = await relink({ data: { offerOrderId: o.id, customerId: choice } });
|
|
36
|
+
toast.success(`Order ${r.orderNumber ?? ""} aangemaakt`);
|
|
37
|
+
onDone();
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
toast.error(e?.message ?? "Koppelen mislukt");
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
setBusy(false);
|
|
44
|
+
}
|
|
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.order_creation_error && _jsx(Badge, { variant: "destructive", 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
|
+
}
|
|
48
|
+
export function NietGekoppeldeBestellingen() {
|
|
49
|
+
const list = useServerFn(listUnlinkedOfferOrders);
|
|
50
|
+
const [items, setItems] = useState([]);
|
|
51
|
+
const [key, setKey] = useState(0);
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
list().then((r) => setItems(Array.isArray(r?.items) ? r.items : [])).catch(() => setItems([]));
|
|
54
|
+
}, [key]);
|
|
55
|
+
if (items.length === 0)
|
|
56
|
+
return null;
|
|
57
|
+
return (_jsx(Card, { className: "border-destructive/40", children: _jsxs(CardContent, { className: "space-y-3 p-4", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(AlertTriangle, { className: "h-5 w-5 text-destructive" }), _jsxs("p", { className: "font-semibold", children: ["Niet gekoppelde bestellingen (", items.length, ")"] })] }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Deze bestellingen staan nog niet in de orders. Koppel de juiste klant, dan wordt de order alsnog aangemaakt." }), items.map((o) => _jsx(Row, { o: o, onDone: () => setKey((k) => k + 1) }, o.id))] }) }));
|
|
58
|
+
}
|
|
@@ -2,8 +2,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
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
|
-
import { resolveBranding, isValidHex, DEFAULT_PRIMARY } from "../../lib/branding";
|
|
6
|
-
import { uploadBrandingLogo, deleteBrandingLogo } from "../../lib/branding.functions";
|
|
5
|
+
import { resolveBranding, isValidHex, DEFAULT_PRIMARY } from "../../lib/branding.js";
|
|
6
|
+
import { uploadBrandingLogo, deleteBrandingLogo } from "../../lib/branding.functions.js";
|
|
7
7
|
const BUCKET = "offer-branding";
|
|
8
8
|
const MAX_BYTES = 2 * 1024 * 1024;
|
|
9
9
|
const ALLOWED = ["image/png", "image/jpeg", "image/webp", "image/svg+xml"];
|
package/dist-lib/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export { EmailPreview, type EmailPreviewProduct } from "./components/aanbieding/
|
|
|
10
10
|
export { RecenteCampagnes, type OverzichtCampaign } from "./components/overzicht/RecenteCampagnes";
|
|
11
11
|
export { PrestatieTegels, type PrestatieTotals } from "./components/overzicht/PrestatieTegels";
|
|
12
12
|
export { TopLijsten, type TopCustomer, type TopProduct } from "./components/overzicht/TopLijsten";
|
|
13
|
+
export { NietGekoppeldeBestellingen } from "./components/overzicht/NietGekoppeldeBestellingen";
|
|
13
14
|
export { CampaignStatusBadge, campaignStatus, campaignTimeLabel, type CampaignStatusInfo, type CampaignStatusKey } from "./components/overzicht/campaignStatus";
|
|
14
15
|
export * from "./lib/voorraad-service";
|
|
15
16
|
export * from "./lib/pricing";
|
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,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;AAS/B,eAAO,MAAM,yBAAyB,EAAE,UAgBvC,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;AAS/B,eAAO,MAAM,yBAAyB,EAAE,UAgBvC,CAAC"}
|
package/dist-lib/index.js
CHANGED
|
@@ -10,6 +10,7 @@ export { EmailPreview } from "./components/aanbieding/EmailPreview";
|
|
|
10
10
|
export { RecenteCampagnes } from "./components/overzicht/RecenteCampagnes";
|
|
11
11
|
export { PrestatieTegels } from "./components/overzicht/PrestatieTegels";
|
|
12
12
|
export { TopLijsten } from "./components/overzicht/TopLijsten";
|
|
13
|
+
export { NietGekoppeldeBestellingen } from "./components/overzicht/NietGekoppeldeBestellingen";
|
|
13
14
|
export { CampaignStatusBadge, campaignStatus, campaignTimeLabel } from "./components/overzicht/campaignStatus";
|
|
14
15
|
export * from "./lib/voorraad-service";
|
|
15
16
|
export * from "./lib/pricing";
|