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

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.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createContext, useMemo, useContext, useRef, useState, useEffect, useCallback } from 'react';
2
- import { createShopifyClient, getProductsByHandles, createCart, updateCartCodes, addCartLines, updateCartLines, removeCartLines, updateCartAttributes, getProduct, getAllProducts, getCollection, getAllCollections, getCollections, getBlog, getAllBlogs, getArticle, getArticles, getArticlesInBlog, getLocalStorage, getCart, setLocalStorage } from '@anker-in/shopify-sdk';
3
- export { ShopifyConfig, clearLocalStorage, createShopifyClient, getLocalStorage, removeLocalStorage, setLocalStorage } from '@anker-in/shopify-sdk';
2
+ import { createShopifyClient, atobID, btoaID, getProductsByHandles, createCart, updateCartCodes, addCartLines, updateCartLines, removeCartLines, updateCartAttributes, getLocalStorage, getProduct, getAllProducts, getCollection, getAllCollections, getCollections, getBlog, getAllBlogs, getArticle, getArticles, getArticlesInBlog, getCart, setLocalStorage, updateCartDeliveryOptions } from '@anker-in/shopify-sdk';
3
+ export * from '@anker-in/shopify-sdk';
4
4
  import Cookies5 from 'js-cookie';
5
5
  import { jsx } from 'react/jsx-runtime';
6
6
  import Decimal2 from 'decimal.js';
@@ -134,6 +134,83 @@ var CODE_AMOUNT_KEY = "_sku_code_money";
134
134
  var SCRIPT_CODE_AMOUNT_KEY = "_code_money";
135
135
  var MAIN_PRODUCT_CODE = ["WS24", "WSTD", "WS7D", "WSCP", "WSPE", "WSPD"];
136
136
 
137
+ // src/hooks/cart/utils/normalize-add-to-cart-lines.ts
138
+ function normalizeAddToCartLines(lines) {
139
+ return lines.filter((line) => line.variant?.id).map((line, index) => {
140
+ const variant = line.variant;
141
+ const product = variant.product;
142
+ const quantity = line.quantity || 1;
143
+ const price = variant.finalPrice?.amount ? Number(variant.finalPrice.amount) : variant.compareAtPrice?.amount ? Number(variant.compareAtPrice.amount) : variant.price?.amount ? Number(variant.price.amount) : 0;
144
+ const subtotalAmount = price * quantity;
145
+ const totalAmount = subtotalAmount;
146
+ return {
147
+ id: `temp-line-${index}-${variant.id}`,
148
+ // Temporary ID for pre-cart lines
149
+ name: product?.title || variant.title || "",
150
+ quantity,
151
+ variantId: variant.id,
152
+ productId: product?.id || variant.id.split("/").slice(0, -2).join("/"),
153
+ totalAmount,
154
+ subtotalAmount,
155
+ discountAllocations: [],
156
+ customAttributes: line.attributes || [],
157
+ variant: {
158
+ id: variant.id,
159
+ price,
160
+ listPrice: variant.compareAtPrice?.amount ? Number(variant.compareAtPrice.amount) : 0,
161
+ sku: variant.sku || "",
162
+ name: variant.title || "",
163
+ image: variant.image ? {
164
+ url: variant.image.url,
165
+ altText: variant.image.altText || void 0
166
+ } : void 0,
167
+ requiresShipping: false,
168
+ // Default value, not available in NormalizedProductVariant
169
+ availableForSale: variant.availableForSale ?? true,
170
+ quantityAvailable: variant.quantityAvailable ?? 0,
171
+ currentlyNotInStock: false,
172
+ // Default value, will be updated when added to cart
173
+ weight: variant.weight,
174
+ metafields: variant.metafields
175
+ },
176
+ product,
177
+ path: product?.handle ? `/products/${product.handle}` : "",
178
+ discounts: [],
179
+ options: variant.selectedOptions?.map((opt) => ({
180
+ name: opt.name,
181
+ value: opt.value
182
+ }))
183
+ };
184
+ });
185
+ }
186
+ function createMockCartFromLines(lines, existingCart) {
187
+ const normalizedLines = normalizeAddToCartLines(lines);
188
+ const subtotalPrice = normalizedLines.reduce((sum, line) => sum + line.subtotalAmount, 0);
189
+ const totalPrice = normalizedLines.reduce((sum, line) => sum + line.totalAmount, 0);
190
+ console.log("lines createMockCartFromLines", lines);
191
+ const currency = lines[0]?.variant?.price?.currencyCode;
192
+ return {
193
+ id: existingCart?.id || "temp-cart-id",
194
+ customerId: existingCart?.customerId,
195
+ email: existingCart?.email,
196
+ createdAt: existingCart?.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
197
+ currency: existingCart?.currency?.code || { code: currency },
198
+ taxesIncluded: existingCart?.taxesIncluded,
199
+ lineItems: normalizedLines,
200
+ totalLineItemsDiscount: 0,
201
+ orderDiscounts: 0,
202
+ lineItemsSubtotalPrice: subtotalPrice,
203
+ subtotalPrice,
204
+ totalPrice,
205
+ totalTaxAmount: 0,
206
+ discountCodes: existingCart?.discountCodes || [],
207
+ discountAllocations: [],
208
+ url: existingCart?.url || "",
209
+ ready: true,
210
+ customAttributes: existingCart?.customAttributes
211
+ };
212
+ }
213
+
137
214
  // src/hooks/cart/utils/index.ts
138
215
  var getQuery = () => {
139
216
  const url = typeof window !== "undefined" ? window.location.search : "";
@@ -151,16 +228,6 @@ var getQuery = () => {
151
228
  }
152
229
  return theRequest;
153
230
  };
154
- function atobID(id) {
155
- if (id && typeof id === "string" && id.includes("/")) {
156
- return id.split("/").pop()?.split("?")?.shift();
157
- } else {
158
- return id;
159
- }
160
- }
161
- function btoaID(id, type = "ProductVariant") {
162
- return `gid://shopify/${type}/${id}`;
163
- }
164
231
  var getMatchedMainProductSubTotal = (cartData, variant_list, main_product) => {
165
232
  const isAllStoreVariant = main_product?.all_store_variant ?? false;
166
233
  const matchedList = cartData?.lineItems?.filter((line) => {
@@ -358,12 +425,18 @@ var formatFunctionAutoFreeGift = ({
358
425
  };
359
426
  return result;
360
427
  };
361
- var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
428
+ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
362
429
  const tags = useMemo(() => customer?.tags || [], [customer?.tags]);
363
430
  const isCustomerLoading = useMemo(() => !customer ? true : false, [customer]);
364
431
  const dealsType = "";
365
432
  const { client, locale } = useShopify();
366
433
  const giftProductsCache = useRef(null);
434
+ const effectiveCart = useMemo(() => {
435
+ if (lines && lines.length > 0) {
436
+ return createMockCartFromLines(lines, cart);
437
+ }
438
+ return cart;
439
+ }, [lines, cart]);
367
440
  const { activeCampaign, subtotal } = useMemo(() => {
368
441
  for (const campaign of autoFreeGiftConfig) {
369
442
  const { rule_conditions = [], rule_result } = campaign;
@@ -371,7 +444,7 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
371
444
  const isPreCheckPassed = preCheck(rule_conditions, tags, []);
372
445
  if (isPreCheckPassed && spend_get_reward) {
373
446
  const matchedSubtotal = getMatchedMainProductSubTotal(
374
- cart,
447
+ effectiveCart,
375
448
  spend_get_reward.main_product?.variant_list?.map((v) => v.variant_id) || [],
376
449
  {
377
450
  spend_money_type: spend_get_reward.main_product?.spend_money_type || 1,
@@ -385,17 +458,26 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
385
458
  }
386
459
  }
387
460
  return { activeCampaign: null, subtotal: 0 };
388
- }, [autoFreeGiftConfig, cart, tags, dealsType]);
461
+ }, [autoFreeGiftConfig, effectiveCart, tags, dealsType]);
389
462
  const { qualifyingGift, nextTierGoal } = useMemo(() => {
390
463
  if (!activeCampaign || !activeCampaign.rule_result?.spend_get_reward?.gift_product) {
391
464
  return { qualifyingGift: null, nextTierGoal: null };
392
465
  }
393
466
  const giftTiers = activeCampaign.rule_result.spend_get_reward.gift_product;
394
- const qualifyingTier = [...giftTiers].reverse().find((tier) => subtotal >= Number(tier.spend_sum_money));
395
- const nextGoal = giftTiers.find((tier) => subtotal < Number(tier.spend_sum_money));
467
+ const currentCurrency = effectiveCart?.currency?.code || "";
468
+ console.log("currentCurrency useCalcAutoFreeGift", effectiveCart, currentCurrency);
469
+ const getThresholdAmount = (tier) => {
470
+ if (tier.spend_sum_money_multi_markets?.[currentCurrency]?.value) {
471
+ return Number(tier.spend_sum_money_multi_markets[currentCurrency].value);
472
+ }
473
+ return Number(tier.spend_sum_money || 0);
474
+ };
475
+ const qualifyingTier = [...giftTiers].sort((a, b) => getThresholdAmount(b) - getThresholdAmount(a)).find((tier) => subtotal >= getThresholdAmount(tier));
476
+ const nextGoal = giftTiers.find((tier) => subtotal < getThresholdAmount(tier));
396
477
  if (!qualifyingTier) {
397
478
  return { qualifyingGift: null, nextTierGoal: nextGoal || null };
398
479
  }
480
+ const actualThreshold = getThresholdAmount(qualifyingTier);
399
481
  const formattedGift = {
400
482
  tier: qualifyingTier,
401
483
  itemsToAdd: qualifyingTier.reward_list?.map((reward) => {
@@ -414,7 +496,10 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
414
496
  value: JSON.stringify({
415
497
  is_gift: true,
416
498
  rule_id: activeCampaign.rule_id,
417
- spend_sum_money: qualifyingTier.spend_sum_money
499
+ spend_sum_money: actualThreshold,
500
+ // 使用实际的门槛金额(多币种支持)
501
+ currency_code: currentCurrency
502
+ // 记录当前币种
418
503
  })
419
504
  }
420
505
  ]
@@ -422,7 +507,7 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
422
507
  }).filter((item) => item !== null)
423
508
  };
424
509
  return { qualifyingGift: formattedGift, nextTierGoal: nextGoal || null };
425
- }, [activeCampaign, subtotal]);
510
+ }, [activeCampaign, subtotal, effectiveCart]);
426
511
  const giftHandles = useMemo(() => {
427
512
  const giftVariant = autoFreeGiftConfig.map(
428
513
  (item) => item.rule_result?.spend_get_reward?.gift_product?.map(
@@ -438,18 +523,24 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
438
523
  }
439
524
  return true;
440
525
  }, [giftHandles]);
441
- const { data: giftProductsResult } = useSWR(shouldFetch ? giftHandles : null, async () => {
442
- const res = await getProductsByHandles(client, {
443
- handles: giftHandles,
444
- locale
445
- });
446
- const result = Array.isArray(res) ? res : [];
447
- giftProductsCache.current = {
448
- data: result,
449
- giftHandles: [...giftHandles]
450
- };
451
- return result;
452
- });
526
+ const { data: giftProductsResult } = useSWR(
527
+ shouldFetch ? giftHandles : null,
528
+ async () => {
529
+ const res = await getProductsByHandles(client, {
530
+ handles: giftHandles,
531
+ locale
532
+ });
533
+ const result = Array.isArray(res) ? res : [];
534
+ giftProductsCache.current = {
535
+ data: result,
536
+ giftHandles: [...giftHandles]
537
+ };
538
+ return result;
539
+ },
540
+ {
541
+ revalidateOnFocus: false
542
+ }
543
+ );
453
544
  const finalGiftProductsResult = useMemo(() => {
454
545
  if (giftProductsCache.current && !shouldFetch) {
455
546
  return giftProductsCache.current.data || void 0;
@@ -468,12 +559,19 @@ var useScriptAutoFreeGift = ({
468
559
  campaign,
469
560
  _giveaway,
470
561
  cart,
471
- locale: providedLocale
562
+ locale: providedLocale,
563
+ lines
472
564
  }) => {
473
565
  const { client, locale: contextLocale } = useShopify();
474
566
  const locale = providedLocale || contextLocale;
475
567
  const [points_subscribe, set_points_subscribe] = useState(false);
476
568
  const giftProductsCache = useRef(null);
569
+ const effectiveCart = useMemo(() => {
570
+ if (lines && lines.length > 0) {
571
+ return createMockCartFromLines(lines, cart);
572
+ }
573
+ return cart;
574
+ }, [lines, cart]);
477
575
  useEffect(() => {
478
576
  if (locale === "au") {
479
577
  const isPointsSubscribe = Cookies5.get("points_subscribe");
@@ -495,14 +593,16 @@ var useScriptAutoFreeGift = ({
495
593
  upgrade_multiple2 = 1.2;
496
594
  upgrade_value2 = 40;
497
595
  }
498
- cart?.lineItems?.forEach(({ customAttributes }) => {
499
- customAttributes?.forEach(({ key, value }) => {
500
- if (key === "_amount_upgrade_multiple") upgrade_multiple2 = Number(value) || 1;
501
- if (key === "_amount_upgrade_value") upgrade_value2 = Number(value) || 0;
502
- });
503
- });
596
+ effectiveCart?.lineItems?.forEach(
597
+ ({ customAttributes }) => {
598
+ customAttributes?.forEach(({ key, value }) => {
599
+ if (key === "_amount_upgrade_multiple") upgrade_multiple2 = Number(value) || 1;
600
+ if (key === "_amount_upgrade_value") upgrade_value2 = Number(value) || 0;
601
+ });
602
+ }
603
+ );
504
604
  return [upgrade_multiple2, upgrade_value2];
505
- }, [cart?.lineItems, points_subscribe]);
605
+ }, [effectiveCart?.lineItems, points_subscribe]);
506
606
  const breakpoints = useMemo(() => {
507
607
  if (!isActivityAvailable) return [];
508
608
  return (campaign?.breakpoints || []).map((item) => ({
@@ -530,7 +630,7 @@ var useScriptAutoFreeGift = ({
530
630
  }, [giftHandles]);
531
631
  const involvedLines = useMemo(() => {
532
632
  if (!isActivityAvailable) return [];
533
- return (cart?.lineItems || []).filter((line) => {
633
+ return (effectiveCart?.lineItems || []).filter((line) => {
534
634
  const isNotGift = line?.totalAmount && Number(line.totalAmount) > 0 && line.customAttributes?.every(
535
635
  (item) => item.key !== _giveaway
536
636
  );
@@ -539,7 +639,7 @@ var useScriptAutoFreeGift = ({
539
639
  );
540
640
  return isNotGift && hasCampaignTag;
541
641
  });
542
- }, [cart?.lineItems, isActivityAvailable, _giveaway]);
642
+ }, [effectiveCart?.lineItems, isActivityAvailable, _giveaway]);
543
643
  const involvedSubTotal = useMemo(() => {
544
644
  if (!isActivityAvailable) return new Decimal2(0);
545
645
  return involvedLines.reduce((prev, item) => {
@@ -565,18 +665,24 @@ var useScriptAutoFreeGift = ({
565
665
  const nextLevel = levelIndex > 0 ? sortedLevels[levelIndex - 1] ?? null : null;
566
666
  return [currentLevel, nextLevel];
567
667
  }, [breakpoints, involvedSubTotal, involvedLines.length]);
568
- const { data: giftProductsResult } = useSWR(shouldFetch ? giftHandles : null, async () => {
569
- const res = await getProductsByHandles(client, {
570
- handles: giftHandles,
571
- locale
572
- });
573
- const result = Array.isArray(res) ? res : [];
574
- giftProductsCache.current = {
575
- data: result,
576
- giftHandles: [...giftHandles]
577
- };
578
- return result;
579
- });
668
+ const { data: giftProductsResult } = useSWR(
669
+ shouldFetch ? giftHandles : null,
670
+ async () => {
671
+ const res = await getProductsByHandles(client, {
672
+ handles: giftHandles,
673
+ locale
674
+ });
675
+ const result = Array.isArray(res) ? res : [];
676
+ giftProductsCache.current = {
677
+ data: result,
678
+ giftHandles: [...giftHandles]
679
+ };
680
+ return result;
681
+ },
682
+ {
683
+ revalidateOnFocus: false
684
+ }
685
+ );
580
686
  const finalGiftProductsResult = useMemo(() => {
581
687
  if (giftProductsCache.current && !shouldFetch) {
582
688
  return giftProductsCache.current.data || void 0;
@@ -839,7 +945,7 @@ function useApplyCartCodes(options) {
839
945
  if (!discountCodes?.length) {
840
946
  throw new Error("Invalid input used for this operation: Miss discountCode");
841
947
  }
842
- const cartId = providedCartId ? void 0 : providedCartId || cart?.id;
948
+ const cartId = providedCartId || cart?.id;
843
949
  if (!cartId) {
844
950
  return void 0;
845
951
  }
@@ -852,6 +958,12 @@ function useApplyCartCodes(options) {
852
958
  cookieAdapter: cartCookieAdapter,
853
959
  metafieldIdentifiers
854
960
  });
961
+ const unApplicableCodes = discountCodes.filter(
962
+ (code) => updatedCart?.discountCodes?.find((item) => item.code === code && !item.applicable)
963
+ );
964
+ if (unApplicableCodes.length) {
965
+ throw new Error(`${unApplicableCodes.join(", ")} is not applicable to the cart`);
966
+ }
855
967
  if (updatedCart) {
856
968
  mutateCart(updatedCart);
857
969
  }
@@ -867,7 +979,7 @@ function useRemoveCartCodes(options) {
867
979
  const removeCodes = useCallback(
868
980
  async (_key, { arg }) => {
869
981
  const { cartId: providedCartId, discountCodes } = arg;
870
- const cartId = providedCartId ? void 0 : providedCartId || cart?.id;
982
+ const cartId = providedCartId || cart?.id;
871
983
  const codes = cart?.discountCodes?.filter((code) => !!code.applicable) || [];
872
984
  const leftCodes = codes.filter((code) => discountCodes?.length ? !discountCodes.includes(code.code) : code.code).map((code) => code.code);
873
985
  const updatedCart = await updateCartCodes(client, {
@@ -889,7 +1001,7 @@ function useRemoveCartCodes(options) {
889
1001
  // src/hooks/cart/use-add-to-cart.ts
890
1002
  function useAddToCart({ withTrack = true } = {}, swrOptions) {
891
1003
  const { client, config, locale, cartCookieAdapter, userAdapter } = useShopify();
892
- const { cart } = useCartContext();
1004
+ const { cart, addCustomAttributes } = useCartContext();
893
1005
  const { trigger: applyCartCodes } = useApplyCartCodes();
894
1006
  const { trigger: removeInvalidCodes } = useRemoveCartCodes();
895
1007
  const { trigger: addCartLines2 } = useAddCartLines();
@@ -903,7 +1015,8 @@ function useAddToCart({ withTrack = true } = {}, swrOptions) {
903
1015
  buyerIdentity,
904
1016
  needCreateCart = false,
905
1017
  onCodesInvalid,
906
- replaceExistingCodes
1018
+ replaceExistingCodes,
1019
+ customAttributes
907
1020
  } = arg;
908
1021
  if (!lineItems || lineItems.length === 0) {
909
1022
  return;
@@ -926,6 +1039,7 @@ function useAddToCart({ withTrack = true } = {}, swrOptions) {
926
1039
  if (!resultCart) {
927
1040
  return void 0;
928
1041
  }
1042
+ console.log("npm addCartLines resultCart", resultCart);
929
1043
  if (resultCart.discountCodes && resultCart.discountCodes.length > 0) {
930
1044
  const unapplicableCodes = resultCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
931
1045
  if (unapplicableCodes.length > 0) {
@@ -947,6 +1061,9 @@ function useAddToCart({ withTrack = true } = {}, swrOptions) {
947
1061
  discountCodes
948
1062
  });
949
1063
  }
1064
+ if (customAttributes && customAttributes.length > 0) {
1065
+ addCustomAttributes(customAttributes);
1066
+ }
950
1067
  if (withTrack) {
951
1068
  trackAddToCartGA({
952
1069
  lineItems,
@@ -1099,6 +1216,60 @@ function useBuyNow({ withTrack = true } = {}, swrOptions) {
1099
1216
  );
1100
1217
  return useSWRMutation("buy-now", buyNow, swrOptions);
1101
1218
  }
1219
+ function useCalcGiftsFromLines({
1220
+ lines,
1221
+ customer,
1222
+ scriptGiveawayKey = CUSTOMER_SCRIPT_GIFT_KEY
1223
+ }) {
1224
+ const { locale } = useShopify();
1225
+ const { cart, autoFreeGiftConfig, gradientGiftsConfig } = useCartContext();
1226
+ const functionGift = useCalcAutoFreeGift(cart, autoFreeGiftConfig || [], customer, lines);
1227
+ const scriptGift = useScriptAutoFreeGift({
1228
+ campaign: gradientGiftsConfig || null,
1229
+ _giveaway: scriptGiveawayKey,
1230
+ cart,
1231
+ locale,
1232
+ lines
1233
+ });
1234
+ const allGiftLines = useMemo(() => {
1235
+ const functionGiftLines = functionGift.qualifyingGift?.itemsToAdd || [];
1236
+ const scriptGiftLines = scriptGift.freeGiftLevel ? scriptGift.freeGiftLevel.giveawayProducts.map((product) => {
1237
+ const giftProduct = scriptGift.giftProductsResult?.find(
1238
+ (p) => p.handle === product.handle
1239
+ );
1240
+ const variant = giftProduct?.variants?.[0];
1241
+ return {
1242
+ variant: {
1243
+ id: variant?.id || "",
1244
+ handle: product.handle,
1245
+ sku: product.sku
1246
+ },
1247
+ quantity: 1,
1248
+ attributes: [
1249
+ {
1250
+ key: scriptGiveawayKey,
1251
+ value: "true"
1252
+ }
1253
+ ]
1254
+ };
1255
+ }).filter((item) => item.variant.id) : [];
1256
+ return [...functionGiftLines, ...scriptGiftLines];
1257
+ }, [
1258
+ functionGift.qualifyingGift,
1259
+ scriptGift.freeGiftLevel,
1260
+ scriptGift.giftProductsResult,
1261
+ scriptGiveawayKey
1262
+ ]);
1263
+ const hasGifts = useMemo(() => {
1264
+ return allGiftLines.length > 0;
1265
+ }, [allGiftLines]);
1266
+ return {
1267
+ functionGift,
1268
+ scriptGift,
1269
+ allGiftLines,
1270
+ hasGifts
1271
+ };
1272
+ }
1102
1273
 
1103
1274
  // src/hooks/cart/types/order-discount.ts
1104
1275
  var OrderDiscountType = /* @__PURE__ */ ((OrderDiscountType2) => {
@@ -1149,9 +1320,12 @@ var useCalcOrderDiscount = (cart, orderDiscountConfig, customer) => {
1149
1320
  discountAmount: 0
1150
1321
  };
1151
1322
  }
1152
- const tieredDiscounts = activeCampaign.result_detail.order_discount_conf.tiered_discounts;
1153
- const qualifyingTier = [...tieredDiscounts].reverse().find((tier) => subtotal >= Number(tier.amount));
1154
- const nextGoal = tieredDiscounts.find((tier) => subtotal < Number(tier.amount));
1323
+ const currentCurrency = cart?.currency?.code || "";
1324
+ console.log("currentCurrency", cart, currentCurrency);
1325
+ const orderDiscountConf = activeCampaign.result_detail.order_discount_conf;
1326
+ const tieredDiscounts = orderDiscountConf.tiered_discounts_markets?.[currentCurrency] || orderDiscountConf.tiered_discounts;
1327
+ const qualifyingTier = [...tieredDiscounts].sort((a, b) => Number(b.amount) - Number(a.amount)).find((tier) => subtotal >= Number(tier.amount));
1328
+ const nextGoal = [...tieredDiscounts].sort((a, b) => Number(a.amount) - Number(b.amount)).find((tier) => subtotal < Number(tier.amount));
1155
1329
  if (!qualifyingTier) {
1156
1330
  return {
1157
1331
  qualifyingDiscount: null,
@@ -1219,12 +1393,10 @@ function useHasPlusMemberInCart({
1219
1393
  };
1220
1394
  }, [cart?.lineItems, plus_monthly_product, plus_annual_product]);
1221
1395
  }
1222
-
1223
- // src/hooks/cart/feature/use-cart-attributes.ts
1224
1396
  var getReferralAttributes = () => {
1225
- const inviteCode = Cookies5.get("invite_code");
1226
- const playModeId = Cookies5.get("playModeId");
1227
- const popup = Cookies5.get("_popup");
1397
+ const inviteCode = getLocalStorage("invite_code") || Cookies5.get("invite_code");
1398
+ const playModeId = getLocalStorage("playModeId") || Cookies5.get("playModeId");
1399
+ const popup = getLocalStorage("_popup") || Cookies5.get("_popup");
1228
1400
  if (inviteCode && playModeId) {
1229
1401
  return popup ? [
1230
1402
  { key: "_invite_code", value: inviteCode ? inviteCode : "" },
@@ -1248,8 +1420,6 @@ var useCartAttributes = ({
1248
1420
  memberSetting,
1249
1421
  cart
1250
1422
  });
1251
- console.log("memberSetting", memberSetting);
1252
- console.log("hasPlusMember", hasPlusMember);
1253
1423
  useEffect(() => {
1254
1424
  setCurrentUrl(window.location.href);
1255
1425
  }, []);
@@ -1275,7 +1445,7 @@ var useCartAttributes = ({
1275
1445
  return "new_user_login";
1276
1446
  }, [customer]);
1277
1447
  const memberAttributes = useMemo(() => {
1278
- return [
1448
+ const attributes = [
1279
1449
  {
1280
1450
  key: "_token",
1281
1451
  value: profile?.token
@@ -1296,17 +1466,28 @@ var useCartAttributes = ({
1296
1466
  value: profile?.token ? "true" : "false"
1297
1467
  }
1298
1468
  ];
1469
+ if (profile?.token) {
1470
+ attributes.push({
1471
+ key: "_login_user",
1472
+ value: "1"
1473
+ });
1474
+ }
1475
+ return attributes;
1299
1476
  }, [profile?.memberType, profile?.token, userType, hasPlusMember]);
1300
1477
  const functionAttributes = useMemo(() => {
1301
- return [
1302
- cart?.discountCodes && {
1478
+ const hasFunctionEnvAttribute = cart?.lineItems.some(
1479
+ (item) => item.customAttributes?.some((attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY)
1480
+ );
1481
+ const discountCodes = cart?.discountCodes.map((item) => item.code).filter((code) => code) || [];
1482
+ return hasFunctionEnvAttribute ? [
1483
+ {
1303
1484
  key: "_discounts_function_env",
1304
1485
  value: JSON.stringify({
1305
- discount_code: cart?.discountCodes.map((item) => item.code),
1486
+ discount_code: discountCodes,
1306
1487
  user_tags: customer?.tags || []
1307
1488
  })
1308
1489
  }
1309
- ];
1490
+ ] : [];
1310
1491
  }, [cart]);
1311
1492
  const presellAttributes = useMemo(() => {
1312
1493
  return [
@@ -1338,18 +1519,50 @@ var useCartAttributes = ({
1338
1519
  }
1339
1520
  ];
1340
1521
  }, [currentUrl]);
1522
+ const commonAttributes = useMemo(
1523
+ () => [
1524
+ ...memberAttributes,
1525
+ ...functionAttributes,
1526
+ ...presellAttributes,
1527
+ ...weightAttributes,
1528
+ ...trackingAttributes,
1529
+ ...getReferralAttributes()
1530
+ ].filter((item) => item?.value),
1531
+ [memberAttributes, functionAttributes, presellAttributes, weightAttributes, trackingAttributes]
1532
+ );
1533
+ const extraAttributesInCart = useMemo(() => {
1534
+ const commonAttributeKeys = [
1535
+ // member attributes
1536
+ "_token",
1537
+ "_member_type",
1538
+ "_user_type",
1539
+ "_is_login",
1540
+ "_login_user",
1541
+ // function attributes
1542
+ "_discounts_function_env",
1543
+ // presell attributes
1544
+ "_presale",
1545
+ // weight attributes
1546
+ "_weight",
1547
+ "_app_source_name",
1548
+ // tracking attributes
1549
+ "utm_params",
1550
+ // referral attributes
1551
+ "_invite_code",
1552
+ "_play_mode_id",
1553
+ "_popup"
1554
+ ];
1555
+ return cart?.customAttributes?.filter(
1556
+ (item) => !commonAttributeKeys.includes(item.key)
1557
+ ) || [];
1558
+ }, [cart]);
1341
1559
  return useMemo(
1342
1560
  () => ({
1343
- attributes: [
1344
- ...memberAttributes,
1345
- ...functionAttributes,
1346
- ...presellAttributes,
1347
- ...weightAttributes,
1348
- ...trackingAttributes,
1349
- ...getReferralAttributes()
1350
- ].filter((item) => item?.value)
1561
+ attributes: [...commonAttributes, ...extraAttributesInCart].filter(
1562
+ (item) => item?.value
1563
+ )
1351
1564
  }),
1352
- [memberAttributes, functionAttributes, presellAttributes, weightAttributes, trackingAttributes]
1565
+ [commonAttributes, extraAttributesInCart]
1353
1566
  );
1354
1567
  };
1355
1568
  var DEFAULT_MIN = 1;
@@ -1566,8 +1779,9 @@ function useProductsByHandles(options = {}) {
1566
1779
  metafieldIdentifiers
1567
1780
  });
1568
1781
  },
1569
- swrOptions || {
1570
- revalidateOnFocus: false
1782
+ {
1783
+ revalidateOnFocus: false,
1784
+ ...swrOptions
1571
1785
  }
1572
1786
  );
1573
1787
  }
@@ -2483,6 +2697,73 @@ var usePlusMemberDeliveryCodes = ({
2483
2697
  [deliveryData]
2484
2698
  );
2485
2699
  };
2700
+ function useUpdateCartDeliveryOptions(mutate, metafieldIdentifiers, options) {
2701
+ const { client, locale, cartCookieAdapter } = useShopify();
2702
+ const updateDeliveryOptions = useCallback(
2703
+ async (_key, { arg }) => {
2704
+ const updatedCart = await updateCartDeliveryOptions(client, {
2705
+ ...arg,
2706
+ metafieldIdentifiers,
2707
+ cookieAdapter: cartCookieAdapter
2708
+ });
2709
+ console.log("useUpdateCartDeliveryOptions updatedCart", updatedCart);
2710
+ if (updatedCart) {
2711
+ mutate(updatedCart);
2712
+ }
2713
+ return updatedCart;
2714
+ },
2715
+ [client, locale, cartCookieAdapter, mutate]
2716
+ );
2717
+ return useSWRMutation("update-cart-delivery-options", updateDeliveryOptions, options);
2718
+ }
2719
+
2720
+ // src/hooks/member/plus/use-update-plus-member-delivery-options.ts
2721
+ var useUpdatePlusMemberDeliveryOptions = ({
2722
+ options
2723
+ } = {}) => {
2724
+ const { cart: cartContextData, mutateCart, metafieldIdentifiers } = useCartContext();
2725
+ const { trigger: updateCartDeliveryOptions2 } = useUpdateCartDeliveryOptions(
2726
+ mutateCart,
2727
+ metafieldIdentifiers
2728
+ );
2729
+ const handler = useCallback(
2730
+ async (_, { arg }) => {
2731
+ const currentCart = arg?.cart || cartContextData;
2732
+ const { deliveryData } = arg;
2733
+ const firstDeliveryGroup = currentCart?.deliveryGroups?.[0];
2734
+ const deliveryGroupId = firstDeliveryGroup?.id;
2735
+ const selectedOptionCode = deliveryData?.deliveryCustomData?.selected_delivery_option?.code;
2736
+ if (!deliveryGroupId || !selectedOptionCode || selectedOptionCode === firstDeliveryGroup?.selectedDeliveryOption?.code) {
2737
+ return null;
2738
+ }
2739
+ const deliveryGroup = currentCart?.deliveryGroups?.find(
2740
+ (group) => group?.id === deliveryGroupId
2741
+ );
2742
+ const matchedOption = deliveryGroup?.deliveryOptions?.find(
2743
+ (option) => option?.code === selectedOptionCode
2744
+ );
2745
+ if (!matchedOption?.handle) {
2746
+ return null;
2747
+ }
2748
+ const deliveryOptions = [
2749
+ {
2750
+ deliveryGroupId,
2751
+ deliveryOptionHandle: matchedOption.handle
2752
+ }
2753
+ ];
2754
+ const updatedCart = await updateCartDeliveryOptions2({
2755
+ selectedDeliveryOptions: deliveryOptions,
2756
+ cartId: currentCart?.id
2757
+ });
2758
+ if (updatedCart && mutateCart) {
2759
+ mutateCart(updatedCart);
2760
+ }
2761
+ return updatedCart;
2762
+ },
2763
+ [cartContextData, updateCartDeliveryOptions2, mutateCart]
2764
+ );
2765
+ return useSWRMutation("update-cart-delivery-options", handler, options);
2766
+ };
2486
2767
  var usePlusMemberItemCustomAttributes = ({
2487
2768
  deliveryData
2488
2769
  }) => {
@@ -2502,48 +2783,18 @@ var usePlusMemberCheckoutCustomAttributes = ({
2502
2783
  deliveryData,
2503
2784
  product,
2504
2785
  variant,
2505
- customer,
2506
2786
  isShowShippingBenefits
2507
2787
  }) => {
2508
2788
  const { deliveryCustomData } = deliveryData || {};
2509
2789
  const { profile } = usePlusMemberContext();
2510
- const userType = useMemo(() => {
2511
- const customerInfo = customer;
2512
- if (!customerInfo) {
2513
- return "new_user_unlogin";
2514
- }
2515
- if (customer) {
2516
- const { orders = {} } = customer;
2517
- const edgesLength = orders?.edges?.length;
2518
- if (edgesLength === 1) {
2519
- return "old_user_orders_once";
2520
- } else if (edgesLength && edgesLength > 1) {
2521
- return "old_user_orders_twice";
2522
- }
2523
- }
2524
- return "new_user_login";
2525
- }, [customer]);
2526
2790
  return useMemo(() => {
2527
2791
  const checkoutCustomAttributes = [
2528
- {
2529
- key: "_token",
2530
- value: profile?.token || ""
2531
- },
2792
+ // _last_url: 付费会员结算完成之后 checkout 有一个继续购买的按钮, 用于跳转到继续购买的页面
2532
2793
  {
2533
2794
  key: "_last_url",
2534
2795
  value: typeof window !== "undefined" ? window.location.origin + window.location.pathname : ""
2535
- },
2536
- {
2537
- key: "_user_type",
2538
- value: userType
2539
2796
  }
2540
2797
  ];
2541
- if (profile) {
2542
- checkoutCustomAttributes.push({
2543
- key: "_login_user",
2544
- value: "1"
2545
- });
2546
- }
2547
2798
  if (deliveryCustomData) {
2548
2799
  checkoutCustomAttributes.push({
2549
2800
  key: "_checkout_delivery_custom",
@@ -2553,12 +2804,6 @@ var usePlusMemberCheckoutCustomAttributes = ({
2553
2804
  })
2554
2805
  });
2555
2806
  }
2556
- if (variant?.metafields?.presell) {
2557
- checkoutCustomAttributes.push({
2558
- key: "_presale",
2559
- value: "true"
2560
- });
2561
- }
2562
2807
  if (isShowShippingBenefits && !isShowShippingBenefits({ variant, product, setting: {} })) {
2563
2808
  checkoutCustomAttributes.push({
2564
2809
  key: "_hide_shipping",
@@ -2566,18 +2811,17 @@ var usePlusMemberCheckoutCustomAttributes = ({
2566
2811
  });
2567
2812
  }
2568
2813
  return checkoutCustomAttributes;
2569
- }, [deliveryCustomData, product, profile, userType, variant, isShowShippingBenefits]);
2814
+ }, [deliveryCustomData, product, profile, variant, isShowShippingBenefits]);
2570
2815
  };
2571
2816
  function useAutoRemovePlusMemberInCart({
2572
- metafields,
2573
- isMonthlyPlus,
2574
- isAnnualPlus
2817
+ cart,
2818
+ profile,
2819
+ memberSetting
2575
2820
  }) {
2576
- const { plus_monthly_product, plus_annual_product } = metafields || {};
2577
- const { cart } = useCartContext();
2821
+ const { plus_monthly_product, plus_annual_product } = memberSetting || {};
2578
2822
  const { trigger: removeCartLines2 } = useRemoveCartLines();
2579
2823
  useEffect(() => {
2580
- if (!cart) return;
2824
+ if (!cart || !plus_monthly_product || !plus_annual_product) return;
2581
2825
  const removePlusProduct = async (productType) => {
2582
2826
  if (!productType) return;
2583
2827
  const product = cart.lineItems?.find(
@@ -2589,33 +2833,25 @@ function useAutoRemovePlusMemberInCart({
2589
2833
  });
2590
2834
  }
2591
2835
  };
2592
- if (isMonthlyPlus) {
2836
+ if (profile?.isMonthlyPlus) {
2593
2837
  removePlusProduct(plus_monthly_product);
2594
2838
  }
2595
- if (isAnnualPlus) {
2839
+ if (profile?.isAnnualPlus) {
2596
2840
  removePlusProduct(plus_annual_product);
2597
2841
  }
2598
- }, [
2599
- cart,
2600
- plus_annual_product,
2601
- plus_monthly_product,
2602
- isAnnualPlus,
2603
- isMonthlyPlus,
2604
- removeCartLines2
2605
- ]);
2842
+ }, [cart, plus_annual_product, plus_monthly_product, profile, removeCartLines2]);
2606
2843
  }
2607
2844
  function useAddPlusMemberProductsToCart({
2608
2845
  cart,
2609
- memberSetting,
2610
- selectedPlusMemberMode,
2611
- selectedPlusMemberProduct
2846
+ profile
2612
2847
  }) {
2848
+ const { selectedPlusMemberMode, selectedPlusMemberProduct, plusMemberMetafields } = usePlusMemberContext();
2613
2849
  const { hasMonthlyPlus, hasAnnualPlus } = useHasPlusMemberInCart({
2614
- cart,
2615
- memberSetting
2850
+ memberSetting: plusMemberMetafields,
2851
+ cart
2616
2852
  });
2617
2853
  const plusMemberProduct = useMemo(() => {
2618
- if (selectedPlusMemberMode === "free" /* FREE */) {
2854
+ if (!selectedPlusMemberProduct || selectedPlusMemberMode === "free" /* FREE */) {
2619
2855
  return void 0;
2620
2856
  }
2621
2857
  if (selectedPlusMemberMode === "monthly" /* MONTHLY */ && hasMonthlyPlus) {
@@ -2624,7 +2860,10 @@ function useAddPlusMemberProductsToCart({
2624
2860
  if (selectedPlusMemberMode === "annual" /* ANNUAL */ && hasAnnualPlus) {
2625
2861
  return void 0;
2626
2862
  }
2627
- if (!selectedPlusMemberProduct) {
2863
+ if (profile?.isMonthlyPlus && selectedPlusMemberMode === "monthly" /* MONTHLY */) {
2864
+ return void 0;
2865
+ }
2866
+ if (profile?.isAnnualPlus && selectedPlusMemberMode === "annual" /* ANNUAL */) {
2628
2867
  return void 0;
2629
2868
  }
2630
2869
  return selectedPlusMemberProduct;
@@ -2943,8 +3182,13 @@ function CartProvider({
2943
3182
  const { attributes } = useCartAttributes({ profile, customer, cart, memberSetting });
2944
3183
  useRequest(
2945
3184
  () => {
2946
- const newAttributes = [...attributes, ...customAttributes];
2947
- const needUpdate = cart && !checkAttributesUpdateNeeded(
3185
+ const newAttributes = [...attributes];
3186
+ customAttributes.forEach((item) => {
3187
+ if (item.value && !newAttributes.some((attr) => attr.key === item.key)) {
3188
+ newAttributes.push(item);
3189
+ }
3190
+ });
3191
+ const needUpdate = cart && checkAttributesUpdateNeeded(
2948
3192
  cart.customAttributes,
2949
3193
  newAttributes,
2950
3194
  customAttributesNeedDelete
@@ -3048,8 +3292,14 @@ function CartProvider({
3048
3292
  );
3049
3293
  return result;
3050
3294
  }, [cart?.lineItems, scriptAutoFreeGift, functionAutoFreeGift]);
3295
+ const totalQuantity = useMemo(() => {
3296
+ const cartLinesCount = cart?.lineItems.reduce((acc, item) => acc + item.quantity, 0) || 0;
3297
+ const giftLinesCount = giftNeedAddToCartLines?.reduce((acc, item) => acc + (item.quantity || 1), 0) || 0;
3298
+ return cartLinesCount + giftLinesCount;
3299
+ }, [cart?.lineItems, giftNeedAddToCartLines]);
3051
3300
  const value = useMemo(
3052
3301
  () => ({
3302
+ totalQuantity,
3053
3303
  cart,
3054
3304
  isCartLoading,
3055
3305
  triggerFetch: fetchCart,
@@ -3061,6 +3311,7 @@ function CartProvider({
3061
3311
  isCodeChanging,
3062
3312
  setIsCodeChanging,
3063
3313
  autoFreeGiftConfig,
3314
+ gradientGiftsConfig,
3064
3315
  setLoadingState,
3065
3316
  loadingState,
3066
3317
  // function满赠
@@ -3076,6 +3327,7 @@ function CartProvider({
3076
3327
  }),
3077
3328
  [
3078
3329
  cart,
3330
+ totalQuantity,
3079
3331
  isCartLoading,
3080
3332
  fetchCart,
3081
3333
  mutateCart,
@@ -3084,6 +3336,7 @@ function CartProvider({
3084
3336
  locale,
3085
3337
  isCodeChanging,
3086
3338
  autoFreeGiftConfig,
3339
+ gradientGiftsConfig,
3087
3340
  loadingState,
3088
3341
  // function满赠
3089
3342
  functionAutoFreeGift,
@@ -3107,6 +3360,6 @@ function useCartContext() {
3107
3360
  return context;
3108
3361
  }
3109
3362
 
3110
- export { BuyRuleType, CODE_AMOUNT_KEY, CUSTOMER_ATTRIBUTE_KEY, CUSTOMER_SCRIPT_GIFT_KEY, CartProvider, DeliveryPlusType, MAIN_PRODUCT_CODE, OrderBasePriceType, OrderDiscountType, PLUS_MEMBER_TYPE, PlusMemberContext, PlusMemberMode, PlusMemberProvider, PriceBasePriceType, PriceDiscountType, RuleType, SCRIPT_CODE_AMOUNT_KEY, ShippingMethodMode, ShopifyContext, ShopifyProvider, SpendMoneyType, atobID, browserCartCookieAdapter, browserCookieAdapter, btoaID, checkAttributesUpdateNeeded, clearGeoLocationCache, currencyCodeMapping, defaultSWRMutationConfiguration, formatFunctionAutoFreeGift, formatScriptAutoFreeGift, gaTrack, getCachedGeoLocation, getDiscountEnvAttributeValue, getMatchedMainProductSubTotal, getQuery, getReferralAttributes, preCheck, safeParse, trackAddToCartFBQ, trackAddToCartGA, trackBeginCheckoutGA, trackBuyNowFBQ, trackBuyNowGA, useAddCartLines, useAddPlusMemberProductsToCart, useAddToCart, useAllBlogs, useAllCollections, useAllProducts, useApplyCartCodes, useArticle, useArticles, useArticlesInBlog, useAutoRemovePlusMemberInCart, useBlog, useBuyNow, useCalcAutoFreeGift, useCalcOrderDiscount, useCartAttributes, useCartContext, useCartItemQuantityLimit, useCollection, useCollections, useCreateCart, useExposure, useGeoLocation, useHasPlusMemberInCart, useIntersection, usePlusAnnualProductVariant, usePlusMemberCheckoutCustomAttributes, usePlusMemberContext, usePlusMemberDeliveryCodes, usePlusMemberItemCustomAttributes, usePlusMonthlyProductVariant, usePrice, useProduct, useProductUrl, useProductsByHandles, useRemoveCartCodes, useRemoveCartLines, useReplaceCartPlusMember, useScriptAutoFreeGift, useSearch, useSelectedOptions, useShippingMethodAvailableCheck, useShippingMethods, useShopify, useSite, useUpdateCartAttributes, useUpdateCartLines, useUpdateLineCodeAmountAttributes, useUpdateVariantQuery, useVariant, useVariantMedia };
3363
+ export { BuyRuleType, CODE_AMOUNT_KEY, CUSTOMER_ATTRIBUTE_KEY, CUSTOMER_SCRIPT_GIFT_KEY, CartProvider, DeliveryPlusType, MAIN_PRODUCT_CODE, OrderBasePriceType, OrderDiscountType, PLUS_MEMBER_TYPE, PlusMemberContext, PlusMemberMode, PlusMemberProvider, PriceBasePriceType, PriceDiscountType, RuleType, SCRIPT_CODE_AMOUNT_KEY, ShippingMethodMode, ShopifyContext, ShopifyProvider, SpendMoneyType, browserCartCookieAdapter, browserCookieAdapter, checkAttributesUpdateNeeded, clearGeoLocationCache, createMockCartFromLines, currencyCodeMapping, defaultSWRMutationConfiguration, formatFunctionAutoFreeGift, formatScriptAutoFreeGift, gaTrack, getCachedGeoLocation, getDiscountEnvAttributeValue, getMatchedMainProductSubTotal, getQuery, getReferralAttributes, normalizeAddToCartLines, preCheck, safeParse, trackAddToCartFBQ, trackAddToCartGA, trackBeginCheckoutGA, trackBuyNowFBQ, trackBuyNowGA, useAddCartLines, useAddPlusMemberProductsToCart, useAddToCart, useAllBlogs, useAllCollections, useAllProducts, useApplyCartCodes, useArticle, useArticles, useArticlesInBlog, useAutoRemovePlusMemberInCart, useBlog, useBuyNow, useCalcAutoFreeGift, useCalcGiftsFromLines, useCalcOrderDiscount, useCartAttributes, useCartContext, useCartItemQuantityLimit, useCollection, useCollections, useCreateCart, useExposure, useGeoLocation, useHasPlusMemberInCart, useIntersection, usePlusAnnualProductVariant, usePlusMemberCheckoutCustomAttributes, usePlusMemberContext, usePlusMemberDeliveryCodes, usePlusMemberItemCustomAttributes, usePlusMonthlyProductVariant, usePrice, useProduct, useProductUrl, useProductsByHandles, useRemoveCartCodes, useRemoveCartLines, useReplaceCartPlusMember, useScriptAutoFreeGift, useSearch, useSelectedOptions, useShippingMethodAvailableCheck, useShippingMethods, useShopify, useSite, useUpdateCartAttributes, useUpdateCartLines, useUpdateLineCodeAmountAttributes, useUpdatePlusMemberDeliveryOptions, useUpdateVariantQuery, useVariant, useVariantMedia };
3111
3364
  //# sourceMappingURL=index.mjs.map
3112
3365
  //# sourceMappingURL=index.mjs.map