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