@mohasinac/appkit 4.9.5 → 4.11.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 (395) hide show
  1. package/dist/_internal/client/features/layout/DashboardLayoutClient.d.ts +6 -1
  2. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +4 -1
  3. package/dist/_internal/client/features/lottery/LotteryPullForm.d.ts +1 -1
  4. package/dist/_internal/client/features/lottery/LotteryPullForm.js +2 -2
  5. package/dist/_internal/server/features/admin/daily-digest-actions.d.ts +18 -0
  6. package/dist/_internal/server/features/admin/daily-digest-actions.js +37 -0
  7. package/dist/_internal/server/features/auctions/actions.js +3 -2
  8. package/dist/_internal/server/features/auctions/service.d.ts +4 -3
  9. package/dist/_internal/server/features/auctions/service.js +6 -6
  10. package/dist/_internal/server/features/audit-log/actions.d.ts +25 -0
  11. package/dist/_internal/server/features/audit-log/actions.js +38 -0
  12. package/dist/_internal/server/features/brands/actions.js +0 -2
  13. package/dist/_internal/server/features/brands/og.d.ts +4 -1
  14. package/dist/_internal/server/features/brands/og.js +1 -1
  15. package/dist/_internal/server/features/bundles/data.d.ts +9 -0
  16. package/dist/_internal/server/features/bundles/data.js +14 -0
  17. package/dist/_internal/server/features/bundles/index.d.ts +1 -1
  18. package/dist/_internal/server/features/bundles/index.js +1 -1
  19. package/dist/_internal/server/features/catalogue/og.d.ts +20 -0
  20. package/dist/_internal/server/features/catalogue/og.js +27 -0
  21. package/dist/_internal/server/features/grouped/data.d.ts +16 -0
  22. package/dist/_internal/server/features/grouped/data.js +50 -1
  23. package/dist/_internal/server/features/grouped/index.d.ts +1 -1
  24. package/dist/_internal/server/features/grouped/index.js +1 -1
  25. package/dist/_internal/server/features/orders/actions.js +9 -0
  26. package/dist/_internal/server/features/orders/adapters.js +25 -0
  27. package/dist/_internal/server/features/products/data.d.ts +23 -0
  28. package/dist/_internal/server/features/products/data.js +159 -0
  29. package/dist/_internal/server/features/products/index.d.ts +1 -1
  30. package/dist/_internal/server/features/products/index.js +1 -1
  31. package/dist/_internal/server/functions/scheduled.d.ts +3 -1
  32. package/dist/_internal/server/functions/scheduled.js +17 -1
  33. package/dist/_internal/server/jobs/core/dailyStatusDigest.d.ts +40 -0
  34. package/dist/_internal/server/jobs/core/dailyStatusDigest.js +164 -0
  35. package/dist/_internal/server/jobs/core/hardBanCascade.js +11 -0
  36. package/dist/_internal/server/jobs/core/testerSandboxCleanup.d.ts +1 -0
  37. package/dist/_internal/server/jobs/core/testerSandboxCleanup.js +4 -1
  38. package/dist/_internal/server/jobs/core/testerSandboxRefresh.d.ts +12 -0
  39. package/dist/_internal/server/jobs/core/testerSandboxRefresh.js +85 -0
  40. package/dist/_internal/server/jobs/core/whatsappNotify.js +16 -0
  41. package/dist/_internal/server/jobs/handlers/dailyStatusDigest.d.ts +2 -0
  42. package/dist/_internal/server/jobs/handlers/dailyStatusDigest.js +4 -0
  43. package/dist/_internal/server/jobs/handlers/index.d.ts +2 -0
  44. package/dist/_internal/server/jobs/handlers/index.js +3 -0
  45. package/dist/_internal/server/jobs/handlers/testerSandboxRefresh.d.ts +2 -0
  46. package/dist/_internal/server/jobs/handlers/testerSandboxRefresh.js +2 -0
  47. package/dist/_internal/server/notifications/channel-health.d.ts +27 -0
  48. package/dist/_internal/server/notifications/channel-health.js +101 -0
  49. package/dist/_internal/shared/features/auctions/config.d.ts +20 -0
  50. package/dist/_internal/shared/features/auctions/config.js +31 -1
  51. package/dist/_internal/shared/features/brands/schema.d.ts +0 -6
  52. package/dist/_internal/shared/features/brands/schema.js +0 -1
  53. package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +7 -0
  54. package/dist/_internal/shared/features/categories/bundle-schemas.js +3 -0
  55. package/dist/_internal/shared/features/orders/schema.d.ts +8 -8
  56. package/dist/_internal/shared/listing-types/art/config.d.ts +1 -1
  57. package/dist/_internal/shared/listing-types/art/config.js +1 -1
  58. package/dist/_internal/shared/listing-types/classified/config.d.ts +1 -1
  59. package/dist/_internal/shared/listing-types/classified/config.js +1 -1
  60. package/dist/_internal/shared/listing-types/digital-code/config.d.ts +1 -1
  61. package/dist/_internal/shared/listing-types/digital-code/config.js +1 -1
  62. package/dist/_internal/shared/listing-types/live/config.d.ts +1 -1
  63. package/dist/_internal/shared/listing-types/live/config.js +1 -1
  64. package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +1 -1
  65. package/dist/_internal/shared/listing-types/prize-draw/config.js +1 -1
  66. package/dist/_internal/shared/listing-types/stickers/config.d.ts +1 -1
  67. package/dist/_internal/shared/listing-types/stickers/config.js +1 -1
  68. package/dist/client.d.ts +21 -12
  69. package/dist/client.js +14 -7
  70. package/dist/constants/api-endpoints.d.ts +9 -9
  71. package/dist/constants/api-endpoints.js +3 -3
  72. package/dist/contracts/client-auth.d.ts +3 -7
  73. package/dist/contracts/email.d.ts +1 -0
  74. package/dist/features/account/components/AddressForm.js +24 -2
  75. package/dist/features/account/components/BecomeSellerView.d.ts +1 -2
  76. package/dist/features/account/components/BecomeSellerView.js +1 -1
  77. package/dist/features/account/components/NotificationBell.js +1 -1
  78. package/dist/features/account/components/UserBidsView.d.ts +1 -0
  79. package/dist/features/account/components/UserBidsView.js +47 -0
  80. package/dist/features/account/components/UserOrdersView.d.ts +4 -11
  81. package/dist/features/account/components/UserOrdersView.js +54 -4
  82. package/dist/features/account/components/UserReturnsView.d.ts +4 -9
  83. package/dist/features/account/components/UserReturnsView.js +37 -3
  84. package/dist/features/account/components/index.d.ts +3 -2
  85. package/dist/features/account/components/index.js +1 -0
  86. package/dist/features/admin/actions/admin-actions.js +22 -0
  87. package/dist/features/admin/actions/admin-coupon-actions.js +10 -0
  88. package/dist/features/admin/actions/notification-actions.js +4 -3
  89. package/dist/features/admin/components/AdminAdsView.d.ts +2 -3
  90. package/dist/features/admin/components/AdminAdsView.js +86 -89
  91. package/dist/features/admin/components/AdminAllEventEntriesView.js +18 -3
  92. package/dist/features/admin/components/AdminAuditLogView.d.ts +11 -0
  93. package/dist/features/admin/components/AdminAuditLogView.js +95 -0
  94. package/dist/features/admin/components/AdminBlogEditorView.js +37 -3
  95. package/dist/features/admin/components/AdminBrandEditorView.js +10 -6
  96. package/dist/features/admin/components/AdminBundleEditorView.js +18 -2
  97. package/dist/features/admin/components/AdminCarouselEditorView.js +2 -2
  98. package/dist/features/admin/components/AdminCarouselGroupEditorView.js +2 -2
  99. package/dist/features/admin/components/AdminCartsView.js +34 -4
  100. package/dist/features/admin/components/AdminCategoryEditorView.js +5 -4
  101. package/dist/features/admin/components/AdminCouponEditorView.js +2 -2
  102. package/dist/features/admin/components/AdminFaqEditorView.js +2 -2
  103. package/dist/features/admin/components/AdminHistoryView.js +11 -1
  104. package/dist/features/admin/components/AdminNotificationsView.js +27 -1
  105. package/dist/features/admin/components/AdminOrderEditorView.d.ts +10 -1
  106. package/dist/features/admin/components/AdminOrderEditorView.js +4 -3
  107. package/dist/features/admin/components/AdminOrdersView.js +92 -24
  108. package/dist/features/admin/components/AdminPayoutMarkPaidModal.d.ts +7 -0
  109. package/dist/features/admin/components/AdminPayoutMarkPaidModal.js +47 -0
  110. package/dist/features/admin/components/AdminPayoutsView.js +15 -31
  111. package/dist/features/admin/components/AdminProductEditorView.js +26 -3
  112. package/dist/features/admin/components/AdminSiteSettingsView.js +31 -4
  113. package/dist/features/admin/components/AdminStoreAddressesView.js +22 -2
  114. package/dist/features/admin/components/AdminStoresView.js +7 -0
  115. package/dist/features/admin/components/AdminSublistingCategoryEditorView.js +2 -2
  116. package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +2 -2
  117. package/dist/features/admin/components/AdminUserEditorView.d.ts +2 -2
  118. package/dist/features/admin/components/AdminUserEditorView.js +4 -2
  119. package/dist/features/admin/components/AdminUsersView.js +1 -1
  120. package/dist/features/admin/components/AdminWishlistsView.js +14 -1
  121. package/dist/features/admin/components/DataListingView.d.ts +2 -2
  122. package/dist/features/admin/components/ViewAuditLogEntryModal.d.ts +19 -0
  123. package/dist/features/admin/components/ViewAuditLogEntryModal.js +22 -0
  124. package/dist/features/admin/components/ViewNotificationModal.d.ts +21 -0
  125. package/dist/features/admin/components/ViewNotificationModal.js +15 -0
  126. package/dist/features/admin/components/analytics/AdminPageViewsReportView.d.ts +4 -7
  127. package/dist/features/admin/components/analytics/AdminPageViewsReportView.js +56 -36
  128. package/dist/features/admin/components/index.d.ts +8 -1
  129. package/dist/features/admin/components/index.js +4 -0
  130. package/dist/features/admin/constants/filter-tabs.d.ts +49 -0
  131. package/dist/features/admin/constants/filter-tabs.js +27 -0
  132. package/dist/features/admin/hooks/useAdminListing.d.ts +6 -0
  133. package/dist/features/admin/hooks/useAdminListing.js +3 -1
  134. package/dist/features/admin/hooks/useAdminListingData.d.ts +9 -1
  135. package/dist/features/admin/hooks/useAdminListingData.js +9 -2
  136. package/dist/features/admin/repository/site-settings.repository.d.ts +5 -0
  137. package/dist/features/admin/schemas/firestore.d.ts +21 -0
  138. package/dist/features/admin/schemas/firestore.js +6 -0
  139. package/dist/features/analytics/types.d.ts +1 -1
  140. package/dist/features/analytics/types.js +8 -0
  141. package/dist/features/auctions/actions/bid-actions.js +4 -1
  142. package/dist/features/auctions/components/AuctionBottomActions.d.ts +2 -1
  143. package/dist/features/auctions/components/AuctionBottomActions.js +14 -1
  144. package/dist/features/auctions/components/AuctionDetailPageView.js +21 -9
  145. package/dist/features/auctions/components/LiveMinIncrement.d.ts +18 -0
  146. package/dist/features/auctions/components/LiveMinIncrement.js +17 -0
  147. package/dist/features/auctions/components/PlaceBidFormClient.d.ts +5 -2
  148. package/dist/features/auctions/components/PlaceBidFormClient.js +7 -3
  149. package/dist/features/auctions/schemas/index.d.ts +5 -0
  150. package/dist/features/audit-log/repository/audit-log.repository.d.ts +45 -0
  151. package/dist/features/audit-log/repository/audit-log.repository.js +30 -0
  152. package/dist/features/audit-log/schemas/firestore.d.ts +59 -0
  153. package/dist/features/audit-log/schemas/firestore.js +35 -0
  154. package/dist/features/auth/actions/index.d.ts +0 -1
  155. package/dist/features/auth/actions/index.js +0 -1
  156. package/dist/features/auth/hooks/useAuth.d.ts +8 -35
  157. package/dist/features/auth/hooks/useAuth.js +21 -37
  158. package/dist/features/auth/permissions/constants.d.ts +1 -1
  159. package/dist/features/auth/permissions/constants.js +2 -0
  160. package/dist/features/blog/schemas/index.d.ts +32 -0
  161. package/dist/features/catalogue/components/AdminCatalogueApprovalsView.js +31 -3
  162. package/dist/features/catalogue/components/CatalogueItemEditorView.js +2 -1
  163. package/dist/features/catalogue/components/PublicCatalogueItemDetailView.d.ts +11 -0
  164. package/dist/features/catalogue/components/PublicCatalogueItemDetailView.js +33 -0
  165. package/dist/features/catalogue/components/PublicCatalogueView.js +2 -1
  166. package/dist/features/catalogue/index.d.ts +2 -0
  167. package/dist/features/catalogue/index.js +1 -0
  168. package/dist/features/categories/components/BrandDetailPageView.js +14 -12
  169. package/dist/features/categories/components/BundleDetailView.d.ts +3 -1
  170. package/dist/features/categories/components/BundleDetailView.js +3 -2
  171. package/dist/features/categories/components/CategoryDetailPageView.js +7 -3
  172. package/dist/features/categories/components/CategoryHighlightsAndFaqSection.d.ts +14 -0
  173. package/dist/features/categories/components/CategoryHighlightsAndFaqSection.js +22 -0
  174. package/dist/features/categories/components/CategoryProductsView.d.ts +1 -5
  175. package/dist/features/categories/components/CategoryProductsView.js +1 -1
  176. package/dist/features/categories/components/CategorySelectorCreate.js +16 -2
  177. package/dist/features/categories/schemas/firestore.d.ts +19 -2
  178. package/dist/features/categories/schemas/index.d.ts +24 -3
  179. package/dist/features/categories/schemas/index.js +3 -1
  180. package/dist/features/categories/types/index.d.ts +7 -0
  181. package/dist/features/checkout/actions/checkout-value-otp-actions.d.ts +17 -3
  182. package/dist/features/checkout/actions/checkout-value-otp-actions.js +101 -22
  183. package/dist/features/classified/components/ClassifiedContactSellerPanel.d.ts +12 -0
  184. package/dist/features/classified/components/ClassifiedContactSellerPanel.js +49 -0
  185. package/dist/features/classified/components/ClassifiedDetailPageView.d.ts +7 -0
  186. package/dist/features/classified/components/ClassifiedDetailPageView.js +69 -0
  187. package/dist/features/contact/components/ContactForm.js +17 -4
  188. package/dist/features/contact/components/ContactPageView.js +8 -2
  189. package/dist/features/contact/email.d.ts +1 -0
  190. package/dist/features/contact/email.js +3 -0
  191. package/dist/features/digital-codes/components/DigitalCodeDetailPageView.d.ts +19 -0
  192. package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +79 -0
  193. package/dist/features/events/components/AdminEventEditorView.js +54 -2
  194. package/dist/features/events/components/AdminEventEntriesView.d.ts +2 -16
  195. package/dist/features/events/components/AdminEventEntriesView.js +56 -89
  196. package/dist/features/events/components/EventFormDrawer.js +5 -1
  197. package/dist/features/events/components/EventRaffleEntryForm.d.ts +1 -3
  198. package/dist/features/events/components/EventRaffleEntryForm.js +1 -1
  199. package/dist/features/events/schemas/index.d.ts +22 -0
  200. package/dist/features/grouped/components/GroupedListingsCarousel.d.ts +13 -0
  201. package/dist/features/grouped/components/GroupedListingsCarousel.js +31 -0
  202. package/dist/features/grouped/repository/grouped-listings.repository.d.ts +12 -0
  203. package/dist/features/grouped/repository/grouped-listings.repository.js +34 -0
  204. package/dist/features/homepage/components/CharacterHotspotForm.js +202 -187
  205. package/dist/features/homepage/components/SectionCarousel.d.ts +1 -7
  206. package/dist/features/homepage/components/SectionCarousel.js +1 -1
  207. package/dist/features/layout/BottomActions.js +4 -3
  208. package/dist/features/layout/BottomActionsContext.d.ts +10 -0
  209. package/dist/features/layout/BottomActionsContext.js +5 -1
  210. package/dist/features/layout/TitleBarLayout.d.ts +1 -1
  211. package/dist/features/layout/TitleBarLayout.js +3 -3
  212. package/dist/features/layout/hooks/useBottomActions.d.ts +2 -0
  213. package/dist/features/layout/hooks/useBottomActions.js +4 -1
  214. package/dist/features/live/components/LiveItemDetailPageView.d.ts +9 -0
  215. package/dist/features/live/components/LiveItemDetailPageView.js +74 -0
  216. package/dist/features/media/MediaImage.js +39 -3
  217. package/dist/features/media/MediaVideo.js +17 -1
  218. package/dist/features/media/types/index.d.ts +10 -0
  219. package/dist/features/media/types/index.js +1 -0
  220. package/dist/features/media/upload/MediaUploadField.d.ts +7 -1
  221. package/dist/features/media/upload/MediaUploadField.js +11 -7
  222. package/dist/features/media/upload/video-poster.d.ts +2 -0
  223. package/dist/features/media/upload/video-poster.js +16 -1
  224. package/dist/features/media/upload/video-poster.test.js +1 -1
  225. package/dist/features/orders/components/OrderStatusTimeline.d.ts +12 -0
  226. package/dist/features/orders/components/OrderStatusTimeline.js +55 -0
  227. package/dist/features/orders/components/index.d.ts +2 -0
  228. package/dist/features/orders/components/index.js +1 -0
  229. package/dist/features/orders/constants/payment-window.d.ts +25 -0
  230. package/dist/features/orders/constants/payment-window.js +25 -0
  231. package/dist/features/orders/repository/orders.repository.d.ts +32 -0
  232. package/dist/features/orders/repository/orders.repository.js +56 -0
  233. package/dist/features/orders/schemas/index.d.ts +24 -24
  234. package/dist/features/orders/types/index.d.ts +33 -0
  235. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +9 -1
  236. package/dist/features/pre-orders/schemas/index.d.ts +5 -0
  237. package/dist/features/products/components/BidHistory.js +9 -1
  238. package/dist/features/products/components/GroupSettingsPanel.js +25 -3
  239. package/dist/features/products/components/PrizeDrawDetailPageView.js +11 -1
  240. package/dist/features/products/components/PrizeDrawEntryActions.d.ts +1 -4
  241. package/dist/features/products/components/PrizeDrawEntryActions.js +1 -1
  242. package/dist/features/products/components/ProductDetailActions.d.ts +1 -2
  243. package/dist/features/products/components/ProductDetailActions.js +1 -1
  244. package/dist/features/products/components/ProductDetailPageView.js +11 -116
  245. package/dist/features/products/components/ProductGrid.js +15 -1
  246. package/dist/features/products/components/RelatedItemsSection.d.ts +16 -0
  247. package/dist/features/products/components/RelatedItemsSection.js +17 -0
  248. package/dist/features/products/constants/action-defs.d.ts +1 -0
  249. package/dist/features/products/constants/action-defs.js +1 -0
  250. package/dist/features/products/schemas/index.d.ts +5 -0
  251. package/dist/features/promotions/components/CouponsIndexListing.d.ts +1 -3
  252. package/dist/features/promotions/components/CouponsIndexListing.js +1 -1
  253. package/dist/features/search/components/SearchView.d.ts +1 -3
  254. package/dist/features/search/components/SearchView.js +1 -1
  255. package/dist/features/seller/components/QuickProductForm.js +2 -1
  256. package/dist/features/seller/components/SellerBidsView.js +66 -107
  257. package/dist/features/seller/components/SellerGoogleReviewsView.js +17 -1
  258. package/dist/features/seller/components/SellerOrdersView.d.ts +15 -3
  259. package/dist/features/seller/components/SellerOrdersView.js +134 -163
  260. package/dist/features/seller/components/SellerPayoutMethodsView.js +60 -48
  261. package/dist/features/seller/components/SellerPayoutSettingsView.js +69 -4
  262. package/dist/features/seller/components/SellerPayoutsView.d.ts +12 -0
  263. package/dist/features/seller/components/SellerPayoutsView.js +25 -5
  264. package/dist/features/seller/components/SellerProductShell.d.ts +10 -3
  265. package/dist/features/seller/components/SellerProductShell.js +90 -37
  266. package/dist/features/seller/components/SellerProductsFilterDrawer.d.ts +2 -7
  267. package/dist/features/seller/components/SellerProductsFilterDrawer.js +4 -4
  268. package/dist/features/seller/components/SellerProductsView.d.ts +2 -4
  269. package/dist/features/seller/components/SellerProductsView.js +131 -189
  270. package/dist/features/seller/components/SellerReviewsView.js +95 -133
  271. package/dist/features/seller/components/SellerShippingConfigsView.js +47 -67
  272. package/dist/features/seller/components/SellerShippingView.js +41 -4
  273. package/dist/features/seller/components/SellerStoreCategoriesView.js +51 -59
  274. package/dist/features/seller/components/SellerStorefrontView.d.ts +6 -1
  275. package/dist/features/seller/components/SellerStorefrontView.js +42 -5
  276. package/dist/features/seller/components/index.d.ts +2 -2
  277. package/dist/features/seller/components/index.js +2 -2
  278. package/dist/features/shell/FormShell.d.ts +24 -4
  279. package/dist/features/shell/FormShell.js +12 -6
  280. package/dist/features/shell/QuickFormDrawer.js +67 -12
  281. package/dist/features/shell/StepForm.d.ts +30 -1
  282. package/dist/features/shell/StepForm.js +47 -4
  283. package/dist/features/shell/index.d.ts +1 -1
  284. package/dist/features/shell/index.js +1 -1
  285. package/dist/features/shipments/components/AdminShipmentEditorView.js +2 -2
  286. package/dist/features/shipments/schemas/validation.d.ts +14 -4
  287. package/dist/features/tester/components/AdminTesterFeedbackListView.js +23 -2
  288. package/dist/features/tester/components/TesterChecklistStepRow.js +1 -1
  289. package/dist/features/tester/components/TesterHubView.js +3 -2
  290. package/dist/features/tester/seed-data/orders-tester-seed-data.js +9 -1
  291. package/dist/features/tester/seed-data/products-tester-seed-data.js +43 -32
  292. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +487 -18
  293. package/dist/index.d.ts +17 -3
  294. package/dist/index.js +23 -5
  295. package/dist/next/routing/route-map.d.ts +13 -0
  296. package/dist/next/routing/route-map.js +12 -0
  297. package/dist/providers/email-resend/provider.js +1 -0
  298. package/dist/providers/firebase-client/auth.d.ts +1 -0
  299. package/dist/providers/firebase-client/auth.js +7 -1
  300. package/dist/repositories/index.d.ts +1 -0
  301. package/dist/repositories/index.js +1 -0
  302. package/dist/schemas/registry.d.ts +61 -25
  303. package/dist/security/pii-mask.js +1 -1
  304. package/dist/seed/bids-seed-data.js +48 -3
  305. package/dist/seed/categories-seed-data.js +69 -0
  306. package/dist/seed/grouped-listings-seed-data.js +167 -0
  307. package/dist/seed/payouts-seed-data.js +4 -4
  308. package/dist/seed/products-art-seed-data.js +188 -5
  309. package/dist/seed/products-auctions-seed-data.js +226 -6
  310. package/dist/seed/products-classifieds-seed-data.js +255 -8
  311. package/dist/seed/products-digital-codes-seed-data.js +258 -19
  312. package/dist/seed/products-live-items-seed-data.js +143 -10
  313. package/dist/seed/products-preorders-seed-data.js +213 -8
  314. package/dist/seed/products-prize-draws-seed-data.js +198 -0
  315. package/dist/seed/products-standard-seed-data.js +234 -4
  316. package/dist/seed/products-stickers-seed-data.js +178 -5
  317. package/dist/seed/site-settings-seed-data.js +23 -30
  318. package/dist/seed/store-extensions-seed-data.js +2 -2
  319. package/dist/server-entry.d.ts +6 -2
  320. package/dist/server-entry.js +24 -3
  321. package/dist/server.d.ts +10 -3
  322. package/dist/server.js +11 -4
  323. package/dist/styles.css +29 -1
  324. package/dist/tailwind-utilities.css +1 -1
  325. package/dist/ui/components/Form.d.ts +11 -2
  326. package/dist/ui/components/Form.js +4 -3
  327. package/dist/ui/components/FormField.d.ts +3 -1
  328. package/dist/ui/components/FormField.js +22 -4
  329. package/dist/ui/components/ImageLightbox.js +37 -3
  330. package/dist/ui/components/ImageLightbox.style.css +28 -0
  331. package/dist/ui/components/ListingLayout.d.ts +1 -2
  332. package/dist/ui/components/ListingLayout.js +1 -1
  333. package/dist/ui/components/RecordDetailModal.d.ts +68 -0
  334. package/dist/ui/components/RecordDetailModal.js +8 -0
  335. package/dist/ui/components/SlottedListingView.js +9 -1
  336. package/dist/ui/forms/FormErrorSummary.d.ts +25 -0
  337. package/dist/ui/forms/FormErrorSummary.js +37 -0
  338. package/dist/ui/forms/FormShell.d.ts +37 -2
  339. package/dist/ui/forms/FormShell.js +37 -7
  340. package/dist/ui/forms/FormShell.style.css +17 -0
  341. package/dist/ui/forms/index.d.ts +2 -0
  342. package/dist/ui/forms/index.js +1 -0
  343. package/dist/ui/index.d.ts +4 -0
  344. package/dist/ui/index.js +5 -0
  345. package/dist/utils/media-url.d.ts +12 -1
  346. package/dist/utils/media-url.js +59 -1
  347. package/dist/validation/schemas.d.ts +4 -4
  348. package/package.json +1 -1
  349. package/dist/_internal/client/features/classified/ClassifiedDetailView.d.ts +0 -9
  350. package/dist/_internal/client/features/classified/ClassifiedDetailView.js +0 -55
  351. package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.d.ts +0 -18
  352. package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.js +0 -21
  353. package/dist/_internal/client/features/live/LiveItemDetailView.d.ts +0 -9
  354. package/dist/_internal/client/features/live/LiveItemDetailView.js +0 -25
  355. package/dist/_internal/server/jobs/core/prizeRevealClose.d.ts +0 -2
  356. package/dist/_internal/server/jobs/core/prizeRevealClose.js +0 -28
  357. package/dist/_internal/server/jobs/core/prizeRevealExpiry.d.ts +0 -2
  358. package/dist/_internal/server/jobs/core/prizeRevealExpiry.js +0 -61
  359. package/dist/_internal/server/jobs/core/prizeRevealOpen.d.ts +0 -2
  360. package/dist/_internal/server/jobs/core/prizeRevealOpen.js +0 -68
  361. package/dist/_internal/server/jobs/core/prizeRevealReminder.d.ts +0 -2
  362. package/dist/_internal/server/jobs/core/prizeRevealReminder.js +0 -49
  363. package/dist/_internal/server/jobs/handlers/prizeRevealClose.d.ts +0 -2
  364. package/dist/_internal/server/jobs/handlers/prizeRevealClose.js +0 -2
  365. package/dist/_internal/server/jobs/handlers/prizeRevealExpiry.d.ts +0 -2
  366. package/dist/_internal/server/jobs/handlers/prizeRevealExpiry.js +0 -2
  367. package/dist/_internal/server/jobs/handlers/prizeRevealOpen.d.ts +0 -2
  368. package/dist/_internal/server/jobs/handlers/prizeRevealOpen.js +0 -2
  369. package/dist/_internal/server/jobs/handlers/prizeRevealReminder.d.ts +0 -2
  370. package/dist/_internal/server/jobs/handlers/prizeRevealReminder.js +0 -2
  371. package/dist/features/auth/consent-otp.d.ts +0 -57
  372. package/dist/features/auth/consent-otp.js +0 -127
  373. package/dist/features/cart/components/CheckoutOtpModal.d.ts +0 -15
  374. package/dist/features/cart/components/CheckoutOtpModal.js +0 -12
  375. package/dist/features/checkout/actions/checkout-actions.d.ts +0 -31
  376. package/dist/features/checkout/actions/checkout-actions.js +0 -124
  377. package/dist/features/classified/components/ClassifiedIndexListing.d.ts +0 -5
  378. package/dist/features/classified/components/ClassifiedIndexListing.js +0 -123
  379. package/dist/features/classified/components/ClassifiedListView.d.ts +0 -6
  380. package/dist/features/classified/components/ClassifiedListView.js +0 -44
  381. package/dist/features/digital-codes/components/DigitalCodesIndexListing.d.ts +0 -5
  382. package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +0 -114
  383. package/dist/features/digital-codes/components/DigitalCodesListView.d.ts +0 -6
  384. package/dist/features/digital-codes/components/DigitalCodesListView.js +0 -38
  385. package/dist/features/live/components/LiveItemsIndexListing.d.ts +0 -5
  386. package/dist/features/live/components/LiveItemsIndexListing.js +0 -115
  387. package/dist/features/live/components/LiveItemsListView.d.ts +0 -6
  388. package/dist/features/live/components/LiveItemsListView.js +0 -44
  389. package/dist/features/seller/components/SellerTemplatesView.d.ts +0 -12
  390. package/dist/features/seller/components/SellerTemplatesView.js +0 -276
  391. package/dist/react/hooks/useVisibleItems.d.ts +0 -37
  392. package/dist/react/hooks/useVisibleItems.js +0 -59
  393. package/dist/ui/components/TabStrip.d.ts +0 -34
  394. package/dist/ui/components/TabStrip.js +0 -56
  395. package/dist/ui/components/TabStrip.style.css +0 -97
@@ -8,6 +8,9 @@ import { Container, Div, Heading, Main, Nav, Section, Span, Text } from "../../.
8
8
  import { MediaImage } from "../../media/MediaImage";
9
9
  import { CategoryDetailTabs } from "./CategoryDetailTabs";
10
10
  import { CategoryGrid } from "./CategoryGrid";
11
+ import { CategoryHighlightsAndFaqSection } from "./CategoryHighlightsAndFaqSection";
12
+ import { GroupedListingsCarousel } from "../../grouped/components/GroupedListingsCarousel";
13
+ import { getGroupsForCategory } from "../../../_internal/server/features/grouped/data";
11
14
  const __O = {
12
15
  hidden: "overflow-hidden",
13
16
  xAuto: "overflow-x-auto",
@@ -25,7 +28,7 @@ export async function CategoryDetailPageView({ slug }) {
25
28
  ? await categoriesRepository.getDescendantIds(category.id).catch(() => [])
26
29
  : [];
27
30
  const categoriesIn = category?.id ? [category.id, ...descendantIds] : null;
28
- const [productsResult, auctionsCountResult, preOrdersCountResult, prizeDrawsCountResult, bundlesResult, childCategories, rootSiblingCategories] = await Promise.all([
31
+ const [productsResult, auctionsCountResult, preOrdersCountResult, prizeDrawsCountResult, bundlesResult, childCategories, rootSiblingCategories, groupedListings] = await Promise.all([
29
32
  categoriesIn
30
33
  ? productRepository
31
34
  .list({
@@ -82,6 +85,7 @@ export async function CategoryDetailPageView({ slug }) {
82
85
  category?.rootId
83
86
  ? categoriesRepository.getCategoriesByRootId(category.rootId).catch(() => [])
84
87
  : Promise.resolve([]),
88
+ category?.slug ? getGroupsForCategory(category.slug).catch(() => []) : Promise.resolve([]),
85
89
  ]);
86
90
  const relatedCategories = rootSiblingCategories.filter((c) => c.id !== category?.id && (!c.categoryType || c.categoryType === "category"));
87
91
  // Stores tab — query stores whose storeCategory matches this category or any child
@@ -126,7 +130,7 @@ export async function CategoryDetailPageView({ slug }) {
126
130
  const storeCount = categoryStores.length;
127
131
  const coverImage = category?.display?.coverImage;
128
132
  const hasCover = Boolean(coverImage);
129
- return (_jsxs(Main, { children: [_jsxs(Section, { className: `relative ${__O.hidden} ${hasCover ? "min-h-[220px] md:min-h-[280px]" : "bg-[var(--appkit-color-bg)]"}`, children: [hasCover && (_jsxs(_Fragment, { children: [_jsx(Div, { className: "absolute inset-0", children: _jsx(MediaImage, { src: coverImage, alt: "", size: "banner" }) }), _jsx(Div, { surface: "overlay-md", className: "absolute inset-0" })] })), _jsxs(Div, { className: "relative z-10 max-w-7xl mx-auto", paddingY: hasCover ? "y-3xl" : "y-xl", padding: "x-md", children: [_jsxs(Nav, { layout: "flex", gap: "2xs", textSize: "sm", className: "mb-4", "aria-label": "Breadcrumb", children: [_jsx(Link, { href: String(ROUTES.HOME), className: hasCover ? "text-white/70 hover:text-white transition-colors" : "text-[var(--appkit-color-text-muted)] 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-[var(--appkit-color-text-muted)] hover:text-primary-600 transition-colors", children: "Categories" }), _jsx(Span, { className: hasCover ? "text-white/40" : "text-zinc-400", children: "/" }), _jsx(Span, { weight: "medium", className: hasCover ? "text-white" : "text-[var(--appkit-color-text)]", children: category?.name ?? slug })] }), _jsx(Heading, { color: "inverse", level: 1, className: `mb-2 ${hasCover ? "" : "text-[var(--appkit-color-text)]"}`, size: "3xl", mdSize: "4xl", weight: "bold", children: category?.name ?? slug }), category?.description && typeof category.description === "string" && !category.description.startsWith("{") && (_jsx(Text, { color: hasCover ? "inverse" : "muted", className: `max-w-2xl mb-4 ${hasCover ? "/80" : ""}`, size: "base", children: category.description })), _jsxs(Row, { wrap: true, gap: "sm", children: [productCount > 0 && (_jsxs(Span, { layout: "inline-flex", gap: "xs", color: "inverse", size: "xs", weight: "medium", className: hasCover ? "bg-[rgba(255,255,255,0.2)] backdrop-blur-sm" : "bg-primary/10 text-primary-700 dark:text-primary-400", rounded: "full", padding: "pill-sm-tall", children: [productCount.toLocaleString(), " ", productCount === 1 ? "product" : "products"] })), auctionCount > 0 && (_jsxs(Span, { layout: "inline-flex", gap: "xs", color: hasCover ? "inverse" : "warning", surface: hasCover ? undefined : "warning-surface", size: "xs", weight: "medium", className: hasCover ? "bg-[rgba(255,255,255,0.2)] backdrop-blur-sm" : "", rounded: "full", padding: "pill-sm-tall", children: [auctionCount.toLocaleString(), " ", auctionCount === 1 ? "auction" : "auctions"] })), preOrderCount > 0 && (_jsxs(Span, { layout: "inline-flex", gap: "xs", color: hasCover ? "inverse" : "info", surface: hasCover ? undefined : "info-surface", size: "xs", weight: "medium", className: hasCover ? "bg-[rgba(255,255,255,0.2)] backdrop-blur-sm" : "", rounded: "full", padding: "pill-sm-tall", children: [preOrderCount.toLocaleString(), " ", preOrderCount === 1 ? "pre-order" : "pre-orders"] })), storeCount > 0 && (_jsxs(Span, { layout: "inline-flex", gap: "xs", color: hasCover ? "inverse" : "success", surface: hasCover ? undefined : "success-surface", size: "xs", weight: "medium", className: hasCover ? "bg-[rgba(255,255,255,0.2)] backdrop-blur-sm" : "", rounded: "full", padding: "pill-sm-tall", children: [storeCount.toLocaleString(), " ", storeCount === 1 ? "store" : "stores"] }))] })] })] }), childCategories.length > 0 && (_jsx(Section, { border: "subtle", surface: "default", className: "border-b", children: _jsx(Div, { className: "max-w-7xl mx-auto", padding: "inline", children: _jsx(Div, { layout: "flex", gap: "2", className: `.5 ${__O.xAuto} [scrollbar-width:none]`, padding: "b-2xs", children: childCategories.map((child) => (_jsxs(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(child.slug)),
133
+ return (_jsxs(Main, { children: [_jsxs(Section, { className: `relative ${__O.hidden} ${hasCover ? "min-h-[220px] md:min-h-[280px]" : "bg-[var(--appkit-color-bg)]"}`, children: [hasCover && (_jsxs(_Fragment, { children: [_jsx(Div, { className: "absolute inset-0", children: _jsx(MediaImage, { src: coverImage, alt: "", size: "banner" }) }), _jsx(Div, { surface: "overlay-md", className: "absolute inset-0" })] })), _jsxs(Div, { className: "relative z-10 max-w-7xl mx-auto", paddingY: hasCover ? "y-3xl" : "y-xl", padding: "x-md", children: [_jsxs(Nav, { layout: "flex", gap: "2xs", textSize: "sm", className: "mb-4", "aria-label": "Breadcrumb", children: [_jsx(Link, { href: String(ROUTES.HOME), className: hasCover ? "text-white/70 hover:text-white transition-colors" : "text-[var(--appkit-color-text-muted)] 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-[var(--appkit-color-text-muted)] hover:text-primary-600 transition-colors", children: "Categories" }), _jsx(Span, { className: hasCover ? "text-white/40" : "text-zinc-400", children: "/" }), _jsx(Span, { weight: "medium", className: hasCover ? "text-white" : "text-[var(--appkit-color-text)]", children: category?.name ?? slug })] }), _jsx(Heading, { color: "inverse", level: 1, className: `mb-2 ${hasCover ? "" : "text-[var(--appkit-color-text)]"}`, size: "3xl", mdSize: "4xl", weight: "bold", children: category?.name ?? slug }), category?.description && typeof category.description === "string" && !category.description.startsWith("{") && (_jsx(Text, { color: hasCover ? "inverse" : "muted", className: `max-w-2xl mb-4 ${hasCover ? "/80" : ""}`, size: "base", children: category.description })), _jsxs(Row, { wrap: true, gap: "sm", children: [productCount > 0 && (_jsxs(Span, { layout: "inline-flex", gap: "xs", color: "inverse", size: "xs", weight: "medium", className: hasCover ? "bg-[rgba(255,255,255,0.2)] backdrop-blur-sm" : "bg-primary/10 text-primary-700 dark:text-primary-400", rounded: "full", padding: "pill-sm-tall", children: [productCount.toLocaleString(), " ", productCount === 1 ? "product" : "products"] })), auctionCount > 0 && (_jsxs(Span, { layout: "inline-flex", gap: "xs", color: hasCover ? "inverse" : "warning", surface: hasCover ? undefined : "warning-surface", size: "xs", weight: "medium", className: hasCover ? "bg-[rgba(255,255,255,0.2)] backdrop-blur-sm" : "", rounded: "full", padding: "pill-sm-tall", children: [auctionCount.toLocaleString(), " ", auctionCount === 1 ? "auction" : "auctions"] })), preOrderCount > 0 && (_jsxs(Span, { layout: "inline-flex", gap: "xs", color: hasCover ? "inverse" : "info", surface: hasCover ? undefined : "info-surface", size: "xs", weight: "medium", className: hasCover ? "bg-[rgba(255,255,255,0.2)] backdrop-blur-sm" : "", rounded: "full", padding: "pill-sm-tall", children: [preOrderCount.toLocaleString(), " ", preOrderCount === 1 ? "pre-order" : "pre-orders"] })), storeCount > 0 && (_jsxs(Span, { layout: "inline-flex", gap: "xs", color: hasCover ? "inverse" : "success", surface: hasCover ? undefined : "success-surface", size: "xs", weight: "medium", className: hasCover ? "bg-[rgba(255,255,255,0.2)] backdrop-blur-sm" : "", rounded: "full", padding: "pill-sm-tall", children: [storeCount.toLocaleString(), " ", storeCount === 1 ? "store" : "stores"] }))] })] })] }), _jsx(CategoryHighlightsAndFaqSection, { highlights: category?.highlights, faqs: category?.faqs }), childCategories.length > 0 && (_jsx(Section, { border: "subtle", surface: "default", className: "border-b", children: _jsx(Div, { className: "max-w-7xl mx-auto", padding: "inline", children: _jsx(Div, { layout: "flex", gap: "2", className: `.5 ${__O.xAuto} [scrollbar-width:none]`, padding: "b-2xs", children: childCategories.map((child) => (_jsxs(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(child.slug)),
130
134
  // audit-responsive-wrap-ok: deliberate horizontal-scroll chip row (parent has overflow-x-auto) — each chip staying single-line is the intended design, not hidden content
131
135
  className: "flex-shrink-0 flex items-center gap-[var(--appkit-space-1-5)] rounded-full border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-elevated)] px-[var(--appkit-space-4)] py-[var(--appkit-space-1-5)] text-[length:var(--appkit-text-sm)] font-medium text-[var(--appkit-color-text-muted)] hover:border-primary hover:text-primary transition-colors whitespace-nowrap", children: [child.display?.icon && (_jsx(Span, { className: "leading-none", children: child.display.icon })), child.name, (child.metrics?.productCount ?? 0) > 0 && (_jsx(Span, { size: "xs", color: "muted", children: (child.metrics?.productCount ?? 0).toLocaleString() }))] }, child.id))) }) }) })), _jsx(Section, { padding: "y-lg", children: _jsx(Container, { size: "xl", children: _jsx(CategoryDetailTabs, { categorySlug: slug, categoryId: category?.id, initialProductsData: productsResult ?? undefined, initialBundles: bundlesResult ?? [], initialStores: categoryStores, counts: {
132
136
  products: productCount,
@@ -135,5 +139,5 @@ export async function CategoryDetailPageView({ slug }) {
135
139
  prizeDraws: prizeDrawCount,
136
140
  bundles: bundleCount,
137
141
  stores: storeCount,
138
- } }) }) }), relatedCategories.length > 0 && (_jsx(Section, { border: "subtle", surface: "default", className: "border-t", padding: "y-lg", children: _jsxs(Container, { size: "xl", children: [_jsx(Heading, { level: 2, className: "mb-4", size: "xl", weight: "semibold", children: "Related Categories" }), _jsx(CategoryGrid, { categories: relatedCategories, getHref: (c) => String(ROUTES.PUBLIC.CATEGORY_DETAIL(c.slug)) })] }) }))] }));
142
+ } }) }) }), groupedListings.length > 0 && (_jsx(Section, { padding: "y-lg", children: _jsx(Container, { size: "xl", children: _jsx(GroupedListingsCarousel, { groups: groupedListings }) }) })), relatedCategories.length > 0 && (_jsx(Section, { border: "subtle", surface: "default", className: "border-t", padding: "y-lg", children: _jsxs(Container, { size: "xl", children: [_jsx(Heading, { level: 2, className: "mb-4", size: "xl", weight: "semibold", children: "Related Categories" }), _jsx(CategoryGrid, { categories: relatedCategories, getHref: (c) => String(ROUTES.PUBLIC.CATEGORY_DETAIL(c.slug)) })] }) }))] }));
139
143
  }
@@ -0,0 +1,14 @@
1
+ export interface CategoryHighlightsAndFaqSectionProps {
2
+ highlights?: string[];
3
+ faqs?: {
4
+ question: string;
5
+ answer: string;
6
+ }[];
7
+ }
8
+ /**
9
+ * Shared "why shop here" highlights + FAQ accordion, rendered on both
10
+ * category and brand detail pages — the only editorial content either page
11
+ * has beyond a one-line description (see CategoryDisplay's field list).
12
+ * Renders nothing when both arrays are empty/absent.
13
+ */
14
+ export declare function CategoryHighlightsAndFaqSection({ highlights, faqs }: CategoryHighlightsAndFaqSectionProps): import("react").JSX.Element | null;
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Container, Heading, Li, Section, Span, Stack, Ul } from "../../../ui";
3
+ import { FAQAccordion } from "../../faq/components/FAQAccordion";
4
+ /**
5
+ * Shared "why shop here" highlights + FAQ accordion, rendered on both
6
+ * category and brand detail pages — the only editorial content either page
7
+ * has beyond a one-line description (see CategoryDisplay's field list).
8
+ * Renders nothing when both arrays are empty/absent.
9
+ */
10
+ export function CategoryHighlightsAndFaqSection({ highlights, faqs }) {
11
+ const hasHighlights = Boolean(highlights && highlights.length > 0);
12
+ const hasFaqs = Boolean(faqs && faqs.length > 0);
13
+ if (!hasHighlights && !hasFaqs)
14
+ return null;
15
+ const faqItems = (faqs ?? []).map((f, i) => ({
16
+ id: `faq-${i}`,
17
+ question: f.question,
18
+ answer: { text: f.answer, format: "plain" },
19
+ category: "general",
20
+ }));
21
+ return (_jsx(Section, { padding: "y-lg", border: "subtle", className: "border-t", children: _jsx(Container, { size: "xl", children: _jsxs(Stack, { gap: "xl", children: [hasHighlights && (_jsxs(Stack, { gap: "sm", children: [_jsx(Heading, { level: 2, size: "lg", weight: "semibold", children: "Why shop here" }), _jsx(Ul, { spacing: "comfortable", size: "sm", color: "primary", children: highlights.map((h, i) => (_jsxs(Li, { layout: "flex-start", gap: "2", children: [_jsx(Span, { className: "mt-0.5 flex-shrink-0 text-primary-500", children: "\u2022" }), h] }, i))) })] })), hasFaqs && (_jsxs(Stack, { gap: "sm", children: [_jsx(Heading, { level: 2, size: "lg", weight: "semibold", children: "Frequently Asked Questions" }), _jsx(FAQAccordion, { faqs: faqItems })] }))] }) }) }));
22
+ }
@@ -9,10 +9,6 @@ export interface CategoryProductsViewProps {
9
9
  initialCategory?: CategoryItem;
10
10
  /** Initial SSR child categories */
11
11
  initialChildren?: CategoryItem[];
12
- labels?: {
13
- emptyTitle?: string;
14
- emptyDescription?: string;
15
- };
16
12
  /** Optional UrlTable-compatible state source for shared filter/sort controls */
17
13
  table?: UrlTable;
18
14
  /** Filter/sort preset for admin/seller/public listing behavior */
@@ -46,4 +42,4 @@ export interface CategoryProductsViewProps {
46
42
  isLoading?: boolean;
47
43
  className?: string;
48
44
  }
49
- export declare function CategoryProductsView({ labels: _labels, table, filterVariant, sortValue, onSortChange, renderBreadcrumbs, renderChildCategories, renderFilters, renderActiveFilters, renderSearch, renderSort, renderViewToggle, renderProducts, renderPagination, category, children: childCategories, total, isLoading, className, }: CategoryProductsViewProps): React.JSX.Element;
45
+ export declare function CategoryProductsView({ table, filterVariant, sortValue, onSortChange, renderBreadcrumbs, renderChildCategories, renderFilters, renderActiveFilters, renderSearch, renderSort, renderViewToggle, renderProducts, renderPagination, category, children: childCategories, total, isLoading, className, }: CategoryProductsViewProps): React.JSX.Element;
@@ -4,7 +4,7 @@ import React from "react";
4
4
  import { Div, Heading, Input, SlottedListingView, Stack, Text } from "../../../ui";
5
5
  import { CategoryFilters } from "./CategoryFilters";
6
6
  import { CategorySortSelect } from "./CategorySortSelect";
7
- export function CategoryProductsView({ labels: _labels = {}, table, filterVariant = "public", sortValue, onSortChange, renderBreadcrumbs, renderChildCategories, renderFilters, renderActiveFilters, renderSearch, renderSort, renderViewToggle, renderProducts, renderPagination, category = null, children: childCategories = [], total = 0, isLoading = false, className = "", }) {
7
+ export function CategoryProductsView({ table, filterVariant = "public", sortValue, onSortChange, renderBreadcrumbs, renderChildCategories, renderFilters, renderActiveFilters, renderSearch, renderSort, renderViewToggle, renderProducts, renderPagination, category = null, children: childCategories = [], total = 0, isLoading = false, className = "", }) {
8
8
  const [search, setSearch] = React.useState("");
9
9
  const [sort, setSort] = React.useState("-createdAt");
10
10
  const [viewMode, setViewMode] = React.useState("grid");
@@ -1,12 +1,21 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { Button, Div, Label, Row, Select, SideDrawer } from "../../../ui";
4
- import { useState, useCallback } from "react";
4
+ import { useState, useCallback, useEffect } from "react";
5
+ import { z } from "zod";
5
6
  import { useCategories, useCreateCategory } from "../hooks/useCategorySelector";
6
7
  import { useMessage } from "../../../react";
7
8
  import { flattenCategories } from "../types";
8
9
  import { DrawerFormFooter } from "../../admin/components/DrawerFormFooter";
9
10
  import { CategoryForm } from "./CategoryForm";
11
+ import { useFormShellState, FormShellContext, FormErrorSummary } from "../../../ui/forms";
12
+ // Form-input subset — `categoryFirestoreSchema` (categories schemas) models
13
+ // the full stored document (id, timestamps, computed metrics) which this
14
+ // create-draft never has.
15
+ const categoryDraftSchema = z.object({
16
+ name: z.string().min(1, "Name is required"),
17
+ slug: z.string().optional(),
18
+ });
10
19
  const DEFAULT_LABELS = {
11
20
  selectPlaceholder: "Select category…",
12
21
  addCategory: "+ Add category",
@@ -21,6 +30,11 @@ function CreateCategoryContent({ allCategories, onSuccess, onCancel, labels, sta
21
30
  parentId: null,
22
31
  order: 0,
23
32
  });
33
+ const { shellCtx, validate } = useFormShellState(categoryDraftSchema);
34
+ useEffect(() => {
35
+ validate(draft);
36
+ // eslint-disable-next-line react-hooks/exhaustive-deps
37
+ }, [draft, validate]);
24
38
  const { mutate, isPending: isLoading } = useCreateCategory({
25
39
  onSuccess: (res) => {
26
40
  showSuccess(labels.successCreated);
@@ -33,7 +47,7 @@ function CreateCategoryContent({ allCategories, onSuccess, onCancel, labels, sta
33
47
  return;
34
48
  mutate(draft);
35
49
  }, [draft, mutate]);
36
- return (_jsxs(Div, { className: stackClassName, children: [_jsx(CategoryForm, { category: draft, allCategories: allCategories, onChange: setDraft, labels: labels.form, stackClassName: stackClassName }), _jsx(DrawerFormFooter, { variant: "inline", isLoading: isLoading, onSubmit: handleSave, onCancel: onCancel, isSubmitDisabled: !draft.name })] }));
50
+ return (_jsx(FormShellContext.Provider, { value: shellCtx, children: _jsxs(Div, { className: stackClassName, children: [_jsx(CategoryForm, { category: draft, allCategories: allCategories, onChange: setDraft, labels: labels.form, stackClassName: stackClassName }), _jsx(FormErrorSummary, {}), _jsx(DrawerFormFooter, { variant: "inline", isLoading: isLoading, onSubmit: handleSave, onCancel: onCancel, isSubmitDisabled: !draft.name })] }) }));
37
51
  }
38
52
  export function CategorySelectorCreate({ value, onChange, disabled = false, label, labels = {}, stackClassName = "space-y-4", }) {
39
53
  const [drawerOpen, setDrawerOpen] = useState(false);
@@ -125,8 +125,16 @@ export interface CategoryDocument extends BaseDocument {
125
125
  brandCountry?: string;
126
126
  /** Brand founding year — categoryType==="brand". */
127
127
  brandFounded?: number;
128
- /** Banner image for the brand storefront page — categoryType==="brand". */
129
- brandBannerImage?: string;
128
+ /**
129
+ * Short bullet points — "why shop this category/brand." Category and
130
+ * brand detail pages only; renders nothing when absent/empty.
131
+ */
132
+ highlights?: string[];
133
+ /** A handful of Q&A pairs shown on the category/brand detail page. */
134
+ faqs?: {
135
+ question: string;
136
+ answer: string;
137
+ }[];
130
138
  /**
131
139
  * "special" — admin-curated bundle; writes reverse `partOfBundleIds`
132
140
  * pointers on member products and shows the "Bundled" badge on cards.
@@ -135,6 +143,15 @@ export interface CategoryDocument extends BaseDocument {
135
143
  * Does NOT update `partOfBundleIds`; used as a discovery surface only.
136
144
  */
137
145
  bundleKind?: "special" | "brand";
146
+ /**
147
+ * Which brand this bundle belongs to, for the brand detail page's bundle
148
+ * tab — works for both `bundleKind:"special"` (static) and `"brand"`
149
+ * (dynamic) bundles. Distinct from `bundleQueryRule.filter.brandSlug`,
150
+ * which is a dynamic-rule query *filter* (only meaningful when
151
+ * `bundleQueryRule.type==="dynamic"`) — this field is the bundle's own
152
+ * brand tag regardless of how its members are resolved.
153
+ */
154
+ brandSlug?: string;
138
155
  /** Discounted bundle price in decimal rupees. */
139
156
  bundlePrice?: number;
140
157
  /** Rule resolving the bundle's member products — static list or live query. */
@@ -229,8 +229,19 @@ export declare const categoryFirestoreSchema: z.ZodObject<{
229
229
  brandWebsite: z.ZodOptional<z.ZodString>;
230
230
  brandCountry: z.ZodOptional<z.ZodString>;
231
231
  brandFounded: z.ZodOptional<z.ZodNumber>;
232
- brandBannerImage: z.ZodOptional<z.ZodString>;
232
+ highlights: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
233
+ faqs: z.ZodOptional<z.ZodArray<z.ZodObject<{
234
+ question: z.ZodString;
235
+ answer: z.ZodString;
236
+ }, "strip", z.ZodTypeAny, {
237
+ question: string;
238
+ answer: string;
239
+ }, {
240
+ question: string;
241
+ answer: string;
242
+ }>, "many">>;
233
243
  bundleKind: z.ZodOptional<z.ZodEnum<["special", "brand"]>>;
244
+ brandSlug: z.ZodOptional<z.ZodString>;
234
245
  bundlePrice: z.ZodOptional<z.ZodEffects<z.ZodNumber, number, number>>;
235
246
  bundleQueryRule: z.ZodOptional<z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
236
247
  type: z.ZodLiteral<"static">;
@@ -419,7 +430,12 @@ export declare const categoryFirestoreSchema: z.ZodObject<{
419
430
  name: string;
420
431
  tier: number;
421
432
  }[];
433
+ faqs?: {
434
+ question: string;
435
+ answer: string;
436
+ }[] | undefined;
422
437
  description?: string | undefined;
438
+ brandSlug?: string | undefined;
423
439
  showOnHomepage?: boolean | undefined;
424
440
  categoryType?: "brand" | "category" | "sublisting" | "bundle" | undefined;
425
441
  bundleKind?: "brand" | "special" | undefined;
@@ -442,7 +458,7 @@ export declare const categoryFirestoreSchema: z.ZodObject<{
442
458
  brandWebsite?: string | undefined;
443
459
  brandCountry?: string | undefined;
444
460
  brandFounded?: number | undefined;
445
- brandBannerImage?: string | undefined;
461
+ highlights?: string[] | undefined;
446
462
  bundlePrice?: number | undefined;
447
463
  bundleQueryRule?: {
448
464
  type: "static";
@@ -513,7 +529,12 @@ export declare const categoryFirestoreSchema: z.ZodObject<{
513
529
  name: string;
514
530
  tier: number;
515
531
  }[];
532
+ faqs?: {
533
+ question: string;
534
+ answer: string;
535
+ }[] | undefined;
516
536
  description?: string | undefined;
537
+ brandSlug?: string | undefined;
517
538
  showOnHomepage?: boolean | undefined;
518
539
  categoryType?: "brand" | "category" | "sublisting" | "bundle" | undefined;
519
540
  bundleKind?: "brand" | "special" | undefined;
@@ -536,7 +557,7 @@ export declare const categoryFirestoreSchema: z.ZodObject<{
536
557
  brandWebsite?: string | undefined;
537
558
  brandCountry?: string | undefined;
538
559
  brandFounded?: number | undefined;
539
- brandBannerImage?: string | undefined;
560
+ highlights?: string[] | undefined;
540
561
  bundlePrice?: number | undefined;
541
562
  bundleQueryRule?: {
542
563
  type: "static";
@@ -76,8 +76,10 @@ export const categoryFirestoreSchema = z.object({
76
76
  brandWebsite: z.string().optional(),
77
77
  brandCountry: z.string().optional(),
78
78
  brandFounded: z.number().int().optional(),
79
- brandBannerImage: z.string().optional(),
79
+ highlights: z.array(z.string()).optional(),
80
+ faqs: z.array(z.object({ question: z.string(), answer: z.string() })).optional(),
80
81
  bundleKind: z.enum(["special", "brand"]).optional(),
82
+ brandSlug: z.string().optional(),
81
83
  bundlePrice: rupeesSchema.optional(),
82
84
  bundleQueryRule: bundleQueryRuleSchema.optional(),
83
85
  bundleStockStatus: z.enum(["in_stock", "out_of_stock"]).optional(),
@@ -37,6 +37,13 @@ export interface CategoryItem {
37
37
  brandCountry?: string;
38
38
  /** Brand founded year — only set when categoryType==="brand". */
39
39
  brandFounded?: number;
40
+ /** Short bullet points — "why shop this category/brand." */
41
+ highlights?: string[];
42
+ /** A handful of Q&A pairs shown on the category/brand detail page. */
43
+ faqs?: {
44
+ question: string;
45
+ answer: string;
46
+ }[];
40
47
  name: string;
41
48
  slug: string;
42
49
  description?: string;
@@ -6,9 +6,23 @@
6
6
  * purpose from `checkout-actions.ts`'s third-party shipping consent OTP —
7
7
  * same crypto primitives, separate Firestore namespace and copy.
8
8
  */
9
- /** Sends a checkout-value OTP to the buyer's registered email. Returns masked email so the UI can confirm which inbox to check. */
10
- export declare function sendCheckoutValueOtp(userId: string, userEmail: string): Promise<{
11
- maskedEmail: string;
9
+ export type CheckoutValueOtpChannel = "email" | "whatsapp";
10
+ /**
11
+ * Sends a checkout-value OTP either by email (default) or WhatsApp
12
+ * (opt-in — the buyer must explicitly choose it in the UI). WhatsApp phone
13
+ * is always resolved server-side from the selected shipping address —
14
+ * never trust a client-supplied phone number.
15
+ *
16
+ * If the chosen channel (and, for email, its skip-worthy fallback) is
17
+ * currently circuit-broken or unconfigured, the OTP gate is treated as
18
+ * satisfied (`skipped: true`) rather than blocking checkout — the caller
19
+ * must log this, since it is a security-relevant bypass even though
20
+ * user-authorized by the channel outage.
21
+ */
22
+ export declare function sendCheckoutValueOtp(userId: string, userEmail: string, channel?: CheckoutValueOtpChannel, addressId?: string): Promise<{
23
+ maskedEmail?: string;
24
+ maskedPhone?: string;
25
+ skipped?: boolean;
12
26
  }>;
13
27
  /** Verifies the 6-digit checkout-value OTP and marks the Firestore record verified. */
14
28
  export declare function verifyCheckoutValueOtp(userId: string, code: string): Promise<void>;
@@ -8,18 +8,94 @@
8
8
  */
9
9
  import { timingSafeEqual } from "crypto";
10
10
  import { ValidationError } from "../../../errors";
11
+ import { normalizeError } from "../../../errors/normalize";
11
12
  import { serverLogger } from "../../../monitoring";
12
13
  import { sendEmail } from "../../contact/email";
13
14
  import { getAdminDb } from "../../../providers/db-firebase";
14
15
  import { resolveDate } from "../../../utils";
15
- import { CHECKOUT_VALUE_OTP_EXPIRY_MS, CHECKOUT_VALUE_OTP_MAX_ATTEMPTS, hashOtp, generateOtpCode, checkoutValueOtpRef, enforceCheckoutValueOtpRateLimit, } from "../../auth/checkout-value-otp";
16
- /** Sends a checkout-value OTP to the buyer's registered email. Returns masked email so the UI can confirm which inbox to check. */
17
- export async function sendCheckoutValueOtp(userId, userEmail) {
16
+ import { addressesRepository } from "../../addresses/repository/addresses.repository";
17
+ import { siteSettingsRepository } from "../../admin/repository/site-settings.repository";
18
+ import { sendWhatsAppBusinessMessage } from "../../whatsapp-bot/helpers/whatsapp";
19
+ import { isChannelHealthy, withChannelRetry } from "../../../_internal/server/notifications/channel-health";
20
+ import { CHECKOUT_VALUE_OTP_EXPIRY_MS, CHECKOUT_VALUE_OTP_MAX_ATTEMPTS, hashOtp, generateOtpCode, checkoutValueOtpRef, enforceCheckoutValueOtpRateLimit, buildCheckoutValueOtpMessage, } from "../../auth/checkout-value-otp";
21
+ function maskEmail(userEmail) {
22
+ const [local, domain] = userEmail.split("@");
23
+ return domain
24
+ ? `${local.length <= 2 ? "*".repeat(local.length) : local[0] + "*".repeat(local.length - 2) + local[local.length - 1]}@${domain}`
25
+ : "***";
26
+ }
27
+ /**
28
+ * Sends a checkout-value OTP either by email (default) or WhatsApp
29
+ * (opt-in — the buyer must explicitly choose it in the UI). WhatsApp phone
30
+ * is always resolved server-side from the selected shipping address —
31
+ * never trust a client-supplied phone number.
32
+ *
33
+ * If the chosen channel (and, for email, its skip-worthy fallback) is
34
+ * currently circuit-broken or unconfigured, the OTP gate is treated as
35
+ * satisfied (`skipped: true`) rather than blocking checkout — the caller
36
+ * must log this, since it is a security-relevant bypass even though
37
+ * user-authorized by the channel outage.
38
+ */
39
+ export async function sendCheckoutValueOtp(userId, userEmail, channel = "email", addressId) {
18
40
  const db = getAdminDb();
19
41
  await enforceCheckoutValueOtpRateLimit(db, userId);
20
42
  const code = generateOtpCode();
21
43
  const codeHash = hashOtp(code);
22
44
  const expiresAt = new Date(Date.now() + CHECKOUT_VALUE_OTP_EXPIRY_MS);
45
+ const siteName = process.env.NEXT_PUBLIC_SITE_NAME || "LetItRip";
46
+ if (channel === "whatsapp") {
47
+ if (!addressId) {
48
+ throw new ValidationError("Select a delivery address before sending the code via WhatsApp.");
49
+ }
50
+ const settings = await siteSettingsRepository.getSingleton().catch(() => null);
51
+ const creds = settings?.credentials ?? {};
52
+ const whatsappOtpEnabled = settings?.notificationChannels?.whatsapp?.otpEnabled === true;
53
+ const phoneNumberId = creds.whatsappPhoneNumberId?.trim() ?? "";
54
+ const accessToken = creds.whatsappCloudApiToken?.trim() ?? "";
55
+ const credsReady = phoneNumberId && accessToken && !phoneNumberId.includes("PLACEHOLDER") && !accessToken.includes("PLACEHOLDER");
56
+ if (!whatsappOtpEnabled || !credsReady) {
57
+ throw new ValidationError("WhatsApp verification isn't available right now — send the code by email instead.");
58
+ }
59
+ const address = await addressesRepository.findById(addressId);
60
+ const phone = address?.phone?.trim();
61
+ if (!phone) {
62
+ throw new ValidationError("The selected address has no phone number on file — send the code by email instead.");
63
+ }
64
+ if (!(await isChannelHealthy("whatsapp"))) {
65
+ serverLogger.warn("sendCheckoutValueOtp: WhatsApp channel unhealthy — skipping OTP gate", { uid: userId, channel });
66
+ return { skipped: true };
67
+ }
68
+ await checkoutValueOtpRef(db, userId).set({
69
+ codeHash,
70
+ expiresAt,
71
+ attempts: 0,
72
+ verified: false,
73
+ createdAt: new Date(),
74
+ });
75
+ const message = buildCheckoutValueOtpMessage(code, siteName);
76
+ try {
77
+ const sent = await withChannelRetry("whatsapp", async () => {
78
+ const ok = await sendWhatsAppBusinessMessage({ toPhone: phone, message, phoneNumberId, accessToken });
79
+ if (!ok)
80
+ throw new Error("WhatsApp Cloud API returned a non-OK response");
81
+ return ok;
82
+ });
83
+ if (!sent)
84
+ throw new Error("WhatsApp send failed");
85
+ }
86
+ catch (err) {
87
+ void normalizeError(err);
88
+ serverLogger.error("Failed to send checkout value OTP via WhatsApp", { uid: userId, err });
89
+ throw new ValidationError("We couldn't send the verification code via WhatsApp — please try again, or send it by email instead.");
90
+ }
91
+ const maskedPhone = phone.length > 4 ? `${"*".repeat(phone.length - 4)}${phone.slice(-4)}` : "***";
92
+ serverLogger.info(`Checkout value OTP sent via WhatsApp: uid=${userId}`);
93
+ return { maskedPhone };
94
+ }
95
+ if (!(await isChannelHealthy("email"))) {
96
+ serverLogger.warn("sendCheckoutValueOtp: email channel unhealthy — skipping OTP gate", { uid: userId, channel });
97
+ return { skipped: true };
98
+ }
23
99
  await checkoutValueOtpRef(db, userId).set({
24
100
  codeHash,
25
101
  expiresAt,
@@ -27,24 +103,27 @@ export async function sendCheckoutValueOtp(userId, userEmail) {
27
103
  verified: false,
28
104
  createdAt: new Date(),
29
105
  });
30
- const siteName = process.env.NEXT_PUBLIC_SITE_NAME || "LetItRip";
31
- const [local, domain] = userEmail.split("@");
32
- const maskedEmail = domain
33
- ? `${local.length <= 2 ? "*".repeat(local.length) : local[0] + "*".repeat(local.length - 2) + local[local.length - 1]}@${domain}`
34
- : "***";
35
- const { error } = await sendEmail({
36
- to: userEmail,
37
- subject: `${siteName}: Verify your order`,
38
- html: `
39
- <div style="font-family:sans-serif;max-width:480px;margin:0 auto;padding:24px">
40
- <h2 style="margin-bottom:8px">Verify Your Order</h2>
41
- <p style="color:#555">Your cart total requires verification before checkout. Enter this code to continue:</p>
42
- <div style="font-size:36px;font-weight:bold;letter-spacing:8px;text-align:center;margin:24px 0;padding:16px;background:#f3f4f6;border-radius:8px">${code}</div>
43
- <p style="color:#888;font-size:12px">This code expires in 10 minutes. If you did not request this, please ignore this email.</p>
44
- </div>
45
- `,
46
- });
47
- if (error) {
106
+ const maskedEmail = maskEmail(userEmail);
107
+ try {
108
+ await withChannelRetry("email", async () => {
109
+ const { error } = await sendEmail({
110
+ to: userEmail,
111
+ subject: `${siteName}: Verify your order`,
112
+ html: `
113
+ <div style="font-family:sans-serif;max-width:480px;margin:0 auto;padding:24px">
114
+ <h2 style="margin-bottom:8px">Verify Your Order</h2>
115
+ <p style="color:#555">Your cart total requires verification before checkout. Enter this code to continue:</p>
116
+ <div style="font-size:36px;font-weight:bold;letter-spacing:8px;text-align:center;margin:24px 0;padding:16px;background:#f3f4f6;border-radius:8px">${code}</div>
117
+ <p style="color:#888;font-size:12px">This code expires in 10 minutes. If you did not request this, please ignore this email.</p>
118
+ </div>
119
+ `,
120
+ });
121
+ if (error)
122
+ throw new Error(String(error));
123
+ });
124
+ }
125
+ catch (err) {
126
+ void normalizeError(err);
48
127
  // Root-caused 2026-08-20: this used to be fire-and-forget — the
49
128
  // Firestore OTP doc was written and the caller always got back a
50
129
  // success response ("code sent") regardless of whether the email
@@ -52,7 +131,7 @@ export async function sendCheckoutValueOtp(userId, userEmail) {
52
131
  // unverified sending domain, outage) silently stranded the buyer
53
132
  // with a checkout they could never complete, since the OTP gate
54
133
  // gave no indication anything had gone wrong.
55
- serverLogger.error("Failed to send checkout value OTP email", { uid: userId, error });
134
+ serverLogger.error("Failed to send checkout value OTP email", { uid: userId, err });
56
135
  throw new ValidationError("We couldn't send the verification code — please try again in a moment, or contact support if this keeps happening.");
57
136
  }
58
137
  serverLogger.info(`Checkout value OTP sent: uid=${userId}`);
@@ -0,0 +1,12 @@
1
+ import React from "react";
2
+ import type { startClassifiedConversationAction } from "../../../_internal/server/features/classified/actions";
3
+ export interface ClassifiedContactSellerPanelProps {
4
+ productId: string;
5
+ onContactSeller: typeof startClassifiedConversationAction;
6
+ }
7
+ /**
8
+ * The only purchase-path CTA on a classified listing — no cart, no checkout.
9
+ * Extracted from the old ClassifiedDetailView so the richer, full-parity
10
+ * ClassifiedDetailPageView can slot this into a `renderBuyBar` prop.
11
+ */
12
+ export declare function ClassifiedContactSellerPanel({ productId, onContactSeller }: ClassifiedContactSellerPanelProps): React.JSX.Element;
@@ -0,0 +1,49 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { normalizeError } from "../../../errors/normalize";
4
+ import { useState } from "react";
5
+ import Link from "next/link";
6
+ import { Button, Div, Stack, Text } from "../../../ui";
7
+ import { ROUTES } from "../../../next/routing/route-map";
8
+ const __P = {
9
+ p4: "p-[var(--appkit-space-4)]",
10
+ };
11
+ /**
12
+ * The only purchase-path CTA on a classified listing — no cart, no checkout.
13
+ * Extracted from the old ClassifiedDetailView so the richer, full-parity
14
+ * ClassifiedDetailPageView can slot this into a `renderBuyBar` prop.
15
+ */
16
+ export function ClassifiedContactSellerPanel({ productId, onContactSeller }) {
17
+ const [pending, setPending] = useState(false);
18
+ const [conversation, setConversation] = useState(null);
19
+ const [error, setError] = useState(null);
20
+ async function handleContactSeller() {
21
+ setPending(true);
22
+ setError(null);
23
+ try {
24
+ const result = await onContactSeller({ productId });
25
+ if (result && typeof result === "object" && "ok" in result) {
26
+ if (result.ok) {
27
+ setConversation(result.data);
28
+ }
29
+ else {
30
+ setError(result.error);
31
+ }
32
+ }
33
+ else {
34
+ setConversation(result);
35
+ }
36
+ }
37
+ catch (e) {
38
+ void normalizeError(e);
39
+ setError(e instanceof Error ? e.message : "Something went wrong");
40
+ }
41
+ finally {
42
+ setPending(false);
43
+ }
44
+ }
45
+ if (conversation) {
46
+ return (_jsxs(Div, { className: `border border-border bg-muted/40 ${__P.p4}`, rounded: "lg", children: [_jsx(Text, { className: "mb-2", weight: "medium", children: "Conversation started!" }), _jsx(Link, { href: ROUTES.USER.MESSAGES, className: "text-primary underline underline-offset-2", children: "Go to your messages \u2192" })] }));
47
+ }
48
+ return (_jsxs(Stack, { gap: "sm", children: [error && (_jsx(Text, { className: "text-destructive", size: "sm", children: error })), _jsx(Button, { type: "button", variant: "primary", size: "lg", isLoading: pending, disabled: pending, onClick: handleContactSeller, className: "w-full", children: "Contact Seller" })] }));
49
+ }
@@ -0,0 +1,7 @@
1
+ import type { ProductDocument } from "../../products/schemas/firestore";
2
+ export interface ClassifiedDetailPageViewProps {
3
+ slug: string;
4
+ /** Pre-fetched product document — dedupes with generateMetadata() via React.cache(). */
5
+ initialProduct?: ProductDocument | null;
6
+ }
7
+ export declare function ClassifiedDetailPageView({ slug, initialProduct }: ClassifiedDetailPageViewProps): Promise<import("react").JSX.Element>;