@mohasinac/appkit 2.8.1 → 2.8.3

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 (434) hide show
  1. package/dist/_internal/client/features/classified/ClassifiedDetailView.js +7 -1
  2. package/dist/_internal/client/features/digital-code/CodeRevealPanel.js +4 -1
  3. package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.js +7 -1
  4. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +3 -2
  5. package/dist/_internal/client/features/live/LiveItemDetailView.js +11 -2
  6. package/dist/_internal/client/scaffolds/AppShell.js +2 -1
  7. package/dist/_internal/client/scaffolds/DashboardScaffold.js +2 -1
  8. package/dist/_internal/server/features/checkout/actions.js +40 -39
  9. package/dist/_internal/shared/actions/action-registry.js +6 -0
  10. package/dist/_internal/shared/config/index.d.ts +1 -1
  11. package/dist/_internal/shared/config/schema.d.ts +0 -8
  12. package/dist/client-entry.d.ts +1 -1
  13. package/dist/client.d.ts +1 -1
  14. package/dist/client.js +1 -1
  15. package/dist/configs/next.js +12 -22
  16. package/dist/constants/api-endpoints.d.ts +6 -0
  17. package/dist/constants/api-endpoints.js +2 -0
  18. package/dist/core/hooks/useSiteSettings.d.ts +1 -1
  19. package/dist/features/about/components/AboutView.js +5 -2
  20. package/dist/features/about/components/FAQPageView.js +3 -3
  21. package/dist/features/about/components/FeesView.js +13 -5
  22. package/dist/features/about/components/HelpPageView.js +9 -5
  23. package/dist/features/about/components/HowAuctionsWorkView.js +9 -5
  24. package/dist/features/about/components/HowCheckoutWorksView.js +9 -5
  25. package/dist/features/about/components/HowOffersWorkView.js +10 -5
  26. package/dist/features/about/components/HowOrdersWorkView.js +10 -5
  27. package/dist/features/about/components/HowPayoutsWorkView.js +9 -5
  28. package/dist/features/about/components/HowPreOrdersWorkView.js +9 -5
  29. package/dist/features/about/components/HowReviewsWorkView.js +9 -5
  30. package/dist/features/about/components/PolicyPageView.js +3 -3
  31. package/dist/features/about/components/PublicProfileView.js +11 -4
  32. package/dist/features/about/components/SecurityPrivacyView.js +8 -4
  33. package/dist/features/about/components/ShippingPolicyView.js +3 -2
  34. package/dist/features/about/components/TrackOrderView.js +2 -2
  35. package/dist/features/about/components/UnauthorizedView.js +3 -3
  36. package/dist/features/account/components/AddressBook.js +1 -1
  37. package/dist/features/account/components/AddressForm.js +2 -2
  38. package/dist/features/account/components/AddressInlineSelect.d.ts +24 -0
  39. package/dist/features/account/components/AddressInlineSelect.js +78 -0
  40. package/dist/features/account/components/AddressSelectorCreate.d.ts +2 -1
  41. package/dist/features/account/components/AddressSelectorCreate.js +5 -32
  42. package/dist/features/account/components/AddressesIndexListing.js +3 -3
  43. package/dist/features/account/components/ChatWindow.js +2 -1
  44. package/dist/features/account/components/NotificationBell.js +13 -7
  45. package/dist/features/account/components/NotificationPreferencesPanel.js +4 -1
  46. package/dist/features/account/components/UserOffersPanel.js +2 -1
  47. package/dist/features/account/components/UserSidebar.js +11 -7
  48. package/dist/features/account/components/UserSupportView.js +13 -4
  49. package/dist/features/account/components/index.d.ts +2 -0
  50. package/dist/features/account/components/index.js +1 -0
  51. package/dist/features/account/hooks/useAccount.d.ts +2 -2
  52. package/dist/features/account/hooks/useAddressSelector.d.ts +1 -1
  53. package/dist/features/account/hooks/useAddresses.d.ts +2 -2
  54. package/dist/features/account/hooks/useNotifications.d.ts +1 -1
  55. package/dist/features/account/hooks/useProfile.d.ts +1 -1
  56. package/dist/features/account/hooks/usePublicProfile.d.ts +2 -2
  57. package/dist/features/addresses/repository/addresses.repository.d.ts +1 -0
  58. package/dist/features/addresses/repository/addresses.repository.js +13 -0
  59. package/dist/features/admin/components/AdminAdEditorView.js +8 -5
  60. package/dist/features/admin/components/AdminAddressEditorView.js +5 -5
  61. package/dist/features/admin/components/AdminAdsView.js +10 -7
  62. package/dist/features/admin/components/AdminBlogEditorView.js +15 -9
  63. package/dist/features/admin/components/AdminBrandEditorView.js +10 -4
  64. package/dist/features/admin/components/AdminBrandsView.js +4 -4
  65. package/dist/features/admin/components/AdminBundleEditorView.js +4 -5
  66. package/dist/features/admin/components/AdminBundlesView.js +3 -3
  67. package/dist/features/admin/components/AdminCarouselEditorView.js +6 -3
  68. package/dist/features/admin/components/AdminCarouselView.js +6 -6
  69. package/dist/features/admin/components/AdminCatalogGuideView.js +2 -1
  70. package/dist/features/admin/components/AdminCategoriesView.js +5 -5
  71. package/dist/features/admin/components/AdminCategoryEditorView.js +11 -5
  72. package/dist/features/admin/components/AdminContactEditorView.js +8 -1
  73. package/dist/features/admin/components/AdminCouponEditorView.js +23 -5
  74. package/dist/features/admin/components/AdminEmployeeEditorView.js +7 -4
  75. package/dist/features/admin/components/AdminFaqEditorView.js +9 -3
  76. package/dist/features/admin/components/AdminFaqsView.js +4 -4
  77. package/dist/features/admin/components/AdminFeatureEditorView.js +7 -1
  78. package/dist/features/admin/components/AdminFeatureFlagsView.js +4 -1
  79. package/dist/features/admin/components/AdminFilterBar.js +4 -4
  80. package/dist/features/admin/components/AdminGroupedListingsView.js +65 -30
  81. package/dist/features/admin/components/AdminGuideHubView.js +4 -1
  82. package/dist/features/admin/components/AdminMediaView.js +4 -1
  83. package/dist/features/admin/components/AdminNavigationView.js +7 -4
  84. package/dist/features/admin/components/AdminNotificationsView.js +2 -2
  85. package/dist/features/admin/components/AdminOrderEditorView.js +2 -2
  86. package/dist/features/admin/components/AdminPageHeader.js +5 -2
  87. package/dist/features/admin/components/AdminPrizeDrawsView.js +5 -5
  88. package/dist/features/admin/components/AdminProductEditorView.js +12 -5
  89. package/dist/features/admin/components/AdminProductsView.js +4 -4
  90. package/dist/features/admin/components/AdminReviewsView.js +2 -2
  91. package/dist/features/admin/components/AdminScammerEditorView.js +6 -2
  92. package/dist/features/admin/components/AdminScammersView.js +3 -3
  93. package/dist/features/admin/components/AdminSectionsView.js +20 -22
  94. package/dist/features/admin/components/AdminSessionsManager.js +2 -1
  95. package/dist/features/admin/components/AdminSessionsView.js +2 -2
  96. package/dist/features/admin/components/AdminSidebar.js +11 -7
  97. package/dist/features/admin/components/AdminSiteConfigGuideView.js +2 -1
  98. package/dist/features/admin/components/AdminSiteSettingsView.js +5 -1
  99. package/dist/features/admin/components/AdminStoreAddressesView.js +2 -2
  100. package/dist/features/admin/components/AdminStoreEditorView.js +5 -5
  101. package/dist/features/admin/components/AdminSublistingCategoryEditorView.js +3 -3
  102. package/dist/features/admin/components/AdminSupportTicketDetailView.js +10 -3
  103. package/dist/features/admin/components/AdminSupportTicketsView.js +3 -3
  104. package/dist/features/admin/components/AdminTrustGuideView.js +3 -3
  105. package/dist/features/admin/components/AdminUsersGuideView.js +3 -3
  106. package/dist/features/admin/components/AdminViewCards.js +12 -6
  107. package/dist/features/admin/components/BrandQuickCreateForm.js +2 -2
  108. package/dist/features/admin/components/CategoryQuickCreateForm.js +2 -2
  109. package/dist/features/admin/components/DashboardStats.js +9 -3
  110. package/dist/features/admin/components/DataListingView.js +3 -3
  111. package/dist/features/admin/components/DataTable.js +11 -7
  112. package/dist/features/admin/components/DrawerFormFooter.js +2 -2
  113. package/dist/features/admin/components/QuickEditMenu.js +2 -1
  114. package/dist/features/admin/components/analytics/AdminAnalyticsCharts.js +5 -1
  115. package/dist/features/admin/hooks/useAdmin.d.ts +1 -1
  116. package/dist/features/admin/hooks/useAdminSectionsListing.d.ts +1 -1
  117. package/dist/features/admin/hooks/useChat.d.ts +1 -1
  118. package/dist/features/auctions/components/AuctionBidsTable.js +4 -1
  119. package/dist/features/auctions/components/AuctionDetailPageView.js +14 -6
  120. package/dist/features/auctions/components/CollapsibleBidHistory.js +5 -1
  121. package/dist/features/auctions/components/MarketplaceAuctionCard.js +9 -3
  122. package/dist/features/auctions/components/MarketplaceAuctionGrid.js +8 -2
  123. package/dist/features/auctions/components/PlaceBidFormClient.js +4 -1
  124. package/dist/features/auctions/hooks/useAuctions.d.ts +8 -8
  125. package/dist/features/auth/components/RegisterForm.js +2 -2
  126. package/dist/features/auth/components/VerifyEmailView.js +5 -2
  127. package/dist/features/auth/consent-otp.d.ts +2 -2
  128. package/dist/features/auth/hooks/useAuth.d.ts +2 -2
  129. package/dist/features/before-after/components/BeforeAfterSlider.js +1 -1
  130. package/dist/features/blog/components/BlogFeaturedCard.js +8 -1
  131. package/dist/features/blog/components/BlogIndexListing.js +11 -5
  132. package/dist/features/blog/components/BlogListView.js +11 -3
  133. package/dist/features/blog/components/BlogPostView.js +10 -3
  134. package/dist/features/cart/components/CartDrawer.js +11 -3
  135. package/dist/features/cart/components/CartSummary.js +2 -2
  136. package/dist/features/cart/components/CheckoutOtpModal.js +2 -1
  137. package/dist/features/cart/hooks/useCart.d.ts +1 -1
  138. package/dist/features/cart/hooks/useCartQuery.d.ts +1 -1
  139. package/dist/features/cart/hooks/useCheckoutReadQueries.d.ts +2 -2
  140. package/dist/features/cart/hooks/useOrder.d.ts +2 -2
  141. package/dist/features/categories/components/BrandDetailPageView.js +5 -2
  142. package/dist/features/categories/components/BrandDetailTabs.js +5 -1
  143. package/dist/features/categories/components/BundleDetailView.js +6 -3
  144. package/dist/features/categories/components/BundleDynamicRuleEditor.js +3 -1
  145. package/dist/features/categories/components/BundleItemsPicker.js +10 -3
  146. package/dist/features/categories/components/CategoriesIndexListing.js +12 -6
  147. package/dist/features/categories/components/CategoryBundlesListing.js +5 -2
  148. package/dist/features/categories/components/CategoryDetailPageView.js +6 -2
  149. package/dist/features/categories/components/CategoryDetailTabs.js +5 -1
  150. package/dist/features/categories/components/CategoryForm.js +6 -3
  151. package/dist/features/categories/components/CategoryGrid.js +9 -2
  152. package/dist/features/categories/components/CategoryProductsListing.js +10 -4
  153. package/dist/features/categories/components/CategorySelectorCreate.js +3 -3
  154. package/dist/features/categories/components/CategorySortSelect.js +1 -1
  155. package/dist/features/categories/components/CategoryStoresListing.js +3 -3
  156. package/dist/features/categories/components/CategoryTableColumns.js +10 -6
  157. package/dist/features/categories/components/CategoryTree.js +1 -1
  158. package/dist/features/categories/hooks/useCategories.d.ts +3 -3
  159. package/dist/features/categories/hooks/useCategorySelector.d.ts +3 -3
  160. package/dist/features/categories/hooks/useCategoryTree.d.ts +1 -1
  161. package/dist/features/checkout/hooks/useCheckoutApi.d.ts +2 -2
  162. package/dist/features/classified/components/ClassifiedFilters.js +2 -2
  163. package/dist/features/classified/components/ClassifiedIndexListing.js +9 -3
  164. package/dist/features/collections/components/CollectionCard.js +2 -1
  165. package/dist/features/collections/hooks/useCollections.d.ts +2 -2
  166. package/dist/features/contact/components/ContactForm.js +4 -2
  167. package/dist/features/contact/components/ContactInfoSidebar.js +4 -1
  168. package/dist/features/copilot/components/AdminCopilotView.js +13 -5
  169. package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +9 -3
  170. package/dist/features/events/components/AdminEventEditorView.js +62 -40
  171. package/dist/features/events/components/AdminEventEntriesView.js +9 -6
  172. package/dist/features/events/components/EventCard.js +7 -1
  173. package/dist/features/events/components/EventFormDrawer.js +2 -1
  174. package/dist/features/events/components/EventLeaderboard.js +4 -4
  175. package/dist/features/events/components/EventOfferCard.js +4 -1
  176. package/dist/features/events/components/EventParticipateView.js +3 -2
  177. package/dist/features/events/components/EventPollWidget.js +6 -5
  178. package/dist/features/events/components/EventRaffleEntryForm.js +5 -2
  179. package/dist/features/events/components/EventRaffleWinnerView.js +7 -1
  180. package/dist/features/events/components/EventRafflesSection.js +2 -2
  181. package/dist/features/events/components/EventSaleBanner.js +5 -2
  182. package/dist/features/events/components/EventsIndexListing.js +8 -2
  183. package/dist/features/events/components/EventsListView.js +4 -1
  184. package/dist/features/events/components/SpinWheelView.js +7 -2
  185. package/dist/features/events/hooks/useEvent.d.ts +3 -3
  186. package/dist/features/events/hooks/useEvents.d.ts +1 -1
  187. package/dist/features/events/schemas/firestore.d.ts +1 -0
  188. package/dist/features/events/types/index.d.ts +1 -0
  189. package/dist/features/faq/components/ContactCTA.js +4 -1
  190. package/dist/features/faq/components/FAQCategorySidebar.js +2 -2
  191. package/dist/features/faq/components/FAQHelpfulButtons.js +8 -5
  192. package/dist/features/faq/components/FAQPageContent.js +5 -5
  193. package/dist/features/faq/components/FAQSortDropdown.js +2 -2
  194. package/dist/features/faq/hooks/useFAQs.d.ts +1 -1
  195. package/dist/features/faq/hooks/useFaqList.d.ts +15 -15
  196. package/dist/features/filters/AsyncFacetSection.js +4 -2
  197. package/dist/features/filters/FilterFacetSection.js +14 -6
  198. package/dist/features/filters/RangeFilter.js +4 -2
  199. package/dist/features/filters/SwitchFilter.js +2 -1
  200. package/dist/features/forms/Checkbox.js +1 -1
  201. package/dist/features/forms/Radio.js +1 -1
  202. package/dist/features/forms/Slider.js +1 -1
  203. package/dist/features/homepage/components/AdSlot.js +4 -4
  204. package/dist/features/homepage/components/AdvertisementBanner.js +13 -4
  205. package/dist/features/homepage/components/AnnouncementBar.js +2 -1
  206. package/dist/features/homepage/components/BeforeAfterCard.js +8 -2
  207. package/dist/features/homepage/components/BrandsSection.js +6 -3
  208. package/dist/features/homepage/components/CTABannerSection.js +2 -2
  209. package/dist/features/homepage/components/CharacterHotspot.js +5 -2
  210. package/dist/features/homepage/components/CharacterHotspotForm.js +8 -4
  211. package/dist/features/homepage/components/CustomCardsSection.js +13 -7
  212. package/dist/features/homepage/components/CustomerReviewsSection.js +9 -3
  213. package/dist/features/homepage/components/FAQSection.js +7 -4
  214. package/dist/features/homepage/components/FeaturedBundlesSection.js +8 -2
  215. package/dist/features/homepage/components/FeaturedResultsSection.js +1 -1
  216. package/dist/features/homepage/components/GoogleReviewsSection.js +14 -8
  217. package/dist/features/homepage/components/HeroCarousel.js +1 -1
  218. package/dist/features/homepage/components/HomepageSkeleton.js +7 -1
  219. package/dist/features/homepage/components/HowItWorksInfoView.js +2 -2
  220. package/dist/features/homepage/components/HowItWorksSection.js +2 -2
  221. package/dist/features/homepage/components/NewsletterBanner.js +3 -2
  222. package/dist/features/homepage/components/NewsletterSection.js +5 -2
  223. package/dist/features/homepage/components/PromoGrid.js +4 -1
  224. package/dist/features/homepage/components/SectionCarousel.js +7 -4
  225. package/dist/features/homepage/components/SecurityHighlightsSection.js +3 -3
  226. package/dist/features/homepage/components/ShopByCategorySection.js +10 -4
  227. package/dist/features/homepage/components/SiteFeaturesSection.js +5 -2
  228. package/dist/features/homepage/components/SocialFeedSection.js +4 -4
  229. package/dist/features/homepage/components/SocialPostCard.js +6 -3
  230. package/dist/features/homepage/components/TrustFeaturesSection.js +5 -5
  231. package/dist/features/homepage/components/TrustIndicatorsSection.js +5 -2
  232. package/dist/features/homepage/components/WelcomeSection.js +1 -1
  233. package/dist/features/homepage/components/WhatsAppCommunitySection.js +3 -3
  234. package/dist/features/homepage/hooks/useBlogArticles.d.ts +1 -1
  235. package/dist/features/homepage/hooks/useFeaturedAuctions.d.ts +1 -1
  236. package/dist/features/homepage/hooks/useFeaturedPreOrders.d.ts +1 -1
  237. package/dist/features/homepage/hooks/useFeaturedProducts.d.ts +1 -1
  238. package/dist/features/homepage/hooks/useFeaturedStores.d.ts +1 -1
  239. package/dist/features/homepage/hooks/useHeroCarousel.d.ts +1 -1
  240. package/dist/features/homepage/hooks/useHomepageEvents.d.ts +1 -1
  241. package/dist/features/homepage/hooks/useHomepageReviews.d.ts +1 -1
  242. package/dist/features/homepage/hooks/useHomepageSections.d.ts +1 -1
  243. package/dist/features/homepage/hooks/useTopBrands.d.ts +1 -1
  244. package/dist/features/homepage/hooks/useTopCategories.d.ts +1 -1
  245. package/dist/features/layout/AppLayoutShell.js +2 -1
  246. package/dist/features/layout/BackToTop.js +1 -1
  247. package/dist/features/layout/BottomActions.js +4 -3
  248. package/dist/features/layout/BottomNavItem.js +1 -1
  249. package/dist/features/layout/BottomSheet.js +4 -1
  250. package/dist/features/layout/FooterLayout.js +1 -1
  251. package/dist/features/layout/NavbarLayout.js +4 -1
  252. package/dist/features/layout/SidebarLayout.js +5 -2
  253. package/dist/features/live/components/LiveItemFilters.js +2 -2
  254. package/dist/features/live/components/LiveItemsIndexListing.js +9 -3
  255. package/dist/features/loyalty/components/CoinsDisplay.js +4 -2
  256. package/dist/features/loyalty/hooks/useLoyaltyBalance.d.ts +1 -1
  257. package/dist/features/media/AvatarUpload.js +2 -2
  258. package/dist/features/media/MediaLightbox.js +3 -2
  259. package/dist/features/media/modals/VideoThumbnailSelector.js +4 -1
  260. package/dist/features/media/modals/VideoTrimModal.js +1 -1
  261. package/dist/features/media/upload/CameraCapture.js +1 -1
  262. package/dist/features/media/upload/ImageUpload.js +4 -1
  263. package/dist/features/media/upload/MediaUploadField.js +11 -2
  264. package/dist/features/media/upload/MediaUploadList.js +5 -1
  265. package/dist/features/orders/components/MarketplaceOrderCard.js +2 -2
  266. package/dist/features/orders/components/OrdersList.js +2 -1
  267. package/dist/features/orders/components/RefundHistoryTable.js +4 -1
  268. package/dist/features/orders/components/RefundRequestView.js +2 -1
  269. package/dist/features/orders/hooks/useOrders.d.ts +2 -2
  270. package/dist/features/payments/hooks/usePayments.d.ts +1 -1
  271. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +5 -1
  272. package/dist/features/pre-orders/components/PreOrderActionsClient.js +3 -3
  273. package/dist/features/pre-orders/components/PreOrderBadge.js +2 -1
  274. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +16 -7
  275. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +32 -24
  276. package/dist/features/pre-orders/hooks/usePreOrders.d.ts +2 -2
  277. package/dist/features/products/columns/productTableColumns.js +9 -4
  278. package/dist/features/products/components/AuctionsIndexListing.js +9 -3
  279. package/dist/features/products/components/BidHistory.js +4 -4
  280. package/dist/features/products/components/CompareOverlay.js +10 -2
  281. package/dist/features/products/components/CustomFieldsEditor.js +2 -1
  282. package/dist/features/products/components/CustomSectionTabContent.js +2 -2
  283. package/dist/features/products/components/CustomSectionsEditor.js +3 -2
  284. package/dist/features/products/components/GroupSettingsPanel.js +34 -26
  285. package/dist/features/products/components/MakeOfferButton.js +6 -2
  286. package/dist/features/products/components/MakeOfferForm.js +2 -1
  287. package/dist/features/products/components/MarketplaceBundleCard.js +6 -3
  288. package/dist/features/products/components/MarketplacePrizeDrawCard.js +3 -2
  289. package/dist/features/products/components/PlaceBidForm.js +2 -1
  290. package/dist/features/products/components/PrizeDrawCollage.js +6 -2
  291. package/dist/features/products/components/PrizeDrawDetailPageView.js +6 -1
  292. package/dist/features/products/components/PrizeDrawItemsEditor.js +4 -2
  293. package/dist/features/products/components/PrizeDrawsIndexListing.js +6 -3
  294. package/dist/features/products/components/PrizeDrawsSection.js +2 -2
  295. package/dist/features/products/components/PrizeRevealModal.js +5 -1
  296. package/dist/features/products/components/ProductDetailPageView.js +32 -16
  297. package/dist/features/products/components/ProductFeatureBadges.js +9 -9
  298. package/dist/features/products/components/ProductForm.d.ts +11 -1
  299. package/dist/features/products/components/ProductForm.js +10 -5
  300. package/dist/features/products/components/ProductGalleryClient.js +8 -4
  301. package/dist/features/products/components/ProductGradingTab.js +4 -1
  302. package/dist/features/products/components/ProductGrid.js +35 -14
  303. package/dist/features/products/components/ProductInfo.js +2 -1
  304. package/dist/features/products/components/ProductTabs.js +2 -1
  305. package/dist/features/products/components/ProductTabsShell.js +5 -1
  306. package/dist/features/products/components/ProductsIndexListing.js +32 -24
  307. package/dist/features/products/components/ProductsIndexPageView.js +2 -2
  308. package/dist/features/products/components/RelatedProducts.js +3 -3
  309. package/dist/features/products/components/ShowGroupSection.js +10 -6
  310. package/dist/features/products/components/SublistingCarouselSection.js +7 -3
  311. package/dist/features/products/components/SublistingCategorySelect.d.ts +3 -1
  312. package/dist/features/products/components/SublistingCategorySelect.js +4 -37
  313. package/dist/features/products/constants/action-defs.js +3 -3
  314. package/dist/features/products/hooks/useProductDetail.d.ts +1 -1
  315. package/dist/features/products/hooks/useRelatedProducts.d.ts +1 -1
  316. package/dist/features/promotions/components/CouponCard.js +5 -3
  317. package/dist/features/promotions/components/CouponsIndexListing.js +7 -3
  318. package/dist/features/promotions/hooks/usePromotions.d.ts +2 -2
  319. package/dist/features/promotions/repository/coupons.repository.d.ts +8 -0
  320. package/dist/features/promotions/repository/coupons.repository.js +2 -0
  321. package/dist/features/reviews/components/ReviewDetailPageView.js +3 -3
  322. package/dist/features/reviews/components/ReviewDetailShell.js +15 -3
  323. package/dist/features/reviews/components/ReviewSummary.js +4 -2
  324. package/dist/features/reviews/components/ReviewsIndexListing.js +8 -2
  325. package/dist/features/reviews/components/ReviewsList.js +1 -1
  326. package/dist/features/reviews/hooks/useReviews.d.ts +2 -2
  327. package/dist/features/scams/components/ScamAwarenessModal.js +2 -2
  328. package/dist/features/scams/components/ScamProfileView.js +3 -3
  329. package/dist/features/scams/components/ScamRegistryView.js +6 -4
  330. package/dist/features/search/components/Search.js +9 -6
  331. package/dist/features/search/components/SearchFiltersRow.js +1 -1
  332. package/dist/features/search/components/SearchResultsSection.js +1 -1
  333. package/dist/features/search/hooks/useSearch.d.ts +2 -2
  334. package/dist/features/seller/components/CouponInlineSelect.d.ts +22 -0
  335. package/dist/features/seller/components/CouponInlineSelect.js +103 -0
  336. package/dist/features/seller/components/GroupInlineSelect.d.ts +23 -0
  337. package/dist/features/seller/components/GroupInlineSelect.js +80 -0
  338. package/dist/features/seller/components/PhysicalLocationModal.js +2 -1
  339. package/dist/features/seller/components/PrintCenterView.js +2 -1
  340. package/dist/features/seller/components/ProductInlineSelect.d.ts +24 -0
  341. package/dist/features/seller/components/ProductInlineSelect.js +42 -0
  342. package/dist/features/seller/components/QuickProductForm.js +4 -1
  343. package/dist/features/seller/components/SellerAddressesView.js +8 -3
  344. package/dist/features/seller/components/SellerAnalyticsAlertsView.js +6 -3
  345. package/dist/features/seller/components/SellerAnalyticsView.js +2 -2
  346. package/dist/features/seller/components/SellerBidsView.js +7 -7
  347. package/dist/features/seller/components/SellerBundlesView.js +2 -1
  348. package/dist/features/seller/components/SellerCouponEditorView.d.ts +2 -0
  349. package/dist/features/seller/components/SellerCouponEditorView.js +15 -3
  350. package/dist/features/seller/components/SellerCouponsView.js +1 -1
  351. package/dist/features/seller/components/SellerDashboardView.js +2 -2
  352. package/dist/features/seller/components/SellerDigitalCodesView.js +2 -2
  353. package/dist/features/seller/components/SellerGoogleReviewsView.js +2 -2
  354. package/dist/features/seller/components/SellerGroupedListingsView.js +5 -5
  355. package/dist/features/seller/components/SellerOrdersView.js +13 -10
  356. package/dist/features/seller/components/SellerPayoutMethodsView.js +5 -4
  357. package/dist/features/seller/components/SellerPayoutRequestView.js +5 -1
  358. package/dist/features/seller/components/SellerPayoutSettingsView.js +5 -2
  359. package/dist/features/seller/components/SellerPreOrdersView.js +6 -6
  360. package/dist/features/seller/components/SellerPrizeDrawsView.js +6 -6
  361. package/dist/features/seller/components/SellerProductShell.js +1 -1
  362. package/dist/features/seller/components/SellerProductsCards.js +4 -1
  363. package/dist/features/seller/components/SellerProductsView.js +5 -5
  364. package/dist/features/seller/components/SellerReviewsView.js +7 -3
  365. package/dist/features/seller/components/SellerShippingConfigsView.js +4 -4
  366. package/dist/features/seller/components/SellerShippingView.js +1 -1
  367. package/dist/features/seller/components/SellerSidebar.js +15 -8
  368. package/dist/features/seller/components/SellerStoreCategoriesView.js +1 -1
  369. package/dist/features/seller/components/SellerStorefrontView.js +2 -2
  370. package/dist/features/seller/components/SellerTemplatesView.js +7 -4
  371. package/dist/features/seller/components/SublistingInlineSelect.d.ts +19 -0
  372. package/dist/features/seller/components/SublistingInlineSelect.js +83 -0
  373. package/dist/features/seller/components/analytics/SellerTopProducts.js +1 -1
  374. package/dist/features/seller/components/index.d.ts +8 -0
  375. package/dist/features/seller/components/index.js +4 -0
  376. package/dist/features/seller/hooks/useSellerPayouts.d.ts +3 -3
  377. package/dist/features/seller/hooks/useSellerStore.d.ts +6 -6
  378. package/dist/features/seller/hooks/useSellerStorefront.d.ts +2 -2
  379. package/dist/features/shell/FormShell.js +10 -2
  380. package/dist/features/shell/QuickFormDrawer.js +5 -5
  381. package/dist/features/shell/StepForm.js +6 -6
  382. package/dist/features/site-settings/components/ActionPermissionsManager.js +8 -4
  383. package/dist/features/site-settings/components/NavPermissionsManager.js +7 -4
  384. package/dist/features/stores/components/InteractiveStoreCard.js +5 -1
  385. package/dist/features/stores/components/StoreAboutView.js +4 -1
  386. package/dist/features/stores/components/StoreAddressSelectorCreate.d.ts +2 -1
  387. package/dist/features/stores/components/StoreAddressSelectorCreate.js +5 -31
  388. package/dist/features/stores/components/StoreAuctionsListing.js +6 -3
  389. package/dist/features/stores/components/StoreGuideHubView.js +5 -2
  390. package/dist/features/stores/components/StoreHeader.js +8 -1
  391. package/dist/features/stores/components/StorePreOrdersListing.js +6 -3
  392. package/dist/features/stores/components/StoreProductsListing.js +6 -3
  393. package/dist/features/stores/components/StoreReviewsListing.js +8 -2
  394. package/dist/features/stores/components/StoresIndexListing.js +12 -6
  395. package/dist/features/stores/hooks/useStoreAddressSelector.d.ts +1 -1
  396. package/dist/features/stores/hooks/useStores.d.ts +6 -6
  397. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +7 -1
  398. package/dist/features/whatsapp-bot/components/WhatsAppChatButton.js +2 -1
  399. package/dist/features/wishlist/components/WishlistPage.js +2 -1
  400. package/dist/features/wishlist/hooks/useUserWishlist.d.ts +15 -15
  401. package/dist/features/wishlist/hooks/useWishlist.d.ts +1 -1
  402. package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
  403. package/dist/index.d.ts +10 -0
  404. package/dist/index.js +13 -1
  405. package/dist/next/components/GlobalError.js +2 -2
  406. package/dist/next/routing/route-map.d.ts +2 -0
  407. package/dist/next/routing/route-map.js +1 -0
  408. package/dist/providers/db-firebase/base.repository.d.ts +1 -1
  409. package/dist/react/ErrorBoundary.js +2 -2
  410. package/dist/seed/actions/demo-seed-actions.d.ts +1 -1
  411. package/dist/seed/manifest.js +10 -0
  412. package/dist/styles.css +2 -1
  413. package/dist/tailwind-utilities.css +1 -1
  414. package/dist/ui/DataTable.js +17 -16
  415. package/dist/ui/components/DateInput.js +2 -2
  416. package/dist/ui/components/DetailPageGallery.js +4 -1
  417. package/dist/ui/components/DetailPageTabs.js +6 -2
  418. package/dist/ui/components/ImageLightbox.js +5 -3
  419. package/dist/ui/components/Input.js +6 -3
  420. package/dist/ui/components/Layout.d.ts +4 -0
  421. package/dist/ui/components/Layout.js +1 -1
  422. package/dist/ui/components/Layout.style.css +1 -0
  423. package/dist/ui/components/ListingFilterDrawer.js +4 -1
  424. package/dist/ui/components/ListingLayout.js +9 -8
  425. package/dist/ui/components/ListingToolbar.js +5 -1
  426. package/dist/ui/components/PaginatedSelect.d.ts +1 -2
  427. package/dist/ui/components/PaginatedSelect.js +1 -2
  428. package/dist/ui/components/Radio.js +1 -1
  429. package/dist/ui/components/Select.js +2 -1
  430. package/dist/ui/components/Slider.js +1 -1
  431. package/dist/ui/components/VacationBanner.js +2 -1
  432. package/dist/ui/components/surface-tokens.d.ts +1 -0
  433. package/dist/ui/components/surface-tokens.js +1 -0
  434. package/package.json +22 -4
@@ -1,6 +1,10 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState } from "react";
4
+ import { Div } from "../../../ui/components/Div";
5
+ const __O = {
6
+ xAuto: "overflow-x-auto",
7
+ };
4
8
  const STATIC_TABS = [
5
9
  { id: "description", label: "Description" },
6
10
  { id: "specs", label: "Specifications" },
@@ -35,7 +39,7 @@ export function ProductTabsShell({ descriptionContent, specsContent, gradingCont
35
39
  if (allTabs.length === 0)
36
40
  return null;
37
41
  const activeContent = allTabs.find((t) => t.id === activeId)?.content;
38
- 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
42
+ return (_jsxs(Div, { className: `mt-8 ${className}`, children: [_jsx(Div, { className: `mb-6 flex gap-1 ${__O.xAuto} 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
39
43
  ? "border-[var(--appkit-color-primary,#6366f1)] text-[var(--appkit-color-primary,#6366f1)]"
40
44
  : "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 })] }));
41
45
  }
@@ -5,7 +5,7 @@ import { ShoppingCart, Heart, Columns } from "lucide-react";
5
5
  import { useRouter } from "next/navigation";
6
6
  import { useUrlTable } from "../../../react/hooks/useUrlTable";
7
7
  import { useProducts } from "../hooks/useProducts";
8
- import { Pagination, useToast, BulkActionBar, ListingToolbar, LoginRequiredModal, FilterDrawer } from "../../../ui";
8
+ import { Div, Pagination, useToast, BulkActionBar, ListingToolbar, LoginRequiredModal, FilterDrawer } from "../../../ui";
9
9
  import { usePendingTable } from "../../../react/hooks/usePendingTable";
10
10
  import { useAuthGate } from "../../../react/hooks/useAuthGate";
11
11
  import { ACTION_ID, ACTION_META, COMPARE_MAX_ITEMS } from "../constants/action-defs";
@@ -23,6 +23,12 @@ 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
25
  import { useBottomActions } from "../../layout";
26
+ const __P = {
27
+ p3: "p-3",
28
+ };
29
+ const __O = {
30
+ hidden: "overflow-hidden",
31
+ };
26
32
  const DEFAULT_SORT = sortBy(PRODUCT_FIELDS.CREATED_AT);
27
33
  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];
28
34
  export function ProductsIndexListing({ initialData }) {
@@ -133,39 +139,41 @@ export function ProductsIndexListing({ initialData }) {
133
139
  router.push(String(ROUTES.USER.CART));
134
140
  });
135
141
  }, [localCart, router, requireAuth]);
142
+ const handleBulkAddToCart = useCallback(() => {
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
+ }, [products, selection, localCart, showToast]);
152
+ const handleBulkAddToWishlist = useCallback(() => {
153
+ requireAuth(ACTION_ID.ADD_TO_WISHLIST, () => {
154
+ const selected = products.filter((p) => selection.selectedIdSet.has(p.id));
155
+ selected.forEach((p) => {
156
+ localWishlist.add(p.id, "product");
157
+ pushWishlistOp({ op: "add", itemId: p.id, type: "product" });
158
+ });
159
+ showToast(`${selected.length} items added to wishlist`, "success");
160
+ selection.clearSelection();
161
+ });
162
+ }, [products, selection, localWishlist, showToast, requireAuth]);
136
163
  useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
137
164
  {
138
165
  id: ACTION_ID.ADD_TO_CART,
139
166
  label: ACTION_META[ACTION_ID.ADD_TO_CART].label,
140
167
  icon: _jsx(ShoppingCart, { className: "h-3.5 w-3.5" }),
141
168
  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
- },
169
+ onClick: handleBulkAddToCart,
152
170
  },
153
171
  {
154
172
  id: ACTION_ID.ADD_TO_WISHLIST,
155
173
  label: ACTION_META[ACTION_ID.ADD_TO_WISHLIST].label,
156
174
  icon: _jsx(Heart, { className: "h-3.5 w-3.5" }),
157
175
  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
- },
176
+ onClick: handleBulkAddToWishlist,
169
177
  },
170
178
  {
171
179
  id: ACTION_ID.COMPARE,
@@ -179,7 +187,7 @@ export function ProductsIndexListing({ initialData }) {
179
187
  },
180
188
  },
181
189
  ] } } : {});
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: [
190
+ 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: [
183
191
  { label: "Show sold", active: showSold, onChange: (next) => table.set(TABLE_KEYS.SHOW_SOLD, next ? "true" : "") },
184
192
  ] }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
185
193
  {
@@ -226,7 +234,7 @@ export function ProductsIndexListing({ initialData }) {
226
234
  setCompareIds(ids);
227
235
  },
228
236
  },
229
- ] }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: page, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsx("div", { className: "py-6", children: isLoading ? (_jsx("div", { className: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4", children: Array.from({ length: 10 }).map((_, i) => (_jsxs("div", { className: "rounded-xl border border-zinc-100 dark:border-slate-700 overflow-hidden animate-pulse", children: [_jsx("div", { className: "aspect-square bg-zinc-200 dark:bg-slate-700" }), _jsxs("div", { className: "p-3 space-y-2", children: [_jsx("div", { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-3/4" }), _jsx("div", { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-1/2" }), _jsx("div", { className: "h-4 bg-zinc-200 dark:bg-slate-700 rounded w-1/3" })] })] }, i))) })) : (_jsx(ProductGrid, { products: products, getProductHref: (p) => String(ROUTES.PUBLIC.PRODUCT_DETAIL(p.slug || p.id)), view: view === "grid" ? "card" : "list", onWishlistToggle: handleWishlistToggle, wishlistedIds: wishlistedIds, onAddToCart: handleAddToCart, onBuyNow: handleBuyNow, selectionMode: selection.isSelecting, selectedIds: selection.selectedIdSet, onToggleSelect: selection.toggle })) }), _jsx(CompareOverlay, { isOpen: compareIds.length > 0, productIds: compareIds, productType: "product", onClose: () => {
237
+ ] }), totalPages > 1 && (_jsx(Div, { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: page, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsx(Div, { className: "py-6", children: isLoading ? (_jsx(Div, { className: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4", children: Array.from({ length: 10 }).map((_, i) => (_jsxs(Div, { className: `rounded-xl border border-zinc-100 dark:border-slate-700 ${__O.hidden} animate-pulse`, children: [_jsx(Div, { className: "aspect-square bg-zinc-200 dark:bg-slate-700" }), _jsxs(Div, { className: `${__P.p3} space-y-2`, children: [_jsx(Div, { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-3/4" }), _jsx(Div, { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-1/2" }), _jsx(Div, { className: "h-4 bg-zinc-200 dark:bg-slate-700 rounded w-1/3" })] })] }, i))) })) : (_jsx(ProductGrid, { products: products, getProductHref: (p) => String(ROUTES.PUBLIC.PRODUCT_DETAIL(p.slug || p.id)), view: view === "grid" ? "card" : "list", onWishlistToggle: handleWishlistToggle, wishlistedIds: wishlistedIds, onAddToCart: handleAddToCart, onBuyNow: handleBuyNow, selectionMode: selection.isSelecting, selectedIds: selection.selectedIdSet, onToggleSelect: selection.toggle })) }), _jsx(CompareOverlay, { isOpen: compareIds.length > 0, productIds: compareIds, productType: "product", onClose: () => {
230
238
  setCompareIds([]);
231
239
  selection.clearSelection();
232
240
  }, onRemove: (id) => setCompareIds((ids) => ids.filter((i) => i !== id)) }), _jsx(FilterDrawer, { open: filterOpen, onOpen: openFilters, onClose: () => setFilterOpen(false), onApply: applyFilters, onReset: onFilterClear, activeCount: filterActiveCount, hideTrigger: true, children: _jsx(ProductFilters, { table: pendingTable, currencyPrefix: "\u20B9", categoryOptions: categoryOptions, brandOptions: brandOptions, featureOptions: featureOptions }) }), _jsx(LoginRequiredModal, { isOpen: modalOpen, onClose: closeModal, message: modalMessage })] }));
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { productRepository } from "../../../repositories";
3
3
  import { ROUTES } from "../../../constants";
4
- import { Container, Heading, Main, Section, Text } from "../../../ui";
4
+ import { Container, Div, Heading, Main, Section, Text } from "../../../ui";
5
5
  import { AdSlot } from "../../homepage/components/AdSlot";
6
6
  import { parseListingSearchParams } from "../../../utils/listing-params";
7
7
  import { ProductsIndexListing } from "./ProductsIndexListing";
@@ -59,5 +59,5 @@ export async function ProductsIndexPageView({ searchParams = {} }) {
59
59
  })
60
60
  .catch(() => null);
61
61
  const products = result ?? null;
62
- return (_jsxs(Main, { children: [_jsx(Section, { className: "pt-8 pb-4 border-b border-zinc-100 dark:border-slate-800", children: _jsxs(Container, { size: "xl", children: [_jsx(Heading, { level: 1, className: "text-3xl font-bold text-zinc-900 dark:text-zinc-100", children: "Products" }), _jsx(Text, { className: "mt-1 text-sm text-zinc-500 dark:text-zinc-400", children: "Discover amazing products and deals" }), _jsx("div", { className: "mt-3", children: _jsx("a", { href: ROUTES.PUBLIC.AUCTIONS, className: "inline-flex items-center gap-1.5 rounded-full border border-primary/30 bg-primary/10 px-4 py-1.5 text-xs font-medium text-primary-700 dark:text-primary-400 hover:bg-primary/15 transition-colors", children: "\uD83C\uDFF7\uFE0F Looking for unique deals? Browse Auctions \u2192" }) })] }) }), _jsxs(Container, { size: "xl", className: "px-4", children: [_jsx(AdSlot, { id: "listing-sidebar-top", className: "mb-4 mt-4" }), _jsx(ProductsIndexListing, { initialData: products }), _jsx(AdSlot, { id: "listing-sidebar-bottom", className: "mt-8" })] })] }));
62
+ return (_jsxs(Main, { children: [_jsx(Section, { className: "pt-8 pb-4 border-b border-zinc-100 dark:border-slate-800", children: _jsxs(Container, { size: "xl", children: [_jsx(Heading, { level: 1, className: "text-3xl font-bold text-zinc-900 dark:text-zinc-100", children: "Products" }), _jsx(Text, { className: "mt-1 text-sm text-zinc-500 dark:text-zinc-400", children: "Discover amazing products and deals" }), _jsx(Div, { className: "mt-3", children: _jsx("a", { href: ROUTES.PUBLIC.AUCTIONS, className: "inline-flex items-center gap-1.5 rounded-full border border-primary/30 bg-primary/10 px-4 py-1.5 text-xs font-medium text-primary-700 dark:text-primary-400 hover:bg-primary/15 transition-colors", children: "\uD83C\uDFF7\uFE0F Looking for unique deals? Browse Auctions \u2192" }) })] }) }), _jsxs(Container, { size: "xl", className: "px-4", children: [_jsx(AdSlot, { id: "listing-sidebar-top", className: "mb-4 mt-4" }), _jsx(ProductsIndexListing, { initialData: products }), _jsx(AdSlot, { id: "listing-sidebar-bottom", className: "mt-8" })] })] }));
63
63
  }
@@ -1,12 +1,12 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Heading } from "../../../ui";
2
+ import { Div, Heading } from "../../../ui";
3
3
  export function RelatedProducts({ isLoading = false, isEmpty = false, renderGrid, renderSkeleton, renderTitle, labels = {}, className = "", }) {
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-zinc-100 dark:bg-zinc-800" }, i))) }));
7
+ return (_jsx(Div, { className: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4 animate-pulse", 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;
11
- return (_jsxs("div", { className: `space-y-4 ${className}`, "data-section": "relatedproducts-div-429", children: [renderTitle ? (renderTitle()) : labels.title ? (_jsx(Heading, { level: 2, className: "text-xl font-bold", variant: "none", children: labels.title })) : null, renderGrid?.()] }));
11
+ return (_jsxs(Div, { className: `space-y-4 ${className}`, children: [renderTitle ? (renderTitle()) : labels.title ? (_jsx(Heading, { level: 2, className: "text-xl font-bold", variant: "none", children: labels.title })) : null, renderGrid?.()] }));
12
12
  }
@@ -3,9 +3,13 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
3
3
  import { useEffect, useState } from "react";
4
4
  import Link from "next/link";
5
5
  import { ROUTES } from "../../../next";
6
- import { Row, Text, Modal, SideDrawer, Button } from "../../../ui";
6
+ import { Div, Row, Span, Table, Thead, Tbody, Tr, Th, Td, Text, Modal, SideDrawer, Button } from "../../../ui";
7
7
  import { formatCurrency } from "../../../utils/number.formatter";
8
8
  import { isPreOrderListing } from "../utils/listing-type";
9
+ const __O = {
10
+ hidden: "overflow-hidden",
11
+ xAuto: "overflow-x-auto",
12
+ };
9
13
  function memberHref(m) {
10
14
  const slug = m.slug ?? m.id;
11
15
  if (isPreOrderListing(m))
@@ -20,15 +24,15 @@ function MemberThumb({ member, isCurrent }) {
20
24
  ? "border-[var(--appkit-color-primary,#6366f1)] ring-2 ring-[var(--appkit-color-primary,#6366f1)]/30"
21
25
  : "border-zinc-200 dark:border-zinc-700 group-hover:border-[var(--appkit-color-primary,#6366f1)]"}`, children: [image ? (
22
26
  // eslint-disable-next-line @next/next/no-img-element
23
- _jsx("img", { src: image, alt: member.title, className: "w-full h-full object-cover", loading: "lazy" })) : (_jsx("div", { className: "w-full h-full bg-zinc-100 dark:bg-zinc-800 flex items-center justify-center text-zinc-400 text-xs", children: "\u00E2\u2014\u00AF" })), member.isGroupParent && (_jsx("span", { className: "absolute bottom-0 right-0 bg-[var(--appkit-color-primary,#6366f1)] text-white text-[8px] leading-none px-1 py-0.5 rounded-tl", children: "Set" }))] }), _jsx(Text, { className: "text-[10px] text-center text-zinc-600 dark:text-zinc-400 leading-tight line-clamp-2 w-full", children: member.title }), _jsx(Text, { className: "text-[10px] font-semibold text-zinc-800 dark:text-zinc-200", children: price })] }));
27
+ _jsx("img", { src: image, alt: member.title, className: "w-full h-full object-cover", loading: "lazy" })) : (_jsx(Div, { className: "w-full h-full bg-zinc-100 dark:bg-zinc-800 flex items-center justify-center text-zinc-400 text-xs", children: "\u00E2\u2014\u00AF" })), member.isGroupParent && (_jsx(Span, { className: "absolute bottom-0 right-0 bg-[var(--appkit-color-primary,#6366f1)] text-white text-[8px] leading-none px-1 py-0.5 rounded-tl", children: "Set" }))] }), _jsx(Text, { className: "text-[10px] text-center text-zinc-600 dark:text-zinc-400 leading-tight line-clamp-2 w-full", children: member.title }), _jsx(Text, { className: "text-[10px] font-semibold text-zinc-800 dark:text-zinc-200", children: price })] }));
24
28
  }
25
29
  function GroupTableRow({ member }) {
26
30
  const href = memberHref(member);
27
31
  const price = formatCurrency(member.price, member.currency ?? "INR");
28
32
  const image = member.images?.[0] ?? "";
29
- return (_jsxs("tr", { className: "border-b border-zinc-100 dark:border-zinc-800 last:border-0", children: [_jsx("td", { className: "py-2 pr-3", children: _jsx("div", { className: "w-10 h-10 rounded-full overflow-hidden border border-zinc-200 dark:border-zinc-700", children: image ? (
33
+ return (_jsxs(Tr, { className: "border-b border-zinc-100 dark:border-zinc-800 last:border-0", children: [_jsx(Td, { className: "py-2 pr-3", children: _jsx(Div, { className: `w-10 h-10 rounded-full ${__O.hidden} border border-zinc-200 dark:border-zinc-700`, children: image ? (
30
34
  // eslint-disable-next-line @next/next/no-img-element
31
- _jsx("img", { src: image, alt: member.title, className: "w-full h-full object-cover", loading: "lazy" })) : (_jsx("div", { className: "w-full h-full bg-zinc-100 dark:bg-zinc-800" })) }) }), _jsxs("td", { className: "py-2 pr-3", children: [_jsx(Text, { className: "text-sm text-zinc-800 dark:text-zinc-200 font-medium line-clamp-2", children: member.title }), member.isGroupParent && (_jsx("span", { className: "text-[10px] text-[var(--appkit-color-primary,#6366f1)] font-semibold", children: "Parent" }))] }), _jsx("td", { className: "py-2 pr-3", children: _jsx(Text, { className: "text-sm text-zinc-700 dark:text-zinc-300", children: price }) }), _jsx("td", { className: "py-2 pr-3", children: _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 capitalize", children: member.condition ?? "—" }) }), _jsx("td", { className: "py-2", children: _jsx(Link, { href: href, className: "text-xs text-[var(--appkit-color-primary,#6366f1)] hover:underline", children: "View \u00E2\u2020\u2019" }) })] }));
35
+ _jsx("img", { src: image, alt: member.title, className: "w-full h-full object-cover", loading: "lazy" })) : (_jsx(Div, { className: "w-full h-full bg-zinc-100 dark:bg-zinc-800" })) }) }), _jsxs(Td, { className: "py-2 pr-3", children: [_jsx(Text, { className: "text-sm text-zinc-800 dark:text-zinc-200 font-medium line-clamp-2", children: member.title }), member.isGroupParent && (_jsx(Span, { weight: "semibold", className: "text-[10px] text-[var(--appkit-color-primary,#6366f1)]", children: "Parent" }))] }), _jsx(Td, { className: "py-2 pr-3", children: _jsx(Text, { className: "text-sm text-zinc-700 dark:text-zinc-300", children: price }) }), _jsx(Td, { className: "py-2 pr-3", children: _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 capitalize", children: member.condition ?? "—" }) }), _jsx(Td, { className: "py-2", children: _jsx(Link, { href: href, className: "text-xs text-[var(--appkit-color-primary,#6366f1)] hover:underline", children: "View \u00E2\u2020\u2019" }) })] }));
32
36
  }
33
37
  export function ShowGroupSection({ groupId, currentSlug, isParent, groupTitle }) {
34
38
  const [open, setOpen] = useState(false);
@@ -50,8 +54,8 @@ export function ShowGroupSection({ groupId, currentSlug, isParent, groupTitle })
50
54
  const label = groupTitle ?? "Product group";
51
55
  const parentLabel = isParent ? `Parts in this group: ${label}` : `Part of: ${label}`;
52
56
  const useDrawer = members.length >= 5;
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-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]
57
+ const tableContent = (_jsx(Div, { className: `${__O.xAuto}`, 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)) })] }) }));
58
+ 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 ${__O.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, { size: "xs", className: "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, { size: "xs", className: "ml-1 rounded-full bg-zinc-200 dark:bg-zinc-700 px-2 py-0.5 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 ${__O.xAuto}`, children: _jsx(Div, { className: "flex gap-3 min-w-0", children: [...members]
55
59
  .sort((a, b) => (b.isGroupParent ? 1 : 0) - (a.isGroupParent ? 1 : 0))
56
60
  .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
61
  }
@@ -3,9 +3,13 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useState } from "react";
4
4
  import Link from "next/link";
5
5
  import { ROUTES } from "../../../next";
6
- import { Row, Text } from "../../../ui";
6
+ import { Div, Row, Span, Text } from "../../../ui";
7
7
  import { formatCurrency } from "../../../utils/number.formatter";
8
8
  import { isAuctionListing, isPreOrderListing } from "../utils/listing-type";
9
+ const __O = {
10
+ hidden: "overflow-hidden",
11
+ xAuto: "overflow-x-auto",
12
+ };
9
13
  function getHref(listing) {
10
14
  const slug = listing.slug ?? listing.id;
11
15
  if (isAuctionListing(listing))
@@ -22,7 +26,7 @@ function ListingThumb({ listing, isCurrent, }) {
22
26
  ? "border-[var(--appkit-color-primary,#6366f1)] ring-2 ring-[var(--appkit-color-primary,#6366f1)]/30"
23
27
  : "border-zinc-200 dark:border-zinc-700 group-hover:border-[var(--appkit-color-primary,#6366f1)]"}`, children: image ? (
24
28
  // eslint-disable-next-line @next/next/no-img-element
25
- _jsx("img", { src: image, alt: listing.title, className: "w-full h-full object-cover", loading: "lazy" })) : (_jsx("div", { className: "w-full h-full bg-zinc-100 dark:bg-zinc-800 flex items-center justify-center text-zinc-400 text-xs", children: "\u00E2\u2014\u00AF" })) }), _jsx(Text, { className: "text-[10px] text-center text-zinc-600 dark:text-zinc-400 leading-tight line-clamp-2 w-full", children: listing.title }), _jsx(Text, { className: "text-[10px] font-semibold text-zinc-800 dark:text-zinc-200", children: price })] }));
29
+ _jsx("img", { src: image, alt: listing.title, className: "w-full h-full object-cover", loading: "lazy" })) : (_jsx(Div, { className: "w-full h-full bg-zinc-100 dark:bg-zinc-800 flex items-center justify-center text-zinc-400 text-xs", children: "\u00E2\u2014\u00AF" })) }), _jsx(Text, { className: "text-[10px] text-center text-zinc-600 dark:text-zinc-400 leading-tight line-clamp-2 w-full", children: listing.title }), _jsx(Text, { className: "text-[10px] font-semibold text-zinc-800 dark:text-zinc-200", children: price })] }));
26
30
  }
27
31
  export function SublistingCarouselSection({ sublistingCategoryId, currentListingId }) {
28
32
  const [open, setOpen] = useState(false);
@@ -50,5 +54,5 @@ export function SublistingCarouselSection({ sublistingCategoryId, currentListing
50
54
  if (others.length === 0)
51
55
  return null;
52
56
  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-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))) }) }))] }));
57
+ return (_jsxs(Div, { className: `rounded-xl border border-zinc-200 dark:border-zinc-700 bg-zinc-50/60 dark:bg-zinc-800/40 ${__O.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, { size: "xs", className: "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, { size: "xs", className: "ml-1 rounded-full bg-zinc-200 dark:bg-zinc-700 px-2 py-0.5 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 ${__O.xAuto}`, 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
58
  }
@@ -2,6 +2,8 @@ interface Props {
2
2
  value: string;
3
3
  onChange: (id: string) => void;
4
4
  disabled?: boolean;
5
+ /** Allow creating a new sub-listing inline. Defaults to false. */
6
+ allowCreate?: boolean;
5
7
  }
6
- export declare function SublistingCategorySelect({ value, onChange, disabled }: Props): import("react/jsx-runtime").JSX.Element;
8
+ export declare function SublistingCategorySelect({ value, onChange, disabled, allowCreate, }: Props): import("react/jsx-runtime").JSX.Element;
7
9
  export {};
@@ -1,40 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useEffect, useState } from "react";
4
- import { Select, Stack, Text } from "../../../ui";
5
- import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
6
- import { apiClient } from "../../../http";
7
- export function SublistingCategorySelect({ value, onChange, disabled }) {
8
- const [options, setOptions] = useState([]);
9
- const [loading, setLoading] = useState(true);
10
- useEffect(() => {
11
- let cancelled = false;
12
- apiClient
13
- .get(`${ADMIN_ENDPOINTS.SUBLISTING_CATEGORIES}?pageSize=200&sorts=name`)
14
- .then((res) => {
15
- if (cancelled)
16
- return;
17
- const items = res?.data?.items ?? [];
18
- const opts = [
19
- { value: "", label: "— None —" },
20
- ...items.map((item) => ({
21
- value: String(item.id ?? ""),
22
- label: item.itemCode
23
- ? `${item.name} (${item.itemCode})`
24
- : String(item.name ?? ""),
25
- })),
26
- ];
27
- setOptions(opts);
28
- })
29
- .catch(() => {
30
- if (!cancelled)
31
- setOptions([{ value: "", label: "— None —" }]);
32
- })
33
- .finally(() => {
34
- if (!cancelled)
35
- setLoading(false);
36
- });
37
- return () => { cancelled = true; };
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-400", children: "Groups this listing with others for the same collectible (e.g. \u201CBase Set Charizard 108/120\u201D)." })] }));
3
+ import { Stack, Text } from "../../../ui";
4
+ import { SublistingInlineSelect } from "../../seller/components/SublistingInlineSelect";
5
+ export function SublistingCategorySelect({ value, onChange, disabled, allowCreate = false, }) {
6
+ 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(SublistingInlineSelect, { value: value, onChange: onChange, disabled: disabled, allowCreate: allowCreate, placeholder: "\u2014 None \u2014" }), _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
7
  }
@@ -31,7 +31,7 @@ function regLabel(resource, id, fallback) {
31
31
  }
32
32
  // ─────────────────────────────────────────────────────────────────────────────
33
33
  // § 1 Product / listing actions
34
- // Used by: detail pages, BulkActionsBar, BuyBar
34
+ // Used by: detail pages, bulk action bars, mobile bottom bars
35
35
  // ─────────────────────────────────────────────────────────────────────────────
36
36
  export const ACTION_ID = {
37
37
  // Standard product
@@ -138,13 +138,13 @@ export const DETAIL_ACTIONS = {
138
138
  /** Pre-order: reserve, wishlist, share */
139
139
  preorder: [ACTION_ID.RESERVE_NOW, ACTION_ID.ADD_TO_WISHLIST, ACTION_ID.SHARE],
140
140
  };
141
- // Mobile BuyBar — 1–2 primary CTAs only (limited horizontal space)
141
+ // Mobile bottom bar — 1–2 primary CTAs only (limited horizontal space)
142
142
  export const MOBILE_PRIMARY_ACTIONS = {
143
143
  product: [ACTION_ID.BUY_NOW, ACTION_ID.ADD_TO_CART],
144
144
  auction: [ACTION_ID.PLACE_BID, ACTION_ID.BUY_NOW_AUCTION],
145
145
  preorder: [ACTION_ID.RESERVE_NOW],
146
146
  };
147
- // Listing page bulk actions — shown in BulkActionsBar when items are selected
147
+ // Listing page bulk actions — shown in the bottom action bar when items are selected
148
148
  export const LISTING_BULK_ACTIONS = {
149
149
  products: [ACTION_ID.ADD_TO_CART, ACTION_ID.ADD_TO_WISHLIST, ACTION_ID.COMPARE],
150
150
  auctions: [ACTION_ID.WATCH_AUCTION, ACTION_ID.UNWATCH_AUCTION, ACTION_ID.COMPARE],
@@ -10,6 +10,6 @@ export declare function useProductDetail<TProduct = ProductItem>(slug: string, o
10
10
  product: TProduct | null;
11
11
  isLoading: boolean;
12
12
  error: Error | null;
13
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<ProductItem | null, Error>>;
13
+ refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<NoInfer<ProductItem | null>, Error>>;
14
14
  };
15
15
  export {};
@@ -4,4 +4,4 @@ import type { ProductListResponse } from "../types";
4
4
  * boolean translates to the canonical `listingType` clause; new callers can
5
5
  * pass the union directly via the same parameter slot in a follow-up.
6
6
  */
7
- export declare function useRelatedProducts(category: string, excludeId: string, limit?: number, isAuction?: boolean): import("@tanstack/react-query").UseQueryResult<ProductListResponse, Error>;
7
+ export declare function useRelatedProducts(category: string, excludeId: string, limit?: number, isAuction?: boolean): import("@tanstack/react-query").UseQueryResult<NoInfer<ProductListResponse>, Error>;
@@ -4,6 +4,8 @@ import { useState } from "react";
4
4
  import { Pencil, Trash2, ToggleLeft, ToggleRight } from "lucide-react";
5
5
  import { BaseListingCard, ConfirmDeleteModal, Div, Row, Span, Text } from "../../../ui";
6
6
  import { useLongPress } from "../../../react/hooks/useLongPress";
7
+ const CLS_TOGGLE_ON = "h-4 w-4 text-emerald-600 dark:text-emerald-400";
8
+ const CLS_DELETE_BTN = "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";
7
9
  const TYPE_COLORS = {
8
10
  percentage: { card: "bg-purple-50 border-purple-200 dark:bg-purple-950/30 dark:border-purple-800", code: "bg-purple-100 dark:bg-purple-900/40 text-purple-800 dark:text-purple-200 border-purple-300 dark:border-purple-700" },
9
11
  fixed: { card: "bg-green-50 border-green-200 dark:bg-green-950/30 dark:border-green-800", code: "bg-green-100 dark:bg-green-900/40 text-green-800 dark:text-green-200 border-green-300 dark:border-green-700" },
@@ -159,7 +161,7 @@ export function CouponCard({ coupon, labels: labelsProp, onCopy, className = "",
159
161
  };
160
162
  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
163
  ? "bg-success-surface text-success"
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", justify: "end", className: "mt-auto pt-3", 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
- ? _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: () => setDeleteConfirmOpen(true), 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" }) }))] })), deleteConfirmOpen && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete Coupon", message: labels.deleteConfirm, onConfirm: handleDeleteConfirmed, onClose: () => setDeleteConfirmOpen(false), isDeleting: busy === "delete" }))] }));
164
+ : "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, { weight: "semibold", className: "inline-flex items-center rounded-full bg-zinc-200/70 px-2 py-0.5 text-[10px] 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, { size: "sm", weight: "bold", className: "flex-1 font-mono 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", justify: "end", className: "mt-auto pt-3", 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
165
+ ? _jsx(ToggleRight, { className: CLS_TOGGLE_ON })
166
+ : _jsx(ToggleLeft, { className: "h-4 w-4" }) })), onDelete && (_jsx("button", { type: "button", onClick: () => setDeleteConfirmOpen(true), disabled: busy === "delete", title: labels.delete, "aria-label": labels.delete, className: CLS_DELETE_BTN, children: _jsx(Trash2, { className: "h-4 w-4" }) }))] })), deleteConfirmOpen && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete Coupon", message: labels.deleteConfirm, onConfirm: handleDeleteConfirmed, onClose: () => setDeleteConfirmOpen(false), isDeleting: busy === "delete" }))] }));
165
167
  }
@@ -3,13 +3,17 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
3
3
  import { useState, useCallback, useMemo } from "react";
4
4
  import { Search, SlidersHorizontal, X } from "lucide-react";
5
5
  import { useUrlTable } from "../../../react/hooks/useUrlTable";
6
- import { ListingFilterDrawer, Pagination, SortDropdown, Div, Grid, Row, Span, Stack, Text, Heading } from "../../../ui";
6
+ import { Button, Label, ListingFilterDrawer, Pagination, SortDropdown, Div, Grid, Row, Span, Stack, Text, Heading } from "../../../ui";
7
7
  import { usePromotions } from "../hooks/usePromotions";
8
8
  import { CouponCard } from "./CouponCard";
9
9
  import { TABLE_KEYS } from "../../../constants/table-keys";
10
10
  import { COUPON_FIELDS } from "../../../constants/field-names";
11
11
  import { sortBy } from "../../../constants/sort";
12
+ const __O = {
13
+ hidden: "overflow-hidden",
14
+ };
12
15
  const DEFAULT_SORT = sortBy(COUPON_FIELDS.CREATED_AT);
16
+ const CLS_CHIP_BTN = "p-0 min-h-0 h-auto inline-flex";
13
17
  const COUPON_SORT_OPTIONS = [
14
18
  { value: sortBy(COUPON_FIELDS.NAME, "ASC"), label: "Name A–Z" },
15
19
  { value: sortBy(COUPON_FIELDS.NAME), label: "Name Z–A" },
@@ -91,12 +95,12 @@ export function CouponsIndexListing({ initialCoupons, storeSlug, storeId, }) {
91
95
  };
92
96
  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(Row, { gap: "xs", className: "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
93
97
  ? "border-primary bg-primary-50 text-primary-700 dark:bg-primary-900/30 dark:text-primary-300"
94
- : "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(Row, { className: "flex-1 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(Row, { gap: "xs", className: "shrink-0 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(Row, { gap: "xs", wrap: true, className: "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(Grid, { gap: "sm", className: "md:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsxs(Stack, { gap: "sm", rounded: "xl", padding: "md", className: "border-2 border-zinc-100 dark:border-slate-700 animate-pulse", 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(Grid, { gap: "sm", className: "md:grid-cols-2 lg:grid-cols-3", children: displayCoupons.map((coupon) => (_jsx(CouponCard, { coupon: coupon, labels: {
98
+ : "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(Row, { surface: "default", className: `flex-1 ${__O.hidden} rounded-lg border border-zinc-300 dark:border-slate-600`, 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(Row, { gap: "xs", className: "shrink-0 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(Row, { gap: "xs", wrap: true, className: "mt-2", children: [activeType && (_jsxs(Span, { size: "xs", weight: "medium", className: "flex items-center gap-1 rounded-full bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300 px-2.5 py-1", children: [COUPON_TYPES.find((t) => t.value === activeType)?.label ?? activeType, _jsx(Button, { variant: "ghost", type: "button", onClick: () => { table.set(TABLE_KEYS.TYPE, ""); }, "aria-label": "Remove type filter", className: CLS_CHIP_BTN, children: _jsx(X, { className: "h-3 w-3" }) })] })), table.get(TABLE_KEYS.DATE_FROM) && (_jsxs(Span, { size: "xs", weight: "medium", className: "flex items-center gap-1 rounded-full bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300 px-2.5 py-1", children: ["From: ", table.get(TABLE_KEYS.DATE_FROM), _jsx(Button, { variant: "ghost", type: "button", onClick: () => { table.set(TABLE_KEYS.DATE_FROM, ""); }, "aria-label": "Remove from-date filter", className: CLS_CHIP_BTN, children: _jsx(X, { className: "h-3 w-3" }) })] })), table.get(TABLE_KEYS.DATE_TO) && (_jsxs(Span, { size: "xs", weight: "medium", className: "flex items-center gap-1 rounded-full bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300 px-2.5 py-1", children: ["To: ", table.get(TABLE_KEYS.DATE_TO), _jsx(Button, { variant: "ghost", type: "button", onClick: () => { table.set(TABLE_KEYS.DATE_TO, ""); }, "aria-label": "Remove to-date filter", className: CLS_CHIP_BTN, 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(Grid, { gap: "sm", className: "md:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsxs(Stack, { gap: "sm", rounded: "xl", padding: "md", className: "border-2 border-zinc-100 dark:border-slate-700 animate-pulse", 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(Grid, { gap: "sm", className: "md:grid-cols-2 lg:grid-cols-3", children: displayCoupons.map((coupon) => (_jsx(CouponCard, { coupon: coupon, labels: {
95
99
  copy: "Copy",
96
100
  copied: "Copied!",
97
101
  expires: "Expires",
98
102
  minOrder: "Min. order",
99
103
  off: "OFF",
100
104
  freeShipping: "Free Shipping",
101
- } }, coupon.id))) })), totalPages > 1 && (_jsx(Row, { justify: "center", className: "mt-8", 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"] }) }))] }), _jsxs(ListingFilterDrawer, { open: filterOpen, onClose: () => setFilterOpen(false), onApply: applyFilters, onClear: clearPending, activeCount: activeFilterCount, 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(Stack, { gap: "xs", 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(Stack, { gap: "sm", 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" })] })] })] })] })] }));
105
+ } }, coupon.id))) })), totalPages > 1 && (_jsx(Row, { justify: "center", className: "mt-8", 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"] }) }))] }), _jsxs(ListingFilterDrawer, { open: filterOpen, onClose: () => setFilterOpen(false), onApply: applyFilters, onClear: clearPending, activeCount: activeFilterCount, 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(Stack, { gap: "xs", 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(Stack, { gap: "sm", 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" })] })] })] })] })] }));
102
106
  }
@@ -9,13 +9,13 @@ export declare function usePromotions(params?: PromotionsListParams, opts?: {
9
9
  hasMore: boolean;
10
10
  isLoading: boolean;
11
11
  error: string | null;
12
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<PromotionsListResponse, Error>>;
12
+ refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<NoInfer<PromotionsListResponse>, Error>>;
13
13
  };
14
14
  export declare function useCoupon(code: string, opts?: {
15
15
  enabled?: boolean;
16
16
  endpoint?: string;
17
17
  }): {
18
- coupon: CouponItem | null;
18
+ coupon: NonNullable<NoInfer<CouponItem | null>> | null;
19
19
  isLoading: boolean;
20
20
  error: string | null;
21
21
  };
@@ -202,6 +202,14 @@ export declare class CouponsRepository extends BaseRepository<CouponDocument> {
202
202
  canFilter: boolean;
203
203
  canSort: boolean;
204
204
  };
205
+ storeId: {
206
+ canFilter: boolean;
207
+ canSort: boolean;
208
+ };
209
+ scope: {
210
+ canFilter: boolean;
211
+ canSort: boolean;
212
+ };
205
213
  };
206
214
  /**
207
215
  * Paginated, Firestore-native coupon list.
@@ -505,6 +505,8 @@ CouponsRepository.SIEVE_FIELDS = {
505
505
  canSort: true,
506
506
  },
507
507
  createdAt: { canFilter: true, canSort: true },
508
+ storeId: { canFilter: true, canSort: false },
509
+ scope: { canFilter: true, canSort: false },
508
510
  };
509
511
  // Export singleton instance
510
512
  export const couponsRepository = new CouponsRepository();
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import Link from "next/link";
3
3
  import { reviewRepository } from "../../../repositories";
4
- import { Container, Heading, Main, Section, Text } from "../../../ui";
4
+ import { Container, Div, Heading, Main, Nav, Section, Span, Text } from "../../../ui";
5
5
  import { ROUTES } from "../../../next";
6
6
  import { ReviewDetailShell } from "./ReviewDetailShell";
7
7
  export async function ReviewDetailPageView({ id }) {
@@ -10,7 +10,7 @@ export async function ReviewDetailPageView({ id }) {
10
10
  // storeId === storeSlug for stores in this project (pure slug IDs)
11
11
  const storeSlug = doc?.storeId ?? null;
12
12
  if (!review || review.status !== "approved") {
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" })] }) }) }) }));
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-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 })] }));
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
  }