@anker-in/shopify-react 0.1.1-beta.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/adapters/index.d.mts +16 -0
- package/dist/adapters/index.d.ts +16 -0
- package/dist/adapters/index.js +49 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/index.mjs +42 -0
- package/dist/adapters/index.mjs.map +1 -0
- package/dist/hooks/index.d.mts +9 -0
- package/dist/hooks/index.d.ts +9 -0
- package/dist/hooks/index.js +2890 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/index.mjs +2801 -0
- package/dist/hooks/index.mjs.map +1 -0
- package/dist/index-BUWkkUdh.d.ts +1936 -0
- package/dist/index-DenyuVGJ.d.mts +1936 -0
- package/dist/index.d.mts +32 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +3220 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +3095 -0
- package/dist/index.mjs.map +1 -0
- package/dist/provider/index.d.mts +161 -0
- package/dist/provider/index.d.ts +161 -0
- package/dist/provider/index.js +1130 -0
- package/dist/provider/index.js.map +1 -0
- package/dist/provider/index.mjs +1117 -0
- package/dist/provider/index.mjs.map +1 -0
- package/dist/types-BLMoxbOk.d.mts +54 -0
- package/dist/types-BLMoxbOk.d.ts +54 -0
- package/dist/types-CMA6_FML.d.mts +550 -0
- package/dist/types-CMA6_FML.d.ts +550 -0
- package/package.json +71 -0
|
@@ -0,0 +1,1117 @@
|
|
|
1
|
+
import { createContext, useMemo, useContext, useState, useCallback, useEffect, useRef } from 'react';
|
|
2
|
+
import { createShopifyClient, getCart, updateCartAttributes, updateCartLines, getProductsByHandles } from '@anker-in/shopify-sdk';
|
|
3
|
+
import Cookies5 from 'js-cookie';
|
|
4
|
+
import { jsx } from 'react/jsx-runtime';
|
|
5
|
+
import Decimal2 from 'decimal.js';
|
|
6
|
+
import useSWR from 'swr';
|
|
7
|
+
import useSWRMutation8 from 'swr/mutation';
|
|
8
|
+
import { useRequest } from 'ahooks';
|
|
9
|
+
|
|
10
|
+
// src/provider/context.ts
|
|
11
|
+
var ShopifyContext = createContext(null);
|
|
12
|
+
var browserCookieAdapter = {
|
|
13
|
+
get(key) {
|
|
14
|
+
return Cookies5.get(key);
|
|
15
|
+
},
|
|
16
|
+
set(key, value, options) {
|
|
17
|
+
Cookies5.set(key, value, {
|
|
18
|
+
domain: options?.domain,
|
|
19
|
+
path: options?.path || "/",
|
|
20
|
+
expires: options?.expires,
|
|
21
|
+
secure: options?.secure,
|
|
22
|
+
sameSite: options?.sameSite
|
|
23
|
+
});
|
|
24
|
+
},
|
|
25
|
+
remove(key) {
|
|
26
|
+
Cookies5.remove(key);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
function getCartCookieName(locale) {
|
|
30
|
+
return `${locale}-shopify-cart-id`;
|
|
31
|
+
}
|
|
32
|
+
var browserCartCookieAdapter = {
|
|
33
|
+
getCartId(locale) {
|
|
34
|
+
return Cookies5.get(getCartCookieName(locale));
|
|
35
|
+
},
|
|
36
|
+
setCartId(locale, cartId) {
|
|
37
|
+
Cookies5.set(getCartCookieName(locale), cartId, {
|
|
38
|
+
path: "/",
|
|
39
|
+
expires: 30
|
|
40
|
+
// 30 days
|
|
41
|
+
});
|
|
42
|
+
},
|
|
43
|
+
removeCartId(locale) {
|
|
44
|
+
Cookies5.remove(getCartCookieName(locale));
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
function ShopifyProvider({
|
|
48
|
+
config,
|
|
49
|
+
locale,
|
|
50
|
+
locales,
|
|
51
|
+
cookieAdapter = browserCookieAdapter,
|
|
52
|
+
cartCookieAdapter = browserCartCookieAdapter,
|
|
53
|
+
routerAdapter,
|
|
54
|
+
userAdapter,
|
|
55
|
+
children
|
|
56
|
+
}) {
|
|
57
|
+
const client = useMemo(() => {
|
|
58
|
+
return createShopifyClient(config, locale);
|
|
59
|
+
}, [config, locale]);
|
|
60
|
+
const value = useMemo(() => {
|
|
61
|
+
return {
|
|
62
|
+
client,
|
|
63
|
+
config,
|
|
64
|
+
locale,
|
|
65
|
+
locales: locales || config.getLocales(),
|
|
66
|
+
cookieAdapter,
|
|
67
|
+
cartCookieAdapter,
|
|
68
|
+
routerAdapter,
|
|
69
|
+
userAdapter
|
|
70
|
+
};
|
|
71
|
+
}, [
|
|
72
|
+
client,
|
|
73
|
+
config,
|
|
74
|
+
locale,
|
|
75
|
+
locales,
|
|
76
|
+
cookieAdapter,
|
|
77
|
+
cartCookieAdapter,
|
|
78
|
+
routerAdapter,
|
|
79
|
+
userAdapter
|
|
80
|
+
]);
|
|
81
|
+
return /* @__PURE__ */ jsx(ShopifyContext.Provider, { value, children });
|
|
82
|
+
}
|
|
83
|
+
function useShopify() {
|
|
84
|
+
const context = useContext(ShopifyContext);
|
|
85
|
+
if (!context) {
|
|
86
|
+
throw new Error("useShopify must be used within a ShopifyProvider");
|
|
87
|
+
}
|
|
88
|
+
return context;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/hooks/cart/const.ts
|
|
92
|
+
var CUSTOMER_ATTRIBUTE_KEY = "_discounts_function_env";
|
|
93
|
+
var CUSTOMER_SCRIPT_GIFT_KEY = "_giveaway_gradient_gifts";
|
|
94
|
+
var CODE_AMOUNT_KEY = "_sku_code_money";
|
|
95
|
+
var SCRIPT_CODE_AMOUNT_KEY = "_code_money";
|
|
96
|
+
var MAIN_PRODUCT_CODE = ["WS24", "WSTD", "WS7D", "WSCP", "WSPE", "WSPD"];
|
|
97
|
+
|
|
98
|
+
// src/hooks/cart/utils/index.ts
|
|
99
|
+
var getQuery = () => {
|
|
100
|
+
const url = typeof window !== "undefined" ? window.location.search : "";
|
|
101
|
+
const theRequest = {};
|
|
102
|
+
if (url.indexOf("?") != -1) {
|
|
103
|
+
const str = url.substr(1), strs = str.split("&");
|
|
104
|
+
for (let i = 0; i < strs.length; i++) {
|
|
105
|
+
const parts = strs[i]?.split("=");
|
|
106
|
+
const key = parts?.[0];
|
|
107
|
+
const value = parts?.[1];
|
|
108
|
+
if (key && value) {
|
|
109
|
+
theRequest[key] = decodeURIComponent(value);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return theRequest;
|
|
114
|
+
};
|
|
115
|
+
function atobID(id) {
|
|
116
|
+
if (id && typeof id === "string" && id.includes("/")) {
|
|
117
|
+
return id.split("/").pop()?.split("?")?.shift();
|
|
118
|
+
} else {
|
|
119
|
+
return id;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function btoaID(id, type = "ProductVariant") {
|
|
123
|
+
return `gid://shopify/${type}/${id}`;
|
|
124
|
+
}
|
|
125
|
+
var getMatchedMainProductSubTotal = (cartData, variant_list, main_product) => {
|
|
126
|
+
const isAllStoreVariant = main_product?.all_store_variant ?? false;
|
|
127
|
+
const matchedList = cartData?.lineItems?.filter((line) => {
|
|
128
|
+
const { is_gift } = getDiscountEnvAttributeValue(line.customAttributes);
|
|
129
|
+
return isAllStoreVariant ? !is_gift : variant_list?.find((item) => {
|
|
130
|
+
return !is_gift && atobID(line.variantId) === item;
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
return matchedList?.reduce((acc, line) => {
|
|
134
|
+
return acc + (main_product?.spend_money_type === 1 /* ORIGIN_PRICE */ ? Number(line.subtotalAmount) || 0 : Number(line.totalAmount) || 0);
|
|
135
|
+
}, 0) || 0;
|
|
136
|
+
};
|
|
137
|
+
var getDiscountEnvAttributeValue = (attributes = []) => {
|
|
138
|
+
const attr = attributes.find((attr2) => attr2.key === CUSTOMER_ATTRIBUTE_KEY);
|
|
139
|
+
return safeParseJson(attr?.value ?? "") ?? {};
|
|
140
|
+
};
|
|
141
|
+
var isAttributesEqual = (attrs1 = [], attrs2 = []) => {
|
|
142
|
+
if (attrs1.length !== attrs2.length) return false;
|
|
143
|
+
const sorted1 = [...attrs1].sort((a, b) => a.key.localeCompare(b.key));
|
|
144
|
+
const sorted2 = [...attrs2].sort((a, b) => a.key.localeCompare(b.key));
|
|
145
|
+
return sorted1.every(
|
|
146
|
+
(attr, i) => attr.key === sorted2[i]?.key && attr.value === sorted2[i]?.value
|
|
147
|
+
);
|
|
148
|
+
};
|
|
149
|
+
var safeParseJson = (str) => {
|
|
150
|
+
try {
|
|
151
|
+
return JSON.parse(str);
|
|
152
|
+
} catch (err) {
|
|
153
|
+
return {};
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
var containsAll = (source, requiredItems = []) => {
|
|
157
|
+
if (!requiredItems?.length) return true;
|
|
158
|
+
const sourceSet = new Set(source);
|
|
159
|
+
return requiredItems.every((item) => sourceSet.has(item));
|
|
160
|
+
};
|
|
161
|
+
var containsNone = (source, forbiddenItems = []) => {
|
|
162
|
+
if (!forbiddenItems?.length) return true;
|
|
163
|
+
const sourceSet = new Set(source);
|
|
164
|
+
return !forbiddenItems.some((item) => sourceSet.has(item));
|
|
165
|
+
};
|
|
166
|
+
function preCheck(rule_conditions, userTags, currentDealsTypes) {
|
|
167
|
+
if (!Array.isArray(rule_conditions)) return false;
|
|
168
|
+
if (rule_conditions.length === 0) return true;
|
|
169
|
+
return rule_conditions.some((rule) => {
|
|
170
|
+
const tagsAreValid = containsAll(userTags, rule.with_user_tags) && containsNone(userTags, rule.without_user_tags);
|
|
171
|
+
const paramsAreValid = containsAll(currentDealsTypes, rule.with_special_url_params) && containsNone(currentDealsTypes, rule.without_special_url_params);
|
|
172
|
+
return tagsAreValid && paramsAreValid;
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
var formatScriptAutoFreeGiftCache = null;
|
|
176
|
+
var formatScriptAutoFreeGift = ({
|
|
177
|
+
scriptAutoFreeGiftResult,
|
|
178
|
+
gradient_gifts,
|
|
179
|
+
locale
|
|
180
|
+
}) => {
|
|
181
|
+
const cacheKey = JSON.stringify({
|
|
182
|
+
freeGiftLevel: scriptAutoFreeGiftResult?.freeGiftLevel ? {
|
|
183
|
+
items: scriptAutoFreeGiftResult.freeGiftLevel.giveawayProducts?.map((item) => ({
|
|
184
|
+
handle: item.handle,
|
|
185
|
+
sku: item.sku,
|
|
186
|
+
quantity: 1
|
|
187
|
+
})) || []
|
|
188
|
+
} : null,
|
|
189
|
+
giftProductsLength: scriptAutoFreeGiftResult?.giftProductsResult?.length || 0,
|
|
190
|
+
giftProductsIds: scriptAutoFreeGiftResult?.giftProductsResult?.map((p) => p.id).sort() || [],
|
|
191
|
+
gradientGiftsId: gradient_gifts?.id || gradient_gifts?.name || "",
|
|
192
|
+
locale
|
|
193
|
+
});
|
|
194
|
+
if (formatScriptAutoFreeGiftCache && formatScriptAutoFreeGiftCache.key === cacheKey) {
|
|
195
|
+
return formatScriptAutoFreeGiftCache.result;
|
|
196
|
+
}
|
|
197
|
+
const result = scriptAutoFreeGiftResult?.freeGiftLevel?.giveawayProducts?.filter(
|
|
198
|
+
(item) => scriptAutoFreeGiftResult?.giftProductsResult?.some(
|
|
199
|
+
(product) => product.handle === item.handle
|
|
200
|
+
)
|
|
201
|
+
).map((item, index) => {
|
|
202
|
+
const product = scriptAutoFreeGiftResult?.giftProductsResult?.find(
|
|
203
|
+
(product2) => product2.handle === item.handle
|
|
204
|
+
);
|
|
205
|
+
const variants = product?.variants;
|
|
206
|
+
const variant = Array.isArray(variants) ? variants.find((v) => v.sku === item.sku) : void 0;
|
|
207
|
+
const query = getQuery();
|
|
208
|
+
const utmCampaign = Cookies5.get("utm_campaign") || query?.utm_campaign;
|
|
209
|
+
const addUTMFreeItem = gradient_gifts.activityAvailableQuery && utmCampaign?.includes(gradient_gifts.activityAvailableQuery);
|
|
210
|
+
let points_subscribe = false;
|
|
211
|
+
if (locale === "au") {
|
|
212
|
+
const isPointsSubscribe = Cookies5.get("points_subscribe");
|
|
213
|
+
points_subscribe = !!isPointsSubscribe;
|
|
214
|
+
}
|
|
215
|
+
const customAttributes = [
|
|
216
|
+
{
|
|
217
|
+
key: "_giveaway_gradient_gifts",
|
|
218
|
+
value: "_giveaway_gradient_gifts"
|
|
219
|
+
},
|
|
220
|
+
...points_subscribe ? [
|
|
221
|
+
{ key: "_amount_upgrade_multiple", value: "1.2" },
|
|
222
|
+
{ key: "_amount_upgrade_value", value: "40" }
|
|
223
|
+
] : [],
|
|
224
|
+
...addUTMFreeItem && gradient_gifts?.activityQroperty ? [
|
|
225
|
+
{
|
|
226
|
+
key: gradient_gifts.activityQroperty,
|
|
227
|
+
value: gradient_gifts.activityQroperty
|
|
228
|
+
}
|
|
229
|
+
] : []
|
|
230
|
+
];
|
|
231
|
+
const line = {
|
|
232
|
+
id: product?.id + "_" + index,
|
|
233
|
+
variantId: String(variant?.id),
|
|
234
|
+
productId: String(product?.id),
|
|
235
|
+
name: product?.name || product?.title || "",
|
|
236
|
+
quantity: 1,
|
|
237
|
+
discounts: [],
|
|
238
|
+
path: product?.handle || "",
|
|
239
|
+
variant,
|
|
240
|
+
totalAmount: 0,
|
|
241
|
+
subtotalAmount: new Decimal2(
|
|
242
|
+
typeof variant?.price === "object" ? variant?.price?.amount || 0 : variant?.price || 0
|
|
243
|
+
).toNumber(),
|
|
244
|
+
options: [],
|
|
245
|
+
discountAllocations: [],
|
|
246
|
+
product,
|
|
247
|
+
customAttributes,
|
|
248
|
+
freeGiftVariant: void 0,
|
|
249
|
+
relatedVariant: void 0
|
|
250
|
+
};
|
|
251
|
+
return {
|
|
252
|
+
line,
|
|
253
|
+
isSoldOut: !variant?.availableForSale
|
|
254
|
+
};
|
|
255
|
+
}) || [];
|
|
256
|
+
formatScriptAutoFreeGiftCache = {
|
|
257
|
+
key: cacheKey,
|
|
258
|
+
result
|
|
259
|
+
};
|
|
260
|
+
return result;
|
|
261
|
+
};
|
|
262
|
+
var formatFunctionAutoFreeGiftCache = null;
|
|
263
|
+
var formatFunctionAutoFreeGift = ({
|
|
264
|
+
qualifyingGift,
|
|
265
|
+
giftProductsResult,
|
|
266
|
+
locale
|
|
267
|
+
}) => {
|
|
268
|
+
const cacheKey = JSON.stringify({
|
|
269
|
+
qualifyingGift: qualifyingGift ? {
|
|
270
|
+
spend: qualifyingGift.tier?.spend_sum_money,
|
|
271
|
+
items: qualifyingGift.itemsToAdd?.map((item) => ({
|
|
272
|
+
variantId: item.variant.id,
|
|
273
|
+
handle: item.variant.handle,
|
|
274
|
+
sku: item.variant.sku,
|
|
275
|
+
quantity: item.quantity ?? 1,
|
|
276
|
+
attributes: item.attributes
|
|
277
|
+
})) || []
|
|
278
|
+
} : null,
|
|
279
|
+
giftProductsLength: giftProductsResult?.length || 0,
|
|
280
|
+
giftProductsIds: giftProductsResult?.map((p) => p.id).sort() || [],
|
|
281
|
+
locale
|
|
282
|
+
});
|
|
283
|
+
if (formatFunctionAutoFreeGiftCache && formatFunctionAutoFreeGiftCache.key === cacheKey) {
|
|
284
|
+
return formatFunctionAutoFreeGiftCache.result;
|
|
285
|
+
}
|
|
286
|
+
const result = qualifyingGift?.itemsToAdd?.map((item, index) => {
|
|
287
|
+
const product = giftProductsResult?.find((product2) => product2.handle === item.variant.handle);
|
|
288
|
+
const variants = product?.variants;
|
|
289
|
+
const variant = Array.isArray(variants) ? variants.find((v) => v.sku === item.variant.sku) : void 0;
|
|
290
|
+
console.log("qualifyingGift variant", product, variant);
|
|
291
|
+
const line = {
|
|
292
|
+
id: product?.id + "_" + index,
|
|
293
|
+
variantId: String(variant?.id),
|
|
294
|
+
productId: String(product?.id),
|
|
295
|
+
name: product?.name || product?.title || "",
|
|
296
|
+
quantity: 1,
|
|
297
|
+
discounts: [],
|
|
298
|
+
path: product?.handle || "",
|
|
299
|
+
variant,
|
|
300
|
+
totalAmount: 0,
|
|
301
|
+
subtotalAmount: new Decimal2(
|
|
302
|
+
typeof variant?.price === "object" ? variant?.price?.amount || 0 : variant?.price || 0
|
|
303
|
+
).toNumber(),
|
|
304
|
+
options: [],
|
|
305
|
+
discountAllocations: [],
|
|
306
|
+
product,
|
|
307
|
+
customAttributes: item.attributes,
|
|
308
|
+
freeGiftVariant: void 0,
|
|
309
|
+
relatedVariant: void 0
|
|
310
|
+
};
|
|
311
|
+
return {
|
|
312
|
+
line,
|
|
313
|
+
isSoldOut: !variant?.availableForSale
|
|
314
|
+
};
|
|
315
|
+
}) || [];
|
|
316
|
+
formatFunctionAutoFreeGiftCache = {
|
|
317
|
+
key: cacheKey,
|
|
318
|
+
result
|
|
319
|
+
};
|
|
320
|
+
return result;
|
|
321
|
+
};
|
|
322
|
+
var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
|
|
323
|
+
const tags = useMemo(() => customer?.tags || [], [customer?.tags]);
|
|
324
|
+
const isCustomerLoading = useMemo(() => !customer ? true : false, [customer]);
|
|
325
|
+
const dealsType = "";
|
|
326
|
+
const { client, locale } = useShopify();
|
|
327
|
+
const giftProductsCache = useRef(null);
|
|
328
|
+
const { activeCampaign, subtotal } = useMemo(() => {
|
|
329
|
+
for (const campaign of autoFreeGiftConfig) {
|
|
330
|
+
const { rule_conditions = [], rule_result } = campaign;
|
|
331
|
+
const { spend_get_reward } = rule_result || {};
|
|
332
|
+
const isPreCheckPassed = preCheck(rule_conditions, tags, []);
|
|
333
|
+
if (isPreCheckPassed && spend_get_reward) {
|
|
334
|
+
const matchedSubtotal = getMatchedMainProductSubTotal(
|
|
335
|
+
cart,
|
|
336
|
+
spend_get_reward.main_product?.variant_list?.map((v) => v.variant_id) || [],
|
|
337
|
+
{
|
|
338
|
+
spend_money_type: spend_get_reward.main_product?.spend_money_type || 1,
|
|
339
|
+
variant_id_list: spend_get_reward.main_product?.variant_list?.map((v) => v.variant_id) || [],
|
|
340
|
+
all_store_variant: spend_get_reward.main_product?.all_store_variant || false
|
|
341
|
+
}
|
|
342
|
+
);
|
|
343
|
+
if (matchedSubtotal > 0) {
|
|
344
|
+
return { activeCampaign: campaign, subtotal: matchedSubtotal };
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return { activeCampaign: null, subtotal: 0 };
|
|
349
|
+
}, [autoFreeGiftConfig, cart, tags, dealsType]);
|
|
350
|
+
const { qualifyingGift, nextTierGoal } = useMemo(() => {
|
|
351
|
+
if (!activeCampaign || !activeCampaign.rule_result?.spend_get_reward?.gift_product) {
|
|
352
|
+
return { qualifyingGift: null, nextTierGoal: null };
|
|
353
|
+
}
|
|
354
|
+
const giftTiers = activeCampaign.rule_result.spend_get_reward.gift_product;
|
|
355
|
+
const qualifyingTier = [...giftTiers].reverse().find((tier) => subtotal >= Number(tier.spend_sum_money));
|
|
356
|
+
const nextGoal = giftTiers.find((tier) => subtotal < Number(tier.spend_sum_money));
|
|
357
|
+
if (!qualifyingTier) {
|
|
358
|
+
return { qualifyingGift: null, nextTierGoal: nextGoal || null };
|
|
359
|
+
}
|
|
360
|
+
const formattedGift = {
|
|
361
|
+
tier: qualifyingTier,
|
|
362
|
+
itemsToAdd: qualifyingTier.reward_list?.map((reward) => {
|
|
363
|
+
const giftProduct = reward?.variant_list?.[0];
|
|
364
|
+
if (!giftProduct) return null;
|
|
365
|
+
return {
|
|
366
|
+
variant: {
|
|
367
|
+
id: btoaID(giftProduct.variant_id),
|
|
368
|
+
handle: giftProduct.handle,
|
|
369
|
+
sku: giftProduct.sku
|
|
370
|
+
},
|
|
371
|
+
quantity: reward?.get_unit || 1,
|
|
372
|
+
attributes: [
|
|
373
|
+
{
|
|
374
|
+
key: CUSTOMER_ATTRIBUTE_KEY,
|
|
375
|
+
value: JSON.stringify({
|
|
376
|
+
is_gift: true,
|
|
377
|
+
rule_id: activeCampaign.rule_id,
|
|
378
|
+
spend_sum_money: qualifyingTier.spend_sum_money
|
|
379
|
+
})
|
|
380
|
+
}
|
|
381
|
+
]
|
|
382
|
+
};
|
|
383
|
+
}).filter((item) => item !== null)
|
|
384
|
+
};
|
|
385
|
+
return { qualifyingGift: formattedGift, nextTierGoal: nextGoal || null };
|
|
386
|
+
}, [activeCampaign, subtotal]);
|
|
387
|
+
const giftHandles = useMemo(() => {
|
|
388
|
+
const giftVariant = autoFreeGiftConfig.map(
|
|
389
|
+
(item) => item.rule_result?.spend_get_reward?.gift_product?.map(
|
|
390
|
+
(v) => v.reward_list.map((reward) => reward.variant_list.map((variant) => variant.handle))
|
|
391
|
+
).flat()
|
|
392
|
+
).flat();
|
|
393
|
+
return giftVariant.flat(2).filter(Boolean);
|
|
394
|
+
}, [autoFreeGiftConfig]);
|
|
395
|
+
const shouldFetch = useMemo(() => {
|
|
396
|
+
if (!giftHandles.length) return false;
|
|
397
|
+
if (giftProductsCache.current && JSON.stringify(giftProductsCache.current.giftHandles) === JSON.stringify(giftHandles)) {
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
return true;
|
|
401
|
+
}, [giftHandles]);
|
|
402
|
+
const { data: giftProductsResult } = useSWR(shouldFetch ? giftHandles : null, async () => {
|
|
403
|
+
const res = await getProductsByHandles(client, {
|
|
404
|
+
handles: giftHandles,
|
|
405
|
+
locale
|
|
406
|
+
});
|
|
407
|
+
const result = Array.isArray(res) ? res : [];
|
|
408
|
+
giftProductsCache.current = {
|
|
409
|
+
data: result,
|
|
410
|
+
giftHandles: [...giftHandles]
|
|
411
|
+
};
|
|
412
|
+
return result;
|
|
413
|
+
});
|
|
414
|
+
const finalGiftProductsResult = useMemo(() => {
|
|
415
|
+
if (giftProductsCache.current && !shouldFetch) {
|
|
416
|
+
return giftProductsCache.current.data || void 0;
|
|
417
|
+
}
|
|
418
|
+
return giftProductsResult;
|
|
419
|
+
}, [giftProductsResult, shouldFetch]);
|
|
420
|
+
return {
|
|
421
|
+
qualifyingGift,
|
|
422
|
+
nextTierGoal,
|
|
423
|
+
activeCampaign,
|
|
424
|
+
isLoading: isCustomerLoading,
|
|
425
|
+
giftProductsResult: finalGiftProductsResult
|
|
426
|
+
};
|
|
427
|
+
};
|
|
428
|
+
var useScriptAutoFreeGift = ({
|
|
429
|
+
campaign,
|
|
430
|
+
_giveaway,
|
|
431
|
+
cart,
|
|
432
|
+
locale: providedLocale
|
|
433
|
+
}) => {
|
|
434
|
+
const { client, locale: contextLocale } = useShopify();
|
|
435
|
+
const locale = providedLocale || contextLocale;
|
|
436
|
+
const [points_subscribe, set_points_subscribe] = useState(false);
|
|
437
|
+
const giftProductsCache = useRef(null);
|
|
438
|
+
useEffect(() => {
|
|
439
|
+
if (locale === "au") {
|
|
440
|
+
const isPointsSubscribe = Cookies5.get("points_subscribe");
|
|
441
|
+
set_points_subscribe(!!isPointsSubscribe);
|
|
442
|
+
}
|
|
443
|
+
}, [locale]);
|
|
444
|
+
const [upgrade_multiple, upgrade_value] = useMemo(() => {
|
|
445
|
+
let upgrade_multiple2 = 1;
|
|
446
|
+
let upgrade_value2 = 0;
|
|
447
|
+
if (points_subscribe) {
|
|
448
|
+
upgrade_multiple2 = 1.2;
|
|
449
|
+
upgrade_value2 = 40;
|
|
450
|
+
}
|
|
451
|
+
cart?.lineItems?.forEach(({ customAttributes }) => {
|
|
452
|
+
customAttributes?.forEach(({ key, value }) => {
|
|
453
|
+
if (key === "_amount_upgrade_multiple") upgrade_multiple2 = Number(value) || 1;
|
|
454
|
+
if (key === "_amount_upgrade_value") upgrade_value2 = Number(value) || 0;
|
|
455
|
+
});
|
|
456
|
+
});
|
|
457
|
+
return [upgrade_multiple2, upgrade_value2];
|
|
458
|
+
}, [cart?.lineItems, points_subscribe]);
|
|
459
|
+
const breakpoints = useMemo(() => {
|
|
460
|
+
if (!campaign) return [];
|
|
461
|
+
return (campaign.breakpoints || []).map((item) => ({
|
|
462
|
+
breakpoint: new Decimal2(item.breakpoint).minus(new Decimal2(upgrade_value)).dividedBy(new Decimal2(upgrade_multiple)).toFixed(2, Decimal2.ROUND_DOWN),
|
|
463
|
+
giveawayProducts: item.giveawayProducts || []
|
|
464
|
+
}));
|
|
465
|
+
}, [campaign, upgrade_multiple, upgrade_value]);
|
|
466
|
+
const giftHandles = useMemo(
|
|
467
|
+
() => (
|
|
468
|
+
// 使用 Set 去重,然后拼接字符串
|
|
469
|
+
[
|
|
470
|
+
...new Set(
|
|
471
|
+
breakpoints.flatMap((b) => b.giveawayProducts.map((p) => p.handle)).filter(Boolean)
|
|
472
|
+
)
|
|
473
|
+
]
|
|
474
|
+
),
|
|
475
|
+
[breakpoints]
|
|
476
|
+
);
|
|
477
|
+
const shouldFetch = useMemo(() => {
|
|
478
|
+
if (!giftHandles.length) return false;
|
|
479
|
+
if (giftProductsCache.current && JSON.stringify(giftProductsCache.current.giftHandles) === JSON.stringify(giftHandles)) {
|
|
480
|
+
return false;
|
|
481
|
+
}
|
|
482
|
+
return true;
|
|
483
|
+
}, [giftHandles]);
|
|
484
|
+
const involvedLines = useMemo(() => {
|
|
485
|
+
if (!campaign) return [];
|
|
486
|
+
return (cart?.lineItems || []).filter((line) => {
|
|
487
|
+
const isNotGift = line?.totalAmount && Number(line.totalAmount) > 0 && line.customAttributes?.every(
|
|
488
|
+
(item) => item.key !== _giveaway
|
|
489
|
+
);
|
|
490
|
+
const hasCampaignTag = line.product?.tags?.some(
|
|
491
|
+
(tag) => campaign.includeTags?.includes(tag.trim()) && line.variant?.availableForSale
|
|
492
|
+
);
|
|
493
|
+
return isNotGift && hasCampaignTag;
|
|
494
|
+
});
|
|
495
|
+
}, [cart?.lineItems, campaign, _giveaway]);
|
|
496
|
+
const involvedSubTotal = useMemo(() => {
|
|
497
|
+
if (!campaign) return new Decimal2(0);
|
|
498
|
+
return involvedLines.reduce((prev, item) => {
|
|
499
|
+
const amount = campaign.useTotalAmount ? item.totalAmount : item.subtotalAmount;
|
|
500
|
+
return new Decimal2(prev).plus(new Decimal2(amount || 0));
|
|
501
|
+
}, new Decimal2(0));
|
|
502
|
+
}, [involvedLines, campaign]);
|
|
503
|
+
const [freeGiftLevel, nextFreeGiftLevel] = useMemo(() => {
|
|
504
|
+
const sortedLevels = [...breakpoints].sort(
|
|
505
|
+
(a, b) => Number(b.breakpoint) - Number(a.breakpoint)
|
|
506
|
+
);
|
|
507
|
+
const levelIndex = sortedLevels.findIndex(
|
|
508
|
+
(level) => involvedSubTotal.gte(new Decimal2(level.breakpoint)) && involvedLines.length > 0
|
|
509
|
+
);
|
|
510
|
+
if (levelIndex === -1) {
|
|
511
|
+
return [
|
|
512
|
+
null,
|
|
513
|
+
sortedLevels.length > 0 ? sortedLevels[sortedLevels.length - 1] ?? null : null
|
|
514
|
+
];
|
|
515
|
+
}
|
|
516
|
+
const currentLevel = sortedLevels[levelIndex] ?? null;
|
|
517
|
+
const nextLevel = levelIndex > 0 ? sortedLevels[levelIndex - 1] ?? null : null;
|
|
518
|
+
return [currentLevel, nextLevel];
|
|
519
|
+
}, [breakpoints, involvedSubTotal, involvedLines.length]);
|
|
520
|
+
const { data: giftProductsResult } = useSWR(shouldFetch ? giftHandles : null, async () => {
|
|
521
|
+
const res = await getProductsByHandles(client, {
|
|
522
|
+
handles: giftHandles,
|
|
523
|
+
locale
|
|
524
|
+
});
|
|
525
|
+
const result = Array.isArray(res) ? res : [];
|
|
526
|
+
giftProductsCache.current = {
|
|
527
|
+
data: result,
|
|
528
|
+
giftHandles: [...giftHandles]
|
|
529
|
+
};
|
|
530
|
+
return result;
|
|
531
|
+
});
|
|
532
|
+
const finalGiftProductsResult = useMemo(() => {
|
|
533
|
+
if (giftProductsCache.current && !shouldFetch) {
|
|
534
|
+
return giftProductsCache.current.data || void 0;
|
|
535
|
+
}
|
|
536
|
+
return giftProductsResult;
|
|
537
|
+
}, [giftProductsResult, shouldFetch]);
|
|
538
|
+
const reorder = useCallback(
|
|
539
|
+
(a, b) => {
|
|
540
|
+
const getPriority = (item) => {
|
|
541
|
+
if (item.customAttributes?.some(
|
|
542
|
+
(attribute) => attribute.key === _giveaway
|
|
543
|
+
))
|
|
544
|
+
return 0;
|
|
545
|
+
if (item.product?.tags?.some((tag) => campaign?.includeTags?.includes(tag)))
|
|
546
|
+
return 1;
|
|
547
|
+
return 2;
|
|
548
|
+
};
|
|
549
|
+
return getPriority(b) - getPriority(a);
|
|
550
|
+
},
|
|
551
|
+
[campaign?.includeTags, _giveaway]
|
|
552
|
+
);
|
|
553
|
+
return {
|
|
554
|
+
involvedLines,
|
|
555
|
+
reorder,
|
|
556
|
+
disableCodeRemove: involvedLines.length > 0,
|
|
557
|
+
nextFreeGiftLevel,
|
|
558
|
+
freeGiftLevel,
|
|
559
|
+
involvedSubTotal,
|
|
560
|
+
giftProductsResult: finalGiftProductsResult
|
|
561
|
+
};
|
|
562
|
+
};
|
|
563
|
+
function useUpdateCartAttributes(mutate, metafieldIdentifiers, options) {
|
|
564
|
+
const { client, locale, cartCookieAdapter } = useShopify();
|
|
565
|
+
const updateAttributes = useCallback(
|
|
566
|
+
async (_key, { arg }) => {
|
|
567
|
+
const updatedCart = await updateCartAttributes(client, {
|
|
568
|
+
...arg,
|
|
569
|
+
metafieldIdentifiers,
|
|
570
|
+
cookieAdapter: cartCookieAdapter
|
|
571
|
+
});
|
|
572
|
+
console.log("useUpdateCartAttributes updatedCart", updatedCart);
|
|
573
|
+
if (updatedCart) {
|
|
574
|
+
mutate(updatedCart);
|
|
575
|
+
}
|
|
576
|
+
return updatedCart;
|
|
577
|
+
},
|
|
578
|
+
[client, locale, cartCookieAdapter, mutate]
|
|
579
|
+
);
|
|
580
|
+
return useSWRMutation8("update-cart-attributes", updateAttributes, options);
|
|
581
|
+
}
|
|
582
|
+
function useHasPlusMemberInCart({
|
|
583
|
+
memberSetting,
|
|
584
|
+
cart
|
|
585
|
+
}) {
|
|
586
|
+
const { plus_monthly_product, plus_annual_product } = memberSetting || {};
|
|
587
|
+
return useMemo(() => {
|
|
588
|
+
if (!cart?.lineItems) {
|
|
589
|
+
return {
|
|
590
|
+
hasPlusMember: false,
|
|
591
|
+
hasMonthlyPlus: false,
|
|
592
|
+
hasAnnualPlus: false
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
const monthlyPlusItem = cart.lineItems.find(
|
|
596
|
+
(item) => item.product?.handle === plus_monthly_product?.handle && item.variant?.sku === plus_monthly_product?.sku
|
|
597
|
+
);
|
|
598
|
+
const annualPlusItem = cart.lineItems.find(
|
|
599
|
+
(item) => item.product?.handle === plus_annual_product?.handle && item.variant?.sku === plus_annual_product?.sku
|
|
600
|
+
);
|
|
601
|
+
const hasMonthlyPlus = !!monthlyPlusItem;
|
|
602
|
+
const hasAnnualPlus = !!annualPlusItem;
|
|
603
|
+
const hasPlusMember = hasMonthlyPlus || hasAnnualPlus;
|
|
604
|
+
return {
|
|
605
|
+
hasPlusMember,
|
|
606
|
+
hasMonthlyPlus,
|
|
607
|
+
hasAnnualPlus,
|
|
608
|
+
monthlyPlusItem,
|
|
609
|
+
annualPlusItem
|
|
610
|
+
};
|
|
611
|
+
}, [cart?.lineItems, plus_monthly_product, plus_annual_product]);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
// src/hooks/cart/feature/use-cart-attributes.ts
|
|
615
|
+
var getReferralAttributes = () => {
|
|
616
|
+
const inviteCode = Cookies5.get("invite_code");
|
|
617
|
+
const playModeId = Cookies5.get("playModeId");
|
|
618
|
+
const popup = Cookies5.get("_popup");
|
|
619
|
+
if (inviteCode && playModeId) {
|
|
620
|
+
return popup ? [
|
|
621
|
+
{ key: "_invite_code", value: inviteCode ? inviteCode : "" },
|
|
622
|
+
{ key: "_play_mode_id", value: playModeId ? playModeId : "" },
|
|
623
|
+
{ key: "_popup", value: popup }
|
|
624
|
+
] : [
|
|
625
|
+
{ key: "_invite_code", value: inviteCode ? inviteCode : "" },
|
|
626
|
+
{ key: "_play_mode_id", value: playModeId ? playModeId : "" }
|
|
627
|
+
];
|
|
628
|
+
}
|
|
629
|
+
return [];
|
|
630
|
+
};
|
|
631
|
+
var useCartAttributes = ({
|
|
632
|
+
profile,
|
|
633
|
+
customer,
|
|
634
|
+
cart,
|
|
635
|
+
memberSetting
|
|
636
|
+
}) => {
|
|
637
|
+
const [currentUrl, setCurrentUrl] = useState("");
|
|
638
|
+
const { hasPlusMember } = useHasPlusMemberInCart({
|
|
639
|
+
memberSetting,
|
|
640
|
+
cart
|
|
641
|
+
});
|
|
642
|
+
console.log("memberSetting", memberSetting);
|
|
643
|
+
console.log("hasPlusMember", hasPlusMember);
|
|
644
|
+
useEffect(() => {
|
|
645
|
+
setCurrentUrl(window.location.href);
|
|
646
|
+
}, []);
|
|
647
|
+
const userType = useMemo(() => {
|
|
648
|
+
let userInfo = Cookies5.get("userInfo");
|
|
649
|
+
if (userInfo) {
|
|
650
|
+
userInfo = JSON.parse(userInfo);
|
|
651
|
+
let arr = typeof userInfo?.id == "string" && userInfo?.id.split("/");
|
|
652
|
+
userInfo.setId = arr[arr.length - 1];
|
|
653
|
+
}
|
|
654
|
+
const customerInfo = userInfo || customer;
|
|
655
|
+
if (!customerInfo) {
|
|
656
|
+
return "new_user_unlogin";
|
|
657
|
+
}
|
|
658
|
+
if (customer) {
|
|
659
|
+
const { orders = {} } = customer;
|
|
660
|
+
if (orders?.edges?.length === 1) {
|
|
661
|
+
return "old_user_orders_once";
|
|
662
|
+
} else if (orders?.edges?.length > 1) {
|
|
663
|
+
return "old_user_orders_twice";
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
return "new_user_login";
|
|
667
|
+
}, [customer]);
|
|
668
|
+
const memberAttributes = useMemo(() => {
|
|
669
|
+
return [
|
|
670
|
+
{
|
|
671
|
+
key: "_token",
|
|
672
|
+
value: profile?.token
|
|
673
|
+
//是否登录
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
key: "_member_type",
|
|
677
|
+
value: hasPlusMember ? "2" : profile?.memberType
|
|
678
|
+
//:0(游客),1(普通会员),2(付费会员)
|
|
679
|
+
},
|
|
680
|
+
{
|
|
681
|
+
key: "_user_type",
|
|
682
|
+
value: userType
|
|
683
|
+
// n
|
|
684
|
+
},
|
|
685
|
+
{
|
|
686
|
+
key: "_is_login",
|
|
687
|
+
value: profile?.token ? "true" : "false"
|
|
688
|
+
}
|
|
689
|
+
];
|
|
690
|
+
}, [profile?.memberType, profile?.token, userType, hasPlusMember]);
|
|
691
|
+
const functionAttributes = useMemo(() => {
|
|
692
|
+
return [
|
|
693
|
+
cart?.discountCodes && {
|
|
694
|
+
key: "_discounts_function_env",
|
|
695
|
+
value: JSON.stringify({
|
|
696
|
+
discount_code: cart?.discountCodes.map((item) => item.code),
|
|
697
|
+
user_tags: customer?.tags || []
|
|
698
|
+
})
|
|
699
|
+
}
|
|
700
|
+
];
|
|
701
|
+
}, [cart]);
|
|
702
|
+
const presellAttributes = useMemo(() => {
|
|
703
|
+
return [
|
|
704
|
+
{
|
|
705
|
+
key: "_presale",
|
|
706
|
+
value: cart?.lineItems.some((item) => item?.variant?.metafields?.presell === "presell")
|
|
707
|
+
}
|
|
708
|
+
];
|
|
709
|
+
}, [cart]);
|
|
710
|
+
const weightAttributes = useMemo(() => {
|
|
711
|
+
return [
|
|
712
|
+
{
|
|
713
|
+
key: "_weight",
|
|
714
|
+
value: cart?.lineItems.reduce((acc, item) => {
|
|
715
|
+
return new Decimal2(acc).plus(item.variant.weight ?? 0).toNumber();
|
|
716
|
+
}, 0).toString()
|
|
717
|
+
},
|
|
718
|
+
{
|
|
719
|
+
key: "_app_source_name",
|
|
720
|
+
value: "dtc"
|
|
721
|
+
}
|
|
722
|
+
];
|
|
723
|
+
}, [cart]);
|
|
724
|
+
const trackingAttributes = useMemo(() => {
|
|
725
|
+
return [
|
|
726
|
+
{
|
|
727
|
+
key: "utm_params",
|
|
728
|
+
value: currentUrl
|
|
729
|
+
}
|
|
730
|
+
];
|
|
731
|
+
}, [currentUrl]);
|
|
732
|
+
return useMemo(
|
|
733
|
+
() => ({
|
|
734
|
+
attributes: [
|
|
735
|
+
...memberAttributes,
|
|
736
|
+
...functionAttributes,
|
|
737
|
+
...presellAttributes,
|
|
738
|
+
...weightAttributes,
|
|
739
|
+
...trackingAttributes,
|
|
740
|
+
...getReferralAttributes()
|
|
741
|
+
].filter((item) => item?.value)
|
|
742
|
+
}),
|
|
743
|
+
[memberAttributes, functionAttributes, presellAttributes, weightAttributes, trackingAttributes]
|
|
744
|
+
);
|
|
745
|
+
};
|
|
746
|
+
var useUpdateLineCodeAmountAttributes = ({
|
|
747
|
+
cart,
|
|
748
|
+
mutateCart,
|
|
749
|
+
isCartLoading,
|
|
750
|
+
setLoadingState,
|
|
751
|
+
metafieldIdentifiers
|
|
752
|
+
}) => {
|
|
753
|
+
const { client, cartCookieAdapter } = useShopify();
|
|
754
|
+
const mainProductDiscountCodes = useMemo(
|
|
755
|
+
() => cart?.discountCodes.filter(
|
|
756
|
+
({ code, applicable }) => applicable && MAIN_PRODUCT_CODE.some((codePrefix) => code.startsWith(codePrefix))
|
|
757
|
+
).map(({ code }) => code),
|
|
758
|
+
[cart]
|
|
759
|
+
);
|
|
760
|
+
const linesNeedUpdate = useMemo(
|
|
761
|
+
() => cart?.lineItems.map((line) => {
|
|
762
|
+
const attrNeedUpdate = [];
|
|
763
|
+
const attrNeedDelete = [];
|
|
764
|
+
const codeDiscount = line.discountAllocations?.find(
|
|
765
|
+
(allocation) => mainProductDiscountCodes?.includes(allocation.code)
|
|
766
|
+
);
|
|
767
|
+
const hasFunctionEnvAttribute = line.customAttributes?.find(
|
|
768
|
+
(attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY
|
|
769
|
+
);
|
|
770
|
+
const functionEnvValue = getDiscountEnvAttributeValue(line.customAttributes);
|
|
771
|
+
const hasSameFunctionEnvAttribute = Number(functionEnvValue.discounted_amount) === Number(line.totalAmount);
|
|
772
|
+
if (!hasSameFunctionEnvAttribute && hasFunctionEnvAttribute) {
|
|
773
|
+
attrNeedUpdate.push({
|
|
774
|
+
key: CUSTOMER_ATTRIBUTE_KEY,
|
|
775
|
+
value: JSON.stringify({
|
|
776
|
+
...functionEnvValue,
|
|
777
|
+
discounted_amount: Number(line.totalAmount)
|
|
778
|
+
})
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
const codeDiscountAmount = codeDiscount?.amount || 0;
|
|
782
|
+
const hasCodeAmountAttribute = line.customAttributes?.find(
|
|
783
|
+
(attr) => attr.key === CODE_AMOUNT_KEY || attr.key === SCRIPT_CODE_AMOUNT_KEY
|
|
784
|
+
);
|
|
785
|
+
const hasSameCodeAmountAttribute = line.customAttributes?.find(
|
|
786
|
+
(attr) => attr.key === CODE_AMOUNT_KEY && attr.value === String(codeDiscountAmount)
|
|
787
|
+
) && line.customAttributes?.find(
|
|
788
|
+
(attr) => attr.key === SCRIPT_CODE_AMOUNT_KEY && attr.value === String(codeDiscountAmount)
|
|
789
|
+
);
|
|
790
|
+
if (codeDiscount && !hasSameCodeAmountAttribute) {
|
|
791
|
+
attrNeedUpdate.push({
|
|
792
|
+
key: CODE_AMOUNT_KEY,
|
|
793
|
+
value: String(codeDiscountAmount)
|
|
794
|
+
});
|
|
795
|
+
attrNeedUpdate.push({
|
|
796
|
+
key: SCRIPT_CODE_AMOUNT_KEY,
|
|
797
|
+
value: String(codeDiscountAmount)
|
|
798
|
+
});
|
|
799
|
+
} else if (!codeDiscount && hasCodeAmountAttribute) {
|
|
800
|
+
attrNeedDelete.push(CODE_AMOUNT_KEY);
|
|
801
|
+
attrNeedDelete.push(SCRIPT_CODE_AMOUNT_KEY);
|
|
802
|
+
}
|
|
803
|
+
return {
|
|
804
|
+
line,
|
|
805
|
+
attrNeedUpdate,
|
|
806
|
+
attrNeedDelete
|
|
807
|
+
};
|
|
808
|
+
}).filter(
|
|
809
|
+
({ attrNeedUpdate, attrNeedDelete }) => attrNeedUpdate.length || attrNeedDelete.length
|
|
810
|
+
).map(({ line, attrNeedUpdate, attrNeedDelete }) => {
|
|
811
|
+
if (attrNeedUpdate.length) {
|
|
812
|
+
return {
|
|
813
|
+
id: line.id,
|
|
814
|
+
attributes: [
|
|
815
|
+
...line.customAttributes?.filter(
|
|
816
|
+
(attr) => !attrNeedUpdate.some((updateAttr) => updateAttr.key === attr.key)
|
|
817
|
+
) || [],
|
|
818
|
+
...attrNeedUpdate
|
|
819
|
+
]
|
|
820
|
+
};
|
|
821
|
+
} else if (attrNeedDelete.length) {
|
|
822
|
+
return {
|
|
823
|
+
id: line.id,
|
|
824
|
+
attributes: line.customAttributes?.filter(
|
|
825
|
+
(attr) => !attrNeedDelete.includes(attr.key)
|
|
826
|
+
) || []
|
|
827
|
+
};
|
|
828
|
+
} else {
|
|
829
|
+
return {
|
|
830
|
+
id: line.id,
|
|
831
|
+
attributes: line.customAttributes || []
|
|
832
|
+
};
|
|
833
|
+
}
|
|
834
|
+
}),
|
|
835
|
+
[cart?.lineItems, mainProductDiscountCodes]
|
|
836
|
+
);
|
|
837
|
+
const { loading } = useRequest(
|
|
838
|
+
async () => {
|
|
839
|
+
if (linesNeedUpdate?.length && !isCartLoading) {
|
|
840
|
+
const result = await updateCartLines(client, {
|
|
841
|
+
cartId: cart?.id || "",
|
|
842
|
+
lines: linesNeedUpdate,
|
|
843
|
+
metafieldIdentifiers,
|
|
844
|
+
cookieAdapter: cartCookieAdapter
|
|
845
|
+
});
|
|
846
|
+
if (result) {
|
|
847
|
+
mutateCart(result);
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
},
|
|
851
|
+
{
|
|
852
|
+
throttleWait: 3e3,
|
|
853
|
+
// 3 秒内只触发最后一次更新
|
|
854
|
+
throttleTrailing: true,
|
|
855
|
+
refreshDeps: [linesNeedUpdate, isCartLoading]
|
|
856
|
+
}
|
|
857
|
+
);
|
|
858
|
+
useEffect(() => {
|
|
859
|
+
setLoadingState((prev) => {
|
|
860
|
+
return {
|
|
861
|
+
...prev,
|
|
862
|
+
editLineCodeAmountLoading: loading
|
|
863
|
+
};
|
|
864
|
+
});
|
|
865
|
+
}, [loading, setLoadingState]);
|
|
866
|
+
};
|
|
867
|
+
var createInitialValue = () => ({
|
|
868
|
+
zipCode: "",
|
|
869
|
+
plusMemberMetafields: {},
|
|
870
|
+
setZipCode: () => {
|
|
871
|
+
},
|
|
872
|
+
allowNextDayDelivery: false,
|
|
873
|
+
setAllowNextDayDelivery: () => {
|
|
874
|
+
},
|
|
875
|
+
allowThirdDayDelivery: false,
|
|
876
|
+
setAllowThirdDayDelivery: () => {
|
|
877
|
+
},
|
|
878
|
+
selectedPlusMemberMode: "free",
|
|
879
|
+
setSelectedPlusMemberMode: () => {
|
|
880
|
+
},
|
|
881
|
+
showAreaCheckModal: false,
|
|
882
|
+
setShowAreaCheckModal: () => {
|
|
883
|
+
},
|
|
884
|
+
selectedShippingMethod: void 0,
|
|
885
|
+
setSelectedShippingMethod: () => {
|
|
886
|
+
},
|
|
887
|
+
showTip: false,
|
|
888
|
+
setShowTip: () => {
|
|
889
|
+
},
|
|
890
|
+
showMoreShippingMethod: false,
|
|
891
|
+
setShowMoreShippingMethod: () => {
|
|
892
|
+
},
|
|
893
|
+
variant: {},
|
|
894
|
+
product: {},
|
|
895
|
+
shippingMethodsContext: {
|
|
896
|
+
freeShippingMethods: [],
|
|
897
|
+
paymentShippingMethods: [],
|
|
898
|
+
nddOverweight: false,
|
|
899
|
+
tddOverweight: false
|
|
900
|
+
},
|
|
901
|
+
selectedPlusMemberProduct: null,
|
|
902
|
+
plusMemberProducts: [],
|
|
903
|
+
showPlusMemberBenefit: false,
|
|
904
|
+
setShowPlusMemberBenefit: () => {
|
|
905
|
+
},
|
|
906
|
+
deleteMarginBottom: false,
|
|
907
|
+
setDeleteMarginBottom: () => {
|
|
908
|
+
},
|
|
909
|
+
profile: void 0,
|
|
910
|
+
locale: void 0
|
|
911
|
+
});
|
|
912
|
+
createContext(createInitialValue());
|
|
913
|
+
var CartContext = createContext(null);
|
|
914
|
+
function CartProvider({
|
|
915
|
+
children,
|
|
916
|
+
// swrOptions,
|
|
917
|
+
autoFreeGiftConfig,
|
|
918
|
+
gradientGiftsConfig,
|
|
919
|
+
profile,
|
|
920
|
+
customer,
|
|
921
|
+
locale,
|
|
922
|
+
metafieldIdentifiers,
|
|
923
|
+
memberSetting
|
|
924
|
+
}) {
|
|
925
|
+
const { client, cartCookieAdapter } = useShopify();
|
|
926
|
+
const [customAttributes, setCustomAttributes] = useState([]);
|
|
927
|
+
const [isCodeChanging, setIsCodeChanging] = useState(false);
|
|
928
|
+
const [loadingState, setLoadingState] = useState({
|
|
929
|
+
editLineQuantityLoading: false,
|
|
930
|
+
editLineCodeAmountLoading: false,
|
|
931
|
+
listingAutoCodeApplying: false,
|
|
932
|
+
userCodeApplying: false
|
|
933
|
+
});
|
|
934
|
+
const [scriptAutoFreeGift, setScriptAutoFreeGift] = useState([]);
|
|
935
|
+
const [functionAutoFreeGift, setFunctionAutoFreeGift] = useState([]);
|
|
936
|
+
const {
|
|
937
|
+
run: fetchCart,
|
|
938
|
+
data: cart,
|
|
939
|
+
loading: isCartLoading,
|
|
940
|
+
mutate: mutateCart
|
|
941
|
+
} = useRequest(
|
|
942
|
+
async () => {
|
|
943
|
+
return getCart(client, {
|
|
944
|
+
cookieAdapter: cartCookieAdapter,
|
|
945
|
+
metafieldIdentifiers
|
|
946
|
+
});
|
|
947
|
+
},
|
|
948
|
+
{
|
|
949
|
+
refreshDeps: [locale]
|
|
950
|
+
}
|
|
951
|
+
);
|
|
952
|
+
const { trigger: updateAttributes } = useUpdateCartAttributes(mutateCart, metafieldIdentifiers);
|
|
953
|
+
const { attributes } = useCartAttributes({ profile, customer, cart, memberSetting });
|
|
954
|
+
useRequest(
|
|
955
|
+
() => {
|
|
956
|
+
const newAttributes = [...attributes, ...customAttributes];
|
|
957
|
+
const needUpdate = cart && !isAttributesEqual(cart.customAttributes, newAttributes);
|
|
958
|
+
if (needUpdate) {
|
|
959
|
+
return updateAttributes({ attributes: newAttributes });
|
|
960
|
+
} else {
|
|
961
|
+
return Promise.resolve(cart);
|
|
962
|
+
}
|
|
963
|
+
},
|
|
964
|
+
{
|
|
965
|
+
throttleWait: 1e3,
|
|
966
|
+
// 1 秒内只触发最后一次更新
|
|
967
|
+
throttleTrailing: true,
|
|
968
|
+
throttleLeading: false,
|
|
969
|
+
refreshDeps: [attributes, customAttributes]
|
|
970
|
+
}
|
|
971
|
+
);
|
|
972
|
+
useUpdateLineCodeAmountAttributes({
|
|
973
|
+
cart,
|
|
974
|
+
mutateCart,
|
|
975
|
+
isCartLoading: isCartLoading || isCodeChanging,
|
|
976
|
+
setLoadingState
|
|
977
|
+
});
|
|
978
|
+
const removeCustomAttributes = useCallback((attributes2) => {
|
|
979
|
+
setCustomAttributes(
|
|
980
|
+
(prev) => prev.filter((attr) => !attributes2.some((a) => a.key === attr.key))
|
|
981
|
+
);
|
|
982
|
+
}, []);
|
|
983
|
+
const addCustomAttributes = useCallback(
|
|
984
|
+
(attributes2) => {
|
|
985
|
+
const sameAttributes = attributes2.filter(
|
|
986
|
+
(attr) => customAttributes.some((a) => a.key === attr.key)
|
|
987
|
+
);
|
|
988
|
+
if (sameAttributes.length) {
|
|
989
|
+
setCustomAttributes((prev) => {
|
|
990
|
+
const removedAttributes = prev.filter(
|
|
991
|
+
(attr) => !sameAttributes.some((a) => a.key === attr.key)
|
|
992
|
+
);
|
|
993
|
+
return [...removedAttributes, ...attributes2];
|
|
994
|
+
});
|
|
995
|
+
} else {
|
|
996
|
+
setCustomAttributes((prev) => [...prev, ...attributes2]);
|
|
997
|
+
}
|
|
998
|
+
},
|
|
999
|
+
[customAttributes]
|
|
1000
|
+
);
|
|
1001
|
+
const functionAutoFreeGiftResult = useCalcAutoFreeGift(cart, autoFreeGiftConfig || [], customer);
|
|
1002
|
+
const scriptAutoFreeGiftResult = useScriptAutoFreeGift({
|
|
1003
|
+
campaign: gradientGiftsConfig || null,
|
|
1004
|
+
_giveaway: CUSTOMER_SCRIPT_GIFT_KEY,
|
|
1005
|
+
cart
|
|
1006
|
+
});
|
|
1007
|
+
const formattedScriptGifts = useMemo(() => {
|
|
1008
|
+
return formatScriptAutoFreeGift({
|
|
1009
|
+
scriptAutoFreeGiftResult,
|
|
1010
|
+
gradient_gifts: gradientGiftsConfig,
|
|
1011
|
+
locale
|
|
1012
|
+
});
|
|
1013
|
+
}, [scriptAutoFreeGiftResult, gradientGiftsConfig, locale]);
|
|
1014
|
+
const formattedFunctionGifts = useMemo(() => {
|
|
1015
|
+
return formatFunctionAutoFreeGift({
|
|
1016
|
+
qualifyingGift: functionAutoFreeGiftResult?.qualifyingGift || null,
|
|
1017
|
+
giftProductsResult: functionAutoFreeGiftResult?.giftProductsResult || [],
|
|
1018
|
+
locale
|
|
1019
|
+
});
|
|
1020
|
+
}, [functionAutoFreeGiftResult, locale]);
|
|
1021
|
+
useEffect(() => {
|
|
1022
|
+
if (loadingState.userCodeApplying || loadingState.editLineQuantityLoading || loadingState.editLineCodeAmountLoading || loadingState.listingAutoCodeApplying) {
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
setScriptAutoFreeGift(formattedScriptGifts);
|
|
1026
|
+
setFunctionAutoFreeGift(formattedFunctionGifts);
|
|
1027
|
+
}, [
|
|
1028
|
+
formattedScriptGifts,
|
|
1029
|
+
formattedFunctionGifts,
|
|
1030
|
+
loadingState.userCodeApplying,
|
|
1031
|
+
loadingState.editLineQuantityLoading,
|
|
1032
|
+
loadingState.editLineCodeAmountLoading,
|
|
1033
|
+
loadingState.listingAutoCodeApplying
|
|
1034
|
+
]);
|
|
1035
|
+
const giftNeedAddToCartLines = useMemo(() => {
|
|
1036
|
+
const cartGiftLineItems = cart?.lineItems.filter(
|
|
1037
|
+
(line) => line.customAttributes?.some(
|
|
1038
|
+
(attr) => [CUSTOMER_ATTRIBUTE_KEY, CUSTOMER_SCRIPT_GIFT_KEY].includes(attr.key)
|
|
1039
|
+
)
|
|
1040
|
+
);
|
|
1041
|
+
const result = [...scriptAutoFreeGift, ...functionAutoFreeGift].filter(
|
|
1042
|
+
(item) => (
|
|
1043
|
+
// 如果购物车中已经存在对应赠品,且标记了 function 满赠的属性,则不添加
|
|
1044
|
+
!cartGiftLineItems?.find((line) => {
|
|
1045
|
+
return line.variantId === item.line.variantId && line.customAttributes?.some((attr) => {
|
|
1046
|
+
if (attr.key === "_discounts_function_env") {
|
|
1047
|
+
return getDiscountEnvAttributeValue(line.customAttributes).is_gift;
|
|
1048
|
+
}
|
|
1049
|
+
return false;
|
|
1050
|
+
});
|
|
1051
|
+
})
|
|
1052
|
+
)
|
|
1053
|
+
);
|
|
1054
|
+
return result;
|
|
1055
|
+
}, [cart?.lineItems, scriptAutoFreeGift, functionAutoFreeGift]);
|
|
1056
|
+
const value = useMemo(
|
|
1057
|
+
() => ({
|
|
1058
|
+
cart,
|
|
1059
|
+
isCartLoading,
|
|
1060
|
+
triggerFetch: fetchCart,
|
|
1061
|
+
mutateCart,
|
|
1062
|
+
addCustomAttributes,
|
|
1063
|
+
removeCustomAttributes,
|
|
1064
|
+
setCustomAttributes,
|
|
1065
|
+
locale,
|
|
1066
|
+
isCodeChanging,
|
|
1067
|
+
setIsCodeChanging,
|
|
1068
|
+
autoFreeGiftConfig,
|
|
1069
|
+
setLoadingState,
|
|
1070
|
+
loadingState,
|
|
1071
|
+
// function满赠
|
|
1072
|
+
functionAutoFreeGift,
|
|
1073
|
+
functionAutoFreeGiftResult,
|
|
1074
|
+
setFunctionAutoFreeGift,
|
|
1075
|
+
// script满赠
|
|
1076
|
+
scriptAutoFreeGift,
|
|
1077
|
+
scriptAutoFreeGiftResult,
|
|
1078
|
+
setScriptAutoFreeGift,
|
|
1079
|
+
giftNeedAddToCartLines,
|
|
1080
|
+
metafieldIdentifiers
|
|
1081
|
+
}),
|
|
1082
|
+
[
|
|
1083
|
+
cart,
|
|
1084
|
+
isCartLoading,
|
|
1085
|
+
fetchCart,
|
|
1086
|
+
mutateCart,
|
|
1087
|
+
addCustomAttributes,
|
|
1088
|
+
removeCustomAttributes,
|
|
1089
|
+
locale,
|
|
1090
|
+
isCodeChanging,
|
|
1091
|
+
autoFreeGiftConfig,
|
|
1092
|
+
loadingState,
|
|
1093
|
+
// function满赠
|
|
1094
|
+
functionAutoFreeGift,
|
|
1095
|
+
functionAutoFreeGiftResult,
|
|
1096
|
+
setFunctionAutoFreeGift,
|
|
1097
|
+
// script满赠
|
|
1098
|
+
scriptAutoFreeGift,
|
|
1099
|
+
scriptAutoFreeGiftResult,
|
|
1100
|
+
setScriptAutoFreeGift,
|
|
1101
|
+
giftNeedAddToCartLines,
|
|
1102
|
+
metafieldIdentifiers
|
|
1103
|
+
]
|
|
1104
|
+
);
|
|
1105
|
+
return /* @__PURE__ */ jsx(CartContext.Provider, { value, children });
|
|
1106
|
+
}
|
|
1107
|
+
function useCartContext() {
|
|
1108
|
+
const context = useContext(CartContext);
|
|
1109
|
+
if (!context) {
|
|
1110
|
+
throw new Error("useCartContext must be used within a CartProvider");
|
|
1111
|
+
}
|
|
1112
|
+
return context;
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
export { CartProvider, ShopifyContext, ShopifyProvider, useCartContext, useShopify };
|
|
1116
|
+
//# sourceMappingURL=index.mjs.map
|
|
1117
|
+
//# sourceMappingURL=index.mjs.map
|