@classytic/commerce-sdk 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.

Potentially problematic release.


This version of @classytic/commerce-sdk might be problematic. Click here for more details.

Files changed (131) hide show
  1. package/LICENSE +14 -0
  2. package/README.md +104 -0
  3. package/dist/adjustment-DTSLM7AN.js +5 -0
  4. package/dist/adjustment-DTSLM7AN.js.map +1 -0
  5. package/dist/analytics/index.d.ts +27 -0
  6. package/dist/analytics/index.js +6 -0
  7. package/dist/analytics/index.js.map +1 -0
  8. package/dist/analytics-DMcD-o8w.d.ts +76 -0
  9. package/dist/api-factory-B_h4RKBm.d.ts +280 -0
  10. package/dist/auth/index.d.ts +39 -0
  11. package/dist/auth/index.js +5 -0
  12. package/dist/auth/index.js.map +1 -0
  13. package/dist/catalog/index.d.ts +479 -0
  14. package/dist/catalog/index.js +9 -0
  15. package/dist/catalog/index.js.map +1 -0
  16. package/dist/chunk-4ZQK3FFN.js +40 -0
  17. package/dist/chunk-4ZQK3FFN.js.map +1 -0
  18. package/dist/chunk-5L6EXDGH.js +465 -0
  19. package/dist/chunk-5L6EXDGH.js.map +1 -0
  20. package/dist/chunk-5ZFW3FEI.js +183 -0
  21. package/dist/chunk-5ZFW3FEI.js.map +1 -0
  22. package/dist/chunk-66OQAZSL.js +94 -0
  23. package/dist/chunk-66OQAZSL.js.map +1 -0
  24. package/dist/chunk-6RYGA6MF.js +123 -0
  25. package/dist/chunk-6RYGA6MF.js.map +1 -0
  26. package/dist/chunk-B6MPVOV7.js +328 -0
  27. package/dist/chunk-B6MPVOV7.js.map +1 -0
  28. package/dist/chunk-BDA2WSJA.js +148 -0
  29. package/dist/chunk-BDA2WSJA.js.map +1 -0
  30. package/dist/chunk-EIVYT3HM.js +126 -0
  31. package/dist/chunk-EIVYT3HM.js.map +1 -0
  32. package/dist/chunk-EPQN7ZKZ.js +27 -0
  33. package/dist/chunk-EPQN7ZKZ.js.map +1 -0
  34. package/dist/chunk-FA7QFJ2G.js +177 -0
  35. package/dist/chunk-FA7QFJ2G.js.map +1 -0
  36. package/dist/chunk-I5TIKUIQ.js +261 -0
  37. package/dist/chunk-I5TIKUIQ.js.map +1 -0
  38. package/dist/chunk-ILQUH444.js +135 -0
  39. package/dist/chunk-ILQUH444.js.map +1 -0
  40. package/dist/chunk-IXMWZJLV.js +616 -0
  41. package/dist/chunk-IXMWZJLV.js.map +1 -0
  42. package/dist/chunk-KZIGRIQG.js +75 -0
  43. package/dist/chunk-KZIGRIQG.js.map +1 -0
  44. package/dist/chunk-OF5M6R2S.js +769 -0
  45. package/dist/chunk-OF5M6R2S.js.map +1 -0
  46. package/dist/chunk-PYYLHUV6.js +3 -0
  47. package/dist/chunk-PYYLHUV6.js.map +1 -0
  48. package/dist/chunk-QO5AGZFP.js +159 -0
  49. package/dist/chunk-QO5AGZFP.js.map +1 -0
  50. package/dist/chunk-QUMTBLNE.js +76 -0
  51. package/dist/chunk-QUMTBLNE.js.map +1 -0
  52. package/dist/chunk-R5Z7NYLH.js +126 -0
  53. package/dist/chunk-R5Z7NYLH.js.map +1 -0
  54. package/dist/chunk-SZYWG5IB.js +75 -0
  55. package/dist/chunk-SZYWG5IB.js.map +1 -0
  56. package/dist/chunk-U3XT35GZ.js +202 -0
  57. package/dist/chunk-U3XT35GZ.js.map +1 -0
  58. package/dist/chunk-UGELTUIZ.js +830 -0
  59. package/dist/chunk-UGELTUIZ.js.map +1 -0
  60. package/dist/chunk-VR36QVX2.js +122 -0
  61. package/dist/chunk-VR36QVX2.js.map +1 -0
  62. package/dist/chunk-WUOQK7BO.js +13 -0
  63. package/dist/chunk-WUOQK7BO.js.map +1 -0
  64. package/dist/chunk-X6PV5MHG.js +582 -0
  65. package/dist/chunk-X6PV5MHG.js.map +1 -0
  66. package/dist/chunk-ZWLMFLLH.js +534 -0
  67. package/dist/chunk-ZWLMFLLH.js.map +1 -0
  68. package/dist/content/index.d.ts +309 -0
  69. package/dist/content/index.js +6 -0
  70. package/dist/content/index.js.map +1 -0
  71. package/dist/core/index.d.ts +107 -0
  72. package/dist/core/index.js +5 -0
  73. package/dist/core/index.js.map +1 -0
  74. package/dist/core/react.d.ts +107 -0
  75. package/dist/core/react.js +5 -0
  76. package/dist/core/react.js.map +1 -0
  77. package/dist/coupon-CHFcw7cd.d.ts +632 -0
  78. package/dist/coupon-zGkvO-Xx.d.ts +129 -0
  79. package/dist/crud.factory-DyKaPHcU.d.ts +181 -0
  80. package/dist/finance/index.d.ts +81 -0
  81. package/dist/finance/index.js +5 -0
  82. package/dist/finance/index.js.map +1 -0
  83. package/dist/finance-BJdfKRw0.d.ts +135 -0
  84. package/dist/index.d.ts +31 -0
  85. package/dist/index.js +29 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/inventory/index.d.ts +512 -0
  88. package/dist/inventory/index.js +16 -0
  89. package/dist/inventory/index.js.map +1 -0
  90. package/dist/inventory-DCiIZh8P.d.ts +742 -0
  91. package/dist/logistics/index.d.ts +226 -0
  92. package/dist/logistics/index.js +7 -0
  93. package/dist/logistics/index.js.map +1 -0
  94. package/dist/logistics-V8a9lUN3.d.ts +428 -0
  95. package/dist/media-CNLJK93J.d.ts +721 -0
  96. package/dist/movement-7MV3ADY5.js +5 -0
  97. package/dist/movement-7MV3ADY5.js.map +1 -0
  98. package/dist/payment-BRboLqvU.d.ts +127 -0
  99. package/dist/payments/index.d.ts +55 -0
  100. package/dist/payments/index.js +6 -0
  101. package/dist/payments/index.js.map +1 -0
  102. package/dist/platform/index.d.ts +645 -0
  103. package/dist/platform/index.js +8 -0
  104. package/dist/platform/index.js.map +1 -0
  105. package/dist/pos-D1jkkFl0.d.ts +885 -0
  106. package/dist/product-p09zXkXB.d.ts +260 -0
  107. package/dist/purchase-24BGT2HA.js +5 -0
  108. package/dist/purchase-24BGT2HA.js.map +1 -0
  109. package/dist/request-652PS6VR.js +5 -0
  110. package/dist/request-652PS6VR.js.map +1 -0
  111. package/dist/sales/index.d.ts +585 -0
  112. package/dist/sales/index.js +9 -0
  113. package/dist/sales/index.js.map +1 -0
  114. package/dist/server.d.ts +120 -0
  115. package/dist/server.js +27 -0
  116. package/dist/server.js.map +1 -0
  117. package/dist/size-guide-DgjzjM5P.d.ts +554 -0
  118. package/dist/stock-DEApGC-w.d.ts +632 -0
  119. package/dist/stock-OOUW57VQ.js +5 -0
  120. package/dist/stock-OOUW57VQ.js.map +1 -0
  121. package/dist/supplier-OC6JAWV6.js +5 -0
  122. package/dist/supplier-OC6JAWV6.js.map +1 -0
  123. package/dist/transaction/index.d.ts +104 -0
  124. package/dist/transaction/index.js +8 -0
  125. package/dist/transaction/index.js.map +1 -0
  126. package/dist/transaction-BTmoHpWh.d.ts +428 -0
  127. package/dist/transaction-u5oaNuav.d.ts +84 -0
  128. package/dist/transfer-7SYSH3RG.js +5 -0
  129. package/dist/transfer-7SYSH3RG.js.map +1 -0
  130. package/dist/user-data-DdLjAGwO.d.ts +132 -0
  131. package/package.json +146 -0
@@ -0,0 +1,582 @@
1
+ import { BaseApi } from './chunk-I5TIKUIQ.js';
2
+ import { createCrudHooks } from './chunk-B6MPVOV7.js';
3
+ import { getToastHandler } from './chunk-U3XT35GZ.js';
4
+ import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
5
+
6
+ // src/catalog/api/product.ts
7
+ var ProductApi = class extends BaseApi {
8
+ constructor(config = {}) {
9
+ super("products", config);
10
+ }
11
+ /**
12
+ * Get product by slug
13
+ * GET /products/slug/:slug
14
+ * (Public endpoint)
15
+ *
16
+ * @param token - Auth token (optional, public endpoint)
17
+ * @param slug - Product slug
18
+ * @param options - Additional fetch options
19
+ * @returns Product object
20
+ */
21
+ async getBySlug({
22
+ token = null,
23
+ slug,
24
+ options = {}
25
+ }) {
26
+ if (!slug) {
27
+ throw new Error("Product slug is required");
28
+ }
29
+ return this.request("GET", `${this.baseUrl}/slug/${slug}`, {
30
+ token: token || void 0,
31
+ options: {
32
+ cache: this.config.cache,
33
+ ...options
34
+ }
35
+ });
36
+ }
37
+ /**
38
+ * Get product recommendations
39
+ * GET /products/:id/recommendations
40
+ * (Public endpoint)
41
+ *
42
+ * @param token - Auth token (optional)
43
+ * @param productId - Product ID to get recommendations for
44
+ * @param options - Additional fetch options
45
+ * @returns List of recommended products
46
+ */
47
+ async getRecommendations({
48
+ token = null,
49
+ productId,
50
+ options = {}
51
+ }) {
52
+ if (!productId) {
53
+ throw new Error("Product ID is required");
54
+ }
55
+ return this.request("GET", `${this.baseUrl}/${productId}/recommendations`, {
56
+ token: token || void 0,
57
+ options: {
58
+ cache: this.config.cache,
59
+ ...options
60
+ }
61
+ });
62
+ }
63
+ /**
64
+ * Get soft-deleted products (Recycle Bin)
65
+ * GET /products/deleted
66
+ * (Admin only)
67
+ *
68
+ * @param token - Auth token (required)
69
+ * @param params - Query parameters for pagination/filtering
70
+ * @param options - Additional fetch options
71
+ * @returns Paginated list of deleted products
72
+ */
73
+ async getDeleted({
74
+ token,
75
+ params = {},
76
+ options = {}
77
+ }) {
78
+ return this.request("GET", `${this.baseUrl}/deleted`, {
79
+ token,
80
+ params,
81
+ options: {
82
+ cache: this.config.cache,
83
+ ...options
84
+ }
85
+ });
86
+ }
87
+ /**
88
+ * Restore a soft-deleted product
89
+ * POST /products/:id/restore
90
+ * (Admin only)
91
+ *
92
+ * @param token - Auth token (required)
93
+ * @param id - Product ID to restore
94
+ * @param options - Additional fetch options
95
+ * @returns Restored product
96
+ */
97
+ async restore({
98
+ token,
99
+ id,
100
+ options = {}
101
+ }) {
102
+ if (!id) {
103
+ throw new Error("Product ID is required");
104
+ }
105
+ return this.request("POST", `${this.baseUrl}/${id}/restore`, {
106
+ token,
107
+ options
108
+ });
109
+ }
110
+ /**
111
+ * Permanently delete a product (Hard delete)
112
+ * DELETE /products/:id?hard=true
113
+ * (Admin only - use with caution)
114
+ *
115
+ * @param token - Auth token (required)
116
+ * @param id - Product ID to permanently delete
117
+ * @param options - Additional fetch options
118
+ * @returns Delete confirmation
119
+ */
120
+ async hardDelete({
121
+ token,
122
+ id,
123
+ options = {}
124
+ }) {
125
+ if (!id) {
126
+ throw new Error("Product ID is required");
127
+ }
128
+ return this.delete({
129
+ token,
130
+ id,
131
+ options: {
132
+ ...options,
133
+ // @ts-ignore - params is handled internally
134
+ params: { hard: "true" }
135
+ }
136
+ });
137
+ }
138
+ /**
139
+ * Sync product stock quantity
140
+ * POST /products/:id/sync-stock
141
+ *
142
+ * Recomputes product.quantity by summing all StockEntry quantities across branches.
143
+ * (Requires: admin, warehouse-admin, warehouse-staff, or store-manager role)
144
+ *
145
+ * @param token - Auth token (required)
146
+ * @param id - Product ID to sync stock for
147
+ * @param options - Additional fetch options
148
+ * @returns Sync result with new quantity
149
+ */
150
+ async syncStock({
151
+ token,
152
+ id,
153
+ options = {}
154
+ }) {
155
+ if (!id) {
156
+ throw new Error("Product ID is required");
157
+ }
158
+ return this.request("POST", `${this.baseUrl}/${id}/sync-stock`, {
159
+ token,
160
+ options
161
+ });
162
+ }
163
+ };
164
+ var productApi = new ProductApi();
165
+
166
+ // src/catalog/api/category.ts
167
+ var CategoryApi = class extends BaseApi {
168
+ constructor(config = {}) {
169
+ super("categories", config);
170
+ }
171
+ /**
172
+ * Get category tree (nested structure)
173
+ * GET /categories/tree
174
+ *
175
+ * **This is the main endpoint - FE should cache this and derive everything else from it.**
176
+ *
177
+ * Returns nested tree structure with children. Use helper functions to flatten, search, or extract children.
178
+ *
179
+ * @param token - Auth token (optional, public endpoint)
180
+ * @param options - Additional fetch options
181
+ * @returns Nested category tree
182
+ *
183
+ * @example
184
+ * ```typescript
185
+ * const { data } = await categoryApi.getTree({ token: null });
186
+ * // data = [{ slug: "clothing", name: "Clothing", children: [...] }]
187
+ * ```
188
+ */
189
+ async getTree({
190
+ token = null,
191
+ options = {}
192
+ } = {}) {
193
+ return this.request("GET", `${this.baseUrl}/tree`, {
194
+ token: token || void 0,
195
+ options: {
196
+ cache: this.config.cache,
197
+ ...options
198
+ }
199
+ });
200
+ }
201
+ /**
202
+ * Get category by slug
203
+ * GET /categories/slug/:slug
204
+ *
205
+ * For URL resolution when you need full category details.
206
+ *
207
+ * @param token - Auth token (optional, public endpoint)
208
+ * @param slug - Category slug (e.g., "electronics", "t-shirts")
209
+ * @param options - Additional fetch options
210
+ * @returns Category object
211
+ *
212
+ * @example
213
+ * ```typescript
214
+ * const { data } = await categoryApi.getBySlug({
215
+ * token: null,
216
+ * slug: 'electronics'
217
+ * });
218
+ * ```
219
+ */
220
+ async getBySlug({
221
+ token = null,
222
+ slug,
223
+ options = {}
224
+ }) {
225
+ if (!slug) {
226
+ throw new Error("Category slug is required");
227
+ }
228
+ return this.request("GET", `${this.baseUrl}/slug/${slug}`, {
229
+ token: token || void 0,
230
+ options: {
231
+ cache: this.config.cache,
232
+ ...options
233
+ }
234
+ });
235
+ }
236
+ /**
237
+ * Sync product counts for all categories
238
+ * POST /categories/sync-product-count
239
+ *
240
+ * Recalculates `productCount` for all categories based on current products.
241
+ * Use when manual data fixes or migrations may have desynced counts.
242
+ *
243
+ * @param token - Auth token (admin or inventory staff required)
244
+ * @param options - Additional fetch options
245
+ * @returns Number of categories updated
246
+ *
247
+ * @example
248
+ * ```typescript
249
+ * const { data } = await categoryApi.syncProductCount({ token });
250
+ * // data = { updated: 42 }
251
+ * ```
252
+ */
253
+ async syncProductCount({
254
+ token,
255
+ options = {}
256
+ }) {
257
+ return this.request("POST", `${this.baseUrl}/sync-product-count`, {
258
+ token,
259
+ options
260
+ });
261
+ }
262
+ };
263
+ var categoryApi = new CategoryApi();
264
+
265
+ // src/catalog/api/size-guide.ts
266
+ var SizeGuideApi = class extends BaseApi {
267
+ constructor(config = {}) {
268
+ super("size-guides", config);
269
+ }
270
+ /**
271
+ * Get size guide by slug
272
+ * GET /size-guides/slug/:slug
273
+ *
274
+ * For product detail pages to fetch the appropriate size guide.
275
+ *
276
+ * @param token - Auth token (optional, public endpoint)
277
+ * @param slug - Size guide slug (e.g., "t-shirts-tops")
278
+ * @param options - Additional fetch options
279
+ * @returns Size guide object
280
+ *
281
+ * @example
282
+ * ```typescript
283
+ * const { data } = await sizeGuideApi.getBySlug({
284
+ * token: null,
285
+ * slug: 't-shirts-tops'
286
+ * });
287
+ * ```
288
+ */
289
+ async getBySlug({
290
+ token = null,
291
+ slug,
292
+ options = {}
293
+ }) {
294
+ if (!slug) {
295
+ throw new Error("Size guide slug is required");
296
+ }
297
+ return this.request("GET", `${this.baseUrl}/slug/${slug}`, {
298
+ token: token || void 0,
299
+ options: {
300
+ cache: this.config.cache,
301
+ ...options
302
+ }
303
+ });
304
+ }
305
+ };
306
+ var sizeGuideApi = new SizeGuideApi();
307
+ var productHooks = createCrudHooks({
308
+ api: productApi,
309
+ entityKey: "products",
310
+ singular: "Product",
311
+ plural: "Products",
312
+ defaults: {
313
+ staleTime: 5 * 60 * 1e3
314
+ // 5 minutes
315
+ }
316
+ });
317
+ var {
318
+ KEYS: PRODUCT_KEYS,
319
+ useList: useProducts,
320
+ useDetail: useProductDetail,
321
+ useActions: useProductActions,
322
+ useNavigation: useProductNavigation
323
+ } = productHooks;
324
+ function useProductBySlug(token, slug, options = {}) {
325
+ return useQuery({
326
+ queryKey: [...PRODUCT_KEYS.all, "slug", slug],
327
+ queryFn: () => productApi.getBySlug({ token, slug }),
328
+ enabled: !!slug,
329
+ staleTime: 5 * 60 * 1e3,
330
+ // 5 minutes
331
+ ...options
332
+ });
333
+ }
334
+ function useProductRecommendations(productId, options = {}) {
335
+ const { data, isLoading, error } = useQuery({
336
+ queryKey: [...PRODUCT_KEYS.all, "recommendations", productId],
337
+ queryFn: () => productApi.getRecommendations({ token: null, productId }),
338
+ enabled: !!productId,
339
+ staleTime: 10 * 60 * 1e3,
340
+ // 10 minutes
341
+ ...options
342
+ });
343
+ return {
344
+ recommendations: data?.data ?? [],
345
+ isLoading,
346
+ error
347
+ };
348
+ }
349
+ function useDeletedProducts(token, params = {}, options = {}) {
350
+ return useQuery({
351
+ queryKey: [...PRODUCT_KEYS.all, "deleted", params],
352
+ queryFn: () => productApi.getDeleted({ token, params }),
353
+ enabled: !!token,
354
+ staleTime: 2 * 60 * 1e3,
355
+ // 2 minutes
356
+ ...options
357
+ });
358
+ }
359
+ function useRestoreProduct(token) {
360
+ const queryClient = useQueryClient();
361
+ const toast = getToastHandler();
362
+ return useMutation({
363
+ mutationFn: (id) => productApi.restore({ token, id }),
364
+ onSuccess: () => {
365
+ toast.success("Product restored successfully");
366
+ queryClient.invalidateQueries({ queryKey: [...PRODUCT_KEYS.all, "deleted"] });
367
+ queryClient.invalidateQueries({ queryKey: PRODUCT_KEYS.lists() });
368
+ },
369
+ onError: (error) => {
370
+ toast.error(error.message || "Failed to restore product");
371
+ }
372
+ });
373
+ }
374
+ function useHardDeleteProduct(token) {
375
+ const queryClient = useQueryClient();
376
+ const toast = getToastHandler();
377
+ return useMutation({
378
+ mutationFn: (id) => productApi.hardDelete({ token, id }),
379
+ onSuccess: () => {
380
+ toast.success("Product permanently deleted");
381
+ queryClient.invalidateQueries({ queryKey: [...PRODUCT_KEYS.all, "deleted"] });
382
+ },
383
+ onError: (error) => {
384
+ toast.error(error.message || "Failed to permanently delete product");
385
+ }
386
+ });
387
+ }
388
+ function useSyncProductStock(token) {
389
+ const queryClient = useQueryClient();
390
+ const toast = getToastHandler();
391
+ return useMutation({
392
+ mutationFn: (id) => productApi.syncStock({ token, id }),
393
+ onSuccess: (result, id) => {
394
+ toast.success(`Stock synced: ${result.totalQuantity} units`);
395
+ queryClient.invalidateQueries({ queryKey: PRODUCT_KEYS.detail(id) });
396
+ queryClient.invalidateQueries({ queryKey: PRODUCT_KEYS.lists() });
397
+ },
398
+ onError: (error) => {
399
+ toast.error(error.message || "Failed to sync stock");
400
+ }
401
+ });
402
+ }
403
+ var categoryHooks = createCrudHooks({
404
+ api: categoryApi,
405
+ entityKey: "categories",
406
+ singular: "Category",
407
+ plural: "Categories",
408
+ defaults: {
409
+ staleTime: 10 * 60 * 1e3
410
+ // 10 minutes
411
+ }
412
+ });
413
+ var {
414
+ KEYS: CATEGORY_KEYS,
415
+ useList: useCategories,
416
+ useDetail: useCategoryDetail,
417
+ useActions: useCategoryActions,
418
+ useNavigation: useCategoryNavigation
419
+ } = categoryHooks;
420
+ function useCategoryTree(token, options = {}) {
421
+ return useQuery({
422
+ queryKey: [...CATEGORY_KEYS.all, "tree"],
423
+ queryFn: () => categoryApi.getTree({ token }),
424
+ staleTime: 30 * 60 * 1e3,
425
+ // 30 minutes (categories rarely change)
426
+ gcTime: 60 * 60 * 1e3,
427
+ // 60 minutes
428
+ ...options
429
+ });
430
+ }
431
+ function useCategoryBySlug(token, slug, options = {}) {
432
+ return useQuery({
433
+ queryKey: [...CATEGORY_KEYS.all, "slug", slug],
434
+ queryFn: () => categoryApi.getBySlug({ token, slug }),
435
+ enabled: !!slug,
436
+ staleTime: 30 * 60 * 1e3,
437
+ // 30 minutes
438
+ ...options
439
+ });
440
+ }
441
+ function useCategorySyncProductCount(token) {
442
+ const queryClient = useQueryClient();
443
+ const toast = getToastHandler();
444
+ return useMutation({
445
+ mutationFn: () => categoryApi.syncProductCount({ token }),
446
+ onSuccess: (result) => {
447
+ const count = result?.data?.updated ?? 0;
448
+ toast.success(`Synced product counts for ${count} categories`);
449
+ queryClient.invalidateQueries({ queryKey: CATEGORY_KEYS.all });
450
+ },
451
+ onError: (error) => {
452
+ toast.error(error.message || "Failed to sync product counts");
453
+ }
454
+ });
455
+ }
456
+ function flattenCategoryTree(nodes, depth = 0, result = []) {
457
+ for (const node of nodes || []) {
458
+ result.push({
459
+ ...node,
460
+ depth,
461
+ displayName: "\xA0\xA0".repeat(depth) + node.name
462
+ });
463
+ if (node.children?.length) {
464
+ flattenCategoryTree(node.children, depth + 1, result);
465
+ }
466
+ }
467
+ return result;
468
+ }
469
+ function getParentCategoryOptions(tree) {
470
+ return (tree || []).map((node) => ({
471
+ value: node.slug,
472
+ label: node.name
473
+ }));
474
+ }
475
+ function getAllCategoryOptions(tree) {
476
+ return flattenCategoryTree(tree).map((node) => ({
477
+ value: node.slug,
478
+ label: node.displayName
479
+ }));
480
+ }
481
+ function findCategoryBySlug(tree, slug) {
482
+ if (!tree || !slug) return void 0;
483
+ for (const node of tree) {
484
+ if (node.slug === slug) return node;
485
+ if (node.children?.length) {
486
+ const found = findCategoryBySlug(node.children, slug);
487
+ if (found) return found;
488
+ }
489
+ }
490
+ return void 0;
491
+ }
492
+ function getCategoryBreadcrumb(tree, slug) {
493
+ if (!tree || !slug) return [];
494
+ function findPath(nodes, target, path = []) {
495
+ for (const node of nodes) {
496
+ const currentPath = [...path, node];
497
+ if (node.slug === target) return currentPath;
498
+ if (node.children?.length) {
499
+ const found = findPath(node.children, target, currentPath);
500
+ if (found) return found;
501
+ }
502
+ }
503
+ return null;
504
+ }
505
+ return findPath(tree, slug) || [];
506
+ }
507
+ function getChildCategorySlugs(tree, parentSlug) {
508
+ const parent = findCategoryBySlug(tree, parentSlug);
509
+ if (!parent?.children?.length) return [];
510
+ const slugs = [];
511
+ function collectSlugs(nodes) {
512
+ for (const node of nodes) {
513
+ slugs.push(node.slug);
514
+ if (node.children?.length) {
515
+ collectSlugs(node.children);
516
+ }
517
+ }
518
+ }
519
+ collectSlugs(parent.children);
520
+ return slugs;
521
+ }
522
+ function getRootCategories(tree) {
523
+ return tree || [];
524
+ }
525
+ var sizeGuideHooks = createCrudHooks({
526
+ api: sizeGuideApi,
527
+ entityKey: "size-guides",
528
+ singular: "Size Guide",
529
+ plural: "Size Guides",
530
+ defaults: {
531
+ staleTime: 30 * 60 * 1e3
532
+ // 30 minutes (size guides change rarely)
533
+ }
534
+ });
535
+ var {
536
+ KEYS: SIZE_GUIDE_KEYS,
537
+ useList: useSizeGuides,
538
+ useDetail: useSizeGuideDetail,
539
+ useActions: useSizeGuideActions,
540
+ useNavigation: useSizeGuideNavigation
541
+ } = sizeGuideHooks;
542
+ function useSizeGuideBySlug(token, slug, options = {}) {
543
+ return useQuery({
544
+ queryKey: [...SIZE_GUIDE_KEYS.all, "slug", slug],
545
+ queryFn: () => sizeGuideApi.getBySlug({ token, slug }),
546
+ enabled: !!slug,
547
+ staleTime: 30 * 60 * 1e3,
548
+ // 30 minutes
549
+ ...options
550
+ });
551
+ }
552
+ function getSizeGuideOptions(sizeGuides) {
553
+ return (sizeGuides || []).map((guide) => ({
554
+ value: guide._id,
555
+ label: guide.name
556
+ }));
557
+ }
558
+ function findSizeGuideById(sizeGuides, id) {
559
+ return sizeGuides?.find((guide) => guide._id === id);
560
+ }
561
+ function findSizeGuideBySlug(sizeGuides, slug) {
562
+ return sizeGuides?.find((guide) => guide.slug === slug);
563
+ }
564
+ function formatMeasurement(value, unit) {
565
+ const unitLabel = unit === "inches" ? "in" : "cm";
566
+ return `${value} ${unitLabel}`;
567
+ }
568
+ function getSizeTableHeaders(guide) {
569
+ if (!guide?.measurementLabels) return ["Size"];
570
+ return ["Size", ...guide.measurementLabels];
571
+ }
572
+ function getSizeTableRows(guide) {
573
+ if (!guide?.sizes) return [];
574
+ return guide.sizes.map((size) => ({
575
+ name: size.name,
576
+ measurements: size.measurements
577
+ }));
578
+ }
579
+
580
+ export { CATEGORY_KEYS, CategoryApi, PRODUCT_KEYS, ProductApi, SIZE_GUIDE_KEYS, SizeGuideApi, categoryApi, categoryHooks, findCategoryBySlug, findSizeGuideById, findSizeGuideBySlug, flattenCategoryTree, formatMeasurement, getAllCategoryOptions, getCategoryBreadcrumb, getChildCategorySlugs, getParentCategoryOptions, getRootCategories, getSizeGuideOptions, getSizeTableHeaders, getSizeTableRows, productApi, productHooks, sizeGuideApi, sizeGuideHooks, useCategories, useCategoryActions, useCategoryBySlug, useCategoryDetail, useCategoryNavigation, useCategorySyncProductCount, useCategoryTree, useDeletedProducts, useHardDeleteProduct, useProductActions, useProductBySlug, useProductDetail, useProductNavigation, useProductRecommendations, useProducts, useRestoreProduct, useSizeGuideActions, useSizeGuideBySlug, useSizeGuideDetail, useSizeGuideNavigation, useSizeGuides, useSyncProductStock };
581
+ //# sourceMappingURL=chunk-X6PV5MHG.js.map
582
+ //# sourceMappingURL=chunk-X6PV5MHG.js.map