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