@anker-in/shopify-react 0.1.1-beta.3 → 0.1.1-beta.31

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.
@@ -6,6 +6,7 @@ var shopifySdk = require('@anker-in/shopify-sdk');
6
6
  var Cookies5 = require('js-cookie');
7
7
  var jsxRuntime = require('react/jsx-runtime');
8
8
  var Decimal2 = require('decimal.js');
9
+ var shopifyCore = require('@anker-in/shopify-core');
9
10
  var useSWR = require('swr');
10
11
  var ahooks = require('ahooks');
11
12
 
@@ -77,9 +78,10 @@ function normalizeAddToCartLines(lines) {
77
78
  const variant = line.variant;
78
79
  const product = variant.product;
79
80
  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;
81
+ const originalPrice = variant.price?.amount ? Number(variant.price.amount) : 0;
82
+ const finalPrice = variant.finalPrice?.amount ? Number(variant.finalPrice.amount) : originalPrice;
83
+ const subtotalAmount = originalPrice * quantity;
84
+ const totalAmount = finalPrice * quantity;
83
85
  return {
84
86
  id: `temp-line-${index}-${variant.id}`,
85
87
  // Temporary ID for pre-cart lines
@@ -93,7 +95,7 @@ function normalizeAddToCartLines(lines) {
93
95
  customAttributes: line.attributes || [],
94
96
  variant: {
95
97
  id: variant.id,
96
- price,
98
+ price: finalPrice,
97
99
  listPrice: variant.compareAtPrice?.amount ? Number(variant.compareAtPrice.amount) : 0,
98
100
  sku: variant.sku || "",
99
101
  name: variant.title || "",
@@ -124,15 +126,16 @@ function createMockCartFromLines(lines, existingCart) {
124
126
  const normalizedLines = normalizeAddToCartLines(lines);
125
127
  const subtotalPrice = normalizedLines.reduce((sum, line) => sum + line.subtotalAmount, 0);
126
128
  const totalPrice = normalizedLines.reduce((sum, line) => sum + line.totalAmount, 0);
129
+ const currency = lines[0]?.variant?.price?.currencyCode;
127
130
  return {
128
131
  id: existingCart?.id || "temp-cart-id",
129
132
  customerId: existingCart?.customerId,
130
133
  email: existingCart?.email,
131
134
  createdAt: existingCart?.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
132
- currency: existingCart?.currency || { code: "USD" },
135
+ currency: existingCart?.currency || { code: currency },
133
136
  taxesIncluded: existingCart?.taxesIncluded,
134
137
  lineItems: normalizedLines,
135
- totallineItemsDiscount: 0,
138
+ totalLineItemsDiscount: 0,
136
139
  orderDiscounts: 0,
137
140
  lineItemsSubtotalPrice: subtotalPrice,
138
141
  subtotalPrice,
@@ -163,22 +166,12 @@ var getQuery = () => {
163
166
  }
164
167
  return theRequest;
165
168
  };
166
- function atobID(id) {
167
- if (id && typeof id === "string" && id.includes("/")) {
168
- return id.split("/").pop()?.split("?")?.shift();
169
- } else {
170
- return id;
171
- }
172
- }
173
- function btoaID(id, type = "ProductVariant") {
174
- return `gid://shopify/${type}/${id}`;
175
- }
176
169
  var getMatchedMainProductSubTotal = (cartData, variant_list, main_product) => {
177
170
  const isAllStoreVariant = main_product?.all_store_variant ?? false;
178
171
  const matchedList = cartData?.lineItems?.filter((line) => {
179
172
  const { is_gift } = getDiscountEnvAttributeValue(line.customAttributes);
180
173
  return isAllStoreVariant ? !is_gift : variant_list?.find((item) => {
181
- return !is_gift && atobID(line.variantId) === item;
174
+ return !is_gift && shopifyCore.atobID(line.variantId) === item;
182
175
  });
183
176
  });
184
177
  return matchedList?.reduce((acc, line) => {
@@ -382,6 +375,7 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
382
375
  }
383
376
  return cart;
384
377
  }, [lines, cart]);
378
+ console.log("effectiveCart useCalcAutoFreeGift", effectiveCart);
385
379
  const { activeCampaign, subtotal } = react.useMemo(() => {
386
380
  for (const campaign of autoFreeGiftConfig) {
387
381
  const { rule_conditions = [], rule_result } = campaign;
@@ -397,6 +391,7 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
397
391
  all_store_variant: spend_get_reward.main_product?.all_store_variant || false
398
392
  }
399
393
  );
394
+ console.log("matchedSubtotal useCalcAutoFreeGift", matchedSubtotal);
400
395
  if (matchedSubtotal > 0) {
401
396
  return { activeCampaign: campaign, subtotal: matchedSubtotal };
402
397
  }
@@ -409,11 +404,20 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
409
404
  return { qualifyingGift: null, nextTierGoal: null };
410
405
  }
411
406
  const giftTiers = activeCampaign.rule_result.spend_get_reward.gift_product;
412
- const qualifyingTier = [...giftTiers].reverse().find((tier) => subtotal >= Number(tier.spend_sum_money));
413
- const nextGoal = giftTiers.find((tier) => subtotal < Number(tier.spend_sum_money));
407
+ const currentCurrency = effectiveCart?.currency?.code || "";
408
+ console.log("currentCurrency useCalcAutoFreeGift", effectiveCart, currentCurrency);
409
+ const getThresholdAmount = (tier) => {
410
+ if (tier.spend_sum_money_multi_markets?.[currentCurrency]?.value) {
411
+ return Number(tier.spend_sum_money_multi_markets[currentCurrency].value);
412
+ }
413
+ return Number(tier.spend_sum_money || 0);
414
+ };
415
+ const qualifyingTier = [...giftTiers].sort((a, b) => getThresholdAmount(b) - getThresholdAmount(a)).find((tier) => subtotal >= getThresholdAmount(tier));
416
+ const nextGoal = giftTiers.find((tier) => subtotal < getThresholdAmount(tier));
414
417
  if (!qualifyingTier) {
415
418
  return { qualifyingGift: null, nextTierGoal: nextGoal || null };
416
419
  }
420
+ const actualThreshold = getThresholdAmount(qualifyingTier);
417
421
  const formattedGift = {
418
422
  tier: qualifyingTier,
419
423
  itemsToAdd: qualifyingTier.reward_list?.map((reward) => {
@@ -421,7 +425,7 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
421
425
  if (!giftProduct) return null;
422
426
  return {
423
427
  variant: {
424
- id: btoaID(giftProduct.variant_id),
428
+ id: shopifyCore.btoaID(giftProduct.variant_id),
425
429
  handle: giftProduct.handle,
426
430
  sku: giftProduct.sku
427
431
  },
@@ -432,7 +436,10 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
432
436
  value: JSON.stringify({
433
437
  is_gift: true,
434
438
  rule_id: activeCampaign.rule_id,
435
- spend_sum_money: qualifyingTier.spend_sum_money
439
+ spend_sum_money: actualThreshold,
440
+ // 使用实际的门槛金额(多币种支持)
441
+ currency_code: currentCurrency
442
+ // 记录当前币种
436
443
  })
437
444
  }
438
445
  ]
@@ -440,7 +447,7 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
440
447
  }).filter((item) => item !== null)
441
448
  };
442
449
  return { qualifyingGift: formattedGift, nextTierGoal: nextGoal || null };
443
- }, [activeCampaign, subtotal]);
450
+ }, [activeCampaign, subtotal, effectiveCart]);
444
451
  const giftHandles = react.useMemo(() => {
445
452
  const giftVariant = autoFreeGiftConfig.map(
446
453
  (item) => item.rule_result?.spend_get_reward?.gift_product?.map(
@@ -456,18 +463,24 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
456
463
  }
457
464
  return true;
458
465
  }, [giftHandles]);
459
- const { data: giftProductsResult } = useSWR__default.default(shouldFetch ? giftHandles : null, async () => {
460
- const res = await shopifySdk.getProductsByHandles(client, {
461
- handles: giftHandles,
462
- locale
463
- });
464
- const result = Array.isArray(res) ? res : [];
465
- giftProductsCache.current = {
466
- data: result,
467
- giftHandles: [...giftHandles]
468
- };
469
- return result;
470
- });
466
+ const { data: giftProductsResult } = useSWR__default.default(
467
+ shouldFetch ? giftHandles : null,
468
+ async () => {
469
+ const res = await shopifySdk.getProductsByHandles(client, {
470
+ handles: giftHandles,
471
+ locale
472
+ });
473
+ const result = Array.isArray(res) ? res : [];
474
+ giftProductsCache.current = {
475
+ data: result,
476
+ giftHandles: [...giftHandles]
477
+ };
478
+ return result;
479
+ },
480
+ {
481
+ revalidateOnFocus: false
482
+ }
483
+ );
471
484
  const finalGiftProductsResult = react.useMemo(() => {
472
485
  if (giftProductsCache.current && !shouldFetch) {
473
486
  return giftProductsCache.current.data || void 0;
@@ -520,12 +533,14 @@ var useScriptAutoFreeGift = ({
520
533
  upgrade_multiple2 = 1.2;
521
534
  upgrade_value2 = 40;
522
535
  }
523
- effectiveCart?.lineItems?.forEach(({ customAttributes }) => {
524
- customAttributes?.forEach(({ key, value }) => {
525
- if (key === "_amount_upgrade_multiple") upgrade_multiple2 = Number(value) || 1;
526
- if (key === "_amount_upgrade_value") upgrade_value2 = Number(value) || 0;
527
- });
528
- });
536
+ effectiveCart?.lineItems?.forEach(
537
+ ({ customAttributes }) => {
538
+ customAttributes?.forEach(({ key, value }) => {
539
+ if (key === "_amount_upgrade_multiple") upgrade_multiple2 = Number(value) || 1;
540
+ if (key === "_amount_upgrade_value") upgrade_value2 = Number(value) || 0;
541
+ });
542
+ }
543
+ );
529
544
  return [upgrade_multiple2, upgrade_value2];
530
545
  }, [effectiveCart?.lineItems, points_subscribe]);
531
546
  const breakpoints = react.useMemo(() => {
@@ -590,18 +605,24 @@ var useScriptAutoFreeGift = ({
590
605
  const nextLevel = levelIndex > 0 ? sortedLevels[levelIndex - 1] ?? null : null;
591
606
  return [currentLevel, nextLevel];
592
607
  }, [breakpoints, involvedSubTotal, involvedLines.length]);
593
- const { data: giftProductsResult } = useSWR__default.default(shouldFetch ? giftHandles : null, 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
- });
608
+ const { data: giftProductsResult } = useSWR__default.default(
609
+ shouldFetch ? giftHandles : null,
610
+ async () => {
611
+ const res = await shopifySdk.getProductsByHandles(client, {
612
+ handles: giftHandles,
613
+ locale
614
+ });
615
+ const result = Array.isArray(res) ? res : [];
616
+ giftProductsCache.current = {
617
+ data: result,
618
+ giftHandles: [...giftHandles]
619
+ };
620
+ return result;
621
+ },
622
+ {
623
+ revalidateOnFocus: false
624
+ }
625
+ );
605
626
  const finalGiftProductsResult = react.useMemo(() => {
606
627
  if (giftProductsCache.current && !shouldFetch) {
607
628
  return giftProductsCache.current.data || void 0;
@@ -634,9 +655,9 @@ var useScriptAutoFreeGift = ({
634
655
  };
635
656
  };
636
657
  var CartContext = react.createContext(null);
637
- function useCartContext() {
658
+ function useCartContext(options) {
638
659
  const context = react.useContext(CartContext);
639
- if (!context) {
660
+ if (!context && true) {
640
661
  throw new Error("useCartContext must be used within a CartProvider");
641
662
  }
642
663
  return context;
@@ -762,10 +783,10 @@ var trackBuyNowGA = ({
762
783
  return;
763
784
  }
764
785
  const { variant } = lineItems[0];
765
- const currencyCode = variant.price?.currencyCode;
786
+ const currencyCode = variant.product?.price?.currencyCode || variant.price?.currencyCode;
766
787
  const totalPrice = lineItems?.reduce(
767
788
  (prev, { variant: variant2 }) => prev.plus(
768
- variant2?.finalPrice?.amount ?? variant2?.compareAtPrice?.amount ?? (variant2?.price?.amount || 0)
789
+ variant2?.finalPrice?.amount ?? variant2?.compareAtPrice?.amount ?? variant2?.price?.amount ?? 0
769
790
  ),
770
791
  new Decimal2__default.default(0)
771
792
  ).toNumber();
@@ -839,7 +860,7 @@ function useApplyCartCodes(options) {
839
860
  if (!discountCodes?.length) {
840
861
  throw new Error("Invalid input used for this operation: Miss discountCode");
841
862
  }
842
- const cartId = providedCartId ? void 0 : providedCartId || cart?.id;
863
+ const cartId = providedCartId || cart?.id;
843
864
  if (!cartId) {
844
865
  return void 0;
845
866
  }
@@ -852,12 +873,18 @@ function useApplyCartCodes(options) {
852
873
  cookieAdapter: cartCookieAdapter,
853
874
  metafieldIdentifiers
854
875
  });
876
+ const unApplicableCodes = discountCodes.filter(
877
+ (code) => updatedCart?.discountCodes?.find((item) => item.code === code && !item.applicable)
878
+ );
879
+ if (unApplicableCodes.length) {
880
+ throw new Error(`${unApplicableCodes.join(", ")} is not applicable to the cart`);
881
+ }
855
882
  if (updatedCart) {
856
883
  mutateCart(updatedCart);
857
884
  }
858
885
  return updatedCart;
859
886
  },
860
- [client, locale, cartCookieAdapter, mutateCart, cart]
887
+ [client, locale, cartCookieAdapter, mutateCart, cart, metafieldIdentifiers]
861
888
  );
862
889
  return useSWRMutation__default.default("apply-codes", applyCodes, options);
863
890
  }
@@ -867,7 +894,7 @@ function useRemoveCartCodes(options) {
867
894
  const removeCodes = react.useCallback(
868
895
  async (_key, { arg }) => {
869
896
  const { cartId: providedCartId, discountCodes } = arg;
870
- const cartId = providedCartId ? void 0 : providedCartId || cart?.id;
897
+ const cartId = providedCartId || cart?.id;
871
898
  const codes = cart?.discountCodes?.filter((code) => !!code.applicable) || [];
872
899
  const leftCodes = codes.filter((code) => discountCodes?.length ? !discountCodes.includes(code.code) : code.code).map((code) => code.code);
873
900
  const updatedCart = await shopifySdk.updateCartCodes(client, {
@@ -881,15 +908,70 @@ function useRemoveCartCodes(options) {
881
908
  }
882
909
  return updatedCart;
883
910
  },
884
- [client, locale, cartCookieAdapter, mutateCart, cart]
911
+ [client, locale, cartCookieAdapter, mutateCart, cart, metafieldIdentifiers]
885
912
  );
886
913
  return useSWRMutation__default.default("remove-codes", removeCodes, options);
887
914
  }
888
915
 
916
+ // src/hooks/cart/utils/add-to-cart.ts
917
+ var getLinesWithAttributes = ({
918
+ cart,
919
+ lineItems
920
+ }) => {
921
+ return lineItems.map((line) => {
922
+ const sameLineInCart = cart?.lineItems.find(
923
+ (lineInCart) => lineInCart.variant.sku === line.variant?.sku && lineInCart.product?.handle === line.variant?.product?.handle
924
+ );
925
+ const codeAmountAttribute = sameLineInCart?.customAttributes?.find(
926
+ (attr) => attr.key === CODE_AMOUNT_KEY
927
+ );
928
+ const scriptCodeAmountAttribute = sameLineInCart?.customAttributes?.find(
929
+ (attr) => attr.key === SCRIPT_CODE_AMOUNT_KEY
930
+ );
931
+ let functionAttribute = null;
932
+ try {
933
+ functionAttribute = sameLineInCart?.customAttributes?.find(
934
+ (attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY && JSON.parse(attr.value)?.discounted_amount
935
+ );
936
+ } catch (error) {
937
+ }
938
+ if (codeAmountAttribute || functionAttribute || scriptCodeAmountAttribute) {
939
+ return {
940
+ ...line,
941
+ attributes: [
942
+ ...line.attributes || [],
943
+ codeAmountAttribute,
944
+ functionAttribute,
945
+ scriptCodeAmountAttribute
946
+ ].filter(Boolean)
947
+ };
948
+ }
949
+ return line;
950
+ });
951
+ };
952
+ var getLinesWithFunctionAttributes = (lineItems) => {
953
+ return lineItems.map((line) => {
954
+ let itemAttributes = line.attributes || [];
955
+ const functionEnvAttribute = itemAttributes.find((attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY);
956
+ if (!functionEnvAttribute) {
957
+ itemAttributes = itemAttributes.concat([
958
+ {
959
+ key: CUSTOMER_ATTRIBUTE_KEY,
960
+ value: JSON.stringify({
961
+ is_gift: false,
962
+ discounted_amount: Number(line.variant?.finalPrice?.amount || line.variant?.price?.amount) * (line.quantity || 1)
963
+ })
964
+ }
965
+ ]);
966
+ }
967
+ return { ...line, attributes: itemAttributes };
968
+ });
969
+ };
970
+
889
971
  // src/hooks/cart/use-add-to-cart.ts
890
972
  function useAddToCart({ withTrack = true } = {}, swrOptions) {
891
973
  const { client, config, locale, cartCookieAdapter, userAdapter } = useShopify();
892
- const { cart } = useCartContext();
974
+ const { cart, addCustomAttributes } = useCartContext();
893
975
  const { trigger: applyCartCodes } = useApplyCartCodes();
894
976
  const { trigger: removeInvalidCodes } = useRemoveCartCodes();
895
977
  const { trigger: addCartLines2 } = useAddCartLines();
@@ -903,12 +985,18 @@ function useAddToCart({ withTrack = true } = {}, swrOptions) {
903
985
  buyerIdentity,
904
986
  needCreateCart = false,
905
987
  onCodesInvalid,
906
- replaceExistingCodes
988
+ replaceExistingCodes,
989
+ customAttributes
907
990
  } = arg;
908
991
  if (!lineItems || lineItems.length === 0) {
909
992
  return;
910
993
  }
911
- const lines = lineItems.map((item) => ({
994
+ const linesWithAttributes = getLinesWithAttributes({
995
+ cart,
996
+ lineItems
997
+ });
998
+ const linesWithFunctionAttributes = getLinesWithFunctionAttributes(linesWithAttributes);
999
+ const lines = linesWithFunctionAttributes.map((item) => ({
912
1000
  merchandiseId: item.variant?.id || "",
913
1001
  quantity: item.quantity || 1,
914
1002
  attributes: item.attributes,
@@ -948,6 +1036,9 @@ function useAddToCart({ withTrack = true } = {}, swrOptions) {
948
1036
  discountCodes
949
1037
  });
950
1038
  }
1039
+ if (customAttributes && customAttributes.length > 0) {
1040
+ addCustomAttributes(customAttributes);
1041
+ }
951
1042
  if (withTrack) {
952
1043
  trackAddToCartGA({
953
1044
  lineItems,
@@ -974,9 +1065,10 @@ function useUpdateCartLines(options) {
974
1065
  if (updatedCart) {
975
1066
  mutateCart(updatedCart);
976
1067
  }
1068
+ console.log("use-update-cart-lines updatedCart", metafieldIdentifiers, updatedCart);
977
1069
  return updatedCart;
978
1070
  },
979
- [client, locale, cartCookieAdapter, mutateCart]
1071
+ [client, locale, cartCookieAdapter, mutateCart, metafieldIdentifiers]
980
1072
  );
981
1073
  return useSWRMutation__default.default("update-cart-lines", updateLines, options);
982
1074
  }
@@ -1015,7 +1107,7 @@ function useRemoveCartLines(options) {
1015
1107
  }
1016
1108
  return updatedCart;
1017
1109
  },
1018
- [client, locale, cartCookieAdapter, mutateCart]
1110
+ [client, locale, cartCookieAdapter, mutateCart, metafieldIdentifiers]
1019
1111
  );
1020
1112
  return useSWRMutation__default.default("remove-cart-lines", removeLines, options);
1021
1113
  }
@@ -1034,7 +1126,7 @@ function useUpdateCartAttributes(mutate, metafieldIdentifiers, options) {
1034
1126
  }
1035
1127
  return updatedCart;
1036
1128
  },
1037
- [client, locale, cartCookieAdapter, mutate]
1129
+ [client, locale, cartCookieAdapter, mutate, metafieldIdentifiers]
1038
1130
  );
1039
1131
  return useSWRMutation__default.default("update-cart-attributes", updateAttributes, options);
1040
1132
  }
@@ -1056,7 +1148,8 @@ function useBuyNow({ withTrack = true } = {}, swrOptions) {
1056
1148
  if (!lineItems || lineItems.length === 0) {
1057
1149
  return;
1058
1150
  }
1059
- const lines = lineItems.map((item) => ({
1151
+ const linesWithFunctionAttributes = getLinesWithFunctionAttributes(lineItems);
1152
+ const lines = linesWithFunctionAttributes.map((item) => ({
1060
1153
  merchandiseId: item.variant?.id || "",
1061
1154
  quantity: item.quantity || 1,
1062
1155
  attributes: item.attributes,
@@ -1174,7 +1267,7 @@ var useCalcOrderDiscount = (cart, orderDiscountConfig, customer) => {
1174
1267
  const isCustomerLoading = react.useMemo(() => !customer ? true : false, [customer]);
1175
1268
  const dealsType = "";
1176
1269
  const { activeCampaign, subtotal } = react.useMemo(() => {
1177
- for (const campaign of orderDiscountConfig) {
1270
+ for (const campaign of orderDiscountConfig || []) {
1178
1271
  const { rule_conditions = [], result_detail } = campaign;
1179
1272
  const { main_product, order_discount_conf } = result_detail || {};
1180
1273
  const isPreCheckPassed = preCheck(rule_conditions, tags, []);
@@ -1204,9 +1297,12 @@ var useCalcOrderDiscount = (cart, orderDiscountConfig, customer) => {
1204
1297
  discountAmount: 0
1205
1298
  };
1206
1299
  }
1207
- const tieredDiscounts = activeCampaign.result_detail.order_discount_conf.tiered_discounts;
1208
- const qualifyingTier = [...tieredDiscounts].reverse().find((tier) => subtotal >= Number(tier.amount));
1209
- const nextGoal = tieredDiscounts.find((tier) => subtotal < Number(tier.amount));
1300
+ const currentCurrency = cart?.currency?.code || "";
1301
+ console.log("currentCurrency", cart, currentCurrency);
1302
+ const orderDiscountConf = activeCampaign.result_detail.order_discount_conf;
1303
+ const tieredDiscounts = orderDiscountConf.tiered_discounts_markets?.[currentCurrency] || orderDiscountConf.tiered_discounts;
1304
+ const qualifyingTier = [...tieredDiscounts].sort((a, b) => Number(b.amount) - Number(a.amount)).find((tier) => subtotal >= Number(tier.amount));
1305
+ const nextGoal = [...tieredDiscounts].sort((a, b) => Number(a.amount) - Number(b.amount)).find((tier) => subtotal < Number(tier.amount));
1210
1306
  if (!qualifyingTier) {
1211
1307
  return {
1212
1308
  qualifyingDiscount: null,
@@ -1274,12 +1370,10 @@ function useHasPlusMemberInCart({
1274
1370
  };
1275
1371
  }, [cart?.lineItems, plus_monthly_product, plus_annual_product]);
1276
1372
  }
1277
-
1278
- // src/hooks/cart/feature/use-cart-attributes.ts
1279
1373
  var getReferralAttributes = () => {
1280
- const inviteCode = Cookies5__default.default.get("invite_code");
1281
- const playModeId = Cookies5__default.default.get("playModeId");
1282
- const popup = Cookies5__default.default.get("_popup");
1374
+ const inviteCode = shopifySdk.getLocalStorage("inviteCode") || Cookies5__default.default.get("inviteCode");
1375
+ const playModeId = shopifySdk.getLocalStorage("playModeId") || Cookies5__default.default.get("playModeId");
1376
+ const popup = shopifySdk.getLocalStorage("_popup") || Cookies5__default.default.get("_popup");
1283
1377
  if (inviteCode && playModeId) {
1284
1378
  return popup ? [
1285
1379
  { key: "_invite_code", value: inviteCode ? inviteCode : "" },
@@ -1303,8 +1397,6 @@ var useCartAttributes = ({
1303
1397
  memberSetting,
1304
1398
  cart
1305
1399
  });
1306
- console.log("memberSetting", memberSetting);
1307
- console.log("hasPlusMember", hasPlusMember);
1308
1400
  react.useEffect(() => {
1309
1401
  setCurrentUrl(window.location.href);
1310
1402
  }, []);
@@ -1330,7 +1422,7 @@ var useCartAttributes = ({
1330
1422
  return "new_user_login";
1331
1423
  }, [customer]);
1332
1424
  const memberAttributes = react.useMemo(() => {
1333
- return [
1425
+ const attributes = [
1334
1426
  {
1335
1427
  key: "_token",
1336
1428
  value: profile?.token
@@ -1351,17 +1443,28 @@ var useCartAttributes = ({
1351
1443
  value: profile?.token ? "true" : "false"
1352
1444
  }
1353
1445
  ];
1446
+ if (profile?.token) {
1447
+ attributes.push({
1448
+ key: "_login_user",
1449
+ value: "1"
1450
+ });
1451
+ }
1452
+ return attributes;
1354
1453
  }, [profile?.memberType, profile?.token, userType, hasPlusMember]);
1355
1454
  const functionAttributes = react.useMemo(() => {
1356
- return [
1357
- cart?.discountCodes && {
1455
+ const hasFunctionEnvAttribute = cart?.lineItems.some(
1456
+ (item) => item.customAttributes?.some((attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY)
1457
+ );
1458
+ const discountCodes = cart?.discountCodes.map((item) => item.code).filter((code) => code) || [];
1459
+ return hasFunctionEnvAttribute ? [
1460
+ {
1358
1461
  key: "_discounts_function_env",
1359
1462
  value: JSON.stringify({
1360
- discount_code: cart?.discountCodes.map((item) => item.code),
1463
+ discount_code: discountCodes,
1361
1464
  user_tags: customer?.tags || []
1362
1465
  })
1363
1466
  }
1364
- ];
1467
+ ] : [];
1365
1468
  }, [cart]);
1366
1469
  const presellAttributes = react.useMemo(() => {
1367
1470
  return [
@@ -1393,18 +1496,50 @@ var useCartAttributes = ({
1393
1496
  }
1394
1497
  ];
1395
1498
  }, [currentUrl]);
1499
+ const commonAttributes = react.useMemo(
1500
+ () => [
1501
+ ...memberAttributes,
1502
+ ...functionAttributes,
1503
+ ...presellAttributes,
1504
+ ...weightAttributes,
1505
+ ...trackingAttributes,
1506
+ ...getReferralAttributes()
1507
+ ].filter((item) => item?.value),
1508
+ [memberAttributes, functionAttributes, presellAttributes, weightAttributes, trackingAttributes]
1509
+ );
1510
+ const extraAttributesInCart = react.useMemo(() => {
1511
+ const commonAttributeKeys = [
1512
+ // member attributes
1513
+ "_token",
1514
+ "_member_type",
1515
+ "_user_type",
1516
+ "_is_login",
1517
+ "_login_user",
1518
+ // function attributes
1519
+ "_discounts_function_env",
1520
+ // presell attributes
1521
+ "_presale",
1522
+ // weight attributes
1523
+ "_weight",
1524
+ "_app_source_name",
1525
+ // tracking attributes
1526
+ "utm_params",
1527
+ // referral attributes
1528
+ "_invite_code",
1529
+ "_play_mode_id",
1530
+ "_popup"
1531
+ ];
1532
+ return cart?.customAttributes?.filter(
1533
+ (item) => !commonAttributeKeys.includes(item.key)
1534
+ ) || [];
1535
+ }, [cart]);
1396
1536
  return react.useMemo(
1397
1537
  () => ({
1398
- attributes: [
1399
- ...memberAttributes,
1400
- ...functionAttributes,
1401
- ...presellAttributes,
1402
- ...weightAttributes,
1403
- ...trackingAttributes,
1404
- ...getReferralAttributes()
1405
- ].filter((item) => item?.value)
1538
+ attributes: [...commonAttributes, ...extraAttributesInCart].filter(
1539
+ (item) => item?.value
1540
+ )
1406
1541
  }),
1407
- [memberAttributes, functionAttributes, presellAttributes, weightAttributes, trackingAttributes]
1542
+ [commonAttributes, extraAttributesInCart]
1408
1543
  );
1409
1544
  };
1410
1545
  var DEFAULT_MIN = 1;
@@ -1467,7 +1602,7 @@ var useUpdateLineCodeAmountAttributes = ({
1467
1602
  );
1468
1603
  const functionEnvValue = getDiscountEnvAttributeValue(line.customAttributes);
1469
1604
  const hasSameFunctionEnvAttribute = Number(functionEnvValue.discounted_amount) === Number(line.totalAmount);
1470
- if (!hasSameFunctionEnvAttribute && hasFunctionEnvAttribute) {
1605
+ if (!hasSameFunctionEnvAttribute && hasFunctionEnvAttribute && !functionEnvValue.is_gift) {
1471
1606
  attrNeedUpdate.push({
1472
1607
  key: CUSTOMER_ATTRIBUTE_KEY,
1473
1608
  value: JSON.stringify({
@@ -1506,29 +1641,22 @@ var useUpdateLineCodeAmountAttributes = ({
1506
1641
  }).filter(
1507
1642
  ({ attrNeedUpdate, attrNeedDelete }) => attrNeedUpdate.length || attrNeedDelete.length
1508
1643
  ).map(({ line, attrNeedUpdate, attrNeedDelete }) => {
1644
+ let lineId = line.id;
1645
+ let attributes = line.customAttributes || [];
1646
+ if (attrNeedDelete.length) {
1647
+ attributes = attributes.filter(
1648
+ (attr) => !attrNeedDelete.includes(attr.key)
1649
+ );
1650
+ }
1509
1651
  if (attrNeedUpdate.length) {
1510
- return {
1511
- id: line.id,
1512
- attributes: [
1513
- ...line.customAttributes?.filter(
1514
- (attr) => !attrNeedUpdate.some((updateAttr) => updateAttr.key === attr.key)
1515
- ) || [],
1516
- ...attrNeedUpdate
1517
- ]
1518
- };
1519
- } else if (attrNeedDelete.length) {
1520
- return {
1521
- id: line.id,
1522
- attributes: line.customAttributes?.filter(
1523
- (attr) => !attrNeedDelete.includes(attr.key)
1524
- ) || []
1525
- };
1526
- } else {
1527
- return {
1528
- id: line.id,
1529
- attributes: line.customAttributes || []
1530
- };
1652
+ attributes = attributes.filter(
1653
+ (attr) => !attrNeedUpdate.some((updateAttr) => updateAttr.key === attr.key)
1654
+ ).concat(attrNeedUpdate);
1531
1655
  }
1656
+ return {
1657
+ id: lineId,
1658
+ attributes
1659
+ };
1532
1660
  }),
1533
1661
  [cart?.lineItems, mainProductDiscountCodes]
1534
1662
  );
@@ -1621,8 +1749,9 @@ function useProductsByHandles(options = {}) {
1621
1749
  metafieldIdentifiers
1622
1750
  });
1623
1751
  },
1624
- swrOptions || {
1625
- revalidateOnFocus: false
1752
+ {
1753
+ revalidateOnFocus: false,
1754
+ ...swrOptions
1626
1755
  }
1627
1756
  );
1628
1757
  }
@@ -2538,6 +2667,73 @@ var usePlusMemberDeliveryCodes = ({
2538
2667
  [deliveryData]
2539
2668
  );
2540
2669
  };
2670
+ function useUpdateCartDeliveryOptions(mutate, metafieldIdentifiers, options) {
2671
+ const { client, locale, cartCookieAdapter } = useShopify();
2672
+ const updateDeliveryOptions = react.useCallback(
2673
+ async (_key, { arg }) => {
2674
+ const updatedCart = await shopifySdk.updateCartDeliveryOptions(client, {
2675
+ ...arg,
2676
+ metafieldIdentifiers,
2677
+ cookieAdapter: cartCookieAdapter
2678
+ });
2679
+ console.log("useUpdateCartDeliveryOptions updatedCart", updatedCart);
2680
+ if (updatedCart) {
2681
+ mutate(updatedCart);
2682
+ }
2683
+ return updatedCart;
2684
+ },
2685
+ [client, locale, cartCookieAdapter, mutate, metafieldIdentifiers]
2686
+ );
2687
+ return useSWRMutation__default.default("update-cart-delivery-options", updateDeliveryOptions, options);
2688
+ }
2689
+
2690
+ // src/hooks/member/plus/use-update-plus-member-delivery-options.ts
2691
+ var useUpdatePlusMemberDeliveryOptions = ({
2692
+ options
2693
+ } = {}) => {
2694
+ const { cart: cartContextData, mutateCart, metafieldIdentifiers } = useCartContext();
2695
+ const { trigger: updateCartDeliveryOptions2 } = useUpdateCartDeliveryOptions(
2696
+ mutateCart,
2697
+ metafieldIdentifiers
2698
+ );
2699
+ const handler = react.useCallback(
2700
+ async (_, { arg }) => {
2701
+ const currentCart = arg?.cart || cartContextData;
2702
+ const { deliveryData } = arg;
2703
+ const firstDeliveryGroup = currentCart?.deliveryGroups?.[0];
2704
+ const deliveryGroupId = firstDeliveryGroup?.id;
2705
+ const selectedOptionCode = deliveryData?.deliveryCustomData?.selected_delivery_option?.code;
2706
+ if (!deliveryGroupId || !selectedOptionCode || selectedOptionCode === firstDeliveryGroup?.selectedDeliveryOption?.code) {
2707
+ return null;
2708
+ }
2709
+ const deliveryGroup = currentCart?.deliveryGroups?.find(
2710
+ (group) => group?.id === deliveryGroupId
2711
+ );
2712
+ const matchedOption = deliveryGroup?.deliveryOptions?.find(
2713
+ (option) => option?.code === selectedOptionCode
2714
+ );
2715
+ if (!matchedOption?.handle) {
2716
+ return null;
2717
+ }
2718
+ const deliveryOptions = [
2719
+ {
2720
+ deliveryGroupId,
2721
+ deliveryOptionHandle: matchedOption.handle
2722
+ }
2723
+ ];
2724
+ const updatedCart = await updateCartDeliveryOptions2({
2725
+ selectedDeliveryOptions: deliveryOptions,
2726
+ cartId: currentCart?.id
2727
+ });
2728
+ if (updatedCart && mutateCart) {
2729
+ mutateCart(updatedCart);
2730
+ }
2731
+ return updatedCart;
2732
+ },
2733
+ [cartContextData, updateCartDeliveryOptions2, mutateCart]
2734
+ );
2735
+ return useSWRMutation__default.default("update-cart-delivery-options", handler, options);
2736
+ };
2541
2737
  var usePlusMemberItemCustomAttributes = ({
2542
2738
  deliveryData
2543
2739
  }) => {
@@ -2557,48 +2753,18 @@ var usePlusMemberCheckoutCustomAttributes = ({
2557
2753
  deliveryData,
2558
2754
  product,
2559
2755
  variant,
2560
- customer,
2561
2756
  isShowShippingBenefits
2562
2757
  }) => {
2563
2758
  const { deliveryCustomData } = deliveryData || {};
2564
2759
  const { profile } = usePlusMemberContext();
2565
- const userType = react.useMemo(() => {
2566
- const customerInfo = customer;
2567
- if (!customerInfo) {
2568
- return "new_user_unlogin";
2569
- }
2570
- if (customer) {
2571
- const { orders = {} } = customer;
2572
- const edgesLength = orders?.edges?.length;
2573
- if (edgesLength === 1) {
2574
- return "old_user_orders_once";
2575
- } else if (edgesLength && edgesLength > 1) {
2576
- return "old_user_orders_twice";
2577
- }
2578
- }
2579
- return "new_user_login";
2580
- }, [customer]);
2581
2760
  return react.useMemo(() => {
2582
2761
  const checkoutCustomAttributes = [
2583
- {
2584
- key: "_token",
2585
- value: profile?.token || ""
2586
- },
2762
+ // _last_url: 付费会员结算完成之后 checkout 有一个继续购买的按钮, 用于跳转到继续购买的页面
2587
2763
  {
2588
2764
  key: "_last_url",
2589
2765
  value: typeof window !== "undefined" ? window.location.origin + window.location.pathname : ""
2590
- },
2591
- {
2592
- key: "_user_type",
2593
- value: userType
2594
2766
  }
2595
2767
  ];
2596
- if (profile) {
2597
- checkoutCustomAttributes.push({
2598
- key: "_login_user",
2599
- value: "1"
2600
- });
2601
- }
2602
2768
  if (deliveryCustomData) {
2603
2769
  checkoutCustomAttributes.push({
2604
2770
  key: "_checkout_delivery_custom",
@@ -2608,12 +2774,6 @@ var usePlusMemberCheckoutCustomAttributes = ({
2608
2774
  })
2609
2775
  });
2610
2776
  }
2611
- if (variant?.metafields?.presell) {
2612
- checkoutCustomAttributes.push({
2613
- key: "_presale",
2614
- value: "true"
2615
- });
2616
- }
2617
2777
  if (isShowShippingBenefits && !isShowShippingBenefits({ variant, product, setting: {} })) {
2618
2778
  checkoutCustomAttributes.push({
2619
2779
  key: "_hide_shipping",
@@ -2621,18 +2781,17 @@ var usePlusMemberCheckoutCustomAttributes = ({
2621
2781
  });
2622
2782
  }
2623
2783
  return checkoutCustomAttributes;
2624
- }, [deliveryCustomData, product, profile, userType, variant, isShowShippingBenefits]);
2784
+ }, [deliveryCustomData, product, profile, variant, isShowShippingBenefits]);
2625
2785
  };
2626
2786
  function useAutoRemovePlusMemberInCart({
2627
- metafields,
2628
- isMonthlyPlus,
2629
- isAnnualPlus
2787
+ cart,
2788
+ profile,
2789
+ memberSetting
2630
2790
  }) {
2631
- const { plus_monthly_product, plus_annual_product } = metafields || {};
2632
- const { cart } = useCartContext();
2791
+ const { plus_monthly_product, plus_annual_product } = memberSetting || {};
2633
2792
  const { trigger: removeCartLines2 } = useRemoveCartLines();
2634
2793
  react.useEffect(() => {
2635
- if (!cart) return;
2794
+ if (!cart || !plus_monthly_product || !plus_annual_product) return;
2636
2795
  const removePlusProduct = async (productType) => {
2637
2796
  if (!productType) return;
2638
2797
  const product = cart.lineItems?.find(
@@ -2644,33 +2803,25 @@ function useAutoRemovePlusMemberInCart({
2644
2803
  });
2645
2804
  }
2646
2805
  };
2647
- if (isMonthlyPlus) {
2806
+ if (profile?.isMonthlyPlus) {
2648
2807
  removePlusProduct(plus_monthly_product);
2649
2808
  }
2650
- if (isAnnualPlus) {
2809
+ if (profile?.isAnnualPlus) {
2651
2810
  removePlusProduct(plus_annual_product);
2652
2811
  }
2653
- }, [
2654
- cart,
2655
- plus_annual_product,
2656
- plus_monthly_product,
2657
- isAnnualPlus,
2658
- isMonthlyPlus,
2659
- removeCartLines2
2660
- ]);
2812
+ }, [cart, plus_annual_product, plus_monthly_product, profile, removeCartLines2]);
2661
2813
  }
2662
2814
  function useAddPlusMemberProductsToCart({
2663
2815
  cart,
2664
- memberSetting,
2665
- selectedPlusMemberMode,
2666
- selectedPlusMemberProduct
2816
+ profile
2667
2817
  }) {
2818
+ const { selectedPlusMemberMode, selectedPlusMemberProduct, plusMemberMetafields } = usePlusMemberContext();
2668
2819
  const { hasMonthlyPlus, hasAnnualPlus } = useHasPlusMemberInCart({
2669
- cart,
2670
- memberSetting
2820
+ memberSetting: plusMemberMetafields,
2821
+ cart
2671
2822
  });
2672
2823
  const plusMemberProduct = react.useMemo(() => {
2673
- if (selectedPlusMemberMode === "free" /* FREE */) {
2824
+ if (!selectedPlusMemberProduct || selectedPlusMemberMode === "free" /* FREE */) {
2674
2825
  return void 0;
2675
2826
  }
2676
2827
  if (selectedPlusMemberMode === "monthly" /* MONTHLY */ && hasMonthlyPlus) {
@@ -2679,7 +2830,10 @@ function useAddPlusMemberProductsToCart({
2679
2830
  if (selectedPlusMemberMode === "annual" /* ANNUAL */ && hasAnnualPlus) {
2680
2831
  return void 0;
2681
2832
  }
2682
- if (!selectedPlusMemberProduct) {
2833
+ if (profile?.isMonthlyPlus && selectedPlusMemberMode === "monthly" /* MONTHLY */) {
2834
+ return void 0;
2835
+ }
2836
+ if (profile?.isAnnualPlus && selectedPlusMemberMode === "annual" /* ANNUAL */) {
2683
2837
  return void 0;
2684
2838
  }
2685
2839
  return selectedPlusMemberProduct;
@@ -2971,8 +3125,6 @@ exports.RuleType = RuleType;
2971
3125
  exports.SCRIPT_CODE_AMOUNT_KEY = SCRIPT_CODE_AMOUNT_KEY;
2972
3126
  exports.ShippingMethodMode = ShippingMethodMode;
2973
3127
  exports.SpendMoneyType = SpendMoneyType;
2974
- exports.atobID = atobID;
2975
- exports.btoaID = btoaID;
2976
3128
  exports.checkAttributesUpdateNeeded = checkAttributesUpdateNeeded;
2977
3129
  exports.clearGeoLocationCache = clearGeoLocationCache;
2978
3130
  exports.createMockCartFromLines = createMockCartFromLines;
@@ -3035,6 +3187,7 @@ exports.useSite = useSite;
3035
3187
  exports.useUpdateCartAttributes = useUpdateCartAttributes;
3036
3188
  exports.useUpdateCartLines = useUpdateCartLines;
3037
3189
  exports.useUpdateLineCodeAmountAttributes = useUpdateLineCodeAmountAttributes;
3190
+ exports.useUpdatePlusMemberDeliveryOptions = useUpdatePlusMemberDeliveryOptions;
3038
3191
  exports.useUpdateVariantQuery = useUpdateVariantQuery;
3039
3192
  exports.useVariant = useVariant;
3040
3193
  exports.useVariantMedia = useVariantMedia;