@fluid-app/portal-sdk 0.1.246 → 0.1.248

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.
Files changed (112) hide show
  1. package/dist/{FluidProvider-CNk1Y2k1.mjs → FluidProvider-Bwg1cGSY.mjs} +177 -5
  2. package/dist/FluidProvider-Bwg1cGSY.mjs.map +1 -0
  3. package/dist/{FluidProvider-o1Gu53TN.cjs → FluidProvider-DprqXNu4.cjs} +188 -4
  4. package/dist/FluidProvider-DprqXNu4.cjs.map +1 -0
  5. package/dist/{MessagingScreen-BwI0RShj.cjs → MessagingScreen-BKb4mWGa.cjs} +2 -2
  6. package/dist/{MessagingScreen-WCeHWGlX.cjs → MessagingScreen-CDiLGmMi.cjs} +2 -2
  7. package/dist/{MessagingScreen-WCeHWGlX.cjs.map → MessagingScreen-CDiLGmMi.cjs.map} +1 -1
  8. package/dist/{MessagingScreen-DiSZ7fyd.mjs → MessagingScreen-DGhqsVXi.mjs} +2 -2
  9. package/dist/{MessagingScreen-DiSZ7fyd.mjs.map → MessagingScreen-DGhqsVXi.mjs.map} +1 -1
  10. package/dist/{ProfileScreen-BfvdQa0q.cjs → ProfileScreen-BDLJgcXg.cjs} +2 -2
  11. package/dist/{ProfileScreen-BfvdQa0q.cjs.map → ProfileScreen-BDLJgcXg.cjs.map} +1 -1
  12. package/dist/{ProfileScreen-CRLf8oDe.mjs → ProfileScreen-CmQDKNaP.mjs} +2 -2
  13. package/dist/{ProfileScreen-CRLf8oDe.mjs.map → ProfileScreen-CmQDKNaP.mjs.map} +1 -1
  14. package/dist/{ProfileScreen-Za3ZIWPO.cjs → ProfileScreen-DHv2Cjpz.cjs} +2 -2
  15. package/dist/{ShopScreen-S6rBaoWM.cjs → ShopScreen---dB03HI.cjs} +282 -63
  16. package/dist/ShopScreen---dB03HI.cjs.map +1 -0
  17. package/dist/{ShopScreen-BigHJ5wE.cjs → ShopScreen-B6ygTHDB.cjs} +2 -2
  18. package/dist/{ShopScreen-BG1pxd2D.mjs → ShopScreen-kiVwC38W.mjs} +283 -64
  19. package/dist/ShopScreen-kiVwC38W.mjs.map +1 -0
  20. package/dist/de-CqKH8kwp.cjs +12 -0
  21. package/dist/de-CqKH8kwp.cjs.map +1 -0
  22. package/dist/de-DWONEOZS.mjs +6 -0
  23. package/dist/de-DWONEOZS.mjs.map +1 -0
  24. package/dist/el-CIrAhB-W.cjs +12 -0
  25. package/dist/el-CIrAhB-W.cjs.map +1 -0
  26. package/dist/el-De7Ne7it.mjs +6 -0
  27. package/dist/el-De7Ne7it.mjs.map +1 -0
  28. package/dist/es-4Wsa13tV.cjs +12 -0
  29. package/dist/es-4Wsa13tV.cjs.map +1 -0
  30. package/dist/es-B5_ItPIn.mjs +6 -0
  31. package/dist/es-B5_ItPIn.mjs.map +1 -0
  32. package/dist/fr-BDKPrKKW.cjs +12 -0
  33. package/dist/fr-BDKPrKKW.cjs.map +1 -0
  34. package/dist/fr-jgEDP2og.mjs +6 -0
  35. package/dist/fr-jgEDP2og.mjs.map +1 -0
  36. package/dist/he-5dq6lV2h.cjs +12 -0
  37. package/dist/he-5dq6lV2h.cjs.map +1 -0
  38. package/dist/he-DLQdVr_g.mjs +6 -0
  39. package/dist/he-DLQdVr_g.mjs.map +1 -0
  40. package/dist/hu-CC4QdkPb.mjs +6 -0
  41. package/dist/hu-CC4QdkPb.mjs.map +1 -0
  42. package/dist/hu-Dpgriy5N.cjs +12 -0
  43. package/dist/hu-Dpgriy5N.cjs.map +1 -0
  44. package/dist/id-Ba-0RT7y.cjs +12 -0
  45. package/dist/id-Ba-0RT7y.cjs.map +1 -0
  46. package/dist/id-CwGC2v1d.mjs +6 -0
  47. package/dist/id-CwGC2v1d.mjs.map +1 -0
  48. package/dist/index.cjs +50 -14
  49. package/dist/index.cjs.map +1 -1
  50. package/dist/index.d.cts +1 -8
  51. package/dist/index.d.cts.map +1 -1
  52. package/dist/index.d.mts +1 -8
  53. package/dist/index.d.mts.map +1 -1
  54. package/dist/index.mjs +51 -15
  55. package/dist/index.mjs.map +1 -1
  56. package/dist/it-CaxIV-R4.cjs +12 -0
  57. package/dist/it-CaxIV-R4.cjs.map +1 -0
  58. package/dist/it-jUZZ5sjO.mjs +6 -0
  59. package/dist/it-jUZZ5sjO.mjs.map +1 -0
  60. package/dist/ja-Lcg_Qqtj.cjs +12 -0
  61. package/dist/ja-Lcg_Qqtj.cjs.map +1 -0
  62. package/dist/ja-QVQymwAE.mjs +6 -0
  63. package/dist/ja-QVQymwAE.mjs.map +1 -0
  64. package/dist/ko-CFu0TjJO.cjs +12 -0
  65. package/dist/ko-CFu0TjJO.cjs.map +1 -0
  66. package/dist/ko-DfzzTwZI.mjs +6 -0
  67. package/dist/ko-DfzzTwZI.mjs.map +1 -0
  68. package/dist/nl-DR9IRXGT.cjs +12 -0
  69. package/dist/nl-DR9IRXGT.cjs.map +1 -0
  70. package/dist/nl-Dys3mUo2.mjs +6 -0
  71. package/dist/nl-Dys3mUo2.mjs.map +1 -0
  72. package/dist/pl-CBwEisEK.mjs +6 -0
  73. package/dist/pl-CBwEisEK.mjs.map +1 -0
  74. package/dist/pl-DSGSRDM2.cjs +12 -0
  75. package/dist/pl-DSGSRDM2.cjs.map +1 -0
  76. package/dist/pt-D5al7xw3.mjs +6 -0
  77. package/dist/pt-D5al7xw3.mjs.map +1 -0
  78. package/dist/pt-Pz_D1HUz.cjs +12 -0
  79. package/dist/pt-Pz_D1HUz.cjs.map +1 -0
  80. package/dist/ro-B43SoGdE.mjs +6 -0
  81. package/dist/ro-B43SoGdE.mjs.map +1 -0
  82. package/dist/ro-BoGeZTac.cjs +12 -0
  83. package/dist/ro-BoGeZTac.cjs.map +1 -0
  84. package/dist/ru-Cd7LUmcu.cjs +12 -0
  85. package/dist/ru-Cd7LUmcu.cjs.map +1 -0
  86. package/dist/ru-ChwnncDc.mjs +6 -0
  87. package/dist/ru-ChwnncDc.mjs.map +1 -0
  88. package/dist/th-C9S_8Tv6.mjs +6 -0
  89. package/dist/th-C9S_8Tv6.mjs.map +1 -0
  90. package/dist/th-DwLAQd0u.cjs +12 -0
  91. package/dist/th-DwLAQd0u.cjs.map +1 -0
  92. package/dist/tl-CiPbx_5F.mjs +6 -0
  93. package/dist/tl-CiPbx_5F.mjs.map +1 -0
  94. package/dist/tl-DwAVpDyB.cjs +12 -0
  95. package/dist/tl-DwAVpDyB.cjs.map +1 -0
  96. package/dist/tr-BFbCmHQZ.cjs +12 -0
  97. package/dist/tr-BFbCmHQZ.cjs.map +1 -0
  98. package/dist/tr-CUd4dp2u.mjs +6 -0
  99. package/dist/tr-CUd4dp2u.mjs.map +1 -0
  100. package/dist/zh_CN-Cn-k18Y5.cjs +12 -0
  101. package/dist/zh_CN-Cn-k18Y5.cjs.map +1 -0
  102. package/dist/zh_CN-D46-GUTP.mjs +6 -0
  103. package/dist/zh_CN-D46-GUTP.mjs.map +1 -0
  104. package/dist/zh_TW-CIUhIeJP.cjs +12 -0
  105. package/dist/zh_TW-CIUhIeJP.cjs.map +1 -0
  106. package/dist/zh_TW-XqA7UKxt.mjs +6 -0
  107. package/dist/zh_TW-XqA7UKxt.mjs.map +1 -0
  108. package/package.json +15 -13
  109. package/dist/FluidProvider-CNk1Y2k1.mjs.map +0 -1
  110. package/dist/FluidProvider-o1Gu53TN.cjs.map +0 -1
  111. package/dist/ShopScreen-BG1pxd2D.mjs.map +0 -1
  112. package/dist/ShopScreen-S6rBaoWM.cjs.map +0 -1
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require("./chunk-9hOWP6kD.cjs");
2
- const require_FluidProvider = require("./FluidProvider-o1Gu53TN.cjs");
2
+ const require_FluidProvider = require("./FluidProvider-DprqXNu4.cjs");
3
3
  const require_src = require("./src-uhf6Szlw.cjs");
4
4
  const require_ScreenHeaderContext = require("./ScreenHeaderContext-oIu5Bvhs.cjs");
5
5
  const require_use_store = require("./use-store-D2S1FywW.cjs");
@@ -12,6 +12,26 @@ let _tanstack_react_query = require("@tanstack/react-query");
12
12
  let react_jsx_runtime = require("react/jsx-runtime");
13
13
  let lucide_react = require("lucide-react");
14
14
  let react_dom = require("react-dom");
15
+ //#region ../../platform/i18n/src/translation-api-context-factory.ts
16
+ function createTranslationContext(domainName) {
17
+ const Ctx = (0, react.createContext)(null);
18
+ function useTranslation() {
19
+ const api = (0, react.useContext)(Ctx);
20
+ if (!api) throw new Error(`use${domainName}Translation must be used within a ${domainName}TranslationProvider`);
21
+ return api;
22
+ }
23
+ return {
24
+ Context: Ctx,
25
+ Provider: Ctx.Provider,
26
+ useTranslation
27
+ };
28
+ }
29
+ //#endregion
30
+ //#region ../../shop/core/src/translation-api-context.ts
31
+ const { Provider, useTranslation } = createTranslationContext("Shop");
32
+ const ShopTranslationProvider = Provider;
33
+ const useShopTranslation = useTranslation;
34
+ //#endregion
15
35
  //#region ../../shop/ui/src/utils/media-helpers.ts
16
36
  const VIDEO_EXTENSIONS = [
17
37
  ".mp4",
@@ -73,10 +93,11 @@ function formatPortalPrice(price, currency) {
73
93
  }
74
94
  function ProductCardContent({ product, countryIso, companyLogoUrl, renderImage = defaultRenderImage$1 }) {
75
95
  const [isHovered, setIsHovered] = (0, react.useState)(false);
96
+ const { t } = useShopTranslation();
76
97
  const isPortal = isPortalProduct(product);
77
98
  const coverImage = isPortal ? getPortalProductCoverImage(product) : require_PortalProductsApiProvider.getProductImageUrl(product);
78
99
  const isVideo = isVideoUrl(coverImage);
79
- const productName = isPortal ? product.name || "No title available" : product.title || "No title available";
100
+ const productName = isPortal ? product.name || t("no_title") : product.title || t("no_title");
80
101
  let repPrice = null;
81
102
  let price = null;
82
103
  if (isPortal) if (product.wholesale_price) {
@@ -144,6 +165,15 @@ function ProductCardContent({ product, countryIso, companyLogoUrl, renderImage =
144
165
  " ",
145
166
  getVariantCountryValue(getSelectedVariant(product), countryIso, "qv") || "-"
146
167
  ]
168
+ }),
169
+ isPortal && product.wholesale_price != null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
170
+ className: "text-muted-foreground text-sm",
171
+ children: [
172
+ "CV ",
173
+ product.cv ?? "-",
174
+ " | QV ",
175
+ product.qv ?? "-"
176
+ ]
147
177
  })
148
178
  ]
149
179
  })] });
@@ -320,18 +350,18 @@ function QuantitySelector({ quantity, setQuantity }) {
320
350
  //#endregion
321
351
  //#region ../../shop/ui/src/components/purchase-options.tsx
322
352
  function PurchaseOptions({ showBuyOnce, showSubscribe, isSubscribe, onSubscribeChange, product_subscription_plans, selectedSubscriptionPlan, onSubscriptionPlanChange, userSelectedSubscribe, wholesalePrice, wholesaleSubscriptionPrice }) {
353
+ const { t } = useShopTranslation();
323
354
  const defaultSubscriptionPlan = (0, react.useMemo)(() => {
324
355
  if (!product_subscription_plans?.length) return null;
325
356
  return product_subscription_plans.find((plan) => plan.default) || product_subscription_plans[0];
326
357
  }, [product_subscription_plans]);
327
358
  const currentSubscriptionPlan = selectedSubscriptionPlan || defaultSubscriptionPlan;
328
- const savingsText = (0, react.useMemo)(() => {
359
+ const savingsPercentage = (0, react.useMemo)(() => {
329
360
  if (wholesalePrice === void 0 || wholesaleSubscriptionPrice === void 0 || wholesalePrice <= 0) return null;
330
361
  const savings = wholesalePrice - wholesaleSubscriptionPrice;
331
362
  if (savings <= 0) return null;
332
- const savingsPercentage = Math.round(savings / wholesalePrice * 100);
333
- if (savingsPercentage <= 0) return null;
334
- return `Save ${savingsPercentage}%`;
363
+ const pct = Math.round(savings / wholesalePrice * 100);
364
+ return pct > 0 ? pct : null;
335
365
  }, [wholesalePrice, wholesaleSubscriptionPrice]);
336
366
  const formatSubscriptionPlan = (plan) => {
337
367
  return `${plan.subscription_plan.billing_interval} ${plan.subscription_plan.billing_interval_unit} (${plan.subscription_plan.name})`;
@@ -365,22 +395,22 @@ function PurchaseOptions({ showBuyOnce, showSubscribe, isSubscribe, onSubscribeC
365
395
  className: `flex items-center justify-center [&_svg]:h-1.5 [&_svg]:w-1.5 [&_svg]:fill-white ${isSubscribe ? "border-contrast bg-contrast text-foreground" : "border-border bg-background text-muted-foreground"}`
366
396
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
367
397
  className: "flex-1",
368
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
398
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
369
399
  className: "text-foreground mb-1 text-sm leading-tight font-medium",
370
- children: ["Subscribe", savingsText ? ` & ${savingsText}` : ""]
400
+ children: savingsPercentage ? t("subscribe_and_save", { percentage: savingsPercentage }) : t("subscribe")
371
401
  }), product_subscription_plans?.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
372
402
  className: "bg-muted mt-3 rounded-lg p-2",
373
403
  onClick: (e) => e.stopPropagation(),
374
404
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
375
405
  className: "text-foreground mb-1 text-xs font-medium",
376
- children: "Delivery Frequency:"
406
+ children: t("delivery_frequency")
377
407
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.Select, {
378
408
  value: currentSubscriptionPlan?.subscription_plan.id.toString() || "",
379
409
  onValueChange: handleSubscriptionPlanChange,
380
410
  disabled: product_subscription_plans?.length === 1,
381
411
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectTrigger, {
382
412
  className: "bg-background text-foreground! w-full text-xs",
383
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectValue, { placeholder: "Select delivery schedule" })
413
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectValue, { placeholder: t("select_delivery_schedule") })
384
414
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectContent, { children: subscriptionPlanOptions.map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectItem, {
385
415
  value: option.value,
386
416
  children: option.label
@@ -400,7 +430,7 @@ function PurchaseOptions({ showBuyOnce, showSubscribe, isSubscribe, onSubscribeC
400
430
  className: `flex items-center justify-center [&_svg]:h-1.5 [&_svg]:w-1.5 [&_svg]:fill-white ${!isSubscribe ? "border-contrast bg-contrast text-foreground" : "border-border bg-background text-muted-foreground"}`
401
431
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
402
432
  className: "text-foreground mb-1 text-sm leading-tight font-medium",
403
- children: "One-Time Purchase"
433
+ children: t("one_time_purchase")
404
434
  })]
405
435
  })
406
436
  })]
@@ -416,32 +446,6 @@ function sanitizeHtml(html) {
416
446
  for (const el of doc.querySelectorAll("*")) for (const attr of [...el.attributes]) if (attr.name.toLowerCase().startsWith("on") || attr.value.toLowerCase().trim().startsWith("javascript:")) el.removeAttribute(attr.name);
417
447
  return doc.body.innerHTML;
418
448
  }
419
- const SORT_OPTIONS = [
420
- {
421
- id: "title_asc",
422
- label: "Title (A-Z)"
423
- },
424
- {
425
- id: "title_desc",
426
- label: "Title (Z-A)"
427
- },
428
- {
429
- id: "price_asc",
430
- label: "Price (Low to High)"
431
- },
432
- {
433
- id: "price_desc",
434
- label: "Price (High to Low)"
435
- },
436
- {
437
- id: "created_at_desc",
438
- label: "Recently Updated"
439
- },
440
- {
441
- id: "created_at_asc",
442
- label: "Oldest Updated"
443
- }
444
- ];
445
449
  const GRID_CLASS = "grid grid-cols-1 gap-8 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-4";
446
450
  function SkeletonGrid({ count = 8 }) {
447
451
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -459,6 +463,7 @@ function SkeletonGrid({ count = 8 }) {
459
463
  }
460
464
  function ProductListing({ companyLogoUrl, renderImage, onSelectProduct, cartButton }) {
461
465
  const observerTarget = (0, react.useRef)(null);
466
+ const { t } = useShopTranslation();
462
467
  const catalog = require_PortalProductsApiProvider.usePortalProductCatalog({ perPage: PAGE_SIZE });
463
468
  const { data, isLoading, isFetchingNextPage, hasNextPage, fetchNextPage, error, isFetched } = (0, _tanstack_react_query.useInfiniteQuery)({
464
469
  queryKey: catalog.queryKey,
@@ -484,6 +489,32 @@ function ProductListing({ companyLogoUrl, renderImage, onSelectProduct, cartButt
484
489
  return () => observer.disconnect();
485
490
  }, [handleIntersect]);
486
491
  const allProducts = data?.pages.flatMap((page) => page.products) ?? [];
492
+ const sortOptions = (0, react.useMemo)(() => [
493
+ {
494
+ id: "title_asc",
495
+ label: t("sort_title_asc")
496
+ },
497
+ {
498
+ id: "title_desc",
499
+ label: t("sort_title_desc")
500
+ },
501
+ {
502
+ id: "price_asc",
503
+ label: t("sort_price_asc")
504
+ },
505
+ {
506
+ id: "price_desc",
507
+ label: t("sort_price_desc")
508
+ },
509
+ {
510
+ id: "created_at_desc",
511
+ label: t("sort_recent")
512
+ },
513
+ {
514
+ id: "created_at_asc",
515
+ label: t("sort_oldest")
516
+ }
517
+ ], [t]);
487
518
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
488
519
  className: "mx-auto px-2 md:px-10",
489
520
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -494,7 +525,7 @@ function ProductListing({ companyLogoUrl, renderImage, onSelectProduct, cartButt
494
525
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_SearchSort.SearchSort, {
495
526
  searchValue: catalog.searchTerm,
496
527
  onSearchChange: catalog.setSearchTerm,
497
- placeholder: "Search products..."
528
+ placeholder: t("search_placeholder")
498
529
  })
499
530
  }),
500
531
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.DropdownMenu, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DropdownMenuTrigger, {
@@ -509,12 +540,12 @@ function ProductListing({ companyLogoUrl, renderImage, onSelectProduct, cartButt
509
540
  align: "end",
510
541
  className: "w-60",
511
542
  children: [
512
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DropdownMenuLabel, { children: "Sort By" }),
543
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DropdownMenuLabel, { children: t("sort_by") }),
513
544
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DropdownMenuSeparator, {}),
514
545
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DropdownMenuRadioGroup, {
515
546
  value: catalog.currentSort,
516
547
  onValueChange: catalog.setCurrentSort,
517
- children: SORT_OPTIONS.map((opt) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DropdownMenuRadioItem, {
548
+ children: sortOptions.map((opt) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DropdownMenuRadioItem, {
518
549
  value: opt.id,
519
550
  children: opt.label
520
551
  }, opt.id))
@@ -529,14 +560,14 @@ function ProductListing({ companyLogoUrl, renderImage, onSelectProduct, cartButt
529
560
  })
530
561
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
531
562
  className: "mx-auto space-y-8 px-2 md:px-10 md:py-8",
532
- children: isLoading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkeletonGrid, {}) : error ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
563
+ children: isLoading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkeletonGrid, {}) : error ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
533
564
  className: "mx-auto my-6 rounded-lg bg-red-100 px-3 py-2 text-red-500",
534
- children: ["Error: ", error.message]
565
+ children: t("error_generic")
535
566
  }) : isFetched && allProducts.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
536
567
  className: "flex flex-col items-center justify-center py-8 text-center",
537
568
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
538
569
  className: "text-muted-foreground text-sm",
539
- children: catalog.searchTerm ? `No products match "${catalog.searchTerm}". Try a different search term.` : "There are no products available at the moment."
570
+ children: catalog.searchTerm ? t("no_search_results", { term: catalog.searchTerm }) : t("no_products")
540
571
  })
541
572
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
542
573
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -629,11 +660,14 @@ function ProductDetail({ productId, renderImage }) {
629
660
  const [selections, setSelections] = (0, react.useState)({});
630
661
  const [userSelectedSubscribe, setUserSelectedSubscribe] = (0, react.useState)(false);
631
662
  const [selectedSubscriptionPlan, setSelectedSubscriptionPlan] = (0, react.useState)(void 0);
663
+ const { t } = useShopTranslation();
632
664
  const { product, isLoading, error, images } = require_PortalProductsApiProvider.usePortalProductDetail({ productId });
633
665
  const variants = (0, react.useMemo)(() => product?.variants ?? [], [product?.variants]);
634
666
  const subscriptionPlans = (0, react.useMemo)(() => product?.subscription_plans ?? [], [product?.subscription_plans]);
635
667
  const masterVariant = (0, react.useMemo)(() => variants.find((v) => v.is_master) ?? variants[0], [variants]);
636
668
  const optionGroups = (0, react.useMemo)(() => buildOptionGroups(variants), [variants]);
669
+ const showVariantChoices = optionGroups.length === 0 && variants.length > 1;
670
+ const [selectedVariantId, setSelectedVariantId] = (0, react.useState)(null);
637
671
  (0, react.useEffect)(() => {
638
672
  if (optionGroups.length === 0) return;
639
673
  const source = variants.find((v) => !v.is_master) ?? masterVariant;
@@ -646,14 +680,27 @@ function ProductDetail({ productId, renderImage }) {
646
680
  variants,
647
681
  masterVariant
648
682
  ]);
683
+ (0, react.useEffect)(() => {
684
+ if (!showVariantChoices) return;
685
+ if (selectedVariantId != null) return;
686
+ if (masterVariant?.id == null) return;
687
+ setSelectedVariantId(masterVariant.id);
688
+ }, [
689
+ showVariantChoices,
690
+ selectedVariantId,
691
+ masterVariant?.id
692
+ ]);
649
693
  const selectedVariant = (0, react.useMemo)(() => {
694
+ if (showVariantChoices) return variants.find((v) => v.id === selectedVariantId) ?? masterVariant;
650
695
  if (optionGroups.length === 0) return masterVariant;
651
696
  return findVariantBySelections(variants, selections) ?? masterVariant;
652
697
  }, [
653
698
  variants,
654
699
  optionGroups,
655
700
  selections,
656
- masterVariant
701
+ masterVariant,
702
+ showVariantChoices,
703
+ selectedVariantId
657
704
  ]);
658
705
  const legacySubscriptionPlans = (0, react.useMemo)(() => mapToLegacySubscriptionPlans(subscriptionPlans), [subscriptionPlans]);
659
706
  const isSubscribe = selectedVariant?.subscription_only === true || userSelectedSubscribe;
@@ -709,10 +756,10 @@ function ProductDetail({ productId, renderImage }) {
709
756
  className: "text-center",
710
757
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
711
758
  className: "text-foreground mb-2 text-lg font-medium",
712
- children: "Unable to load product"
759
+ children: t("error_loading")
713
760
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
714
761
  className: "text-muted-foreground",
715
- children: "Something went wrong. Please try again later."
762
+ children: t("error_generic")
716
763
  })]
717
764
  })
718
765
  });
@@ -722,14 +769,14 @@ function ProductDetail({ productId, renderImage }) {
722
769
  className: "text-center",
723
770
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
724
771
  className: "text-foreground mb-2 text-lg font-medium",
725
- children: "Product not found"
772
+ children: t("product_not_found")
726
773
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
727
774
  className: "text-muted-foreground",
728
- children: "The product you're looking for doesn't exist."
775
+ children: t("product_not_found_description")
729
776
  })]
730
777
  })
731
778
  });
732
- const title = product.name || "Product";
779
+ const title = product.name || t("product_fallback_name");
733
780
  const isBundle = product.bundle === true;
734
781
  const bundleUrl = isBundle && product.canonical_url ? product.canonical_url : null;
735
782
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -764,12 +811,22 @@ function ProductDetail({ productId, renderImage }) {
764
811
  className: "pt-2",
765
812
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
766
813
  className: "text-foreground mb-1 text-sm font-medium",
767
- children: "Product Description"
814
+ children: t("product_description")
768
815
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
769
816
  className: "text-foreground mb-3 text-[12px]",
770
817
  dangerouslySetInnerHTML: { __html: sanitizeHtml(product.description ?? "") }
771
818
  })]
772
819
  }),
820
+ product.wholesale_price != null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
821
+ className: "text-muted-foreground mb-3 text-sm",
822
+ children: [
823
+ "CV ",
824
+ selectedVariant?.cv ?? "-",
825
+ " | QV",
826
+ " ",
827
+ selectedVariant?.qv ?? "-"
828
+ ]
829
+ }),
773
830
  isBundle ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
774
831
  className: "pt-4",
775
832
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Button, {
@@ -779,10 +836,10 @@ function ProductDetail({ productId, renderImage }) {
779
836
  onClick: () => {
780
837
  if (bundleUrl) window.open(bundleUrl, "_blank", "noopener,noreferrer");
781
838
  },
782
- children: "Purchase Bundle"
839
+ children: t("purchase_bundle")
783
840
  }), !bundleUrl && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
784
841
  className: "text-muted-foreground mt-2 text-center text-xs",
785
- children: "Bundle configuration is unavailable. Please contact support."
842
+ children: t("bundle_unavailable")
786
843
  })]
787
844
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
788
845
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PurchaseOptions, {
@@ -812,7 +869,7 @@ function ProductDetail({ productId, renderImage }) {
812
869
  })),
813
870
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectTrigger, {
814
871
  className: "w-48 max-w-full",
815
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectValue, { placeholder: `Select ${group.name}` })
872
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectValue, { placeholder: t("select_option", { name: group.name }) })
816
873
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectContent, {
817
874
  position: "popper",
818
875
  className: "max-h-60",
@@ -824,9 +881,33 @@ function ProductDetail({ productId, renderImage }) {
824
881
  })]
825
882
  }, group.optionId))
826
883
  }),
884
+ showVariantChoices && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
885
+ className: "mb-4 pt-4",
886
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
887
+ className: "mb-3 flex items-center",
888
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
889
+ className: "text-md text-foreground w-24 font-bold",
890
+ children: "Variant"
891
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.Select, {
892
+ value: selectedVariantId != null ? String(selectedVariantId) : "",
893
+ onValueChange: (value) => setSelectedVariantId(Number(value)),
894
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectTrigger, {
895
+ className: "w-48 max-w-full",
896
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectValue, { placeholder: "Select variant" })
897
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectContent, {
898
+ position: "popper",
899
+ className: "max-h-60",
900
+ children: variants.map((v, idx) => v.id == null ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectItem, {
901
+ value: String(v.id),
902
+ children: v.title || `Variant ${idx + 1}`
903
+ }, v.id))
904
+ })]
905
+ })]
906
+ })
907
+ }),
827
908
  selectedVariant?.subscription_only && !selectedVariant?.allow_subscription && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
828
909
  className: "text-muted-foreground text-sm",
829
- children: "This product is unavailable for purchase."
910
+ children: t("product_unavailable")
830
911
  }),
831
912
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "mt-4 mb-3" }),
832
913
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -843,7 +924,7 @@ function ProductDetail({ productId, renderImage }) {
843
924
  "data-fluid-subscribe": isSubscribe,
844
925
  "data-fluid-subscription-plan-id": isSubscribe ? String(resolvedPlanId ?? "") : "",
845
926
  "data-fluid-open-cart-after-add": "false",
846
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ShoppingCart, { className: "h-4 w-4" }), isSubscribe ? "Subscribe" : "Add to Cart"]
927
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ShoppingCart, { className: "h-4 w-4" }), isSubscribe ? t("subscribe") : t("add_to_cart")]
847
928
  })]
848
929
  })
849
930
  ] })
@@ -1028,9 +1109,138 @@ function ShopContainer({ children, className = "", cartScript, cartWidget }) {
1028
1109
  }) });
1029
1110
  }
1030
1111
  //#endregion
1112
+ //#region ../../platform/i18n/src/use-domain-dict.ts
1113
+ function useDomainDict(domain, locale) {
1114
+ const [dict, setDict] = (0, react.useState)(domain.fallback);
1115
+ (0, react.useEffect)(() => {
1116
+ let cancelled = false;
1117
+ if (locale === domain.fallbackLocale) {
1118
+ setDict(domain.fallback);
1119
+ return;
1120
+ }
1121
+ setDict(domain.fallback);
1122
+ domain.load(locale).then((next) => {
1123
+ if (!cancelled) setDict(next);
1124
+ }).catch(() => {
1125
+ if (!cancelled) setDict(domain.fallback);
1126
+ });
1127
+ return () => {
1128
+ cancelled = true;
1129
+ };
1130
+ }, [domain, locale]);
1131
+ return dict;
1132
+ }
1133
+ //#endregion
1134
+ //#region ../../platform/i18n/src/translations.ts
1135
+ function createDomainTranslations(config) {
1136
+ const fallbackLocale = config.fallbackLocale ?? "en";
1137
+ return {
1138
+ fallback: config.fallback,
1139
+ fallbackLocale,
1140
+ async load(locale) {
1141
+ if (locale === fallbackLocale) return config.fallback;
1142
+ const loader = config.loaders?.[locale];
1143
+ if (!loader) return config.fallback;
1144
+ const target = await loader();
1145
+ return {
1146
+ ...config.fallback,
1147
+ ...target
1148
+ };
1149
+ }
1150
+ };
1151
+ }
1152
+ //#endregion
1153
+ //#region ../../platform/i18n/src/static-dict-adapter.ts
1154
+ function createStaticDictAdapter(locale, dict) {
1155
+ return {
1156
+ locale,
1157
+ t(key, ...args) {
1158
+ const template = dict[key] ?? key;
1159
+ const params = args[0];
1160
+ if (!params) return template;
1161
+ return template.replace(/\{\{(\w+)\}\}/g, (match, name) => name in params ? String(params[name]) : match);
1162
+ }
1163
+ };
1164
+ }
1165
+ //#endregion
1166
+ //#region ../../shop/core/src/translation-adapter.ts
1167
+ const shopDomain = createDomainTranslations({
1168
+ fallback: {
1169
+ breadcrumb: "Shop",
1170
+ product_fallback_name: "Product",
1171
+ search_placeholder: "Search products...",
1172
+ sort_by: "Sort By",
1173
+ sort_title_asc: "Title (A-Z)",
1174
+ sort_title_desc: "Title (Z-A)",
1175
+ sort_price_asc: "Price (Low to High)",
1176
+ sort_price_desc: "Price (High to Low)",
1177
+ sort_recent: "Recently Updated",
1178
+ sort_oldest: "Oldest Updated",
1179
+ no_products: "There are no products available at the moment.",
1180
+ no_search_results: "No products match \"{{term}}\". Try a different search term.",
1181
+ error_loading: "Unable to load product",
1182
+ error_generic: "Something went wrong. Please try again later.",
1183
+ product_not_found: "Product not found",
1184
+ product_not_found_description: "The product you're looking for doesn't exist.",
1185
+ product_description: "Product Description",
1186
+ no_title: "No title available",
1187
+ add_to_cart: "Add to Cart",
1188
+ subscribe: "Subscribe",
1189
+ subscribe_and_save: "Subscribe & Save {{percentage}}%",
1190
+ one_time_purchase: "One-Time Purchase",
1191
+ delivery_frequency: "Delivery Frequency:",
1192
+ select_delivery_schedule: "Select delivery schedule",
1193
+ purchase_bundle: "Purchase Bundle",
1194
+ bundle_unavailable: "Bundle configuration is unavailable. Please contact support.",
1195
+ product_unavailable: "This product is unavailable for purchase.",
1196
+ ratings_and_reviews: "Ratings and reviews",
1197
+ ratings_count: "{{count}} ratings",
1198
+ select_option: "Select {{name}}"
1199
+ },
1200
+ loaders: {
1201
+ de: () => Promise.resolve().then(() => require("./de-CqKH8kwp.cjs")).then((m) => m.default),
1202
+ el: () => Promise.resolve().then(() => require("./el-CIrAhB-W.cjs")).then((m) => m.default),
1203
+ es: () => Promise.resolve().then(() => require("./es-4Wsa13tV.cjs")).then((m) => m.default),
1204
+ fr: () => Promise.resolve().then(() => require("./fr-BDKPrKKW.cjs")).then((m) => m.default),
1205
+ he: () => Promise.resolve().then(() => require("./he-5dq6lV2h.cjs")).then((m) => m.default),
1206
+ hu: () => Promise.resolve().then(() => require("./hu-Dpgriy5N.cjs")).then((m) => m.default),
1207
+ id: () => Promise.resolve().then(() => require("./id-Ba-0RT7y.cjs")).then((m) => m.default),
1208
+ it: () => Promise.resolve().then(() => require("./it-CaxIV-R4.cjs")).then((m) => m.default),
1209
+ ja: () => Promise.resolve().then(() => require("./ja-Lcg_Qqtj.cjs")).then((m) => m.default),
1210
+ ko: () => Promise.resolve().then(() => require("./ko-CFu0TjJO.cjs")).then((m) => m.default),
1211
+ nl: () => Promise.resolve().then(() => require("./nl-DR9IRXGT.cjs")).then((m) => m.default),
1212
+ pl: () => Promise.resolve().then(() => require("./pl-DSGSRDM2.cjs")).then((m) => m.default),
1213
+ pt: () => Promise.resolve().then(() => require("./pt-Pz_D1HUz.cjs")).then((m) => m.default),
1214
+ ro: () => Promise.resolve().then(() => require("./ro-BoGeZTac.cjs")).then((m) => m.default),
1215
+ ru: () => Promise.resolve().then(() => require("./ru-Cd7LUmcu.cjs")).then((m) => m.default),
1216
+ th: () => Promise.resolve().then(() => require("./th-DwLAQd0u.cjs")).then((m) => m.default),
1217
+ tl: () => Promise.resolve().then(() => require("./tl-DwAVpDyB.cjs")).then((m) => m.default),
1218
+ tr: () => Promise.resolve().then(() => require("./tr-BFbCmHQZ.cjs")).then((m) => m.default),
1219
+ zh_CN: () => Promise.resolve().then(() => require("./zh_CN-Cn-k18Y5.cjs")).then((m) => m.default),
1220
+ zh_TW: () => Promise.resolve().then(() => require("./zh_TW-CIUhIeJP.cjs")).then((m) => m.default)
1221
+ }
1222
+ });
1223
+ function createShopTranslationAdapter(locale, dict) {
1224
+ return createStaticDictAdapter(locale, dict);
1225
+ }
1226
+ //#endregion
1227
+ //#region src/providers/ShopTranslationBridge.tsx
1228
+ function ShopTranslationBridge({ children }) {
1229
+ const { locale } = require_FluidProvider.useActiveLocale();
1230
+ const dict = useDomainDict(shopDomain, locale);
1231
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShopTranslationProvider, {
1232
+ value: (0, react.useMemo)(() => createShopTranslationAdapter(locale, dict), [locale, dict]),
1233
+ children
1234
+ });
1235
+ }
1236
+ //#endregion
1031
1237
  //#region src/screens/ShopScreen.tsx
1032
- function ShopScreen({ background, textColor, accentColor, padding, borderRadius, ...divProps }) {
1238
+ function ShopScreen(props) {
1239
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShopTranslationBridge, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShopScreenContent, { ...props }) });
1240
+ }
1241
+ function ShopScreenContent({ background, textColor, accentColor, padding, borderRadius, ...divProps }) {
1033
1242
  const { config } = require_FluidProvider.useFluidContext();
1243
+ const { t } = useShopTranslation();
1034
1244
  const { data: store } = require_use_store.useStore();
1035
1245
  const { currentSlug, navigate } = require_AppNavigationContext.useAppNavigation();
1036
1246
  const countryCode = config.countryIso ?? "US";
@@ -1041,12 +1251,16 @@ function ShopScreen({ background, textColor, accentColor, padding, borderRadius,
1041
1251
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.BreadcrumbItem, { children: productId ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.BreadcrumbLink, {
1042
1252
  onClick: () => navigate("shop"),
1043
1253
  className: "cursor-pointer font-semibold",
1044
- children: "Shop"
1254
+ children: t("breadcrumb")
1045
1255
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.BreadcrumbPage, {
1046
1256
  className: "font-semibold",
1047
- children: "Shop"
1257
+ children: t("breadcrumb")
1048
1258
  }) })
1049
- }) }), [productId, navigate]));
1259
+ }) }), [
1260
+ productId,
1261
+ navigate,
1262
+ t
1263
+ ]));
1050
1264
  require_ScreenHeaderContext.useScreenHeaderActions((0, react.useMemo)(() => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1051
1265
  className: "flex items-center gap-4",
1052
1266
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CartButton, {})
@@ -1120,15 +1334,16 @@ const shopScreenPropertySchema = {
1120
1334
  */
1121
1335
  function ProductBreadcrumb({ productId }) {
1122
1336
  const { navigate } = require_AppNavigationContext.useAppNavigation();
1337
+ const { t } = useShopTranslation();
1123
1338
  const { product } = require_PortalProductsApiProvider.usePortalProductDetail({ productId });
1124
- const productName = product?.name ?? "Product";
1339
+ const productName = product?.name ?? t("product_fallback_name");
1125
1340
  require_ScreenHeaderContext.useScreenHeaderBreadcrumbs((0, react.useMemo)(() => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Breadcrumb, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.BreadcrumbList, {
1126
1341
  className: "text-lg",
1127
1342
  children: [
1128
1343
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.BreadcrumbItem, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.BreadcrumbLink, {
1129
1344
  onClick: () => navigate("shop"),
1130
1345
  className: "cursor-pointer font-semibold",
1131
- children: "Shop"
1346
+ children: t("breadcrumb")
1132
1347
  }) }),
1133
1348
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.BreadcrumbSeparator, {}),
1134
1349
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.BreadcrumbItem, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.BreadcrumbPage, {
@@ -1136,7 +1351,11 @@ function ProductBreadcrumb({ productId }) {
1136
1351
  children: productName
1137
1352
  }) })
1138
1353
  ]
1139
- }) }), [productName, navigate]));
1354
+ }) }), [
1355
+ productName,
1356
+ navigate,
1357
+ t
1358
+ ]));
1140
1359
  return null;
1141
1360
  }
1142
1361
  //#endregion
@@ -1153,4 +1372,4 @@ Object.defineProperty(exports, "shopScreenPropertySchema", {
1153
1372
  }
1154
1373
  });
1155
1374
 
1156
- //# sourceMappingURL=ShopScreen-S6rBaoWM.cjs.map
1375
+ //# sourceMappingURL=ShopScreen---dB03HI.cjs.map