@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,2801 @@
|
|
|
1
|
+
import { createContext, useMemo, useRef, useState, useEffect, useCallback, useContext } from 'react';
|
|
2
|
+
import useSWRMutation from 'swr/mutation';
|
|
3
|
+
import { getProductsByHandles, createCart, updateCartCodes, addCartLines, updateCartLines, removeCartLines, updateCartAttributes, getProduct, getAllProducts, getCollection, getAllCollections, getCollections, getBlog, getAllBlogs, getArticle, getArticles, getArticlesInBlog, getLocalStorage, setLocalStorage } from '@anker-in/shopify-sdk';
|
|
4
|
+
import Cookies5 from 'js-cookie';
|
|
5
|
+
import { jsx } from 'react/jsx-runtime';
|
|
6
|
+
import Decimal2 from 'decimal.js';
|
|
7
|
+
import useSWR from 'swr';
|
|
8
|
+
import { useRequest } from 'ahooks';
|
|
9
|
+
|
|
10
|
+
// src/hooks/cart/use-create-cart.ts
|
|
11
|
+
var ShopifyContext = createContext(null);
|
|
12
|
+
function useShopify() {
|
|
13
|
+
const context = useContext(ShopifyContext);
|
|
14
|
+
if (!context) {
|
|
15
|
+
throw new Error("useShopify must be used within a ShopifyProvider");
|
|
16
|
+
}
|
|
17
|
+
return context;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// src/hooks/cart/types/auto-free-gift.ts
|
|
21
|
+
var RuleType = /* @__PURE__ */ ((RuleType2) => {
|
|
22
|
+
RuleType2[RuleType2["AUTO_FREE_GIFT"] = 1] = "AUTO_FREE_GIFT";
|
|
23
|
+
RuleType2[RuleType2["BUNDLE"] = 2] = "BUNDLE";
|
|
24
|
+
RuleType2[RuleType2["VOLUME_DISCOUNT"] = 3] = "VOLUME_DISCOUNT";
|
|
25
|
+
RuleType2[RuleType2["ORDER_DISCOUNT"] = 4] = "ORDER_DISCOUNT";
|
|
26
|
+
RuleType2[RuleType2["PRICE_DISCOUNT"] = 5] = "PRICE_DISCOUNT";
|
|
27
|
+
return RuleType2;
|
|
28
|
+
})(RuleType || {});
|
|
29
|
+
var BuyRuleType = /* @__PURE__ */ ((BuyRuleType2) => {
|
|
30
|
+
BuyRuleType2[BuyRuleType2["BUY_GET_GIFT"] = 1] = "BUY_GET_GIFT";
|
|
31
|
+
BuyRuleType2[BuyRuleType2["SPEND_GET_GIFT"] = 2] = "SPEND_GET_GIFT";
|
|
32
|
+
return BuyRuleType2;
|
|
33
|
+
})(BuyRuleType || {});
|
|
34
|
+
var SpendMoneyType = /* @__PURE__ */ ((SpendMoneyType2) => {
|
|
35
|
+
SpendMoneyType2[SpendMoneyType2["ORIGIN_PRICE"] = 1] = "ORIGIN_PRICE";
|
|
36
|
+
SpendMoneyType2[SpendMoneyType2["DISCOUNT_PRICE"] = 2] = "DISCOUNT_PRICE";
|
|
37
|
+
return SpendMoneyType2;
|
|
38
|
+
})(SpendMoneyType || {});
|
|
39
|
+
|
|
40
|
+
// src/hooks/cart/const.ts
|
|
41
|
+
var currencyCodeMapping = {
|
|
42
|
+
us: "USD",
|
|
43
|
+
ca: "CAD",
|
|
44
|
+
gb: "GBP",
|
|
45
|
+
eu: "EUR",
|
|
46
|
+
au: "AUD",
|
|
47
|
+
nz: "NZD",
|
|
48
|
+
de: "EUR",
|
|
49
|
+
fr: "EUR",
|
|
50
|
+
es: "EUR",
|
|
51
|
+
it: "EUR",
|
|
52
|
+
nl: "EUR",
|
|
53
|
+
pl: "EUR",
|
|
54
|
+
ro: "EUR"
|
|
55
|
+
};
|
|
56
|
+
var defaultSWRMutationConfiguration = {
|
|
57
|
+
throwOnError: false
|
|
58
|
+
};
|
|
59
|
+
var CUSTOMER_ATTRIBUTE_KEY = "_discounts_function_env";
|
|
60
|
+
var CUSTOMER_SCRIPT_GIFT_KEY = "_giveaway_gradient_gifts";
|
|
61
|
+
var CODE_AMOUNT_KEY = "_sku_code_money";
|
|
62
|
+
var SCRIPT_CODE_AMOUNT_KEY = "_code_money";
|
|
63
|
+
var MAIN_PRODUCT_CODE = ["WS24", "WSTD", "WS7D", "WSCP", "WSPE", "WSPD"];
|
|
64
|
+
|
|
65
|
+
// src/hooks/cart/utils/index.ts
|
|
66
|
+
var getQuery = () => {
|
|
67
|
+
const url = typeof window !== "undefined" ? window.location.search : "";
|
|
68
|
+
const theRequest = {};
|
|
69
|
+
if (url.indexOf("?") != -1) {
|
|
70
|
+
const str = url.substr(1), strs = str.split("&");
|
|
71
|
+
for (let i = 0; i < strs.length; i++) {
|
|
72
|
+
const parts = strs[i]?.split("=");
|
|
73
|
+
const key = parts?.[0];
|
|
74
|
+
const value = parts?.[1];
|
|
75
|
+
if (key && value) {
|
|
76
|
+
theRequest[key] = decodeURIComponent(value);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return theRequest;
|
|
81
|
+
};
|
|
82
|
+
function atobID(id) {
|
|
83
|
+
if (id && typeof id === "string" && id.includes("/")) {
|
|
84
|
+
return id.split("/").pop()?.split("?")?.shift();
|
|
85
|
+
} else {
|
|
86
|
+
return id;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function btoaID(id, type = "ProductVariant") {
|
|
90
|
+
return `gid://shopify/${type}/${id}`;
|
|
91
|
+
}
|
|
92
|
+
var getMatchedMainProductSubTotal = (cartData, variant_list, main_product) => {
|
|
93
|
+
const isAllStoreVariant = main_product?.all_store_variant ?? false;
|
|
94
|
+
const matchedList = cartData?.lineItems?.filter((line) => {
|
|
95
|
+
const { is_gift } = getDiscountEnvAttributeValue(line.customAttributes);
|
|
96
|
+
return isAllStoreVariant ? !is_gift : variant_list?.find((item) => {
|
|
97
|
+
return !is_gift && atobID(line.variantId) === item;
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
return matchedList?.reduce((acc, line) => {
|
|
101
|
+
return acc + (main_product?.spend_money_type === 1 /* ORIGIN_PRICE */ ? Number(line.subtotalAmount) || 0 : Number(line.totalAmount) || 0);
|
|
102
|
+
}, 0) || 0;
|
|
103
|
+
};
|
|
104
|
+
var getDiscountEnvAttributeValue = (attributes = []) => {
|
|
105
|
+
const attr = attributes.find((attr2) => attr2.key === CUSTOMER_ATTRIBUTE_KEY);
|
|
106
|
+
return safeParseJson(attr?.value ?? "") ?? {};
|
|
107
|
+
};
|
|
108
|
+
var isAttributesEqual = (attrs1 = [], attrs2 = []) => {
|
|
109
|
+
if (attrs1.length !== attrs2.length) return false;
|
|
110
|
+
const sorted1 = [...attrs1].sort((a, b) => a.key.localeCompare(b.key));
|
|
111
|
+
const sorted2 = [...attrs2].sort((a, b) => a.key.localeCompare(b.key));
|
|
112
|
+
return sorted1.every(
|
|
113
|
+
(attr, i) => attr.key === sorted2[i]?.key && attr.value === sorted2[i]?.value
|
|
114
|
+
);
|
|
115
|
+
};
|
|
116
|
+
var safeParseJson = (str) => {
|
|
117
|
+
try {
|
|
118
|
+
return JSON.parse(str);
|
|
119
|
+
} catch (err) {
|
|
120
|
+
return {};
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
var containsAll = (source, requiredItems = []) => {
|
|
124
|
+
if (!requiredItems?.length) return true;
|
|
125
|
+
const sourceSet = new Set(source);
|
|
126
|
+
return requiredItems.every((item) => sourceSet.has(item));
|
|
127
|
+
};
|
|
128
|
+
var containsNone = (source, forbiddenItems = []) => {
|
|
129
|
+
if (!forbiddenItems?.length) return true;
|
|
130
|
+
const sourceSet = new Set(source);
|
|
131
|
+
return !forbiddenItems.some((item) => sourceSet.has(item));
|
|
132
|
+
};
|
|
133
|
+
function preCheck(rule_conditions, userTags, currentDealsTypes) {
|
|
134
|
+
if (!Array.isArray(rule_conditions)) return false;
|
|
135
|
+
if (rule_conditions.length === 0) return true;
|
|
136
|
+
return rule_conditions.some((rule) => {
|
|
137
|
+
const tagsAreValid = containsAll(userTags, rule.with_user_tags) && containsNone(userTags, rule.without_user_tags);
|
|
138
|
+
const paramsAreValid = containsAll(currentDealsTypes, rule.with_special_url_params) && containsNone(currentDealsTypes, rule.without_special_url_params);
|
|
139
|
+
return tagsAreValid && paramsAreValid;
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
var formatScriptAutoFreeGiftCache = null;
|
|
143
|
+
var formatScriptAutoFreeGift = ({
|
|
144
|
+
scriptAutoFreeGiftResult,
|
|
145
|
+
gradient_gifts,
|
|
146
|
+
locale
|
|
147
|
+
}) => {
|
|
148
|
+
const cacheKey = JSON.stringify({
|
|
149
|
+
freeGiftLevel: scriptAutoFreeGiftResult?.freeGiftLevel ? {
|
|
150
|
+
items: scriptAutoFreeGiftResult.freeGiftLevel.giveawayProducts?.map((item) => ({
|
|
151
|
+
handle: item.handle,
|
|
152
|
+
sku: item.sku,
|
|
153
|
+
quantity: 1
|
|
154
|
+
})) || []
|
|
155
|
+
} : null,
|
|
156
|
+
giftProductsLength: scriptAutoFreeGiftResult?.giftProductsResult?.length || 0,
|
|
157
|
+
giftProductsIds: scriptAutoFreeGiftResult?.giftProductsResult?.map((p) => p.id).sort() || [],
|
|
158
|
+
gradientGiftsId: gradient_gifts?.id || gradient_gifts?.name || "",
|
|
159
|
+
locale
|
|
160
|
+
});
|
|
161
|
+
if (formatScriptAutoFreeGiftCache && formatScriptAutoFreeGiftCache.key === cacheKey) {
|
|
162
|
+
return formatScriptAutoFreeGiftCache.result;
|
|
163
|
+
}
|
|
164
|
+
const result = scriptAutoFreeGiftResult?.freeGiftLevel?.giveawayProducts?.filter(
|
|
165
|
+
(item) => scriptAutoFreeGiftResult?.giftProductsResult?.some(
|
|
166
|
+
(product) => product.handle === item.handle
|
|
167
|
+
)
|
|
168
|
+
).map((item, index) => {
|
|
169
|
+
const product = scriptAutoFreeGiftResult?.giftProductsResult?.find(
|
|
170
|
+
(product2) => product2.handle === item.handle
|
|
171
|
+
);
|
|
172
|
+
const variants = product?.variants;
|
|
173
|
+
const variant = Array.isArray(variants) ? variants.find((v) => v.sku === item.sku) : void 0;
|
|
174
|
+
const query = getQuery();
|
|
175
|
+
const utmCampaign = Cookies5.get("utm_campaign") || query?.utm_campaign;
|
|
176
|
+
const addUTMFreeItem = gradient_gifts.activityAvailableQuery && utmCampaign?.includes(gradient_gifts.activityAvailableQuery);
|
|
177
|
+
let points_subscribe = false;
|
|
178
|
+
if (locale === "au") {
|
|
179
|
+
const isPointsSubscribe = Cookies5.get("points_subscribe");
|
|
180
|
+
points_subscribe = !!isPointsSubscribe;
|
|
181
|
+
}
|
|
182
|
+
const customAttributes = [
|
|
183
|
+
{
|
|
184
|
+
key: "_giveaway_gradient_gifts",
|
|
185
|
+
value: "_giveaway_gradient_gifts"
|
|
186
|
+
},
|
|
187
|
+
...points_subscribe ? [
|
|
188
|
+
{ key: "_amount_upgrade_multiple", value: "1.2" },
|
|
189
|
+
{ key: "_amount_upgrade_value", value: "40" }
|
|
190
|
+
] : [],
|
|
191
|
+
...addUTMFreeItem && gradient_gifts?.activityQroperty ? [
|
|
192
|
+
{
|
|
193
|
+
key: gradient_gifts.activityQroperty,
|
|
194
|
+
value: gradient_gifts.activityQroperty
|
|
195
|
+
}
|
|
196
|
+
] : []
|
|
197
|
+
];
|
|
198
|
+
const line = {
|
|
199
|
+
id: product?.id + "_" + index,
|
|
200
|
+
variantId: String(variant?.id),
|
|
201
|
+
productId: String(product?.id),
|
|
202
|
+
name: product?.name || product?.title || "",
|
|
203
|
+
quantity: 1,
|
|
204
|
+
discounts: [],
|
|
205
|
+
path: product?.handle || "",
|
|
206
|
+
variant,
|
|
207
|
+
totalAmount: 0,
|
|
208
|
+
subtotalAmount: new Decimal2(
|
|
209
|
+
typeof variant?.price === "object" ? variant?.price?.amount || 0 : variant?.price || 0
|
|
210
|
+
).toNumber(),
|
|
211
|
+
options: [],
|
|
212
|
+
discountAllocations: [],
|
|
213
|
+
product,
|
|
214
|
+
customAttributes,
|
|
215
|
+
freeGiftVariant: void 0,
|
|
216
|
+
relatedVariant: void 0
|
|
217
|
+
};
|
|
218
|
+
return {
|
|
219
|
+
line,
|
|
220
|
+
isSoldOut: !variant?.availableForSale
|
|
221
|
+
};
|
|
222
|
+
}) || [];
|
|
223
|
+
formatScriptAutoFreeGiftCache = {
|
|
224
|
+
key: cacheKey,
|
|
225
|
+
result
|
|
226
|
+
};
|
|
227
|
+
return result;
|
|
228
|
+
};
|
|
229
|
+
var formatFunctionAutoFreeGiftCache = null;
|
|
230
|
+
var formatFunctionAutoFreeGift = ({
|
|
231
|
+
qualifyingGift,
|
|
232
|
+
giftProductsResult,
|
|
233
|
+
locale
|
|
234
|
+
}) => {
|
|
235
|
+
const cacheKey = JSON.stringify({
|
|
236
|
+
qualifyingGift: qualifyingGift ? {
|
|
237
|
+
spend: qualifyingGift.tier?.spend_sum_money,
|
|
238
|
+
items: qualifyingGift.itemsToAdd?.map((item) => ({
|
|
239
|
+
variantId: item.variant.id,
|
|
240
|
+
handle: item.variant.handle,
|
|
241
|
+
sku: item.variant.sku,
|
|
242
|
+
quantity: item.quantity ?? 1,
|
|
243
|
+
attributes: item.attributes
|
|
244
|
+
})) || []
|
|
245
|
+
} : null,
|
|
246
|
+
giftProductsLength: giftProductsResult?.length || 0,
|
|
247
|
+
giftProductsIds: giftProductsResult?.map((p) => p.id).sort() || [],
|
|
248
|
+
locale
|
|
249
|
+
});
|
|
250
|
+
if (formatFunctionAutoFreeGiftCache && formatFunctionAutoFreeGiftCache.key === cacheKey) {
|
|
251
|
+
return formatFunctionAutoFreeGiftCache.result;
|
|
252
|
+
}
|
|
253
|
+
const result = qualifyingGift?.itemsToAdd?.map((item, index) => {
|
|
254
|
+
const product = giftProductsResult?.find((product2) => product2.handle === item.variant.handle);
|
|
255
|
+
const variants = product?.variants;
|
|
256
|
+
const variant = Array.isArray(variants) ? variants.find((v) => v.sku === item.variant.sku) : void 0;
|
|
257
|
+
console.log("qualifyingGift variant", product, variant);
|
|
258
|
+
const line = {
|
|
259
|
+
id: product?.id + "_" + index,
|
|
260
|
+
variantId: String(variant?.id),
|
|
261
|
+
productId: String(product?.id),
|
|
262
|
+
name: product?.name || product?.title || "",
|
|
263
|
+
quantity: 1,
|
|
264
|
+
discounts: [],
|
|
265
|
+
path: product?.handle || "",
|
|
266
|
+
variant,
|
|
267
|
+
totalAmount: 0,
|
|
268
|
+
subtotalAmount: new Decimal2(
|
|
269
|
+
typeof variant?.price === "object" ? variant?.price?.amount || 0 : variant?.price || 0
|
|
270
|
+
).toNumber(),
|
|
271
|
+
options: [],
|
|
272
|
+
discountAllocations: [],
|
|
273
|
+
product,
|
|
274
|
+
customAttributes: item.attributes,
|
|
275
|
+
freeGiftVariant: void 0,
|
|
276
|
+
relatedVariant: void 0
|
|
277
|
+
};
|
|
278
|
+
return {
|
|
279
|
+
line,
|
|
280
|
+
isSoldOut: !variant?.availableForSale
|
|
281
|
+
};
|
|
282
|
+
}) || [];
|
|
283
|
+
formatFunctionAutoFreeGiftCache = {
|
|
284
|
+
key: cacheKey,
|
|
285
|
+
result
|
|
286
|
+
};
|
|
287
|
+
return result;
|
|
288
|
+
};
|
|
289
|
+
var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
|
|
290
|
+
const tags = useMemo(() => customer?.tags || [], [customer?.tags]);
|
|
291
|
+
const isCustomerLoading = useMemo(() => !customer ? true : false, [customer]);
|
|
292
|
+
const dealsType = "";
|
|
293
|
+
const { client, locale } = useShopify();
|
|
294
|
+
const giftProductsCache = useRef(null);
|
|
295
|
+
const { activeCampaign, subtotal } = useMemo(() => {
|
|
296
|
+
for (const campaign of autoFreeGiftConfig) {
|
|
297
|
+
const { rule_conditions = [], rule_result } = campaign;
|
|
298
|
+
const { spend_get_reward } = rule_result || {};
|
|
299
|
+
const isPreCheckPassed = preCheck(rule_conditions, tags, []);
|
|
300
|
+
if (isPreCheckPassed && spend_get_reward) {
|
|
301
|
+
const matchedSubtotal = getMatchedMainProductSubTotal(
|
|
302
|
+
cart,
|
|
303
|
+
spend_get_reward.main_product?.variant_list?.map((v) => v.variant_id) || [],
|
|
304
|
+
{
|
|
305
|
+
spend_money_type: spend_get_reward.main_product?.spend_money_type || 1,
|
|
306
|
+
variant_id_list: spend_get_reward.main_product?.variant_list?.map((v) => v.variant_id) || [],
|
|
307
|
+
all_store_variant: spend_get_reward.main_product?.all_store_variant || false
|
|
308
|
+
}
|
|
309
|
+
);
|
|
310
|
+
if (matchedSubtotal > 0) {
|
|
311
|
+
return { activeCampaign: campaign, subtotal: matchedSubtotal };
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
return { activeCampaign: null, subtotal: 0 };
|
|
316
|
+
}, [autoFreeGiftConfig, cart, tags, dealsType]);
|
|
317
|
+
const { qualifyingGift, nextTierGoal } = useMemo(() => {
|
|
318
|
+
if (!activeCampaign || !activeCampaign.rule_result?.spend_get_reward?.gift_product) {
|
|
319
|
+
return { qualifyingGift: null, nextTierGoal: null };
|
|
320
|
+
}
|
|
321
|
+
const giftTiers = activeCampaign.rule_result.spend_get_reward.gift_product;
|
|
322
|
+
const qualifyingTier = [...giftTiers].reverse().find((tier) => subtotal >= Number(tier.spend_sum_money));
|
|
323
|
+
const nextGoal = giftTiers.find((tier) => subtotal < Number(tier.spend_sum_money));
|
|
324
|
+
if (!qualifyingTier) {
|
|
325
|
+
return { qualifyingGift: null, nextTierGoal: nextGoal || null };
|
|
326
|
+
}
|
|
327
|
+
const formattedGift = {
|
|
328
|
+
tier: qualifyingTier,
|
|
329
|
+
itemsToAdd: qualifyingTier.reward_list?.map((reward) => {
|
|
330
|
+
const giftProduct = reward?.variant_list?.[0];
|
|
331
|
+
if (!giftProduct) return null;
|
|
332
|
+
return {
|
|
333
|
+
variant: {
|
|
334
|
+
id: btoaID(giftProduct.variant_id),
|
|
335
|
+
handle: giftProduct.handle,
|
|
336
|
+
sku: giftProduct.sku
|
|
337
|
+
},
|
|
338
|
+
quantity: reward?.get_unit || 1,
|
|
339
|
+
attributes: [
|
|
340
|
+
{
|
|
341
|
+
key: CUSTOMER_ATTRIBUTE_KEY,
|
|
342
|
+
value: JSON.stringify({
|
|
343
|
+
is_gift: true,
|
|
344
|
+
rule_id: activeCampaign.rule_id,
|
|
345
|
+
spend_sum_money: qualifyingTier.spend_sum_money
|
|
346
|
+
})
|
|
347
|
+
}
|
|
348
|
+
]
|
|
349
|
+
};
|
|
350
|
+
}).filter((item) => item !== null)
|
|
351
|
+
};
|
|
352
|
+
return { qualifyingGift: formattedGift, nextTierGoal: nextGoal || null };
|
|
353
|
+
}, [activeCampaign, subtotal]);
|
|
354
|
+
const giftHandles = useMemo(() => {
|
|
355
|
+
const giftVariant = autoFreeGiftConfig.map(
|
|
356
|
+
(item) => item.rule_result?.spend_get_reward?.gift_product?.map(
|
|
357
|
+
(v) => v.reward_list.map((reward) => reward.variant_list.map((variant) => variant.handle))
|
|
358
|
+
).flat()
|
|
359
|
+
).flat();
|
|
360
|
+
return giftVariant.flat(2).filter(Boolean);
|
|
361
|
+
}, [autoFreeGiftConfig]);
|
|
362
|
+
const shouldFetch = useMemo(() => {
|
|
363
|
+
if (!giftHandles.length) return false;
|
|
364
|
+
if (giftProductsCache.current && JSON.stringify(giftProductsCache.current.giftHandles) === JSON.stringify(giftHandles)) {
|
|
365
|
+
return false;
|
|
366
|
+
}
|
|
367
|
+
return true;
|
|
368
|
+
}, [giftHandles]);
|
|
369
|
+
const { data: giftProductsResult } = useSWR(shouldFetch ? giftHandles : null, async () => {
|
|
370
|
+
const res = await getProductsByHandles(client, {
|
|
371
|
+
handles: giftHandles,
|
|
372
|
+
locale
|
|
373
|
+
});
|
|
374
|
+
const result = Array.isArray(res) ? res : [];
|
|
375
|
+
giftProductsCache.current = {
|
|
376
|
+
data: result,
|
|
377
|
+
giftHandles: [...giftHandles]
|
|
378
|
+
};
|
|
379
|
+
return result;
|
|
380
|
+
});
|
|
381
|
+
const finalGiftProductsResult = useMemo(() => {
|
|
382
|
+
if (giftProductsCache.current && !shouldFetch) {
|
|
383
|
+
return giftProductsCache.current.data || void 0;
|
|
384
|
+
}
|
|
385
|
+
return giftProductsResult;
|
|
386
|
+
}, [giftProductsResult, shouldFetch]);
|
|
387
|
+
return {
|
|
388
|
+
qualifyingGift,
|
|
389
|
+
nextTierGoal,
|
|
390
|
+
activeCampaign,
|
|
391
|
+
isLoading: isCustomerLoading,
|
|
392
|
+
giftProductsResult: finalGiftProductsResult
|
|
393
|
+
};
|
|
394
|
+
};
|
|
395
|
+
var useScriptAutoFreeGift = ({
|
|
396
|
+
campaign,
|
|
397
|
+
_giveaway,
|
|
398
|
+
cart,
|
|
399
|
+
locale: providedLocale
|
|
400
|
+
}) => {
|
|
401
|
+
const { client, locale: contextLocale } = useShopify();
|
|
402
|
+
const locale = providedLocale || contextLocale;
|
|
403
|
+
const [points_subscribe, set_points_subscribe] = useState(false);
|
|
404
|
+
const giftProductsCache = useRef(null);
|
|
405
|
+
useEffect(() => {
|
|
406
|
+
if (locale === "au") {
|
|
407
|
+
const isPointsSubscribe = Cookies5.get("points_subscribe");
|
|
408
|
+
set_points_subscribe(!!isPointsSubscribe);
|
|
409
|
+
}
|
|
410
|
+
}, [locale]);
|
|
411
|
+
const [upgrade_multiple, upgrade_value] = useMemo(() => {
|
|
412
|
+
let upgrade_multiple2 = 1;
|
|
413
|
+
let upgrade_value2 = 0;
|
|
414
|
+
if (points_subscribe) {
|
|
415
|
+
upgrade_multiple2 = 1.2;
|
|
416
|
+
upgrade_value2 = 40;
|
|
417
|
+
}
|
|
418
|
+
cart?.lineItems?.forEach(({ customAttributes }) => {
|
|
419
|
+
customAttributes?.forEach(({ key, value }) => {
|
|
420
|
+
if (key === "_amount_upgrade_multiple") upgrade_multiple2 = Number(value) || 1;
|
|
421
|
+
if (key === "_amount_upgrade_value") upgrade_value2 = Number(value) || 0;
|
|
422
|
+
});
|
|
423
|
+
});
|
|
424
|
+
return [upgrade_multiple2, upgrade_value2];
|
|
425
|
+
}, [cart?.lineItems, points_subscribe]);
|
|
426
|
+
const breakpoints = useMemo(() => {
|
|
427
|
+
if (!campaign) return [];
|
|
428
|
+
return (campaign.breakpoints || []).map((item) => ({
|
|
429
|
+
breakpoint: new Decimal2(item.breakpoint).minus(new Decimal2(upgrade_value)).dividedBy(new Decimal2(upgrade_multiple)).toFixed(2, Decimal2.ROUND_DOWN),
|
|
430
|
+
giveawayProducts: item.giveawayProducts || []
|
|
431
|
+
}));
|
|
432
|
+
}, [campaign, upgrade_multiple, upgrade_value]);
|
|
433
|
+
const giftHandles = useMemo(
|
|
434
|
+
() => (
|
|
435
|
+
// 使用 Set 去重,然后拼接字符串
|
|
436
|
+
[
|
|
437
|
+
...new Set(
|
|
438
|
+
breakpoints.flatMap((b) => b.giveawayProducts.map((p) => p.handle)).filter(Boolean)
|
|
439
|
+
)
|
|
440
|
+
]
|
|
441
|
+
),
|
|
442
|
+
[breakpoints]
|
|
443
|
+
);
|
|
444
|
+
const shouldFetch = useMemo(() => {
|
|
445
|
+
if (!giftHandles.length) return false;
|
|
446
|
+
if (giftProductsCache.current && JSON.stringify(giftProductsCache.current.giftHandles) === JSON.stringify(giftHandles)) {
|
|
447
|
+
return false;
|
|
448
|
+
}
|
|
449
|
+
return true;
|
|
450
|
+
}, [giftHandles]);
|
|
451
|
+
const involvedLines = useMemo(() => {
|
|
452
|
+
if (!campaign) return [];
|
|
453
|
+
return (cart?.lineItems || []).filter((line) => {
|
|
454
|
+
const isNotGift = line?.totalAmount && Number(line.totalAmount) > 0 && line.customAttributes?.every(
|
|
455
|
+
(item) => item.key !== _giveaway
|
|
456
|
+
);
|
|
457
|
+
const hasCampaignTag = line.product?.tags?.some(
|
|
458
|
+
(tag) => campaign.includeTags?.includes(tag.trim()) && line.variant?.availableForSale
|
|
459
|
+
);
|
|
460
|
+
return isNotGift && hasCampaignTag;
|
|
461
|
+
});
|
|
462
|
+
}, [cart?.lineItems, campaign, _giveaway]);
|
|
463
|
+
const involvedSubTotal = useMemo(() => {
|
|
464
|
+
if (!campaign) return new Decimal2(0);
|
|
465
|
+
return involvedLines.reduce((prev, item) => {
|
|
466
|
+
const amount = campaign.useTotalAmount ? item.totalAmount : item.subtotalAmount;
|
|
467
|
+
return new Decimal2(prev).plus(new Decimal2(amount || 0));
|
|
468
|
+
}, new Decimal2(0));
|
|
469
|
+
}, [involvedLines, campaign]);
|
|
470
|
+
const [freeGiftLevel, nextFreeGiftLevel] = useMemo(() => {
|
|
471
|
+
const sortedLevels = [...breakpoints].sort(
|
|
472
|
+
(a, b) => Number(b.breakpoint) - Number(a.breakpoint)
|
|
473
|
+
);
|
|
474
|
+
const levelIndex = sortedLevels.findIndex(
|
|
475
|
+
(level) => involvedSubTotal.gte(new Decimal2(level.breakpoint)) && involvedLines.length > 0
|
|
476
|
+
);
|
|
477
|
+
if (levelIndex === -1) {
|
|
478
|
+
return [
|
|
479
|
+
null,
|
|
480
|
+
sortedLevels.length > 0 ? sortedLevels[sortedLevels.length - 1] ?? null : null
|
|
481
|
+
];
|
|
482
|
+
}
|
|
483
|
+
const currentLevel = sortedLevels[levelIndex] ?? null;
|
|
484
|
+
const nextLevel = levelIndex > 0 ? sortedLevels[levelIndex - 1] ?? null : null;
|
|
485
|
+
return [currentLevel, nextLevel];
|
|
486
|
+
}, [breakpoints, involvedSubTotal, involvedLines.length]);
|
|
487
|
+
const { data: giftProductsResult } = useSWR(shouldFetch ? giftHandles : null, async () => {
|
|
488
|
+
const res = await getProductsByHandles(client, {
|
|
489
|
+
handles: giftHandles,
|
|
490
|
+
locale
|
|
491
|
+
});
|
|
492
|
+
const result = Array.isArray(res) ? res : [];
|
|
493
|
+
giftProductsCache.current = {
|
|
494
|
+
data: result,
|
|
495
|
+
giftHandles: [...giftHandles]
|
|
496
|
+
};
|
|
497
|
+
return result;
|
|
498
|
+
});
|
|
499
|
+
const finalGiftProductsResult = useMemo(() => {
|
|
500
|
+
if (giftProductsCache.current && !shouldFetch) {
|
|
501
|
+
return giftProductsCache.current.data || void 0;
|
|
502
|
+
}
|
|
503
|
+
return giftProductsResult;
|
|
504
|
+
}, [giftProductsResult, shouldFetch]);
|
|
505
|
+
const reorder = useCallback(
|
|
506
|
+
(a, b) => {
|
|
507
|
+
const getPriority = (item) => {
|
|
508
|
+
if (item.customAttributes?.some(
|
|
509
|
+
(attribute) => attribute.key === _giveaway
|
|
510
|
+
))
|
|
511
|
+
return 0;
|
|
512
|
+
if (item.product?.tags?.some((tag) => campaign?.includeTags?.includes(tag)))
|
|
513
|
+
return 1;
|
|
514
|
+
return 2;
|
|
515
|
+
};
|
|
516
|
+
return getPriority(b) - getPriority(a);
|
|
517
|
+
},
|
|
518
|
+
[campaign?.includeTags, _giveaway]
|
|
519
|
+
);
|
|
520
|
+
return {
|
|
521
|
+
involvedLines,
|
|
522
|
+
reorder,
|
|
523
|
+
disableCodeRemove: involvedLines.length > 0,
|
|
524
|
+
nextFreeGiftLevel,
|
|
525
|
+
freeGiftLevel,
|
|
526
|
+
involvedSubTotal,
|
|
527
|
+
giftProductsResult: finalGiftProductsResult
|
|
528
|
+
};
|
|
529
|
+
};
|
|
530
|
+
var CartContext = createContext(null);
|
|
531
|
+
function useCartContext() {
|
|
532
|
+
const context = useContext(CartContext);
|
|
533
|
+
if (!context) {
|
|
534
|
+
throw new Error("useCartContext must be used within a CartProvider");
|
|
535
|
+
}
|
|
536
|
+
return context;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// src/hooks/cart/use-create-cart.ts
|
|
540
|
+
function useCreateCart(options) {
|
|
541
|
+
const { client, locale, cartCookieAdapter } = useShopify();
|
|
542
|
+
const { mutateCart, metafieldIdentifiers } = useCartContext();
|
|
543
|
+
const createNewCart = useCallback(
|
|
544
|
+
async (_key, { arg }) => {
|
|
545
|
+
let newCart = await createCart(client, {
|
|
546
|
+
...arg,
|
|
547
|
+
metafieldIdentifiers,
|
|
548
|
+
cookieAdapter: cartCookieAdapter
|
|
549
|
+
});
|
|
550
|
+
if (newCart) {
|
|
551
|
+
const unApplicableCodes = newCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
|
|
552
|
+
if (unApplicableCodes.length > 0) {
|
|
553
|
+
newCart = await updateCartCodes(client, {
|
|
554
|
+
cartId: newCart.id,
|
|
555
|
+
discountCodes: newCart.discountCodes.filter((item) => item.applicable).map((item) => item.code),
|
|
556
|
+
metafieldIdentifiers,
|
|
557
|
+
cookieAdapter: cartCookieAdapter
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
if (newCart) {
|
|
562
|
+
mutateCart(newCart);
|
|
563
|
+
}
|
|
564
|
+
return newCart;
|
|
565
|
+
},
|
|
566
|
+
[client, locale, cartCookieAdapter, mutateCart, metafieldIdentifiers]
|
|
567
|
+
);
|
|
568
|
+
return useSWRMutation("create-cart", createNewCart, options);
|
|
569
|
+
}
|
|
570
|
+
function useAddCartLines(options) {
|
|
571
|
+
const { client, locale, cartCookieAdapter } = useShopify();
|
|
572
|
+
const { mutateCart, metafieldIdentifiers } = useCartContext();
|
|
573
|
+
const addLines = useCallback(
|
|
574
|
+
async (_key, { arg }) => {
|
|
575
|
+
let updatedCart = await addCartLines(client, {
|
|
576
|
+
...arg,
|
|
577
|
+
metafieldIdentifiers,
|
|
578
|
+
cookieAdapter: cartCookieAdapter
|
|
579
|
+
});
|
|
580
|
+
if (updatedCart) {
|
|
581
|
+
const unApplicableCodes = updatedCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
|
|
582
|
+
if (unApplicableCodes.length > 0) {
|
|
583
|
+
updatedCart = await updateCartCodes(client, {
|
|
584
|
+
cartId: updatedCart.id,
|
|
585
|
+
discountCodes: updatedCart.discountCodes.filter((item) => item.applicable).map((item) => item.code),
|
|
586
|
+
metafieldIdentifiers,
|
|
587
|
+
cookieAdapter: cartCookieAdapter
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
if (updatedCart) {
|
|
592
|
+
mutateCart(updatedCart);
|
|
593
|
+
}
|
|
594
|
+
return updatedCart;
|
|
595
|
+
},
|
|
596
|
+
[client, locale, cartCookieAdapter, mutateCart, metafieldIdentifiers]
|
|
597
|
+
);
|
|
598
|
+
return useSWRMutation("add-cart-lines", addLines, options);
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
// src/tracking/ga.ts
|
|
602
|
+
var gaTrack = (data) => {
|
|
603
|
+
if (typeof window === "undefined") {
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
window.dataLayer = window?.dataLayer || [];
|
|
607
|
+
if (!Array.isArray(window.dataLayer)) {
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
try {
|
|
611
|
+
window?.dataLayer?.push({ event_parameters: null });
|
|
612
|
+
window?.dataLayer?.push(data || {});
|
|
613
|
+
} catch (error) {
|
|
614
|
+
console.error("GA tracking error:", error);
|
|
615
|
+
}
|
|
616
|
+
};
|
|
617
|
+
var trackAddToCartGA = ({
|
|
618
|
+
lineItems = [],
|
|
619
|
+
gtmParams = {},
|
|
620
|
+
brand
|
|
621
|
+
}) => {
|
|
622
|
+
if (!lineItems.length || !lineItems[0]?.variant) {
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
const { variant } = lineItems[0];
|
|
626
|
+
const currencyCode = variant?.price?.currencyCode;
|
|
627
|
+
const totalPrice = lineItems.reduce((sum, item) => {
|
|
628
|
+
const price = parseFloat(item.variant?.price?.amount || "0");
|
|
629
|
+
return sum + price;
|
|
630
|
+
}, 0);
|
|
631
|
+
gaTrack({
|
|
632
|
+
event: "ga4Event",
|
|
633
|
+
event_name: "add_to_cart",
|
|
634
|
+
event_parameters: {
|
|
635
|
+
page_group: gtmParams?.pageGroup,
|
|
636
|
+
currency: currencyCode,
|
|
637
|
+
value: totalPrice,
|
|
638
|
+
position: gtmParams?.position || "",
|
|
639
|
+
items: lineItems.map(({ variant: variant2, quantity }) => ({
|
|
640
|
+
item_id: variant2?.sku,
|
|
641
|
+
item_name: variant2?.product?.title || variant2?.product?.name,
|
|
642
|
+
item_brand: brand || gtmParams?.brand || "",
|
|
643
|
+
item_category: variant2?.product?.productType || "",
|
|
644
|
+
item_variant: variant2?.title || variant2?.name,
|
|
645
|
+
price: variant2?.finalPrice?.amount ?? variant2?.price?.amount,
|
|
646
|
+
quantity: quantity || 1
|
|
647
|
+
})),
|
|
648
|
+
...gtmParams?.ga4Params
|
|
649
|
+
}
|
|
650
|
+
});
|
|
651
|
+
};
|
|
652
|
+
var trackBuyNowGA = ({
|
|
653
|
+
lineItems = [],
|
|
654
|
+
gtmParams = {},
|
|
655
|
+
brand
|
|
656
|
+
}) => {
|
|
657
|
+
if (!lineItems.length || !lineItems[0]?.variant) {
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
const { variant } = lineItems[0];
|
|
661
|
+
const currencyCode = variant.price?.currencyCode;
|
|
662
|
+
const totalPrice = lineItems.reduce((sum, item) => {
|
|
663
|
+
const price = parseFloat(item.finalPrice?.amount || item.variant?.price?.amount || "0");
|
|
664
|
+
const quantity = item.quantity || 1;
|
|
665
|
+
return sum + price * quantity;
|
|
666
|
+
}, 0);
|
|
667
|
+
gaTrack({
|
|
668
|
+
event: "ga4Event",
|
|
669
|
+
event_name: "begin_checkout",
|
|
670
|
+
event_parameters: {
|
|
671
|
+
page_group: gtmParams?.pageGroup,
|
|
672
|
+
position: gtmParams?.position,
|
|
673
|
+
currency: currencyCode,
|
|
674
|
+
value: totalPrice,
|
|
675
|
+
items: lineItems.map((item) => ({
|
|
676
|
+
item_id: item.variant?.sku,
|
|
677
|
+
item_name: item.variant?.product?.title || item.variant?.title,
|
|
678
|
+
item_brand: item.variant?.product?.vendor || brand || gtmParams?.brand || "",
|
|
679
|
+
item_category: item.variant?.product?.productType || "",
|
|
680
|
+
item_variant: item.variant?.title,
|
|
681
|
+
price: item.finalPrice?.amount || item.variant?.price?.amount,
|
|
682
|
+
quantity: item.quantity || 1
|
|
683
|
+
})),
|
|
684
|
+
...gtmParams?.ga4Params
|
|
685
|
+
}
|
|
686
|
+
});
|
|
687
|
+
};
|
|
688
|
+
|
|
689
|
+
// src/tracking/fbq.ts
|
|
690
|
+
var trackAddToCartFBQ = ({ lineItems = [] }) => {
|
|
691
|
+
if (typeof window === "undefined" || !window.fbq) {
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
if (lineItems.length && lineItems[0]?.variant) {
|
|
695
|
+
const { variant, quantity, finalPrice } = lineItems[0];
|
|
696
|
+
try {
|
|
697
|
+
window.fbq("track", "AddToCart", {
|
|
698
|
+
value: finalPrice?.amount || variant?.price?.amount,
|
|
699
|
+
num_items: quantity,
|
|
700
|
+
currency: variant?.price?.currencyCode,
|
|
701
|
+
content_name: variant?.product?.title,
|
|
702
|
+
content_type: "product_group",
|
|
703
|
+
content_ids: String(variant?.id),
|
|
704
|
+
content_category: variant?.product?.metafields?.global?.trafficType || "public"
|
|
705
|
+
});
|
|
706
|
+
} catch (error) {
|
|
707
|
+
console.error("FBQ tracking error:", error);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
};
|
|
711
|
+
var trackBuyNowFBQ = ({ trackConfig }) => {
|
|
712
|
+
if (typeof window === "undefined") {
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
try {
|
|
716
|
+
if (trackConfig?.fbqBuyNowEvent && window.fbq) {
|
|
717
|
+
window.fbq("trackCustom", trackConfig.fbqBuyNowEvent);
|
|
718
|
+
}
|
|
719
|
+
if (trackConfig?.gtagBuyNowLabel && trackConfig?.gtagId && window.gtag) {
|
|
720
|
+
window.gtag("event", trackConfig.gtagBuyNowConversion || "conversion", {
|
|
721
|
+
send_to: `${trackConfig.gtagId}/${trackConfig.gtagBuyNowLabel}`
|
|
722
|
+
});
|
|
723
|
+
}
|
|
724
|
+
} catch (error) {
|
|
725
|
+
console.error("Buy Now tracking error:", error);
|
|
726
|
+
}
|
|
727
|
+
};
|
|
728
|
+
function useApplyCartCodes(options) {
|
|
729
|
+
const { client, locale, cartCookieAdapter } = useShopify();
|
|
730
|
+
const { mutateCart, cart, metafieldIdentifiers } = useCartContext();
|
|
731
|
+
const applyCodes = useCallback(
|
|
732
|
+
async (_key, { arg }) => {
|
|
733
|
+
const { cartId: providedCartId, discountCodes, replaceExistingCodes } = arg;
|
|
734
|
+
if (!discountCodes?.length) {
|
|
735
|
+
throw new Error("Invalid input used for this operation: Miss discountCode");
|
|
736
|
+
}
|
|
737
|
+
const cartId = providedCartId ? void 0 : providedCartId || cart?.id;
|
|
738
|
+
if (!cartId) {
|
|
739
|
+
return void 0;
|
|
740
|
+
}
|
|
741
|
+
const updatedCart = await updateCartCodes(client, {
|
|
742
|
+
cartId,
|
|
743
|
+
discountCodes: replaceExistingCodes ? discountCodes : [
|
|
744
|
+
...discountCodes,
|
|
745
|
+
...cart?.discountCodes?.filter((item) => item.applicable).map((item) => item.code) || []
|
|
746
|
+
],
|
|
747
|
+
cookieAdapter: cartCookieAdapter,
|
|
748
|
+
metafieldIdentifiers
|
|
749
|
+
});
|
|
750
|
+
if (updatedCart) {
|
|
751
|
+
mutateCart(updatedCart);
|
|
752
|
+
}
|
|
753
|
+
return updatedCart;
|
|
754
|
+
},
|
|
755
|
+
[client, locale, cartCookieAdapter, mutateCart, cart]
|
|
756
|
+
);
|
|
757
|
+
return useSWRMutation("apply-codes", applyCodes, options);
|
|
758
|
+
}
|
|
759
|
+
function useRemoveCartCodes(options) {
|
|
760
|
+
const { client, locale, cartCookieAdapter } = useShopify();
|
|
761
|
+
const { mutateCart, cart, metafieldIdentifiers } = useCartContext();
|
|
762
|
+
const removeCodes = useCallback(
|
|
763
|
+
async (_key, { arg }) => {
|
|
764
|
+
const { cartId: providedCartId, discountCodes } = arg;
|
|
765
|
+
const cartId = providedCartId ? void 0 : providedCartId || cart?.id;
|
|
766
|
+
const codes = cart?.discountCodes?.filter((code) => !!code.applicable) || [];
|
|
767
|
+
const leftCodes = codes.filter((code) => discountCodes?.length ? !discountCodes.includes(code.code) : code.code).map((code) => code.code);
|
|
768
|
+
const updatedCart = await updateCartCodes(client, {
|
|
769
|
+
cartId,
|
|
770
|
+
discountCodes: leftCodes,
|
|
771
|
+
metafieldIdentifiers,
|
|
772
|
+
cookieAdapter: cartCookieAdapter
|
|
773
|
+
});
|
|
774
|
+
if (updatedCart) {
|
|
775
|
+
mutateCart(updatedCart);
|
|
776
|
+
}
|
|
777
|
+
return updatedCart;
|
|
778
|
+
},
|
|
779
|
+
[client, locale, cartCookieAdapter, mutateCart, cart]
|
|
780
|
+
);
|
|
781
|
+
return useSWRMutation("remove-codes", removeCodes, options);
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
// src/hooks/cart/use-add-to-cart.ts
|
|
785
|
+
function useAddToCart({ withTrack = true, brand } = {}, swrOptions) {
|
|
786
|
+
const { client, locale, cartCookieAdapter, userAdapter } = useShopify();
|
|
787
|
+
const { mutateCart, cart, metafieldIdentifiers } = useCartContext();
|
|
788
|
+
const { trigger: applyCartCodes } = useApplyCartCodes();
|
|
789
|
+
const { trigger: removeInvalidCodes } = useRemoveCartCodes();
|
|
790
|
+
const { trigger: addCartLines2 } = useAddCartLines();
|
|
791
|
+
const addToCart = useCallback(
|
|
792
|
+
async (_key, { arg }) => {
|
|
793
|
+
const {
|
|
794
|
+
lineItems,
|
|
795
|
+
cartId: providedCartId,
|
|
796
|
+
discountCodes,
|
|
797
|
+
gtmParams = {},
|
|
798
|
+
buyerIdentity,
|
|
799
|
+
needCreateCart = false,
|
|
800
|
+
onCodesInvalid,
|
|
801
|
+
replaceExistingCodes
|
|
802
|
+
} = arg;
|
|
803
|
+
if (!lineItems || lineItems.length === 0) {
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
const lines = lineItems.map((item) => ({
|
|
807
|
+
merchandiseId: item.variant?.id || "",
|
|
808
|
+
quantity: item.quantity || 1,
|
|
809
|
+
attributes: item.attributes
|
|
810
|
+
})).filter((item) => item.merchandiseId && item.quantity);
|
|
811
|
+
if (lines.length === 0) {
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
const cartId = needCreateCart ? void 0 : providedCartId || cart?.id;
|
|
815
|
+
let resultCart = await addCartLines2({
|
|
816
|
+
cartId,
|
|
817
|
+
lines,
|
|
818
|
+
buyerIdentity
|
|
819
|
+
});
|
|
820
|
+
if (!resultCart) {
|
|
821
|
+
return void 0;
|
|
822
|
+
}
|
|
823
|
+
if (resultCart.discountCodes && resultCart.discountCodes.length > 0) {
|
|
824
|
+
const unapplicableCodes = resultCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
|
|
825
|
+
if (unapplicableCodes.length > 0) {
|
|
826
|
+
if (onCodesInvalid) {
|
|
827
|
+
const handledCart = await onCodesInvalid(resultCart, unapplicableCodes);
|
|
828
|
+
if (handledCart) {
|
|
829
|
+
resultCart = handledCart;
|
|
830
|
+
}
|
|
831
|
+
} else {
|
|
832
|
+
await removeInvalidCodes({
|
|
833
|
+
discountCodes: unapplicableCodes
|
|
834
|
+
});
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
if (discountCodes && discountCodes.length > 0) {
|
|
839
|
+
applyCartCodes({
|
|
840
|
+
replaceExistingCodes,
|
|
841
|
+
discountCodes
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
if (withTrack && resultCart.lineItems) {
|
|
845
|
+
const trackingLineItems = resultCart.lineItems.map((line) => ({
|
|
846
|
+
variant: {
|
|
847
|
+
id: line.variant.id,
|
|
848
|
+
sku: line.variant.sku || "",
|
|
849
|
+
title: line.variant.name,
|
|
850
|
+
price: {
|
|
851
|
+
amount: String(line.variant.price),
|
|
852
|
+
currencyCode: resultCart.currency.code
|
|
853
|
+
},
|
|
854
|
+
product: line.product ? {
|
|
855
|
+
title: line.product.title || line.name,
|
|
856
|
+
productType: line.product.productType,
|
|
857
|
+
vendor: line.product.vendor
|
|
858
|
+
} : void 0
|
|
859
|
+
},
|
|
860
|
+
quantity: line.quantity
|
|
861
|
+
}));
|
|
862
|
+
trackAddToCartGA({
|
|
863
|
+
lineItems: trackingLineItems,
|
|
864
|
+
gtmParams: { ...gtmParams, brand },
|
|
865
|
+
brand
|
|
866
|
+
});
|
|
867
|
+
trackAddToCartFBQ({ lineItems: trackingLineItems });
|
|
868
|
+
}
|
|
869
|
+
return resultCart;
|
|
870
|
+
},
|
|
871
|
+
[client, locale, cartCookieAdapter, userAdapter, cart, withTrack, brand]
|
|
872
|
+
);
|
|
873
|
+
return useSWRMutation("add-to-cart", addToCart, swrOptions);
|
|
874
|
+
}
|
|
875
|
+
function useUpdateCartLines(options) {
|
|
876
|
+
const { client, locale, cartCookieAdapter } = useShopify();
|
|
877
|
+
const { mutateCart, metafieldIdentifiers } = useCartContext();
|
|
878
|
+
const updateLines = useCallback(
|
|
879
|
+
async (_key, { arg }) => {
|
|
880
|
+
const updatedCart = await updateCartLines(client, {
|
|
881
|
+
...arg,
|
|
882
|
+
metafieldIdentifiers,
|
|
883
|
+
cookieAdapter: cartCookieAdapter
|
|
884
|
+
});
|
|
885
|
+
if (updatedCart) {
|
|
886
|
+
mutateCart(updatedCart);
|
|
887
|
+
}
|
|
888
|
+
return updatedCart;
|
|
889
|
+
},
|
|
890
|
+
[client, locale, cartCookieAdapter, mutateCart]
|
|
891
|
+
);
|
|
892
|
+
return useSWRMutation("update-cart-lines", updateLines, options);
|
|
893
|
+
}
|
|
894
|
+
function useRemoveCartLines(options) {
|
|
895
|
+
const { client, locale, cartCookieAdapter } = useShopify();
|
|
896
|
+
const { mutateCart, metafieldIdentifiers } = useCartContext();
|
|
897
|
+
const removeLines = useCallback(
|
|
898
|
+
async (_key, { arg }) => {
|
|
899
|
+
const { autoRemoveInvalidCodes = true, onCodesRemoved, cartId, lineIds } = arg;
|
|
900
|
+
let updatedCart = await removeCartLines(client, {
|
|
901
|
+
cartId,
|
|
902
|
+
lineIds,
|
|
903
|
+
metafieldIdentifiers,
|
|
904
|
+
cookieAdapter: cartCookieAdapter
|
|
905
|
+
});
|
|
906
|
+
if (updatedCart && autoRemoveInvalidCodes) {
|
|
907
|
+
const unApplicableCodes = updatedCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
|
|
908
|
+
if (unApplicableCodes.length > 0) {
|
|
909
|
+
if (onCodesRemoved) {
|
|
910
|
+
const handledCart = await onCodesRemoved(updatedCart, unApplicableCodes);
|
|
911
|
+
if (handledCart) {
|
|
912
|
+
updatedCart = handledCart;
|
|
913
|
+
}
|
|
914
|
+
} else {
|
|
915
|
+
updatedCart = await updateCartCodes(client, {
|
|
916
|
+
cartId: updatedCart.id,
|
|
917
|
+
discountCodes: updatedCart.discountCodes.filter((item) => item.applicable).map((item) => item.code),
|
|
918
|
+
metafieldIdentifiers,
|
|
919
|
+
cookieAdapter: cartCookieAdapter
|
|
920
|
+
}) || updatedCart;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
if (updatedCart) {
|
|
925
|
+
mutateCart(updatedCart);
|
|
926
|
+
}
|
|
927
|
+
return updatedCart;
|
|
928
|
+
},
|
|
929
|
+
[client, locale, cartCookieAdapter, mutateCart]
|
|
930
|
+
);
|
|
931
|
+
return useSWRMutation("remove-cart-lines", removeLines, options);
|
|
932
|
+
}
|
|
933
|
+
function useUpdateCartAttributes(mutate, metafieldIdentifiers, options) {
|
|
934
|
+
const { client, locale, cartCookieAdapter } = useShopify();
|
|
935
|
+
const updateAttributes = useCallback(
|
|
936
|
+
async (_key, { arg }) => {
|
|
937
|
+
const updatedCart = await updateCartAttributes(client, {
|
|
938
|
+
...arg,
|
|
939
|
+
metafieldIdentifiers,
|
|
940
|
+
cookieAdapter: cartCookieAdapter
|
|
941
|
+
});
|
|
942
|
+
console.log("useUpdateCartAttributes updatedCart", updatedCart);
|
|
943
|
+
if (updatedCart) {
|
|
944
|
+
mutate(updatedCart);
|
|
945
|
+
}
|
|
946
|
+
return updatedCart;
|
|
947
|
+
},
|
|
948
|
+
[client, locale, cartCookieAdapter, mutate]
|
|
949
|
+
);
|
|
950
|
+
return useSWRMutation("update-cart-attributes", updateAttributes, options);
|
|
951
|
+
}
|
|
952
|
+
function useBuyNow({ withTrack = true, brand } = {}, swrOptions) {
|
|
953
|
+
const { client, locale, cartCookieAdapter, userAdapter } = useShopify();
|
|
954
|
+
const isLoggedIn = userAdapter?.isLoggedIn || false;
|
|
955
|
+
const buyNow = useCallback(
|
|
956
|
+
async (_key, { arg }) => {
|
|
957
|
+
const {
|
|
958
|
+
lineItems,
|
|
959
|
+
discountCodes,
|
|
960
|
+
gtmParams = {},
|
|
961
|
+
buyerIdentity,
|
|
962
|
+
fbqTrackConfig,
|
|
963
|
+
customAttributes,
|
|
964
|
+
metafieldIdentifiers,
|
|
965
|
+
redirectToCheckout
|
|
966
|
+
} = arg;
|
|
967
|
+
if (!lineItems || lineItems.length === 0) {
|
|
968
|
+
return;
|
|
969
|
+
}
|
|
970
|
+
const lines = lineItems.map((item) => ({
|
|
971
|
+
merchandiseId: item.variant?.id || item.variantId || "",
|
|
972
|
+
quantity: item.quantity || 1,
|
|
973
|
+
attributes: item.attributes
|
|
974
|
+
})).filter((item) => item.merchandiseId && item.quantity);
|
|
975
|
+
if (lines.length === 0) {
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
const resultCart = await createCart(client, {
|
|
979
|
+
lines,
|
|
980
|
+
metafieldIdentifiers,
|
|
981
|
+
cookieAdapter: cartCookieAdapter,
|
|
982
|
+
buyerIdentity,
|
|
983
|
+
discountCodes,
|
|
984
|
+
customAttributes
|
|
985
|
+
});
|
|
986
|
+
if (!resultCart) {
|
|
987
|
+
throw new Error("Failed to create cart for buy now");
|
|
988
|
+
}
|
|
989
|
+
if (withTrack && resultCart.lineItems) {
|
|
990
|
+
const trackingLineItems = resultCart.lineItems.map((line) => ({
|
|
991
|
+
variant: {
|
|
992
|
+
id: line.variantId,
|
|
993
|
+
sku: line.variant.sku || "",
|
|
994
|
+
title: line.variant.name,
|
|
995
|
+
price: {
|
|
996
|
+
amount: String(line.variant.price),
|
|
997
|
+
currencyCode: resultCart.currency.code
|
|
998
|
+
},
|
|
999
|
+
product: line.product ? {
|
|
1000
|
+
title: line.product.title || line.name,
|
|
1001
|
+
productType: line.product.productType,
|
|
1002
|
+
vendor: line.product.vendor
|
|
1003
|
+
} : void 0
|
|
1004
|
+
},
|
|
1005
|
+
quantity: line.quantity
|
|
1006
|
+
}));
|
|
1007
|
+
trackBuyNowGA({
|
|
1008
|
+
lineItems: trackingLineItems,
|
|
1009
|
+
gtmParams: { ...gtmParams, brand },
|
|
1010
|
+
brand
|
|
1011
|
+
});
|
|
1012
|
+
if (fbqTrackConfig) {
|
|
1013
|
+
trackBuyNowFBQ({ trackConfig: fbqTrackConfig });
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
if (redirectToCheckout) {
|
|
1017
|
+
if (resultCart.url) {
|
|
1018
|
+
if (typeof window !== "undefined") {
|
|
1019
|
+
window.location.href = resultCart.url;
|
|
1020
|
+
}
|
|
1021
|
+
} else {
|
|
1022
|
+
throw new Error("Failed to get checkout URL");
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
return resultCart;
|
|
1026
|
+
},
|
|
1027
|
+
[client, locale, isLoggedIn, cartCookieAdapter, withTrack, brand]
|
|
1028
|
+
);
|
|
1029
|
+
return useSWRMutation("buy-now", buyNow, swrOptions);
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
// src/hooks/cart/types/order-discount.ts
|
|
1033
|
+
var OrderDiscountType = /* @__PURE__ */ ((OrderDiscountType2) => {
|
|
1034
|
+
OrderDiscountType2[OrderDiscountType2["PERCENTAGE"] = 1] = "PERCENTAGE";
|
|
1035
|
+
OrderDiscountType2[OrderDiscountType2["FIXED_AMOUNT"] = 2] = "FIXED_AMOUNT";
|
|
1036
|
+
OrderDiscountType2[OrderDiscountType2["REDUCE_PRICE"] = 3] = "REDUCE_PRICE";
|
|
1037
|
+
return OrderDiscountType2;
|
|
1038
|
+
})(OrderDiscountType || {});
|
|
1039
|
+
var OrderBasePriceType = /* @__PURE__ */ ((OrderBasePriceType2) => {
|
|
1040
|
+
OrderBasePriceType2[OrderBasePriceType2["ORIGIN_PRICE"] = 1] = "ORIGIN_PRICE";
|
|
1041
|
+
OrderBasePriceType2[OrderBasePriceType2["MIN_DISCOUNTED_PRICE"] = 2] = "MIN_DISCOUNTED_PRICE";
|
|
1042
|
+
return OrderBasePriceType2;
|
|
1043
|
+
})(OrderBasePriceType || {});
|
|
1044
|
+
|
|
1045
|
+
// src/hooks/cart/feature/use-calc-order-discount.ts
|
|
1046
|
+
var useCalcOrderDiscount = (cart, orderDiscountConfig, customer) => {
|
|
1047
|
+
const tags = useMemo(() => customer?.tags || [], [customer?.tags]);
|
|
1048
|
+
const isCustomerLoading = useMemo(() => !customer ? true : false, [customer]);
|
|
1049
|
+
const dealsType = "";
|
|
1050
|
+
const { activeCampaign, subtotal } = useMemo(() => {
|
|
1051
|
+
for (const campaign of orderDiscountConfig) {
|
|
1052
|
+
const { rule_conditions = [], result_detail } = campaign;
|
|
1053
|
+
const { main_product, order_discount_conf } = result_detail || {};
|
|
1054
|
+
const isPreCheckPassed = preCheck(rule_conditions, tags, []);
|
|
1055
|
+
if (isPreCheckPassed && main_product && order_discount_conf) {
|
|
1056
|
+
const matchedSubtotal = getMatchedMainProductSubTotal(
|
|
1057
|
+
cart,
|
|
1058
|
+
main_product?.variant_list?.map((v) => v.variant_id) || [],
|
|
1059
|
+
{
|
|
1060
|
+
spend_money_type: order_discount_conf.base_price === 2 /* MIN_DISCOUNTED_PRICE */ ? 2 : 1,
|
|
1061
|
+
// 根据基础价格类型设置
|
|
1062
|
+
variant_id_list: main_product?.variant_list?.map((v) => v.variant_id) || [],
|
|
1063
|
+
all_store_variant: main_product?.all_store_variant || false
|
|
1064
|
+
}
|
|
1065
|
+
);
|
|
1066
|
+
if (matchedSubtotal > 0) {
|
|
1067
|
+
return { activeCampaign: campaign, subtotal: matchedSubtotal };
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
return { activeCampaign: null, subtotal: 0 };
|
|
1072
|
+
}, [orderDiscountConfig, cart, tags, dealsType]);
|
|
1073
|
+
const { qualifyingDiscount, nextTierGoal, discountAmount } = useMemo(() => {
|
|
1074
|
+
if (!activeCampaign || !activeCampaign.result_detail?.order_discount_conf?.tiered_discounts) {
|
|
1075
|
+
return {
|
|
1076
|
+
qualifyingDiscount: null,
|
|
1077
|
+
nextTierGoal: null,
|
|
1078
|
+
discountAmount: 0
|
|
1079
|
+
};
|
|
1080
|
+
}
|
|
1081
|
+
const tieredDiscounts = activeCampaign.result_detail.order_discount_conf.tiered_discounts;
|
|
1082
|
+
const qualifyingTier = [...tieredDiscounts].reverse().find((tier) => subtotal >= Number(tier.amount));
|
|
1083
|
+
const nextGoal = tieredDiscounts.find((tier) => subtotal < Number(tier.amount));
|
|
1084
|
+
if (!qualifyingTier) {
|
|
1085
|
+
return {
|
|
1086
|
+
qualifyingDiscount: null,
|
|
1087
|
+
nextTierGoal: nextGoal || null,
|
|
1088
|
+
discountAmount: 0
|
|
1089
|
+
};
|
|
1090
|
+
}
|
|
1091
|
+
let calculatedDiscount = 0;
|
|
1092
|
+
switch (qualifyingTier.discount_type) {
|
|
1093
|
+
case 1 /* PERCENTAGE */:
|
|
1094
|
+
calculatedDiscount = subtotal * qualifyingTier.discount / 100;
|
|
1095
|
+
break;
|
|
1096
|
+
case 2 /* FIXED_AMOUNT */:
|
|
1097
|
+
calculatedDiscount = qualifyingTier.discount;
|
|
1098
|
+
break;
|
|
1099
|
+
case 3 /* REDUCE_PRICE */:
|
|
1100
|
+
calculatedDiscount = Math.min(subtotal, qualifyingTier.discount);
|
|
1101
|
+
break;
|
|
1102
|
+
default:
|
|
1103
|
+
calculatedDiscount = 0;
|
|
1104
|
+
}
|
|
1105
|
+
return {
|
|
1106
|
+
qualifyingDiscount: qualifyingTier,
|
|
1107
|
+
nextTierGoal: nextGoal || null,
|
|
1108
|
+
discountAmount: calculatedDiscount
|
|
1109
|
+
};
|
|
1110
|
+
}, [activeCampaign, subtotal]);
|
|
1111
|
+
return {
|
|
1112
|
+
qualifyingDiscount,
|
|
1113
|
+
nextTierGoal,
|
|
1114
|
+
activeCampaign,
|
|
1115
|
+
discountAmount,
|
|
1116
|
+
cartTotalForDiscount: subtotal,
|
|
1117
|
+
isLoading: isCustomerLoading
|
|
1118
|
+
};
|
|
1119
|
+
};
|
|
1120
|
+
function useHasPlusMemberInCart({
|
|
1121
|
+
memberSetting,
|
|
1122
|
+
cart
|
|
1123
|
+
}) {
|
|
1124
|
+
const { plus_monthly_product, plus_annual_product } = memberSetting || {};
|
|
1125
|
+
return useMemo(() => {
|
|
1126
|
+
if (!cart?.lineItems) {
|
|
1127
|
+
return {
|
|
1128
|
+
hasPlusMember: false,
|
|
1129
|
+
hasMonthlyPlus: false,
|
|
1130
|
+
hasAnnualPlus: false
|
|
1131
|
+
};
|
|
1132
|
+
}
|
|
1133
|
+
const monthlyPlusItem = cart.lineItems.find(
|
|
1134
|
+
(item) => item.product?.handle === plus_monthly_product?.handle && item.variant?.sku === plus_monthly_product?.sku
|
|
1135
|
+
);
|
|
1136
|
+
const annualPlusItem = cart.lineItems.find(
|
|
1137
|
+
(item) => item.product?.handle === plus_annual_product?.handle && item.variant?.sku === plus_annual_product?.sku
|
|
1138
|
+
);
|
|
1139
|
+
const hasMonthlyPlus = !!monthlyPlusItem;
|
|
1140
|
+
const hasAnnualPlus = !!annualPlusItem;
|
|
1141
|
+
const hasPlusMember = hasMonthlyPlus || hasAnnualPlus;
|
|
1142
|
+
return {
|
|
1143
|
+
hasPlusMember,
|
|
1144
|
+
hasMonthlyPlus,
|
|
1145
|
+
hasAnnualPlus,
|
|
1146
|
+
monthlyPlusItem,
|
|
1147
|
+
annualPlusItem
|
|
1148
|
+
};
|
|
1149
|
+
}, [cart?.lineItems, plus_monthly_product, plus_annual_product]);
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
// src/hooks/cart/feature/use-cart-attributes.ts
|
|
1153
|
+
var getReferralAttributes = () => {
|
|
1154
|
+
const inviteCode = Cookies5.get("invite_code");
|
|
1155
|
+
const playModeId = Cookies5.get("playModeId");
|
|
1156
|
+
const popup = Cookies5.get("_popup");
|
|
1157
|
+
if (inviteCode && playModeId) {
|
|
1158
|
+
return popup ? [
|
|
1159
|
+
{ key: "_invite_code", value: inviteCode ? inviteCode : "" },
|
|
1160
|
+
{ key: "_play_mode_id", value: playModeId ? playModeId : "" },
|
|
1161
|
+
{ key: "_popup", value: popup }
|
|
1162
|
+
] : [
|
|
1163
|
+
{ key: "_invite_code", value: inviteCode ? inviteCode : "" },
|
|
1164
|
+
{ key: "_play_mode_id", value: playModeId ? playModeId : "" }
|
|
1165
|
+
];
|
|
1166
|
+
}
|
|
1167
|
+
return [];
|
|
1168
|
+
};
|
|
1169
|
+
var useCartAttributes = ({
|
|
1170
|
+
profile,
|
|
1171
|
+
customer,
|
|
1172
|
+
cart,
|
|
1173
|
+
memberSetting
|
|
1174
|
+
}) => {
|
|
1175
|
+
const [currentUrl, setCurrentUrl] = useState("");
|
|
1176
|
+
const { hasPlusMember } = useHasPlusMemberInCart({
|
|
1177
|
+
memberSetting,
|
|
1178
|
+
cart
|
|
1179
|
+
});
|
|
1180
|
+
console.log("memberSetting", memberSetting);
|
|
1181
|
+
console.log("hasPlusMember", hasPlusMember);
|
|
1182
|
+
useEffect(() => {
|
|
1183
|
+
setCurrentUrl(window.location.href);
|
|
1184
|
+
}, []);
|
|
1185
|
+
const userType = useMemo(() => {
|
|
1186
|
+
let userInfo = Cookies5.get("userInfo");
|
|
1187
|
+
if (userInfo) {
|
|
1188
|
+
userInfo = JSON.parse(userInfo);
|
|
1189
|
+
let arr = typeof userInfo?.id == "string" && userInfo?.id.split("/");
|
|
1190
|
+
userInfo.setId = arr[arr.length - 1];
|
|
1191
|
+
}
|
|
1192
|
+
const customerInfo = userInfo || customer;
|
|
1193
|
+
if (!customerInfo) {
|
|
1194
|
+
return "new_user_unlogin";
|
|
1195
|
+
}
|
|
1196
|
+
if (customer) {
|
|
1197
|
+
const { orders = {} } = customer;
|
|
1198
|
+
if (orders?.edges?.length === 1) {
|
|
1199
|
+
return "old_user_orders_once";
|
|
1200
|
+
} else if (orders?.edges?.length > 1) {
|
|
1201
|
+
return "old_user_orders_twice";
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
return "new_user_login";
|
|
1205
|
+
}, [customer]);
|
|
1206
|
+
const memberAttributes = useMemo(() => {
|
|
1207
|
+
return [
|
|
1208
|
+
{
|
|
1209
|
+
key: "_token",
|
|
1210
|
+
value: profile?.token
|
|
1211
|
+
//是否登录
|
|
1212
|
+
},
|
|
1213
|
+
{
|
|
1214
|
+
key: "_member_type",
|
|
1215
|
+
value: hasPlusMember ? "2" : profile?.memberType
|
|
1216
|
+
//:0(游客),1(普通会员),2(付费会员)
|
|
1217
|
+
},
|
|
1218
|
+
{
|
|
1219
|
+
key: "_user_type",
|
|
1220
|
+
value: userType
|
|
1221
|
+
// n
|
|
1222
|
+
},
|
|
1223
|
+
{
|
|
1224
|
+
key: "_is_login",
|
|
1225
|
+
value: profile?.token ? "true" : "false"
|
|
1226
|
+
}
|
|
1227
|
+
];
|
|
1228
|
+
}, [profile?.memberType, profile?.token, userType, hasPlusMember]);
|
|
1229
|
+
const functionAttributes = useMemo(() => {
|
|
1230
|
+
return [
|
|
1231
|
+
cart?.discountCodes && {
|
|
1232
|
+
key: "_discounts_function_env",
|
|
1233
|
+
value: JSON.stringify({
|
|
1234
|
+
discount_code: cart?.discountCodes.map((item) => item.code),
|
|
1235
|
+
user_tags: customer?.tags || []
|
|
1236
|
+
})
|
|
1237
|
+
}
|
|
1238
|
+
];
|
|
1239
|
+
}, [cart]);
|
|
1240
|
+
const presellAttributes = useMemo(() => {
|
|
1241
|
+
return [
|
|
1242
|
+
{
|
|
1243
|
+
key: "_presale",
|
|
1244
|
+
value: cart?.lineItems.some((item) => item?.variant?.metafields?.presell === "presell")
|
|
1245
|
+
}
|
|
1246
|
+
];
|
|
1247
|
+
}, [cart]);
|
|
1248
|
+
const weightAttributes = useMemo(() => {
|
|
1249
|
+
return [
|
|
1250
|
+
{
|
|
1251
|
+
key: "_weight",
|
|
1252
|
+
value: cart?.lineItems.reduce((acc, item) => {
|
|
1253
|
+
return new Decimal2(acc).plus(item.variant.weight ?? 0).toNumber();
|
|
1254
|
+
}, 0).toString()
|
|
1255
|
+
},
|
|
1256
|
+
{
|
|
1257
|
+
key: "_app_source_name",
|
|
1258
|
+
value: "dtc"
|
|
1259
|
+
}
|
|
1260
|
+
];
|
|
1261
|
+
}, [cart]);
|
|
1262
|
+
const trackingAttributes = useMemo(() => {
|
|
1263
|
+
return [
|
|
1264
|
+
{
|
|
1265
|
+
key: "utm_params",
|
|
1266
|
+
value: currentUrl
|
|
1267
|
+
}
|
|
1268
|
+
];
|
|
1269
|
+
}, [currentUrl]);
|
|
1270
|
+
return useMemo(
|
|
1271
|
+
() => ({
|
|
1272
|
+
attributes: [
|
|
1273
|
+
...memberAttributes,
|
|
1274
|
+
...functionAttributes,
|
|
1275
|
+
...presellAttributes,
|
|
1276
|
+
...weightAttributes,
|
|
1277
|
+
...trackingAttributes,
|
|
1278
|
+
...getReferralAttributes()
|
|
1279
|
+
].filter((item) => item?.value)
|
|
1280
|
+
}),
|
|
1281
|
+
[memberAttributes, functionAttributes, presellAttributes, weightAttributes, trackingAttributes]
|
|
1282
|
+
);
|
|
1283
|
+
};
|
|
1284
|
+
var DEFAULT_MIN = 1;
|
|
1285
|
+
var DEFAULT_MAX = 999;
|
|
1286
|
+
var useCartItemQuantityLimit = ({
|
|
1287
|
+
cart,
|
|
1288
|
+
cartItem,
|
|
1289
|
+
config
|
|
1290
|
+
}) => {
|
|
1291
|
+
const quantityLimit = useMemo(() => {
|
|
1292
|
+
if (config?.handle) {
|
|
1293
|
+
const cartItemQuantityLimit = config?.handle?.[cartItem?.product?.handle || ""];
|
|
1294
|
+
const sameHandleTotalQuantity = cart?.lineItems.reduce((acc, item) => {
|
|
1295
|
+
if (item.product?.handle === cartItem?.product?.handle && item.variant.sku !== cartItem.variant.sku) {
|
|
1296
|
+
acc += item.quantity;
|
|
1297
|
+
}
|
|
1298
|
+
return acc;
|
|
1299
|
+
}, 0) || 0;
|
|
1300
|
+
return {
|
|
1301
|
+
min: cartItemQuantityLimit?.min || DEFAULT_MIN,
|
|
1302
|
+
max: cartItemQuantityLimit?.max ? cartItemQuantityLimit?.max - sameHandleTotalQuantity : DEFAULT_MAX
|
|
1303
|
+
};
|
|
1304
|
+
} else if (config?.sku) {
|
|
1305
|
+
const cartItemQuantityLimit = config?.sku?.[cartItem?.variant?.sku];
|
|
1306
|
+
return {
|
|
1307
|
+
min: cartItemQuantityLimit?.min || DEFAULT_MIN,
|
|
1308
|
+
max: cartItemQuantityLimit?.max || DEFAULT_MAX
|
|
1309
|
+
};
|
|
1310
|
+
}
|
|
1311
|
+
return {
|
|
1312
|
+
min: DEFAULT_MIN,
|
|
1313
|
+
max: DEFAULT_MAX
|
|
1314
|
+
};
|
|
1315
|
+
}, [cartItem, cart]);
|
|
1316
|
+
return quantityLimit;
|
|
1317
|
+
};
|
|
1318
|
+
var useUpdateLineCodeAmountAttributes = ({
|
|
1319
|
+
cart,
|
|
1320
|
+
mutateCart,
|
|
1321
|
+
isCartLoading,
|
|
1322
|
+
setLoadingState,
|
|
1323
|
+
metafieldIdentifiers
|
|
1324
|
+
}) => {
|
|
1325
|
+
const { client, cartCookieAdapter } = useShopify();
|
|
1326
|
+
const mainProductDiscountCodes = useMemo(
|
|
1327
|
+
() => cart?.discountCodes.filter(
|
|
1328
|
+
({ code, applicable }) => applicable && MAIN_PRODUCT_CODE.some((codePrefix) => code.startsWith(codePrefix))
|
|
1329
|
+
).map(({ code }) => code),
|
|
1330
|
+
[cart]
|
|
1331
|
+
);
|
|
1332
|
+
const linesNeedUpdate = useMemo(
|
|
1333
|
+
() => cart?.lineItems.map((line) => {
|
|
1334
|
+
const attrNeedUpdate = [];
|
|
1335
|
+
const attrNeedDelete = [];
|
|
1336
|
+
const codeDiscount = line.discountAllocations?.find(
|
|
1337
|
+
(allocation) => mainProductDiscountCodes?.includes(allocation.code)
|
|
1338
|
+
);
|
|
1339
|
+
const hasFunctionEnvAttribute = line.customAttributes?.find(
|
|
1340
|
+
(attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY
|
|
1341
|
+
);
|
|
1342
|
+
const functionEnvValue = getDiscountEnvAttributeValue(line.customAttributes);
|
|
1343
|
+
const hasSameFunctionEnvAttribute = Number(functionEnvValue.discounted_amount) === Number(line.totalAmount);
|
|
1344
|
+
if (!hasSameFunctionEnvAttribute && hasFunctionEnvAttribute) {
|
|
1345
|
+
attrNeedUpdate.push({
|
|
1346
|
+
key: CUSTOMER_ATTRIBUTE_KEY,
|
|
1347
|
+
value: JSON.stringify({
|
|
1348
|
+
...functionEnvValue,
|
|
1349
|
+
discounted_amount: Number(line.totalAmount)
|
|
1350
|
+
})
|
|
1351
|
+
});
|
|
1352
|
+
}
|
|
1353
|
+
const codeDiscountAmount = codeDiscount?.amount || 0;
|
|
1354
|
+
const hasCodeAmountAttribute = line.customAttributes?.find(
|
|
1355
|
+
(attr) => attr.key === CODE_AMOUNT_KEY || attr.key === SCRIPT_CODE_AMOUNT_KEY
|
|
1356
|
+
);
|
|
1357
|
+
const hasSameCodeAmountAttribute = line.customAttributes?.find(
|
|
1358
|
+
(attr) => attr.key === CODE_AMOUNT_KEY && attr.value === String(codeDiscountAmount)
|
|
1359
|
+
) && line.customAttributes?.find(
|
|
1360
|
+
(attr) => attr.key === SCRIPT_CODE_AMOUNT_KEY && attr.value === String(codeDiscountAmount)
|
|
1361
|
+
);
|
|
1362
|
+
if (codeDiscount && !hasSameCodeAmountAttribute) {
|
|
1363
|
+
attrNeedUpdate.push({
|
|
1364
|
+
key: CODE_AMOUNT_KEY,
|
|
1365
|
+
value: String(codeDiscountAmount)
|
|
1366
|
+
});
|
|
1367
|
+
attrNeedUpdate.push({
|
|
1368
|
+
key: SCRIPT_CODE_AMOUNT_KEY,
|
|
1369
|
+
value: String(codeDiscountAmount)
|
|
1370
|
+
});
|
|
1371
|
+
} else if (!codeDiscount && hasCodeAmountAttribute) {
|
|
1372
|
+
attrNeedDelete.push(CODE_AMOUNT_KEY);
|
|
1373
|
+
attrNeedDelete.push(SCRIPT_CODE_AMOUNT_KEY);
|
|
1374
|
+
}
|
|
1375
|
+
return {
|
|
1376
|
+
line,
|
|
1377
|
+
attrNeedUpdate,
|
|
1378
|
+
attrNeedDelete
|
|
1379
|
+
};
|
|
1380
|
+
}).filter(
|
|
1381
|
+
({ attrNeedUpdate, attrNeedDelete }) => attrNeedUpdate.length || attrNeedDelete.length
|
|
1382
|
+
).map(({ line, attrNeedUpdate, attrNeedDelete }) => {
|
|
1383
|
+
if (attrNeedUpdate.length) {
|
|
1384
|
+
return {
|
|
1385
|
+
id: line.id,
|
|
1386
|
+
attributes: [
|
|
1387
|
+
...line.customAttributes?.filter(
|
|
1388
|
+
(attr) => !attrNeedUpdate.some((updateAttr) => updateAttr.key === attr.key)
|
|
1389
|
+
) || [],
|
|
1390
|
+
...attrNeedUpdate
|
|
1391
|
+
]
|
|
1392
|
+
};
|
|
1393
|
+
} else if (attrNeedDelete.length) {
|
|
1394
|
+
return {
|
|
1395
|
+
id: line.id,
|
|
1396
|
+
attributes: line.customAttributes?.filter(
|
|
1397
|
+
(attr) => !attrNeedDelete.includes(attr.key)
|
|
1398
|
+
) || []
|
|
1399
|
+
};
|
|
1400
|
+
} else {
|
|
1401
|
+
return {
|
|
1402
|
+
id: line.id,
|
|
1403
|
+
attributes: line.customAttributes || []
|
|
1404
|
+
};
|
|
1405
|
+
}
|
|
1406
|
+
}),
|
|
1407
|
+
[cart?.lineItems, mainProductDiscountCodes]
|
|
1408
|
+
);
|
|
1409
|
+
const { loading } = useRequest(
|
|
1410
|
+
async () => {
|
|
1411
|
+
if (linesNeedUpdate?.length && !isCartLoading) {
|
|
1412
|
+
const result = await updateCartLines(client, {
|
|
1413
|
+
cartId: cart?.id || "",
|
|
1414
|
+
lines: linesNeedUpdate,
|
|
1415
|
+
metafieldIdentifiers,
|
|
1416
|
+
cookieAdapter: cartCookieAdapter
|
|
1417
|
+
});
|
|
1418
|
+
if (result) {
|
|
1419
|
+
mutateCart(result);
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
},
|
|
1423
|
+
{
|
|
1424
|
+
throttleWait: 3e3,
|
|
1425
|
+
// 3 秒内只触发最后一次更新
|
|
1426
|
+
throttleTrailing: true,
|
|
1427
|
+
refreshDeps: [linesNeedUpdate, isCartLoading]
|
|
1428
|
+
}
|
|
1429
|
+
);
|
|
1430
|
+
useEffect(() => {
|
|
1431
|
+
setLoadingState((prev) => {
|
|
1432
|
+
return {
|
|
1433
|
+
...prev,
|
|
1434
|
+
editLineCodeAmountLoading: loading
|
|
1435
|
+
};
|
|
1436
|
+
});
|
|
1437
|
+
}, [loading, setLoadingState]);
|
|
1438
|
+
};
|
|
1439
|
+
|
|
1440
|
+
// src/hooks/cart/types/price-discount.ts
|
|
1441
|
+
var PriceDiscountType = /* @__PURE__ */ ((PriceDiscountType2) => {
|
|
1442
|
+
PriceDiscountType2[PriceDiscountType2["PERCENTAGE"] = 1] = "PERCENTAGE";
|
|
1443
|
+
PriceDiscountType2[PriceDiscountType2["FIXED_AMOUNT"] = 2] = "FIXED_AMOUNT";
|
|
1444
|
+
return PriceDiscountType2;
|
|
1445
|
+
})(PriceDiscountType || {});
|
|
1446
|
+
var PriceBasePriceType = /* @__PURE__ */ ((PriceBasePriceType2) => {
|
|
1447
|
+
PriceBasePriceType2[PriceBasePriceType2["MIN_DISCOUNTED_PRICE"] = 1] = "MIN_DISCOUNTED_PRICE";
|
|
1448
|
+
PriceBasePriceType2[PriceBasePriceType2["MIN_TOTAL_PRICE"] = 2] = "MIN_TOTAL_PRICE";
|
|
1449
|
+
return PriceBasePriceType2;
|
|
1450
|
+
})(PriceBasePriceType || {});
|
|
1451
|
+
function useProduct(options = {}) {
|
|
1452
|
+
const { client, locale } = useShopify();
|
|
1453
|
+
const { handle, metafieldIdentifiers, ...swrOptions } = options;
|
|
1454
|
+
return useSWR(
|
|
1455
|
+
handle ? ["product", locale, handle, metafieldIdentifiers] : null,
|
|
1456
|
+
() => getProduct(client, {
|
|
1457
|
+
handle,
|
|
1458
|
+
locale,
|
|
1459
|
+
metafieldIdentifiers
|
|
1460
|
+
}),
|
|
1461
|
+
swrOptions
|
|
1462
|
+
);
|
|
1463
|
+
}
|
|
1464
|
+
function useAllProducts(options = {}) {
|
|
1465
|
+
const { client, locale } = useShopify();
|
|
1466
|
+
const { first, query, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
|
|
1467
|
+
return useSWR(
|
|
1468
|
+
["all-products", locale, first, query, sortKey, reverse, metafieldIdentifiers],
|
|
1469
|
+
() => getAllProducts(client, {
|
|
1470
|
+
locale,
|
|
1471
|
+
first,
|
|
1472
|
+
query,
|
|
1473
|
+
sortKey,
|
|
1474
|
+
reverse,
|
|
1475
|
+
metafieldIdentifiers
|
|
1476
|
+
}),
|
|
1477
|
+
swrOptions
|
|
1478
|
+
);
|
|
1479
|
+
}
|
|
1480
|
+
function useProductsByHandles(options = {}) {
|
|
1481
|
+
const { client, locale } = useShopify();
|
|
1482
|
+
const { handles: originHandles, metafieldIdentifiers, ...swrOptions } = options;
|
|
1483
|
+
const handles = new Set(originHandles || []);
|
|
1484
|
+
const sortedHandles = handles ? [...handles].sort() : void 0;
|
|
1485
|
+
return useSWR(
|
|
1486
|
+
sortedHandles && sortedHandles.length > 0 ? ["products-by-handles", locale, sortedHandles.join(","), metafieldIdentifiers] : null,
|
|
1487
|
+
() => {
|
|
1488
|
+
const handlesArray = [...handles];
|
|
1489
|
+
if (handlesArray?.length === 0) {
|
|
1490
|
+
throw new Error("Handles are required");
|
|
1491
|
+
}
|
|
1492
|
+
return getProductsByHandles(client, {
|
|
1493
|
+
handles: [...handles],
|
|
1494
|
+
locale,
|
|
1495
|
+
metafieldIdentifiers
|
|
1496
|
+
});
|
|
1497
|
+
},
|
|
1498
|
+
swrOptions || {
|
|
1499
|
+
revalidateOnFocus: false
|
|
1500
|
+
}
|
|
1501
|
+
);
|
|
1502
|
+
}
|
|
1503
|
+
function getFirstAvailableVariant(product) {
|
|
1504
|
+
const availableVariant = product.variants.find((v) => v.availableForSale);
|
|
1505
|
+
return availableVariant || product.variants[0];
|
|
1506
|
+
}
|
|
1507
|
+
function getVariantFromSelectedOptions(product, selectedOptions) {
|
|
1508
|
+
return product.variants.find((variant) => {
|
|
1509
|
+
return variant.selectedOptions.every((option) => {
|
|
1510
|
+
return selectedOptions[option.name] === option.value;
|
|
1511
|
+
});
|
|
1512
|
+
});
|
|
1513
|
+
}
|
|
1514
|
+
function useVariant({
|
|
1515
|
+
product,
|
|
1516
|
+
selectedOptions
|
|
1517
|
+
}) {
|
|
1518
|
+
const [variant, setVariant] = useState(
|
|
1519
|
+
product ? getFirstAvailableVariant(product) : void 0
|
|
1520
|
+
);
|
|
1521
|
+
useEffect(() => {
|
|
1522
|
+
if (!product) {
|
|
1523
|
+
setVariant(void 0);
|
|
1524
|
+
return;
|
|
1525
|
+
}
|
|
1526
|
+
const newVariant = getVariantFromSelectedOptions(product, selectedOptions);
|
|
1527
|
+
if (newVariant && newVariant.id !== variant?.id) {
|
|
1528
|
+
setVariant(newVariant);
|
|
1529
|
+
} else if (!newVariant) {
|
|
1530
|
+
setVariant(getFirstAvailableVariant(product));
|
|
1531
|
+
}
|
|
1532
|
+
}, [selectedOptions, product, variant?.id]);
|
|
1533
|
+
return variant;
|
|
1534
|
+
}
|
|
1535
|
+
var FAKE_PRICE = 999999999e-2;
|
|
1536
|
+
function formatPrice({
|
|
1537
|
+
amount,
|
|
1538
|
+
currencyCode,
|
|
1539
|
+
locale,
|
|
1540
|
+
maximumFractionDigits,
|
|
1541
|
+
minimumFractionDigits,
|
|
1542
|
+
removeTrailingZeros
|
|
1543
|
+
}) {
|
|
1544
|
+
const formatter = new Intl.NumberFormat(locale, {
|
|
1545
|
+
style: "currency",
|
|
1546
|
+
currency: currencyCode,
|
|
1547
|
+
maximumFractionDigits: maximumFractionDigits ?? 2,
|
|
1548
|
+
minimumFractionDigits: minimumFractionDigits ?? 2
|
|
1549
|
+
});
|
|
1550
|
+
let formatted = formatter.format(amount);
|
|
1551
|
+
if (removeTrailingZeros) {
|
|
1552
|
+
formatted = formatted.replace(/\.00$/, "");
|
|
1553
|
+
}
|
|
1554
|
+
return formatted;
|
|
1555
|
+
}
|
|
1556
|
+
function formatVariantPrice({
|
|
1557
|
+
amount,
|
|
1558
|
+
baseAmount,
|
|
1559
|
+
currencyCode,
|
|
1560
|
+
locale,
|
|
1561
|
+
maximumFractionDigits,
|
|
1562
|
+
minimumFractionDigits,
|
|
1563
|
+
removeTrailingZeros
|
|
1564
|
+
}) {
|
|
1565
|
+
return {
|
|
1566
|
+
price: formatPrice({
|
|
1567
|
+
amount,
|
|
1568
|
+
currencyCode,
|
|
1569
|
+
locale,
|
|
1570
|
+
maximumFractionDigits,
|
|
1571
|
+
minimumFractionDigits,
|
|
1572
|
+
removeTrailingZeros
|
|
1573
|
+
}),
|
|
1574
|
+
basePrice: formatPrice({
|
|
1575
|
+
amount: baseAmount,
|
|
1576
|
+
currencyCode,
|
|
1577
|
+
locale,
|
|
1578
|
+
maximumFractionDigits,
|
|
1579
|
+
minimumFractionDigits,
|
|
1580
|
+
removeTrailingZeros
|
|
1581
|
+
})
|
|
1582
|
+
};
|
|
1583
|
+
}
|
|
1584
|
+
function usePrice({
|
|
1585
|
+
amount,
|
|
1586
|
+
baseAmount,
|
|
1587
|
+
currencyCode,
|
|
1588
|
+
soldOutDescription = "",
|
|
1589
|
+
maximumFractionDigits,
|
|
1590
|
+
minimumFractionDigits,
|
|
1591
|
+
removeTrailingZeros
|
|
1592
|
+
}) {
|
|
1593
|
+
const { locale } = useShopify();
|
|
1594
|
+
const value = useMemo(() => {
|
|
1595
|
+
if (typeof amount !== "number" || !currencyCode) {
|
|
1596
|
+
return "";
|
|
1597
|
+
}
|
|
1598
|
+
if (soldOutDescription && amount >= FAKE_PRICE) {
|
|
1599
|
+
return soldOutDescription;
|
|
1600
|
+
}
|
|
1601
|
+
return baseAmount ? formatVariantPrice({
|
|
1602
|
+
amount,
|
|
1603
|
+
baseAmount,
|
|
1604
|
+
currencyCode,
|
|
1605
|
+
locale,
|
|
1606
|
+
maximumFractionDigits,
|
|
1607
|
+
minimumFractionDigits,
|
|
1608
|
+
removeTrailingZeros
|
|
1609
|
+
}) : formatPrice({
|
|
1610
|
+
amount,
|
|
1611
|
+
currencyCode,
|
|
1612
|
+
locale,
|
|
1613
|
+
maximumFractionDigits,
|
|
1614
|
+
minimumFractionDigits,
|
|
1615
|
+
removeTrailingZeros
|
|
1616
|
+
});
|
|
1617
|
+
}, [
|
|
1618
|
+
amount,
|
|
1619
|
+
baseAmount,
|
|
1620
|
+
currencyCode,
|
|
1621
|
+
locale,
|
|
1622
|
+
maximumFractionDigits,
|
|
1623
|
+
minimumFractionDigits,
|
|
1624
|
+
soldOutDescription,
|
|
1625
|
+
removeTrailingZeros
|
|
1626
|
+
]);
|
|
1627
|
+
const result = useMemo(() => {
|
|
1628
|
+
const free = Boolean(amount && amount <= 0);
|
|
1629
|
+
return typeof value === "string" ? { price: value, basePrice: value, free } : { ...value, free };
|
|
1630
|
+
}, [value, amount]);
|
|
1631
|
+
return result;
|
|
1632
|
+
}
|
|
1633
|
+
function optionsConstructor(selectedOptions) {
|
|
1634
|
+
return selectedOptions.reduce((acc, option) => {
|
|
1635
|
+
acc[option.name] = option.value;
|
|
1636
|
+
return acc;
|
|
1637
|
+
}, {});
|
|
1638
|
+
}
|
|
1639
|
+
function decodeShopifyId(gid) {
|
|
1640
|
+
try {
|
|
1641
|
+
const base64 = gid.split("/").pop() || "";
|
|
1642
|
+
return atob(base64);
|
|
1643
|
+
} catch {
|
|
1644
|
+
return gid;
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
function useSelectedOptions(product, sku) {
|
|
1648
|
+
const [options, setOptions] = useState({});
|
|
1649
|
+
useEffect(() => {
|
|
1650
|
+
if (!product || !product.variants.length) {
|
|
1651
|
+
setOptions({});
|
|
1652
|
+
return;
|
|
1653
|
+
}
|
|
1654
|
+
let variant = product.variants[0];
|
|
1655
|
+
if (typeof window !== "undefined") {
|
|
1656
|
+
const searchParams = new URLSearchParams(window.location.search);
|
|
1657
|
+
const variantIdParam = searchParams.get("variant");
|
|
1658
|
+
if (variantIdParam) {
|
|
1659
|
+
const foundVariant = product.variants.find((v) => {
|
|
1660
|
+
if (sku) return v.sku === sku;
|
|
1661
|
+
return v.id === variantIdParam || v.id.includes(variantIdParam) || decodeShopifyId(v.id) === variantIdParam;
|
|
1662
|
+
});
|
|
1663
|
+
if (foundVariant) {
|
|
1664
|
+
variant = foundVariant;
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
if (variant) {
|
|
1669
|
+
const newOptions = optionsConstructor(variant.selectedOptions);
|
|
1670
|
+
setOptions(newOptions);
|
|
1671
|
+
}
|
|
1672
|
+
}, [product, sku]);
|
|
1673
|
+
return [options, setOptions];
|
|
1674
|
+
}
|
|
1675
|
+
function decodeShopifyId2(gid) {
|
|
1676
|
+
try {
|
|
1677
|
+
const parts = gid.split("/");
|
|
1678
|
+
return parts[parts.length - 1] || gid;
|
|
1679
|
+
} catch {
|
|
1680
|
+
return gid;
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
function useProductUrl(otherQuery) {
|
|
1684
|
+
const { routerAdapter } = useShopify();
|
|
1685
|
+
return useCallback(
|
|
1686
|
+
({ product, variant }) => {
|
|
1687
|
+
if (!product) return "";
|
|
1688
|
+
const queryParams = new URLSearchParams();
|
|
1689
|
+
if (variant?.id) {
|
|
1690
|
+
const variantId = decodeShopifyId2(variant.id);
|
|
1691
|
+
if (variantId) {
|
|
1692
|
+
queryParams.set("variant", variantId);
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
if (otherQuery) {
|
|
1696
|
+
Object.entries(otherQuery).forEach(([key, value]) => {
|
|
1697
|
+
queryParams.set(key, value);
|
|
1698
|
+
});
|
|
1699
|
+
}
|
|
1700
|
+
const queryString = queryParams.toString();
|
|
1701
|
+
const path = `/products/${product.handle}${queryString ? `?${queryString}` : ""}`;
|
|
1702
|
+
if (routerAdapter?.getLocalizedPath) {
|
|
1703
|
+
return routerAdapter.getLocalizedPath(path);
|
|
1704
|
+
}
|
|
1705
|
+
return path;
|
|
1706
|
+
},
|
|
1707
|
+
[routerAdapter, otherQuery]
|
|
1708
|
+
);
|
|
1709
|
+
}
|
|
1710
|
+
function decodeShopifyId3(gid) {
|
|
1711
|
+
try {
|
|
1712
|
+
const parts = gid.split("/");
|
|
1713
|
+
return parts[parts.length - 1] || gid;
|
|
1714
|
+
} catch {
|
|
1715
|
+
return gid;
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
function useUpdateVariantQuery(variant) {
|
|
1719
|
+
useEffect(() => {
|
|
1720
|
+
if (!variant || typeof window === "undefined") {
|
|
1721
|
+
return;
|
|
1722
|
+
}
|
|
1723
|
+
const searchParams = new URLSearchParams(window.location.search);
|
|
1724
|
+
const currentVariantId = searchParams.get("variant");
|
|
1725
|
+
const newVariantId = decodeShopifyId3(variant.id);
|
|
1726
|
+
if (newVariantId && currentVariantId !== newVariantId) {
|
|
1727
|
+
searchParams.set("variant", newVariantId);
|
|
1728
|
+
const newUrl = `${window.location.pathname}?${searchParams.toString()}${window.location.hash}`;
|
|
1729
|
+
window.history.replaceState({}, "", newUrl);
|
|
1730
|
+
}
|
|
1731
|
+
}, [variant]);
|
|
1732
|
+
}
|
|
1733
|
+
function getVariantMediaList({
|
|
1734
|
+
product,
|
|
1735
|
+
variant
|
|
1736
|
+
}) {
|
|
1737
|
+
if (variant.image?.url) {
|
|
1738
|
+
const variantMediaId = variant.image.url;
|
|
1739
|
+
const variantMedia = product.media.filter((media) => {
|
|
1740
|
+
if (media.mediaContentType === "IMAGE" && media.previewImage) {
|
|
1741
|
+
return media.previewImage?.url === variantMediaId;
|
|
1742
|
+
}
|
|
1743
|
+
return false;
|
|
1744
|
+
});
|
|
1745
|
+
if (variantMedia.length > 0) {
|
|
1746
|
+
const otherMedia = product.media.filter((media) => {
|
|
1747
|
+
if (media.mediaContentType === "IMAGE" && media.previewImage) {
|
|
1748
|
+
return media.previewImage.url !== variantMediaId;
|
|
1749
|
+
}
|
|
1750
|
+
return true;
|
|
1751
|
+
});
|
|
1752
|
+
return [...variantMedia, ...otherMedia];
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
return product.media;
|
|
1756
|
+
}
|
|
1757
|
+
function useVariantMedia({
|
|
1758
|
+
product,
|
|
1759
|
+
variant
|
|
1760
|
+
}) {
|
|
1761
|
+
const [imageList, setImageList] = useState([]);
|
|
1762
|
+
const [sceneList, setSceneList] = useState([]);
|
|
1763
|
+
const [videoList, setVideoList] = useState([]);
|
|
1764
|
+
useEffect(() => {
|
|
1765
|
+
if (!product || !variant) {
|
|
1766
|
+
setImageList([]);
|
|
1767
|
+
setSceneList([]);
|
|
1768
|
+
setVideoList([]);
|
|
1769
|
+
return;
|
|
1770
|
+
}
|
|
1771
|
+
const mediaList = getVariantMediaList({ product, variant });
|
|
1772
|
+
const images = mediaList.filter((media) => media.mediaContentType === "IMAGE");
|
|
1773
|
+
const videos = mediaList.filter(
|
|
1774
|
+
(media) => media.mediaContentType === "VIDEO" || media.mediaContentType === "EXTERNAL_VIDEO"
|
|
1775
|
+
);
|
|
1776
|
+
setImageList(images.length > 0 && images[0] ? [images[0]] : []);
|
|
1777
|
+
setSceneList(images.length > 1 ? images.slice(1) : []);
|
|
1778
|
+
setVideoList(videos);
|
|
1779
|
+
}, [product, variant]);
|
|
1780
|
+
return {
|
|
1781
|
+
productList: imageList,
|
|
1782
|
+
sceneList,
|
|
1783
|
+
videoList
|
|
1784
|
+
};
|
|
1785
|
+
}
|
|
1786
|
+
function useCollection(options = {}) {
|
|
1787
|
+
const { client, locale } = useShopify();
|
|
1788
|
+
const { handle, metafieldIdentifiers, ...swrOptions } = options;
|
|
1789
|
+
return useSWR(
|
|
1790
|
+
handle ? ["collection", locale, handle, metafieldIdentifiers] : null,
|
|
1791
|
+
() => getCollection(client, {
|
|
1792
|
+
handle,
|
|
1793
|
+
locale,
|
|
1794
|
+
metafieldIdentifiers
|
|
1795
|
+
}),
|
|
1796
|
+
swrOptions
|
|
1797
|
+
);
|
|
1798
|
+
}
|
|
1799
|
+
function useAllCollections(options = {}) {
|
|
1800
|
+
const { client, locale } = useShopify();
|
|
1801
|
+
const { first, query, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
|
|
1802
|
+
return useSWR(
|
|
1803
|
+
["all-collections", locale, first, query, sortKey, reverse, metafieldIdentifiers],
|
|
1804
|
+
() => getAllCollections(client, {
|
|
1805
|
+
locale,
|
|
1806
|
+
first,
|
|
1807
|
+
query,
|
|
1808
|
+
sortKey,
|
|
1809
|
+
reverse,
|
|
1810
|
+
metafieldIdentifiers
|
|
1811
|
+
}),
|
|
1812
|
+
swrOptions
|
|
1813
|
+
);
|
|
1814
|
+
}
|
|
1815
|
+
function useCollections(options = {}) {
|
|
1816
|
+
const { client, locale } = useShopify();
|
|
1817
|
+
const { first, after, query, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
|
|
1818
|
+
return useSWR(
|
|
1819
|
+
["collections", locale, first, after, query, sortKey, reverse, metafieldIdentifiers],
|
|
1820
|
+
() => getCollections(client, {
|
|
1821
|
+
locale,
|
|
1822
|
+
first,
|
|
1823
|
+
after,
|
|
1824
|
+
query,
|
|
1825
|
+
sortKey,
|
|
1826
|
+
reverse,
|
|
1827
|
+
metafieldIdentifiers
|
|
1828
|
+
}),
|
|
1829
|
+
swrOptions
|
|
1830
|
+
);
|
|
1831
|
+
}
|
|
1832
|
+
function useBlog(options = {}) {
|
|
1833
|
+
const { client, locale } = useShopify();
|
|
1834
|
+
const { handle, metafieldIdentifiers, ...swrOptions } = options;
|
|
1835
|
+
return useSWR(
|
|
1836
|
+
handle ? ["blog", locale, handle, metafieldIdentifiers] : null,
|
|
1837
|
+
() => getBlog(client, { handle, locale, metafieldIdentifiers }),
|
|
1838
|
+
swrOptions
|
|
1839
|
+
);
|
|
1840
|
+
}
|
|
1841
|
+
function useAllBlogs(options = {}) {
|
|
1842
|
+
const { client, locale } = useShopify();
|
|
1843
|
+
const { first, query, metafieldIdentifiers, ...swrOptions } = options;
|
|
1844
|
+
return useSWR(
|
|
1845
|
+
["all-blogs", locale, first, query, metafieldIdentifiers],
|
|
1846
|
+
() => getAllBlogs(client, {
|
|
1847
|
+
locale,
|
|
1848
|
+
first,
|
|
1849
|
+
query,
|
|
1850
|
+
metafieldIdentifiers
|
|
1851
|
+
}),
|
|
1852
|
+
swrOptions
|
|
1853
|
+
);
|
|
1854
|
+
}
|
|
1855
|
+
function useArticle(options = {}) {
|
|
1856
|
+
const { client, locale } = useShopify();
|
|
1857
|
+
const { blogHandle, articleHandle, metafieldIdentifiers, ...swrOptions } = options;
|
|
1858
|
+
return useSWR(
|
|
1859
|
+
blogHandle && articleHandle ? ["article", locale, blogHandle, articleHandle, metafieldIdentifiers] : null,
|
|
1860
|
+
() => getArticle(client, {
|
|
1861
|
+
blogHandle,
|
|
1862
|
+
articleHandle,
|
|
1863
|
+
locale,
|
|
1864
|
+
metafieldIdentifiers
|
|
1865
|
+
}),
|
|
1866
|
+
swrOptions
|
|
1867
|
+
);
|
|
1868
|
+
}
|
|
1869
|
+
function useArticles(options = {}) {
|
|
1870
|
+
const { client, locale } = useShopify();
|
|
1871
|
+
const { first, query, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
|
|
1872
|
+
return useSWR(
|
|
1873
|
+
["articles", locale, first, query, sortKey, reverse, metafieldIdentifiers],
|
|
1874
|
+
() => getArticles(client, {
|
|
1875
|
+
locale,
|
|
1876
|
+
first,
|
|
1877
|
+
query,
|
|
1878
|
+
sortKey,
|
|
1879
|
+
reverse,
|
|
1880
|
+
metafieldIdentifiers
|
|
1881
|
+
}),
|
|
1882
|
+
swrOptions
|
|
1883
|
+
);
|
|
1884
|
+
}
|
|
1885
|
+
function useArticlesInBlog(options = {}) {
|
|
1886
|
+
const { client, locale } = useShopify();
|
|
1887
|
+
const { blogHandle, first, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
|
|
1888
|
+
return useSWR(
|
|
1889
|
+
blogHandle ? ["articles-in-blog", locale, blogHandle, first, sortKey, reverse, metafieldIdentifiers] : null,
|
|
1890
|
+
() => getArticlesInBlog(client, {
|
|
1891
|
+
blogHandle,
|
|
1892
|
+
locale,
|
|
1893
|
+
first,
|
|
1894
|
+
sortKey,
|
|
1895
|
+
reverse,
|
|
1896
|
+
metafieldIdentifiers
|
|
1897
|
+
}),
|
|
1898
|
+
swrOptions
|
|
1899
|
+
);
|
|
1900
|
+
}
|
|
1901
|
+
async function performSearch(client, locale, searchQuery, first = 20, types = ["PRODUCT", "ARTICLE", "PAGE"]) {
|
|
1902
|
+
if (!searchQuery) {
|
|
1903
|
+
return void 0;
|
|
1904
|
+
}
|
|
1905
|
+
const query = (
|
|
1906
|
+
/* GraphQL */
|
|
1907
|
+
`
|
|
1908
|
+
query search($query: String!, $first: Int!, $types: [SearchType!])
|
|
1909
|
+
@inContext(language: $language) {
|
|
1910
|
+
search(query: $query, first: $first, types: $types, unavailableProducts: HIDE) {
|
|
1911
|
+
totalCount
|
|
1912
|
+
edges {
|
|
1913
|
+
node {
|
|
1914
|
+
... on Article {
|
|
1915
|
+
__typename
|
|
1916
|
+
id
|
|
1917
|
+
handle
|
|
1918
|
+
title
|
|
1919
|
+
excerpt
|
|
1920
|
+
image {
|
|
1921
|
+
url
|
|
1922
|
+
altText
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
... on Page {
|
|
1926
|
+
__typename
|
|
1927
|
+
id
|
|
1928
|
+
handle
|
|
1929
|
+
title
|
|
1930
|
+
}
|
|
1931
|
+
... on Product {
|
|
1932
|
+
__typename
|
|
1933
|
+
id
|
|
1934
|
+
handle
|
|
1935
|
+
title
|
|
1936
|
+
description
|
|
1937
|
+
featuredImage {
|
|
1938
|
+
url
|
|
1939
|
+
altText
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
pageInfo {
|
|
1945
|
+
hasNextPage
|
|
1946
|
+
endCursor
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
`
|
|
1951
|
+
);
|
|
1952
|
+
const data = await client.query(query, {
|
|
1953
|
+
query: searchQuery,
|
|
1954
|
+
first,
|
|
1955
|
+
types
|
|
1956
|
+
});
|
|
1957
|
+
if (!data || !data.search) {
|
|
1958
|
+
return void 0;
|
|
1959
|
+
}
|
|
1960
|
+
const items = data.search.edges?.map((edge) => {
|
|
1961
|
+
const node = edge.node;
|
|
1962
|
+
const item = {
|
|
1963
|
+
type: node.__typename.toUpperCase(),
|
|
1964
|
+
id: node.id,
|
|
1965
|
+
handle: node.handle,
|
|
1966
|
+
title: node.title
|
|
1967
|
+
};
|
|
1968
|
+
if (node.__typename === "Product") {
|
|
1969
|
+
item.description = node.description;
|
|
1970
|
+
item.image = node.featuredImage ? {
|
|
1971
|
+
url: node.featuredImage.url,
|
|
1972
|
+
altText: node.featuredImage.altText
|
|
1973
|
+
} : void 0;
|
|
1974
|
+
} else if (node.__typename === "Article") {
|
|
1975
|
+
item.description = node.excerpt;
|
|
1976
|
+
item.image = node.image ? {
|
|
1977
|
+
url: node.image.url,
|
|
1978
|
+
altText: node.image.altText
|
|
1979
|
+
} : void 0;
|
|
1980
|
+
}
|
|
1981
|
+
return item;
|
|
1982
|
+
}) || [];
|
|
1983
|
+
return {
|
|
1984
|
+
items,
|
|
1985
|
+
totalCount: data.search.totalCount || 0,
|
|
1986
|
+
pageInfo: data.search.pageInfo
|
|
1987
|
+
};
|
|
1988
|
+
}
|
|
1989
|
+
function useSearch(options = {}) {
|
|
1990
|
+
const { client, locale } = useShopify();
|
|
1991
|
+
const { query, first = 20, types = ["PRODUCT", "ARTICLE", "PAGE"], ...swrOptions } = options;
|
|
1992
|
+
return useSWR(
|
|
1993
|
+
query ? ["search", locale, query, first, types] : null,
|
|
1994
|
+
() => performSearch(client, locale, query, first, types),
|
|
1995
|
+
swrOptions
|
|
1996
|
+
);
|
|
1997
|
+
}
|
|
1998
|
+
async function getSiteInfo(client, locale, metafieldIdentifiers) {
|
|
1999
|
+
const hasMetafields = metafieldIdentifiers && metafieldIdentifiers.length > 0;
|
|
2000
|
+
const query = (
|
|
2001
|
+
/* GraphQL */
|
|
2002
|
+
`
|
|
2003
|
+
query getSiteInfo(
|
|
2004
|
+
${hasMetafields ? "$shopMetafieldIdentifiers: [HasMetafieldsIdentifier!]!" : ""}
|
|
2005
|
+
) @inContext(language: $language) {
|
|
2006
|
+
shop {
|
|
2007
|
+
name
|
|
2008
|
+
description
|
|
2009
|
+
primaryDomain {
|
|
2010
|
+
url
|
|
2011
|
+
host
|
|
2012
|
+
}
|
|
2013
|
+
brand {
|
|
2014
|
+
logo {
|
|
2015
|
+
image {
|
|
2016
|
+
url
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2019
|
+
colors {
|
|
2020
|
+
primary {
|
|
2021
|
+
background
|
|
2022
|
+
}
|
|
2023
|
+
secondary {
|
|
2024
|
+
background
|
|
2025
|
+
}
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
${hasMetafields ? "metafields(identifiers: $shopMetafieldIdentifiers) { key value }" : ""}
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
`
|
|
2032
|
+
);
|
|
2033
|
+
const variables = {};
|
|
2034
|
+
if (hasMetafields) {
|
|
2035
|
+
variables.shopMetafieldIdentifiers = metafieldIdentifiers;
|
|
2036
|
+
}
|
|
2037
|
+
const data = await client.query(query, variables);
|
|
2038
|
+
if (!data || !data.shop) {
|
|
2039
|
+
return void 0;
|
|
2040
|
+
}
|
|
2041
|
+
const shop = data.shop;
|
|
2042
|
+
const metafields = shop.metafields?.reduce((acc, mf) => {
|
|
2043
|
+
if (mf && mf.key) {
|
|
2044
|
+
acc[mf.key] = mf.value;
|
|
2045
|
+
}
|
|
2046
|
+
return acc;
|
|
2047
|
+
}, {});
|
|
2048
|
+
return {
|
|
2049
|
+
name: shop.name,
|
|
2050
|
+
description: shop.description,
|
|
2051
|
+
primaryDomain: shop.primaryDomain,
|
|
2052
|
+
brand: shop.brand ? {
|
|
2053
|
+
logo: shop.brand.logo,
|
|
2054
|
+
colors: shop.brand.colors ? {
|
|
2055
|
+
primary: shop.brand.colors.primary?.background,
|
|
2056
|
+
secondary: shop.brand.colors.secondary?.background
|
|
2057
|
+
} : void 0
|
|
2058
|
+
} : void 0,
|
|
2059
|
+
metafields
|
|
2060
|
+
};
|
|
2061
|
+
}
|
|
2062
|
+
function useSite(options = {}) {
|
|
2063
|
+
const { client, locale } = useShopify();
|
|
2064
|
+
const { metafieldIdentifiers, ...swrOptions } = options;
|
|
2065
|
+
return useSWR(
|
|
2066
|
+
["site", locale, metafieldIdentifiers],
|
|
2067
|
+
() => getSiteInfo(client, locale, metafieldIdentifiers),
|
|
2068
|
+
swrOptions
|
|
2069
|
+
);
|
|
2070
|
+
}
|
|
2071
|
+
|
|
2072
|
+
// src/hooks/member/plus/types.ts
|
|
2073
|
+
var PLUS_MEMBER_TYPE = /* @__PURE__ */ ((PLUS_MEMBER_TYPE2) => {
|
|
2074
|
+
PLUS_MEMBER_TYPE2[PLUS_MEMBER_TYPE2["FREE"] = 0] = "FREE";
|
|
2075
|
+
PLUS_MEMBER_TYPE2[PLUS_MEMBER_TYPE2["MONTHLY"] = 1] = "MONTHLY";
|
|
2076
|
+
PLUS_MEMBER_TYPE2[PLUS_MEMBER_TYPE2["ANNUAL"] = 2] = "ANNUAL";
|
|
2077
|
+
return PLUS_MEMBER_TYPE2;
|
|
2078
|
+
})(PLUS_MEMBER_TYPE || {});
|
|
2079
|
+
var PlusMemberMode = /* @__PURE__ */ ((PlusMemberMode2) => {
|
|
2080
|
+
PlusMemberMode2["MONTHLY"] = "monthly";
|
|
2081
|
+
PlusMemberMode2["ANNUAL"] = "annual";
|
|
2082
|
+
return PlusMemberMode2;
|
|
2083
|
+
})(PlusMemberMode || {});
|
|
2084
|
+
var DeliveryPlusType = /* @__PURE__ */ ((DeliveryPlusType2) => {
|
|
2085
|
+
DeliveryPlusType2["FREE"] = "free";
|
|
2086
|
+
DeliveryPlusType2["MONTHLY"] = "monthly";
|
|
2087
|
+
DeliveryPlusType2["ANNUAL"] = "annual";
|
|
2088
|
+
return DeliveryPlusType2;
|
|
2089
|
+
})(DeliveryPlusType || {});
|
|
2090
|
+
var ShippingMethodMode = /* @__PURE__ */ ((ShippingMethodMode2) => {
|
|
2091
|
+
ShippingMethodMode2["FREE"] = "free";
|
|
2092
|
+
ShippingMethodMode2["TDD"] = "tdd";
|
|
2093
|
+
ShippingMethodMode2["NDD"] = "ndd";
|
|
2094
|
+
return ShippingMethodMode2;
|
|
2095
|
+
})(ShippingMethodMode || {});
|
|
2096
|
+
var createInitialValue = () => ({
|
|
2097
|
+
zipCode: "",
|
|
2098
|
+
plusMemberMetafields: {},
|
|
2099
|
+
setZipCode: () => {
|
|
2100
|
+
},
|
|
2101
|
+
allowNextDayDelivery: false,
|
|
2102
|
+
setAllowNextDayDelivery: () => {
|
|
2103
|
+
},
|
|
2104
|
+
allowThirdDayDelivery: false,
|
|
2105
|
+
setAllowThirdDayDelivery: () => {
|
|
2106
|
+
},
|
|
2107
|
+
selectedPlusMemberMode: "free",
|
|
2108
|
+
setSelectedPlusMemberMode: () => {
|
|
2109
|
+
},
|
|
2110
|
+
showAreaCheckModal: false,
|
|
2111
|
+
setShowAreaCheckModal: () => {
|
|
2112
|
+
},
|
|
2113
|
+
selectedShippingMethod: void 0,
|
|
2114
|
+
setSelectedShippingMethod: () => {
|
|
2115
|
+
},
|
|
2116
|
+
showTip: false,
|
|
2117
|
+
setShowTip: () => {
|
|
2118
|
+
},
|
|
2119
|
+
showMoreShippingMethod: false,
|
|
2120
|
+
setShowMoreShippingMethod: () => {
|
|
2121
|
+
},
|
|
2122
|
+
variant: {},
|
|
2123
|
+
product: {},
|
|
2124
|
+
shippingMethodsContext: {
|
|
2125
|
+
freeShippingMethods: [],
|
|
2126
|
+
paymentShippingMethods: [],
|
|
2127
|
+
nddOverweight: false,
|
|
2128
|
+
tddOverweight: false
|
|
2129
|
+
},
|
|
2130
|
+
selectedPlusMemberProduct: null,
|
|
2131
|
+
plusMemberProducts: [],
|
|
2132
|
+
showPlusMemberBenefit: false,
|
|
2133
|
+
setShowPlusMemberBenefit: () => {
|
|
2134
|
+
},
|
|
2135
|
+
deleteMarginBottom: false,
|
|
2136
|
+
setDeleteMarginBottom: () => {
|
|
2137
|
+
},
|
|
2138
|
+
profile: void 0,
|
|
2139
|
+
locale: void 0
|
|
2140
|
+
});
|
|
2141
|
+
var PlusMemberContext = createContext(createInitialValue());
|
|
2142
|
+
function usePlusMemberContext() {
|
|
2143
|
+
return useContext(PlusMemberContext);
|
|
2144
|
+
}
|
|
2145
|
+
function usePlusMonthlyProductVariant() {
|
|
2146
|
+
const { plusMemberProducts, plusMemberMetafields } = usePlusMemberContext();
|
|
2147
|
+
const plusMonthly = plusMemberMetafields?.plus_monthly_product;
|
|
2148
|
+
const plusMonthlyProductVariant = useMemo(() => {
|
|
2149
|
+
const product = plusMemberProducts?.find(
|
|
2150
|
+
(item) => item?.handle === plusMonthly?.handle
|
|
2151
|
+
);
|
|
2152
|
+
const productVariant = product?.variants?.find(
|
|
2153
|
+
(item) => item.sku === plusMonthly?.sku
|
|
2154
|
+
);
|
|
2155
|
+
return productVariant;
|
|
2156
|
+
}, [plusMemberProducts, plusMonthly]);
|
|
2157
|
+
return plusMonthlyProductVariant;
|
|
2158
|
+
}
|
|
2159
|
+
function usePlusAnnualProductVariant() {
|
|
2160
|
+
const { plusMemberProducts, plusMemberMetafields } = usePlusMemberContext();
|
|
2161
|
+
const plusAnnual = plusMemberMetafields?.plus_annual_product;
|
|
2162
|
+
const plusAnnualProductVariant = useMemo(() => {
|
|
2163
|
+
const product = plusMemberProducts?.find(
|
|
2164
|
+
(item) => item?.handle === plusAnnual?.handle
|
|
2165
|
+
);
|
|
2166
|
+
const productVariant = product?.variants?.find(
|
|
2167
|
+
(item) => item.sku === plusAnnual?.sku
|
|
2168
|
+
);
|
|
2169
|
+
return productVariant;
|
|
2170
|
+
}, [plusMemberProducts, plusAnnual]);
|
|
2171
|
+
return plusAnnualProductVariant;
|
|
2172
|
+
}
|
|
2173
|
+
function useShippingMethods(options) {
|
|
2174
|
+
const {
|
|
2175
|
+
variant,
|
|
2176
|
+
plusMemberMetafields,
|
|
2177
|
+
selectedPlusMemberMode,
|
|
2178
|
+
isPlus = false,
|
|
2179
|
+
nddCoupon,
|
|
2180
|
+
tddCoupon
|
|
2181
|
+
} = options;
|
|
2182
|
+
const { plus_shipping, shippingMethod } = plusMemberMetafields || {};
|
|
2183
|
+
const nddOverweight = useMemo(() => {
|
|
2184
|
+
return (variant?.weight || 0) > (shippingMethod?.overWeight_ndd || Infinity);
|
|
2185
|
+
}, [shippingMethod?.overWeight_ndd, variant?.weight]);
|
|
2186
|
+
const tddOverweight = useMemo(() => {
|
|
2187
|
+
return (variant?.weight || 0) > (shippingMethod?.overWeight_tdd || Infinity);
|
|
2188
|
+
}, [shippingMethod?.overWeight_tdd, variant?.weight]);
|
|
2189
|
+
const paymentShippingMethods = useMemo(() => {
|
|
2190
|
+
const weight = variant?.weight || 0;
|
|
2191
|
+
const methods = plus_shipping?.shipping_methods?.filter(
|
|
2192
|
+
({ weight_low, weight_high, __mode, __plus }) => {
|
|
2193
|
+
const fitWeight = (!weight_low || weight >= weight_low) && (!weight_high || weight <= weight_high);
|
|
2194
|
+
return __mode !== "free" /* FREE */ && !__plus && fitWeight;
|
|
2195
|
+
}
|
|
2196
|
+
) || [];
|
|
2197
|
+
return methods.map((method) => {
|
|
2198
|
+
let disabled = false;
|
|
2199
|
+
const selectedFreeMember = selectedPlusMemberMode === "free";
|
|
2200
|
+
if (method.__mode === "ndd" /* NDD */) {
|
|
2201
|
+
disabled = selectedFreeMember || nddOverweight;
|
|
2202
|
+
} else if (method.__mode === "tdd" /* TDD */) {
|
|
2203
|
+
disabled = selectedFreeMember || tddOverweight;
|
|
2204
|
+
}
|
|
2205
|
+
return {
|
|
2206
|
+
...method,
|
|
2207
|
+
id: method.__mode + method.__code,
|
|
2208
|
+
useCoupon: false,
|
|
2209
|
+
subtitle: plus_shipping?.directly || "",
|
|
2210
|
+
disabled
|
|
2211
|
+
};
|
|
2212
|
+
});
|
|
2213
|
+
}, [
|
|
2214
|
+
nddOverweight,
|
|
2215
|
+
plus_shipping?.directly,
|
|
2216
|
+
plus_shipping?.shipping_methods,
|
|
2217
|
+
selectedPlusMemberMode,
|
|
2218
|
+
tddOverweight,
|
|
2219
|
+
variant?.weight
|
|
2220
|
+
]);
|
|
2221
|
+
const nddPrice = useMemo(() => {
|
|
2222
|
+
const weight = variant?.weight || 0;
|
|
2223
|
+
const nddMethod = paymentShippingMethods.find(
|
|
2224
|
+
({ __mode, weight_high, weight_low }) => {
|
|
2225
|
+
const fitWeight = (!weight_low || weight >= weight_low) && (!weight_high || weight <= weight_high);
|
|
2226
|
+
return __mode === "ndd" && fitWeight;
|
|
2227
|
+
}
|
|
2228
|
+
);
|
|
2229
|
+
return nddMethod?.price || 0;
|
|
2230
|
+
}, [variant?.weight, paymentShippingMethods]);
|
|
2231
|
+
const tddPrice = useMemo(() => {
|
|
2232
|
+
const weight = variant?.weight || 0;
|
|
2233
|
+
const tddMethod = paymentShippingMethods.find(
|
|
2234
|
+
({ __mode, weight_high, weight_low }) => {
|
|
2235
|
+
const fitWeight = (!weight_low || weight >= weight_low) && (!weight_high || weight <= weight_high);
|
|
2236
|
+
return __mode === "tdd" && fitWeight;
|
|
2237
|
+
}
|
|
2238
|
+
);
|
|
2239
|
+
return tddMethod?.price || 0;
|
|
2240
|
+
}, [variant?.weight, paymentShippingMethods]);
|
|
2241
|
+
const freeShippingMethods = useMemo(() => {
|
|
2242
|
+
const weight = variant?.weight || 0;
|
|
2243
|
+
let methods = plus_shipping?.shipping_methods?.filter(
|
|
2244
|
+
({ __mode, __plus, weight_low, weight_high }) => {
|
|
2245
|
+
if (__mode === "free" /* FREE */) {
|
|
2246
|
+
return true;
|
|
2247
|
+
}
|
|
2248
|
+
if (isPlus) {
|
|
2249
|
+
const hasCoupon = isPlus && __mode === "ndd" /* NDD */ && nddCoupon || isPlus && __mode === "tdd" /* TDD */ && (tddCoupon || nddCoupon);
|
|
2250
|
+
const fitWeight = (!weight_low || weight >= weight_low) && (!weight_high || weight <= weight_high);
|
|
2251
|
+
return hasCoupon && fitWeight && !__plus;
|
|
2252
|
+
} else {
|
|
2253
|
+
return __plus;
|
|
2254
|
+
}
|
|
2255
|
+
}
|
|
2256
|
+
) || [];
|
|
2257
|
+
if (isPlus) {
|
|
2258
|
+
methods = methods.sort((a, b) => {
|
|
2259
|
+
if (b.__mode === "free" /* FREE */) return -1;
|
|
2260
|
+
return 0;
|
|
2261
|
+
});
|
|
2262
|
+
}
|
|
2263
|
+
return methods.map((method) => {
|
|
2264
|
+
let price = 0;
|
|
2265
|
+
let coupon;
|
|
2266
|
+
let disabled;
|
|
2267
|
+
if (method.__mode !== "free" /* FREE */) {
|
|
2268
|
+
switch (method.__mode) {
|
|
2269
|
+
case "tdd":
|
|
2270
|
+
price = tddPrice;
|
|
2271
|
+
coupon = tddCoupon || nddCoupon;
|
|
2272
|
+
break;
|
|
2273
|
+
case "ndd":
|
|
2274
|
+
price = nddPrice;
|
|
2275
|
+
coupon = nddCoupon;
|
|
2276
|
+
break;
|
|
2277
|
+
}
|
|
2278
|
+
disabled = selectedPlusMemberMode === "free";
|
|
2279
|
+
if (method.__mode === "ndd" /* NDD */) {
|
|
2280
|
+
disabled = disabled || nddOverweight;
|
|
2281
|
+
} else if (method.__mode === "tdd" /* TDD */) {
|
|
2282
|
+
disabled = disabled || tddOverweight;
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
return {
|
|
2286
|
+
...method,
|
|
2287
|
+
id: method.__mode + method.__code,
|
|
2288
|
+
useCoupon: true,
|
|
2289
|
+
disabled,
|
|
2290
|
+
coupon,
|
|
2291
|
+
price
|
|
2292
|
+
};
|
|
2293
|
+
});
|
|
2294
|
+
}, [
|
|
2295
|
+
variant?.weight,
|
|
2296
|
+
plus_shipping?.shipping_methods,
|
|
2297
|
+
isPlus,
|
|
2298
|
+
nddCoupon,
|
|
2299
|
+
tddCoupon,
|
|
2300
|
+
selectedPlusMemberMode,
|
|
2301
|
+
tddPrice,
|
|
2302
|
+
nddPrice,
|
|
2303
|
+
nddOverweight,
|
|
2304
|
+
tddOverweight
|
|
2305
|
+
]);
|
|
2306
|
+
return {
|
|
2307
|
+
freeShippingMethods,
|
|
2308
|
+
paymentShippingMethods,
|
|
2309
|
+
nddOverweight,
|
|
2310
|
+
tddOverweight
|
|
2311
|
+
};
|
|
2312
|
+
}
|
|
2313
|
+
function useShippingMethodAvailableCheck() {
|
|
2314
|
+
const {
|
|
2315
|
+
zipCode,
|
|
2316
|
+
allowNextDayDelivery,
|
|
2317
|
+
allowThirdDayDelivery,
|
|
2318
|
+
selectedShippingMethod,
|
|
2319
|
+
setSelectedShippingMethod,
|
|
2320
|
+
setShowTip,
|
|
2321
|
+
shippingMethodsContext
|
|
2322
|
+
} = usePlusMemberContext();
|
|
2323
|
+
useEffect(() => {
|
|
2324
|
+
const freeShippingMethod = shippingMethodsContext.freeShippingMethods[0];
|
|
2325
|
+
const standardShippingMethod = shippingMethodsContext.freeShippingMethods?.find(
|
|
2326
|
+
(item) => item.__mode === "free" /* FREE */
|
|
2327
|
+
);
|
|
2328
|
+
const freeTDD = shippingMethodsContext.freeShippingMethods.find(
|
|
2329
|
+
(item) => item.__mode === "tdd" /* TDD */
|
|
2330
|
+
);
|
|
2331
|
+
const paymentTDD = shippingMethodsContext.paymentShippingMethods.find(
|
|
2332
|
+
(item) => item.__mode === "tdd" /* TDD */
|
|
2333
|
+
);
|
|
2334
|
+
if (zipCode) {
|
|
2335
|
+
console.log(
|
|
2336
|
+
"allowNextDayDelivery, allowThirdDayDelivery:",
|
|
2337
|
+
allowNextDayDelivery,
|
|
2338
|
+
allowThirdDayDelivery
|
|
2339
|
+
);
|
|
2340
|
+
if (!allowNextDayDelivery && !allowThirdDayDelivery) {
|
|
2341
|
+
setShowTip(true);
|
|
2342
|
+
setSelectedShippingMethod(standardShippingMethod);
|
|
2343
|
+
} else {
|
|
2344
|
+
if (selectedShippingMethod?.__mode === "ndd" /* NDD */ && !allowNextDayDelivery) {
|
|
2345
|
+
setShowTip(true);
|
|
2346
|
+
if (allowThirdDayDelivery) {
|
|
2347
|
+
if (selectedShippingMethod.useCoupon) {
|
|
2348
|
+
const method = freeTDD || freeShippingMethod;
|
|
2349
|
+
if (method) setSelectedShippingMethod(method);
|
|
2350
|
+
} else {
|
|
2351
|
+
const method = paymentTDD || freeShippingMethod;
|
|
2352
|
+
if (method) setSelectedShippingMethod(method);
|
|
2353
|
+
}
|
|
2354
|
+
} else {
|
|
2355
|
+
if (freeShippingMethod) setSelectedShippingMethod(freeShippingMethod);
|
|
2356
|
+
}
|
|
2357
|
+
} else if (
|
|
2358
|
+
// TDD 无法使用
|
|
2359
|
+
selectedShippingMethod?.__mode === "tdd" /* TDD */ && !allowThirdDayDelivery
|
|
2360
|
+
) {
|
|
2361
|
+
setShowTip(true);
|
|
2362
|
+
if (freeShippingMethod) setSelectedShippingMethod(freeShippingMethod);
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
}, [
|
|
2367
|
+
allowNextDayDelivery,
|
|
2368
|
+
allowThirdDayDelivery,
|
|
2369
|
+
zipCode,
|
|
2370
|
+
shippingMethodsContext,
|
|
2371
|
+
selectedShippingMethod,
|
|
2372
|
+
setSelectedShippingMethod,
|
|
2373
|
+
setShowTip
|
|
2374
|
+
]);
|
|
2375
|
+
}
|
|
2376
|
+
var useReplaceCartPlusMember = () => {
|
|
2377
|
+
const { plusMemberMetafields, selectedPlusMemberMode } = usePlusMemberContext();
|
|
2378
|
+
const { trigger: removeCartLines2 } = useRemoveCartLines();
|
|
2379
|
+
const { cart } = useCartContext();
|
|
2380
|
+
const plusMonthly = plusMemberMetafields?.plus_monthly_product;
|
|
2381
|
+
const plusAnnual = plusMemberMetafields?.plus_annual_product;
|
|
2382
|
+
const handler = useCallback(async () => {
|
|
2383
|
+
const plusMonthlyInCart = cart?.lineItems.find(
|
|
2384
|
+
(item) => item.variant?.sku === plusMonthly?.sku
|
|
2385
|
+
);
|
|
2386
|
+
const plusAnnualInCart = cart?.lineItems.find(
|
|
2387
|
+
(item) => item.variant?.sku === plusAnnual?.sku
|
|
2388
|
+
);
|
|
2389
|
+
if (selectedPlusMemberMode === "annual" /* ANNUAL */ && plusMonthlyInCart) {
|
|
2390
|
+
await removeCartLines2({
|
|
2391
|
+
lineIds: [plusMonthlyInCart.id]
|
|
2392
|
+
});
|
|
2393
|
+
} else if (selectedPlusMemberMode === "monthly" /* MONTHLY */ && plusAnnualInCart) {
|
|
2394
|
+
await removeCartLines2({
|
|
2395
|
+
lineIds: [plusAnnualInCart.id]
|
|
2396
|
+
});
|
|
2397
|
+
}
|
|
2398
|
+
}, [
|
|
2399
|
+
cart?.lineItems,
|
|
2400
|
+
selectedPlusMemberMode,
|
|
2401
|
+
plusMonthly?.sku,
|
|
2402
|
+
plusAnnual?.sku,
|
|
2403
|
+
removeCartLines2
|
|
2404
|
+
]);
|
|
2405
|
+
return handler;
|
|
2406
|
+
};
|
|
2407
|
+
var usePlusMemberDeliveryCodes = ({
|
|
2408
|
+
deliveryData
|
|
2409
|
+
}) => {
|
|
2410
|
+
return useMemo(
|
|
2411
|
+
() => deliveryData?.deliveryCustomData?.discount_code,
|
|
2412
|
+
[deliveryData]
|
|
2413
|
+
);
|
|
2414
|
+
};
|
|
2415
|
+
var usePlusMemberItemCustomAttributes = ({
|
|
2416
|
+
deliveryData
|
|
2417
|
+
}) => {
|
|
2418
|
+
const { deliveryCustomData } = deliveryData || {};
|
|
2419
|
+
return useMemo(() => {
|
|
2420
|
+
const itemCustomAttributes = [];
|
|
2421
|
+
if (deliveryCustomData?.is_presale) {
|
|
2422
|
+
itemCustomAttributes.push({
|
|
2423
|
+
key: "_is_presale",
|
|
2424
|
+
value: "true"
|
|
2425
|
+
});
|
|
2426
|
+
}
|
|
2427
|
+
return itemCustomAttributes;
|
|
2428
|
+
}, [deliveryCustomData]);
|
|
2429
|
+
};
|
|
2430
|
+
var usePlusMemberCheckoutCustomAttributes = ({
|
|
2431
|
+
deliveryData,
|
|
2432
|
+
product,
|
|
2433
|
+
variant,
|
|
2434
|
+
customer,
|
|
2435
|
+
isShowShippingBenefits
|
|
2436
|
+
}) => {
|
|
2437
|
+
const { deliveryCustomData } = deliveryData || {};
|
|
2438
|
+
const { profile } = usePlusMemberContext();
|
|
2439
|
+
const userType = useMemo(() => {
|
|
2440
|
+
const customerInfo = customer;
|
|
2441
|
+
if (!customerInfo) {
|
|
2442
|
+
return "new_user_unlogin";
|
|
2443
|
+
}
|
|
2444
|
+
if (customer) {
|
|
2445
|
+
const { orders = {} } = customer;
|
|
2446
|
+
const edgesLength = orders?.edges?.length;
|
|
2447
|
+
if (edgesLength === 1) {
|
|
2448
|
+
return "old_user_orders_once";
|
|
2449
|
+
} else if (edgesLength && edgesLength > 1) {
|
|
2450
|
+
return "old_user_orders_twice";
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2453
|
+
return "new_user_login";
|
|
2454
|
+
}, [customer]);
|
|
2455
|
+
return useMemo(() => {
|
|
2456
|
+
const checkoutCustomAttributes = [
|
|
2457
|
+
{
|
|
2458
|
+
key: "_token",
|
|
2459
|
+
value: profile?.token || ""
|
|
2460
|
+
},
|
|
2461
|
+
{
|
|
2462
|
+
key: "_last_url",
|
|
2463
|
+
value: typeof window !== "undefined" ? window.location.origin + window.location.pathname : ""
|
|
2464
|
+
},
|
|
2465
|
+
{
|
|
2466
|
+
key: "_user_type",
|
|
2467
|
+
value: userType
|
|
2468
|
+
}
|
|
2469
|
+
];
|
|
2470
|
+
if (profile) {
|
|
2471
|
+
checkoutCustomAttributes.push({
|
|
2472
|
+
key: "_login_user",
|
|
2473
|
+
value: "1"
|
|
2474
|
+
});
|
|
2475
|
+
}
|
|
2476
|
+
if (deliveryCustomData) {
|
|
2477
|
+
checkoutCustomAttributes.push({
|
|
2478
|
+
key: "_checkout_delivery_custom",
|
|
2479
|
+
value: JSON.stringify({
|
|
2480
|
+
...deliveryCustomData,
|
|
2481
|
+
is_prime: profile?.isPlus
|
|
2482
|
+
})
|
|
2483
|
+
});
|
|
2484
|
+
}
|
|
2485
|
+
if (variant?.metafields?.presell) {
|
|
2486
|
+
checkoutCustomAttributes.push({
|
|
2487
|
+
key: "_presale",
|
|
2488
|
+
value: "true"
|
|
2489
|
+
});
|
|
2490
|
+
}
|
|
2491
|
+
if (isShowShippingBenefits && !isShowShippingBenefits({ variant, product, setting: {} })) {
|
|
2492
|
+
checkoutCustomAttributes.push({
|
|
2493
|
+
key: "_hide_shipping",
|
|
2494
|
+
value: "true"
|
|
2495
|
+
});
|
|
2496
|
+
}
|
|
2497
|
+
return checkoutCustomAttributes;
|
|
2498
|
+
}, [deliveryCustomData, product, profile, userType, variant, isShowShippingBenefits]);
|
|
2499
|
+
};
|
|
2500
|
+
function useAutoRemovePlusMemberInCart({
|
|
2501
|
+
metafields,
|
|
2502
|
+
isMonthlyPlus,
|
|
2503
|
+
isAnnualPlus
|
|
2504
|
+
}) {
|
|
2505
|
+
const { plus_monthly_product, plus_annual_product } = metafields || {};
|
|
2506
|
+
const { cart } = useCartContext();
|
|
2507
|
+
const { trigger: removeCartLines2 } = useRemoveCartLines();
|
|
2508
|
+
useEffect(() => {
|
|
2509
|
+
if (!cart) return;
|
|
2510
|
+
const removePlusProduct = async (productType) => {
|
|
2511
|
+
if (!productType) return;
|
|
2512
|
+
const product = cart.lineItems?.find(
|
|
2513
|
+
(item) => item.product?.handle === productType?.handle && item.variant?.sku === productType?.sku
|
|
2514
|
+
);
|
|
2515
|
+
if (product) {
|
|
2516
|
+
await removeCartLines2({
|
|
2517
|
+
lineIds: [product.id]
|
|
2518
|
+
});
|
|
2519
|
+
}
|
|
2520
|
+
};
|
|
2521
|
+
if (isMonthlyPlus) {
|
|
2522
|
+
removePlusProduct(plus_monthly_product);
|
|
2523
|
+
}
|
|
2524
|
+
if (isAnnualPlus) {
|
|
2525
|
+
removePlusProduct(plus_annual_product);
|
|
2526
|
+
}
|
|
2527
|
+
}, [
|
|
2528
|
+
cart,
|
|
2529
|
+
plus_annual_product,
|
|
2530
|
+
plus_monthly_product,
|
|
2531
|
+
isAnnualPlus,
|
|
2532
|
+
isMonthlyPlus,
|
|
2533
|
+
removeCartLines2
|
|
2534
|
+
]);
|
|
2535
|
+
}
|
|
2536
|
+
var PlusMemberProvider = ({
|
|
2537
|
+
variant,
|
|
2538
|
+
product,
|
|
2539
|
+
shopCommon,
|
|
2540
|
+
metafields,
|
|
2541
|
+
initialSelectedPlusMemberMode = "free",
|
|
2542
|
+
profile,
|
|
2543
|
+
locale,
|
|
2544
|
+
children
|
|
2545
|
+
}) => {
|
|
2546
|
+
const [zipCode, setZipCode] = useState("");
|
|
2547
|
+
const [showTip, setShowTip] = useState(false);
|
|
2548
|
+
const [selectedPlusMemberMode, setSelectedPlusMemberMode] = useState(
|
|
2549
|
+
initialSelectedPlusMemberMode
|
|
2550
|
+
);
|
|
2551
|
+
const [selectedShippingMethod, setSelectedShippingMethod] = useState();
|
|
2552
|
+
const [allowNextDayDelivery, setAllowNextDayDelivery] = useState(false);
|
|
2553
|
+
const [allowThirdDayDelivery, setAllowThirdDayDelivery] = useState(false);
|
|
2554
|
+
const [showAreaCheckModal, setShowAreaCheckModal] = useState(false);
|
|
2555
|
+
const [showMoreShippingMethod, setShowMoreShippingMethod] = useState(false);
|
|
2556
|
+
const [showPlusMemberBenefit, setShowPlusMemberBenefit] = useState(false);
|
|
2557
|
+
const [deleteMarginBottom, setDeleteMarginBottom] = useState(false);
|
|
2558
|
+
const shippingMethodsContext = useShippingMethods({
|
|
2559
|
+
variant,
|
|
2560
|
+
plusMemberMetafields: metafields,
|
|
2561
|
+
selectedPlusMemberMode});
|
|
2562
|
+
const plusMemberHandles = useMemo(() => {
|
|
2563
|
+
return [
|
|
2564
|
+
metafields?.plus_monthly_product?.handle,
|
|
2565
|
+
metafields?.plus_annual_product?.handle
|
|
2566
|
+
].filter(Boolean);
|
|
2567
|
+
}, [metafields]);
|
|
2568
|
+
const { data: plusMemberProducts = [] } = useProductsByHandles({
|
|
2569
|
+
handles: plusMemberHandles
|
|
2570
|
+
});
|
|
2571
|
+
const selectedPlusMemberProduct = useMemo(() => {
|
|
2572
|
+
if (selectedPlusMemberMode === "free" /* FREE */) {
|
|
2573
|
+
return null;
|
|
2574
|
+
}
|
|
2575
|
+
const handle = selectedPlusMemberMode === "monthly" /* MONTHLY */ ? metafields?.plus_monthly_product?.handle : metafields?.plus_annual_product?.handle;
|
|
2576
|
+
const sku = selectedPlusMemberMode === "monthly" /* MONTHLY */ ? metafields?.plus_monthly_product?.sku : metafields?.plus_annual_product?.sku;
|
|
2577
|
+
const product2 = plusMemberProducts?.find((p) => p.handle === handle);
|
|
2578
|
+
const variant2 = product2?.variants?.find((v) => v.sku === sku);
|
|
2579
|
+
return product2 && variant2 ? { product: product2, variant: variant2 } : null;
|
|
2580
|
+
}, [plusMemberProducts, metafields, selectedPlusMemberMode]);
|
|
2581
|
+
return /* @__PURE__ */ jsx(
|
|
2582
|
+
PlusMemberContext.Provider,
|
|
2583
|
+
{
|
|
2584
|
+
value: {
|
|
2585
|
+
variant,
|
|
2586
|
+
shopCommon,
|
|
2587
|
+
zipCode,
|
|
2588
|
+
setZipCode,
|
|
2589
|
+
allowNextDayDelivery,
|
|
2590
|
+
setAllowNextDayDelivery,
|
|
2591
|
+
allowThirdDayDelivery,
|
|
2592
|
+
setAllowThirdDayDelivery,
|
|
2593
|
+
plusMemberMetafields: metafields,
|
|
2594
|
+
selectedPlusMemberMode,
|
|
2595
|
+
setSelectedPlusMemberMode,
|
|
2596
|
+
showAreaCheckModal,
|
|
2597
|
+
setShowAreaCheckModal,
|
|
2598
|
+
selectedShippingMethod,
|
|
2599
|
+
setSelectedShippingMethod,
|
|
2600
|
+
shippingMethodsContext,
|
|
2601
|
+
showTip,
|
|
2602
|
+
setShowTip,
|
|
2603
|
+
showMoreShippingMethod,
|
|
2604
|
+
setShowMoreShippingMethod,
|
|
2605
|
+
selectedPlusMemberProduct,
|
|
2606
|
+
plusMemberProducts,
|
|
2607
|
+
product,
|
|
2608
|
+
showPlusMemberBenefit,
|
|
2609
|
+
setShowPlusMemberBenefit,
|
|
2610
|
+
deleteMarginBottom,
|
|
2611
|
+
setDeleteMarginBottom,
|
|
2612
|
+
profile,
|
|
2613
|
+
locale
|
|
2614
|
+
},
|
|
2615
|
+
children
|
|
2616
|
+
}
|
|
2617
|
+
);
|
|
2618
|
+
};
|
|
2619
|
+
function useIntersection(targetRef, options) {
|
|
2620
|
+
const {
|
|
2621
|
+
callback,
|
|
2622
|
+
once = false,
|
|
2623
|
+
root = null,
|
|
2624
|
+
rootMargin = "0px",
|
|
2625
|
+
threshold = 0.8
|
|
2626
|
+
} = options;
|
|
2627
|
+
useEffect(() => {
|
|
2628
|
+
if (!targetRef?.current) {
|
|
2629
|
+
return;
|
|
2630
|
+
}
|
|
2631
|
+
if (typeof IntersectionObserver === "undefined") {
|
|
2632
|
+
console.warn("[useIntersection] IntersectionObserver is not supported");
|
|
2633
|
+
return;
|
|
2634
|
+
}
|
|
2635
|
+
const current = targetRef.current;
|
|
2636
|
+
const observerOptions = {
|
|
2637
|
+
root,
|
|
2638
|
+
rootMargin,
|
|
2639
|
+
threshold
|
|
2640
|
+
};
|
|
2641
|
+
const observer = new IntersectionObserver((entries) => {
|
|
2642
|
+
entries.forEach((entry) => {
|
|
2643
|
+
if (entry.isIntersecting) {
|
|
2644
|
+
callback();
|
|
2645
|
+
if (once) {
|
|
2646
|
+
observer.disconnect();
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2649
|
+
});
|
|
2650
|
+
}, observerOptions);
|
|
2651
|
+
observer.observe(current);
|
|
2652
|
+
return () => {
|
|
2653
|
+
observer.disconnect();
|
|
2654
|
+
};
|
|
2655
|
+
}, [targetRef, callback, once, root, rootMargin, threshold]);
|
|
2656
|
+
}
|
|
2657
|
+
function useExposure(targetRef, options) {
|
|
2658
|
+
const { threshold = 0.5, duration = 2e3, once = true, onExposure } = options;
|
|
2659
|
+
const [isVisible, setIsVisible] = useState(false);
|
|
2660
|
+
const timeoutRef = useRef(void 0);
|
|
2661
|
+
const hasTriggeredRef = useRef(false);
|
|
2662
|
+
useEffect(() => {
|
|
2663
|
+
if (!targetRef?.current || typeof IntersectionObserver === "undefined") {
|
|
2664
|
+
return;
|
|
2665
|
+
}
|
|
2666
|
+
if (once && hasTriggeredRef.current) {
|
|
2667
|
+
return;
|
|
2668
|
+
}
|
|
2669
|
+
const current = targetRef.current;
|
|
2670
|
+
const clearTimer = () => {
|
|
2671
|
+
if (timeoutRef.current) {
|
|
2672
|
+
clearTimeout(timeoutRef.current);
|
|
2673
|
+
timeoutRef.current = void 0;
|
|
2674
|
+
}
|
|
2675
|
+
};
|
|
2676
|
+
const observer = new IntersectionObserver(
|
|
2677
|
+
(entries) => {
|
|
2678
|
+
entries.forEach((entry) => {
|
|
2679
|
+
setIsVisible(entry.isIntersecting);
|
|
2680
|
+
if (entry.isIntersecting) {
|
|
2681
|
+
timeoutRef.current = setTimeout(() => {
|
|
2682
|
+
if (once && hasTriggeredRef.current) {
|
|
2683
|
+
return;
|
|
2684
|
+
}
|
|
2685
|
+
onExposure();
|
|
2686
|
+
hasTriggeredRef.current = true;
|
|
2687
|
+
if (once) {
|
|
2688
|
+
observer.disconnect();
|
|
2689
|
+
}
|
|
2690
|
+
}, duration);
|
|
2691
|
+
} else {
|
|
2692
|
+
clearTimer();
|
|
2693
|
+
}
|
|
2694
|
+
});
|
|
2695
|
+
},
|
|
2696
|
+
{
|
|
2697
|
+
root: null,
|
|
2698
|
+
rootMargin: "0px",
|
|
2699
|
+
threshold
|
|
2700
|
+
}
|
|
2701
|
+
);
|
|
2702
|
+
observer.observe(current);
|
|
2703
|
+
return () => {
|
|
2704
|
+
clearTimer();
|
|
2705
|
+
observer.disconnect();
|
|
2706
|
+
};
|
|
2707
|
+
}, [targetRef, threshold, duration, once, onExposure]);
|
|
2708
|
+
return isVisible;
|
|
2709
|
+
}
|
|
2710
|
+
function determineSuggestedLocale(countryCode, mapping) {
|
|
2711
|
+
if (!countryCode) {
|
|
2712
|
+
return "us";
|
|
2713
|
+
}
|
|
2714
|
+
const upperCode = countryCode.toUpperCase();
|
|
2715
|
+
if (mapping?.customMapping?.[upperCode]) {
|
|
2716
|
+
return mapping.customMapping[upperCode];
|
|
2717
|
+
}
|
|
2718
|
+
if (mapping?.euCountries?.includes(upperCode)) {
|
|
2719
|
+
if (upperCode === "PL") {
|
|
2720
|
+
return "pl";
|
|
2721
|
+
}
|
|
2722
|
+
return "eu";
|
|
2723
|
+
}
|
|
2724
|
+
if (mapping?.auCountries?.includes(upperCode)) {
|
|
2725
|
+
return "au";
|
|
2726
|
+
}
|
|
2727
|
+
if (mapping?.deCountries?.includes(upperCode)) {
|
|
2728
|
+
return "de";
|
|
2729
|
+
}
|
|
2730
|
+
if (mapping?.aeEnCountries?.includes(upperCode)) {
|
|
2731
|
+
return "ae-en";
|
|
2732
|
+
}
|
|
2733
|
+
if (upperCode === "GB") {
|
|
2734
|
+
return "uk";
|
|
2735
|
+
}
|
|
2736
|
+
return countryCode.toLowerCase();
|
|
2737
|
+
}
|
|
2738
|
+
function useGeoLocation(options = {}) {
|
|
2739
|
+
const {
|
|
2740
|
+
endpoint = "/geolocation",
|
|
2741
|
+
cacheKey = "geoLocation",
|
|
2742
|
+
cacheDuration = 1e3 * 60 * 60 * 24,
|
|
2743
|
+
// 24 hours
|
|
2744
|
+
localeMapping,
|
|
2745
|
+
enableCache = true,
|
|
2746
|
+
...swrOptions
|
|
2747
|
+
} = options;
|
|
2748
|
+
const fetcher = async () => {
|
|
2749
|
+
if (enableCache) {
|
|
2750
|
+
const cached = getLocalStorage(cacheKey);
|
|
2751
|
+
if (cached) {
|
|
2752
|
+
return cached;
|
|
2753
|
+
}
|
|
2754
|
+
}
|
|
2755
|
+
try {
|
|
2756
|
+
const response = await fetch(endpoint);
|
|
2757
|
+
if (!response.ok) {
|
|
2758
|
+
throw new Error(`Failed to fetch geo location: ${response.status}`);
|
|
2759
|
+
}
|
|
2760
|
+
const result = await response.json();
|
|
2761
|
+
const countryCode = result?.geo?.country?.code;
|
|
2762
|
+
if (!countryCode) {
|
|
2763
|
+
console.warn("[useGeoLocation] No country code in response");
|
|
2764
|
+
return void 0;
|
|
2765
|
+
}
|
|
2766
|
+
const suggestLocale = determineSuggestedLocale(
|
|
2767
|
+
countryCode,
|
|
2768
|
+
localeMapping
|
|
2769
|
+
);
|
|
2770
|
+
const geoData = {
|
|
2771
|
+
geo: result.geo,
|
|
2772
|
+
suggestLocale
|
|
2773
|
+
};
|
|
2774
|
+
if (enableCache) {
|
|
2775
|
+
const expires = new Date(Date.now() + cacheDuration);
|
|
2776
|
+
setLocalStorage(cacheKey, geoData, { expires });
|
|
2777
|
+
}
|
|
2778
|
+
return geoData;
|
|
2779
|
+
} catch (error) {
|
|
2780
|
+
console.error("[useGeoLocation] Error fetching geo data:", error);
|
|
2781
|
+
return void 0;
|
|
2782
|
+
}
|
|
2783
|
+
};
|
|
2784
|
+
return useSWR(
|
|
2785
|
+
cacheKey,
|
|
2786
|
+
fetcher,
|
|
2787
|
+
swrOptions
|
|
2788
|
+
);
|
|
2789
|
+
}
|
|
2790
|
+
function getCachedGeoLocation(cacheKey = "geoLocation") {
|
|
2791
|
+
return getLocalStorage(cacheKey) ?? void 0;
|
|
2792
|
+
}
|
|
2793
|
+
function clearGeoLocationCache(cacheKey = "geoLocation") {
|
|
2794
|
+
if (typeof localStorage !== "undefined") {
|
|
2795
|
+
localStorage.removeItem(cacheKey);
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2798
|
+
|
|
2799
|
+
export { BuyRuleType, CODE_AMOUNT_KEY, CUSTOMER_ATTRIBUTE_KEY, CUSTOMER_SCRIPT_GIFT_KEY, DeliveryPlusType, MAIN_PRODUCT_CODE, OrderBasePriceType, OrderDiscountType, PLUS_MEMBER_TYPE, PlusMemberContext, PlusMemberMode, PlusMemberProvider, PriceBasePriceType, PriceDiscountType, RuleType, SCRIPT_CODE_AMOUNT_KEY, ShippingMethodMode, SpendMoneyType, atobID, btoaID, clearGeoLocationCache, currencyCodeMapping, defaultSWRMutationConfiguration, formatFunctionAutoFreeGift, formatScriptAutoFreeGift, getCachedGeoLocation, getDiscountEnvAttributeValue, getMatchedMainProductSubTotal, getQuery, getReferralAttributes, isAttributesEqual, preCheck, safeParseJson, useAddCartLines, useAddToCart, useAllBlogs, useAllCollections, useAllProducts, useApplyCartCodes, useArticle, useArticles, useArticlesInBlog, useAutoRemovePlusMemberInCart, useBlog, useBuyNow, useCalcAutoFreeGift, useCalcOrderDiscount, useCartAttributes, useCartItemQuantityLimit, useCollection, useCollections, useCreateCart, useExposure, useGeoLocation, useHasPlusMemberInCart, useIntersection, usePlusAnnualProductVariant, usePlusMemberCheckoutCustomAttributes, usePlusMemberContext, usePlusMemberDeliveryCodes, usePlusMemberItemCustomAttributes, usePlusMonthlyProductVariant, usePrice, useProduct, useProductUrl, useProductsByHandles, useRemoveCartCodes, useRemoveCartLines, useReplaceCartPlusMember, useScriptAutoFreeGift, useSearch, useSelectedOptions, useShippingMethodAvailableCheck, useShippingMethods, useSite, useUpdateCartAttributes, useUpdateCartLines, useUpdateLineCodeAmountAttributes, useUpdateVariantQuery, useVariant, useVariantMedia };
|
|
2800
|
+
//# sourceMappingURL=index.mjs.map
|
|
2801
|
+
//# sourceMappingURL=index.mjs.map
|