@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.
- package/LICENSE +14 -0
- package/README.md +104 -0
- package/dist/adjustment-DTSLM7AN.js +5 -0
- package/dist/adjustment-DTSLM7AN.js.map +1 -0
- package/dist/analytics/index.d.ts +27 -0
- package/dist/analytics/index.js +6 -0
- package/dist/analytics/index.js.map +1 -0
- package/dist/analytics-DMcD-o8w.d.ts +76 -0
- package/dist/api-factory-B_h4RKBm.d.ts +280 -0
- package/dist/auth/index.d.ts +39 -0
- package/dist/auth/index.js +5 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/catalog/index.d.ts +479 -0
- package/dist/catalog/index.js +9 -0
- package/dist/catalog/index.js.map +1 -0
- package/dist/chunk-4ZQK3FFN.js +40 -0
- package/dist/chunk-4ZQK3FFN.js.map +1 -0
- package/dist/chunk-5L6EXDGH.js +465 -0
- package/dist/chunk-5L6EXDGH.js.map +1 -0
- package/dist/chunk-5ZFW3FEI.js +183 -0
- package/dist/chunk-5ZFW3FEI.js.map +1 -0
- package/dist/chunk-66OQAZSL.js +94 -0
- package/dist/chunk-66OQAZSL.js.map +1 -0
- package/dist/chunk-6RYGA6MF.js +123 -0
- package/dist/chunk-6RYGA6MF.js.map +1 -0
- package/dist/chunk-B6MPVOV7.js +328 -0
- package/dist/chunk-B6MPVOV7.js.map +1 -0
- package/dist/chunk-BDA2WSJA.js +148 -0
- package/dist/chunk-BDA2WSJA.js.map +1 -0
- package/dist/chunk-EIVYT3HM.js +126 -0
- package/dist/chunk-EIVYT3HM.js.map +1 -0
- package/dist/chunk-EPQN7ZKZ.js +27 -0
- package/dist/chunk-EPQN7ZKZ.js.map +1 -0
- package/dist/chunk-FA7QFJ2G.js +177 -0
- package/dist/chunk-FA7QFJ2G.js.map +1 -0
- package/dist/chunk-I5TIKUIQ.js +261 -0
- package/dist/chunk-I5TIKUIQ.js.map +1 -0
- package/dist/chunk-ILQUH444.js +135 -0
- package/dist/chunk-ILQUH444.js.map +1 -0
- package/dist/chunk-IXMWZJLV.js +616 -0
- package/dist/chunk-IXMWZJLV.js.map +1 -0
- package/dist/chunk-KZIGRIQG.js +75 -0
- package/dist/chunk-KZIGRIQG.js.map +1 -0
- package/dist/chunk-OF5M6R2S.js +769 -0
- package/dist/chunk-OF5M6R2S.js.map +1 -0
- package/dist/chunk-PYYLHUV6.js +3 -0
- package/dist/chunk-PYYLHUV6.js.map +1 -0
- package/dist/chunk-QO5AGZFP.js +159 -0
- package/dist/chunk-QO5AGZFP.js.map +1 -0
- package/dist/chunk-QUMTBLNE.js +76 -0
- package/dist/chunk-QUMTBLNE.js.map +1 -0
- package/dist/chunk-R5Z7NYLH.js +126 -0
- package/dist/chunk-R5Z7NYLH.js.map +1 -0
- package/dist/chunk-SZYWG5IB.js +75 -0
- package/dist/chunk-SZYWG5IB.js.map +1 -0
- package/dist/chunk-U3XT35GZ.js +202 -0
- package/dist/chunk-U3XT35GZ.js.map +1 -0
- package/dist/chunk-UGELTUIZ.js +830 -0
- package/dist/chunk-UGELTUIZ.js.map +1 -0
- package/dist/chunk-VR36QVX2.js +122 -0
- package/dist/chunk-VR36QVX2.js.map +1 -0
- package/dist/chunk-WUOQK7BO.js +13 -0
- package/dist/chunk-WUOQK7BO.js.map +1 -0
- package/dist/chunk-X6PV5MHG.js +582 -0
- package/dist/chunk-X6PV5MHG.js.map +1 -0
- package/dist/chunk-ZWLMFLLH.js +534 -0
- package/dist/chunk-ZWLMFLLH.js.map +1 -0
- package/dist/content/index.d.ts +309 -0
- package/dist/content/index.js +6 -0
- package/dist/content/index.js.map +1 -0
- package/dist/core/index.d.ts +107 -0
- package/dist/core/index.js +5 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/react.d.ts +107 -0
- package/dist/core/react.js +5 -0
- package/dist/core/react.js.map +1 -0
- package/dist/coupon-CHFcw7cd.d.ts +632 -0
- package/dist/coupon-zGkvO-Xx.d.ts +129 -0
- package/dist/crud.factory-DyKaPHcU.d.ts +181 -0
- package/dist/finance/index.d.ts +81 -0
- package/dist/finance/index.js +5 -0
- package/dist/finance/index.js.map +1 -0
- package/dist/finance-BJdfKRw0.d.ts +135 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/inventory/index.d.ts +512 -0
- package/dist/inventory/index.js +16 -0
- package/dist/inventory/index.js.map +1 -0
- package/dist/inventory-DCiIZh8P.d.ts +742 -0
- package/dist/logistics/index.d.ts +226 -0
- package/dist/logistics/index.js +7 -0
- package/dist/logistics/index.js.map +1 -0
- package/dist/logistics-V8a9lUN3.d.ts +428 -0
- package/dist/media-CNLJK93J.d.ts +721 -0
- package/dist/movement-7MV3ADY5.js +5 -0
- package/dist/movement-7MV3ADY5.js.map +1 -0
- package/dist/payment-BRboLqvU.d.ts +127 -0
- package/dist/payments/index.d.ts +55 -0
- package/dist/payments/index.js +6 -0
- package/dist/payments/index.js.map +1 -0
- package/dist/platform/index.d.ts +645 -0
- package/dist/platform/index.js +8 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/pos-D1jkkFl0.d.ts +885 -0
- package/dist/product-p09zXkXB.d.ts +260 -0
- package/dist/purchase-24BGT2HA.js +5 -0
- package/dist/purchase-24BGT2HA.js.map +1 -0
- package/dist/request-652PS6VR.js +5 -0
- package/dist/request-652PS6VR.js.map +1 -0
- package/dist/sales/index.d.ts +585 -0
- package/dist/sales/index.js +9 -0
- package/dist/sales/index.js.map +1 -0
- package/dist/server.d.ts +120 -0
- package/dist/server.js +27 -0
- package/dist/server.js.map +1 -0
- package/dist/size-guide-DgjzjM5P.d.ts +554 -0
- package/dist/stock-DEApGC-w.d.ts +632 -0
- package/dist/stock-OOUW57VQ.js +5 -0
- package/dist/stock-OOUW57VQ.js.map +1 -0
- package/dist/supplier-OC6JAWV6.js +5 -0
- package/dist/supplier-OC6JAWV6.js.map +1 -0
- package/dist/transaction/index.d.ts +104 -0
- package/dist/transaction/index.js +8 -0
- package/dist/transaction/index.js.map +1 -0
- package/dist/transaction-BTmoHpWh.d.ts +428 -0
- package/dist/transaction-u5oaNuav.d.ts +84 -0
- package/dist/transfer-7SYSH3RG.js +5 -0
- package/dist/transfer-7SYSH3RG.js.map +1 -0
- package/dist/user-data-DdLjAGwO.d.ts +132 -0
- 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
|