@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.
@@ -1,8 +1,9 @@
1
1
  import { createContext, useMemo, useContext, useState, useCallback, useEffect, useRef } from 'react';
2
- import { createShopifyClient, getCart, updateCartAttributes, updateCartLines, getProductsByHandles } from '@anker-in/shopify-sdk';
2
+ import { createShopifyClient, getCart, updateCartAttributes, updateCartLines, getProductsByHandles, getLocalStorage } from '@anker-in/shopify-sdk';
3
3
  import Cookies5 from 'js-cookie';
4
4
  import { jsx } from 'react/jsx-runtime';
5
5
  import Decimal2 from 'decimal.js';
6
+ import { btoaID, atobID } from '@anker-in/shopify-core';
6
7
  import useSWR from 'swr';
7
8
  import useSWRMutation8 from 'swr/mutation';
8
9
  import { useRequest } from 'ahooks';
@@ -101,9 +102,10 @@ function normalizeAddToCartLines(lines) {
101
102
  const variant = line.variant;
102
103
  const product = variant.product;
103
104
  const quantity = line.quantity || 1;
104
- const price = variant.finalPrice?.amount ? Number(variant.finalPrice.amount) : variant.compareAtPrice?.amount ? Number(variant.compareAtPrice.amount) : variant.price?.amount ? Number(variant.price.amount) : 0;
105
- const subtotalAmount = price * quantity;
106
- const totalAmount = subtotalAmount;
105
+ const originalPrice = variant.price?.amount ? Number(variant.price.amount) : 0;
106
+ const finalPrice = variant.finalPrice?.amount ? Number(variant.finalPrice.amount) : originalPrice;
107
+ const subtotalAmount = originalPrice * quantity;
108
+ const totalAmount = finalPrice * quantity;
107
109
  return {
108
110
  id: `temp-line-${index}-${variant.id}`,
109
111
  // Temporary ID for pre-cart lines
@@ -117,7 +119,7 @@ function normalizeAddToCartLines(lines) {
117
119
  customAttributes: line.attributes || [],
118
120
  variant: {
119
121
  id: variant.id,
120
- price,
122
+ price: finalPrice,
121
123
  listPrice: variant.compareAtPrice?.amount ? Number(variant.compareAtPrice.amount) : 0,
122
124
  sku: variant.sku || "",
123
125
  name: variant.title || "",
@@ -148,15 +150,16 @@ function createMockCartFromLines(lines, existingCart) {
148
150
  const normalizedLines = normalizeAddToCartLines(lines);
149
151
  const subtotalPrice = normalizedLines.reduce((sum, line) => sum + line.subtotalAmount, 0);
150
152
  const totalPrice = normalizedLines.reduce((sum, line) => sum + line.totalAmount, 0);
153
+ const currency = lines[0]?.variant?.price?.currencyCode;
151
154
  return {
152
155
  id: existingCart?.id || "temp-cart-id",
153
156
  customerId: existingCart?.customerId,
154
157
  email: existingCart?.email,
155
158
  createdAt: existingCart?.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
156
- currency: existingCart?.currency || { code: "USD" },
159
+ currency: existingCart?.currency || { code: currency },
157
160
  taxesIncluded: existingCart?.taxesIncluded,
158
161
  lineItems: normalizedLines,
159
- totallineItemsDiscount: 0,
162
+ totalLineItemsDiscount: 0,
160
163
  orderDiscounts: 0,
161
164
  lineItemsSubtotalPrice: subtotalPrice,
162
165
  subtotalPrice,
@@ -187,16 +190,6 @@ var getQuery = () => {
187
190
  }
188
191
  return theRequest;
189
192
  };
190
- function atobID(id) {
191
- if (id && typeof id === "string" && id.includes("/")) {
192
- return id.split("/").pop()?.split("?")?.shift();
193
- } else {
194
- return id;
195
- }
196
- }
197
- function btoaID(id, type = "ProductVariant") {
198
- return `gid://shopify/${type}/${id}`;
199
- }
200
193
  var getMatchedMainProductSubTotal = (cartData, variant_list, main_product) => {
201
194
  const isAllStoreVariant = main_product?.all_store_variant ?? false;
202
195
  const matchedList = cartData?.lineItems?.filter((line) => {
@@ -403,6 +396,7 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
403
396
  const effectiveCart = useMemo(() => {
404
397
  return cart;
405
398
  }, [lines, cart]);
399
+ console.log("effectiveCart useCalcAutoFreeGift", effectiveCart);
406
400
  const { activeCampaign, subtotal } = useMemo(() => {
407
401
  for (const campaign of autoFreeGiftConfig) {
408
402
  const { rule_conditions = [], rule_result } = campaign;
@@ -418,6 +412,7 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
418
412
  all_store_variant: spend_get_reward.main_product?.all_store_variant || false
419
413
  }
420
414
  );
415
+ console.log("matchedSubtotal useCalcAutoFreeGift", matchedSubtotal);
421
416
  if (matchedSubtotal > 0) {
422
417
  return { activeCampaign: campaign, subtotal: matchedSubtotal };
423
418
  }
@@ -430,11 +425,20 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
430
425
  return { qualifyingGift: null, nextTierGoal: null };
431
426
  }
432
427
  const giftTiers = activeCampaign.rule_result.spend_get_reward.gift_product;
433
- const qualifyingTier = [...giftTiers].reverse().find((tier) => subtotal >= Number(tier.spend_sum_money));
434
- const nextGoal = giftTiers.find((tier) => subtotal < Number(tier.spend_sum_money));
428
+ const currentCurrency = effectiveCart?.currency?.code || "";
429
+ console.log("currentCurrency useCalcAutoFreeGift", effectiveCart, currentCurrency);
430
+ const getThresholdAmount = (tier) => {
431
+ if (tier.spend_sum_money_multi_markets?.[currentCurrency]?.value) {
432
+ return Number(tier.spend_sum_money_multi_markets[currentCurrency].value);
433
+ }
434
+ return Number(tier.spend_sum_money || 0);
435
+ };
436
+ const qualifyingTier = [...giftTiers].sort((a, b) => getThresholdAmount(b) - getThresholdAmount(a)).find((tier) => subtotal >= getThresholdAmount(tier));
437
+ const nextGoal = giftTiers.find((tier) => subtotal < getThresholdAmount(tier));
435
438
  if (!qualifyingTier) {
436
439
  return { qualifyingGift: null, nextTierGoal: nextGoal || null };
437
440
  }
441
+ const actualThreshold = getThresholdAmount(qualifyingTier);
438
442
  const formattedGift = {
439
443
  tier: qualifyingTier,
440
444
  itemsToAdd: qualifyingTier.reward_list?.map((reward) => {
@@ -453,7 +457,10 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
453
457
  value: JSON.stringify({
454
458
  is_gift: true,
455
459
  rule_id: activeCampaign.rule_id,
456
- spend_sum_money: qualifyingTier.spend_sum_money
460
+ spend_sum_money: actualThreshold,
461
+ // 使用实际的门槛金额(多币种支持)
462
+ currency_code: currentCurrency
463
+ // 记录当前币种
457
464
  })
458
465
  }
459
466
  ]
@@ -461,7 +468,7 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
461
468
  }).filter((item) => item !== null)
462
469
  };
463
470
  return { qualifyingGift: formattedGift, nextTierGoal: nextGoal || null };
464
- }, [activeCampaign, subtotal]);
471
+ }, [activeCampaign, subtotal, effectiveCart]);
465
472
  const giftHandles = useMemo(() => {
466
473
  const giftVariant = autoFreeGiftConfig.map(
467
474
  (item) => item.rule_result?.spend_get_reward?.gift_product?.map(
@@ -477,18 +484,24 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
477
484
  }
478
485
  return true;
479
486
  }, [giftHandles]);
480
- const { data: giftProductsResult } = useSWR(shouldFetch ? giftHandles : null, async () => {
481
- const res = await getProductsByHandles(client, {
482
- handles: giftHandles,
483
- locale
484
- });
485
- const result = Array.isArray(res) ? res : [];
486
- giftProductsCache.current = {
487
- data: result,
488
- giftHandles: [...giftHandles]
489
- };
490
- return result;
491
- });
487
+ const { data: giftProductsResult } = useSWR(
488
+ shouldFetch ? giftHandles : null,
489
+ async () => {
490
+ const res = await getProductsByHandles(client, {
491
+ handles: giftHandles,
492
+ locale
493
+ });
494
+ const result = Array.isArray(res) ? res : [];
495
+ giftProductsCache.current = {
496
+ data: result,
497
+ giftHandles: [...giftHandles]
498
+ };
499
+ return result;
500
+ },
501
+ {
502
+ revalidateOnFocus: false
503
+ }
504
+ );
492
505
  const finalGiftProductsResult = useMemo(() => {
493
506
  if (giftProductsCache.current && !shouldFetch) {
494
507
  return giftProductsCache.current.data || void 0;
@@ -541,12 +554,14 @@ var useScriptAutoFreeGift = ({
541
554
  upgrade_multiple2 = 1.2;
542
555
  upgrade_value2 = 40;
543
556
  }
544
- effectiveCart?.lineItems?.forEach(({ customAttributes }) => {
545
- customAttributes?.forEach(({ key, value }) => {
546
- if (key === "_amount_upgrade_multiple") upgrade_multiple2 = Number(value) || 1;
547
- if (key === "_amount_upgrade_value") upgrade_value2 = Number(value) || 0;
548
- });
549
- });
557
+ effectiveCart?.lineItems?.forEach(
558
+ ({ customAttributes }) => {
559
+ customAttributes?.forEach(({ key, value }) => {
560
+ if (key === "_amount_upgrade_multiple") upgrade_multiple2 = Number(value) || 1;
561
+ if (key === "_amount_upgrade_value") upgrade_value2 = Number(value) || 0;
562
+ });
563
+ }
564
+ );
550
565
  return [upgrade_multiple2, upgrade_value2];
551
566
  }, [effectiveCart?.lineItems, points_subscribe]);
552
567
  const breakpoints = useMemo(() => {
@@ -611,18 +626,24 @@ var useScriptAutoFreeGift = ({
611
626
  const nextLevel = levelIndex > 0 ? sortedLevels[levelIndex - 1] ?? null : null;
612
627
  return [currentLevel, nextLevel];
613
628
  }, [breakpoints, involvedSubTotal, involvedLines.length]);
614
- const { data: giftProductsResult } = useSWR(shouldFetch ? giftHandles : null, async () => {
615
- const res = await getProductsByHandles(client, {
616
- handles: giftHandles,
617
- locale
618
- });
619
- const result = Array.isArray(res) ? res : [];
620
- giftProductsCache.current = {
621
- data: result,
622
- giftHandles: [...giftHandles]
623
- };
624
- return result;
625
- });
629
+ const { data: giftProductsResult } = useSWR(
630
+ shouldFetch ? giftHandles : null,
631
+ async () => {
632
+ const res = await getProductsByHandles(client, {
633
+ handles: giftHandles,
634
+ locale
635
+ });
636
+ const result = Array.isArray(res) ? res : [];
637
+ giftProductsCache.current = {
638
+ data: result,
639
+ giftHandles: [...giftHandles]
640
+ };
641
+ return result;
642
+ },
643
+ {
644
+ revalidateOnFocus: false
645
+ }
646
+ );
626
647
  const finalGiftProductsResult = useMemo(() => {
627
648
  if (giftProductsCache.current && !shouldFetch) {
628
649
  return giftProductsCache.current.data || void 0;
@@ -704,12 +725,10 @@ function useHasPlusMemberInCart({
704
725
  };
705
726
  }, [cart?.lineItems, plus_monthly_product, plus_annual_product]);
706
727
  }
707
-
708
- // src/hooks/cart/feature/use-cart-attributes.ts
709
728
  var getReferralAttributes = () => {
710
- const inviteCode = Cookies5.get("invite_code");
711
- const playModeId = Cookies5.get("playModeId");
712
- const popup = Cookies5.get("_popup");
729
+ const inviteCode = getLocalStorage("invite_code") || Cookies5.get("invite_code");
730
+ const playModeId = getLocalStorage("playModeId") || Cookies5.get("playModeId");
731
+ const popup = getLocalStorage("_popup") || Cookies5.get("_popup");
713
732
  if (inviteCode && playModeId) {
714
733
  return popup ? [
715
734
  { key: "_invite_code", value: inviteCode ? inviteCode : "" },
@@ -733,8 +752,6 @@ var useCartAttributes = ({
733
752
  memberSetting,
734
753
  cart
735
754
  });
736
- console.log("memberSetting", memberSetting);
737
- console.log("hasPlusMember", hasPlusMember);
738
755
  useEffect(() => {
739
756
  setCurrentUrl(window.location.href);
740
757
  }, []);
@@ -760,7 +777,7 @@ var useCartAttributes = ({
760
777
  return "new_user_login";
761
778
  }, [customer]);
762
779
  const memberAttributes = useMemo(() => {
763
- return [
780
+ const attributes = [
764
781
  {
765
782
  key: "_token",
766
783
  value: profile?.token
@@ -781,17 +798,28 @@ var useCartAttributes = ({
781
798
  value: profile?.token ? "true" : "false"
782
799
  }
783
800
  ];
801
+ if (profile?.token) {
802
+ attributes.push({
803
+ key: "_login_user",
804
+ value: "1"
805
+ });
806
+ }
807
+ return attributes;
784
808
  }, [profile?.memberType, profile?.token, userType, hasPlusMember]);
785
809
  const functionAttributes = useMemo(() => {
786
- return [
787
- cart?.discountCodes && {
810
+ const hasFunctionEnvAttribute = cart?.lineItems.some(
811
+ (item) => item.customAttributes?.some((attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY)
812
+ );
813
+ const discountCodes = cart?.discountCodes.map((item) => item.code).filter((code) => code) || [];
814
+ return hasFunctionEnvAttribute ? [
815
+ {
788
816
  key: "_discounts_function_env",
789
817
  value: JSON.stringify({
790
- discount_code: cart?.discountCodes.map((item) => item.code),
818
+ discount_code: discountCodes,
791
819
  user_tags: customer?.tags || []
792
820
  })
793
821
  }
794
- ];
822
+ ] : [];
795
823
  }, [cart]);
796
824
  const presellAttributes = useMemo(() => {
797
825
  return [
@@ -823,18 +851,50 @@ var useCartAttributes = ({
823
851
  }
824
852
  ];
825
853
  }, [currentUrl]);
854
+ const commonAttributes = useMemo(
855
+ () => [
856
+ ...memberAttributes,
857
+ ...functionAttributes,
858
+ ...presellAttributes,
859
+ ...weightAttributes,
860
+ ...trackingAttributes,
861
+ ...getReferralAttributes()
862
+ ].filter((item) => item?.value),
863
+ [memberAttributes, functionAttributes, presellAttributes, weightAttributes, trackingAttributes]
864
+ );
865
+ const extraAttributesInCart = useMemo(() => {
866
+ const commonAttributeKeys = [
867
+ // member attributes
868
+ "_token",
869
+ "_member_type",
870
+ "_user_type",
871
+ "_is_login",
872
+ "_login_user",
873
+ // function attributes
874
+ "_discounts_function_env",
875
+ // presell attributes
876
+ "_presale",
877
+ // weight attributes
878
+ "_weight",
879
+ "_app_source_name",
880
+ // tracking attributes
881
+ "utm_params",
882
+ // referral attributes
883
+ "_invite_code",
884
+ "_play_mode_id",
885
+ "_popup"
886
+ ];
887
+ return cart?.customAttributes?.filter(
888
+ (item) => !commonAttributeKeys.includes(item.key)
889
+ ) || [];
890
+ }, [cart]);
826
891
  return useMemo(
827
892
  () => ({
828
- attributes: [
829
- ...memberAttributes,
830
- ...functionAttributes,
831
- ...presellAttributes,
832
- ...weightAttributes,
833
- ...trackingAttributes,
834
- ...getReferralAttributes()
835
- ].filter((item) => item?.value)
893
+ attributes: [...commonAttributes, ...extraAttributesInCart].filter(
894
+ (item) => item?.value
895
+ )
836
896
  }),
837
- [memberAttributes, functionAttributes, presellAttributes, weightAttributes, trackingAttributes]
897
+ [commonAttributes, extraAttributesInCart]
838
898
  );
839
899
  };
840
900
  var useUpdateLineCodeAmountAttributes = ({
@@ -863,7 +923,7 @@ var useUpdateLineCodeAmountAttributes = ({
863
923
  );
864
924
  const functionEnvValue = getDiscountEnvAttributeValue(line.customAttributes);
865
925
  const hasSameFunctionEnvAttribute = Number(functionEnvValue.discounted_amount) === Number(line.totalAmount);
866
- if (!hasSameFunctionEnvAttribute && hasFunctionEnvAttribute) {
926
+ if (!hasSameFunctionEnvAttribute && hasFunctionEnvAttribute && !functionEnvValue.is_gift) {
867
927
  attrNeedUpdate.push({
868
928
  key: CUSTOMER_ATTRIBUTE_KEY,
869
929
  value: JSON.stringify({
@@ -902,29 +962,22 @@ var useUpdateLineCodeAmountAttributes = ({
902
962
  }).filter(
903
963
  ({ attrNeedUpdate, attrNeedDelete }) => attrNeedUpdate.length || attrNeedDelete.length
904
964
  ).map(({ line, attrNeedUpdate, attrNeedDelete }) => {
965
+ let lineId = line.id;
966
+ let attributes = line.customAttributes || [];
967
+ if (attrNeedDelete.length) {
968
+ attributes = attributes.filter(
969
+ (attr) => !attrNeedDelete.includes(attr.key)
970
+ );
971
+ }
905
972
  if (attrNeedUpdate.length) {
906
- return {
907
- id: line.id,
908
- attributes: [
909
- ...line.customAttributes?.filter(
910
- (attr) => !attrNeedUpdate.some((updateAttr) => updateAttr.key === attr.key)
911
- ) || [],
912
- ...attrNeedUpdate
913
- ]
914
- };
915
- } else if (attrNeedDelete.length) {
916
- return {
917
- id: line.id,
918
- attributes: line.customAttributes?.filter(
919
- (attr) => !attrNeedDelete.includes(attr.key)
920
- ) || []
921
- };
922
- } else {
923
- return {
924
- id: line.id,
925
- attributes: line.customAttributes || []
926
- };
973
+ attributes = attributes.filter(
974
+ (attr) => !attrNeedUpdate.some((updateAttr) => updateAttr.key === attr.key)
975
+ ).concat(attrNeedUpdate);
927
976
  }
977
+ return {
978
+ id: lineId,
979
+ attributes
980
+ };
928
981
  }),
929
982
  [cart?.lineItems, mainProductDiscountCodes]
930
983
  );
@@ -1050,8 +1103,13 @@ function CartProvider({
1050
1103
  const { attributes } = useCartAttributes({ profile, customer, cart, memberSetting });
1051
1104
  useRequest(
1052
1105
  () => {
1053
- const newAttributes = [...attributes, ...customAttributes];
1054
- const needUpdate = cart && !checkAttributesUpdateNeeded(
1106
+ const newAttributes = [...attributes];
1107
+ customAttributes.forEach((item) => {
1108
+ if (item.value && !newAttributes.some((attr) => attr.key === item.key)) {
1109
+ newAttributes.push(item);
1110
+ }
1111
+ });
1112
+ const needUpdate = cart && checkAttributesUpdateNeeded(
1055
1113
  cart.customAttributes,
1056
1114
  newAttributes,
1057
1115
  customAttributesNeedDelete
@@ -1155,8 +1213,14 @@ function CartProvider({
1155
1213
  );
1156
1214
  return result;
1157
1215
  }, [cart?.lineItems, scriptAutoFreeGift, functionAutoFreeGift]);
1216
+ const totalQuantity = useMemo(() => {
1217
+ const cartLinesCount = cart?.lineItems.reduce((acc, item) => acc + item.quantity, 0) || 0;
1218
+ const giftLinesCount = giftNeedAddToCartLines?.reduce((acc, item) => acc + (item.quantity || 1), 0) || 0;
1219
+ return cartLinesCount + giftLinesCount;
1220
+ }, [cart?.lineItems, giftNeedAddToCartLines]);
1158
1221
  const value = useMemo(
1159
1222
  () => ({
1223
+ totalQuantity,
1160
1224
  cart,
1161
1225
  isCartLoading,
1162
1226
  triggerFetch: fetchCart,
@@ -1184,6 +1248,7 @@ function CartProvider({
1184
1248
  }),
1185
1249
  [
1186
1250
  cart,
1251
+ totalQuantity,
1187
1252
  isCartLoading,
1188
1253
  fetchCart,
1189
1254
  mutateCart,