@flowselections/floriday-voorraad 1.0.23 → 1.0.26
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/assets/floriday-logo.png.asset.json +4 -4
- package/dist-lib/components/voorraad/ArtikelWizard.d.ts.map +1 -1
- package/dist-lib/components/voorraad/ArtikelWizard.js +633 -101
- package/dist-lib/components/voorraad/StepSamenstelling.d.ts +10 -0
- package/dist-lib/components/voorraad/StepSamenstelling.d.ts.map +1 -0
- package/dist-lib/components/voorraad/StepSamenstelling.js +333 -0
- package/dist-lib/components/voorraad/VoorraadPage.d.ts.map +1 -1
- package/dist-lib/components/voorraad/VoorraadPage.js +14 -3
- package/dist-lib/components/voorraad/VoorraadTable.d.ts.map +1 -1
- package/dist-lib/components/voorraad/VoorraadTable.js +6 -13
- package/dist-lib/hooks/useFloridayPriceGroups.d.ts +20 -0
- package/dist-lib/hooks/useFloridayPriceGroups.d.ts.map +1 -0
- package/dist-lib/hooks/useFloridayPriceGroups.js +55 -0
- package/dist-lib/hooks/useFloridayVbnRequired.d.ts +5 -0
- package/dist-lib/hooks/useFloridayVbnRequired.d.ts.map +1 -0
- package/dist-lib/hooks/useFloridayVbnRequired.js +16 -0
- package/dist-lib/hooks/useLocalTradeItems.d.ts.map +1 -1
- package/dist-lib/hooks/useLocalTradeItems.js +14 -0
- package/dist-lib/hooks/useTradeItemSpec.d.ts.map +1 -1
- package/dist-lib/hooks/useTradeItemSpec.js +48 -1
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +2378 -361
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.d.ts +2378 -361
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +2378 -361
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +2412 -344
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.js +11 -9
- package/dist-lib/lib/centralSecrets.server.d.ts +21 -0
- package/dist-lib/lib/centralSecrets.server.d.ts.map +1 -0
- package/dist-lib/lib/centralSecrets.server.js +111 -0
- package/dist-lib/lib/floricode-required-features.functions.d.ts +2378 -361
- package/dist-lib/lib/floricode-required-features.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-customer-offer.functions.d.ts +2378 -361
- package/dist-lib/lib/floriday-customer-offer.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-gateway.functions.d.ts +10760 -675
- package/dist-lib/lib/floriday-gateway.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-gateway.server.d.ts.map +1 -1
- package/dist-lib/lib/floriday-gateway.server.js +34 -9
- package/dist-lib/lib/floriday-payload.d.ts +21 -3
- package/dist-lib/lib/floriday-payload.d.ts.map +1 -1
- package/dist-lib/lib/floriday-payload.js +167 -34
- package/dist-lib/lib/floriday-vbn-required.functions.d.ts +27769 -0
- package/dist-lib/lib/floriday-vbn-required.functions.d.ts.map +1 -0
- package/dist-lib/lib/floriday-vbn-required.functions.js +85 -0
- package/dist-lib/lib/floriday-warehouse.functions.d.ts +6542 -491
- package/dist-lib/lib/floriday-warehouse.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-writes.functions.d.ts +4647 -612
- package/dist-lib/lib/floriday-writes.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-writes.functions.js +36 -1
- package/dist-lib/lib/trade-item-prices.d.ts +43 -0
- package/dist-lib/lib/trade-item-prices.d.ts.map +1 -0
- package/dist-lib/lib/trade-item-prices.js +229 -0
- package/package.json +3 -3
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { PackingConfigurationInput } from "../../lib/floriday-payload";
|
|
2
|
+
interface Props {
|
|
3
|
+
productId: string | null;
|
|
4
|
+
floridayId: string | null;
|
|
5
|
+
packings: PackingConfigurationInput[];
|
|
6
|
+
packagingTypeLabel: (code: string) => string;
|
|
7
|
+
}
|
|
8
|
+
export declare function StepSamenstelling({ productId, floridayId, packings, packagingTypeLabel, }: Props): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=StepSamenstelling.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StepSamenstelling.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/StepSamenstelling.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAsB5E,UAAU,KAAK;IACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,yBAAyB,EAAE,CAAC;IACtC,kBAAkB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAC9C;AAUD,wBAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,UAAU,EACV,QAAQ,EACR,kBAAkB,GACnB,EAAE,KAAK,2CA+ZP"}
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
3
|
+
import { Button, Input, Popover, PopoverContent, PopoverTrigger, toast, } from "@flowselections/core";
|
|
4
|
+
import { Loader2, Package, Plus, Search, Trash2 } from "lucide-react";
|
|
5
|
+
import { supabase } from "../../integrations/supabase/client";
|
|
6
|
+
function newRowId() {
|
|
7
|
+
return `new:${typeof crypto !== "undefined" && "randomUUID" in crypto
|
|
8
|
+
? crypto.randomUUID()
|
|
9
|
+
: Date.now().toString(36) + Math.random().toString(36).slice(2)}`;
|
|
10
|
+
}
|
|
11
|
+
export function StepSamenstelling({ productId, floridayId, packings, packagingTypeLabel, }) {
|
|
12
|
+
const [loading, setLoading] = useState(true);
|
|
13
|
+
const [saving, setSaving] = useState(false);
|
|
14
|
+
const [rows, setRows] = useState([]);
|
|
15
|
+
const [names, setNames] = useState(new Map());
|
|
16
|
+
const [activeTab, setActiveTab] = useState("__base__");
|
|
17
|
+
const hasParent = Boolean(productId || floridayId);
|
|
18
|
+
const load = useCallback(async () => {
|
|
19
|
+
if (!hasParent) {
|
|
20
|
+
setRows([]);
|
|
21
|
+
setLoading(false);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
setLoading(true);
|
|
25
|
+
let q = supabase
|
|
26
|
+
.from("product_bom_items")
|
|
27
|
+
.select("id,packing_configuration_id,component_product_id,component_trade_item_floriday_id,quantity,sort_order")
|
|
28
|
+
.order("sort_order", { ascending: true });
|
|
29
|
+
if (productId && floridayId) {
|
|
30
|
+
q = q.or(`parent_product_id.eq.${productId},parent_trade_item_floriday_id.eq.${floridayId}`);
|
|
31
|
+
}
|
|
32
|
+
else if (productId) {
|
|
33
|
+
q = q.eq("parent_product_id", productId);
|
|
34
|
+
}
|
|
35
|
+
else if (floridayId) {
|
|
36
|
+
q = q.eq("parent_trade_item_floriday_id", floridayId);
|
|
37
|
+
}
|
|
38
|
+
const { data, error } = await q;
|
|
39
|
+
if (error) {
|
|
40
|
+
toast.error("Kon samenstelling niet laden");
|
|
41
|
+
setRows([]);
|
|
42
|
+
setLoading(false);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const list = (data ?? []).map((r) => ({
|
|
46
|
+
id: r.id,
|
|
47
|
+
packing_configuration_id: r.packing_configuration_id ?? null,
|
|
48
|
+
component_product_id: r.component_product_id ?? null,
|
|
49
|
+
component_trade_item_floriday_id: r.component_trade_item_floriday_id ?? null,
|
|
50
|
+
quantity: Number(r.quantity ?? 1),
|
|
51
|
+
sort_order: Number(r.sort_order ?? 0),
|
|
52
|
+
}));
|
|
53
|
+
setRows(list);
|
|
54
|
+
await resolveNames(list);
|
|
55
|
+
setLoading(false);
|
|
56
|
+
}, [productId, floridayId, hasParent]);
|
|
57
|
+
const resolveNames = useCallback(async (list) => {
|
|
58
|
+
const prodIds = Array.from(new Set(list.map((r) => r.component_product_id).filter((v) => !!v)));
|
|
59
|
+
const flIds = Array.from(new Set(list
|
|
60
|
+
.map((r) => r.component_trade_item_floriday_id)
|
|
61
|
+
.filter((v) => !!v)));
|
|
62
|
+
const map = new Map();
|
|
63
|
+
if (prodIds.length) {
|
|
64
|
+
const { data } = await supabase
|
|
65
|
+
.from("products")
|
|
66
|
+
.select("id,product,barcode,article_number")
|
|
67
|
+
.in("id", prodIds);
|
|
68
|
+
(data ?? []).forEach((p) => {
|
|
69
|
+
map.set(`product:${p.id}`, {
|
|
70
|
+
kind: "product",
|
|
71
|
+
id: p.id,
|
|
72
|
+
name: String(p.product ?? p.id),
|
|
73
|
+
code: p.barcode ? String(p.barcode) : p.article_number ? String(p.article_number) : undefined,
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
if (flIds.length) {
|
|
78
|
+
const { data } = await supabase
|
|
79
|
+
.from("floriday_trade_items_cache")
|
|
80
|
+
.select("floriday_id,data")
|
|
81
|
+
.in("floriday_id", flIds);
|
|
82
|
+
(data ?? []).forEach((n) => {
|
|
83
|
+
const nm = n.data?.tradeItemName?.nl ??
|
|
84
|
+
n.data?.tradeItemName?.en ??
|
|
85
|
+
Object.values(n.data?.tradeItemName ?? {})[0] ??
|
|
86
|
+
n.floriday_id;
|
|
87
|
+
const code = n.data?.supplierArticleCode ??
|
|
88
|
+
n.data?.articleGtin ??
|
|
89
|
+
undefined;
|
|
90
|
+
map.set(`floriday:${n.floriday_id}`, {
|
|
91
|
+
kind: "floriday",
|
|
92
|
+
id: n.floriday_id,
|
|
93
|
+
name: String(nm),
|
|
94
|
+
code: code ? String(code) : undefined,
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
setNames((prev) => {
|
|
99
|
+
const merged = new Map(prev);
|
|
100
|
+
map.forEach((v, k) => merged.set(k, v));
|
|
101
|
+
return merged;
|
|
102
|
+
});
|
|
103
|
+
}, []);
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
load();
|
|
106
|
+
}, [load]);
|
|
107
|
+
// Tabs = base + one per current packing.
|
|
108
|
+
const tabs = useMemo(() => [
|
|
109
|
+
{ key: "__base__", label: "Basissamenstelling" },
|
|
110
|
+
...packings.map((p, i) => ({
|
|
111
|
+
key: p.id,
|
|
112
|
+
label: `Belading ${i + 1}${p.isPrimary ? " (primair)" : ""}${p.packagingType ? " · " + packagingTypeLabel(p.packagingType) : ""}`,
|
|
113
|
+
})),
|
|
114
|
+
], [packings, packagingTypeLabel]);
|
|
115
|
+
// If the active tab no longer exists (packing removed), fall back to base.
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
if (!tabs.some((t) => t.key === activeTab))
|
|
118
|
+
setActiveTab("__base__");
|
|
119
|
+
}, [tabs, activeTab]);
|
|
120
|
+
const currentPackingId = activeTab === "__base__" ? null : activeTab;
|
|
121
|
+
const currentRows = rows.filter((r) => r.packing_configuration_id === currentPackingId);
|
|
122
|
+
const baseRows = rows.filter((r) => r.packing_configuration_id === null);
|
|
123
|
+
const addRow = (opt) => {
|
|
124
|
+
const sortOrder = currentRows.length;
|
|
125
|
+
setRows((prev) => [
|
|
126
|
+
...prev,
|
|
127
|
+
{
|
|
128
|
+
id: newRowId(),
|
|
129
|
+
packing_configuration_id: currentPackingId,
|
|
130
|
+
component_product_id: opt.kind === "product" ? opt.id : null,
|
|
131
|
+
component_trade_item_floriday_id: opt.kind === "floriday" ? opt.id : null,
|
|
132
|
+
quantity: 1,
|
|
133
|
+
sort_order: sortOrder,
|
|
134
|
+
_new: true,
|
|
135
|
+
_dirty: true,
|
|
136
|
+
},
|
|
137
|
+
]);
|
|
138
|
+
setNames((prev) => {
|
|
139
|
+
const m = new Map(prev);
|
|
140
|
+
m.set(`${opt.kind}:${opt.id}`, opt);
|
|
141
|
+
return m;
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
const updateRow = (id, patch) => {
|
|
145
|
+
setRows((prev) => prev.map((r) => (r.id === id ? { ...r, ...patch, _dirty: true } : r)));
|
|
146
|
+
};
|
|
147
|
+
const removeRow = async (id) => {
|
|
148
|
+
const row = rows.find((r) => r.id === id);
|
|
149
|
+
if (!row)
|
|
150
|
+
return;
|
|
151
|
+
if (!row._new) {
|
|
152
|
+
const { error } = await supabase.from("product_bom_items").delete().eq("id", id);
|
|
153
|
+
if (error) {
|
|
154
|
+
toast.error("Verwijderen mislukt");
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
setRows((prev) => prev.filter((r) => r.id !== id));
|
|
159
|
+
};
|
|
160
|
+
const saveAll = async () => {
|
|
161
|
+
if (!hasParent) {
|
|
162
|
+
toast.error("Sla het artikel eerst op voordat je een samenstelling toevoegt.");
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const dirty = rows.filter((r) => r._dirty);
|
|
166
|
+
if (dirty.length === 0)
|
|
167
|
+
return;
|
|
168
|
+
setSaving(true);
|
|
169
|
+
try {
|
|
170
|
+
const inserts = dirty
|
|
171
|
+
.filter((r) => r._new)
|
|
172
|
+
.map((r) => ({
|
|
173
|
+
parent_product_id: productId,
|
|
174
|
+
parent_trade_item_floriday_id: floridayId,
|
|
175
|
+
packing_configuration_id: r.packing_configuration_id,
|
|
176
|
+
component_product_id: r.component_product_id,
|
|
177
|
+
component_trade_item_floriday_id: r.component_trade_item_floriday_id,
|
|
178
|
+
quantity: r.quantity,
|
|
179
|
+
unit: "PIECE",
|
|
180
|
+
sort_order: r.sort_order,
|
|
181
|
+
}));
|
|
182
|
+
const updates = dirty.filter((r) => !r._new);
|
|
183
|
+
if (inserts.length) {
|
|
184
|
+
const { data, error } = await supabase
|
|
185
|
+
.from("product_bom_items")
|
|
186
|
+
.insert(inserts)
|
|
187
|
+
.select("id");
|
|
188
|
+
if (error)
|
|
189
|
+
throw error;
|
|
190
|
+
// Map new ids back onto local rows (align by index of the "new" rows we sent)
|
|
191
|
+
const newIds = (data ?? []).map((d) => d.id);
|
|
192
|
+
const newLocal = dirty.filter((r) => r._new);
|
|
193
|
+
setRows((prev) => {
|
|
194
|
+
const map = new Map();
|
|
195
|
+
newLocal.forEach((r, i) => {
|
|
196
|
+
if (newIds[i])
|
|
197
|
+
map.set(r.id, newIds[i]);
|
|
198
|
+
});
|
|
199
|
+
return prev.map((r) => map.has(r.id)
|
|
200
|
+
? { ...r, id: map.get(r.id), _new: false, _dirty: false }
|
|
201
|
+
: r);
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
for (const r of updates) {
|
|
205
|
+
const { error } = await supabase
|
|
206
|
+
.from("product_bom_items")
|
|
207
|
+
.update({
|
|
208
|
+
quantity: r.quantity,
|
|
209
|
+
sort_order: r.sort_order,
|
|
210
|
+
})
|
|
211
|
+
.eq("id", r.id);
|
|
212
|
+
if (error)
|
|
213
|
+
throw error;
|
|
214
|
+
}
|
|
215
|
+
setRows((prev) => prev.map((r) => ({ ...r, _dirty: false })));
|
|
216
|
+
toast.success("Samenstelling opgeslagen");
|
|
217
|
+
}
|
|
218
|
+
catch (e) {
|
|
219
|
+
toast.error("Opslaan mislukt: " + e.message);
|
|
220
|
+
}
|
|
221
|
+
finally {
|
|
222
|
+
setSaving(false);
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
const hasUnsaved = rows.some((r) => r._dirty);
|
|
226
|
+
if (!hasParent) {
|
|
227
|
+
return (_jsx("div", { className: "rounded-md border border-dashed p-6 text-center text-sm text-muted-foreground", children: "Sla het artikel eerst op om een samenstelling te configureren." }));
|
|
228
|
+
}
|
|
229
|
+
return (_jsxs("div", { className: "space-y-4", children: [_jsx("div", { className: "rounded-md border bg-muted/30 p-3 text-xs text-muted-foreground", children: "Configureer een basissamenstelling en optioneel afwijkende onderdelen per belading. Rijen op de belading-tabbladen gelden bovenop of in plaats van de basissamenstelling." }), _jsx("div", { className: "flex flex-wrap gap-1 border-b", children: tabs.map((t) => {
|
|
230
|
+
const active = t.key === activeTab;
|
|
231
|
+
const count = rows.filter((r) => r.packing_configuration_id === (t.key === "__base__" ? null : t.key)).length;
|
|
232
|
+
return (_jsxs("button", { type: "button", onClick: () => setActiveTab(t.key), className: `-mb-px border-b-2 px-3 py-2 text-sm ${active
|
|
233
|
+
? "border-primary text-foreground font-medium"
|
|
234
|
+
: "border-transparent text-muted-foreground hover:text-foreground"}`, children: [t.label, _jsx("span", { className: "ml-2 rounded bg-muted px-1.5 py-0.5 text-xs", children: count })] }, t.key));
|
|
235
|
+
}) }), currentPackingId && baseRows.length > 0 && (_jsxs("div", { className: "rounded-md border bg-muted/20 p-3", children: [_jsx("div", { className: "mb-2 text-xs font-medium text-muted-foreground", children: "Basissamenstelling (referentie)" }), _jsx("ul", { className: "divide-y", children: baseRows.map((r) => {
|
|
236
|
+
const key = r.component_product_id
|
|
237
|
+
? `product:${r.component_product_id}`
|
|
238
|
+
: `floriday:${r.component_trade_item_floriday_id}`;
|
|
239
|
+
const info = names.get(key);
|
|
240
|
+
return (_jsxs("li", { className: "flex items-center gap-3 py-1.5 text-sm", children: [_jsx(Package, { className: "h-3.5 w-3.5 text-muted-foreground shrink-0" }), _jsxs("div", { className: "flex-1 min-w-0 truncate", children: [info?.name ?? key, info?.code && (_jsx("span", { className: "ml-2 text-xs text-muted-foreground", children: info.code }))] }), _jsxs("div", { className: "text-xs tabular-nums text-muted-foreground", children: [r.quantity, "\u00D7"] })] }, r.id));
|
|
241
|
+
}) })] })), loading ? (_jsxs("div", { className: "flex items-center gap-2 py-6 text-sm text-muted-foreground", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), " Samenstelling laden\u2026"] })) : currentRows.length === 0 ? (_jsx("div", { className: "rounded-md border border-dashed p-6 text-center", children: _jsx("p", { className: "text-sm text-muted-foreground", children: currentPackingId
|
|
242
|
+
? "Nog geen afwijkende onderdelen voor deze belading."
|
|
243
|
+
: "Nog geen onderdelen in de basissamenstelling." }) })) : (_jsx("div", { className: "overflow-hidden rounded-md border", children: _jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { className: "bg-muted/50 text-left text-xs uppercase text-muted-foreground", children: _jsxs("tr", { children: [_jsx("th", { className: "px-3 py-2 font-medium", children: "Onderdeel" }), _jsx("th", { className: "px-3 py-2 font-medium w-32", children: "Aantal per verpakking" }), _jsx("th", { className: "px-3 py-2" })] }) }), _jsx("tbody", { className: "divide-y", children: currentRows.map((r) => {
|
|
244
|
+
const key = r.component_product_id
|
|
245
|
+
? `product:${r.component_product_id}`
|
|
246
|
+
: `floriday:${r.component_trade_item_floriday_id}`;
|
|
247
|
+
const info = names.get(key);
|
|
248
|
+
return (_jsxs("tr", { children: [_jsx("td", { className: "px-3 py-2", children: _jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [_jsx("div", { className: "h-8 w-8 rounded bg-muted flex items-center justify-center shrink-0", children: _jsx(Package, { className: "h-4 w-4 text-muted-foreground" }) }), _jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "font-medium truncate", children: info?.name ?? key }), info?.code && (_jsx("div", { className: "text-xs text-muted-foreground truncate", children: info.code }))] })] }) }), _jsx("td", { className: "px-3 py-2", children: _jsx(Input, { type: "number", inputMode: "decimal", min: 0, step: "0.01", value: r.quantity, onChange: (e) => updateRow(r.id, { quantity: Number(e.target.value) }), className: "h-8 w-24" }) }), _jsx("td", { className: "px-3 py-2 text-right", children: _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => removeRow(r.id), children: _jsx(Trash2, { className: "h-4 w-4" }) }) })] }, r.id));
|
|
249
|
+
}) })] }) })), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(ComponentPicker, { excludeKeys: new Set(currentRows.map((r) => r.component_product_id
|
|
250
|
+
? `product:${r.component_product_id}`
|
|
251
|
+
: `floriday:${r.component_trade_item_floriday_id}`)), onPick: addRow }), _jsxs("div", { className: "ml-auto flex items-center gap-2", children: [hasUnsaved && (_jsx("span", { className: "text-xs text-amber-700", children: "Niet-opgeslagen wijzigingen" })), _jsxs(Button, { type: "button", size: "sm", onClick: saveAll, disabled: !hasUnsaved || saving, children: [saving && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Opslaan"] })] })] })] }));
|
|
252
|
+
}
|
|
253
|
+
// ============================================================
|
|
254
|
+
// Component picker
|
|
255
|
+
// ============================================================
|
|
256
|
+
function ComponentPicker({ onPick, excludeKeys, }) {
|
|
257
|
+
const [open, setOpen] = useState(false);
|
|
258
|
+
const [query, setQuery] = useState("");
|
|
259
|
+
const [loading, setLoading] = useState(false);
|
|
260
|
+
const [results, setResults] = useState([]);
|
|
261
|
+
useEffect(() => {
|
|
262
|
+
if (!open)
|
|
263
|
+
return;
|
|
264
|
+
const q = query.trim();
|
|
265
|
+
let cancelled = false;
|
|
266
|
+
setLoading(true);
|
|
267
|
+
const timer = setTimeout(async () => {
|
|
268
|
+
try {
|
|
269
|
+
const [prodRes, flRes] = await Promise.all([
|
|
270
|
+
q.length > 0
|
|
271
|
+
? supabase
|
|
272
|
+
.from("products")
|
|
273
|
+
.select("id,product,barcode,article_number")
|
|
274
|
+
.or(`product.ilike.%${q}%,barcode.ilike.%${q}%,article_number.ilike.%${q}%`)
|
|
275
|
+
.limit(25)
|
|
276
|
+
: supabase
|
|
277
|
+
.from("products")
|
|
278
|
+
.select("id,product,barcode,article_number")
|
|
279
|
+
.order("updated_at", { ascending: false })
|
|
280
|
+
.limit(15),
|
|
281
|
+
supabase
|
|
282
|
+
.from("floriday_trade_items_cache")
|
|
283
|
+
.select("floriday_id,data")
|
|
284
|
+
.eq("is_deleted", false)
|
|
285
|
+
.limit(200),
|
|
286
|
+
]);
|
|
287
|
+
if (cancelled)
|
|
288
|
+
return;
|
|
289
|
+
const prodOpts = (prodRes.data ?? []).map((p) => ({
|
|
290
|
+
kind: "product",
|
|
291
|
+
id: p.id,
|
|
292
|
+
name: String(p.product ?? p.id),
|
|
293
|
+
code: p.barcode
|
|
294
|
+
? String(p.barcode)
|
|
295
|
+
: p.article_number
|
|
296
|
+
? String(p.article_number)
|
|
297
|
+
: undefined,
|
|
298
|
+
}));
|
|
299
|
+
const flOptsAll = (flRes.data ?? []).map((n) => {
|
|
300
|
+
const nm = n.data?.tradeItemName?.nl ??
|
|
301
|
+
n.data?.tradeItemName?.en ??
|
|
302
|
+
Object.values(n.data?.tradeItemName ?? {})[0] ??
|
|
303
|
+
n.floriday_id;
|
|
304
|
+
const code = n.data?.supplierArticleCode ?? n.data?.articleGtin ?? undefined;
|
|
305
|
+
return {
|
|
306
|
+
kind: "floriday",
|
|
307
|
+
id: n.floriday_id,
|
|
308
|
+
name: String(nm),
|
|
309
|
+
code: code ? String(code) : undefined,
|
|
310
|
+
};
|
|
311
|
+
});
|
|
312
|
+
const flOpts = q.length
|
|
313
|
+
? flOptsAll.filter((o) => o.name.toLowerCase().includes(q.toLowerCase()) ||
|
|
314
|
+
(o.code ?? "").toLowerCase().includes(q.toLowerCase()))
|
|
315
|
+
: flOptsAll.slice(0, 15);
|
|
316
|
+
setResults([...prodOpts, ...flOpts].filter((o) => !excludeKeys.has(`${o.kind}:${o.id}`)));
|
|
317
|
+
}
|
|
318
|
+
finally {
|
|
319
|
+
if (!cancelled)
|
|
320
|
+
setLoading(false);
|
|
321
|
+
}
|
|
322
|
+
}, 200);
|
|
323
|
+
return () => {
|
|
324
|
+
cancelled = true;
|
|
325
|
+
clearTimeout(timer);
|
|
326
|
+
};
|
|
327
|
+
}, [open, query, excludeKeys]);
|
|
328
|
+
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { type: "button", variant: "outline", size: "sm", children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), "Onderdeel toevoegen"] }) }), _jsxs(PopoverContent, { className: "w-96 p-0", align: "start", children: [_jsx("div", { className: "border-b p-2", children: _jsxs("div", { className: "relative", children: [_jsx(Search, { className: "pointer-events-none absolute left-2 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { autoFocus: true, placeholder: "Zoek artikel of Floriday-item\u2026", value: query, onChange: (e) => setQuery(e.target.value), className: "h-8 pl-8" })] }) }), _jsx("div", { className: "max-h-80 overflow-y-auto", children: loading ? (_jsxs("div", { className: "flex items-center gap-2 p-3 text-sm text-muted-foreground", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), " Zoeken\u2026"] })) : results.length === 0 ? (_jsx("div", { className: "p-3 text-sm text-muted-foreground", children: "Geen resultaten." })) : (_jsx("ul", { className: "divide-y", children: results.map((r) => (_jsx("li", { children: _jsxs("button", { type: "button", className: "flex w-full items-center gap-2 px-3 py-2 text-left hover:bg-muted", onClick: () => {
|
|
329
|
+
onPick(r);
|
|
330
|
+
setOpen(false);
|
|
331
|
+
setQuery("");
|
|
332
|
+
}, children: [_jsx(Package, { className: "h-4 w-4 text-muted-foreground shrink-0" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "truncate text-sm font-medium", children: r.name }), _jsxs("div", { className: "truncate text-xs text-muted-foreground", children: [r.kind === "product" ? "Lokaal artikel" : "Floriday", " \u00B7", " ", r.code ?? r.id] })] })] }) }, `${r.kind}:${r.id}`))) })) })] })] }));
|
|
333
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VoorraadPage.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/VoorraadPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"VoorraadPage.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/VoorraadPage.tsx"],"names":[],"mappings":"AA4FA,wBAAgB,YAAY,4CAkO3B"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useMemo, useState } from "react";
|
|
3
3
|
import { Link } from "@tanstack/react-router";
|
|
4
|
-
import { Button, Card, Input } from "@flowselections/core";
|
|
4
|
+
import { Button, Card, Input, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@flowselections/core";
|
|
5
5
|
import { AlertTriangle, CheckCircle2, FileText, PackageX, Plus, Search, } from "lucide-react";
|
|
6
6
|
import { useFloridayConnection } from "../../hooks/useFloridayConnection";
|
|
7
7
|
import { useVoorraadData } from "../../hooks/useVoorraadData";
|
|
@@ -9,6 +9,9 @@ import { ExcelExportButton } from "./ExcelExportButton";
|
|
|
9
9
|
import { StockBulkButtons } from "./StockBulkButtons";
|
|
10
10
|
import { VoorraadTable } from "./VoorraadTable";
|
|
11
11
|
import { VoorraadPagination } from "./VoorraadPagination";
|
|
12
|
+
function isLinkedToFloriday(i) {
|
|
13
|
+
return Boolean(i.floridayId) || i.source === "published";
|
|
14
|
+
}
|
|
12
15
|
function toneClasses(tone) {
|
|
13
16
|
switch (tone) {
|
|
14
17
|
case "emerald":
|
|
@@ -34,6 +37,8 @@ export function VoorraadPage() {
|
|
|
34
37
|
const { items, loading, error, reload } = useVoorraadData(activeId);
|
|
35
38
|
const [search, setSearch] = useState("");
|
|
36
39
|
const [stockFilter, setStockFilter] = useState("all");
|
|
40
|
+
const [floridayFilter, setFloridayFilter] = useState("all");
|
|
41
|
+
const [typeFilter, setTypeFilter] = useState("all");
|
|
37
42
|
const [page, setPage] = useState(1);
|
|
38
43
|
const [pageSize, setPageSize] = useState(25);
|
|
39
44
|
const counts = useMemo(() => {
|
|
@@ -62,12 +67,18 @@ export function VoorraadPage() {
|
|
|
62
67
|
if (stockFilter === "below_min" &&
|
|
63
68
|
!((i.minQuantity ?? 0) > 0 && avail < i.minQuantity))
|
|
64
69
|
return false;
|
|
70
|
+
if (floridayFilter === "linked" && !isLinkedToFloriday(i))
|
|
71
|
+
return false;
|
|
72
|
+
if (floridayFilter === "unlinked" && isLinkedToFloriday(i))
|
|
73
|
+
return false;
|
|
74
|
+
if (typeFilter !== "all" && (i.itemType ?? "artikel") !== typeFilter)
|
|
75
|
+
return false;
|
|
65
76
|
if (!q)
|
|
66
77
|
return true;
|
|
67
78
|
return (i.name.toLowerCase().includes(q) ||
|
|
68
79
|
(i.articleNumber ?? "").toLowerCase().includes(q));
|
|
69
80
|
});
|
|
70
|
-
}, [items, search, stockFilter]);
|
|
81
|
+
}, [items, search, stockFilter, floridayFilter, typeFilter]);
|
|
71
82
|
const totalPages = Math.max(1, Math.ceil(filtered.length / pageSize));
|
|
72
83
|
useEffect(() => {
|
|
73
84
|
if (page > totalPages)
|
|
@@ -86,5 +97,5 @@ export function VoorraadPage() {
|
|
|
86
97
|
return (_jsxs("button", { type: "button", onClick: () => setStockFilter(t.id), className: `relative py-3 px-3 text-sm font-medium whitespace-nowrap transition-colors ${active
|
|
87
98
|
? "text-foreground"
|
|
88
99
|
: "text-muted-foreground hover:text-foreground"}`, children: [t.label, _jsx("span", { className: `ml-2 text-xs ${active ? "text-primary" : "text-muted-foreground/70"}`, children: t.count }), active && (_jsx("span", { className: "absolute left-2 right-2 -bottom-px h-0.5 bg-primary rounded-full" }))] }, t.id));
|
|
89
|
-
}) }), _jsxs("div", { className: "flex flex-wrap items-center gap-2 p-4 border-b", children: [_jsxs("div", { className: "relative flex-1 min-w-[220px] max-w-md", children: [_jsx(Search, { className: "w-4 h-4 absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { placeholder: "Zoek op product of artikelnummer...", className: "pl-9", value: search, onChange: (e) => setSearch(e.target.value) })] }), _jsxs("div", { className: "ml-auto flex flex-wrap items-center gap-2", children: [_jsx(ExcelExportButton, { items: filtered }), _jsx(StockBulkButtons, { items: items, activeConnectionId: activeId, onImported: reload })] })] }), _jsx("div", { className: "overflow-x-auto", children: _jsx(VoorraadTable, { items: paged, loading: loading }) }), _jsx(VoorraadPagination, { total: filtered.length, page: page, pageSize: pageSize, onPageChange: setPage, onPageSizeChange: setPageSize })] })] }));
|
|
100
|
+
}) }), _jsxs("div", { className: "flex flex-wrap items-center gap-2 p-4 border-b", children: [_jsxs("div", { className: "relative flex-1 min-w-[220px] max-w-md", children: [_jsx(Search, { className: "w-4 h-4 absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { placeholder: "Zoek op product of artikelnummer...", className: "pl-9", value: search, onChange: (e) => setSearch(e.target.value) })] }), _jsxs(Select, { value: floridayFilter, onValueChange: (v) => setFloridayFilter(v), children: [_jsx(SelectTrigger, { className: "h-9 w-[190px]", children: _jsx(SelectValue, { placeholder: "Floriday" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "all", children: "Alle (Floriday)" }), _jsx(SelectItem, { value: "linked", children: "Gekoppeld aan Floriday" }), _jsx(SelectItem, { value: "unlinked", children: "Niet gekoppeld" })] })] }), _jsxs(Select, { value: typeFilter, onValueChange: (v) => setTypeFilter(v), children: [_jsx(SelectTrigger, { className: "h-9 w-[170px]", children: _jsx(SelectValue, { placeholder: "Type" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "all", children: "Alle types" }), _jsx(SelectItem, { value: "artikel", children: "Artikel" }), _jsx(SelectItem, { value: "productgroep", children: "Productgroep" }), _jsx(SelectItem, { value: "samenstelling", children: "Samenstelling" })] })] }), _jsxs("div", { className: "ml-auto flex flex-wrap items-center gap-2", children: [_jsx(ExcelExportButton, { items: filtered }), _jsx(StockBulkButtons, { items: items, activeConnectionId: activeId, onImported: reload })] })] }), _jsx("div", { className: "overflow-x-auto", children: _jsx(VoorraadTable, { items: paged, loading: loading }) }), _jsx(VoorraadPagination, { total: filtered.length, page: page, pageSize: pageSize, onPageChange: setPage, onPageSizeChange: setPageSize })] })] }));
|
|
90
101
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VoorraadTable.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/VoorraadTable.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"VoorraadTable.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/VoorraadTable.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAY3D,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,OAAO,GACR,EAAE;IACD,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB,2CA6IA"}
|
|
@@ -29,18 +29,6 @@ export function VoorraadTable({ items, loading, }) {
|
|
|
29
29
|
};
|
|
30
30
|
const floriday = item.floriday ?? null;
|
|
31
31
|
const thumbUrl = floriday?.photoUrl || item.imageUrl;
|
|
32
|
-
const floridayTooltip = floriday
|
|
33
|
-
? [
|
|
34
|
-
`Naam (Floriday): ${floriday.name || "—"}`,
|
|
35
|
-
`Artikelnr (Floriday): ${floriday.supplierArticleCode || "—"}`,
|
|
36
|
-
`GTIN: ${floriday.articleGtin || "—"}`,
|
|
37
|
-
floriday.vbnProductCode
|
|
38
|
-
? `VBN-code: ${floriday.vbnProductCode}`
|
|
39
|
-
: null,
|
|
40
|
-
]
|
|
41
|
-
.filter(Boolean)
|
|
42
|
-
.join("\n")
|
|
43
|
-
: null;
|
|
44
32
|
return (_jsxs("tr", { className: `border-t hover:bg-muted/30 ${clickable ? "cursor-pointer" : ""}`, onClick: clickable ? open : undefined, role: clickable ? "button" : undefined, tabIndex: clickable ? 0 : undefined, onKeyDown: clickable
|
|
45
33
|
? (e) => {
|
|
46
34
|
if (e.key === "Enter" || e.key === " ") {
|
|
@@ -48,6 +36,11 @@ export function VoorraadTable({ items, loading, }) {
|
|
|
48
36
|
open();
|
|
49
37
|
}
|
|
50
38
|
}
|
|
51
|
-
: undefined, "aria-label": clickable ? `Bewerk ${item.name}` : undefined, children: [_jsx("td", { className: "p-2", children: thumbUrl ? (_jsx("img", { src: thumbUrl, alt: item.name, className: "h-10 w-10 rounded object-cover", loading: "lazy" })) : (_jsx("div", { className: "h-10 w-10 rounded bg-muted flex items-center justify-center", children: _jsx(Package, { className: "h-4 w-4 text-muted-foreground" }) })) }), _jsxs("td", { className: "p-3", children: [_jsxs("div", { className: "flex items-
|
|
39
|
+
: undefined, "aria-label": clickable ? `Bewerk ${item.name}` : undefined, children: [_jsx("td", { className: "p-2", children: thumbUrl ? (_jsx("img", { src: thumbUrl, alt: item.name, className: "h-10 w-10 rounded object-cover", loading: "lazy" })) : (_jsx("div", { className: "h-10 w-10 rounded bg-muted flex items-center justify-center", children: _jsx(Package, { className: "h-4 w-4 text-muted-foreground" }) })) }), _jsxs("td", { className: "p-3", children: [_jsxs("div", { className: "flex flex-col items-start gap-1", children: [_jsx("span", { className: "font-medium text-foreground", children: item.name }), _jsxs("div", { role: "status", "aria-label": floriday
|
|
40
|
+
? "Online in Floriday"
|
|
41
|
+
: "Niet online in Floriday", title: floriday
|
|
42
|
+
? "Online in Floriday"
|
|
43
|
+
: "Niet online in Floriday", className: "inline-flex items-center gap-1.5 rounded-full border border-border bg-background px-2 py-0.5 text-[11px] font-medium leading-none text-muted-foreground", children: [_jsx("span", { className: "h-1.5 w-1.5 rounded-full " +
|
|
44
|
+
(floriday ? "bg-emerald-500" : "bg-red-500"), "aria-hidden": true }), _jsx("span", { children: "Floriday" })] })] }), low && (_jsx("div", { className: "text-xs text-destructive", children: "onder minimumvoorraad" }))] }), _jsx("td", { className: "p-3", children: item.itemType === "productgroep" ? (_jsx(Badge, { className: "bg-indigo-500/15 text-indigo-700 border-indigo-500/30", children: "Productgroep" })) : item.itemType === "samenstelling" ? (_jsx(Badge, { className: "bg-emerald-500/15 text-emerald-700 border-emerald-500/30", children: "Samenstelling" })) : (_jsx(Badge, { variant: "secondary", children: "Artikel" })) }), _jsx("td", { className: "p-3 font-mono text-xs", children: item.articleNumber || "—" }), columns.map((c) => (_jsx("td", { className: "p-3 text-right tabular-nums text-muted-foreground", children: Number(item[c.key] ?? 0) }, c.key)))] }, item.id));
|
|
52
45
|
}) })] }) }));
|
|
53
46
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface FloridayPriceGroup {
|
|
2
|
+
/** Floriday priceGroupId (UUID). */
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
currency: string;
|
|
6
|
+
salesUnit: string;
|
|
7
|
+
/** Floriday buyer-organization ids die tot deze prijsgroep behoren. */
|
|
8
|
+
customerOrganizationIds: string[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Leest alle actieve (niet verwijderde) Floriday-prijsgroepen voor de opgegeven
|
|
12
|
+
* connectie uit `floriday_price_groups_cache`. De sync wordt door de
|
|
13
|
+
* Authenticatie-module beheerd; dit is puur een read-side hook.
|
|
14
|
+
*/
|
|
15
|
+
export declare function useFloridayPriceGroups(activeId: string | null): {
|
|
16
|
+
priceGroups: FloridayPriceGroup[];
|
|
17
|
+
loading: boolean;
|
|
18
|
+
error: string | null;
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=useFloridayPriceGroups.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFloridayPriceGroups.d.ts","sourceRoot":"","sources":["../../src/hooks/useFloridayPriceGroups.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,kBAAkB;IACjC,oCAAoC;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,uBAAuB,EAAE,MAAM,EAAE,CAAC;CACnC;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;;;;EA+C7D"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { supabase } from "../integrations/supabase/client";
|
|
3
|
+
/**
|
|
4
|
+
* Leest alle actieve (niet verwijderde) Floriday-prijsgroepen voor de opgegeven
|
|
5
|
+
* connectie uit `floriday_price_groups_cache`. De sync wordt door de
|
|
6
|
+
* Authenticatie-module beheerd; dit is puur een read-side hook.
|
|
7
|
+
*/
|
|
8
|
+
export function useFloridayPriceGroups(activeId) {
|
|
9
|
+
const [priceGroups, setPriceGroups] = useState([]);
|
|
10
|
+
const [loading, setLoading] = useState(Boolean(activeId));
|
|
11
|
+
const [error, setError] = useState(null);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
if (!activeId) {
|
|
14
|
+
setPriceGroups([]);
|
|
15
|
+
setLoading(false);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
let cancelled = false;
|
|
19
|
+
setLoading(true);
|
|
20
|
+
(async () => {
|
|
21
|
+
const { data, error } = await supabase
|
|
22
|
+
.from("floriday_price_groups_cache")
|
|
23
|
+
.select("floriday_id,data")
|
|
24
|
+
.eq("connection_id", activeId)
|
|
25
|
+
.eq("is_deleted", false);
|
|
26
|
+
if (cancelled)
|
|
27
|
+
return;
|
|
28
|
+
if (error) {
|
|
29
|
+
setError(error.message);
|
|
30
|
+
setPriceGroups([]);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
const rows = (data ?? []).map((row) => {
|
|
34
|
+
const raw = row.data ?? {};
|
|
35
|
+
const customers = Array.isArray(raw.customers) ? raw.customers : [];
|
|
36
|
+
return {
|
|
37
|
+
id: String(raw.priceGroupId ?? row.floriday_id),
|
|
38
|
+
name: String(raw.name ?? "Prijsgroep"),
|
|
39
|
+
currency: String(raw.currency ?? "EUR"),
|
|
40
|
+
salesUnit: String(raw.salesUnit ?? "PIECE"),
|
|
41
|
+
customerOrganizationIds: customers.map((c) => String(c)),
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
rows.sort((a, b) => a.name.localeCompare(b.name, "nl"));
|
|
45
|
+
setPriceGroups(rows);
|
|
46
|
+
setError(null);
|
|
47
|
+
}
|
|
48
|
+
setLoading(false);
|
|
49
|
+
})();
|
|
50
|
+
return () => {
|
|
51
|
+
cancelled = true;
|
|
52
|
+
};
|
|
53
|
+
}, [activeId]);
|
|
54
|
+
return { priceGroups, loading, error };
|
|
55
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFloridayVbnRequired.d.ts","sourceRoot":"","sources":["../../src/hooks/useFloridayVbnRequired.ts"],"names":[],"mappings":"AAOA,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;;;UASxE"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Leest de gedeelde cache van door Floriday afgedwongen verplichte
|
|
3
|
+
* characteristic-codes per VBN-productcode.
|
|
4
|
+
*/
|
|
5
|
+
import { useQuery } from "@tanstack/react-query";
|
|
6
|
+
import { getFloridayVbnRequired } from "../lib/floriday-vbn-required.functions";
|
|
7
|
+
export function useFloridayVbnRequired(vbnCode) {
|
|
8
|
+
const code = String(vbnCode ?? "").trim();
|
|
9
|
+
const enabled = /^\d{5,6}$/.test(code);
|
|
10
|
+
return useQuery({
|
|
11
|
+
queryKey: ["floriday-vbn-required", code],
|
|
12
|
+
queryFn: () => getFloridayVbnRequired({ data: { vbnCode: code } }),
|
|
13
|
+
enabled,
|
|
14
|
+
staleTime: 10 * 60 * 1000,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLocalTradeItems.d.ts","sourceRoot":"","sources":["../../src/hooks/useLocalTradeItems.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAwB,KAAK,kBAAkB,EAAE,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAGvG;;;;;GAKG;AAEH,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,IAAI,EAAE,UAAU,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,kBAAkB,CAAC;IAC1C,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,uBAAuB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC1C,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AA2DD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI;;;;EA0B9D;AAED,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAsBrF;AAED,MAAM,WAAW,SAAS;IACxB,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,MAAM,CAAC,EAAE,QAAQ,GAAG,cAAc,CAAC;CACpC;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB,GAAG,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"useLocalTradeItems.d.ts","sourceRoot":"","sources":["../../src/hooks/useLocalTradeItems.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAwB,KAAK,kBAAkB,EAAE,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAGvG;;;;;GAKG;AAEH,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,IAAI,EAAE,UAAU,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,kBAAkB,CAAC;IAC1C,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,uBAAuB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC1C,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AA2DD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI;;;;EA0B9D;AAED,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAsBrF;AAED,MAAM,WAAW,SAAS;IACxB,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,MAAM,CAAC,EAAE,QAAQ,GAAG,cAAc,CAAC;CACpC;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB,GAAG,OAAO,CAAC,MAAM,CAAC,CA2ElB;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAOhF;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGpE"}
|
|
@@ -128,6 +128,14 @@ export async function upsertLocalTradeItem(params) {
|
|
|
128
128
|
const firstImageUrl = firstImage?.url || firstImage?.previewUrl;
|
|
129
129
|
if (firstImageUrl)
|
|
130
130
|
productPatch.image_url = firstImageUrl;
|
|
131
|
+
if (payload.vatRate !== undefined) {
|
|
132
|
+
const v = payload.vatRate;
|
|
133
|
+
productPatch.vat_rate = v === null || v === "" || Number.isNaN(Number(v)) ? null : Number(v);
|
|
134
|
+
}
|
|
135
|
+
if (payload.vatCode !== undefined) {
|
|
136
|
+
const c = payload.vatCode;
|
|
137
|
+
productPatch.vat_code = c && String(c).length > 0 ? String(c) : null;
|
|
138
|
+
}
|
|
131
139
|
if (targetId) {
|
|
132
140
|
const { error } = await supabase
|
|
133
141
|
.from("products")
|
|
@@ -153,6 +161,12 @@ export async function upsertLocalTradeItem(params) {
|
|
|
153
161
|
floriday_payload: payload,
|
|
154
162
|
floriday_trade_item_id: params.meta?.floridayId ?? null,
|
|
155
163
|
floriday_active: params.meta?.floridayLinkStatus === "published",
|
|
164
|
+
vat_rate: payload.vatRate !== null && payload.vatRate !== undefined && payload.vatRate !== ""
|
|
165
|
+
? Number(payload.vatRate)
|
|
166
|
+
: null,
|
|
167
|
+
vat_code: payload.vatCode && String(payload.vatCode).length > 0
|
|
168
|
+
? String(payload.vatCode)
|
|
169
|
+
: null,
|
|
156
170
|
};
|
|
157
171
|
const { error } = await supabase.from("products").insert(insertRow);
|
|
158
172
|
if (error)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTradeItemSpec.d.ts","sourceRoot":"","sources":["../../src/hooks/useTradeItemSpec.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAuB,MAAM,eAAe,CAAC;AAEzE,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,aAAa,EAAE,uBAAuB,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,eAAe,EAAE,kBAAkB,EAAE,CAAC;IACtC,2DAA2D;IAC3D,2BAA2B,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzC,0FAA0F;IAC1F,2BAA2B,EAAE,OAAO,CAAC;IACrC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mGAAmG;IACnG,0BAA0B,EAAE,OAAO,CAAC;IACpC,4FAA4F;IAC5F,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,uBAAuB,EAAE,OAAO,CAAC;CAClC;
|
|
1
|
+
{"version":3,"file":"useTradeItemSpec.d.ts","sourceRoot":"","sources":["../../src/hooks/useTradeItemSpec.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAuB,MAAM,eAAe,CAAC;AAEzE,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,aAAa,EAAE,uBAAuB,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,eAAe,EAAE,kBAAkB,EAAE,CAAC;IACtC,2DAA2D;IAC3D,2BAA2B,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzC,0FAA0F;IAC1F,2BAA2B,EAAE,OAAO,CAAC;IACrC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mGAAmG;IACnG,0BAA0B,EAAE,OAAO,CAAC;IACpC,4FAA4F;IAC5F,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,uBAAuB,EAAE,OAAO,CAAC;CAClC;AAgeD,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;IAC/C,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC3C;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,cAAc,GAAG,SAAS,EAClC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,YAAY,GAAG,IAAI,EACjC,kBAAkB,CAAC,EAAE,sBAAsB,EAAE,GAAG,IAAI,GACnD,aAAa,CAsFf"}
|