@anker-in/shopify-react 0.1.1-beta.42 → 0.1.1-beta.44

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.
@@ -525,7 +525,8 @@ var useScriptAutoFreeGift = ({
525
525
  _giveaway,
526
526
  cart,
527
527
  locale: providedLocale,
528
- lines
528
+ lines,
529
+ profile
529
530
  }) => {
530
531
  const { client, locale: contextLocale } = useShopify();
531
532
  const locale = providedLocale || contextLocale;
@@ -549,8 +550,9 @@ var useScriptAutoFreeGift = ({
549
550
  const utmCampaign = Cookies5__default.default.get("utm_campaign") || query?.utm_campaign;
550
551
  if (campaign.activityAvailableQuery && !utmCampaign?.includes(campaign.activityAvailableQuery))
551
552
  return false;
553
+ if (campaign.requireLogin && !profile?.email) return false;
552
554
  return true;
553
- }, [campaign]);
555
+ }, [campaign, profile]);
554
556
  const [upgrade_multiple, upgrade_value] = react.useMemo(() => {
555
557
  let upgrade_multiple2 = 1;
556
558
  let upgrade_value2 = 0;
@@ -689,7 +691,10 @@ function useCartContext(options) {
689
691
  }
690
692
 
691
693
  // src/hooks/cart/use-create-cart.ts
692
- function useCreateCart(options) {
694
+ function useCreateCart({
695
+ updateCookie = false,
696
+ options
697
+ }) {
693
698
  const { client, locale, cartCookieAdapter } = useShopify();
694
699
  const { mutateCart, metafieldIdentifiers } = useCartContext();
695
700
  const createNewCart = react.useCallback(
@@ -697,7 +702,8 @@ function useCreateCart(options) {
697
702
  let newCart = await shopifySdk.createCart(client, {
698
703
  ...arg,
699
704
  metafieldIdentifiers,
700
- cookieAdapter: cartCookieAdapter
705
+ cookieAdapter: cartCookieAdapter,
706
+ updateCookie
701
707
  });
702
708
  if (newCart) {
703
709
  const unApplicableCodes = newCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
@@ -1035,377 +1041,123 @@ var getLinesWithAttributes = ({
1035
1041
  return functionLine;
1036
1042
  });
1037
1043
  };
1038
-
1039
- // src/hooks/cart/use-add-to-cart.ts
1040
- function useAddToCart({ withTrack = true } = {}, swrOptions) {
1041
- const { client, config, locale, cartCookieAdapter, userAdapter, performanceAdapter } = useShopify();
1042
- const { cart, addCustomAttributes } = useCartContext();
1043
- const { trigger: applyCartCodes } = useApplyCartCodes();
1044
- const { trigger: removeInvalidCodes } = useRemoveCartCodes();
1045
- const { trigger: addCartLines2 } = useAddCartLines();
1046
- const { trigger: createCart4 } = useCreateCart();
1047
- const addToCart = react.useCallback(
1048
- async (_key, { arg }) => {
1049
- const {
1050
- lineItems,
1051
- cartId: providedCartId,
1052
- discountCodes,
1053
- gtmParams = {},
1054
- buyerIdentity,
1055
- needCreateCart = false,
1056
- onCodesInvalid,
1057
- replaceExistingCodes,
1058
- customAttributes
1059
- } = arg;
1060
- if (!lineItems || lineItems.length === 0) {
1061
- return;
1044
+ function useCalcGiftsFromLines({
1045
+ lines,
1046
+ customer,
1047
+ scriptGiveawayKey = CUSTOMER_SCRIPT_GIFT_KEY
1048
+ }) {
1049
+ const { locale } = useShopify();
1050
+ const { cart, autoFreeGiftConfig, gradientGiftsConfig } = useCartContext();
1051
+ const functionGift = useCalcAutoFreeGift(cart, autoFreeGiftConfig || [], customer, lines);
1052
+ const scriptGift = useScriptAutoFreeGift({
1053
+ campaign: gradientGiftsConfig || null,
1054
+ _giveaway: scriptGiveawayKey,
1055
+ cart,
1056
+ locale,
1057
+ lines
1058
+ });
1059
+ const allGiftLines = react.useMemo(() => {
1060
+ const functionGiftLines = (functionGift.qualifyingGift?.itemsToAdd || []).map((item) => {
1061
+ const product = functionGift.giftProductsResult?.find(
1062
+ (product2) => product2.handle === item.variant.handle
1063
+ );
1064
+ const variants = product?.variants;
1065
+ const variant = Array.isArray(variants) ? variants.find((v) => v.sku === item.variant.sku) : void 0;
1066
+ if (!variant) {
1067
+ console.warn(
1068
+ `Function gift: Variant not found for handle=${item.variant.handle}, sku=${item.variant.sku}`
1069
+ );
1070
+ return null;
1062
1071
  }
1063
- performanceAdapter?.addToCartStart();
1064
- const linesWithFunctionAttributes = getLinesWithAttributes({ cart, lineItems });
1065
- const lines = linesWithFunctionAttributes.map((item) => ({
1066
- merchandiseId: item.variant?.id || "",
1067
- quantity: item.quantity || 1,
1068
- attributes: item.attributes,
1069
- sellingPlanId: item.sellingPlanId
1070
- })).filter((item) => item.merchandiseId && item.quantity);
1071
- if (lines.length === 0) {
1072
- return;
1072
+ return {
1073
+ variant: {
1074
+ ...variant,
1075
+ product
1076
+ },
1077
+ quantity: item.quantity ?? 1,
1078
+ attributes: item.attributes
1079
+ };
1080
+ }).filter((item) => item !== null);
1081
+ const scriptGiftLines = scriptGift.freeGiftLevel ? scriptGift.freeGiftLevel.giveawayProducts.map((item) => {
1082
+ const product = scriptGift.giftProductsResult?.find(
1083
+ (product2) => product2.handle === item.handle
1084
+ );
1085
+ const variants = product?.variants;
1086
+ const variant = Array.isArray(variants) ? variants.find((v) => v.sku === item.sku) : void 0;
1087
+ if (!variant) {
1088
+ console.warn(`Script gift: Variant not found for handle=${item.handle}, sku=${item.sku}`);
1089
+ return null;
1073
1090
  }
1074
- let cartId = needCreateCart ? void 0 : providedCartId || cart?.id;
1075
- let resultCart = null;
1076
- if (!cartId) {
1077
- resultCart = await createCart4({
1078
- lines,
1079
- buyerIdentity,
1080
- discountCodes,
1081
- customAttributes
1082
- });
1083
- } else {
1084
- resultCart = await addCartLines2({
1085
- cartId,
1086
- lines
1087
- });
1088
- console.log("npm addCartLines resultCart", resultCart);
1089
- if (resultCart && resultCart.discountCodes && resultCart.discountCodes.length > 0) {
1090
- const unapplicableCodes = resultCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
1091
- if (unapplicableCodes.length > 0) {
1092
- if (onCodesInvalid) {
1093
- const handledCart = await onCodesInvalid(resultCart, unapplicableCodes);
1094
- if (handledCart) {
1095
- resultCart = handledCart;
1096
- }
1097
- } else {
1098
- await removeInvalidCodes({
1099
- discountCodes: unapplicableCodes
1100
- });
1101
- }
1091
+ return {
1092
+ variant: {
1093
+ ...variant,
1094
+ product
1095
+ },
1096
+ quantity: 1,
1097
+ attributes: [
1098
+ {
1099
+ key: scriptGiveawayKey,
1100
+ value: "true"
1102
1101
  }
1103
- }
1104
- if (resultCart && discountCodes && discountCodes.length > 0) {
1105
- applyCartCodes({
1106
- replaceExistingCodes,
1107
- discountCodes
1108
- });
1109
- }
1110
- if (customAttributes && customAttributes.length > 0) {
1111
- addCustomAttributes(customAttributes);
1112
- }
1113
- }
1114
- if (withTrack) {
1115
- trackAddToCartGA({
1116
- lineItems,
1117
- gtmParams: { ...gtmParams, brand: config.getBrand() }
1118
- });
1119
- trackAddToCartFBQ({ lineItems });
1120
- }
1121
- performanceAdapter?.addToCartEnd();
1122
- return resultCart;
1123
- },
1124
- [
1125
- client,
1126
- locale,
1127
- cartCookieAdapter,
1128
- userAdapter,
1129
- cart,
1130
- withTrack,
1131
- performanceAdapter,
1132
- createCart4,
1133
- addCartLines2,
1134
- applyCartCodes,
1135
- removeInvalidCodes,
1136
- addCustomAttributes,
1137
- config
1138
- ]
1139
- );
1140
- return useSWRMutation__default.default("add-to-cart", addToCart, swrOptions);
1102
+ ]
1103
+ };
1104
+ }).filter((item) => item !== null) : [];
1105
+ return [...functionGiftLines, ...scriptGiftLines];
1106
+ }, [
1107
+ functionGift.qualifyingGift,
1108
+ functionGift.giftProductsResult,
1109
+ scriptGift.freeGiftLevel,
1110
+ scriptGift.giftProductsResult,
1111
+ scriptGiveawayKey
1112
+ ]);
1113
+ const hasGifts = react.useMemo(() => {
1114
+ return allGiftLines.length > 0;
1115
+ }, [allGiftLines]);
1116
+ return {
1117
+ functionGift,
1118
+ scriptGift,
1119
+ allGiftLines,
1120
+ hasGifts
1121
+ };
1141
1122
  }
1142
- function useUpdateCartLines(options) {
1143
- const { client, locale, cartCookieAdapter } = useShopify();
1144
- const { mutateCart, metafieldIdentifiers } = useCartContext();
1145
- const updateLines = react.useCallback(
1146
- async (_key, { arg }) => {
1147
- const updatedCart = await shopifySdk.updateCartLines(client, {
1148
- ...arg,
1149
- metafieldIdentifiers,
1150
- cookieAdapter: cartCookieAdapter
1151
- });
1152
- if (updatedCart) {
1153
- mutateCart(updatedCart);
1154
- }
1155
- console.log("use-update-cart-lines updatedCart", metafieldIdentifiers, updatedCart);
1156
- return updatedCart;
1157
- },
1158
- [client, locale, cartCookieAdapter, mutateCart, metafieldIdentifiers]
1159
- );
1160
- return useSWRMutation__default.default("update-cart-lines", updateLines, options);
1161
- }
1162
- function useRemoveCartLines(options) {
1163
- const { client, locale, cartCookieAdapter } = useShopify();
1164
- const { mutateCart, metafieldIdentifiers } = useCartContext();
1165
- const removeLines = react.useCallback(
1166
- async (_key, { arg }) => {
1167
- const { autoRemoveInvalidCodes = true, onCodesRemoved, cartId, lineIds } = arg;
1168
- let updatedCart = await shopifySdk.removeCartLines(client, {
1169
- cartId,
1170
- lineIds,
1171
- metafieldIdentifiers,
1172
- cookieAdapter: cartCookieAdapter
1173
- });
1174
- if (updatedCart && autoRemoveInvalidCodes) {
1175
- const unApplicableCodes = updatedCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
1176
- if (unApplicableCodes.length > 0) {
1177
- if (onCodesRemoved) {
1178
- const handledCart = await onCodesRemoved(updatedCart, unApplicableCodes);
1179
- if (handledCart) {
1180
- updatedCart = handledCart;
1181
- }
1182
- } else {
1183
- updatedCart = await shopifySdk.updateCartCodes(client, {
1184
- cartId: updatedCart.id,
1185
- discountCodes: updatedCart.discountCodes.filter((item) => item.applicable).map((item) => item.code),
1186
- metafieldIdentifiers,
1187
- cookieAdapter: cartCookieAdapter
1188
- }) || updatedCart;
1189
- }
1190
- }
1191
- }
1192
- if (updatedCart) {
1193
- mutateCart(updatedCart);
1194
- }
1195
- return updatedCart;
1196
- },
1197
- [client, locale, cartCookieAdapter, mutateCart, metafieldIdentifiers]
1198
- );
1199
- return useSWRMutation__default.default("remove-cart-lines", removeLines, options);
1200
- }
1201
- function useUpdateCartAttributes({
1202
- mutate,
1203
- metafieldIdentifiers,
1204
- disabled = false,
1205
- swrOptions
1206
- }) {
1207
- const { client, locale, cartCookieAdapter } = useShopify();
1208
- const updateAttributes = react.useCallback(
1209
- async (_key, { arg }) => {
1210
- if (disabled || !cartCookieAdapter?.getCartId(locale)) {
1211
- return void 0;
1212
- }
1213
- const updatedCart = await shopifySdk.updateCartAttributes(client, {
1214
- ...arg,
1215
- metafieldIdentifiers,
1216
- cookieAdapter: cartCookieAdapter
1217
- });
1218
- if (updatedCart) {
1219
- mutate(updatedCart);
1220
- }
1221
- return updatedCart;
1222
- },
1223
- [client, locale, cartCookieAdapter, mutate, metafieldIdentifiers, disabled]
1224
- );
1225
- return useSWRMutation__default.default("update-cart-attributes", updateAttributes, swrOptions);
1226
- }
1227
- function useBuyNow({ withTrack = true } = {}, swrOptions) {
1228
- const { client, config, locale, cartCookieAdapter, userAdapter } = useShopify();
1229
- const isLoggedIn = userAdapter?.isLoggedIn || false;
1230
- const buyNow = react.useCallback(
1231
- async (_key, { arg }) => {
1232
- const {
1233
- lineItems,
1234
- discountCodes,
1235
- gtmParams = {},
1236
- buyerIdentity,
1237
- fbqTrackConfig,
1238
- customAttributes,
1239
- metafieldIdentifiers,
1240
- redirectToCheckout
1241
- } = arg;
1242
- if (!lineItems || lineItems.length === 0) {
1243
- return;
1244
- }
1245
- const linesWithFunctionAttributes = getLinesWithAttributes({
1246
- lineItems
1247
- });
1248
- const lines = linesWithFunctionAttributes.map((item) => ({
1249
- merchandiseId: item.variant?.id || "",
1250
- quantity: item.quantity || 1,
1251
- attributes: item.attributes,
1252
- sellingPlanId: item.sellingPlanId
1253
- })).filter((item) => item.merchandiseId);
1254
- if (lines.length === 0) {
1255
- return;
1256
- }
1257
- const resultCart = await shopifySdk.createCart(client, {
1258
- lines,
1259
- metafieldIdentifiers,
1260
- cookieAdapter: cartCookieAdapter,
1261
- buyerIdentity,
1262
- discountCodes,
1263
- customAttributes
1264
- });
1265
- if (!resultCart) {
1266
- throw new Error("Failed to create cart for buy now");
1267
- }
1268
- if (withTrack && resultCart.lineItems) {
1269
- trackBuyNowGA({
1270
- lineItems,
1271
- gtmParams: { ...gtmParams, brand: config.getBrand() }
1272
- });
1273
- if (fbqTrackConfig) {
1274
- trackBuyNowFBQ({ trackConfig: fbqTrackConfig });
1275
- }
1276
- }
1277
- if (redirectToCheckout) {
1278
- if (resultCart.url) {
1279
- if (typeof window !== "undefined") {
1280
- window.location.href = resultCart.url;
1281
- }
1282
- } else {
1283
- throw new Error("Failed to get checkout URL");
1284
- }
1285
- }
1286
- return resultCart;
1287
- },
1288
- [client, locale, isLoggedIn, cartCookieAdapter, withTrack]
1289
- );
1290
- return useSWRMutation__default.default("buy-now", buyNow, swrOptions);
1291
- }
1292
- function useCalcGiftsFromLines({
1293
- lines,
1294
- customer,
1295
- scriptGiveawayKey = CUSTOMER_SCRIPT_GIFT_KEY
1296
- }) {
1297
- const { locale } = useShopify();
1298
- const { cart, autoFreeGiftConfig, gradientGiftsConfig } = useCartContext();
1299
- const functionGift = useCalcAutoFreeGift(cart, autoFreeGiftConfig || [], customer, lines);
1300
- const scriptGift = useScriptAutoFreeGift({
1301
- campaign: gradientGiftsConfig || null,
1302
- _giveaway: scriptGiveawayKey,
1303
- cart,
1304
- locale,
1305
- lines
1306
- });
1307
- const allGiftLines = react.useMemo(() => {
1308
- const functionGiftLines = (functionGift.qualifyingGift?.itemsToAdd || []).map((item) => {
1309
- const product = functionGift.giftProductsResult?.find(
1310
- (product2) => product2.handle === item.variant.handle
1311
- );
1312
- const variants = product?.variants;
1313
- const variant = Array.isArray(variants) ? variants.find((v) => v.sku === item.variant.sku) : void 0;
1314
- if (!variant) {
1315
- console.warn(
1316
- `Function gift: Variant not found for handle=${item.variant.handle}, sku=${item.variant.sku}`
1317
- );
1318
- return null;
1319
- }
1320
- return {
1321
- variant: {
1322
- ...variant,
1323
- product
1324
- },
1325
- quantity: item.quantity ?? 1,
1326
- attributes: item.attributes
1327
- };
1328
- }).filter((item) => item !== null);
1329
- const scriptGiftLines = scriptGift.freeGiftLevel ? scriptGift.freeGiftLevel.giveawayProducts.map((item) => {
1330
- const product = scriptGift.giftProductsResult?.find(
1331
- (product2) => product2.handle === item.handle
1332
- );
1333
- const variants = product?.variants;
1334
- const variant = Array.isArray(variants) ? variants.find((v) => v.sku === item.sku) : void 0;
1335
- if (!variant) {
1336
- console.warn(`Script gift: Variant not found for handle=${item.handle}, sku=${item.sku}`);
1337
- return null;
1338
- }
1339
- return {
1340
- variant: {
1341
- ...variant,
1342
- product
1343
- },
1344
- quantity: 1,
1345
- attributes: [
1346
- {
1347
- key: scriptGiveawayKey,
1348
- value: "true"
1349
- }
1350
- ]
1351
- };
1352
- }).filter((item) => item !== null) : [];
1353
- return [...functionGiftLines, ...scriptGiftLines];
1354
- }, [
1355
- functionGift.qualifyingGift,
1356
- functionGift.giftProductsResult,
1357
- scriptGift.freeGiftLevel,
1358
- scriptGift.giftProductsResult,
1359
- scriptGiveawayKey
1360
- ]);
1361
- const hasGifts = react.useMemo(() => {
1362
- return allGiftLines.length > 0;
1363
- }, [allGiftLines]);
1364
- return {
1365
- functionGift,
1366
- scriptGift,
1367
- allGiftLines,
1368
- hasGifts
1369
- };
1370
- }
1371
-
1372
- // src/hooks/cart/types/order-discount.ts
1373
- var OrderDiscountType = /* @__PURE__ */ ((OrderDiscountType2) => {
1374
- OrderDiscountType2[OrderDiscountType2["PERCENTAGE"] = 1] = "PERCENTAGE";
1375
- OrderDiscountType2[OrderDiscountType2["FIXED_AMOUNT"] = 2] = "FIXED_AMOUNT";
1376
- OrderDiscountType2[OrderDiscountType2["REDUCE_PRICE"] = 3] = "REDUCE_PRICE";
1377
- return OrderDiscountType2;
1378
- })(OrderDiscountType || {});
1379
- var OrderBasePriceType = /* @__PURE__ */ ((OrderBasePriceType2) => {
1380
- OrderBasePriceType2[OrderBasePriceType2["ORIGIN_PRICE"] = 1] = "ORIGIN_PRICE";
1381
- OrderBasePriceType2[OrderBasePriceType2["MIN_DISCOUNTED_PRICE"] = 2] = "MIN_DISCOUNTED_PRICE";
1382
- return OrderBasePriceType2;
1383
- })(OrderBasePriceType || {});
1384
-
1385
- // src/hooks/cart/feature/use-calc-order-discount.ts
1386
- var useCalcOrderDiscount = (cart, orderDiscountConfig, customer) => {
1387
- const tags = react.useMemo(() => customer?.tags || [], [customer?.tags]);
1388
- const isCustomerLoading = react.useMemo(() => !customer ? true : false, [customer]);
1389
- const dealsType = "";
1390
- const { activeCampaign, subtotal } = react.useMemo(() => {
1391
- for (const campaign of orderDiscountConfig || []) {
1392
- const { rule_conditions = [], result_detail } = campaign;
1393
- const { main_product, order_discount_conf } = result_detail || {};
1394
- const isPreCheckPassed = preCheck(rule_conditions, tags, []);
1395
- if (isPreCheckPassed && main_product && order_discount_conf) {
1396
- const matchedSubtotal = getMatchedMainProductSubTotal(
1397
- cart,
1398
- main_product?.variant_list?.map((v) => v.variant_id) || [],
1399
- {
1400
- spend_money_type: order_discount_conf.base_price === 2 /* MIN_DISCOUNTED_PRICE */ ? 2 : 1,
1401
- // 根据基础价格类型设置
1402
- variant_id_list: main_product?.variant_list?.map((v) => v.variant_id) || [],
1403
- all_store_variant: main_product?.all_store_variant || false
1404
- }
1405
- );
1406
- if (matchedSubtotal > 0) {
1407
- return { activeCampaign: campaign, subtotal: matchedSubtotal };
1408
- }
1123
+
1124
+ // src/hooks/cart/types/order-discount.ts
1125
+ var OrderDiscountType = /* @__PURE__ */ ((OrderDiscountType2) => {
1126
+ OrderDiscountType2[OrderDiscountType2["PERCENTAGE"] = 1] = "PERCENTAGE";
1127
+ OrderDiscountType2[OrderDiscountType2["FIXED_AMOUNT"] = 2] = "FIXED_AMOUNT";
1128
+ OrderDiscountType2[OrderDiscountType2["REDUCE_PRICE"] = 3] = "REDUCE_PRICE";
1129
+ return OrderDiscountType2;
1130
+ })(OrderDiscountType || {});
1131
+ var OrderBasePriceType = /* @__PURE__ */ ((OrderBasePriceType2) => {
1132
+ OrderBasePriceType2[OrderBasePriceType2["ORIGIN_PRICE"] = 1] = "ORIGIN_PRICE";
1133
+ OrderBasePriceType2[OrderBasePriceType2["MIN_DISCOUNTED_PRICE"] = 2] = "MIN_DISCOUNTED_PRICE";
1134
+ return OrderBasePriceType2;
1135
+ })(OrderBasePriceType || {});
1136
+
1137
+ // src/hooks/cart/feature/use-calc-order-discount.ts
1138
+ var useCalcOrderDiscount = (cart, orderDiscountConfig, customer) => {
1139
+ const tags = react.useMemo(() => customer?.tags || [], [customer?.tags]);
1140
+ const isCustomerLoading = react.useMemo(() => !customer ? true : false, [customer]);
1141
+ const dealsType = "";
1142
+ const { activeCampaign, subtotal } = react.useMemo(() => {
1143
+ for (const campaign of orderDiscountConfig || []) {
1144
+ const { rule_conditions = [], result_detail } = campaign;
1145
+ const { main_product, order_discount_conf } = result_detail || {};
1146
+ const isPreCheckPassed = preCheck(rule_conditions, tags, []);
1147
+ if (isPreCheckPassed && main_product && order_discount_conf) {
1148
+ const matchedSubtotal = getMatchedMainProductSubTotal(
1149
+ cart,
1150
+ main_product?.variant_list?.map((v) => v.variant_id) || [],
1151
+ {
1152
+ spend_money_type: order_discount_conf.base_price === 2 /* MIN_DISCOUNTED_PRICE */ ? 2 : 1,
1153
+ // 根据基础价格类型设置
1154
+ variant_id_list: main_product?.variant_list?.map((v) => v.variant_id) || [],
1155
+ all_store_variant: main_product?.all_store_variant || false
1156
+ }
1157
+ );
1158
+ if (matchedSubtotal > 0) {
1159
+ return { activeCampaign: campaign, subtotal: matchedSubtotal };
1160
+ }
1409
1161
  }
1410
1162
  }
1411
1163
  return { activeCampaign: null, subtotal: 0 };
@@ -1460,37 +1212,6 @@ var useCalcOrderDiscount = (cart, orderDiscountConfig, customer) => {
1460
1212
  isLoading: isCustomerLoading
1461
1213
  };
1462
1214
  };
1463
- function useHasPlusMemberInCart({
1464
- memberSetting,
1465
- cart
1466
- }) {
1467
- const { plus_monthly_product, plus_annual_product } = memberSetting || {};
1468
- return react.useMemo(() => {
1469
- if (!cart?.lineItems) {
1470
- return {
1471
- hasPlusMember: false,
1472
- hasMonthlyPlus: false,
1473
- hasAnnualPlus: false
1474
- };
1475
- }
1476
- const monthlyPlusItem = cart.lineItems.find(
1477
- (item) => item.product?.handle === plus_monthly_product?.handle && item.variant?.sku === plus_monthly_product?.sku
1478
- );
1479
- const annualPlusItem = cart.lineItems.find(
1480
- (item) => item.product?.handle === plus_annual_product?.handle && item.variant?.sku === plus_annual_product?.sku
1481
- );
1482
- const hasMonthlyPlus = !!monthlyPlusItem;
1483
- const hasAnnualPlus = !!annualPlusItem;
1484
- const hasPlusMember = hasMonthlyPlus || hasAnnualPlus;
1485
- return {
1486
- hasPlusMember,
1487
- hasMonthlyPlus,
1488
- hasAnnualPlus,
1489
- monthlyPlusItem,
1490
- annualPlusItem
1491
- };
1492
- }, [cart?.lineItems, plus_monthly_product, plus_annual_product]);
1493
- }
1494
1215
  var getReferralAttributes = () => {
1495
1216
  const inviteCode = shopifySdk.getLocalStorage("inviteCode") || Cookies5__default.default.get("inviteCode");
1496
1217
  const playModeId = shopifySdk.getLocalStorage("playModeId") || Cookies5__default.default.get("playModeId");
@@ -1507,158 +1228,130 @@ var getReferralAttributes = () => {
1507
1228
  }
1508
1229
  return [];
1509
1230
  };
1510
- var useCartAttributes = ({
1231
+ var getUserType = (customer) => {
1232
+ let userInfo = Cookies5__default.default.get("userInfo");
1233
+ if (userInfo) {
1234
+ userInfo = JSON.parse(userInfo);
1235
+ let arr = typeof userInfo?.id == "string" && userInfo?.id.split("/");
1236
+ userInfo.setId = arr[arr.length - 1];
1237
+ }
1238
+ const customerInfo = userInfo || customer;
1239
+ if (!customerInfo) {
1240
+ return "new_user_unlogin";
1241
+ }
1242
+ if (customer) {
1243
+ const { orders = {} } = customer;
1244
+ if (orders?.edges?.length === 1) {
1245
+ return "old_user_orders_once";
1246
+ } else if (orders?.edges?.length > 1) {
1247
+ return "old_user_orders_twice";
1248
+ }
1249
+ }
1250
+ return "new_user_login";
1251
+ };
1252
+ function getCartAttributes({
1511
1253
  profile,
1512
1254
  customer,
1513
1255
  cart,
1514
- memberSetting
1515
- }) => {
1516
- const [currentUrl, setCurrentUrl] = react.useState("");
1517
- const { hasPlusMember } = useHasPlusMemberInCart({
1518
- memberSetting,
1519
- cart
1520
- });
1521
- react.useEffect(() => {
1522
- setCurrentUrl(window.location.href);
1523
- }, []);
1524
- const userType = react.useMemo(() => {
1525
- let userInfo = Cookies5__default.default.get("userInfo");
1526
- if (userInfo) {
1527
- userInfo = JSON.parse(userInfo);
1528
- let arr = typeof userInfo?.id == "string" && userInfo?.id.split("/");
1529
- userInfo.setId = arr[arr.length - 1];
1530
- }
1531
- const customerInfo = userInfo || customer;
1532
- if (!customerInfo) {
1533
- return "new_user_unlogin";
1534
- }
1535
- if (customer) {
1536
- const { orders = {} } = customer;
1537
- if (orders?.edges?.length === 1) {
1538
- return "old_user_orders_once";
1539
- } else if (orders?.edges?.length > 1) {
1540
- return "old_user_orders_twice";
1541
- }
1256
+ memberType,
1257
+ currentUrl = ""
1258
+ }) {
1259
+ const userType = getUserType(customer);
1260
+ const memberAttributes = [
1261
+ {
1262
+ key: "_token",
1263
+ value: profile?.token
1264
+ },
1265
+ {
1266
+ key: "_member_type",
1267
+ value: memberType ?? String(profile?.memberType || 0)
1268
+ },
1269
+ {
1270
+ key: "_user_type",
1271
+ value: userType
1272
+ },
1273
+ {
1274
+ key: "_is_login",
1275
+ value: profile?.token ? "true" : "false"
1276
+ }
1277
+ ];
1278
+ if (profile?.token) {
1279
+ memberAttributes.push({
1280
+ key: "_login_user",
1281
+ value: "1"
1282
+ });
1283
+ }
1284
+ const discountCodes = cart?.discountCodes.map((item) => item.code).filter((code) => code) || [];
1285
+ const functionAttributes = [
1286
+ {
1287
+ key: CUSTOMER_ATTRIBUTE_KEY,
1288
+ value: JSON.stringify({
1289
+ discount_code: discountCodes,
1290
+ user_tags: customer?.tags || []
1291
+ })
1292
+ }
1293
+ ];
1294
+ const presellAttributes = [
1295
+ {
1296
+ key: "_presale",
1297
+ value: cart?.lineItems.some((item) => item?.variant?.metafields?.presell === "presell")
1542
1298
  }
1543
- return "new_user_login";
1544
- }, [customer]);
1545
- const memberAttributes = react.useMemo(() => {
1546
- const attributes = [
1547
- {
1548
- key: "_token",
1549
- value: profile?.token
1550
- //是否登录
1551
- },
1552
- {
1553
- key: "_member_type",
1554
- value: hasPlusMember ? "2" : profile?.memberType
1555
- //:0(游客),1(普通会员),2(付费会员)
1556
- },
1557
- {
1558
- key: "_user_type",
1559
- value: userType
1560
- // n
1561
- },
1562
- {
1563
- key: "_is_login",
1564
- value: profile?.token ? "true" : "false"
1565
- }
1566
- ];
1567
- if (profile?.token) {
1568
- attributes.push({
1569
- key: "_login_user",
1570
- value: "1"
1571
- });
1299
+ ];
1300
+ const weightAttributes = [
1301
+ {
1302
+ key: "_weight",
1303
+ value: cart?.lineItems.reduce((acc, item) => {
1304
+ return new Decimal2__default.default(acc).plus(item.variant.weight ?? 0).toNumber();
1305
+ }, 0).toString()
1306
+ },
1307
+ {
1308
+ key: "_app_source_name",
1309
+ value: "dtc"
1572
1310
  }
1573
- return attributes;
1574
- }, [profile?.memberType, profile?.token, userType, hasPlusMember]);
1575
- const functionAttributes = react.useMemo(() => {
1576
- const hasFunctionEnvAttribute = cart?.lineItems.some(
1577
- (item) => item.customAttributes?.some((attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY)
1578
- );
1579
- const discountCodes = cart?.discountCodes.map((item) => item.code).filter((code) => code) || [];
1580
- return hasFunctionEnvAttribute ? [
1581
- {
1582
- key: "_discounts_function_env",
1583
- value: JSON.stringify({
1584
- discount_code: discountCodes,
1585
- user_tags: customer?.tags || []
1586
- })
1587
- }
1588
- ] : [];
1589
- }, [cart, customer]);
1590
- const presellAttributes = react.useMemo(() => {
1591
- return [
1592
- {
1593
- key: "_presale",
1594
- value: cart?.lineItems.some((item) => item?.variant?.metafields?.presell === "presell")
1595
- }
1596
- ];
1597
- }, [cart]);
1598
- const weightAttributes = react.useMemo(() => {
1599
- return [
1600
- {
1601
- key: "_weight",
1602
- value: cart?.lineItems.reduce((acc, item) => {
1603
- return new Decimal2__default.default(acc).plus(item.variant.weight ?? 0).toNumber();
1604
- }, 0).toString()
1605
- },
1606
- {
1607
- key: "_app_source_name",
1608
- value: "dtc"
1609
- }
1610
- ];
1611
- }, [cart]);
1612
- const trackingAttributes = react.useMemo(() => {
1613
- return [
1614
- {
1615
- key: "utm_params",
1616
- value: currentUrl
1617
- }
1618
- ];
1619
- }, [currentUrl]);
1620
- const commonAttributes = react.useMemo(
1621
- () => [
1622
- ...memberAttributes,
1623
- ...functionAttributes,
1624
- ...presellAttributes,
1625
- ...weightAttributes,
1626
- ...trackingAttributes,
1627
- ...getReferralAttributes()
1628
- ].filter((item) => item?.value),
1629
- [memberAttributes, functionAttributes, presellAttributes, weightAttributes, trackingAttributes]
1630
- );
1631
- const extraAttributesInCart = react.useMemo(() => {
1632
- const commonAttributeKeys = [
1633
- // member attributes
1634
- "_token",
1635
- "_member_type",
1636
- "_user_type",
1637
- "_is_login",
1638
- "_login_user",
1639
- // function attributes
1640
- "_discounts_function_env",
1641
- // presell attributes
1642
- "_presale",
1643
- // weight attributes
1644
- "_weight",
1645
- "_app_source_name",
1646
- // tracking attributes
1647
- "utm_params",
1648
- // referral attributes
1649
- "_invite_code",
1650
- "_play_mode_id",
1651
- "_popup"
1652
- ];
1653
- return cart?.customAttributes?.filter((item) => !commonAttributeKeys.includes(item.key)) || [];
1654
- }, [cart]);
1311
+ ];
1312
+ const trackingAttributes = [
1313
+ {
1314
+ key: "utm_params",
1315
+ value: currentUrl
1316
+ }
1317
+ ];
1318
+ const commonAttributes = [
1319
+ ...memberAttributes,
1320
+ ...functionAttributes,
1321
+ ...presellAttributes,
1322
+ ...weightAttributes,
1323
+ ...trackingAttributes,
1324
+ ...getReferralAttributes()
1325
+ ].filter((item) => item?.value);
1326
+ const extraAttributesInCart = cart?.customAttributes?.filter(
1327
+ (item) => !commonAttributes.some((attr) => attr.key === item.key)
1328
+ ) || [];
1329
+ return [...commonAttributes, ...extraAttributesInCart].filter((item) => item?.value);
1330
+ }
1331
+ var useCartAttributes = ({
1332
+ profile,
1333
+ customer,
1334
+ cart,
1335
+ memberType
1336
+ }) => {
1337
+ const [currentUrl, setCurrentUrl] = react.useState("");
1338
+ react.useEffect(() => {
1339
+ setCurrentUrl(window.location.href);
1340
+ }, []);
1341
+ const attributes = react.useMemo(() => {
1342
+ return getCartAttributes({
1343
+ profile,
1344
+ customer,
1345
+ cart,
1346
+ memberType,
1347
+ currentUrl
1348
+ });
1349
+ }, [profile, customer, cart, memberType, currentUrl]);
1655
1350
  return react.useMemo(
1656
1351
  () => ({
1657
- attributes: [...commonAttributes, ...extraAttributesInCart].filter(
1658
- (item) => item?.value
1659
- )
1352
+ attributes
1660
1353
  }),
1661
- [commonAttributes, extraAttributesInCart]
1354
+ [attributes]
1662
1355
  );
1663
1356
  };
1664
1357
  var DEFAULT_MIN = 1;
@@ -1695,6 +1388,51 @@ var useCartItemQuantityLimit = ({
1695
1388
  }, [cartItem, cart]);
1696
1389
  return quantityLimit;
1697
1390
  };
1391
+ function hasPlusMemberInLines({
1392
+ memberSetting,
1393
+ lines
1394
+ }) {
1395
+ const { plus_monthly_product, plus_annual_product } = memberSetting || {};
1396
+ if (!lines || lines.length === 0) {
1397
+ return {
1398
+ hasPlusMember: false,
1399
+ hasMonthlyPlus: false,
1400
+ hasAnnualPlus: false
1401
+ };
1402
+ }
1403
+ const monthlyPlusLine = lines.find((line) => {
1404
+ const variantHandle = line.variant?.product?.handle;
1405
+ const variantSku = line.variant?.sku;
1406
+ return variantHandle === plus_monthly_product?.handle && variantSku === plus_monthly_product?.sku;
1407
+ });
1408
+ const annualPlusLine = lines.find((line) => {
1409
+ const variantHandle = line.variant?.product?.handle;
1410
+ const variantSku = line.variant?.sku;
1411
+ return variantHandle === plus_annual_product?.handle && variantSku === plus_annual_product?.sku;
1412
+ });
1413
+ const hasMonthlyPlus = !!monthlyPlusLine;
1414
+ const hasAnnualPlus = !!annualPlusLine;
1415
+ const hasPlusMember = hasMonthlyPlus || hasAnnualPlus;
1416
+ return {
1417
+ hasPlusMember,
1418
+ hasMonthlyPlus,
1419
+ hasAnnualPlus,
1420
+ monthlyPlusLine,
1421
+ annualPlusLine
1422
+ };
1423
+ }
1424
+ function useHasPlusMemberInLines({
1425
+ memberSetting,
1426
+ lines
1427
+ }) {
1428
+ return react.useMemo(
1429
+ () => hasPlusMemberInLines({
1430
+ memberSetting,
1431
+ lines
1432
+ }),
1433
+ [memberSetting, lines]
1434
+ );
1435
+ }
1698
1436
  var useUpdateLineCodeAmountAttributes = ({
1699
1437
  cart,
1700
1438
  mutateCart,
@@ -1810,45 +1548,61 @@ var useUpdateLineCodeAmountAttributes = ({
1810
1548
  }, [loading, setLoadingState]);
1811
1549
  };
1812
1550
 
1813
- // src/hooks/cart/types/price-discount.ts
1814
- var PriceDiscountType = /* @__PURE__ */ ((PriceDiscountType2) => {
1815
- PriceDiscountType2[PriceDiscountType2["PERCENTAGE"] = 1] = "PERCENTAGE";
1816
- PriceDiscountType2[PriceDiscountType2["FIXED_AMOUNT"] = 2] = "FIXED_AMOUNT";
1817
- return PriceDiscountType2;
1818
- })(PriceDiscountType || {});
1819
- var PriceBasePriceType = /* @__PURE__ */ ((PriceBasePriceType2) => {
1820
- PriceBasePriceType2[PriceBasePriceType2["MIN_DISCOUNTED_PRICE"] = 1] = "MIN_DISCOUNTED_PRICE";
1821
- PriceBasePriceType2[PriceBasePriceType2["MIN_TOTAL_PRICE"] = 2] = "MIN_TOTAL_PRICE";
1822
- return PriceBasePriceType2;
1823
- })(PriceBasePriceType || {});
1824
- function useProduct(options = {}) {
1825
- const { client, locale } = useShopify();
1826
- const { handle, metafieldIdentifiers, ...swrOptions } = options;
1827
- return useSWR__default.default(
1828
- handle ? ["product", locale, handle, metafieldIdentifiers] : null,
1829
- () => shopifySdk.getProduct(client, {
1830
- handle,
1831
- locale,
1832
- metafieldIdentifiers
1833
- }),
1834
- swrOptions
1835
- );
1836
- }
1837
- function useAllProducts(options = {}) {
1838
- const { client, locale } = useShopify();
1839
- const { first, query, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
1840
- return useSWR__default.default(
1841
- ["all-products", locale, first, query, sortKey, reverse, metafieldIdentifiers],
1842
- () => shopifySdk.getAllProducts(client, {
1843
- locale,
1844
- first,
1845
- query,
1846
- sortKey,
1847
- reverse,
1848
- metafieldIdentifiers
1849
- }),
1850
- swrOptions
1851
- );
1551
+ // src/hooks/member/plus/types.ts
1552
+ var PLUS_MEMBER_TYPE = /* @__PURE__ */ ((PLUS_MEMBER_TYPE2) => {
1553
+ PLUS_MEMBER_TYPE2[PLUS_MEMBER_TYPE2["FREE"] = 0] = "FREE";
1554
+ PLUS_MEMBER_TYPE2[PLUS_MEMBER_TYPE2["MONTHLY"] = 1] = "MONTHLY";
1555
+ PLUS_MEMBER_TYPE2[PLUS_MEMBER_TYPE2["ANNUAL"] = 2] = "ANNUAL";
1556
+ return PLUS_MEMBER_TYPE2;
1557
+ })(PLUS_MEMBER_TYPE || {});
1558
+ var PlusMemberMode = /* @__PURE__ */ ((PlusMemberMode2) => {
1559
+ PlusMemberMode2["MONTHLY"] = "monthly";
1560
+ PlusMemberMode2["ANNUAL"] = "annual";
1561
+ return PlusMemberMode2;
1562
+ })(PlusMemberMode || {});
1563
+ var DeliveryPlusType = /* @__PURE__ */ ((DeliveryPlusType2) => {
1564
+ DeliveryPlusType2["FREE"] = "free";
1565
+ DeliveryPlusType2["MONTHLY"] = "monthly";
1566
+ DeliveryPlusType2["ANNUAL"] = "annual";
1567
+ return DeliveryPlusType2;
1568
+ })(DeliveryPlusType || {});
1569
+ var ShippingMethodMode = /* @__PURE__ */ ((ShippingMethodMode2) => {
1570
+ ShippingMethodMode2["FREE"] = "free";
1571
+ ShippingMethodMode2["TDD"] = "tdd";
1572
+ ShippingMethodMode2["NDD"] = "ndd";
1573
+ return ShippingMethodMode2;
1574
+ })(ShippingMethodMode || {});
1575
+ var createInitialValue = () => ({
1576
+ plusMemberMetafields: {},
1577
+ selectedPlusMemberMode: "free",
1578
+ setSelectedPlusMemberMode: () => {
1579
+ },
1580
+ selectedShippingMethod: void 0,
1581
+ setSelectedShippingMethod: () => {
1582
+ },
1583
+ showMoreShippingMethod: false,
1584
+ setShowMoreShippingMethod: () => {
1585
+ },
1586
+ variant: {},
1587
+ product: {},
1588
+ shippingMethodsContext: {
1589
+ freeShippingMethods: [],
1590
+ paymentShippingMethods: [],
1591
+ nddOverweight: false,
1592
+ tddOverweight: false,
1593
+ nddCoupon: void 0,
1594
+ tddCoupon: void 0,
1595
+ isLoadingCoupon: false
1596
+ },
1597
+ selectedPlusMemberVariant: void 0,
1598
+ showPlusMemberBenefit: false,
1599
+ setShowPlusMemberBenefit: () => {
1600
+ },
1601
+ profile: void 0
1602
+ });
1603
+ var PlusMemberContext = react.createContext(createInitialValue());
1604
+ function usePlusMemberContext() {
1605
+ return react.useContext(PlusMemberContext);
1852
1606
  }
1853
1607
  function useProductsByHandles(options = {}) {
1854
1608
  const { client, locale } = useShopify();
@@ -1874,1185 +1628,1298 @@ function useProductsByHandles(options = {}) {
1874
1628
  }
1875
1629
  );
1876
1630
  }
1877
- function getFirstAvailableVariant(product) {
1878
- const availableVariant = product.variants.find((v) => v.availableForSale);
1879
- return availableVariant || product.variants[0];
1880
- }
1881
- function getVariantFromSelectedOptions(product, selectedOptions) {
1882
- return product.variants.find((variant) => {
1883
- return variant.selectedOptions.every((option) => {
1884
- return selectedOptions[option.name] === option.value;
1885
- });
1886
- });
1887
- }
1888
- function useVariant({
1889
- product,
1890
- selectedOptions
1891
- }) {
1892
- const [variant, setVariant] = react.useState(
1893
- product ? getFirstAvailableVariant(product) : void 0
1894
- );
1895
- react.useEffect(() => {
1896
- if (!product) {
1897
- setVariant(void 0);
1898
- return;
1899
- }
1900
- const newVariant = getVariantFromSelectedOptions(product, selectedOptions);
1901
- if (newVariant && newVariant.id !== variant?.id) {
1902
- setVariant(newVariant);
1903
- } else if (!newVariant) {
1904
- setVariant(getFirstAvailableVariant(product));
1905
- }
1906
- }, [selectedOptions, product, variant?.id]);
1907
- return variant;
1908
- }
1909
- var FAKE_PRICE = 999999999e-2;
1910
- function formatPrice({
1911
- amount,
1912
- currencyCode,
1913
- locale,
1914
- maximumFractionDigits,
1915
- minimumFractionDigits,
1916
- removeTrailingZeros
1631
+
1632
+ // src/hooks/member/plus/use-plus-member-variants.ts
1633
+ function usePlusMemberVariants({
1634
+ memberSetting
1917
1635
  }) {
1918
- const formatter = new Intl.NumberFormat(locale, {
1919
- style: "currency",
1920
- currency: currencyCode,
1921
- maximumFractionDigits: maximumFractionDigits ?? 2,
1922
- minimumFractionDigits: minimumFractionDigits ?? 2
1636
+ const plusMonthly = memberSetting?.plus_monthly_product;
1637
+ const plusAnnual = memberSetting?.plus_annual_product;
1638
+ const plusMemberHandles = react.useMemo(() => {
1639
+ return [plusMonthly?.handle, plusAnnual?.handle].filter(Boolean);
1640
+ }, [plusMonthly?.handle, plusAnnual?.handle]);
1641
+ const { data: plusMemberProducts = [] } = useProductsByHandles({
1642
+ handles: plusMemberHandles
1923
1643
  });
1924
- let formatted = formatter.format(amount);
1925
- if (removeTrailingZeros) {
1926
- formatted = formatted.replace(/\.00$/, "");
1927
- }
1928
- return formatted;
1929
- }
1930
- function formatVariantPrice({
1931
- amount,
1932
- baseAmount,
1933
- currencyCode,
1934
- locale,
1935
- maximumFractionDigits,
1936
- minimumFractionDigits,
1937
- removeTrailingZeros
1938
- }) {
1644
+ const monthlyProduct = react.useMemo(() => {
1645
+ return plusMemberProducts?.find((item) => item?.handle === plusMonthly?.handle);
1646
+ }, [plusMemberProducts, plusMonthly]);
1647
+ const annualProduct = react.useMemo(() => {
1648
+ return plusMemberProducts?.find((item) => item?.handle === plusAnnual?.handle);
1649
+ }, [plusMemberProducts, plusAnnual]);
1650
+ const monthlyVariant = react.useMemo(() => {
1651
+ return monthlyProduct?.variants?.find((item) => item.sku === plusMonthly?.sku);
1652
+ }, [monthlyProduct, plusMonthly]);
1653
+ const annualVariant = react.useMemo(() => {
1654
+ return annualProduct?.variants?.find((item) => item.sku === plusAnnual?.sku);
1655
+ }, [annualProduct, plusAnnual]);
1939
1656
  return {
1940
- price: formatPrice({
1941
- amount,
1942
- currencyCode,
1943
- locale,
1944
- maximumFractionDigits,
1945
- minimumFractionDigits,
1946
- removeTrailingZeros
1947
- }),
1948
- basePrice: formatPrice({
1949
- amount: baseAmount,
1950
- currencyCode,
1951
- locale,
1952
- maximumFractionDigits,
1953
- minimumFractionDigits,
1954
- removeTrailingZeros
1955
- })
1657
+ monthlyVariant: monthlyVariant ? {
1658
+ ...monthlyVariant,
1659
+ product: monthlyProduct
1660
+ } : void 0,
1661
+ annualVariant: annualVariant ? {
1662
+ ...annualVariant,
1663
+ product: annualProduct
1664
+ } : void 0
1956
1665
  };
1957
1666
  }
1958
- function usePrice({
1959
- amount,
1960
- baseAmount,
1961
- currencyCode,
1962
- soldOutDescription = "",
1963
- maximumFractionDigits,
1964
- minimumFractionDigits,
1965
- removeTrailingZeros
1966
- }) {
1967
- const { locale } = useShopify();
1968
- const value = react.useMemo(() => {
1969
- if (typeof amount !== "number" || !currencyCode) {
1970
- return "";
1971
- }
1972
- if (soldOutDescription && amount >= FAKE_PRICE) {
1973
- return soldOutDescription;
1667
+ var useAvailableDeliveryCoupon = ({
1668
+ profile
1669
+ }) => {
1670
+ const { data: availableDeliveryCoupon, isLoading } = useSWR__default.default(
1671
+ profile?.email ? ["/api/multipass/subsrv/v1/prime/delivery_coupons/current/available", profile?.email] : void 0,
1672
+ async ([apiPath]) => {
1673
+ return fetch(apiPath).then((res) => res.json());
1974
1674
  }
1975
- return baseAmount ? formatVariantPrice({
1976
- amount,
1977
- baseAmount,
1978
- currencyCode,
1979
- locale,
1980
- maximumFractionDigits,
1981
- minimumFractionDigits,
1982
- removeTrailingZeros
1983
- }) : formatPrice({
1984
- amount,
1985
- currencyCode,
1986
- locale,
1987
- maximumFractionDigits,
1988
- minimumFractionDigits,
1989
- removeTrailingZeros
1675
+ );
1676
+ console.log("availableDeliveryCoupon", availableDeliveryCoupon);
1677
+ const { ndd_coupon: nddCoupon, tdd_coupon: tddCoupon } = availableDeliveryCoupon?.data?.data || {};
1678
+ return {
1679
+ nddCoupon,
1680
+ tddCoupon,
1681
+ isLoading
1682
+ };
1683
+ };
1684
+
1685
+ // src/hooks/member/plus/use-shipping-methods.ts
1686
+ function useShippingMethods(options) {
1687
+ const { variant, plusMemberMetafields, selectedPlusMemberMode, profile } = options;
1688
+ const isPlus = profile?.isPlus || false;
1689
+ const { nddCoupon, tddCoupon, isLoading } = useAvailableDeliveryCoupon({ profile });
1690
+ const { plus_shipping, shippingMethod } = plusMemberMetafields || {};
1691
+ const nddOverweight = react.useMemo(() => {
1692
+ return (variant?.weight || 0) > (shippingMethod?.overWeight_ndd || Infinity);
1693
+ }, [shippingMethod?.overWeight_ndd, variant?.weight]);
1694
+ const tddOverweight = react.useMemo(() => {
1695
+ return (variant?.weight || 0) > (shippingMethod?.overWeight_tdd || Infinity);
1696
+ }, [shippingMethod?.overWeight_tdd, variant?.weight]);
1697
+ const paymentShippingMethods = react.useMemo(() => {
1698
+ const weight = variant?.weight || 0;
1699
+ const methods = plus_shipping?.shipping_methods?.filter(({ weight_low, weight_high, __mode, __plus }) => {
1700
+ const fitWeight = (!weight_low || weight >= weight_low) && (!weight_high || weight <= weight_high);
1701
+ return __mode !== "free" /* FREE */ && !__plus && fitWeight;
1702
+ }) || [];
1703
+ return methods.map((method) => {
1704
+ let disabled = false;
1705
+ const selectedFreeMember = selectedPlusMemberMode === "free";
1706
+ if (method.__mode === "ndd" /* NDD */) {
1707
+ disabled = selectedFreeMember || nddOverweight;
1708
+ } else if (method.__mode === "tdd" /* TDD */) {
1709
+ disabled = selectedFreeMember || tddOverweight;
1710
+ }
1711
+ return {
1712
+ ...method,
1713
+ id: method.__mode + method.__code,
1714
+ useCoupon: false,
1715
+ subtitle: plus_shipping?.directly || "",
1716
+ disabled
1717
+ };
1990
1718
  });
1991
1719
  }, [
1992
- amount,
1993
- baseAmount,
1994
- currencyCode,
1995
- locale,
1996
- maximumFractionDigits,
1997
- minimumFractionDigits,
1998
- soldOutDescription,
1999
- removeTrailingZeros
1720
+ nddOverweight,
1721
+ plus_shipping?.directly,
1722
+ plus_shipping?.shipping_methods,
1723
+ selectedPlusMemberMode,
1724
+ tddOverweight,
1725
+ variant?.weight
2000
1726
  ]);
2001
- const result = react.useMemo(() => {
2002
- const free = Boolean(amount && amount <= 0);
2003
- return typeof value === "string" ? { price: value, basePrice: value, free } : { ...value, free };
2004
- }, [value, amount]);
2005
- return result;
2006
- }
2007
- function optionsConstructor(selectedOptions) {
2008
- return selectedOptions.reduce((acc, option) => {
2009
- acc[option.name] = option.value;
2010
- return acc;
2011
- }, {});
2012
- }
2013
- function decodeShopifyId(gid) {
2014
- try {
2015
- const base64 = gid.split("/").pop() || "";
2016
- return atob(base64);
2017
- } catch {
2018
- return gid;
2019
- }
2020
- }
2021
- function useSelectedOptions(product, sku) {
2022
- const [options, setOptions] = react.useState({});
2023
- react.useEffect(() => {
2024
- if (!product || !product.variants.length) {
2025
- setOptions({});
2026
- return;
2027
- }
2028
- let variant = product.variants[0];
2029
- if (typeof window !== "undefined") {
2030
- const searchParams = new URLSearchParams(window.location.search);
2031
- const variantIdParam = searchParams.get("variant");
2032
- if (variantIdParam) {
2033
- const foundVariant = product.variants.find((v) => {
2034
- if (sku) return v.sku === sku;
2035
- return v.id === variantIdParam || v.id.includes(variantIdParam) || decodeShopifyId(v.id) === variantIdParam;
2036
- });
2037
- if (foundVariant) {
2038
- variant = foundVariant;
2039
- }
1727
+ const nddPrice = react.useMemo(() => {
1728
+ const weight = variant?.weight || 0;
1729
+ const nddMethod = paymentShippingMethods.find(({ __mode, weight_high, weight_low }) => {
1730
+ const fitWeight = (!weight_low || weight >= weight_low) && (!weight_high || weight <= weight_high);
1731
+ return __mode === "ndd" && fitWeight;
1732
+ });
1733
+ return nddMethod?.price || 0;
1734
+ }, [variant?.weight, paymentShippingMethods]);
1735
+ const tddPrice = react.useMemo(() => {
1736
+ const weight = variant?.weight || 0;
1737
+ const tddMethod = paymentShippingMethods.find(({ __mode, weight_high, weight_low }) => {
1738
+ const fitWeight = (!weight_low || weight >= weight_low) && (!weight_high || weight <= weight_high);
1739
+ return __mode === "tdd" && fitWeight;
1740
+ });
1741
+ return tddMethod?.price || 0;
1742
+ }, [variant?.weight, paymentShippingMethods]);
1743
+ const freeShippingMethods = react.useMemo(() => {
1744
+ const weight = variant?.weight || 0;
1745
+ let methods = plus_shipping?.shipping_methods?.filter(({ __mode, __plus, weight_low, weight_high }) => {
1746
+ if (__mode === "free" /* FREE */) {
1747
+ return true;
2040
1748
  }
1749
+ if (isPlus) {
1750
+ const hasCoupon = isPlus && __mode === "ndd" /* NDD */ && nddCoupon || isPlus && __mode === "tdd" /* TDD */ && (tddCoupon || nddCoupon);
1751
+ const fitWeight = (!weight_low || weight >= weight_low) && (!weight_high || weight <= weight_high);
1752
+ return hasCoupon && fitWeight && !__plus;
1753
+ } else {
1754
+ return __plus;
1755
+ }
1756
+ }) || [];
1757
+ if (isPlus) {
1758
+ methods = methods.sort((a, b) => {
1759
+ if (b.__mode === "free" /* FREE */) return -1;
1760
+ return 0;
1761
+ });
2041
1762
  }
2042
- if (variant) {
2043
- const newOptions = optionsConstructor(variant.selectedOptions);
2044
- setOptions(newOptions);
2045
- }
2046
- }, [product, sku]);
2047
- return [options, setOptions];
2048
- }
2049
- function decodeShopifyId2(gid) {
2050
- try {
2051
- const parts = gid.split("/");
2052
- return parts[parts.length - 1] || gid;
2053
- } catch {
2054
- return gid;
2055
- }
2056
- }
2057
- function useProductUrl(otherQuery) {
2058
- const { routerAdapter } = useShopify();
2059
- return react.useCallback(
2060
- ({ product, variant }) => {
2061
- if (!product) return "";
2062
- const queryParams = new URLSearchParams();
2063
- if (variant?.id) {
2064
- const variantId = decodeShopifyId2(variant.id);
2065
- if (variantId) {
2066
- queryParams.set("variant", variantId);
1763
+ return methods.map((method) => {
1764
+ let price = 0;
1765
+ let coupon;
1766
+ let disabled;
1767
+ if (method.__mode !== "free" /* FREE */) {
1768
+ switch (method.__mode) {
1769
+ case "tdd":
1770
+ price = tddPrice;
1771
+ coupon = tddCoupon || nddCoupon;
1772
+ break;
1773
+ case "ndd":
1774
+ price = nddPrice;
1775
+ coupon = nddCoupon;
1776
+ break;
1777
+ }
1778
+ disabled = selectedPlusMemberMode === "free";
1779
+ if (method.__mode === "ndd" /* NDD */) {
1780
+ disabled = disabled || nddOverweight;
1781
+ } else if (method.__mode === "tdd" /* TDD */) {
1782
+ disabled = disabled || tddOverweight;
2067
1783
  }
2068
1784
  }
2069
- if (otherQuery) {
2070
- Object.entries(otherQuery).forEach(([key, value]) => {
2071
- queryParams.set(key, value);
2072
- });
2073
- }
2074
- const queryString = queryParams.toString();
2075
- const path = `/products/${product.handle}${queryString ? `?${queryString}` : ""}`;
2076
- if (routerAdapter?.getLocalizedPath) {
2077
- return routerAdapter.getLocalizedPath(path);
2078
- }
2079
- return path;
2080
- },
2081
- [routerAdapter, otherQuery]
2082
- );
2083
- }
2084
- function decodeShopifyId3(gid) {
2085
- try {
2086
- const parts = gid.split("/");
2087
- return parts[parts.length - 1] || gid;
2088
- } catch {
2089
- return gid;
2090
- }
2091
- }
2092
- function useUpdateVariantQuery(variant) {
2093
- react.useEffect(() => {
2094
- if (!variant || typeof window === "undefined") {
2095
- return;
2096
- }
2097
- const searchParams = new URLSearchParams(window.location.search);
2098
- const currentVariantId = searchParams.get("variant");
2099
- const newVariantId = decodeShopifyId3(variant.id);
2100
- if (newVariantId && currentVariantId !== newVariantId) {
2101
- searchParams.set("variant", newVariantId);
2102
- const newUrl = `${window.location.pathname}?${searchParams.toString()}${window.location.hash}`;
2103
- window.history.replaceState({}, "", newUrl);
2104
- }
2105
- }, [variant]);
1785
+ return {
1786
+ ...method,
1787
+ id: method.__mode + method.__code,
1788
+ useCoupon: true,
1789
+ disabled,
1790
+ coupon,
1791
+ price
1792
+ };
1793
+ });
1794
+ }, [
1795
+ variant?.weight,
1796
+ plus_shipping?.shipping_methods,
1797
+ isPlus,
1798
+ nddCoupon,
1799
+ tddCoupon,
1800
+ selectedPlusMemberMode,
1801
+ tddPrice,
1802
+ nddPrice,
1803
+ nddOverweight,
1804
+ tddOverweight
1805
+ ]);
1806
+ return {
1807
+ freeShippingMethods,
1808
+ paymentShippingMethods,
1809
+ nddOverweight,
1810
+ tddOverweight,
1811
+ nddCoupon,
1812
+ tddCoupon,
1813
+ isLoadingCoupon: isLoading
1814
+ };
2106
1815
  }
2107
- function getVariantMediaList({
2108
- product,
2109
- variant
2110
- }) {
2111
- if (variant.image?.url) {
2112
- const variantMediaId = variant.image.url;
2113
- const variantMedia = product.media.filter((media) => {
2114
- if (media.mediaContentType === "IMAGE" && media.previewImage) {
2115
- return media.previewImage?.url === variantMediaId;
1816
+ var useReplaceCartPlusMember = () => {
1817
+ const { plusMemberMetafields, selectedPlusMemberMode } = usePlusMemberContext();
1818
+ const { trigger: removeCartLines2 } = useRemoveCartLines();
1819
+ const { cart } = useCartContext();
1820
+ const plusMonthly = plusMemberMetafields?.plus_monthly_product;
1821
+ const plusAnnual = plusMemberMetafields?.plus_annual_product;
1822
+ const handler = react.useCallback(async () => {
1823
+ const plusMonthlyInCart = cart?.lineItems.find(
1824
+ (item) => item.variant?.sku === plusMonthly?.sku
1825
+ );
1826
+ const plusAnnualInCart = cart?.lineItems.find(
1827
+ (item) => item.variant?.sku === plusAnnual?.sku
1828
+ );
1829
+ if (selectedPlusMemberMode === "annual" /* ANNUAL */ && plusMonthlyInCart) {
1830
+ await removeCartLines2({
1831
+ lineIds: [plusMonthlyInCart.id]
1832
+ });
1833
+ } else if (selectedPlusMemberMode === "monthly" /* MONTHLY */ && plusAnnualInCart) {
1834
+ await removeCartLines2({
1835
+ lineIds: [plusAnnualInCart.id]
1836
+ });
1837
+ }
1838
+ }, [
1839
+ cart?.lineItems,
1840
+ selectedPlusMemberMode,
1841
+ plusMonthly?.sku,
1842
+ plusAnnual?.sku,
1843
+ removeCartLines2
1844
+ ]);
1845
+ return handler;
1846
+ };
1847
+ var usePlusMemberCheckoutCustomAttributes = ({
1848
+ disableShipping = false,
1849
+ isPresaleContains = false
1850
+ }) => {
1851
+ const { profile, selectedShippingMethod, selectedPlusMemberMode } = usePlusMemberContext();
1852
+ return react.useMemo(() => {
1853
+ const checkoutCustomAttributes = [
1854
+ {
1855
+ key: "_last_url",
1856
+ value: typeof window !== "undefined" ? window.location.origin + window.location.pathname : ""
2116
1857
  }
2117
- return false;
1858
+ ];
1859
+ checkoutCustomAttributes.push({
1860
+ key: "_checkout_delivery_custom",
1861
+ value: JSON.stringify({
1862
+ allow_nextday_delivery: true,
1863
+ allow_thirdday_delivery: true,
1864
+ selected_delivery_option: {
1865
+ code: selectedShippingMethod?.__code,
1866
+ mode: selectedShippingMethod?.__mode
1867
+ },
1868
+ is_presale: isPresaleContains,
1869
+ discount_code: selectedShippingMethod?.coupon ? [selectedShippingMethod.coupon] : [],
1870
+ plus_type: profile?.isPlus ? "free" /* FREE */ : selectedPlusMemberMode,
1871
+ is_prime: profile?.isPlus
1872
+ })
2118
1873
  });
2119
- if (variantMedia.length > 0) {
2120
- const otherMedia = product.media.filter((media) => {
2121
- if (media.mediaContentType === "IMAGE" && media.previewImage) {
2122
- return media.previewImage.url !== variantMediaId;
2123
- }
2124
- return true;
1874
+ if (disableShipping) {
1875
+ checkoutCustomAttributes.push({
1876
+ key: "_hide_shipping",
1877
+ value: "true"
2125
1878
  });
2126
- return [...variantMedia, ...otherMedia];
2127
1879
  }
2128
- }
2129
- return product.media;
1880
+ return checkoutCustomAttributes;
1881
+ }, [profile, selectedShippingMethod, selectedPlusMemberMode, isPresaleContains]);
1882
+ };
1883
+ function useRemoveCartLines(options) {
1884
+ const { client, locale, cartCookieAdapter } = useShopify();
1885
+ const { mutateCart, metafieldIdentifiers } = useCartContext();
1886
+ const removeLines = react.useCallback(
1887
+ async (_key, { arg }) => {
1888
+ const { autoRemoveInvalidCodes = true, onCodesRemoved, cartId, lineIds } = arg;
1889
+ let updatedCart = await shopifySdk.removeCartLines(client, {
1890
+ cartId,
1891
+ lineIds,
1892
+ metafieldIdentifiers,
1893
+ cookieAdapter: cartCookieAdapter
1894
+ });
1895
+ if (updatedCart && autoRemoveInvalidCodes) {
1896
+ const unApplicableCodes = updatedCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
1897
+ if (unApplicableCodes.length > 0) {
1898
+ if (onCodesRemoved) {
1899
+ const handledCart = await onCodesRemoved(updatedCart, unApplicableCodes);
1900
+ if (handledCart) {
1901
+ updatedCart = handledCart;
1902
+ }
1903
+ } else {
1904
+ updatedCart = await shopifySdk.updateCartCodes(client, {
1905
+ cartId: updatedCart.id,
1906
+ discountCodes: updatedCart.discountCodes.filter((item) => item.applicable).map((item) => item.code),
1907
+ metafieldIdentifiers,
1908
+ cookieAdapter: cartCookieAdapter
1909
+ }) || updatedCart;
1910
+ }
1911
+ }
1912
+ }
1913
+ if (updatedCart) {
1914
+ mutateCart(updatedCart);
1915
+ }
1916
+ return updatedCart;
1917
+ },
1918
+ [client, locale, cartCookieAdapter, mutateCart, metafieldIdentifiers]
1919
+ );
1920
+ return useSWRMutation__default.default("remove-cart-lines", removeLines, options);
2130
1921
  }
2131
- function useVariantMedia({
2132
- product,
2133
- variant
1922
+
1923
+ // src/hooks/member/plus/use-auto-remove-plus-member-in-cart.ts
1924
+ function useAutoRemovePlusMemberInCart({
1925
+ cart,
1926
+ profile,
1927
+ memberSetting
2134
1928
  }) {
2135
- const [imageList, setImageList] = react.useState([]);
2136
- const [sceneList, setSceneList] = react.useState([]);
2137
- const [videoList, setVideoList] = react.useState([]);
1929
+ const { plus_monthly_product, plus_annual_product } = memberSetting || {};
1930
+ const { trigger: removeCartLines2 } = useRemoveCartLines();
2138
1931
  react.useEffect(() => {
2139
- if (!product || !variant) {
2140
- setImageList([]);
2141
- setSceneList([]);
2142
- setVideoList([]);
2143
- return;
1932
+ if (!cart || !plus_monthly_product || !plus_annual_product) return;
1933
+ const removePlusProduct = async (productType) => {
1934
+ if (!productType) return;
1935
+ const product = cart.lineItems?.find(
1936
+ (item) => item.product?.handle === productType?.handle && item.variant?.sku === productType?.sku
1937
+ );
1938
+ if (product) {
1939
+ await removeCartLines2({
1940
+ lineIds: [product.id]
1941
+ });
1942
+ }
1943
+ };
1944
+ if (profile?.isMonthlyPlus) {
1945
+ removePlusProduct(plus_monthly_product);
2144
1946
  }
2145
- const mediaList = getVariantMediaList({ product, variant });
2146
- const images = mediaList.filter((media) => media.mediaContentType === "IMAGE");
2147
- const videos = mediaList.filter(
2148
- (media) => media.mediaContentType === "VIDEO" || media.mediaContentType === "EXTERNAL_VIDEO"
2149
- );
2150
- setImageList(images.length > 0 && images[0] ? [images[0]] : []);
2151
- setSceneList(images.length > 1 ? images.slice(1) : []);
2152
- setVideoList(videos);
2153
- }, [product, variant]);
2154
- return {
2155
- productList: imageList,
2156
- sceneList,
2157
- videoList
2158
- };
1947
+ if (profile?.isAnnualPlus) {
1948
+ removePlusProduct(plus_annual_product);
1949
+ }
1950
+ }, [cart, plus_annual_product, plus_monthly_product, profile, removeCartLines2]);
2159
1951
  }
2160
- function useCollection(options = {}) {
2161
- const { client, locale } = useShopify();
2162
- const { handle, metafieldIdentifiers, ...swrOptions } = options;
2163
- return useSWR__default.default(
2164
- handle ? ["collection", locale, handle, metafieldIdentifiers] : null,
2165
- () => shopifySdk.getCollection(client, {
2166
- handle,
2167
- locale,
2168
- metafieldIdentifiers
2169
- }),
2170
- swrOptions
1952
+ function hasPlusMemberInCart({
1953
+ memberSetting,
1954
+ cart
1955
+ }) {
1956
+ const { plus_monthly_product, plus_annual_product } = memberSetting || {};
1957
+ if (!cart?.lineItems) {
1958
+ return {
1959
+ hasPlusMember: false,
1960
+ hasMonthlyPlus: false,
1961
+ hasAnnualPlus: false
1962
+ };
1963
+ }
1964
+ const monthlyPlusItem = cart.lineItems.find(
1965
+ (item) => item.product?.handle === plus_monthly_product?.handle && item.variant?.sku === plus_monthly_product?.sku
2171
1966
  );
2172
- }
2173
- function useAllCollections(options = {}) {
2174
- const { client, locale } = useShopify();
2175
- const { first, query, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
2176
- return useSWR__default.default(
2177
- ["all-collections", locale, first, query, sortKey, reverse, metafieldIdentifiers],
2178
- () => shopifySdk.getAllCollections(client, {
2179
- locale,
2180
- first,
2181
- query,
2182
- sortKey,
2183
- reverse,
2184
- metafieldIdentifiers
2185
- }),
2186
- swrOptions
1967
+ const annualPlusItem = cart.lineItems.find(
1968
+ (item) => item.product?.handle === plus_annual_product?.handle && item.variant?.sku === plus_annual_product?.sku
2187
1969
  );
1970
+ const hasMonthlyPlus = !!monthlyPlusItem;
1971
+ const hasAnnualPlus = !!annualPlusItem;
1972
+ const hasPlusMember = hasMonthlyPlus || hasAnnualPlus;
1973
+ return {
1974
+ hasPlusMember,
1975
+ hasMonthlyPlus,
1976
+ hasAnnualPlus,
1977
+ monthlyPlusItem,
1978
+ annualPlusItem
1979
+ };
2188
1980
  }
2189
- function useCollections(options = {}) {
2190
- const { client, locale } = useShopify();
2191
- const { first, after, query, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
2192
- return useSWR__default.default(
2193
- ["collections", locale, first, after, query, sortKey, reverse, metafieldIdentifiers],
2194
- () => shopifySdk.getCollections(client, {
2195
- locale,
2196
- first,
2197
- after,
2198
- query,
2199
- sortKey,
2200
- reverse,
2201
- metafieldIdentifiers
1981
+ function useHasPlusMemberInCart({
1982
+ memberSetting,
1983
+ cart
1984
+ }) {
1985
+ return react.useMemo(
1986
+ () => hasPlusMemberInCart({
1987
+ memberSetting,
1988
+ cart
2202
1989
  }),
2203
- swrOptions
1990
+ [memberSetting, cart]
2204
1991
  );
2205
1992
  }
2206
- function useBlog(options = {}) {
2207
- const { client, locale } = useShopify();
2208
- const { handle, metafieldIdentifiers, ...swrOptions } = options;
2209
- return useSWR__default.default(
2210
- handle ? ["blog", locale, handle, metafieldIdentifiers] : null,
2211
- () => shopifySdk.getBlog(client, { handle, locale, metafieldIdentifiers }),
2212
- swrOptions
2213
- );
2214
- }
2215
- function useAllBlogs(options = {}) {
2216
- const { client, locale } = useShopify();
2217
- const { first, query, metafieldIdentifiers, ...swrOptions } = options;
2218
- return useSWR__default.default(
2219
- ["all-blogs", locale, first, query, metafieldIdentifiers],
2220
- () => shopifySdk.getAllBlogs(client, {
2221
- locale,
2222
- first,
2223
- query,
2224
- metafieldIdentifiers
2225
- }),
2226
- swrOptions
2227
- );
2228
- }
2229
- function useArticle(options = {}) {
2230
- const { client, locale } = useShopify();
2231
- const { blogHandle, articleHandle, metafieldIdentifiers, ...swrOptions } = options;
2232
- return useSWR__default.default(
2233
- blogHandle && articleHandle ? ["article", locale, blogHandle, articleHandle, metafieldIdentifiers] : null,
2234
- () => shopifySdk.getArticle(client, {
2235
- blogHandle,
2236
- articleHandle,
2237
- locale,
2238
- metafieldIdentifiers
2239
- }),
2240
- swrOptions
2241
- );
1993
+ function usePlusMemberNeedAddToCart({
1994
+ cart,
1995
+ profile
1996
+ }) {
1997
+ const { selectedPlusMemberMode, selectedPlusMemberVariant, plusMemberMetafields } = usePlusMemberContext();
1998
+ const { hasMonthlyPlus, hasAnnualPlus } = useHasPlusMemberInCart({
1999
+ memberSetting: plusMemberMetafields,
2000
+ cart
2001
+ });
2002
+ const plusMemberVariant = react.useMemo(() => {
2003
+ if (!selectedPlusMemberVariant || selectedPlusMemberMode === "free" /* FREE */) {
2004
+ return void 0;
2005
+ }
2006
+ if (selectedPlusMemberMode === "monthly" /* MONTHLY */ && hasMonthlyPlus) {
2007
+ return void 0;
2008
+ }
2009
+ if (selectedPlusMemberMode === "annual" /* ANNUAL */ && hasAnnualPlus) {
2010
+ return void 0;
2011
+ }
2012
+ if (profile?.isMonthlyPlus && selectedPlusMemberMode === "monthly" /* MONTHLY */) {
2013
+ return void 0;
2014
+ }
2015
+ if (profile?.isAnnualPlus && selectedPlusMemberMode === "annual" /* ANNUAL */) {
2016
+ return void 0;
2017
+ }
2018
+ return selectedPlusMemberVariant;
2019
+ }, [selectedPlusMemberMode, selectedPlusMemberVariant, hasMonthlyPlus, hasAnnualPlus]);
2020
+ return plusMemberVariant;
2242
2021
  }
2243
- function useArticles(options = {}) {
2244
- const { client, locale } = useShopify();
2245
- const { first, query, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
2246
- return useSWR__default.default(
2247
- ["articles", locale, first, query, sortKey, reverse, metafieldIdentifiers],
2248
- () => shopifySdk.getArticles(client, {
2249
- locale,
2250
- first,
2251
- query,
2252
- sortKey,
2253
- reverse,
2254
- metafieldIdentifiers
2255
- }),
2256
- swrOptions
2022
+ var PlusMemberProvider = ({
2023
+ variant,
2024
+ product,
2025
+ memberSetting,
2026
+ initialSelectedPlusMemberMode = "free",
2027
+ profile,
2028
+ children
2029
+ }) => {
2030
+ const [selectedPlusMemberMode, setSelectedPlusMemberMode] = react.useState(
2031
+ initialSelectedPlusMemberMode
2257
2032
  );
2258
- }
2259
- function useArticlesInBlog(options = {}) {
2260
- const { client, locale } = useShopify();
2261
- const { blogHandle, first, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
2262
- return useSWR__default.default(
2263
- blogHandle ? ["articles-in-blog", locale, blogHandle, first, sortKey, reverse, metafieldIdentifiers] : null,
2264
- () => shopifySdk.getArticlesInBlog(client, {
2265
- blogHandle,
2266
- locale,
2267
- first,
2268
- sortKey,
2269
- reverse,
2270
- metafieldIdentifiers
2271
- }),
2272
- swrOptions
2033
+ const [selectedShippingMethod, setSelectedShippingMethod] = react.useState();
2034
+ const [showMoreShippingMethod, setShowMoreShippingMethod] = react.useState(false);
2035
+ const [showPlusMemberBenefit, setShowPlusMemberBenefit] = react.useState(false);
2036
+ const shippingMethodsContext = useShippingMethods({
2037
+ variant,
2038
+ plusMemberMetafields: memberSetting,
2039
+ selectedPlusMemberMode,
2040
+ profile
2041
+ });
2042
+ const { monthlyVariant, annualVariant } = usePlusMemberVariants({
2043
+ memberSetting
2044
+ });
2045
+ const selectedPlusMemberVariant = react.useMemo(() => {
2046
+ if (selectedPlusMemberMode === "free" /* FREE */) {
2047
+ return void 0;
2048
+ }
2049
+ return selectedPlusMemberMode === "monthly" /* MONTHLY */ ? monthlyVariant : annualVariant;
2050
+ }, [monthlyVariant, annualVariant, selectedPlusMemberMode]);
2051
+ return /* @__PURE__ */ jsxRuntime.jsx(
2052
+ PlusMemberContext.Provider,
2053
+ {
2054
+ value: {
2055
+ variant,
2056
+ plusMemberMetafields: memberSetting,
2057
+ selectedPlusMemberMode,
2058
+ setSelectedPlusMemberMode,
2059
+ selectedShippingMethod,
2060
+ setSelectedShippingMethod,
2061
+ shippingMethodsContext,
2062
+ showMoreShippingMethod,
2063
+ setShowMoreShippingMethod,
2064
+ selectedPlusMemberVariant,
2065
+ product,
2066
+ showPlusMemberBenefit,
2067
+ setShowPlusMemberBenefit,
2068
+ profile
2069
+ },
2070
+ children
2071
+ }
2273
2072
  );
2274
- }
2275
- async function performSearch(client, locale, searchQuery, first = 20, types = ["PRODUCT", "ARTICLE", "PAGE"]) {
2276
- if (!searchQuery) {
2277
- return void 0;
2278
- }
2279
- const query = (
2280
- /* GraphQL */
2281
- `
2282
- query search($query: String!, $first: Int!, $types: [SearchType!])
2283
- @inContext(language: $language) {
2284
- search(query: $query, first: $first, types: $types, unavailableProducts: HIDE) {
2285
- totalCount
2286
- edges {
2287
- node {
2288
- ... on Article {
2289
- __typename
2290
- id
2291
- handle
2292
- title
2293
- excerpt
2294
- image {
2295
- url
2296
- altText
2297
- }
2298
- }
2299
- ... on Page {
2300
- __typename
2301
- id
2302
- handle
2303
- title
2304
- }
2305
- ... on Product {
2306
- __typename
2307
- id
2308
- handle
2309
- title
2310
- description
2311
- featuredImage {
2312
- url
2313
- altText
2073
+ };
2074
+
2075
+ // src/hooks/cart/use-add-to-cart.ts
2076
+ function useAddToCart({ withTrack = true } = {}, swrOptions) {
2077
+ const { client, config, locale, cartCookieAdapter, userAdapter, performanceAdapter } = useShopify();
2078
+ const { cart, addCustomAttributes, memberSetting, profile, customer } = useCartContext();
2079
+ const { trigger: applyCartCodes } = useApplyCartCodes();
2080
+ const { trigger: removeInvalidCodes } = useRemoveCartCodes();
2081
+ const { trigger: addCartLines2 } = useAddCartLines();
2082
+ const { trigger: createCart4 } = useCreateCart({
2083
+ updateCookie: true
2084
+ });
2085
+ const { hasPlusMember } = useHasPlusMemberInCart({
2086
+ memberSetting,
2087
+ cart
2088
+ });
2089
+ const { attributes: cartAttributes } = useCartAttributes({
2090
+ profile,
2091
+ customer,
2092
+ cart,
2093
+ memberType: hasPlusMember ? "2" : String(profile?.memberType ?? 0)
2094
+ });
2095
+ const addToCart = react.useCallback(
2096
+ async (_key, { arg }) => {
2097
+ const {
2098
+ lineItems,
2099
+ cartId: providedCartId,
2100
+ discountCodes,
2101
+ gtmParams = {},
2102
+ buyerIdentity,
2103
+ needCreateCart = false,
2104
+ onCodesInvalid,
2105
+ replaceExistingCodes,
2106
+ customAttributes
2107
+ } = arg;
2108
+ if (!lineItems || lineItems.length === 0) {
2109
+ return;
2110
+ }
2111
+ performanceAdapter?.addToCartStart();
2112
+ const linesWithFunctionAttributes = getLinesWithAttributes({ cart, lineItems });
2113
+ const lines = linesWithFunctionAttributes.map((item) => ({
2114
+ merchandiseId: item.variant?.id || "",
2115
+ quantity: item.quantity || 1,
2116
+ attributes: item.attributes,
2117
+ sellingPlanId: item.sellingPlanId
2118
+ })).filter((item) => item.merchandiseId && item.quantity);
2119
+ if (lines.length === 0) {
2120
+ return;
2121
+ }
2122
+ let cartId = needCreateCart ? void 0 : providedCartId || cart?.id;
2123
+ let resultCart = null;
2124
+ if (!cartId) {
2125
+ resultCart = await createCart4({
2126
+ lines,
2127
+ buyerIdentity,
2128
+ discountCodes,
2129
+ customAttributes: [...cartAttributes, ...customAttributes || []]
2130
+ // 初次加购时,就把所有 cart attributes 带上
2131
+ });
2132
+ } else {
2133
+ resultCart = await addCartLines2({
2134
+ cartId,
2135
+ lines
2136
+ });
2137
+ console.log("npm addCartLines resultCart", resultCart);
2138
+ if (resultCart && resultCart.discountCodes && resultCart.discountCodes.length > 0) {
2139
+ const unapplicableCodes = resultCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
2140
+ if (unapplicableCodes.length > 0) {
2141
+ if (onCodesInvalid) {
2142
+ const handledCart = await onCodesInvalid(resultCart, unapplicableCodes);
2143
+ if (handledCart) {
2144
+ resultCart = handledCart;
2314
2145
  }
2146
+ } else {
2147
+ await removeInvalidCodes({
2148
+ discountCodes: unapplicableCodes
2149
+ });
2315
2150
  }
2316
2151
  }
2317
2152
  }
2318
- pageInfo {
2319
- hasNextPage
2320
- endCursor
2153
+ if (resultCart && discountCodes && discountCodes.length > 0) {
2154
+ applyCartCodes({
2155
+ replaceExistingCodes,
2156
+ discountCodes
2157
+ });
2158
+ }
2159
+ if (customAttributes && customAttributes.length > 0) {
2160
+ addCustomAttributes(customAttributes);
2321
2161
  }
2322
2162
  }
2323
- }
2324
- `
2325
- );
2326
- const data = await client.query(query, {
2327
- query: searchQuery,
2328
- first,
2329
- types
2330
- });
2331
- if (!data || !data.search) {
2332
- return void 0;
2333
- }
2334
- const items = data.search.edges?.map((edge) => {
2335
- const node = edge.node;
2336
- const item = {
2337
- type: node.__typename.toUpperCase(),
2338
- id: node.id,
2339
- handle: node.handle,
2340
- title: node.title
2341
- };
2342
- if (node.__typename === "Product") {
2343
- item.description = node.description;
2344
- item.image = node.featuredImage ? {
2345
- url: node.featuredImage.url,
2346
- altText: node.featuredImage.altText
2347
- } : void 0;
2348
- } else if (node.__typename === "Article") {
2349
- item.description = node.excerpt;
2350
- item.image = node.image ? {
2351
- url: node.image.url,
2352
- altText: node.image.altText
2353
- } : void 0;
2354
- }
2355
- return item;
2356
- }) || [];
2357
- return {
2358
- items,
2359
- totalCount: data.search.totalCount || 0,
2360
- pageInfo: data.search.pageInfo
2361
- };
2163
+ if (withTrack) {
2164
+ trackAddToCartGA({
2165
+ lineItems,
2166
+ gtmParams: { ...gtmParams, brand: config.getBrand() }
2167
+ });
2168
+ trackAddToCartFBQ({ lineItems });
2169
+ }
2170
+ performanceAdapter?.addToCartEnd();
2171
+ return resultCart;
2172
+ },
2173
+ [
2174
+ client,
2175
+ locale,
2176
+ cartCookieAdapter,
2177
+ userAdapter,
2178
+ cart,
2179
+ withTrack,
2180
+ performanceAdapter,
2181
+ createCart4,
2182
+ addCartLines2,
2183
+ applyCartCodes,
2184
+ removeInvalidCodes,
2185
+ addCustomAttributes,
2186
+ config
2187
+ ]
2188
+ );
2189
+ return useSWRMutation__default.default("add-to-cart", addToCart, swrOptions);
2362
2190
  }
2363
- function useSearch(options = {}) {
2364
- const { client, locale } = useShopify();
2365
- const { query, first = 20, types = ["PRODUCT", "ARTICLE", "PAGE"], ...swrOptions } = options;
2366
- return useSWR__default.default(
2367
- query ? ["search", locale, query, first, types] : null,
2368
- () => performSearch(client, locale, query, first, types),
2369
- swrOptions
2191
+ function useUpdateCartLines(options) {
2192
+ const { client, locale, cartCookieAdapter } = useShopify();
2193
+ const { mutateCart, metafieldIdentifiers } = useCartContext();
2194
+ const updateLines = react.useCallback(
2195
+ async (_key, { arg }) => {
2196
+ const updatedCart = await shopifySdk.updateCartLines(client, {
2197
+ ...arg,
2198
+ metafieldIdentifiers,
2199
+ cookieAdapter: cartCookieAdapter
2200
+ });
2201
+ if (updatedCart) {
2202
+ mutateCart(updatedCart);
2203
+ }
2204
+ console.log("use-update-cart-lines updatedCart", metafieldIdentifiers, updatedCart);
2205
+ return updatedCart;
2206
+ },
2207
+ [client, locale, cartCookieAdapter, mutateCart, metafieldIdentifiers]
2370
2208
  );
2209
+ return useSWRMutation__default.default("update-cart-lines", updateLines, options);
2371
2210
  }
2372
- async function getSiteInfo(client, locale, metafieldIdentifiers) {
2373
- const hasMetafields = metafieldIdentifiers && metafieldIdentifiers.length > 0;
2374
- const query = (
2375
- /* GraphQL */
2376
- `
2377
- query getSiteInfo(
2378
- ${hasMetafields ? "$shopMetafieldIdentifiers: [HasMetafieldsIdentifier!]!" : ""}
2379
- ) @inContext(language: $language) {
2380
- shop {
2381
- name
2382
- description
2383
- primaryDomain {
2384
- url
2385
- host
2211
+ function useUpdateCartAttributes({
2212
+ mutate,
2213
+ metafieldIdentifiers,
2214
+ disabled = false,
2215
+ swrOptions
2216
+ }) {
2217
+ const { client, locale, cartCookieAdapter } = useShopify();
2218
+ const updateAttributes = react.useCallback(
2219
+ async (_key, { arg }) => {
2220
+ if (disabled) {
2221
+ return void 0;
2222
+ }
2223
+ const updatedCart = await shopifySdk.updateCartAttributes(client, {
2224
+ ...arg,
2225
+ metafieldIdentifiers,
2226
+ cookieAdapter: cartCookieAdapter
2227
+ });
2228
+ if (updatedCart) {
2229
+ mutate(updatedCart);
2230
+ }
2231
+ return updatedCart;
2232
+ },
2233
+ [client, locale, cartCookieAdapter, mutate, metafieldIdentifiers, disabled]
2234
+ );
2235
+ return useSWRMutation__default.default("update-cart-attributes", updateAttributes, swrOptions);
2236
+ }
2237
+ function useBuyNow({ withTrack = true } = {}, swrOptions) {
2238
+ const { client, config, locale, cartCookieAdapter, userAdapter } = useShopify();
2239
+ const { profile, customer, memberSetting } = useCartContext();
2240
+ const isLoggedIn = userAdapter?.isLoggedIn || false;
2241
+ const buyNow = react.useCallback(
2242
+ async (_key, { arg }) => {
2243
+ const {
2244
+ lineItems,
2245
+ discountCodes,
2246
+ gtmParams = {},
2247
+ buyerIdentity,
2248
+ fbqTrackConfig,
2249
+ customAttributes,
2250
+ metafieldIdentifiers,
2251
+ redirectToCheckout
2252
+ } = arg;
2253
+ if (!lineItems || lineItems.length === 0) {
2254
+ return;
2255
+ }
2256
+ const { hasPlusMember } = useHasPlusMemberInLines({
2257
+ memberSetting,
2258
+ lines: lineItems
2259
+ });
2260
+ const memberType = hasPlusMember ? "2" : String(profile?.memberType ?? 0);
2261
+ const cartAttributes = getCartAttributes({
2262
+ profile,
2263
+ customer,
2264
+ memberType,
2265
+ currentUrl: window.location.href
2266
+ });
2267
+ const linesWithFunctionAttributes = getLinesWithAttributes({
2268
+ lineItems
2269
+ });
2270
+ const lines = linesWithFunctionAttributes.map((item) => ({
2271
+ merchandiseId: item.variant?.id || "",
2272
+ quantity: item.quantity || 1,
2273
+ attributes: item.attributes,
2274
+ sellingPlanId: item.sellingPlanId
2275
+ })).filter((item) => item.merchandiseId);
2276
+ if (lines.length === 0) {
2277
+ return;
2278
+ }
2279
+ const resultCart = await shopifySdk.createCart(client, {
2280
+ lines,
2281
+ metafieldIdentifiers,
2282
+ cookieAdapter: cartCookieAdapter,
2283
+ buyerIdentity,
2284
+ discountCodes,
2285
+ customAttributes: [...cartAttributes, ...customAttributes || []]
2286
+ });
2287
+ if (!resultCart) {
2288
+ throw new Error("Failed to create cart for buy now");
2289
+ }
2290
+ if (withTrack && resultCart.lineItems) {
2291
+ trackBuyNowGA({
2292
+ lineItems,
2293
+ gtmParams: { ...gtmParams, brand: config.getBrand() }
2294
+ });
2295
+ if (fbqTrackConfig) {
2296
+ trackBuyNowFBQ({ trackConfig: fbqTrackConfig });
2386
2297
  }
2387
- brand {
2388
- logo {
2389
- image {
2390
- url
2391
- }
2392
- }
2393
- colors {
2394
- primary {
2395
- background
2396
- }
2397
- secondary {
2398
- background
2399
- }
2298
+ }
2299
+ if (redirectToCheckout) {
2300
+ if (resultCart.url) {
2301
+ if (typeof window !== "undefined") {
2302
+ window.location.href = resultCart.url;
2400
2303
  }
2304
+ } else {
2305
+ throw new Error("Failed to get checkout URL");
2401
2306
  }
2402
- ${hasMetafields ? "metafields(identifiers: $shopMetafieldIdentifiers) { key value }" : ""}
2403
2307
  }
2404
- }
2405
- `
2308
+ return resultCart;
2309
+ },
2310
+ [client, locale, isLoggedIn, cartCookieAdapter, withTrack]
2406
2311
  );
2407
- const variables = {};
2408
- if (hasMetafields) {
2409
- variables.shopMetafieldIdentifiers = metafieldIdentifiers;
2410
- }
2411
- const data = await client.query(query, variables);
2412
- if (!data || !data.shop) {
2413
- return void 0;
2414
- }
2415
- const shop = data.shop;
2416
- const metafields = shop.metafields?.reduce((acc, mf) => {
2417
- if (mf && mf.key) {
2418
- acc[mf.key] = mf.value;
2419
- }
2420
- return acc;
2421
- }, {});
2422
- return {
2423
- name: shop.name,
2424
- description: shop.description,
2425
- primaryDomain: shop.primaryDomain,
2426
- brand: shop.brand ? {
2427
- logo: shop.brand.logo,
2428
- colors: shop.brand.colors ? {
2429
- primary: shop.brand.colors.primary?.background,
2430
- secondary: shop.brand.colors.secondary?.background
2431
- } : void 0
2432
- } : void 0,
2433
- metafields
2434
- };
2312
+ return useSWRMutation__default.default("buy-now", buyNow, swrOptions);
2435
2313
  }
2436
- function useSite(options = {}) {
2314
+
2315
+ // src/hooks/cart/types/price-discount.ts
2316
+ var PriceDiscountType = /* @__PURE__ */ ((PriceDiscountType2) => {
2317
+ PriceDiscountType2[PriceDiscountType2["PERCENTAGE"] = 1] = "PERCENTAGE";
2318
+ PriceDiscountType2[PriceDiscountType2["FIXED_AMOUNT"] = 2] = "FIXED_AMOUNT";
2319
+ return PriceDiscountType2;
2320
+ })(PriceDiscountType || {});
2321
+ var PriceBasePriceType = /* @__PURE__ */ ((PriceBasePriceType2) => {
2322
+ PriceBasePriceType2[PriceBasePriceType2["MIN_DISCOUNTED_PRICE"] = 1] = "MIN_DISCOUNTED_PRICE";
2323
+ PriceBasePriceType2[PriceBasePriceType2["MIN_TOTAL_PRICE"] = 2] = "MIN_TOTAL_PRICE";
2324
+ return PriceBasePriceType2;
2325
+ })(PriceBasePriceType || {});
2326
+ function useProduct(options = {}) {
2437
2327
  const { client, locale } = useShopify();
2438
- const { metafieldIdentifiers, ...swrOptions } = options;
2328
+ const { handle, metafieldIdentifiers, ...swrOptions } = options;
2439
2329
  return useSWR__default.default(
2440
- ["site", locale, metafieldIdentifiers],
2441
- () => getSiteInfo(client, locale, metafieldIdentifiers),
2330
+ handle ? ["product", locale, handle, metafieldIdentifiers] : null,
2331
+ () => shopifySdk.getProduct(client, {
2332
+ handle,
2333
+ locale,
2334
+ metafieldIdentifiers
2335
+ }),
2442
2336
  swrOptions
2443
2337
  );
2444
2338
  }
2445
-
2446
- // src/hooks/member/plus/types.ts
2447
- var PLUS_MEMBER_TYPE = /* @__PURE__ */ ((PLUS_MEMBER_TYPE2) => {
2448
- PLUS_MEMBER_TYPE2[PLUS_MEMBER_TYPE2["FREE"] = 0] = "FREE";
2449
- PLUS_MEMBER_TYPE2[PLUS_MEMBER_TYPE2["MONTHLY"] = 1] = "MONTHLY";
2450
- PLUS_MEMBER_TYPE2[PLUS_MEMBER_TYPE2["ANNUAL"] = 2] = "ANNUAL";
2451
- return PLUS_MEMBER_TYPE2;
2452
- })(PLUS_MEMBER_TYPE || {});
2453
- var PlusMemberMode = /* @__PURE__ */ ((PlusMemberMode2) => {
2454
- PlusMemberMode2["MONTHLY"] = "monthly";
2455
- PlusMemberMode2["ANNUAL"] = "annual";
2456
- return PlusMemberMode2;
2457
- })(PlusMemberMode || {});
2458
- var DeliveryPlusType = /* @__PURE__ */ ((DeliveryPlusType2) => {
2459
- DeliveryPlusType2["FREE"] = "free";
2460
- DeliveryPlusType2["MONTHLY"] = "monthly";
2461
- DeliveryPlusType2["ANNUAL"] = "annual";
2462
- return DeliveryPlusType2;
2463
- })(DeliveryPlusType || {});
2464
- var ShippingMethodMode = /* @__PURE__ */ ((ShippingMethodMode2) => {
2465
- ShippingMethodMode2["FREE"] = "free";
2466
- ShippingMethodMode2["TDD"] = "tdd";
2467
- ShippingMethodMode2["NDD"] = "ndd";
2468
- return ShippingMethodMode2;
2469
- })(ShippingMethodMode || {});
2470
- var createInitialValue = () => ({
2471
- zipCode: "",
2472
- plusMemberMetafields: {},
2473
- setZipCode: () => {
2474
- },
2475
- allowNextDayDelivery: false,
2476
- setAllowNextDayDelivery: () => {
2477
- },
2478
- allowThirdDayDelivery: false,
2479
- setAllowThirdDayDelivery: () => {
2480
- },
2481
- selectedPlusMemberMode: "free",
2482
- setSelectedPlusMemberMode: () => {
2483
- },
2484
- showAreaCheckModal: false,
2485
- setShowAreaCheckModal: () => {
2486
- },
2487
- selectedShippingMethod: void 0,
2488
- setSelectedShippingMethod: () => {
2489
- },
2490
- showTip: false,
2491
- setShowTip: () => {
2492
- },
2493
- showMoreShippingMethod: false,
2494
- setShowMoreShippingMethod: () => {
2495
- },
2496
- variant: {},
2497
- product: {},
2498
- shippingMethodsContext: {
2499
- freeShippingMethods: [],
2500
- paymentShippingMethods: [],
2501
- nddOverweight: false,
2502
- tddOverweight: false,
2503
- nddCoupon: void 0,
2504
- tddCoupon: void 0,
2505
- isLoadingCoupon: false
2506
- },
2507
- selectedPlusMemberVariant: void 0,
2508
- monthlyVariant: void 0,
2509
- annualVariant: void 0,
2510
- showPlusMemberBenefit: false,
2511
- setShowPlusMemberBenefit: () => {
2512
- },
2513
- deleteMarginBottom: false,
2514
- setDeleteMarginBottom: () => {
2515
- },
2516
- profile: void 0,
2517
- locale: void 0
2518
- });
2519
- var PlusMemberContext = react.createContext(createInitialValue());
2520
- function usePlusMemberContext() {
2521
- return react.useContext(PlusMemberContext);
2339
+ function useAllProducts(options = {}) {
2340
+ const { client, locale } = useShopify();
2341
+ const { first, query, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
2342
+ return useSWR__default.default(
2343
+ ["all-products", locale, first, query, sortKey, reverse, metafieldIdentifiers],
2344
+ () => shopifySdk.getAllProducts(client, {
2345
+ locale,
2346
+ first,
2347
+ query,
2348
+ sortKey,
2349
+ reverse,
2350
+ metafieldIdentifiers
2351
+ }),
2352
+ swrOptions
2353
+ );
2522
2354
  }
2523
- function usePlusMemberVariants({
2524
- memberSetting
2355
+ function getFirstAvailableVariant(product) {
2356
+ const availableVariant = product.variants.find((v) => v.availableForSale);
2357
+ return availableVariant || product.variants[0];
2358
+ }
2359
+ function getVariantFromSelectedOptions(product, selectedOptions) {
2360
+ return product.variants.find((variant) => {
2361
+ return variant.selectedOptions.every((option) => {
2362
+ return selectedOptions[option.name] === option.value;
2363
+ });
2364
+ });
2365
+ }
2366
+ function useVariant({
2367
+ product,
2368
+ selectedOptions
2525
2369
  }) {
2526
- const plusMonthly = memberSetting?.plus_monthly_product;
2527
- const plusAnnual = memberSetting?.plus_annual_product;
2528
- const plusMemberHandles = react.useMemo(() => {
2529
- return [plusMonthly?.handle, plusAnnual?.handle].filter(Boolean);
2530
- }, [plusMonthly?.handle, plusAnnual?.handle]);
2531
- const { data: plusMemberProducts = [] } = useProductsByHandles({
2532
- handles: plusMemberHandles
2370
+ const [variant, setVariant] = react.useState(
2371
+ product ? getFirstAvailableVariant(product) : void 0
2372
+ );
2373
+ react.useEffect(() => {
2374
+ if (!product) {
2375
+ setVariant(void 0);
2376
+ return;
2377
+ }
2378
+ const newVariant = getVariantFromSelectedOptions(product, selectedOptions);
2379
+ if (newVariant && newVariant.id !== variant?.id) {
2380
+ setVariant(newVariant);
2381
+ } else if (!newVariant) {
2382
+ setVariant(getFirstAvailableVariant(product));
2383
+ }
2384
+ }, [selectedOptions, product, variant?.id]);
2385
+ return variant;
2386
+ }
2387
+ var FAKE_PRICE = 999999999e-2;
2388
+ function formatPrice({
2389
+ amount,
2390
+ currencyCode,
2391
+ locale,
2392
+ maximumFractionDigits,
2393
+ minimumFractionDigits,
2394
+ removeTrailingZeros
2395
+ }) {
2396
+ const formatter = new Intl.NumberFormat(locale, {
2397
+ style: "currency",
2398
+ currency: currencyCode,
2399
+ maximumFractionDigits: maximumFractionDigits ?? 2,
2400
+ minimumFractionDigits: minimumFractionDigits ?? 2
2533
2401
  });
2534
- const monthlyProduct = react.useMemo(() => {
2535
- return plusMemberProducts?.find((item) => item?.handle === plusMonthly?.handle);
2536
- }, [plusMemberProducts, plusMonthly]);
2537
- const annualProduct = react.useMemo(() => {
2538
- return plusMemberProducts?.find((item) => item?.handle === plusAnnual?.handle);
2539
- }, [plusMemberProducts, plusAnnual]);
2540
- const monthlyVariant = react.useMemo(() => {
2541
- return monthlyProduct?.variants?.find((item) => item.sku === plusMonthly?.sku);
2542
- }, [monthlyProduct, plusMonthly]);
2543
- const annualVariant = react.useMemo(() => {
2544
- return annualProduct?.variants?.find((item) => item.sku === plusAnnual?.sku);
2545
- }, [annualProduct, plusAnnual]);
2402
+ let formatted = formatter.format(amount);
2403
+ if (removeTrailingZeros) {
2404
+ formatted = formatted.replace(/\.00$/, "");
2405
+ }
2406
+ return formatted;
2407
+ }
2408
+ function formatVariantPrice({
2409
+ amount,
2410
+ baseAmount,
2411
+ currencyCode,
2412
+ locale,
2413
+ maximumFractionDigits,
2414
+ minimumFractionDigits,
2415
+ removeTrailingZeros
2416
+ }) {
2546
2417
  return {
2547
- monthlyVariant: monthlyVariant ? {
2548
- ...monthlyVariant,
2549
- product: monthlyProduct
2550
- } : void 0,
2551
- annualVariant: annualVariant ? {
2552
- ...annualVariant,
2553
- product: annualProduct
2554
- } : void 0
2418
+ price: formatPrice({
2419
+ amount,
2420
+ currencyCode,
2421
+ locale,
2422
+ maximumFractionDigits,
2423
+ minimumFractionDigits,
2424
+ removeTrailingZeros
2425
+ }),
2426
+ basePrice: formatPrice({
2427
+ amount: baseAmount,
2428
+ currencyCode,
2429
+ locale,
2430
+ maximumFractionDigits,
2431
+ minimumFractionDigits,
2432
+ removeTrailingZeros
2433
+ })
2555
2434
  };
2556
2435
  }
2557
- var useAvailableDeliveryCoupon = ({
2558
- profile
2559
- }) => {
2560
- const { data: availableDeliveryCoupon, isLoading } = useSWR__default.default(
2561
- profile?.email ? ["/api/multipass/subsrv/v1/prime/delivery_coupons/current/available", profile?.email] : void 0,
2562
- async ([apiPath]) => {
2563
- return fetch(apiPath).then((res) => res.json());
2436
+ function usePrice({
2437
+ amount,
2438
+ baseAmount,
2439
+ currencyCode,
2440
+ soldOutDescription = "",
2441
+ maximumFractionDigits,
2442
+ minimumFractionDigits,
2443
+ removeTrailingZeros
2444
+ }) {
2445
+ const { locale } = useShopify();
2446
+ const value = react.useMemo(() => {
2447
+ if (typeof amount !== "number" || !currencyCode) {
2448
+ return "";
2564
2449
  }
2565
- );
2566
- console.log("availableDeliveryCoupon", availableDeliveryCoupon);
2567
- const { ndd_coupon: nddCoupon, tdd_coupon: tddCoupon } = availableDeliveryCoupon?.data?.data || {};
2568
- return {
2569
- nddCoupon,
2570
- tddCoupon,
2571
- isLoading
2572
- };
2573
- };
2574
-
2575
- // src/hooks/member/plus/use-shipping-methods.ts
2576
- function useShippingMethods(options) {
2577
- const { variant, plusMemberMetafields, selectedPlusMemberMode, isPlus = false, profile } = options;
2578
- const { nddCoupon, tddCoupon, isLoading } = useAvailableDeliveryCoupon({ profile });
2579
- console.log("nddCoupon", nddCoupon);
2580
- const { plus_shipping, shippingMethod } = plusMemberMetafields || {};
2581
- const nddOverweight = react.useMemo(() => {
2582
- return (variant?.weight || 0) > (shippingMethod?.overWeight_ndd || Infinity);
2583
- }, [shippingMethod?.overWeight_ndd, variant?.weight]);
2584
- const tddOverweight = react.useMemo(() => {
2585
- return (variant?.weight || 0) > (shippingMethod?.overWeight_tdd || Infinity);
2586
- }, [shippingMethod?.overWeight_tdd, variant?.weight]);
2587
- const paymentShippingMethods = react.useMemo(() => {
2588
- const weight = variant?.weight || 0;
2589
- const methods = plus_shipping?.shipping_methods?.filter(({ weight_low, weight_high, __mode, __plus }) => {
2590
- const fitWeight = (!weight_low || weight >= weight_low) && (!weight_high || weight <= weight_high);
2591
- return __mode !== "free" /* FREE */ && !__plus && fitWeight;
2592
- }) || [];
2593
- return methods.map((method) => {
2594
- let disabled = false;
2595
- const selectedFreeMember = selectedPlusMemberMode === "free";
2596
- if (method.__mode === "ndd" /* NDD */) {
2597
- disabled = selectedFreeMember || nddOverweight;
2598
- } else if (method.__mode === "tdd" /* TDD */) {
2599
- disabled = selectedFreeMember || tddOverweight;
2600
- }
2601
- return {
2602
- ...method,
2603
- id: method.__mode + method.__code,
2604
- useCoupon: false,
2605
- subtitle: plus_shipping?.directly || "",
2606
- disabled
2607
- };
2450
+ if (soldOutDescription && amount >= FAKE_PRICE) {
2451
+ return soldOutDescription;
2452
+ }
2453
+ return baseAmount ? formatVariantPrice({
2454
+ amount,
2455
+ baseAmount,
2456
+ currencyCode,
2457
+ locale,
2458
+ maximumFractionDigits,
2459
+ minimumFractionDigits,
2460
+ removeTrailingZeros
2461
+ }) : formatPrice({
2462
+ amount,
2463
+ currencyCode,
2464
+ locale,
2465
+ maximumFractionDigits,
2466
+ minimumFractionDigits,
2467
+ removeTrailingZeros
2608
2468
  });
2609
2469
  }, [
2610
- nddOverweight,
2611
- plus_shipping?.directly,
2612
- plus_shipping?.shipping_methods,
2613
- selectedPlusMemberMode,
2614
- tddOverweight,
2615
- variant?.weight
2470
+ amount,
2471
+ baseAmount,
2472
+ currencyCode,
2473
+ locale,
2474
+ maximumFractionDigits,
2475
+ minimumFractionDigits,
2476
+ soldOutDescription,
2477
+ removeTrailingZeros
2616
2478
  ]);
2617
- const nddPrice = react.useMemo(() => {
2618
- const weight = variant?.weight || 0;
2619
- const nddMethod = paymentShippingMethods.find(({ __mode, weight_high, weight_low }) => {
2620
- const fitWeight = (!weight_low || weight >= weight_low) && (!weight_high || weight <= weight_high);
2621
- return __mode === "ndd" && fitWeight;
2622
- });
2623
- return nddMethod?.price || 0;
2624
- }, [variant?.weight, paymentShippingMethods]);
2625
- const tddPrice = react.useMemo(() => {
2626
- const weight = variant?.weight || 0;
2627
- const tddMethod = paymentShippingMethods.find(({ __mode, weight_high, weight_low }) => {
2628
- const fitWeight = (!weight_low || weight >= weight_low) && (!weight_high || weight <= weight_high);
2629
- return __mode === "tdd" && fitWeight;
2630
- });
2631
- return tddMethod?.price || 0;
2632
- }, [variant?.weight, paymentShippingMethods]);
2633
- const freeShippingMethods = react.useMemo(() => {
2634
- const weight = variant?.weight || 0;
2635
- let methods = plus_shipping?.shipping_methods?.filter(({ __mode, __plus, weight_low, weight_high }) => {
2636
- if (__mode === "free" /* FREE */) {
2637
- return true;
2638
- }
2639
- if (isPlus) {
2640
- const hasCoupon = isPlus && __mode === "ndd" /* NDD */ && nddCoupon || isPlus && __mode === "tdd" /* TDD */ && (tddCoupon || nddCoupon);
2641
- const fitWeight = (!weight_low || weight >= weight_low) && (!weight_high || weight <= weight_high);
2642
- return hasCoupon && fitWeight && !__plus;
2643
- } else {
2644
- return __plus;
2645
- }
2646
- }) || [];
2647
- if (isPlus) {
2648
- methods = methods.sort((a, b) => {
2649
- if (b.__mode === "free" /* FREE */) return -1;
2650
- return 0;
2651
- });
2479
+ const result = react.useMemo(() => {
2480
+ const free = Boolean(amount && amount <= 0);
2481
+ return typeof value === "string" ? { price: value, basePrice: value, free } : { ...value, free };
2482
+ }, [value, amount]);
2483
+ return result;
2484
+ }
2485
+ function optionsConstructor(selectedOptions) {
2486
+ return selectedOptions.reduce((acc, option) => {
2487
+ acc[option.name] = option.value;
2488
+ return acc;
2489
+ }, {});
2490
+ }
2491
+ function decodeShopifyId(gid) {
2492
+ try {
2493
+ const base64 = gid.split("/").pop() || "";
2494
+ return atob(base64);
2495
+ } catch {
2496
+ return gid;
2497
+ }
2498
+ }
2499
+ function useSelectedOptions(product, sku) {
2500
+ const [options, setOptions] = react.useState({});
2501
+ react.useEffect(() => {
2502
+ if (!product || !product.variants.length) {
2503
+ setOptions({});
2504
+ return;
2652
2505
  }
2653
- return methods.map((method) => {
2654
- let price = 0;
2655
- let coupon;
2656
- let disabled;
2657
- if (method.__mode !== "free" /* FREE */) {
2658
- switch (method.__mode) {
2659
- case "tdd":
2660
- price = tddPrice;
2661
- coupon = tddCoupon || nddCoupon;
2662
- break;
2663
- case "ndd":
2664
- price = nddPrice;
2665
- coupon = nddCoupon;
2666
- break;
2506
+ let variant = product.variants[0];
2507
+ if (typeof window !== "undefined") {
2508
+ const searchParams = new URLSearchParams(window.location.search);
2509
+ const variantIdParam = searchParams.get("variant");
2510
+ if (variantIdParam) {
2511
+ const foundVariant = product.variants.find((v) => {
2512
+ if (sku) return v.sku === sku;
2513
+ return v.id === variantIdParam || v.id.includes(variantIdParam) || decodeShopifyId(v.id) === variantIdParam;
2514
+ });
2515
+ if (foundVariant) {
2516
+ variant = foundVariant;
2667
2517
  }
2668
- disabled = selectedPlusMemberMode === "free";
2669
- if (method.__mode === "ndd" /* NDD */) {
2670
- disabled = disabled || nddOverweight;
2671
- } else if (method.__mode === "tdd" /* TDD */) {
2672
- disabled = disabled || tddOverweight;
2518
+ }
2519
+ }
2520
+ if (variant) {
2521
+ const newOptions = optionsConstructor(variant.selectedOptions);
2522
+ setOptions(newOptions);
2523
+ }
2524
+ }, [product, sku]);
2525
+ return [options, setOptions];
2526
+ }
2527
+ function decodeShopifyId2(gid) {
2528
+ try {
2529
+ const parts = gid.split("/");
2530
+ return parts[parts.length - 1] || gid;
2531
+ } catch {
2532
+ return gid;
2533
+ }
2534
+ }
2535
+ function useProductUrl(otherQuery) {
2536
+ const { routerAdapter } = useShopify();
2537
+ return react.useCallback(
2538
+ ({ product, variant }) => {
2539
+ if (!product) return "";
2540
+ const queryParams = new URLSearchParams();
2541
+ if (variant?.id) {
2542
+ const variantId = decodeShopifyId2(variant.id);
2543
+ if (variantId) {
2544
+ queryParams.set("variant", variantId);
2673
2545
  }
2674
2546
  }
2675
- return {
2676
- ...method,
2677
- id: method.__mode + method.__code,
2678
- useCoupon: true,
2679
- disabled,
2680
- coupon,
2681
- price
2682
- };
2683
- });
2684
- }, [
2685
- variant?.weight,
2686
- plus_shipping?.shipping_methods,
2687
- isPlus,
2688
- nddCoupon,
2689
- tddCoupon,
2690
- selectedPlusMemberMode,
2691
- tddPrice,
2692
- nddPrice,
2693
- nddOverweight,
2694
- tddOverweight
2695
- ]);
2696
- return {
2697
- freeShippingMethods,
2698
- paymentShippingMethods,
2699
- nddOverweight,
2700
- tddOverweight,
2701
- nddCoupon,
2702
- tddCoupon,
2703
- isLoadingCoupon: isLoading
2704
- };
2547
+ if (otherQuery) {
2548
+ Object.entries(otherQuery).forEach(([key, value]) => {
2549
+ queryParams.set(key, value);
2550
+ });
2551
+ }
2552
+ const queryString = queryParams.toString();
2553
+ const path = `/products/${product.handle}${queryString ? `?${queryString}` : ""}`;
2554
+ if (routerAdapter?.getLocalizedPath) {
2555
+ return routerAdapter.getLocalizedPath(path);
2556
+ }
2557
+ return path;
2558
+ },
2559
+ [routerAdapter, otherQuery]
2560
+ );
2705
2561
  }
2706
- function useShippingMethodAvailableCheck() {
2707
- const {
2708
- zipCode,
2709
- allowNextDayDelivery,
2710
- allowThirdDayDelivery,
2711
- selectedShippingMethod,
2712
- setSelectedShippingMethod,
2713
- setShowTip,
2714
- shippingMethodsContext
2715
- } = usePlusMemberContext();
2562
+ function decodeShopifyId3(gid) {
2563
+ try {
2564
+ const parts = gid.split("/");
2565
+ return parts[parts.length - 1] || gid;
2566
+ } catch {
2567
+ return gid;
2568
+ }
2569
+ }
2570
+ function useUpdateVariantQuery(variant) {
2716
2571
  react.useEffect(() => {
2717
- const freeShippingMethod = shippingMethodsContext.freeShippingMethods[0];
2718
- const standardShippingMethod = shippingMethodsContext.freeShippingMethods?.find(
2719
- (item) => item.__mode === "free" /* FREE */
2720
- );
2721
- const freeTDD = shippingMethodsContext.freeShippingMethods.find(
2722
- (item) => item.__mode === "tdd" /* TDD */
2723
- );
2724
- const paymentTDD = shippingMethodsContext.paymentShippingMethods.find(
2725
- (item) => item.__mode === "tdd" /* TDD */
2726
- );
2727
- if (zipCode) {
2728
- console.log(
2729
- "allowNextDayDelivery, allowThirdDayDelivery:",
2730
- allowNextDayDelivery,
2731
- allowThirdDayDelivery
2732
- );
2733
- if (!allowNextDayDelivery && !allowThirdDayDelivery) {
2734
- setShowTip(true);
2735
- setSelectedShippingMethod(standardShippingMethod);
2736
- } else {
2737
- if (selectedShippingMethod?.__mode === "ndd" /* NDD */ && !allowNextDayDelivery) {
2738
- setShowTip(true);
2739
- if (allowThirdDayDelivery) {
2740
- if (selectedShippingMethod.useCoupon) {
2741
- const method = freeTDD || freeShippingMethod;
2742
- if (method) setSelectedShippingMethod(method);
2743
- } else {
2744
- const method = paymentTDD || freeShippingMethod;
2745
- if (method) setSelectedShippingMethod(method);
2746
- }
2747
- } else {
2748
- if (freeShippingMethod) setSelectedShippingMethod(freeShippingMethod);
2749
- }
2750
- } else if (
2751
- // TDD 无法使用
2752
- selectedShippingMethod?.__mode === "tdd" /* TDD */ && !allowThirdDayDelivery
2753
- ) {
2754
- setShowTip(true);
2755
- if (freeShippingMethod) setSelectedShippingMethod(freeShippingMethod);
2756
- }
2572
+ if (!variant || typeof window === "undefined") {
2573
+ return;
2574
+ }
2575
+ const searchParams = new URLSearchParams(window.location.search);
2576
+ const currentVariantId = searchParams.get("variant");
2577
+ const newVariantId = decodeShopifyId3(variant.id);
2578
+ if (newVariantId && currentVariantId !== newVariantId) {
2579
+ searchParams.set("variant", newVariantId);
2580
+ const newUrl = `${window.location.pathname}?${searchParams.toString()}${window.location.hash}`;
2581
+ window.history.replaceState({}, "", newUrl);
2582
+ }
2583
+ }, [variant]);
2584
+ }
2585
+ function getVariantMediaList({
2586
+ product,
2587
+ variant
2588
+ }) {
2589
+ if (variant.image?.url) {
2590
+ const variantMediaId = variant.image.url;
2591
+ const variantMedia = product.media.filter((media) => {
2592
+ if (media.mediaContentType === "IMAGE" && media.previewImage) {
2593
+ return media.previewImage?.url === variantMediaId;
2757
2594
  }
2595
+ return false;
2596
+ });
2597
+ if (variantMedia.length > 0) {
2598
+ const otherMedia = product.media.filter((media) => {
2599
+ if (media.mediaContentType === "IMAGE" && media.previewImage) {
2600
+ return media.previewImage.url !== variantMediaId;
2601
+ }
2602
+ return true;
2603
+ });
2604
+ return [...variantMedia, ...otherMedia];
2758
2605
  }
2759
- }, [
2760
- allowNextDayDelivery,
2761
- allowThirdDayDelivery,
2762
- zipCode,
2763
- shippingMethodsContext,
2764
- selectedShippingMethod,
2765
- setSelectedShippingMethod,
2766
- setShowTip
2767
- ]);
2606
+ }
2607
+ return product.media;
2768
2608
  }
2769
- var useReplaceCartPlusMember = () => {
2770
- const { plusMemberMetafields, selectedPlusMemberMode } = usePlusMemberContext();
2771
- const { trigger: removeCartLines2 } = useRemoveCartLines();
2772
- const { cart } = useCartContext();
2773
- const plusMonthly = plusMemberMetafields?.plus_monthly_product;
2774
- const plusAnnual = plusMemberMetafields?.plus_annual_product;
2775
- const handler = react.useCallback(async () => {
2776
- const plusMonthlyInCart = cart?.lineItems.find(
2777
- (item) => item.variant?.sku === plusMonthly?.sku
2778
- );
2779
- const plusAnnualInCart = cart?.lineItems.find(
2780
- (item) => item.variant?.sku === plusAnnual?.sku
2781
- );
2782
- if (selectedPlusMemberMode === "annual" /* ANNUAL */ && plusMonthlyInCart) {
2783
- await removeCartLines2({
2784
- lineIds: [plusMonthlyInCart.id]
2785
- });
2786
- } else if (selectedPlusMemberMode === "monthly" /* MONTHLY */ && plusAnnualInCart) {
2787
- await removeCartLines2({
2788
- lineIds: [plusAnnualInCart.id]
2789
- });
2609
+ function useVariantMedia({
2610
+ product,
2611
+ variant
2612
+ }) {
2613
+ const [imageList, setImageList] = react.useState([]);
2614
+ const [sceneList, setSceneList] = react.useState([]);
2615
+ const [videoList, setVideoList] = react.useState([]);
2616
+ react.useEffect(() => {
2617
+ if (!product || !variant) {
2618
+ setImageList([]);
2619
+ setSceneList([]);
2620
+ setVideoList([]);
2621
+ return;
2790
2622
  }
2791
- }, [
2792
- cart?.lineItems,
2793
- selectedPlusMemberMode,
2794
- plusMonthly?.sku,
2795
- plusAnnual?.sku,
2796
- removeCartLines2
2797
- ]);
2798
- return handler;
2799
- };
2800
- var usePlusMemberDeliveryCodes = ({
2801
- deliveryData
2802
- }) => {
2803
- return react.useMemo(
2804
- () => deliveryData?.deliveryCustomData?.discount_code,
2805
- [deliveryData]
2623
+ const mediaList = getVariantMediaList({ product, variant });
2624
+ const images = mediaList.filter((media) => media.mediaContentType === "IMAGE");
2625
+ const videos = mediaList.filter(
2626
+ (media) => media.mediaContentType === "VIDEO" || media.mediaContentType === "EXTERNAL_VIDEO"
2627
+ );
2628
+ setImageList(images.length > 0 && images[0] ? [images[0]] : []);
2629
+ setSceneList(images.length > 1 ? images.slice(1) : []);
2630
+ setVideoList(videos);
2631
+ }, [product, variant]);
2632
+ return {
2633
+ productList: imageList,
2634
+ sceneList,
2635
+ videoList
2636
+ };
2637
+ }
2638
+ function useCollection(options = {}) {
2639
+ const { client, locale } = useShopify();
2640
+ const { handle, metafieldIdentifiers, ...swrOptions } = options;
2641
+ return useSWR__default.default(
2642
+ handle ? ["collection", locale, handle, metafieldIdentifiers] : null,
2643
+ () => shopifySdk.getCollection(client, {
2644
+ handle,
2645
+ locale,
2646
+ metafieldIdentifiers
2647
+ }),
2648
+ swrOptions
2806
2649
  );
2807
- };
2808
- function useUpdateCartDeliveryOptions(mutate, metafieldIdentifiers, options) {
2809
- const { client, locale, cartCookieAdapter } = useShopify();
2810
- const updateDeliveryOptions = react.useCallback(
2811
- async (_key, { arg }) => {
2812
- const updatedCart = await shopifySdk.updateCartDeliveryOptions(client, {
2813
- ...arg,
2814
- metafieldIdentifiers,
2815
- cookieAdapter: cartCookieAdapter
2816
- });
2817
- console.log("useUpdateCartDeliveryOptions updatedCart", updatedCart);
2818
- if (updatedCart) {
2819
- mutate(updatedCart);
2820
- }
2821
- return updatedCart;
2822
- },
2823
- [client, locale, cartCookieAdapter, mutate, metafieldIdentifiers]
2650
+ }
2651
+ function useAllCollections(options = {}) {
2652
+ const { client, locale } = useShopify();
2653
+ const { first, query, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
2654
+ return useSWR__default.default(
2655
+ ["all-collections", locale, first, query, sortKey, reverse, metafieldIdentifiers],
2656
+ () => shopifySdk.getAllCollections(client, {
2657
+ locale,
2658
+ first,
2659
+ query,
2660
+ sortKey,
2661
+ reverse,
2662
+ metafieldIdentifiers
2663
+ }),
2664
+ swrOptions
2824
2665
  );
2825
- return useSWRMutation__default.default("update-cart-delivery-options", updateDeliveryOptions, options);
2826
2666
  }
2827
-
2828
- // src/hooks/member/plus/use-update-plus-member-delivery-options.ts
2829
- var useUpdatePlusMemberDeliveryOptions = ({
2830
- options
2831
- } = {}) => {
2832
- const { cart: cartContextData, mutateCart, metafieldIdentifiers } = useCartContext();
2833
- const { trigger: updateCartDeliveryOptions2 } = useUpdateCartDeliveryOptions(
2834
- mutateCart,
2835
- metafieldIdentifiers
2667
+ function useCollections(options = {}) {
2668
+ const { client, locale } = useShopify();
2669
+ const { first, after, query, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
2670
+ return useSWR__default.default(
2671
+ ["collections", locale, first, after, query, sortKey, reverse, metafieldIdentifiers],
2672
+ () => shopifySdk.getCollections(client, {
2673
+ locale,
2674
+ first,
2675
+ after,
2676
+ query,
2677
+ sortKey,
2678
+ reverse,
2679
+ metafieldIdentifiers
2680
+ }),
2681
+ swrOptions
2836
2682
  );
2837
- const handler = react.useCallback(
2838
- async (_, { arg }) => {
2839
- const currentCart = arg?.cart || cartContextData;
2840
- const { deliveryData } = arg;
2841
- const firstDeliveryGroup = currentCart?.deliveryGroups?.[0];
2842
- const deliveryGroupId = firstDeliveryGroup?.id;
2843
- const selectedOptionCode = deliveryData?.deliveryCustomData?.selected_delivery_option?.code;
2844
- if (!deliveryGroupId || !selectedOptionCode || selectedOptionCode === firstDeliveryGroup?.selectedDeliveryOption?.code) {
2845
- return null;
2846
- }
2847
- const deliveryGroup = currentCart?.deliveryGroups?.find(
2848
- (group) => group?.id === deliveryGroupId
2849
- );
2850
- const matchedOption = deliveryGroup?.deliveryOptions?.find(
2851
- (option) => option?.code === selectedOptionCode
2852
- );
2853
- if (!matchedOption?.handle) {
2854
- return null;
2855
- }
2856
- const deliveryOptions = [
2857
- {
2858
- deliveryGroupId,
2859
- deliveryOptionHandle: matchedOption.handle
2683
+ }
2684
+ function useBlog(options = {}) {
2685
+ const { client, locale } = useShopify();
2686
+ const { handle, metafieldIdentifiers, ...swrOptions } = options;
2687
+ return useSWR__default.default(
2688
+ handle ? ["blog", locale, handle, metafieldIdentifiers] : null,
2689
+ () => shopifySdk.getBlog(client, { handle, locale, metafieldIdentifiers }),
2690
+ swrOptions
2691
+ );
2692
+ }
2693
+ function useAllBlogs(options = {}) {
2694
+ const { client, locale } = useShopify();
2695
+ const { first, query, metafieldIdentifiers, ...swrOptions } = options;
2696
+ return useSWR__default.default(
2697
+ ["all-blogs", locale, first, query, metafieldIdentifiers],
2698
+ () => shopifySdk.getAllBlogs(client, {
2699
+ locale,
2700
+ first,
2701
+ query,
2702
+ metafieldIdentifiers
2703
+ }),
2704
+ swrOptions
2705
+ );
2706
+ }
2707
+ function useArticle(options = {}) {
2708
+ const { client, locale } = useShopify();
2709
+ const { blogHandle, articleHandle, metafieldIdentifiers, ...swrOptions } = options;
2710
+ return useSWR__default.default(
2711
+ blogHandle && articleHandle ? ["article", locale, blogHandle, articleHandle, metafieldIdentifiers] : null,
2712
+ () => shopifySdk.getArticle(client, {
2713
+ blogHandle,
2714
+ articleHandle,
2715
+ locale,
2716
+ metafieldIdentifiers
2717
+ }),
2718
+ swrOptions
2719
+ );
2720
+ }
2721
+ function useArticles(options = {}) {
2722
+ const { client, locale } = useShopify();
2723
+ const { first, query, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
2724
+ return useSWR__default.default(
2725
+ ["articles", locale, first, query, sortKey, reverse, metafieldIdentifiers],
2726
+ () => shopifySdk.getArticles(client, {
2727
+ locale,
2728
+ first,
2729
+ query,
2730
+ sortKey,
2731
+ reverse,
2732
+ metafieldIdentifiers
2733
+ }),
2734
+ swrOptions
2735
+ );
2736
+ }
2737
+ function useArticlesInBlog(options = {}) {
2738
+ const { client, locale } = useShopify();
2739
+ const { blogHandle, first, sortKey, reverse, metafieldIdentifiers, ...swrOptions } = options;
2740
+ return useSWR__default.default(
2741
+ blogHandle ? ["articles-in-blog", locale, blogHandle, first, sortKey, reverse, metafieldIdentifiers] : null,
2742
+ () => shopifySdk.getArticlesInBlog(client, {
2743
+ blogHandle,
2744
+ locale,
2745
+ first,
2746
+ sortKey,
2747
+ reverse,
2748
+ metafieldIdentifiers
2749
+ }),
2750
+ swrOptions
2751
+ );
2752
+ }
2753
+ async function performSearch(client, locale, searchQuery, first = 20, types = ["PRODUCT", "ARTICLE", "PAGE"]) {
2754
+ if (!searchQuery) {
2755
+ return void 0;
2756
+ }
2757
+ const query = (
2758
+ /* GraphQL */
2759
+ `
2760
+ query search($query: String!, $first: Int!, $types: [SearchType!])
2761
+ @inContext(language: $language) {
2762
+ search(query: $query, first: $first, types: $types, unavailableProducts: HIDE) {
2763
+ totalCount
2764
+ edges {
2765
+ node {
2766
+ ... on Article {
2767
+ __typename
2768
+ id
2769
+ handle
2770
+ title
2771
+ excerpt
2772
+ image {
2773
+ url
2774
+ altText
2775
+ }
2776
+ }
2777
+ ... on Page {
2778
+ __typename
2779
+ id
2780
+ handle
2781
+ title
2782
+ }
2783
+ ... on Product {
2784
+ __typename
2785
+ id
2786
+ handle
2787
+ title
2788
+ description
2789
+ featuredImage {
2790
+ url
2791
+ altText
2792
+ }
2793
+ }
2794
+ }
2795
+ }
2796
+ pageInfo {
2797
+ hasNextPage
2798
+ endCursor
2860
2799
  }
2861
- ];
2862
- const updatedCart = await updateCartDeliveryOptions2({
2863
- selectedDeliveryOptions: deliveryOptions,
2864
- cartId: currentCart?.id
2865
- });
2866
- if (updatedCart && mutateCart) {
2867
- mutateCart(updatedCart);
2868
- }
2869
- return updatedCart;
2870
- },
2871
- [cartContextData, updateCartDeliveryOptions2, mutateCart]
2872
- );
2873
- return useSWRMutation__default.default("update-cart-delivery-options", handler, options);
2874
- };
2875
- var usePlusMemberItemCustomAttributes = ({
2876
- deliveryData
2877
- }) => {
2878
- const { deliveryCustomData } = deliveryData || {};
2879
- return react.useMemo(() => {
2880
- const itemCustomAttributes = [];
2881
- if (deliveryCustomData?.is_presale) {
2882
- itemCustomAttributes.push({
2883
- key: "_is_presale",
2884
- value: "true"
2885
- });
2886
- }
2887
- return itemCustomAttributes;
2888
- }, [deliveryCustomData]);
2889
- };
2890
- var usePlusMemberCheckoutCustomAttributes = ({
2891
- deliveryData,
2892
- product,
2893
- variant,
2894
- isShowShippingBenefits
2895
- }) => {
2896
- const { deliveryCustomData } = deliveryData || {};
2897
- const { profile } = usePlusMemberContext();
2898
- return react.useMemo(() => {
2899
- const checkoutCustomAttributes = [
2900
- // _last_url: 付费会员结算完成之后 checkout 有一个继续购买的按钮, 用于跳转到继续购买的页面
2901
- {
2902
- key: "_last_url",
2903
- value: typeof window !== "undefined" ? window.location.origin + window.location.pathname : ""
2904
- }
2905
- ];
2906
- if (deliveryCustomData) {
2907
- checkoutCustomAttributes.push({
2908
- key: "_checkout_delivery_custom",
2909
- value: JSON.stringify({
2910
- ...deliveryCustomData,
2911
- is_prime: profile?.isPlus
2912
- })
2913
- });
2914
- }
2915
- if (isShowShippingBenefits && !isShowShippingBenefits({ variant, product, setting: {} })) {
2916
- checkoutCustomAttributes.push({
2917
- key: "_hide_shipping",
2918
- value: "true"
2919
- });
2920
- }
2921
- return checkoutCustomAttributes;
2922
- }, [deliveryCustomData, product, profile, variant, isShowShippingBenefits]);
2923
- };
2924
- function useAutoRemovePlusMemberInCart({
2925
- cart,
2926
- profile,
2927
- memberSetting
2928
- }) {
2929
- const { plus_monthly_product, plus_annual_product } = memberSetting || {};
2930
- const { trigger: removeCartLines2 } = useRemoveCartLines();
2931
- react.useEffect(() => {
2932
- if (!cart || !plus_monthly_product || !plus_annual_product) return;
2933
- const removePlusProduct = async (productType) => {
2934
- if (!productType) return;
2935
- const product = cart.lineItems?.find(
2936
- (item) => item.product?.handle === productType?.handle && item.variant?.sku === productType?.sku
2937
- );
2938
- if (product) {
2939
- await removeCartLines2({
2940
- lineIds: [product.id]
2941
- });
2942
2800
  }
2943
- };
2944
- if (profile?.isMonthlyPlus) {
2945
- removePlusProduct(plus_monthly_product);
2946
- }
2947
- if (profile?.isAnnualPlus) {
2948
- removePlusProduct(plus_annual_product);
2949
2801
  }
2950
- }, [cart, plus_annual_product, plus_monthly_product, profile, removeCartLines2]);
2951
- }
2952
- function usePlusMemberNeedAddToCart({
2953
- cart,
2954
- profile
2955
- }) {
2956
- const { selectedPlusMemberMode, selectedPlusMemberVariant, plusMemberMetafields } = usePlusMemberContext();
2957
- const { hasMonthlyPlus, hasAnnualPlus } = useHasPlusMemberInCart({
2958
- memberSetting: plusMemberMetafields,
2959
- cart
2802
+ `
2803
+ );
2804
+ const data = await client.query(query, {
2805
+ query: searchQuery,
2806
+ first,
2807
+ types
2960
2808
  });
2961
- const plusMemberVariant = react.useMemo(() => {
2962
- if (!selectedPlusMemberVariant || selectedPlusMemberMode === "free" /* FREE */) {
2963
- return void 0;
2964
- }
2965
- if (selectedPlusMemberMode === "monthly" /* MONTHLY */ && hasMonthlyPlus) {
2966
- return void 0;
2967
- }
2968
- if (selectedPlusMemberMode === "annual" /* ANNUAL */ && hasAnnualPlus) {
2969
- return void 0;
2970
- }
2971
- if (profile?.isMonthlyPlus && selectedPlusMemberMode === "monthly" /* MONTHLY */) {
2972
- return void 0;
2973
- }
2974
- if (profile?.isAnnualPlus && selectedPlusMemberMode === "annual" /* ANNUAL */) {
2975
- return void 0;
2809
+ if (!data || !data.search) {
2810
+ return void 0;
2811
+ }
2812
+ const items = data.search.edges?.map((edge) => {
2813
+ const node = edge.node;
2814
+ const item = {
2815
+ type: node.__typename.toUpperCase(),
2816
+ id: node.id,
2817
+ handle: node.handle,
2818
+ title: node.title
2819
+ };
2820
+ if (node.__typename === "Product") {
2821
+ item.description = node.description;
2822
+ item.image = node.featuredImage ? {
2823
+ url: node.featuredImage.url,
2824
+ altText: node.featuredImage.altText
2825
+ } : void 0;
2826
+ } else if (node.__typename === "Article") {
2827
+ item.description = node.excerpt;
2828
+ item.image = node.image ? {
2829
+ url: node.image.url,
2830
+ altText: node.image.altText
2831
+ } : void 0;
2976
2832
  }
2977
- return selectedPlusMemberVariant;
2978
- }, [selectedPlusMemberMode, selectedPlusMemberVariant, hasMonthlyPlus, hasAnnualPlus]);
2979
- return plusMemberVariant;
2833
+ return item;
2834
+ }) || [];
2835
+ return {
2836
+ items,
2837
+ totalCount: data.search.totalCount || 0,
2838
+ pageInfo: data.search.pageInfo
2839
+ };
2980
2840
  }
2981
- var PlusMemberProvider = ({
2982
- variant,
2983
- product,
2984
- memberSetting,
2985
- initialSelectedPlusMemberMode = "free",
2986
- profile,
2987
- children
2988
- }) => {
2989
- const { locale } = useShopify();
2990
- const [zipCode, setZipCode] = react.useState("");
2991
- const [showTip, setShowTip] = react.useState(false);
2992
- const [selectedPlusMemberMode, setSelectedPlusMemberMode] = react.useState(
2993
- initialSelectedPlusMemberMode
2841
+ function useSearch(options = {}) {
2842
+ const { client, locale } = useShopify();
2843
+ const { query, first = 20, types = ["PRODUCT", "ARTICLE", "PAGE"], ...swrOptions } = options;
2844
+ return useSWR__default.default(
2845
+ query ? ["search", locale, query, first, types] : null,
2846
+ () => performSearch(client, locale, query, first, types),
2847
+ swrOptions
2994
2848
  );
2995
- const [selectedShippingMethod, setSelectedShippingMethod] = react.useState();
2996
- const [allowNextDayDelivery, setAllowNextDayDelivery] = react.useState(false);
2997
- const [allowThirdDayDelivery, setAllowThirdDayDelivery] = react.useState(false);
2998
- const [showAreaCheckModal, setShowAreaCheckModal] = react.useState(false);
2999
- const [showMoreShippingMethod, setShowMoreShippingMethod] = react.useState(false);
3000
- const [showPlusMemberBenefit, setShowPlusMemberBenefit] = react.useState(false);
3001
- const [deleteMarginBottom, setDeleteMarginBottom] = react.useState(false);
3002
- const shippingMethodsContext = useShippingMethods({
3003
- variant,
3004
- plusMemberMetafields: memberSetting,
3005
- selectedPlusMemberMode,
3006
- profile,
3007
- isPlus: profile?.isPlus || false
3008
- });
3009
- const { monthlyVariant, annualVariant } = usePlusMemberVariants({
3010
- memberSetting
3011
- });
3012
- const selectedPlusMemberVariant = react.useMemo(() => {
3013
- if (selectedPlusMemberMode === "free" /* FREE */) {
3014
- return void 0;
2849
+ }
2850
+ async function getSiteInfo(client, locale, metafieldIdentifiers) {
2851
+ const hasMetafields = metafieldIdentifiers && metafieldIdentifiers.length > 0;
2852
+ const query = (
2853
+ /* GraphQL */
2854
+ `
2855
+ query getSiteInfo(
2856
+ ${hasMetafields ? "$shopMetafieldIdentifiers: [HasMetafieldsIdentifier!]!" : ""}
2857
+ ) @inContext(language: $language) {
2858
+ shop {
2859
+ name
2860
+ description
2861
+ primaryDomain {
2862
+ url
2863
+ host
2864
+ }
2865
+ brand {
2866
+ logo {
2867
+ image {
2868
+ url
2869
+ }
2870
+ }
2871
+ colors {
2872
+ primary {
2873
+ background
2874
+ }
2875
+ secondary {
2876
+ background
2877
+ }
2878
+ }
2879
+ }
2880
+ ${hasMetafields ? "metafields(identifiers: $shopMetafieldIdentifiers) { key value }" : ""}
2881
+ }
3015
2882
  }
3016
- return selectedPlusMemberMode === "monthly" /* MONTHLY */ ? monthlyVariant : annualVariant;
3017
- }, [monthlyVariant, annualVariant, selectedPlusMemberMode]);
3018
- return /* @__PURE__ */ jsxRuntime.jsx(
3019
- PlusMemberContext.Provider,
3020
- {
3021
- value: {
3022
- variant,
3023
- zipCode,
3024
- setZipCode,
3025
- allowNextDayDelivery,
3026
- setAllowNextDayDelivery,
3027
- allowThirdDayDelivery,
3028
- setAllowThirdDayDelivery,
3029
- plusMemberMetafields: memberSetting,
3030
- selectedPlusMemberMode,
3031
- setSelectedPlusMemberMode,
3032
- showAreaCheckModal,
3033
- setShowAreaCheckModal,
3034
- selectedShippingMethod,
3035
- setSelectedShippingMethod,
3036
- shippingMethodsContext,
3037
- showTip,
3038
- setShowTip,
3039
- showMoreShippingMethod,
3040
- setShowMoreShippingMethod,
3041
- selectedPlusMemberVariant,
3042
- monthlyVariant,
3043
- annualVariant,
3044
- product,
3045
- showPlusMemberBenefit,
3046
- setShowPlusMemberBenefit,
3047
- deleteMarginBottom,
3048
- setDeleteMarginBottom,
3049
- profile,
3050
- locale
3051
- },
3052
- children
2883
+ `
2884
+ );
2885
+ const variables = {};
2886
+ if (hasMetafields) {
2887
+ variables.shopMetafieldIdentifiers = metafieldIdentifiers;
2888
+ }
2889
+ const data = await client.query(query, variables);
2890
+ if (!data || !data.shop) {
2891
+ return void 0;
2892
+ }
2893
+ const shop = data.shop;
2894
+ const metafields = shop.metafields?.reduce((acc, mf) => {
2895
+ if (mf && mf.key) {
2896
+ acc[mf.key] = mf.value;
3053
2897
  }
2898
+ return acc;
2899
+ }, {});
2900
+ return {
2901
+ name: shop.name,
2902
+ description: shop.description,
2903
+ primaryDomain: shop.primaryDomain,
2904
+ brand: shop.brand ? {
2905
+ logo: shop.brand.logo,
2906
+ colors: shop.brand.colors ? {
2907
+ primary: shop.brand.colors.primary?.background,
2908
+ secondary: shop.brand.colors.secondary?.background
2909
+ } : void 0
2910
+ } : void 0,
2911
+ metafields
2912
+ };
2913
+ }
2914
+ function useSite(options = {}) {
2915
+ const { client, locale } = useShopify();
2916
+ const { metafieldIdentifiers, ...swrOptions } = options;
2917
+ return useSWR__default.default(
2918
+ ["site", locale, metafieldIdentifiers],
2919
+ () => getSiteInfo(client, locale, metafieldIdentifiers),
2920
+ swrOptions
3054
2921
  );
3055
- };
2922
+ }
3056
2923
  function useIntersection(targetRef, options) {
3057
2924
  const {
3058
2925
  callback,
@@ -3260,10 +3127,14 @@ exports.defaultSWRMutationConfiguration = defaultSWRMutationConfiguration;
3260
3127
  exports.formatFunctionAutoFreeGift = formatFunctionAutoFreeGift;
3261
3128
  exports.formatScriptAutoFreeGift = formatScriptAutoFreeGift;
3262
3129
  exports.getCachedGeoLocation = getCachedGeoLocation;
3130
+ exports.getCartAttributes = getCartAttributes;
3263
3131
  exports.getDiscountEnvAttributeValue = getDiscountEnvAttributeValue;
3264
3132
  exports.getMatchedMainProductSubTotal = getMatchedMainProductSubTotal;
3265
3133
  exports.getQuery = getQuery;
3266
3134
  exports.getReferralAttributes = getReferralAttributes;
3135
+ exports.getUserType = getUserType;
3136
+ exports.hasPlusMemberInCart = hasPlusMemberInCart;
3137
+ exports.hasPlusMemberInLines = hasPlusMemberInLines;
3267
3138
  exports.normalizeAddToCartLines = normalizeAddToCartLines;
3268
3139
  exports.preCheck = preCheck;
3269
3140
  exports.safeParse = safeParse;
@@ -3291,11 +3162,10 @@ exports.useCreateCart = useCreateCart;
3291
3162
  exports.useExposure = useExposure;
3292
3163
  exports.useGeoLocation = useGeoLocation;
3293
3164
  exports.useHasPlusMemberInCart = useHasPlusMemberInCart;
3165
+ exports.useHasPlusMemberInLines = useHasPlusMemberInLines;
3294
3166
  exports.useIntersection = useIntersection;
3295
3167
  exports.usePlusMemberCheckoutCustomAttributes = usePlusMemberCheckoutCustomAttributes;
3296
3168
  exports.usePlusMemberContext = usePlusMemberContext;
3297
- exports.usePlusMemberDeliveryCodes = usePlusMemberDeliveryCodes;
3298
- exports.usePlusMemberItemCustomAttributes = usePlusMemberItemCustomAttributes;
3299
3169
  exports.usePlusMemberNeedAddToCart = usePlusMemberNeedAddToCart;
3300
3170
  exports.usePlusMemberVariants = usePlusMemberVariants;
3301
3171
  exports.usePrice = usePrice;
@@ -3308,13 +3178,11 @@ exports.useReplaceCartPlusMember = useReplaceCartPlusMember;
3308
3178
  exports.useScriptAutoFreeGift = useScriptAutoFreeGift;
3309
3179
  exports.useSearch = useSearch;
3310
3180
  exports.useSelectedOptions = useSelectedOptions;
3311
- exports.useShippingMethodAvailableCheck = useShippingMethodAvailableCheck;
3312
3181
  exports.useShippingMethods = useShippingMethods;
3313
3182
  exports.useSite = useSite;
3314
3183
  exports.useUpdateCartAttributes = useUpdateCartAttributes;
3315
3184
  exports.useUpdateCartLines = useUpdateCartLines;
3316
3185
  exports.useUpdateLineCodeAmountAttributes = useUpdateLineCodeAmountAttributes;
3317
- exports.useUpdatePlusMemberDeliveryOptions = useUpdatePlusMemberDeliveryOptions;
3318
3186
  exports.useUpdateVariantQuery = useUpdateVariantQuery;
3319
3187
  exports.useVariant = useVariant;
3320
3188
  exports.useVariantMedia = useVariantMedia;