@anker-in/shopify-react 0.1.1-beta.2 → 0.1.1-beta.20

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.
@@ -71,6 +71,81 @@ var CODE_AMOUNT_KEY = "_sku_code_money";
71
71
  var SCRIPT_CODE_AMOUNT_KEY = "_code_money";
72
72
  var MAIN_PRODUCT_CODE = ["WS24", "WSTD", "WS7D", "WSCP", "WSPE", "WSPD"];
73
73
 
74
+ // src/hooks/cart/utils/normalize-add-to-cart-lines.ts
75
+ function normalizeAddToCartLines(lines) {
76
+ return lines.filter((line) => line.variant?.id).map((line, index) => {
77
+ const variant = line.variant;
78
+ const product = variant.product;
79
+ const quantity = line.quantity || 1;
80
+ const price = variant.finalPrice?.amount ? Number(variant.finalPrice.amount) : variant.compareAtPrice?.amount ? Number(variant.compareAtPrice.amount) : variant.price?.amount ? Number(variant.price.amount) : 0;
81
+ const subtotalAmount = price * quantity;
82
+ const totalAmount = subtotalAmount;
83
+ return {
84
+ id: `temp-line-${index}-${variant.id}`,
85
+ // Temporary ID for pre-cart lines
86
+ name: product?.title || variant.title || "",
87
+ quantity,
88
+ variantId: variant.id,
89
+ productId: product?.id || variant.id.split("/").slice(0, -2).join("/"),
90
+ totalAmount,
91
+ subtotalAmount,
92
+ discountAllocations: [],
93
+ customAttributes: line.attributes || [],
94
+ variant: {
95
+ id: variant.id,
96
+ price,
97
+ listPrice: variant.compareAtPrice?.amount ? Number(variant.compareAtPrice.amount) : 0,
98
+ sku: variant.sku || "",
99
+ name: variant.title || "",
100
+ image: variant.image ? {
101
+ url: variant.image.url,
102
+ altText: variant.image.altText || void 0
103
+ } : void 0,
104
+ requiresShipping: false,
105
+ // Default value, not available in NormalizedProductVariant
106
+ availableForSale: variant.availableForSale ?? true,
107
+ quantityAvailable: variant.quantityAvailable ?? 0,
108
+ currentlyNotInStock: false,
109
+ // Default value, will be updated when added to cart
110
+ weight: variant.weight,
111
+ metafields: variant.metafields
112
+ },
113
+ product,
114
+ path: product?.handle ? `/products/${product.handle}` : "",
115
+ discounts: [],
116
+ options: variant.selectedOptions?.map((opt) => ({
117
+ name: opt.name,
118
+ value: opt.value
119
+ }))
120
+ };
121
+ });
122
+ }
123
+ function createMockCartFromLines(lines, existingCart) {
124
+ const normalizedLines = normalizeAddToCartLines(lines);
125
+ const subtotalPrice = normalizedLines.reduce((sum, line) => sum + line.subtotalAmount, 0);
126
+ const totalPrice = normalizedLines.reduce((sum, line) => sum + line.totalAmount, 0);
127
+ return {
128
+ id: existingCart?.id || "temp-cart-id",
129
+ customerId: existingCart?.customerId,
130
+ email: existingCart?.email,
131
+ createdAt: existingCart?.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
132
+ currency: existingCart?.currency || { code: "USD" },
133
+ taxesIncluded: existingCart?.taxesIncluded,
134
+ lineItems: normalizedLines,
135
+ totalLineItemsDiscount: 0,
136
+ orderDiscounts: 0,
137
+ lineItemsSubtotalPrice: subtotalPrice,
138
+ subtotalPrice,
139
+ totalPrice,
140
+ totalTaxAmount: 0,
141
+ discountCodes: existingCart?.discountCodes || [],
142
+ discountAllocations: [],
143
+ url: existingCart?.url || "",
144
+ ready: true,
145
+ customAttributes: existingCart?.customAttributes
146
+ };
147
+ }
148
+
74
149
  // src/hooks/cart/utils/index.ts
75
150
  var getQuery = () => {
76
151
  const url = typeof window !== "undefined" ? window.location.search : "";
@@ -88,22 +163,12 @@ var getQuery = () => {
88
163
  }
89
164
  return theRequest;
90
165
  };
91
- function atobID(id) {
92
- if (id && typeof id === "string" && id.includes("/")) {
93
- return id.split("/").pop()?.split("?")?.shift();
94
- } else {
95
- return id;
96
- }
97
- }
98
- function btoaID(id, type = "ProductVariant") {
99
- return `gid://shopify/${type}/${id}`;
100
- }
101
166
  var getMatchedMainProductSubTotal = (cartData, variant_list, main_product) => {
102
167
  const isAllStoreVariant = main_product?.all_store_variant ?? false;
103
168
  const matchedList = cartData?.lineItems?.filter((line) => {
104
169
  const { is_gift } = getDiscountEnvAttributeValue(line.customAttributes);
105
170
  return isAllStoreVariant ? !is_gift : variant_list?.find((item) => {
106
- return !is_gift && atobID(line.variantId) === item;
171
+ return !is_gift && shopifySdk.atobID(line.variantId) === item;
107
172
  });
108
173
  });
109
174
  return matchedList?.reduce((acc, line) => {
@@ -295,12 +360,18 @@ var formatFunctionAutoFreeGift = ({
295
360
  };
296
361
  return result;
297
362
  };
298
- var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
363
+ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
299
364
  const tags = react.useMemo(() => customer?.tags || [], [customer?.tags]);
300
365
  const isCustomerLoading = react.useMemo(() => !customer ? true : false, [customer]);
301
366
  const dealsType = "";
302
367
  const { client, locale } = useShopify();
303
368
  const giftProductsCache = react.useRef(null);
369
+ const effectiveCart = react.useMemo(() => {
370
+ if (lines && lines.length > 0) {
371
+ return createMockCartFromLines(lines, cart);
372
+ }
373
+ return cart;
374
+ }, [lines, cart]);
304
375
  const { activeCampaign, subtotal } = react.useMemo(() => {
305
376
  for (const campaign of autoFreeGiftConfig) {
306
377
  const { rule_conditions = [], rule_result } = campaign;
@@ -308,7 +379,7 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
308
379
  const isPreCheckPassed = preCheck(rule_conditions, tags, []);
309
380
  if (isPreCheckPassed && spend_get_reward) {
310
381
  const matchedSubtotal = getMatchedMainProductSubTotal(
311
- cart,
382
+ effectiveCart,
312
383
  spend_get_reward.main_product?.variant_list?.map((v) => v.variant_id) || [],
313
384
  {
314
385
  spend_money_type: spend_get_reward.main_product?.spend_money_type || 1,
@@ -322,13 +393,13 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
322
393
  }
323
394
  }
324
395
  return { activeCampaign: null, subtotal: 0 };
325
- }, [autoFreeGiftConfig, cart, tags, dealsType]);
396
+ }, [autoFreeGiftConfig, effectiveCart, tags, dealsType]);
326
397
  const { qualifyingGift, nextTierGoal } = react.useMemo(() => {
327
398
  if (!activeCampaign || !activeCampaign.rule_result?.spend_get_reward?.gift_product) {
328
399
  return { qualifyingGift: null, nextTierGoal: null };
329
400
  }
330
401
  const giftTiers = activeCampaign.rule_result.spend_get_reward.gift_product;
331
- const qualifyingTier = [...giftTiers].reverse().find((tier) => subtotal >= Number(tier.spend_sum_money));
402
+ const qualifyingTier = [...giftTiers].sort((a, b) => Number(b.spend_sum_money) - Number(a.spend_sum_money)).find((tier) => subtotal >= Number(tier.spend_sum_money));
332
403
  const nextGoal = giftTiers.find((tier) => subtotal < Number(tier.spend_sum_money));
333
404
  if (!qualifyingTier) {
334
405
  return { qualifyingGift: null, nextTierGoal: nextGoal || null };
@@ -340,7 +411,7 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
340
411
  if (!giftProduct) return null;
341
412
  return {
342
413
  variant: {
343
- id: btoaID(giftProduct.variant_id),
414
+ id: shopifySdk.btoaID(giftProduct.variant_id),
344
415
  handle: giftProduct.handle,
345
416
  sku: giftProduct.sku
346
417
  },
@@ -375,18 +446,24 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
375
446
  }
376
447
  return true;
377
448
  }, [giftHandles]);
378
- const { data: giftProductsResult } = useSWR__default.default(shouldFetch ? giftHandles : null, async () => {
379
- const res = await shopifySdk.getProductsByHandles(client, {
380
- handles: giftHandles,
381
- locale
382
- });
383
- const result = Array.isArray(res) ? res : [];
384
- giftProductsCache.current = {
385
- data: result,
386
- giftHandles: [...giftHandles]
387
- };
388
- return result;
389
- });
449
+ const { data: giftProductsResult } = useSWR__default.default(
450
+ shouldFetch ? giftHandles : null,
451
+ async () => {
452
+ const res = await shopifySdk.getProductsByHandles(client, {
453
+ handles: giftHandles,
454
+ locale
455
+ });
456
+ const result = Array.isArray(res) ? res : [];
457
+ giftProductsCache.current = {
458
+ data: result,
459
+ giftHandles: [...giftHandles]
460
+ };
461
+ return result;
462
+ },
463
+ {
464
+ revalidateOnFocus: false
465
+ }
466
+ );
390
467
  const finalGiftProductsResult = react.useMemo(() => {
391
468
  if (giftProductsCache.current && !shouldFetch) {
392
469
  return giftProductsCache.current.data || void 0;
@@ -405,12 +482,19 @@ var useScriptAutoFreeGift = ({
405
482
  campaign,
406
483
  _giveaway,
407
484
  cart,
408
- locale: providedLocale
485
+ locale: providedLocale,
486
+ lines
409
487
  }) => {
410
488
  const { client, locale: contextLocale } = useShopify();
411
489
  const locale = providedLocale || contextLocale;
412
490
  const [points_subscribe, set_points_subscribe] = react.useState(false);
413
491
  const giftProductsCache = react.useRef(null);
492
+ const effectiveCart = react.useMemo(() => {
493
+ if (lines && lines.length > 0) {
494
+ return createMockCartFromLines(lines, cart);
495
+ }
496
+ return cart;
497
+ }, [lines, cart]);
414
498
  react.useEffect(() => {
415
499
  if (locale === "au") {
416
500
  const isPointsSubscribe = Cookies5__default.default.get("points_subscribe");
@@ -432,14 +516,16 @@ var useScriptAutoFreeGift = ({
432
516
  upgrade_multiple2 = 1.2;
433
517
  upgrade_value2 = 40;
434
518
  }
435
- cart?.lineItems?.forEach(({ customAttributes }) => {
436
- customAttributes?.forEach(({ key, value }) => {
437
- if (key === "_amount_upgrade_multiple") upgrade_multiple2 = Number(value) || 1;
438
- if (key === "_amount_upgrade_value") upgrade_value2 = Number(value) || 0;
439
- });
440
- });
519
+ effectiveCart?.lineItems?.forEach(
520
+ ({ customAttributes }) => {
521
+ customAttributes?.forEach(({ key, value }) => {
522
+ if (key === "_amount_upgrade_multiple") upgrade_multiple2 = Number(value) || 1;
523
+ if (key === "_amount_upgrade_value") upgrade_value2 = Number(value) || 0;
524
+ });
525
+ }
526
+ );
441
527
  return [upgrade_multiple2, upgrade_value2];
442
- }, [cart?.lineItems, points_subscribe]);
528
+ }, [effectiveCart?.lineItems, points_subscribe]);
443
529
  const breakpoints = react.useMemo(() => {
444
530
  if (!isActivityAvailable) return [];
445
531
  return (campaign?.breakpoints || []).map((item) => ({
@@ -467,7 +553,7 @@ var useScriptAutoFreeGift = ({
467
553
  }, [giftHandles]);
468
554
  const involvedLines = react.useMemo(() => {
469
555
  if (!isActivityAvailable) return [];
470
- return (cart?.lineItems || []).filter((line) => {
556
+ return (effectiveCart?.lineItems || []).filter((line) => {
471
557
  const isNotGift = line?.totalAmount && Number(line.totalAmount) > 0 && line.customAttributes?.every(
472
558
  (item) => item.key !== _giveaway
473
559
  );
@@ -476,7 +562,7 @@ var useScriptAutoFreeGift = ({
476
562
  );
477
563
  return isNotGift && hasCampaignTag;
478
564
  });
479
- }, [cart?.lineItems, isActivityAvailable, _giveaway]);
565
+ }, [effectiveCart?.lineItems, isActivityAvailable, _giveaway]);
480
566
  const involvedSubTotal = react.useMemo(() => {
481
567
  if (!isActivityAvailable) return new Decimal2__default.default(0);
482
568
  return involvedLines.reduce((prev, item) => {
@@ -502,18 +588,24 @@ var useScriptAutoFreeGift = ({
502
588
  const nextLevel = levelIndex > 0 ? sortedLevels[levelIndex - 1] ?? null : null;
503
589
  return [currentLevel, nextLevel];
504
590
  }, [breakpoints, involvedSubTotal, involvedLines.length]);
505
- const { data: giftProductsResult } = useSWR__default.default(shouldFetch ? giftHandles : null, async () => {
506
- const res = await shopifySdk.getProductsByHandles(client, {
507
- handles: giftHandles,
508
- locale
509
- });
510
- const result = Array.isArray(res) ? res : [];
511
- giftProductsCache.current = {
512
- data: result,
513
- giftHandles: [...giftHandles]
514
- };
515
- return result;
516
- });
591
+ const { data: giftProductsResult } = useSWR__default.default(
592
+ shouldFetch ? giftHandles : null,
593
+ async () => {
594
+ const res = await shopifySdk.getProductsByHandles(client, {
595
+ handles: giftHandles,
596
+ locale
597
+ });
598
+ const result = Array.isArray(res) ? res : [];
599
+ giftProductsCache.current = {
600
+ data: result,
601
+ giftHandles: [...giftHandles]
602
+ };
603
+ return result;
604
+ },
605
+ {
606
+ revalidateOnFocus: false
607
+ }
608
+ );
517
609
  const finalGiftProductsResult = react.useMemo(() => {
518
610
  if (giftProductsCache.current && !shouldFetch) {
519
611
  return giftProductsCache.current.data || void 0;
@@ -751,7 +843,7 @@ function useApplyCartCodes(options) {
751
843
  if (!discountCodes?.length) {
752
844
  throw new Error("Invalid input used for this operation: Miss discountCode");
753
845
  }
754
- const cartId = providedCartId ? void 0 : providedCartId || cart?.id;
846
+ const cartId = providedCartId || cart?.id;
755
847
  if (!cartId) {
756
848
  return void 0;
757
849
  }
@@ -779,7 +871,7 @@ function useRemoveCartCodes(options) {
779
871
  const removeCodes = react.useCallback(
780
872
  async (_key, { arg }) => {
781
873
  const { cartId: providedCartId, discountCodes } = arg;
782
- const cartId = providedCartId ? void 0 : providedCartId || cart?.id;
874
+ const cartId = providedCartId || cart?.id;
783
875
  const codes = cart?.discountCodes?.filter((code) => !!code.applicable) || [];
784
876
  const leftCodes = codes.filter((code) => discountCodes?.length ? !discountCodes.includes(code.code) : code.code).map((code) => code.code);
785
877
  const updatedCart = await shopifySdk.updateCartCodes(client, {
@@ -801,7 +893,7 @@ function useRemoveCartCodes(options) {
801
893
  // src/hooks/cart/use-add-to-cart.ts
802
894
  function useAddToCart({ withTrack = true } = {}, swrOptions) {
803
895
  const { client, config, locale, cartCookieAdapter, userAdapter } = useShopify();
804
- const { cart } = useCartContext();
896
+ const { cart, addCustomAttributes } = useCartContext();
805
897
  const { trigger: applyCartCodes } = useApplyCartCodes();
806
898
  const { trigger: removeInvalidCodes } = useRemoveCartCodes();
807
899
  const { trigger: addCartLines2 } = useAddCartLines();
@@ -815,7 +907,8 @@ function useAddToCart({ withTrack = true } = {}, swrOptions) {
815
907
  buyerIdentity,
816
908
  needCreateCart = false,
817
909
  onCodesInvalid,
818
- replaceExistingCodes
910
+ replaceExistingCodes,
911
+ customAttributes
819
912
  } = arg;
820
913
  if (!lineItems || lineItems.length === 0) {
821
914
  return;
@@ -838,6 +931,7 @@ function useAddToCart({ withTrack = true } = {}, swrOptions) {
838
931
  if (!resultCart) {
839
932
  return void 0;
840
933
  }
934
+ console.log("npm addCartLines resultCart", resultCart);
841
935
  if (resultCart.discountCodes && resultCart.discountCodes.length > 0) {
842
936
  const unapplicableCodes = resultCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
843
937
  if (unapplicableCodes.length > 0) {
@@ -859,6 +953,9 @@ function useAddToCart({ withTrack = true } = {}, swrOptions) {
859
953
  discountCodes
860
954
  });
861
955
  }
956
+ if (customAttributes && customAttributes.length > 0) {
957
+ addCustomAttributes(customAttributes);
958
+ }
862
959
  if (withTrack) {
863
960
  trackAddToCartGA({
864
961
  lineItems,
@@ -1011,6 +1108,60 @@ function useBuyNow({ withTrack = true } = {}, swrOptions) {
1011
1108
  );
1012
1109
  return useSWRMutation__default.default("buy-now", buyNow, swrOptions);
1013
1110
  }
1111
+ function useCalcGiftsFromLines({
1112
+ lines,
1113
+ customer,
1114
+ scriptGiveawayKey = CUSTOMER_SCRIPT_GIFT_KEY
1115
+ }) {
1116
+ const { locale } = useShopify();
1117
+ const { cart, autoFreeGiftConfig, gradientGiftsConfig } = useCartContext();
1118
+ const functionGift = useCalcAutoFreeGift(cart, autoFreeGiftConfig || [], customer, lines);
1119
+ const scriptGift = useScriptAutoFreeGift({
1120
+ campaign: gradientGiftsConfig || null,
1121
+ _giveaway: scriptGiveawayKey,
1122
+ cart,
1123
+ locale,
1124
+ lines
1125
+ });
1126
+ const allGiftLines = react.useMemo(() => {
1127
+ const functionGiftLines = functionGift.qualifyingGift?.itemsToAdd || [];
1128
+ const scriptGiftLines = scriptGift.freeGiftLevel ? scriptGift.freeGiftLevel.giveawayProducts.map((product) => {
1129
+ const giftProduct = scriptGift.giftProductsResult?.find(
1130
+ (p) => p.handle === product.handle
1131
+ );
1132
+ const variant = giftProduct?.variants?.[0];
1133
+ return {
1134
+ variant: {
1135
+ id: variant?.id || "",
1136
+ handle: product.handle,
1137
+ sku: product.sku
1138
+ },
1139
+ quantity: 1,
1140
+ attributes: [
1141
+ {
1142
+ key: scriptGiveawayKey,
1143
+ value: "true"
1144
+ }
1145
+ ]
1146
+ };
1147
+ }).filter((item) => item.variant.id) : [];
1148
+ return [...functionGiftLines, ...scriptGiftLines];
1149
+ }, [
1150
+ functionGift.qualifyingGift,
1151
+ scriptGift.freeGiftLevel,
1152
+ scriptGift.giftProductsResult,
1153
+ scriptGiveawayKey
1154
+ ]);
1155
+ const hasGifts = react.useMemo(() => {
1156
+ return allGiftLines.length > 0;
1157
+ }, [allGiftLines]);
1158
+ return {
1159
+ functionGift,
1160
+ scriptGift,
1161
+ allGiftLines,
1162
+ hasGifts
1163
+ };
1164
+ }
1014
1165
 
1015
1166
  // src/hooks/cart/types/order-discount.ts
1016
1167
  var OrderDiscountType = /* @__PURE__ */ ((OrderDiscountType2) => {
@@ -1131,12 +1282,10 @@ function useHasPlusMemberInCart({
1131
1282
  };
1132
1283
  }, [cart?.lineItems, plus_monthly_product, plus_annual_product]);
1133
1284
  }
1134
-
1135
- // src/hooks/cart/feature/use-cart-attributes.ts
1136
1285
  var getReferralAttributes = () => {
1137
- const inviteCode = Cookies5__default.default.get("invite_code");
1138
- const playModeId = Cookies5__default.default.get("playModeId");
1139
- const popup = Cookies5__default.default.get("_popup");
1286
+ const inviteCode = shopifySdk.getLocalStorage("invite_code") || Cookies5__default.default.get("invite_code");
1287
+ const playModeId = shopifySdk.getLocalStorage("playModeId") || Cookies5__default.default.get("playModeId");
1288
+ const popup = shopifySdk.getLocalStorage("_popup") || Cookies5__default.default.get("_popup");
1140
1289
  if (inviteCode && playModeId) {
1141
1290
  return popup ? [
1142
1291
  { key: "_invite_code", value: inviteCode ? inviteCode : "" },
@@ -1160,8 +1309,6 @@ var useCartAttributes = ({
1160
1309
  memberSetting,
1161
1310
  cart
1162
1311
  });
1163
- console.log("memberSetting", memberSetting);
1164
- console.log("hasPlusMember", hasPlusMember);
1165
1312
  react.useEffect(() => {
1166
1313
  setCurrentUrl(window.location.href);
1167
1314
  }, []);
@@ -1187,7 +1334,7 @@ var useCartAttributes = ({
1187
1334
  return "new_user_login";
1188
1335
  }, [customer]);
1189
1336
  const memberAttributes = react.useMemo(() => {
1190
- return [
1337
+ const attributes = [
1191
1338
  {
1192
1339
  key: "_token",
1193
1340
  value: profile?.token
@@ -1208,17 +1355,28 @@ var useCartAttributes = ({
1208
1355
  value: profile?.token ? "true" : "false"
1209
1356
  }
1210
1357
  ];
1358
+ if (profile?.token) {
1359
+ attributes.push({
1360
+ key: "_login_user",
1361
+ value: "1"
1362
+ });
1363
+ }
1364
+ return attributes;
1211
1365
  }, [profile?.memberType, profile?.token, userType, hasPlusMember]);
1212
1366
  const functionAttributes = react.useMemo(() => {
1213
- return [
1214
- cart?.discountCodes && {
1367
+ const hasFunctionEnvAttribute = cart?.lineItems.some(
1368
+ (item) => item.customAttributes?.some((attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY)
1369
+ );
1370
+ const discountCodes = cart?.discountCodes.map((item) => item.code).filter((code) => code) || [];
1371
+ return hasFunctionEnvAttribute ? [
1372
+ {
1215
1373
  key: "_discounts_function_env",
1216
1374
  value: JSON.stringify({
1217
- discount_code: cart?.discountCodes.map((item) => item.code),
1375
+ discount_code: discountCodes,
1218
1376
  user_tags: customer?.tags || []
1219
1377
  })
1220
1378
  }
1221
- ];
1379
+ ] : [];
1222
1380
  }, [cart]);
1223
1381
  const presellAttributes = react.useMemo(() => {
1224
1382
  return [
@@ -1250,18 +1408,50 @@ var useCartAttributes = ({
1250
1408
  }
1251
1409
  ];
1252
1410
  }, [currentUrl]);
1411
+ const commonAttributes = react.useMemo(
1412
+ () => [
1413
+ ...memberAttributes,
1414
+ ...functionAttributes,
1415
+ ...presellAttributes,
1416
+ ...weightAttributes,
1417
+ ...trackingAttributes,
1418
+ ...getReferralAttributes()
1419
+ ].filter((item) => item?.value),
1420
+ [memberAttributes, functionAttributes, presellAttributes, weightAttributes, trackingAttributes]
1421
+ );
1422
+ const extraAttributesInCart = react.useMemo(() => {
1423
+ const commonAttributeKeys = [
1424
+ // member attributes
1425
+ "_token",
1426
+ "_member_type",
1427
+ "_user_type",
1428
+ "_is_login",
1429
+ "_login_user",
1430
+ // function attributes
1431
+ "_discounts_function_env",
1432
+ // presell attributes
1433
+ "_presale",
1434
+ // weight attributes
1435
+ "_weight",
1436
+ "_app_source_name",
1437
+ // tracking attributes
1438
+ "utm_params",
1439
+ // referral attributes
1440
+ "_invite_code",
1441
+ "_play_mode_id",
1442
+ "_popup"
1443
+ ];
1444
+ return cart?.customAttributes?.filter(
1445
+ (item) => !commonAttributeKeys.includes(item.key)
1446
+ ) || [];
1447
+ }, [cart]);
1253
1448
  return react.useMemo(
1254
1449
  () => ({
1255
- attributes: [
1256
- ...memberAttributes,
1257
- ...functionAttributes,
1258
- ...presellAttributes,
1259
- ...weightAttributes,
1260
- ...trackingAttributes,
1261
- ...getReferralAttributes()
1262
- ].filter((item) => item?.value)
1450
+ attributes: [...commonAttributes, ...extraAttributesInCart].filter(
1451
+ (item) => item?.value
1452
+ )
1263
1453
  }),
1264
- [memberAttributes, functionAttributes, presellAttributes, weightAttributes, trackingAttributes]
1454
+ [commonAttributes, extraAttributesInCart]
1265
1455
  );
1266
1456
  };
1267
1457
  var DEFAULT_MIN = 1;
@@ -1478,8 +1668,9 @@ function useProductsByHandles(options = {}) {
1478
1668
  metafieldIdentifiers
1479
1669
  });
1480
1670
  },
1481
- swrOptions || {
1482
- revalidateOnFocus: false
1671
+ {
1672
+ revalidateOnFocus: false,
1673
+ ...swrOptions
1483
1674
  }
1484
1675
  );
1485
1676
  }
@@ -2395,6 +2586,73 @@ var usePlusMemberDeliveryCodes = ({
2395
2586
  [deliveryData]
2396
2587
  );
2397
2588
  };
2589
+ function useUpdateCartDeliveryOptions(mutate, metafieldIdentifiers, options) {
2590
+ const { client, locale, cartCookieAdapter } = useShopify();
2591
+ const updateDeliveryOptions = react.useCallback(
2592
+ async (_key, { arg }) => {
2593
+ const updatedCart = await shopifySdk.updateCartDeliveryOptions(client, {
2594
+ ...arg,
2595
+ metafieldIdentifiers,
2596
+ cookieAdapter: cartCookieAdapter
2597
+ });
2598
+ console.log("useUpdateCartDeliveryOptions updatedCart", updatedCart);
2599
+ if (updatedCart) {
2600
+ mutate(updatedCart);
2601
+ }
2602
+ return updatedCart;
2603
+ },
2604
+ [client, locale, cartCookieAdapter, mutate]
2605
+ );
2606
+ return useSWRMutation__default.default("update-cart-delivery-options", updateDeliveryOptions, options);
2607
+ }
2608
+
2609
+ // src/hooks/member/plus/use-update-plus-member-delivery-options.ts
2610
+ var useUpdatePlusMemberDeliveryOptions = ({
2611
+ options
2612
+ } = {}) => {
2613
+ const { cart: cartContextData, mutateCart, metafieldIdentifiers } = useCartContext();
2614
+ const { trigger: updateCartDeliveryOptions2 } = useUpdateCartDeliveryOptions(
2615
+ mutateCart,
2616
+ metafieldIdentifiers
2617
+ );
2618
+ const handler = react.useCallback(
2619
+ async (_, { arg }) => {
2620
+ const currentCart = arg?.cart || cartContextData;
2621
+ const { deliveryData } = arg;
2622
+ const firstDeliveryGroup = currentCart?.deliveryGroups?.[0];
2623
+ const deliveryGroupId = firstDeliveryGroup?.id;
2624
+ const selectedOptionCode = deliveryData?.deliveryCustomData?.selected_delivery_option?.code;
2625
+ if (!deliveryGroupId || !selectedOptionCode || selectedOptionCode === firstDeliveryGroup?.selectedDeliveryOption?.code) {
2626
+ return null;
2627
+ }
2628
+ const deliveryGroup = currentCart?.deliveryGroups?.find(
2629
+ (group) => group?.id === deliveryGroupId
2630
+ );
2631
+ const matchedOption = deliveryGroup?.deliveryOptions?.find(
2632
+ (option) => option?.code === selectedOptionCode
2633
+ );
2634
+ if (!matchedOption?.handle) {
2635
+ return null;
2636
+ }
2637
+ const deliveryOptions = [
2638
+ {
2639
+ deliveryGroupId,
2640
+ deliveryOptionHandle: matchedOption.handle
2641
+ }
2642
+ ];
2643
+ const updatedCart = await updateCartDeliveryOptions2({
2644
+ selectedDeliveryOptions: deliveryOptions,
2645
+ cartId: currentCart?.id
2646
+ });
2647
+ if (updatedCart && mutateCart) {
2648
+ mutateCart(updatedCart);
2649
+ }
2650
+ return updatedCart;
2651
+ },
2652
+ [cartContextData, updateCartDeliveryOptions2, mutateCart]
2653
+ );
2654
+ return useSWRMutation__default.default("update-cart-delivery-options", handler, options);
2655
+ };
2398
2656
  var usePlusMemberItemCustomAttributes = ({
2399
2657
  deliveryData
2400
2658
  }) => {
@@ -2414,48 +2672,18 @@ var usePlusMemberCheckoutCustomAttributes = ({
2414
2672
  deliveryData,
2415
2673
  product,
2416
2674
  variant,
2417
- customer,
2418
2675
  isShowShippingBenefits
2419
2676
  }) => {
2420
2677
  const { deliveryCustomData } = deliveryData || {};
2421
2678
  const { profile } = usePlusMemberContext();
2422
- const userType = react.useMemo(() => {
2423
- const customerInfo = customer;
2424
- if (!customerInfo) {
2425
- return "new_user_unlogin";
2426
- }
2427
- if (customer) {
2428
- const { orders = {} } = customer;
2429
- const edgesLength = orders?.edges?.length;
2430
- if (edgesLength === 1) {
2431
- return "old_user_orders_once";
2432
- } else if (edgesLength && edgesLength > 1) {
2433
- return "old_user_orders_twice";
2434
- }
2435
- }
2436
- return "new_user_login";
2437
- }, [customer]);
2438
2679
  return react.useMemo(() => {
2439
2680
  const checkoutCustomAttributes = [
2440
- {
2441
- key: "_token",
2442
- value: profile?.token || ""
2443
- },
2681
+ // _last_url: 付费会员结算完成之后 checkout 有一个继续购买的按钮, 用于跳转到继续购买的页面
2444
2682
  {
2445
2683
  key: "_last_url",
2446
2684
  value: typeof window !== "undefined" ? window.location.origin + window.location.pathname : ""
2447
- },
2448
- {
2449
- key: "_user_type",
2450
- value: userType
2451
2685
  }
2452
2686
  ];
2453
- if (profile) {
2454
- checkoutCustomAttributes.push({
2455
- key: "_login_user",
2456
- value: "1"
2457
- });
2458
- }
2459
2687
  if (deliveryCustomData) {
2460
2688
  checkoutCustomAttributes.push({
2461
2689
  key: "_checkout_delivery_custom",
@@ -2465,12 +2693,6 @@ var usePlusMemberCheckoutCustomAttributes = ({
2465
2693
  })
2466
2694
  });
2467
2695
  }
2468
- if (variant?.metafields?.presell) {
2469
- checkoutCustomAttributes.push({
2470
- key: "_presale",
2471
- value: "true"
2472
- });
2473
- }
2474
2696
  if (isShowShippingBenefits && !isShowShippingBenefits({ variant, product, setting: {} })) {
2475
2697
  checkoutCustomAttributes.push({
2476
2698
  key: "_hide_shipping",
@@ -2478,18 +2700,17 @@ var usePlusMemberCheckoutCustomAttributes = ({
2478
2700
  });
2479
2701
  }
2480
2702
  return checkoutCustomAttributes;
2481
- }, [deliveryCustomData, product, profile, userType, variant, isShowShippingBenefits]);
2703
+ }, [deliveryCustomData, product, profile, variant, isShowShippingBenefits]);
2482
2704
  };
2483
2705
  function useAutoRemovePlusMemberInCart({
2484
- metafields,
2485
- isMonthlyPlus,
2486
- isAnnualPlus
2706
+ cart,
2707
+ profile,
2708
+ memberSetting
2487
2709
  }) {
2488
- const { plus_monthly_product, plus_annual_product } = metafields || {};
2489
- const { cart } = useCartContext();
2710
+ const { plus_monthly_product, plus_annual_product } = memberSetting || {};
2490
2711
  const { trigger: removeCartLines2 } = useRemoveCartLines();
2491
2712
  react.useEffect(() => {
2492
- if (!cart) return;
2713
+ if (!cart || !plus_monthly_product || !plus_annual_product) return;
2493
2714
  const removePlusProduct = async (productType) => {
2494
2715
  if (!productType) return;
2495
2716
  const product = cart.lineItems?.find(
@@ -2501,33 +2722,25 @@ function useAutoRemovePlusMemberInCart({
2501
2722
  });
2502
2723
  }
2503
2724
  };
2504
- if (isMonthlyPlus) {
2725
+ if (profile?.isMonthlyPlus) {
2505
2726
  removePlusProduct(plus_monthly_product);
2506
2727
  }
2507
- if (isAnnualPlus) {
2728
+ if (profile?.isAnnualPlus) {
2508
2729
  removePlusProduct(plus_annual_product);
2509
2730
  }
2510
- }, [
2511
- cart,
2512
- plus_annual_product,
2513
- plus_monthly_product,
2514
- isAnnualPlus,
2515
- isMonthlyPlus,
2516
- removeCartLines2
2517
- ]);
2731
+ }, [cart, plus_annual_product, plus_monthly_product, profile, removeCartLines2]);
2518
2732
  }
2519
2733
  function useAddPlusMemberProductsToCart({
2520
2734
  cart,
2521
- memberSetting,
2522
- selectedPlusMemberMode,
2523
- selectedPlusMemberProduct
2735
+ profile
2524
2736
  }) {
2737
+ const { selectedPlusMemberMode, selectedPlusMemberProduct, plusMemberMetafields } = usePlusMemberContext();
2525
2738
  const { hasMonthlyPlus, hasAnnualPlus } = useHasPlusMemberInCart({
2526
- cart,
2527
- memberSetting
2739
+ memberSetting: plusMemberMetafields,
2740
+ cart
2528
2741
  });
2529
2742
  const plusMemberProduct = react.useMemo(() => {
2530
- if (selectedPlusMemberMode === "free" /* FREE */) {
2743
+ if (!selectedPlusMemberProduct || selectedPlusMemberMode === "free" /* FREE */) {
2531
2744
  return void 0;
2532
2745
  }
2533
2746
  if (selectedPlusMemberMode === "monthly" /* MONTHLY */ && hasMonthlyPlus) {
@@ -2536,7 +2749,10 @@ function useAddPlusMemberProductsToCart({
2536
2749
  if (selectedPlusMemberMode === "annual" /* ANNUAL */ && hasAnnualPlus) {
2537
2750
  return void 0;
2538
2751
  }
2539
- if (!selectedPlusMemberProduct) {
2752
+ if (profile?.isMonthlyPlus && selectedPlusMemberMode === "monthly" /* MONTHLY */) {
2753
+ return void 0;
2754
+ }
2755
+ if (profile?.isAnnualPlus && selectedPlusMemberMode === "annual" /* ANNUAL */) {
2540
2756
  return void 0;
2541
2757
  }
2542
2758
  return selectedPlusMemberProduct;
@@ -2828,10 +3044,9 @@ exports.RuleType = RuleType;
2828
3044
  exports.SCRIPT_CODE_AMOUNT_KEY = SCRIPT_CODE_AMOUNT_KEY;
2829
3045
  exports.ShippingMethodMode = ShippingMethodMode;
2830
3046
  exports.SpendMoneyType = SpendMoneyType;
2831
- exports.atobID = atobID;
2832
- exports.btoaID = btoaID;
2833
3047
  exports.checkAttributesUpdateNeeded = checkAttributesUpdateNeeded;
2834
3048
  exports.clearGeoLocationCache = clearGeoLocationCache;
3049
+ exports.createMockCartFromLines = createMockCartFromLines;
2835
3050
  exports.currencyCodeMapping = currencyCodeMapping;
2836
3051
  exports.defaultSWRMutationConfiguration = defaultSWRMutationConfiguration;
2837
3052
  exports.formatFunctionAutoFreeGift = formatFunctionAutoFreeGift;
@@ -2841,6 +3056,7 @@ exports.getDiscountEnvAttributeValue = getDiscountEnvAttributeValue;
2841
3056
  exports.getMatchedMainProductSubTotal = getMatchedMainProductSubTotal;
2842
3057
  exports.getQuery = getQuery;
2843
3058
  exports.getReferralAttributes = getReferralAttributes;
3059
+ exports.normalizeAddToCartLines = normalizeAddToCartLines;
2844
3060
  exports.preCheck = preCheck;
2845
3061
  exports.safeParse = safeParse;
2846
3062
  exports.useAddCartLines = useAddCartLines;
@@ -2857,6 +3073,7 @@ exports.useAutoRemovePlusMemberInCart = useAutoRemovePlusMemberInCart;
2857
3073
  exports.useBlog = useBlog;
2858
3074
  exports.useBuyNow = useBuyNow;
2859
3075
  exports.useCalcAutoFreeGift = useCalcAutoFreeGift;
3076
+ exports.useCalcGiftsFromLines = useCalcGiftsFromLines;
2860
3077
  exports.useCalcOrderDiscount = useCalcOrderDiscount;
2861
3078
  exports.useCartAttributes = useCartAttributes;
2862
3079
  exports.useCartItemQuantityLimit = useCartItemQuantityLimit;
@@ -2889,6 +3106,7 @@ exports.useSite = useSite;
2889
3106
  exports.useUpdateCartAttributes = useUpdateCartAttributes;
2890
3107
  exports.useUpdateCartLines = useUpdateCartLines;
2891
3108
  exports.useUpdateLineCodeAmountAttributes = useUpdateLineCodeAmountAttributes;
3109
+ exports.useUpdatePlusMemberDeliveryOptions = useUpdatePlusMemberDeliveryOptions;
2892
3110
  exports.useUpdateVariantQuery = useUpdateVariantQuery;
2893
3111
  exports.useVariant = useVariant;
2894
3112
  exports.useVariantMedia = useVariantMedia;