@payloadcms/plugin-ecommerce 3.67.0-internal.87c53da → 3.68.0-canary.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/collections/addresses/createAddressesCollection.d.ts +1 -5
- package/dist/collections/addresses/createAddressesCollection.d.ts.map +1 -1
- package/dist/collections/addresses/createAddressesCollection.js +7 -6
- package/dist/collections/addresses/createAddressesCollection.js.map +1 -1
- package/dist/collections/carts/beforeChange.d.ts.map +1 -1
- package/dist/collections/carts/beforeChange.js +13 -1
- package/dist/collections/carts/beforeChange.js.map +1 -1
- package/dist/collections/carts/createCartsCollection.d.ts +6 -4
- package/dist/collections/carts/createCartsCollection.d.ts.map +1 -1
- package/dist/collections/carts/createCartsCollection.js +36 -5
- package/dist/collections/carts/createCartsCollection.js.map +1 -1
- package/dist/collections/carts/hasCartSecretAccess.d.ts +10 -0
- package/dist/collections/carts/hasCartSecretAccess.d.ts.map +1 -0
- package/dist/collections/carts/hasCartSecretAccess.js +24 -0
- package/dist/collections/carts/hasCartSecretAccess.js.map +1 -0
- package/dist/collections/orders/createOrdersCollection.d.ts +1 -5
- package/dist/collections/orders/createOrdersCollection.d.ts.map +1 -1
- package/dist/collections/orders/createOrdersCollection.js +9 -8
- package/dist/collections/orders/createOrdersCollection.js.map +1 -1
- package/dist/collections/products/createProductsCollection.d.ts +1 -4
- package/dist/collections/products/createProductsCollection.d.ts.map +1 -1
- package/dist/collections/products/createProductsCollection.js +5 -5
- package/dist/collections/products/createProductsCollection.js.map +1 -1
- package/dist/collections/transactions/createTransactionsCollection.d.ts +1 -3
- package/dist/collections/transactions/createTransactionsCollection.d.ts.map +1 -1
- package/dist/collections/transactions/createTransactionsCollection.js +5 -5
- package/dist/collections/transactions/createTransactionsCollection.js.map +1 -1
- package/dist/collections/variants/createVariantOptionsCollection.d.ts +1 -4
- package/dist/collections/variants/createVariantOptionsCollection.d.ts.map +1 -1
- package/dist/collections/variants/createVariantOptionsCollection.js +5 -5
- package/dist/collections/variants/createVariantOptionsCollection.js.map +1 -1
- package/dist/collections/variants/createVariantTypesCollection.d.ts +1 -4
- package/dist/collections/variants/createVariantTypesCollection.d.ts.map +1 -1
- package/dist/collections/variants/createVariantTypesCollection.js +5 -5
- package/dist/collections/variants/createVariantTypesCollection.js.map +1 -1
- package/dist/collections/variants/createVariantsCollection/index.d.ts +1 -4
- package/dist/collections/variants/createVariantsCollection/index.d.ts.map +1 -1
- package/dist/collections/variants/createVariantsCollection/index.js +5 -5
- package/dist/collections/variants/createVariantsCollection/index.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -33
- package/dist/index.js.map +1 -1
- package/dist/react/provider/index.d.ts +3 -0
- package/dist/react/provider/index.d.ts.map +1 -1
- package/dist/react/provider/index.js +259 -156
- package/dist/react/provider/index.js.map +1 -1
- package/dist/translations/en.d.ts.map +1 -1
- package/dist/translations/en.js +1 -0
- package/dist/translations/en.js.map +1 -1
- package/dist/types/index.d.ts +43 -25
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/utilities/accessComposition.d.ts +55 -0
- package/dist/utilities/accessComposition.d.ts.map +1 -0
- package/dist/utilities/accessComposition.js +103 -0
- package/dist/utilities/accessComposition.js.map +1 -0
- package/dist/utilities/accessComposition.spec.js +803 -0
- package/dist/utilities/accessComposition.spec.js.map +1 -0
- package/dist/utilities/defaultProductsValidation.spec.js +383 -0
- package/dist/utilities/defaultProductsValidation.spec.js.map +1 -0
- package/dist/utilities/getCollectionSlugMap.spec.js +159 -0
- package/dist/utilities/getCollectionSlugMap.spec.js.map +1 -0
- package/dist/utilities/sanitizePluginConfig.d.ts.map +1 -1
- package/dist/utilities/sanitizePluginConfig.js +10 -2
- package/dist/utilities/sanitizePluginConfig.js.map +1 -1
- package/dist/utilities/sanitizePluginConfig.spec.js +515 -0
- package/dist/utilities/sanitizePluginConfig.spec.js.map +1 -0
- package/package.json +7 -6
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { deepMergeSimple } from 'payload/shared';
|
|
4
4
|
import * as qs from 'qs-esm';
|
|
5
|
-
import React, { createContext, use, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
5
|
+
import React, { createContext, use, useCallback, useEffect, useMemo, useRef, useState, useTransition } from 'react';
|
|
6
6
|
const defaultContext = {
|
|
7
7
|
addItem: async ()=>{},
|
|
8
8
|
clearCart: async ()=>{},
|
|
@@ -28,6 +28,7 @@ const defaultContext = {
|
|
|
28
28
|
decrementItem: async ()=>{},
|
|
29
29
|
incrementItem: async ()=>{},
|
|
30
30
|
initiatePayment: async ()=>{},
|
|
31
|
+
isLoading: false,
|
|
31
32
|
paymentMethods: [],
|
|
32
33
|
removeItem: async ()=>{},
|
|
33
34
|
setCurrency: ()=>{},
|
|
@@ -54,6 +55,7 @@ export const EcommerceProvider = ({ addressesSlug = 'addresses', api, cartsSlug
|
|
|
54
55
|
} : defaultLocalStorage;
|
|
55
56
|
const { apiRoute = '/api', cartsFetchQuery = {}, serverURL = '' } = api || {};
|
|
56
57
|
const baseAPIURL = `${serverURL}${apiRoute}`;
|
|
58
|
+
const [isLoading, startTransition] = useTransition();
|
|
57
59
|
const [user, setUser] = useState(null);
|
|
58
60
|
const [addresses, setAddresses] = useState();
|
|
59
61
|
const hasRendered = useRef(false);
|
|
@@ -62,6 +64,10 @@ export const EcommerceProvider = ({ addressesSlug = 'addresses', api, cartsSlug
|
|
|
62
64
|
* This is used to identify the cart in the database or local storage.
|
|
63
65
|
* It can be null if no cart has been created yet.
|
|
64
66
|
*/ const [cartID, setCartID] = useState();
|
|
67
|
+
/**
|
|
68
|
+
* The secret for accessing guest carts without authentication.
|
|
69
|
+
* This is generated when a guest user creates a cart.
|
|
70
|
+
*/ const [cartSecret, setCartSecret] = useState(undefined);
|
|
65
71
|
const [cart, setCart] = useState();
|
|
66
72
|
const [selectedCurrency, setSelectedCurrency] = useState(()=>currenciesConfig.supportedCurrencies.find((c)=>c.code === currenciesConfig.defaultCurrency));
|
|
67
73
|
const [selectedPaymentMethod, setSelectedPaymentMethod] = useState(null);
|
|
@@ -110,16 +116,28 @@ export const EcommerceProvider = ({ addressesSlug = 'addresses', api, cartsSlug
|
|
|
110
116
|
if (data.error) {
|
|
111
117
|
throw new Error(`Cart creation error: ${data.error}`);
|
|
112
118
|
}
|
|
119
|
+
// Store the secret for guest cart access
|
|
120
|
+
if (!user && data.doc?.secret) {
|
|
121
|
+
setCartSecret(data.doc.secret);
|
|
122
|
+
}
|
|
113
123
|
return data.doc;
|
|
114
124
|
}, [
|
|
115
125
|
baseAPIURL,
|
|
116
126
|
cartQuery,
|
|
117
127
|
cartsSlug,
|
|
118
128
|
selectedCurrency.code,
|
|
119
|
-
user
|
|
129
|
+
user
|
|
120
130
|
]);
|
|
121
|
-
const getCart = useCallback(async (cartID)=>{
|
|
122
|
-
const
|
|
131
|
+
const getCart = useCallback(async (cartID, options)=>{
|
|
132
|
+
const secret = options?.secret;
|
|
133
|
+
// Build query params with secret if provided
|
|
134
|
+
const queryParams = {
|
|
135
|
+
...cartQuery,
|
|
136
|
+
...secret ? {
|
|
137
|
+
secret
|
|
138
|
+
} : {}
|
|
139
|
+
};
|
|
140
|
+
const query = qs.stringify(queryParams);
|
|
123
141
|
const response = await fetch(`${baseAPIURL}/${cartsSlug}/${cartID}?${query}`, {
|
|
124
142
|
credentials: 'include',
|
|
125
143
|
headers: {
|
|
@@ -142,7 +160,14 @@ export const EcommerceProvider = ({ addressesSlug = 'addresses', api, cartsSlug
|
|
|
142
160
|
cartsSlug
|
|
143
161
|
]);
|
|
144
162
|
const updateCart = useCallback(async (cartID, data)=>{
|
|
145
|
-
|
|
163
|
+
// Build query params with secret if provided
|
|
164
|
+
const queryParams = {
|
|
165
|
+
...cartQuery,
|
|
166
|
+
...cartSecret ? {
|
|
167
|
+
secret: cartSecret
|
|
168
|
+
} : {}
|
|
169
|
+
};
|
|
170
|
+
const query = qs.stringify(queryParams);
|
|
146
171
|
const response = await fetch(`${baseAPIURL}/${cartsSlug}/${cartID}?${query}`, {
|
|
147
172
|
body: JSON.stringify(data),
|
|
148
173
|
credentials: 'include',
|
|
@@ -160,10 +185,17 @@ export const EcommerceProvider = ({ addressesSlug = 'addresses', api, cartsSlug
|
|
|
160
185
|
}, [
|
|
161
186
|
baseAPIURL,
|
|
162
187
|
cartQuery,
|
|
163
|
-
cartsSlug
|
|
188
|
+
cartsSlug,
|
|
189
|
+
cartSecret
|
|
164
190
|
]);
|
|
165
191
|
const deleteCart = useCallback(async (cartID)=>{
|
|
166
|
-
|
|
192
|
+
// Build query params with secret if provided
|
|
193
|
+
const queryParams = cartSecret ? {
|
|
194
|
+
secret: cartSecret
|
|
195
|
+
} : {};
|
|
196
|
+
const query = qs.stringify(queryParams);
|
|
197
|
+
const url = `${baseAPIURL}/${cartsSlug}/${cartID}${query ? `?${query}` : ''}`;
|
|
198
|
+
const response = await fetch(url, {
|
|
167
199
|
credentials: 'include',
|
|
168
200
|
headers: {
|
|
169
201
|
'Content-Type': 'application/json'
|
|
@@ -172,196 +204,255 @@ export const EcommerceProvider = ({ addressesSlug = 'addresses', api, cartsSlug
|
|
|
172
204
|
});
|
|
173
205
|
if (!response.ok) {
|
|
174
206
|
const errorText = await response.text();
|
|
175
|
-
throw new Error(`Failed to
|
|
207
|
+
throw new Error(`Failed to delete cart: ${errorText}`);
|
|
176
208
|
}
|
|
177
209
|
setCart(undefined);
|
|
178
210
|
setCartID(undefined);
|
|
211
|
+
setCartSecret(undefined);
|
|
179
212
|
}, [
|
|
180
213
|
baseAPIURL,
|
|
181
|
-
cartsSlug
|
|
214
|
+
cartsSlug,
|
|
215
|
+
cartSecret
|
|
182
216
|
]);
|
|
217
|
+
// Persist cart ID and secret to localStorage
|
|
183
218
|
useEffect(()=>{
|
|
184
219
|
if (hasRendered.current) {
|
|
185
|
-
if (syncLocalStorage
|
|
186
|
-
|
|
220
|
+
if (syncLocalStorage) {
|
|
221
|
+
if (cartID) {
|
|
222
|
+
localStorage.setItem(localStorageConfig.key, cartID);
|
|
223
|
+
} else {
|
|
224
|
+
localStorage.removeItem(localStorageConfig.key);
|
|
225
|
+
}
|
|
226
|
+
if (cartSecret) {
|
|
227
|
+
localStorage.setItem(`${localStorageConfig.key}_secret`, cartSecret);
|
|
228
|
+
} else {
|
|
229
|
+
localStorage.removeItem(`${localStorageConfig.key}_secret`);
|
|
230
|
+
}
|
|
187
231
|
}
|
|
188
232
|
}
|
|
189
233
|
}, [
|
|
190
234
|
cartID,
|
|
235
|
+
cartSecret,
|
|
191
236
|
localStorageConfig.key,
|
|
192
237
|
syncLocalStorage
|
|
193
238
|
]);
|
|
194
239
|
const addItem = useCallback(async (item, quantity = 1)=>{
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
const variantID = cartItem.variant && typeof cartItem.variant === 'object' ? cartItem.variant.id : item.variant;
|
|
207
|
-
return productID === item.product && (item.variant && variantID ? variantID === item.variant : true);
|
|
208
|
-
}) ?? -1;
|
|
209
|
-
let updatedItems = existingCart.items ? [
|
|
210
|
-
...existingCart.items
|
|
211
|
-
] : [];
|
|
212
|
-
if (existingItemIndex !== -1) {
|
|
213
|
-
// If the item exists, update its quantity
|
|
214
|
-
updatedItems[existingItemIndex].quantity = updatedItems[existingItemIndex].quantity + quantity;
|
|
215
|
-
// Update the cart with the new items
|
|
216
|
-
await updateCart(cartID, {
|
|
217
|
-
items: updatedItems
|
|
218
|
-
});
|
|
219
|
-
} else {
|
|
220
|
-
// If the item does not exist, add it to the cart
|
|
221
|
-
updatedItems = [
|
|
222
|
-
...existingCart.items ?? [],
|
|
223
|
-
{
|
|
224
|
-
...item,
|
|
225
|
-
quantity
|
|
240
|
+
return new Promise((resolve)=>{
|
|
241
|
+
startTransition(async ()=>{
|
|
242
|
+
if (cartID) {
|
|
243
|
+
const existingCart = await getCart(cartID, {
|
|
244
|
+
secret: cartSecret
|
|
245
|
+
});
|
|
246
|
+
if (!existingCart) {
|
|
247
|
+
// console.error(`Cart with ID "${cartID}" not found`)
|
|
248
|
+
setCartID(undefined);
|
|
249
|
+
setCart(undefined);
|
|
250
|
+
return;
|
|
226
251
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
252
|
+
// Check if the item already exists in the cart
|
|
253
|
+
const existingItemIndex = existingCart.items?.findIndex((cartItem)=>{
|
|
254
|
+
const productID = typeof cartItem.product === 'object' ? cartItem.product.id : item.product;
|
|
255
|
+
const variantID = cartItem.variant && typeof cartItem.variant === 'object' ? cartItem.variant.id : item.variant;
|
|
256
|
+
return productID === item.product && (item.variant && variantID ? variantID === item.variant : true);
|
|
257
|
+
}) ?? -1;
|
|
258
|
+
let updatedItems = existingCart.items ? [
|
|
259
|
+
...existingCart.items
|
|
260
|
+
] : [];
|
|
261
|
+
if (existingItemIndex !== -1) {
|
|
262
|
+
// If the item exists, update its quantity
|
|
263
|
+
updatedItems[existingItemIndex].quantity = updatedItems[existingItemIndex].quantity + quantity;
|
|
264
|
+
// Update the cart with the new items
|
|
265
|
+
await updateCart(cartID, {
|
|
266
|
+
items: updatedItems
|
|
267
|
+
});
|
|
268
|
+
} else {
|
|
269
|
+
// If the item does not exist, add it to the cart
|
|
270
|
+
updatedItems = [
|
|
271
|
+
...existingCart.items ?? [],
|
|
272
|
+
{
|
|
273
|
+
...item,
|
|
274
|
+
quantity
|
|
275
|
+
}
|
|
276
|
+
];
|
|
240
277
|
}
|
|
241
|
-
|
|
278
|
+
// Update the cart with the new items
|
|
279
|
+
await updateCart(cartID, {
|
|
280
|
+
items: updatedItems
|
|
281
|
+
});
|
|
282
|
+
} else {
|
|
283
|
+
// If no cartID exists, create a new cart
|
|
284
|
+
const newCart = await createCart({
|
|
285
|
+
items: [
|
|
286
|
+
{
|
|
287
|
+
...item,
|
|
288
|
+
quantity
|
|
289
|
+
}
|
|
290
|
+
]
|
|
291
|
+
});
|
|
292
|
+
setCartID(newCart.id);
|
|
293
|
+
setCart(newCart);
|
|
294
|
+
}
|
|
295
|
+
resolve();
|
|
242
296
|
});
|
|
243
|
-
|
|
244
|
-
setCart(newCart);
|
|
245
|
-
}
|
|
297
|
+
});
|
|
246
298
|
}, [
|
|
247
299
|
cartID,
|
|
300
|
+
cartSecret,
|
|
248
301
|
createCart,
|
|
249
302
|
getCart,
|
|
303
|
+
startTransition,
|
|
250
304
|
updateCart
|
|
251
305
|
]);
|
|
252
306
|
const removeItem = useCallback(async (targetID)=>{
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
307
|
+
return new Promise((resolve)=>{
|
|
308
|
+
startTransition(async ()=>{
|
|
309
|
+
if (!cartID) {
|
|
310
|
+
resolve();
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
const existingCart = await getCart(cartID, {
|
|
314
|
+
secret: cartSecret
|
|
315
|
+
});
|
|
316
|
+
if (!existingCart) {
|
|
317
|
+
// console.error(`Cart with ID "${cartID}" not found`)
|
|
318
|
+
setCartID(undefined);
|
|
319
|
+
setCart(undefined);
|
|
320
|
+
resolve();
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
// Check if the item already exists in the cart
|
|
324
|
+
const existingItemIndex = existingCart.items?.findIndex((cartItem)=>cartItem.id === targetID) ?? -1;
|
|
325
|
+
if (existingItemIndex !== -1) {
|
|
326
|
+
// If the item exists, remove it from the cart
|
|
327
|
+
const updatedItems = existingCart.items ? [
|
|
328
|
+
...existingCart.items
|
|
329
|
+
] : [];
|
|
330
|
+
updatedItems.splice(existingItemIndex, 1);
|
|
331
|
+
// Update the cart with the new items
|
|
332
|
+
await updateCart(cartID, {
|
|
333
|
+
items: updatedItems
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
resolve();
|
|
274
337
|
});
|
|
275
|
-
}
|
|
338
|
+
});
|
|
276
339
|
}, [
|
|
277
340
|
cartID,
|
|
341
|
+
cartSecret,
|
|
278
342
|
getCart,
|
|
343
|
+
startTransition,
|
|
279
344
|
updateCart
|
|
280
345
|
]);
|
|
281
346
|
const incrementItem = useCallback(async (targetID)=>{
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
// console.error(`Cart with ID "${cartID}" not found`)
|
|
288
|
-
setCartID(undefined);
|
|
289
|
-
setCart(undefined);
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
// Check if the item already exists in the cart
|
|
293
|
-
const existingItemIndex = existingCart.items?.findIndex((cartItem)=>cartItem.id === targetID) ?? -1;
|
|
294
|
-
let updatedItems = existingCart.items ? [
|
|
295
|
-
...existingCart.items
|
|
296
|
-
] : [];
|
|
297
|
-
if (existingItemIndex !== -1) {
|
|
298
|
-
// If the item exists, increment its quantity
|
|
299
|
-
updatedItems[existingItemIndex].quantity = updatedItems[existingItemIndex].quantity + 1 // Increment by 1
|
|
300
|
-
;
|
|
301
|
-
// Update the cart with the new items
|
|
302
|
-
await updateCart(cartID, {
|
|
303
|
-
items: updatedItems
|
|
304
|
-
});
|
|
305
|
-
} else {
|
|
306
|
-
// If the item does not exist, add it to the cart with quantity 1
|
|
307
|
-
updatedItems = [
|
|
308
|
-
...existingCart.items ?? [],
|
|
309
|
-
{
|
|
310
|
-
product: targetID,
|
|
311
|
-
quantity: 1
|
|
347
|
+
return new Promise((resolve)=>{
|
|
348
|
+
startTransition(async ()=>{
|
|
349
|
+
if (!cartID) {
|
|
350
|
+
resolve();
|
|
351
|
+
return;
|
|
312
352
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
353
|
+
const existingCart = await getCart(cartID, {
|
|
354
|
+
secret: cartSecret
|
|
355
|
+
});
|
|
356
|
+
if (!existingCart) {
|
|
357
|
+
// console.error(`Cart with ID "${cartID}" not found`)
|
|
358
|
+
setCartID(undefined);
|
|
359
|
+
setCart(undefined);
|
|
360
|
+
resolve();
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
// Check if the item already exists in the cart
|
|
364
|
+
const existingItemIndex = existingCart.items?.findIndex((cartItem)=>cartItem.id === targetID) ?? -1;
|
|
365
|
+
let updatedItems = existingCart.items ? [
|
|
366
|
+
...existingCart.items
|
|
367
|
+
] : [];
|
|
368
|
+
if (existingItemIndex !== -1) {
|
|
369
|
+
// If the item exists, increment its quantity
|
|
370
|
+
updatedItems[existingItemIndex].quantity = updatedItems[existingItemIndex].quantity + 1; // Increment by 1
|
|
371
|
+
// Update the cart with the new items
|
|
372
|
+
await updateCart(cartID, {
|
|
373
|
+
items: updatedItems
|
|
374
|
+
});
|
|
375
|
+
} else {
|
|
376
|
+
// If the item does not exist, add it to the cart with quantity 1
|
|
377
|
+
updatedItems = [
|
|
378
|
+
...existingCart.items ?? [],
|
|
379
|
+
{
|
|
380
|
+
product: targetID,
|
|
381
|
+
quantity: 1
|
|
382
|
+
}
|
|
383
|
+
];
|
|
384
|
+
// Update the cart with the new items
|
|
385
|
+
await updateCart(cartID, {
|
|
386
|
+
items: updatedItems
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
resolve();
|
|
317
390
|
});
|
|
318
|
-
}
|
|
391
|
+
});
|
|
319
392
|
}, [
|
|
320
393
|
cartID,
|
|
394
|
+
cartSecret,
|
|
321
395
|
getCart,
|
|
396
|
+
startTransition,
|
|
322
397
|
updateCart
|
|
323
398
|
]);
|
|
324
399
|
const decrementItem = useCallback(async (targetID)=>{
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
400
|
+
return new Promise((resolve)=>{
|
|
401
|
+
startTransition(async ()=>{
|
|
402
|
+
if (!cartID) {
|
|
403
|
+
resolve();
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
const existingCart = await getCart(cartID, {
|
|
407
|
+
secret: cartSecret
|
|
408
|
+
});
|
|
409
|
+
if (!existingCart) {
|
|
410
|
+
// console.error(`Cart with ID "${cartID}" not found`)
|
|
411
|
+
setCartID(undefined);
|
|
412
|
+
setCart(undefined);
|
|
413
|
+
resolve();
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
// Check if the item already exists in the cart
|
|
417
|
+
const existingItemIndex = existingCart.items?.findIndex((cartItem)=>cartItem.id === targetID) ?? -1;
|
|
418
|
+
const updatedItems = existingCart.items ? [
|
|
419
|
+
...existingCart.items
|
|
420
|
+
] : [];
|
|
421
|
+
if (existingItemIndex !== -1) {
|
|
422
|
+
// If the item exists, decrement its quantity
|
|
423
|
+
updatedItems[existingItemIndex].quantity = updatedItems[existingItemIndex].quantity - 1; // Decrement by 1
|
|
424
|
+
// If the quantity reaches 0, remove the item from the cart
|
|
425
|
+
if (updatedItems[existingItemIndex].quantity <= 0) {
|
|
426
|
+
updatedItems.splice(existingItemIndex, 1);
|
|
427
|
+
}
|
|
428
|
+
// Update the cart with the new items
|
|
429
|
+
await updateCart(cartID, {
|
|
430
|
+
items: updatedItems
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
resolve();
|
|
351
434
|
});
|
|
352
|
-
}
|
|
435
|
+
});
|
|
353
436
|
}, [
|
|
354
437
|
cartID,
|
|
438
|
+
cartSecret,
|
|
355
439
|
getCart,
|
|
440
|
+
startTransition,
|
|
356
441
|
updateCart
|
|
357
442
|
]);
|
|
358
443
|
const clearCart = useCallback(async ()=>{
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
444
|
+
return new Promise((resolve)=>{
|
|
445
|
+
startTransition(async ()=>{
|
|
446
|
+
if (cartID) {
|
|
447
|
+
await deleteCart(cartID);
|
|
448
|
+
}
|
|
449
|
+
resolve();
|
|
450
|
+
});
|
|
451
|
+
});
|
|
362
452
|
}, [
|
|
363
453
|
cartID,
|
|
364
|
-
deleteCart
|
|
454
|
+
deleteCart,
|
|
455
|
+
startTransition
|
|
365
456
|
]);
|
|
366
457
|
const setCurrency = useCallback((currency)=>{
|
|
367
458
|
if (selectedCurrency.code === currency) {
|
|
@@ -629,21 +720,29 @@ export const EcommerceProvider = ({ addressesSlug = 'addresses', api, cartsSlug
|
|
|
629
720
|
getAddresses,
|
|
630
721
|
debug
|
|
631
722
|
]);
|
|
632
|
-
// If localStorage is enabled,
|
|
723
|
+
// If localStorage is enabled, restore cart from storage
|
|
633
724
|
useEffect(()=>{
|
|
634
725
|
if (!hasRendered.current) {
|
|
635
726
|
if (syncLocalStorage) {
|
|
636
|
-
const
|
|
637
|
-
|
|
638
|
-
|
|
727
|
+
const storedCartID = localStorage.getItem(localStorageConfig.key);
|
|
728
|
+
const storedSecret = localStorage.getItem(`${localStorageConfig.key}_secret`);
|
|
729
|
+
if (storedCartID) {
|
|
730
|
+
getCart(storedCartID, {
|
|
731
|
+
secret: storedSecret || undefined
|
|
732
|
+
}).then((fetchedCart)=>{
|
|
639
733
|
setCart(fetchedCart);
|
|
640
|
-
setCartID(
|
|
734
|
+
setCartID(storedCartID);
|
|
735
|
+
if (storedSecret) {
|
|
736
|
+
setCartSecret(storedSecret);
|
|
737
|
+
}
|
|
641
738
|
}).catch((_)=>{
|
|
642
739
|
// console.error('Error fetching cart from localStorage:', error)
|
|
643
|
-
// If there's an error fetching the cart,
|
|
740
|
+
// If there's an error fetching the cart, clear it from localStorage
|
|
644
741
|
localStorage.removeItem(localStorageConfig.key);
|
|
742
|
+
localStorage.removeItem(`${localStorageConfig.key}_secret`);
|
|
645
743
|
setCartID(undefined);
|
|
646
744
|
setCart(undefined);
|
|
745
|
+
setCartSecret(undefined);
|
|
647
746
|
});
|
|
648
747
|
}
|
|
649
748
|
}
|
|
@@ -702,6 +801,7 @@ export const EcommerceProvider = ({ addressesSlug = 'addresses', api, cartsSlug
|
|
|
702
801
|
decrementItem,
|
|
703
802
|
incrementItem,
|
|
704
803
|
initiatePayment,
|
|
804
|
+
isLoading,
|
|
705
805
|
paymentMethods,
|
|
706
806
|
removeItem,
|
|
707
807
|
selectedPaymentMethod,
|
|
@@ -749,7 +849,7 @@ export const useCurrency = ()=>{
|
|
|
749
849
|
};
|
|
750
850
|
};
|
|
751
851
|
export function useCart() {
|
|
752
|
-
const { addItem, cart, clearCart, decrementItem, incrementItem, removeItem } = useEcommerce();
|
|
852
|
+
const { addItem, cart, clearCart, decrementItem, incrementItem, isLoading, removeItem } = useEcommerce();
|
|
753
853
|
if (!addItem) {
|
|
754
854
|
throw new Error('useCart must be used within an EcommerceProvider');
|
|
755
855
|
}
|
|
@@ -759,29 +859,32 @@ export function useCart() {
|
|
|
759
859
|
clearCart,
|
|
760
860
|
decrementItem,
|
|
761
861
|
incrementItem,
|
|
862
|
+
isLoading,
|
|
762
863
|
removeItem
|
|
763
864
|
};
|
|
764
865
|
}
|
|
765
866
|
export const usePayments = ()=>{
|
|
766
|
-
const { confirmOrder, initiatePayment, paymentMethods, selectedPaymentMethod } = useEcommerce();
|
|
867
|
+
const { confirmOrder, initiatePayment, isLoading, paymentMethods, selectedPaymentMethod } = useEcommerce();
|
|
767
868
|
if (!initiatePayment) {
|
|
768
869
|
throw new Error('usePayments must be used within an EcommerceProvider');
|
|
769
870
|
}
|
|
770
871
|
return {
|
|
771
872
|
confirmOrder,
|
|
772
873
|
initiatePayment,
|
|
874
|
+
isLoading,
|
|
773
875
|
paymentMethods,
|
|
774
876
|
selectedPaymentMethod
|
|
775
877
|
};
|
|
776
878
|
};
|
|
777
879
|
export function useAddresses() {
|
|
778
|
-
const { addresses, createAddress, updateAddress } = useEcommerce();
|
|
880
|
+
const { addresses, createAddress, isLoading, updateAddress } = useEcommerce();
|
|
779
881
|
if (!createAddress) {
|
|
780
882
|
throw new Error('usePayments must be used within an EcommerceProvider');
|
|
781
883
|
}
|
|
782
884
|
return {
|
|
783
885
|
addresses: addresses,
|
|
784
886
|
createAddress,
|
|
887
|
+
isLoading,
|
|
785
888
|
updateAddress
|
|
786
889
|
};
|
|
787
890
|
}
|