@mohasinac/appkit 2.3.2 → 2.4.0

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 (677) hide show
  1. package/dist/client.d.ts +44 -12
  2. package/dist/client.js +22 -6
  3. package/dist/constants/api-endpoints.d.ts +380 -22
  4. package/dist/constants/api-endpoints.js +66 -13
  5. package/dist/constants/index.d.ts +1 -1
  6. package/dist/constants/index.js +1 -1
  7. package/dist/core/hooks/useSyncManager.d.ts +1 -0
  8. package/dist/core/hooks/useSyncManager.js +83 -0
  9. package/dist/core/integration-keys.d.ts +4 -0
  10. package/dist/core/integration-keys.js +8 -0
  11. package/dist/features/about/components/FAQPageView.js +9 -11
  12. package/dist/features/about/components/PolicyPageView.js +32 -11
  13. package/dist/features/about/components/PublicProfileView.js +77 -11
  14. package/dist/features/account/components/AddressesIndexListing.js +63 -38
  15. package/dist/features/account/components/UserOffersPanel.d.ts +8 -0
  16. package/dist/features/account/components/UserOffersPanel.js +81 -0
  17. package/dist/features/account/components/UserSettingsView.d.ts +2 -1
  18. package/dist/features/account/components/UserSettingsView.js +2 -1
  19. package/dist/features/account/components/UserSidebar.d.ts +6 -1
  20. package/dist/features/account/components/UserSidebar.js +48 -42
  21. package/dist/features/account/components/index.d.ts +2 -0
  22. package/dist/features/account/components/index.js +1 -0
  23. package/dist/features/admin/actions/admin-actions.d.ts +1 -1
  24. package/dist/features/admin/actions/admin-actions.js +13 -3
  25. package/dist/features/admin/components/AdminAdEditorView.js +6 -7
  26. package/dist/features/admin/components/AdminAllEventEntriesView.d.ts +4 -0
  27. package/dist/features/admin/components/AdminAllEventEntriesView.js +102 -0
  28. package/dist/features/admin/components/AdminBidsView.js +94 -8
  29. package/dist/features/admin/components/AdminBlogEditorView.d.ts +7 -0
  30. package/dist/features/admin/components/AdminBlogEditorView.js +162 -0
  31. package/dist/features/admin/components/AdminBlogView.d.ts +4 -1
  32. package/dist/features/admin/components/AdminBlogView.js +61 -31
  33. package/dist/features/admin/components/AdminBrandEditorView.d.ts +7 -0
  34. package/dist/features/admin/components/AdminBrandEditorView.js +104 -0
  35. package/dist/features/admin/components/AdminBrandsView.d.ts +4 -0
  36. package/dist/features/admin/components/AdminBrandsView.js +76 -0
  37. package/dist/features/admin/components/AdminCarouselEditorView.d.ts +8 -0
  38. package/dist/features/admin/components/AdminCarouselEditorView.js +204 -0
  39. package/dist/features/admin/components/AdminCarouselView.js +153 -34
  40. package/dist/features/admin/components/AdminCartsView.d.ts +4 -0
  41. package/dist/features/admin/components/AdminCartsView.js +82 -0
  42. package/dist/features/admin/components/AdminCategoriesView.d.ts +4 -1
  43. package/dist/features/admin/components/AdminCategoriesView.js +66 -48
  44. package/dist/features/admin/components/AdminCategoryEditorView.d.ts +7 -0
  45. package/dist/features/admin/components/AdminCategoryEditorView.js +115 -0
  46. package/dist/features/admin/components/AdminContactEditorView.d.ts +11 -0
  47. package/dist/features/admin/components/AdminContactEditorView.js +32 -0
  48. package/dist/features/admin/components/AdminContactView.js +111 -20
  49. package/dist/features/admin/components/AdminCouponEditorView.d.ts +7 -0
  50. package/dist/features/admin/components/AdminCouponEditorView.js +179 -0
  51. package/dist/features/admin/components/AdminCouponsView.d.ts +4 -1
  52. package/dist/features/admin/components/AdminCouponsView.js +57 -9
  53. package/dist/features/admin/components/AdminDashboardView.js +3 -0
  54. package/dist/features/admin/components/AdminFaqEditorView.d.ts +7 -0
  55. package/dist/features/admin/components/AdminFaqEditorView.js +128 -0
  56. package/dist/features/admin/components/AdminFaqsView.d.ts +4 -1
  57. package/dist/features/admin/components/AdminFaqsView.js +55 -23
  58. package/dist/features/admin/components/AdminFeatureFlagsView.js +33 -24
  59. package/dist/features/admin/components/AdminListingScaffold.d.ts +7 -1
  60. package/dist/features/admin/components/AdminListingScaffold.js +2 -2
  61. package/dist/features/admin/components/AdminMediaView.js +18 -8
  62. package/dist/features/admin/components/AdminNavEditorView.d.ts +20 -0
  63. package/dist/features/admin/components/AdminNavEditorView.js +84 -0
  64. package/dist/features/admin/components/AdminNavigationView.d.ts +1 -7
  65. package/dist/features/admin/components/AdminNavigationView.js +84 -72
  66. package/dist/features/admin/components/AdminNewsletterView.js +102 -20
  67. package/dist/features/admin/components/AdminNotificationsView.d.ts +4 -0
  68. package/dist/features/admin/components/AdminNotificationsView.js +119 -0
  69. package/dist/features/admin/components/AdminOrderEditorView.d.ts +8 -0
  70. package/dist/features/admin/components/AdminOrderEditorView.js +74 -0
  71. package/dist/features/admin/components/AdminOrdersView.js +64 -8
  72. package/dist/features/admin/components/AdminPayoutsView.js +122 -13
  73. package/dist/features/admin/components/AdminProductEditorView.d.ts +7 -0
  74. package/dist/features/admin/components/AdminProductEditorView.js +143 -0
  75. package/dist/features/admin/components/AdminProductsView.d.ts +4 -1
  76. package/dist/features/admin/components/AdminProductsView.js +119 -30
  77. package/dist/features/admin/components/AdminReturnRequestsView.d.ts +5 -0
  78. package/dist/features/admin/components/AdminReturnRequestsView.js +101 -0
  79. package/dist/features/admin/components/AdminReviewsView.js +138 -28
  80. package/dist/features/admin/components/AdminSectionsView.js +361 -472
  81. package/dist/features/admin/components/AdminSessionsView.d.ts +4 -0
  82. package/dist/features/admin/components/AdminSessionsView.js +119 -0
  83. package/dist/features/admin/components/AdminSidebar.d.ts +18 -3
  84. package/dist/features/admin/components/AdminSidebar.js +51 -4
  85. package/dist/features/admin/components/AdminSiteSettingsView.d.ts +7 -0
  86. package/dist/features/admin/components/AdminSiteSettingsView.js +319 -0
  87. package/dist/features/admin/components/AdminStoreAddressesView.d.ts +5 -0
  88. package/dist/features/admin/components/AdminStoreAddressesView.js +52 -0
  89. package/dist/features/admin/components/AdminStoreEditorView.d.ts +9 -0
  90. package/dist/features/admin/components/AdminStoreEditorView.js +55 -0
  91. package/dist/features/admin/components/AdminStoresView.js +62 -20
  92. package/dist/features/admin/components/AdminUserEditorView.d.ts +10 -0
  93. package/dist/features/admin/components/AdminUserEditorView.js +72 -0
  94. package/dist/features/admin/components/AdminUsersView.js +70 -36
  95. package/dist/features/admin/components/AdminWishlistsView.d.ts +4 -0
  96. package/dist/features/admin/components/AdminWishlistsView.js +53 -0
  97. package/dist/features/admin/components/BrandQuickCreateForm.d.ts +5 -0
  98. package/dist/features/admin/components/BrandQuickCreateForm.js +36 -0
  99. package/dist/features/admin/components/CategoryQuickCreateForm.d.ts +5 -0
  100. package/dist/features/admin/components/CategoryQuickCreateForm.js +35 -0
  101. package/dist/features/admin/components/DataTable.d.ts +4 -2
  102. package/dist/features/admin/components/DataTable.js +26 -6
  103. package/dist/features/admin/components/index.d.ts +47 -1
  104. package/dist/features/admin/components/index.js +23 -0
  105. package/dist/features/admin/components/sections/adminSectionsBuildParse.d.ts +48 -0
  106. package/dist/features/admin/components/sections/adminSectionsBuildParse.js +653 -0
  107. package/dist/features/admin/components/sections/adminSectionsTypes.d.ts +298 -0
  108. package/dist/features/admin/components/sections/adminSectionsTypes.js +278 -0
  109. package/dist/features/admin/schemas/firestore.d.ts +26 -0
  110. package/dist/features/admin/schemas/firestore.js +1 -0
  111. package/dist/features/admin/types/product.types.d.ts +2 -3
  112. package/dist/features/auctions/actions/bid-actions.js +6 -2
  113. package/dist/features/auctions/components/AuctionDetailPageView.d.ts +3 -1
  114. package/dist/features/auctions/components/AuctionDetailPageView.js +38 -12
  115. package/dist/features/auctions/components/AuctionFilters.d.ts +3 -1
  116. package/dist/features/auctions/components/AuctionFilters.js +6 -2
  117. package/dist/features/auctions/components/CollapsibleBidHistory.d.ts +7 -0
  118. package/dist/features/auctions/components/CollapsibleBidHistory.js +8 -0
  119. package/dist/features/auctions/components/MarketplaceAuctionCard.d.ts +4 -0
  120. package/dist/features/auctions/components/MarketplaceAuctionCard.js +43 -9
  121. package/dist/features/auctions/components/MarketplaceAuctionGrid.js +1 -0
  122. package/dist/features/auctions/components/PlaceBidFormClient.d.ts +18 -0
  123. package/dist/features/auctions/components/PlaceBidFormClient.js +33 -0
  124. package/dist/features/auctions/hooks/useAuctions.d.ts +1 -0
  125. package/dist/features/auctions/hooks/useAuctions.js +1 -0
  126. package/dist/features/auctions/schemas/index.d.ts +22 -12
  127. package/dist/features/auth/actions/profile-actions.d.ts +5 -3
  128. package/dist/features/auth/actions/profile-actions.js +30 -11
  129. package/dist/features/auth/auth-helpers.js +1 -0
  130. package/dist/features/auth/components/LoginForm.js +2 -1
  131. package/dist/features/auth/hooks/useAuth.js +16 -4
  132. package/dist/features/auth/permissions/constants.d.ts +63 -0
  133. package/dist/features/auth/permissions/constants.js +323 -0
  134. package/dist/features/auth/schemas/firestore.d.ts +20 -0
  135. package/dist/features/auth/schemas/index.d.ts +4 -4
  136. package/dist/features/auth/schemas/index.js +3 -2
  137. package/dist/features/auth/types/index.d.ts +1 -1
  138. package/dist/features/before-after/schemas/index.d.ts +2 -2
  139. package/dist/features/blog/actions/blog-actions.d.ts +15 -15
  140. package/dist/features/blog/components/BlogFilters.js +1 -1
  141. package/dist/features/blog/components/BlogIndexListing.js +57 -5
  142. package/dist/features/blog/components/BlogIndexPageView.js +14 -2
  143. package/dist/features/blog/components/BlogPostForm.js +6 -2
  144. package/dist/features/blog/components/BlogPostView.js +2 -1
  145. package/dist/features/blog/hooks/useBlog.d.ts +2 -0
  146. package/dist/features/blog/hooks/useBlog.js +2 -0
  147. package/dist/features/blog/schemas/index.d.ts +46 -12
  148. package/dist/features/brands/actions/brand-actions.d.ts +2 -0
  149. package/dist/features/brands/actions/brand-actions.js +5 -0
  150. package/dist/features/brands/index.d.ts +3 -0
  151. package/dist/features/brands/index.js +3 -0
  152. package/dist/features/brands/repository/brands.repository.d.ts +13 -0
  153. package/dist/features/brands/repository/brands.repository.js +60 -0
  154. package/dist/features/brands/schemas/index.d.ts +33 -0
  155. package/dist/features/brands/schemas/index.js +15 -0
  156. package/dist/features/brands/server.d.ts +7 -0
  157. package/dist/features/brands/server.js +7 -0
  158. package/dist/features/cart/actions/cart-actions.js +2 -2
  159. package/dist/features/cart/components/CartDrawer.d.ts +5 -1
  160. package/dist/features/cart/components/CartDrawer.js +3 -3
  161. package/dist/features/cart/hooks/useCartCount.d.ts +3 -2
  162. package/dist/features/cart/hooks/useCartCount.js +4 -2
  163. package/dist/features/cart/hooks/useGuestCartMerge.js +1 -1
  164. package/dist/features/cart/index.d.ts +1 -0
  165. package/dist/features/cart/index.js +1 -0
  166. package/dist/features/cart/repository/cart.repository.d.ts +5 -1
  167. package/dist/features/cart/repository/cart.repository.js +36 -5
  168. package/dist/features/cart/schemas/firestore.d.ts +25 -6
  169. package/dist/features/cart/schemas/firestore.js +2 -2
  170. package/dist/features/cart/schemas/index.d.ts +9 -9
  171. package/dist/features/cart/schemas/index.js +1 -1
  172. package/dist/features/cart/types/index.d.ts +1 -1
  173. package/dist/features/cart/utils/pending-ops.d.ts +33 -0
  174. package/dist/features/cart/utils/pending-ops.js +102 -0
  175. package/dist/features/categories/components/BrandDetailPageView.d.ts +4 -0
  176. package/dist/features/categories/components/BrandDetailPageView.js +54 -0
  177. package/dist/features/categories/components/BrandDetailTabs.d.ts +10 -0
  178. package/dist/features/categories/components/BrandDetailTabs.js +22 -0
  179. package/dist/features/categories/components/CategoriesIndexListing.d.ts +3 -1
  180. package/dist/features/categories/components/CategoriesIndexListing.js +83 -7
  181. package/dist/features/categories/components/CategoryDetailPageView.js +42 -21
  182. package/dist/features/categories/components/CategoryDetailTabs.d.ts +7 -1
  183. package/dist/features/categories/components/CategoryDetailTabs.js +12 -7
  184. package/dist/features/categories/components/CategoryFilters.js +1 -1
  185. package/dist/features/categories/components/CategoryForm.js +10 -4
  186. package/dist/features/categories/components/CategoryProductsListing.d.ts +4 -1
  187. package/dist/features/categories/components/CategoryProductsListing.js +34 -5
  188. package/dist/features/categories/components/ConcernCard.js +1 -1
  189. package/dist/features/categories/hooks/useCategories.js +2 -0
  190. package/dist/features/categories/repository/categories.repository.js +2 -3
  191. package/dist/features/categories/schemas/firestore.d.ts +23 -2
  192. package/dist/features/categories/schemas/firestore.js +8 -0
  193. package/dist/features/categories/schemas/index.d.ts +8 -8
  194. package/dist/features/categories/types/index.d.ts +1 -0
  195. package/dist/features/collections/schemas/index.d.ts +2 -2
  196. package/dist/features/events/components/AdminEventEditorView.js +2 -2
  197. package/dist/features/events/components/AdminEventsView.d.ts +4 -1
  198. package/dist/features/events/components/AdminEventsView.js +64 -38
  199. package/dist/features/events/components/EventCard.js +1 -1
  200. package/dist/features/events/components/EventFilters.js +1 -1
  201. package/dist/features/events/components/EventPollWidget.d.ts +12 -0
  202. package/dist/features/events/components/EventPollWidget.js +62 -0
  203. package/dist/features/events/components/EventsIndexListing.js +57 -5
  204. package/dist/features/events/components/EventsListPageView.js +1 -1
  205. package/dist/features/events/components/index.d.ts +2 -0
  206. package/dist/features/events/components/index.js +1 -0
  207. package/dist/features/events/hooks/useEvents.d.ts +1 -0
  208. package/dist/features/events/hooks/useEvents.js +1 -0
  209. package/dist/features/events/repository/events.repository.js +3 -0
  210. package/dist/features/events/schemas/firestore.d.ts +1 -0
  211. package/dist/features/events/schemas/index.d.ts +44 -0
  212. package/dist/features/events/types/index.d.ts +2 -0
  213. package/dist/features/faq/actions/faq-actions.d.ts +16 -16
  214. package/dist/features/faq/hooks/useFaqList.js +1 -1
  215. package/dist/features/faq/schemas/firestore.d.ts +2 -2
  216. package/dist/features/faq/schemas/firestore.js +2 -1
  217. package/dist/features/faq/schemas/index.d.ts +4 -4
  218. package/dist/features/filters/FilterFacetSection.d.ts +1 -0
  219. package/dist/features/filters/FilterFacetSection.js +13 -1
  220. package/dist/features/filters/SwitchFilter.js +1 -1
  221. package/dist/features/grouped/schemas/firestore.d.ts +32 -0
  222. package/dist/features/grouped/schemas/firestore.js +19 -0
  223. package/dist/features/homepage/components/AdSlot.d.ts +1 -3
  224. package/dist/features/homepage/components/AdSlot.js +15 -14
  225. package/dist/features/homepage/components/BlogArticlesSection.d.ts +3 -1
  226. package/dist/features/homepage/components/BlogArticlesSection.js +2 -2
  227. package/dist/features/homepage/components/BrandsSection.d.ts +3 -1
  228. package/dist/features/homepage/components/BrandsSection.js +4 -3
  229. package/dist/features/homepage/components/CustomCardsSection.d.ts +3 -0
  230. package/dist/features/homepage/components/CustomCardsSection.js +76 -0
  231. package/dist/features/homepage/components/EventsSection.d.ts +3 -1
  232. package/dist/features/homepage/components/EventsSection.js +2 -2
  233. package/dist/features/homepage/components/FeaturedAuctionsSection.d.ts +4 -1
  234. package/dist/features/homepage/components/FeaturedAuctionsSection.js +2 -2
  235. package/dist/features/homepage/components/FeaturedPreOrdersSection.d.ts +4 -1
  236. package/dist/features/homepage/components/FeaturedPreOrdersSection.js +2 -2
  237. package/dist/features/homepage/components/FeaturedProductsSection.d.ts +4 -1
  238. package/dist/features/homepage/components/FeaturedProductsSection.js +8 -3
  239. package/dist/features/homepage/components/FeaturedStoresSection.d.ts +3 -1
  240. package/dist/features/homepage/components/FeaturedStoresSection.js +2 -2
  241. package/dist/features/homepage/components/GoogleReviewsSection.d.ts +3 -0
  242. package/dist/features/homepage/components/GoogleReviewsSection.js +65 -0
  243. package/dist/features/homepage/components/HeroCarousel.js +128 -84
  244. package/dist/features/homepage/components/MarketplaceHomepageView.d.ts +2 -20
  245. package/dist/features/homepage/components/MarketplaceHomepageView.js +73 -230
  246. package/dist/features/homepage/components/SectionCarousel.d.ts +1 -1
  247. package/dist/features/homepage/components/SectionCarousel.js +2 -0
  248. package/dist/features/homepage/components/ShopByCategorySection.d.ts +3 -1
  249. package/dist/features/homepage/components/ShopByCategorySection.js +8 -4
  250. package/dist/features/homepage/components/SocialFeedSection.d.ts +3 -0
  251. package/dist/features/homepage/components/SocialFeedSection.js +86 -0
  252. package/dist/features/homepage/components/SocialPostCard.d.ts +7 -0
  253. package/dist/features/homepage/components/SocialPostCard.js +39 -0
  254. package/dist/features/homepage/components/StatsCounterSection.js +1 -1
  255. package/dist/features/homepage/components/WelcomeSection.js +1 -1
  256. package/dist/features/homepage/components/WhatsAppCommunitySection.js +1 -1
  257. package/dist/features/homepage/hooks/useActiveAd.d.ts +23 -0
  258. package/dist/features/homepage/hooks/useActiveAd.js +20 -0
  259. package/dist/features/homepage/hooks/useBlogArticles.d.ts +1 -0
  260. package/dist/features/homepage/hooks/useBlogArticles.js +10 -0
  261. package/dist/features/homepage/hooks/useFeaturedAuctions.d.ts +4 -1
  262. package/dist/features/homepage/hooks/useFeaturedAuctions.js +8 -4
  263. package/dist/features/homepage/hooks/useFeaturedPreOrders.d.ts +4 -1
  264. package/dist/features/homepage/hooks/useFeaturedPreOrders.js +8 -4
  265. package/dist/features/homepage/hooks/useFeaturedProducts.d.ts +1 -0
  266. package/dist/features/homepage/hooks/useFeaturedProducts.js +6 -3
  267. package/dist/features/homepage/hooks/useFeaturedStores.d.ts +3 -1
  268. package/dist/features/homepage/hooks/useFeaturedStores.js +2 -1
  269. package/dist/features/homepage/hooks/useHomepageEvents.d.ts +3 -1
  270. package/dist/features/homepage/hooks/useHomepageEvents.js +2 -1
  271. package/dist/features/homepage/hooks/useTopBrands.d.ts +3 -1
  272. package/dist/features/homepage/hooks/useTopBrands.js +2 -1
  273. package/dist/features/homepage/index.d.ts +2 -0
  274. package/dist/features/homepage/index.js +1 -0
  275. package/dist/features/homepage/lib/google-reviews-fetcher.d.ts +14 -0
  276. package/dist/features/homepage/lib/google-reviews-fetcher.js +27 -0
  277. package/dist/features/homepage/lib/live-stats.d.ts +14 -0
  278. package/dist/features/homepage/lib/live-stats.js +62 -0
  279. package/dist/features/homepage/lib/section-defaults.d.ts +11 -0
  280. package/dist/features/homepage/lib/section-defaults.js +45 -0
  281. package/dist/features/homepage/lib/section-helpers.d.ts +5 -0
  282. package/dist/features/homepage/lib/section-helpers.js +25 -0
  283. package/dist/features/homepage/lib/section-renderer.d.ts +33 -0
  284. package/dist/features/homepage/lib/section-renderer.js +164 -0
  285. package/dist/features/homepage/lib/social-feed-fetcher.d.ts +5 -0
  286. package/dist/features/homepage/lib/social-feed-fetcher.js +193 -0
  287. package/dist/features/homepage/schemas/firestore.d.ts +180 -29
  288. package/dist/features/homepage/schemas/firestore.js +5 -0
  289. package/dist/features/homepage/types/index.d.ts +48 -19
  290. package/dist/features/layout/AppLayoutShell.d.ts +6 -1
  291. package/dist/features/layout/AppLayoutShell.js +25 -9
  292. package/dist/features/layout/BottomActions.js +1 -1
  293. package/dist/features/layout/BottomNavbar.d.ts +15 -1
  294. package/dist/features/layout/BottomNavbar.js +8 -2
  295. package/dist/features/layout/FooterLayout.d.ts +7 -1
  296. package/dist/features/layout/FooterLayout.js +3 -3
  297. package/dist/features/layout/ListingLayout.js +2 -2
  298. package/dist/features/layout/MainNavbar.d.ts +6 -14
  299. package/dist/features/layout/MainNavbar.js +4 -16
  300. package/dist/features/layout/NavItem.js +1 -1
  301. package/dist/features/layout/NavbarLayout.d.ts +3 -1
  302. package/dist/features/layout/NavbarLayout.js +5 -5
  303. package/dist/features/layout/TitleBar.d.ts +4 -2
  304. package/dist/features/layout/TitleBar.js +5 -3
  305. package/dist/features/layout/TitleBarLayout.d.ts +3 -1
  306. package/dist/features/layout/TitleBarLayout.js +2 -2
  307. package/dist/features/layout/index.d.ts +1 -1
  308. package/dist/features/media/MediaPickerModal.d.ts +30 -0
  309. package/dist/features/media/MediaPickerModal.js +72 -0
  310. package/dist/features/media/index.d.ts +3 -1
  311. package/dist/features/media/index.js +1 -0
  312. package/dist/features/media/types/index.d.ts +12 -0
  313. package/dist/features/media/types/index.js +4 -2
  314. package/dist/features/media/upload/MediaUploadField.d.ts +5 -1
  315. package/dist/features/media/upload/MediaUploadField.js +56 -3
  316. package/dist/features/messages/schemas/firestore.d.ts +36 -0
  317. package/dist/features/messages/schemas/firestore.js +16 -0
  318. package/dist/features/orders/repository/orders.repository.d.ts +2 -2
  319. package/dist/features/orders/repository/orders.repository.js +2 -2
  320. package/dist/features/orders/schemas/firestore.d.ts +17 -4
  321. package/dist/features/orders/schemas/firestore.js +2 -2
  322. package/dist/features/orders/schemas/index.d.ts +18 -18
  323. package/dist/features/orders/schemas/index.js +3 -3
  324. package/dist/features/orders/types/index.d.ts +1 -1
  325. package/dist/features/orders/utils/order-splitter.d.ts +1 -1
  326. package/dist/features/orders/utils/order-splitter.js +2 -2
  327. package/dist/features/payments/repository/payout.repository.d.ts +4 -4
  328. package/dist/features/payments/repository/payout.repository.js +7 -7
  329. package/dist/features/payments/schemas/firestore.d.ts +6 -6
  330. package/dist/features/payments/schemas/firestore.js +6 -6
  331. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +11 -10
  332. package/dist/features/pre-orders/components/PreOrderActionsClient.d.ts +11 -0
  333. package/dist/features/pre-orders/components/PreOrderActionsClient.js +28 -0
  334. package/dist/features/pre-orders/components/PreOrderDetailPageView.d.ts +2 -1
  335. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +27 -9
  336. package/dist/features/pre-orders/components/PreOrderFilters.d.ts +3 -1
  337. package/dist/features/pre-orders/components/PreOrderFilters.js +9 -6
  338. package/dist/features/pre-orders/components/PreOrdersIndexListing.d.ts +3 -1
  339. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +132 -36
  340. package/dist/features/pre-orders/components/PreOrdersListView.js +3 -3
  341. package/dist/features/pre-orders/components/PreorderCard.js +1 -1
  342. package/dist/features/pre-orders/schemas/index.d.ts +10 -0
  343. package/dist/features/products/actions/product-actions.d.ts +2 -2
  344. package/dist/features/products/actions/product-actions.js +5 -5
  345. package/dist/features/products/api/[id]/route.js +5 -2
  346. package/dist/features/products/api/route.js +10 -14
  347. package/dist/features/products/columns/productTableColumns.js +2 -2
  348. package/dist/features/products/components/AuctionDetailView.d.ts +2 -1
  349. package/dist/features/products/components/AuctionDetailView.js +2 -2
  350. package/dist/features/products/components/AuctionsIndexListing.d.ts +3 -1
  351. package/dist/features/products/components/AuctionsIndexListing.js +93 -31
  352. package/dist/features/products/components/BidHistory.d.ts +2 -1
  353. package/dist/features/products/components/BidHistory.js +18 -2
  354. package/dist/features/products/components/MakeOfferButton.d.ts +10 -0
  355. package/dist/features/products/components/MakeOfferButton.js +68 -0
  356. package/dist/features/products/components/ProductDetailPageView.d.ts +11 -1
  357. package/dist/features/products/components/ProductDetailPageView.js +27 -8
  358. package/dist/features/products/components/ProductFilters.d.ts +7 -1
  359. package/dist/features/products/components/ProductFilters.js +4 -2
  360. package/dist/features/products/components/ProductForm.d.ts +19 -1
  361. package/dist/features/products/components/ProductForm.js +24 -6
  362. package/dist/features/products/components/ProductGrid.d.ts +10 -2
  363. package/dist/features/products/components/ProductGrid.js +76 -29
  364. package/dist/features/products/components/ProductsIndexListing.js +131 -45
  365. package/dist/features/products/components/RelatedProductsCarousel.js +1 -1
  366. package/dist/features/products/components/ShareButton.d.ts +7 -0
  367. package/dist/features/products/components/ShareButton.js +22 -0
  368. package/dist/features/products/components/index.d.ts +2 -0
  369. package/dist/features/products/components/index.js +1 -0
  370. package/dist/features/products/hooks/useProducts.d.ts +7 -0
  371. package/dist/features/products/hooks/useProducts.js +6 -4
  372. package/dist/features/products/repository/products.repository.d.ts +4 -8
  373. package/dist/features/products/repository/products.repository.js +17 -50
  374. package/dist/features/products/schemas/firestore.d.ts +11 -9
  375. package/dist/features/products/schemas/firestore.js +11 -3
  376. package/dist/features/products/schemas/index.d.ts +51 -50
  377. package/dist/features/products/schemas/index.js +2 -5
  378. package/dist/features/products/types/index.d.ts +13 -5
  379. package/dist/features/promotions/actions/coupon-actions.d.ts +2 -2
  380. package/dist/features/promotions/actions/coupon-actions.js +1 -1
  381. package/dist/features/promotions/actions/seller-coupon-actions.js +11 -6
  382. package/dist/features/promotions/api/route.js +3 -3
  383. package/dist/features/promotions/components/CouponCard.js +16 -7
  384. package/dist/features/promotions/components/CouponsIndexListing.js +3 -9
  385. package/dist/features/promotions/hooks/useCouponValidate.d.ts +1 -1
  386. package/dist/features/promotions/hooks/usePromotions.js +2 -2
  387. package/dist/features/promotions/repository/coupons.repository.d.ts +21 -15
  388. package/dist/features/promotions/repository/coupons.repository.js +97 -125
  389. package/dist/features/promotions/schemas/firestore.d.ts +31 -2
  390. package/dist/features/promotions/schemas/firestore.js +29 -0
  391. package/dist/features/promotions/schemas/index.d.ts +9 -12
  392. package/dist/features/promotions/schemas/index.js +1 -2
  393. package/dist/features/promotions/types/index.d.ts +1 -2
  394. package/dist/features/reviews/actions/review-actions.js +3 -2
  395. package/dist/features/reviews/components/ReviewDetailPageView.js +5 -9
  396. package/dist/features/reviews/components/ReviewFilters.js +1 -1
  397. package/dist/features/reviews/components/ReviewsIndexListing.js +58 -7
  398. package/dist/features/reviews/components/ReviewsList.js +2 -2
  399. package/dist/features/reviews/hooks/useReviews.d.ts +1 -0
  400. package/dist/features/reviews/hooks/useReviews.js +2 -1
  401. package/dist/features/reviews/repository/reviews.repository.d.ts +9 -4
  402. package/dist/features/reviews/repository/reviews.repository.js +18 -7
  403. package/dist/features/reviews/schemas/firestore.d.ts +5 -2
  404. package/dist/features/reviews/schemas/firestore.js +1 -0
  405. package/dist/features/reviews/schemas/index.d.ts +19 -16
  406. package/dist/features/reviews/schemas/index.js +3 -2
  407. package/dist/features/reviews/types/index.d.ts +3 -2
  408. package/dist/features/scams/actions/scam-actions.d.ts +29 -0
  409. package/dist/features/scams/actions/scam-actions.js +62 -0
  410. package/dist/features/scams/components/ScamProfileView.d.ts +7 -0
  411. package/dist/features/scams/components/ScamProfileView.js +49 -0
  412. package/dist/features/scams/components/ScamRegistryView.d.ts +6 -0
  413. package/dist/features/scams/components/ScamRegistryView.js +41 -0
  414. package/dist/features/scams/components/index.d.ts +4 -0
  415. package/dist/features/scams/components/index.js +2 -0
  416. package/dist/features/scams/constants/scam-types.d.ts +38 -0
  417. package/dist/features/scams/constants/scam-types.js +443 -0
  418. package/dist/features/scams/repository/scammer.repository.d.ts +67 -0
  419. package/dist/features/scams/repository/scammer.repository.js +160 -0
  420. package/dist/features/scams/schemas/firestore.d.ts +362 -0
  421. package/dist/features/scams/schemas/firestore.js +233 -0
  422. package/dist/features/search/components/Search.d.ts +12 -2
  423. package/dist/features/search/components/Search.js +26 -7
  424. package/dist/features/search/components/index.d.ts +1 -1
  425. package/dist/features/search/hooks/useNavSuggestions.d.ts +1 -1
  426. package/dist/features/search/hooks/useNavSuggestions.js +2 -2
  427. package/dist/features/search/schemas/index.d.ts +7 -7
  428. package/dist/features/seller/actions/offer-actions.js +52 -36
  429. package/dist/features/seller/actions/seller-actions.js +19 -13
  430. package/dist/features/seller/api/products/route.js +9 -4
  431. package/dist/features/seller/components/SellerAddressesView.d.ts +3 -12
  432. package/dist/features/seller/components/SellerAddressesView.js +144 -4
  433. package/dist/features/seller/components/SellerAuctionsView.js +58 -5
  434. package/dist/features/seller/components/SellerBidsView.d.ts +4 -0
  435. package/dist/features/seller/components/SellerBidsView.js +131 -0
  436. package/dist/features/seller/components/SellerCouponEditorView.d.ts +19 -0
  437. package/dist/features/seller/components/SellerCouponEditorView.js +67 -0
  438. package/dist/features/seller/components/SellerCouponsView.d.ts +5 -3
  439. package/dist/features/seller/components/SellerCouponsView.js +135 -13
  440. package/dist/features/seller/components/SellerCreateProductView.d.ts +4 -10
  441. package/dist/features/seller/components/SellerCreateProductView.js +4 -3
  442. package/dist/features/seller/components/SellerEditProductView.d.ts +4 -10
  443. package/dist/features/seller/components/SellerEditProductView.js +4 -3
  444. package/dist/features/seller/components/SellerOffersPanel.d.ts +20 -0
  445. package/dist/features/seller/components/SellerOffersPanel.js +138 -0
  446. package/dist/features/seller/components/SellerOffersView.js +56 -5
  447. package/dist/features/seller/components/SellerOrdersView.d.ts +2 -1
  448. package/dist/features/seller/components/SellerOrdersView.js +185 -16
  449. package/dist/features/seller/components/SellerPayoutRequestView.d.ts +7 -0
  450. package/dist/features/seller/components/SellerPayoutRequestView.js +63 -0
  451. package/dist/features/seller/components/SellerPayoutSettingsView.d.ts +3 -10
  452. package/dist/features/seller/components/SellerPayoutSettingsView.js +89 -3
  453. package/dist/features/seller/components/SellerPayoutsView.js +56 -5
  454. package/dist/features/seller/components/SellerProductShell.d.ts +68 -0
  455. package/dist/features/seller/components/SellerProductShell.js +179 -0
  456. package/dist/features/seller/components/SellerProductsView.d.ts +2 -3
  457. package/dist/features/seller/components/SellerProductsView.js +194 -18
  458. package/dist/features/seller/components/SellerReviewsView.d.ts +5 -0
  459. package/dist/features/seller/components/SellerReviewsView.js +100 -0
  460. package/dist/features/seller/components/SellerShippingView.d.ts +3 -11
  461. package/dist/features/seller/components/SellerShippingView.js +87 -3
  462. package/dist/features/seller/components/SellerSidebar.d.ts +11 -3
  463. package/dist/features/seller/components/SellerSidebar.js +52 -8
  464. package/dist/features/seller/components/SellerStorefrontView.d.ts +26 -11
  465. package/dist/features/seller/components/SellerStorefrontView.js +45 -7
  466. package/dist/features/seller/components/index.d.ts +16 -2
  467. package/dist/features/seller/components/index.js +7 -0
  468. package/dist/features/seller/hooks/useSellerListingData.d.ts +3 -1
  469. package/dist/features/seller/hooks/useSellerListingData.js +6 -4
  470. package/dist/features/seller/repository/offer.repository.d.ts +3 -3
  471. package/dist/features/seller/repository/offer.repository.js +6 -6
  472. package/dist/features/seller/schemas/firestore.d.ts +7 -7
  473. package/dist/features/seller/schemas/firestore.js +4 -4
  474. package/dist/features/seller/schemas/index.d.ts +16 -16
  475. package/dist/features/shell/FormShell.d.ts +29 -0
  476. package/dist/features/shell/FormShell.js +103 -0
  477. package/dist/features/shell/QuickFormDrawer.d.ts +29 -0
  478. package/dist/features/shell/QuickFormDrawer.js +117 -0
  479. package/dist/features/shell/StepForm.d.ts +44 -0
  480. package/dist/features/shell/StepForm.js +81 -0
  481. package/dist/features/shell/index.d.ts +6 -0
  482. package/dist/features/shell/index.js +3 -0
  483. package/dist/features/stores/actions/store-query-actions.js +3 -3
  484. package/dist/features/stores/api/[storeSlug]/auctions/route.js +1 -1
  485. package/dist/features/stores/api/[storeSlug]/products/route.js +1 -1
  486. package/dist/features/stores/api/[storeSlug]/reviews/route.js +1 -1
  487. package/dist/features/stores/components/InteractiveStoreCard.d.ts +2 -2
  488. package/dist/features/stores/components/InteractiveStoreCard.js +21 -7
  489. package/dist/features/stores/components/StoreAboutView.js +1 -1
  490. package/dist/features/stores/components/StoreAuctionsListing.d.ts +5 -2
  491. package/dist/features/stores/components/StoreAuctionsListing.js +81 -8
  492. package/dist/features/stores/components/StoreAuctionsPageView.js +8 -7
  493. package/dist/features/stores/components/StoreDetailLayoutView.d.ts +1 -0
  494. package/dist/features/stores/components/StoreDetailLayoutView.js +29 -5
  495. package/dist/features/stores/components/StoreHeader.js +2 -1
  496. package/dist/features/stores/components/StorePreOrdersListing.d.ts +4 -2
  497. package/dist/features/stores/components/StorePreOrdersListing.js +59 -7
  498. package/dist/features/stores/components/StorePreOrdersPageView.js +8 -7
  499. package/dist/features/stores/components/StoreProductsListing.d.ts +5 -2
  500. package/dist/features/stores/components/StoreProductsListing.js +97 -8
  501. package/dist/features/stores/components/StoreProductsPageView.js +8 -7
  502. package/dist/features/stores/components/StoreReviewsListing.js +2 -2
  503. package/dist/features/stores/components/StoresIndexListing.js +74 -11
  504. package/dist/features/stores/components/StoresListView.js +1 -1
  505. package/dist/features/stores/hooks/useStores.d.ts +1 -0
  506. package/dist/features/stores/hooks/useStores.js +1 -0
  507. package/dist/features/stores/schemas/firestore.d.ts +34 -0
  508. package/dist/features/stores/schemas/index.d.ts +8 -8
  509. package/dist/features/sublisting/schemas/firestore.d.ts +30 -0
  510. package/dist/features/sublisting/schemas/firestore.js +19 -0
  511. package/dist/features/support/schemas/firestore.d.ts +113 -0
  512. package/dist/features/support/schemas/firestore.js +95 -0
  513. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.d.ts +5 -0
  514. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +143 -0
  515. package/dist/features/whatsapp-bot/components/index.d.ts +2 -0
  516. package/dist/features/whatsapp-bot/components/index.js +1 -0
  517. package/dist/features/whatsapp-bot/helpers/whatsapp.d.ts +23 -1
  518. package/dist/features/whatsapp-bot/helpers/whatsapp.js +104 -0
  519. package/dist/features/whatsapp-bot/server.d.ts +1 -0
  520. package/dist/features/whatsapp-bot/server.js +1 -0
  521. package/dist/features/whatsapp-bot/types/index.d.ts +49 -0
  522. package/dist/features/wishlist/components/WishlistView.d.ts +0 -10
  523. package/dist/features/wishlist/components/WishlistView.js +13 -6
  524. package/dist/features/wishlist/hooks/useWishlist.js +2 -0
  525. package/dist/features/wishlist/hooks/useWishlistCount.d.ts +11 -3
  526. package/dist/features/wishlist/hooks/useWishlistCount.js +89 -25
  527. package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
  528. package/dist/features/wishlist/schemas/index.d.ts +2 -2
  529. package/dist/features/wishlist/types/index.d.ts +16 -0
  530. package/dist/http/api-handler.js +8 -1
  531. package/dist/index.d.ts +112 -16
  532. package/dist/index.js +133 -28
  533. package/dist/monitoring/server-logger.js +9 -3
  534. package/dist/next/routing/route-map.d.ts +120 -6
  535. package/dist/next/routing/route-map.js +53 -2
  536. package/dist/providers/db-firebase/realtime.d.ts +1 -1
  537. package/dist/react/contexts/SessionContext.js +17 -26
  538. package/dist/react/hooks/useBulkSelection.d.ts +7 -24
  539. package/dist/react/hooks/useBulkSelection.js +27 -34
  540. package/dist/react/hooks/useLongPress.d.ts +3 -16
  541. package/dist/react/hooks/useLongPress.js +6 -25
  542. package/dist/react/index.d.ts +1 -0
  543. package/dist/react/index.js +2 -0
  544. package/dist/repositories/index.d.ts +3 -0
  545. package/dist/repositories/index.js +2 -0
  546. package/dist/seed/actions/demo-seed-actions.d.ts +2 -2
  547. package/dist/seed/actions/demo-seed-actions.js +1 -1
  548. package/dist/seed/anime-figures-seed-data.d.ts +8 -0
  549. package/dist/seed/anime-figures-seed-data.js +1033 -0
  550. package/dist/seed/beyblade-seed-data.js +206 -24
  551. package/dist/seed/bids-seed-data.d.ts +4 -10
  552. package/dist/seed/bids-seed-data.js +365 -238
  553. package/dist/seed/blog-posts-seed-data.d.ts +3 -2
  554. package/dist/seed/blog-posts-seed-data.js +250 -511
  555. package/dist/seed/brands-seed-data.d.ts +7 -0
  556. package/dist/seed/brands-seed-data.js +410 -0
  557. package/dist/seed/carousel-slides-seed-data.d.ts +3 -2
  558. package/dist/seed/carousel-slides-seed-data.js +177 -216
  559. package/dist/seed/cart-seed-data.d.ts +9 -9
  560. package/dist/seed/cart-seed-data.js +73 -73
  561. package/dist/seed/categories-seed-data.d.ts +4 -2
  562. package/dist/seed/categories-seed-data.js +720 -879
  563. package/dist/seed/conversations-seed-data.d.ts +8 -0
  564. package/dist/seed/conversations-seed-data.js +388 -0
  565. package/dist/seed/cosplay-accessories-seed-data.d.ts +8 -0
  566. package/dist/seed/cosplay-accessories-seed-data.js +647 -0
  567. package/dist/seed/coupon-usage-seed-data.d.ts +25 -0
  568. package/dist/seed/coupon-usage-seed-data.js +69 -0
  569. package/dist/seed/coupons-seed-data.d.ts +6 -3
  570. package/dist/seed/coupons-seed-data.js +375 -3
  571. package/dist/seed/events-seed-data.d.ts +4 -2
  572. package/dist/seed/events-seed-data.js +128 -430
  573. package/dist/seed/factories/cart.factory.d.ts +0 -1
  574. package/dist/seed/factories/cart.factory.js +2 -2
  575. package/dist/seed/faq-seed-data.d.ts +11 -18
  576. package/dist/seed/faq-seed-data.js +786 -1817
  577. package/dist/seed/grouped-listings-seed-data.d.ts +8 -0
  578. package/dist/seed/grouped-listings-seed-data.js +201 -0
  579. package/dist/seed/homepage-sections-seed-data.d.ts +3 -13
  580. package/dist/seed/homepage-sections-seed-data.js +228 -252
  581. package/dist/seed/hot-wheels-seed-data.js +285 -38
  582. package/dist/seed/index.d.ts +12 -11
  583. package/dist/seed/index.js +10 -12
  584. package/dist/seed/letitrip-official-seed-data.d.ts +8 -0
  585. package/dist/seed/letitrip-official-seed-data.js +399 -0
  586. package/dist/seed/manifest.d.ts +15 -0
  587. package/dist/seed/manifest.js +140 -0
  588. package/dist/seed/notifications-seed-data.d.ts +4 -2
  589. package/dist/seed/notifications-seed-data.js +117 -440
  590. package/dist/seed/orders-seed-data.d.ts +4 -2
  591. package/dist/seed/orders-seed-data.js +1090 -521
  592. package/dist/seed/payouts-seed-data.d.ts +4 -2
  593. package/dist/seed/payouts-seed-data.js +522 -145
  594. package/dist/seed/pokemon-carousel-slides-seed-data.js +6 -1
  595. package/dist/seed/pokemon-categories-seed-data.js +81 -81
  596. package/dist/seed/pokemon-homepage-sections-seed-data.d.ts +1 -1
  597. package/dist/seed/pokemon-homepage-sections-seed-data.js +116 -23
  598. package/dist/seed/pokemon-products-seed-data.d.ts +1 -1
  599. package/dist/seed/pokemon-products-seed-data.js +83 -73
  600. package/dist/seed/pokemon-seed-bundle.d.ts +5 -1
  601. package/dist/seed/pokemon-seed-bundle.js +21 -2
  602. package/dist/seed/pokemon-stores-seed-data.js +85 -9
  603. package/dist/seed/pokemon-users-seed-data.js +107 -8
  604. package/dist/seed/products-auctions-seed-data.d.ts +10 -0
  605. package/dist/seed/products-auctions-seed-data.js +689 -0
  606. package/dist/seed/products-preorders-seed-data.d.ts +9 -0
  607. package/dist/seed/products-preorders-seed-data.js +483 -0
  608. package/dist/seed/products-seed-data.js +34 -13
  609. package/dist/seed/products-standard-seed-data.d.ts +8 -0
  610. package/dist/seed/products-standard-seed-data.js +4179 -0
  611. package/dist/seed/retro-gaming-seed-data.d.ts +8 -0
  612. package/dist/seed/retro-gaming-seed-data.js +801 -0
  613. package/dist/seed/reviews-seed-data.d.ts +4 -17
  614. package/dist/seed/reviews-seed-data.js +1043 -515
  615. package/dist/seed/scammers-seed-data.d.ts +17 -0
  616. package/dist/seed/scammers-seed-data.js +118 -0
  617. package/dist/seed/site-settings-seed-data.js +25 -2
  618. package/dist/seed/store-addresses-seed-data.js +188 -84
  619. package/dist/seed/stores-seed-data.d.ts +3 -9
  620. package/dist/seed/stores-seed-data.js +212 -102
  621. package/dist/seed/sublisting-categories-seed-data.d.ts +7 -0
  622. package/dist/seed/sublisting-categories-seed-data.js +315 -0
  623. package/dist/seed/transformers-seed-data.js +34 -14
  624. package/dist/seed/users-seed-data.d.ts +3 -2
  625. package/dist/seed/users-seed-data.js +531 -440
  626. package/dist/seed/wishlists-seed-data.js +13 -13
  627. package/dist/server.d.ts +9 -2
  628. package/dist/server.js +12 -4
  629. package/dist/tokens/tokens.css +76 -31
  630. package/dist/ui/components/Avatar.style.css +10 -12
  631. package/dist/ui/components/BaseListingCard.d.ts +8 -3
  632. package/dist/ui/components/BaseListingCard.js +17 -6
  633. package/dist/ui/components/BaseListingCard.style.css +3 -1
  634. package/dist/ui/components/BulkActionsBar.d.ts +16 -0
  635. package/dist/ui/components/BulkActionsBar.js +22 -0
  636. package/dist/ui/components/Button.style.css +23 -23
  637. package/dist/ui/components/Card.style.css +60 -62
  638. package/dist/ui/components/Checkbox.style.css +19 -21
  639. package/dist/ui/components/DashboardStatsCard.style.css +12 -14
  640. package/dist/ui/components/Drawer.style.css +18 -14
  641. package/dist/ui/components/Dropdown.style.css +25 -27
  642. package/dist/ui/components/EmptyState.style.css +2 -4
  643. package/dist/ui/components/HorizontalScroller.d.ts +3 -1
  644. package/dist/ui/components/HorizontalScroller.js +116 -21
  645. package/dist/ui/components/HorizontalScroller.style.css +2 -2
  646. package/dist/ui/components/ImageLightbox.d.ts +0 -9
  647. package/dist/ui/components/ImageLightbox.js +43 -9
  648. package/dist/ui/components/InlineCreateSelect.d.ts +38 -0
  649. package/dist/ui/components/InlineCreateSelect.js +70 -0
  650. package/dist/ui/components/ListingLayout.style.css +41 -77
  651. package/dist/ui/components/ListingToolbar.d.ts +54 -0
  652. package/dist/ui/components/ListingToolbar.js +34 -0
  653. package/dist/ui/components/Modal.style.css +14 -10
  654. package/dist/ui/components/PageLoader.d.ts +11 -0
  655. package/dist/ui/components/PageLoader.js +21 -0
  656. package/dist/ui/components/Radio.style.css +34 -36
  657. package/dist/ui/components/RichTextEditor.js +1 -1
  658. package/dist/ui/components/RowActionMenu.d.ts +1 -0
  659. package/dist/ui/components/RowActionMenu.js +4 -2
  660. package/dist/ui/components/SectionTabs.js +1 -1
  661. package/dist/ui/components/SectionTabs.style.css +1 -0
  662. package/dist/ui/components/SideModal.style.css +4 -8
  663. package/dist/ui/components/Slider.style.css +2 -4
  664. package/dist/ui/components/Tabs.style.css +8 -10
  665. package/dist/ui/components/Toast.style.css +22 -24
  666. package/dist/ui/components/Toggle.style.css +11 -13
  667. package/dist/ui/index.d.ts +9 -0
  668. package/dist/ui/index.js +5 -0
  669. package/dist/ui/rich-text/RichText.js +2 -1
  670. package/dist/ui/rich-text/RichText.style.css +292 -5
  671. package/dist/ui/rich-text/RichTextRenderer.d.ts +15 -0
  672. package/dist/ui/rich-text/RichTextRenderer.js +15 -0
  673. package/dist/utils/id-generators.d.ts +10 -0
  674. package/dist/utils/id-generators.js +12 -0
  675. package/dist/validation/schemas.d.ts +9 -9
  676. package/package.json +5 -1
  677. package/README.md +0 -116
@@ -1,25 +1,78 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { useState, useCallback } from "react";
4
- import { Search, SlidersHorizontal, X } from "lucide-react";
3
+ import { useState, useCallback, useMemo } from "react";
4
+ import { X } from "lucide-react";
5
5
  import { useCategoriesFiltered } from "../hooks/useCategories";
6
6
  import { ROUTES } from "../../../next";
7
- import { Pagination } from "../../../ui";
7
+ import { Pagination, ListingToolbar } from "../../../ui";
8
8
  import { CategoryCard } from "./CategoryGrid";
9
9
  import { CategoryFilters } from "./CategoryFilters";
10
10
  import { useUrlTable } from "../../../react/hooks/useUrlTable";
11
11
  const PAGE_SIZE = 24;
12
+ const FILTER_KEYS = ["isFeatured", "isBrand", "rootOnly", "tier", "minItemCount", "maxItemCount"];
12
13
  const SORT_OPTIONS = [
13
14
  { value: "name", label: "Name A–Z" },
14
15
  { value: "-name", label: "Name Z–A" },
15
16
  { value: "-productCount", label: "Most Products" },
16
17
  ];
17
- export function CategoriesIndexListing({ initialData: _ }) {
18
+ export function CategoriesIndexListing({ initialData: _, brandsOnly = false }) {
18
19
  const table = useUrlTable({ defaults: { pageSize: String(PAGE_SIZE), sort: "name" } });
19
20
  const [searchInput, setSearchInput] = useState(table.get("q") || "");
20
21
  const [filterOpen, setFilterOpen] = useState(false);
21
22
  const sort = table.get("sort") || "name";
22
23
  const page = table.getNumber("page", 1);
24
+ // Pending filter state — buffered until "Apply Filters" clicked
25
+ const [pendingFilters, setPendingFilters] = useState(() => Object.fromEntries(FILTER_KEYS.map((k) => [k, table.get(k)])));
26
+ const pendingTable = useMemo(() => ({
27
+ get: (key) => pendingFilters[key] ?? "",
28
+ getNumber: (key, fallback = 0) => {
29
+ const v = pendingFilters[key];
30
+ if (!v)
31
+ return fallback;
32
+ const n = Number(v);
33
+ return isNaN(n) ? fallback : n;
34
+ },
35
+ set: (key, value) => setPendingFilters((p) => ({ ...p, [key]: value })),
36
+ setMany: (updates) => setPendingFilters((p) => ({ ...p, ...updates })),
37
+ clear: (keys) => {
38
+ const ks = keys ?? FILTER_KEYS;
39
+ setPendingFilters((p) => ({
40
+ ...p,
41
+ ...Object.fromEntries(ks.map((k) => [k, ""])),
42
+ }));
43
+ },
44
+ setPage: (_) => { },
45
+ setPageSize: (_) => { },
46
+ setSort: (_) => { },
47
+ buildSieveParams: () => "",
48
+ buildSearchParams: () => "",
49
+ params: new URLSearchParams(),
50
+ }), [pendingFilters]);
51
+ const openFilters = useCallback(() => {
52
+ setPendingFilters(Object.fromEntries(FILTER_KEYS.map((k) => [k, table.get(k)])));
53
+ setFilterOpen(true);
54
+ }, [table]);
55
+ const applyFilters = useCallback(() => {
56
+ const updates = { page: "1" };
57
+ for (const k of FILTER_KEYS)
58
+ updates[k] = pendingFilters[k] ?? "";
59
+ table.setMany(updates);
60
+ setFilterOpen(false);
61
+ }, [pendingFilters, table]);
62
+ const clearFilters = useCallback(() => {
63
+ setPendingFilters(Object.fromEntries(FILTER_KEYS.map((k) => [k, ""])));
64
+ }, []);
65
+ const resetAll = useCallback(() => {
66
+ const updates = { q: "", sort: "" };
67
+ for (const k of FILTER_KEYS)
68
+ updates[k] = "";
69
+ table.setMany(updates);
70
+ setSearchInput("");
71
+ }, [table]);
72
+ const activeFilterCount = FILTER_KEYS.filter((k) => !!table.get(k)).length;
73
+ const hasActiveState = !!table.get("q") ||
74
+ table.get("sort") !== "name" ||
75
+ activeFilterCount > 0;
23
76
  const commitSearch = useCallback(() => {
24
77
  table.set("q", searchInput.trim());
25
78
  table.setPage(1);
@@ -29,11 +82,20 @@ export function CategoriesIndexListing({ initialData: _ }) {
29
82
  table.set("q", "");
30
83
  table.setPage(1);
31
84
  };
32
- const closeFilters = () => setFilterOpen(false);
85
+ // Tab state — "all" | "categories" | "brands" (not used when brandsOnly=true)
86
+ const activeTab = brandsOnly ? "brands" : (table.get("tab") || "all");
87
+ const isBrandParam = brandsOnly ? true :
88
+ activeTab === "brands" ? true :
89
+ activeTab === "categories" ? false :
90
+ undefined;
91
+ const switchTab = (key) => {
92
+ table.set("tab", key);
93
+ table.setPage(1);
94
+ };
33
95
  const { categories, total, totalPages, isLoading } = useCategoriesFiltered({
34
96
  q: table.get("q") || undefined,
35
97
  isFeatured: table.get("isFeatured") === "true" || undefined,
36
- isBrand: table.get("isBrand") === "true" || undefined,
98
+ isBrand: isBrandParam,
37
99
  rootOnly: table.get("rootOnly") === "true" || undefined,
38
100
  tier: table.get("tier") ? Number(table.get("tier")) : undefined,
39
101
  minProductCount: table.get("minItemCount") ? Number(table.get("minItemCount")) : undefined,
@@ -43,5 +105,19 @@ export function CategoriesIndexListing({ initialData: _ }) {
43
105
  pageSize: PAGE_SIZE,
44
106
  });
45
107
  const activeSearch = table.get("q") || "";
46
- return (_jsxs("div", { className: "min-h-screen", children: [_jsx("div", { className: "sticky top-0 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 -mx-4", children: _jsxs("div", { className: "flex items-center gap-2.5 max-w-full", children: [_jsxs("button", { type: "button", onClick: () => setFilterOpen(true), className: "flex shrink-0 items-center gap-2 rounded-lg border border-zinc-300 dark:border-slate-600 px-3.5 py-2 text-sm font-medium text-zinc-700 dark:text-zinc-200 hover:bg-zinc-50 dark:hover:bg-slate-800 transition-colors", children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), _jsx("span", { className: "hidden sm:inline", children: "Filters" })] }), _jsxs("div", { className: "flex flex-1 items-center overflow-hidden rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-900", children: [_jsx("input", { type: "text", value: searchInput, onChange: (e) => setSearchInput(e.target.value), onKeyDown: (e) => e.key === "Enter" && commitSearch(), placeholder: "Search categories...", 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: clearSearch, className: "px-2 text-zinc-400 hover:text-zinc-600 transition-colors", "aria-label": "Clear search", children: _jsx(X, { className: "h-3.5 w-3.5" }) })), _jsx("button", { type: "button", onClick: commitSearch, className: "flex shrink-0 items-center justify-center px-3 py-2 text-zinc-400 hover:text-primary dark:hover:text-primary-400 transition-colors", "aria-label": "Search", children: _jsx(Search, { className: "h-4 w-4" }) })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1.5 text-sm text-zinc-500 dark:text-zinc-400", children: [_jsx("span", { className: "hidden md:inline whitespace-nowrap", children: "Sort" }), _jsx("select", { value: sort, onChange: (e) => { table.set("sort", e.target.value); table.setPage(1); }, className: "rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-900 px-3 py-2 text-sm text-zinc-700 dark:text-zinc-200 outline-none focus:ring-2 focus:ring-primary/30", children: SORT_OPTIONS.map((o) => _jsx("option", { value: o.value, children: o.label }, o.value)) })] })] }) }), _jsxs("div", { className: "py-6", children: [isLoading ? (_jsx("div", { className: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 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-[4/3] bg-zinc-200 dark:bg-slate-700" }), _jsxs("div", { className: "p-3.5 space-y-2", children: [_jsx("div", { className: "h-3.5 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-full" })] })] }, i))) })) : categories.length === 0 ? (_jsx("p", { className: "py-12 text-center text-sm text-zinc-500 dark:text-zinc-400", children: activeSearch ? `No categories matching "${activeSearch}"` : "No categories found" })) : (_jsx("div", { className: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4", children: categories.map((category) => (_jsx(CategoryCard, { category: category, href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(category.slug)) }, category.id))) })), totalPages > 1 && (_jsx("div", { className: "mt-8 flex justify-center", children: _jsx(Pagination, { currentPage: page, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) }))] }), filterOpen && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-40 bg-black/40", "aria-hidden": "true", onClick: closeFilters }), _jsxs("div", { className: "fixed inset-y-0 left-0 z-50 flex w-80 flex-col bg-white dark:bg-slate-900 shadow-2xl", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: [_jsxs("span", { className: "flex items-center gap-2 text-base font-semibold text-zinc-900 dark:text-zinc-100", children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), "Filters"] }), _jsx("button", { type: "button", onClick: closeFilters, "aria-label": "Close filters", className: "rounded-lg p-1.5 text-zinc-500 hover:bg-zinc-100 dark:hover:bg-slate-800 transition-colors", children: _jsx(X, { className: "h-5 w-5" }) })] }), _jsx("div", { className: "flex-1 overflow-y-auto px-4 py-4", children: _jsx(CategoryFilters, { table: table, variant: "public" }) }), _jsx("div", { className: "border-t border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: _jsx("button", { type: "button", onClick: closeFilters, className: "w-full rounded-lg bg-primary py-2.5 text-sm font-semibold text-white hover:bg-primary-600 transition-colors", children: "Apply filters" }) })] })] }))] }));
108
+ const TABS = [
109
+ { key: "all", label: "All" },
110
+ { key: "categories", label: "Categories" },
111
+ { key: "brands", label: "Brands" },
112
+ ];
113
+ return (_jsxs("div", { className: "min-h-screen", children: [!brandsOnly && (_jsx("div", { className: "flex gap-1 border-b border-zinc-200 dark:border-slate-700 mb-2", children: TABS.map((tab) => (_jsx("button", { type: "button", onClick: () => switchTab(tab.key), className: [
114
+ "px-4 py-2.5 text-sm font-medium transition-colors border-b-2 -mb-px",
115
+ activeTab === tab.key
116
+ ? "border-primary text-primary dark:text-primary-400 dark:border-primary-400"
117
+ : "border-transparent text-zinc-500 hover:text-zinc-800 dark:text-zinc-400 dark:hover:text-zinc-200",
118
+ ].join(" "), children: tab.label }, tab.key))) })), _jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: activeTab === "brands" || brandsOnly ? "Search brands..." : "Search categories...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: sort, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set("sort", v); table.setPage(1); }, hideViewToggle: true, onResetAll: resetAll, hasActiveState: hasActiveState }), 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 xl:grid-cols-5 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-[4/3] bg-zinc-200 dark:bg-slate-700" }), _jsxs("div", { className: "p-3.5 space-y-2", children: [_jsx("div", { className: "h-3.5 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-full" })] })] }, i))) })) : categories.length === 0 ? (_jsx("p", { className: "py-12 text-center text-sm text-zinc-500 dark:text-zinc-400", children: activeSearch
119
+ ? `No ${activeTab === "brands" || brandsOnly ? "brands" : "categories"} matching "${activeSearch}"`
120
+ : activeTab === "brands" || brandsOnly
121
+ ? "No brands found"
122
+ : "No categories found" })) : (_jsx("div", { className: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4", children: categories.map((category) => (_jsx(CategoryCard, { category: category, href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(category.slug)) }, category.id))) })) }), filterOpen && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-40 bg-black/40", "aria-hidden": "true", onClick: () => setFilterOpen(false) }), _jsxs("div", { className: "fixed inset-y-0 left-0 z-50 flex w-80 flex-col bg-white dark:bg-slate-900 shadow-2xl", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: [_jsx("span", { className: "flex items-center gap-2 text-base font-semibold text-zinc-900 dark:text-zinc-100", children: "Filters" }), _jsxs("div", { className: "flex items-center gap-2", children: [activeFilterCount > 0 && (_jsx("button", { type: "button", onClick: clearFilters, className: "text-xs text-zinc-500 hover:text-rose-500 dark:text-zinc-400 transition-colors", children: "Clear all" })), _jsx("button", { type: "button", onClick: () => setFilterOpen(false), "aria-label": "Close filters", className: "rounded-lg p-1.5 text-zinc-500 hover:bg-zinc-100 dark:hover:bg-slate-800 transition-colors", children: _jsx(X, { className: "h-5 w-5" }) })] })] }), _jsx("div", { className: "flex-1 overflow-y-auto px-4 py-4", children: _jsx(CategoryFilters, { table: pendingTable, variant: "public" }) }), _jsx("div", { className: "border-t border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: _jsxs("button", { type: "button", onClick: applyFilters, className: "w-full rounded-lg bg-primary py-2.5 text-sm font-semibold text-white hover:bg-primary-600 transition-colors active:scale-[0.98]", children: ["Apply Filters", activeFilterCount > 0 ? ` (${activeFilterCount})` : ""] }) })] })] }))] }));
47
123
  }
@@ -5,28 +5,49 @@ import { ROUTES } from "../../../next";
5
5
  import { Container, Main, Section } from "../../../ui";
6
6
  import { CategoryDetailTabs } from "./CategoryDetailTabs";
7
7
  export async function CategoryDetailPageView({ slug }) {
8
- const [categoryResult, productsResult] = await Promise.all([
9
- categoriesRepository
10
- .findBy("slug", slug)
11
- .then((items) => items[0])
12
- .catch(() => undefined),
13
- productRepository
14
- .list({
15
- filters: `status==published,categorySlug==${slug},isAuction==false`,
16
- sorts: "-createdAt",
17
- page: 1,
18
- pageSize: 24,
19
- })
20
- .catch(() => null),
8
+ const category = await categoriesRepository
9
+ .getCategoryBySlug(slug)
10
+ .catch(() => undefined);
11
+ const [productsResult, auctionsCountResult, preOrdersCountResult, childCategories] = await Promise.all([
12
+ category?.id
13
+ ? productRepository
14
+ .list({
15
+ filters: `status==published,category==${category.id},isAuction==false,isPreOrder==false`,
16
+ sorts: "-createdAt",
17
+ page: 1,
18
+ pageSize: 24,
19
+ })
20
+ .catch(() => null)
21
+ : Promise.resolve(null),
22
+ category?.id
23
+ ? productRepository
24
+ .list({
25
+ filters: `status==published,category==${category.id},isAuction==true`,
26
+ sorts: "auctionEndDate",
27
+ page: 1,
28
+ pageSize: 1,
29
+ })
30
+ .catch(() => null)
31
+ : Promise.resolve(null),
32
+ category?.id
33
+ ? productRepository
34
+ .list({
35
+ filters: `status==published,category==${category.id},isPreOrder==true`,
36
+ sorts: "-createdAt",
37
+ page: 1,
38
+ pageSize: 1,
39
+ })
40
+ .catch(() => null)
41
+ : Promise.resolve(null),
42
+ category?.id
43
+ ? categoriesRepository.getChildren(category.id).catch(() => [])
44
+ : Promise.resolve([]),
21
45
  ]);
22
- const category = categoryResult;
23
- const childCategories = category?.id
24
- ? await categoriesRepository.getChildren(category.id).catch(() => [])
25
- : [];
26
- const productCount = category?.metrics?.productCount ?? 0;
46
+ const productCount = productsResult?.total ?? category?.metrics?.productCount ?? 0;
47
+ const auctionCount = auctionsCountResult?.total ?? category?.metrics?.auctionCount ?? 0;
48
+ const preOrderCount = preOrdersCountResult?.total ?? 0;
49
+ const totalCount = productCount + auctionCount + preOrderCount;
27
50
  const coverImage = category?.display?.coverImage;
28
51
  const hasCover = Boolean(coverImage);
29
- return (_jsxs(Main, { children: [_jsxs("section", { className: `relative overflow-hidden ${hasCover ? "min-h-[220px] md:min-h-[280px]" : "bg-zinc-50 dark:bg-zinc-900"}`, children: [hasCover && (_jsxs(_Fragment, { children: [_jsx("div", { className: "absolute inset-0 bg-center bg-cover", style: { backgroundImage: `url(${coverImage})` } }), _jsx("div", { className: "absolute inset-0 bg-black/55" })] })), _jsxs("div", { className: `relative z-10 max-w-7xl mx-auto px-4 ${hasCover ? "py-12" : "py-8"}`, children: [_jsxs("nav", { className: "flex items-center gap-1.5 text-sm mb-4", "aria-label": "Breadcrumb", children: [_jsx(Link, { href: String(ROUTES.HOME), className: hasCover ? "text-white/70 hover:text-white transition-colors" : "text-zinc-500 hover:text-primary-600 transition-colors", children: "Home" }), _jsx("span", { className: hasCover ? "text-white/40" : "text-zinc-400", children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORIES), className: hasCover ? "text-white/70 hover:text-white transition-colors" : "text-zinc-500 hover:text-primary-600 transition-colors", children: "Categories" }), _jsx("span", { className: hasCover ? "text-white/40" : "text-zinc-400", children: "/" }), _jsx("span", { className: hasCover ? "text-white font-medium" : "text-zinc-900 dark:text-zinc-100 font-medium", children: category?.name ?? slug })] }), _jsx("h1", { className: `text-3xl md:text-4xl font-bold mb-2 ${hasCover ? "text-white" : "text-zinc-900 dark:text-zinc-50"}`, children: category?.name ?? slug }), category?.description && typeof category.description === "string" && !category.description.startsWith("{") && (_jsx("p", { className: `text-base max-w-2xl mb-4 ${hasCover ? "text-white/80" : "text-zinc-600 dark:text-zinc-400"}`, children: category.description })), productCount > 0 && (_jsxs("span", { className: `inline-flex items-center gap-1.5 text-sm font-medium px-3 py-1 rounded-full ${hasCover
30
- ? "bg-white/20 text-white backdrop-blur-sm"
31
- : "bg-primary/10 text-primary-700 dark:text-primary-400"}`, children: [productCount.toLocaleString(), " ", productCount === 1 ? "item" : "items"] }))] })] }), childCategories.length > 0 && (_jsx("section", { className: "border-b border-zinc-100 dark:border-zinc-800 bg-white dark:bg-zinc-900", children: _jsx("div", { className: "max-w-7xl mx-auto px-4 py-3", children: _jsx("div", { className: "flex gap-2.5 overflow-x-auto pb-1", style: { scrollbarWidth: "none" }, children: childCategories.map((child) => (_jsxs(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(child.slug)), className: "flex-shrink-0 flex items-center gap-1.5 rounded-full border border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-800 px-4 py-1.5 text-sm font-medium text-zinc-700 dark:text-zinc-200 hover:border-primary hover:text-primary transition-colors whitespace-nowrap", children: [child.display?.icon && (_jsx("span", { className: "text-base leading-none", children: child.display.icon })), child.name, (child.metrics?.productCount ?? 0) > 0 && (_jsx("span", { className: "text-xs text-zinc-400 dark:text-zinc-500", children: (child.metrics?.productCount ?? 0).toLocaleString() }))] }, child.id))) }) }) })), _jsx(Section, { className: "py-6", children: _jsx(Container, { size: "xl", children: _jsx(CategoryDetailTabs, { categorySlug: slug, initialProductsData: productsResult ?? undefined }) }) })] }));
52
+ return (_jsxs(Main, { children: [_jsxs("section", { className: `relative overflow-hidden ${hasCover ? "min-h-[220px] md:min-h-[280px]" : "bg-zinc-50 dark:bg-zinc-900"}`, children: [hasCover && (_jsxs(_Fragment, { children: [_jsx("div", { className: "absolute inset-0 bg-center bg-cover", style: { backgroundImage: `url(${coverImage})` } }), _jsx("div", { className: "absolute inset-0 bg-black/55" })] })), _jsxs("div", { className: `relative z-10 max-w-7xl mx-auto px-4 ${hasCover ? "py-12" : "py-8"}`, children: [_jsxs("nav", { className: "flex items-center gap-1.5 text-sm mb-4", "aria-label": "Breadcrumb", children: [_jsx(Link, { href: String(ROUTES.HOME), className: hasCover ? "text-white/70 hover:text-white transition-colors" : "text-zinc-500 hover:text-primary-600 transition-colors", children: "Home" }), _jsx("span", { className: hasCover ? "text-white/40" : "text-zinc-400", children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORIES), className: hasCover ? "text-white/70 hover:text-white transition-colors" : "text-zinc-500 hover:text-primary-600 transition-colors", children: "Categories" }), _jsx("span", { className: hasCover ? "text-white/40" : "text-zinc-400", children: "/" }), _jsx("span", { className: hasCover ? "text-white font-medium" : "text-zinc-900 dark:text-zinc-100 font-medium", children: category?.name ?? slug })] }), _jsx("h1", { className: `text-3xl md:text-4xl font-bold mb-2 ${hasCover ? "text-white" : "text-zinc-900 dark:text-zinc-50"}`, children: category?.name ?? slug }), category?.description && typeof category.description === "string" && !category.description.startsWith("{") && (_jsx("p", { className: `text-base max-w-2xl mb-4 ${hasCover ? "text-white/80" : "text-zinc-600 dark:text-zinc-400"}`, children: category.description })), _jsxs("div", { className: "flex flex-wrap gap-2", children: [productCount > 0 && (_jsxs("span", { className: `inline-flex items-center gap-1 text-xs font-medium px-2.5 py-1 rounded-full ${hasCover ? "bg-white/20 text-white backdrop-blur-sm" : "bg-primary/10 text-primary-700 dark:text-primary-400"}`, children: [productCount.toLocaleString(), " ", productCount === 1 ? "product" : "products"] })), auctionCount > 0 && (_jsxs("span", { className: `inline-flex items-center gap-1 text-xs font-medium px-2.5 py-1 rounded-full ${hasCover ? "bg-white/20 text-white backdrop-blur-sm" : "bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400"}`, children: [auctionCount.toLocaleString(), " ", auctionCount === 1 ? "auction" : "auctions"] })), preOrderCount > 0 && (_jsxs("span", { className: `inline-flex items-center gap-1 text-xs font-medium px-2.5 py-1 rounded-full ${hasCover ? "bg-white/20 text-white backdrop-blur-sm" : "bg-violet-100 text-violet-700 dark:bg-violet-900/30 dark:text-violet-400"}`, children: [preOrderCount.toLocaleString(), " ", preOrderCount === 1 ? "pre-order" : "pre-orders"] }))] })] })] }), childCategories.length > 0 && (_jsx("section", { className: "border-b border-zinc-100 dark:border-zinc-800 bg-white dark:bg-zinc-900", children: _jsx("div", { className: "max-w-7xl mx-auto px-4 py-3", children: _jsx("div", { className: "flex gap-2.5 overflow-x-auto pb-1", style: { scrollbarWidth: "none" }, children: childCategories.map((child) => (_jsxs(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(child.slug)), className: "flex-shrink-0 flex items-center gap-1.5 rounded-full border border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-800 px-4 py-1.5 text-sm font-medium text-zinc-700 dark:text-zinc-200 hover:border-primary hover:text-primary transition-colors whitespace-nowrap", children: [child.display?.icon && (_jsx("span", { className: "text-base leading-none", children: child.display.icon })), child.name, (child.metrics?.productCount ?? 0) > 0 && (_jsx("span", { className: "text-xs text-zinc-400 dark:text-zinc-500", children: (child.metrics?.productCount ?? 0).toLocaleString() }))] }, child.id))) }) }) })), _jsx(Section, { className: "py-6", children: _jsx(Container, { size: "xl", children: _jsx(CategoryDetailTabs, { categorySlug: slug, categoryId: category?.id, initialProductsData: productsResult ?? undefined, counts: { products: productCount, auctions: auctionCount, preOrders: preOrderCount } }) }) })] }));
32
53
  }
@@ -1,5 +1,11 @@
1
1
  export interface CategoryDetailTabsProps {
2
2
  categorySlug: string;
3
+ categoryId?: string;
3
4
  initialProductsData?: any;
5
+ counts?: {
6
+ products?: number;
7
+ auctions?: number;
8
+ preOrders?: number;
9
+ };
4
10
  }
5
- export declare function CategoryDetailTabs({ categorySlug, initialProductsData }: CategoryDetailTabsProps): import("react/jsx-runtime").JSX.Element;
11
+ export declare function CategoryDetailTabs({ categorySlug, categoryId, initialProductsData, counts }: CategoryDetailTabsProps): import("react/jsx-runtime").JSX.Element;
@@ -4,14 +4,19 @@ import { useState } from "react";
4
4
  import { CategoryProductsListing } from "./CategoryProductsListing";
5
5
  import { AuctionsIndexListing } from "../../products/components/AuctionsIndexListing";
6
6
  import { PreOrdersIndexListing } from "../../pre-orders/components/PreOrdersIndexListing";
7
- const TABS = [
8
- { id: "products", label: "Products" },
9
- { id: "auctions", label: "Auctions" },
10
- { id: "pre-orders", label: "Pre-Orders" },
11
- ];
12
- export function CategoryDetailTabs({ categorySlug, initialProductsData }) {
7
+ function tabLabel(label, count) {
8
+ if (!count)
9
+ return label;
10
+ return `${label} (${count.toLocaleString()})`;
11
+ }
12
+ export function CategoryDetailTabs({ categorySlug, categoryId, initialProductsData, counts }) {
13
13
  const [activeTab, setActiveTab] = useState("products");
14
+ const TABS = [
15
+ { id: "products", label: tabLabel("Products", counts?.products) },
16
+ { id: "auctions", label: tabLabel("Auctions", counts?.auctions) },
17
+ { id: "pre-orders", label: tabLabel("Pre-Orders", counts?.preOrders) },
18
+ ];
14
19
  return (_jsxs("div", { children: [_jsx("div", { className: "flex border-b border-zinc-200 dark:border-slate-700 mb-6", children: TABS.map((t) => (_jsx("button", { type: "button", onClick: () => setActiveTab(t.id), className: `px-5 py-2.5 text-sm font-medium transition-colors -mb-px border-b-2 ${activeTab === t.id
15
20
  ? "border-primary text-primary"
16
- : "border-transparent text-zinc-500 hover:text-zinc-900 dark:hover:text-zinc-100"}`, children: t.label }, t.id))) }), activeTab === "products" && (_jsx(CategoryProductsListing, { categorySlug: categorySlug, initialData: initialProductsData })), activeTab === "auctions" && (_jsx(AuctionsIndexListing, { categorySlug: categorySlug })), activeTab === "pre-orders" && (_jsx(PreOrdersIndexListing, { categorySlug: categorySlug }))] }));
21
+ : "border-transparent text-zinc-500 hover:text-zinc-900 dark:hover:text-zinc-100"}`, children: t.label }, t.id))) }), activeTab === "products" && (_jsx(CategoryProductsListing, { categorySlug: categorySlug, categoryId: categoryId, initialData: initialProductsData })), activeTab === "auctions" && (_jsx(AuctionsIndexListing, { categorySlug: categorySlug })), activeTab === "pre-orders" && (_jsx(PreOrdersIndexListing, { categorySlug: categorySlug }))] }));
17
22
  }
@@ -71,5 +71,5 @@ export function CategoryFilters({ table, variant = "admin", }) {
71
71
  const activeOnly = table.get("isActive") === "true";
72
72
  const searchableOnly = table.get("isSearchable") === "true";
73
73
  const leafOnly = table.get("isLeaf") === "true";
74
- return (_jsxs(Div, { children: [_jsx(FilterFacetSection, { title: tr("tier", "Tier"), options: tierOptions, selected: selectedTier, onChange: (vals) => table.set("tier", vals.join("|")), searchable: false, defaultCollapsed: variant !== "admin" }), _jsx(SwitchFilter, { title: tr("featured", "Featured"), label: tr("showFeaturedOnly", "Show featured only"), checked: featuredOnly, onChange: (v) => table.set("isFeatured", v ? "true" : ""), defaultCollapsed: true }), _jsx(SwitchFilter, { title: tr("brand", "Brand"), label: tr("showBrandsOnly", "Show brands only"), checked: brandOnly, onChange: (v) => table.set("isBrand", v ? "true" : ""), defaultCollapsed: true }), variant !== "public" && (_jsx(SwitchFilter, { title: tr("status", "Status"), label: tr("showActiveOnly", "Show active only"), checked: activeOnly, onChange: (v) => table.set("isActive", v ? "true" : ""), defaultCollapsed: true })), variant === "admin" && (_jsxs(_Fragment, { children: [_jsx(SwitchFilter, { title: tr("searchable", "Searchable"), label: tr("showSearchableOnly", "Show searchable only"), checked: searchableOnly, onChange: (v) => table.set("isSearchable", v ? "true" : ""), defaultCollapsed: true }), _jsx(SwitchFilter, { title: tr("leaf", "Leaf"), label: tr("showLeafOnly", "Show leaf only"), checked: leafOnly, onChange: (v) => table.set("isLeaf", v ? "true" : ""), defaultCollapsed: true })] })), _jsx(SwitchFilter, { title: tr("rootLevelOnly", "Root Level"), label: tr("showRootLevelOnly", "Top level only"), checked: table.get("rootOnly") === "true", onChange: (v) => table.set("rootOnly", v ? "true" : ""), defaultCollapsed: true }), _jsx(RangeFilter, { title: tr("itemCount", "Item Count"), minValue: table.get("minItemCount"), maxValue: table.get("maxItemCount"), onMinChange: (v) => table.set("minItemCount", v), onMaxChange: (v) => table.set("maxItemCount", v), minBound: 0, maxBound: 10000, step: 10, minPlaceholder: tr("minItemCount", "Min items"), maxPlaceholder: tr("maxItemCount", "Max items"), defaultCollapsed: true })] }));
74
+ return (_jsxs(Div, { children: [_jsx(FilterFacetSection, { title: tr("tier", "Tier"), options: tierOptions, selected: selectedTier, onChange: (vals) => table.set("tier", vals.join("|")), searchable: false, defaultCollapsed: variant !== "admin" }), _jsx(SwitchFilter, { title: tr("featured", "Featured"), label: tr("showFeaturedOnly", "Show featured only"), checked: featuredOnly, onChange: (v) => table.set("isFeatured", v ? "true" : "") }), _jsx(SwitchFilter, { title: tr("brand", "Brand"), label: tr("showBrandsOnly", "Show brands only"), checked: brandOnly, onChange: (v) => table.set("isBrand", v ? "true" : "") }), variant !== "public" && (_jsx(SwitchFilter, { title: tr("status", "Status"), label: tr("showActiveOnly", "Show active only"), checked: activeOnly, onChange: (v) => table.set("isActive", v ? "true" : "") })), variant === "admin" && (_jsxs(_Fragment, { children: [_jsx(SwitchFilter, { title: tr("searchable", "Searchable"), label: tr("showSearchableOnly", "Show searchable only"), checked: searchableOnly, onChange: (v) => table.set("isSearchable", v ? "true" : "") }), _jsx(SwitchFilter, { title: tr("leaf", "Leaf"), label: tr("showLeafOnly", "Show leaf only"), checked: leafOnly, onChange: (v) => table.set("isLeaf", v ? "true" : "") })] })), _jsx(SwitchFilter, { title: tr("rootLevelOnly", "Root Level"), label: tr("showRootLevelOnly", "Top level only"), checked: table.get("rootOnly") === "true", onChange: (v) => table.set("rootOnly", v ? "true" : "") }), _jsx(RangeFilter, { title: tr("itemCount", "Item Count"), minValue: table.get("minItemCount"), maxValue: table.get("maxItemCount"), onMinChange: (v) => table.set("minItemCount", v), onMaxChange: (v) => table.set("maxItemCount", v), minBound: 0, maxBound: 10000, step: 10, minPlaceholder: tr("minItemCount", "Min items"), maxPlaceholder: tr("maxItemCount", "Max items"), defaultCollapsed: false })] }));
75
75
  }
@@ -4,7 +4,7 @@ import { Label, Checkbox, RichTextEditor, Text } from "../../../ui";
4
4
  import { ImageUpload, MediaImage, useMediaUpload } from "../../media";
5
5
  import { FormField } from "../../../ui";
6
6
  import { flattenCategories } from "../types";
7
- import { normalizeRichTextHtml } from "../../../utils/string.formatter";
7
+ import { normalizeRichTextHtml, slugify } from "../../../utils/string.formatter";
8
8
  const DEFAULT_LABELS = {
9
9
  name: "Name",
10
10
  slug: "Slug",
@@ -24,9 +24,12 @@ export function CategoryForm({ category, allCategories, onChange, isReadonly = f
24
24
  const update = (partial) => {
25
25
  onChange({ ...category, ...partial });
26
26
  };
27
+ const makeSlug = (name, isBrand) => {
28
+ const base = slugify(name);
29
+ return isBrand ? `category-brand-${base}` : `category-${base}`;
30
+ };
27
31
  const handleNameChange = (value) => {
28
- const slug = value.toLowerCase().replace(/[^a-z0-9]+/g, "-");
29
- update({ name: value, slug });
32
+ update({ name: value, slug: makeSlug(value, category.isBrand ?? false) });
30
33
  };
31
34
  return (_jsxs("div", { className: stackClassName, "data-section": "categoryform-div-262", children: [_jsxs(FormGroup, { columns: 2, children: [_jsx(FormField, { name: "name", label: L.name, type: "text", value: category.name || "", onChange: handleNameChange, disabled: isReadonly }), _jsx(FormField, { name: "slug", label: L.slug, type: "text", value: category.slug || "", onChange: (value) => update({ slug: value }), disabled: isReadonly })] }), _jsxs("div", { className: "appkit-form-field", "data-section": "categoryform-div-263", children: [_jsx(Label, { className: "appkit-form-field__label", children: L.description }), _jsx(RichTextEditor, { value: normalizeRichTextHtml(category.description || ""), onChange: (value) => update({ description: value }), disabled: isReadonly, minHeightClassName: "min-h-[140px]", placeholder: "Enter category description" }), _jsx(Text, { size: "sm", variant: "secondary", className: "appkit-form-field__hint", children: "Rich text is supported for category descriptions." })] }), !isReadonly && (_jsx(ImageUpload, { currentImage: category.display?.coverImage, onUpload: (file) => upload(file, "categories", true, {
32
35
  type: "category-image",
@@ -38,5 +41,8 @@ export function CategoryForm({ category, allCategories, onChange, isReadonly = f
38
41
  label: `${" ".repeat(cat.tier)}${cat.name}`,
39
42
  disabled: cat.id === category.id,
40
43
  })),
41
- ] }), _jsxs(FormGroup, { columns: 2, children: [_jsx(Checkbox, { checked: category.isActive || false, onChange: (e) => update({ isActive: e.target.checked }), disabled: isReadonly, label: L.enabled }), _jsx(Checkbox, { checked: category.showOnHomepage || false, onChange: (e) => update({ showOnHomepage: e.target.checked }), disabled: isReadonly, label: L.showOnHomepage }), _jsx(Checkbox, { checked: category.isBrand || false, onChange: (e) => update({ isBrand: e.target.checked }), disabled: isReadonly, label: L.isBrand })] }), _jsx(FormField, { name: "order", label: L.order, type: "number", value: String(category.order || 0), onChange: (value) => update({ order: parseInt(value) || 0 }), disabled: isReadonly })] }));
44
+ ] }), _jsxs(FormGroup, { columns: 2, children: [_jsx(Checkbox, { checked: category.isActive || false, onChange: (e) => update({ isActive: e.target.checked }), disabled: isReadonly, label: L.enabled }), _jsx(Checkbox, { checked: category.showOnHomepage || false, onChange: (e) => update({ showOnHomepage: e.target.checked }), disabled: isReadonly, label: L.showOnHomepage }), _jsx(Checkbox, { checked: category.isBrand || false, onChange: (e) => {
45
+ const isBrand = e.target.checked;
46
+ update({ isBrand, slug: makeSlug(category.name ?? "", isBrand) });
47
+ }, disabled: isReadonly, label: L.isBrand })] }), _jsx(FormField, { name: "order", label: L.order, type: "number", value: String(category.order || 0), onChange: (value) => update({ order: parseInt(value) || 0 }), disabled: isReadonly })] }));
42
48
  }
@@ -1,5 +1,8 @@
1
1
  export interface CategoryProductsListingProps {
2
2
  categorySlug: string;
3
+ categoryId?: string;
4
+ /** Filter products by brand name (for brand detail pages) */
5
+ brandName?: string;
3
6
  initialData?: any;
4
7
  }
5
- export declare function CategoryProductsListing({ categorySlug, initialData, }: CategoryProductsListingProps): import("react/jsx-runtime").JSX.Element;
8
+ export declare function CategoryProductsListing({ categorySlug, categoryId, brandName, initialData, }: CategoryProductsListingProps): import("react/jsx-runtime").JSX.Element;
@@ -4,21 +4,28 @@ import { useState, useCallback } from "react";
4
4
  import { Search, SlidersHorizontal, LayoutGrid, List, X } from "lucide-react";
5
5
  import { useUrlTable } from "../../../react/hooks/useUrlTable";
6
6
  import { useProducts } from "../../products/hooks/useProducts";
7
- import { Pagination, SortDropdown } from "../../../ui";
7
+ import { Pagination, SortDropdown, useToast } from "../../../ui";
8
8
  import { ROUTES } from "../../../next";
9
9
  import { ProductGrid } from "../../products/components/ProductGrid";
10
10
  import { ProductFilters } from "../../products/components/ProductFilters";
11
11
  import { PRODUCT_PUBLIC_SORT_OPTIONS } from "../../products/components/ProductFilters";
12
- export function CategoryProductsListing({ categorySlug, initialData, }) {
12
+ import { useGuestCart } from "../../cart/hooks/useGuestCart";
13
+ import { useGuestWishlist } from "../../wishlist/hooks/useGuestWishlist";
14
+ import { pushCartOp, pushWishlistOp } from "../../cart/utils/pending-ops";
15
+ export function CategoryProductsListing({ categorySlug, categoryId, brandName, initialData, }) {
13
16
  const table = useUrlTable({ defaults: { pageSize: "24", sort: "-createdAt" } });
17
+ const { showToast } = useToast();
14
18
  const [searchInput, setSearchInput] = useState(table.get("q") || "");
15
19
  const [filterOpen, setFilterOpen] = useState(false);
16
20
  const [view, setView] = useState(table.get("view") || "card");
21
+ const localCart = useGuestCart();
22
+ const localWishlist = useGuestWishlist();
23
+ const wishlistedIds = new Set(localWishlist.items.filter((i) => i.type === "product").map((i) => i.itemId));
17
24
  const params = {
18
25
  q: table.get("q") || undefined,
19
- categorySlug,
26
+ category: categoryId || undefined,
20
27
  condition: table.get("condition") || undefined,
21
- brand: table.get("brand") || undefined,
28
+ brand: brandName || table.get("brand") || undefined,
22
29
  minPrice: table.get("minPrice") ? Number(table.get("minPrice")) : undefined,
23
30
  maxPrice: table.get("maxPrice") ? Number(table.get("maxPrice")) : undefined,
24
31
  sort: table.get("sort") || "-createdAt",
@@ -31,10 +38,32 @@ export function CategoryProductsListing({ categorySlug, initialData, }) {
31
38
  table.set("q", searchInput.trim());
32
39
  table.setPage(1);
33
40
  }, [searchInput, table]);
41
+ const handleWishlistToggle = useCallback((productId) => {
42
+ const isWishlisted = wishlistedIds.has(productId);
43
+ if (isWishlisted) {
44
+ localWishlist.remove(productId, "product");
45
+ pushWishlistOp({ op: "remove", itemId: productId, type: "product" });
46
+ showToast("Removed from wishlist", "info");
47
+ }
48
+ else {
49
+ localWishlist.add(productId, "product");
50
+ pushWishlistOp({ op: "add", itemId: productId, type: "product" });
51
+ showToast("Added to wishlist", "success");
52
+ }
53
+ }, [wishlistedIds, localWishlist, showToast]);
54
+ const handleAddToCart = useCallback((product) => {
55
+ localCart.add(product.id, 1, {
56
+ productTitle: product.title,
57
+ productImage: product.mainImage,
58
+ price: product.price,
59
+ });
60
+ pushCartOp({ op: "add", productId: product.id, quantity: 1, productTitle: product.title, productImage: product.mainImage, price: product.price });
61
+ showToast("Added to cart", "success");
62
+ }, [localCart, showToast]);
34
63
  const handleViewToggle = (next) => {
35
64
  setView(next);
36
65
  table.set("view", next);
37
66
  };
38
67
  const closeFilters = () => setFilterOpen(false);
39
- return (_jsxs("div", { className: "min-h-[200px]", children: [_jsx("div", { className: "sticky top-0 z-20 border-b border-zinc-200 dark:border-slate-700 bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm py-2.5 px-4", children: _jsxs("div", { className: "flex items-center gap-2.5 max-w-full", children: [_jsxs("button", { type: "button", onClick: () => setFilterOpen(true), className: "flex shrink-0 items-center gap-2 rounded-lg border border-zinc-300 dark:border-slate-600 px-3.5 py-2 text-sm font-medium text-zinc-700 dark:text-zinc-200 hover:bg-zinc-50 dark:hover:bg-slate-800 transition-colors", children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), _jsx("span", { className: "hidden sm:inline", children: "Filters" })] }), _jsxs("div", { className: "flex flex-1 items-center overflow-hidden rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-900", children: [_jsx("input", { type: "text", value: searchInput, onChange: (e) => setSearchInput(e.target.value), onKeyDown: (e) => e.key === "Enter" && commitSearch(), placeholder: `Search in ${categorySlug.replace(/-/g, " ")}...`, 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" }), _jsx("button", { type: "button", onClick: commitSearch, className: "flex shrink-0 items-center justify-center px-3 py-2 text-zinc-400 hover:text-primary dark:hover:text-primary-400 transition-colors", "aria-label": "Search", children: _jsx(Search, { className: "h-4 w-4" }) })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1.5 text-sm text-zinc-500 dark:text-zinc-400", children: [_jsx("span", { className: "hidden md:inline whitespace-nowrap", children: "Sort by" }), _jsx(SortDropdown, { value: table.get("sort") || "-createdAt", onChange: (v) => { table.set("sort", v); table.setPage(1); }, options: PRODUCT_PUBLIC_SORT_OPTIONS })] }), _jsxs("div", { className: "flex shrink-0 items-center rounded-lg border border-zinc-300 dark:border-slate-600 overflow-hidden", children: [_jsx("button", { type: "button", onClick: () => handleViewToggle("card"), "aria-label": "Grid view", className: `p-2 transition-colors ${view === "card" ? "bg-primary text-white" : "text-zinc-500 hover:bg-zinc-50 dark:hover:bg-slate-800 dark:text-zinc-400"}`, children: _jsx(LayoutGrid, { className: "h-4 w-4" }) }), _jsx("button", { type: "button", onClick: () => handleViewToggle("list"), "aria-label": "List view", className: `p-2 transition-colors ${view === "list" ? "bg-primary text-white" : "text-zinc-500 hover:bg-zinc-50 dark:hover:bg-slate-800 dark:text-zinc-400"}`, children: _jsx(List, { className: "h-4 w-4" }) })] })] }) }), _jsxs("div", { className: "py-6", children: [isLoading ? (_jsx("div", { className: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 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, emptyLabel: `No products found in this category.` })), totalPages > 1 && (_jsx("div", { className: "mt-8 flex justify-center", children: _jsx(Pagination, { currentPage: page, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) }))] }), filterOpen && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-40 bg-black/40", "aria-hidden": "true", onClick: closeFilters }), _jsxs("div", { className: "fixed inset-y-0 left-0 z-50 flex w-80 flex-col bg-white dark:bg-slate-900 shadow-2xl", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: [_jsxs("span", { className: "flex items-center gap-2 text-base font-semibold text-zinc-900 dark:text-zinc-100", children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), "Filters"] }), _jsx("button", { type: "button", onClick: closeFilters, "aria-label": "Close filters", className: "rounded-lg p-1.5 text-zinc-500 hover:bg-zinc-100 dark:hover:bg-slate-800 transition-colors", children: _jsx(X, { className: "h-5 w-5" }) })] }), _jsx("div", { className: "flex-1 overflow-y-auto px-4 py-4", children: _jsx(ProductFilters, { table: table, currencyPrefix: "\u20B9" }) }), _jsx("div", { className: "border-t border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: _jsx("button", { type: "button", onClick: closeFilters, className: "w-full rounded-lg bg-primary py-2.5 text-sm font-semibold text-white hover:bg-primary-600 transition-colors", children: "Apply filters" }) })] })] }))] }));
68
+ return (_jsxs("div", { className: "min-h-[200px]", children: [_jsx("div", { className: "sticky top-[var(--header-height,0px)] z-20 border-b border-zinc-200 dark:border-slate-700 bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm py-2.5 px-4", children: _jsxs("div", { className: "flex items-center gap-2.5 max-w-full", children: [_jsxs("button", { type: "button", onClick: () => setFilterOpen(true), className: "flex shrink-0 items-center gap-2 rounded-lg border border-zinc-300 dark:border-slate-600 px-3.5 py-2 text-sm font-medium text-zinc-700 dark:text-zinc-200 hover:bg-zinc-50 dark:hover:bg-slate-800 transition-colors", children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), _jsx("span", { className: "hidden sm:inline", children: "Filters" })] }), _jsxs("div", { className: "flex flex-1 items-center overflow-hidden rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-900", children: [_jsx("input", { type: "text", value: searchInput, onChange: (e) => setSearchInput(e.target.value), onKeyDown: (e) => e.key === "Enter" && commitSearch(), placeholder: `Search in ${categorySlug.replace(/-/g, " ")}...`, 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" }), _jsx("button", { type: "button", onClick: commitSearch, className: "flex shrink-0 items-center justify-center px-3 py-2 text-zinc-400 hover:text-primary dark:hover:text-primary-400 transition-colors", "aria-label": "Search", children: _jsx(Search, { className: "h-4 w-4" }) })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1.5 text-sm text-zinc-500 dark:text-zinc-400", children: [_jsx("span", { className: "hidden md:inline whitespace-nowrap", children: "Sort by" }), _jsx(SortDropdown, { value: table.get("sort") || "-createdAt", onChange: (v) => { table.set("sort", v); table.setPage(1); }, options: PRODUCT_PUBLIC_SORT_OPTIONS })] }), _jsxs("div", { className: "flex shrink-0 items-center rounded-lg border border-zinc-300 dark:border-slate-600 overflow-hidden", children: [_jsx("button", { type: "button", onClick: () => handleViewToggle("card"), "aria-label": "Grid view", className: `p-2 transition-colors ${view === "card" ? "bg-primary text-white" : "text-zinc-500 hover:bg-zinc-50 dark:hover:bg-slate-800 dark:text-zinc-400"}`, children: _jsx(LayoutGrid, { className: "h-4 w-4" }) }), _jsx("button", { type: "button", onClick: () => handleViewToggle("list"), "aria-label": "List view", className: `p-2 transition-colors ${view === "list" ? "bg-primary text-white" : "text-zinc-500 hover:bg-zinc-50 dark:hover:bg-slate-800 dark:text-zinc-400"}`, children: _jsx(List, { className: "h-4 w-4" }) })] })] }) }), _jsxs("div", { className: "py-6", children: [isLoading ? (_jsx("div", { className: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-6", children: Array.from({ length: 8 }).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, emptyLabel: "No products found in this category.", onWishlistToggle: handleWishlistToggle, wishlistedIds: wishlistedIds, onAddToCart: handleAddToCart })), totalPages > 1 && (_jsx("div", { className: "mt-8 flex justify-center", children: _jsx(Pagination, { currentPage: page, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) }))] }), filterOpen && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-40 bg-black/40", "aria-hidden": "true", onClick: closeFilters }), _jsxs("div", { className: "fixed inset-y-0 left-0 z-50 flex w-80 flex-col bg-white dark:bg-slate-900 shadow-2xl", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: [_jsxs("span", { className: "flex items-center gap-2 text-base font-semibold text-zinc-900 dark:text-zinc-100", children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), "Filters"] }), _jsx("button", { type: "button", onClick: closeFilters, "aria-label": "Close filters", className: "rounded-lg p-1.5 text-zinc-500 hover:bg-zinc-100 dark:hover:bg-slate-800 transition-colors", children: _jsx(X, { className: "h-5 w-5" }) })] }), _jsx("div", { className: "flex-1 overflow-y-auto px-4 py-4", children: _jsx(ProductFilters, { table: table, currencyPrefix: "\u20B9" }) }), _jsx("div", { className: "border-t border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: _jsx("button", { type: "button", onClick: closeFilters, className: "w-full rounded-lg bg-primary py-2.5 text-sm font-semibold text-white hover:bg-primary-600 transition-colors", children: "Apply filters" }) })] })] }))] }));
40
69
  }
@@ -2,5 +2,5 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Button, Div, Heading, Text } from "../../../ui";
3
3
  import { THEME_CONSTANTS } from "../../../tokens";
4
4
  export function ConcernCard({ concern, onClick, className = "", }) {
5
- return (_jsxs(Button, { type: "button", variant: "outline", onClick: () => onClick?.(concern), className: `group flex flex-col items-center gap-3 rounded-xl border border-neutral-200 bg-white p-4 text-center shadow-sm transition hover:border-primary hover:shadow-md ${className}`, children: [concern.display?.coverImage && (_jsx(Div, { role: "img", "aria-label": concern.name, className: "h-16 w-16 rounded-full bg-center bg-cover", style: { backgroundImage: `url(${concern.display.coverImage})` } })), _jsxs(Div, { children: [_jsx(Heading, { level: 3, className: "text-sm font-semibold text-neutral-900 group-hover:text-primary", children: concern.name }), concern.description && (_jsx(Text, { className: `mt-1 text-xs ${THEME_CONSTANTS.utilities.textClamp2} text-neutral-500`, children: concern.description }))] })] }));
5
+ return (_jsxs(Button, { type: "button", variant: "outline", onClick: () => onClick?.(concern), className: `group flex flex-col items-center gap-3 rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-900 p-4 text-center shadow-sm transition hover:border-primary dark:hover:border-primary-400 hover:shadow-md ${className}`, children: [concern.display?.coverImage && (_jsx(Div, { role: "img", "aria-label": concern.name, className: "h-16 w-16 rounded-full bg-center bg-cover", style: { backgroundImage: `url(${concern.display.coverImage})` } })), _jsxs(Div, { children: [_jsx(Heading, { level: 3, className: "text-sm font-semibold text-neutral-900 dark:text-zinc-100 group-hover:text-primary dark:group-hover:text-primary-400", children: concern.name }), concern.description && (_jsx(Text, { className: `mt-1 text-xs ${THEME_CONSTANTS.utilities.textClamp2} text-neutral-500 dark:text-zinc-400`, children: concern.description }))] })] }));
6
6
  }
@@ -41,6 +41,8 @@ export function useCategoriesFiltered(params = {}) {
41
41
  const lq = q.toLowerCase();
42
42
  if (lq)
43
43
  items = items.filter((c) => c.name.toLowerCase().includes(lq) || (c.description ?? "").toLowerCase().includes(lq));
44
+ if (params.isBrand === false)
45
+ items = items.filter((c) => !c.isBrand);
44
46
  if (minProductCount !== undefined)
45
47
  items = items.filter((c) => (c.productCount ?? 0) >= minProductCount);
46
48
  if (maxProductCount !== undefined)
@@ -98,6 +98,7 @@ export class CategoriesRepository extends BaseRepository {
98
98
  .collection(this.collection)
99
99
  .where("isLeaf", "==", true)
100
100
  .where("isActive", "==", true)
101
+ .limit(500)
101
102
  .get();
102
103
  return snapshot.docs.map((doc) => this.mapDoc(doc));
103
104
  }
@@ -141,10 +142,8 @@ export class CategoriesRepository extends BaseRepository {
141
142
  .collection(this.collection)
142
143
  .where("parentIds", "array-contains", parentId)
143
144
  .orderBy("order", "asc")
145
+ .limit(100)
144
146
  .get();
145
- const parent = await this.findById(parentId);
146
- if (!parent)
147
- return [];
148
147
  return snapshot.docs
149
148
  .map((doc) => this.mapDoc(doc))
150
149
  .filter((category) => category.parentIds[category.parentIds.length - 1] === parentId);
@@ -41,26 +41,45 @@ export interface CategoryDocument {
41
41
  path: string;
42
42
  order: number;
43
43
  isLeaf: boolean;
44
+ /**
45
+ * Global DFS pre-order position across the entire category tree (1-indexed).
46
+ * Set and maintained by the onCategoryWrite Cloud Function.
47
+ * Enables ordered range queries without loading the whole tree.
48
+ */
49
+ position: number;
50
+ /**
51
+ * Count of this node plus all its descendants.
52
+ * The range [position, position + subtreeSize - 1] covers the full subtree.
53
+ * Used to efficiently locate insertion points and shift sibling positions.
54
+ */
55
+ subtreeSize: number;
44
56
  metrics: CategoryDocumentMetrics;
45
57
  isFeatured: boolean;
46
58
  featuredPriority?: number;
47
59
  isBrand?: boolean;
60
+ type?: import("../types").CategoryType;
48
61
  seo: CategoryDocumentSEO;
49
62
  display: CategoryDocumentDisplay;
50
63
  isActive: boolean;
51
64
  isSearchable: boolean;
52
65
  showOnHomepage?: boolean;
53
66
  createdBy: string;
67
+ /** Whether this category was created by admin or a store owner. */
68
+ createdByType?: "admin" | "store";
69
+ /** The storeId of the store that requested this category (only set when createdByType === "store"). */
70
+ createdByStoreId?: string;
71
+ /** Display name of the store that requested this category. */
72
+ createdByStoreName?: string;
54
73
  createdAt: Date;
55
74
  updatedAt: Date;
56
75
  ancestors: CategoryAncestor[];
57
76
  }
58
77
  export declare const CATEGORIES_COLLECTION: "categories";
59
- export declare const CATEGORIES_INDEXED_FIELDS: readonly ["slug", "rootId", "tier", "parentIds", "isLeaf", "isFeatured", "featuredPriority", "isBrand", "isActive", "isSearchable", "showOnHomepage", "createdBy", "createdAt"];
78
+ export declare const CATEGORIES_INDEXED_FIELDS: readonly ["slug", "rootId", "tier", "parentIds", "isLeaf", "isFeatured", "featuredPriority", "isBrand", "isActive", "isSearchable", "showOnHomepage", "createdBy", "createdByType", "createdByStoreId", "createdAt"];
60
79
  export declare const MIN_ITEMS_FOR_FEATURED: 8;
61
80
  export declare const MAX_FEATURED_CATEGORIES: 4;
62
81
  export declare const DEFAULT_CATEGORY_DATA: Partial<CategoryDocument>;
63
- export declare const CATEGORIES_PUBLIC_FIELDS: readonly ["id", "name", "slug", "description", "rootId", "parentIds", "childrenIds", "tier", "path", "order", "isLeaf", "metrics.totalProductCount", "metrics.totalAuctionCount", "metrics.totalItemCount", "isFeatured", "featuredPriority", "isBrand", "seo", "display", "isActive", "ancestors"];
82
+ export declare const CATEGORIES_PUBLIC_FIELDS: readonly ["id", "name", "slug", "description", "rootId", "parentIds", "childrenIds", "tier", "path", "order", "position", "subtreeSize", "isLeaf", "metrics.totalProductCount", "metrics.totalAuctionCount", "metrics.totalItemCount", "isFeatured", "featuredPriority", "isBrand", "seo", "display", "isActive", "ancestors"];
64
83
  export declare const CATEGORIES_UPDATABLE_FIELDS: readonly ["name", "slug", "description", "order", "isFeatured", "featuredPriority", "isBrand", "seo", "display", "isActive", "isSearchable"];
65
84
  export type CategoryCreateInput = Omit<CategoryDocument, "id" | "createdAt" | "updatedAt" | "metrics" | "isLeaf" | "ancestors"> & {
66
85
  parentIds?: string[];
@@ -110,6 +129,8 @@ export declare const CATEGORY_FIELDS: {
110
129
  readonly TIER: "tier";
111
130
  readonly PATH: "path";
112
131
  readonly ORDER: "order";
132
+ readonly POSITION: "position";
133
+ readonly SUBTREE_SIZE: "subtreeSize";
113
134
  readonly IS_LEAF: "isLeaf";
114
135
  readonly METRICS: "metrics";
115
136
  readonly METRIC: {
@@ -20,6 +20,8 @@ export const CATEGORIES_INDEXED_FIELDS = [
20
20
  "isSearchable",
21
21
  "showOnHomepage",
22
22
  "createdBy",
23
+ "createdByType",
24
+ "createdByStoreId",
23
25
  "createdAt",
24
26
  ];
25
27
  export const MIN_ITEMS_FOR_FEATURED = 8;
@@ -28,6 +30,8 @@ export const DEFAULT_CATEGORY_DATA = {
28
30
  childrenIds: [],
29
31
  isLeaf: true,
30
32
  order: 0,
33
+ position: 0,
34
+ subtreeSize: 1,
31
35
  isFeatured: false,
32
36
  isBrand: false,
33
37
  isActive: true,
@@ -58,6 +62,8 @@ export const CATEGORIES_PUBLIC_FIELDS = [
58
62
  "tier",
59
63
  "path",
60
64
  "order",
65
+ "position",
66
+ "subtreeSize",
61
67
  "isLeaf",
62
68
  "metrics.totalProductCount",
63
69
  "metrics.totalAuctionCount",
@@ -145,6 +151,8 @@ export const CATEGORY_FIELDS = {
145
151
  TIER: "tier",
146
152
  PATH: "path",
147
153
  ORDER: "order",
154
+ POSITION: "position",
155
+ SUBTREE_SIZE: "subtreeSize",
148
156
  IS_LEAF: "isLeaf",
149
157
  METRICS: "metrics",
150
158
  METRIC: {