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

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;
@@ -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,6 +873,12 @@ 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
  }
@@ -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, {
@@ -886,10 +913,65 @@ function useRemoveCartCodes(options) {
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,
@@ -1056,7 +1147,8 @@ function useBuyNow({ withTrack = true } = {}, swrOptions) {
1056
1147
  if (!lineItems || lineItems.length === 0) {
1057
1148
  return;
1058
1149
  }
1059
- const lines = lineItems.map((item) => ({
1150
+ const linesWithFunctionAttributes = getLinesWithFunctionAttributes(lineItems);
1151
+ const lines = linesWithFunctionAttributes.map((item) => ({
1060
1152
  merchandiseId: item.variant?.id || "",
1061
1153
  quantity: item.quantity || 1,
1062
1154
  attributes: item.attributes,
@@ -1204,9 +1296,12 @@ var useCalcOrderDiscount = (cart, orderDiscountConfig, customer) => {
1204
1296
  discountAmount: 0
1205
1297
  };
1206
1298
  }
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));
1299
+ const currentCurrency = cart?.currency?.code || "";
1300
+ console.log("currentCurrency", cart, currentCurrency);
1301
+ const orderDiscountConf = activeCampaign.result_detail.order_discount_conf;
1302
+ const tieredDiscounts = orderDiscountConf.tiered_discounts_markets?.[currentCurrency] || orderDiscountConf.tiered_discounts;
1303
+ const qualifyingTier = [...tieredDiscounts].sort((a, b) => Number(b.amount) - Number(a.amount)).find((tier) => subtotal >= Number(tier.amount));
1304
+ const nextGoal = [...tieredDiscounts].sort((a, b) => Number(a.amount) - Number(b.amount)).find((tier) => subtotal < Number(tier.amount));
1210
1305
  if (!qualifyingTier) {
1211
1306
  return {
1212
1307
  qualifyingDiscount: null,
@@ -1274,12 +1369,10 @@ function useHasPlusMemberInCart({
1274
1369
  };
1275
1370
  }, [cart?.lineItems, plus_monthly_product, plus_annual_product]);
1276
1371
  }
1277
-
1278
- // src/hooks/cart/feature/use-cart-attributes.ts
1279
1372
  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");
1373
+ const inviteCode = shopifySdk.getLocalStorage("invite_code") || Cookies5__default.default.get("invite_code");
1374
+ const playModeId = shopifySdk.getLocalStorage("playModeId") || Cookies5__default.default.get("playModeId");
1375
+ const popup = shopifySdk.getLocalStorage("_popup") || Cookies5__default.default.get("_popup");
1283
1376
  if (inviteCode && playModeId) {
1284
1377
  return popup ? [
1285
1378
  { key: "_invite_code", value: inviteCode ? inviteCode : "" },
@@ -1303,8 +1396,6 @@ var useCartAttributes = ({
1303
1396
  memberSetting,
1304
1397
  cart
1305
1398
  });
1306
- console.log("memberSetting", memberSetting);
1307
- console.log("hasPlusMember", hasPlusMember);
1308
1399
  react.useEffect(() => {
1309
1400
  setCurrentUrl(window.location.href);
1310
1401
  }, []);
@@ -1330,7 +1421,7 @@ var useCartAttributes = ({
1330
1421
  return "new_user_login";
1331
1422
  }, [customer]);
1332
1423
  const memberAttributes = react.useMemo(() => {
1333
- return [
1424
+ const attributes = [
1334
1425
  {
1335
1426
  key: "_token",
1336
1427
  value: profile?.token
@@ -1351,17 +1442,28 @@ var useCartAttributes = ({
1351
1442
  value: profile?.token ? "true" : "false"
1352
1443
  }
1353
1444
  ];
1445
+ if (profile?.token) {
1446
+ attributes.push({
1447
+ key: "_login_user",
1448
+ value: "1"
1449
+ });
1450
+ }
1451
+ return attributes;
1354
1452
  }, [profile?.memberType, profile?.token, userType, hasPlusMember]);
1355
1453
  const functionAttributes = react.useMemo(() => {
1356
- return [
1357
- cart?.discountCodes && {
1454
+ const hasFunctionEnvAttribute = cart?.lineItems.some(
1455
+ (item) => item.customAttributes?.some((attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY)
1456
+ );
1457
+ const discountCodes = cart?.discountCodes.map((item) => item.code).filter((code) => code) || [];
1458
+ return hasFunctionEnvAttribute ? [
1459
+ {
1358
1460
  key: "_discounts_function_env",
1359
1461
  value: JSON.stringify({
1360
- discount_code: cart?.discountCodes.map((item) => item.code),
1462
+ discount_code: discountCodes,
1361
1463
  user_tags: customer?.tags || []
1362
1464
  })
1363
1465
  }
1364
- ];
1466
+ ] : [];
1365
1467
  }, [cart]);
1366
1468
  const presellAttributes = react.useMemo(() => {
1367
1469
  return [
@@ -1393,18 +1495,50 @@ var useCartAttributes = ({
1393
1495
  }
1394
1496
  ];
1395
1497
  }, [currentUrl]);
1498
+ const commonAttributes = react.useMemo(
1499
+ () => [
1500
+ ...memberAttributes,
1501
+ ...functionAttributes,
1502
+ ...presellAttributes,
1503
+ ...weightAttributes,
1504
+ ...trackingAttributes,
1505
+ ...getReferralAttributes()
1506
+ ].filter((item) => item?.value),
1507
+ [memberAttributes, functionAttributes, presellAttributes, weightAttributes, trackingAttributes]
1508
+ );
1509
+ const extraAttributesInCart = react.useMemo(() => {
1510
+ const commonAttributeKeys = [
1511
+ // member attributes
1512
+ "_token",
1513
+ "_member_type",
1514
+ "_user_type",
1515
+ "_is_login",
1516
+ "_login_user",
1517
+ // function attributes
1518
+ "_discounts_function_env",
1519
+ // presell attributes
1520
+ "_presale",
1521
+ // weight attributes
1522
+ "_weight",
1523
+ "_app_source_name",
1524
+ // tracking attributes
1525
+ "utm_params",
1526
+ // referral attributes
1527
+ "_invite_code",
1528
+ "_play_mode_id",
1529
+ "_popup"
1530
+ ];
1531
+ return cart?.customAttributes?.filter(
1532
+ (item) => !commonAttributeKeys.includes(item.key)
1533
+ ) || [];
1534
+ }, [cart]);
1396
1535
  return react.useMemo(
1397
1536
  () => ({
1398
- attributes: [
1399
- ...memberAttributes,
1400
- ...functionAttributes,
1401
- ...presellAttributes,
1402
- ...weightAttributes,
1403
- ...trackingAttributes,
1404
- ...getReferralAttributes()
1405
- ].filter((item) => item?.value)
1537
+ attributes: [...commonAttributes, ...extraAttributesInCart].filter(
1538
+ (item) => item?.value
1539
+ )
1406
1540
  }),
1407
- [memberAttributes, functionAttributes, presellAttributes, weightAttributes, trackingAttributes]
1541
+ [commonAttributes, extraAttributesInCart]
1408
1542
  );
1409
1543
  };
1410
1544
  var DEFAULT_MIN = 1;
@@ -1467,7 +1601,7 @@ var useUpdateLineCodeAmountAttributes = ({
1467
1601
  );
1468
1602
  const functionEnvValue = getDiscountEnvAttributeValue(line.customAttributes);
1469
1603
  const hasSameFunctionEnvAttribute = Number(functionEnvValue.discounted_amount) === Number(line.totalAmount);
1470
- if (!hasSameFunctionEnvAttribute && hasFunctionEnvAttribute) {
1604
+ if (!hasSameFunctionEnvAttribute && hasFunctionEnvAttribute && !functionEnvValue.is_gift) {
1471
1605
  attrNeedUpdate.push({
1472
1606
  key: CUSTOMER_ATTRIBUTE_KEY,
1473
1607
  value: JSON.stringify({
@@ -1506,29 +1640,22 @@ var useUpdateLineCodeAmountAttributes = ({
1506
1640
  }).filter(
1507
1641
  ({ attrNeedUpdate, attrNeedDelete }) => attrNeedUpdate.length || attrNeedDelete.length
1508
1642
  ).map(({ line, attrNeedUpdate, attrNeedDelete }) => {
1643
+ let lineId = line.id;
1644
+ let attributes = line.customAttributes || [];
1645
+ if (attrNeedDelete.length) {
1646
+ attributes = attributes.filter(
1647
+ (attr) => !attrNeedDelete.includes(attr.key)
1648
+ );
1649
+ }
1509
1650
  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
- };
1651
+ attributes = attributes.filter(
1652
+ (attr) => !attrNeedUpdate.some((updateAttr) => updateAttr.key === attr.key)
1653
+ ).concat(attrNeedUpdate);
1531
1654
  }
1655
+ return {
1656
+ id: lineId,
1657
+ attributes
1658
+ };
1532
1659
  }),
1533
1660
  [cart?.lineItems, mainProductDiscountCodes]
1534
1661
  );
@@ -1621,8 +1748,9 @@ function useProductsByHandles(options = {}) {
1621
1748
  metafieldIdentifiers
1622
1749
  });
1623
1750
  },
1624
- swrOptions || {
1625
- revalidateOnFocus: false
1751
+ {
1752
+ revalidateOnFocus: false,
1753
+ ...swrOptions
1626
1754
  }
1627
1755
  );
1628
1756
  }
@@ -2538,6 +2666,73 @@ var usePlusMemberDeliveryCodes = ({
2538
2666
  [deliveryData]
2539
2667
  );
2540
2668
  };
2669
+ function useUpdateCartDeliveryOptions(mutate, metafieldIdentifiers, options) {
2670
+ const { client, locale, cartCookieAdapter } = useShopify();
2671
+ const updateDeliveryOptions = react.useCallback(
2672
+ async (_key, { arg }) => {
2673
+ const updatedCart = await shopifySdk.updateCartDeliveryOptions(client, {
2674
+ ...arg,
2675
+ metafieldIdentifiers,
2676
+ cookieAdapter: cartCookieAdapter
2677
+ });
2678
+ console.log("useUpdateCartDeliveryOptions updatedCart", updatedCart);
2679
+ if (updatedCart) {
2680
+ mutate(updatedCart);
2681
+ }
2682
+ return updatedCart;
2683
+ },
2684
+ [client, locale, cartCookieAdapter, mutate]
2685
+ );
2686
+ return useSWRMutation__default.default("update-cart-delivery-options", updateDeliveryOptions, options);
2687
+ }
2688
+
2689
+ // src/hooks/member/plus/use-update-plus-member-delivery-options.ts
2690
+ var useUpdatePlusMemberDeliveryOptions = ({
2691
+ options
2692
+ } = {}) => {
2693
+ const { cart: cartContextData, mutateCart, metafieldIdentifiers } = useCartContext();
2694
+ const { trigger: updateCartDeliveryOptions2 } = useUpdateCartDeliveryOptions(
2695
+ mutateCart,
2696
+ metafieldIdentifiers
2697
+ );
2698
+ const handler = react.useCallback(
2699
+ async (_, { arg }) => {
2700
+ const currentCart = arg?.cart || cartContextData;
2701
+ const { deliveryData } = arg;
2702
+ const firstDeliveryGroup = currentCart?.deliveryGroups?.[0];
2703
+ const deliveryGroupId = firstDeliveryGroup?.id;
2704
+ const selectedOptionCode = deliveryData?.deliveryCustomData?.selected_delivery_option?.code;
2705
+ if (!deliveryGroupId || !selectedOptionCode || selectedOptionCode === firstDeliveryGroup?.selectedDeliveryOption?.code) {
2706
+ return null;
2707
+ }
2708
+ const deliveryGroup = currentCart?.deliveryGroups?.find(
2709
+ (group) => group?.id === deliveryGroupId
2710
+ );
2711
+ const matchedOption = deliveryGroup?.deliveryOptions?.find(
2712
+ (option) => option?.code === selectedOptionCode
2713
+ );
2714
+ if (!matchedOption?.handle) {
2715
+ return null;
2716
+ }
2717
+ const deliveryOptions = [
2718
+ {
2719
+ deliveryGroupId,
2720
+ deliveryOptionHandle: matchedOption.handle
2721
+ }
2722
+ ];
2723
+ const updatedCart = await updateCartDeliveryOptions2({
2724
+ selectedDeliveryOptions: deliveryOptions,
2725
+ cartId: currentCart?.id
2726
+ });
2727
+ if (updatedCart && mutateCart) {
2728
+ mutateCart(updatedCart);
2729
+ }
2730
+ return updatedCart;
2731
+ },
2732
+ [cartContextData, updateCartDeliveryOptions2, mutateCart]
2733
+ );
2734
+ return useSWRMutation__default.default("update-cart-delivery-options", handler, options);
2735
+ };
2541
2736
  var usePlusMemberItemCustomAttributes = ({
2542
2737
  deliveryData
2543
2738
  }) => {
@@ -2557,48 +2752,18 @@ var usePlusMemberCheckoutCustomAttributes = ({
2557
2752
  deliveryData,
2558
2753
  product,
2559
2754
  variant,
2560
- customer,
2561
2755
  isShowShippingBenefits
2562
2756
  }) => {
2563
2757
  const { deliveryCustomData } = deliveryData || {};
2564
2758
  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
2759
  return react.useMemo(() => {
2582
2760
  const checkoutCustomAttributes = [
2583
- {
2584
- key: "_token",
2585
- value: profile?.token || ""
2586
- },
2761
+ // _last_url: 付费会员结算完成之后 checkout 有一个继续购买的按钮, 用于跳转到继续购买的页面
2587
2762
  {
2588
2763
  key: "_last_url",
2589
2764
  value: typeof window !== "undefined" ? window.location.origin + window.location.pathname : ""
2590
- },
2591
- {
2592
- key: "_user_type",
2593
- value: userType
2594
2765
  }
2595
2766
  ];
2596
- if (profile) {
2597
- checkoutCustomAttributes.push({
2598
- key: "_login_user",
2599
- value: "1"
2600
- });
2601
- }
2602
2767
  if (deliveryCustomData) {
2603
2768
  checkoutCustomAttributes.push({
2604
2769
  key: "_checkout_delivery_custom",
@@ -2608,12 +2773,6 @@ var usePlusMemberCheckoutCustomAttributes = ({
2608
2773
  })
2609
2774
  });
2610
2775
  }
2611
- if (variant?.metafields?.presell) {
2612
- checkoutCustomAttributes.push({
2613
- key: "_presale",
2614
- value: "true"
2615
- });
2616
- }
2617
2776
  if (isShowShippingBenefits && !isShowShippingBenefits({ variant, product, setting: {} })) {
2618
2777
  checkoutCustomAttributes.push({
2619
2778
  key: "_hide_shipping",
@@ -2621,18 +2780,17 @@ var usePlusMemberCheckoutCustomAttributes = ({
2621
2780
  });
2622
2781
  }
2623
2782
  return checkoutCustomAttributes;
2624
- }, [deliveryCustomData, product, profile, userType, variant, isShowShippingBenefits]);
2783
+ }, [deliveryCustomData, product, profile, variant, isShowShippingBenefits]);
2625
2784
  };
2626
2785
  function useAutoRemovePlusMemberInCart({
2627
- metafields,
2628
- isMonthlyPlus,
2629
- isAnnualPlus
2786
+ cart,
2787
+ profile,
2788
+ memberSetting
2630
2789
  }) {
2631
- const { plus_monthly_product, plus_annual_product } = metafields || {};
2632
- const { cart } = useCartContext();
2790
+ const { plus_monthly_product, plus_annual_product } = memberSetting || {};
2633
2791
  const { trigger: removeCartLines2 } = useRemoveCartLines();
2634
2792
  react.useEffect(() => {
2635
- if (!cart) return;
2793
+ if (!cart || !plus_monthly_product || !plus_annual_product) return;
2636
2794
  const removePlusProduct = async (productType) => {
2637
2795
  if (!productType) return;
2638
2796
  const product = cart.lineItems?.find(
@@ -2644,33 +2802,25 @@ function useAutoRemovePlusMemberInCart({
2644
2802
  });
2645
2803
  }
2646
2804
  };
2647
- if (isMonthlyPlus) {
2805
+ if (profile?.isMonthlyPlus) {
2648
2806
  removePlusProduct(plus_monthly_product);
2649
2807
  }
2650
- if (isAnnualPlus) {
2808
+ if (profile?.isAnnualPlus) {
2651
2809
  removePlusProduct(plus_annual_product);
2652
2810
  }
2653
- }, [
2654
- cart,
2655
- plus_annual_product,
2656
- plus_monthly_product,
2657
- isAnnualPlus,
2658
- isMonthlyPlus,
2659
- removeCartLines2
2660
- ]);
2811
+ }, [cart, plus_annual_product, plus_monthly_product, profile, removeCartLines2]);
2661
2812
  }
2662
2813
  function useAddPlusMemberProductsToCart({
2663
2814
  cart,
2664
- memberSetting,
2665
- selectedPlusMemberMode,
2666
- selectedPlusMemberProduct
2815
+ profile
2667
2816
  }) {
2817
+ const { selectedPlusMemberMode, selectedPlusMemberProduct, plusMemberMetafields } = usePlusMemberContext();
2668
2818
  const { hasMonthlyPlus, hasAnnualPlus } = useHasPlusMemberInCart({
2669
- cart,
2670
- memberSetting
2819
+ memberSetting: plusMemberMetafields,
2820
+ cart
2671
2821
  });
2672
2822
  const plusMemberProduct = react.useMemo(() => {
2673
- if (selectedPlusMemberMode === "free" /* FREE */) {
2823
+ if (!selectedPlusMemberProduct || selectedPlusMemberMode === "free" /* FREE */) {
2674
2824
  return void 0;
2675
2825
  }
2676
2826
  if (selectedPlusMemberMode === "monthly" /* MONTHLY */ && hasMonthlyPlus) {
@@ -2679,7 +2829,10 @@ function useAddPlusMemberProductsToCart({
2679
2829
  if (selectedPlusMemberMode === "annual" /* ANNUAL */ && hasAnnualPlus) {
2680
2830
  return void 0;
2681
2831
  }
2682
- if (!selectedPlusMemberProduct) {
2832
+ if (profile?.isMonthlyPlus && selectedPlusMemberMode === "monthly" /* MONTHLY */) {
2833
+ return void 0;
2834
+ }
2835
+ if (profile?.isAnnualPlus && selectedPlusMemberMode === "annual" /* ANNUAL */) {
2683
2836
  return void 0;
2684
2837
  }
2685
2838
  return selectedPlusMemberProduct;
@@ -2971,8 +3124,6 @@ exports.RuleType = RuleType;
2971
3124
  exports.SCRIPT_CODE_AMOUNT_KEY = SCRIPT_CODE_AMOUNT_KEY;
2972
3125
  exports.ShippingMethodMode = ShippingMethodMode;
2973
3126
  exports.SpendMoneyType = SpendMoneyType;
2974
- exports.atobID = atobID;
2975
- exports.btoaID = btoaID;
2976
3127
  exports.checkAttributesUpdateNeeded = checkAttributesUpdateNeeded;
2977
3128
  exports.clearGeoLocationCache = clearGeoLocationCache;
2978
3129
  exports.createMockCartFromLines = createMockCartFromLines;
@@ -3035,6 +3186,7 @@ exports.useSite = useSite;
3035
3186
  exports.useUpdateCartAttributes = useUpdateCartAttributes;
3036
3187
  exports.useUpdateCartLines = useUpdateCartLines;
3037
3188
  exports.useUpdateLineCodeAmountAttributes = useUpdateLineCodeAmountAttributes;
3189
+ exports.useUpdatePlusMemberDeliveryOptions = useUpdatePlusMemberDeliveryOptions;
3038
3190
  exports.useUpdateVariantQuery = useUpdateVariantQuery;
3039
3191
  exports.useVariant = useVariant;
3040
3192
  exports.useVariantMedia = useVariantMedia;