@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.js CHANGED
@@ -142,6 +142,83 @@ var CODE_AMOUNT_KEY = "_sku_code_money";
142
142
  var SCRIPT_CODE_AMOUNT_KEY = "_code_money";
143
143
  var MAIN_PRODUCT_CODE = ["WS24", "WSTD", "WS7D", "WSCP", "WSPE", "WSPD"];
144
144
 
145
+ // src/hooks/cart/utils/normalize-add-to-cart-lines.ts
146
+ function normalizeAddToCartLines(lines) {
147
+ return lines.filter((line) => line.variant?.id).map((line, index) => {
148
+ const variant = line.variant;
149
+ const product = variant.product;
150
+ 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;
154
+ return {
155
+ id: `temp-line-${index}-${variant.id}`,
156
+ // Temporary ID for pre-cart lines
157
+ name: product?.title || variant.title || "",
158
+ quantity,
159
+ variantId: variant.id,
160
+ productId: product?.id || variant.id.split("/").slice(0, -2).join("/"),
161
+ totalAmount,
162
+ subtotalAmount,
163
+ discountAllocations: [],
164
+ customAttributes: line.attributes || [],
165
+ variant: {
166
+ id: variant.id,
167
+ price,
168
+ listPrice: variant.compareAtPrice?.amount ? Number(variant.compareAtPrice.amount) : 0,
169
+ sku: variant.sku || "",
170
+ name: variant.title || "",
171
+ image: variant.image ? {
172
+ url: variant.image.url,
173
+ altText: variant.image.altText || void 0
174
+ } : void 0,
175
+ requiresShipping: false,
176
+ // Default value, not available in NormalizedProductVariant
177
+ availableForSale: variant.availableForSale ?? true,
178
+ quantityAvailable: variant.quantityAvailable ?? 0,
179
+ currentlyNotInStock: false,
180
+ // Default value, will be updated when added to cart
181
+ weight: variant.weight,
182
+ metafields: variant.metafields
183
+ },
184
+ product,
185
+ path: product?.handle ? `/products/${product.handle}` : "",
186
+ discounts: [],
187
+ options: variant.selectedOptions?.map((opt) => ({
188
+ name: opt.name,
189
+ value: opt.value
190
+ }))
191
+ };
192
+ });
193
+ }
194
+ function createMockCartFromLines(lines, existingCart) {
195
+ const normalizedLines = normalizeAddToCartLines(lines);
196
+ const subtotalPrice = normalizedLines.reduce((sum, line) => sum + line.subtotalAmount, 0);
197
+ const totalPrice = normalizedLines.reduce((sum, line) => sum + line.totalAmount, 0);
198
+ console.log("lines createMockCartFromLines", lines);
199
+ const currency = lines[0]?.variant?.price?.currencyCode;
200
+ return {
201
+ id: existingCart?.id || "temp-cart-id",
202
+ customerId: existingCart?.customerId,
203
+ email: existingCart?.email,
204
+ createdAt: existingCart?.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
205
+ currency: existingCart?.currency?.code || { code: currency },
206
+ taxesIncluded: existingCart?.taxesIncluded,
207
+ lineItems: normalizedLines,
208
+ totalLineItemsDiscount: 0,
209
+ orderDiscounts: 0,
210
+ lineItemsSubtotalPrice: subtotalPrice,
211
+ subtotalPrice,
212
+ totalPrice,
213
+ totalTaxAmount: 0,
214
+ discountCodes: existingCart?.discountCodes || [],
215
+ discountAllocations: [],
216
+ url: existingCart?.url || "",
217
+ ready: true,
218
+ customAttributes: existingCart?.customAttributes
219
+ };
220
+ }
221
+
145
222
  // src/hooks/cart/utils/index.ts
146
223
  var getQuery = () => {
147
224
  const url = typeof window !== "undefined" ? window.location.search : "";
@@ -159,22 +236,12 @@ var getQuery = () => {
159
236
  }
160
237
  return theRequest;
161
238
  };
162
- function atobID(id) {
163
- if (id && typeof id === "string" && id.includes("/")) {
164
- return id.split("/").pop()?.split("?")?.shift();
165
- } else {
166
- return id;
167
- }
168
- }
169
- function btoaID(id, type = "ProductVariant") {
170
- return `gid://shopify/${type}/${id}`;
171
- }
172
239
  var getMatchedMainProductSubTotal = (cartData, variant_list, main_product) => {
173
240
  const isAllStoreVariant = main_product?.all_store_variant ?? false;
174
241
  const matchedList = cartData?.lineItems?.filter((line) => {
175
242
  const { is_gift } = getDiscountEnvAttributeValue(line.customAttributes);
176
243
  return isAllStoreVariant ? !is_gift : variant_list?.find((item) => {
177
- return !is_gift && atobID(line.variantId) === item;
244
+ return !is_gift && shopifySdk.atobID(line.variantId) === item;
178
245
  });
179
246
  });
180
247
  return matchedList?.reduce((acc, line) => {
@@ -366,12 +433,18 @@ var formatFunctionAutoFreeGift = ({
366
433
  };
367
434
  return result;
368
435
  };
369
- var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
436
+ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
370
437
  const tags = react.useMemo(() => customer?.tags || [], [customer?.tags]);
371
438
  const isCustomerLoading = react.useMemo(() => !customer ? true : false, [customer]);
372
439
  const dealsType = "";
373
440
  const { client, locale } = useShopify();
374
441
  const giftProductsCache = react.useRef(null);
442
+ const effectiveCart = react.useMemo(() => {
443
+ if (lines && lines.length > 0) {
444
+ return createMockCartFromLines(lines, cart);
445
+ }
446
+ return cart;
447
+ }, [lines, cart]);
375
448
  const { activeCampaign, subtotal } = react.useMemo(() => {
376
449
  for (const campaign of autoFreeGiftConfig) {
377
450
  const { rule_conditions = [], rule_result } = campaign;
@@ -379,7 +452,7 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
379
452
  const isPreCheckPassed = preCheck(rule_conditions, tags, []);
380
453
  if (isPreCheckPassed && spend_get_reward) {
381
454
  const matchedSubtotal = getMatchedMainProductSubTotal(
382
- cart,
455
+ effectiveCart,
383
456
  spend_get_reward.main_product?.variant_list?.map((v) => v.variant_id) || [],
384
457
  {
385
458
  spend_money_type: spend_get_reward.main_product?.spend_money_type || 1,
@@ -393,17 +466,26 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
393
466
  }
394
467
  }
395
468
  return { activeCampaign: null, subtotal: 0 };
396
- }, [autoFreeGiftConfig, cart, tags, dealsType]);
469
+ }, [autoFreeGiftConfig, effectiveCart, tags, dealsType]);
397
470
  const { qualifyingGift, nextTierGoal } = react.useMemo(() => {
398
471
  if (!activeCampaign || !activeCampaign.rule_result?.spend_get_reward?.gift_product) {
399
472
  return { qualifyingGift: null, nextTierGoal: null };
400
473
  }
401
474
  const giftTiers = activeCampaign.rule_result.spend_get_reward.gift_product;
402
- const qualifyingTier = [...giftTiers].reverse().find((tier) => subtotal >= Number(tier.spend_sum_money));
403
- const nextGoal = giftTiers.find((tier) => subtotal < Number(tier.spend_sum_money));
475
+ const currentCurrency = effectiveCart?.currency?.code || "";
476
+ console.log("currentCurrency useCalcAutoFreeGift", effectiveCart, currentCurrency);
477
+ const getThresholdAmount = (tier) => {
478
+ if (tier.spend_sum_money_multi_markets?.[currentCurrency]?.value) {
479
+ return Number(tier.spend_sum_money_multi_markets[currentCurrency].value);
480
+ }
481
+ return Number(tier.spend_sum_money || 0);
482
+ };
483
+ const qualifyingTier = [...giftTiers].sort((a, b) => getThresholdAmount(b) - getThresholdAmount(a)).find((tier) => subtotal >= getThresholdAmount(tier));
484
+ const nextGoal = giftTiers.find((tier) => subtotal < getThresholdAmount(tier));
404
485
  if (!qualifyingTier) {
405
486
  return { qualifyingGift: null, nextTierGoal: nextGoal || null };
406
487
  }
488
+ const actualThreshold = getThresholdAmount(qualifyingTier);
407
489
  const formattedGift = {
408
490
  tier: qualifyingTier,
409
491
  itemsToAdd: qualifyingTier.reward_list?.map((reward) => {
@@ -411,7 +493,7 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
411
493
  if (!giftProduct) return null;
412
494
  return {
413
495
  variant: {
414
- id: btoaID(giftProduct.variant_id),
496
+ id: shopifySdk.btoaID(giftProduct.variant_id),
415
497
  handle: giftProduct.handle,
416
498
  sku: giftProduct.sku
417
499
  },
@@ -422,7 +504,10 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
422
504
  value: JSON.stringify({
423
505
  is_gift: true,
424
506
  rule_id: activeCampaign.rule_id,
425
- spend_sum_money: qualifyingTier.spend_sum_money
507
+ spend_sum_money: actualThreshold,
508
+ // 使用实际的门槛金额(多币种支持)
509
+ currency_code: currentCurrency
510
+ // 记录当前币种
426
511
  })
427
512
  }
428
513
  ]
@@ -430,7 +515,7 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
430
515
  }).filter((item) => item !== null)
431
516
  };
432
517
  return { qualifyingGift: formattedGift, nextTierGoal: nextGoal || null };
433
- }, [activeCampaign, subtotal]);
518
+ }, [activeCampaign, subtotal, effectiveCart]);
434
519
  const giftHandles = react.useMemo(() => {
435
520
  const giftVariant = autoFreeGiftConfig.map(
436
521
  (item) => item.rule_result?.spend_get_reward?.gift_product?.map(
@@ -446,18 +531,24 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
446
531
  }
447
532
  return true;
448
533
  }, [giftHandles]);
449
- const { data: giftProductsResult } = useSWR__default.default(shouldFetch ? giftHandles : null, async () => {
450
- const res = await shopifySdk.getProductsByHandles(client, {
451
- handles: giftHandles,
452
- locale
453
- });
454
- const result = Array.isArray(res) ? res : [];
455
- giftProductsCache.current = {
456
- data: result,
457
- giftHandles: [...giftHandles]
458
- };
459
- return result;
460
- });
534
+ const { data: giftProductsResult } = useSWR__default.default(
535
+ shouldFetch ? giftHandles : null,
536
+ async () => {
537
+ const res = await shopifySdk.getProductsByHandles(client, {
538
+ handles: giftHandles,
539
+ locale
540
+ });
541
+ const result = Array.isArray(res) ? res : [];
542
+ giftProductsCache.current = {
543
+ data: result,
544
+ giftHandles: [...giftHandles]
545
+ };
546
+ return result;
547
+ },
548
+ {
549
+ revalidateOnFocus: false
550
+ }
551
+ );
461
552
  const finalGiftProductsResult = react.useMemo(() => {
462
553
  if (giftProductsCache.current && !shouldFetch) {
463
554
  return giftProductsCache.current.data || void 0;
@@ -476,12 +567,19 @@ var useScriptAutoFreeGift = ({
476
567
  campaign,
477
568
  _giveaway,
478
569
  cart,
479
- locale: providedLocale
570
+ locale: providedLocale,
571
+ lines
480
572
  }) => {
481
573
  const { client, locale: contextLocale } = useShopify();
482
574
  const locale = providedLocale || contextLocale;
483
575
  const [points_subscribe, set_points_subscribe] = react.useState(false);
484
576
  const giftProductsCache = react.useRef(null);
577
+ const effectiveCart = react.useMemo(() => {
578
+ if (lines && lines.length > 0) {
579
+ return createMockCartFromLines(lines, cart);
580
+ }
581
+ return cart;
582
+ }, [lines, cart]);
485
583
  react.useEffect(() => {
486
584
  if (locale === "au") {
487
585
  const isPointsSubscribe = Cookies5__default.default.get("points_subscribe");
@@ -503,14 +601,16 @@ var useScriptAutoFreeGift = ({
503
601
  upgrade_multiple2 = 1.2;
504
602
  upgrade_value2 = 40;
505
603
  }
506
- cart?.lineItems?.forEach(({ customAttributes }) => {
507
- customAttributes?.forEach(({ key, value }) => {
508
- if (key === "_amount_upgrade_multiple") upgrade_multiple2 = Number(value) || 1;
509
- if (key === "_amount_upgrade_value") upgrade_value2 = Number(value) || 0;
510
- });
511
- });
604
+ effectiveCart?.lineItems?.forEach(
605
+ ({ customAttributes }) => {
606
+ customAttributes?.forEach(({ key, value }) => {
607
+ if (key === "_amount_upgrade_multiple") upgrade_multiple2 = Number(value) || 1;
608
+ if (key === "_amount_upgrade_value") upgrade_value2 = Number(value) || 0;
609
+ });
610
+ }
611
+ );
512
612
  return [upgrade_multiple2, upgrade_value2];
513
- }, [cart?.lineItems, points_subscribe]);
613
+ }, [effectiveCart?.lineItems, points_subscribe]);
514
614
  const breakpoints = react.useMemo(() => {
515
615
  if (!isActivityAvailable) return [];
516
616
  return (campaign?.breakpoints || []).map((item) => ({
@@ -538,7 +638,7 @@ var useScriptAutoFreeGift = ({
538
638
  }, [giftHandles]);
539
639
  const involvedLines = react.useMemo(() => {
540
640
  if (!isActivityAvailable) return [];
541
- return (cart?.lineItems || []).filter((line) => {
641
+ return (effectiveCart?.lineItems || []).filter((line) => {
542
642
  const isNotGift = line?.totalAmount && Number(line.totalAmount) > 0 && line.customAttributes?.every(
543
643
  (item) => item.key !== _giveaway
544
644
  );
@@ -547,7 +647,7 @@ var useScriptAutoFreeGift = ({
547
647
  );
548
648
  return isNotGift && hasCampaignTag;
549
649
  });
550
- }, [cart?.lineItems, isActivityAvailable, _giveaway]);
650
+ }, [effectiveCart?.lineItems, isActivityAvailable, _giveaway]);
551
651
  const involvedSubTotal = react.useMemo(() => {
552
652
  if (!isActivityAvailable) return new Decimal2__default.default(0);
553
653
  return involvedLines.reduce((prev, item) => {
@@ -573,18 +673,24 @@ var useScriptAutoFreeGift = ({
573
673
  const nextLevel = levelIndex > 0 ? sortedLevels[levelIndex - 1] ?? null : null;
574
674
  return [currentLevel, nextLevel];
575
675
  }, [breakpoints, involvedSubTotal, involvedLines.length]);
576
- const { data: giftProductsResult } = useSWR__default.default(shouldFetch ? giftHandles : null, async () => {
577
- const res = await shopifySdk.getProductsByHandles(client, {
578
- handles: giftHandles,
579
- locale
580
- });
581
- const result = Array.isArray(res) ? res : [];
582
- giftProductsCache.current = {
583
- data: result,
584
- giftHandles: [...giftHandles]
585
- };
586
- return result;
587
- });
676
+ const { data: giftProductsResult } = useSWR__default.default(
677
+ shouldFetch ? giftHandles : null,
678
+ async () => {
679
+ const res = await shopifySdk.getProductsByHandles(client, {
680
+ handles: giftHandles,
681
+ locale
682
+ });
683
+ const result = Array.isArray(res) ? res : [];
684
+ giftProductsCache.current = {
685
+ data: result,
686
+ giftHandles: [...giftHandles]
687
+ };
688
+ return result;
689
+ },
690
+ {
691
+ revalidateOnFocus: false
692
+ }
693
+ );
588
694
  const finalGiftProductsResult = react.useMemo(() => {
589
695
  if (giftProductsCache.current && !shouldFetch) {
590
696
  return giftProductsCache.current.data || void 0;
@@ -847,7 +953,7 @@ function useApplyCartCodes(options) {
847
953
  if (!discountCodes?.length) {
848
954
  throw new Error("Invalid input used for this operation: Miss discountCode");
849
955
  }
850
- const cartId = providedCartId ? void 0 : providedCartId || cart?.id;
956
+ const cartId = providedCartId || cart?.id;
851
957
  if (!cartId) {
852
958
  return void 0;
853
959
  }
@@ -860,6 +966,12 @@ function useApplyCartCodes(options) {
860
966
  cookieAdapter: cartCookieAdapter,
861
967
  metafieldIdentifiers
862
968
  });
969
+ const unApplicableCodes = discountCodes.filter(
970
+ (code) => updatedCart?.discountCodes?.find((item) => item.code === code && !item.applicable)
971
+ );
972
+ if (unApplicableCodes.length) {
973
+ throw new Error(`${unApplicableCodes.join(", ")} is not applicable to the cart`);
974
+ }
863
975
  if (updatedCart) {
864
976
  mutateCart(updatedCart);
865
977
  }
@@ -875,7 +987,7 @@ function useRemoveCartCodes(options) {
875
987
  const removeCodes = react.useCallback(
876
988
  async (_key, { arg }) => {
877
989
  const { cartId: providedCartId, discountCodes } = arg;
878
- const cartId = providedCartId ? void 0 : providedCartId || cart?.id;
990
+ const cartId = providedCartId || cart?.id;
879
991
  const codes = cart?.discountCodes?.filter((code) => !!code.applicable) || [];
880
992
  const leftCodes = codes.filter((code) => discountCodes?.length ? !discountCodes.includes(code.code) : code.code).map((code) => code.code);
881
993
  const updatedCart = await shopifySdk.updateCartCodes(client, {
@@ -897,7 +1009,7 @@ function useRemoveCartCodes(options) {
897
1009
  // src/hooks/cart/use-add-to-cart.ts
898
1010
  function useAddToCart({ withTrack = true } = {}, swrOptions) {
899
1011
  const { client, config, locale, cartCookieAdapter, userAdapter } = useShopify();
900
- const { cart } = useCartContext();
1012
+ const { cart, addCustomAttributes } = useCartContext();
901
1013
  const { trigger: applyCartCodes } = useApplyCartCodes();
902
1014
  const { trigger: removeInvalidCodes } = useRemoveCartCodes();
903
1015
  const { trigger: addCartLines2 } = useAddCartLines();
@@ -911,7 +1023,8 @@ function useAddToCart({ withTrack = true } = {}, swrOptions) {
911
1023
  buyerIdentity,
912
1024
  needCreateCart = false,
913
1025
  onCodesInvalid,
914
- replaceExistingCodes
1026
+ replaceExistingCodes,
1027
+ customAttributes
915
1028
  } = arg;
916
1029
  if (!lineItems || lineItems.length === 0) {
917
1030
  return;
@@ -934,6 +1047,7 @@ function useAddToCart({ withTrack = true } = {}, swrOptions) {
934
1047
  if (!resultCart) {
935
1048
  return void 0;
936
1049
  }
1050
+ console.log("npm addCartLines resultCart", resultCart);
937
1051
  if (resultCart.discountCodes && resultCart.discountCodes.length > 0) {
938
1052
  const unapplicableCodes = resultCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
939
1053
  if (unapplicableCodes.length > 0) {
@@ -955,6 +1069,9 @@ function useAddToCart({ withTrack = true } = {}, swrOptions) {
955
1069
  discountCodes
956
1070
  });
957
1071
  }
1072
+ if (customAttributes && customAttributes.length > 0) {
1073
+ addCustomAttributes(customAttributes);
1074
+ }
958
1075
  if (withTrack) {
959
1076
  trackAddToCartGA({
960
1077
  lineItems,
@@ -1107,6 +1224,60 @@ function useBuyNow({ withTrack = true } = {}, swrOptions) {
1107
1224
  );
1108
1225
  return useSWRMutation__default.default("buy-now", buyNow, swrOptions);
1109
1226
  }
1227
+ function useCalcGiftsFromLines({
1228
+ lines,
1229
+ customer,
1230
+ scriptGiveawayKey = CUSTOMER_SCRIPT_GIFT_KEY
1231
+ }) {
1232
+ const { locale } = useShopify();
1233
+ const { cart, autoFreeGiftConfig, gradientGiftsConfig } = useCartContext();
1234
+ const functionGift = useCalcAutoFreeGift(cart, autoFreeGiftConfig || [], customer, lines);
1235
+ const scriptGift = useScriptAutoFreeGift({
1236
+ campaign: gradientGiftsConfig || null,
1237
+ _giveaway: scriptGiveawayKey,
1238
+ cart,
1239
+ locale,
1240
+ lines
1241
+ });
1242
+ const allGiftLines = react.useMemo(() => {
1243
+ const functionGiftLines = functionGift.qualifyingGift?.itemsToAdd || [];
1244
+ const scriptGiftLines = scriptGift.freeGiftLevel ? scriptGift.freeGiftLevel.giveawayProducts.map((product) => {
1245
+ const giftProduct = scriptGift.giftProductsResult?.find(
1246
+ (p) => p.handle === product.handle
1247
+ );
1248
+ const variant = giftProduct?.variants?.[0];
1249
+ return {
1250
+ variant: {
1251
+ id: variant?.id || "",
1252
+ handle: product.handle,
1253
+ sku: product.sku
1254
+ },
1255
+ quantity: 1,
1256
+ attributes: [
1257
+ {
1258
+ key: scriptGiveawayKey,
1259
+ value: "true"
1260
+ }
1261
+ ]
1262
+ };
1263
+ }).filter((item) => item.variant.id) : [];
1264
+ return [...functionGiftLines, ...scriptGiftLines];
1265
+ }, [
1266
+ functionGift.qualifyingGift,
1267
+ scriptGift.freeGiftLevel,
1268
+ scriptGift.giftProductsResult,
1269
+ scriptGiveawayKey
1270
+ ]);
1271
+ const hasGifts = react.useMemo(() => {
1272
+ return allGiftLines.length > 0;
1273
+ }, [allGiftLines]);
1274
+ return {
1275
+ functionGift,
1276
+ scriptGift,
1277
+ allGiftLines,
1278
+ hasGifts
1279
+ };
1280
+ }
1110
1281
 
1111
1282
  // src/hooks/cart/types/order-discount.ts
1112
1283
  var OrderDiscountType = /* @__PURE__ */ ((OrderDiscountType2) => {
@@ -1157,9 +1328,12 @@ var useCalcOrderDiscount = (cart, orderDiscountConfig, customer) => {
1157
1328
  discountAmount: 0
1158
1329
  };
1159
1330
  }
1160
- const tieredDiscounts = activeCampaign.result_detail.order_discount_conf.tiered_discounts;
1161
- const qualifyingTier = [...tieredDiscounts].reverse().find((tier) => subtotal >= Number(tier.amount));
1162
- const nextGoal = tieredDiscounts.find((tier) => subtotal < Number(tier.amount));
1331
+ const currentCurrency = cart?.currency?.code || "";
1332
+ console.log("currentCurrency", cart, currentCurrency);
1333
+ const orderDiscountConf = activeCampaign.result_detail.order_discount_conf;
1334
+ const tieredDiscounts = orderDiscountConf.tiered_discounts_markets?.[currentCurrency] || orderDiscountConf.tiered_discounts;
1335
+ const qualifyingTier = [...tieredDiscounts].sort((a, b) => Number(b.amount) - Number(a.amount)).find((tier) => subtotal >= Number(tier.amount));
1336
+ const nextGoal = [...tieredDiscounts].sort((a, b) => Number(a.amount) - Number(b.amount)).find((tier) => subtotal < Number(tier.amount));
1163
1337
  if (!qualifyingTier) {
1164
1338
  return {
1165
1339
  qualifyingDiscount: null,
@@ -1227,12 +1401,10 @@ function useHasPlusMemberInCart({
1227
1401
  };
1228
1402
  }, [cart?.lineItems, plus_monthly_product, plus_annual_product]);
1229
1403
  }
1230
-
1231
- // src/hooks/cart/feature/use-cart-attributes.ts
1232
1404
  var getReferralAttributes = () => {
1233
- const inviteCode = Cookies5__default.default.get("invite_code");
1234
- const playModeId = Cookies5__default.default.get("playModeId");
1235
- const popup = Cookies5__default.default.get("_popup");
1405
+ const inviteCode = shopifySdk.getLocalStorage("invite_code") || Cookies5__default.default.get("invite_code");
1406
+ const playModeId = shopifySdk.getLocalStorage("playModeId") || Cookies5__default.default.get("playModeId");
1407
+ const popup = shopifySdk.getLocalStorage("_popup") || Cookies5__default.default.get("_popup");
1236
1408
  if (inviteCode && playModeId) {
1237
1409
  return popup ? [
1238
1410
  { key: "_invite_code", value: inviteCode ? inviteCode : "" },
@@ -1256,8 +1428,6 @@ var useCartAttributes = ({
1256
1428
  memberSetting,
1257
1429
  cart
1258
1430
  });
1259
- console.log("memberSetting", memberSetting);
1260
- console.log("hasPlusMember", hasPlusMember);
1261
1431
  react.useEffect(() => {
1262
1432
  setCurrentUrl(window.location.href);
1263
1433
  }, []);
@@ -1283,7 +1453,7 @@ var useCartAttributes = ({
1283
1453
  return "new_user_login";
1284
1454
  }, [customer]);
1285
1455
  const memberAttributes = react.useMemo(() => {
1286
- return [
1456
+ const attributes = [
1287
1457
  {
1288
1458
  key: "_token",
1289
1459
  value: profile?.token
@@ -1304,17 +1474,28 @@ var useCartAttributes = ({
1304
1474
  value: profile?.token ? "true" : "false"
1305
1475
  }
1306
1476
  ];
1477
+ if (profile?.token) {
1478
+ attributes.push({
1479
+ key: "_login_user",
1480
+ value: "1"
1481
+ });
1482
+ }
1483
+ return attributes;
1307
1484
  }, [profile?.memberType, profile?.token, userType, hasPlusMember]);
1308
1485
  const functionAttributes = react.useMemo(() => {
1309
- return [
1310
- cart?.discountCodes && {
1486
+ const hasFunctionEnvAttribute = cart?.lineItems.some(
1487
+ (item) => item.customAttributes?.some((attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY)
1488
+ );
1489
+ const discountCodes = cart?.discountCodes.map((item) => item.code).filter((code) => code) || [];
1490
+ return hasFunctionEnvAttribute ? [
1491
+ {
1311
1492
  key: "_discounts_function_env",
1312
1493
  value: JSON.stringify({
1313
- discount_code: cart?.discountCodes.map((item) => item.code),
1494
+ discount_code: discountCodes,
1314
1495
  user_tags: customer?.tags || []
1315
1496
  })
1316
1497
  }
1317
- ];
1498
+ ] : [];
1318
1499
  }, [cart]);
1319
1500
  const presellAttributes = react.useMemo(() => {
1320
1501
  return [
@@ -1346,18 +1527,50 @@ var useCartAttributes = ({
1346
1527
  }
1347
1528
  ];
1348
1529
  }, [currentUrl]);
1530
+ const commonAttributes = react.useMemo(
1531
+ () => [
1532
+ ...memberAttributes,
1533
+ ...functionAttributes,
1534
+ ...presellAttributes,
1535
+ ...weightAttributes,
1536
+ ...trackingAttributes,
1537
+ ...getReferralAttributes()
1538
+ ].filter((item) => item?.value),
1539
+ [memberAttributes, functionAttributes, presellAttributes, weightAttributes, trackingAttributes]
1540
+ );
1541
+ const extraAttributesInCart = react.useMemo(() => {
1542
+ const commonAttributeKeys = [
1543
+ // member attributes
1544
+ "_token",
1545
+ "_member_type",
1546
+ "_user_type",
1547
+ "_is_login",
1548
+ "_login_user",
1549
+ // function attributes
1550
+ "_discounts_function_env",
1551
+ // presell attributes
1552
+ "_presale",
1553
+ // weight attributes
1554
+ "_weight",
1555
+ "_app_source_name",
1556
+ // tracking attributes
1557
+ "utm_params",
1558
+ // referral attributes
1559
+ "_invite_code",
1560
+ "_play_mode_id",
1561
+ "_popup"
1562
+ ];
1563
+ return cart?.customAttributes?.filter(
1564
+ (item) => !commonAttributeKeys.includes(item.key)
1565
+ ) || [];
1566
+ }, [cart]);
1349
1567
  return react.useMemo(
1350
1568
  () => ({
1351
- attributes: [
1352
- ...memberAttributes,
1353
- ...functionAttributes,
1354
- ...presellAttributes,
1355
- ...weightAttributes,
1356
- ...trackingAttributes,
1357
- ...getReferralAttributes()
1358
- ].filter((item) => item?.value)
1569
+ attributes: [...commonAttributes, ...extraAttributesInCart].filter(
1570
+ (item) => item?.value
1571
+ )
1359
1572
  }),
1360
- [memberAttributes, functionAttributes, presellAttributes, weightAttributes, trackingAttributes]
1573
+ [commonAttributes, extraAttributesInCart]
1361
1574
  );
1362
1575
  };
1363
1576
  var DEFAULT_MIN = 1;
@@ -1574,8 +1787,9 @@ function useProductsByHandles(options = {}) {
1574
1787
  metafieldIdentifiers
1575
1788
  });
1576
1789
  },
1577
- swrOptions || {
1578
- revalidateOnFocus: false
1790
+ {
1791
+ revalidateOnFocus: false,
1792
+ ...swrOptions
1579
1793
  }
1580
1794
  );
1581
1795
  }
@@ -2491,6 +2705,73 @@ var usePlusMemberDeliveryCodes = ({
2491
2705
  [deliveryData]
2492
2706
  );
2493
2707
  };
2708
+ function useUpdateCartDeliveryOptions(mutate, metafieldIdentifiers, options) {
2709
+ const { client, locale, cartCookieAdapter } = useShopify();
2710
+ const updateDeliveryOptions = react.useCallback(
2711
+ async (_key, { arg }) => {
2712
+ const updatedCart = await shopifySdk.updateCartDeliveryOptions(client, {
2713
+ ...arg,
2714
+ metafieldIdentifiers,
2715
+ cookieAdapter: cartCookieAdapter
2716
+ });
2717
+ console.log("useUpdateCartDeliveryOptions updatedCart", updatedCart);
2718
+ if (updatedCart) {
2719
+ mutate(updatedCart);
2720
+ }
2721
+ return updatedCart;
2722
+ },
2723
+ [client, locale, cartCookieAdapter, mutate]
2724
+ );
2725
+ return useSWRMutation__default.default("update-cart-delivery-options", updateDeliveryOptions, options);
2726
+ }
2727
+
2728
+ // src/hooks/member/plus/use-update-plus-member-delivery-options.ts
2729
+ var useUpdatePlusMemberDeliveryOptions = ({
2730
+ options
2731
+ } = {}) => {
2732
+ const { cart: cartContextData, mutateCart, metafieldIdentifiers } = useCartContext();
2733
+ const { trigger: updateCartDeliveryOptions2 } = useUpdateCartDeliveryOptions(
2734
+ mutateCart,
2735
+ metafieldIdentifiers
2736
+ );
2737
+ const handler = react.useCallback(
2738
+ async (_, { arg }) => {
2739
+ const currentCart = arg?.cart || cartContextData;
2740
+ const { deliveryData } = arg;
2741
+ const firstDeliveryGroup = currentCart?.deliveryGroups?.[0];
2742
+ const deliveryGroupId = firstDeliveryGroup?.id;
2743
+ const selectedOptionCode = deliveryData?.deliveryCustomData?.selected_delivery_option?.code;
2744
+ if (!deliveryGroupId || !selectedOptionCode || selectedOptionCode === firstDeliveryGroup?.selectedDeliveryOption?.code) {
2745
+ return null;
2746
+ }
2747
+ const deliveryGroup = currentCart?.deliveryGroups?.find(
2748
+ (group) => group?.id === deliveryGroupId
2749
+ );
2750
+ const matchedOption = deliveryGroup?.deliveryOptions?.find(
2751
+ (option) => option?.code === selectedOptionCode
2752
+ );
2753
+ if (!matchedOption?.handle) {
2754
+ return null;
2755
+ }
2756
+ const deliveryOptions = [
2757
+ {
2758
+ deliveryGroupId,
2759
+ deliveryOptionHandle: matchedOption.handle
2760
+ }
2761
+ ];
2762
+ const updatedCart = await updateCartDeliveryOptions2({
2763
+ selectedDeliveryOptions: deliveryOptions,
2764
+ cartId: currentCart?.id
2765
+ });
2766
+ if (updatedCart && mutateCart) {
2767
+ mutateCart(updatedCart);
2768
+ }
2769
+ return updatedCart;
2770
+ },
2771
+ [cartContextData, updateCartDeliveryOptions2, mutateCart]
2772
+ );
2773
+ return useSWRMutation__default.default("update-cart-delivery-options", handler, options);
2774
+ };
2494
2775
  var usePlusMemberItemCustomAttributes = ({
2495
2776
  deliveryData
2496
2777
  }) => {
@@ -2510,48 +2791,18 @@ var usePlusMemberCheckoutCustomAttributes = ({
2510
2791
  deliveryData,
2511
2792
  product,
2512
2793
  variant,
2513
- customer,
2514
2794
  isShowShippingBenefits
2515
2795
  }) => {
2516
2796
  const { deliveryCustomData } = deliveryData || {};
2517
2797
  const { profile } = usePlusMemberContext();
2518
- const userType = react.useMemo(() => {
2519
- const customerInfo = customer;
2520
- if (!customerInfo) {
2521
- return "new_user_unlogin";
2522
- }
2523
- if (customer) {
2524
- const { orders = {} } = customer;
2525
- const edgesLength = orders?.edges?.length;
2526
- if (edgesLength === 1) {
2527
- return "old_user_orders_once";
2528
- } else if (edgesLength && edgesLength > 1) {
2529
- return "old_user_orders_twice";
2530
- }
2531
- }
2532
- return "new_user_login";
2533
- }, [customer]);
2534
2798
  return react.useMemo(() => {
2535
2799
  const checkoutCustomAttributes = [
2536
- {
2537
- key: "_token",
2538
- value: profile?.token || ""
2539
- },
2800
+ // _last_url: 付费会员结算完成之后 checkout 有一个继续购买的按钮, 用于跳转到继续购买的页面
2540
2801
  {
2541
2802
  key: "_last_url",
2542
2803
  value: typeof window !== "undefined" ? window.location.origin + window.location.pathname : ""
2543
- },
2544
- {
2545
- key: "_user_type",
2546
- value: userType
2547
2804
  }
2548
2805
  ];
2549
- if (profile) {
2550
- checkoutCustomAttributes.push({
2551
- key: "_login_user",
2552
- value: "1"
2553
- });
2554
- }
2555
2806
  if (deliveryCustomData) {
2556
2807
  checkoutCustomAttributes.push({
2557
2808
  key: "_checkout_delivery_custom",
@@ -2561,12 +2812,6 @@ var usePlusMemberCheckoutCustomAttributes = ({
2561
2812
  })
2562
2813
  });
2563
2814
  }
2564
- if (variant?.metafields?.presell) {
2565
- checkoutCustomAttributes.push({
2566
- key: "_presale",
2567
- value: "true"
2568
- });
2569
- }
2570
2815
  if (isShowShippingBenefits && !isShowShippingBenefits({ variant, product, setting: {} })) {
2571
2816
  checkoutCustomAttributes.push({
2572
2817
  key: "_hide_shipping",
@@ -2574,18 +2819,17 @@ var usePlusMemberCheckoutCustomAttributes = ({
2574
2819
  });
2575
2820
  }
2576
2821
  return checkoutCustomAttributes;
2577
- }, [deliveryCustomData, product, profile, userType, variant, isShowShippingBenefits]);
2822
+ }, [deliveryCustomData, product, profile, variant, isShowShippingBenefits]);
2578
2823
  };
2579
2824
  function useAutoRemovePlusMemberInCart({
2580
- metafields,
2581
- isMonthlyPlus,
2582
- isAnnualPlus
2825
+ cart,
2826
+ profile,
2827
+ memberSetting
2583
2828
  }) {
2584
- const { plus_monthly_product, plus_annual_product } = metafields || {};
2585
- const { cart } = useCartContext();
2829
+ const { plus_monthly_product, plus_annual_product } = memberSetting || {};
2586
2830
  const { trigger: removeCartLines2 } = useRemoveCartLines();
2587
2831
  react.useEffect(() => {
2588
- if (!cart) return;
2832
+ if (!cart || !plus_monthly_product || !plus_annual_product) return;
2589
2833
  const removePlusProduct = async (productType) => {
2590
2834
  if (!productType) return;
2591
2835
  const product = cart.lineItems?.find(
@@ -2597,33 +2841,25 @@ function useAutoRemovePlusMemberInCart({
2597
2841
  });
2598
2842
  }
2599
2843
  };
2600
- if (isMonthlyPlus) {
2844
+ if (profile?.isMonthlyPlus) {
2601
2845
  removePlusProduct(plus_monthly_product);
2602
2846
  }
2603
- if (isAnnualPlus) {
2847
+ if (profile?.isAnnualPlus) {
2604
2848
  removePlusProduct(plus_annual_product);
2605
2849
  }
2606
- }, [
2607
- cart,
2608
- plus_annual_product,
2609
- plus_monthly_product,
2610
- isAnnualPlus,
2611
- isMonthlyPlus,
2612
- removeCartLines2
2613
- ]);
2850
+ }, [cart, plus_annual_product, plus_monthly_product, profile, removeCartLines2]);
2614
2851
  }
2615
2852
  function useAddPlusMemberProductsToCart({
2616
2853
  cart,
2617
- memberSetting,
2618
- selectedPlusMemberMode,
2619
- selectedPlusMemberProduct
2854
+ profile
2620
2855
  }) {
2856
+ const { selectedPlusMemberMode, selectedPlusMemberProduct, plusMemberMetafields } = usePlusMemberContext();
2621
2857
  const { hasMonthlyPlus, hasAnnualPlus } = useHasPlusMemberInCart({
2622
- cart,
2623
- memberSetting
2858
+ memberSetting: plusMemberMetafields,
2859
+ cart
2624
2860
  });
2625
2861
  const plusMemberProduct = react.useMemo(() => {
2626
- if (selectedPlusMemberMode === "free" /* FREE */) {
2862
+ if (!selectedPlusMemberProduct || selectedPlusMemberMode === "free" /* FREE */) {
2627
2863
  return void 0;
2628
2864
  }
2629
2865
  if (selectedPlusMemberMode === "monthly" /* MONTHLY */ && hasMonthlyPlus) {
@@ -2632,7 +2868,10 @@ function useAddPlusMemberProductsToCart({
2632
2868
  if (selectedPlusMemberMode === "annual" /* ANNUAL */ && hasAnnualPlus) {
2633
2869
  return void 0;
2634
2870
  }
2635
- if (!selectedPlusMemberProduct) {
2871
+ if (profile?.isMonthlyPlus && selectedPlusMemberMode === "monthly" /* MONTHLY */) {
2872
+ return void 0;
2873
+ }
2874
+ if (profile?.isAnnualPlus && selectedPlusMemberMode === "annual" /* ANNUAL */) {
2636
2875
  return void 0;
2637
2876
  }
2638
2877
  return selectedPlusMemberProduct;
@@ -2951,8 +3190,13 @@ function CartProvider({
2951
3190
  const { attributes } = useCartAttributes({ profile, customer, cart, memberSetting });
2952
3191
  ahooks.useRequest(
2953
3192
  () => {
2954
- const newAttributes = [...attributes, ...customAttributes];
2955
- const needUpdate = cart && !checkAttributesUpdateNeeded(
3193
+ const newAttributes = [...attributes];
3194
+ customAttributes.forEach((item) => {
3195
+ if (item.value && !newAttributes.some((attr) => attr.key === item.key)) {
3196
+ newAttributes.push(item);
3197
+ }
3198
+ });
3199
+ const needUpdate = cart && checkAttributesUpdateNeeded(
2956
3200
  cart.customAttributes,
2957
3201
  newAttributes,
2958
3202
  customAttributesNeedDelete
@@ -3056,8 +3300,14 @@ function CartProvider({
3056
3300
  );
3057
3301
  return result;
3058
3302
  }, [cart?.lineItems, scriptAutoFreeGift, functionAutoFreeGift]);
3303
+ const totalQuantity = react.useMemo(() => {
3304
+ const cartLinesCount = cart?.lineItems.reduce((acc, item) => acc + item.quantity, 0) || 0;
3305
+ const giftLinesCount = giftNeedAddToCartLines?.reduce((acc, item) => acc + (item.quantity || 1), 0) || 0;
3306
+ return cartLinesCount + giftLinesCount;
3307
+ }, [cart?.lineItems, giftNeedAddToCartLines]);
3059
3308
  const value = react.useMemo(
3060
3309
  () => ({
3310
+ totalQuantity,
3061
3311
  cart,
3062
3312
  isCartLoading,
3063
3313
  triggerFetch: fetchCart,
@@ -3069,6 +3319,7 @@ function CartProvider({
3069
3319
  isCodeChanging,
3070
3320
  setIsCodeChanging,
3071
3321
  autoFreeGiftConfig,
3322
+ gradientGiftsConfig,
3072
3323
  setLoadingState,
3073
3324
  loadingState,
3074
3325
  // function满赠
@@ -3084,6 +3335,7 @@ function CartProvider({
3084
3335
  }),
3085
3336
  [
3086
3337
  cart,
3338
+ totalQuantity,
3087
3339
  isCartLoading,
3088
3340
  fetchCart,
3089
3341
  mutateCart,
@@ -3092,6 +3344,7 @@ function CartProvider({
3092
3344
  locale,
3093
3345
  isCodeChanging,
3094
3346
  autoFreeGiftConfig,
3347
+ gradientGiftsConfig,
3095
3348
  loadingState,
3096
3349
  // function满赠
3097
3350
  functionAutoFreeGift,
@@ -3115,30 +3368,6 @@ function useCartContext() {
3115
3368
  return context;
3116
3369
  }
3117
3370
 
3118
- Object.defineProperty(exports, "ShopifyConfig", {
3119
- enumerable: true,
3120
- get: function () { return shopifySdk.ShopifyConfig; }
3121
- });
3122
- Object.defineProperty(exports, "clearLocalStorage", {
3123
- enumerable: true,
3124
- get: function () { return shopifySdk.clearLocalStorage; }
3125
- });
3126
- Object.defineProperty(exports, "createShopifyClient", {
3127
- enumerable: true,
3128
- get: function () { return shopifySdk.createShopifyClient; }
3129
- });
3130
- Object.defineProperty(exports, "getLocalStorage", {
3131
- enumerable: true,
3132
- get: function () { return shopifySdk.getLocalStorage; }
3133
- });
3134
- Object.defineProperty(exports, "removeLocalStorage", {
3135
- enumerable: true,
3136
- get: function () { return shopifySdk.removeLocalStorage; }
3137
- });
3138
- Object.defineProperty(exports, "setLocalStorage", {
3139
- enumerable: true,
3140
- get: function () { return shopifySdk.setLocalStorage; }
3141
- });
3142
3371
  exports.BuyRuleType = BuyRuleType;
3143
3372
  exports.CODE_AMOUNT_KEY = CODE_AMOUNT_KEY;
3144
3373
  exports.CUSTOMER_ATTRIBUTE_KEY = CUSTOMER_ATTRIBUTE_KEY;
@@ -3160,12 +3389,11 @@ exports.ShippingMethodMode = ShippingMethodMode;
3160
3389
  exports.ShopifyContext = ShopifyContext;
3161
3390
  exports.ShopifyProvider = ShopifyProvider;
3162
3391
  exports.SpendMoneyType = SpendMoneyType;
3163
- exports.atobID = atobID;
3164
3392
  exports.browserCartCookieAdapter = browserCartCookieAdapter;
3165
3393
  exports.browserCookieAdapter = browserCookieAdapter;
3166
- exports.btoaID = btoaID;
3167
3394
  exports.checkAttributesUpdateNeeded = checkAttributesUpdateNeeded;
3168
3395
  exports.clearGeoLocationCache = clearGeoLocationCache;
3396
+ exports.createMockCartFromLines = createMockCartFromLines;
3169
3397
  exports.currencyCodeMapping = currencyCodeMapping;
3170
3398
  exports.defaultSWRMutationConfiguration = defaultSWRMutationConfiguration;
3171
3399
  exports.formatFunctionAutoFreeGift = formatFunctionAutoFreeGift;
@@ -3176,6 +3404,7 @@ exports.getDiscountEnvAttributeValue = getDiscountEnvAttributeValue;
3176
3404
  exports.getMatchedMainProductSubTotal = getMatchedMainProductSubTotal;
3177
3405
  exports.getQuery = getQuery;
3178
3406
  exports.getReferralAttributes = getReferralAttributes;
3407
+ exports.normalizeAddToCartLines = normalizeAddToCartLines;
3179
3408
  exports.preCheck = preCheck;
3180
3409
  exports.safeParse = safeParse;
3181
3410
  exports.trackAddToCartFBQ = trackAddToCartFBQ;
@@ -3197,6 +3426,7 @@ exports.useAutoRemovePlusMemberInCart = useAutoRemovePlusMemberInCart;
3197
3426
  exports.useBlog = useBlog;
3198
3427
  exports.useBuyNow = useBuyNow;
3199
3428
  exports.useCalcAutoFreeGift = useCalcAutoFreeGift;
3429
+ exports.useCalcGiftsFromLines = useCalcGiftsFromLines;
3200
3430
  exports.useCalcOrderDiscount = useCalcOrderDiscount;
3201
3431
  exports.useCartAttributes = useCartAttributes;
3202
3432
  exports.useCartContext = useCartContext;
@@ -3231,8 +3461,15 @@ exports.useSite = useSite;
3231
3461
  exports.useUpdateCartAttributes = useUpdateCartAttributes;
3232
3462
  exports.useUpdateCartLines = useUpdateCartLines;
3233
3463
  exports.useUpdateLineCodeAmountAttributes = useUpdateLineCodeAmountAttributes;
3464
+ exports.useUpdatePlusMemberDeliveryOptions = useUpdatePlusMemberDeliveryOptions;
3234
3465
  exports.useUpdateVariantQuery = useUpdateVariantQuery;
3235
3466
  exports.useVariant = useVariant;
3236
3467
  exports.useVariantMedia = useVariantMedia;
3468
+ Object.keys(shopifySdk).forEach(function (k) {
3469
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
3470
+ enumerable: true,
3471
+ get: function () { return shopifySdk[k]; }
3472
+ });
3473
+ });
3237
3474
  //# sourceMappingURL=index.js.map
3238
3475
  //# sourceMappingURL=index.js.map