@mohasinac/appkit 2.7.59 → 2.8.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 (311) hide show
  1. package/dist/_internal/client/features/filters/filter-load-options.d.ts +4 -5
  2. package/dist/_internal/server/features/auctions/og.js +8 -32
  3. package/dist/_internal/server/features/blog/og.js +10 -49
  4. package/dist/_internal/server/features/checkout/actions.js +6 -0
  5. package/dist/_internal/server/features/classified/og.js +9 -51
  6. package/dist/_internal/server/features/digital-code/actions.d.ts +11 -0
  7. package/dist/_internal/server/features/digital-code/actions.js +30 -0
  8. package/dist/_internal/server/features/digital-code/index.d.ts +1 -0
  9. package/dist/_internal/server/features/digital-code/index.js +1 -0
  10. package/dist/_internal/server/features/digital-code/og.js +9 -51
  11. package/dist/_internal/server/features/events/og.js +10 -49
  12. package/dist/_internal/server/features/item-requests/data.d.ts +17 -0
  13. package/dist/_internal/server/features/item-requests/data.js +20 -0
  14. package/dist/_internal/server/features/item-requests/index.d.ts +2 -0
  15. package/dist/_internal/server/features/item-requests/index.js +2 -0
  16. package/dist/_internal/server/features/item-requests/og.d.ts +40 -0
  17. package/dist/_internal/server/features/item-requests/og.js +136 -0
  18. package/dist/_internal/server/features/live/actions.d.ts +5 -0
  19. package/dist/_internal/server/features/live/actions.js +24 -0
  20. package/dist/_internal/server/features/live/index.d.ts +1 -0
  21. package/dist/_internal/server/features/live/index.js +1 -0
  22. package/dist/_internal/server/features/live/og.js +9 -51
  23. package/dist/_internal/server/features/media/contextGuards.js +19 -8
  24. package/dist/_internal/server/features/pre-orders/og.js +8 -32
  25. package/dist/_internal/server/features/prize-draws/data.d.ts +17 -0
  26. package/dist/_internal/server/features/prize-draws/data.js +20 -0
  27. package/dist/_internal/server/features/prize-draws/index.d.ts +2 -0
  28. package/dist/_internal/server/features/prize-draws/index.js +2 -0
  29. package/dist/_internal/server/features/prize-draws/og.d.ts +30 -0
  30. package/dist/_internal/server/features/prize-draws/og.js +50 -0
  31. package/dist/_internal/server/features/products/og.js +8 -33
  32. package/dist/_internal/server/features/seo/og-layout.d.ts +42 -0
  33. package/dist/_internal/server/features/seo/og-layout.js +69 -0
  34. package/dist/_internal/server/features/stores/og.js +8 -41
  35. package/dist/_internal/server/features/sublisting-categories/og.js +11 -42
  36. package/dist/client.d.ts +10 -6
  37. package/dist/client.js +7 -3
  38. package/dist/constants/index.d.ts +4 -0
  39. package/dist/constants/index.js +2 -0
  40. package/dist/constants/notification-types.d.ts +20 -0
  41. package/dist/constants/notification-types.js +37 -0
  42. package/dist/constants/pagination-presets.d.ts +39 -0
  43. package/dist/constants/pagination-presets.js +38 -0
  44. package/dist/errors/messages.d.ts +0 -4
  45. package/dist/errors/messages.js +0 -4
  46. package/dist/features/account/components/UserOffersPanel.js +1 -1
  47. package/dist/features/account/components/UserSupportView.d.ts +1 -2
  48. package/dist/features/account/components/UserSupportView.js +9 -1
  49. package/dist/features/admin/actions/admin-actions.js +16 -1
  50. package/dist/features/admin/components/AdminAllEventEntriesView.d.ts +2 -3
  51. package/dist/features/admin/components/AdminAllEventEntriesView.js +50 -83
  52. package/dist/features/admin/components/AdminBidsView.d.ts +2 -3
  53. package/dist/features/admin/components/AdminBidsView.js +64 -98
  54. package/dist/features/admin/components/AdminBlogView.d.ts +3 -7
  55. package/dist/features/admin/components/AdminBlogView.js +53 -83
  56. package/dist/features/admin/components/AdminBrandsView.d.ts +2 -3
  57. package/dist/features/admin/components/AdminBrandsView.js +84 -83
  58. package/dist/features/admin/components/AdminBundlesView.js +82 -125
  59. package/dist/features/admin/components/AdminCarouselView.d.ts +2 -2
  60. package/dist/features/admin/components/AdminCarouselView.js +17 -52
  61. package/dist/features/admin/components/AdminCartsView.d.ts +2 -3
  62. package/dist/features/admin/components/AdminCartsView.js +39 -88
  63. package/dist/features/admin/components/AdminCategoriesView.d.ts +3 -3
  64. package/dist/features/admin/components/AdminCategoriesView.js +98 -92
  65. package/dist/features/admin/components/AdminCategoryEditorView.js +2 -2
  66. package/dist/features/admin/components/AdminClassifiedView.d.ts +3 -0
  67. package/dist/features/admin/components/AdminClassifiedView.js +44 -0
  68. package/dist/features/admin/components/AdminContactView.d.ts +2 -2
  69. package/dist/features/admin/components/AdminContactView.js +104 -111
  70. package/dist/features/admin/components/AdminCouponsView.d.ts +3 -6
  71. package/dist/features/admin/components/AdminCouponsView.js +66 -86
  72. package/dist/features/admin/components/AdminDigitalCodesView.d.ts +3 -0
  73. package/dist/features/admin/components/AdminDigitalCodesView.js +51 -0
  74. package/dist/features/admin/components/AdminFaqsView.d.ts +4 -4
  75. package/dist/features/admin/components/AdminFaqsView.js +77 -33
  76. package/dist/features/admin/components/AdminFeaturesView.d.ts +2 -3
  77. package/dist/features/admin/components/AdminFeaturesView.js +57 -70
  78. package/dist/features/admin/components/AdminGroupedListingsView.d.ts +3 -0
  79. package/dist/features/admin/components/AdminGroupedListingsView.js +43 -0
  80. package/dist/features/admin/components/AdminHistoryView.d.ts +2 -3
  81. package/dist/features/admin/components/AdminHistoryView.js +35 -52
  82. package/dist/features/admin/components/AdminListingScaffold.d.ts +2 -2
  83. package/dist/features/admin/components/AdminListingScaffold.js +3 -3
  84. package/dist/features/admin/components/AdminLiveView.d.ts +3 -0
  85. package/dist/features/admin/components/AdminLiveView.js +50 -0
  86. package/dist/features/admin/components/AdminNewsletterView.d.ts +2 -2
  87. package/dist/features/admin/components/AdminNewsletterView.js +67 -97
  88. package/dist/features/admin/components/AdminNotificationsView.d.ts +2 -3
  89. package/dist/features/admin/components/AdminNotificationsView.js +67 -93
  90. package/dist/features/admin/components/AdminOrderEditorView.js +10 -10
  91. package/dist/features/admin/components/AdminOrdersView.d.ts +2 -3
  92. package/dist/features/admin/components/AdminOrdersView.js +93 -107
  93. package/dist/features/admin/components/AdminPayoutsView.d.ts +2 -3
  94. package/dist/features/admin/components/AdminPayoutsView.js +51 -91
  95. package/dist/features/admin/components/AdminPrizeDrawsView.d.ts +2 -3
  96. package/dist/features/admin/components/AdminPrizeDrawsView.js +39 -76
  97. package/dist/features/admin/components/AdminProductEditorView.js +3 -3
  98. package/dist/features/admin/components/AdminProductsView.d.ts +4 -4
  99. package/dist/features/admin/components/AdminProductsView.js +167 -163
  100. package/dist/features/admin/components/AdminReturnRequestsView.d.ts +1 -1
  101. package/dist/features/admin/components/AdminReturnRequestsView.js +64 -66
  102. package/dist/features/admin/components/AdminReviewsView.d.ts +3 -7
  103. package/dist/features/admin/components/AdminReviewsView.js +94 -110
  104. package/dist/features/admin/components/AdminScammersView.d.ts +2 -3
  105. package/dist/features/admin/components/AdminScammersView.js +53 -97
  106. package/dist/features/admin/components/AdminSectionsView.js +1 -1
  107. package/dist/features/admin/components/AdminSessionsView.d.ts +2 -3
  108. package/dist/features/admin/components/AdminSessionsView.js +62 -89
  109. package/dist/features/admin/components/AdminStoreAddressesView.d.ts +1 -1
  110. package/dist/features/admin/components/AdminStoreAddressesView.js +39 -53
  111. package/dist/features/admin/components/AdminStoreEditorView.js +21 -8
  112. package/dist/features/admin/components/AdminStoresView.d.ts +2 -3
  113. package/dist/features/admin/components/AdminStoresView.js +67 -99
  114. package/dist/features/admin/components/AdminSublistingCategoriesView.d.ts +1 -1
  115. package/dist/features/admin/components/AdminSublistingCategoriesView.js +28 -44
  116. package/dist/features/admin/components/AdminSupportTicketDetailView.d.ts +10 -1
  117. package/dist/features/admin/components/AdminSupportTicketDetailView.js +191 -5
  118. package/dist/features/admin/components/AdminSupportTicketsView.d.ts +2 -3
  119. package/dist/features/admin/components/AdminSupportTicketsView.js +65 -96
  120. package/dist/features/admin/components/AdminTeamView.d.ts +2 -2
  121. package/dist/features/admin/components/AdminTeamView.js +40 -74
  122. package/dist/features/admin/components/AdminUserEditorView.d.ts +11 -1
  123. package/dist/features/admin/components/AdminUserEditorView.js +80 -6
  124. package/dist/features/admin/components/AdminUsersView.d.ts +2 -3
  125. package/dist/features/admin/components/AdminUsersView.js +108 -100
  126. package/dist/features/admin/components/AdminViewCards.d.ts +1 -1
  127. package/dist/features/admin/components/AdminWishlistsView.d.ts +2 -3
  128. package/dist/features/admin/components/AdminWishlistsView.js +36 -62
  129. package/dist/features/admin/components/DataListingView.d.ts +122 -0
  130. package/dist/features/admin/components/DataListingView.js +66 -0
  131. package/dist/features/admin/components/index.d.ts +10 -4
  132. package/dist/features/admin/components/index.js +6 -2
  133. package/dist/features/admin/constants/filter-tabs.d.ts +23 -17
  134. package/dist/features/admin/constants/filter-tabs.js +21 -17
  135. package/dist/features/admin/hooks/useAdminListing.d.ts +1 -0
  136. package/dist/features/admin/hooks/useAdminListing.js +1 -1
  137. package/dist/features/admin/schemas/firestore.js +6 -7
  138. package/dist/features/auctions/server.d.ts +0 -1
  139. package/dist/features/auctions/server.js +0 -1
  140. package/dist/features/auth/actions/realtime-token-actions.js +1 -1
  141. package/dist/features/auth/repository/user.repository.js +1 -1
  142. package/dist/features/cart/repository/cart.repository.d.ts +4 -1
  143. package/dist/features/cart/repository/cart.repository.js +12 -0
  144. package/dist/features/checkout/hooks/useCheckoutApi.d.ts +0 -2
  145. package/dist/features/checkout/index.d.ts +1 -1
  146. package/dist/features/events/components/AdminEventsView.d.ts +3 -3
  147. package/dist/features/events/components/AdminEventsView.js +50 -86
  148. package/dist/features/events/components/EventOfferCard.d.ts +19 -0
  149. package/dist/features/events/components/EventOfferCard.js +29 -0
  150. package/dist/features/events/components/EventRaffleEntryForm.d.ts +25 -0
  151. package/dist/features/events/components/EventRaffleEntryForm.js +37 -0
  152. package/dist/features/events/components/EventRafflesSection.d.ts +1 -4
  153. package/dist/features/events/components/EventRafflesSection.js +17 -6
  154. package/dist/features/events/components/EventSaleBanner.d.ts +21 -0
  155. package/dist/features/events/components/EventSaleBanner.js +18 -0
  156. package/dist/features/events/components/index.d.ts +6 -0
  157. package/dist/features/events/components/index.js +4 -0
  158. package/dist/features/events/repository/event-entry.repository.d.ts +5 -0
  159. package/dist/features/events/repository/event-entry.repository.js +7 -0
  160. package/dist/features/filters/AsyncFacetSection.d.ts +1 -1
  161. package/dist/features/homepage/components/FAQSection.d.ts +0 -5
  162. package/dist/features/homepage/lib/live-stats.js +1 -1
  163. package/dist/features/homepage/schemas/firestore.d.ts +0 -2
  164. package/dist/features/layout/index.d.ts +0 -2
  165. package/dist/features/layout/index.js +0 -1
  166. package/dist/features/pre-orders/server.d.ts +0 -1
  167. package/dist/features/pre-orders/server.js +0 -1
  168. package/dist/features/products/components/GroupSettingsPanel.js +2 -2
  169. package/dist/features/products/components/PrizeDrawItemsEditor.js +2 -2
  170. package/dist/features/products/components/PrizeDrawsSection.d.ts +1 -4
  171. package/dist/features/products/components/PrizeDrawsSection.js +17 -6
  172. package/dist/features/products/components/PrizeRevealModal.js +1 -1
  173. package/dist/features/products/components/ProductCardMetadataSection.d.ts +11 -0
  174. package/dist/features/products/components/ProductCardMetadataSection.js +25 -0
  175. package/dist/features/products/components/ProductDetailPageView.js +3 -1
  176. package/dist/features/products/components/ProductFeaturesSelector.js +1 -1
  177. package/dist/features/products/components/ProductGradingTab.d.ts +13 -0
  178. package/dist/features/products/components/ProductGradingTab.js +25 -0
  179. package/dist/features/products/components/ProductGrid.js +14 -2
  180. package/dist/features/products/components/ProductTabsShell.d.ts +5 -1
  181. package/dist/features/products/components/ProductTabsShell.js +6 -1
  182. package/dist/features/products/components/index.d.ts +4 -0
  183. package/dist/features/products/components/index.js +3 -0
  184. package/dist/features/products/constants/action-defs.d.ts +5 -0
  185. package/dist/features/products/constants/action-defs.js +52 -32
  186. package/dist/features/products/constants/sieve.d.ts +24 -4
  187. package/dist/features/products/constants/sieve.js +20 -11
  188. package/dist/features/products/schemas/firestore.d.ts +17 -0
  189. package/dist/features/products/schemas/product-features.validators.d.ts +2 -2
  190. package/dist/features/products/schemas/product-templates.d.ts +2 -4
  191. package/dist/features/products/types/index.d.ts +4 -0
  192. package/dist/features/promotions/server.d.ts +0 -1
  193. package/dist/features/promotions/server.js +0 -1
  194. package/dist/features/search/api/route.js +44 -1
  195. package/dist/features/search/components/Search.js +2 -0
  196. package/dist/features/search/hooks/useNavSuggestions.d.ts +5 -1
  197. package/dist/features/search/hooks/useNavSuggestions.js +31 -4
  198. package/dist/features/seller/components/BrandInlineSelect.js +2 -2
  199. package/dist/features/seller/components/CategoryInlineSelect.js +2 -2
  200. package/dist/features/seller/components/SellerAddressesView.js +1 -1
  201. package/dist/features/seller/components/SellerAuctionsView.d.ts +3 -3
  202. package/dist/features/seller/components/SellerAuctionsView.js +60 -90
  203. package/dist/features/seller/components/SellerBidsView.js +1 -1
  204. package/dist/features/seller/components/SellerBundlesView.js +64 -89
  205. package/dist/features/seller/components/SellerClassifiedView.js +67 -90
  206. package/dist/features/seller/components/SellerCouponEditorView.js +1 -1
  207. package/dist/features/seller/components/SellerCouponsView.d.ts +2 -2
  208. package/dist/features/seller/components/SellerCouponsView.js +45 -84
  209. package/dist/features/seller/components/SellerDigitalCodesView.js +63 -88
  210. package/dist/features/seller/components/SellerGroupedListingsView.js +33 -49
  211. package/dist/features/seller/components/SellerLiveView.js +63 -84
  212. package/dist/features/seller/components/SellerOffersPanel.js +1 -1
  213. package/dist/features/seller/components/SellerOffersView.d.ts +2 -2
  214. package/dist/features/seller/components/SellerOffersView.js +37 -69
  215. package/dist/features/seller/components/SellerOrdersView.d.ts +2 -2
  216. package/dist/features/seller/components/SellerOrdersView.js +4 -4
  217. package/dist/features/seller/components/SellerPayoutMethodsView.js +1 -1
  218. package/dist/features/seller/components/SellerPayoutsView.d.ts +2 -2
  219. package/dist/features/seller/components/SellerPayoutsView.js +34 -68
  220. package/dist/features/seller/components/SellerPreOrdersView.d.ts +2 -2
  221. package/dist/features/seller/components/SellerPreOrdersView.js +49 -82
  222. package/dist/features/seller/components/SellerPrizeDrawsView.d.ts +2 -2
  223. package/dist/features/seller/components/SellerPrizeDrawsView.js +49 -82
  224. package/dist/features/seller/components/SellerProductShell.d.ts +1 -1
  225. package/dist/features/seller/components/SellerProductsView.d.ts +2 -2
  226. package/dist/features/seller/components/SellerProductsView.js +15 -10
  227. package/dist/features/seller/components/SellerShippingConfigsView.js +1 -1
  228. package/dist/features/seller/components/SellerSidebar.d.ts +0 -4
  229. package/dist/features/seller/components/SellerSidebar.js +0 -2
  230. package/dist/features/seller/components/SellerStoreCategoriesView.js +1 -1
  231. package/dist/features/seller/components/SellerTemplatesView.js +2 -2
  232. package/dist/features/seller/components/SellersListView.d.ts +1 -2
  233. package/dist/features/seller/components/analytics/SellerAnalyticsStats.d.ts +5 -0
  234. package/dist/features/seller/components/analytics/SellerAnalyticsStats.js +2 -8
  235. package/dist/features/seller/components/index.d.ts +0 -3
  236. package/dist/features/seller/components/index.js +0 -2
  237. package/dist/features/seller/server.d.ts +0 -1
  238. package/dist/features/seller/server.js +0 -1
  239. package/dist/features/shell/FormShell.d.ts +1 -1
  240. package/dist/features/shell/FormShell.js +4 -1
  241. package/dist/features/shell/field-groups/ImageFieldGroup.d.ts +18 -0
  242. package/dist/features/shell/field-groups/ImageFieldGroup.js +15 -0
  243. package/dist/features/shell/field-groups/SeoFieldGroup.d.ts +22 -0
  244. package/dist/features/shell/field-groups/SeoFieldGroup.js +16 -0
  245. package/dist/features/shell/field-groups/StatusFieldGroup.d.ts +35 -0
  246. package/dist/features/shell/field-groups/StatusFieldGroup.js +16 -0
  247. package/dist/features/shell/field-groups/TitleDescriptionGroup.d.ts +40 -0
  248. package/dist/features/shell/field-groups/TitleDescriptionGroup.js +16 -0
  249. package/dist/features/shell/field-groups/index.d.ts +13 -0
  250. package/dist/features/shell/field-groups/index.js +9 -0
  251. package/dist/features/shell/index.d.ts +2 -0
  252. package/dist/features/shell/index.js +1 -0
  253. package/dist/features/stores/components/StoreCapabilitiesGuideView.d.ts +1 -2
  254. package/dist/features/stores/components/StoreFinanceGuideView.d.ts +1 -2
  255. package/dist/features/stores/components/StoreHeader.js +2 -1
  256. package/dist/features/stores/components/StoreListingsGuideView.d.ts +1 -2
  257. package/dist/features/stores/components/StoreOrdersGuideView.d.ts +1 -2
  258. package/dist/features/stores/components/StoreScopedSearch.d.ts +16 -0
  259. package/dist/features/stores/components/StoreScopedSearch.js +27 -0
  260. package/dist/features/stores/components/StoreSettingsGuideView.d.ts +1 -2
  261. package/dist/features/stores/server.d.ts +0 -1
  262. package/dist/features/stores/server.js +0 -1
  263. package/dist/features/support/schemas/firestore.d.ts +22 -1
  264. package/dist/features/support/schemas/firestore.js +10 -0
  265. package/dist/features/wishlist/server.d.ts +0 -1
  266. package/dist/features/wishlist/server.js +0 -1
  267. package/dist/index.d.ts +9 -27
  268. package/dist/index.js +14 -50
  269. package/dist/next/routing/route-map.d.ts +8 -0
  270. package/dist/next/routing/route-map.js +4 -0
  271. package/dist/react/hooks/useListingTypeFlags.d.ts +32 -0
  272. package/dist/react/hooks/useListingTypeFlags.js +19 -0
  273. package/dist/security/index.d.ts +1 -1
  274. package/dist/security/index.js +1 -1
  275. package/dist/security/pii-redact.d.ts +8 -0
  276. package/dist/security/pii-redact.js +10 -1
  277. package/dist/seed/grouped-listings-seed-data.d.ts +4 -0
  278. package/dist/seed/products-preorders-seed-data.d.ts +4 -0
  279. package/dist/seed/products-prize-draws-seed-data.js +3 -0
  280. package/dist/seed/site-settings-seed-data.js +5 -5
  281. package/dist/seed/sub-listings-seed-data.d.ts +4 -0
  282. package/dist/server.d.ts +2 -0
  283. package/dist/server.js +4 -0
  284. package/dist/styles.css +54 -395
  285. package/dist/tailwind-utilities.css +1 -1
  286. package/dist/ui/components/BaseListingCard.d.ts +10 -0
  287. package/dist/ui/components/BaseListingCard.js +17 -1
  288. package/dist/ui/components/DetailPageGallery.d.ts +32 -0
  289. package/dist/ui/components/DetailPageGallery.js +47 -0
  290. package/dist/ui/components/DetailPageHero.d.ts +30 -0
  291. package/dist/ui/components/DetailPageHero.js +22 -0
  292. package/dist/ui/components/DetailPageTabs.d.ts +34 -0
  293. package/dist/ui/components/DetailPageTabs.js +38 -0
  294. package/dist/ui/components/HorizontalScroller.style.css +15 -2
  295. package/dist/ui/components/ListingLayout.d.ts +11 -2
  296. package/dist/ui/components/ListingLayout.js +12 -6
  297. package/dist/ui/components/PaginatedSelect.d.ts +66 -0
  298. package/dist/ui/components/PaginatedSelect.js +201 -0
  299. package/dist/ui/components/PaginatedSelect.style.css +254 -0
  300. package/dist/ui/components/Semantic.d.ts +0 -4
  301. package/dist/ui/components/Semantic.js +0 -2
  302. package/dist/ui/components/SettingsSection.d.ts +47 -0
  303. package/dist/ui/components/SettingsSection.js +38 -0
  304. package/dist/ui/components/index.style.css +1 -4
  305. package/dist/ui/index.d.ts +12 -14
  306. package/dist/ui/index.js +6 -7
  307. package/dist/utils/id-generators.d.ts +1 -18
  308. package/dist/utils/id-generators.js +51 -18
  309. package/dist/validation/schemas.d.ts +25 -0
  310. package/dist/validation/schemas.js +28 -0
  311. package/package.json +1 -1
@@ -88,7 +88,10 @@ export declare const ADMIN_USER_STATUS_TABS: readonly [{
88
88
  readonly id: "Disabled";
89
89
  readonly label: "Disabled";
90
90
  }];
91
- /** Admin > Users — role filter chip set. */
91
+ /** Admin > Users — role filter chip set. IDs match the canonical UserRole
92
+ * union ("user" | "seller" | "moderator" | "employee" | "admin") and the
93
+ * Firestore `users/{uid}.role` field. The label "Buyer" maps to id "user"
94
+ * per SB-UNI-E. Previously sent "buyer" which silently returned 0 rows. */
92
95
  export declare const ADMIN_USER_ROLE_TABS: readonly [{
93
96
  readonly id: "All";
94
97
  readonly label: "All";
@@ -99,11 +102,14 @@ export declare const ADMIN_USER_ROLE_TABS: readonly [{
99
102
  readonly id: "seller";
100
103
  readonly label: "Seller";
101
104
  }, {
102
- readonly id: "buyer";
105
+ readonly id: "user";
103
106
  readonly label: "Buyer";
104
107
  }, {
105
108
  readonly id: "moderator";
106
109
  readonly label: "Moderator";
110
+ }, {
111
+ readonly id: "employee";
112
+ readonly label: "Employee";
107
113
  }];
108
114
  /** Admin > Stores — seller-onboarding state filter chip set. */
109
115
  export declare const ADMIN_STORE_STATUS_TABS: readonly [{
@@ -122,49 +128,49 @@ export declare const ADMIN_STORE_STATUS_TABS: readonly [{
122
128
  readonly id: "rejected";
123
129
  readonly label: "Rejected";
124
130
  }];
125
- /** Admin > Payouts — payout state filter chip set. Uppercase IDs match the
126
- * `PayoutDocument.status` enum on the server. */
131
+ /** Admin > Payouts — payout state filter chip set. Lowercase IDs match
132
+ * `PayoutStatusValues` and the actual Firestore document `status` field. */
127
133
  export declare const ADMIN_PAYOUT_STATUS_TABS: readonly [{
128
134
  readonly id: "All";
129
135
  readonly label: "All";
130
136
  }, {
131
- readonly id: "PENDING";
137
+ readonly id: "pending";
132
138
  readonly label: "Pending";
133
139
  }, {
134
- readonly id: "PROCESSING";
140
+ readonly id: "processing";
135
141
  readonly label: "Processing";
136
142
  }, {
137
- readonly id: "PAID";
143
+ readonly id: "paid";
138
144
  readonly label: "Paid";
139
145
  }, {
140
- readonly id: "FAILED";
146
+ readonly id: "failed";
141
147
  readonly label: "Failed";
142
148
  }];
143
- /** Admin > Orders — order-state filter chip set. Uppercase IDs match the
144
- * `OrderDocument.status` enum on the server. */
149
+ /** Admin > Orders — order-state filter chip set. Lowercase IDs match
150
+ * `OrderStatusValues` and the actual Firestore document `status` field. */
145
151
  export declare const ADMIN_ORDER_STATUS_TABS: readonly [{
146
152
  readonly id: "All";
147
153
  readonly label: "All";
148
154
  }, {
149
- readonly id: "PENDING";
155
+ readonly id: "pending";
150
156
  readonly label: "Pending";
151
157
  }, {
152
- readonly id: "PROCESSING";
158
+ readonly id: "processing";
153
159
  readonly label: "Processing";
154
160
  }, {
155
- readonly id: "SHIPPED";
161
+ readonly id: "shipped";
156
162
  readonly label: "Shipped";
157
163
  }, {
158
- readonly id: "DELIVERED";
164
+ readonly id: "delivered";
159
165
  readonly label: "Delivered";
160
166
  }, {
161
- readonly id: "CANCELLED";
167
+ readonly id: "cancelled";
162
168
  readonly label: "Cancelled";
163
169
  }, {
164
- readonly id: "REFUNDED";
170
+ readonly id: "refunded";
165
171
  readonly label: "Refunded";
166
172
  }, {
167
- readonly id: "RETURN_REQUESTED";
173
+ readonly id: "return_requested";
168
174
  readonly label: "Return Requested";
169
175
  }];
170
176
  /** Admin > Reviews — moderation state filter chip set. */
@@ -43,13 +43,17 @@ export const ADMIN_USER_STATUS_TABS = [
43
43
  { id: "Active", label: "Active" },
44
44
  { id: "Disabled", label: "Disabled" },
45
45
  ];
46
- /** Admin > Users — role filter chip set. */
46
+ /** Admin > Users — role filter chip set. IDs match the canonical UserRole
47
+ * union ("user" | "seller" | "moderator" | "employee" | "admin") and the
48
+ * Firestore `users/{uid}.role` field. The label "Buyer" maps to id "user"
49
+ * per SB-UNI-E. Previously sent "buyer" which silently returned 0 rows. */
47
50
  export const ADMIN_USER_ROLE_TABS = [
48
51
  ALL_TAB,
49
52
  { id: "admin", label: "Admin" },
50
53
  { id: "seller", label: "Seller" },
51
- { id: "buyer", label: "Buyer" },
54
+ { id: "user", label: "Buyer" },
52
55
  { id: "moderator", label: "Moderator" },
56
+ { id: "employee", label: "Employee" },
53
57
  ];
54
58
  /** Admin > Stores — seller-onboarding state filter chip set. */
55
59
  export const ADMIN_STORE_STATUS_TABS = [
@@ -59,26 +63,26 @@ export const ADMIN_STORE_STATUS_TABS = [
59
63
  { id: "suspended", label: "Suspended" },
60
64
  { id: "rejected", label: "Rejected" },
61
65
  ];
62
- /** Admin > Payouts — payout state filter chip set. Uppercase IDs match the
63
- * `PayoutDocument.status` enum on the server. */
66
+ /** Admin > Payouts — payout state filter chip set. Lowercase IDs match
67
+ * `PayoutStatusValues` and the actual Firestore document `status` field. */
64
68
  export const ADMIN_PAYOUT_STATUS_TABS = [
65
69
  ALL_TAB,
66
- { id: "PENDING", label: "Pending" },
67
- { id: "PROCESSING", label: "Processing" },
68
- { id: "PAID", label: "Paid" },
69
- { id: "FAILED", label: "Failed" },
70
+ { id: "pending", label: "Pending" },
71
+ { id: "processing", label: "Processing" },
72
+ { id: "paid", label: "Paid" },
73
+ { id: "failed", label: "Failed" },
70
74
  ];
71
- /** Admin > Orders — order-state filter chip set. Uppercase IDs match the
72
- * `OrderDocument.status` enum on the server. */
75
+ /** Admin > Orders — order-state filter chip set. Lowercase IDs match
76
+ * `OrderStatusValues` and the actual Firestore document `status` field. */
73
77
  export const ADMIN_ORDER_STATUS_TABS = [
74
78
  ALL_TAB,
75
- { id: "PENDING", label: "Pending" },
76
- { id: "PROCESSING", label: "Processing" },
77
- { id: "SHIPPED", label: "Shipped" },
78
- { id: "DELIVERED", label: "Delivered" },
79
- { id: "CANCELLED", label: "Cancelled" },
80
- { id: "REFUNDED", label: "Refunded" },
81
- { id: "RETURN_REQUESTED", label: "Return Requested" },
79
+ { id: "pending", label: "Pending" },
80
+ { id: "processing", label: "Processing" },
81
+ { id: "shipped", label: "Shipped" },
82
+ { id: "delivered", label: "Delivered" },
83
+ { id: "cancelled", label: "Cancelled" },
84
+ { id: "refunded", label: "Refunded" },
85
+ { id: "return_requested", label: "Return Requested" },
82
86
  ];
83
87
  /** Admin > Reviews — moderation state filter chip set. */
84
88
  export const ADMIN_REVIEW_STATUS_TABS = [
@@ -9,6 +9,7 @@ export interface AdminListingConfig<TResponse, TRow extends {
9
9
  mapRows: (response: TResponse) => TRow[];
10
10
  getTotal?: (response: TResponse, rows: TRow[]) => number;
11
11
  buildFilters: (filterState: Record<string, string>) => string | undefined;
12
+ initialView?: "grid" | "list" | "table";
12
13
  }
13
14
  export declare function useAdminListing<TResponse, TRow extends {
14
15
  id: string;
@@ -6,7 +6,7 @@ import { usePanelUrlSync } from "../../../react/hooks/use-panel-url-sync";
6
6
  import { useAdminListingData } from "./useAdminListingData";
7
7
  export function useAdminListing(config) {
8
8
  const { filterKeys, defaultSort, pageSize = 25, queryKey, endpoint, mapRows, getTotal, buildFilters, } = config;
9
- const [view, setView] = useState("table");
9
+ const [view, setView] = useState(config.initialView ?? "table");
10
10
  const table = useUrlTable({ defaults: { pageSize: String(pageSize), sort: defaultSort } });
11
11
  const panel = usePanelUrlSync();
12
12
  const [searchInput, setSearchInput] = useState(table.get("q") || "");
@@ -183,19 +183,18 @@ export const DEFAULT_SITE_SETTINGS_DATA = {
183
183
  coupons: true,
184
184
  notifications: true,
185
185
  sellerRegistration: true,
186
- preOrders: false,
186
+ preOrders: true,
187
187
  seedPanel: true,
188
- // SB-UNI-X4 2026-05-13 — Phase 1 types enabled by default; Phase 2 types
189
- // (classified / digital-code / live) gated until per-type Phase 3 + 5
190
- // surfaces ship. Admin Feature Flags UI lets the operator flip them.
188
+ // W1-37 2026-05-23 — Phase 2 listing types enabled by default; all per-type
189
+ // surfaces (seller + admin via W1-29 + public) are now shipped.
191
190
  listingTypes: {
192
191
  standard: true,
193
192
  auction: true,
194
193
  "pre-order": true,
195
194
  "prize-draw": true,
196
- classified: false,
197
- "digital-code": false,
198
- live: false,
195
+ classified: true,
196
+ "digital-code": true,
197
+ live: true,
199
198
  },
200
199
  categoryTypes: {
201
200
  category: true,
@@ -4,6 +4,5 @@
4
4
  * Server-only entry point for auction API route handlers.
5
5
  */
6
6
  export * from "./actions";
7
- export { AuctionsRepository } from "./repository/auctions.repository";
8
7
  export { bidRepository } from "./repository/bid.repository";
9
8
  export { GET as bidsGET, GET } from "./api/route";
@@ -4,6 +4,5 @@
4
4
  * Server-only entry point for auction API route handlers.
5
5
  */
6
6
  export * from "./actions";
7
- export { AuctionsRepository } from "./repository/auctions.repository";
8
7
  export { bidRepository } from "./repository/bid.repository";
9
8
  export { GET as bidsGET, GET } from "./api/route";
@@ -18,7 +18,7 @@ export async function issueRealtimeToken(userId, userRole) {
18
18
  catch (err) {
19
19
  serverLogger.warn("Could not resolve chatIds for realtime token", { userId, err });
20
20
  }
21
- let conversationIds = {};
21
+ const conversationIds = {};
22
22
  try {
23
23
  const buyerConvs = await conversationsRepository.listByBuyer(userId);
24
24
  buyerConvs.forEach((c) => { conversationIds[c.id] = true; });
@@ -22,7 +22,7 @@ export class UserRepository extends BaseRepository {
22
22
  // addPiiIndices is intentionally NOT called here — it spreads the original
23
23
  // plaintext `data` back into the result, which would overwrite the encrypted
24
24
  // ciphertext with the original plaintext values, defeating the encryption.
25
- let encrypted = encryptPiiFields(data, [...USER_PII_FIELDS]);
25
+ const encrypted = encryptPiiFields(data, [...USER_PII_FIELDS]);
26
26
  if (encrypted.payoutDetails) {
27
27
  encrypted.payoutDetails =
28
28
  encryptPayoutDetails(encrypted.payoutDetails);
@@ -1,9 +1,12 @@
1
1
  import type { DocumentReference } from "firebase-admin/firestore";
2
2
  import type { DocumentSnapshot } from "../../../providers/db-firebase";
3
- import { BaseRepository } from "../../../providers/db-firebase";
3
+ import { BaseRepository, type FirebaseSieveResult, type SieveModel } from "../../../providers/db-firebase";
4
4
  import { type AddToCartInput, type CartAppliedCoupon, type CartDocument, type UpdateCartItemInput } from "../schemas";
5
5
  export declare class CartRepository extends BaseRepository<CartDocument> {
6
+ private static readonly SIEVE_FIELDS;
6
7
  constructor();
8
+ /** Admin-facing paginated list of carts. */
9
+ list(model: SieveModel): Promise<FirebaseSieveResult<CartDocument>>;
7
10
  protected mapDoc<D = CartDocument>(snap: DocumentSnapshot): D;
8
11
  findByUserId(userId: string): Promise<CartDocument | null>;
9
12
  getOrCreate(userId: string): Promise<CartDocument>;
@@ -9,6 +9,10 @@ export class CartRepository extends BaseRepository {
9
9
  constructor() {
10
10
  super(CART_COLLECTION);
11
11
  }
12
+ /** Admin-facing paginated list of carts. */
13
+ async list(model) {
14
+ return this.sieveQuery(model, CartRepository.SIEVE_FIELDS);
15
+ }
12
16
  mapDoc(snap) {
13
17
  const raw = super.mapDoc(snap);
14
18
  return {
@@ -279,4 +283,12 @@ export class CartRepository extends BaseRepository {
279
283
  return snap.docs.map((d) => d.ref);
280
284
  }
281
285
  }
286
+ // W1-42 — admin-facing Sieve list. Filterable on userId, sessionId, updatedAt;
287
+ // sortable on updatedAt.
288
+ CartRepository.SIEVE_FIELDS = {
289
+ userId: { canFilter: true, canSort: false },
290
+ sessionId: { canFilter: true, canSort: false },
291
+ updatedAt: { canFilter: true, canSort: true },
292
+ createdAt: { canFilter: true, canSort: true },
293
+ };
282
294
  export const cartRepository = new CartRepository();
@@ -22,8 +22,6 @@ export interface PreflightResponse {
22
22
  available: any[];
23
23
  unavailable: UnavailableItem[];
24
24
  }
25
- /** @deprecated Use `CreatePaymentOrderResponse` instead. */
26
- export type CreateRazorpayOrderResponse = CreatePaymentOrderResponse;
27
25
  export interface CreatePaymentOrderResponse {
28
26
  gatewayOrderId: string;
29
27
  amount: number;
@@ -2,7 +2,7 @@ export * from "./types";
2
2
  export * from "./schemas";
3
3
  export * from "./hooks/useCheckout";
4
4
  export { useCheckout as useCheckoutApi } from "./hooks/useCheckoutApi";
5
- export type { AddressListResponse, CartApiResponse, PlaceOrderResponse, CreatePaymentOrderResponse, CreateRazorpayOrderResponse, UnavailableItem, PreflightResponse, } from "./hooks/useCheckoutApi";
5
+ export type { AddressListResponse, CartApiResponse, PlaceOrderResponse, CreatePaymentOrderResponse, UnavailableItem, PreflightResponse, } from "./hooks/useCheckoutApi";
6
6
  export * from "./hooks/usePaymentCheckout";
7
7
  export * from "./components";
8
8
  export { manifest } from "./manifest";
@@ -1,7 +1,7 @@
1
- import type { ListingViewShellProps } from "../../../ui";
2
- export interface AdminEventsViewProps extends ListingViewShellProps {
1
+ import type { ListingLayoutProps } from "../../../ui";
2
+ export interface AdminEventsViewProps extends ListingLayoutProps {
3
3
  getRowHref?: (row: {
4
4
  id: string;
5
5
  }) => string;
6
6
  }
7
- export declare function AdminEventsView({ children, getRowHref, ...props }: AdminEventsViewProps): import("react/jsx-runtime").JSX.Element;
7
+ export declare function AdminEventsView({ children, ...props }: AdminEventsViewProps): import("react/jsx-runtime").JSX.Element;
@@ -1,28 +1,12 @@
1
1
  "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import React, { useState, useCallback } from "react";
4
- import { Plus } from "lucide-react";
5
- import { useUrlTable } from "../../../react/hooks/useUrlTable";
6
- import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
7
- import { AdminViewCards } from "../../admin/components/AdminViewCards";
8
- import { usePanelUrlSync } from "../../../react/hooks/use-panel-url-sync";
9
- import { BulkActionBar, Button, FilterChipGroup, ListingFilterDrawer, ListingToolbar, Pagination, ListingViewShell, SideDrawer } from "../../../ui";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import React from "react";
4
+ import { FilterChipGroup, ListingLayout } from "../../../ui";
10
5
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
11
6
  import { ADMIN_EVENT_STATUS_TABS } from "../../admin/constants/filter-tabs";
12
- import { toRecordArray, toRelativeDate, toStringValue, useAdminListingData, } from "../../admin/hooks/useAdminListingData";
13
- import { DataTable } from "../../admin/components/DataTable";
7
+ import { toRecordArray, toRelativeDate, toStringValue, } from "../../admin/hooks/useAdminListingData";
8
+ import { DataListingView } from "../../admin/components/DataListingView";
14
9
  import { AdminEventEditorView } from "./AdminEventEditorView";
15
- import { useBottomActions } from "../../layout";
16
- const PAGE_SIZE = 25;
17
- const FILTER_KEYS = ["status", "type"];
18
- const DEFAULT_SORT = "-startsAt";
19
- const SORT_OPTIONS = [
20
- { value: "-startsAt", label: "Starting soonest" },
21
- { value: "startsAt", label: "Starting latest" },
22
- { value: "-createdAt", label: "Newest" },
23
- { value: "title", label: "Title A–Z" },
24
- ];
25
- const STATUS_OPTIONS = ADMIN_EVENT_STATUS_TABS;
26
10
  // TODO(events): TYPE_OPTIONS list pre-dates the SB9 EventType union refresh
27
11
  // (sale|offer|poll|survey|feedback|raffle|spin_wheel). Keep current values to
28
12
  // avoid silently breaking saved-filter URLs — sync in a dedicated follow-up.
@@ -35,78 +19,58 @@ const TYPE_OPTIONS = [
35
19
  { id: "survey", label: "Survey" },
36
20
  { id: "flash-sale", label: "Flash Sale" },
37
21
  ];
38
- export function AdminEventsView({ children, getRowHref, ...props }) {
39
- const hasChildren = React.Children.count(children) > 0;
40
- const [view, setView] = useState("table");
41
- const table = useUrlTable({ defaults: { pageSize: String(PAGE_SIZE), sort: DEFAULT_SORT } });
42
- const { openCreatePanel, openEditPanel, closePanel, isCreateOpen, isEditOpen, editId } = usePanelUrlSync();
43
- const [searchInput, setSearchInput] = useState(table.get("q") || "");
44
- const [filterOpen, setFilterOpen] = useState(false);
45
- const [pendingFilters, setPendingFilters] = useState(() => Object.fromEntries(FILTER_KEYS.map((k) => [k, table.get(k)])));
46
- const openFilters = useCallback(() => {
47
- setPendingFilters(Object.fromEntries(FILTER_KEYS.map((k) => [k, table.get(k)])));
48
- setFilterOpen(true);
49
- }, [table]);
50
- const applyFilters = useCallback(() => {
51
- const updates = { page: "1" };
52
- for (const k of FILTER_KEYS)
53
- updates[k] = pendingFilters[k] ?? "";
54
- table.setMany(updates);
55
- setFilterOpen(false);
56
- }, [pendingFilters, table]);
57
- const clearFilters = useCallback(() => {
58
- setPendingFilters(Object.fromEntries(FILTER_KEYS.map((k) => [k, ""])));
59
- }, []);
60
- const resetAll = useCallback(() => {
61
- const updates = { q: "", sort: "" };
62
- for (const k of FILTER_KEYS)
63
- updates[k] = "";
64
- table.setMany(updates);
65
- setSearchInput("");
66
- }, [table]);
67
- const commitSearch = useCallback(() => {
68
- table.set("q", searchInput.trim());
69
- }, [searchInput, table]);
70
- const activeFilterCount = FILTER_KEYS.filter((k) => !!table.get(k)).length;
71
- const hasActiveState = !!table.get("q") || table.get("sort") !== DEFAULT_SORT || activeFilterCount > 0;
72
- const filterParts = [];
73
- const statusRaw = table.get("status");
74
- if (statusRaw && statusRaw !== "All")
75
- filterParts.push(`status==${statusRaw}`);
76
- const typeRaw = table.get("type");
77
- if (typeRaw && typeRaw !== "All")
78
- filterParts.push(`type==${typeRaw}`);
79
- const filters = filterParts.join(",") || undefined;
80
- const { rows, total, isLoading, errorMessage } = useAdminListingData({
22
+ export function AdminEventsView({ children, ...props }) {
23
+ if (React.Children.count(children) > 0) {
24
+ return (_jsx(ListingLayout, { portal: "admin", ...props, children: children }));
25
+ }
26
+ const config = {
27
+ portal: "admin",
28
+ title: "Events",
29
+ searchPlaceholder: "Search events by title or type",
30
+ emptyLabel: "No events found",
31
+ filterKeys: ["status", "type"],
32
+ defaultSort: "-startsAt",
81
33
  queryKey: ["admin", "events", "listing"],
82
34
  endpoint: ADMIN_ENDPOINTS.EVENTS,
83
- page: table.getNumber("page", 1),
84
- pageSize: PAGE_SIZE,
85
- sorts: table.get("sort") || DEFAULT_SORT,
86
- filters,
87
- q: table.get("q") || undefined,
35
+ sortOptions: [
36
+ { value: "-startsAt", label: "Starting soonest" },
37
+ { value: "startsAt", label: "Starting latest" },
38
+ { value: "-createdAt", label: "Newest" },
39
+ { value: "title", label: "Title A–Z" },
40
+ ],
88
41
  mapRows: (response) => toRecordArray(response.items).map((item, index) => ({
89
42
  id: toStringValue(item.id, `event-${index}`),
90
43
  primary: toStringValue(item.title, "Untitled event"),
91
- secondary: [
92
- toStringValue(item.type, "event"),
93
- toStringValue(item.startsAt, ""),
94
- ].filter(Boolean).join(" · "),
44
+ secondary: [toStringValue(item.type, "event"), toStringValue(item.startsAt, "")]
45
+ .filter(Boolean)
46
+ .join(" · "),
95
47
  status: toStringValue(item.status, "active"),
96
48
  updatedAt: toRelativeDate(item.updatedAt ?? item.createdAt),
97
49
  })),
98
50
  getTotal: (response, mappedRows) => typeof response.total === "number" ? response.total : mappedRows.length,
99
- });
100
- const currentPage = table.getNumber("page", 1);
101
- const totalPages = Math.ceil(total / PAGE_SIZE);
102
- const selection = useBulkSelection({ items: rows, keyExtractor: (r) => r.id });
103
- if (hasChildren) {
104
- return _jsx(ListingViewShell, { portal: "admin", ...props, children: children });
105
- }
106
- useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
107
- { id: "delete", label: "Delete Selected", variant: "secondary", onClick: () => { selection.clearSelection(); } },
108
- ] } } : {});
109
- return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search events by title or type", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get("sort") || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set("sort", v); }, showTableView: true, view: view, onViewChange: (v) => setView(v), onResetAll: resetAll, hasActiveState: hasActiveState, extra: _jsxs(Button, { size: "sm", onClick: openCreatePanel, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), "Add Event"] }) }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
110
- { id: "delete", label: "Delete Selected", variant: "secondary", onClick: () => { selection.clearSelection(); } },
111
- ] }), 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: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-error-surface px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })), view === "table" ? (_jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No events found", onRowClick: (row) => openEditPanel(row.id) })) : (_jsx(AdminViewCards, { rows: rows, view: view, isLoading: isLoading, emptyLabel: "No events found", onRowClick: undefined, selectedIdSet: selection.selectedIdSet, onToggleSelect: selection.toggle }))] }), _jsxs(ListingFilterDrawer, { open: filterOpen, onClose: () => setFilterOpen(false), onApply: applyFilters, onClear: clearFilters, activeCount: activeFilterCount, children: [_jsx(FilterChipGroup, { label: "Status", tabs: STATUS_OPTIONS, value: pendingFilters.status ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, status: id })) }), _jsx(FilterChipGroup, { label: "Type", tabs: TYPE_OPTIONS, value: pendingFilters.type ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, type: id })) })] }), _jsx(SideDrawer, { isOpen: isCreateOpen || isEditOpen, onClose: closePanel, title: isCreateOpen ? "Add Event" : "Edit Event", mode: isCreateOpen ? "create" : "edit", children: (isCreateOpen || isEditOpen) && (_jsx(AdminEventEditorView, { eventId: editId ?? undefined, onSaved: closePanel, embedded: true })) })] }));
51
+ buildFilters: (state) => {
52
+ const parts = [];
53
+ if (state.status && state.status !== "All")
54
+ parts.push(`status==${state.status}`);
55
+ if (state.type && state.type !== "All")
56
+ parts.push(`type==${state.type}`);
57
+ return parts.join(",") || undefined;
58
+ },
59
+ primaryAction: {
60
+ label: "Add Event",
61
+ onClick: ({ openCreatePanel }) => openCreatePanel(),
62
+ },
63
+ buildBulkActions: (selection) => [
64
+ {
65
+ id: "delete",
66
+ label: "Delete Selected",
67
+ variant: "secondary",
68
+ onClick: () => selection.clearSelection(),
69
+ },
70
+ ],
71
+ renderFilterPanel: ({ pendingFilters, setPendingFilters }) => (_jsxs(_Fragment, { children: [_jsx(FilterChipGroup, { label: "Status", tabs: ADMIN_EVENT_STATUS_TABS, value: pendingFilters.status ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, status: id })) }), _jsx(FilterChipGroup, { label: "Type", tabs: TYPE_OPTIONS, value: pendingFilters.type ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, type: id })) })] })),
72
+ renderEditor: ({ editId, closePanel }) => (_jsx(AdminEventEditorView, { eventId: editId ?? undefined, onSaved: closePanel, embedded: true })),
73
+ resolveEditorTitle: ({ isCreate }) => (isCreate ? "Add Event" : "Edit Event"),
74
+ };
75
+ return _jsx(DataListingView, { config: config });
112
76
  }
@@ -0,0 +1,19 @@
1
+ export interface EventOfferCardProps {
2
+ /** Coupon code to copy. */
3
+ couponCode: string;
4
+ /** Description of what the coupon does. */
5
+ offerDescription?: string;
6
+ /** Headline. */
7
+ title?: string;
8
+ /** Optional filter param for the CTA — e.g. {key: "category", value: "trading-cards"}. */
9
+ filterParam?: {
10
+ key: string;
11
+ value: string;
12
+ };
13
+ }
14
+ /**
15
+ * `EventOfferCard` — W1-18 — offer event UI noted as missing in the plan.
16
+ * Renders a coupon code with copy-to-clipboard + a CTA to the filtered
17
+ * products page.
18
+ */
19
+ export declare function EventOfferCard({ couponCode, offerDescription, title, filterParam, }: EventOfferCardProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import Link from "next/link";
5
+ import { Div, Heading, Stack, Text } from "../../../ui";
6
+ import { Button } from "../../../ui/components/Button";
7
+ import { ROUTES } from "../../../next/routing/route-map";
8
+ /**
9
+ * `EventOfferCard` — W1-18 — offer event UI noted as missing in the plan.
10
+ * Renders a coupon code with copy-to-clipboard + a CTA to the filtered
11
+ * products page.
12
+ */
13
+ export function EventOfferCard({ couponCode, offerDescription, title = "Exclusive offer", filterParam, }) {
14
+ const [copied, setCopied] = useState(false);
15
+ const href = filterParam
16
+ ? `${ROUTES.PUBLIC.PRODUCTS}?${encodeURIComponent(filterParam.key)}=${encodeURIComponent(filterParam.value)}`
17
+ : String(ROUTES.PUBLIC.PRODUCTS);
18
+ const copyCode = async () => {
19
+ try {
20
+ await navigator.clipboard.writeText(couponCode);
21
+ setCopied(true);
22
+ setTimeout(() => setCopied(false), 2000);
23
+ }
24
+ catch {
25
+ /* clipboard unavailable — leave button as-is */
26
+ }
27
+ };
28
+ return (_jsx(Div, { className: "rounded-2xl border border-zinc-200 dark:border-zinc-700 p-6", children: _jsxs(Stack, { gap: "md", children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 2, className: "text-2xl font-semibold", children: title }), offerDescription ? (_jsx(Text, { className: "text-sm text-zinc-600 dark:text-zinc-400", children: offerDescription })) : null] }), _jsxs(Div, { className: "flex items-center gap-3 rounded-lg bg-zinc-50 dark:bg-zinc-900 px-4 py-3", children: [_jsx("code", { className: "flex-1 font-mono text-lg font-bold text-zinc-900 dark:text-zinc-100", children: couponCode }), _jsx(Button, { type: "button", variant: "outline", onClick: copyCode, children: copied ? "Copied!" : "Copy code" })] }), _jsx(Div, { children: _jsx(Link, { href: href, children: _jsx(Button, { variant: "primary", children: "Apply at checkout" }) }) })] }) }));
29
+ }
@@ -0,0 +1,25 @@
1
+ export interface EventRaffleEntryFormProps {
2
+ /** Event id used for the entry POST. */
3
+ eventId: string;
4
+ /** Raffle prize label rendered prominently above the form. */
5
+ prizeLabel?: string;
6
+ /** Raffle type — drives the helper copy. */
7
+ raffleType?: "open_raffle" | "top_n_scorers" | "top_n_participants" | "spin_wheel";
8
+ /** Top-N value when raffleType supports it. */
9
+ topN?: number;
10
+ /** Max entries this user already has (drives the over-limit message). */
11
+ userEntryCount?: number;
12
+ /** Server-enforced max entries per user (defaults to 1). */
13
+ maxEntriesPerUser?: number;
14
+ /** When true, the form is in a submitted/locked state. */
15
+ submitted?: boolean;
16
+ /** Caller-provided submit handler. Receives the user's optional message. */
17
+ onSubmit: (message: string) => Promise<void> | void;
18
+ }
19
+ /**
20
+ * `EventRaffleEntryForm` — W1-18 — fills the gap noted in the plan ("Raffle
21
+ * entry form (71 LOC stub) — no entry form"). Renders the prize hero,
22
+ * eligibility status, an optional message field, and a submit button. Server
23
+ * action wiring stays with the caller via the `onSubmit` prop.
24
+ */
25
+ export declare function EventRaffleEntryForm({ eventId: _eventId, prizeLabel, raffleType, topN, userEntryCount, maxEntriesPerUser, submitted, onSubmit, }: EventRaffleEntryFormProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,37 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import { Button } from "../../../ui/components/Button";
5
+ import { Div, Heading, Stack, Text } from "../../../ui";
6
+ import { Badge } from "../../../ui/components/Badge";
7
+ /**
8
+ * `EventRaffleEntryForm` — W1-18 — fills the gap noted in the plan ("Raffle
9
+ * entry form (71 LOC stub) — no entry form"). Renders the prize hero,
10
+ * eligibility status, an optional message field, and a submit button. Server
11
+ * action wiring stays with the caller via the `onSubmit` prop.
12
+ */
13
+ export function EventRaffleEntryForm({ eventId: _eventId, prizeLabel, raffleType = "open_raffle", topN, userEntryCount = 0, maxEntriesPerUser = 1, submitted = false, onSubmit, }) {
14
+ const [message, setMessage] = useState("");
15
+ const [busy, setBusy] = useState(false);
16
+ const overLimit = userEntryCount >= maxEntriesPerUser;
17
+ const handleSubmit = async (e) => {
18
+ e.preventDefault();
19
+ if (overLimit || submitted || busy)
20
+ return;
21
+ setBusy(true);
22
+ try {
23
+ await onSubmit(message.trim());
24
+ }
25
+ finally {
26
+ setBusy(false);
27
+ }
28
+ };
29
+ const eligibilityCopy = raffleType === "open_raffle"
30
+ ? "Open to all eligible participants — one entry per user."
31
+ : raffleType === "top_n_scorers"
32
+ ? `Top ${topN ?? "N"} highest-scoring entries win.`
33
+ : raffleType === "top_n_participants"
34
+ ? `Earliest ${topN ?? "N"} entries qualify.`
35
+ : "Spin the wheel to claim your prize.";
36
+ return (_jsxs(Div, { className: "rounded-2xl border border-zinc-200 dark:border-zinc-700 p-6 space-y-4", children: [prizeLabel ? (_jsxs(Stack, { gap: "xs", children: [_jsx(Badge, { variant: "warning", children: "Prize" }), _jsx(Heading, { level: 2, className: "text-2xl font-bold", children: prizeLabel })] })) : null, _jsx(Text, { className: "text-sm text-zinc-600 dark:text-zinc-400", children: eligibilityCopy }), submitted ? (_jsx(Div, { className: "rounded-lg bg-success-surface px-4 py-3 text-sm text-success", children: "You're in. Check the leaderboard for results." })) : overLimit ? (_jsxs(Div, { className: "rounded-lg bg-warning-surface px-4 py-3 text-sm text-warning", children: ["You've used all ", maxEntriesPerUser, " entry slot", maxEntriesPerUser === 1 ? "" : "s", " for this raffle."] })) : (_jsxs("form", { onSubmit: handleSubmit, className: "space-y-3", children: [_jsxs("label", { htmlFor: "raffle-message", className: "block text-sm font-medium", children: ["Message ", _jsx("span", { className: "text-zinc-400", children: "(optional)" })] }), _jsx("textarea", { id: "raffle-message", value: message, onChange: (e) => setMessage(e.target.value), rows: 3, maxLength: 500, className: "w-full rounded-lg border border-zinc-300 dark:border-zinc-700 px-3 py-2 text-sm bg-white dark:bg-zinc-900 focus:outline-none focus:ring-2 focus:ring-[var(--appkit-color-primary)]", placeholder: "Share why you'd like to win", disabled: busy }), _jsx(Button, { type: "submit", variant: "primary", disabled: busy, children: busy ? "Submitting…" : "Enter raffle" })] }))] }));
37
+ }
@@ -4,9 +4,6 @@ export interface EventRafflesSectionProps {
4
4
  }
5
5
  /**
6
6
  * Renders a live-raffle/spin-wheel strip on the homepage.
7
- *
8
- * Reads events with `hasRaffle=true` and status in {"active","upcoming"}. The
9
- * `hasRaffle` flag is added later with the raffle feature; for now the
10
- * component renders an empty state and the section ships disabled in seed.
7
+ * W1-38 (2026-05-23): fetches events with hasRaffle=true and renders the EventCard grid.
11
8
  */
12
9
  export declare function EventRafflesSection({ config, }: EventRafflesSectionProps): Promise<import("react/jsx-runtime").JSX.Element>;