@simpleapps-com/augur-hooks 0.1.0

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/index.js ADDED
@@ -0,0 +1,971 @@
1
+ // src/provider.tsx
2
+ import { createContext, useContext } from "react";
3
+ import { jsx } from "react/jsx-runtime";
4
+ var AugurApiContext = createContext(null);
5
+ function AugurHooksProvider({ api, children }) {
6
+ return /* @__PURE__ */ jsx(AugurApiContext.Provider, { value: api, children });
7
+ }
8
+ function useAugurApi() {
9
+ const api = useContext(AugurApiContext);
10
+ if (!api) {
11
+ throw new Error(
12
+ "useAugurApi must be used within an <AugurHooksProvider>. Wrap your app with <AugurHooksProvider api={apiInstance}>."
13
+ );
14
+ }
15
+ return api;
16
+ }
17
+
18
+ // src/stores/cart-store.ts
19
+ import { create } from "zustand";
20
+ import { devtools } from "zustand/middleware";
21
+ var useCartStore = create()(
22
+ devtools(
23
+ (set) => ({
24
+ cartHdrUid: void 0,
25
+ cartLines: [],
26
+ cartItemCount: 0,
27
+ setCartHdrUid: (cartHdrUid) => set({ cartHdrUid }, false, "setCartHdrUid"),
28
+ setCartLines: (cartLines) => {
29
+ const cartItemCount = cartLines.reduce(
30
+ (sum, line) => sum + (line.quantity || 0),
31
+ 0
32
+ );
33
+ set({ cartLines, cartItemCount }, false, "setCartLines");
34
+ }
35
+ }),
36
+ { name: "CartStore", enabled: process.env.NODE_ENV === "development" }
37
+ )
38
+ );
39
+ var useCartHdrUid = () => useCartStore((s) => s.cartHdrUid);
40
+ var useCartLines = () => useCartStore((s) => s.cartLines);
41
+ var useCartItemCount = () => useCartStore((s) => s.cartItemCount);
42
+ var useSetCartHdrUid = () => useCartStore((s) => s.setCartHdrUid);
43
+ var useSetCartLines = () => useCartStore((s) => s.setCartLines);
44
+
45
+ // src/stores/items-filters-store.ts
46
+ import { create as create2 } from "zustand";
47
+ import { devtools as devtools2 } from "zustand/middleware";
48
+ var DEFAULT_FILTER_STATE = {
49
+ filters: [],
50
+ limit: 12,
51
+ offset: 0,
52
+ sortBy: "asc",
53
+ q: "",
54
+ page: 1
55
+ };
56
+ var useItemFiltersStore = create2()(
57
+ devtools2(
58
+ (set) => ({
59
+ initialFiltersState: DEFAULT_FILTER_STATE,
60
+ itemsFilters: DEFAULT_FILTER_STATE,
61
+ setItemsFilters: (state) => set({ itemsFilters: state }, false, "setItemsFilters")
62
+ }),
63
+ {
64
+ name: "ItemsFiltersStore",
65
+ enabled: process.env.NODE_ENV === "development"
66
+ }
67
+ )
68
+ );
69
+
70
+ // src/hooks/use-debounce.ts
71
+ import { useEffect, useState } from "react";
72
+ function useDebounce(value, delay = 500) {
73
+ const [debouncedValue, setDebouncedValue] = useState(value);
74
+ useEffect(() => {
75
+ const handler = setTimeout(() => {
76
+ setDebouncedValue(value);
77
+ }, delay);
78
+ return () => {
79
+ clearTimeout(handler);
80
+ };
81
+ }, [value, delay]);
82
+ return debouncedValue;
83
+ }
84
+
85
+ // src/hooks/use-format-price.ts
86
+ function useFormatPrice(locale = "en-US", currency = "USD") {
87
+ const formatPrice = (price) => {
88
+ return new Intl.NumberFormat(locale, {
89
+ style: "currency",
90
+ currency,
91
+ minimumFractionDigits: 2
92
+ }).format(price);
93
+ };
94
+ return { formatPrice };
95
+ }
96
+
97
+ // src/hooks/use-item-price.ts
98
+ import { useQuery } from "@tanstack/react-query";
99
+ import { CACHE_CONFIG } from "@simpleapps-com/augur-utils";
100
+ var PRICE_CACHE_OPTIONS = {
101
+ ...CACHE_CONFIG.SEMI_STATIC,
102
+ refetchOnReconnect: true,
103
+ refetchOnWindowFocus: false,
104
+ meta: { persist: true }
105
+ };
106
+ var getItemPriceKey = (itemId, customerId, quantity = 1) => {
107
+ return ["price", itemId?.toUpperCase() || "", customerId, quantity];
108
+ };
109
+ var getItemPriceOptions = (api, itemId, customerId, quantity = 1) => ({
110
+ queryKey: getItemPriceKey(itemId, customerId, quantity),
111
+ queryFn: async () => {
112
+ const response = await api.pricing.priceEngine.get({
113
+ itemId: itemId?.toUpperCase() || "",
114
+ customerId: Number(customerId),
115
+ quantity
116
+ });
117
+ return response.data;
118
+ },
119
+ ...PRICE_CACHE_OPTIONS
120
+ });
121
+ function useItemPrice(itemId, customerId, quantity = 1, options = {}) {
122
+ const api = useAugurApi();
123
+ const defaultOptions = getItemPriceOptions(api, itemId, customerId, quantity);
124
+ return useQuery({
125
+ ...defaultOptions,
126
+ ...options.queryFn ? { queryFn: options.queryFn } : {},
127
+ enabled: options.enabled ?? (Boolean(itemId) && Boolean(customerId)),
128
+ retry: 3
129
+ });
130
+ }
131
+
132
+ // src/hooks/use-inv-mast-doc.ts
133
+ import { useQuery as useQuery2 } from "@tanstack/react-query";
134
+ import { CACHE_CONFIG as CACHE_CONFIG2 } from "@simpleapps-com/augur-utils";
135
+ var INV_MAST_DOC_CACHE_OPTIONS = CACHE_CONFIG2.STATIC;
136
+ var getInvMastDocKey = (invMastUid, itemId, includePricing) => {
137
+ return [
138
+ "invMastDoc",
139
+ invMastUid,
140
+ itemId.toUpperCase(),
141
+ includePricing
142
+ ];
143
+ };
144
+ var getInvMastDocOptions = (api, invMastUid, itemId, includePricing) => ({
145
+ queryKey: getInvMastDocKey(invMastUid, itemId, includePricing),
146
+ queryFn: async () => {
147
+ const response = await api.items.invMast.doc.list(invMastUid, {
148
+ includePricing
149
+ });
150
+ if (!response.data) throw new Error("Item not found");
151
+ return response.data;
152
+ },
153
+ ...INV_MAST_DOC_CACHE_OPTIONS
154
+ });
155
+ function useInvMastDoc(invMastUid, itemId, options = {}) {
156
+ const api = useAugurApi();
157
+ const queryOpts = getInvMastDocOptions(
158
+ api,
159
+ invMastUid,
160
+ itemId,
161
+ options.includePricing ?? "N"
162
+ );
163
+ const { data, isLoading, error } = useQuery2({
164
+ ...queryOpts,
165
+ ...options.queryFn ? { queryFn: options.queryFn } : {},
166
+ enabled: options.enabled ?? true,
167
+ initialData: options.initialData
168
+ });
169
+ return { item: data, isLoading, error };
170
+ }
171
+
172
+ // src/hooks/use-item-category.ts
173
+ import { useQuery as useQuery3 } from "@tanstack/react-query";
174
+ import { CACHE_CONFIG as CACHE_CONFIG3 } from "@simpleapps-com/augur-utils";
175
+ var CATEGORY_CACHE_OPTIONS = CACHE_CONFIG3.STATIC;
176
+ var getItemCategoryKey = (itemCategoryUid, apiOptions) => {
177
+ return ["itemCategory", itemCategoryUid, apiOptions];
178
+ };
179
+ var getItemCategoryOptions = (api, itemCategoryUid, apiOptions) => ({
180
+ queryKey: getItemCategoryKey(itemCategoryUid, apiOptions),
181
+ queryFn: async () => {
182
+ const response = await api.items.itemCategory.get(
183
+ itemCategoryUid,
184
+ apiOptions
185
+ );
186
+ if (!response.data) throw new Error("Item category not found");
187
+ return response.data;
188
+ },
189
+ ...CATEGORY_CACHE_OPTIONS
190
+ });
191
+ function useItemCategory(itemCategoryUid, options = {}) {
192
+ const api = useAugurApi();
193
+ const queryOpts = getItemCategoryOptions(
194
+ api,
195
+ itemCategoryUid,
196
+ options.apiOptions
197
+ );
198
+ const { data, isLoading, error } = useQuery3({
199
+ ...queryOpts,
200
+ ...options.queryFn ? { queryFn: options.queryFn } : {},
201
+ enabled: options.enabled ?? true
202
+ });
203
+ return { category: data, isLoading, error };
204
+ }
205
+
206
+ // src/hooks/use-inv-mast.ts
207
+ import { useQuery as useQuery4 } from "@tanstack/react-query";
208
+ import { CACHE_CONFIG as CACHE_CONFIG4 } from "@simpleapps-com/augur-utils";
209
+ var INV_MAST_CACHE_OPTIONS = CACHE_CONFIG4.STATIC;
210
+ var getInvMastKey = (invMastUid, itemId) => {
211
+ return ["invMast", invMastUid, itemId.toUpperCase()];
212
+ };
213
+ var getInvMastOptions = (api, invMastUid, itemId) => ({
214
+ queryKey: getInvMastKey(invMastUid, itemId),
215
+ queryFn: async () => {
216
+ const response = await api.items.invMast.get(invMastUid);
217
+ if (!response.data) throw new Error("Item not found");
218
+ return response.data;
219
+ },
220
+ ...INV_MAST_CACHE_OPTIONS
221
+ });
222
+ function useInvMast(invMastUid, itemId, options = {}) {
223
+ const api = useAugurApi();
224
+ const queryOpts = getInvMastOptions(api, invMastUid, itemId);
225
+ const { data, isLoading, error } = useQuery4({
226
+ ...queryOpts,
227
+ ...options.queryFn ? { queryFn: options.queryFn } : {},
228
+ enabled: options.enabled ?? true
229
+ });
230
+ return { item: data, isLoading, error };
231
+ }
232
+
233
+ // src/hooks/use-inv-mast-stock.ts
234
+ import { useQuery as useQuery5 } from "@tanstack/react-query";
235
+ import { CACHE_CONFIG as CACHE_CONFIG5 } from "@simpleapps-com/augur-utils";
236
+ var getInvMastStockKey = (invMastUid) => {
237
+ return ["invMastStock", invMastUid];
238
+ };
239
+ var getInvMastStockOptions = (api, invMastUid) => ({
240
+ queryKey: getInvMastStockKey(invMastUid),
241
+ queryFn: async () => {
242
+ const response = await api.items.invMast.stock.list(Number(invMastUid));
243
+ const stockData = response.data?.stockData ?? [];
244
+ return stockData.reduce(
245
+ (qty, stock) => qty + stock.qtyOnHand,
246
+ 0
247
+ );
248
+ },
249
+ ...CACHE_CONFIG5.SEMI_STATIC
250
+ });
251
+ function useInvMastStock(invMastUid, options = {}) {
252
+ const api = useAugurApi();
253
+ const queryOpts = getInvMastStockOptions(api, invMastUid);
254
+ const { data, isLoading, error } = useQuery5({
255
+ ...queryOpts,
256
+ ...options.queryFn ? { queryFn: options.queryFn } : {},
257
+ enabled: (options.enabled ?? true) && !!invMastUid,
258
+ retry: 3,
259
+ retryDelay: (attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 1e4)
260
+ });
261
+ return {
262
+ qtyOnHand: data ?? null,
263
+ loading: isLoading,
264
+ error
265
+ };
266
+ }
267
+
268
+ // src/hooks/use-product-category.ts
269
+ import { useQuery as useQuery6 } from "@tanstack/react-query";
270
+ import { CACHE_CONFIG as CACHE_CONFIG6 } from "@simpleapps-com/augur-utils";
271
+ var getProductCategoryKey = (itemCategoryUid) => {
272
+ return ["productCategory", itemCategoryUid];
273
+ };
274
+ var getProductCategoryOptions = (api, itemCategoryUid) => ({
275
+ queryKey: getProductCategoryKey(itemCategoryUid),
276
+ queryFn: async () => {
277
+ const response = await api.items.itemCategory.get(
278
+ Number(itemCategoryUid)
279
+ );
280
+ return response.data;
281
+ },
282
+ ...CACHE_CONFIG6.STATIC
283
+ });
284
+ function useProductCategory(itemCategoryUid, options = {}) {
285
+ const api = useAugurApi();
286
+ const { data, isLoading, error } = useQuery6({
287
+ ...itemCategoryUid ? getProductCategoryOptions(api, itemCategoryUid) : { queryKey: getProductCategoryKey(null), queryFn: () => Promise.reject() },
288
+ ...options.queryFn ? { queryFn: options.queryFn } : {},
289
+ enabled: (options.enabled ?? true) && !!itemCategoryUid,
290
+ retry: 3,
291
+ retryDelay: (attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 1e4)
292
+ });
293
+ return {
294
+ childrenTotal: data?.childrenTotal ?? 0,
295
+ itemCategoryDesc: data?.itemCategoryDesc ?? "",
296
+ productCategories: data?.children ?? null,
297
+ productCategoryImage: data?.categoryImage ?? null,
298
+ loading: isLoading,
299
+ error
300
+ };
301
+ }
302
+
303
+ // src/hooks/use-item-details.ts
304
+ import { useQuery as useQuery7 } from "@tanstack/react-query";
305
+ import { CACHE_CONFIG as CACHE_CONFIG7 } from "@simpleapps-com/augur-utils";
306
+ var getItemDetailsKey = (itemId) => {
307
+ return ["itemDetails", itemId];
308
+ };
309
+ var getItemDetailsOptions = (api, itemId) => ({
310
+ queryKey: getItemDetailsKey(itemId),
311
+ queryFn: async () => {
312
+ const response = await api.items.invMast.doc.list(Number(itemId));
313
+ if (!response.data) throw new Error("Item not found");
314
+ return response.data;
315
+ },
316
+ ...CACHE_CONFIG7.STATIC
317
+ });
318
+ function useItemDetails(itemId, options = {}) {
319
+ const api = useAugurApi();
320
+ const { data, isLoading, error } = useQuery7({
321
+ ...itemId ? getItemDetailsOptions(api, itemId) : { queryKey: getItemDetailsKey(""), queryFn: () => Promise.reject() },
322
+ ...options.queryFn ? { queryFn: options.queryFn } : {},
323
+ enabled: (options.enabled ?? true) && !!itemId,
324
+ retry: 3,
325
+ retryDelay: (attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 1e4)
326
+ });
327
+ const categoryList = data?.categoryList ?? [];
328
+ return {
329
+ itemCategoryUid: categoryList.length > 0 ? categoryList[categoryList.length - 1] : null,
330
+ itemDetails: data ?? null,
331
+ loading: isLoading,
332
+ error
333
+ };
334
+ }
335
+
336
+ // src/hooks/use-item-attributes.ts
337
+ import { useQuery as useQuery8 } from "@tanstack/react-query";
338
+ import { CACHE_CONFIG as CACHE_CONFIG8 } from "@simpleapps-com/augur-utils";
339
+ var getItemAttributesKey = (itemCategoryUid) => {
340
+ return ["itemAttributes", itemCategoryUid];
341
+ };
342
+ var getItemAttributesOptions = (api, itemCategoryUid) => ({
343
+ queryKey: getItemAttributesKey(itemCategoryUid),
344
+ queryFn: async () => {
345
+ const response = await api.openSearch.itemSearch.attributes.list({
346
+ q: "",
347
+ searchType: "query",
348
+ classId5List: String(itemCategoryUid)
349
+ });
350
+ return response.data;
351
+ },
352
+ ...CACHE_CONFIG8.STATIC
353
+ });
354
+ function useItemAttributes(itemCategoryUid, options = {}) {
355
+ const api = useAugurApi();
356
+ const { data, isLoading, error } = useQuery8({
357
+ ...itemCategoryUid ? getItemAttributesOptions(api, itemCategoryUid) : {
358
+ queryKey: getItemAttributesKey(null),
359
+ queryFn: () => Promise.reject()
360
+ },
361
+ ...options.queryFn ? { queryFn: options.queryFn } : {},
362
+ enabled: (options.enabled ?? true) && !!itemCategoryUid,
363
+ retry: 3,
364
+ retryDelay: (attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 1e4)
365
+ });
366
+ return {
367
+ attributes: data?.attributes ?? null,
368
+ loading: isLoading,
369
+ error
370
+ };
371
+ }
372
+
373
+ // src/hooks/use-product-search.ts
374
+ import { useQuery as useQuery9 } from "@tanstack/react-query";
375
+ import { CACHE_CONFIG as CACHE_CONFIG9 } from "@simpleapps-com/augur-utils";
376
+ var getProductSearchKey = (pageData) => {
377
+ return [
378
+ "productSearch",
379
+ pageData.q,
380
+ pageData.limit,
381
+ pageData.offset,
382
+ pageData.sortBy,
383
+ pageData.itemCategoryUid
384
+ ];
385
+ };
386
+ var getProductSearchOptions = (api, pageData) => ({
387
+ queryKey: getProductSearchKey(pageData),
388
+ queryFn: async () => {
389
+ const response = await api.openSearch.itemSearch.list({
390
+ q: pageData.q,
391
+ searchType: "query",
392
+ size: pageData.limit,
393
+ from: pageData.offset,
394
+ classId5List: pageData.itemCategoryUid ? String(pageData.itemCategoryUid) : void 0,
395
+ filters: pageData.filters ? JSON.stringify(pageData.filters) : void 0
396
+ });
397
+ return response.data;
398
+ },
399
+ ...CACHE_CONFIG9.SEMI_STATIC
400
+ });
401
+ function useProductSearch(pageData, options = {}) {
402
+ const api = useAugurApi();
403
+ const defaultOptions = getProductSearchOptions(api, pageData);
404
+ const { data, isLoading, error } = useQuery9({
405
+ ...defaultOptions,
406
+ ...options.queryFn ? { queryFn: options.queryFn } : {},
407
+ retry: 3,
408
+ retryDelay: (attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 1e4)
409
+ });
410
+ return {
411
+ productItems: data?.items ?? null,
412
+ total: data?.totalResults ?? 0,
413
+ loading: isLoading,
414
+ error
415
+ };
416
+ }
417
+
418
+ // src/hooks/use-search-suggestions.ts
419
+ import { useQuery as useQuery10 } from "@tanstack/react-query";
420
+ import { CACHE_CONFIG as CACHE_CONFIG10 } from "@simpleapps-com/augur-utils";
421
+ var SEARCH_SUGGESTIONS_CACHE_OPTIONS = CACHE_CONFIG10.STATIC;
422
+ var getSearchSuggestionsKey = (query, limit, offset) => {
423
+ return ["searchSuggestions", query, limit, offset];
424
+ };
425
+ var getSearchSuggestionsOptions = (api, query, limit = 10, offset = 0) => ({
426
+ queryKey: getSearchSuggestionsKey(query, limit, offset),
427
+ queryFn: async () => {
428
+ const response = await api.openSearch.suggestions.suggest.list({
429
+ q: query
430
+ });
431
+ return response.data;
432
+ },
433
+ ...SEARCH_SUGGESTIONS_CACHE_OPTIONS
434
+ });
435
+ function useSearchSuggestions(query, options = {}) {
436
+ const api = useAugurApi();
437
+ const limit = options.limit ?? 10;
438
+ const offset = options.offset ?? 0;
439
+ const enabled = (options.enabled ?? true) && query.trim().length > 0;
440
+ const defaultOptions = getSearchSuggestionsOptions(api, query, limit, offset);
441
+ const { data, isLoading, error } = useQuery10({
442
+ ...defaultOptions,
443
+ ...options.queryFn ? { queryFn: options.queryFn } : {},
444
+ enabled
445
+ });
446
+ return {
447
+ suggestions: data?.data ?? [],
448
+ total: data?.total ?? 0,
449
+ isLoading,
450
+ error
451
+ };
452
+ }
453
+
454
+ // src/hooks/use-cart-actions.ts
455
+ import { useCallback } from "react";
456
+ import { useQueryClient } from "@tanstack/react-query";
457
+ function useCartActions(callbacks) {
458
+ const queryClient = useQueryClient();
459
+ const cartHdrUid = useCartHdrUid();
460
+ const cartLines = useCartLines();
461
+ const setCartLines = useSetCartLines();
462
+ const notify = callbacks.toast;
463
+ const cartHdrUidNum = typeof cartHdrUid === "string" ? Number(cartHdrUid) : cartHdrUid;
464
+ const invalidateCartCache = useCallback(() => {
465
+ queryClient.invalidateQueries({ queryKey: ["cartLines", cartHdrUid] });
466
+ queryClient.invalidateQueries({
467
+ queryKey: ["cart-also-bought", cartHdrUid]
468
+ });
469
+ }, [queryClient, cartHdrUid]);
470
+ const addToCart = useCallback(
471
+ async (item, options = {}) => {
472
+ const { showToast = true, itemId = "", onSuccess, onError } = options;
473
+ if (!cartHdrUidNum) throw new Error("Cart UID is not set");
474
+ const previousCartLines = [...cartLines];
475
+ const existingIndex = cartLines.findIndex(
476
+ (line) => line.invMastUid === item.invMastUid
477
+ );
478
+ let optimisticCartLines;
479
+ if (existingIndex >= 0) {
480
+ optimisticCartLines = cartLines.map(
481
+ (line, index) => index === existingIndex ? { ...line, quantity: line.quantity + item.quantity } : line
482
+ );
483
+ } else {
484
+ const newLine = {
485
+ cartHdrUid: cartHdrUidNum,
486
+ invMastUid: item.invMastUid,
487
+ invMastUidCount: 1,
488
+ isAssembly: "N",
489
+ itemId,
490
+ lineNo: cartLines.length + 1,
491
+ lineNote: null,
492
+ quantity: item.quantity,
493
+ unitOfMeasure: item.unitOfMeasure
494
+ };
495
+ optimisticCartLines = [...cartLines, newLine];
496
+ }
497
+ setCartLines(optimisticCartLines);
498
+ try {
499
+ const success = await callbacks.addToCart(cartHdrUidNum, [
500
+ {
501
+ cartHdrUid: cartHdrUidNum,
502
+ invMastUid: item.invMastUid,
503
+ quantity: item.quantity,
504
+ unitOfMeasure: item.unitOfMeasure
505
+ }
506
+ ]);
507
+ if (!success) throw new Error("Failed to add item to cart");
508
+ invalidateCartCache();
509
+ if (showToast && notify?.info) {
510
+ notify.info(
511
+ `${item.quantity} x ${itemId || "Item"} added to cart`
512
+ );
513
+ }
514
+ onSuccess?.();
515
+ return true;
516
+ } catch (error) {
517
+ setCartLines(previousCartLines);
518
+ if (showToast && notify?.error) {
519
+ notify.error("Failed to add item to cart. Please try again.");
520
+ }
521
+ onError?.(error);
522
+ return false;
523
+ }
524
+ },
525
+ [cartHdrUid, cartLines, setCartLines, invalidateCartCache, callbacks, notify]
526
+ );
527
+ const updateQuantity = useCallback(
528
+ async (invMastUid, newQuantity, options = {}) => {
529
+ const { showToast = false, onSuccess, onError } = options;
530
+ if (!cartHdrUidNum) throw new Error("Cart UID is not set");
531
+ const previousCartLines = [...cartLines];
532
+ const optimisticCartLines = cartLines.map(
533
+ (line) => line.invMastUid === invMastUid ? { ...line, quantity: newQuantity } : line
534
+ );
535
+ setCartLines(optimisticCartLines);
536
+ try {
537
+ const updatedLines = cartLines.map(
538
+ (line) => line.invMastUid === invMastUid ? { ...line, quantity: newQuantity } : line
539
+ );
540
+ const success = await callbacks.updateCartLines(
541
+ cartHdrUidNum,
542
+ updatedLines
543
+ );
544
+ if (!success) throw new Error("Failed to update quantity");
545
+ invalidateCartCache();
546
+ onSuccess?.();
547
+ return true;
548
+ } catch (error) {
549
+ setCartLines(previousCartLines);
550
+ if (showToast && notify?.error) {
551
+ notify.error("Failed to update quantity. Please try again.");
552
+ }
553
+ onError?.(error);
554
+ return false;
555
+ }
556
+ },
557
+ [cartHdrUid, cartLines, setCartLines, invalidateCartCache, callbacks, notify]
558
+ );
559
+ const removeFromCart = useCallback(
560
+ async (invMastUid, options = {}) => {
561
+ const { showToast = true, itemId = "", onSuccess, onError } = options;
562
+ if (!cartHdrUidNum) throw new Error("Cart UID is not set");
563
+ const previousCartLines = [...cartLines];
564
+ const optimisticCartLines = cartLines.filter(
565
+ (line) => line.invMastUid !== invMastUid
566
+ );
567
+ setCartLines(optimisticCartLines);
568
+ try {
569
+ const updatedLines = cartLines.map(
570
+ (line) => line.invMastUid === invMastUid ? { ...line, quantity: 0 } : line
571
+ );
572
+ const success = await callbacks.updateCartLines(
573
+ cartHdrUidNum,
574
+ updatedLines
575
+ );
576
+ if (!success) throw new Error("Failed to remove item");
577
+ invalidateCartCache();
578
+ if (showToast && notify?.info) {
579
+ notify.info(`${itemId || "Item"} removed from cart`);
580
+ }
581
+ onSuccess?.();
582
+ return true;
583
+ } catch (error) {
584
+ setCartLines(previousCartLines);
585
+ if (showToast && notify?.error) {
586
+ notify.error("Failed to remove item. Please try again.");
587
+ }
588
+ onError?.(error);
589
+ return false;
590
+ }
591
+ },
592
+ [cartHdrUid, cartLines, setCartLines, invalidateCartCache, callbacks, notify]
593
+ );
594
+ const clearCart = useCallback(
595
+ async (options = {}) => {
596
+ const { showToast = true, onSuccess, onError } = options;
597
+ if (!cartHdrUidNum) throw new Error("Cart UID is not set");
598
+ const previousCartLines = [...cartLines];
599
+ setCartLines([]);
600
+ try {
601
+ const success = await callbacks.deleteItemsFromCart(cartHdrUidNum);
602
+ if (!success) throw new Error("Failed to clear cart");
603
+ invalidateCartCache();
604
+ if (showToast && notify?.info) {
605
+ notify.info("Cart cleared");
606
+ }
607
+ onSuccess?.();
608
+ return true;
609
+ } catch (error) {
610
+ setCartLines(previousCartLines);
611
+ if (showToast && notify?.error) {
612
+ notify.error("Failed to clear cart. Please try again.");
613
+ }
614
+ onError?.(error);
615
+ return false;
616
+ }
617
+ },
618
+ [cartHdrUid, cartLines, setCartLines, invalidateCartCache, callbacks, notify]
619
+ );
620
+ const isInCart = useCallback(
621
+ (invMastUid) => {
622
+ return cartLines.some((line) => line.invMastUid === invMastUid);
623
+ },
624
+ [cartLines]
625
+ );
626
+ const getItemQuantity = useCallback(
627
+ (invMastUid) => {
628
+ return cartLines.find((line) => line.invMastUid === invMastUid)?.quantity ?? 0;
629
+ },
630
+ [cartLines]
631
+ );
632
+ return {
633
+ addToCart,
634
+ updateQuantity,
635
+ removeFromCart,
636
+ clearCart,
637
+ isInCart,
638
+ getItemQuantity,
639
+ cartHdrUid,
640
+ cartLines,
641
+ invalidateCartCache
642
+ };
643
+ }
644
+
645
+ // src/hooks/use-cart-initialization.ts
646
+ import { useEffect as useEffect2, useRef } from "react";
647
+ import { useQuery as useQuery11 } from "@tanstack/react-query";
648
+ import { CACHE_CONFIG as CACHE_CONFIG11 } from "@simpleapps-com/augur-utils";
649
+ var MAX_RETRY_ATTEMPTS = 7;
650
+ var RETRY_DELAY_MS = 1e3;
651
+ function useCartInitialization(session, callbacks) {
652
+ const cartHdrUid = useCartHdrUid();
653
+ const setCartHdrUid = useSetCartHdrUid();
654
+ const setCartLines = useSetCartLines();
655
+ const retryCountRef = useRef(0);
656
+ const isInitializingRef = useRef(false);
657
+ useEffect2(() => {
658
+ if (cartHdrUid || session.status === "loading") return;
659
+ if (session.cartHdrUid && session.status === "authenticated") {
660
+ setCartHdrUid(session.cartHdrUid);
661
+ return;
662
+ }
663
+ if (session.status === "unauthenticated" && !isInitializingRef.current) {
664
+ isInitializingRef.current = true;
665
+ retryCountRef.current = 0;
666
+ const initializeGuestCart = async () => {
667
+ const existingToken = callbacks.getCartToken();
668
+ const cartToken = existingToken && typeof existingToken === "string" ? existingToken : callbacks.generateCartToken();
669
+ while (retryCountRef.current < MAX_RETRY_ATTEMPTS) {
670
+ try {
671
+ const cartHdr = await callbacks.cartHdrLookup("0", cartToken);
672
+ if (cartHdr && cartHdr.cartHdrUid !== 0) {
673
+ callbacks.saveCartToken(cartToken);
674
+ setCartHdrUid(cartHdr.cartHdrUid);
675
+ isInitializingRef.current = false;
676
+ return;
677
+ }
678
+ retryCountRef.current++;
679
+ if (retryCountRef.current < MAX_RETRY_ATTEMPTS) {
680
+ const delay = Math.min(
681
+ RETRY_DELAY_MS * Math.pow(1.5, retryCountRef.current),
682
+ 1e4
683
+ );
684
+ await new Promise((resolve) => setTimeout(resolve, delay));
685
+ }
686
+ } catch (error) {
687
+ console.error(
688
+ `Cart initialization attempt ${retryCountRef.current + 1} failed:`,
689
+ error
690
+ );
691
+ retryCountRef.current++;
692
+ if (retryCountRef.current < MAX_RETRY_ATTEMPTS) {
693
+ const delay = Math.min(
694
+ RETRY_DELAY_MS * Math.pow(1.5, retryCountRef.current),
695
+ 1e4
696
+ );
697
+ await new Promise((resolve) => setTimeout(resolve, delay));
698
+ }
699
+ }
700
+ }
701
+ console.error(
702
+ `Cart initialization failed after ${MAX_RETRY_ATTEMPTS} attempts`
703
+ );
704
+ isInitializingRef.current = false;
705
+ };
706
+ initializeGuestCart();
707
+ }
708
+ }, [session, cartHdrUid, setCartHdrUid, callbacks]);
709
+ const { data: cartLinesData } = useQuery11({
710
+ queryKey: ["cartLines", cartHdrUid],
711
+ queryFn: () => callbacks.getCartLines(Number(cartHdrUid)),
712
+ enabled: !!cartHdrUid,
713
+ ...CACHE_CONFIG11.CART
714
+ });
715
+ useEffect2(() => {
716
+ if (cartLinesData) {
717
+ setCartLines(cartLinesData);
718
+ }
719
+ }, [cartLinesData, setCartLines]);
720
+ return {
721
+ cartHdrUid,
722
+ isInitializing: isInitializingRef.current,
723
+ retryCount: retryCountRef.current
724
+ };
725
+ }
726
+
727
+ // src/hooks/use-cart-pricing.ts
728
+ import { useMemo } from "react";
729
+ import { useQueries } from "@tanstack/react-query";
730
+ function useCartPricing(options = {}) {
731
+ const api = useAugurApi();
732
+ const cartLines = useCartLines();
733
+ const { customerId } = options;
734
+ const priceQueries = useQueries({
735
+ queries: cartLines.map((line) => ({
736
+ ...getItemPriceOptions(api, line.itemId, customerId, line.quantity),
737
+ enabled: !!customerId && !!line.itemId
738
+ }))
739
+ });
740
+ const prices = useMemo(() => {
741
+ const map = {};
742
+ cartLines.forEach((line, index) => {
743
+ const queryResult = priceQueries[index];
744
+ if (queryResult?.data) {
745
+ map[line.itemId.toUpperCase()] = {
746
+ unitPrice: queryResult.data.unitPrice ?? 0,
747
+ priceData: queryResult.data
748
+ };
749
+ }
750
+ });
751
+ return map;
752
+ }, [cartLines, priceQueries]);
753
+ const getUnitPrice = useMemo(() => {
754
+ return (itemId) => {
755
+ return prices[itemId?.toUpperCase()]?.unitPrice ?? 0;
756
+ };
757
+ }, [prices]);
758
+ const getItemTotal = useMemo(() => {
759
+ return (itemId, quantity) => {
760
+ return getUnitPrice(itemId) * quantity;
761
+ };
762
+ }, [getUnitPrice]);
763
+ const subtotal = useMemo(() => {
764
+ return cartLines.reduce((sum, line) => {
765
+ const unitPrice = prices[line.itemId.toUpperCase()]?.unitPrice ?? 0;
766
+ return sum + unitPrice * line.quantity;
767
+ }, 0);
768
+ }, [cartLines, prices]);
769
+ const isLoading = priceQueries.some((q) => q.isLoading);
770
+ const isSuccess = priceQueries.every((q) => q.isSuccess);
771
+ const isError = priceQueries.some((q) => q.isError);
772
+ return {
773
+ prices,
774
+ getUnitPrice,
775
+ getItemTotal,
776
+ subtotal,
777
+ isLoading,
778
+ isSuccess,
779
+ isError
780
+ };
781
+ }
782
+ function getCartPricingQueryOptions(api, cartLines, customerId) {
783
+ return cartLines.map((line) => ({
784
+ ...getItemPriceOptions(api, line.itemId, customerId, line.quantity),
785
+ enabled: !!customerId && !!line.itemId
786
+ }));
787
+ }
788
+
789
+ // src/hooks/use-pagination-prefetch.ts
790
+ import { useQueryClient as useQueryClient2 } from "@tanstack/react-query";
791
+ import { useCallback as useCallback2 } from "react";
792
+ var usePaginationPrefetch = ({
793
+ queryKey,
794
+ queryFn,
795
+ pageSize,
796
+ staleTime = 10 * 60 * 1e3,
797
+ gcTime = 30 * 60 * 1e3,
798
+ enabled = true
799
+ }) => {
800
+ const queryClient = useQueryClient2();
801
+ const prefetchPage = useCallback2(
802
+ async (page) => {
803
+ if (!enabled) return;
804
+ const offset = (page - 1) * pageSize;
805
+ try {
806
+ await queryClient.prefetchQuery({
807
+ queryKey: [...queryKey, offset],
808
+ queryFn: () => queryFn(offset),
809
+ staleTime,
810
+ gcTime
811
+ });
812
+ } catch (error) {
813
+ console.warn(`Error prefetching page ${page}:`, error);
814
+ }
815
+ },
816
+ [queryKey, queryFn, pageSize, staleTime, gcTime, queryClient, enabled]
817
+ );
818
+ const handlePaginationHover = useCallback2(
819
+ (page) => {
820
+ const timeoutId = setTimeout(() => prefetchPage(page), 150);
821
+ return () => clearTimeout(timeoutId);
822
+ },
823
+ [prefetchPage]
824
+ );
825
+ return {
826
+ prefetchPage,
827
+ handlePaginationHover
828
+ };
829
+ };
830
+
831
+ // src/hooks/use-category-items-infinite.ts
832
+ import { useInfiniteQuery } from "@tanstack/react-query";
833
+ import {
834
+ CACHE_CONFIG as CACHE_CONFIG12
835
+ } from "@simpleapps-com/augur-utils";
836
+ var getCategoryItemsInfiniteKey = (itemCategoryUid, itemsFilters) => {
837
+ return [
838
+ "categoryItemsInfinite",
839
+ itemCategoryUid,
840
+ JSON.stringify(itemsFilters)
841
+ ];
842
+ };
843
+ function useCategoryItemsInfinite(itemCategoryUid, itemsFilters, options = {}) {
844
+ const api = useAugurApi();
845
+ const { enabled = true } = options;
846
+ return useInfiniteQuery({
847
+ queryKey: getCategoryItemsInfiniteKey(itemCategoryUid, itemsFilters),
848
+ queryFn: async ({ pageParam = 0 }) => {
849
+ const response = await api.openSearch.itemSearch.list({
850
+ q: itemsFilters.q || "",
851
+ searchType: "query",
852
+ size: itemsFilters.limit,
853
+ from: pageParam,
854
+ classId5List: String(itemCategoryUid),
855
+ filters: itemsFilters.filters?.length ? JSON.stringify(itemsFilters.filters) : void 0
856
+ });
857
+ const items = response.data?.items ?? [];
858
+ const total = response.data?.totalResults ?? 0;
859
+ const nextOffset = pageParam + itemsFilters.limit;
860
+ return {
861
+ data: items,
862
+ total,
863
+ nextCursor: nextOffset < total ? nextOffset : void 0
864
+ };
865
+ },
866
+ initialPageParam: 0,
867
+ getNextPageParam: (lastPage) => lastPage.nextCursor,
868
+ ...CACHE_CONFIG12.SEMI_STATIC,
869
+ enabled: enabled && !!itemCategoryUid
870
+ });
871
+ }
872
+
873
+ // src/hooks/use-item-search-infinite.ts
874
+ import { useInfiniteQuery as useInfiniteQuery2 } from "@tanstack/react-query";
875
+ import {
876
+ CACHE_CONFIG as CACHE_CONFIG13
877
+ } from "@simpleapps-com/augur-utils";
878
+ var getItemSearchInfiniteKey = (itemsFilters, itemCategoryUid) => {
879
+ return [
880
+ "itemSearchInfinite",
881
+ JSON.stringify(itemsFilters),
882
+ itemCategoryUid
883
+ ];
884
+ };
885
+ function useItemSearchInfinite(itemsFilters, itemCategoryUid, options = {}) {
886
+ const api = useAugurApi();
887
+ const { enabled = true } = options;
888
+ return useInfiniteQuery2({
889
+ queryKey: getItemSearchInfiniteKey(itemsFilters, itemCategoryUid),
890
+ queryFn: async ({ pageParam = 0 }) => {
891
+ const response = await api.openSearch.itemSearch.list({
892
+ q: itemsFilters.q,
893
+ searchType: "query",
894
+ size: itemsFilters.limit,
895
+ from: pageParam,
896
+ classId5List: itemCategoryUid ? String(itemCategoryUid) : void 0,
897
+ filters: itemsFilters.filters?.length ? JSON.stringify(itemsFilters.filters) : void 0
898
+ });
899
+ const items = response.data?.items ?? [];
900
+ const total = response.data?.totalResults ?? 0;
901
+ const nextOffset = pageParam + itemsFilters.limit;
902
+ return {
903
+ data: items,
904
+ total,
905
+ nextCursor: nextOffset < total ? nextOffset : void 0
906
+ };
907
+ },
908
+ initialPageParam: 0,
909
+ getNextPageParam: (lastPage) => lastPage.nextCursor,
910
+ ...CACHE_CONFIG13.SEMI_STATIC,
911
+ enabled: enabled && !!itemsFilters.q,
912
+ meta: { persist: true }
913
+ });
914
+ }
915
+ export {
916
+ AugurHooksProvider,
917
+ CATEGORY_CACHE_OPTIONS,
918
+ INV_MAST_CACHE_OPTIONS,
919
+ INV_MAST_DOC_CACHE_OPTIONS,
920
+ PRICE_CACHE_OPTIONS,
921
+ getCartPricingQueryOptions,
922
+ getCategoryItemsInfiniteKey,
923
+ getInvMastDocKey,
924
+ getInvMastDocOptions,
925
+ getInvMastKey,
926
+ getInvMastOptions,
927
+ getInvMastStockKey,
928
+ getInvMastStockOptions,
929
+ getItemAttributesKey,
930
+ getItemAttributesOptions,
931
+ getItemCategoryKey,
932
+ getItemCategoryOptions,
933
+ getItemDetailsKey,
934
+ getItemDetailsOptions,
935
+ getItemPriceKey,
936
+ getItemPriceOptions,
937
+ getItemSearchInfiniteKey,
938
+ getProductCategoryKey,
939
+ getProductCategoryOptions,
940
+ getProductSearchKey,
941
+ getProductSearchOptions,
942
+ getSearchSuggestionsKey,
943
+ getSearchSuggestionsOptions,
944
+ useAugurApi,
945
+ useCartActions,
946
+ useCartHdrUid,
947
+ useCartInitialization,
948
+ useCartItemCount,
949
+ useCartLines,
950
+ useCartPricing,
951
+ useCartStore,
952
+ useCategoryItemsInfinite,
953
+ useDebounce,
954
+ useFormatPrice,
955
+ useInvMast,
956
+ useInvMastDoc,
957
+ useInvMastStock,
958
+ useItemAttributes,
959
+ useItemCategory,
960
+ useItemDetails,
961
+ useItemFiltersStore,
962
+ useItemPrice,
963
+ useItemSearchInfinite,
964
+ usePaginationPrefetch,
965
+ useProductCategory,
966
+ useProductSearch,
967
+ useSearchSuggestions,
968
+ useSetCartHdrUid,
969
+ useSetCartLines
970
+ };
971
+ //# sourceMappingURL=index.js.map