@flowselections/actie-mail-kwekers-erp-mathot 1.0.8 → 1.0.9
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 +39 -6
- package/dist-lib/components/ActiePage.d.ts.map +1 -1
- package/dist-lib/components/ActiePage.js +37 -8
- 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 +1285 -23
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.d.ts +1285 -23
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +1285 -23
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +1297 -17
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/campaigns.functions.d.ts +6310 -0
- package/dist-lib/lib/campaigns.functions.d.ts.map +1 -1
- package/dist-lib/lib/campaigns.functions.js +1 -1
- package/dist-lib/lib/public-offer.functions.d.ts.map +1 -1
- package/dist-lib/lib/public-offer.functions.js +37 -21
- package/dist-lib/lib/stats.functions.d.ts +2671 -147
- package/dist-lib/lib/stats.functions.d.ts.map +1 -1
- package/dist-lib/lib/voorraad-service.d.ts +23 -0
- package/dist-lib/lib/voorraad-service.d.ts.map +1 -0
- package/dist-lib/lib/voorraad-service.js +31 -0
- package/package.json +2 -2
|
@@ -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":"AA0CA,wBAAgB,sBAAsB,gCAylBrC"}
|
|
@@ -5,6 +5,7 @@ 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, List, BarChart3 } from "lucide-react";
|
|
7
7
|
import { createCampaign, sendCampaign } from "../lib/campaigns.functions";
|
|
8
|
+
import { createVoorraadStockMap, voorraadAvailableStock } from "../lib/voorraad-service";
|
|
8
9
|
export function AanbiedingsmailtjePage() {
|
|
9
10
|
const { user } = useAuth();
|
|
10
11
|
const navigate = useNavigate();
|
|
@@ -69,13 +70,25 @@ export function AanbiedingsmailtjePage() {
|
|
|
69
70
|
.order("updated_at", { ascending: false })
|
|
70
71
|
.limit(1000)
|
|
71
72
|
: Promise.resolve({ data: [] });
|
|
72
|
-
const
|
|
73
|
+
const stockPromise = activeId
|
|
74
|
+
? sb.from("trade_item_stock")
|
|
75
|
+
.select("trade_item_key, physical_stock, reserved_stock, updated_at")
|
|
76
|
+
.eq("connection_id", activeId)
|
|
77
|
+
.limit(5000)
|
|
78
|
+
: Promise.resolve({ data: [] });
|
|
79
|
+
const [{ data: cacheRows }, { data: draftRows }, { data: stockRows }, { data: cs }, { data: extCs }, { data: settings }] = await Promise.all([
|
|
73
80
|
cachePromise,
|
|
74
81
|
draftPromise,
|
|
82
|
+
stockPromise,
|
|
75
83
|
sb.from("customers").select("id, company_name, email, customer_class, country").not("email", "is", null).order("company_name").limit(1000),
|
|
76
84
|
sb.from("external_customers_grouped").select("group_key, display_name, email, country, is_active").not("email", "is", null).eq("is_active", true).limit(2000),
|
|
77
85
|
sb.from("offer_settings").select("default_subject, default_intro, default_sticker_cost, show_customer_classes").maybeSingle(),
|
|
78
86
|
]);
|
|
87
|
+
const stockMap = createVoorraadStockMap((Array.isArray(stockRows) ? stockRows : []));
|
|
88
|
+
const stockFor = (key) => {
|
|
89
|
+
const s = stockMap.get(key);
|
|
90
|
+
return voorraadAvailableStock(s);
|
|
91
|
+
};
|
|
79
92
|
const pickName = (n) => {
|
|
80
93
|
if (!n)
|
|
81
94
|
return "";
|
|
@@ -94,28 +107,48 @@ export function AanbiedingsmailtjePage() {
|
|
|
94
107
|
return d.imageUrls[0];
|
|
95
108
|
return null;
|
|
96
109
|
};
|
|
110
|
+
const pickPacking = (d) => {
|
|
111
|
+
const cfgs = Array.isArray(d?.packingConfigurations) ? d.packingConfigurations : [];
|
|
112
|
+
const primary = cfgs.find((c) => c?.primary) ?? cfgs[0];
|
|
113
|
+
if (!primary)
|
|
114
|
+
return { plants_per_crate: null, belading: null };
|
|
115
|
+
const ppc = Number(primary.piecesPerPackage);
|
|
116
|
+
const perLayer = Number(primary.packagesPerLayer);
|
|
117
|
+
const layers = Number(primary.layersPerLoadCarrier);
|
|
118
|
+
const parts = [ppc, perLayer, layers].filter((n) => Number.isFinite(n) && n > 0);
|
|
119
|
+
return {
|
|
120
|
+
plants_per_crate: Number.isFinite(ppc) && ppc > 0 ? ppc : null,
|
|
121
|
+
belading: parts.length === 3 ? `${ppc}x${perLayer}x${layers}` : null,
|
|
122
|
+
};
|
|
123
|
+
};
|
|
97
124
|
const published = (cacheRows ?? []).map((r) => {
|
|
98
125
|
const d = r.data ?? {};
|
|
126
|
+
const packing = pickPacking(d);
|
|
99
127
|
return {
|
|
100
128
|
id: r.floriday_id,
|
|
101
129
|
product: pickName(d.tradeItemName) || pickName(d.name) || pickName(d.vbnName) || (d.botanicalNames?.[0] ?? "(naamloos)"),
|
|
102
130
|
sale_price: null,
|
|
103
|
-
quantity:
|
|
131
|
+
quantity: stockFor(r.floriday_id),
|
|
104
132
|
image_url: pickImage(d),
|
|
105
133
|
barcode: d.supplierArticleCode ?? d.articleCode ?? d.gtin ?? d.articleGtin ?? d.tradeItemReference ?? "",
|
|
134
|
+
plants_per_crate: packing.plants_per_crate,
|
|
135
|
+
belading: packing.belading,
|
|
106
136
|
is_draft: false,
|
|
107
137
|
};
|
|
108
138
|
});
|
|
109
139
|
const drafts = (draftRows ?? []).map((r) => {
|
|
110
140
|
const d = r.data ?? {};
|
|
111
141
|
const firstImage = Array.isArray(d.images) && d.images[0] ? d.images[0] : null;
|
|
142
|
+
const packing = pickPacking(d);
|
|
112
143
|
return {
|
|
113
144
|
id: `local:${r.id}`,
|
|
114
145
|
product: d.name || d.vbnName || "(naamloos)",
|
|
115
146
|
sale_price: null,
|
|
116
|
-
quantity:
|
|
147
|
+
quantity: stockFor(`draft:${r.id}`),
|
|
117
148
|
image_url: firstImage?.url ?? firstImage?.previewUrl ?? null,
|
|
118
149
|
barcode: d.articleCode ?? d.gtin ?? "",
|
|
150
|
+
plants_per_crate: packing.plants_per_crate,
|
|
151
|
+
belading: packing.belading,
|
|
119
152
|
is_draft: true,
|
|
120
153
|
};
|
|
121
154
|
});
|
|
@@ -168,8 +201,8 @@ export function AanbiedingsmailtjePage() {
|
|
|
168
201
|
normal_price: 0,
|
|
169
202
|
discount_price: 0,
|
|
170
203
|
available_stock: p.quantity ?? 0,
|
|
171
|
-
plants_per_crate: 10,
|
|
172
|
-
belading: "",
|
|
204
|
+
plants_per_crate: p.plants_per_crate ?? 10,
|
|
205
|
+
belading: p.belading ?? "",
|
|
173
206
|
barcode: p.barcode ?? "",
|
|
174
207
|
crate_price: 0,
|
|
175
208
|
sticker_cost: null,
|
|
@@ -306,7 +339,7 @@ export function AanbiedingsmailtjePage() {
|
|
|
306
339
|
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", { children: [_jsx("div", { className: "font-medium text-sm", children: p.product_name }), _jsxs("div", { className: "text-xs text-muted-foreground", children: ["Originele prijs: \u20AC ", p.normal_price.toFixed(2)] })] }), _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(Input, { type: "number", value: p.plants_per_crate, onChange: (e) => updateProd(p.product_id, { plants_per_crate: Number(e.target.value) }) })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Label, { className: "text-xs w-20 shrink-0", children: "Belading:" }), _jsx(Input, { placeholder: "AxBxC", value: p.belading, onChange: (e) => updateProd(p.product_id, { belading: e.target.value }) })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Label, { className: "text-xs w-24 shrink-0", children: "Barcode:" }), _jsx(Input, { value: p.barcode, onChange: (e) => updateProd(p.product_id, { barcode: e.target.value }) })] }), _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", value: p.crate_price, onChange: (e) => updateProd(p.product_id, { crate_price: Number(e.target.value) }) })] })] }), _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) => {
|
|
307
340
|
const pct = p.normal_price > 0 ? Math.round((1 - t.price_per_crate / p.normal_price) * 100) : 0;
|
|
308
341
|
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, "%)"] }), p.tiers.length > 1 && (_jsx(Button, { variant: "ghost", size: "icon", className: "h-7 w-7", onClick: () => removeTier(idx), children: _jsx(X, { className: "h-3 w-3" }) }))] }, idx));
|
|
309
|
-
})] }),
|
|
342
|
+
})] }), _jsx(Textarea, { placeholder: "Omschrijving (optioneel)", rows: 2, value: p.description, onChange: (e) => updateProd(p.product_id, { description: e.target.value }) })] }, p.product_id));
|
|
310
343
|
}) })] }))] })] }), _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: "Klanten Selecteren" })] }), _jsx(CardDescription, { children: "Kies klanten om de actie naar te versturen" })] }), _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) => {
|
|
311
344
|
const allSel = g.customers.length > 0 && g.customers.every((c) => selCustomers.has(c.id));
|
|
312
345
|
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));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActiePage.d.ts","sourceRoot":"","sources":["../../src/components/ActiePage.tsx"],"names":[],"mappings":"AAqCA,wBAAgB,SAAS,
|
|
1
|
+
{"version":3,"file":"ActiePage.d.ts","sourceRoot":"","sources":["../../src/components/ActiePage.tsx"],"names":[],"mappings":"AAqCA,wBAAgB,SAAS,gCAoexB"}
|
|
@@ -83,19 +83,46 @@ export function ActiePage() {
|
|
|
83
83
|
}
|
|
84
84
|
const safeProducts = Array.isArray(data?.products) ? data.products : [];
|
|
85
85
|
const lineFor = (p) => {
|
|
86
|
-
const stockPlants = Math.max(0, Number(p.live_stock ??
|
|
86
|
+
const stockPlants = Math.max(0, Number(p.live_stock ?? 0));
|
|
87
87
|
const ppc = Math.max(1, Math.floor(Number(p.plants_per_crate ?? 1) || 1));
|
|
88
88
|
const maxCrates = Math.floor(stockPlants / ppc);
|
|
89
89
|
const soldOut = maxCrates <= 0;
|
|
90
90
|
const crates = Math.max(0, Math.floor(qty[p.id] ?? 0));
|
|
91
91
|
const plants = crates * ppc;
|
|
92
|
-
|
|
92
|
+
// Prijsprioriteit: (1) tier-prijs uit actie-e-mail, (2) discount_price uit e-mail,
|
|
93
|
+
// (3) standaardprijs uit artikelbeheer. De e-mailprijs is ALTIJD leidend.
|
|
94
|
+
const tiers = Array.isArray(p.tiers)
|
|
95
|
+
? [...p.tiers].map((t) => ({ min_crates: Number(t.min_crates), price_per_crate: Number(t.price_per_crate) }))
|
|
96
|
+
.sort((a, b) => a.min_crates - b.min_crates)
|
|
97
|
+
: [];
|
|
98
|
+
let unit = 0;
|
|
99
|
+
let cratePrice = 0;
|
|
100
|
+
let priceSource = "normal";
|
|
101
|
+
if (tiers.length > 0) {
|
|
102
|
+
const applicable = [...tiers].reverse().find((t) => crates >= t.min_crates) ?? tiers[0];
|
|
103
|
+
cratePrice = applicable.price_per_crate;
|
|
104
|
+
unit = cratePrice / ppc;
|
|
105
|
+
priceSource = "tier";
|
|
106
|
+
}
|
|
107
|
+
else if (Number(p.discount_price) > 0) {
|
|
108
|
+
unit = Number(p.discount_price);
|
|
109
|
+
cratePrice = unit * ppc;
|
|
110
|
+
priceSource = "discount";
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
unit = Number(p.normal_price ?? 0);
|
|
114
|
+
cratePrice = unit * ppc;
|
|
115
|
+
priceSource = "normal";
|
|
116
|
+
}
|
|
117
|
+
const priceSourceLabel = priceSource === "tier" ? "Prijs uit actie-e-mail"
|
|
118
|
+
: priceSource === "discount" ? "Actieprijs uit e-mail"
|
|
119
|
+
: "Standaardprijs artikelbeheer";
|
|
93
120
|
const stickerCost = Number(p.sticker_cost ?? 0);
|
|
94
121
|
const stickerAvail = p.sticker_available !== false;
|
|
95
122
|
const stickerOn = stickerAvail && !!sticker[p.id];
|
|
96
123
|
const productSubtotal = plants * unit;
|
|
97
124
|
const stickerSubtotal = stickerOn ? plants * stickerCost : 0;
|
|
98
|
-
return { q: crates, plants, ppc, unit, stickerCost, stickerAvail, stickerOn, productSubtotal, stickerSubtotal, total: productSubtotal + stickerSubtotal, stock: stockPlants, maxCrates, soldOut };
|
|
125
|
+
return { q: crates, plants, ppc, unit, cratePrice, priceSource, priceSourceLabel, tiers, stickerCost, stickerAvail, stickerOn, productSubtotal, stickerSubtotal, total: productSubtotal + stickerSubtotal, stock: stockPlants, maxCrates, soldOut };
|
|
99
126
|
};
|
|
100
127
|
const totalAmount = safeProducts.reduce((s, p) => s + lineFor(p).total, 0);
|
|
101
128
|
const hasItems = safeProducts.some((p) => (qty[p.id] ?? 0) > 0);
|
|
@@ -108,7 +135,7 @@ export function ActiePage() {
|
|
|
108
135
|
return {
|
|
109
136
|
product_id: p.id,
|
|
110
137
|
product_name: p.product_name,
|
|
111
|
-
quantity: l.
|
|
138
|
+
quantity: l.plants,
|
|
112
139
|
unit_price: l.unit,
|
|
113
140
|
sticker: l.stickerOn,
|
|
114
141
|
sticker_unit_price: l.stickerOn ? l.stickerCost : 0,
|
|
@@ -157,12 +184,14 @@ export function ActiePage() {
|
|
|
157
184
|
safeProducts.forEach((p) => { next[p.id] = false; });
|
|
158
185
|
setSticker(next);
|
|
159
186
|
}, className: "text-xs font-semibold bg-white text-blue-700 border border-blue-300 rounded px-3 py-1.5 hover:bg-blue-50", children: "Alles uit" })] })] })), _jsx("div", { className: "space-y-4", children: safeProducts.map((p) => {
|
|
160
|
-
const normal = Number(p.normal_price ?? 0);
|
|
161
|
-
const price = Number(p.discount_price ?? 0);
|
|
162
|
-
const showStrike = normal > price;
|
|
163
187
|
const l = lineFor(p);
|
|
188
|
+
const normal = Number(p.normal_price ?? 0);
|
|
189
|
+
const price = l.cratePrice > 0 ? l.cratePrice : Number(p.discount_price ?? 0);
|
|
190
|
+
const showStrike = normal > 0 && normal > price && price > 0;
|
|
164
191
|
const currentQty = l.q;
|
|
165
|
-
return (_jsxs("div", { className: `bg-white rounded-xl border shadow-sm overflow-hidden ${l.soldOut ? "border-slate-200 opacity-75" : "border-slate-200"}`, children: [_jsxs("div", { className: "p-4 flex gap-4", children: [_jsxs("div", { className: "shrink-0 relative", children: [p.image_url ? (_jsx("img", { src: p.image_url, alt: p.product_name, className: `w-24 h-24 rounded-lg object-cover border border-slate-200 bg-slate-50 ${l.soldOut ? "grayscale" : ""}` })) : (_jsx("div", { className: `w-24 h-24 rounded-lg border border-slate-200 bg-green-50 grid place-items-center overflow-hidden ${l.soldOut ? "grayscale" : ""}`, children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 96 96", className: "w-full h-full", children: [_jsx("path", { d: "M48 60 Q46 75 44 86", stroke: "#16a34a", strokeWidth: "2.5", fill: "none", strokeLinecap: "round" }), _jsx("path", { d: "M48 72 Q40 70 36 64 Q42 66 48 72", fill: "#22c55e" }), _jsx("path", { d: "M48 78 Q56 76 60 70 Q54 72 48 78", fill: "#22c55e" }), _jsxs("g", { transform: "translate(48 40)", children: [_jsx("ellipse", { cx: "0", cy: "-14", rx: "9", ry: "14", fill: "#f9a8d4" }), _jsx("ellipse", { cx: "13.3", cy: "-4.3", rx: "9", ry: "14", fill: "#f472b6", transform: "rotate(72)" }), _jsx("ellipse", { cx: "8.2", cy: "11.3", rx: "9", ry: "14", fill: "#ec4899", transform: "rotate(144)" }), _jsx("ellipse", { cx: "-8.2", cy: "11.3", rx: "9", ry: "14", fill: "#f472b6", transform: "rotate(216)" }), _jsx("ellipse", { cx: "-13.3", cy: "-4.3", rx: "9", ry: "14", fill: "#f9a8d4", transform: "rotate(288)" }), _jsx("circle", { cx: "0", cy: "0", r: "6", fill: "#fbbf24" }), _jsx("circle", { cx: "0", cy: "0", r: "3", fill: "#f59e0b" })] })] }) })), l.soldOut && (_jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: _jsx("span", { className: "bg-red-600 text-white text-xs font-bold px-2 py-1 rounded rotate-[-8deg] shadow", children: "UITVERKOCHT" }) }))] }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("div", { className: "font-bold text-slate-900 truncate", children: p.product_name }), p.plants_per_crate ? (_jsxs("div", { className: "text-sm text-slate-500", children: [p.plants_per_crate, " planten/fust"] })) : null, _jsxs("div", { className: "mt-2 flex items-baseline gap-2 flex-wrap", children: [showStrike && (_jsx("span", { className: "text-slate-400 line-through text-sm", children: fmtEuro(normal) })), _jsx("span", { className: "text-green-700 font-bold text-lg", children: fmtEuro(price) })
|
|
192
|
+
return (_jsxs("div", { className: `bg-white rounded-xl border shadow-sm overflow-hidden ${l.soldOut ? "border-slate-200 opacity-75" : "border-slate-200"}`, children: [_jsxs("div", { className: "p-4 flex gap-4", children: [_jsxs("div", { className: "shrink-0 relative", children: [p.image_url ? (_jsx("img", { src: p.image_url, alt: p.product_name, className: `w-24 h-24 rounded-lg object-cover border border-slate-200 bg-slate-50 ${l.soldOut ? "grayscale" : ""}` })) : (_jsx("div", { className: `w-24 h-24 rounded-lg border border-slate-200 bg-green-50 grid place-items-center overflow-hidden ${l.soldOut ? "grayscale" : ""}`, children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 96 96", className: "w-full h-full", children: [_jsx("path", { d: "M48 60 Q46 75 44 86", stroke: "#16a34a", strokeWidth: "2.5", fill: "none", strokeLinecap: "round" }), _jsx("path", { d: "M48 72 Q40 70 36 64 Q42 66 48 72", fill: "#22c55e" }), _jsx("path", { d: "M48 78 Q56 76 60 70 Q54 72 48 78", fill: "#22c55e" }), _jsxs("g", { transform: "translate(48 40)", children: [_jsx("ellipse", { cx: "0", cy: "-14", rx: "9", ry: "14", fill: "#f9a8d4" }), _jsx("ellipse", { cx: "13.3", cy: "-4.3", rx: "9", ry: "14", fill: "#f472b6", transform: "rotate(72)" }), _jsx("ellipse", { cx: "8.2", cy: "11.3", rx: "9", ry: "14", fill: "#ec4899", transform: "rotate(144)" }), _jsx("ellipse", { cx: "-8.2", cy: "11.3", rx: "9", ry: "14", fill: "#f472b6", transform: "rotate(216)" }), _jsx("ellipse", { cx: "-13.3", cy: "-4.3", rx: "9", ry: "14", fill: "#f9a8d4", transform: "rotate(288)" }), _jsx("circle", { cx: "0", cy: "0", r: "6", fill: "#fbbf24" }), _jsx("circle", { cx: "0", cy: "0", r: "3", fill: "#f59e0b" })] })] }) })), l.soldOut && (_jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: _jsx("span", { className: "bg-red-600 text-white text-xs font-bold px-2 py-1 rounded rotate-[-8deg] shadow", children: "UITVERKOCHT" }) }))] }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("div", { className: "font-bold text-slate-900 truncate", children: p.product_name }), p.plants_per_crate ? (_jsxs("div", { className: "text-sm text-slate-500", children: [p.plants_per_crate, " planten/fust"] })) : null, _jsxs("div", { className: "mt-2 flex items-baseline gap-2 flex-wrap", children: [showStrike && (_jsx("span", { className: "text-slate-400 line-through text-sm", children: fmtEuro(normal) })), _jsx("span", { className: "text-green-700 font-bold text-lg", children: fmtEuro(price) }), _jsx("span", { className: "text-xs text-slate-500", children: "per fust" })] }), l.tiers.length > 0 && (_jsx("div", { className: "mt-1 flex flex-wrap gap-1", children: l.tiers.map((t) => (_jsxs("span", { className: `text-[11px] px-2 py-0.5 rounded border ${l.cratePrice === t.price_per_crate && l.priceSource === "tier"
|
|
193
|
+
? "bg-green-100 border-green-300 text-green-800 font-semibold"
|
|
194
|
+
: "bg-slate-50 border-slate-200 text-slate-600"}`, children: ["\u2265 ", t.min_crates, " fust: ", fmtEuro(t.price_per_crate)] }, t.min_crates))) })), _jsx("div", { className: "mt-2", children: l.soldOut ? (_jsx("span", { className: "inline-flex items-center gap-1 text-xs font-semibold bg-red-100 text-red-800 border border-red-200 rounded px-2 py-1", children: "\u25CF Uitverkocht" })) : l.stock <= 10 ? (_jsxs("span", { className: "inline-flex items-center gap-1 text-xs font-semibold bg-amber-100 text-amber-800 border border-amber-200 rounded px-2 py-1", children: ["\u25CF Nog ", l.stock, " op voorraad"] })) : (_jsxs("span", { className: "inline-flex items-center gap-1 text-xs font-semibold bg-green-100 text-green-800 border border-green-200 rounded px-2 py-1", children: ["\u25CF Op voorraad: ", l.stock, " stuks"] })) }), !l.soldOut && l.stickerAvail && (_jsxs("label", { className: "mt-2 flex items-start gap-2 text-xs text-blue-900 bg-blue-50 border-l-4 border-blue-400 rounded px-2 py-2 cursor-pointer select-none", children: [_jsx("input", { type: "checkbox", className: "mt-0.5", checked: l.stickerOn, onChange: (e) => setSticker({ ...sticker, [p.id]: e.target.checked }) }), _jsxs("span", { children: ["Stickeropdruk toevoegen", l.stickerCost > 0 ? _jsxs(_Fragment, { children: [" \u2014 ", _jsx("strong", { children: fmtEuro(l.stickerCost) }), " per stuk"] }) : _jsxs(_Fragment, { children: [" \u2014 ", _jsx("strong", { children: "geen meerprijs" })] })] })] })), !l.soldOut && !l.stickerAvail && (_jsx("div", { className: "mt-2 text-xs text-slate-500 bg-slate-50 border-l-4 border-slate-300 rounded px-2 py-2", children: "Stickeropdruk niet beschikbaar voor dit product" })), !l.soldOut && currentQty > 0 && (_jsxs("div", { className: "mt-3 text-xs text-slate-600 space-y-0.5 border-t border-slate-100 pt-2", children: [_jsxs("div", { className: "flex justify-between", children: [_jsxs("span", { children: ["Productprijs (", l.plants, " \u00D7 ", fmtEuro(l.unit), ")"] }), _jsx("span", { children: fmtEuro(l.productSubtotal) })] }), l.stickerOn && (_jsxs("div", { className: "flex justify-between", children: [_jsxs("span", { children: ["Stickeropdruk (", l.plants, " \u00D7 ", fmtEuro(l.stickerCost), ")"] }), _jsx("span", { children: fmtEuro(l.stickerSubtotal) })] })), _jsxs("div", { className: "flex justify-between font-bold text-slate-900 pt-0.5", children: [_jsx("span", { children: "Totaalprijs" }), _jsx("span", { className: "text-green-700", children: fmtEuro(l.total) })] }), _jsxs("div", { className: "pt-1 text-[11px] text-slate-500 italic", children: ["Herkomst prijs: ", l.priceSourceLabel] })] }))] })] }), l.soldOut ? (_jsx("div", { className: "border-t border-slate-100 px-4 py-3 text-center text-sm text-red-700 bg-red-50 font-medium", children: "Dit product is niet meer beschikbaar" })) : (_jsxs("div", { className: "border-t border-slate-100 px-4 py-3 flex flex-wrap items-center justify-between gap-2", children: [_jsxs("span", { className: "text-sm text-slate-600", children: ["Aantal fusten:", currentQty > 0 && (_jsxs("span", { className: "ml-1 text-slate-500", children: ["= ", l.plants.toLocaleString("nl-NL"), " planten"] }))] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { type: "button", onClick: () => setQ(p.id, currentQty - 1, l.maxCrates), className: "h-9 w-9 rounded-md border border-slate-200 grid place-items-center text-slate-600 hover:bg-slate-50 disabled:opacity-40", disabled: currentQty <= 0, "aria-label": "Minder", children: _jsx(Minus, { className: "h-4 w-4" }) }), _jsx(Input, { type: "number", inputMode: "numeric", step: 1, min: 0, max: l.maxCrates, value: currentQty, onChange: (e) => setQ(p.id, parseInt(e.target.value, 10), l.maxCrates), onKeyDown: (e) => {
|
|
166
195
|
if (["e", "E", "+", "-", ".", ","].includes(e.key))
|
|
167
196
|
e.preventDefault();
|
|
168
197
|
}, className: "w-28 text-center" }), _jsx("button", { type: "button", onClick: () => setQ(p.id, currentQty + 1, l.maxCrates), className: "h-9 w-9 rounded-md border border-slate-200 grid place-items-center text-slate-600 hover:bg-slate-50 disabled:opacity-40", disabled: currentQty >= l.maxCrates, "aria-label": "Meer", children: _jsx(Plus, { className: "h-4 w-4" }) })] })] }))] }, p.id));
|
package/dist-lib/index.d.ts
CHANGED
|
@@ -5,5 +5,6 @@ export { CampagneOverzicht } from "./components/CampagneOverzicht";
|
|
|
5
5
|
export { CampagneDetail } from "./components/CampagneDetail";
|
|
6
6
|
export { RapportagePage } from "./components/RapportagePage";
|
|
7
7
|
export { ActiePage } from "./components/ActiePage";
|
|
8
|
+
export * from "./lib/voorraad-service";
|
|
8
9
|
export declare const actiemailKwekersErpMathot: FlowModule;
|
|
9
10
|
//# sourceMappingURL=index.d.ts.map
|
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;
|
|
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,cAAc,wBAAwB,CAAC;AASvC,eAAO,MAAM,yBAAyB,EAAE,UAgBvC,CAAC"}
|
package/dist-lib/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export { CampagneOverzicht } from "./components/CampagneOverzicht";
|
|
|
5
5
|
export { CampagneDetail } from "./components/CampagneDetail";
|
|
6
6
|
export { RapportagePage } from "./components/RapportagePage";
|
|
7
7
|
export { ActiePage } from "./components/ActiePage";
|
|
8
|
+
export * from "./lib/voorraad-service";
|
|
8
9
|
import { HuisstijlSettingsCard } from "./components/settings/HuisstijlSettingsCard";
|
|
9
10
|
import { TrackingSettingsCard } from "./components/settings/TrackingSettingsCard";
|
|
10
11
|
import { UitsluitingenSettingsCard } from "./components/settings/UitsluitingenSettingsCard";
|