@flowselections/floriday-voorraad 1.0.110 → 1.0.115

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist-lib/components/voorraad/ArtikelWizard.d.ts.map +1 -1
  2. package/dist-lib/components/voorraad/ArtikelWizard.js +63 -7
  3. package/dist-lib/components/voorraad/FustenPage.d.ts.map +1 -1
  4. package/dist-lib/components/voorraad/FustenPage.js +10 -6
  5. package/dist-lib/components/voorraad/PriceStatusBadge.d.ts.map +1 -1
  6. package/dist-lib/components/voorraad/PriceStatusBadge.js +6 -1
  7. package/dist-lib/components/voorraad/PublishProgressCard.d.ts +5 -0
  8. package/dist-lib/components/voorraad/PublishProgressCard.d.ts.map +1 -1
  9. package/dist-lib/components/voorraad/PublishProgressCard.js +16 -1
  10. package/dist-lib/components/voorraad/VoorraadPage.d.ts +13 -0
  11. package/dist-lib/components/voorraad/VoorraadPage.d.ts.map +1 -1
  12. package/dist-lib/components/voorraad/VoorraadPage.js +36 -54
  13. package/dist-lib/hooks/useNoPriceProducts.d.ts +10 -0
  14. package/dist-lib/hooks/useNoPriceProducts.d.ts.map +1 -0
  15. package/dist-lib/hooks/useNoPriceProducts.js +56 -0
  16. package/dist-lib/hooks/useStockPushJobs.d.ts.map +1 -1
  17. package/dist-lib/hooks/useStockPushJobs.js +6 -1
  18. package/dist-lib/hooks/useStockSyncHealth.d.ts.map +1 -1
  19. package/dist-lib/hooks/useStockSyncHealth.js +2 -9
  20. package/dist-lib/hooks/useVoorraadData.d.ts.map +1 -1
  21. package/dist-lib/hooks/useVoorraadData.js +45 -24
  22. package/dist-lib/integrations/supabase/types.d.ts +818 -122
  23. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  24. package/dist-lib/integrations/supabase/types.js +1 -0
  25. package/dist-lib/lib/__tests__/fust-dimensions.test.d.ts +2 -0
  26. package/dist-lib/lib/__tests__/fust-dimensions.test.d.ts.map +1 -0
  27. package/dist-lib/lib/__tests__/fust-dimensions.test.js +27 -0
  28. package/dist-lib/lib/__tests__/publish-114.test.d.ts +2 -0
  29. package/dist-lib/lib/__tests__/publish-114.test.d.ts.map +1 -0
  30. package/dist-lib/lib/__tests__/publish-114.test.js +31 -0
  31. package/dist-lib/lib/__tests__/request-guard.test.d.ts +2 -0
  32. package/dist-lib/lib/__tests__/request-guard.test.d.ts.map +1 -0
  33. package/dist-lib/lib/__tests__/request-guard.test.js +50 -0
  34. package/dist-lib/lib/fusten.d.ts +14 -3
  35. package/dist-lib/lib/fusten.d.ts.map +1 -1
  36. package/dist-lib/lib/fusten.js +38 -7
  37. package/dist-lib/lib/publish-errors.d.ts +6 -1
  38. package/dist-lib/lib/publish-errors.d.ts.map +1 -1
  39. package/dist-lib/lib/publish-errors.js +22 -2
  40. package/dist-lib/lib/request-guard.d.ts +46 -0
  41. package/dist-lib/lib/request-guard.d.ts.map +1 -0
  42. package/dist-lib/lib/request-guard.js +100 -0
  43. package/package.json +1 -1
  44. package/sql/floriday-voorraad-schema.sql +186 -27
@@ -1,12 +1,3 @@
1
- /**
2
- * Gezondheid van de voorraad-push-wachtrij richting Floriday.
3
- *
4
- * Bewust een venster van 24 uur: oude, allang achterhaalde fouten mogen de
5
- * gebruiker niet eindeloos blijven waarschuwen. Regels die door een nieuwere
6
- * voorraadstand zijn vervangen (`superseded`) tellen niet mee.
7
- * Toont ook de meest voorkomende reden, het aantal artikelen en hoeveel
8
- * daarvan geen prijs in het weekaanbod hebben.
9
- */
10
1
  import { useQuery } from "@tanstack/react-query";
11
2
  import { supabase } from "../integrations/supabase/client.js";
12
3
  const STALE_MINUTES = 10;
@@ -29,6 +20,8 @@ export function useStockSyncHealth() {
29
20
  return useQuery({
30
21
  queryKey: ["stock-sync-health"],
31
22
  refetchInterval: 60000,
23
+ refetchIntervalInBackground: false,
24
+ refetchOnWindowFocus: false,
32
25
  queryFn: async () => {
33
26
  const since = new Date(Date.now() - WINDOW_HOURS * 3600000).toISOString();
34
27
  const { data, error } = await supabase
@@ -1 +1 @@
1
- {"version":3,"file":"useVoorraadData.d.ts","sourceRoot":"","sources":["../../src/hooks/useVoorraadData.ts"],"names":[],"mappings":"AAEA,OAAO,EAAsB,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAsB5E;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;;;;;EA+U1D"}
1
+ {"version":3,"file":"useVoorraadData.d.ts","sourceRoot":"","sources":["../../src/hooks/useVoorraadData.ts"],"names":[],"mappings":"AAGA,OAAO,EAAsB,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAsB5E;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;;;;;EA2U1D"}
@@ -1,4 +1,5 @@
1
- import { useCallback, useEffect, useState } from "react";
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
+ import { createBundler, pageRequestGuard } from "../lib/request-guard.js";
2
3
  import { supabase } from "../integrations/supabase/client.js";
3
4
  import { normaliseTradeItem } from "../lib/floriday-client.js";
4
5
  import { floridayInfoFromCache } from "../lib/floriday-info.js";
@@ -45,6 +46,8 @@ export function useVoorraadData(connectionId) {
45
46
  const [error, setError] = useState(null);
46
47
  const { items: localItems, loading: localLoading, reload: reloadLocal, } = useLocalTradeItems(connectionId);
47
48
  const loadPublished = useCallback(async () => {
49
+ if (!pageRequestGuard.allow("products-overzicht"))
50
+ return;
48
51
  setLoading(true);
49
52
  setError(null);
50
53
  try {
@@ -148,30 +151,46 @@ export function useVoorraadData(connectionId) {
148
151
  useEffect(() => {
149
152
  loadPublished();
150
153
  }, [loadPublished]);
154
+ // Realtime-seintjes gebundeld: hooguit één herlaadactie per 2 s, niet in een
155
+ // verborgen tabblad (wel bij terugkeren). Voorkomt opvraag-stormen (1.0.111).
156
+ const reloadRef = useRef({ stock: false, all: false });
151
157
  useEffect(() => {
152
- const channel = supabase
158
+ const bundler = createBundler(() => {
159
+ const r = reloadRef.current;
160
+ reloadRef.current = { stock: false, all: false };
161
+ if (r.all) {
162
+ loadPublished();
163
+ reloadLocal();
164
+ }
165
+ else if (r.stock && pageRequestGuard.allow("trade_item_stock")) {
166
+ fetchStockMap(connectionId).then(setStockMap).catch(() => { });
167
+ }
168
+ }, 2000);
169
+ const markAll = () => {
170
+ reloadRef.current.all = true;
171
+ bundler.trigger();
172
+ };
173
+ const markStock = () => {
174
+ reloadRef.current.stock = true;
175
+ bundler.trigger();
176
+ };
177
+ let channel = supabase
153
178
  .channel(`voorraad-stock-${connectionId ?? "eigen"}`)
154
- .on("postgres_changes", { event: "*", schema: "public", table: "trade_item_stock" }, () => {
155
- fetchStockMap(connectionId).then(setStockMap).catch(() => { });
156
- })
157
- .on("postgres_changes", { event: "*", schema: "public", table: "products" }, () => {
158
- loadPublished();
159
- reloadLocal();
160
- })
161
- .on("postgres_changes", { event: "*", schema: "public", table: "floriday_trade_items_cache", filter: `connection_id=eq.${connectionId}` }, () => {
162
- loadPublished();
163
- })
164
- .on("postgres_changes", { event: "*", schema: "public", table: "product_groups" }, () => {
165
- loadPublished();
166
- })
167
- .on("postgres_changes", { event: "*", schema: "public", table: "product_bom_items" }, () => {
168
- loadPublished();
169
- })
170
- .on("postgres_changes", { event: "*", schema: "public", table: "product_group_items" }, () => {
171
- loadPublished();
172
- })
173
- .subscribe();
179
+ .on("postgres_changes", { event: "*", schema: "public", table: "trade_item_stock" }, markStock)
180
+ .on("postgres_changes", { event: "*", schema: "public", table: "products" }, markAll);
181
+ if (connectionId) {
182
+ channel = channel.on("postgres_changes", { event: "*", schema: "public", table: "floriday_trade_items_cache", filter: `connection_id=eq.${connectionId}` }, markAll);
183
+ }
184
+ channel = channel
185
+ .on("postgres_changes", { event: "*", schema: "public", table: "product_groups" }, markAll)
186
+ .on("postgres_changes", { event: "*", schema: "public", table: "product_bom_items" }, markAll)
187
+ .on("postgres_changes", { event: "*", schema: "public", table: "product_group_items" }, markAll);
188
+ channel.subscribe();
189
+ const onVis = () => bundler.flushIfPending();
190
+ document.addEventListener("visibilitychange", onVis);
174
191
  return () => {
192
+ bundler.cancel();
193
+ document.removeEventListener("visibilitychange", onVis);
175
194
  supabase.removeChannel(channel);
176
195
  };
177
196
  }, [connectionId, loadPublished, reloadLocal]);
@@ -274,7 +293,8 @@ export function useVoorraadData(connectionId) {
274
293
  return i;
275
294
  return { ...i, floriday: info };
276
295
  };
277
- const merged = [
296
+ // Stabiele identiteit: alleen een nieuwe lijst als de onderliggende data verandert.
297
+ const merged = useMemo(() => [
278
298
  ...localItems.map((i) => applyProductGroupReservation(classify(attachFloriday(applyStock(i, lookupStock(stockMap, {
279
299
  tradeItemKey: i.tradeItemKey ?? null,
280
300
  floridayId: i.floridayId ?? null,
@@ -287,7 +307,8 @@ export function useVoorraadData(connectionId) {
287
307
  tradeItemKey: i.tradeItemKey ?? null,
288
308
  productId: i.productId ?? null,
289
309
  })))))),
290
- ];
310
+ // eslint-disable-next-line react-hooks/exhaustive-deps
311
+ ], [localItems, publishedItems, stockMap, typeSets, floridayInfoMap, floridayStockMap]);
291
312
  return {
292
313
  items: merged,
293
314
  loading: loading || localLoading,