@mohasinac/appkit 2.7.55 → 2.7.57

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 (276) hide show
  1. package/dist/_internal/shared/actions/action-registry.js +31 -5
  2. package/dist/client.d.ts +1 -3
  3. package/dist/client.js +1 -2
  4. package/dist/constants/field-names.d.ts +3 -0
  5. package/dist/constants/field-names.js +3 -0
  6. package/dist/features/about/components/FAQPageView.js +2 -2
  7. package/dist/features/about/components/FeesView.js +1 -1
  8. package/dist/features/about/components/PolicyPageView.js +1 -1
  9. package/dist/features/about/components/PublicProfileView.js +1 -1
  10. package/dist/features/account/components/AddressesIndexListing.js +1 -1
  11. package/dist/features/account/components/MessagesView.js +1 -1
  12. package/dist/features/account/components/NotificationPreferencesPanel.js +12 -3
  13. package/dist/features/account/components/UserOffersPanel.js +2 -2
  14. package/dist/features/account/components/UserSidebar.js +3 -3
  15. package/dist/features/account/components/UserSupportView.js +1 -1
  16. package/dist/features/admin/components/AdminAllEventEntriesView.js +1 -1
  17. package/dist/features/admin/components/AdminBidsView.js +5 -1
  18. package/dist/features/admin/components/AdminBlogView.js +6 -1
  19. package/dist/features/admin/components/AdminBrandsView.js +6 -1
  20. package/dist/features/admin/components/AdminBundleEditorView.js +13 -9
  21. package/dist/features/admin/components/AdminBundlesView.js +3 -1
  22. package/dist/features/admin/components/AdminCarouselEditorView.js +7 -8
  23. package/dist/features/admin/components/AdminCarouselView.js +4 -2
  24. package/dist/features/admin/components/AdminCartsView.js +1 -1
  25. package/dist/features/admin/components/AdminCategoriesView.js +6 -1
  26. package/dist/features/admin/components/AdminContactView.js +3 -1
  27. package/dist/features/admin/components/AdminCouponsView.js +4 -2
  28. package/dist/features/admin/components/AdminEmployeeEditorView.js +1 -1
  29. package/dist/features/admin/components/AdminFaqsView.js +3 -1
  30. package/dist/features/admin/components/AdminFeatureFlagsView.js +1 -1
  31. package/dist/features/admin/components/AdminFeaturesView.js +4 -0
  32. package/dist/features/admin/components/AdminMediaView.js +10 -5
  33. package/dist/features/admin/components/AdminNavigationView.js +1 -1
  34. package/dist/features/admin/components/AdminNewsletterView.js +3 -1
  35. package/dist/features/admin/components/AdminNotificationsView.js +6 -1
  36. package/dist/features/admin/components/AdminOrdersView.js +10 -1
  37. package/dist/features/admin/components/AdminPayoutsView.js +5 -1
  38. package/dist/features/admin/components/AdminPrizeDrawsView.js +4 -0
  39. package/dist/features/admin/components/AdminProductsView.js +13 -1
  40. package/dist/features/admin/components/AdminReviewsView.js +6 -1
  41. package/dist/features/admin/components/AdminScammersView.js +1 -1
  42. package/dist/features/admin/components/AdminSectionsView.js +1 -1
  43. package/dist/features/admin/components/AdminSessionsView.js +5 -1
  44. package/dist/features/admin/components/AdminSidebar.js +3 -3
  45. package/dist/features/admin/components/AdminSiteSettingsView.js +1 -1
  46. package/dist/features/admin/components/AdminStoreEditorView.js +1 -1
  47. package/dist/features/admin/components/AdminStoresView.js +6 -1
  48. package/dist/features/admin/components/AdminSublistingCategoriesView.js +2 -0
  49. package/dist/features/admin/components/AdminSupportTicketDetailView.js +1 -1
  50. package/dist/features/admin/components/AdminSupportTicketsView.js +1 -1
  51. package/dist/features/admin/components/AdminTeamView.js +3 -1
  52. package/dist/features/admin/components/AdminUserEditorView.js +1 -1
  53. package/dist/features/admin/components/AdminUsersView.js +5 -1
  54. package/dist/features/admin/components/AdminViewCards.js +2 -2
  55. package/dist/features/admin/constants/filter-tabs.d.ts +9 -0
  56. package/dist/features/admin/constants/filter-tabs.js +3 -0
  57. package/dist/features/auctions/components/AuctionBottomActions.d.ts +7 -0
  58. package/dist/features/auctions/components/AuctionBottomActions.js +24 -0
  59. package/dist/features/auctions/components/AuctionDetailPageView.js +7 -7
  60. package/dist/features/auctions/components/AuctionsListView.js +1 -1
  61. package/dist/features/auctions/components/MarketplaceAuctionGrid.js +1 -1
  62. package/dist/features/auctions/components/PlaceBidFormClient.js +1 -1
  63. package/dist/features/auth/components/LoginForm.js +1 -1
  64. package/dist/features/auth/components/VerifyEmailView.js +2 -2
  65. package/dist/features/before-after/components/BeforeAfterGallery.js +1 -1
  66. package/dist/features/blog/components/BlogFeaturedCard.js +1 -1
  67. package/dist/features/blog/components/BlogIndexListing.js +1 -1
  68. package/dist/features/blog/components/BlogListView.js +2 -2
  69. package/dist/features/blog/components/BlogPostView.js +8 -8
  70. package/dist/features/cart/components/CartDrawer.js +1 -1
  71. package/dist/features/cart/repository/cart.repository.js +11 -4
  72. package/dist/features/cart/schemas/firestore.d.ts +3 -0
  73. package/dist/features/categories/components/BrandDetailPageView.js +1 -1
  74. package/dist/features/categories/components/CategoriesIndexListing.js +1 -1
  75. package/dist/features/categories/components/CategoryDetailPageView.js +39 -3
  76. package/dist/features/categories/components/CategoryDetailTabs.d.ts +4 -1
  77. package/dist/features/categories/components/CategoryDetailTabs.js +7 -2
  78. package/dist/features/categories/components/CategoryGrid.js +1 -1
  79. package/dist/features/categories/components/CategoryProductsView.js +1 -1
  80. package/dist/features/categories/components/CategoryStoresListing.d.ts +5 -0
  81. package/dist/features/categories/components/CategoryStoresListing.js +11 -0
  82. package/dist/features/categories/components/CategoryTableColumns.js +2 -2
  83. package/dist/features/categories/components/CategoryTree.js +1 -1
  84. package/dist/features/categories/components/index.d.ts +2 -0
  85. package/dist/features/categories/components/index.js +1 -0
  86. package/dist/features/checkout/components/CheckoutStepper.js +1 -1
  87. package/dist/features/classified/components/ClassifiedIndexListing.js +2 -0
  88. package/dist/features/classified/components/ClassifiedListView.js +1 -1
  89. package/dist/features/contact/components/ContactInfoSidebar.js +1 -1
  90. package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +2 -0
  91. package/dist/features/digital-codes/components/DigitalCodesListView.js +1 -1
  92. package/dist/features/events/components/AdminEventsView.js +5 -1
  93. package/dist/features/events/components/EventCard.js +1 -1
  94. package/dist/features/events/components/EventPollWidget.js +1 -1
  95. package/dist/features/events/components/EventStatusBadge.js +5 -5
  96. package/dist/features/events/components/EventsIndexListing.js +1 -1
  97. package/dist/features/events/components/EventsListView.js +2 -2
  98. package/dist/features/events/components/SpinWheelView.js +4 -2
  99. package/dist/features/filters/AsyncFacetSection.js +3 -3
  100. package/dist/features/filters/FilterFacetSection.js +5 -5
  101. package/dist/features/filters/RangeFilter.js +1 -1
  102. package/dist/features/forms/Input.js +2 -2
  103. package/dist/features/forms/Select.js +1 -1
  104. package/dist/features/forms/Slider.js +1 -1
  105. package/dist/features/forms/Textarea.js +1 -1
  106. package/dist/features/forms/utils.d.ts +1 -1
  107. package/dist/features/forms/utils.js +1 -1
  108. package/dist/features/history/hooks/useHistory.js +23 -10
  109. package/dist/features/homepage/components/AdvertisementBanner.js +2 -2
  110. package/dist/features/homepage/components/FeaturedResultsSection.js +1 -1
  111. package/dist/features/homepage/components/HeroSection.js +1 -1
  112. package/dist/features/homepage/components/NewsletterSection.js +1 -1
  113. package/dist/features/homepage/components/SectionCarousel.js +1 -1
  114. package/dist/features/live/components/LiveItemsIndexListing.js +2 -0
  115. package/dist/features/live/components/LiveItemsListView.js +1 -1
  116. package/dist/features/orders/components/OrdersList.js +12 -12
  117. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +1 -1
  118. package/dist/features/pre-orders/components/PreOrderActionsClient.js +1 -1
  119. package/dist/features/pre-orders/components/PreOrderBadge.js +5 -5
  120. package/dist/features/pre-orders/components/PreOrderBottomActions.d.ts +5 -0
  121. package/dist/features/pre-orders/components/PreOrderBottomActions.js +22 -0
  122. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +5 -5
  123. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +47 -0
  124. package/dist/features/pre-orders/components/PreOrdersListView.js +1 -1
  125. package/dist/features/pre-orders/components/PreorderCard.js +3 -3
  126. package/dist/features/products/components/AuctionsIndexListing.js +23 -0
  127. package/dist/features/products/components/BidHistory.js +2 -2
  128. package/dist/features/products/components/CompareOverlay.js +1 -1
  129. package/dist/features/products/components/CustomFieldsEditor.js +1 -1
  130. package/dist/features/products/components/CustomSectionTabContent.js +1 -1
  131. package/dist/features/products/components/CustomSectionsEditor.js +1 -1
  132. package/dist/features/products/components/GroupSettingsPanel.js +2 -2
  133. package/dist/features/products/components/MakeOfferButton.js +1 -1
  134. package/dist/features/products/components/PrizeDrawBottomActions.d.ts +6 -0
  135. package/dist/features/products/components/PrizeDrawBottomActions.js +24 -0
  136. package/dist/features/products/components/PrizeDrawDetailPageView.js +3 -5
  137. package/dist/features/products/components/PrizeDrawEntryActions.js +5 -18
  138. package/dist/features/products/components/PrizeRevealModal.js +5 -2
  139. package/dist/features/products/components/ProductDetailActions.d.ts +6 -1
  140. package/dist/features/products/components/ProductDetailActions.js +36 -6
  141. package/dist/features/products/components/ProductDetailPageView.js +17 -16
  142. package/dist/features/products/components/ProductGalleryClient.js +1 -1
  143. package/dist/features/products/components/ProductGrid.js +6 -6
  144. package/dist/features/products/components/ProductTabs.js +1 -1
  145. package/dist/features/products/components/ProductTabsShell.js +1 -1
  146. package/dist/features/products/components/ProductsIndexListing.js +47 -0
  147. package/dist/features/products/components/RelatedProducts.js +1 -1
  148. package/dist/features/products/components/ShowGroupSection.js +1 -1
  149. package/dist/features/products/components/SublistingCarouselSection.js +1 -1
  150. package/dist/features/products/components/SublistingCategorySelect.js +1 -1
  151. package/dist/features/products/components/index.d.ts +0 -2
  152. package/dist/features/products/components/index.js +0 -1
  153. package/dist/features/products/constants/action-defs.d.ts +7 -0
  154. package/dist/features/products/constants/action-defs.js +14 -0
  155. package/dist/features/products/constants/listing-tabs.d.ts +6 -0
  156. package/dist/features/products/constants/listing-tabs.js +1 -0
  157. package/dist/features/promotions/components/CouponCard.js +2 -2
  158. package/dist/features/promotions/components/CouponsIndexListing.js +2 -2
  159. package/dist/features/reviews/components/ReviewDetailPageView.js +1 -1
  160. package/dist/features/reviews/components/ReviewDetailShell.js +3 -3
  161. package/dist/features/reviews/components/ReviewModal.js +2 -2
  162. package/dist/features/reviews/components/ReviewSummary.js +1 -1
  163. package/dist/features/reviews/components/ReviewsIndexListing.js +1 -1
  164. package/dist/features/reviews/components/ReviewsList.js +1 -1
  165. package/dist/features/seller/components/SellerAddressesView.js +4 -3
  166. package/dist/features/seller/components/SellerAnalyticsAlertsView.js +1 -1
  167. package/dist/features/seller/components/SellerAuctionsView.js +10 -3
  168. package/dist/features/seller/components/SellerBidsView.js +22 -7
  169. package/dist/features/seller/components/SellerBundlesView.js +10 -3
  170. package/dist/features/seller/components/SellerClassifiedView.js +10 -3
  171. package/dist/features/seller/components/SellerCouponsView.js +13 -4
  172. package/dist/features/seller/components/SellerDigitalCodesView.js +10 -3
  173. package/dist/features/seller/components/SellerGoogleReviewsView.js +10 -5
  174. package/dist/features/seller/components/SellerGroupedListingsView.js +2 -0
  175. package/dist/features/seller/components/SellerLiveView.js +10 -3
  176. package/dist/features/seller/components/SellerOffersPanel.js +2 -2
  177. package/dist/features/seller/components/SellerOffersView.js +1 -1
  178. package/dist/features/seller/components/SellerOrdersView.js +40 -17
  179. package/dist/features/seller/components/SellerPayoutMethodsView.js +13 -4
  180. package/dist/features/seller/components/SellerPayoutsView.js +1 -1
  181. package/dist/features/seller/components/SellerPreOrdersView.js +7 -2
  182. package/dist/features/seller/components/SellerPrizeDrawsView.js +7 -2
  183. package/dist/features/seller/components/SellerProductShell.js +27 -9
  184. package/dist/features/seller/components/SellerProductsCards.js +2 -1
  185. package/dist/features/seller/components/SellerProductsView.js +21 -8
  186. package/dist/features/seller/components/SellerReviewsView.js +8 -0
  187. package/dist/features/seller/components/SellerShippingConfigsView.js +13 -4
  188. package/dist/features/seller/components/SellerSidebar.js +2 -2
  189. package/dist/features/seller/components/SellerStoreCategoriesView.js +10 -3
  190. package/dist/features/seller/components/SellerTemplatesView.js +19 -6
  191. package/dist/features/shell/StepForm.js +9 -3
  192. package/dist/features/site-settings/components/ActionPermissionsManager.js +1 -1
  193. package/dist/features/site-settings/components/NavPermissionsManager.js +1 -1
  194. package/dist/features/stores/components/InteractiveStoreCard.js +1 -1
  195. package/dist/features/stores/components/StoreDetailLayoutView.js +1 -1
  196. package/dist/features/stores/components/StoreReviewsListing.js +1 -1
  197. package/dist/features/stores/components/StoresIndexListing.js +17 -1
  198. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +1 -1
  199. package/dist/features/wishlist/components/WishlistPage.js +2 -2
  200. package/dist/features/wishlist/hooks/useWishlistToggle.js +6 -1
  201. package/dist/index.d.ts +3 -2
  202. package/dist/index.js +6 -3
  203. package/dist/react/hooks/use-action-dispatch.d.ts +5 -0
  204. package/dist/react/hooks/use-action-dispatch.js +10 -0
  205. package/dist/seed/cart-seed-data.js +50 -3
  206. package/dist/seed/categories-seed-data.js +80 -16
  207. package/dist/seed/index.d.ts +3 -0
  208. package/dist/seed/index.js +3 -0
  209. package/dist/seed/manifest.js +15 -1
  210. package/dist/seed/products-classifieds-seed-data.d.ts +10 -0
  211. package/dist/seed/products-classifieds-seed-data.js +197 -0
  212. package/dist/seed/products-digital-codes-seed-data.d.ts +10 -0
  213. package/dist/seed/products-digital-codes-seed-data.js +204 -0
  214. package/dist/seed/products-live-items-seed-data.d.ts +13 -0
  215. package/dist/seed/products-live-items-seed-data.js +190 -0
  216. package/dist/styles.css +16 -1
  217. package/dist/tailwind-utilities.css +1 -1
  218. package/dist/tokens/index.d.ts +3 -3
  219. package/dist/tokens/index.js +3 -3
  220. package/dist/ui/DataTable.js +3 -3
  221. package/dist/ui/components/Button.style.css +15 -0
  222. package/dist/ui/components/Input.js +1 -1
  223. package/dist/ui/components/ListingToolbar.js +1 -1
  224. package/dist/ui/components/Select.js +1 -1
  225. package/dist/ui/components/StatsGrid.js +1 -1
  226. package/dist/ui/index.d.ts +0 -4
  227. package/dist/ui/index.js +0 -2
  228. package/package.json +1 -1
  229. package/dist/_internal/client/features/seller/print-center/InventoryLabel.d.ts +0 -12
  230. package/dist/_internal/client/features/seller/print-center/InventoryLabel.js +0 -49
  231. package/dist/_internal/client/features/seller/print-center/LabelDesignPicker.d.ts +0 -7
  232. package/dist/_internal/client/features/seller/print-center/LabelDesignPicker.js +0 -32
  233. package/dist/_internal/client/features/seller/print-center/OrderPackingLabel.d.ts +0 -28
  234. package/dist/_internal/client/features/seller/print-center/OrderPackingLabel.js +0 -33
  235. package/dist/_internal/client/features/seller/print-center/PhysicalLocationModal.d.ts +0 -12
  236. package/dist/_internal/client/features/seller/print-center/PhysicalLocationModal.js +0 -30
  237. package/dist/_internal/client/features/seller/print-center/PrintCenterView.d.ts +0 -12
  238. package/dist/_internal/client/features/seller/print-center/PrintCenterView.js +0 -102
  239. package/dist/_internal/client/features/seller/print-center/PrintGrid.d.ts +0 -12
  240. package/dist/_internal/client/features/seller/print-center/PrintGrid.js +0 -13
  241. package/dist/_internal/client/features/seller/print-center/StoreCard.d.ts +0 -19
  242. package/dist/_internal/client/features/seller/print-center/StoreCard.js +0 -30
  243. package/dist/_internal/client/features/seller/print-center/WebsiteCard.d.ts +0 -11
  244. package/dist/_internal/client/features/seller/print-center/WebsiteCard.js +0 -25
  245. package/dist/_internal/client/features/seller/print-center/index.d.ts +0 -11
  246. package/dist/_internal/client/features/seller/print-center/index.js +0 -10
  247. package/dist/_internal/client/features/seller/print-center/types.d.ts +0 -20
  248. package/dist/_internal/client/features/seller/print-center/types.js +0 -20
  249. package/dist/_internal/client/features/seller/print-center/useInventoryPdf.d.ts +0 -18
  250. package/dist/_internal/client/features/seller/print-center/useInventoryPdf.js +0 -76
  251. package/dist/features/account/repository/address.repository.d.ts +0 -17
  252. package/dist/features/account/repository/address.repository.js +0 -184
  253. package/dist/features/auctions/components/AuctionCard.d.ts +0 -29
  254. package/dist/features/auctions/components/AuctionCard.js +0 -38
  255. package/dist/features/categories/components/BundleAddToCartCta.d.ts +0 -16
  256. package/dist/features/categories/components/BundleAddToCartCta.js +0 -54
  257. package/dist/features/categories/components/CategoriesListView.d.ts +0 -31
  258. package/dist/features/categories/components/CategoriesListView.js +0 -27
  259. package/dist/features/products/components/AuctionsView.d.ts +0 -6
  260. package/dist/features/products/components/AuctionsView.js +0 -5
  261. package/dist/features/products/components/BuyBar.d.ts +0 -21
  262. package/dist/features/products/components/BuyBar.js +0 -19
  263. package/dist/features/products/components/PreOrdersView.d.ts +0 -6
  264. package/dist/features/products/components/PreOrdersView.js +0 -5
  265. package/dist/features/reviews/components/ReviewsListView.d.ts +0 -31
  266. package/dist/features/reviews/components/ReviewsListView.js +0 -16
  267. package/dist/features/stores/components/StoresListView.d.ts +0 -19
  268. package/dist/features/stores/components/StoresListView.js +0 -25
  269. package/dist/features/stores/repository/store-address.repository.d.ts +0 -55
  270. package/dist/features/stores/repository/store-address.repository.js +0 -187
  271. package/dist/ui/components/BulkActionsBar.d.ts +0 -18
  272. package/dist/ui/components/BulkActionsBar.js +0 -25
  273. package/dist/ui/components/CollageLightbox.d.ts +0 -18
  274. package/dist/ui/components/CollageLightbox.js +0 -41
  275. package/dist/ui/components/StickyBottomBar.d.ts +0 -22
  276. package/dist/ui/components/StickyBottomBar.js +0 -20
@@ -16,7 +16,6 @@ import { ProductTabsShell } from "./ProductTabsShell";
16
16
  import { ProductFeatureBadges } from "./ProductFeatureBadges";
17
17
  import { FeatureBadgeList } from "./FeatureBadge";
18
18
  import { RelatedProductsCarousel } from "./RelatedProductsCarousel";
19
- import { BuyBar } from "./BuyBar";
20
19
  import { ShareButton } from "./ShareButton";
21
20
  import { CustomSectionTabContent } from "./CustomSectionTabContent";
22
21
  import { SublistingCarouselSection } from "./SublistingCarouselSection";
@@ -97,7 +96,7 @@ export async function ProductDetailPageView({ slug, initialProduct, renderOfferA
97
96
  ? (initialProduct ?? undefined)
98
97
  : await productRepository.findByIdOrSlug(slug).catch(() => undefined);
99
98
  if (!product) {
100
- return (_jsx(Main, { children: _jsx(Section, { className: "py-20", children: _jsx(Container, { size: "md", children: _jsxs(Stack, { align: "center", gap: "md", className: "text-center", children: [_jsx(Heading, { level: 1, className: "text-2xl font-semibold text-zinc-900 dark:text-zinc-50", children: "Product Not Found" }), _jsx(Text, { className: "text-zinc-500", children: "The product you are looking for may have been removed or the link is incorrect." }), _jsx(Link, { href: String(ROUTES.PUBLIC.PRODUCTS), className: "text-sm font-medium text-primary-600 hover:underline", children: "Browse Products" })] }) }) }) }));
99
+ return (_jsx(Main, { children: _jsx(Section, { className: "py-20", children: _jsx(Container, { size: "md", children: _jsxs(Stack, { align: "center", gap: "md", className: "text-center", children: [_jsx(Heading, { level: 1, className: "text-2xl font-semibold text-zinc-900 dark:text-zinc-50", children: "Product Not Found" }), _jsx(Text, { className: "text-zinc-500 dark:text-zinc-400", children: "The product you are looking for may have been removed or the link is incorrect." }), _jsx(Link, { href: String(ROUTES.PUBLIC.PRODUCTS), className: "text-sm font-medium text-primary-600 hover:underline", children: "Browse Products" })] }) }) }) }));
101
100
  }
102
101
  const p = product;
103
102
  const currency = p.currency || getDefaultCurrency();
@@ -263,7 +262,7 @@ export async function ProductDetailPageView({ slug, initialProduct, renderOfferA
263
262
  codAvailable: "Cash on Delivery",
264
263
  wishlistCount: (n) => `${n} wishlisted`,
265
264
  categoryProductCount: (n, cat) => `${n} in ${cat}`,
266
- } }), productFeatures && features.length > 0 && (_jsx(FeatureBadgeList, { productFeatureIds: features, features: productFeatures })), !productFeatures && features.length > 0 && (_jsxs(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 px-4 py-3", children: [_jsx(Text, { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-zinc-500 dark:text-zinc-400", children: "About this product" }), _jsx("ul", { className: "space-y-1.5", children: features.map((f, i) => (_jsxs("li", { className: "flex items-start gap-2 text-sm text-zinc-700 dark:text-zinc-300", children: [_jsx(Span, { className: "mt-0.5 flex-shrink-0 text-primary-500", children: "\u2022" }), f] }, i))) })] })), descriptionHtml && (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "text-sm leading-relaxed text-zinc-600 dark:text-zinc-400 line-clamp-4" })), safeSeller && (_jsx(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 p-3", children: _jsxs(Row, { justify: "between", align: "center", children: [_jsxs(Div, { children: [_jsx(Text, { className: "text-[10px] uppercase tracking-wide text-zinc-400 dark:text-zinc-500 mb-0.5", children: "Sold by" }), _jsx(Text, { className: "text-sm font-semibold text-zinc-800 dark:text-zinc-200", children: safeSeller })] }), storeHref && (_jsx(Link, { href: storeHref, className: "shrink-0 rounded-lg bg-primary/10 dark:bg-primary/20 px-3 py-1.5 text-xs font-semibold text-primary-700 dark:text-primary-300 hover:bg-primary/20 dark:hover:bg-primary/30 transition-colors", children: "Visit Store \u2192" }))] }) }))] })), renderActions: () => (_jsxs(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 p-5 space-y-4", children: [formattedPrice && (_jsxs(Div, { children: [_jsxs(Row, { align: "baseline", gap: "sm", wrap: true, children: [_jsx(Text, { className: "text-2xl font-bold text-zinc-900 dark:text-zinc-50", children: formattedPrice }), formattedOriginal && discount && (_jsxs(_Fragment, { children: [_jsx(Span, { className: "text-sm text-zinc-400 line-through dark:text-zinc-500", children: formattedOriginal }), _jsxs(Span, { className: "rounded-full bg-red-500 px-2 py-0.5 text-xs font-bold text-white", children: ["-", discount, "%"] })] }))] }), inStock && effectiveStock !== null && effectiveStock <= 10 && (_jsxs(Text, { className: "mt-1 text-xs text-amber-600 dark:text-amber-400", children: ["Only ", effectiveStock, " left \u2014 order soon!"] }))] })), _jsxs(Stack, { gap: "sm", children: [renderPrimaryActions ? (renderPrimaryActions({
265
+ } }), productFeatures && features.length > 0 && (_jsx(FeatureBadgeList, { productFeatureIds: features, features: productFeatures })), !productFeatures && features.length > 0 && (_jsxs(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 px-4 py-3", children: [_jsx(Text, { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-zinc-500 dark:text-zinc-400", children: "About this product" }), _jsx("ul", { className: "space-y-1.5", children: features.map((f, i) => (_jsxs("li", { className: "flex items-start gap-2 text-sm text-zinc-700 dark:text-zinc-300", children: [_jsx(Span, { className: "mt-0.5 flex-shrink-0 text-primary-500", children: "\u2022" }), f] }, i))) })] })), descriptionHtml && (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "text-sm leading-relaxed text-zinc-600 dark:text-zinc-400 line-clamp-4" })), safeSeller && (_jsx(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 p-3", children: _jsxs(Row, { justify: "between", align: "center", children: [_jsxs(Div, { children: [_jsx(Text, { className: "text-[10px] uppercase tracking-wide text-zinc-400 dark:text-zinc-400 mb-0.5", children: "Sold by" }), _jsx(Text, { className: "text-sm font-semibold text-zinc-800 dark:text-zinc-200", children: safeSeller })] }), storeHref && (_jsx(Link, { href: storeHref, className: "shrink-0 rounded-lg bg-primary/10 dark:bg-primary/20 px-3 py-1.5 text-xs font-semibold text-primary-700 dark:text-primary-300 hover:bg-primary/20 dark:hover:bg-primary/30 transition-colors", children: "Visit Store \u2192" }))] }) }))] })), renderActions: () => (_jsxs(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 p-5 space-y-4", children: [formattedPrice && (_jsxs(Div, { children: [_jsxs(Row, { align: "baseline", gap: "sm", wrap: true, children: [_jsx(Text, { className: "text-2xl font-bold text-zinc-900 dark:text-zinc-50", children: formattedPrice }), formattedOriginal && discount && (_jsxs(_Fragment, { children: [_jsx(Span, { className: "text-sm text-zinc-400 line-through dark:text-zinc-400", children: formattedOriginal }), _jsxs(Span, { className: "rounded-full bg-red-500 px-2 py-0.5 text-xs font-bold text-white", children: ["-", discount, "%"] })] }))] }), inStock && effectiveStock !== null && effectiveStock <= 10 && (_jsxs(Text, { className: "mt-1 text-xs text-amber-600 dark:text-amber-400", children: ["Only ", effectiveStock, " left \u2014 order soon!"] }))] })), _jsxs(Stack, { gap: "sm", children: [renderPrimaryActions ? (renderPrimaryActions({
267
266
  productId: product.id,
268
267
  productSlug: product.slug ?? slug,
269
268
  productTitle: product.title,
@@ -279,7 +278,7 @@ export async function ProductDetailPageView({ slug, initialProduct, renderOfferA
279
278
  price,
280
279
  currency,
281
280
  minOfferPercent,
282
- })] }), (shippingInfo || returnPolicy || freeShipping) && (_jsxs(Div, { className: "border-t border-zinc-200 dark:border-zinc-700 pt-4 space-y-2.5", children: [freeShipping && (_jsxs(Row, { align: "start", gap: "sm", children: [_jsx(Span, { className: "mt-0.5 flex-shrink-0 text-emerald-500", children: "\uD83D\uDE9A" }), _jsxs(Div, { children: [_jsx(Text, { className: "text-xs font-medium text-zinc-700 dark:text-zinc-300", children: "Free Delivery" }), shippingInfo && (_jsx(Text, { className: "text-xs text-zinc-500", children: shippingInfo }))] })] })), !freeShipping && shippingInfo && (_jsxs(Row, { align: "start", gap: "sm", children: [_jsx(Span, { className: "mt-0.5 flex-shrink-0 text-zinc-400", children: "\uD83D\uDCE6" }), _jsx(Text, { className: "text-xs text-zinc-600 dark:text-zinc-400", children: shippingInfo })] })), returnPolicy && (_jsxs(Row, { align: "start", gap: "sm", children: [_jsx(Span, { className: "mt-0.5 flex-shrink-0 text-zinc-400", children: "\u21BA" }), _jsx(Text, { className: "text-xs text-zinc-600 dark:text-zinc-400", children: returnPolicy })] }))] })), tags.length > 0 && (_jsxs(Div, { className: "border-t border-zinc-200 dark:border-zinc-700 pt-4", children: [_jsx(Text, { className: "mb-2 text-xs font-medium text-zinc-500 dark:text-zinc-400", children: "Tags" }), _jsx(Row, { wrap: true, gap: "xs", children: tags.map((tag) => (_jsx(Span, { className: "rounded-full bg-zinc-100 dark:bg-zinc-800 px-2.5 py-1 text-xs text-zinc-600 dark:text-zinc-300", children: tag }, tag))) })] })), _jsx(Div, { className: "border-t border-zinc-200 dark:border-zinc-700 pt-4", children: _jsx(Row, { wrap: true, gap: "sm", className: "justify-center text-center", children: [
281
+ })] }), (shippingInfo || returnPolicy || freeShipping) && (_jsxs(Div, { className: "border-t border-zinc-200 dark:border-zinc-700 pt-4 space-y-2.5", children: [freeShipping && (_jsxs(Row, { align: "start", gap: "sm", children: [_jsx(Span, { className: "mt-0.5 flex-shrink-0 text-emerald-500", children: "\uD83D\uDE9A" }), _jsxs(Div, { children: [_jsx(Text, { className: "text-xs font-medium text-zinc-700 dark:text-zinc-300", children: "Free Delivery" }), shippingInfo && (_jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: shippingInfo }))] })] })), !freeShipping && shippingInfo && (_jsxs(Row, { align: "start", gap: "sm", children: [_jsx(Span, { className: "mt-0.5 flex-shrink-0 text-zinc-400", children: "\uD83D\uDCE6" }), _jsx(Text, { className: "text-xs text-zinc-600 dark:text-zinc-400", children: shippingInfo })] })), returnPolicy && (_jsxs(Row, { align: "start", gap: "sm", children: [_jsx(Span, { className: "mt-0.5 flex-shrink-0 text-zinc-400", children: "\u21BA" }), _jsx(Text, { className: "text-xs text-zinc-600 dark:text-zinc-400", children: returnPolicy })] }))] })), tags.length > 0 && (_jsxs(Div, { className: "border-t border-zinc-200 dark:border-zinc-700 pt-4", children: [_jsx(Text, { className: "mb-2 text-xs font-medium text-zinc-500 dark:text-zinc-400", children: "Tags" }), _jsx(Row, { wrap: true, gap: "xs", children: tags.map((tag) => (_jsx(Span, { className: "rounded-full bg-zinc-100 dark:bg-zinc-800 px-2.5 py-1 text-xs text-zinc-600 dark:text-zinc-300", children: tag }, tag))) })] })), _jsx(Div, { className: "border-t border-zinc-200 dark:border-zinc-700 pt-4", children: _jsx(Row, { wrap: true, gap: "sm", className: "justify-center text-center", children: [
283
282
  { icon: "🔒", label: "Secure\nPayment" },
284
283
  { icon: "✓", label: "Verified\nSeller" },
285
284
  { icon: "⭐", label: "Quality\nGuarantee" },
@@ -293,16 +292,18 @@ export async function ProductDetailPageView({ slug, initialProduct, renderOfferA
293
292
  content: _jsx(CustomSectionTabContent, { section: s }),
294
293
  })) })), renderBundleSection: bundleMemberships.length > 0
295
294
  ? () => (_jsxs("div", { className: "rounded-xl border border-teal-200 dark:border-teal-800/60 bg-teal-50/60 dark:bg-teal-900/20 p-5", children: [_jsxs("div", { className: "flex items-center gap-2 mb-3", children: [_jsx(Span, { className: "text-teal-600 dark:text-teal-400 text-base", "aria-hidden": "true", children: "\uD83D\uDCE6" }), _jsxs(Text, { className: "text-sm font-semibold text-teal-800 dark:text-teal-200", children: ["Part of ", bundleMemberships.length === 1 ? "a bundle" : `${bundleMemberships.length} bundles`] })] }), _jsx("div", { className: "flex flex-col gap-3", children: bundleMemberships.map((b) => (_jsxs("div", { className: "flex items-center justify-between gap-4 rounded-lg border border-teal-200 dark:border-teal-800/50 bg-white dark:bg-teal-900/30 px-4 py-3", children: [_jsxs("div", { className: "min-w-0", children: [_jsx(Text, { className: "text-xs text-teal-600 dark:text-teal-400 font-medium uppercase tracking-wide mb-0.5", children: "Included in bundle" }), _jsx(Text, { className: "text-sm font-semibold text-zinc-800 dark:text-zinc-100 truncate", children: b.title })] }), _jsx(Link, { href: String(ROUTES.PUBLIC.BUNDLE_DETAIL(b.id)), className: "flex-shrink-0 rounded-lg bg-teal-600 hover:bg-teal-700 px-3 py-1.5 text-xs font-semibold text-white transition-colors", children: "View Bundle \u2192" })] }, b.id))) })] }))
296
- : undefined, renderRelated: () => relatedItems.length > 0 ? (_jsx(RelatedProductsCarousel, { items: relatedItems })) : null }), _jsxs(BuyBar, { children: [formattedPrice && (_jsx(Span, { className: "mr-auto text-sm font-bold text-zinc-900 dark:text-zinc-50", children: formattedPrice })), renderPrimaryActions ? (renderPrimaryActions({
297
- productId: product.id,
298
- productSlug: product.slug ?? slug,
299
- productTitle: product.title,
300
- productImage: product.mainImage,
301
- price,
302
- currency,
303
- storeId: typeof p.storeId === "string" ? p.storeId : undefined,
304
- storeName: typeof p.storeName === "string" ? p.storeName : undefined,
305
- inStock,
306
- variant: "mobile",
307
- })) : (_jsxs(_Fragment, { children: [_jsx(Button, { variant: "secondary", size: "sm", className: "shrink-0", disabled: true, title: ACTION_NOT_WIRED, children: "Add to Cart" }), _jsx(Button, { variant: "primary", size: "sm", className: "flex-1", disabled: true, title: ACTION_NOT_WIRED, children: inStock ? "Buy Now" : "Out of Stock" })] }))] })] })] }));
295
+ : undefined, renderRelated: () => relatedItems.length > 0 ? (_jsx(RelatedProductsCarousel, { items: relatedItems })) : null }), renderPrimaryActions
296
+ ? renderPrimaryActions({
297
+ productId: product.id,
298
+ productSlug: product.slug ?? slug,
299
+ productTitle: product.title,
300
+ productImage: product.mainImage,
301
+ price,
302
+ currency,
303
+ storeId: typeof p.storeId === "string" ? p.storeId : undefined,
304
+ storeName: typeof p.storeName === "string" ? p.storeName : undefined,
305
+ inStock,
306
+ variant: "mobile",
307
+ })
308
+ : null] })] }));
308
309
  }
@@ -20,5 +20,5 @@ export function ProductGalleryClient({ images, productName }) {
20
20
  setLightboxIndex(activeIndex);
21
21
  }, "aria-label": `View ${productName ?? "product"} image in full screen`, children: _jsx("img", { src: mainImage, alt: productName ? `${productName} — image ${activeIndex + 1}` : `Product image ${activeIndex + 1}`, className: "aspect-square w-full object-cover transition-transform duration-300 hover:scale-105" }) }), images.length > 1 && (_jsx("div", { className: "flex gap-2 overflow-x-auto pb-1", children: images.map((src, i) => (_jsx("button", { type: "button", onClick: () => setActiveIndex(i), className: `flex-shrink-0 h-16 w-16 overflow-hidden rounded-lg border-2 transition-all${i === activeIndex
22
22
  ? " border-primary-500"
23
- : " border-transparent opacity-60 hover:opacity-100"}`, "aria-label": `View image ${i + 1}`, "aria-current": i === activeIndex ? "true" : undefined, children: _jsx("img", { src: src, alt: "", className: "h-full w-full object-cover" }) }, i))) })), images.length > 1 && (_jsxs(Text, { className: "text-center text-xs text-zinc-400 dark:text-zinc-500", children: [activeIndex + 1, " / ", images.length] })), _jsx(ImageLightbox, { images: lightboxImages, activeIndex: lightboxIndex, onClose: () => setLightboxIndex(null), onNavigate: (i) => setLightboxIndex(i) })] }));
23
+ : " border-transparent opacity-60 hover:opacity-100"}`, "aria-label": `View image ${i + 1}`, "aria-current": i === activeIndex ? "true" : undefined, children: _jsx("img", { src: src, alt: "", className: "h-full w-full object-cover" }) }, i))) })), images.length > 1 && (_jsxs(Text, { className: "text-center text-xs text-zinc-400 dark:text-zinc-400", children: [activeIndex + 1, " / ", images.length] })), _jsx(ImageLightbox, { images: lightboxImages, activeIndex: lightboxIndex, onClose: () => setLightboxIndex(null), onNavigate: (i) => setLightboxIndex(i) })] }));
24
24
  }
@@ -59,10 +59,10 @@ export function ProductCard({ product, href, onClick, onAddToWishlist, isWishlis
59
59
  isWishlisted
60
60
  ? "bg-rose-500 text-white hover:bg-rose-600"
61
61
  : "bg-white/90 dark:bg-slate-800/90 text-zinc-500 dark:text-zinc-400 hover:text-rose-500 hover:bg-white dark:hover:bg-slate-800",
62
- ].join(" "), children: _jsx("svg", { className: "h-4 w-4", fill: isWishlisted ? "currentColor" : "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12z" }) }) }))] }), _jsxs(Div, { className: "flex flex-1 flex-col p-3 pt-2.5", children: [_jsx(Text, { className: `${THEME_CONSTANTS.utilities.textClamp2} text-sm font-semibold text-zinc-900 dark:text-white leading-snug`, children: product.title }), ((Array.isArray(product.categoryNames) ? product.categoryNames[0] : product.categoryName) || product.brand) && (_jsxs(Row, { className: "mt-1 gap-1 flex-wrap", children: [(Array.isArray(product.categoryNames) ? product.categoryNames[0] : product.categoryName) && (_jsxs(Span, { className: "inline-flex items-center gap-0.5 rounded-full bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 text-[10px] text-zinc-500 dark:text-zinc-400 truncate max-w-[100px]", children: [_jsx("svg", { className: "h-2.5 w-2.5 flex-shrink-0", fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3 7a2 2 0 012-2h14a2 2 0 012 2v10a2 2 0 01-2 2H5a2 2 0 01-2-2V7z" }) }), (Array.isArray(product.categoryNames) ? product.categoryNames[0] : product.categoryName)] })), product.brand && (_jsxs(Span, { className: "inline-flex items-center gap-0.5 rounded-full bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 text-[10px] text-zinc-500 dark:text-zinc-400 truncate max-w-[90px]", children: [_jsx("svg", { className: "h-2.5 w-2.5 flex-shrink-0", fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z" }) }), product.brand] }))] })), (() => {
62
+ ].join(" "), children: _jsx("svg", { className: "h-4 w-4", fill: isWishlisted ? "currentColor" : "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12z" }) }) }))] }), _jsxs(Div, { className: "flex flex-1 flex-col p-3 pt-2.5", children: [_jsx(Text, { className: `${THEME_CONSTANTS.utilities.textClamp2} text-sm font-semibold text-zinc-900 dark:text-white leading-snug`, children: product.title }), ((Array.isArray(product.categoryNames) ? product.categoryNames[0] : product.categoryName) || product.brand) && (_jsxs(Row, { className: "mt-1 gap-1 flex-wrap", children: [(Array.isArray(product.categoryNames) ? product.categoryNames[0] : product.categoryName) && (_jsxs(Span, { className: "inline-flex items-center gap-0.5 rounded-full bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 text-[10px] text-zinc-600 dark:text-zinc-400 truncate max-w-[100px]", children: [_jsx("svg", { className: "h-2.5 w-2.5 flex-shrink-0", fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3 7a2 2 0 012-2h14a2 2 0 012 2v10a2 2 0 01-2 2H5a2 2 0 01-2-2V7z" }) }), (Array.isArray(product.categoryNames) ? product.categoryNames[0] : product.categoryName)] })), product.brand && (_jsxs(Span, { className: "inline-flex items-center gap-0.5 rounded-full bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 text-[10px] text-zinc-600 dark:text-zinc-400 truncate max-w-[90px]", children: [_jsx("svg", { className: "h-2.5 w-2.5 flex-shrink-0", fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z" }) }), product.brand] }))] })), (() => {
63
63
  const seller = safeDisplayName(product.storeName, "");
64
- return seller ? (_jsxs(Text, { className: "mt-0.5 text-[11px] text-zinc-400 dark:text-zinc-500 truncate", children: ["by ", seller] })) : null;
65
- })(), product.rating !== undefined && (_jsxs(Row, { className: "mt-1 gap-1 items-center", children: [_jsx(Span, { className: "text-[11px] text-amber-400", children: "\u2605" }), _jsxs(Span, { className: "text-[11px] text-zinc-500 dark:text-zinc-400", children: [product.rating.toFixed(1), product.reviewCount ? ` (${product.reviewCount})` : ""] })] })), _jsxs(Div, { className: "mt-auto pt-2", children: [_jsxs(Row, { className: "items-baseline gap-2", children: [_jsx(Span, { className: "text-base font-bold text-primary dark:text-primary-400", children: formatCurrency(product.price, getDefaultCurrency()) }), product.originalPrice && product.originalPrice > product.price && (_jsx(Span, { className: "text-xs text-zinc-400 line-through dark:text-zinc-500", children: formatCurrency(product.originalPrice, getDefaultCurrency()) }))] }), (() => {
64
+ return seller ? (_jsxs(Text, { className: "mt-0.5 text-[11px] text-zinc-400 dark:text-zinc-400 truncate", children: ["by ", seller] })) : null;
65
+ })(), product.rating !== undefined && (_jsxs(Row, { className: "mt-1 gap-1 items-center", children: [_jsx(Span, { className: "text-[11px] text-amber-400", children: "\u2605" }), _jsxs(Span, { className: "text-[11px] text-zinc-500 dark:text-zinc-400", children: [product.rating.toFixed(1), product.reviewCount ? ` (${product.reviewCount})` : ""] })] })), _jsxs(Div, { className: "mt-auto pt-2", children: [_jsxs(Row, { className: "items-baseline gap-2", children: [_jsx(Span, { className: "text-base font-bold text-primary dark:text-primary-400", children: formatCurrency(product.price, getDefaultCurrency()) }), product.originalPrice && product.originalPrice > product.price && (_jsx(Span, { className: "text-xs text-zinc-400 line-through dark:text-zinc-400", children: formatCurrency(product.originalPrice, getDefaultCurrency()) }))] }), (() => {
66
66
  const stock = product.stockCount ?? product.stockQuantity ?? product.availableQuantity;
67
67
  if (stock === undefined || isAuction)
68
68
  return null;
@@ -104,7 +104,7 @@ function ProductListRow({ product, onClick, onAddToWishlist, isWishlisted, }) {
104
104
  onClick ? "cursor-pointer" : "",
105
105
  ]
106
106
  .filter(Boolean)
107
- .join(" "), children: [_jsx(Div, { className: "flex-shrink-0 w-16 h-16 sm:w-20 sm:h-20 rounded-lg overflow-hidden bg-neutral-100 dark:bg-zinc-800", children: product.mainImage ? (_jsx(MediaImage, { src: product.mainImage, alt: product.title, size: "thumbnail" })) : (_jsx(Div, { className: "w-full h-full bg-neutral-200 dark:bg-zinc-700" })) }), _jsxs(Div, { className: "flex flex-1 flex-col min-w-0 gap-0.5", children: [_jsx(Text, { className: `${THEME_CONSTANTS.utilities.textClamp2} text-sm font-medium text-zinc-900 dark:text-zinc-100`, children: product.title }), (product.categoryName || product.brand) && (_jsx(Span, { className: "text-[11px] text-zinc-400 dark:text-zinc-500 truncate", children: [product.categoryName, product.brand].filter(Boolean).join(" · ") })), _jsxs(Div, { className: "flex items-center gap-2 flex-wrap mt-0.5", children: [_jsx(Span, { className: "text-sm font-semibold text-primary", children: formatCurrency(product.price, getDefaultCurrency()) }), discount && (_jsxs(Span, { className: "text-[10px] font-bold text-rose-500", children: ["-", discount, "%"] })), product.rating !== undefined && (_jsxs(Span, { className: "text-[11px] text-zinc-400 dark:text-zinc-500 flex items-center gap-0.5", children: [_jsx(Span, { className: "text-amber-400", children: "\u2605" }), product.rating.toFixed(1)] })), (() => {
107
+ .join(" "), children: [_jsx(Div, { className: "flex-shrink-0 w-16 h-16 sm:w-20 sm:h-20 rounded-lg overflow-hidden bg-neutral-100 dark:bg-zinc-800", children: product.mainImage ? (_jsx(MediaImage, { src: product.mainImage, alt: product.title, size: "thumbnail" })) : (_jsx(Div, { className: "w-full h-full bg-neutral-200 dark:bg-zinc-700" })) }), _jsxs(Div, { className: "flex flex-1 flex-col min-w-0 gap-0.5", children: [_jsx(Text, { className: `${THEME_CONSTANTS.utilities.textClamp2} text-sm font-medium text-zinc-900 dark:text-zinc-100`, children: product.title }), (product.categoryName || product.brand) && (_jsx(Span, { className: "text-[11px] text-zinc-400 dark:text-zinc-400 truncate", children: [product.categoryName, product.brand].filter(Boolean).join(" · ") })), _jsxs(Div, { className: "flex items-center gap-2 flex-wrap mt-0.5", children: [_jsx(Span, { className: "text-sm font-semibold text-primary", children: formatCurrency(product.price, getDefaultCurrency()) }), discount && (_jsxs(Span, { className: "text-[10px] font-bold text-rose-500", children: ["-", discount, "%"] })), product.rating !== undefined && (_jsxs(Span, { className: "text-[11px] text-zinc-400 dark:text-zinc-400 flex items-center gap-0.5", children: [_jsx(Span, { className: "text-amber-400", children: "\u2605" }), product.rating.toFixed(1)] })), (() => {
108
108
  const stock = product.stockCount ?? product.stockQuantity ?? product.availableQuantity;
109
109
  if (stock === undefined)
110
110
  return null;
@@ -114,7 +114,7 @@ function ProductListRow({ product, onClick, onAddToWishlist, isWishlisted, }) {
114
114
  const low = stock <= 5;
115
115
  return (_jsx(Span, { className: `text-[11px] font-medium ${low
116
116
  ? "text-amber-600 dark:text-amber-400"
117
- : "text-zinc-400 dark:text-zinc-500"}`, children: low ? `Only ${stock} left` : `${stock} in stock` }));
117
+ : "text-zinc-400 dark:text-zinc-400"}`, children: low ? `Only ${stock} left` : `${stock} in stock` }));
118
118
  })()] })] }), onAddToWishlist && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: (e) => {
119
119
  e.stopPropagation();
120
120
  onAddToWishlist(product.id);
@@ -178,6 +178,6 @@ export function ProductGrid({ products, renderCard, onProductClick, getProductHr
178
178
  }) }));
179
179
  };
180
180
  return (_jsxs(Div, { children: [resolvedHeader, isEmpty
181
- ? (resolvedEmpty ?? (_jsx(Text, { className: "py-12 text-center text-sm text-neutral-500", children: emptyLabel })))
181
+ ? (resolvedEmpty ?? (_jsx(Text, { className: "py-12 text-center text-sm text-zinc-500 dark:text-zinc-400", children: emptyLabel })))
182
182
  : renderItems(), resolvedFooter] }));
183
183
  }
@@ -19,5 +19,5 @@ export function ProductTabs({ renderDescription, renderSpecs, renderReviews, ext
19
19
  const tabs = allTabs.length > 0 ? allTabs : DEFAULT_TABS;
20
20
  return (_jsxs("div", { className: className, "data-section": "producttabs-div-426", children: [renderTabBar ? (renderTabBar(activeTab, setActiveTab, tabs)) : (_jsx("div", { className: "flex gap-4 border-b mb-4", "data-section": "producttabs-div-427", children: tabs.map((t) => (_jsx("button", { onClick: () => setActiveTab(t.value), className: `pb-2 text-sm font-medium border-b-2 transition-colors ${activeTab === t.value
21
21
  ? "border-current text-current"
22
- : "border-transparent text-neutral-500"}`, children: t.label }, t.value))) })), activeTab === "description" && renderDescription?.(), activeTab === "specs" && renderSpecs?.(), activeTab === "reviews" && renderReviews?.(), renderExtraTab?.(activeTab)] }));
22
+ : "border-transparent text-zinc-500 dark:text-zinc-400"}`, children: t.label }, t.value))) })), activeTab === "description" && renderDescription?.(), activeTab === "specs" && renderSpecs?.(), activeTab === "reviews" && renderReviews?.(), renderExtraTab?.(activeTab)] }));
23
23
  }
@@ -32,5 +32,5 @@ export function ProductTabsShell({ descriptionContent, specsContent, ingredients
32
32
  const activeContent = allTabs.find((t) => t.id === activeId)?.content;
33
33
  return (_jsxs("div", { className: `mt-8 ${className}`, children: [_jsx("div", { className: "mb-6 flex gap-1 overflow-x-auto border-b border-zinc-200 dark:border-zinc-700 pb-px", children: allTabs.map((t) => (_jsx("button", { type: "button", onClick: () => setActiveId(t.id), className: `flex-shrink-0 -mb-px pb-3 px-4 text-sm font-medium border-b-2 transition-colors ${activeId === t.id
34
34
  ? "border-[var(--appkit-color-primary,#6366f1)] text-[var(--appkit-color-primary,#6366f1)]"
35
- : "border-transparent text-zinc-500 hover:text-zinc-700 dark:hover:text-zinc-300"}`, children: t.label }, t.id))) }), _jsx("div", { children: activeContent })] }));
35
+ : "border-transparent text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-300"}`, children: t.label }, t.id))) }), _jsx("div", { children: activeContent })] }));
36
36
  }
@@ -22,6 +22,7 @@ import { useProductFeatures } from "./ProductFeaturesContext";
22
22
  import { TABLE_KEYS, VIEW_MODE } from "../../../constants/table-keys";
23
23
  import { sortBy } from "../../../constants/sort";
24
24
  import { PRODUCT_FIELDS } from "../../../constants/field-names";
25
+ import { useBottomActions } from "../../layout";
25
26
  const DEFAULT_SORT = sortBy(PRODUCT_FIELDS.CREATED_AT);
26
27
  const FILTER_KEYS = [TABLE_KEYS.CATEGORY, TABLE_KEYS.CONDITION, TABLE_KEYS.MIN_PRICE, TABLE_KEYS.MAX_PRICE, TABLE_KEYS.BRAND, TABLE_KEYS.STORE_ID, TABLE_KEYS.FREE_SHIPPING, TABLE_KEYS.TAGS, TABLE_KEYS.FEATURES, TABLE_KEYS.IS_PART_OF_BUNDLE];
27
28
  export function ProductsIndexListing({ initialData }) {
@@ -132,6 +133,52 @@ export function ProductsIndexListing({ initialData }) {
132
133
  router.push(String(ROUTES.USER.CART));
133
134
  });
134
135
  }, [localCart, router, requireAuth]);
136
+ useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
137
+ {
138
+ id: ACTION_ID.ADD_TO_CART,
139
+ label: ACTION_META[ACTION_ID.ADD_TO_CART].label,
140
+ icon: _jsx(ShoppingCart, { className: "h-3.5 w-3.5" }),
141
+ variant: "primary",
142
+ onClick: () => {
143
+ const selected = products.filter((p) => selection.selectedIdSet.has(p.id));
144
+ selected.forEach((p) => {
145
+ const snapshot = { productTitle: p.title, productImage: p.mainImage, price: p.price, storeId: p.storeId, storeName: p.storeName };
146
+ localCart.add(p.id, 1, snapshot);
147
+ pushCartOp({ op: "add", productId: p.id, quantity: 1, ...snapshot });
148
+ });
149
+ showToast(`${selected.length} items added to cart`, "success");
150
+ selection.clearSelection();
151
+ },
152
+ },
153
+ {
154
+ id: ACTION_ID.ADD_TO_WISHLIST,
155
+ label: ACTION_META[ACTION_ID.ADD_TO_WISHLIST].label,
156
+ icon: _jsx(Heart, { className: "h-3.5 w-3.5" }),
157
+ variant: "secondary",
158
+ onClick: () => {
159
+ requireAuth(ACTION_ID.ADD_TO_WISHLIST, () => {
160
+ const selected = products.filter((p) => selection.selectedIdSet.has(p.id));
161
+ selected.forEach((p) => {
162
+ localWishlist.add(p.id, "product");
163
+ pushWishlistOp({ op: "add", itemId: p.id, type: "product" });
164
+ });
165
+ showToast(`${selected.length} items added to wishlist`, "success");
166
+ selection.clearSelection();
167
+ });
168
+ },
169
+ },
170
+ {
171
+ id: ACTION_ID.COMPARE,
172
+ label: ACTION_META[ACTION_ID.COMPARE].label,
173
+ icon: _jsx(Columns, { className: "h-3.5 w-3.5" }),
174
+ variant: "secondary",
175
+ disabled: selection.selectedCount < 2 || selection.selectedCount > COMPARE_MAX_ITEMS,
176
+ onClick: () => {
177
+ const ids = Array.from(selection.selectedIdSet).slice(0, COMPARE_MAX_ITEMS);
178
+ setCompareIds(ids);
179
+ },
180
+ },
181
+ ] } } : {});
135
182
  return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: filterActiveCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search products...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, onSearchKeyDown: handleSearchKeyDown, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: PRODUCT_PUBLIC_SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, view: view, onViewChange: handleViewToggle, onResetAll: resetAll, hasActiveState: hasActiveState, bulkMode: selection.isSelecting, bulkSelectedCount: selection.selectedCount, bulkTotalCount: products.length, onBulkSelectAll: selection.toggleAll, onBulkClear: selection.clearSelection, toggles: [
136
183
  { label: "Show sold", active: showSold, onChange: (next) => table.set(TABLE_KEYS.SHOW_SOLD, next ? "true" : "") },
137
184
  ] }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
@@ -4,7 +4,7 @@ export function RelatedProducts({ isLoading = false, isEmpty = false, renderGrid
4
4
  if (isLoading) {
5
5
  if (renderSkeleton)
6
6
  return _jsx(_Fragment, { children: renderSkeleton() });
7
- return (_jsx("div", { className: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4 animate-pulse", "data-section": "relatedproducts-div-428", children: Array.from({ length: 4 }).map((_, i) => (_jsx("div", { className: "aspect-square rounded-xl bg-neutral-100" }, i))) }));
7
+ return (_jsx("div", { className: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4 animate-pulse", "data-section": "relatedproducts-div-428", children: Array.from({ length: 4 }).map((_, i) => (_jsx("div", { className: "aspect-square rounded-xl bg-zinc-100 dark:bg-zinc-800" }, i))) }));
8
8
  }
9
9
  if (isEmpty)
10
10
  return null;
@@ -51,7 +51,7 @@ export function ShowGroupSection({ groupId, currentSlug, isParent, groupTitle })
51
51
  const parentLabel = isParent ? `Parts in this group: ${label}` : `Part of: ${label}`;
52
52
  const useDrawer = members.length >= 5;
53
53
  const tableContent = (_jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "w-full text-left min-w-[400px]", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b border-zinc-200 dark:border-zinc-700", children: [_jsx("th", { className: "pb-2 pr-3 text-xs font-semibold text-zinc-500 dark:text-zinc-400", children: "Image" }), _jsx("th", { className: "pb-2 pr-3 text-xs font-semibold text-zinc-500 dark:text-zinc-400", children: "Name" }), _jsx("th", { className: "pb-2 pr-3 text-xs font-semibold text-zinc-500 dark:text-zinc-400", children: "Price" }), _jsx("th", { className: "pb-2 pr-3 text-xs font-semibold text-zinc-500 dark:text-zinc-400", children: "Condition" }), _jsx("th", { className: "pb-2 text-xs font-semibold text-zinc-500 dark:text-zinc-400" })] }) }), _jsx("tbody", { children: members.map((m) => _jsx(GroupTableRow, { member: m }, m.id)) })] }) }));
54
- return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "rounded-xl border border-zinc-200 dark:border-zinc-700 bg-zinc-50/60 dark:bg-zinc-800/40 overflow-hidden", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "w-full flex items-center justify-between px-4 py-3 text-left hover:bg-zinc-100/70 dark:hover:bg-zinc-800/70 transition-colors", "aria-expanded": open, children: [_jsxs(Row, { align: "center", gap: "xs", children: [_jsx("span", { className: "text-xs text-zinc-400 dark:text-zinc-500 mr-1", children: open ? "â–¼" : "â–¶" }), _jsx(Text, { className: "text-sm font-medium text-zinc-800 dark:text-zinc-200", children: parentLabel }), _jsx("span", { className: "ml-1 rounded-full bg-zinc-200 dark:bg-zinc-700 px-2 py-0.5 text-xs text-zinc-600 dark:text-zinc-400", children: members.length })] }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: (e) => { e.stopPropagation(); setShowAll(true); }, className: "text-xs text-[var(--appkit-color-primary,#6366f1)] hover:underline ml-3 flex-shrink-0", children: "View whole group \u00E2\u2020\u2019" })] }), open && (_jsx("div", { className: "px-4 pb-4 pt-1 overflow-x-auto", children: _jsx("div", { className: "flex gap-3 min-w-0", children: [...members]
54
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "rounded-xl border border-zinc-200 dark:border-zinc-700 bg-zinc-50/60 dark:bg-zinc-800/40 overflow-hidden", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "w-full flex items-center justify-between px-4 py-3 text-left hover:bg-zinc-100/70 dark:hover:bg-zinc-800/70 transition-colors", "aria-expanded": open, children: [_jsxs(Row, { align: "center", gap: "xs", children: [_jsx("span", { className: "text-xs text-zinc-400 dark:text-zinc-400 mr-1", children: open ? "â–¼" : "â–¶" }), _jsx(Text, { className: "text-sm font-medium text-zinc-800 dark:text-zinc-200", children: parentLabel }), _jsx("span", { className: "ml-1 rounded-full bg-zinc-200 dark:bg-zinc-700 px-2 py-0.5 text-xs text-zinc-600 dark:text-zinc-400", children: members.length })] }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: (e) => { e.stopPropagation(); setShowAll(true); }, className: "text-xs text-[var(--appkit-color-primary,#6366f1)] hover:underline ml-3 flex-shrink-0", children: "View whole group \u00E2\u2020\u2019" })] }), open && (_jsx("div", { className: "px-4 pb-4 pt-1 overflow-x-auto", children: _jsx("div", { className: "flex gap-3 min-w-0", children: [...members]
55
55
  .sort((a, b) => (b.isGroupParent ? 1 : 0) - (a.isGroupParent ? 1 : 0))
56
56
  .map((m) => (_jsx(MemberThumb, { member: m, isCurrent: m.slug === currentSlug || m.id === currentSlug }, m.id))) }) }))] }), useDrawer ? (_jsx(SideDrawer, { isOpen: showAll, onClose: () => setShowAll(false), title: label, children: tableContent })) : (_jsx(Modal, { open: showAll, onClose: () => setShowAll(false), title: label, children: tableContent }))] }));
57
57
  }
@@ -50,5 +50,5 @@ export function SublistingCarouselSection({ sublistingCategoryId, currentListing
50
50
  if (others.length === 0)
51
51
  return null;
52
52
  const label = category?.name ?? "More listings like this";
53
- return (_jsxs("div", { className: "rounded-xl border border-zinc-200 dark:border-zinc-700 bg-zinc-50/60 dark:bg-zinc-800/40 overflow-hidden", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "w-full flex items-center justify-between px-4 py-3 text-left hover:bg-zinc-100/70 dark:hover:bg-zinc-800/70 transition-colors", "aria-expanded": open, children: [_jsxs(Row, { align: "center", gap: "xs", children: [_jsx("span", { className: "text-xs text-zinc-400 dark:text-zinc-500 mr-1", children: open ? "â–¼" : "â–¶" }), _jsxs(Text, { className: "text-sm font-medium text-zinc-800 dark:text-zinc-200", children: ["More listings like this:", " ", _jsx("span", { className: "text-[var(--appkit-color-primary,#6366f1)]", children: label })] }), _jsx("span", { className: "ml-1 rounded-full bg-zinc-200 dark:bg-zinc-700 px-2 py-0.5 text-xs text-zinc-600 dark:text-zinc-400", children: listings.length })] }), category && (_jsx(Link, { href: String(ROUTES.PUBLIC.SUBLISTING_CATEGORY(category.slug)), onClick: (e) => e.stopPropagation(), className: "text-xs text-[var(--appkit-color-primary,#6366f1)] hover:underline ml-3 flex-shrink-0", children: "View all \u00E2\u2020\u2019" }))] }), open && (_jsx("div", { className: "px-4 pb-4 pt-1 overflow-x-auto", children: _jsx("div", { className: "flex gap-3 min-w-0", children: listings.map((listing) => (_jsx(ListingThumb, { listing: listing, isCurrent: listing.id === currentListingId }, listing.id))) }) }))] }));
53
+ return (_jsxs("div", { className: "rounded-xl border border-zinc-200 dark:border-zinc-700 bg-zinc-50/60 dark:bg-zinc-800/40 overflow-hidden", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "w-full flex items-center justify-between px-4 py-3 text-left hover:bg-zinc-100/70 dark:hover:bg-zinc-800/70 transition-colors", "aria-expanded": open, children: [_jsxs(Row, { align: "center", gap: "xs", children: [_jsx("span", { className: "text-xs text-zinc-400 dark:text-zinc-400 mr-1", children: open ? "â–¼" : "â–¶" }), _jsxs(Text, { className: "text-sm font-medium text-zinc-800 dark:text-zinc-200", children: ["More listings like this:", " ", _jsx("span", { className: "text-[var(--appkit-color-primary,#6366f1)]", children: label })] }), _jsx("span", { className: "ml-1 rounded-full bg-zinc-200 dark:bg-zinc-700 px-2 py-0.5 text-xs text-zinc-600 dark:text-zinc-400", children: listings.length })] }), category && (_jsx(Link, { href: String(ROUTES.PUBLIC.SUBLISTING_CATEGORY(category.slug)), onClick: (e) => e.stopPropagation(), className: "text-xs text-[var(--appkit-color-primary,#6366f1)] hover:underline ml-3 flex-shrink-0", children: "View all \u00E2\u2020\u2019" }))] }), open && (_jsx("div", { className: "px-4 pb-4 pt-1 overflow-x-auto", children: _jsx("div", { className: "flex gap-3 min-w-0", children: listings.map((listing) => (_jsx(ListingThumb, { listing: listing, isCurrent: listing.id === currentListingId }, listing.id))) }) }))] }));
54
54
  }
@@ -36,5 +36,5 @@ export function SublistingCategorySelect({ value, onChange, disabled }) {
36
36
  });
37
37
  return () => { cancelled = true; };
38
38
  }, []);
39
- return (_jsxs(Stack, { gap: "xs", children: [_jsx(Text, { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100", children: "Sub-listing category" }), _jsx(Select, { options: loading ? [{ value: "", label: "Loading…" }] : options, value: value, onChange: (e) => onChange(e.target.value), disabled: disabled || loading, "aria-label": "Sub-listing category" }), _jsx(Text, { className: "text-xs text-zinc-400 dark:text-zinc-500", children: "Groups this listing with others for the same collectible (e.g. \u201CBase Set Charizard 108/120\u201D)." })] }));
39
+ return (_jsxs(Stack, { gap: "xs", children: [_jsx(Text, { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100", children: "Sub-listing category" }), _jsx(Select, { options: loading ? [{ value: "", label: "Loading…" }] : options, value: value, onChange: (e) => onChange(e.target.value), disabled: disabled || loading, "aria-label": "Sub-listing category" }), _jsx(Text, { className: "text-xs text-zinc-400 dark:text-zinc-400", children: "Groups this listing with others for the same collectible (e.g. \u201CBase Set Charizard 108/120\u201D)." })] }));
40
40
  }
@@ -28,8 +28,6 @@ export { FeatureBadge, FeatureBadgeList } from "./FeatureBadge";
28
28
  export type { FeatureBadgeProps, FeatureBadgeListProps, } from "./FeatureBadge";
29
29
  export { ProductFeaturesProvider, useProductFeatures, } from "./ProductFeaturesContext";
30
30
  export type { ProductFeaturesProviderProps } from "./ProductFeaturesContext";
31
- export { BuyBar } from "./BuyBar";
32
- export type { BuyBarProps } from "./BuyBar";
33
31
  export { ProductsView } from "./ProductsView";
34
32
  export type { ProductsViewProps } from "./ProductsView";
35
33
  export { ProductDetailView } from "./ProductDetailView";
@@ -19,7 +19,6 @@ export { ProductFeaturesSelector } from "./ProductFeaturesSelector";
19
19
  export { ProductFeatureBadges } from "./ProductFeatureBadges";
20
20
  export { FeatureBadge, FeatureBadgeList } from "./FeatureBadge";
21
21
  export { ProductFeaturesProvider, useProductFeatures, } from "./ProductFeaturesContext";
22
- export { BuyBar } from "./BuyBar";
23
22
  export { ProductsView } from "./ProductsView";
24
23
  export { ProductDetailView } from "./ProductDetailView";
25
24
  export { AuctionDetailView } from "./AuctionDetailView";
@@ -26,6 +26,13 @@ export declare const ACTION_ID: {
26
26
  readonly RESERVE_NOW: "reserve-now";
27
27
  readonly CANCEL_RESERVATION: "cancel-reservation";
28
28
  readonly CHECKOUT: "checkout";
29
+ readonly CONTINUE_TO_VERIFY: "continue-to-verification";
30
+ readonly SEND_OTP: "send-otp";
31
+ readonly VERIFY_OTP: "verify-otp";
32
+ readonly PAY_ONLINE: "pay-online";
33
+ readonly PAY_COD: "pay-cod";
34
+ readonly APPLY_COUPON: "apply-coupon";
35
+ readonly REMOVE_COUPON: "remove-coupon";
29
36
  readonly ENTER_PRIZE_DRAW: "enter-prize-draw";
30
37
  readonly ENTER_RAFFLE: "enter-raffle";
31
38
  readonly REPORT_LISTING: "report-listing";
@@ -33,6 +33,13 @@ export const ACTION_ID = {
33
33
  CANCEL_RESERVATION: "cancel-reservation",
34
34
  // ── Checkout / navigation CTAs ───────────────────────────────────────────
35
35
  CHECKOUT: "checkout",
36
+ CONTINUE_TO_VERIFY: "continue-to-verification",
37
+ SEND_OTP: "send-otp",
38
+ VERIFY_OTP: "verify-otp",
39
+ PAY_ONLINE: "pay-online",
40
+ PAY_COD: "pay-cod",
41
+ APPLY_COUPON: "apply-coupon",
42
+ REMOVE_COUPON: "remove-coupon",
36
43
  ENTER_PRIZE_DRAW: "enter-prize-draw",
37
44
  ENTER_RAFFLE: "enter-raffle",
38
45
  REPORT_LISTING: "report-listing",
@@ -72,6 +79,13 @@ export const ACTION_META = {
72
79
  [ACTION_ID.CANCEL_RESERVATION]: { id: ACTION_ID.CANCEL_RESERVATION, label: "Cancel Reservation", variant: "danger", iconName: "X", requiresAuth: true, authMessage: "You need to be signed in to cancel a reservation." },
73
80
  // ── Checkout / navigation CTAs ────────────────────────────────────────────
74
81
  [ACTION_ID.CHECKOUT]: { id: ACTION_ID.CHECKOUT, label: "Checkout", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to checkout." },
82
+ [ACTION_ID.CONTINUE_TO_VERIFY]: { id: ACTION_ID.CONTINUE_TO_VERIFY, label: "Continue", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to checkout." },
83
+ [ACTION_ID.SEND_OTP]: { id: ACTION_ID.SEND_OTP, label: "Send Code", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to checkout." },
84
+ [ACTION_ID.VERIFY_OTP]: { id: ACTION_ID.VERIFY_OTP, label: "Verify & Continue", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to checkout." },
85
+ [ACTION_ID.PAY_ONLINE]: { id: ACTION_ID.PAY_ONLINE, label: "Pay Online", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to checkout." },
86
+ [ACTION_ID.PAY_COD]: { id: ACTION_ID.PAY_COD, label: "Cash on Delivery", variant: "secondary", requiresAuth: true, authMessage: "You need to be signed in to checkout." },
87
+ [ACTION_ID.APPLY_COUPON]: { id: ACTION_ID.APPLY_COUPON, label: "Apply", variant: "secondary", requiresAuth: true, authMessage: "You need to be signed in to apply a coupon." },
88
+ [ACTION_ID.REMOVE_COUPON]: { id: ACTION_ID.REMOVE_COUPON, label: "Remove", variant: "ghost", requiresAuth: true, authMessage: "You need to be signed in to manage coupons." },
75
89
  [ACTION_ID.ENTER_PRIZE_DRAW]: { id: ACTION_ID.ENTER_PRIZE_DRAW, label: "Enter Draw", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to enter a prize draw." },
76
90
  [ACTION_ID.ENTER_RAFFLE]: { id: ACTION_ID.ENTER_RAFFLE, label: "Enter Raffle", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to enter a raffle." },
77
91
  [ACTION_ID.REPORT_LISTING]: { id: ACTION_ID.REPORT_LISTING, label: "Report Listing", variant: "ghost", requiresAuth: true, authMessage: "You need to be signed in to report a listing." },
@@ -16,6 +16,8 @@ export interface ListingTab {
16
16
  listingType?: ListingType;
17
17
  /** Set when the tab queries a different collection (e.g. `bundles`). */
18
18
  collection?: "bundles";
19
+ /** Set when the tab queries a non-product entity (e.g. `stores`). */
20
+ entity?: "stores";
19
21
  }
20
22
  /** Tabs shown on `/categories/[slug]` and `/brands/[slug]` detail pages. */
21
23
  export declare const CATEGORY_PAGE_TABS: readonly [{
@@ -38,6 +40,10 @@ export declare const CATEGORY_PAGE_TABS: readonly [{
38
40
  readonly id: "bundles";
39
41
  readonly label: "Bundles";
40
42
  readonly collection: "bundles";
43
+ }, {
44
+ readonly id: "stores";
45
+ readonly label: "Stores";
46
+ readonly entity: "stores";
41
47
  }];
42
48
  export type CategoryTabId = (typeof CATEGORY_PAGE_TABS)[number]["id"];
43
49
  /** Tabs shown on the public `/stores/[slug]` nav bar. */
@@ -15,6 +15,7 @@ export const CATEGORY_PAGE_TABS = [
15
15
  { id: "pre-orders", label: "Pre-Orders", listingType: "pre-order" },
16
16
  { id: "prize-draws", label: "Prize Draws", listingType: "prize-draw" },
17
17
  { id: "bundles", label: "Bundles", collection: "bundles" },
18
+ { id: "stores", label: "Stores", entity: "stores" },
18
19
  ];
19
20
  /** Tabs shown on the public `/stores/[slug]` nav bar. */
20
21
  export const STORE_PAGE_TABS = [
@@ -159,7 +159,7 @@ export function CouponCard({ coupon, labels: labelsProp, onCopy, className = "",
159
159
  };
160
160
  return (_jsxs(Div, { className: `group relative flex h-full flex-col rounded-xl border-2 p-4 ${colors.card} ${isSelected ? "ring-2 ring-primary" : ""} ${!n.isActive ? "opacity-70" : ""} ${className}`, onMouseDown: onSelect && !isSelected ? longPress.onMouseDown : undefined, onMouseUp: onSelect && !isSelected ? longPress.onMouseUp : undefined, onMouseLeave: onSelect && !isSelected ? longPress.onMouseLeave : undefined, onTouchStart: onSelect && !isSelected ? longPress.onTouchStart : undefined, onTouchEnd: onSelect && !isSelected ? longPress.onTouchEnd : undefined, children: [onSelect && (_jsx(BaseListingCard.Checkbox, { selected: isSelected, onSelect: (e) => { e.preventDefault(); onSelect(n.id, !isSelected); }, label: isSelected ? "Deselect coupon" : "Select coupon", position: "top-2 right-2", className: selectable || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), (hasAdminActions || n.scope) && (_jsxs(Row, { gap: "xs", className: "mb-2 flex-wrap", children: [_jsx(Span, { className: `inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide ${n.isActive
161
161
  ? "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300"
162
- : "bg-zinc-200 text-zinc-600 dark:bg-zinc-700 dark:text-zinc-300"}`, children: n.isActive ? labels.active : labels.inactive }), n.scope && (_jsx(Span, { className: "inline-flex items-center rounded-full bg-zinc-200/70 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-zinc-700 dark:bg-zinc-700/60 dark:text-zinc-200", children: n.scope }))] })), _jsxs(Div, { className: "mb-3", children: [_jsx(Text, { className: "text-2xl font-extrabold tracking-tight leading-none", children: discountLabel }), n.name && (_jsx(Text, { className: "text-sm mt-0.5 font-medium opacity-80", children: n.name }))] }), n.description && (_jsx(Text, { className: "text-xs opacity-60 mb-3", children: n.description })), _jsxs("div", { className: `flex items-center gap-2 rounded-lg border border-dashed px-3 py-2 ${colors.code}`, children: [_jsx("span", { className: "flex-1 font-mono text-sm font-bold tracking-widest uppercase select-all", children: n.code || "—" }), n.code && (_jsx("button", { type: "button", onClick: handleCopy, className: "shrink-0 rounded-md px-2.5 py-1 text-xs font-semibold transition-all hover:opacity-80 active:scale-95 bg-white/60 dark:bg-black/20 border border-current/20", "aria-label": "Copy coupon code", children: copied ? labels.copied : labels.copy }))] }), showClaim && n.code && n.isActive && (_jsx("div", { className: "mt-2", children: _jsx("button", { type: "button", onClick: handleClaim, disabled: claiming, className: "w-full rounded-md px-3 py-1.5 text-xs font-semibold transition-all active:scale-95 bg-[var(--appkit-color-primary-700)] text-[var(--appkit-color-text-on-primary,#fff)] hover:bg-[var(--appkit-color-primary-800)] disabled:opacity-50", "aria-label": `Claim coupon ${n.code} and apply at checkout`, children: claiming ? labels.claiming : labels.claim }) })), _jsxs(Row, { wrap: true, gap: "sm", className: "text-xs opacity-60 mt-2", children: [n.minOrderAmount ? (_jsxs(Span, { children: [labels.minOrder, ": \u20B9", (n.minOrderAmount / 100).toFixed(0)] })) : null, expiry && (_jsxs(Span, { children: [labels.expires, ": ", expiry] })), n.usageLimit ? (_jsxs(Span, { children: [n.usageCount, "/", n.usageLimit, " ", labels.used] })) : n.usageCount > 0 ? (_jsxs(Span, { children: [n.usageCount, " ", labels.used] })) : null] }), hasAdminActions && (_jsxs(Row, { gap: "xs", className: "mt-auto pt-3 justify-end", children: [onEdit && (_jsx("button", { type: "button", onClick: () => onEdit(n.id), title: labels.edit, "aria-label": labels.edit, className: "rounded-lg p-1.5 text-zinc-500 hover:bg-white/60 dark:hover:bg-black/30 hover:text-zinc-800 dark:hover:text-zinc-200 transition-colors", children: _jsx(Pencil, { className: "h-4 w-4" }) })), onToggleActive && (_jsx("button", { type: "button", onClick: handleToggle, disabled: busy === "toggle", title: n.isActive ? labels.deactivate : labels.activate, "aria-label": n.isActive ? labels.deactivate : labels.activate, className: "rounded-lg p-1.5 text-zinc-500 hover:bg-white/60 dark:hover:bg-black/30 transition-colors disabled:opacity-50", children: n.isActive
162
+ : "bg-zinc-200 text-zinc-600 dark:bg-zinc-700 dark:text-zinc-300"}`, children: n.isActive ? labels.active : labels.inactive }), n.scope && (_jsx(Span, { className: "inline-flex items-center rounded-full bg-zinc-200/70 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-zinc-700 dark:bg-zinc-700/60 dark:text-zinc-200", children: n.scope }))] })), _jsxs(Div, { className: "mb-3", children: [_jsx(Text, { className: "text-2xl font-extrabold tracking-tight leading-none", children: discountLabel }), n.name && (_jsx(Text, { className: "text-sm mt-0.5 font-medium opacity-80", children: n.name }))] }), n.description && (_jsx(Text, { className: "text-xs opacity-60 mb-3", children: n.description })), _jsxs("div", { className: `flex items-center gap-2 rounded-lg border border-dashed px-3 py-2 ${colors.code}`, children: [_jsx("span", { className: "flex-1 font-mono text-sm font-bold tracking-widest uppercase select-all", children: n.code || "—" }), n.code && (_jsx("button", { type: "button", onClick: handleCopy, className: "shrink-0 rounded-md px-2.5 py-1 text-xs font-semibold transition-all hover:opacity-80 active:scale-95 bg-white/60 dark:bg-black/20 border border-current/20", "aria-label": "Copy coupon code", children: copied ? labels.copied : labels.copy }))] }), showClaim && n.code && n.isActive && (_jsx("div", { className: "mt-2", children: _jsx("button", { type: "button", onClick: handleClaim, disabled: claiming, className: "w-full rounded-md px-3 py-1.5 text-xs font-semibold transition-all active:scale-95 bg-[var(--appkit-color-primary-700)] text-[var(--appkit-color-text-on-primary,#fff)] hover:bg-[var(--appkit-color-primary-800)] disabled:opacity-50", "aria-label": `Claim coupon ${n.code} and apply at checkout`, children: claiming ? labels.claiming : labels.claim }) })), _jsxs(Row, { wrap: true, gap: "sm", className: "text-xs opacity-60 mt-2", children: [n.minOrderAmount ? (_jsxs(Span, { children: [labels.minOrder, ": \u20B9", (n.minOrderAmount / 100).toFixed(0)] })) : null, expiry && (_jsxs(Span, { children: [labels.expires, ": ", expiry] })), n.usageLimit ? (_jsxs(Span, { children: [n.usageCount, "/", n.usageLimit, " ", labels.used] })) : n.usageCount > 0 ? (_jsxs(Span, { children: [n.usageCount, " ", labels.used] })) : null] }), hasAdminActions && (_jsxs(Row, { gap: "xs", className: "mt-auto pt-3 justify-end", children: [onEdit && (_jsx("button", { type: "button", onClick: () => onEdit(n.id), title: labels.edit, "aria-label": labels.edit, className: "rounded-lg p-1.5 text-zinc-500 dark:text-zinc-400 hover:bg-white/60 dark:hover:bg-black/30 hover:text-zinc-800 dark:hover:text-zinc-200 transition-colors", children: _jsx(Pencil, { className: "h-4 w-4" }) })), onToggleActive && (_jsx("button", { type: "button", onClick: handleToggle, disabled: busy === "toggle", title: n.isActive ? labels.deactivate : labels.activate, "aria-label": n.isActive ? labels.deactivate : labels.activate, className: "rounded-lg p-1.5 text-zinc-500 dark:text-zinc-400 hover:bg-white/60 dark:hover:bg-black/30 transition-colors disabled:opacity-50", children: n.isActive
163
163
  ? _jsx(ToggleRight, { className: "h-4 w-4 text-emerald-600 dark:text-emerald-400" })
164
- : _jsx(ToggleLeft, { className: "h-4 w-4" }) })), onDelete && (_jsx("button", { type: "button", onClick: handleDelete, disabled: busy === "delete", title: labels.delete, "aria-label": labels.delete, className: "rounded-lg p-1.5 text-zinc-500 hover:bg-red-50 dark:hover:bg-red-950/40 hover:text-red-600 dark:hover:text-red-400 transition-colors disabled:opacity-50", children: _jsx(Trash2, { className: "h-4 w-4" }) }))] }))] }));
164
+ : _jsx(ToggleLeft, { className: "h-4 w-4" }) })), onDelete && (_jsx("button", { type: "button", onClick: handleDelete, disabled: busy === "delete", title: labels.delete, "aria-label": labels.delete, className: "rounded-lg p-1.5 text-zinc-500 dark:text-zinc-400 hover:bg-red-50 dark:hover:bg-red-950/40 hover:text-red-600 dark:hover:text-red-400 transition-colors disabled:opacity-50", children: _jsx(Trash2, { className: "h-4 w-4" }) }))] }))] }));
165
165
  }
@@ -90,12 +90,12 @@ export function CouponsIndexListing({ initialCoupons, storeSlug, storeId, }) {
90
90
  };
91
91
  return (_jsxs("div", { className: "min-h-[40vh]", children: [_jsxs("div", { className: "sticky top-[var(--header-height,0px)] z-20 border-b border-zinc-200 dark:border-slate-700 bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm py-2.5 px-4", children: [_jsxs("div", { className: "flex items-center gap-2.5 max-w-full", children: [_jsxs("button", { type: "button", onClick: openFilters, className: `flex shrink-0 items-center gap-2 rounded-lg border px-3.5 py-2 text-sm font-medium transition-colors ${hasActiveFilters
92
92
  ? "border-primary bg-primary-50 text-primary-700 dark:bg-primary-900/30 dark:text-primary-300"
93
- : "border-zinc-300 dark:border-slate-600 text-zinc-700 dark:text-zinc-200 hover:bg-zinc-50 dark:hover:bg-slate-800"}`, children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), _jsxs("span", { className: "hidden sm:inline", children: ["Filters", hasActiveFilters ? " •" : ""] })] }), _jsxs("div", { className: "flex flex-1 items-center overflow-hidden rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-900", children: [_jsx("input", { type: "text", value: searchInput, onChange: (e) => setSearchInput(e.target.value), onKeyDown: handleKeyDown, placeholder: "Search by name or description\u2026", className: "min-w-0 flex-1 bg-transparent px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 placeholder-zinc-400 outline-none" }), searchInput && (_jsx("button", { type: "button", onClick: () => { setSearchInput(""); table.set(TABLE_KEYS.QUERY, ""); }, className: "p-2 text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300", "aria-label": "Clear search", children: _jsx(X, { className: "h-3.5 w-3.5" }) })), _jsx("button", { type: "button", onClick: commitSearch, className: "flex shrink-0 items-center justify-center px-3 py-2 text-zinc-400 hover:text-primary dark:hover:text-primary-400 transition-colors", "aria-label": "Search", children: _jsx(Search, { className: "h-4 w-4" }) })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1.5 text-sm text-zinc-500 dark:text-zinc-400", children: [_jsx("span", { className: "hidden md:inline whitespace-nowrap", children: "Sort by" }), _jsx(SortDropdown, { value: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, onChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, options: COUPON_SORT_OPTIONS })] })] }), hasActiveFilters && (_jsxs("div", { className: "flex flex-wrap items-center gap-2 mt-2", children: [activeType && (_jsxs("span", { className: "flex items-center gap-1 rounded-full bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300 text-xs font-medium px-2.5 py-1", children: [COUPON_TYPES.find((t) => t.value === activeType)?.label ?? activeType, _jsx("button", { type: "button", onClick: () => { table.set(TABLE_KEYS.TYPE, ""); }, "aria-label": "Remove type filter", children: _jsx(X, { className: "h-3 w-3" }) })] })), table.get(TABLE_KEYS.DATE_FROM) && (_jsxs("span", { className: "flex items-center gap-1 rounded-full bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300 text-xs font-medium px-2.5 py-1", children: ["From: ", table.get(TABLE_KEYS.DATE_FROM), _jsx("button", { type: "button", onClick: () => { table.set(TABLE_KEYS.DATE_FROM, ""); }, "aria-label": "Remove from-date filter", children: _jsx(X, { className: "h-3 w-3" }) })] })), table.get(TABLE_KEYS.DATE_TO) && (_jsxs("span", { className: "flex items-center gap-1 rounded-full bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300 text-xs font-medium px-2.5 py-1", children: ["To: ", table.get(TABLE_KEYS.DATE_TO), _jsx("button", { type: "button", onClick: () => { table.set(TABLE_KEYS.DATE_TO, ""); }, "aria-label": "Remove to-date filter", children: _jsx(X, { className: "h-3 w-3" }) })] })), _jsx("button", { type: "button", onClick: clearFilters, className: "text-xs text-zinc-500 hover:text-zinc-700 dark:hover:text-zinc-300 underline", children: "Clear all" })] }))] }), _jsxs("div", { className: "py-6 px-4", children: [isLoading ? (_jsx("div", { className: "grid gap-3 md:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsxs("div", { className: "rounded-xl border-2 border-zinc-100 dark:border-slate-700 p-4 animate-pulse space-y-3", children: [_jsx("div", { className: "h-6 bg-zinc-200 dark:bg-slate-700 rounded w-2/3" }), _jsx("div", { className: "h-4 bg-zinc-200 dark:bg-slate-700 rounded w-full" }), _jsx("div", { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-1/2" })] }, i))) })) : displayCoupons.length === 0 ? (_jsx("div", { className: "py-16 text-center", children: _jsx(Text, { className: "text-zinc-400 dark:text-zinc-500", children: "No coupons match your search." }) })) : (_jsx("div", { className: "grid gap-3 md:grid-cols-2 lg:grid-cols-3", children: displayCoupons.map((coupon) => (_jsx(CouponCard, { coupon: coupon, labels: {
93
+ : "border-zinc-300 dark:border-slate-600 text-zinc-700 dark:text-zinc-200 hover:bg-zinc-50 dark:hover:bg-slate-800"}`, children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), _jsxs("span", { className: "hidden sm:inline", children: ["Filters", hasActiveFilters ? " •" : ""] })] }), _jsxs("div", { className: "flex flex-1 items-center overflow-hidden rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-900", children: [_jsx("input", { type: "text", value: searchInput, onChange: (e) => setSearchInput(e.target.value), onKeyDown: handleKeyDown, placeholder: "Search by name or description\u2026", className: "min-w-0 flex-1 bg-transparent px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 placeholder-zinc-400 outline-none" }), searchInput && (_jsx("button", { type: "button", onClick: () => { setSearchInput(""); table.set(TABLE_KEYS.QUERY, ""); }, className: "p-2 text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300", "aria-label": "Clear search", children: _jsx(X, { className: "h-3.5 w-3.5" }) })), _jsx("button", { type: "button", onClick: commitSearch, className: "flex shrink-0 items-center justify-center px-3 py-2 text-zinc-400 hover:text-primary dark:hover:text-primary-400 transition-colors", "aria-label": "Search", children: _jsx(Search, { className: "h-4 w-4" }) })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1.5 text-sm text-zinc-500 dark:text-zinc-400", children: [_jsx("span", { className: "hidden md:inline whitespace-nowrap", children: "Sort by" }), _jsx(SortDropdown, { value: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, onChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, options: COUPON_SORT_OPTIONS })] })] }), hasActiveFilters && (_jsxs("div", { className: "flex flex-wrap items-center gap-2 mt-2", children: [activeType && (_jsxs("span", { className: "flex items-center gap-1 rounded-full bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300 text-xs font-medium px-2.5 py-1", children: [COUPON_TYPES.find((t) => t.value === activeType)?.label ?? activeType, _jsx("button", { type: "button", onClick: () => { table.set(TABLE_KEYS.TYPE, ""); }, "aria-label": "Remove type filter", children: _jsx(X, { className: "h-3 w-3" }) })] })), table.get(TABLE_KEYS.DATE_FROM) && (_jsxs("span", { className: "flex items-center gap-1 rounded-full bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300 text-xs font-medium px-2.5 py-1", children: ["From: ", table.get(TABLE_KEYS.DATE_FROM), _jsx("button", { type: "button", onClick: () => { table.set(TABLE_KEYS.DATE_FROM, ""); }, "aria-label": "Remove from-date filter", children: _jsx(X, { className: "h-3 w-3" }) })] })), table.get(TABLE_KEYS.DATE_TO) && (_jsxs("span", { className: "flex items-center gap-1 rounded-full bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300 text-xs font-medium px-2.5 py-1", children: ["To: ", table.get(TABLE_KEYS.DATE_TO), _jsx("button", { type: "button", onClick: () => { table.set(TABLE_KEYS.DATE_TO, ""); }, "aria-label": "Remove to-date filter", children: _jsx(X, { className: "h-3 w-3" }) })] })), _jsx("button", { type: "button", onClick: clearFilters, className: "text-xs text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-300 underline", children: "Clear all" })] }))] }), _jsxs("div", { className: "py-6 px-4", children: [isLoading ? (_jsx("div", { className: "grid gap-3 md:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsxs("div", { className: "rounded-xl border-2 border-zinc-100 dark:border-slate-700 p-4 animate-pulse space-y-3", children: [_jsx("div", { className: "h-6 bg-zinc-200 dark:bg-slate-700 rounded w-2/3" }), _jsx("div", { className: "h-4 bg-zinc-200 dark:bg-slate-700 rounded w-full" }), _jsx("div", { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-1/2" })] }, i))) })) : displayCoupons.length === 0 ? (_jsx("div", { className: "py-16 text-center", children: _jsx(Text, { className: "text-zinc-400 dark:text-zinc-400", children: "No coupons match your search." }) })) : (_jsx("div", { className: "grid gap-3 md:grid-cols-2 lg:grid-cols-3", children: displayCoupons.map((coupon) => (_jsx(CouponCard, { coupon: coupon, labels: {
94
94
  copy: "Copy",
95
95
  copied: "Copied!",
96
96
  expires: "Expires",
97
97
  minOrder: "Min. order",
98
98
  off: "OFF",
99
99
  freeShipping: "Free Shipping",
100
- } }, coupon.id))) })), totalPages > 1 && (_jsx("div", { className: "mt-8 flex justify-center", children: _jsx(Pagination, { currentPage: table.getNumber("page", 1), totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), !isLoading && total > 0 && (_jsx(Div, { className: "mt-4 text-center", children: _jsxs(Text, { className: "text-xs text-zinc-400 dark:text-zinc-500", children: [total, " coupon", total !== 1 ? "s" : "", " available"] }) }))] }), filterOpen && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-40 bg-black/40", "aria-hidden": "true", onClick: () => setFilterOpen(false) }), _jsxs("div", { className: "fixed inset-y-0 left-0 z-50 flex w-80 flex-col bg-white dark:bg-slate-900 shadow-2xl", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: [_jsxs("span", { className: "flex items-center gap-2 text-base font-semibold text-zinc-900 dark:text-zinc-100", children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), "Filters"] }), _jsx("button", { type: "button", onClick: () => setFilterOpen(false), "aria-label": "Close filters", className: "rounded-lg p-1.5 text-zinc-500 hover:bg-zinc-100 dark:hover:bg-slate-800 transition-colors", children: _jsx(X, { className: "h-5 w-5" }) })] }), _jsxs("div", { className: "flex-1 overflow-y-auto px-4 py-4 space-y-6", children: [_jsxs(_Fragment, { children: [_jsx(Heading, { level: 6, className: "text-xs font-semibold uppercase tracking-wider text-zinc-500 dark:text-zinc-400 mb-3", children: "Discount Type" }), _jsxs("div", { className: "space-y-2", children: [COUPON_TYPES.map((t) => (_jsxs("label", { className: "flex items-center gap-2 cursor-pointer text-sm text-zinc-700 dark:text-zinc-300", children: [_jsx("input", { type: "radio", name: "coupon-type", value: t.value, checked: pendingTable.get(TABLE_KEYS.TYPE) === t.value, onChange: () => { pendingTable.set(TABLE_KEYS.TYPE, t.value); }, className: "accent-primary" }), t.label] }, t.value))), pendingTable.get(TABLE_KEYS.TYPE) && (_jsx("button", { type: "button", onClick: () => { pendingTable.set(TABLE_KEYS.TYPE, ""); }, className: "text-xs text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300 underline", children: "Clear type" }))] })] }), _jsxs(_Fragment, { children: [_jsx(Heading, { level: 6, className: "text-xs font-semibold uppercase tracking-wider text-zinc-500 dark:text-zinc-400 mb-3", children: "Valid Date Range" }), _jsxs("div", { className: "space-y-3", children: [_jsxs(_Fragment, { children: [_jsx("label", { className: "block text-xs text-zinc-500 dark:text-zinc-400 mb-1", children: "From date" }), _jsx("input", { type: "date", value: pendingTable.get(TABLE_KEYS.DATE_FROM) || "", onChange: (e) => { pendingTable.set(TABLE_KEYS.DATE_FROM, e.target.value); }, className: "w-full rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 outline-none focus:ring-2 focus:ring-primary" })] }), _jsxs(_Fragment, { children: [_jsx("label", { className: "block text-xs text-zinc-500 dark:text-zinc-400 mb-1", children: "To date" }), _jsx("input", { type: "date", value: pendingTable.get(TABLE_KEYS.DATE_TO) || "", onChange: (e) => { pendingTable.set(TABLE_KEYS.DATE_TO, e.target.value); }, className: "w-full rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 outline-none focus:ring-2 focus:ring-primary" })] })] })] })] }), _jsxs("div", { className: "border-t border-zinc-200 dark:border-slate-700 px-4 py-3.5 flex gap-2", children: [_jsx("button", { type: "button", onClick: clearPending, className: "flex-1 rounded-lg border border-zinc-300 dark:border-slate-600 py-2.5 text-sm font-medium text-zinc-700 dark:text-zinc-200 hover:bg-zinc-50 dark:hover:bg-slate-800 transition-colors", children: "Clear all" }), _jsx("button", { type: "button", onClick: applyFilters, className: "flex-1 rounded-lg bg-primary py-2.5 text-sm font-semibold text-white hover:bg-primary-600 transition-colors", children: "Apply Filters" })] })] })] }))] }));
100
+ } }, coupon.id))) })), totalPages > 1 && (_jsx("div", { className: "mt-8 flex justify-center", children: _jsx(Pagination, { currentPage: table.getNumber("page", 1), totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), !isLoading && total > 0 && (_jsx(Div, { className: "mt-4 text-center", children: _jsxs(Text, { className: "text-xs text-zinc-400 dark:text-zinc-400", children: [total, " coupon", total !== 1 ? "s" : "", " available"] }) }))] }), filterOpen && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-40 bg-black/40", "aria-hidden": "true", onClick: () => setFilterOpen(false) }), _jsxs("div", { className: "fixed inset-y-0 left-0 z-50 flex w-80 flex-col bg-white dark:bg-slate-900 shadow-2xl", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: [_jsxs("span", { className: "flex items-center gap-2 text-base font-semibold text-zinc-900 dark:text-zinc-100", children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), "Filters"] }), _jsx("button", { type: "button", onClick: () => setFilterOpen(false), "aria-label": "Close filters", className: "rounded-lg p-1.5 text-zinc-500 dark:text-zinc-400 hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors", children: _jsx(X, { className: "h-5 w-5" }) })] }), _jsxs("div", { className: "flex-1 overflow-y-auto px-4 py-4 space-y-6", children: [_jsxs(_Fragment, { children: [_jsx(Heading, { level: 6, className: "text-xs font-semibold uppercase tracking-wider text-zinc-500 dark:text-zinc-400 mb-3", children: "Discount Type" }), _jsxs("div", { className: "space-y-2", children: [COUPON_TYPES.map((t) => (_jsxs("label", { className: "flex items-center gap-2 cursor-pointer text-sm text-zinc-700 dark:text-zinc-300", children: [_jsx("input", { type: "radio", name: "coupon-type", value: t.value, checked: pendingTable.get(TABLE_KEYS.TYPE) === t.value, onChange: () => { pendingTable.set(TABLE_KEYS.TYPE, t.value); }, className: "accent-primary" }), t.label] }, t.value))), pendingTable.get(TABLE_KEYS.TYPE) && (_jsx("button", { type: "button", onClick: () => { pendingTable.set(TABLE_KEYS.TYPE, ""); }, className: "text-xs text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300 underline", children: "Clear type" }))] })] }), _jsxs(_Fragment, { children: [_jsx(Heading, { level: 6, className: "text-xs font-semibold uppercase tracking-wider text-zinc-500 dark:text-zinc-400 mb-3", children: "Valid Date Range" }), _jsxs("div", { className: "space-y-3", children: [_jsxs(_Fragment, { children: [_jsx("label", { className: "block text-xs text-zinc-500 dark:text-zinc-400 mb-1", children: "From date" }), _jsx("input", { type: "date", value: pendingTable.get(TABLE_KEYS.DATE_FROM) || "", onChange: (e) => { pendingTable.set(TABLE_KEYS.DATE_FROM, e.target.value); }, className: "w-full rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 outline-none focus:ring-2 focus:ring-primary" })] }), _jsxs(_Fragment, { children: [_jsx("label", { className: "block text-xs text-zinc-500 dark:text-zinc-400 mb-1", children: "To date" }), _jsx("input", { type: "date", value: pendingTable.get(TABLE_KEYS.DATE_TO) || "", onChange: (e) => { pendingTable.set(TABLE_KEYS.DATE_TO, e.target.value); }, className: "w-full rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 outline-none focus:ring-2 focus:ring-primary" })] })] })] })] }), _jsxs("div", { className: "border-t border-zinc-200 dark:border-slate-700 px-4 py-3.5 flex gap-2", children: [_jsx("button", { type: "button", onClick: clearPending, className: "flex-1 rounded-lg border border-zinc-300 dark:border-slate-600 py-2.5 text-sm font-medium text-zinc-700 dark:text-zinc-200 hover:bg-zinc-50 dark:hover:bg-slate-800 transition-colors", children: "Clear all" }), _jsx("button", { type: "button", onClick: applyFilters, className: "flex-1 rounded-lg bg-primary py-2.5 text-sm font-semibold text-white hover:bg-primary-600 transition-colors", children: "Apply Filters" })] })] })] }))] }));
101
101
  }
@@ -12,5 +12,5 @@ export async function ReviewDetailPageView({ id }) {
12
12
  if (!review || review.status !== "approved") {
13
13
  return (_jsx(Main, { children: _jsx(Section, { className: "py-24", children: _jsx(Container, { size: "sm", children: _jsxs("div", { className: "text-center", children: [_jsx(Text, { className: "text-5xl mb-4", "aria-hidden": "true", children: "\uD83D\uDD0D" }), _jsx(Heading, { level: 1, className: "text-2xl font-bold text-neutral-900 dark:text-white mb-2", children: "Review not found" }), _jsx(Text, { className: "text-sm text-neutral-500 dark:text-zinc-400 mb-6", children: "This review may have been removed or is no longer available." }), _jsx(Link, { href: String(ROUTES.PUBLIC.REVIEWS), className: "inline-flex items-center gap-2 rounded-lg bg-primary px-5 py-2.5 text-sm font-medium text-white hover:bg-primary-600 transition-colors", children: "\u2190 Back to Reviews" })] }) }) }) }));
14
14
  }
15
- return (_jsxs(Main, { children: [_jsx("div", { className: "border-b border-neutral-100 dark:border-zinc-800 bg-neutral-50 dark:bg-zinc-950 py-2.5 px-4", children: _jsxs("nav", { className: "mx-auto max-w-3xl flex items-center gap-1.5 text-xs text-neutral-400 dark:text-zinc-500", "aria-label": "Breadcrumb", children: [_jsx(Link, { href: String(ROUTES.HOME), className: "hover:text-primary transition-colors", children: "Home" }), _jsx("span", { children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.REVIEWS), className: "hover:text-primary transition-colors", children: "Reviews" }), _jsx("span", { children: "/" }), _jsx("span", { className: "text-neutral-700 dark:text-zinc-300 truncate max-w-[200px]", children: review.title ?? review.id })] }) }), _jsx(ReviewDetailShell, { review: review, storeHref: storeSlug ? String(ROUTES.PUBLIC.STORE_DETAIL(storeSlug)) : null })] }));
15
+ return (_jsxs(Main, { children: [_jsx("div", { className: "border-b border-neutral-100 dark:border-zinc-800 bg-neutral-50 dark:bg-zinc-950 py-2.5 px-4", children: _jsxs("nav", { className: "mx-auto max-w-3xl flex items-center gap-1.5 text-xs text-zinc-400 dark:text-zinc-400", "aria-label": "Breadcrumb", children: [_jsx(Link, { href: String(ROUTES.HOME), className: "hover:text-primary transition-colors", children: "Home" }), _jsx("span", { children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.REVIEWS), className: "hover:text-primary transition-colors", children: "Reviews" }), _jsx("span", { children: "/" }), _jsx("span", { className: "text-neutral-700 dark:text-zinc-300 truncate max-w-[200px]", children: review.title ?? review.id })] }) }), _jsx(ReviewDetailShell, { review: review, storeHref: storeSlug ? String(ROUTES.PUBLIC.STORE_DETAIL(storeSlug)) : null })] }));
16
16
  }
@@ -2,7 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { useState, useEffect, useCallback } from "react";
4
4
  const CLS_RELATED_LINK = "group flex items-center gap-3 rounded-xl border border-neutral-200 dark:border-zinc-700 bg-white dark:bg-zinc-900 p-4 hover:border-primary hover:shadow-sm transition-all";
5
- const CLS_RELATED_LABEL = "text-xs text-neutral-400 dark:text-zinc-500 mb-0.5";
5
+ const CLS_RELATED_LABEL = "text-xs text-zinc-400 dark:text-zinc-400 mb-0.5";
6
6
  const CLS_RELATED_TITLE = "text-sm font-medium text-neutral-900 dark:text-white truncate group-hover:text-primary transition-colors";
7
7
  import Link from "next/link";
8
8
  import { Heading, RichText, Section, Span, StarRating, Text } from "../../../ui";
@@ -77,9 +77,9 @@ export function ReviewDetailShell({ review, storeHref }) {
77
77
  ? String(ROUTES.PUBLIC.PROFILE(reviewerProfileId))
78
78
  : null;
79
79
  const currentImage = lightboxIdx !== null ? images[lightboxIdx] : null;
80
- return (_jsxs(_Fragment, { children: [_jsx("div", { className: "border-b border-neutral-200 dark:border-zinc-800 bg-white dark:bg-zinc-900 pb-8 pt-10", children: _jsxs("div", { className: "mx-auto max-w-3xl px-4", children: [_jsxs("div", { className: "mb-4 flex items-center gap-3", children: [_jsx(StarRating, { value: review.rating, size: "lg", readOnly: true }), _jsxs("span", { className: "text-2xl font-bold text-neutral-900 dark:text-white", children: [review.rating, ".0"] }), review.verified && (_jsx("span", { className: "inline-flex items-center gap-1 rounded-full bg-emerald-100 px-3 py-1 text-xs font-semibold text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400", children: "\u2713 Verified Purchase" })), review.featured && (_jsx("span", { className: "inline-flex items-center gap-1 rounded-full bg-yellow-100 px-3 py-1 text-xs font-semibold text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400", children: "\u2605 Featured" }))] }), review.title && (_jsx(Heading, { level: 1, className: "text-2xl font-bold text-neutral-900 dark:text-white mb-4 leading-snug", children: review.title })), _jsxs("div", { className: "flex items-center gap-3", children: [review.userAvatar ? (_jsx("div", { role: "img", "aria-label": displayName, className: "h-11 w-11 flex-shrink-0 rounded-full bg-center bg-cover ring-2 ring-white dark:ring-zinc-800", style: { backgroundImage: `url(${review.userAvatar})` } })) : (_jsx("div", { className: "flex h-11 w-11 flex-shrink-0 items-center justify-center rounded-full bg-primary/10 text-base font-bold text-primary ring-2 ring-white dark:ring-zinc-800", children: initials })), _jsxs("div", { className: "min-w-0", children: [reviewerHref ? (_jsx(Link, { href: reviewerHref, className: "text-sm font-semibold text-neutral-900 dark:text-white hover:text-primary transition-colors", children: displayName })) : (_jsx("span", { className: "text-sm font-semibold text-neutral-900 dark:text-white", children: review.isAnonymous ? "Anonymous" : displayName })), date && (_jsx(Text, { className: "text-xs text-neutral-400 dark:text-zinc-500 mt-0.5", children: date }))] })] })] }) }), _jsxs("div", { className: "mx-auto max-w-3xl px-4 py-8 space-y-8", children: [review.comment && (_jsx(Section, { children: _jsx(RichText, { html: normalizeRichTextHtml(review.comment), proseClass: "prose prose-neutral dark:prose-invert max-w-none prose-p:leading-relaxed prose-headings:font-semibold prose-img:rounded-lg prose-a:text-primary", className: "text-neutral-700 dark:text-zinc-300" }) })), images.length > 0 && (_jsxs(Section, { children: [_jsxs(Heading, { level: 2, className: "text-sm font-semibold uppercase tracking-wide text-neutral-400 dark:text-zinc-500 mb-3", children: ["Photos (", images.length, ")"] }), _jsx("div", { className: "grid grid-cols-3 sm:grid-cols-4 gap-2", children: images.map((img, i) => (_jsxs("button", { type: "button", onClick: () => setLightboxIdx(i), "aria-label": `View photo ${i + 1}`, className: "group relative aspect-square overflow-hidden rounded-xl border border-neutral-200 dark:border-zinc-700 bg-neutral-100 dark:bg-zinc-800 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary", children: [_jsx("div", { className: "h-full w-full bg-center bg-cover transition-transform duration-300 group-hover:scale-105", style: { backgroundImage: `url(${img.thumbnailUrl ?? img.url})` } }), _jsx("div", { className: "absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity bg-black/30", children: _jsx("span", { className: "text-white text-xl", children: "\uD83D\uDD0D" }) })] }, i))) })] })), review.video && (_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "text-sm font-semibold uppercase tracking-wide text-neutral-400 dark:text-zinc-500 mb-3", children: "Video" }), _jsx("div", { className: "overflow-hidden rounded-xl border border-neutral-200 dark:border-zinc-700 bg-black aspect-video", children: _jsx("video", { src: review.video.url, poster: review.video.thumbnailUrl, controls: true, className: "h-full w-full", preload: "metadata" }) })] })), _jsxs(Section, { className: "flex items-center gap-4 py-4 border-t border-neutral-100 dark:border-zinc-800", children: [_jsx("div", { className: "text-sm text-neutral-500 dark:text-zinc-400", children: helpfulCount > 0 && (_jsxs("span", { children: [_jsx("strong", { className: "text-neutral-900 dark:text-white", children: helpfulCount }), " ", helpfulCount === 1 ? "person" : "people", " found this helpful"] })) }), _jsxs("button", { type: "button", onClick: handleVote, disabled: voted || voting, className: `ml-auto flex items-center gap-2 rounded-lg border px-4 py-2 text-sm font-medium transition-colors ${voted
80
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: "border-b border-neutral-200 dark:border-zinc-800 bg-white dark:bg-zinc-900 pb-8 pt-10", children: _jsxs("div", { className: "mx-auto max-w-3xl px-4", children: [_jsxs("div", { className: "mb-4 flex items-center gap-3", children: [_jsx(StarRating, { value: review.rating, size: "lg", readOnly: true }), _jsxs("span", { className: "text-2xl font-bold text-neutral-900 dark:text-white", children: [review.rating, ".0"] }), review.verified && (_jsx("span", { className: "inline-flex items-center gap-1 rounded-full bg-emerald-100 px-3 py-1 text-xs font-semibold text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400", children: "\u2713 Verified Purchase" })), review.featured && (_jsx("span", { className: "inline-flex items-center gap-1 rounded-full bg-yellow-100 px-3 py-1 text-xs font-semibold text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400", children: "\u2605 Featured" }))] }), review.title && (_jsx(Heading, { level: 1, className: "text-2xl font-bold text-neutral-900 dark:text-white mb-4 leading-snug", children: review.title })), _jsxs("div", { className: "flex items-center gap-3", children: [review.userAvatar ? (_jsx("div", { role: "img", "aria-label": displayName, className: "h-11 w-11 flex-shrink-0 rounded-full bg-center bg-cover ring-2 ring-white dark:ring-zinc-800", style: { backgroundImage: `url(${review.userAvatar})` } })) : (_jsx("div", { className: "flex h-11 w-11 flex-shrink-0 items-center justify-center rounded-full bg-primary/10 text-base font-bold text-primary ring-2 ring-white dark:ring-zinc-800", children: initials })), _jsxs("div", { className: "min-w-0", children: [reviewerHref ? (_jsx(Link, { href: reviewerHref, className: "text-sm font-semibold text-neutral-900 dark:text-white hover:text-primary transition-colors", children: displayName })) : (_jsx("span", { className: "text-sm font-semibold text-neutral-900 dark:text-white", children: review.isAnonymous ? "Anonymous" : displayName })), date && (_jsx(Text, { className: "text-xs text-zinc-400 dark:text-zinc-400 mt-0.5", children: date }))] })] })] }) }), _jsxs("div", { className: "mx-auto max-w-3xl px-4 py-8 space-y-8", children: [review.comment && (_jsx(Section, { children: _jsx(RichText, { html: normalizeRichTextHtml(review.comment), proseClass: "prose prose-neutral dark:prose-invert max-w-none prose-p:leading-relaxed prose-headings:font-semibold prose-img:rounded-lg prose-a:text-primary", className: "text-neutral-700 dark:text-zinc-300" }) })), images.length > 0 && (_jsxs(Section, { children: [_jsxs(Heading, { level: 2, className: "text-sm font-semibold uppercase tracking-wide text-zinc-400 dark:text-zinc-400 mb-3", children: ["Photos (", images.length, ")"] }), _jsx("div", { className: "grid grid-cols-3 sm:grid-cols-4 gap-2", children: images.map((img, i) => (_jsxs("button", { type: "button", onClick: () => setLightboxIdx(i), "aria-label": `View photo ${i + 1}`, className: "group relative aspect-square overflow-hidden rounded-xl border border-neutral-200 dark:border-zinc-700 bg-neutral-100 dark:bg-zinc-800 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary", children: [_jsx("div", { className: "h-full w-full bg-center bg-cover transition-transform duration-300 group-hover:scale-105", style: { backgroundImage: `url(${img.thumbnailUrl ?? img.url})` } }), _jsx("div", { className: "absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity bg-black/30", children: _jsx("span", { className: "text-white text-xl", children: "\uD83D\uDD0D" }) })] }, i))) })] })), review.video && (_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "text-sm font-semibold uppercase tracking-wide text-zinc-400 dark:text-zinc-400 mb-3", children: "Video" }), _jsx("div", { className: "overflow-hidden rounded-xl border border-neutral-200 dark:border-zinc-700 bg-black aspect-video", children: _jsx("video", { src: review.video.url, poster: review.video.thumbnailUrl, controls: true, className: "h-full w-full", preload: "metadata" }) })] })), _jsxs(Section, { className: "flex items-center gap-4 py-4 border-t border-neutral-100 dark:border-zinc-800", children: [_jsx("div", { className: "text-sm text-neutral-500 dark:text-zinc-400", children: helpfulCount > 0 && (_jsxs("span", { children: [_jsx("strong", { className: "text-neutral-900 dark:text-white", children: helpfulCount }), " ", helpfulCount === 1 ? "person" : "people", " found this helpful"] })) }), _jsxs("button", { type: "button", onClick: handleVote, disabled: voted || voting, className: `ml-auto flex items-center gap-2 rounded-lg border px-4 py-2 text-sm font-medium transition-colors ${voted
81
81
  ? "border-emerald-200 bg-emerald-50 text-emerald-600 dark:border-emerald-800 dark:bg-emerald-900/20 dark:text-emerald-400 cursor-default"
82
- : "border-neutral-300 dark:border-zinc-600 text-neutral-700 dark:text-zinc-200 hover:border-primary hover:text-primary dark:hover:border-primary dark:hover:text-primary disabled:opacity-50"}`, children: [_jsx("span", { "aria-hidden": "true", children: voted ? "✓" : "👍" }), voted ? "Marked helpful" : voting ? "Saving…" : "Helpful?"] })] }), _jsxs(Section, { className: "grid gap-3 sm:grid-cols-3", children: [productHref && (_jsxs(Link, { href: productHref, className: CLS_RELATED_LINK, children: [_jsx("span", { className: "flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-orange-100 dark:bg-orange-900/30 text-xl", children: "\uD83D\uDCE6" }), _jsxs("div", { className: "min-w-0", children: [_jsx(Text, { className: CLS_RELATED_LABEL, children: "Product" }), _jsx(Text, { className: CLS_RELATED_TITLE, children: review.productTitle ?? "View Product" })] })] })), sellerHref && (_jsxs(Link, { href: sellerHref, className: CLS_RELATED_LINK, children: [_jsx("span", { className: "flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-blue-100 dark:bg-blue-900/30 text-xl", children: "\uD83C\uDFEA" }), _jsxs("div", { className: "min-w-0", children: [_jsx(Text, { className: CLS_RELATED_LABEL, children: "Seller" }), _jsx(Text, { className: CLS_RELATED_TITLE, children: "View Seller" })] })] })), reviewerHref ? (_jsxs(Link, { href: reviewerHref, className: CLS_RELATED_LINK, children: [_jsx("span", { className: "flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-purple-100 dark:bg-purple-900/30 text-xl", children: "\uD83D\uDC64" }), _jsxs("div", { className: "min-w-0", children: [_jsx(Text, { className: CLS_RELATED_LABEL, children: "Reviewer" }), _jsx(Text, { className: CLS_RELATED_TITLE, children: displayName })] })] })) : (_jsxs("div", { className: "flex items-center gap-3 rounded-xl border border-neutral-200 dark:border-zinc-700 bg-white dark:bg-zinc-900 p-4", children: [_jsx("span", { className: "flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-purple-100 dark:bg-purple-900/30 text-xl", children: "\uD83D\uDC64" }), _jsxs("div", { className: "min-w-0", children: [_jsx(Span, { className: "block text-xs text-neutral-400 dark:text-zinc-500 mb-0.5", children: "Reviewer" }), _jsx(Span, { className: "block text-sm font-medium text-neutral-900 dark:text-white truncate", children: "Anonymous" })] })] }))] })] }), lightboxIdx !== null && currentImage && (_jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/95", onClick: closeLightbox, role: "dialog", "aria-modal": "true", "aria-label": "Image lightbox", children: [_jsx("button", { type: "button", onClick: closeLightbox, "aria-label": "Close lightbox", className: "absolute top-4 right-4 z-10 flex h-10 w-10 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/20 transition-colors text-xl", children: "\u00D7" }), _jsxs("div", { className: "absolute top-4 left-1/2 -translate-x-1/2 text-white/70 text-sm", children: [lightboxIdx + 1, " / ", images.length] }), images.length > 1 && (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); prevImage(); }, "aria-label": "Previous image", className: "absolute left-4 top-1/2 -translate-y-1/2 z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/25 transition-colors text-2xl", children: "\u2039" })), _jsx("div", { className: "max-h-[85vh] max-w-[85vw] flex items-center justify-center", onClick: (e) => e.stopPropagation(), children: _jsx("img", { src: currentImage.url, alt: `Review photo ${lightboxIdx + 1}`, className: "max-h-[85vh] max-w-[85vw] rounded-lg object-contain shadow-2xl" }) }), images.length > 1 && (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); nextImage(); }, "aria-label": "Next image", className: "absolute right-4 top-1/2 -translate-y-1/2 z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/25 transition-colors text-2xl", children: "\u203A" })), images.length > 1 && (_jsx("div", { className: "absolute bottom-4 left-0 right-0 flex justify-center gap-2 px-4", children: images.map((img, i) => (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); setLightboxIdx(i); }, "aria-label": `Go to image ${i + 1}`, className: `h-12 w-12 flex-shrink-0 rounded-md bg-center bg-cover border-2 transition-all ${i === lightboxIdx
82
+ : "border-neutral-300 dark:border-zinc-600 text-neutral-700 dark:text-zinc-200 hover:border-primary hover:text-primary dark:hover:border-primary dark:hover:text-primary disabled:opacity-50"}`, children: [_jsx("span", { "aria-hidden": "true", children: voted ? "✓" : "👍" }), voted ? "Marked helpful" : voting ? "Saving…" : "Helpful?"] })] }), _jsxs(Section, { className: "grid gap-3 sm:grid-cols-3", children: [productHref && (_jsxs(Link, { href: productHref, className: CLS_RELATED_LINK, children: [_jsx("span", { className: "flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-orange-100 dark:bg-orange-900/30 text-xl", children: "\uD83D\uDCE6" }), _jsxs("div", { className: "min-w-0", children: [_jsx(Text, { className: CLS_RELATED_LABEL, children: "Product" }), _jsx(Text, { className: CLS_RELATED_TITLE, children: review.productTitle ?? "View Product" })] })] })), sellerHref && (_jsxs(Link, { href: sellerHref, className: CLS_RELATED_LINK, children: [_jsx("span", { className: "flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-blue-100 dark:bg-blue-900/30 text-xl", children: "\uD83C\uDFEA" }), _jsxs("div", { className: "min-w-0", children: [_jsx(Text, { className: CLS_RELATED_LABEL, children: "Seller" }), _jsx(Text, { className: CLS_RELATED_TITLE, children: "View Seller" })] })] })), reviewerHref ? (_jsxs(Link, { href: reviewerHref, className: CLS_RELATED_LINK, children: [_jsx("span", { className: "flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-purple-100 dark:bg-purple-900/30 text-xl", children: "\uD83D\uDC64" }), _jsxs("div", { className: "min-w-0", children: [_jsx(Text, { className: CLS_RELATED_LABEL, children: "Reviewer" }), _jsx(Text, { className: CLS_RELATED_TITLE, children: displayName })] })] })) : (_jsxs("div", { className: "flex items-center gap-3 rounded-xl border border-neutral-200 dark:border-zinc-700 bg-white dark:bg-zinc-900 p-4", children: [_jsx("span", { className: "flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-purple-100 dark:bg-purple-900/30 text-xl", children: "\uD83D\uDC64" }), _jsxs("div", { className: "min-w-0", children: [_jsx(Span, { className: "block text-xs text-zinc-400 dark:text-zinc-400 mb-0.5", children: "Reviewer" }), _jsx(Span, { className: "block text-sm font-medium text-neutral-900 dark:text-white truncate", children: "Anonymous" })] })] }))] })] }), lightboxIdx !== null && currentImage && (_jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/95", onClick: closeLightbox, role: "dialog", "aria-modal": "true", "aria-label": "Image lightbox", children: [_jsx("button", { type: "button", onClick: closeLightbox, "aria-label": "Close lightbox", className: "absolute top-4 right-4 z-10 flex h-10 w-10 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/20 transition-colors text-xl", children: "\u00D7" }), _jsxs("div", { className: "absolute top-4 left-1/2 -translate-x-1/2 text-white/70 text-sm", children: [lightboxIdx + 1, " / ", images.length] }), images.length > 1 && (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); prevImage(); }, "aria-label": "Previous image", className: "absolute left-4 top-1/2 -translate-y-1/2 z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/25 transition-colors text-2xl", children: "\u2039" })), _jsx("div", { className: "max-h-[85vh] max-w-[85vw] flex items-center justify-center", onClick: (e) => e.stopPropagation(), children: _jsx("img", { src: currentImage.url, alt: `Review photo ${lightboxIdx + 1}`, className: "max-h-[85vh] max-w-[85vw] rounded-lg object-contain shadow-2xl" }) }), images.length > 1 && (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); nextImage(); }, "aria-label": "Next image", className: "absolute right-4 top-1/2 -translate-y-1/2 z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/25 transition-colors text-2xl", children: "\u203A" })), images.length > 1 && (_jsx("div", { className: "absolute bottom-4 left-0 right-0 flex justify-center gap-2 px-4", children: images.map((img, i) => (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); setLightboxIdx(i); }, "aria-label": `Go to image ${i + 1}`, className: `h-12 w-12 flex-shrink-0 rounded-md bg-center bg-cover border-2 transition-all ${i === lightboxIdx
83
83
  ? "border-white scale-110"
84
84
  : "border-transparent opacity-60 hover:opacity-100"}`, style: { backgroundImage: `url(${img.thumbnailUrl ?? img.url})` } }, i))) }))] }))] }));
85
85
  }