@anker-in/shopify-react 0.1.1-beta.9 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,6 +6,7 @@ var shopifySdk = require('@anker-in/shopify-sdk');
6
6
  var Cookies5 = require('js-cookie');
7
7
  var jsxRuntime = require('react/jsx-runtime');
8
8
  var Decimal2 = require('decimal.js');
9
+ var shopifyCore = require('@anker-in/shopify-core');
9
10
  var useSWR = require('swr');
10
11
  var ahooks = require('ahooks');
11
12
 
@@ -69,6 +70,7 @@ var CUSTOMER_ATTRIBUTE_KEY = "_discounts_function_env";
69
70
  var CUSTOMER_SCRIPT_GIFT_KEY = "_giveaway_gradient_gifts";
70
71
  var CODE_AMOUNT_KEY = "_sku_code_money";
71
72
  var SCRIPT_CODE_AMOUNT_KEY = "_code_money";
73
+ var MEMBER_PRICE_ATTRIBUTE_KEY = "_member_price";
72
74
  var MAIN_PRODUCT_CODE = ["WS24", "WSTD", "WS7D", "WSCP", "WSPE", "WSPD"];
73
75
 
74
76
  // src/hooks/cart/utils/normalize-add-to-cart-lines.ts
@@ -77,9 +79,10 @@ function normalizeAddToCartLines(lines) {
77
79
  const variant = line.variant;
78
80
  const product = variant.product;
79
81
  const quantity = line.quantity || 1;
80
- const price = variant.finalPrice?.amount ? Number(variant.finalPrice.amount) : variant.compareAtPrice?.amount ? Number(variant.compareAtPrice.amount) : variant.price?.amount ? Number(variant.price.amount) : 0;
81
- const subtotalAmount = price * quantity;
82
- const totalAmount = subtotalAmount;
82
+ const originalPrice = variant.price?.amount ? Number(variant.price.amount) : 0;
83
+ const finalPrice = variant.finalPrice?.amount === void 0 ? originalPrice : Number(variant.finalPrice?.amount);
84
+ const subtotalAmount = originalPrice * quantity;
85
+ const totalAmount = finalPrice * quantity;
83
86
  return {
84
87
  id: `temp-line-${index}-${variant.id}`,
85
88
  // Temporary ID for pre-cart lines
@@ -93,7 +96,7 @@ function normalizeAddToCartLines(lines) {
93
96
  customAttributes: line.attributes || [],
94
97
  variant: {
95
98
  id: variant.id,
96
- price,
99
+ price: finalPrice,
97
100
  listPrice: variant.compareAtPrice?.amount ? Number(variant.compareAtPrice.amount) : 0,
98
101
  sku: variant.sku || "",
99
102
  name: variant.title || "",
@@ -124,12 +127,13 @@ function createMockCartFromLines(lines, existingCart) {
124
127
  const normalizedLines = normalizeAddToCartLines(lines);
125
128
  const subtotalPrice = normalizedLines.reduce((sum, line) => sum + line.subtotalAmount, 0);
126
129
  const totalPrice = normalizedLines.reduce((sum, line) => sum + line.totalAmount, 0);
130
+ const currency = lines[0]?.variant?.price?.currencyCode;
127
131
  return {
128
132
  id: existingCart?.id || "temp-cart-id",
129
133
  customerId: existingCart?.customerId,
130
134
  email: existingCart?.email,
131
135
  createdAt: existingCart?.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
132
- currency: existingCart?.currency || { code: "USD" },
136
+ currency: existingCart?.currency || { code: currency },
133
137
  taxesIncluded: existingCart?.taxesIncluded,
134
138
  lineItems: normalizedLines,
135
139
  totalLineItemsDiscount: 0,
@@ -163,22 +167,12 @@ var getQuery = () => {
163
167
  }
164
168
  return theRequest;
165
169
  };
166
- function atobID(id) {
167
- if (id && typeof id === "string" && id.includes("/")) {
168
- return id.split("/").pop()?.split("?")?.shift();
169
- } else {
170
- return id;
171
- }
172
- }
173
- function btoaID(id, type = "ProductVariant") {
174
- return `gid://shopify/${type}/${id}`;
175
- }
176
170
  var getMatchedMainProductSubTotal = (cartData, variant_list, main_product) => {
177
171
  const isAllStoreVariant = main_product?.all_store_variant ?? false;
178
172
  const matchedList = cartData?.lineItems?.filter((line) => {
179
173
  const { is_gift } = getDiscountEnvAttributeValue(line.customAttributes);
180
174
  return isAllStoreVariant ? !is_gift : variant_list?.find((item) => {
181
- return !is_gift && atobID(line.variantId) === item;
175
+ return !is_gift && shopifyCore.atobID(line.variantId) === item;
182
176
  });
183
177
  });
184
178
  return matchedList?.reduce((acc, line) => {
@@ -196,14 +190,6 @@ var getDiscountEnvAttributeValue = (attributes = []) => {
196
190
  const attr = attributes.find((attr2) => attr2.key === CUSTOMER_ATTRIBUTE_KEY);
197
191
  return safeParse(attr?.value ?? "") ?? {};
198
192
  };
199
- var checkAttributesUpdateNeeded = (oldAttributes, newAttributes, customAttributesNeedRemove) => {
200
- return oldAttributes.some((attr) => {
201
- const newAttr = newAttributes.find((newAttr2) => newAttr2.key === attr.key);
202
- return newAttr ? newAttr.value !== attr.value : true;
203
- }) || newAttributes.some((attr) => !oldAttributes.some((oldAttr) => oldAttr.key === attr.key)) || customAttributesNeedRemove.some(
204
- (removeAttr) => oldAttributes.some((oldAttr) => oldAttr.key === removeAttr.key)
205
- );
206
- };
207
193
  var containsAll = (source, requiredItems = []) => {
208
194
  if (!requiredItems?.length) return true;
209
195
  const sourceSet = new Set(source);
@@ -404,43 +390,29 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
404
390
  }
405
391
  return { activeCampaign: null, subtotal: 0 };
406
392
  }, [autoFreeGiftConfig, effectiveCart, tags, dealsType]);
407
- const { qualifyingGift, nextTierGoal } = react.useMemo(() => {
393
+ const { qualifyingTier, nextTierGoal, actualThreshold, currentCurrency } = react.useMemo(() => {
408
394
  if (!activeCampaign || !activeCampaign.rule_result?.spend_get_reward?.gift_product) {
409
- return { qualifyingGift: null, nextTierGoal: null };
395
+ return { qualifyingTier: null, nextTierGoal: null, actualThreshold: 0, currentCurrency: "" };
410
396
  }
411
397
  const giftTiers = activeCampaign.rule_result.spend_get_reward.gift_product;
412
- const qualifyingTier = [...giftTiers].sort((a, b) => Number(b.spend_sum_money) - Number(a.spend_sum_money)).find((tier) => subtotal >= Number(tier.spend_sum_money));
413
- const nextGoal = giftTiers.find((tier) => subtotal < Number(tier.spend_sum_money));
414
- if (!qualifyingTier) {
415
- return { qualifyingGift: null, nextTierGoal: nextGoal || null };
416
- }
417
- const formattedGift = {
418
- tier: qualifyingTier,
419
- itemsToAdd: qualifyingTier.reward_list?.map((reward) => {
420
- const giftProduct = reward?.variant_list?.[0];
421
- if (!giftProduct) return null;
422
- return {
423
- variant: {
424
- id: btoaID(giftProduct.variant_id),
425
- handle: giftProduct.handle,
426
- sku: giftProduct.sku
427
- },
428
- quantity: reward?.get_unit || 1,
429
- attributes: [
430
- {
431
- key: CUSTOMER_ATTRIBUTE_KEY,
432
- value: JSON.stringify({
433
- is_gift: true,
434
- rule_id: activeCampaign.rule_id,
435
- spend_sum_money: qualifyingTier.spend_sum_money
436
- })
437
- }
438
- ]
439
- };
440
- }).filter((item) => item !== null)
398
+ const currentCurrency2 = effectiveCart?.currency?.code || "";
399
+ console.log("currentCurrency useCalcAutoFreeGift", effectiveCart, currentCurrency2);
400
+ const getThresholdAmount = (tier) => {
401
+ if (tier.spend_sum_money_multi_markets?.[currentCurrency2]?.value) {
402
+ return Number(tier.spend_sum_money_multi_markets[currentCurrency2].value);
403
+ }
404
+ return Number(tier.spend_sum_money || 0);
441
405
  };
442
- return { qualifyingGift: formattedGift, nextTierGoal: nextGoal || null };
443
- }, [activeCampaign, subtotal]);
406
+ const qualifyingTier2 = [...giftTiers].sort((a, b) => getThresholdAmount(b) - getThresholdAmount(a)).find((tier) => subtotal >= getThresholdAmount(tier));
407
+ const nextGoal = giftTiers.find((tier) => subtotal < getThresholdAmount(tier));
408
+ const actualThreshold2 = qualifyingTier2 ? getThresholdAmount(qualifyingTier2) : 0;
409
+ return {
410
+ qualifyingTier: qualifyingTier2,
411
+ nextTierGoal: nextGoal || null,
412
+ actualThreshold: actualThreshold2,
413
+ currentCurrency: currentCurrency2
414
+ };
415
+ }, [activeCampaign, subtotal, effectiveCart]);
444
416
  const giftHandles = react.useMemo(() => {
445
417
  const giftVariant = autoFreeGiftConfig.map(
446
418
  (item) => item.rule_result?.spend_get_reward?.gift_product?.map(
@@ -456,24 +428,82 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
456
428
  }
457
429
  return true;
458
430
  }, [giftHandles]);
459
- const { data: giftProductsResult } = useSWR__default.default(shouldFetch ? giftHandles : null, async () => {
460
- const res = await shopifySdk.getProductsByHandles(client, {
461
- handles: giftHandles,
462
- locale
463
- });
464
- const result = Array.isArray(res) ? res : [];
465
- giftProductsCache.current = {
466
- data: result,
467
- giftHandles: [...giftHandles]
468
- };
469
- return result;
470
- });
431
+ const { data: giftProductsResult } = useSWR__default.default(
432
+ shouldFetch ? giftHandles : null,
433
+ async () => {
434
+ const res = await shopifySdk.getProductsByHandles(client, {
435
+ handles: giftHandles,
436
+ locale
437
+ });
438
+ const result = Array.isArray(res) ? res : [];
439
+ giftProductsCache.current = {
440
+ data: result,
441
+ giftHandles: [...giftHandles]
442
+ };
443
+ return result;
444
+ },
445
+ {
446
+ revalidateOnFocus: false
447
+ }
448
+ );
471
449
  const finalGiftProductsResult = react.useMemo(() => {
472
450
  if (giftProductsCache.current && !shouldFetch) {
473
451
  return giftProductsCache.current.data || void 0;
474
452
  }
475
453
  return giftProductsResult;
476
454
  }, [giftProductsResult, shouldFetch]);
455
+ const qualifyingGift = react.useMemo(() => {
456
+ if (!qualifyingTier || !activeCampaign) {
457
+ return null;
458
+ }
459
+ const itemsToAdd = qualifyingTier.reward_list?.map((reward) => {
460
+ if (!reward.variant_list || reward.variant_list.length === 0) {
461
+ return null;
462
+ }
463
+ let selectedGiftProduct = null;
464
+ for (const giftVariant of reward.variant_list) {
465
+ const productInfo = finalGiftProductsResult?.find(
466
+ (p) => p.handle === giftVariant.handle
467
+ );
468
+ if (productInfo) {
469
+ const variantInfo = productInfo.variants?.find((v) => v.sku === giftVariant.sku);
470
+ if (variantInfo?.availableForSale) {
471
+ selectedGiftProduct = giftVariant;
472
+ break;
473
+ }
474
+ }
475
+ }
476
+ if (!selectedGiftProduct) {
477
+ selectedGiftProduct = reward.variant_list[0];
478
+ }
479
+ return {
480
+ variant: {
481
+ id: shopifyCore.btoaID(selectedGiftProduct.variant_id),
482
+ handle: selectedGiftProduct.handle,
483
+ sku: selectedGiftProduct.sku
484
+ },
485
+ quantity: reward?.get_unit || 1,
486
+ attributes: [
487
+ {
488
+ key: CUSTOMER_ATTRIBUTE_KEY,
489
+ value: JSON.stringify({
490
+ is_gift: true,
491
+ rule_id: activeCampaign.rule_id,
492
+ spend_sum_money: actualThreshold,
493
+ // 使用实际的门槛金额(多币种支持)
494
+ currency_code: currentCurrency
495
+ // 记录当前币种
496
+ })
497
+ }
498
+ ]
499
+ };
500
+ }).filter((item) => item !== null);
501
+ const formattedGift = {
502
+ tier: qualifyingTier,
503
+ itemsToAdd
504
+ };
505
+ return formattedGift;
506
+ }, [qualifyingTier, activeCampaign, finalGiftProductsResult, actualThreshold, currentCurrency]);
477
507
  return {
478
508
  qualifyingGift,
479
509
  nextTierGoal,
@@ -487,7 +517,8 @@ var useScriptAutoFreeGift = ({
487
517
  _giveaway,
488
518
  cart,
489
519
  locale: providedLocale,
490
- lines
520
+ lines,
521
+ profile
491
522
  }) => {
492
523
  const { client, locale: contextLocale } = useShopify();
493
524
  const locale = providedLocale || contextLocale;
@@ -511,8 +542,9 @@ var useScriptAutoFreeGift = ({
511
542
  const utmCampaign = Cookies5__default.default.get("utm_campaign") || query?.utm_campaign;
512
543
  if (campaign.activityAvailableQuery && !utmCampaign?.includes(campaign.activityAvailableQuery))
513
544
  return false;
545
+ if (campaign.requireLogin && !profile?.email) return false;
514
546
  return true;
515
- }, [campaign]);
547
+ }, [campaign, profile]);
516
548
  const [upgrade_multiple, upgrade_value] = react.useMemo(() => {
517
549
  let upgrade_multiple2 = 1;
518
550
  let upgrade_value2 = 0;
@@ -520,12 +552,14 @@ var useScriptAutoFreeGift = ({
520
552
  upgrade_multiple2 = 1.2;
521
553
  upgrade_value2 = 40;
522
554
  }
523
- effectiveCart?.lineItems?.forEach(({ customAttributes }) => {
524
- customAttributes?.forEach(({ key, value }) => {
525
- if (key === "_amount_upgrade_multiple") upgrade_multiple2 = Number(value) || 1;
526
- if (key === "_amount_upgrade_value") upgrade_value2 = Number(value) || 0;
527
- });
528
- });
555
+ effectiveCart?.lineItems?.forEach(
556
+ ({ customAttributes }) => {
557
+ customAttributes?.forEach(({ key, value }) => {
558
+ if (key === "_amount_upgrade_multiple") upgrade_multiple2 = Number(value) || 1;
559
+ if (key === "_amount_upgrade_value") upgrade_value2 = Number(value) || 0;
560
+ });
561
+ }
562
+ );
529
563
  return [upgrade_multiple2, upgrade_value2];
530
564
  }, [effectiveCart?.lineItems, points_subscribe]);
531
565
  const breakpoints = react.useMemo(() => {
@@ -590,18 +624,24 @@ var useScriptAutoFreeGift = ({
590
624
  const nextLevel = levelIndex > 0 ? sortedLevels[levelIndex - 1] ?? null : null;
591
625
  return [currentLevel, nextLevel];
592
626
  }, [breakpoints, involvedSubTotal, involvedLines.length]);
593
- const { data: giftProductsResult } = useSWR__default.default(shouldFetch ? giftHandles : null, async () => {
594
- const res = await shopifySdk.getProductsByHandles(client, {
595
- handles: giftHandles,
596
- locale
597
- });
598
- const result = Array.isArray(res) ? res : [];
599
- giftProductsCache.current = {
600
- data: result,
601
- giftHandles: [...giftHandles]
602
- };
603
- return result;
604
- });
627
+ const { data: giftProductsResult } = useSWR__default.default(
628
+ shouldFetch ? giftHandles : null,
629
+ async () => {
630
+ const res = await shopifySdk.getProductsByHandles(client, {
631
+ handles: giftHandles,
632
+ locale
633
+ });
634
+ const result = Array.isArray(res) ? res : [];
635
+ giftProductsCache.current = {
636
+ data: result,
637
+ giftHandles: [...giftHandles]
638
+ };
639
+ return result;
640
+ },
641
+ {
642
+ revalidateOnFocus: false
643
+ }
644
+ );
605
645
  const finalGiftProductsResult = react.useMemo(() => {
606
646
  if (giftProductsCache.current && !shouldFetch) {
607
647
  return giftProductsCache.current.data || void 0;
@@ -634,16 +674,19 @@ var useScriptAutoFreeGift = ({
634
674
  };
635
675
  };
636
676
  var CartContext = react.createContext(null);
637
- function useCartContext() {
677
+ function useCartContext(options) {
638
678
  const context = react.useContext(CartContext);
639
- if (!context) {
679
+ if (!context && true) {
640
680
  throw new Error("useCartContext must be used within a CartProvider");
641
681
  }
642
682
  return context;
643
683
  }
644
684
 
645
685
  // src/hooks/cart/use-create-cart.ts
646
- function useCreateCart(options) {
686
+ function useCreateCart({
687
+ updateCookie = false,
688
+ options
689
+ }) {
647
690
  const { client, locale, cartCookieAdapter } = useShopify();
648
691
  const { mutateCart, metafieldIdentifiers } = useCartContext();
649
692
  const createNewCart = react.useCallback(
@@ -651,7 +694,8 @@ function useCreateCart(options) {
651
694
  let newCart = await shopifySdk.createCart(client, {
652
695
  ...arg,
653
696
  metafieldIdentifiers,
654
- cookieAdapter: cartCookieAdapter
697
+ cookieAdapter: cartCookieAdapter,
698
+ updateCookie
655
699
  });
656
700
  if (newCart) {
657
701
  const unApplicableCodes = newCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
@@ -678,11 +722,23 @@ function useAddCartLines(options) {
678
722
  const { mutateCart, metafieldIdentifiers } = useCartContext();
679
723
  const addLines = react.useCallback(
680
724
  async (_key, { arg }) => {
681
- let updatedCart = await shopifySdk.addCartLines(client, {
682
- ...arg,
683
- metafieldIdentifiers,
684
- cookieAdapter: cartCookieAdapter
685
- });
725
+ const { cartId, lines } = arg;
726
+ const id = cartId || cartCookieAdapter?.getCartId(locale);
727
+ let updatedCart;
728
+ if (!id) {
729
+ updatedCart = await shopifySdk.createCart(client, {
730
+ lines,
731
+ metafieldIdentifiers,
732
+ cookieAdapter: cartCookieAdapter
733
+ });
734
+ } else {
735
+ updatedCart = await shopifySdk.addCartLines(client, {
736
+ cartId: id,
737
+ lines,
738
+ metafieldIdentifiers,
739
+ cookieAdapter: cartCookieAdapter
740
+ });
741
+ }
686
742
  if (updatedCart) {
687
743
  const unApplicableCodes = updatedCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
688
744
  if (unApplicableCodes.length > 0) {
@@ -729,7 +785,7 @@ var trackAddToCartGA = ({
729
785
  const currencyCode = variant.product?.price?.currencyCode;
730
786
  const totalPrice = lineItems?.reduce(
731
787
  (prev, { variant: variant2 }) => prev.plus(
732
- variant2?.finalPrice?.amount ?? variant2?.compareAtPrice?.amount ?? variant2?.price?.amount ?? 0
788
+ variant2?.finalPrice?.amount === void 0 ? Number(variant2?.price?.amount) || 0 : Number(variant2?.finalPrice?.amount) || 0
733
789
  ),
734
790
  new Decimal2__default.default(0)
735
791
  ).toNumber();
@@ -762,10 +818,10 @@ var trackBuyNowGA = ({
762
818
  return;
763
819
  }
764
820
  const { variant } = lineItems[0];
765
- const currencyCode = variant.price?.currencyCode;
821
+ const currencyCode = variant.product?.price?.currencyCode || variant.price?.currencyCode;
766
822
  const totalPrice = lineItems?.reduce(
767
823
  (prev, { variant: variant2 }) => prev.plus(
768
- variant2?.finalPrice?.amount ?? variant2?.compareAtPrice?.amount ?? (variant2?.price?.amount || 0)
824
+ variant2?.finalPrice?.amount === void 0 ? Number(variant2?.price?.amount) || 0 : Number(variant2?.finalPrice?.amount) || 0
769
825
  ),
770
826
  new Decimal2__default.default(0)
771
827
  ).toNumber();
@@ -839,7 +895,7 @@ function useApplyCartCodes(options) {
839
895
  if (!discountCodes?.length) {
840
896
  throw new Error("Invalid input used for this operation: Miss discountCode");
841
897
  }
842
- const cartId = providedCartId ? void 0 : providedCartId || cart?.id;
898
+ const cartId = providedCartId || cart?.id;
843
899
  if (!cartId) {
844
900
  return void 0;
845
901
  }
@@ -852,12 +908,18 @@ function useApplyCartCodes(options) {
852
908
  cookieAdapter: cartCookieAdapter,
853
909
  metafieldIdentifiers
854
910
  });
911
+ const unApplicableCodes = discountCodes.filter(
912
+ (code) => updatedCart?.discountCodes?.find((item) => item.code === code && !item.applicable)
913
+ );
914
+ if (unApplicableCodes.length) {
915
+ throw new Error(`${unApplicableCodes.join(", ")} is not applicable to the cart`);
916
+ }
855
917
  if (updatedCart) {
856
918
  mutateCart(updatedCart);
857
919
  }
858
920
  return updatedCart;
859
921
  },
860
- [client, locale, cartCookieAdapter, mutateCart, cart]
922
+ [client, locale, cartCookieAdapter, mutateCart, cart, metafieldIdentifiers]
861
923
  );
862
924
  return useSWRMutation__default.default("apply-codes", applyCodes, options);
863
925
  }
@@ -867,7 +929,7 @@ function useRemoveCartCodes(options) {
867
929
  const removeCodes = react.useCallback(
868
930
  async (_key, { arg }) => {
869
931
  const { cartId: providedCartId, discountCodes } = arg;
870
- const cartId = providedCartId ? void 0 : providedCartId || cart?.id;
932
+ const cartId = providedCartId || cart?.id;
871
933
  const codes = cart?.discountCodes?.filter((code) => !!code.applicable) || [];
872
934
  const leftCodes = codes.filter((code) => discountCodes?.length ? !discountCodes.includes(code.code) : code.code).map((code) => code.code);
873
935
  const updatedCart = await shopifySdk.updateCartCodes(client, {
@@ -881,225 +943,96 @@ function useRemoveCartCodes(options) {
881
943
  }
882
944
  return updatedCart;
883
945
  },
884
- [client, locale, cartCookieAdapter, mutateCart, cart]
946
+ [client, locale, cartCookieAdapter, mutateCart, cart, metafieldIdentifiers]
885
947
  );
886
948
  return useSWRMutation__default.default("remove-codes", removeCodes, options);
887
949
  }
888
-
889
- // src/hooks/cart/use-add-to-cart.ts
890
- function useAddToCart({ withTrack = true } = {}, swrOptions) {
891
- const { client, config, locale, cartCookieAdapter, userAdapter } = useShopify();
892
- const { cart } = useCartContext();
893
- const { trigger: applyCartCodes } = useApplyCartCodes();
894
- const { trigger: removeInvalidCodes } = useRemoveCartCodes();
895
- const { trigger: addCartLines2 } = useAddCartLines();
896
- const addToCart = react.useCallback(
897
- async (_key, { arg }) => {
898
- const {
899
- lineItems,
900
- cartId: providedCartId,
901
- discountCodes,
902
- gtmParams = {},
903
- buyerIdentity,
904
- needCreateCart = false,
905
- onCodesInvalid,
906
- replaceExistingCodes
907
- } = arg;
908
- if (!lineItems || lineItems.length === 0) {
909
- return;
910
- }
911
- const lines = lineItems.map((item) => ({
912
- merchandiseId: item.variant?.id || "",
913
- quantity: item.quantity || 1,
914
- attributes: item.attributes,
915
- sellingPlanId: item.sellingPlanId
916
- })).filter((item) => item.merchandiseId && item.quantity);
917
- if (lines.length === 0) {
918
- return;
919
- }
920
- const cartId = needCreateCart ? void 0 : providedCartId || cart?.id;
921
- let resultCart = await addCartLines2({
922
- cartId,
923
- lines,
924
- buyerIdentity
925
- });
926
- if (!resultCart) {
927
- return void 0;
928
- }
929
- console.log("npm addCartLines resultCart", resultCart);
930
- if (resultCart.discountCodes && resultCart.discountCodes.length > 0) {
931
- const unapplicableCodes = resultCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
932
- if (unapplicableCodes.length > 0) {
933
- if (onCodesInvalid) {
934
- const handledCart = await onCodesInvalid(resultCart, unapplicableCodes);
935
- if (handledCart) {
936
- resultCart = handledCart;
937
- }
938
- } else {
939
- await removeInvalidCodes({
940
- discountCodes: unapplicableCodes
941
- });
942
- }
943
- }
944
- }
945
- if (discountCodes && discountCodes.length > 0) {
946
- applyCartCodes({
947
- replaceExistingCodes,
948
- discountCodes
949
- });
950
- }
951
- if (withTrack) {
952
- trackAddToCartGA({
953
- lineItems,
954
- gtmParams: { ...gtmParams, brand: config.getBrand() }
955
- });
956
- trackAddToCartFBQ({ lineItems });
957
- }
958
- return resultCart;
959
- },
960
- [client, locale, cartCookieAdapter, userAdapter, cart, withTrack]
950
+ var initSameLinesAttributes = ({
951
+ cart,
952
+ line
953
+ }) => {
954
+ const sameLineInCart = cart?.lineItems.find(
955
+ (lineInCart) => lineInCart.variant.sku === line.variant?.sku && lineInCart.product?.handle === line.variant?.product?.handle
961
956
  );
962
- return useSWRMutation__default.default("add-to-cart", addToCart, swrOptions);
963
- }
964
- function useUpdateCartLines(options) {
965
- const { client, locale, cartCookieAdapter } = useShopify();
966
- const { mutateCart, metafieldIdentifiers } = useCartContext();
967
- const updateLines = react.useCallback(
968
- async (_key, { arg }) => {
969
- const updatedCart = await shopifySdk.updateCartLines(client, {
970
- ...arg,
971
- metafieldIdentifiers,
972
- cookieAdapter: cartCookieAdapter
973
- });
974
- if (updatedCart) {
975
- mutateCart(updatedCart);
976
- }
977
- return updatedCart;
978
- },
979
- [client, locale, cartCookieAdapter, mutateCart]
957
+ const codeAmountAttribute = sameLineInCart?.customAttributes?.find(
958
+ (attr) => attr.key === CODE_AMOUNT_KEY
980
959
  );
981
- return useSWRMutation__default.default("update-cart-lines", updateLines, options);
982
- }
983
- function useRemoveCartLines(options) {
984
- const { client, locale, cartCookieAdapter } = useShopify();
985
- const { mutateCart, metafieldIdentifiers } = useCartContext();
986
- const removeLines = react.useCallback(
987
- async (_key, { arg }) => {
988
- const { autoRemoveInvalidCodes = true, onCodesRemoved, cartId, lineIds } = arg;
989
- let updatedCart = await shopifySdk.removeCartLines(client, {
990
- cartId,
991
- lineIds,
992
- metafieldIdentifiers,
993
- cookieAdapter: cartCookieAdapter
994
- });
995
- if (updatedCart && autoRemoveInvalidCodes) {
996
- const unApplicableCodes = updatedCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
997
- if (unApplicableCodes.length > 0) {
998
- if (onCodesRemoved) {
999
- const handledCart = await onCodesRemoved(updatedCart, unApplicableCodes);
1000
- if (handledCart) {
1001
- updatedCart = handledCart;
1002
- }
1003
- } else {
1004
- updatedCart = await shopifySdk.updateCartCodes(client, {
1005
- cartId: updatedCart.id,
1006
- discountCodes: updatedCart.discountCodes.filter((item) => item.applicable).map((item) => item.code),
1007
- metafieldIdentifiers,
1008
- cookieAdapter: cartCookieAdapter
1009
- }) || updatedCart;
1010
- }
1011
- }
1012
- }
1013
- if (updatedCart) {
1014
- mutateCart(updatedCart);
1015
- }
1016
- return updatedCart;
1017
- },
1018
- [client, locale, cartCookieAdapter, mutateCart]
960
+ const scriptCodeAmountAttribute = sameLineInCart?.customAttributes?.find(
961
+ (attr) => attr.key === SCRIPT_CODE_AMOUNT_KEY
1019
962
  );
1020
- return useSWRMutation__default.default("remove-cart-lines", removeLines, options);
1021
- }
1022
- function useUpdateCartAttributes(mutate, metafieldIdentifiers, options) {
1023
- const { client, locale, cartCookieAdapter } = useShopify();
1024
- const updateAttributes = react.useCallback(
1025
- async (_key, { arg }) => {
1026
- const updatedCart = await shopifySdk.updateCartAttributes(client, {
1027
- ...arg,
1028
- metafieldIdentifiers,
1029
- cookieAdapter: cartCookieAdapter
1030
- });
1031
- console.log("useUpdateCartAttributes updatedCart", updatedCart);
1032
- if (updatedCart) {
1033
- mutate(updatedCart);
963
+ let functionAttribute = null;
964
+ try {
965
+ functionAttribute = sameLineInCart?.customAttributes?.find(
966
+ (attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY && JSON.parse(attr.value)?.discounted_amount
967
+ );
968
+ } catch (error) {
969
+ }
970
+ if (codeAmountAttribute || functionAttribute || scriptCodeAmountAttribute) {
971
+ return {
972
+ ...line,
973
+ attributes: [
974
+ ...line.attributes || [],
975
+ codeAmountAttribute,
976
+ functionAttribute,
977
+ scriptCodeAmountAttribute
978
+ ].filter(Boolean)
979
+ };
980
+ }
981
+ return line;
982
+ };
983
+ var initDiscountAttributes = ({ line }) => {
984
+ let itemAttributes = line.attributes || [];
985
+ const functionEnvAttribute = itemAttributes.find((attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY);
986
+ if (!functionEnvAttribute) {
987
+ itemAttributes = itemAttributes.concat([
988
+ {
989
+ key: CUSTOMER_ATTRIBUTE_KEY,
990
+ value: JSON.stringify({
991
+ is_gift: false,
992
+ discounted_amount: line.variant?.finalPrice?.amount === void 0 ? Number(line.variant?.price?.amount) * (line.quantity || 1) : Number(line.variant?.finalPrice?.amount) * (line.quantity || 1)
993
+ })
1034
994
  }
1035
- return updatedCart;
1036
- },
1037
- [client, locale, cartCookieAdapter, mutate]
995
+ ]);
996
+ }
997
+ const memberPriceAttribute = itemAttributes.find(
998
+ (attr) => attr.key === MEMBER_PRICE_ATTRIBUTE_KEY
1038
999
  );
1039
- return useSWRMutation__default.default("update-cart-attributes", updateAttributes, options);
1040
- }
1041
- function useBuyNow({ withTrack = true } = {}, swrOptions) {
1042
- const { client, config, locale, cartCookieAdapter, userAdapter } = useShopify();
1043
- const isLoggedIn = userAdapter?.isLoggedIn || false;
1044
- const buyNow = react.useCallback(
1045
- async (_key, { arg }) => {
1046
- const {
1047
- lineItems,
1048
- discountCodes,
1049
- gtmParams = {},
1050
- buyerIdentity,
1051
- fbqTrackConfig,
1052
- customAttributes,
1053
- metafieldIdentifiers,
1054
- redirectToCheckout
1055
- } = arg;
1056
- if (!lineItems || lineItems.length === 0) {
1057
- return;
1000
+ const coupon = line.coupon;
1001
+ if (!memberPriceAttribute && coupon) {
1002
+ itemAttributes = itemAttributes.concat([
1003
+ {
1004
+ key: MEMBER_PRICE_ATTRIBUTE_KEY,
1005
+ value: JSON.stringify({ code: coupon.code })
1058
1006
  }
1059
- const lines = lineItems.map((item) => ({
1060
- merchandiseId: item.variant?.id || "",
1061
- quantity: item.quantity || 1,
1062
- attributes: item.attributes,
1063
- sellingPlanId: item.sellingPlanId
1064
- })).filter((item) => item.merchandiseId && item.quantity);
1065
- if (lines.length === 0) {
1066
- return;
1007
+ ]);
1008
+ }
1009
+ const couponDiscountAttribute = itemAttributes.find(
1010
+ (attr) => attr.key === CODE_AMOUNT_KEY || attr.key === SCRIPT_CODE_AMOUNT_KEY
1011
+ );
1012
+ if (!couponDiscountAttribute && coupon && Number(coupon?.amount) > 0) {
1013
+ itemAttributes = itemAttributes.concat([
1014
+ {
1015
+ key: CODE_AMOUNT_KEY,
1016
+ value: new Decimal2__default.default(coupon.amount).times(line.quantity || 1).toString()
1017
+ },
1018
+ {
1019
+ key: SCRIPT_CODE_AMOUNT_KEY,
1020
+ value: new Decimal2__default.default(coupon.amount).times(line.quantity || 1).toString()
1067
1021
  }
1068
- const resultCart = await shopifySdk.createCart(client, {
1069
- lines,
1070
- metafieldIdentifiers,
1071
- cookieAdapter: cartCookieAdapter,
1072
- buyerIdentity,
1073
- discountCodes,
1074
- customAttributes
1075
- });
1076
- if (!resultCart) {
1077
- throw new Error("Failed to create cart for buy now");
1078
- }
1079
- if (withTrack && resultCart.lineItems) {
1080
- trackBuyNowGA({
1081
- lineItems,
1082
- gtmParams: { ...gtmParams, brand: config.getBrand() }
1083
- });
1084
- if (fbqTrackConfig) {
1085
- trackBuyNowFBQ({ trackConfig: fbqTrackConfig });
1086
- }
1087
- }
1088
- if (redirectToCheckout) {
1089
- if (resultCart.url) {
1090
- if (typeof window !== "undefined") {
1091
- window.location.href = resultCart.url;
1092
- }
1093
- } else {
1094
- throw new Error("Failed to get checkout URL");
1095
- }
1096
- }
1097
- return resultCart;
1098
- },
1099
- [client, locale, isLoggedIn, cartCookieAdapter, withTrack]
1100
- );
1101
- return useSWRMutation__default.default("buy-now", buyNow, swrOptions);
1102
- }
1022
+ ]);
1023
+ }
1024
+ return { ...line, attributes: itemAttributes };
1025
+ };
1026
+ var getLinesWithAttributes = ({
1027
+ cart,
1028
+ lineItems
1029
+ }) => {
1030
+ return lineItems.map((line) => {
1031
+ const sameLine = initSameLinesAttributes({ cart, line });
1032
+ const functionLine = initDiscountAttributes({ line: sameLine });
1033
+ return functionLine;
1034
+ });
1035
+ };
1103
1036
  function useCalcGiftsFromLines({
1104
1037
  lines,
1105
1038
  customer,
@@ -1116,30 +1049,55 @@ function useCalcGiftsFromLines({
1116
1049
  lines
1117
1050
  });
1118
1051
  const allGiftLines = react.useMemo(() => {
1119
- const functionGiftLines = functionGift.qualifyingGift?.itemsToAdd || [];
1120
- const scriptGiftLines = scriptGift.freeGiftLevel ? scriptGift.freeGiftLevel.giveawayProducts.map((product) => {
1121
- const giftProduct = scriptGift.giftProductsResult?.find(
1122
- (p) => p.handle === product.handle
1052
+ const functionGiftLines = (functionGift.qualifyingGift?.itemsToAdd || []).map((item) => {
1053
+ const product = functionGift.giftProductsResult?.find(
1054
+ (product2) => product2.handle === item.variant.handle
1055
+ );
1056
+ const variants = product?.variants;
1057
+ const variant = Array.isArray(variants) ? variants.find((v) => v.sku === item.variant.sku) : void 0;
1058
+ if (!variant) {
1059
+ console.warn(
1060
+ `Function gift: Variant not found for handle=${item.variant.handle}, sku=${item.variant.sku}`
1061
+ );
1062
+ return null;
1063
+ }
1064
+ return {
1065
+ variant: {
1066
+ ...variant,
1067
+ product
1068
+ },
1069
+ quantity: item.quantity ?? 1,
1070
+ attributes: item.attributes
1071
+ };
1072
+ }).filter((item) => item !== null);
1073
+ const scriptGiftLines = scriptGift.freeGiftLevel ? scriptGift.freeGiftLevel.giveawayProducts.map((item) => {
1074
+ const product = scriptGift.giftProductsResult?.find(
1075
+ (product2) => product2.handle === item.handle
1123
1076
  );
1124
- const variant = giftProduct?.variants?.[0];
1077
+ const variants = product?.variants;
1078
+ const variant = Array.isArray(variants) ? variants.find((v) => v.sku === item.sku) : void 0;
1079
+ if (!variant) {
1080
+ console.warn(`Script gift: Variant not found for handle=${item.handle}, sku=${item.sku}`);
1081
+ return null;
1082
+ }
1125
1083
  return {
1126
1084
  variant: {
1127
- id: variant?.id || "",
1128
- handle: product.handle,
1129
- sku: product.sku
1085
+ ...variant,
1086
+ product
1130
1087
  },
1131
1088
  quantity: 1,
1132
1089
  attributes: [
1133
1090
  {
1134
1091
  key: scriptGiveawayKey,
1135
- value: "true"
1092
+ value: scriptGiveawayKey
1136
1093
  }
1137
1094
  ]
1138
1095
  };
1139
- }).filter((item) => item.variant.id) : [];
1096
+ }).filter((item) => item !== null) : [];
1140
1097
  return [...functionGiftLines, ...scriptGiftLines];
1141
1098
  }, [
1142
1099
  functionGift.qualifyingGift,
1100
+ functionGift.giftProductsResult,
1143
1101
  scriptGift.freeGiftLevel,
1144
1102
  scriptGift.giftProductsResult,
1145
1103
  scriptGiveawayKey
@@ -1174,7 +1132,7 @@ var useCalcOrderDiscount = (cart, orderDiscountConfig, customer) => {
1174
1132
  const isCustomerLoading = react.useMemo(() => !customer ? true : false, [customer]);
1175
1133
  const dealsType = "";
1176
1134
  const { activeCampaign, subtotal } = react.useMemo(() => {
1177
- for (const campaign of orderDiscountConfig) {
1135
+ for (const campaign of orderDiscountConfig || []) {
1178
1136
  const { rule_conditions = [], result_detail } = campaign;
1179
1137
  const { main_product, order_discount_conf } = result_detail || {};
1180
1138
  const isPreCheckPassed = preCheck(rule_conditions, tags, []);
@@ -1204,9 +1162,12 @@ var useCalcOrderDiscount = (cart, orderDiscountConfig, customer) => {
1204
1162
  discountAmount: 0
1205
1163
  };
1206
1164
  }
1207
- const tieredDiscounts = activeCampaign.result_detail.order_discount_conf.tiered_discounts;
1208
- const qualifyingTier = [...tieredDiscounts].reverse().find((tier) => subtotal >= Number(tier.amount));
1209
- const nextGoal = tieredDiscounts.find((tier) => subtotal < Number(tier.amount));
1165
+ const currentCurrency = cart?.currency?.code || "";
1166
+ console.log("currentCurrency", cart, currentCurrency);
1167
+ const orderDiscountConf = activeCampaign.result_detail.order_discount_conf;
1168
+ const tieredDiscounts = orderDiscountConf.tiered_discounts_markets?.[currentCurrency] || orderDiscountConf.tiered_discounts;
1169
+ const qualifyingTier = [...tieredDiscounts].sort((a, b) => Number(b.amount) - Number(a.amount)).find((tier) => subtotal >= Number(tier.amount));
1170
+ const nextGoal = [...tieredDiscounts].sort((a, b) => Number(a.amount) - Number(b.amount)).find((tier) => subtotal < Number(tier.amount));
1210
1171
  if (!qualifyingTier) {
1211
1172
  return {
1212
1173
  qualifyingDiscount: null,
@@ -1243,43 +1204,10 @@ var useCalcOrderDiscount = (cart, orderDiscountConfig, customer) => {
1243
1204
  isLoading: isCustomerLoading
1244
1205
  };
1245
1206
  };
1246
- function useHasPlusMemberInCart({
1247
- memberSetting,
1248
- cart
1249
- }) {
1250
- const { plus_monthly_product, plus_annual_product } = memberSetting || {};
1251
- return react.useMemo(() => {
1252
- if (!cart?.lineItems) {
1253
- return {
1254
- hasPlusMember: false,
1255
- hasMonthlyPlus: false,
1256
- hasAnnualPlus: false
1257
- };
1258
- }
1259
- const monthlyPlusItem = cart.lineItems.find(
1260
- (item) => item.product?.handle === plus_monthly_product?.handle && item.variant?.sku === plus_monthly_product?.sku
1261
- );
1262
- const annualPlusItem = cart.lineItems.find(
1263
- (item) => item.product?.handle === plus_annual_product?.handle && item.variant?.sku === plus_annual_product?.sku
1264
- );
1265
- const hasMonthlyPlus = !!monthlyPlusItem;
1266
- const hasAnnualPlus = !!annualPlusItem;
1267
- const hasPlusMember = hasMonthlyPlus || hasAnnualPlus;
1268
- return {
1269
- hasPlusMember,
1270
- hasMonthlyPlus,
1271
- hasAnnualPlus,
1272
- monthlyPlusItem,
1273
- annualPlusItem
1274
- };
1275
- }, [cart?.lineItems, plus_monthly_product, plus_annual_product]);
1276
- }
1277
-
1278
- // src/hooks/cart/feature/use-cart-attributes.ts
1279
1207
  var getReferralAttributes = () => {
1280
- const inviteCode = Cookies5__default.default.get("invite_code");
1281
- const playModeId = Cookies5__default.default.get("playModeId");
1282
- const popup = Cookies5__default.default.get("_popup");
1208
+ const inviteCode = shopifySdk.getLocalStorage("inviteCode") || Cookies5__default.default.get("inviteCode");
1209
+ const playModeId = shopifySdk.getLocalStorage("playModeId") || Cookies5__default.default.get("playModeId");
1210
+ const popup = shopifySdk.getLocalStorage("_popup") || Cookies5__default.default.get("_popup");
1283
1211
  if (inviteCode && playModeId) {
1284
1212
  return popup ? [
1285
1213
  { key: "_invite_code", value: inviteCode ? inviteCode : "" },
@@ -1292,121 +1220,130 @@ var getReferralAttributes = () => {
1292
1220
  }
1293
1221
  return [];
1294
1222
  };
1223
+ var getUserType = (customer) => {
1224
+ let userInfo = Cookies5__default.default.get("userInfo");
1225
+ if (userInfo) {
1226
+ userInfo = JSON.parse(userInfo);
1227
+ let arr = typeof userInfo?.id == "string" && userInfo?.id.split("/");
1228
+ userInfo.setId = arr[arr.length - 1];
1229
+ }
1230
+ const customerInfo = userInfo || customer;
1231
+ if (!customerInfo) {
1232
+ return "new_user_unlogin";
1233
+ }
1234
+ if (customer) {
1235
+ const { orders = {} } = customer;
1236
+ if (orders?.edges?.length === 1) {
1237
+ return "old_user_orders_once";
1238
+ } else if (orders?.edges?.length > 1) {
1239
+ return "old_user_orders_twice";
1240
+ }
1241
+ }
1242
+ return "new_user_login";
1243
+ };
1244
+ function getCartAttributes({
1245
+ profile,
1246
+ customer,
1247
+ cart,
1248
+ memberType,
1249
+ currentUrl = ""
1250
+ }) {
1251
+ const userType = getUserType(customer);
1252
+ const memberAttributes = [
1253
+ {
1254
+ key: "_token",
1255
+ value: profile?.token
1256
+ },
1257
+ {
1258
+ key: "_member_type",
1259
+ value: memberType ?? String(profile?.memberType ?? 0)
1260
+ },
1261
+ {
1262
+ key: "_user_type",
1263
+ value: userType
1264
+ },
1265
+ {
1266
+ key: "_is_login",
1267
+ value: profile?.token ? "true" : "false"
1268
+ }
1269
+ ];
1270
+ if (profile?.token) {
1271
+ memberAttributes.push({
1272
+ key: "_login_user",
1273
+ value: "1"
1274
+ });
1275
+ }
1276
+ const discountCodes = cart?.discountCodes.map((item) => item.code).filter((code) => code) || [];
1277
+ const functionAttributes = [
1278
+ {
1279
+ key: CUSTOMER_ATTRIBUTE_KEY,
1280
+ value: JSON.stringify({
1281
+ discount_code: discountCodes,
1282
+ user_tags: customer?.tags || []
1283
+ })
1284
+ }
1285
+ ];
1286
+ const presellAttributes = [
1287
+ {
1288
+ key: "_presale",
1289
+ value: cart?.lineItems.some((item) => item?.variant?.metafields?.presell === "presell")
1290
+ }
1291
+ ];
1292
+ const weightAttributes = [
1293
+ {
1294
+ key: "_weight",
1295
+ value: cart?.lineItems.reduce((acc, item) => {
1296
+ return new Decimal2__default.default(acc).plus(item.variant.weight ?? 0).toNumber();
1297
+ }, 0).toString()
1298
+ },
1299
+ {
1300
+ key: "_app_source_name",
1301
+ value: "dtc"
1302
+ }
1303
+ ];
1304
+ const trackingAttributes = [
1305
+ {
1306
+ key: "utm_params",
1307
+ value: currentUrl
1308
+ }
1309
+ ];
1310
+ const commonAttributes = [
1311
+ ...memberAttributes,
1312
+ ...functionAttributes,
1313
+ ...presellAttributes,
1314
+ ...weightAttributes,
1315
+ ...trackingAttributes,
1316
+ ...getReferralAttributes()
1317
+ ].filter((item) => item?.value);
1318
+ const extraAttributesInCart = cart?.customAttributes?.filter(
1319
+ (item) => !commonAttributes.some((attr) => attr.key === item.key)
1320
+ ) || [];
1321
+ return [...commonAttributes, ...extraAttributesInCart].filter((item) => item?.value);
1322
+ }
1295
1323
  var useCartAttributes = ({
1296
1324
  profile,
1297
1325
  customer,
1298
1326
  cart,
1299
- memberSetting
1327
+ memberType
1300
1328
  }) => {
1301
1329
  const [currentUrl, setCurrentUrl] = react.useState("");
1302
- const { hasPlusMember } = useHasPlusMemberInCart({
1303
- memberSetting,
1304
- cart
1305
- });
1306
1330
  react.useEffect(() => {
1307
1331
  setCurrentUrl(window.location.href);
1308
1332
  }, []);
1309
- const userType = react.useMemo(() => {
1310
- let userInfo = Cookies5__default.default.get("userInfo");
1311
- if (userInfo) {
1312
- userInfo = JSON.parse(userInfo);
1313
- let arr = typeof userInfo?.id == "string" && userInfo?.id.split("/");
1314
- userInfo.setId = arr[arr.length - 1];
1315
- }
1316
- const customerInfo = userInfo || customer;
1317
- if (!customerInfo) {
1318
- return "new_user_unlogin";
1319
- }
1320
- if (customer) {
1321
- const { orders = {} } = customer;
1322
- if (orders?.edges?.length === 1) {
1323
- return "old_user_orders_once";
1324
- } else if (orders?.edges?.length > 1) {
1325
- return "old_user_orders_twice";
1326
- }
1327
- }
1328
- return "new_user_login";
1329
- }, [customer]);
1330
- const memberAttributes = react.useMemo(() => {
1331
- return [
1332
- {
1333
- key: "_token",
1334
- value: profile?.token
1335
- //是否登录
1336
- },
1337
- {
1338
- key: "_member_type",
1339
- value: hasPlusMember ? "2" : profile?.memberType
1340
- //:0(游客),1(普通会员),2(付费会员)
1341
- },
1342
- {
1343
- key: "_user_type",
1344
- value: userType
1345
- // n
1346
- },
1347
- {
1348
- key: "_is_login",
1349
- value: profile?.token ? "true" : "false"
1350
- }
1351
- ];
1352
- }, [profile?.memberType, profile?.token, userType, hasPlusMember]);
1353
- const functionAttributes = react.useMemo(() => {
1354
- const hasFunctionEnvAttribute = cart?.lineItems.some(
1355
- (item) => item.customAttributes?.some((attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY)
1356
- );
1357
- const discountCodes = cart?.discountCodes.map((item) => item.code).filter((code) => code) || [];
1358
- return hasFunctionEnvAttribute ? [
1359
- {
1360
- key: "_discounts_function_env",
1361
- value: JSON.stringify({
1362
- discount_code: discountCodes,
1363
- user_tags: customer?.tags || []
1364
- })
1365
- }
1366
- ] : [];
1367
- }, [cart]);
1368
- const presellAttributes = react.useMemo(() => {
1369
- return [
1370
- {
1371
- key: "_presale",
1372
- value: cart?.lineItems.some((item) => item?.variant?.metafields?.presell === "presell")
1373
- }
1374
- ];
1375
- }, [cart]);
1376
- const weightAttributes = react.useMemo(() => {
1377
- return [
1378
- {
1379
- key: "_weight",
1380
- value: cart?.lineItems.reduce((acc, item) => {
1381
- return new Decimal2__default.default(acc).plus(item.variant.weight ?? 0).toNumber();
1382
- }, 0).toString()
1383
- },
1384
- {
1385
- key: "_app_source_name",
1386
- value: "dtc"
1387
- }
1388
- ];
1389
- }, [cart]);
1390
- const trackingAttributes = react.useMemo(() => {
1391
- return [
1392
- {
1393
- key: "utm_params",
1394
- value: currentUrl
1395
- }
1396
- ];
1397
- }, [currentUrl]);
1333
+ const attributes = react.useMemo(() => {
1334
+ return getCartAttributes({
1335
+ profile,
1336
+ customer,
1337
+ cart,
1338
+ memberType,
1339
+ currentUrl
1340
+ });
1341
+ }, [profile, customer, cart, memberType, currentUrl]);
1398
1342
  return react.useMemo(
1399
1343
  () => ({
1400
- attributes: [
1401
- ...memberAttributes,
1402
- ...functionAttributes,
1403
- ...presellAttributes,
1404
- ...weightAttributes,
1405
- ...trackingAttributes,
1406
- ...getReferralAttributes()
1407
- ].filter((item) => item?.value)
1344
+ attributes
1408
1345
  }),
1409
- [memberAttributes, functionAttributes, presellAttributes, weightAttributes, trackingAttributes]
1346
+ [attributes]
1410
1347
  );
1411
1348
  };
1412
1349
  var DEFAULT_MIN = 1;
@@ -1469,7 +1406,7 @@ var useUpdateLineCodeAmountAttributes = ({
1469
1406
  );
1470
1407
  const functionEnvValue = getDiscountEnvAttributeValue(line.customAttributes);
1471
1408
  const hasSameFunctionEnvAttribute = Number(functionEnvValue.discounted_amount) === Number(line.totalAmount);
1472
- if (!hasSameFunctionEnvAttribute && hasFunctionEnvAttribute) {
1409
+ if (!hasSameFunctionEnvAttribute && hasFunctionEnvAttribute && !functionEnvValue.is_gift) {
1473
1410
  attrNeedUpdate.push({
1474
1411
  key: CUSTOMER_ATTRIBUTE_KEY,
1475
1412
  value: JSON.stringify({
@@ -1508,29 +1445,22 @@ var useUpdateLineCodeAmountAttributes = ({
1508
1445
  }).filter(
1509
1446
  ({ attrNeedUpdate, attrNeedDelete }) => attrNeedUpdate.length || attrNeedDelete.length
1510
1447
  ).map(({ line, attrNeedUpdate, attrNeedDelete }) => {
1448
+ let lineId = line.id;
1449
+ let attributes = line.customAttributes || [];
1450
+ if (attrNeedDelete.length) {
1451
+ attributes = attributes.filter(
1452
+ (attr) => !attrNeedDelete.includes(attr.key)
1453
+ );
1454
+ }
1511
1455
  if (attrNeedUpdate.length) {
1512
- return {
1513
- id: line.id,
1514
- attributes: [
1515
- ...line.customAttributes?.filter(
1516
- (attr) => !attrNeedUpdate.some((updateAttr) => updateAttr.key === attr.key)
1517
- ) || [],
1518
- ...attrNeedUpdate
1519
- ]
1520
- };
1521
- } else if (attrNeedDelete.length) {
1522
- return {
1523
- id: line.id,
1524
- attributes: line.customAttributes?.filter(
1525
- (attr) => !attrNeedDelete.includes(attr.key)
1526
- ) || []
1527
- };
1528
- } else {
1529
- return {
1530
- id: line.id,
1531
- attributes: line.customAttributes || []
1532
- };
1456
+ attributes = attributes.filter(
1457
+ (attr) => !attrNeedUpdate.some((updateAttr) => updateAttr.key === attr.key)
1458
+ ).concat(attrNeedUpdate);
1533
1459
  }
1460
+ return {
1461
+ id: lineId,
1462
+ attributes
1463
+ };
1534
1464
  }),
1535
1465
  [cart?.lineItems, mainProductDiscountCodes]
1536
1466
  );
@@ -1565,45 +1495,61 @@ var useUpdateLineCodeAmountAttributes = ({
1565
1495
  }, [loading, setLoadingState]);
1566
1496
  };
1567
1497
 
1568
- // src/hooks/cart/types/price-discount.ts
1569
- var PriceDiscountType = /* @__PURE__ */ ((PriceDiscountType2) => {
1570
- PriceDiscountType2[PriceDiscountType2["PERCENTAGE"] = 1] = "PERCENTAGE";
1571
- PriceDiscountType2[PriceDiscountType2["FIXED_AMOUNT"] = 2] = "FIXED_AMOUNT";
1572
- return PriceDiscountType2;
1573
- })(PriceDiscountType || {});
1574
- var PriceBasePriceType = /* @__PURE__ */ ((PriceBasePriceType2) => {
1575
- PriceBasePriceType2[PriceBasePriceType2["MIN_DISCOUNTED_PRICE"] = 1] = "MIN_DISCOUNTED_PRICE";
1576
- PriceBasePriceType2[PriceBasePriceType2["MIN_TOTAL_PRICE"] = 2] = "MIN_TOTAL_PRICE";
1577
- return PriceBasePriceType2;
1578
- })(PriceBasePriceType || {});
1579
- function useProduct(options = {}) {
1580
- const { client, locale } = useShopify();
1581
- const { handle, metafieldIdentifiers, ...swrOptions } = options;
1582
- return useSWR__default.default(
1583
- handle ? ["product", locale, handle, metafieldIdentifiers] : null,
1584
- () => shopifySdk.getProduct(client, {
1585
- handle,
1586
- locale,
1587
- metafieldIdentifiers
1588
- }),
1589
- swrOptions
1590
- );
1591
- }
1592
- function useAllProducts(options = {}) {
1593
- const { client, locale } = useShopify();
1594
- const { first, query, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
1595
- return useSWR__default.default(
1596
- ["all-products", locale, first, query, sortKey, reverse, metafieldIdentifiers],
1597
- () => shopifySdk.getAllProducts(client, {
1598
- locale,
1599
- first,
1600
- query,
1601
- sortKey,
1602
- reverse,
1603
- metafieldIdentifiers
1604
- }),
1605
- swrOptions
1606
- );
1498
+ // src/hooks/member/plus/types.ts
1499
+ var PLUS_MEMBER_TYPE = /* @__PURE__ */ ((PLUS_MEMBER_TYPE2) => {
1500
+ PLUS_MEMBER_TYPE2[PLUS_MEMBER_TYPE2["FREE"] = 0] = "FREE";
1501
+ PLUS_MEMBER_TYPE2[PLUS_MEMBER_TYPE2["MONTHLY"] = 1] = "MONTHLY";
1502
+ PLUS_MEMBER_TYPE2[PLUS_MEMBER_TYPE2["ANNUAL"] = 2] = "ANNUAL";
1503
+ return PLUS_MEMBER_TYPE2;
1504
+ })(PLUS_MEMBER_TYPE || {});
1505
+ var PlusMemberMode = /* @__PURE__ */ ((PlusMemberMode2) => {
1506
+ PlusMemberMode2["MONTHLY"] = "monthly";
1507
+ PlusMemberMode2["ANNUAL"] = "annual";
1508
+ return PlusMemberMode2;
1509
+ })(PlusMemberMode || {});
1510
+ var DeliveryPlusType = /* @__PURE__ */ ((DeliveryPlusType2) => {
1511
+ DeliveryPlusType2["FREE"] = "free";
1512
+ DeliveryPlusType2["MONTHLY"] = "monthly";
1513
+ DeliveryPlusType2["ANNUAL"] = "annual";
1514
+ return DeliveryPlusType2;
1515
+ })(DeliveryPlusType || {});
1516
+ var ShippingMethodMode = /* @__PURE__ */ ((ShippingMethodMode2) => {
1517
+ ShippingMethodMode2["FREE"] = "free";
1518
+ ShippingMethodMode2["TDD"] = "tdd";
1519
+ ShippingMethodMode2["NDD"] = "ndd";
1520
+ return ShippingMethodMode2;
1521
+ })(ShippingMethodMode || {});
1522
+ var createInitialValue = () => ({
1523
+ plusMemberMetafields: {},
1524
+ selectedPlusMemberMode: "free",
1525
+ setSelectedPlusMemberMode: () => {
1526
+ },
1527
+ selectedShippingMethod: void 0,
1528
+ setSelectedShippingMethod: () => {
1529
+ },
1530
+ showMoreShippingMethod: false,
1531
+ setShowMoreShippingMethod: () => {
1532
+ },
1533
+ variant: {},
1534
+ product: {},
1535
+ shippingMethodsContext: {
1536
+ freeShippingMethods: [],
1537
+ paymentShippingMethods: [],
1538
+ nddOverweight: false,
1539
+ tddOverweight: false,
1540
+ nddCoupon: void 0,
1541
+ tddCoupon: void 0,
1542
+ isLoadingCoupon: false
1543
+ },
1544
+ selectedPlusMemberVariant: void 0,
1545
+ showPlusMemberBenefit: false,
1546
+ setShowPlusMemberBenefit: () => {
1547
+ },
1548
+ profile: void 0
1549
+ });
1550
+ var PlusMemberContext = react.createContext(createInitialValue());
1551
+ function usePlusMemberContext() {
1552
+ return react.useContext(PlusMemberContext);
1607
1553
  }
1608
1554
  function useProductsByHandles(options = {}) {
1609
1555
  const { client, locale } = useShopify();
@@ -1623,1213 +1569,1349 @@ function useProductsByHandles(options = {}) {
1623
1569
  metafieldIdentifiers
1624
1570
  });
1625
1571
  },
1626
- swrOptions || {
1627
- revalidateOnFocus: false
1572
+ {
1573
+ revalidateOnFocus: false,
1574
+ ...swrOptions
1628
1575
  }
1629
1576
  );
1630
1577
  }
1631
- function getFirstAvailableVariant(product) {
1632
- const availableVariant = product.variants.find((v) => v.availableForSale);
1633
- return availableVariant || product.variants[0];
1634
- }
1635
- function getVariantFromSelectedOptions(product, selectedOptions) {
1636
- return product.variants.find((variant) => {
1637
- return variant.selectedOptions.every((option) => {
1638
- return selectedOptions[option.name] === option.value;
1639
- });
1578
+
1579
+ // src/hooks/member/plus/use-plus-member-variants.ts
1580
+ function usePlusMemberVariants({
1581
+ memberSetting
1582
+ }) {
1583
+ const plusMonthly = memberSetting?.plus_monthly_product;
1584
+ const plusAnnual = memberSetting?.plus_annual_product;
1585
+ const plusMemberHandles = react.useMemo(() => {
1586
+ return [plusMonthly?.handle, plusAnnual?.handle].filter(Boolean);
1587
+ }, [plusMonthly?.handle, plusAnnual?.handle]);
1588
+ const { data: plusMemberProducts = [] } = useProductsByHandles({
1589
+ handles: plusMemberHandles
1640
1590
  });
1591
+ const monthlyProduct = react.useMemo(() => {
1592
+ return plusMemberProducts?.find((item) => item?.handle === plusMonthly?.handle);
1593
+ }, [plusMemberProducts, plusMonthly]);
1594
+ const annualProduct = react.useMemo(() => {
1595
+ return plusMemberProducts?.find((item) => item?.handle === plusAnnual?.handle);
1596
+ }, [plusMemberProducts, plusAnnual]);
1597
+ const monthlyVariant = react.useMemo(() => {
1598
+ return monthlyProduct?.variants?.find((item) => item.sku === plusMonthly?.sku);
1599
+ }, [monthlyProduct, plusMonthly]);
1600
+ const annualVariant = react.useMemo(() => {
1601
+ return annualProduct?.variants?.find((item) => item.sku === plusAnnual?.sku);
1602
+ }, [annualProduct, plusAnnual]);
1603
+ return {
1604
+ monthlyVariant: monthlyVariant ? {
1605
+ ...monthlyVariant,
1606
+ product: monthlyProduct
1607
+ } : void 0,
1608
+ annualVariant: annualVariant ? {
1609
+ ...annualVariant,
1610
+ product: annualProduct
1611
+ } : void 0
1612
+ };
1641
1613
  }
1642
- function useVariant({
1643
- product,
1644
- selectedOptions
1645
- }) {
1646
- const [variant, setVariant] = react.useState(
1647
- product ? getFirstAvailableVariant(product) : void 0
1648
- );
1649
- react.useEffect(() => {
1650
- if (!product) {
1651
- setVariant(void 0);
1652
- return;
1653
- }
1654
- const newVariant = getVariantFromSelectedOptions(product, selectedOptions);
1655
- if (newVariant && newVariant.id !== variant?.id) {
1656
- setVariant(newVariant);
1657
- } else if (!newVariant) {
1658
- setVariant(getFirstAvailableVariant(product));
1614
+ var useAvailableDeliveryCoupon = ({
1615
+ profile
1616
+ }) => {
1617
+ const { data: availableDeliveryCoupon, isLoading } = useSWR__default.default(
1618
+ profile?.email ? ["/api/multipass/subsrv/v1/prime/delivery_coupons/current/available", profile?.email] : void 0,
1619
+ async ([apiPath]) => {
1620
+ return fetch(apiPath).then((res) => res.json());
1659
1621
  }
1660
- }, [selectedOptions, product, variant?.id]);
1661
- return variant;
1662
- }
1663
- var FAKE_PRICE = 999999999e-2;
1664
- function formatPrice({
1665
- amount,
1666
- currencyCode,
1667
- locale,
1668
- maximumFractionDigits,
1669
- minimumFractionDigits,
1670
- removeTrailingZeros
1671
- }) {
1672
- const formatter = new Intl.NumberFormat(locale, {
1673
- style: "currency",
1674
- currency: currencyCode,
1675
- maximumFractionDigits: maximumFractionDigits ?? 2,
1676
- minimumFractionDigits: minimumFractionDigits ?? 2
1677
- });
1678
- let formatted = formatter.format(amount);
1679
- if (removeTrailingZeros) {
1680
- formatted = formatted.replace(/\.00$/, "");
1681
- }
1682
- return formatted;
1683
- }
1684
- function formatVariantPrice({
1685
- amount,
1686
- baseAmount,
1687
- currencyCode,
1688
- locale,
1689
- maximumFractionDigits,
1690
- minimumFractionDigits,
1691
- removeTrailingZeros
1692
- }) {
1622
+ );
1623
+ console.log("availableDeliveryCoupon", availableDeliveryCoupon);
1624
+ const { ndd_coupon: nddCoupon, tdd_coupon: tddCoupon } = availableDeliveryCoupon?.data?.data || {};
1693
1625
  return {
1694
- price: formatPrice({
1695
- amount,
1696
- currencyCode,
1697
- locale,
1698
- maximumFractionDigits,
1699
- minimumFractionDigits,
1700
- removeTrailingZeros
1701
- }),
1702
- basePrice: formatPrice({
1703
- amount: baseAmount,
1704
- currencyCode,
1705
- locale,
1706
- maximumFractionDigits,
1707
- minimumFractionDigits,
1708
- removeTrailingZeros
1709
- })
1626
+ nddCoupon,
1627
+ tddCoupon,
1628
+ isLoading
1710
1629
  };
1711
- }
1712
- function usePrice({
1713
- amount,
1714
- baseAmount,
1715
- currencyCode,
1716
- soldOutDescription = "",
1717
- maximumFractionDigits,
1718
- minimumFractionDigits,
1719
- removeTrailingZeros
1720
- }) {
1721
- const { locale } = useShopify();
1722
- const value = react.useMemo(() => {
1723
- if (typeof amount !== "number" || !currencyCode) {
1724
- return "";
1725
- }
1726
- if (soldOutDescription && amount >= FAKE_PRICE) {
1727
- return soldOutDescription;
1728
- }
1729
- return baseAmount ? formatVariantPrice({
1730
- amount,
1731
- baseAmount,
1732
- currencyCode,
1733
- locale,
1734
- maximumFractionDigits,
1735
- minimumFractionDigits,
1736
- removeTrailingZeros
1737
- }) : formatPrice({
1738
- amount,
1739
- currencyCode,
1740
- locale,
1741
- maximumFractionDigits,
1742
- minimumFractionDigits,
1743
- removeTrailingZeros
1630
+ };
1631
+
1632
+ // src/hooks/member/plus/use-shipping-methods.ts
1633
+ function useShippingMethods(options) {
1634
+ const { variant, plusMemberMetafields, selectedPlusMemberMode, profile } = options;
1635
+ const isPlus = profile?.isPlus || false;
1636
+ const { nddCoupon, tddCoupon, isLoading } = useAvailableDeliveryCoupon({ profile });
1637
+ const { plus_shipping, shippingMethod } = plusMemberMetafields || {};
1638
+ const nddOverweight = react.useMemo(() => {
1639
+ return (variant?.weight || 0) > (shippingMethod?.overWeight_ndd || Infinity);
1640
+ }, [shippingMethod?.overWeight_ndd, variant?.weight]);
1641
+ const tddOverweight = react.useMemo(() => {
1642
+ return (variant?.weight || 0) > (shippingMethod?.overWeight_tdd || Infinity);
1643
+ }, [shippingMethod?.overWeight_tdd, variant?.weight]);
1644
+ const paymentShippingMethods = react.useMemo(() => {
1645
+ const weight = variant?.weight || 0;
1646
+ const methods = plus_shipping?.shipping_methods?.filter(({ weight_low, weight_high, __mode, __plus }) => {
1647
+ const fitWeight = (!weight_low || weight >= weight_low) && (!weight_high || weight <= weight_high);
1648
+ return __mode !== "free" /* FREE */ && !__plus && fitWeight;
1649
+ }) || [];
1650
+ return methods.map((method) => {
1651
+ let disabled = false;
1652
+ const selectedFreeMember = selectedPlusMemberMode === "free";
1653
+ if (method.__mode === "ndd" /* NDD */) {
1654
+ disabled = selectedFreeMember || nddOverweight;
1655
+ } else if (method.__mode === "tdd" /* TDD */) {
1656
+ disabled = selectedFreeMember || tddOverweight;
1657
+ }
1658
+ return {
1659
+ ...method,
1660
+ id: method.__mode + method.__code,
1661
+ useCoupon: false,
1662
+ subtitle: plus_shipping?.directly || "",
1663
+ disabled
1664
+ };
1744
1665
  });
1745
1666
  }, [
1746
- amount,
1747
- baseAmount,
1748
- currencyCode,
1749
- locale,
1750
- maximumFractionDigits,
1751
- minimumFractionDigits,
1752
- soldOutDescription,
1753
- removeTrailingZeros
1667
+ nddOverweight,
1668
+ plus_shipping?.directly,
1669
+ plus_shipping?.shipping_methods,
1670
+ selectedPlusMemberMode,
1671
+ tddOverweight,
1672
+ variant?.weight
1754
1673
  ]);
1755
- const result = react.useMemo(() => {
1756
- const free = Boolean(amount && amount <= 0);
1757
- return typeof value === "string" ? { price: value, basePrice: value, free } : { ...value, free };
1758
- }, [value, amount]);
1759
- return result;
1760
- }
1761
- function optionsConstructor(selectedOptions) {
1762
- return selectedOptions.reduce((acc, option) => {
1763
- acc[option.name] = option.value;
1764
- return acc;
1765
- }, {});
1766
- }
1767
- function decodeShopifyId(gid) {
1768
- try {
1769
- const base64 = gid.split("/").pop() || "";
1770
- return atob(base64);
1771
- } catch {
1772
- return gid;
1773
- }
1774
- }
1775
- function useSelectedOptions(product, sku) {
1776
- const [options, setOptions] = react.useState({});
1777
- react.useEffect(() => {
1778
- if (!product || !product.variants.length) {
1779
- setOptions({});
1780
- return;
1781
- }
1782
- let variant = product.variants[0];
1783
- if (typeof window !== "undefined") {
1784
- const searchParams = new URLSearchParams(window.location.search);
1785
- const variantIdParam = searchParams.get("variant");
1786
- if (variantIdParam) {
1787
- const foundVariant = product.variants.find((v) => {
1788
- if (sku) return v.sku === sku;
1789
- return v.id === variantIdParam || v.id.includes(variantIdParam) || decodeShopifyId(v.id) === variantIdParam;
1790
- });
1791
- if (foundVariant) {
1792
- variant = foundVariant;
1793
- }
1674
+ const nddPrice = react.useMemo(() => {
1675
+ const weight = variant?.weight || 0;
1676
+ const nddMethod = paymentShippingMethods.find(({ __mode, weight_high, weight_low }) => {
1677
+ const fitWeight = (!weight_low || weight >= weight_low) && (!weight_high || weight <= weight_high);
1678
+ return __mode === "ndd" && fitWeight;
1679
+ });
1680
+ return nddMethod?.price || 0;
1681
+ }, [variant?.weight, paymentShippingMethods]);
1682
+ const tddPrice = react.useMemo(() => {
1683
+ const weight = variant?.weight || 0;
1684
+ const tddMethod = paymentShippingMethods.find(({ __mode, weight_high, weight_low }) => {
1685
+ const fitWeight = (!weight_low || weight >= weight_low) && (!weight_high || weight <= weight_high);
1686
+ return __mode === "tdd" && fitWeight;
1687
+ });
1688
+ return tddMethod?.price || 0;
1689
+ }, [variant?.weight, paymentShippingMethods]);
1690
+ const freeShippingMethods = react.useMemo(() => {
1691
+ const weight = variant?.weight || 0;
1692
+ let methods = plus_shipping?.shipping_methods?.filter(({ __mode, __plus, weight_low, weight_high }) => {
1693
+ if (__mode === "free" /* FREE */) {
1694
+ return true;
1794
1695
  }
1696
+ if (isPlus) {
1697
+ const hasCoupon = isPlus && __mode === "ndd" /* NDD */ && nddCoupon || isPlus && __mode === "tdd" /* TDD */ && (tddCoupon || nddCoupon);
1698
+ const fitWeight = (!weight_low || weight >= weight_low) && (!weight_high || weight <= weight_high);
1699
+ return hasCoupon && fitWeight && !__plus;
1700
+ } else {
1701
+ return __plus;
1702
+ }
1703
+ }) || [];
1704
+ if (isPlus) {
1705
+ methods = methods.sort((a, b) => {
1706
+ if (b.__mode === "free" /* FREE */) return -1;
1707
+ return 0;
1708
+ });
1795
1709
  }
1796
- if (variant) {
1797
- const newOptions = optionsConstructor(variant.selectedOptions);
1798
- setOptions(newOptions);
1799
- }
1800
- }, [product, sku]);
1801
- return [options, setOptions];
1802
- }
1803
- function decodeShopifyId2(gid) {
1804
- try {
1805
- const parts = gid.split("/");
1806
- return parts[parts.length - 1] || gid;
1807
- } catch {
1808
- return gid;
1809
- }
1810
- }
1811
- function useProductUrl(otherQuery) {
1812
- const { routerAdapter } = useShopify();
1813
- return react.useCallback(
1814
- ({ product, variant }) => {
1815
- if (!product) return "";
1816
- const queryParams = new URLSearchParams();
1817
- if (variant?.id) {
1818
- const variantId = decodeShopifyId2(variant.id);
1819
- if (variantId) {
1820
- queryParams.set("variant", variantId);
1710
+ return methods.map((method) => {
1711
+ let price = 0;
1712
+ let coupon;
1713
+ let disabled;
1714
+ if (method.__mode !== "free" /* FREE */) {
1715
+ switch (method.__mode) {
1716
+ case "tdd":
1717
+ price = tddPrice;
1718
+ coupon = tddCoupon || nddCoupon;
1719
+ break;
1720
+ case "ndd":
1721
+ price = nddPrice;
1722
+ coupon = nddCoupon;
1723
+ break;
1724
+ }
1725
+ disabled = selectedPlusMemberMode === "free";
1726
+ if (method.__mode === "ndd" /* NDD */) {
1727
+ disabled = disabled || nddOverweight;
1728
+ } else if (method.__mode === "tdd" /* TDD */) {
1729
+ disabled = disabled || tddOverweight;
1821
1730
  }
1822
1731
  }
1823
- if (otherQuery) {
1824
- Object.entries(otherQuery).forEach(([key, value]) => {
1825
- queryParams.set(key, value);
1826
- });
1732
+ return {
1733
+ ...method,
1734
+ id: method.__mode + method.__code,
1735
+ useCoupon: true,
1736
+ disabled,
1737
+ coupon,
1738
+ price
1739
+ };
1740
+ });
1741
+ }, [
1742
+ variant?.weight,
1743
+ plus_shipping?.shipping_methods,
1744
+ isPlus,
1745
+ nddCoupon,
1746
+ tddCoupon,
1747
+ selectedPlusMemberMode,
1748
+ tddPrice,
1749
+ nddPrice,
1750
+ nddOverweight,
1751
+ tddOverweight
1752
+ ]);
1753
+ return {
1754
+ freeShippingMethods,
1755
+ paymentShippingMethods,
1756
+ nddOverweight,
1757
+ tddOverweight,
1758
+ nddCoupon,
1759
+ tddCoupon,
1760
+ isLoadingCoupon: isLoading
1761
+ };
1762
+ }
1763
+ var useReplaceCartPlusMember = () => {
1764
+ const { plusMemberMetafields, selectedPlusMemberMode } = usePlusMemberContext();
1765
+ const { trigger: removeCartLines2 } = useRemoveCartLines();
1766
+ const { cart } = useCartContext();
1767
+ const plusMonthly = plusMemberMetafields?.plus_monthly_product;
1768
+ const plusAnnual = plusMemberMetafields?.plus_annual_product;
1769
+ const handler = react.useCallback(async () => {
1770
+ const plusMonthlyInCart = cart?.lineItems.find(
1771
+ (item) => item.variant?.sku === plusMonthly?.sku
1772
+ );
1773
+ const plusAnnualInCart = cart?.lineItems.find(
1774
+ (item) => item.variant?.sku === plusAnnual?.sku
1775
+ );
1776
+ if (selectedPlusMemberMode === "annual" /* ANNUAL */ && plusMonthlyInCart) {
1777
+ await removeCartLines2({
1778
+ lineIds: [plusMonthlyInCart.id]
1779
+ });
1780
+ } else if (selectedPlusMemberMode === "monthly" /* MONTHLY */ && plusAnnualInCart) {
1781
+ await removeCartLines2({
1782
+ lineIds: [plusAnnualInCart.id]
1783
+ });
1784
+ }
1785
+ }, [
1786
+ cart?.lineItems,
1787
+ selectedPlusMemberMode,
1788
+ plusMonthly?.sku,
1789
+ plusAnnual?.sku,
1790
+ removeCartLines2
1791
+ ]);
1792
+ return handler;
1793
+ };
1794
+ var usePlusMemberCheckoutCustomAttributes = ({
1795
+ disableShipping = false,
1796
+ isPresaleContains = false
1797
+ }) => {
1798
+ const { profile, selectedShippingMethod, selectedPlusMemberMode } = usePlusMemberContext();
1799
+ return react.useMemo(() => {
1800
+ const checkoutCustomAttributes = [
1801
+ {
1802
+ key: "_last_url",
1803
+ value: typeof window !== "undefined" ? window.location.origin + window.location.pathname : ""
1827
1804
  }
1828
- const queryString = queryParams.toString();
1829
- const path = `/products/${product.handle}${queryString ? `?${queryString}` : ""}`;
1830
- if (routerAdapter?.getLocalizedPath) {
1831
- return routerAdapter.getLocalizedPath(path);
1805
+ ];
1806
+ checkoutCustomAttributes.push({
1807
+ key: "_checkout_delivery_custom",
1808
+ value: JSON.stringify({
1809
+ allow_nextday_delivery: true,
1810
+ allow_thirdday_delivery: true,
1811
+ selected_delivery_option: {
1812
+ code: selectedShippingMethod?.__code,
1813
+ mode: selectedShippingMethod?.__mode
1814
+ },
1815
+ is_presale: isPresaleContains,
1816
+ discount_code: selectedShippingMethod?.coupon ? [selectedShippingMethod.coupon] : [],
1817
+ plus_type: profile?.isPlus ? "free" /* FREE */ : selectedPlusMemberMode,
1818
+ is_prime: profile?.isPlus
1819
+ })
1820
+ });
1821
+ if (disableShipping) {
1822
+ checkoutCustomAttributes.push({
1823
+ key: "_hide_shipping",
1824
+ value: "true"
1825
+ });
1826
+ }
1827
+ return checkoutCustomAttributes;
1828
+ }, [profile, selectedShippingMethod, selectedPlusMemberMode, isPresaleContains]);
1829
+ };
1830
+ function useRemoveCartLines(options) {
1831
+ const { client, locale, cartCookieAdapter } = useShopify();
1832
+ const { mutateCart, metafieldIdentifiers } = useCartContext();
1833
+ const removeLines = react.useCallback(
1834
+ async (_key, { arg }) => {
1835
+ const { autoRemoveInvalidCodes = true, onCodesRemoved, cartId, lineIds } = arg;
1836
+ let updatedCart = await shopifySdk.removeCartLines(client, {
1837
+ cartId,
1838
+ lineIds,
1839
+ metafieldIdentifiers,
1840
+ cookieAdapter: cartCookieAdapter
1841
+ });
1842
+ if (updatedCart && autoRemoveInvalidCodes) {
1843
+ const unApplicableCodes = updatedCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
1844
+ if (unApplicableCodes.length > 0) {
1845
+ if (onCodesRemoved) {
1846
+ const handledCart = await onCodesRemoved(updatedCart, unApplicableCodes);
1847
+ if (handledCart) {
1848
+ updatedCart = handledCart;
1849
+ }
1850
+ } else {
1851
+ updatedCart = await shopifySdk.updateCartCodes(client, {
1852
+ cartId: updatedCart.id,
1853
+ discountCodes: updatedCart.discountCodes.filter((item) => item.applicable).map((item) => item.code),
1854
+ metafieldIdentifiers,
1855
+ cookieAdapter: cartCookieAdapter
1856
+ }) || updatedCart;
1857
+ }
1858
+ }
1832
1859
  }
1833
- return path;
1860
+ if (updatedCart) {
1861
+ mutateCart(updatedCart);
1862
+ }
1863
+ return updatedCart;
1834
1864
  },
1835
- [routerAdapter, otherQuery]
1865
+ [client, locale, cartCookieAdapter, mutateCart, metafieldIdentifiers]
1836
1866
  );
1867
+ return useSWRMutation__default.default("remove-cart-lines", removeLines, options);
1837
1868
  }
1838
- function decodeShopifyId3(gid) {
1839
- try {
1840
- const parts = gid.split("/");
1841
- return parts[parts.length - 1] || gid;
1842
- } catch {
1843
- return gid;
1844
- }
1845
- }
1846
- function useUpdateVariantQuery(variant) {
1869
+
1870
+ // src/hooks/member/plus/use-auto-remove-plus-member-in-cart.ts
1871
+ function useAutoRemovePlusMemberInCart({
1872
+ cart,
1873
+ profile,
1874
+ memberSetting
1875
+ }) {
1876
+ const { plus_monthly_product, plus_annual_product } = memberSetting || {};
1877
+ const { trigger: removeCartLines2 } = useRemoveCartLines();
1847
1878
  react.useEffect(() => {
1848
- if (!variant || typeof window === "undefined") {
1849
- return;
1879
+ if (!cart || !plus_monthly_product || !plus_annual_product) return;
1880
+ const removePlusProduct = async (productType) => {
1881
+ if (!productType) return;
1882
+ const product = cart.lineItems?.find(
1883
+ (item) => item.product?.handle === productType?.handle && item.variant?.sku === productType?.sku
1884
+ );
1885
+ if (product) {
1886
+ await removeCartLines2({
1887
+ lineIds: [product.id]
1888
+ });
1889
+ }
1890
+ };
1891
+ if (profile?.isMonthlyPlus) {
1892
+ removePlusProduct(plus_monthly_product);
1850
1893
  }
1851
- const searchParams = new URLSearchParams(window.location.search);
1852
- const currentVariantId = searchParams.get("variant");
1853
- const newVariantId = decodeShopifyId3(variant.id);
1854
- if (newVariantId && currentVariantId !== newVariantId) {
1855
- searchParams.set("variant", newVariantId);
1856
- const newUrl = `${window.location.pathname}?${searchParams.toString()}${window.location.hash}`;
1857
- window.history.replaceState({}, "", newUrl);
1894
+ if (profile?.isAnnualPlus) {
1895
+ removePlusProduct(plus_annual_product);
1858
1896
  }
1859
- }, [variant]);
1897
+ }, [cart, plus_annual_product, plus_monthly_product, profile, removeCartLines2]);
1860
1898
  }
1861
- function getVariantMediaList({
1862
- product,
1863
- variant
1899
+ function hasPlusMemberInCart({
1900
+ memberSetting,
1901
+ cart
1864
1902
  }) {
1865
- if (variant.image?.url) {
1866
- const variantMediaId = variant.image.url;
1867
- const variantMedia = product.media.filter((media) => {
1868
- if (media.mediaContentType === "IMAGE" && media.previewImage) {
1869
- return media.previewImage?.url === variantMediaId;
1870
- }
1871
- return false;
1872
- });
1873
- if (variantMedia.length > 0) {
1874
- const otherMedia = product.media.filter((media) => {
1875
- if (media.mediaContentType === "IMAGE" && media.previewImage) {
1876
- return media.previewImage.url !== variantMediaId;
1877
- }
1878
- return true;
1879
- });
1880
- return [...variantMedia, ...otherMedia];
1881
- }
1903
+ const { plus_monthly_product, plus_annual_product } = memberSetting || {};
1904
+ if (!cart?.lineItems) {
1905
+ return {
1906
+ hasPlusMember: false,
1907
+ hasMonthlyPlus: false,
1908
+ hasAnnualPlus: false
1909
+ };
1882
1910
  }
1883
- return product.media;
1884
- }
1885
- function useVariantMedia({
1886
- product,
1887
- variant
1888
- }) {
1889
- const [imageList, setImageList] = react.useState([]);
1890
- const [sceneList, setSceneList] = react.useState([]);
1891
- const [videoList, setVideoList] = react.useState([]);
1892
- react.useEffect(() => {
1893
- if (!product || !variant) {
1894
- setImageList([]);
1895
- setSceneList([]);
1896
- setVideoList([]);
1897
- return;
1898
- }
1899
- const mediaList = getVariantMediaList({ product, variant });
1900
- const images = mediaList.filter((media) => media.mediaContentType === "IMAGE");
1901
- const videos = mediaList.filter(
1902
- (media) => media.mediaContentType === "VIDEO" || media.mediaContentType === "EXTERNAL_VIDEO"
1903
- );
1904
- setImageList(images.length > 0 && images[0] ? [images[0]] : []);
1905
- setSceneList(images.length > 1 ? images.slice(1) : []);
1906
- setVideoList(videos);
1907
- }, [product, variant]);
1908
- return {
1909
- productList: imageList,
1910
- sceneList,
1911
- videoList
1912
- };
1913
- }
1914
- function useCollection(options = {}) {
1915
- const { client, locale } = useShopify();
1916
- const { handle, metafieldIdentifiers, ...swrOptions } = options;
1917
- return useSWR__default.default(
1918
- handle ? ["collection", locale, handle, metafieldIdentifiers] : null,
1919
- () => shopifySdk.getCollection(client, {
1920
- handle,
1921
- locale,
1922
- metafieldIdentifiers
1923
- }),
1924
- swrOptions
1925
- );
1926
- }
1927
- function useAllCollections(options = {}) {
1928
- const { client, locale } = useShopify();
1929
- const { first, query, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
1930
- return useSWR__default.default(
1931
- ["all-collections", locale, first, query, sortKey, reverse, metafieldIdentifiers],
1932
- () => shopifySdk.getAllCollections(client, {
1933
- locale,
1934
- first,
1935
- query,
1936
- sortKey,
1937
- reverse,
1938
- metafieldIdentifiers
1939
- }),
1940
- swrOptions
1941
- );
1942
- }
1943
- function useCollections(options = {}) {
1944
- const { client, locale } = useShopify();
1945
- const { first, after, query, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
1946
- return useSWR__default.default(
1947
- ["collections", locale, first, after, query, sortKey, reverse, metafieldIdentifiers],
1948
- () => shopifySdk.getCollections(client, {
1949
- locale,
1950
- first,
1951
- after,
1952
- query,
1953
- sortKey,
1954
- reverse,
1955
- metafieldIdentifiers
1956
- }),
1957
- swrOptions
1911
+ const monthlyPlusItem = cart.lineItems.find(
1912
+ (item) => item.product?.handle === plus_monthly_product?.handle && item.variant?.sku === plus_monthly_product?.sku
1958
1913
  );
1959
- }
1960
- function useBlog(options = {}) {
1961
- const { client, locale } = useShopify();
1962
- const { handle, metafieldIdentifiers, ...swrOptions } = options;
1963
- return useSWR__default.default(
1964
- handle ? ["blog", locale, handle, metafieldIdentifiers] : null,
1965
- () => shopifySdk.getBlog(client, { handle, locale, metafieldIdentifiers }),
1966
- swrOptions
1914
+ const annualPlusItem = cart.lineItems.find(
1915
+ (item) => item.product?.handle === plus_annual_product?.handle && item.variant?.sku === plus_annual_product?.sku
1967
1916
  );
1917
+ const hasMonthlyPlus = !!monthlyPlusItem;
1918
+ const hasAnnualPlus = !!annualPlusItem;
1919
+ const hasPlusMember = hasMonthlyPlus || hasAnnualPlus;
1920
+ return {
1921
+ hasPlusMember,
1922
+ hasMonthlyPlus,
1923
+ hasAnnualPlus,
1924
+ monthlyPlusItem,
1925
+ annualPlusItem
1926
+ };
1968
1927
  }
1969
- function useAllBlogs(options = {}) {
1970
- const { client, locale } = useShopify();
1971
- const { first, query, metafieldIdentifiers, ...swrOptions } = options;
1972
- return useSWR__default.default(
1973
- ["all-blogs", locale, first, query, metafieldIdentifiers],
1974
- () => shopifySdk.getAllBlogs(client, {
1975
- locale,
1976
- first,
1977
- query,
1978
- metafieldIdentifiers
1928
+ function useHasPlusMemberInCart({
1929
+ memberSetting,
1930
+ cart
1931
+ }) {
1932
+ return react.useMemo(
1933
+ () => hasPlusMemberInCart({
1934
+ memberSetting,
1935
+ cart
1979
1936
  }),
1980
- swrOptions
1937
+ [memberSetting, cart]
1981
1938
  );
1982
1939
  }
1983
- function useArticle(options = {}) {
1984
- const { client, locale } = useShopify();
1985
- const { blogHandle, articleHandle, metafieldIdentifiers, ...swrOptions } = options;
1986
- return useSWR__default.default(
1987
- blogHandle && articleHandle ? ["article", locale, blogHandle, articleHandle, metafieldIdentifiers] : null,
1988
- () => shopifySdk.getArticle(client, {
1989
- blogHandle,
1990
- articleHandle,
1991
- locale,
1992
- metafieldIdentifiers
1993
- }),
1994
- swrOptions
1995
- );
1940
+ function hasPlusMemberInLines({
1941
+ memberSetting,
1942
+ lines
1943
+ }) {
1944
+ const { plus_monthly_product, plus_annual_product } = memberSetting || {};
1945
+ if (!lines || lines.length === 0) {
1946
+ return {
1947
+ hasPlusMember: false,
1948
+ hasMonthlyPlus: false,
1949
+ hasAnnualPlus: false
1950
+ };
1951
+ }
1952
+ const monthlyPlusLine = lines.find((line) => {
1953
+ const variantHandle = line.variant?.product?.handle;
1954
+ const variantSku = line.variant?.sku;
1955
+ return variantHandle === plus_monthly_product?.handle && variantSku === plus_monthly_product?.sku;
1956
+ });
1957
+ const annualPlusLine = lines.find((line) => {
1958
+ const variantHandle = line.variant?.product?.handle;
1959
+ const variantSku = line.variant?.sku;
1960
+ return variantHandle === plus_annual_product?.handle && variantSku === plus_annual_product?.sku;
1961
+ });
1962
+ const hasMonthlyPlus = !!monthlyPlusLine;
1963
+ const hasAnnualPlus = !!annualPlusLine;
1964
+ const hasPlusMember = hasMonthlyPlus || hasAnnualPlus;
1965
+ return {
1966
+ hasPlusMember,
1967
+ hasMonthlyPlus,
1968
+ hasAnnualPlus,
1969
+ monthlyPlusLine,
1970
+ annualPlusLine
1971
+ };
1996
1972
  }
1997
- function useArticles(options = {}) {
1998
- const { client, locale } = useShopify();
1999
- const { first, query, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
2000
- return useSWR__default.default(
2001
- ["articles", locale, first, query, sortKey, reverse, metafieldIdentifiers],
2002
- () => shopifySdk.getArticles(client, {
2003
- locale,
2004
- first,
2005
- query,
2006
- sortKey,
2007
- reverse,
2008
- metafieldIdentifiers
1973
+ function useHasPlusMemberInLines({
1974
+ memberSetting,
1975
+ lines
1976
+ }) {
1977
+ return react.useMemo(
1978
+ () => hasPlusMemberInLines({
1979
+ memberSetting,
1980
+ lines
2009
1981
  }),
2010
- swrOptions
1982
+ [memberSetting, lines]
2011
1983
  );
2012
1984
  }
2013
- function useArticlesInBlog(options = {}) {
2014
- const { client, locale } = useShopify();
2015
- const { blogHandle, first, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
2016
- return useSWR__default.default(
2017
- blogHandle ? ["articles-in-blog", locale, blogHandle, first, sortKey, reverse, metafieldIdentifiers] : null,
2018
- () => shopifySdk.getArticlesInBlog(client, {
2019
- blogHandle,
2020
- locale,
2021
- first,
2022
- sortKey,
2023
- reverse,
2024
- metafieldIdentifiers
2025
- }),
2026
- swrOptions
2027
- );
1985
+ function usePlusMemberNeedAddToCart({
1986
+ cart,
1987
+ profile
1988
+ }) {
1989
+ const { selectedPlusMemberMode, selectedPlusMemberVariant, plusMemberMetafields } = usePlusMemberContext();
1990
+ const { hasMonthlyPlus, hasAnnualPlus } = useHasPlusMemberInCart({
1991
+ memberSetting: plusMemberMetafields,
1992
+ cart
1993
+ });
1994
+ const plusMemberVariant = react.useMemo(() => {
1995
+ if (!selectedPlusMemberVariant || selectedPlusMemberMode === "free" /* FREE */) {
1996
+ return void 0;
1997
+ }
1998
+ if (selectedPlusMemberMode === "monthly" /* MONTHLY */ && hasMonthlyPlus) {
1999
+ return void 0;
2000
+ }
2001
+ if (selectedPlusMemberMode === "annual" /* ANNUAL */ && hasAnnualPlus) {
2002
+ return void 0;
2003
+ }
2004
+ if (profile?.isMonthlyPlus && selectedPlusMemberMode === "monthly" /* MONTHLY */) {
2005
+ return void 0;
2006
+ }
2007
+ if (profile?.isAnnualPlus && selectedPlusMemberMode === "annual" /* ANNUAL */) {
2008
+ return void 0;
2009
+ }
2010
+ return selectedPlusMemberVariant;
2011
+ }, [selectedPlusMemberMode, selectedPlusMemberVariant, hasMonthlyPlus, hasAnnualPlus]);
2012
+ return plusMemberVariant;
2028
2013
  }
2029
- async function performSearch(client, locale, searchQuery, first = 20, types = ["PRODUCT", "ARTICLE", "PAGE"]) {
2030
- if (!searchQuery) {
2031
- return void 0;
2032
- }
2033
- const query = (
2034
- /* GraphQL */
2035
- `
2036
- query search($query: String!, $first: Int!, $types: [SearchType!])
2037
- @inContext(language: $language) {
2038
- search(query: $query, first: $first, types: $types, unavailableProducts: HIDE) {
2039
- totalCount
2040
- edges {
2041
- node {
2042
- ... on Article {
2043
- __typename
2044
- id
2045
- handle
2046
- title
2047
- excerpt
2048
- image {
2049
- url
2050
- altText
2051
- }
2052
- }
2053
- ... on Page {
2054
- __typename
2055
- id
2056
- handle
2057
- title
2058
- }
2059
- ... on Product {
2060
- __typename
2061
- id
2062
- handle
2063
- title
2064
- description
2065
- featuredImage {
2066
- url
2067
- altText
2014
+ var PlusMemberProvider = ({
2015
+ variant,
2016
+ product,
2017
+ memberSetting,
2018
+ initialSelectedPlusMemberMode = "free",
2019
+ profile,
2020
+ children
2021
+ }) => {
2022
+ const [selectedPlusMemberMode, setSelectedPlusMemberMode] = react.useState(
2023
+ initialSelectedPlusMemberMode
2024
+ );
2025
+ const [selectedShippingMethod, setSelectedShippingMethod] = react.useState();
2026
+ const [showMoreShippingMethod, setShowMoreShippingMethod] = react.useState(false);
2027
+ const [showPlusMemberBenefit, setShowPlusMemberBenefit] = react.useState(false);
2028
+ const shippingMethodsContext = useShippingMethods({
2029
+ variant,
2030
+ plusMemberMetafields: memberSetting,
2031
+ selectedPlusMemberMode,
2032
+ profile
2033
+ });
2034
+ const { monthlyVariant, annualVariant } = usePlusMemberVariants({
2035
+ memberSetting
2036
+ });
2037
+ const selectedPlusMemberVariant = react.useMemo(() => {
2038
+ if (selectedPlusMemberMode === "free" /* FREE */) {
2039
+ return void 0;
2040
+ }
2041
+ return selectedPlusMemberMode === "monthly" /* MONTHLY */ ? monthlyVariant : annualVariant;
2042
+ }, [monthlyVariant, annualVariant, selectedPlusMemberMode]);
2043
+ return /* @__PURE__ */ jsxRuntime.jsx(
2044
+ PlusMemberContext.Provider,
2045
+ {
2046
+ value: {
2047
+ variant,
2048
+ plusMemberMetafields: memberSetting,
2049
+ selectedPlusMemberMode,
2050
+ setSelectedPlusMemberMode,
2051
+ selectedShippingMethod,
2052
+ setSelectedShippingMethod,
2053
+ shippingMethodsContext,
2054
+ showMoreShippingMethod,
2055
+ setShowMoreShippingMethod,
2056
+ selectedPlusMemberVariant,
2057
+ product,
2058
+ showPlusMemberBenefit,
2059
+ setShowPlusMemberBenefit,
2060
+ profile
2061
+ },
2062
+ children
2063
+ }
2064
+ );
2065
+ };
2066
+
2067
+ // src/hooks/cart/use-add-to-cart.ts
2068
+ function useAddToCart({ withTrack = true } = {}, swrOptions) {
2069
+ const { client, config, locale, cartCookieAdapter, userAdapter, performanceAdapter } = useShopify();
2070
+ const { cart, addCustomAttributes, memberSetting, profile, customer } = useCartContext();
2071
+ const { trigger: applyCartCodes } = useApplyCartCodes();
2072
+ const { trigger: removeInvalidCodes } = useRemoveCartCodes();
2073
+ const { trigger: addCartLines2 } = useAddCartLines();
2074
+ const { trigger: createCart4 } = useCreateCart({
2075
+ updateCookie: true
2076
+ });
2077
+ const { hasPlusMember } = useHasPlusMemberInCart({
2078
+ memberSetting,
2079
+ cart
2080
+ });
2081
+ const { attributes: cartAttributes } = useCartAttributes({
2082
+ profile,
2083
+ customer,
2084
+ cart,
2085
+ memberType: hasPlusMember ? "2" : String(profile?.memberType ?? 0)
2086
+ });
2087
+ const addToCart = react.useCallback(
2088
+ async (_key, { arg }) => {
2089
+ const {
2090
+ lineItems,
2091
+ cartId: providedCartId,
2092
+ discountCodes,
2093
+ gtmParams = {},
2094
+ buyerIdentity,
2095
+ needCreateCart = false,
2096
+ onCodesInvalid,
2097
+ replaceExistingCodes,
2098
+ customAttributes
2099
+ } = arg;
2100
+ if (!lineItems || lineItems.length === 0) {
2101
+ return;
2102
+ }
2103
+ performanceAdapter?.addToCartStart();
2104
+ const linesWithFunctionAttributes = getLinesWithAttributes({ cart, lineItems });
2105
+ const lines = linesWithFunctionAttributes.map((item) => ({
2106
+ merchandiseId: item.variant?.id || "",
2107
+ quantity: item.quantity || 1,
2108
+ attributes: item.attributes,
2109
+ sellingPlanId: item.sellingPlanId
2110
+ })).filter((item) => item.merchandiseId && item.quantity);
2111
+ if (lines.length === 0) {
2112
+ return;
2113
+ }
2114
+ let cartId = needCreateCart ? void 0 : providedCartId || cart?.id;
2115
+ let resultCart = null;
2116
+ if (!cartId) {
2117
+ resultCart = await createCart4({
2118
+ lines,
2119
+ buyerIdentity,
2120
+ discountCodes,
2121
+ customAttributes: [...cartAttributes, ...customAttributes || []]
2122
+ // 初次加购时,就把所有 cart attributes 带上
2123
+ });
2124
+ } else {
2125
+ resultCart = await addCartLines2({
2126
+ cartId,
2127
+ lines
2128
+ });
2129
+ console.log("npm addCartLines resultCart", resultCart);
2130
+ if (resultCart && resultCart.discountCodes && resultCart.discountCodes.length > 0) {
2131
+ const unapplicableCodes = resultCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
2132
+ if (unapplicableCodes.length > 0) {
2133
+ if (onCodesInvalid) {
2134
+ const handledCart = await onCodesInvalid(resultCart, unapplicableCodes);
2135
+ if (handledCart) {
2136
+ resultCart = handledCart;
2068
2137
  }
2138
+ } else {
2139
+ await removeInvalidCodes({
2140
+ discountCodes: unapplicableCodes
2141
+ });
2069
2142
  }
2070
2143
  }
2071
2144
  }
2072
- pageInfo {
2073
- hasNextPage
2074
- endCursor
2145
+ if (resultCart && discountCodes && discountCodes.length > 0) {
2146
+ applyCartCodes({
2147
+ replaceExistingCodes,
2148
+ discountCodes
2149
+ });
2150
+ }
2151
+ if (customAttributes && customAttributes.length > 0) {
2152
+ addCustomAttributes(customAttributes);
2075
2153
  }
2076
2154
  }
2077
- }
2078
- `
2155
+ if (withTrack) {
2156
+ trackAddToCartGA({
2157
+ lineItems,
2158
+ gtmParams: { ...gtmParams, brand: config.getBrand() }
2159
+ });
2160
+ trackAddToCartFBQ({ lineItems });
2161
+ }
2162
+ performanceAdapter?.addToCartEnd();
2163
+ return resultCart;
2164
+ },
2165
+ [
2166
+ client,
2167
+ locale,
2168
+ cartCookieAdapter,
2169
+ userAdapter,
2170
+ cart,
2171
+ withTrack,
2172
+ performanceAdapter,
2173
+ createCart4,
2174
+ addCartLines2,
2175
+ applyCartCodes,
2176
+ removeInvalidCodes,
2177
+ addCustomAttributes,
2178
+ config
2179
+ ]
2079
2180
  );
2080
- const data = await client.query(query, {
2081
- query: searchQuery,
2082
- first,
2083
- types
2084
- });
2085
- if (!data || !data.search) {
2086
- return void 0;
2087
- }
2088
- const items = data.search.edges?.map((edge) => {
2089
- const node = edge.node;
2090
- const item = {
2091
- type: node.__typename.toUpperCase(),
2092
- id: node.id,
2093
- handle: node.handle,
2094
- title: node.title
2095
- };
2096
- if (node.__typename === "Product") {
2097
- item.description = node.description;
2098
- item.image = node.featuredImage ? {
2099
- url: node.featuredImage.url,
2100
- altText: node.featuredImage.altText
2101
- } : void 0;
2102
- } else if (node.__typename === "Article") {
2103
- item.description = node.excerpt;
2104
- item.image = node.image ? {
2105
- url: node.image.url,
2106
- altText: node.image.altText
2107
- } : void 0;
2108
- }
2109
- return item;
2110
- }) || [];
2111
- return {
2112
- items,
2113
- totalCount: data.search.totalCount || 0,
2114
- pageInfo: data.search.pageInfo
2115
- };
2181
+ return useSWRMutation__default.default("add-to-cart", addToCart, swrOptions);
2116
2182
  }
2117
- function useSearch(options = {}) {
2118
- const { client, locale } = useShopify();
2119
- const { query, first = 20, types = ["PRODUCT", "ARTICLE", "PAGE"], ...swrOptions } = options;
2120
- return useSWR__default.default(
2121
- query ? ["search", locale, query, first, types] : null,
2122
- () => performSearch(client, locale, query, first, types),
2123
- swrOptions
2183
+ function useUpdateCartLines(options) {
2184
+ const { client, locale, cartCookieAdapter } = useShopify();
2185
+ const { mutateCart, metafieldIdentifiers } = useCartContext();
2186
+ const updateLines = react.useCallback(
2187
+ async (_key, { arg }) => {
2188
+ const updatedCart = await shopifySdk.updateCartLines(client, {
2189
+ ...arg,
2190
+ metafieldIdentifiers,
2191
+ cookieAdapter: cartCookieAdapter
2192
+ });
2193
+ if (updatedCart) {
2194
+ mutateCart(updatedCart);
2195
+ }
2196
+ console.log("use-update-cart-lines updatedCart", metafieldIdentifiers, updatedCart);
2197
+ return updatedCart;
2198
+ },
2199
+ [client, locale, cartCookieAdapter, mutateCart, metafieldIdentifiers]
2124
2200
  );
2201
+ return useSWRMutation__default.default("update-cart-lines", updateLines, options);
2125
2202
  }
2126
- async function getSiteInfo(client, locale, metafieldIdentifiers) {
2127
- const hasMetafields = metafieldIdentifiers && metafieldIdentifiers.length > 0;
2128
- const query = (
2129
- /* GraphQL */
2130
- `
2131
- query getSiteInfo(
2132
- ${hasMetafields ? "$shopMetafieldIdentifiers: [HasMetafieldsIdentifier!]!" : ""}
2133
- ) @inContext(language: $language) {
2134
- shop {
2135
- name
2136
- description
2137
- primaryDomain {
2138
- url
2139
- host
2203
+ function useUpdateCartAttributes({
2204
+ mutate,
2205
+ metafieldIdentifiers,
2206
+ disabled = false,
2207
+ swrOptions
2208
+ }) {
2209
+ const { client, locale, cartCookieAdapter } = useShopify();
2210
+ const updateAttributes = react.useCallback(
2211
+ async (_key, { arg }) => {
2212
+ if (disabled) {
2213
+ return void 0;
2214
+ }
2215
+ const updatedCart = await shopifySdk.updateCartAttributes(client, {
2216
+ ...arg,
2217
+ metafieldIdentifiers,
2218
+ cookieAdapter: cartCookieAdapter
2219
+ });
2220
+ if (updatedCart) {
2221
+ mutate(updatedCart);
2222
+ }
2223
+ return updatedCart;
2224
+ },
2225
+ [client, locale, cartCookieAdapter, mutate, metafieldIdentifiers, disabled]
2226
+ );
2227
+ return useSWRMutation__default.default("update-cart-attributes", updateAttributes, swrOptions);
2228
+ }
2229
+ function useBuyNow({ withTrack = true } = {}, swrOptions) {
2230
+ const { client, config, locale, cartCookieAdapter, userAdapter } = useShopify();
2231
+ const { profile, customer, memberSetting } = useCartContext();
2232
+ const isLoggedIn = userAdapter?.isLoggedIn || false;
2233
+ const buyNow = react.useCallback(
2234
+ async (_key, { arg }) => {
2235
+ const {
2236
+ lineItems,
2237
+ discountCodes,
2238
+ gtmParams = {},
2239
+ buyerIdentity,
2240
+ fbqTrackConfig,
2241
+ customAttributes,
2242
+ metafieldIdentifiers,
2243
+ redirectToCheckout = true
2244
+ } = arg;
2245
+ if (!lineItems || lineItems.length === 0) {
2246
+ return;
2247
+ }
2248
+ const { hasPlusMember } = hasPlusMemberInLines({
2249
+ memberSetting,
2250
+ lines: lineItems
2251
+ });
2252
+ const memberType = hasPlusMember ? "2" : String(profile?.memberType ?? 0);
2253
+ const cartAttributes = getCartAttributes({
2254
+ profile,
2255
+ customer,
2256
+ memberType,
2257
+ currentUrl: window.location.href
2258
+ });
2259
+ const linesWithFunctionAttributes = getLinesWithAttributes({
2260
+ lineItems
2261
+ });
2262
+ const lines = linesWithFunctionAttributes.map((item) => ({
2263
+ merchandiseId: item.variant?.id || "",
2264
+ quantity: item.quantity || 1,
2265
+ attributes: item.attributes,
2266
+ sellingPlanId: item.sellingPlanId
2267
+ })).filter((item) => item.merchandiseId);
2268
+ if (lines.length === 0) {
2269
+ return;
2270
+ }
2271
+ const resultCart = await shopifySdk.createCart(client, {
2272
+ lines,
2273
+ metafieldIdentifiers,
2274
+ cookieAdapter: cartCookieAdapter,
2275
+ buyerIdentity,
2276
+ discountCodes,
2277
+ customAttributes: [...cartAttributes, ...customAttributes || []]
2278
+ });
2279
+ if (!resultCart) {
2280
+ throw new Error("Failed to create cart for buy now");
2281
+ }
2282
+ if (withTrack && resultCart.lineItems) {
2283
+ trackBuyNowGA({
2284
+ lineItems,
2285
+ gtmParams: { ...gtmParams, brand: config.getBrand() }
2286
+ });
2287
+ if (fbqTrackConfig) {
2288
+ trackBuyNowFBQ({ trackConfig: fbqTrackConfig });
2140
2289
  }
2141
- brand {
2142
- logo {
2143
- image {
2144
- url
2145
- }
2146
- }
2147
- colors {
2148
- primary {
2149
- background
2150
- }
2151
- secondary {
2152
- background
2153
- }
2290
+ }
2291
+ if (redirectToCheckout) {
2292
+ if (resultCart.url) {
2293
+ if (typeof window !== "undefined") {
2294
+ window.location.href = resultCart.url;
2154
2295
  }
2296
+ } else {
2297
+ throw new Error("Failed to get checkout URL");
2155
2298
  }
2156
- ${hasMetafields ? "metafields(identifiers: $shopMetafieldIdentifiers) { key value }" : ""}
2157
2299
  }
2158
- }
2159
- `
2300
+ return resultCart;
2301
+ },
2302
+ [client, locale, isLoggedIn, cartCookieAdapter, withTrack, customer, profile, memberSetting]
2160
2303
  );
2161
- const variables = {};
2162
- if (hasMetafields) {
2163
- variables.shopMetafieldIdentifiers = metafieldIdentifiers;
2164
- }
2165
- const data = await client.query(query, variables);
2166
- if (!data || !data.shop) {
2167
- return void 0;
2168
- }
2169
- const shop = data.shop;
2170
- const metafields = shop.metafields?.reduce((acc, mf) => {
2171
- if (mf && mf.key) {
2172
- acc[mf.key] = mf.value;
2173
- }
2174
- return acc;
2175
- }, {});
2176
- return {
2177
- name: shop.name,
2178
- description: shop.description,
2179
- primaryDomain: shop.primaryDomain,
2180
- brand: shop.brand ? {
2181
- logo: shop.brand.logo,
2182
- colors: shop.brand.colors ? {
2183
- primary: shop.brand.colors.primary?.background,
2184
- secondary: shop.brand.colors.secondary?.background
2185
- } : void 0
2186
- } : void 0,
2187
- metafields
2188
- };
2304
+ return useSWRMutation__default.default("buy-now", buyNow, swrOptions);
2189
2305
  }
2190
- function useSite(options = {}) {
2306
+
2307
+ // src/hooks/cart/types/price-discount.ts
2308
+ var PriceDiscountType = /* @__PURE__ */ ((PriceDiscountType2) => {
2309
+ PriceDiscountType2[PriceDiscountType2["PERCENTAGE"] = 1] = "PERCENTAGE";
2310
+ PriceDiscountType2[PriceDiscountType2["FIXED_AMOUNT"] = 2] = "FIXED_AMOUNT";
2311
+ return PriceDiscountType2;
2312
+ })(PriceDiscountType || {});
2313
+ var PriceBasePriceType = /* @__PURE__ */ ((PriceBasePriceType2) => {
2314
+ PriceBasePriceType2[PriceBasePriceType2["MIN_DISCOUNTED_PRICE"] = 1] = "MIN_DISCOUNTED_PRICE";
2315
+ PriceBasePriceType2[PriceBasePriceType2["MIN_TOTAL_PRICE"] = 2] = "MIN_TOTAL_PRICE";
2316
+ return PriceBasePriceType2;
2317
+ })(PriceBasePriceType || {});
2318
+ function useProduct(options = {}) {
2191
2319
  const { client, locale } = useShopify();
2192
- const { metafieldIdentifiers, ...swrOptions } = options;
2320
+ const { handle, metafieldIdentifiers, ...swrOptions } = options;
2193
2321
  return useSWR__default.default(
2194
- ["site", locale, metafieldIdentifiers],
2195
- () => getSiteInfo(client, locale, metafieldIdentifiers),
2322
+ handle ? ["product", locale, handle, metafieldIdentifiers] : null,
2323
+ () => shopifySdk.getProduct(client, {
2324
+ handle,
2325
+ locale,
2326
+ metafieldIdentifiers
2327
+ }),
2196
2328
  swrOptions
2197
2329
  );
2198
2330
  }
2199
-
2200
- // src/hooks/member/plus/types.ts
2201
- var PLUS_MEMBER_TYPE = /* @__PURE__ */ ((PLUS_MEMBER_TYPE2) => {
2202
- PLUS_MEMBER_TYPE2[PLUS_MEMBER_TYPE2["FREE"] = 0] = "FREE";
2203
- PLUS_MEMBER_TYPE2[PLUS_MEMBER_TYPE2["MONTHLY"] = 1] = "MONTHLY";
2204
- PLUS_MEMBER_TYPE2[PLUS_MEMBER_TYPE2["ANNUAL"] = 2] = "ANNUAL";
2205
- return PLUS_MEMBER_TYPE2;
2206
- })(PLUS_MEMBER_TYPE || {});
2207
- var PlusMemberMode = /* @__PURE__ */ ((PlusMemberMode2) => {
2208
- PlusMemberMode2["MONTHLY"] = "monthly";
2209
- PlusMemberMode2["ANNUAL"] = "annual";
2210
- return PlusMemberMode2;
2211
- })(PlusMemberMode || {});
2212
- var DeliveryPlusType = /* @__PURE__ */ ((DeliveryPlusType2) => {
2213
- DeliveryPlusType2["FREE"] = "free";
2214
- DeliveryPlusType2["MONTHLY"] = "monthly";
2215
- DeliveryPlusType2["ANNUAL"] = "annual";
2216
- return DeliveryPlusType2;
2217
- })(DeliveryPlusType || {});
2218
- var ShippingMethodMode = /* @__PURE__ */ ((ShippingMethodMode2) => {
2219
- ShippingMethodMode2["FREE"] = "free";
2220
- ShippingMethodMode2["TDD"] = "tdd";
2221
- ShippingMethodMode2["NDD"] = "ndd";
2222
- return ShippingMethodMode2;
2223
- })(ShippingMethodMode || {});
2224
- var createInitialValue = () => ({
2225
- zipCode: "",
2226
- plusMemberMetafields: {},
2227
- setZipCode: () => {
2228
- },
2229
- allowNextDayDelivery: false,
2230
- setAllowNextDayDelivery: () => {
2231
- },
2232
- allowThirdDayDelivery: false,
2233
- setAllowThirdDayDelivery: () => {
2234
- },
2235
- selectedPlusMemberMode: "free",
2236
- setSelectedPlusMemberMode: () => {
2237
- },
2238
- showAreaCheckModal: false,
2239
- setShowAreaCheckModal: () => {
2240
- },
2241
- selectedShippingMethod: void 0,
2242
- setSelectedShippingMethod: () => {
2243
- },
2244
- showTip: false,
2245
- setShowTip: () => {
2246
- },
2247
- showMoreShippingMethod: false,
2248
- setShowMoreShippingMethod: () => {
2249
- },
2250
- variant: {},
2251
- product: {},
2252
- shippingMethodsContext: {
2253
- freeShippingMethods: [],
2254
- paymentShippingMethods: [],
2255
- nddOverweight: false,
2256
- tddOverweight: false
2257
- },
2258
- selectedPlusMemberProduct: null,
2259
- plusMemberProducts: [],
2260
- showPlusMemberBenefit: false,
2261
- setShowPlusMemberBenefit: () => {
2262
- },
2263
- deleteMarginBottom: false,
2264
- setDeleteMarginBottom: () => {
2265
- },
2266
- profile: void 0,
2267
- locale: void 0
2268
- });
2269
- var PlusMemberContext = react.createContext(createInitialValue());
2270
- function usePlusMemberContext() {
2271
- return react.useContext(PlusMemberContext);
2331
+ function useAllProducts(options = {}) {
2332
+ const { client, locale } = useShopify();
2333
+ const { first, query, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
2334
+ return useSWR__default.default(
2335
+ ["all-products", locale, first, query, sortKey, reverse, metafieldIdentifiers],
2336
+ () => shopifySdk.getAllProducts(client, {
2337
+ locale,
2338
+ first,
2339
+ query,
2340
+ sortKey,
2341
+ reverse,
2342
+ metafieldIdentifiers
2343
+ }),
2344
+ swrOptions
2345
+ );
2272
2346
  }
2273
- function usePlusMonthlyProductVariant() {
2274
- const { plusMemberProducts, plusMemberMetafields } = usePlusMemberContext();
2275
- const plusMonthly = plusMemberMetafields?.plus_monthly_product;
2276
- const plusMonthlyProductVariant = react.useMemo(() => {
2277
- const product = plusMemberProducts?.find(
2278
- (item) => item?.handle === plusMonthly?.handle
2279
- );
2280
- const productVariant = product?.variants?.find(
2281
- (item) => item.sku === plusMonthly?.sku
2282
- );
2283
- return productVariant;
2284
- }, [plusMemberProducts, plusMonthly]);
2285
- return plusMonthlyProductVariant;
2347
+ function getFirstAvailableVariant(product) {
2348
+ const availableVariant = product.variants.find((v) => v.availableForSale);
2349
+ return availableVariant || product.variants[0];
2286
2350
  }
2287
- function usePlusAnnualProductVariant() {
2288
- const { plusMemberProducts, plusMemberMetafields } = usePlusMemberContext();
2289
- const plusAnnual = plusMemberMetafields?.plus_annual_product;
2290
- const plusAnnualProductVariant = react.useMemo(() => {
2291
- const product = plusMemberProducts?.find(
2292
- (item) => item?.handle === plusAnnual?.handle
2293
- );
2294
- const productVariant = product?.variants?.find(
2295
- (item) => item.sku === plusAnnual?.sku
2296
- );
2297
- return productVariant;
2298
- }, [plusMemberProducts, plusAnnual]);
2299
- return plusAnnualProductVariant;
2351
+ function getVariantFromSelectedOptions(product, selectedOptions) {
2352
+ return product.variants.find((variant) => {
2353
+ return variant.selectedOptions.every((option) => {
2354
+ return selectedOptions[option.name] === option.value;
2355
+ });
2356
+ });
2357
+ }
2358
+ function useVariant({
2359
+ product,
2360
+ selectedOptions
2361
+ }) {
2362
+ const [variant, setVariant] = react.useState(
2363
+ product ? getFirstAvailableVariant(product) : void 0
2364
+ );
2365
+ react.useEffect(() => {
2366
+ if (!product) {
2367
+ setVariant(void 0);
2368
+ return;
2369
+ }
2370
+ const newVariant = getVariantFromSelectedOptions(product, selectedOptions);
2371
+ if (newVariant && newVariant.id !== variant?.id) {
2372
+ setVariant(newVariant);
2373
+ } else if (!newVariant) {
2374
+ setVariant(getFirstAvailableVariant(product));
2375
+ }
2376
+ }, [selectedOptions, product, variant?.id]);
2377
+ return variant;
2378
+ }
2379
+ var FAKE_PRICE = 999999999e-2;
2380
+ function formatPrice({
2381
+ amount,
2382
+ currencyCode,
2383
+ locale,
2384
+ maximumFractionDigits,
2385
+ minimumFractionDigits,
2386
+ removeTrailingZeros
2387
+ }) {
2388
+ const formatter = new Intl.NumberFormat(locale, {
2389
+ style: "currency",
2390
+ currency: currencyCode,
2391
+ maximumFractionDigits: maximumFractionDigits ?? 2,
2392
+ minimumFractionDigits: minimumFractionDigits ?? 2
2393
+ });
2394
+ let formatted = formatter.format(amount);
2395
+ if (removeTrailingZeros) {
2396
+ formatted = formatted.replace(/\.00$/, "");
2397
+ }
2398
+ return formatted;
2399
+ }
2400
+ function formatVariantPrice({
2401
+ amount,
2402
+ baseAmount,
2403
+ currencyCode,
2404
+ locale,
2405
+ maximumFractionDigits,
2406
+ minimumFractionDigits,
2407
+ removeTrailingZeros
2408
+ }) {
2409
+ return {
2410
+ price: formatPrice({
2411
+ amount,
2412
+ currencyCode,
2413
+ locale,
2414
+ maximumFractionDigits,
2415
+ minimumFractionDigits,
2416
+ removeTrailingZeros
2417
+ }),
2418
+ basePrice: formatPrice({
2419
+ amount: baseAmount,
2420
+ currencyCode,
2421
+ locale,
2422
+ maximumFractionDigits,
2423
+ minimumFractionDigits,
2424
+ removeTrailingZeros
2425
+ })
2426
+ };
2300
2427
  }
2301
- function useShippingMethods(options) {
2302
- const {
2303
- variant,
2304
- plusMemberMetafields,
2305
- selectedPlusMemberMode,
2306
- isPlus = false,
2307
- nddCoupon,
2308
- tddCoupon
2309
- } = options;
2310
- const { plus_shipping, shippingMethod } = plusMemberMetafields || {};
2311
- const nddOverweight = react.useMemo(() => {
2312
- return (variant?.weight || 0) > (shippingMethod?.overWeight_ndd || Infinity);
2313
- }, [shippingMethod?.overWeight_ndd, variant?.weight]);
2314
- const tddOverweight = react.useMemo(() => {
2315
- return (variant?.weight || 0) > (shippingMethod?.overWeight_tdd || Infinity);
2316
- }, [shippingMethod?.overWeight_tdd, variant?.weight]);
2317
- const paymentShippingMethods = react.useMemo(() => {
2318
- const weight = variant?.weight || 0;
2319
- const methods = plus_shipping?.shipping_methods?.filter(
2320
- ({ weight_low, weight_high, __mode, __plus }) => {
2321
- const fitWeight = (!weight_low || weight >= weight_low) && (!weight_high || weight <= weight_high);
2322
- return __mode !== "free" /* FREE */ && !__plus && fitWeight;
2323
- }
2324
- ) || [];
2325
- return methods.map((method) => {
2326
- let disabled = false;
2327
- const selectedFreeMember = selectedPlusMemberMode === "free";
2328
- if (method.__mode === "ndd" /* NDD */) {
2329
- disabled = selectedFreeMember || nddOverweight;
2330
- } else if (method.__mode === "tdd" /* TDD */) {
2331
- disabled = selectedFreeMember || tddOverweight;
2332
- }
2333
- return {
2334
- ...method,
2335
- id: method.__mode + method.__code,
2336
- useCoupon: false,
2337
- subtitle: plus_shipping?.directly || "",
2338
- disabled
2339
- };
2340
- });
2341
- }, [
2342
- nddOverweight,
2343
- plus_shipping?.directly,
2344
- plus_shipping?.shipping_methods,
2345
- selectedPlusMemberMode,
2346
- tddOverweight,
2347
- variant?.weight
2348
- ]);
2349
- const nddPrice = react.useMemo(() => {
2350
- const weight = variant?.weight || 0;
2351
- const nddMethod = paymentShippingMethods.find(
2352
- ({ __mode, weight_high, weight_low }) => {
2353
- const fitWeight = (!weight_low || weight >= weight_low) && (!weight_high || weight <= weight_high);
2354
- return __mode === "ndd" && fitWeight;
2355
- }
2356
- );
2357
- return nddMethod?.price || 0;
2358
- }, [variant?.weight, paymentShippingMethods]);
2359
- const tddPrice = react.useMemo(() => {
2360
- const weight = variant?.weight || 0;
2361
- const tddMethod = paymentShippingMethods.find(
2362
- ({ __mode, weight_high, weight_low }) => {
2363
- const fitWeight = (!weight_low || weight >= weight_low) && (!weight_high || weight <= weight_high);
2364
- return __mode === "tdd" && fitWeight;
2365
- }
2366
- );
2367
- return tddMethod?.price || 0;
2368
- }, [variant?.weight, paymentShippingMethods]);
2369
- const freeShippingMethods = react.useMemo(() => {
2370
- const weight = variant?.weight || 0;
2371
- let methods = plus_shipping?.shipping_methods?.filter(
2372
- ({ __mode, __plus, weight_low, weight_high }) => {
2373
- if (__mode === "free" /* FREE */) {
2374
- return true;
2375
- }
2376
- if (isPlus) {
2377
- const hasCoupon = isPlus && __mode === "ndd" /* NDD */ && nddCoupon || isPlus && __mode === "tdd" /* TDD */ && (tddCoupon || nddCoupon);
2378
- const fitWeight = (!weight_low || weight >= weight_low) && (!weight_high || weight <= weight_high);
2379
- return hasCoupon && fitWeight && !__plus;
2380
- } else {
2381
- return __plus;
2382
- }
2383
- }
2384
- ) || [];
2385
- if (isPlus) {
2386
- methods = methods.sort((a, b) => {
2387
- if (b.__mode === "free" /* FREE */) return -1;
2388
- return 0;
2389
- });
2428
+ function usePrice({
2429
+ amount,
2430
+ baseAmount,
2431
+ currencyCode,
2432
+ soldOutDescription = "",
2433
+ maximumFractionDigits,
2434
+ minimumFractionDigits,
2435
+ removeTrailingZeros
2436
+ }) {
2437
+ const { locale } = useShopify();
2438
+ const value = react.useMemo(() => {
2439
+ if (typeof amount !== "number" || !currencyCode) {
2440
+ return "";
2390
2441
  }
2391
- return methods.map((method) => {
2392
- let price = 0;
2393
- let coupon;
2394
- let disabled;
2395
- if (method.__mode !== "free" /* FREE */) {
2396
- switch (method.__mode) {
2397
- case "tdd":
2398
- price = tddPrice;
2399
- coupon = tddCoupon || nddCoupon;
2400
- break;
2401
- case "ndd":
2402
- price = nddPrice;
2403
- coupon = nddCoupon;
2404
- break;
2405
- }
2406
- disabled = selectedPlusMemberMode === "free";
2407
- if (method.__mode === "ndd" /* NDD */) {
2408
- disabled = disabled || nddOverweight;
2409
- } else if (method.__mode === "tdd" /* TDD */) {
2410
- disabled = disabled || tddOverweight;
2411
- }
2412
- }
2413
- return {
2414
- ...method,
2415
- id: method.__mode + method.__code,
2416
- useCoupon: true,
2417
- disabled,
2418
- coupon,
2419
- price
2420
- };
2442
+ if (soldOutDescription && amount >= FAKE_PRICE) {
2443
+ return soldOutDescription;
2444
+ }
2445
+ return baseAmount ? formatVariantPrice({
2446
+ amount,
2447
+ baseAmount,
2448
+ currencyCode,
2449
+ locale,
2450
+ maximumFractionDigits,
2451
+ minimumFractionDigits,
2452
+ removeTrailingZeros
2453
+ }) : formatPrice({
2454
+ amount,
2455
+ currencyCode,
2456
+ locale,
2457
+ maximumFractionDigits,
2458
+ minimumFractionDigits,
2459
+ removeTrailingZeros
2421
2460
  });
2422
2461
  }, [
2423
- variant?.weight,
2424
- plus_shipping?.shipping_methods,
2425
- isPlus,
2426
- nddCoupon,
2427
- tddCoupon,
2428
- selectedPlusMemberMode,
2429
- tddPrice,
2430
- nddPrice,
2431
- nddOverweight,
2432
- tddOverweight
2462
+ amount,
2463
+ baseAmount,
2464
+ currencyCode,
2465
+ locale,
2466
+ maximumFractionDigits,
2467
+ minimumFractionDigits,
2468
+ soldOutDescription,
2469
+ removeTrailingZeros
2433
2470
  ]);
2434
- return {
2435
- freeShippingMethods,
2436
- paymentShippingMethods,
2437
- nddOverweight,
2438
- tddOverweight
2439
- };
2471
+ const result = react.useMemo(() => {
2472
+ const free = Boolean(amount && amount <= 0);
2473
+ return typeof value === "string" ? { price: value, basePrice: value, free } : { ...value, free };
2474
+ }, [value, amount]);
2475
+ return result;
2440
2476
  }
2441
- function useShippingMethodAvailableCheck() {
2442
- const {
2443
- zipCode,
2444
- allowNextDayDelivery,
2445
- allowThirdDayDelivery,
2446
- selectedShippingMethod,
2447
- setSelectedShippingMethod,
2448
- setShowTip,
2449
- shippingMethodsContext
2450
- } = usePlusMemberContext();
2477
+ function optionsConstructor(selectedOptions) {
2478
+ return selectedOptions.reduce((acc, option) => {
2479
+ acc[option.name] = option.value;
2480
+ return acc;
2481
+ }, {});
2482
+ }
2483
+ function decodeShopifyId(gid) {
2484
+ try {
2485
+ const base64 = gid.split("/").pop() || "";
2486
+ return atob(base64);
2487
+ } catch {
2488
+ return gid;
2489
+ }
2490
+ }
2491
+ function useSelectedOptions(product, sku) {
2492
+ const [options, setOptions] = react.useState({});
2451
2493
  react.useEffect(() => {
2452
- const freeShippingMethod = shippingMethodsContext.freeShippingMethods[0];
2453
- const standardShippingMethod = shippingMethodsContext.freeShippingMethods?.find(
2454
- (item) => item.__mode === "free" /* FREE */
2455
- );
2456
- const freeTDD = shippingMethodsContext.freeShippingMethods.find(
2457
- (item) => item.__mode === "tdd" /* TDD */
2458
- );
2459
- const paymentTDD = shippingMethodsContext.paymentShippingMethods.find(
2460
- (item) => item.__mode === "tdd" /* TDD */
2461
- );
2462
- if (zipCode) {
2463
- console.log(
2464
- "allowNextDayDelivery, allowThirdDayDelivery:",
2465
- allowNextDayDelivery,
2466
- allowThirdDayDelivery
2467
- );
2468
- if (!allowNextDayDelivery && !allowThirdDayDelivery) {
2469
- setShowTip(true);
2470
- setSelectedShippingMethod(standardShippingMethod);
2471
- } else {
2472
- if (selectedShippingMethod?.__mode === "ndd" /* NDD */ && !allowNextDayDelivery) {
2473
- setShowTip(true);
2474
- if (allowThirdDayDelivery) {
2475
- if (selectedShippingMethod.useCoupon) {
2476
- const method = freeTDD || freeShippingMethod;
2477
- if (method) setSelectedShippingMethod(method);
2478
- } else {
2479
- const method = paymentTDD || freeShippingMethod;
2480
- if (method) setSelectedShippingMethod(method);
2481
- }
2482
- } else {
2483
- if (freeShippingMethod) setSelectedShippingMethod(freeShippingMethod);
2484
- }
2485
- } else if (
2486
- // TDD 无法使用
2487
- selectedShippingMethod?.__mode === "tdd" /* TDD */ && !allowThirdDayDelivery
2488
- ) {
2489
- setShowTip(true);
2490
- if (freeShippingMethod) setSelectedShippingMethod(freeShippingMethod);
2494
+ if (!product || !product.variants.length) {
2495
+ setOptions({});
2496
+ return;
2497
+ }
2498
+ let variant = product.variants[0];
2499
+ if (typeof window !== "undefined") {
2500
+ const searchParams = new URLSearchParams(window.location.search);
2501
+ const variantIdParam = searchParams.get("variant");
2502
+ if (variantIdParam) {
2503
+ const foundVariant = product.variants.find((v) => {
2504
+ if (sku) return v.sku === sku;
2505
+ return v.id === variantIdParam || v.id.includes(variantIdParam) || decodeShopifyId(v.id) === variantIdParam;
2506
+ });
2507
+ if (foundVariant) {
2508
+ variant = foundVariant;
2491
2509
  }
2492
2510
  }
2493
2511
  }
2494
- }, [
2495
- allowNextDayDelivery,
2496
- allowThirdDayDelivery,
2497
- zipCode,
2498
- shippingMethodsContext,
2499
- selectedShippingMethod,
2500
- setSelectedShippingMethod,
2501
- setShowTip
2502
- ]);
2503
- }
2504
- var useReplaceCartPlusMember = () => {
2505
- const { plusMemberMetafields, selectedPlusMemberMode } = usePlusMemberContext();
2506
- const { trigger: removeCartLines2 } = useRemoveCartLines();
2507
- const { cart } = useCartContext();
2508
- const plusMonthly = plusMemberMetafields?.plus_monthly_product;
2509
- const plusAnnual = plusMemberMetafields?.plus_annual_product;
2510
- const handler = react.useCallback(async () => {
2511
- const plusMonthlyInCart = cart?.lineItems.find(
2512
- (item) => item.variant?.sku === plusMonthly?.sku
2513
- );
2514
- const plusAnnualInCart = cart?.lineItems.find(
2515
- (item) => item.variant?.sku === plusAnnual?.sku
2516
- );
2517
- if (selectedPlusMemberMode === "annual" /* ANNUAL */ && plusMonthlyInCart) {
2518
- await removeCartLines2({
2519
- lineIds: [plusMonthlyInCart.id]
2520
- });
2521
- } else if (selectedPlusMemberMode === "monthly" /* MONTHLY */ && plusAnnualInCart) {
2522
- await removeCartLines2({
2523
- lineIds: [plusAnnualInCart.id]
2524
- });
2512
+ if (variant) {
2513
+ const newOptions = optionsConstructor(variant.selectedOptions);
2514
+ setOptions(newOptions);
2525
2515
  }
2526
- }, [
2527
- cart?.lineItems,
2528
- selectedPlusMemberMode,
2529
- plusMonthly?.sku,
2530
- plusAnnual?.sku,
2531
- removeCartLines2
2532
- ]);
2533
- return handler;
2534
- };
2535
- var usePlusMemberDeliveryCodes = ({
2536
- deliveryData
2537
- }) => {
2538
- return react.useMemo(
2539
- () => deliveryData?.deliveryCustomData?.discount_code,
2540
- [deliveryData]
2541
- );
2542
- };
2543
- function useUpdateCartDeliveryOptions(mutate, metafieldIdentifiers, options) {
2544
- const { client, locale, cartCookieAdapter } = useShopify();
2545
- const updateDeliveryOptions = react.useCallback(
2546
- async (_key, { arg }) => {
2547
- const updatedCart = await shopifySdk.updateCartDeliveryOptions(client, {
2548
- ...arg,
2549
- metafieldIdentifiers,
2550
- cookieAdapter: cartCookieAdapter
2551
- });
2552
- console.log("useUpdateCartDeliveryOptions updatedCart", updatedCart);
2553
- if (updatedCart) {
2554
- mutate(updatedCart);
2516
+ }, [product, sku]);
2517
+ return [options, setOptions];
2518
+ }
2519
+ function decodeShopifyId2(gid) {
2520
+ try {
2521
+ const parts = gid.split("/");
2522
+ return parts[parts.length - 1] || gid;
2523
+ } catch {
2524
+ return gid;
2525
+ }
2526
+ }
2527
+ function useProductUrl(otherQuery) {
2528
+ const { routerAdapter } = useShopify();
2529
+ return react.useCallback(
2530
+ ({ product, variant }) => {
2531
+ if (!product) return "";
2532
+ const queryParams = new URLSearchParams();
2533
+ if (variant?.id) {
2534
+ const variantId = decodeShopifyId2(variant.id);
2535
+ if (variantId) {
2536
+ queryParams.set("variant", variantId);
2537
+ }
2555
2538
  }
2556
- return updatedCart;
2539
+ if (otherQuery) {
2540
+ Object.entries(otherQuery).forEach(([key, value]) => {
2541
+ queryParams.set(key, value);
2542
+ });
2543
+ }
2544
+ const queryString = queryParams.toString();
2545
+ const path = `/products/${product.handle}${queryString ? `?${queryString}` : ""}`;
2546
+ if (routerAdapter?.getLocalizedPath) {
2547
+ return routerAdapter.getLocalizedPath(path);
2548
+ }
2549
+ return path;
2557
2550
  },
2558
- [client, locale, cartCookieAdapter, mutate]
2551
+ [routerAdapter, otherQuery]
2559
2552
  );
2560
- return useSWRMutation__default.default("update-cart-delivery-options", updateDeliveryOptions, options);
2561
2553
  }
2562
-
2563
- // src/hooks/member/plus/use-update-plus-member-delivery-options.ts
2564
- var useUpdatePlusMemberDeliveryOptions = ({
2565
- deliveryData,
2566
- options
2567
- }) => {
2568
- const { cart, mutateCart: mutate, metafieldIdentifiers } = useCartContext();
2569
- const { trigger: updateCartDeliveryOptions2, isMutating } = useUpdateCartDeliveryOptions(
2570
- mutate,
2571
- metafieldIdentifiers
2572
- );
2573
- const deliveryOptions = react.useMemo(() => {
2574
- const deliveryGroupId = cart?.deliveryGroups?.[0]?.id;
2575
- const selectedOptionCode = deliveryData?.deliveryCustomData?.selected_delivery_option;
2576
- if (!deliveryGroupId || !selectedOptionCode) {
2577
- return [];
2578
- }
2579
- const deliveryGroup = cart?.deliveryGroups?.find((group) => group?.id === deliveryGroupId);
2580
- const matchedOption = deliveryGroup?.deliveryOptions?.find(
2581
- (option) => option?.code === selectedOptionCode
2582
- );
2583
- if (!matchedOption?.handle) {
2584
- return [];
2585
- }
2586
- return [
2587
- {
2588
- deliveryGroupId,
2589
- deliveryOptionHandle: matchedOption.handle
2590
- }
2591
- ];
2592
- }, [deliveryData, cart]);
2593
- const handler = react.useCallback(async () => {
2594
- const updatedCart = await updateCartDeliveryOptions2({
2595
- selectedDeliveryOptions: deliveryOptions
2596
- });
2597
- if (updatedCart && mutate) {
2598
- mutate(updatedCart);
2554
+ function decodeShopifyId3(gid) {
2555
+ try {
2556
+ const parts = gid.split("/");
2557
+ return parts[parts.length - 1] || gid;
2558
+ } catch {
2559
+ return gid;
2560
+ }
2561
+ }
2562
+ function useUpdateVariantQuery(variant) {
2563
+ react.useEffect(() => {
2564
+ if (!variant || typeof window === "undefined") {
2565
+ return;
2599
2566
  }
2600
- return updatedCart;
2601
- }, [deliveryOptions, mutate, updateCartDeliveryOptions2]);
2602
- return useSWRMutation__default.default("update-cart-delivery-options", handler, options);
2603
- };
2604
- var usePlusMemberItemCustomAttributes = ({
2605
- deliveryData
2606
- }) => {
2607
- const { deliveryCustomData } = deliveryData || {};
2608
- return react.useMemo(() => {
2609
- const itemCustomAttributes = [];
2610
- if (deliveryCustomData?.is_presale) {
2611
- itemCustomAttributes.push({
2612
- key: "_is_presale",
2613
- value: "true"
2614
- });
2567
+ const searchParams = new URLSearchParams(window.location.search);
2568
+ const currentVariantId = searchParams.get("variant");
2569
+ const newVariantId = decodeShopifyId3(variant.id);
2570
+ if (newVariantId && currentVariantId !== newVariantId) {
2571
+ searchParams.set("variant", newVariantId);
2572
+ const newUrl = `${window.location.pathname}?${searchParams.toString()}${window.location.hash}`;
2573
+ window.history.replaceState({}, "", newUrl);
2615
2574
  }
2616
- return itemCustomAttributes;
2617
- }, [deliveryCustomData]);
2618
- };
2619
- var usePlusMemberCheckoutCustomAttributes = ({
2620
- deliveryData,
2575
+ }, [variant]);
2576
+ }
2577
+ function getVariantMediaList({
2621
2578
  product,
2622
- variant,
2623
- customer,
2624
- isShowShippingBenefits
2625
- }) => {
2626
- const { deliveryCustomData } = deliveryData || {};
2627
- const { profile } = usePlusMemberContext();
2628
- const userType = react.useMemo(() => {
2629
- const customerInfo = customer;
2630
- if (!customerInfo) {
2631
- return "new_user_unlogin";
2632
- }
2633
- if (customer) {
2634
- const { orders = {} } = customer;
2635
- const edgesLength = orders?.edges?.length;
2636
- if (edgesLength === 1) {
2637
- return "old_user_orders_once";
2638
- } else if (edgesLength && edgesLength > 1) {
2639
- return "old_user_orders_twice";
2640
- }
2641
- }
2642
- return "new_user_login";
2643
- }, [customer]);
2644
- return react.useMemo(() => {
2645
- const checkoutCustomAttributes = [
2646
- {
2647
- key: "_token",
2648
- value: profile?.token || ""
2649
- },
2650
- {
2651
- key: "_last_url",
2652
- value: typeof window !== "undefined" ? window.location.origin + window.location.pathname : ""
2653
- },
2654
- {
2655
- key: "_user_type",
2656
- value: userType
2579
+ variant
2580
+ }) {
2581
+ if (variant.image?.url) {
2582
+ const variantMediaId = variant.image.url;
2583
+ const variantMedia = product.media.filter((media) => {
2584
+ if (media.mediaContentType === "IMAGE" && media.previewImage) {
2585
+ return media.previewImage?.url === variantMediaId;
2657
2586
  }
2658
- ];
2659
- if (profile) {
2660
- checkoutCustomAttributes.push({
2661
- key: "_login_user",
2662
- value: "1"
2663
- });
2664
- }
2665
- if (deliveryCustomData) {
2666
- checkoutCustomAttributes.push({
2667
- key: "_checkout_delivery_custom",
2668
- value: JSON.stringify({
2669
- ...deliveryCustomData,
2670
- is_prime: profile?.isPlus
2671
- })
2672
- });
2673
- }
2674
- if (variant?.metafields?.presell) {
2675
- checkoutCustomAttributes.push({
2676
- key: "_presale",
2677
- value: "true"
2678
- });
2679
- }
2680
- if (isShowShippingBenefits && !isShowShippingBenefits({ variant, product, setting: {} })) {
2681
- checkoutCustomAttributes.push({
2682
- key: "_hide_shipping",
2683
- value: "true"
2587
+ return false;
2588
+ });
2589
+ if (variantMedia.length > 0) {
2590
+ const otherMedia = product.media.filter((media) => {
2591
+ if (media.mediaContentType === "IMAGE" && media.previewImage) {
2592
+ return media.previewImage.url !== variantMediaId;
2593
+ }
2594
+ return true;
2684
2595
  });
2596
+ return [...variantMedia, ...otherMedia];
2685
2597
  }
2686
- return checkoutCustomAttributes;
2687
- }, [deliveryCustomData, product, profile, userType, variant, isShowShippingBenefits]);
2688
- };
2689
- function useAutoRemovePlusMemberInCart({
2690
- cart,
2691
- profile,
2692
- memberSetting
2598
+ }
2599
+ return product.media;
2600
+ }
2601
+ function useVariantMedia({
2602
+ product,
2603
+ variant
2693
2604
  }) {
2694
- const { plus_monthly_product, plus_annual_product } = memberSetting || {};
2695
- const { trigger: removeCartLines2 } = useRemoveCartLines();
2605
+ const [imageList, setImageList] = react.useState([]);
2606
+ const [sceneList, setSceneList] = react.useState([]);
2607
+ const [videoList, setVideoList] = react.useState([]);
2696
2608
  react.useEffect(() => {
2697
- if (!cart || !plus_monthly_product || !plus_annual_product) return;
2698
- const removePlusProduct = async (productType) => {
2699
- if (!productType) return;
2700
- const product = cart.lineItems?.find(
2701
- (item) => item.product?.handle === productType?.handle && item.variant?.sku === productType?.sku
2702
- );
2703
- if (product) {
2704
- await removeCartLines2({
2705
- lineIds: [product.id]
2706
- });
2609
+ if (!product || !variant) {
2610
+ setImageList([]);
2611
+ setSceneList([]);
2612
+ setVideoList([]);
2613
+ return;
2614
+ }
2615
+ const mediaList = getVariantMediaList({ product, variant });
2616
+ const images = mediaList.filter((media) => media.mediaContentType === "IMAGE");
2617
+ const videos = mediaList.filter(
2618
+ (media) => media.mediaContentType === "VIDEO" || media.mediaContentType === "EXTERNAL_VIDEO"
2619
+ );
2620
+ setImageList(images.length > 0 && images[0] ? [images[0]] : []);
2621
+ setSceneList(images.length > 1 ? images.slice(1) : []);
2622
+ setVideoList(videos);
2623
+ }, [product, variant]);
2624
+ return {
2625
+ productList: imageList,
2626
+ sceneList,
2627
+ videoList
2628
+ };
2629
+ }
2630
+ function useCollection(options = {}) {
2631
+ const { client, locale } = useShopify();
2632
+ const { handle, metafieldIdentifiers, ...swrOptions } = options;
2633
+ return useSWR__default.default(
2634
+ handle ? ["collection", locale, handle, metafieldIdentifiers] : null,
2635
+ () => shopifySdk.getCollection(client, {
2636
+ handle,
2637
+ locale,
2638
+ metafieldIdentifiers
2639
+ }),
2640
+ swrOptions
2641
+ );
2642
+ }
2643
+ function useAllCollections(options = {}) {
2644
+ const { client, locale } = useShopify();
2645
+ const { first, query, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
2646
+ return useSWR__default.default(
2647
+ ["all-collections", locale, first, query, sortKey, reverse, metafieldIdentifiers],
2648
+ () => shopifySdk.getAllCollections(client, {
2649
+ locale,
2650
+ first,
2651
+ query,
2652
+ sortKey,
2653
+ reverse,
2654
+ metafieldIdentifiers
2655
+ }),
2656
+ swrOptions
2657
+ );
2658
+ }
2659
+ function useCollections(options = {}) {
2660
+ const { client, locale } = useShopify();
2661
+ const { first, after, query, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
2662
+ return useSWR__default.default(
2663
+ ["collections", locale, first, after, query, sortKey, reverse, metafieldIdentifiers],
2664
+ () => shopifySdk.getCollections(client, {
2665
+ locale,
2666
+ first,
2667
+ after,
2668
+ query,
2669
+ sortKey,
2670
+ reverse,
2671
+ metafieldIdentifiers
2672
+ }),
2673
+ swrOptions
2674
+ );
2675
+ }
2676
+ function useBlog(options = {}) {
2677
+ const { client, locale } = useShopify();
2678
+ const { handle, metafieldIdentifiers, ...swrOptions } = options;
2679
+ return useSWR__default.default(
2680
+ handle ? ["blog", locale, handle, metafieldIdentifiers] : null,
2681
+ () => shopifySdk.getBlog(client, { handle, locale, metafieldIdentifiers }),
2682
+ swrOptions
2683
+ );
2684
+ }
2685
+ function useAllBlogs(options = {}) {
2686
+ const { client, locale } = useShopify();
2687
+ const { first, query, metafieldIdentifiers, ...swrOptions } = options;
2688
+ return useSWR__default.default(
2689
+ ["all-blogs", locale, first, query, metafieldIdentifiers],
2690
+ () => shopifySdk.getAllBlogs(client, {
2691
+ locale,
2692
+ first,
2693
+ query,
2694
+ metafieldIdentifiers
2695
+ }),
2696
+ swrOptions
2697
+ );
2698
+ }
2699
+ function useArticle(options = {}) {
2700
+ const { client, locale } = useShopify();
2701
+ const { blogHandle, articleHandle, metafieldIdentifiers, ...swrOptions } = options;
2702
+ return useSWR__default.default(
2703
+ blogHandle && articleHandle ? ["article", locale, blogHandle, articleHandle, metafieldIdentifiers] : null,
2704
+ () => shopifySdk.getArticle(client, {
2705
+ blogHandle,
2706
+ articleHandle,
2707
+ locale,
2708
+ metafieldIdentifiers
2709
+ }),
2710
+ swrOptions
2711
+ );
2712
+ }
2713
+ function useArticles(options = {}) {
2714
+ const { client, locale } = useShopify();
2715
+ const { first, query, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
2716
+ return useSWR__default.default(
2717
+ ["articles", locale, first, query, sortKey, reverse, metafieldIdentifiers],
2718
+ () => shopifySdk.getArticles(client, {
2719
+ locale,
2720
+ first,
2721
+ query,
2722
+ sortKey,
2723
+ reverse,
2724
+ metafieldIdentifiers
2725
+ }),
2726
+ swrOptions
2727
+ );
2728
+ }
2729
+ function useArticlesInBlog(options = {}) {
2730
+ const { client, locale } = useShopify();
2731
+ const { blogHandle, first, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
2732
+ return useSWR__default.default(
2733
+ blogHandle ? ["articles-in-blog", locale, blogHandle, first, sortKey, reverse, metafieldIdentifiers] : null,
2734
+ () => shopifySdk.getArticlesInBlog(client, {
2735
+ blogHandle,
2736
+ locale,
2737
+ first,
2738
+ sortKey,
2739
+ reverse,
2740
+ metafieldIdentifiers
2741
+ }),
2742
+ swrOptions
2743
+ );
2744
+ }
2745
+ async function performSearch(client, locale, searchQuery, first = 20, types = ["PRODUCT", "ARTICLE", "PAGE"]) {
2746
+ if (!searchQuery) {
2747
+ return void 0;
2748
+ }
2749
+ const query = (
2750
+ /* GraphQL */
2751
+ `
2752
+ query search($query: String!, $first: Int!, $types: [SearchType!])
2753
+ @inContext(language: $language) {
2754
+ search(query: $query, first: $first, types: $types, unavailableProducts: HIDE) {
2755
+ totalCount
2756
+ edges {
2757
+ node {
2758
+ ... on Article {
2759
+ __typename
2760
+ id
2761
+ handle
2762
+ title
2763
+ excerpt
2764
+ image {
2765
+ url
2766
+ altText
2767
+ }
2768
+ }
2769
+ ... on Page {
2770
+ __typename
2771
+ id
2772
+ handle
2773
+ title
2774
+ }
2775
+ ... on Product {
2776
+ __typename
2777
+ id
2778
+ handle
2779
+ title
2780
+ description
2781
+ featuredImage {
2782
+ url
2783
+ altText
2784
+ }
2785
+ }
2786
+ }
2787
+ }
2788
+ pageInfo {
2789
+ hasNextPage
2790
+ endCursor
2791
+ }
2707
2792
  }
2708
- };
2709
- if (profile?.isMonthlyPlus) {
2710
- removePlusProduct(plus_monthly_product);
2711
- }
2712
- if (profile?.isAnnualPlus) {
2713
- removePlusProduct(plus_annual_product);
2714
2793
  }
2715
- }, [cart, plus_annual_product, plus_monthly_product, profile, removeCartLines2]);
2716
- }
2717
- function useAddPlusMemberProductsToCart({
2718
- cart,
2719
- profile
2720
- }) {
2721
- const { selectedPlusMemberMode, selectedPlusMemberProduct, plusMemberMetafields } = usePlusMemberContext();
2722
- const { hasMonthlyPlus, hasAnnualPlus } = useHasPlusMemberInCart({
2723
- memberSetting: plusMemberMetafields,
2724
- cart
2794
+ `
2795
+ );
2796
+ const data = await client.query(query, {
2797
+ query: searchQuery,
2798
+ first,
2799
+ types
2725
2800
  });
2726
- const plusMemberProduct = react.useMemo(() => {
2727
- if (!selectedPlusMemberProduct || selectedPlusMemberMode === "free" /* FREE */) {
2728
- return void 0;
2729
- }
2730
- if (selectedPlusMemberMode === "monthly" /* MONTHLY */ && hasMonthlyPlus) {
2731
- return void 0;
2732
- }
2733
- if (selectedPlusMemberMode === "annual" /* ANNUAL */ && hasAnnualPlus) {
2734
- return void 0;
2735
- }
2736
- if (profile?.isMonthlyPlus && selectedPlusMemberMode === "monthly" /* MONTHLY */) {
2737
- return void 0;
2738
- }
2739
- if (!profile?.isAnnualPlus && selectedPlusMemberMode === "annual" /* ANNUAL */) {
2740
- return void 0;
2801
+ if (!data || !data.search) {
2802
+ return void 0;
2803
+ }
2804
+ const items = data.search.edges?.map((edge) => {
2805
+ const node = edge.node;
2806
+ const item = {
2807
+ type: node.__typename.toUpperCase(),
2808
+ id: node.id,
2809
+ handle: node.handle,
2810
+ title: node.title
2811
+ };
2812
+ if (node.__typename === "Product") {
2813
+ item.description = node.description;
2814
+ item.image = node.featuredImage ? {
2815
+ url: node.featuredImage.url,
2816
+ altText: node.featuredImage.altText
2817
+ } : void 0;
2818
+ } else if (node.__typename === "Article") {
2819
+ item.description = node.excerpt;
2820
+ item.image = node.image ? {
2821
+ url: node.image.url,
2822
+ altText: node.image.altText
2823
+ } : void 0;
2741
2824
  }
2742
- return selectedPlusMemberProduct;
2743
- }, [
2744
- selectedPlusMemberMode,
2745
- selectedPlusMemberProduct?.variant,
2746
- selectedPlusMemberProduct?.product,
2747
- hasMonthlyPlus,
2748
- hasAnnualPlus
2749
- ]);
2750
- return plusMemberProduct;
2825
+ return item;
2826
+ }) || [];
2827
+ return {
2828
+ items,
2829
+ totalCount: data.search.totalCount || 0,
2830
+ pageInfo: data.search.pageInfo
2831
+ };
2751
2832
  }
2752
- var PlusMemberProvider = ({
2753
- variant,
2754
- product,
2755
- memberSetting,
2756
- initialSelectedPlusMemberMode = "free",
2757
- profile,
2758
- locale,
2759
- children
2760
- }) => {
2761
- const [zipCode, setZipCode] = react.useState("");
2762
- const [showTip, setShowTip] = react.useState(false);
2763
- const [selectedPlusMemberMode, setSelectedPlusMemberMode] = react.useState(
2764
- initialSelectedPlusMemberMode
2833
+ function useSearch(options = {}) {
2834
+ const { client, locale } = useShopify();
2835
+ const { query, first = 20, types = ["PRODUCT", "ARTICLE", "PAGE"], ...swrOptions } = options;
2836
+ return useSWR__default.default(
2837
+ query ? ["search", locale, query, first, types] : null,
2838
+ () => performSearch(client, locale, query, first, types),
2839
+ swrOptions
2765
2840
  );
2766
- const [selectedShippingMethod, setSelectedShippingMethod] = react.useState();
2767
- const [allowNextDayDelivery, setAllowNextDayDelivery] = react.useState(false);
2768
- const [allowThirdDayDelivery, setAllowThirdDayDelivery] = react.useState(false);
2769
- const [showAreaCheckModal, setShowAreaCheckModal] = react.useState(false);
2770
- const [showMoreShippingMethod, setShowMoreShippingMethod] = react.useState(false);
2771
- const [showPlusMemberBenefit, setShowPlusMemberBenefit] = react.useState(false);
2772
- const [deleteMarginBottom, setDeleteMarginBottom] = react.useState(false);
2773
- const shippingMethodsContext = useShippingMethods({
2774
- variant,
2775
- plusMemberMetafields: memberSetting,
2776
- selectedPlusMemberMode});
2777
- const plusMemberHandles = react.useMemo(() => {
2778
- return [
2779
- memberSetting?.plus_monthly_product?.handle,
2780
- memberSetting?.plus_annual_product?.handle
2781
- ].filter(Boolean);
2782
- }, [memberSetting]);
2783
- const { data: plusMemberProducts = [] } = useProductsByHandles({
2784
- handles: plusMemberHandles
2785
- });
2786
- const selectedPlusMemberProduct = react.useMemo(() => {
2787
- if (selectedPlusMemberMode === "free" /* FREE */) {
2788
- return null;
2841
+ }
2842
+ async function getSiteInfo(client, locale, metafieldIdentifiers) {
2843
+ const hasMetafields = metafieldIdentifiers && metafieldIdentifiers.length > 0;
2844
+ const query = (
2845
+ /* GraphQL */
2846
+ `
2847
+ query getSiteInfo(
2848
+ ${hasMetafields ? "$shopMetafieldIdentifiers: [HasMetafieldsIdentifier!]!" : ""}
2849
+ ) @inContext(language: $language) {
2850
+ shop {
2851
+ name
2852
+ description
2853
+ primaryDomain {
2854
+ url
2855
+ host
2856
+ }
2857
+ brand {
2858
+ logo {
2859
+ image {
2860
+ url
2861
+ }
2862
+ }
2863
+ colors {
2864
+ primary {
2865
+ background
2866
+ }
2867
+ secondary {
2868
+ background
2869
+ }
2870
+ }
2871
+ }
2872
+ ${hasMetafields ? "metafields(identifiers: $shopMetafieldIdentifiers) { key value }" : ""}
2873
+ }
2789
2874
  }
2790
- const handle = selectedPlusMemberMode === "monthly" /* MONTHLY */ ? memberSetting?.plus_monthly_product?.handle : memberSetting?.plus_annual_product?.handle;
2791
- const sku = selectedPlusMemberMode === "monthly" /* MONTHLY */ ? memberSetting?.plus_monthly_product?.sku : memberSetting?.plus_annual_product?.sku;
2792
- const product2 = plusMemberProducts?.find((p) => p.handle === handle);
2793
- const variant2 = product2?.variants?.find((v) => v.sku === sku);
2794
- return product2 && variant2 ? { product: product2, variant: variant2 } : null;
2795
- }, [plusMemberProducts, memberSetting, selectedPlusMemberMode]);
2796
- return /* @__PURE__ */ jsxRuntime.jsx(
2797
- PlusMemberContext.Provider,
2798
- {
2799
- value: {
2800
- variant,
2801
- zipCode,
2802
- setZipCode,
2803
- allowNextDayDelivery,
2804
- setAllowNextDayDelivery,
2805
- allowThirdDayDelivery,
2806
- setAllowThirdDayDelivery,
2807
- plusMemberMetafields: memberSetting,
2808
- selectedPlusMemberMode,
2809
- setSelectedPlusMemberMode,
2810
- showAreaCheckModal,
2811
- setShowAreaCheckModal,
2812
- selectedShippingMethod,
2813
- setSelectedShippingMethod,
2814
- shippingMethodsContext,
2815
- showTip,
2816
- setShowTip,
2817
- showMoreShippingMethod,
2818
- setShowMoreShippingMethod,
2819
- selectedPlusMemberProduct,
2820
- plusMemberProducts,
2821
- product,
2822
- showPlusMemberBenefit,
2823
- setShowPlusMemberBenefit,
2824
- deleteMarginBottom,
2825
- setDeleteMarginBottom,
2826
- profile,
2827
- locale
2828
- },
2829
- children
2875
+ `
2876
+ );
2877
+ const variables = {};
2878
+ if (hasMetafields) {
2879
+ variables.shopMetafieldIdentifiers = metafieldIdentifiers;
2880
+ }
2881
+ const data = await client.query(query, variables);
2882
+ if (!data || !data.shop) {
2883
+ return void 0;
2884
+ }
2885
+ const shop = data.shop;
2886
+ const metafields = shop.metafields?.reduce((acc, mf) => {
2887
+ if (mf && mf.key) {
2888
+ acc[mf.key] = mf.value;
2830
2889
  }
2890
+ return acc;
2891
+ }, {});
2892
+ return {
2893
+ name: shop.name,
2894
+ description: shop.description,
2895
+ primaryDomain: shop.primaryDomain,
2896
+ brand: shop.brand ? {
2897
+ logo: shop.brand.logo,
2898
+ colors: shop.brand.colors ? {
2899
+ primary: shop.brand.colors.primary?.background,
2900
+ secondary: shop.brand.colors.secondary?.background
2901
+ } : void 0
2902
+ } : void 0,
2903
+ metafields
2904
+ };
2905
+ }
2906
+ function useSite(options = {}) {
2907
+ const { client, locale } = useShopify();
2908
+ const { metafieldIdentifiers, ...swrOptions } = options;
2909
+ return useSWR__default.default(
2910
+ ["site", locale, metafieldIdentifiers],
2911
+ () => getSiteInfo(client, locale, metafieldIdentifiers),
2912
+ swrOptions
2831
2913
  );
2832
- };
2914
+ }
2833
2915
  function useIntersection(targetRef, options) {
2834
2916
  const {
2835
2917
  callback,
@@ -3016,6 +3098,7 @@ exports.CUSTOMER_ATTRIBUTE_KEY = CUSTOMER_ATTRIBUTE_KEY;
3016
3098
  exports.CUSTOMER_SCRIPT_GIFT_KEY = CUSTOMER_SCRIPT_GIFT_KEY;
3017
3099
  exports.DeliveryPlusType = DeliveryPlusType;
3018
3100
  exports.MAIN_PRODUCT_CODE = MAIN_PRODUCT_CODE;
3101
+ exports.MEMBER_PRICE_ATTRIBUTE_KEY = MEMBER_PRICE_ATTRIBUTE_KEY;
3019
3102
  exports.OrderBasePriceType = OrderBasePriceType;
3020
3103
  exports.OrderDiscountType = OrderDiscountType;
3021
3104
  exports.PLUS_MEMBER_TYPE = PLUS_MEMBER_TYPE;
@@ -3028,9 +3111,6 @@ exports.RuleType = RuleType;
3028
3111
  exports.SCRIPT_CODE_AMOUNT_KEY = SCRIPT_CODE_AMOUNT_KEY;
3029
3112
  exports.ShippingMethodMode = ShippingMethodMode;
3030
3113
  exports.SpendMoneyType = SpendMoneyType;
3031
- exports.atobID = atobID;
3032
- exports.btoaID = btoaID;
3033
- exports.checkAttributesUpdateNeeded = checkAttributesUpdateNeeded;
3034
3114
  exports.clearGeoLocationCache = clearGeoLocationCache;
3035
3115
  exports.createMockCartFromLines = createMockCartFromLines;
3036
3116
  exports.currencyCodeMapping = currencyCodeMapping;
@@ -3038,15 +3118,18 @@ exports.defaultSWRMutationConfiguration = defaultSWRMutationConfiguration;
3038
3118
  exports.formatFunctionAutoFreeGift = formatFunctionAutoFreeGift;
3039
3119
  exports.formatScriptAutoFreeGift = formatScriptAutoFreeGift;
3040
3120
  exports.getCachedGeoLocation = getCachedGeoLocation;
3121
+ exports.getCartAttributes = getCartAttributes;
3041
3122
  exports.getDiscountEnvAttributeValue = getDiscountEnvAttributeValue;
3042
3123
  exports.getMatchedMainProductSubTotal = getMatchedMainProductSubTotal;
3043
3124
  exports.getQuery = getQuery;
3044
3125
  exports.getReferralAttributes = getReferralAttributes;
3126
+ exports.getUserType = getUserType;
3127
+ exports.hasPlusMemberInCart = hasPlusMemberInCart;
3128
+ exports.hasPlusMemberInLines = hasPlusMemberInLines;
3045
3129
  exports.normalizeAddToCartLines = normalizeAddToCartLines;
3046
3130
  exports.preCheck = preCheck;
3047
3131
  exports.safeParse = safeParse;
3048
3132
  exports.useAddCartLines = useAddCartLines;
3049
- exports.useAddPlusMemberProductsToCart = useAddPlusMemberProductsToCart;
3050
3133
  exports.useAddToCart = useAddToCart;
3051
3134
  exports.useAllBlogs = useAllBlogs;
3052
3135
  exports.useAllCollections = useAllCollections;
@@ -3056,6 +3139,7 @@ exports.useArticle = useArticle;
3056
3139
  exports.useArticles = useArticles;
3057
3140
  exports.useArticlesInBlog = useArticlesInBlog;
3058
3141
  exports.useAutoRemovePlusMemberInCart = useAutoRemovePlusMemberInCart;
3142
+ exports.useAvailableDeliveryCoupon = useAvailableDeliveryCoupon;
3059
3143
  exports.useBlog = useBlog;
3060
3144
  exports.useBuyNow = useBuyNow;
3061
3145
  exports.useCalcAutoFreeGift = useCalcAutoFreeGift;
@@ -3069,13 +3153,12 @@ exports.useCreateCart = useCreateCart;
3069
3153
  exports.useExposure = useExposure;
3070
3154
  exports.useGeoLocation = useGeoLocation;
3071
3155
  exports.useHasPlusMemberInCart = useHasPlusMemberInCart;
3156
+ exports.useHasPlusMemberInLines = useHasPlusMemberInLines;
3072
3157
  exports.useIntersection = useIntersection;
3073
- exports.usePlusAnnualProductVariant = usePlusAnnualProductVariant;
3074
3158
  exports.usePlusMemberCheckoutCustomAttributes = usePlusMemberCheckoutCustomAttributes;
3075
3159
  exports.usePlusMemberContext = usePlusMemberContext;
3076
- exports.usePlusMemberDeliveryCodes = usePlusMemberDeliveryCodes;
3077
- exports.usePlusMemberItemCustomAttributes = usePlusMemberItemCustomAttributes;
3078
- exports.usePlusMonthlyProductVariant = usePlusMonthlyProductVariant;
3160
+ exports.usePlusMemberNeedAddToCart = usePlusMemberNeedAddToCart;
3161
+ exports.usePlusMemberVariants = usePlusMemberVariants;
3079
3162
  exports.usePrice = usePrice;
3080
3163
  exports.useProduct = useProduct;
3081
3164
  exports.useProductUrl = useProductUrl;
@@ -3086,13 +3169,11 @@ exports.useReplaceCartPlusMember = useReplaceCartPlusMember;
3086
3169
  exports.useScriptAutoFreeGift = useScriptAutoFreeGift;
3087
3170
  exports.useSearch = useSearch;
3088
3171
  exports.useSelectedOptions = useSelectedOptions;
3089
- exports.useShippingMethodAvailableCheck = useShippingMethodAvailableCheck;
3090
3172
  exports.useShippingMethods = useShippingMethods;
3091
3173
  exports.useSite = useSite;
3092
3174
  exports.useUpdateCartAttributes = useUpdateCartAttributes;
3093
3175
  exports.useUpdateCartLines = useUpdateCartLines;
3094
3176
  exports.useUpdateLineCodeAmountAttributes = useUpdateLineCodeAmountAttributes;
3095
- exports.useUpdatePlusMemberDeliveryOptions = useUpdatePlusMemberDeliveryOptions;
3096
3177
  exports.useUpdateVariantQuery = useUpdateVariantQuery;
3097
3178
  exports.useVariant = useVariant;
3098
3179
  exports.useVariantMedia = useVariantMedia;