@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.
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ var shopifySdk = require('@anker-in/shopify-sdk');
5
5
  var Cookies5 = require('js-cookie');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
  var Decimal2 = require('decimal.js');
8
+ var shopifyCore = require('@anker-in/shopify-core');
8
9
  var useSWR = require('swr');
9
10
  var useSWRMutation = require('swr/mutation');
10
11
  var ahooks = require('ahooks');
@@ -148,9 +149,10 @@ function normalizeAddToCartLines(lines) {
148
149
  const variant = line.variant;
149
150
  const product = variant.product;
150
151
  const quantity = line.quantity || 1;
151
- const price = variant.finalPrice?.amount ? Number(variant.finalPrice.amount) : variant.compareAtPrice?.amount ? Number(variant.compareAtPrice.amount) : variant.price?.amount ? Number(variant.price.amount) : 0;
152
- const subtotalAmount = price * quantity;
153
- const totalAmount = subtotalAmount;
152
+ const originalPrice = variant.price?.amount ? Number(variant.price.amount) : 0;
153
+ const finalPrice = variant.finalPrice?.amount ? Number(variant.finalPrice.amount) : originalPrice;
154
+ const subtotalAmount = originalPrice * quantity;
155
+ const totalAmount = finalPrice * quantity;
154
156
  return {
155
157
  id: `temp-line-${index}-${variant.id}`,
156
158
  // Temporary ID for pre-cart lines
@@ -164,7 +166,7 @@ function normalizeAddToCartLines(lines) {
164
166
  customAttributes: line.attributes || [],
165
167
  variant: {
166
168
  id: variant.id,
167
- price,
169
+ price: finalPrice,
168
170
  listPrice: variant.compareAtPrice?.amount ? Number(variant.compareAtPrice.amount) : 0,
169
171
  sku: variant.sku || "",
170
172
  name: variant.title || "",
@@ -195,15 +197,16 @@ function createMockCartFromLines(lines, existingCart) {
195
197
  const normalizedLines = normalizeAddToCartLines(lines);
196
198
  const subtotalPrice = normalizedLines.reduce((sum, line) => sum + line.subtotalAmount, 0);
197
199
  const totalPrice = normalizedLines.reduce((sum, line) => sum + line.totalAmount, 0);
200
+ const currency = lines[0]?.variant?.price?.currencyCode;
198
201
  return {
199
202
  id: existingCart?.id || "temp-cart-id",
200
203
  customerId: existingCart?.customerId,
201
204
  email: existingCart?.email,
202
205
  createdAt: existingCart?.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
203
- currency: existingCart?.currency || { code: "USD" },
206
+ currency: existingCart?.currency || { code: currency },
204
207
  taxesIncluded: existingCart?.taxesIncluded,
205
208
  lineItems: normalizedLines,
206
- totallineItemsDiscount: 0,
209
+ totalLineItemsDiscount: 0,
207
210
  orderDiscounts: 0,
208
211
  lineItemsSubtotalPrice: subtotalPrice,
209
212
  subtotalPrice,
@@ -234,22 +237,12 @@ var getQuery = () => {
234
237
  }
235
238
  return theRequest;
236
239
  };
237
- function atobID(id) {
238
- if (id && typeof id === "string" && id.includes("/")) {
239
- return id.split("/").pop()?.split("?")?.shift();
240
- } else {
241
- return id;
242
- }
243
- }
244
- function btoaID(id, type = "ProductVariant") {
245
- return `gid://shopify/${type}/${id}`;
246
- }
247
240
  var getMatchedMainProductSubTotal = (cartData, variant_list, main_product) => {
248
241
  const isAllStoreVariant = main_product?.all_store_variant ?? false;
249
242
  const matchedList = cartData?.lineItems?.filter((line) => {
250
243
  const { is_gift } = getDiscountEnvAttributeValue(line.customAttributes);
251
244
  return isAllStoreVariant ? !is_gift : variant_list?.find((item) => {
252
- return !is_gift && atobID(line.variantId) === item;
245
+ return !is_gift && shopifyCore.atobID(line.variantId) === item;
253
246
  });
254
247
  });
255
248
  return matchedList?.reduce((acc, line) => {
@@ -453,6 +446,7 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
453
446
  }
454
447
  return cart;
455
448
  }, [lines, cart]);
449
+ console.log("effectiveCart useCalcAutoFreeGift", effectiveCart);
456
450
  const { activeCampaign, subtotal } = react.useMemo(() => {
457
451
  for (const campaign of autoFreeGiftConfig) {
458
452
  const { rule_conditions = [], rule_result } = campaign;
@@ -468,6 +462,7 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
468
462
  all_store_variant: spend_get_reward.main_product?.all_store_variant || false
469
463
  }
470
464
  );
465
+ console.log("matchedSubtotal useCalcAutoFreeGift", matchedSubtotal);
471
466
  if (matchedSubtotal > 0) {
472
467
  return { activeCampaign: campaign, subtotal: matchedSubtotal };
473
468
  }
@@ -480,11 +475,20 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
480
475
  return { qualifyingGift: null, nextTierGoal: null };
481
476
  }
482
477
  const giftTiers = activeCampaign.rule_result.spend_get_reward.gift_product;
483
- const qualifyingTier = [...giftTiers].reverse().find((tier) => subtotal >= Number(tier.spend_sum_money));
484
- const nextGoal = giftTiers.find((tier) => subtotal < Number(tier.spend_sum_money));
478
+ const currentCurrency = effectiveCart?.currency?.code || "";
479
+ console.log("currentCurrency useCalcAutoFreeGift", effectiveCart, currentCurrency);
480
+ const getThresholdAmount = (tier) => {
481
+ if (tier.spend_sum_money_multi_markets?.[currentCurrency]?.value) {
482
+ return Number(tier.spend_sum_money_multi_markets[currentCurrency].value);
483
+ }
484
+ return Number(tier.spend_sum_money || 0);
485
+ };
486
+ const qualifyingTier = [...giftTiers].sort((a, b) => getThresholdAmount(b) - getThresholdAmount(a)).find((tier) => subtotal >= getThresholdAmount(tier));
487
+ const nextGoal = giftTiers.find((tier) => subtotal < getThresholdAmount(tier));
485
488
  if (!qualifyingTier) {
486
489
  return { qualifyingGift: null, nextTierGoal: nextGoal || null };
487
490
  }
491
+ const actualThreshold = getThresholdAmount(qualifyingTier);
488
492
  const formattedGift = {
489
493
  tier: qualifyingTier,
490
494
  itemsToAdd: qualifyingTier.reward_list?.map((reward) => {
@@ -492,7 +496,7 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
492
496
  if (!giftProduct) return null;
493
497
  return {
494
498
  variant: {
495
- id: btoaID(giftProduct.variant_id),
499
+ id: shopifyCore.btoaID(giftProduct.variant_id),
496
500
  handle: giftProduct.handle,
497
501
  sku: giftProduct.sku
498
502
  },
@@ -503,7 +507,10 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
503
507
  value: JSON.stringify({
504
508
  is_gift: true,
505
509
  rule_id: activeCampaign.rule_id,
506
- spend_sum_money: qualifyingTier.spend_sum_money
510
+ spend_sum_money: actualThreshold,
511
+ // 使用实际的门槛金额(多币种支持)
512
+ currency_code: currentCurrency
513
+ // 记录当前币种
507
514
  })
508
515
  }
509
516
  ]
@@ -511,7 +518,7 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
511
518
  }).filter((item) => item !== null)
512
519
  };
513
520
  return { qualifyingGift: formattedGift, nextTierGoal: nextGoal || null };
514
- }, [activeCampaign, subtotal]);
521
+ }, [activeCampaign, subtotal, effectiveCart]);
515
522
  const giftHandles = react.useMemo(() => {
516
523
  const giftVariant = autoFreeGiftConfig.map(
517
524
  (item) => item.rule_result?.spend_get_reward?.gift_product?.map(
@@ -527,18 +534,24 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
527
534
  }
528
535
  return true;
529
536
  }, [giftHandles]);
530
- const { data: giftProductsResult } = useSWR__default.default(shouldFetch ? giftHandles : null, async () => {
531
- const res = await shopifySdk.getProductsByHandles(client, {
532
- handles: giftHandles,
533
- locale
534
- });
535
- const result = Array.isArray(res) ? res : [];
536
- giftProductsCache.current = {
537
- data: result,
538
- giftHandles: [...giftHandles]
539
- };
540
- return result;
541
- });
537
+ const { data: giftProductsResult } = useSWR__default.default(
538
+ shouldFetch ? giftHandles : null,
539
+ async () => {
540
+ const res = await shopifySdk.getProductsByHandles(client, {
541
+ handles: giftHandles,
542
+ locale
543
+ });
544
+ const result = Array.isArray(res) ? res : [];
545
+ giftProductsCache.current = {
546
+ data: result,
547
+ giftHandles: [...giftHandles]
548
+ };
549
+ return result;
550
+ },
551
+ {
552
+ revalidateOnFocus: false
553
+ }
554
+ );
542
555
  const finalGiftProductsResult = react.useMemo(() => {
543
556
  if (giftProductsCache.current && !shouldFetch) {
544
557
  return giftProductsCache.current.data || void 0;
@@ -591,12 +604,14 @@ var useScriptAutoFreeGift = ({
591
604
  upgrade_multiple2 = 1.2;
592
605
  upgrade_value2 = 40;
593
606
  }
594
- effectiveCart?.lineItems?.forEach(({ customAttributes }) => {
595
- customAttributes?.forEach(({ key, value }) => {
596
- if (key === "_amount_upgrade_multiple") upgrade_multiple2 = Number(value) || 1;
597
- if (key === "_amount_upgrade_value") upgrade_value2 = Number(value) || 0;
598
- });
599
- });
607
+ effectiveCart?.lineItems?.forEach(
608
+ ({ customAttributes }) => {
609
+ customAttributes?.forEach(({ key, value }) => {
610
+ if (key === "_amount_upgrade_multiple") upgrade_multiple2 = Number(value) || 1;
611
+ if (key === "_amount_upgrade_value") upgrade_value2 = Number(value) || 0;
612
+ });
613
+ }
614
+ );
600
615
  return [upgrade_multiple2, upgrade_value2];
601
616
  }, [effectiveCart?.lineItems, points_subscribe]);
602
617
  const breakpoints = react.useMemo(() => {
@@ -661,18 +676,24 @@ var useScriptAutoFreeGift = ({
661
676
  const nextLevel = levelIndex > 0 ? sortedLevels[levelIndex - 1] ?? null : null;
662
677
  return [currentLevel, nextLevel];
663
678
  }, [breakpoints, involvedSubTotal, involvedLines.length]);
664
- const { data: giftProductsResult } = useSWR__default.default(shouldFetch ? giftHandles : null, async () => {
665
- const res = await shopifySdk.getProductsByHandles(client, {
666
- handles: giftHandles,
667
- locale
668
- });
669
- const result = Array.isArray(res) ? res : [];
670
- giftProductsCache.current = {
671
- data: result,
672
- giftHandles: [...giftHandles]
673
- };
674
- return result;
675
- });
679
+ const { data: giftProductsResult } = useSWR__default.default(
680
+ shouldFetch ? giftHandles : null,
681
+ async () => {
682
+ const res = await shopifySdk.getProductsByHandles(client, {
683
+ handles: giftHandles,
684
+ locale
685
+ });
686
+ const result = Array.isArray(res) ? res : [];
687
+ giftProductsCache.current = {
688
+ data: result,
689
+ giftHandles: [...giftHandles]
690
+ };
691
+ return result;
692
+ },
693
+ {
694
+ revalidateOnFocus: false
695
+ }
696
+ );
676
697
  const finalGiftProductsResult = react.useMemo(() => {
677
698
  if (giftProductsCache.current && !shouldFetch) {
678
699
  return giftProductsCache.current.data || void 0;
@@ -858,10 +879,10 @@ var trackBuyNowGA = ({
858
879
  return;
859
880
  }
860
881
  const { variant } = lineItems[0];
861
- const currencyCode = variant.price?.currencyCode;
882
+ const currencyCode = variant.product?.price?.currencyCode || variant.price?.currencyCode;
862
883
  const totalPrice = lineItems?.reduce(
863
884
  (prev, { variant: variant2 }) => prev.plus(
864
- variant2?.finalPrice?.amount ?? variant2?.compareAtPrice?.amount ?? (variant2?.price?.amount || 0)
885
+ variant2?.finalPrice?.amount ?? variant2?.compareAtPrice?.amount ?? variant2?.price?.amount ?? 0
865
886
  ),
866
887
  new Decimal2__default.default(0)
867
888
  ).toNumber();
@@ -935,7 +956,7 @@ function useApplyCartCodes(options) {
935
956
  if (!discountCodes?.length) {
936
957
  throw new Error("Invalid input used for this operation: Miss discountCode");
937
958
  }
938
- const cartId = providedCartId ? void 0 : providedCartId || cart?.id;
959
+ const cartId = providedCartId || cart?.id;
939
960
  if (!cartId) {
940
961
  return void 0;
941
962
  }
@@ -948,6 +969,12 @@ function useApplyCartCodes(options) {
948
969
  cookieAdapter: cartCookieAdapter,
949
970
  metafieldIdentifiers
950
971
  });
972
+ const unApplicableCodes = discountCodes.filter(
973
+ (code) => updatedCart?.discountCodes?.find((item) => item.code === code && !item.applicable)
974
+ );
975
+ if (unApplicableCodes.length) {
976
+ throw new Error(`${unApplicableCodes.join(", ")} is not applicable to the cart`);
977
+ }
951
978
  if (updatedCart) {
952
979
  mutateCart(updatedCart);
953
980
  }
@@ -963,7 +990,7 @@ function useRemoveCartCodes(options) {
963
990
  const removeCodes = react.useCallback(
964
991
  async (_key, { arg }) => {
965
992
  const { cartId: providedCartId, discountCodes } = arg;
966
- const cartId = providedCartId ? void 0 : providedCartId || cart?.id;
993
+ const cartId = providedCartId || cart?.id;
967
994
  const codes = cart?.discountCodes?.filter((code) => !!code.applicable) || [];
968
995
  const leftCodes = codes.filter((code) => discountCodes?.length ? !discountCodes.includes(code.code) : code.code).map((code) => code.code);
969
996
  const updatedCart = await shopifySdk.updateCartCodes(client, {
@@ -982,10 +1009,65 @@ function useRemoveCartCodes(options) {
982
1009
  return useSWRMutation__default.default("remove-codes", removeCodes, options);
983
1010
  }
984
1011
 
1012
+ // src/hooks/cart/utils/add-to-cart.ts
1013
+ var getLinesWithAttributes = ({
1014
+ cart,
1015
+ lineItems
1016
+ }) => {
1017
+ return lineItems.map((line) => {
1018
+ const sameLineInCart = cart?.lineItems.find(
1019
+ (lineInCart) => lineInCart.variant.sku === line.variant?.sku && lineInCart.product?.handle === line.variant?.product?.handle
1020
+ );
1021
+ const codeAmountAttribute = sameLineInCart?.customAttributes?.find(
1022
+ (attr) => attr.key === CODE_AMOUNT_KEY
1023
+ );
1024
+ const scriptCodeAmountAttribute = sameLineInCart?.customAttributes?.find(
1025
+ (attr) => attr.key === SCRIPT_CODE_AMOUNT_KEY
1026
+ );
1027
+ let functionAttribute = null;
1028
+ try {
1029
+ functionAttribute = sameLineInCart?.customAttributes?.find(
1030
+ (attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY && JSON.parse(attr.value)?.discounted_amount
1031
+ );
1032
+ } catch (error) {
1033
+ }
1034
+ if (codeAmountAttribute || functionAttribute || scriptCodeAmountAttribute) {
1035
+ return {
1036
+ ...line,
1037
+ attributes: [
1038
+ ...line.attributes || [],
1039
+ codeAmountAttribute,
1040
+ functionAttribute,
1041
+ scriptCodeAmountAttribute
1042
+ ].filter(Boolean)
1043
+ };
1044
+ }
1045
+ return line;
1046
+ });
1047
+ };
1048
+ var getLinesWithFunctionAttributes = (lineItems) => {
1049
+ return lineItems.map((line) => {
1050
+ let itemAttributes = line.attributes || [];
1051
+ const functionEnvAttribute = itemAttributes.find((attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY);
1052
+ if (!functionEnvAttribute) {
1053
+ itemAttributes = itemAttributes.concat([
1054
+ {
1055
+ key: CUSTOMER_ATTRIBUTE_KEY,
1056
+ value: JSON.stringify({
1057
+ is_gift: false,
1058
+ discounted_amount: Number(line.variant?.finalPrice?.amount || line.variant?.price?.amount) * (line.quantity || 1)
1059
+ })
1060
+ }
1061
+ ]);
1062
+ }
1063
+ return { ...line, attributes: itemAttributes };
1064
+ });
1065
+ };
1066
+
985
1067
  // src/hooks/cart/use-add-to-cart.ts
986
1068
  function useAddToCart({ withTrack = true } = {}, swrOptions) {
987
1069
  const { client, config, locale, cartCookieAdapter, userAdapter } = useShopify();
988
- const { cart } = useCartContext();
1070
+ const { cart, addCustomAttributes } = useCartContext();
989
1071
  const { trigger: applyCartCodes } = useApplyCartCodes();
990
1072
  const { trigger: removeInvalidCodes } = useRemoveCartCodes();
991
1073
  const { trigger: addCartLines2 } = useAddCartLines();
@@ -999,12 +1081,18 @@ function useAddToCart({ withTrack = true } = {}, swrOptions) {
999
1081
  buyerIdentity,
1000
1082
  needCreateCart = false,
1001
1083
  onCodesInvalid,
1002
- replaceExistingCodes
1084
+ replaceExistingCodes,
1085
+ customAttributes
1003
1086
  } = arg;
1004
1087
  if (!lineItems || lineItems.length === 0) {
1005
1088
  return;
1006
1089
  }
1007
- const lines = lineItems.map((item) => ({
1090
+ const linesWithAttributes = getLinesWithAttributes({
1091
+ cart,
1092
+ lineItems
1093
+ });
1094
+ const linesWithFunctionAttributes = getLinesWithFunctionAttributes(linesWithAttributes);
1095
+ const lines = linesWithFunctionAttributes.map((item) => ({
1008
1096
  merchandiseId: item.variant?.id || "",
1009
1097
  quantity: item.quantity || 1,
1010
1098
  attributes: item.attributes,
@@ -1044,6 +1132,9 @@ function useAddToCart({ withTrack = true } = {}, swrOptions) {
1044
1132
  discountCodes
1045
1133
  });
1046
1134
  }
1135
+ if (customAttributes && customAttributes.length > 0) {
1136
+ addCustomAttributes(customAttributes);
1137
+ }
1047
1138
  if (withTrack) {
1048
1139
  trackAddToCartGA({
1049
1140
  lineItems,
@@ -1152,7 +1243,8 @@ function useBuyNow({ withTrack = true } = {}, swrOptions) {
1152
1243
  if (!lineItems || lineItems.length === 0) {
1153
1244
  return;
1154
1245
  }
1155
- const lines = lineItems.map((item) => ({
1246
+ const linesWithFunctionAttributes = getLinesWithFunctionAttributes(lineItems);
1247
+ const lines = linesWithFunctionAttributes.map((item) => ({
1156
1248
  merchandiseId: item.variant?.id || "",
1157
1249
  quantity: item.quantity || 1,
1158
1250
  attributes: item.attributes,
@@ -1300,9 +1392,12 @@ var useCalcOrderDiscount = (cart, orderDiscountConfig, customer) => {
1300
1392
  discountAmount: 0
1301
1393
  };
1302
1394
  }
1303
- const tieredDiscounts = activeCampaign.result_detail.order_discount_conf.tiered_discounts;
1304
- const qualifyingTier = [...tieredDiscounts].reverse().find((tier) => subtotal >= Number(tier.amount));
1305
- const nextGoal = tieredDiscounts.find((tier) => subtotal < Number(tier.amount));
1395
+ const currentCurrency = cart?.currency?.code || "";
1396
+ console.log("currentCurrency", cart, currentCurrency);
1397
+ const orderDiscountConf = activeCampaign.result_detail.order_discount_conf;
1398
+ const tieredDiscounts = orderDiscountConf.tiered_discounts_markets?.[currentCurrency] || orderDiscountConf.tiered_discounts;
1399
+ const qualifyingTier = [...tieredDiscounts].sort((a, b) => Number(b.amount) - Number(a.amount)).find((tier) => subtotal >= Number(tier.amount));
1400
+ const nextGoal = [...tieredDiscounts].sort((a, b) => Number(a.amount) - Number(b.amount)).find((tier) => subtotal < Number(tier.amount));
1306
1401
  if (!qualifyingTier) {
1307
1402
  return {
1308
1403
  qualifyingDiscount: null,
@@ -1370,12 +1465,10 @@ function useHasPlusMemberInCart({
1370
1465
  };
1371
1466
  }, [cart?.lineItems, plus_monthly_product, plus_annual_product]);
1372
1467
  }
1373
-
1374
- // src/hooks/cart/feature/use-cart-attributes.ts
1375
1468
  var getReferralAttributes = () => {
1376
- const inviteCode = Cookies5__default.default.get("invite_code");
1377
- const playModeId = Cookies5__default.default.get("playModeId");
1378
- const popup = Cookies5__default.default.get("_popup");
1469
+ const inviteCode = shopifySdk.getLocalStorage("invite_code") || Cookies5__default.default.get("invite_code");
1470
+ const playModeId = shopifySdk.getLocalStorage("playModeId") || Cookies5__default.default.get("playModeId");
1471
+ const popup = shopifySdk.getLocalStorage("_popup") || Cookies5__default.default.get("_popup");
1379
1472
  if (inviteCode && playModeId) {
1380
1473
  return popup ? [
1381
1474
  { key: "_invite_code", value: inviteCode ? inviteCode : "" },
@@ -1399,8 +1492,6 @@ var useCartAttributes = ({
1399
1492
  memberSetting,
1400
1493
  cart
1401
1494
  });
1402
- console.log("memberSetting", memberSetting);
1403
- console.log("hasPlusMember", hasPlusMember);
1404
1495
  react.useEffect(() => {
1405
1496
  setCurrentUrl(window.location.href);
1406
1497
  }, []);
@@ -1426,7 +1517,7 @@ var useCartAttributes = ({
1426
1517
  return "new_user_login";
1427
1518
  }, [customer]);
1428
1519
  const memberAttributes = react.useMemo(() => {
1429
- return [
1520
+ const attributes = [
1430
1521
  {
1431
1522
  key: "_token",
1432
1523
  value: profile?.token
@@ -1447,17 +1538,28 @@ var useCartAttributes = ({
1447
1538
  value: profile?.token ? "true" : "false"
1448
1539
  }
1449
1540
  ];
1541
+ if (profile?.token) {
1542
+ attributes.push({
1543
+ key: "_login_user",
1544
+ value: "1"
1545
+ });
1546
+ }
1547
+ return attributes;
1450
1548
  }, [profile?.memberType, profile?.token, userType, hasPlusMember]);
1451
1549
  const functionAttributes = react.useMemo(() => {
1452
- return [
1453
- cart?.discountCodes && {
1550
+ const hasFunctionEnvAttribute = cart?.lineItems.some(
1551
+ (item) => item.customAttributes?.some((attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY)
1552
+ );
1553
+ const discountCodes = cart?.discountCodes.map((item) => item.code).filter((code) => code) || [];
1554
+ return hasFunctionEnvAttribute ? [
1555
+ {
1454
1556
  key: "_discounts_function_env",
1455
1557
  value: JSON.stringify({
1456
- discount_code: cart?.discountCodes.map((item) => item.code),
1558
+ discount_code: discountCodes,
1457
1559
  user_tags: customer?.tags || []
1458
1560
  })
1459
1561
  }
1460
- ];
1562
+ ] : [];
1461
1563
  }, [cart]);
1462
1564
  const presellAttributes = react.useMemo(() => {
1463
1565
  return [
@@ -1489,18 +1591,50 @@ var useCartAttributes = ({
1489
1591
  }
1490
1592
  ];
1491
1593
  }, [currentUrl]);
1594
+ const commonAttributes = react.useMemo(
1595
+ () => [
1596
+ ...memberAttributes,
1597
+ ...functionAttributes,
1598
+ ...presellAttributes,
1599
+ ...weightAttributes,
1600
+ ...trackingAttributes,
1601
+ ...getReferralAttributes()
1602
+ ].filter((item) => item?.value),
1603
+ [memberAttributes, functionAttributes, presellAttributes, weightAttributes, trackingAttributes]
1604
+ );
1605
+ const extraAttributesInCart = react.useMemo(() => {
1606
+ const commonAttributeKeys = [
1607
+ // member attributes
1608
+ "_token",
1609
+ "_member_type",
1610
+ "_user_type",
1611
+ "_is_login",
1612
+ "_login_user",
1613
+ // function attributes
1614
+ "_discounts_function_env",
1615
+ // presell attributes
1616
+ "_presale",
1617
+ // weight attributes
1618
+ "_weight",
1619
+ "_app_source_name",
1620
+ // tracking attributes
1621
+ "utm_params",
1622
+ // referral attributes
1623
+ "_invite_code",
1624
+ "_play_mode_id",
1625
+ "_popup"
1626
+ ];
1627
+ return cart?.customAttributes?.filter(
1628
+ (item) => !commonAttributeKeys.includes(item.key)
1629
+ ) || [];
1630
+ }, [cart]);
1492
1631
  return react.useMemo(
1493
1632
  () => ({
1494
- attributes: [
1495
- ...memberAttributes,
1496
- ...functionAttributes,
1497
- ...presellAttributes,
1498
- ...weightAttributes,
1499
- ...trackingAttributes,
1500
- ...getReferralAttributes()
1501
- ].filter((item) => item?.value)
1633
+ attributes: [...commonAttributes, ...extraAttributesInCart].filter(
1634
+ (item) => item?.value
1635
+ )
1502
1636
  }),
1503
- [memberAttributes, functionAttributes, presellAttributes, weightAttributes, trackingAttributes]
1637
+ [commonAttributes, extraAttributesInCart]
1504
1638
  );
1505
1639
  };
1506
1640
  var DEFAULT_MIN = 1;
@@ -1563,7 +1697,7 @@ var useUpdateLineCodeAmountAttributes = ({
1563
1697
  );
1564
1698
  const functionEnvValue = getDiscountEnvAttributeValue(line.customAttributes);
1565
1699
  const hasSameFunctionEnvAttribute = Number(functionEnvValue.discounted_amount) === Number(line.totalAmount);
1566
- if (!hasSameFunctionEnvAttribute && hasFunctionEnvAttribute) {
1700
+ if (!hasSameFunctionEnvAttribute && hasFunctionEnvAttribute && !functionEnvValue.is_gift) {
1567
1701
  attrNeedUpdate.push({
1568
1702
  key: CUSTOMER_ATTRIBUTE_KEY,
1569
1703
  value: JSON.stringify({
@@ -1602,29 +1736,22 @@ var useUpdateLineCodeAmountAttributes = ({
1602
1736
  }).filter(
1603
1737
  ({ attrNeedUpdate, attrNeedDelete }) => attrNeedUpdate.length || attrNeedDelete.length
1604
1738
  ).map(({ line, attrNeedUpdate, attrNeedDelete }) => {
1739
+ let lineId = line.id;
1740
+ let attributes = line.customAttributes || [];
1741
+ if (attrNeedDelete.length) {
1742
+ attributes = attributes.filter(
1743
+ (attr) => !attrNeedDelete.includes(attr.key)
1744
+ );
1745
+ }
1605
1746
  if (attrNeedUpdate.length) {
1606
- return {
1607
- id: line.id,
1608
- attributes: [
1609
- ...line.customAttributes?.filter(
1610
- (attr) => !attrNeedUpdate.some((updateAttr) => updateAttr.key === attr.key)
1611
- ) || [],
1612
- ...attrNeedUpdate
1613
- ]
1614
- };
1615
- } else if (attrNeedDelete.length) {
1616
- return {
1617
- id: line.id,
1618
- attributes: line.customAttributes?.filter(
1619
- (attr) => !attrNeedDelete.includes(attr.key)
1620
- ) || []
1621
- };
1622
- } else {
1623
- return {
1624
- id: line.id,
1625
- attributes: line.customAttributes || []
1626
- };
1747
+ attributes = attributes.filter(
1748
+ (attr) => !attrNeedUpdate.some((updateAttr) => updateAttr.key === attr.key)
1749
+ ).concat(attrNeedUpdate);
1627
1750
  }
1751
+ return {
1752
+ id: lineId,
1753
+ attributes
1754
+ };
1628
1755
  }),
1629
1756
  [cart?.lineItems, mainProductDiscountCodes]
1630
1757
  );
@@ -1717,8 +1844,9 @@ function useProductsByHandles(options = {}) {
1717
1844
  metafieldIdentifiers
1718
1845
  });
1719
1846
  },
1720
- swrOptions || {
1721
- revalidateOnFocus: false
1847
+ {
1848
+ revalidateOnFocus: false,
1849
+ ...swrOptions
1722
1850
  }
1723
1851
  );
1724
1852
  }
@@ -2634,6 +2762,73 @@ var usePlusMemberDeliveryCodes = ({
2634
2762
  [deliveryData]
2635
2763
  );
2636
2764
  };
2765
+ function useUpdateCartDeliveryOptions(mutate, metafieldIdentifiers, options) {
2766
+ const { client, locale, cartCookieAdapter } = useShopify();
2767
+ const updateDeliveryOptions = react.useCallback(
2768
+ async (_key, { arg }) => {
2769
+ const updatedCart = await shopifySdk.updateCartDeliveryOptions(client, {
2770
+ ...arg,
2771
+ metafieldIdentifiers,
2772
+ cookieAdapter: cartCookieAdapter
2773
+ });
2774
+ console.log("useUpdateCartDeliveryOptions updatedCart", updatedCart);
2775
+ if (updatedCart) {
2776
+ mutate(updatedCart);
2777
+ }
2778
+ return updatedCart;
2779
+ },
2780
+ [client, locale, cartCookieAdapter, mutate]
2781
+ );
2782
+ return useSWRMutation__default.default("update-cart-delivery-options", updateDeliveryOptions, options);
2783
+ }
2784
+
2785
+ // src/hooks/member/plus/use-update-plus-member-delivery-options.ts
2786
+ var useUpdatePlusMemberDeliveryOptions = ({
2787
+ options
2788
+ } = {}) => {
2789
+ const { cart: cartContextData, mutateCart, metafieldIdentifiers } = useCartContext();
2790
+ const { trigger: updateCartDeliveryOptions2 } = useUpdateCartDeliveryOptions(
2791
+ mutateCart,
2792
+ metafieldIdentifiers
2793
+ );
2794
+ const handler = react.useCallback(
2795
+ async (_, { arg }) => {
2796
+ const currentCart = arg?.cart || cartContextData;
2797
+ const { deliveryData } = arg;
2798
+ const firstDeliveryGroup = currentCart?.deliveryGroups?.[0];
2799
+ const deliveryGroupId = firstDeliveryGroup?.id;
2800
+ const selectedOptionCode = deliveryData?.deliveryCustomData?.selected_delivery_option?.code;
2801
+ if (!deliveryGroupId || !selectedOptionCode || selectedOptionCode === firstDeliveryGroup?.selectedDeliveryOption?.code) {
2802
+ return null;
2803
+ }
2804
+ const deliveryGroup = currentCart?.deliveryGroups?.find(
2805
+ (group) => group?.id === deliveryGroupId
2806
+ );
2807
+ const matchedOption = deliveryGroup?.deliveryOptions?.find(
2808
+ (option) => option?.code === selectedOptionCode
2809
+ );
2810
+ if (!matchedOption?.handle) {
2811
+ return null;
2812
+ }
2813
+ const deliveryOptions = [
2814
+ {
2815
+ deliveryGroupId,
2816
+ deliveryOptionHandle: matchedOption.handle
2817
+ }
2818
+ ];
2819
+ const updatedCart = await updateCartDeliveryOptions2({
2820
+ selectedDeliveryOptions: deliveryOptions,
2821
+ cartId: currentCart?.id
2822
+ });
2823
+ if (updatedCart && mutateCart) {
2824
+ mutateCart(updatedCart);
2825
+ }
2826
+ return updatedCart;
2827
+ },
2828
+ [cartContextData, updateCartDeliveryOptions2, mutateCart]
2829
+ );
2830
+ return useSWRMutation__default.default("update-cart-delivery-options", handler, options);
2831
+ };
2637
2832
  var usePlusMemberItemCustomAttributes = ({
2638
2833
  deliveryData
2639
2834
  }) => {
@@ -2653,48 +2848,18 @@ var usePlusMemberCheckoutCustomAttributes = ({
2653
2848
  deliveryData,
2654
2849
  product,
2655
2850
  variant,
2656
- customer,
2657
2851
  isShowShippingBenefits
2658
2852
  }) => {
2659
2853
  const { deliveryCustomData } = deliveryData || {};
2660
2854
  const { profile } = usePlusMemberContext();
2661
- const userType = react.useMemo(() => {
2662
- const customerInfo = customer;
2663
- if (!customerInfo) {
2664
- return "new_user_unlogin";
2665
- }
2666
- if (customer) {
2667
- const { orders = {} } = customer;
2668
- const edgesLength = orders?.edges?.length;
2669
- if (edgesLength === 1) {
2670
- return "old_user_orders_once";
2671
- } else if (edgesLength && edgesLength > 1) {
2672
- return "old_user_orders_twice";
2673
- }
2674
- }
2675
- return "new_user_login";
2676
- }, [customer]);
2677
2855
  return react.useMemo(() => {
2678
2856
  const checkoutCustomAttributes = [
2679
- {
2680
- key: "_token",
2681
- value: profile?.token || ""
2682
- },
2857
+ // _last_url: 付费会员结算完成之后 checkout 有一个继续购买的按钮, 用于跳转到继续购买的页面
2683
2858
  {
2684
2859
  key: "_last_url",
2685
2860
  value: typeof window !== "undefined" ? window.location.origin + window.location.pathname : ""
2686
- },
2687
- {
2688
- key: "_user_type",
2689
- value: userType
2690
2861
  }
2691
2862
  ];
2692
- if (profile) {
2693
- checkoutCustomAttributes.push({
2694
- key: "_login_user",
2695
- value: "1"
2696
- });
2697
- }
2698
2863
  if (deliveryCustomData) {
2699
2864
  checkoutCustomAttributes.push({
2700
2865
  key: "_checkout_delivery_custom",
@@ -2704,12 +2869,6 @@ var usePlusMemberCheckoutCustomAttributes = ({
2704
2869
  })
2705
2870
  });
2706
2871
  }
2707
- if (variant?.metafields?.presell) {
2708
- checkoutCustomAttributes.push({
2709
- key: "_presale",
2710
- value: "true"
2711
- });
2712
- }
2713
2872
  if (isShowShippingBenefits && !isShowShippingBenefits({ variant, product, setting: {} })) {
2714
2873
  checkoutCustomAttributes.push({
2715
2874
  key: "_hide_shipping",
@@ -2717,18 +2876,17 @@ var usePlusMemberCheckoutCustomAttributes = ({
2717
2876
  });
2718
2877
  }
2719
2878
  return checkoutCustomAttributes;
2720
- }, [deliveryCustomData, product, profile, userType, variant, isShowShippingBenefits]);
2879
+ }, [deliveryCustomData, product, profile, variant, isShowShippingBenefits]);
2721
2880
  };
2722
2881
  function useAutoRemovePlusMemberInCart({
2723
- metafields,
2724
- isMonthlyPlus,
2725
- isAnnualPlus
2882
+ cart,
2883
+ profile,
2884
+ memberSetting
2726
2885
  }) {
2727
- const { plus_monthly_product, plus_annual_product } = metafields || {};
2728
- const { cart } = useCartContext();
2886
+ const { plus_monthly_product, plus_annual_product } = memberSetting || {};
2729
2887
  const { trigger: removeCartLines2 } = useRemoveCartLines();
2730
2888
  react.useEffect(() => {
2731
- if (!cart) return;
2889
+ if (!cart || !plus_monthly_product || !plus_annual_product) return;
2732
2890
  const removePlusProduct = async (productType) => {
2733
2891
  if (!productType) return;
2734
2892
  const product = cart.lineItems?.find(
@@ -2740,33 +2898,25 @@ function useAutoRemovePlusMemberInCart({
2740
2898
  });
2741
2899
  }
2742
2900
  };
2743
- if (isMonthlyPlus) {
2901
+ if (profile?.isMonthlyPlus) {
2744
2902
  removePlusProduct(plus_monthly_product);
2745
2903
  }
2746
- if (isAnnualPlus) {
2904
+ if (profile?.isAnnualPlus) {
2747
2905
  removePlusProduct(plus_annual_product);
2748
2906
  }
2749
- }, [
2750
- cart,
2751
- plus_annual_product,
2752
- plus_monthly_product,
2753
- isAnnualPlus,
2754
- isMonthlyPlus,
2755
- removeCartLines2
2756
- ]);
2907
+ }, [cart, plus_annual_product, plus_monthly_product, profile, removeCartLines2]);
2757
2908
  }
2758
2909
  function useAddPlusMemberProductsToCart({
2759
2910
  cart,
2760
- memberSetting,
2761
- selectedPlusMemberMode,
2762
- selectedPlusMemberProduct
2911
+ profile
2763
2912
  }) {
2913
+ const { selectedPlusMemberMode, selectedPlusMemberProduct, plusMemberMetafields } = usePlusMemberContext();
2764
2914
  const { hasMonthlyPlus, hasAnnualPlus } = useHasPlusMemberInCart({
2765
- cart,
2766
- memberSetting
2915
+ memberSetting: plusMemberMetafields,
2916
+ cart
2767
2917
  });
2768
2918
  const plusMemberProduct = react.useMemo(() => {
2769
- if (selectedPlusMemberMode === "free" /* FREE */) {
2919
+ if (!selectedPlusMemberProduct || selectedPlusMemberMode === "free" /* FREE */) {
2770
2920
  return void 0;
2771
2921
  }
2772
2922
  if (selectedPlusMemberMode === "monthly" /* MONTHLY */ && hasMonthlyPlus) {
@@ -2775,7 +2925,10 @@ function useAddPlusMemberProductsToCart({
2775
2925
  if (selectedPlusMemberMode === "annual" /* ANNUAL */ && hasAnnualPlus) {
2776
2926
  return void 0;
2777
2927
  }
2778
- if (!selectedPlusMemberProduct) {
2928
+ if (profile?.isMonthlyPlus && selectedPlusMemberMode === "monthly" /* MONTHLY */) {
2929
+ return void 0;
2930
+ }
2931
+ if (profile?.isAnnualPlus && selectedPlusMemberMode === "annual" /* ANNUAL */) {
2779
2932
  return void 0;
2780
2933
  }
2781
2934
  return selectedPlusMemberProduct;
@@ -3094,8 +3247,13 @@ function CartProvider({
3094
3247
  const { attributes } = useCartAttributes({ profile, customer, cart, memberSetting });
3095
3248
  ahooks.useRequest(
3096
3249
  () => {
3097
- const newAttributes = [...attributes, ...customAttributes];
3098
- const needUpdate = cart && !checkAttributesUpdateNeeded(
3250
+ const newAttributes = [...attributes];
3251
+ customAttributes.forEach((item) => {
3252
+ if (item.value && !newAttributes.some((attr) => attr.key === item.key)) {
3253
+ newAttributes.push(item);
3254
+ }
3255
+ });
3256
+ const needUpdate = cart && checkAttributesUpdateNeeded(
3099
3257
  cart.customAttributes,
3100
3258
  newAttributes,
3101
3259
  customAttributesNeedDelete
@@ -3199,8 +3357,14 @@ function CartProvider({
3199
3357
  );
3200
3358
  return result;
3201
3359
  }, [cart?.lineItems, scriptAutoFreeGift, functionAutoFreeGift]);
3360
+ const totalQuantity = react.useMemo(() => {
3361
+ const cartLinesCount = cart?.lineItems.reduce((acc, item) => acc + item.quantity, 0) || 0;
3362
+ const giftLinesCount = giftNeedAddToCartLines?.reduce((acc, item) => acc + (item.quantity || 1), 0) || 0;
3363
+ return cartLinesCount + giftLinesCount;
3364
+ }, [cart?.lineItems, giftNeedAddToCartLines]);
3202
3365
  const value = react.useMemo(
3203
3366
  () => ({
3367
+ totalQuantity,
3204
3368
  cart,
3205
3369
  isCartLoading,
3206
3370
  triggerFetch: fetchCart,
@@ -3228,6 +3392,7 @@ function CartProvider({
3228
3392
  }),
3229
3393
  [
3230
3394
  cart,
3395
+ totalQuantity,
3231
3396
  isCartLoading,
3232
3397
  fetchCart,
3233
3398
  mutateCart,
@@ -3260,30 +3425,6 @@ function useCartContext() {
3260
3425
  return context;
3261
3426
  }
3262
3427
 
3263
- Object.defineProperty(exports, "ShopifyConfig", {
3264
- enumerable: true,
3265
- get: function () { return shopifySdk.ShopifyConfig; }
3266
- });
3267
- Object.defineProperty(exports, "clearLocalStorage", {
3268
- enumerable: true,
3269
- get: function () { return shopifySdk.clearLocalStorage; }
3270
- });
3271
- Object.defineProperty(exports, "createShopifyClient", {
3272
- enumerable: true,
3273
- get: function () { return shopifySdk.createShopifyClient; }
3274
- });
3275
- Object.defineProperty(exports, "getLocalStorage", {
3276
- enumerable: true,
3277
- get: function () { return shopifySdk.getLocalStorage; }
3278
- });
3279
- Object.defineProperty(exports, "removeLocalStorage", {
3280
- enumerable: true,
3281
- get: function () { return shopifySdk.removeLocalStorage; }
3282
- });
3283
- Object.defineProperty(exports, "setLocalStorage", {
3284
- enumerable: true,
3285
- get: function () { return shopifySdk.setLocalStorage; }
3286
- });
3287
3428
  exports.BuyRuleType = BuyRuleType;
3288
3429
  exports.CODE_AMOUNT_KEY = CODE_AMOUNT_KEY;
3289
3430
  exports.CUSTOMER_ATTRIBUTE_KEY = CUSTOMER_ATTRIBUTE_KEY;
@@ -3305,10 +3446,8 @@ exports.ShippingMethodMode = ShippingMethodMode;
3305
3446
  exports.ShopifyContext = ShopifyContext;
3306
3447
  exports.ShopifyProvider = ShopifyProvider;
3307
3448
  exports.SpendMoneyType = SpendMoneyType;
3308
- exports.atobID = atobID;
3309
3449
  exports.browserCartCookieAdapter = browserCartCookieAdapter;
3310
3450
  exports.browserCookieAdapter = browserCookieAdapter;
3311
- exports.btoaID = btoaID;
3312
3451
  exports.checkAttributesUpdateNeeded = checkAttributesUpdateNeeded;
3313
3452
  exports.clearGeoLocationCache = clearGeoLocationCache;
3314
3453
  exports.createMockCartFromLines = createMockCartFromLines;
@@ -3379,8 +3518,15 @@ exports.useSite = useSite;
3379
3518
  exports.useUpdateCartAttributes = useUpdateCartAttributes;
3380
3519
  exports.useUpdateCartLines = useUpdateCartLines;
3381
3520
  exports.useUpdateLineCodeAmountAttributes = useUpdateLineCodeAmountAttributes;
3521
+ exports.useUpdatePlusMemberDeliveryOptions = useUpdatePlusMemberDeliveryOptions;
3382
3522
  exports.useUpdateVariantQuery = useUpdateVariantQuery;
3383
3523
  exports.useVariant = useVariant;
3384
3524
  exports.useVariantMedia = useVariantMedia;
3525
+ Object.keys(shopifySdk).forEach(function (k) {
3526
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
3527
+ enumerable: true,
3528
+ get: function () { return shopifySdk[k]; }
3529
+ });
3530
+ });
3385
3531
  //# sourceMappingURL=index.js.map
3386
3532
  //# sourceMappingURL=index.js.map