@mohasinac/appkit 2.7.59 → 2.8.1

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 (324) 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/about/components/PublicProfileView.js +8 -8
  47. package/dist/features/account/components/UserOffersPanel.js +1 -1
  48. package/dist/features/account/components/UserSupportView.d.ts +1 -2
  49. package/dist/features/account/components/UserSupportView.js +9 -1
  50. package/dist/features/admin/actions/admin-actions.js +16 -1
  51. package/dist/features/admin/components/AdminAllEventEntriesView.d.ts +2 -3
  52. package/dist/features/admin/components/AdminAllEventEntriesView.js +50 -83
  53. package/dist/features/admin/components/AdminBidsView.d.ts +2 -3
  54. package/dist/features/admin/components/AdminBidsView.js +64 -98
  55. package/dist/features/admin/components/AdminBlogView.d.ts +3 -7
  56. package/dist/features/admin/components/AdminBlogView.js +53 -83
  57. package/dist/features/admin/components/AdminBrandsView.d.ts +2 -3
  58. package/dist/features/admin/components/AdminBrandsView.js +84 -83
  59. package/dist/features/admin/components/AdminBundlesView.js +82 -125
  60. package/dist/features/admin/components/AdminCarouselView.d.ts +2 -2
  61. package/dist/features/admin/components/AdminCarouselView.js +17 -52
  62. package/dist/features/admin/components/AdminCartsView.d.ts +2 -3
  63. package/dist/features/admin/components/AdminCartsView.js +39 -88
  64. package/dist/features/admin/components/AdminCategoriesView.d.ts +3 -3
  65. package/dist/features/admin/components/AdminCategoriesView.js +98 -92
  66. package/dist/features/admin/components/AdminCategoryEditorView.js +2 -2
  67. package/dist/features/admin/components/AdminClassifiedView.d.ts +3 -0
  68. package/dist/features/admin/components/AdminClassifiedView.js +44 -0
  69. package/dist/features/admin/components/AdminContactView.d.ts +2 -2
  70. package/dist/features/admin/components/AdminContactView.js +104 -111
  71. package/dist/features/admin/components/AdminCouponsView.d.ts +3 -6
  72. package/dist/features/admin/components/AdminCouponsView.js +66 -86
  73. package/dist/features/admin/components/AdminDigitalCodesView.d.ts +3 -0
  74. package/dist/features/admin/components/AdminDigitalCodesView.js +51 -0
  75. package/dist/features/admin/components/AdminFaqsView.d.ts +4 -4
  76. package/dist/features/admin/components/AdminFaqsView.js +77 -33
  77. package/dist/features/admin/components/AdminFeaturesView.d.ts +2 -3
  78. package/dist/features/admin/components/AdminFeaturesView.js +57 -70
  79. package/dist/features/admin/components/AdminGroupedListingsView.d.ts +3 -0
  80. package/dist/features/admin/components/AdminGroupedListingsView.js +43 -0
  81. package/dist/features/admin/components/AdminHistoryView.d.ts +2 -3
  82. package/dist/features/admin/components/AdminHistoryView.js +35 -52
  83. package/dist/features/admin/components/AdminListingScaffold.d.ts +2 -2
  84. package/dist/features/admin/components/AdminListingScaffold.js +3 -3
  85. package/dist/features/admin/components/AdminLiveView.d.ts +3 -0
  86. package/dist/features/admin/components/AdminLiveView.js +50 -0
  87. package/dist/features/admin/components/AdminNewsletterView.d.ts +2 -2
  88. package/dist/features/admin/components/AdminNewsletterView.js +67 -97
  89. package/dist/features/admin/components/AdminNotificationsView.d.ts +2 -3
  90. package/dist/features/admin/components/AdminNotificationsView.js +67 -93
  91. package/dist/features/admin/components/AdminOrderEditorView.js +10 -10
  92. package/dist/features/admin/components/AdminOrdersView.d.ts +2 -3
  93. package/dist/features/admin/components/AdminOrdersView.js +93 -107
  94. package/dist/features/admin/components/AdminPayoutsView.d.ts +2 -3
  95. package/dist/features/admin/components/AdminPayoutsView.js +51 -91
  96. package/dist/features/admin/components/AdminPrizeDrawsView.d.ts +2 -3
  97. package/dist/features/admin/components/AdminPrizeDrawsView.js +39 -76
  98. package/dist/features/admin/components/AdminProductEditorView.js +3 -3
  99. package/dist/features/admin/components/AdminProductsView.d.ts +4 -4
  100. package/dist/features/admin/components/AdminProductsView.js +167 -163
  101. package/dist/features/admin/components/AdminReturnRequestsView.d.ts +1 -1
  102. package/dist/features/admin/components/AdminReturnRequestsView.js +64 -66
  103. package/dist/features/admin/components/AdminReviewsView.d.ts +3 -7
  104. package/dist/features/admin/components/AdminReviewsView.js +94 -110
  105. package/dist/features/admin/components/AdminScammersView.d.ts +2 -3
  106. package/dist/features/admin/components/AdminScammersView.js +53 -97
  107. package/dist/features/admin/components/AdminSectionsView.js +1 -1
  108. package/dist/features/admin/components/AdminSessionsView.d.ts +2 -3
  109. package/dist/features/admin/components/AdminSessionsView.js +62 -89
  110. package/dist/features/admin/components/AdminSiteSettingsView.js +4 -5
  111. package/dist/features/admin/components/AdminStoreAddressesView.d.ts +1 -1
  112. package/dist/features/admin/components/AdminStoreAddressesView.js +39 -53
  113. package/dist/features/admin/components/AdminStoreEditorView.js +21 -8
  114. package/dist/features/admin/components/AdminStoresView.d.ts +2 -3
  115. package/dist/features/admin/components/AdminStoresView.js +67 -99
  116. package/dist/features/admin/components/AdminSublistingCategoriesView.d.ts +1 -1
  117. package/dist/features/admin/components/AdminSublistingCategoriesView.js +28 -44
  118. package/dist/features/admin/components/AdminSupportTicketDetailView.d.ts +10 -1
  119. package/dist/features/admin/components/AdminSupportTicketDetailView.js +191 -5
  120. package/dist/features/admin/components/AdminSupportTicketsView.d.ts +2 -3
  121. package/dist/features/admin/components/AdminSupportTicketsView.js +65 -96
  122. package/dist/features/admin/components/AdminTeamView.d.ts +2 -2
  123. package/dist/features/admin/components/AdminTeamView.js +40 -74
  124. package/dist/features/admin/components/AdminUserEditorView.d.ts +11 -1
  125. package/dist/features/admin/components/AdminUserEditorView.js +77 -7
  126. package/dist/features/admin/components/AdminUsersView.d.ts +2 -3
  127. package/dist/features/admin/components/AdminUsersView.js +108 -100
  128. package/dist/features/admin/components/AdminViewCards.d.ts +1 -1
  129. package/dist/features/admin/components/AdminViewCards.js +15 -15
  130. package/dist/features/admin/components/AdminWishlistsView.d.ts +2 -3
  131. package/dist/features/admin/components/AdminWishlistsView.js +36 -62
  132. package/dist/features/admin/components/DataListingView.d.ts +122 -0
  133. package/dist/features/admin/components/DataListingView.js +66 -0
  134. package/dist/features/admin/components/index.d.ts +10 -4
  135. package/dist/features/admin/components/index.js +6 -2
  136. package/dist/features/admin/constants/filter-tabs.d.ts +23 -17
  137. package/dist/features/admin/constants/filter-tabs.js +21 -17
  138. package/dist/features/admin/hooks/useAdminListing.d.ts +1 -0
  139. package/dist/features/admin/hooks/useAdminListing.js +1 -1
  140. package/dist/features/admin/schemas/firestore.js +6 -7
  141. package/dist/features/auctions/server.d.ts +0 -1
  142. package/dist/features/auctions/server.js +0 -1
  143. package/dist/features/auth/actions/realtime-token-actions.js +1 -1
  144. package/dist/features/auth/repository/user.repository.js +1 -1
  145. package/dist/features/blog/components/BlogFeaturedCard.js +1 -0
  146. package/dist/features/cart/repository/cart.repository.d.ts +4 -1
  147. package/dist/features/cart/repository/cart.repository.js +12 -0
  148. package/dist/features/checkout/hooks/useCheckoutApi.d.ts +0 -2
  149. package/dist/features/checkout/index.d.ts +1 -1
  150. package/dist/features/events/components/AdminEventEditorView.js +10 -13
  151. package/dist/features/events/components/AdminEventsView.d.ts +3 -3
  152. package/dist/features/events/components/AdminEventsView.js +50 -86
  153. package/dist/features/events/components/EventCard.js +1 -0
  154. package/dist/features/events/components/EventOfferCard.d.ts +19 -0
  155. package/dist/features/events/components/EventOfferCard.js +29 -0
  156. package/dist/features/events/components/EventRaffleEntryForm.d.ts +25 -0
  157. package/dist/features/events/components/EventRaffleEntryForm.js +37 -0
  158. package/dist/features/events/components/EventRafflesSection.d.ts +1 -4
  159. package/dist/features/events/components/EventRafflesSection.js +17 -6
  160. package/dist/features/events/components/EventSaleBanner.d.ts +21 -0
  161. package/dist/features/events/components/EventSaleBanner.js +18 -0
  162. package/dist/features/events/components/index.d.ts +6 -0
  163. package/dist/features/events/components/index.js +4 -0
  164. package/dist/features/events/repository/event-entry.repository.d.ts +5 -0
  165. package/dist/features/events/repository/event-entry.repository.js +7 -0
  166. package/dist/features/faq/components/FAQPageContent.js +1 -0
  167. package/dist/features/filters/AsyncFacetSection.d.ts +1 -1
  168. package/dist/features/homepage/components/AdvertisementBanner.js +6 -6
  169. package/dist/features/homepage/components/FAQSection.d.ts +0 -5
  170. package/dist/features/homepage/components/HomepageSkeleton.js +2 -2
  171. package/dist/features/homepage/components/WelcomeSection.js +3 -3
  172. package/dist/features/homepage/lib/live-stats.js +1 -1
  173. package/dist/features/homepage/schemas/firestore.d.ts +0 -2
  174. package/dist/features/layout/TitleBar.js +1 -0
  175. package/dist/features/layout/index.d.ts +0 -2
  176. package/dist/features/layout/index.js +0 -1
  177. package/dist/features/pre-orders/server.d.ts +0 -1
  178. package/dist/features/pre-orders/server.js +0 -1
  179. package/dist/features/products/components/GroupSettingsPanel.js +2 -2
  180. package/dist/features/products/components/PrizeDrawItemsEditor.js +2 -2
  181. package/dist/features/products/components/PrizeDrawsSection.d.ts +1 -4
  182. package/dist/features/products/components/PrizeDrawsSection.js +17 -6
  183. package/dist/features/products/components/PrizeRevealModal.js +1 -1
  184. package/dist/features/products/components/ProductCardMetadataSection.d.ts +11 -0
  185. package/dist/features/products/components/ProductCardMetadataSection.js +25 -0
  186. package/dist/features/products/components/ProductDetailPageView.js +3 -1
  187. package/dist/features/products/components/ProductFeaturesSelector.js +1 -1
  188. package/dist/features/products/components/ProductGradingTab.d.ts +13 -0
  189. package/dist/features/products/components/ProductGradingTab.js +25 -0
  190. package/dist/features/products/components/ProductGrid.js +15 -2
  191. package/dist/features/products/components/ProductTabsShell.d.ts +5 -1
  192. package/dist/features/products/components/ProductTabsShell.js +6 -1
  193. package/dist/features/products/components/index.d.ts +4 -0
  194. package/dist/features/products/components/index.js +3 -0
  195. package/dist/features/products/constants/action-defs.d.ts +5 -0
  196. package/dist/features/products/constants/action-defs.js +52 -32
  197. package/dist/features/products/constants/sieve.d.ts +24 -4
  198. package/dist/features/products/constants/sieve.js +20 -11
  199. package/dist/features/products/schemas/firestore.d.ts +17 -0
  200. package/dist/features/products/schemas/product-features.validators.d.ts +2 -2
  201. package/dist/features/products/schemas/product-templates.d.ts +2 -4
  202. package/dist/features/products/types/index.d.ts +4 -0
  203. package/dist/features/promotions/components/CouponsIndexListing.js +4 -4
  204. package/dist/features/promotions/server.d.ts +0 -1
  205. package/dist/features/promotions/server.js +0 -1
  206. package/dist/features/reviews/components/ReviewDetailShell.js +3 -3
  207. package/dist/features/search/api/route.js +44 -1
  208. package/dist/features/search/components/Search.js +2 -0
  209. package/dist/features/search/hooks/useNavSuggestions.d.ts +5 -1
  210. package/dist/features/search/hooks/useNavSuggestions.js +31 -4
  211. package/dist/features/seller/components/BrandInlineSelect.js +2 -2
  212. package/dist/features/seller/components/CategoryInlineSelect.js +2 -2
  213. package/dist/features/seller/components/SellerAddressesView.js +4 -5
  214. package/dist/features/seller/components/SellerAuctionsView.d.ts +3 -3
  215. package/dist/features/seller/components/SellerAuctionsView.js +60 -90
  216. package/dist/features/seller/components/SellerBidsView.js +1 -1
  217. package/dist/features/seller/components/SellerBundlesView.js +64 -89
  218. package/dist/features/seller/components/SellerClassifiedView.js +67 -90
  219. package/dist/features/seller/components/SellerCouponEditorView.js +1 -1
  220. package/dist/features/seller/components/SellerCouponsView.d.ts +2 -2
  221. package/dist/features/seller/components/SellerCouponsView.js +45 -84
  222. package/dist/features/seller/components/SellerDigitalCodesView.js +63 -88
  223. package/dist/features/seller/components/SellerGroupedListingsView.js +33 -49
  224. package/dist/features/seller/components/SellerLiveView.js +63 -84
  225. package/dist/features/seller/components/SellerOffersPanel.js +1 -1
  226. package/dist/features/seller/components/SellerOffersView.d.ts +2 -2
  227. package/dist/features/seller/components/SellerOffersView.js +37 -69
  228. package/dist/features/seller/components/SellerOrdersView.d.ts +2 -2
  229. package/dist/features/seller/components/SellerOrdersView.js +4 -4
  230. package/dist/features/seller/components/SellerPayoutMethodsView.js +1 -1
  231. package/dist/features/seller/components/SellerPayoutsView.d.ts +2 -2
  232. package/dist/features/seller/components/SellerPayoutsView.js +34 -68
  233. package/dist/features/seller/components/SellerPreOrdersView.d.ts +2 -2
  234. package/dist/features/seller/components/SellerPreOrdersView.js +49 -82
  235. package/dist/features/seller/components/SellerPrizeDrawsView.d.ts +2 -2
  236. package/dist/features/seller/components/SellerPrizeDrawsView.js +49 -82
  237. package/dist/features/seller/components/SellerProductShell.d.ts +1 -1
  238. package/dist/features/seller/components/SellerProductsView.d.ts +2 -2
  239. package/dist/features/seller/components/SellerProductsView.js +15 -10
  240. package/dist/features/seller/components/SellerShippingConfigsView.js +1 -1
  241. package/dist/features/seller/components/SellerSidebar.d.ts +0 -4
  242. package/dist/features/seller/components/SellerSidebar.js +0 -2
  243. package/dist/features/seller/components/SellerStoreCategoriesView.js +1 -1
  244. package/dist/features/seller/components/SellerTemplatesView.js +2 -2
  245. package/dist/features/seller/components/SellersListView.d.ts +1 -2
  246. package/dist/features/seller/components/analytics/SellerAnalyticsStats.d.ts +5 -0
  247. package/dist/features/seller/components/analytics/SellerAnalyticsStats.js +2 -8
  248. package/dist/features/seller/components/index.d.ts +0 -3
  249. package/dist/features/seller/components/index.js +0 -2
  250. package/dist/features/seller/server.d.ts +0 -1
  251. package/dist/features/seller/server.js +0 -1
  252. package/dist/features/shell/FormShell.d.ts +1 -1
  253. package/dist/features/shell/FormShell.js +7 -4
  254. package/dist/features/shell/field-groups/ImageFieldGroup.d.ts +18 -0
  255. package/dist/features/shell/field-groups/ImageFieldGroup.js +15 -0
  256. package/dist/features/shell/field-groups/SeoFieldGroup.d.ts +22 -0
  257. package/dist/features/shell/field-groups/SeoFieldGroup.js +16 -0
  258. package/dist/features/shell/field-groups/StatusFieldGroup.d.ts +35 -0
  259. package/dist/features/shell/field-groups/StatusFieldGroup.js +16 -0
  260. package/dist/features/shell/field-groups/TitleDescriptionGroup.d.ts +40 -0
  261. package/dist/features/shell/field-groups/TitleDescriptionGroup.js +16 -0
  262. package/dist/features/shell/field-groups/index.d.ts +13 -0
  263. package/dist/features/shell/field-groups/index.js +9 -0
  264. package/dist/features/shell/index.d.ts +2 -0
  265. package/dist/features/shell/index.js +1 -0
  266. package/dist/features/stores/components/StoreCapabilitiesGuideView.d.ts +1 -2
  267. package/dist/features/stores/components/StoreFinanceGuideView.d.ts +1 -2
  268. package/dist/features/stores/components/StoreHeader.js +2 -1
  269. package/dist/features/stores/components/StoreListingsGuideView.d.ts +1 -2
  270. package/dist/features/stores/components/StoreOrdersGuideView.d.ts +1 -2
  271. package/dist/features/stores/components/StoreScopedSearch.d.ts +16 -0
  272. package/dist/features/stores/components/StoreScopedSearch.js +27 -0
  273. package/dist/features/stores/components/StoreSettingsGuideView.d.ts +1 -2
  274. package/dist/features/stores/server.d.ts +0 -1
  275. package/dist/features/stores/server.js +0 -1
  276. package/dist/features/support/schemas/firestore.d.ts +22 -1
  277. package/dist/features/support/schemas/firestore.js +10 -0
  278. package/dist/features/wishlist/server.d.ts +0 -1
  279. package/dist/features/wishlist/server.js +0 -1
  280. package/dist/index.d.ts +9 -27
  281. package/dist/index.js +14 -50
  282. package/dist/next/routing/route-map.d.ts +8 -0
  283. package/dist/next/routing/route-map.js +4 -0
  284. package/dist/react/hooks/useListingTypeFlags.d.ts +32 -0
  285. package/dist/react/hooks/useListingTypeFlags.js +19 -0
  286. package/dist/security/index.d.ts +1 -1
  287. package/dist/security/index.js +1 -1
  288. package/dist/security/pii-redact.d.ts +8 -0
  289. package/dist/security/pii-redact.js +10 -1
  290. package/dist/seed/grouped-listings-seed-data.d.ts +4 -0
  291. package/dist/seed/products-preorders-seed-data.d.ts +4 -0
  292. package/dist/seed/products-prize-draws-seed-data.js +3 -0
  293. package/dist/seed/site-settings-seed-data.js +5 -5
  294. package/dist/seed/sub-listings-seed-data.d.ts +4 -0
  295. package/dist/server.d.ts +2 -0
  296. package/dist/server.js +4 -0
  297. package/dist/styles.css +54 -395
  298. package/dist/tailwind-utilities.css +1 -1
  299. package/dist/ui/components/BaseListingCard.d.ts +10 -0
  300. package/dist/ui/components/BaseListingCard.js +17 -1
  301. package/dist/ui/components/DetailPageGallery.d.ts +32 -0
  302. package/dist/ui/components/DetailPageGallery.js +47 -0
  303. package/dist/ui/components/DetailPageHero.d.ts +30 -0
  304. package/dist/ui/components/DetailPageHero.js +22 -0
  305. package/dist/ui/components/DetailPageTabs.d.ts +34 -0
  306. package/dist/ui/components/DetailPageTabs.js +38 -0
  307. package/dist/ui/components/HorizontalScroller.style.css +15 -2
  308. package/dist/ui/components/ListingLayout.d.ts +11 -2
  309. package/dist/ui/components/ListingLayout.js +12 -6
  310. package/dist/ui/components/PaginatedSelect.d.ts +66 -0
  311. package/dist/ui/components/PaginatedSelect.js +201 -0
  312. package/dist/ui/components/PaginatedSelect.style.css +254 -0
  313. package/dist/ui/components/Semantic.d.ts +0 -4
  314. package/dist/ui/components/Semantic.js +0 -2
  315. package/dist/ui/components/SettingsSection.d.ts +47 -0
  316. package/dist/ui/components/SettingsSection.js +38 -0
  317. package/dist/ui/components/index.style.css +1 -4
  318. package/dist/ui/index.d.ts +12 -14
  319. package/dist/ui/index.js +6 -7
  320. package/dist/utils/id-generators.d.ts +1 -18
  321. package/dist/utils/id-generators.js +51 -18
  322. package/dist/validation/schemas.d.ts +25 -0
  323. package/dist/validation/schemas.js +28 -0
  324. package/package.json +1 -1
@@ -0,0 +1,66 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Plus } from "lucide-react";
4
+ import { BulkActionBar, Button, ListingFilterDrawer, ListingToolbar, Pagination, SideDrawer, } from "../../../ui";
5
+ import { useBottomActions } from "../../layout";
6
+ import { useAdminListing } from "../hooks/useAdminListing";
7
+ import { AdminViewCards } from "./AdminViewCards";
8
+ import { DataTable } from "./DataTable";
9
+ export function DataListingView({ config, }) {
10
+ const effectiveInitialView = config.initialView ?? (config.hideTableView ? "grid" : "table");
11
+ const listing = useAdminListing({
12
+ ...config,
13
+ initialView: effectiveInitialView,
14
+ });
15
+ const { view, setView, table, panel, searchInput, setSearchInput, commitSearch, filterOpen, setFilterOpen, openFilters, applyFilters, clearFilters, pendingFilters, setPendingFilters, activeFilterCount, hasActiveState, resetAll, rows, isLoading, errorMessage, currentPage, totalPages, selection, } = listing;
16
+ const selectionContext = {
17
+ selectedIds: selection.selectedIds,
18
+ selectedCount: selection.selectedCount,
19
+ clearSelection: selection.clearSelection,
20
+ toggleSelect: selection.toggle,
21
+ rows,
22
+ openEditPanel: panel.openEditPanel,
23
+ };
24
+ const bulkActionItems = config.buildBulkActions?.(selectionContext);
25
+ // Mobile bulk bar
26
+ useBottomActions(selection.selectedCount > 0 && bulkActionItems
27
+ ? {
28
+ bulk: {
29
+ selectedCount: selection.selectedCount,
30
+ onClearSelection: selection.clearSelection,
31
+ actions: bulkActionItems,
32
+ },
33
+ }
34
+ : {});
35
+ const editorTitle = config.resolveEditorTitle
36
+ ? config.resolveEditorTitle({
37
+ isCreate: panel.isCreateOpen,
38
+ editId: panel.editId,
39
+ closePanel: panel.closePanel,
40
+ })
41
+ : panel.isCreateOpen
42
+ ? `Add ${config.title.replace(/s$/, "")}`
43
+ : `Edit ${config.title.replace(/s$/, "")}`;
44
+ const isEditorOpen = panel.isCreateOpen || panel.isEditOpen;
45
+ return (_jsxs("div", { className: config.className ?? "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: config.searchPlaceholder, onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get("sort") || config.defaultSort, sortOptions: config.sortOptions, onSortChange: (v) => table.set("sort", v), showTableView: !config.hideTableView, toggles: config.toggles, view: view, onViewChange: (v) => setView(v), onResetAll: resetAll, hasActiveState: hasActiveState, extra: config.primaryAction || config.toolbarExtra ? (_jsxs("div", { className: "flex items-center gap-2", children: [config.toolbarExtra, config.primaryAction && (_jsxs(Button, { size: "sm", onClick: () => config.primaryAction.onClick({
46
+ openCreatePanel: panel.openCreatePanel,
47
+ }), className: "flex items-center gap-1.5", children: [config.primaryAction.icon ?? _jsx(Plus, { className: "h-4 w-4" }), config.primaryAction.label] }))] })) : undefined }), config.renderAboveContent?.(), bulkActionItems && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: bulkActionItems })), 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-error/20 bg-error-surface px-4 py-3 text-sm text-error", children: errorMessage })), view === "table" ? (_jsx(DataTable, { columns: config.columns, rows: rows, isLoading: isLoading, emptyLabel: config.emptyLabel ?? `No ${config.title.toLowerCase()} found`, selectedIds: selection.selectedIdSet, onToggleSelect: selection.toggle, onToggleSelectAll: (next) => next
48
+ ? selection.setSelectedIds(rows.map((r) => r.id))
49
+ : selection.clearSelection(), getRowHref: config.getRowHref, onRowClick: config.onRowClick
50
+ ? (row) => config.onRowClick(row, {
51
+ openEditPanel: panel.openEditPanel,
52
+ })
53
+ : config.renderEditor
54
+ ? (row) => panel.openEditPanel(row.id)
55
+ : undefined, renderRowActions: config.renderRowActions })) : config.renderCards ? (config.renderCards(rows, view, selectionContext, isLoading)) : (_jsx(AdminViewCards, { rows: rows, view: view, isLoading: isLoading, emptyLabel: config.emptyLabel ?? `No ${config.title.toLowerCase()} found`, onRowClick: (row) => panel.openEditPanel(row.id), selectedIdSet: selection.selectedIdSet, onToggleSelect: selection.toggle }))] }), config.renderFilterPanel && (_jsx(ListingFilterDrawer, { open: filterOpen, onClose: () => setFilterOpen(false), onApply: applyFilters, onClear: clearFilters, activeCount: activeFilterCount, children: config.renderFilterPanel({
56
+ pendingFilters,
57
+ setPendingFilters,
58
+ applyFilters,
59
+ clearFilters,
60
+ }) })), config.renderEditor && (_jsx(SideDrawer, { isOpen: isEditorOpen, onClose: panel.closePanel, title: editorTitle, mode: panel.isCreateOpen ? "create" : "edit", children: isEditorOpen &&
61
+ config.renderEditor({
62
+ isCreate: panel.isCreateOpen,
63
+ editId: panel.editId,
64
+ closePanel: panel.closePanel,
65
+ }) }))] }));
66
+ }
@@ -1,8 +1,8 @@
1
1
  export { DataTable } from "./DataTable";
2
2
  export { QuickEditMenu } from "./QuickEditMenu";
3
3
  export type { QuickEditAction, QuickEditMenuProps } from "./QuickEditMenu";
4
- export { AdminListingScaffold } from "./AdminListingScaffold";
5
- export type { AdminListingScaffoldRow } from "./AdminListingScaffold";
4
+ export { DataListingView } from "./DataListingView";
5
+ export type { AdminListingScaffoldRow, ListingViewConfig, ListingSortOption, ListingPanelContext, ListingEditorContext, ListingSelectionContext, } from "./DataListingView";
6
6
  export { DashboardStatsGrid } from "./DashboardStats";
7
7
  export { AdminUsersView } from "./AdminUsersView";
8
8
  export type { AdminUsersViewProps } from "./AdminUsersView";
@@ -34,6 +34,14 @@ export { AdminAddressEditorView } from "./AdminAddressEditorView";
34
34
  export type { AdminAddressEditorViewProps } from "./AdminAddressEditorView";
35
35
  export { AdminPrizeDrawsView } from "./AdminPrizeDrawsView";
36
36
  export type { AdminPrizeDrawsViewProps } from "./AdminPrizeDrawsView";
37
+ export { AdminClassifiedView } from "./AdminClassifiedView";
38
+ export type { AdminClassifiedViewProps } from "./AdminClassifiedView";
39
+ export { AdminDigitalCodesView } from "./AdminDigitalCodesView";
40
+ export type { AdminDigitalCodesViewProps } from "./AdminDigitalCodesView";
41
+ export { AdminLiveView } from "./AdminLiveView";
42
+ export type { AdminLiveViewProps } from "./AdminLiveView";
43
+ export { AdminGroupedListingsView } from "./AdminGroupedListingsView";
44
+ export type { AdminGroupedListingsViewProps } from "./AdminGroupedListingsView";
37
45
  export { AdminBundlesView } from "./AdminBundlesView";
38
46
  export type { AdminBundlesViewProps } from "./AdminBundlesView";
39
47
  export { AdminBundleEditorView } from "./AdminBundleEditorView";
@@ -133,8 +141,6 @@ export { AdminSidebar } from "./AdminSidebar";
133
141
  export type { AdminSidebarProps, AdminNavItem, AdminNavGroup } from "./AdminSidebar";
134
142
  export { AdminTopBar } from "./AdminTopBar";
135
143
  export type { AdminTopBarProps } from "./AdminTopBar";
136
- export { DemoSeedView } from "./DemoSeedView";
137
- export type { DemoSeedViewProps } from "./DemoSeedView";
138
144
  export { AdminTeamView } from "./AdminTeamView";
139
145
  export type { AdminTeamViewProps } from "./AdminTeamView";
140
146
  export { AdminEmployeeEditorView } from "./AdminEmployeeEditorView";
@@ -1,6 +1,6 @@
1
1
  export { DataTable } from "./DataTable";
2
2
  export { QuickEditMenu } from "./QuickEditMenu";
3
- export { AdminListingScaffold } from "./AdminListingScaffold";
3
+ export { DataListingView } from "./DataListingView";
4
4
  export { DashboardStatsGrid } from "./DashboardStats";
5
5
  export { AdminUsersView } from "./AdminUsersView";
6
6
  export { AdminProductsView } from "./AdminProductsView";
@@ -18,6 +18,11 @@ export { AdminBrandEditorView } from "./AdminBrandEditorView";
18
18
  export { AdminAddressEditorView } from "./AdminAddressEditorView";
19
19
  // SB4-E 2026-05-14 — admin prize draws listing view.
20
20
  export { AdminPrizeDrawsView } from "./AdminPrizeDrawsView";
21
+ // W1-29 2026-05-23 — admin listing views for orphaned listing types (classified/digital-codes/live).
22
+ export { AdminClassifiedView } from "./AdminClassifiedView";
23
+ export { AdminDigitalCodesView } from "./AdminDigitalCodesView";
24
+ export { AdminLiveView } from "./AdminLiveView";
25
+ export { AdminGroupedListingsView } from "./AdminGroupedListingsView";
21
26
  // S-SBUNI-4 2026-05-13 — admin bundle CRUD views.
22
27
  export { AdminBundlesView } from "./AdminBundlesView";
23
28
  export { AdminBundleEditorView } from "./AdminBundleEditorView";
@@ -69,7 +74,6 @@ export { AdminReturnRequestsView } from "./AdminReturnRequestsView";
69
74
  export { AdminStoreAddressesView } from "./AdminStoreAddressesView";
70
75
  export { AdminSidebar } from "./AdminSidebar";
71
76
  export { AdminTopBar } from "./AdminTopBar";
72
- export { DemoSeedView } from "./DemoSeedView";
73
77
  export { AdminTeamView } from "./AdminTeamView";
74
78
  export { AdminEmployeeEditorView } from "./AdminEmployeeEditorView";
75
79
  export { AdminSupportTicketsView } from "./AdminSupportTicketsView";
@@ -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,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { Article, BaseListingCard, Div, Heading, Row, Span, Text, TextLink } from "../../../ui";
3
4
  import { THEME_CONSTANTS } from "../../../tokens";
@@ -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";
@@ -2,13 +2,10 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import React from "react";
4
4
  import { useMutation, useQuery } from "@tanstack/react-query";
5
- import { Alert, Button, Div, Heading, Input, RichTextEditor, Select, StackedViewShell, TagInput, Text, Toggle, } from "../../../ui";
5
+ import { Alert, Button, Div, Grid, Heading, Input, Label, RichTextEditor, Row, Select, Stack, StackedViewShell, TagInput, Text, Textarea, Toggle, } from "../../../ui";
6
6
  import { apiClient } from "../../../http";
7
7
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
8
8
  import { StepForm } from "../../shell";
9
- // --- Constants ---------------------------------------------------------------
10
- const CLS_PANEL_SM = "rounded-lg border border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-800 p-3 space-y-2";
11
- const CLS_PANEL_LG = "rounded-xl border border-zinc-200 dark:border-slate-700 p-4 space-y-4";
12
9
  const EVENT_TYPE_OPTIONS = [
13
10
  { label: "Sale", value: "sale" },
14
11
  { label: "Offer / Coupon", value: "offer" },
@@ -49,11 +46,11 @@ function FormFieldBuilder({ fields, setFields }) {
49
46
  const addField = () => setFields([...fields, { id: `field-${Date.now()}`, type: "text", label: "", required: false, order: fields.length }]);
50
47
  const removeField = (id) => setFields(fields.filter((f) => f.id !== id));
51
48
  const updateField = (id, patch) => setFields(fields.map((f) => (f.id === id ? { ...f, ...patch } : f)));
52
- return (_jsxs("div", { className: "space-y-3", children: [_jsx(Text, { className: "text-xs font-medium text-zinc-600 dark:text-zinc-400 uppercase tracking-wide", children: "Form fields" }), fields.length === 0 && (_jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "No fields yet. Add fields to collect responses from participants." })), fields.map((field, idx) => {
49
+ return (_jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "xs", weight: "medium", color: "muted", className: "uppercase tracking-wide", children: "Form fields" }), fields.length === 0 && (_jsx(Text, { size: "xs", color: "muted", children: "No fields yet. Add fields to collect responses from participants." })), fields.map((field, idx) => {
53
50
  const hasOptions = FIELD_TYPES_WITH_OPTIONS.includes(field.type);
54
51
  const isNumeric = field.type === "number" || field.type === "rating";
55
52
  const isText = field.type === "text" || field.type === "textarea" || field.type === "email";
56
- return (_jsxs("div", { className: "rounded-lg border border-zinc-200 dark:border-zinc-600 p-3 space-y-2 bg-white dark:bg-zinc-900", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsxs(Text, { className: "text-xs font-medium text-zinc-500 dark:text-zinc-400", children: ["Field ", idx + 1] }), _jsx("button", { type: "button", onClick: () => removeField(field.id), className: "text-zinc-400 hover:text-red-500 transition-colors text-lg leading-none px-1", "aria-label": "Remove field", children: "\u00D7" })] }), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-2", children: [_jsx(Select, { label: "Type", value: field.type, options: FORM_FIELD_TYPE_OPTIONS, onChange: (e) => updateField(field.id, { type: e.target.value, options: undefined }) }), _jsx(Input, { label: "Label", value: field.label, onChange: (e) => updateField(field.id, { label: e.target.value }), placeholder: "e.g. Describe your entry", required: true })] }), !hasOptions && field.type !== "date" && field.type !== "file" && field.type !== "rating" && (_jsx(Input, { label: "Placeholder (optional)", value: field.placeholder ?? "", onChange: (e) => updateField(field.id, { placeholder: e.target.value || undefined }), placeholder: "Hint shown inside the field" })), hasOptions && (_jsxs("div", { className: "space-y-1", children: [_jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "Options \u2014 one per line" }), _jsx("textarea", { className: "w-full rounded-lg border border-zinc-200 dark:border-zinc-600 bg-white dark:bg-zinc-800 text-sm text-zinc-800 dark:text-zinc-200 px-3 py-2 resize-y min-h-[72px] focus:outline-none focus:ring-2 focus:ring-primary/50", value: (field.options ?? []).join("\n"), onChange: (e) => updateField(field.id, { options: e.target.value.split("\n").map((s) => s.trim()).filter(Boolean) }), placeholder: "Option A\nOption B\nOption C" })] })), (isText || isNumeric) && (_jsxs("div", { className: "rounded bg-zinc-50 dark:bg-zinc-800 p-2 space-y-2", children: [_jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "Validation (optional)" }), _jsxs("div", { className: "grid grid-cols-2 gap-2", children: [isText && (_jsxs(_Fragment, { children: [_jsx(Input, { label: "Min length", type: "number", value: String(field.validation?.minLength ?? ""), onChange: (e) => updateField(field.id, { validation: { ...field.validation, minLength: e.target.value ? Number(e.target.value) : undefined } }), placeholder: "0" }), _jsx(Input, { label: "Max length", type: "number", value: String(field.validation?.maxLength ?? ""), onChange: (e) => updateField(field.id, { validation: { ...field.validation, maxLength: e.target.value ? Number(e.target.value) : undefined } }), placeholder: "500" })] })), isNumeric && (_jsxs(_Fragment, { children: [_jsx(Input, { label: "Min value", type: "number", value: String(field.validation?.min ?? ""), onChange: (e) => updateField(field.id, { validation: { ...field.validation, min: e.target.value ? Number(e.target.value) : undefined } }), placeholder: "0" }), _jsx(Input, { label: "Max value", type: "number", value: String(field.validation?.max ?? ""), onChange: (e) => updateField(field.id, { validation: { ...field.validation, max: e.target.value ? Number(e.target.value) : undefined } }), placeholder: "100" })] }))] }), field.type === "text" && (_jsx(Input, { label: "Pattern (regex, optional)", value: field.validation?.pattern ?? "", onChange: (e) => updateField(field.id, { validation: { ...field.validation, pattern: e.target.value || undefined } }), placeholder: "^[A-Z].*" }))] })), _jsx(Toggle, { checked: field.required, onChange: (v) => updateField(field.id, { required: v }), label: "Required" })] }, field.id));
53
+ return (_jsxs(Stack, { gap: "xs", surface: "default", rounded: "lg", border: "default", padding: "sm", children: [_jsxs(Row, { justify: "between", gap: "xs", children: [_jsxs(Text, { size: "xs", weight: "medium", color: "muted", children: ["Field ", idx + 1] }), _jsx("button", { type: "button", onClick: () => removeField(field.id), className: "text-zinc-400 hover:text-red-500 transition-colors text-lg leading-none px-1", "aria-label": "Remove field", children: "\u00D7" })] }), _jsxs(Grid, { cols: 2, gap: "xs", children: [_jsx(Select, { label: "Type", value: field.type, options: FORM_FIELD_TYPE_OPTIONS, onChange: (e) => updateField(field.id, { type: e.target.value, options: undefined }) }), _jsx(Input, { label: "Label", value: field.label, onChange: (e) => updateField(field.id, { label: e.target.value }), placeholder: "e.g. Describe your entry", required: true })] }), !hasOptions && field.type !== "date" && field.type !== "file" && field.type !== "rating" && (_jsx(Input, { label: "Placeholder (optional)", value: field.placeholder ?? "", onChange: (e) => updateField(field.id, { placeholder: e.target.value || undefined }), placeholder: "Hint shown inside the field" })), hasOptions && (_jsx(Textarea, { label: "Options \u2014 one per line", value: (field.options ?? []).join("\n"), onChange: (e) => updateField(field.id, { options: e.target.value.split("\n").map((s) => s.trim()).filter(Boolean) }), placeholder: "Option A\nOption B\nOption C", rows: 3 })), (isText || isNumeric) && (_jsxs(Stack, { gap: "xs", surface: "muted", rounded: "md", padding: "xs", children: [_jsx(Text, { size: "xs", color: "muted", children: "Validation (optional)" }), _jsxs(Grid, { gap: "xs", className: "grid-cols-2", children: [isText && (_jsxs(_Fragment, { children: [_jsx(Input, { label: "Min length", type: "number", value: String(field.validation?.minLength ?? ""), onChange: (e) => updateField(field.id, { validation: { ...field.validation, minLength: e.target.value ? Number(e.target.value) : undefined } }), placeholder: "0" }), _jsx(Input, { label: "Max length", type: "number", value: String(field.validation?.maxLength ?? ""), onChange: (e) => updateField(field.id, { validation: { ...field.validation, maxLength: e.target.value ? Number(e.target.value) : undefined } }), placeholder: "500" })] })), isNumeric && (_jsxs(_Fragment, { children: [_jsx(Input, { label: "Min value", type: "number", value: String(field.validation?.min ?? ""), onChange: (e) => updateField(field.id, { validation: { ...field.validation, min: e.target.value ? Number(e.target.value) : undefined } }), placeholder: "0" }), _jsx(Input, { label: "Max value", type: "number", value: String(field.validation?.max ?? ""), onChange: (e) => updateField(field.id, { validation: { ...field.validation, max: e.target.value ? Number(e.target.value) : undefined } }), placeholder: "100" })] }))] }), field.type === "text" && (_jsx(Input, { label: "Pattern (regex, optional)", value: field.validation?.pattern ?? "", onChange: (e) => updateField(field.id, { validation: { ...field.validation, pattern: e.target.value || undefined } }), placeholder: "^[A-Z].*" }))] })), _jsx(Toggle, { checked: field.required, onChange: (v) => updateField(field.id, { required: v }), label: "Required" })] }, field.id));
57
54
  }), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: addField, children: "+ Add field" })] }));
58
55
  }
59
56
  const POLL_VISIBILITY_OPTIONS = [
@@ -299,14 +296,14 @@ export function AdminEventEditorView({ eventId, onSaved, embedded, ...rest }) {
299
296
  return "End date is required";
300
297
  return null;
301
298
  },
302
- render: ({ values, onChange }) => (_jsxs("div", { className: "space-y-5", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Event Details" }), !isEdit && (_jsx(Select, { label: "Event type", value: values.type, options: EVENT_TYPE_OPTIONS, onChange: (e) => onChange({ type: e.target.value }) })), _jsx(Input, { label: "Title", value: values.title, onChange: (e) => {
299
+ render: ({ values, onChange }) => (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Event Details" }), !isEdit && (_jsx(Select, { label: "Event type", value: values.type, options: EVENT_TYPE_OPTIONS, onChange: (e) => onChange({ type: e.target.value }) })), _jsx(Input, { label: "Title", value: values.title, onChange: (e) => {
303
300
  const v = e.target.value;
304
301
  onChange({ title: v, ...(!slugManual && { slug: toEventSlug(v) }) });
305
- }, placeholder: "Charizard Flash Sale 2026", required: true }), _jsx(Input, { label: "Slug", value: values.slug, onChange: (e) => { setSlugManual(true); onChange({ slug: e.target.value }); }, placeholder: "event-charizard-flash-sale-2026", helperText: "Auto-generated from title. Must start with 'event-'." }), _jsxs(Div, { children: [_jsx("label", { className: "block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1", children: "Description" }), _jsx(RichTextEditor, { value: values.description, onChange: (v) => onChange({ description: v }), minHeightClassName: "min-h-[120px]", placeholder: "Describe this event\u2026" })] }), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: [_jsx(Input, { label: "Starts at", type: "datetime-local", value: values.startsAt, onChange: (e) => onChange({ startsAt: e.target.value }), required: true }), _jsx(Input, { label: "Ends at", type: "datetime-local", value: values.endsAt, onChange: (e) => onChange({ endsAt: e.target.value }), required: true })] }), _jsx(TagInput, { label: "Tags", value: values.tags, onChange: (t) => onChange({ tags: t }), placeholder: "e.g. pokemon, sale, 2026" })] })),
302
+ }, placeholder: "Charizard Flash Sale 2026", required: true }), _jsx(Input, { label: "Slug", value: values.slug, onChange: (e) => { setSlugManual(true); onChange({ slug: e.target.value }); }, placeholder: "event-charizard-flash-sale-2026", helperText: "Auto-generated from title. Must start with 'event-'." }), _jsxs(Stack, { gap: "xs", children: [_jsx(Label, { children: "Description" }), _jsx(RichTextEditor, { value: values.description, onChange: (v) => onChange({ description: v }), minHeightClassName: "min-h-[120px]", placeholder: "Describe this event\u2026" })] }), _jsxs(Grid, { cols: 2, gap: "sm", children: [_jsx(Input, { label: "Starts at", type: "datetime-local", value: values.startsAt, onChange: (e) => onChange({ startsAt: e.target.value }), required: true }), _jsx(Input, { label: "Ends at", type: "datetime-local", value: values.endsAt, onChange: (e) => onChange({ endsAt: e.target.value }), required: true })] }), _jsx(TagInput, { label: "Tags", value: values.tags, onChange: (t) => onChange({ tags: t }), placeholder: "e.g. pokemon, sale, 2026" })] })),
306
303
  },
307
304
  {
308
305
  label: "Media",
309
- render: ({ values, onChange }) => (_jsxs("div", { className: "space-y-5", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Media" }), _jsx(Input, { label: "Cover Image URL (optional)", value: values.coverImageUrl, onChange: (e) => onChange({ coverImageUrl: e.target.value }), placeholder: "https://\u2026", helperText: "Direct link to the event cover image." })] })),
306
+ render: ({ values, onChange }) => (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Media" }), _jsx(Input, { label: "Cover Image URL (optional)", value: values.coverImageUrl, onChange: (e) => onChange({ coverImageUrl: e.target.value }), placeholder: "https://\u2026", helperText: "Direct link to the event cover image." })] })),
310
307
  },
311
308
  {
312
309
  label: "Settings",
@@ -319,7 +316,7 @@ export function AdminEventEditorView({ eventId, onSaved, embedded, ...rest }) {
319
316
  return "Poll events require at least 2 options";
320
317
  return null;
321
318
  },
322
- render: ({ values, onChange }) => (_jsxs("div", { className: "space-y-5", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Event Settings" }), isEdit && (_jsx(Select, { label: "Status", value: values.status, options: EVENT_STATUS_OPTIONS, onChange: (e) => onChange({ status: e.target.value }) })), values.createdBy && (_jsxs(Div, { children: [_jsx(Text, { className: "text-sm font-medium mb-1", children: "Created by" }), _jsx(Text, { className: "text-sm text-[var(--appkit-color-text-muted)]", children: values.createdBy })] })), values.type === "sale" && (_jsxs("div", { className: CLS_PANEL_SM, children: [_jsx(Text, { className: "text-sm font-semibold text-zinc-700 dark:text-zinc-300", children: "Sale configuration" }), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: [_jsx(Input, { label: "Discount %", type: "number", value: values.discountPercent, onChange: (e) => onChange({ discountPercent: e.target.value }), placeholder: "10" }), _jsx(Input, { label: "Banner text (optional)", value: values.saleBannerText, onChange: (e) => onChange({ saleBannerText: e.target.value }), placeholder: "Limited time \u2014 ends Sunday!" })] })] })), values.type === "offer" && (_jsxs("div", { className: CLS_PANEL_SM, children: [_jsx(Text, { className: "text-sm font-semibold text-zinc-700 dark:text-zinc-300", children: "Offer configuration" }), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: [_jsx(Input, { label: "Coupon ID", value: values.couponId, onChange: (e) => onChange({ couponId: e.target.value }), placeholder: "Firestore coupon document ID", required: true }), _jsx(Input, { label: "Display code", value: values.displayCode, onChange: (e) => onChange({ displayCode: e.target.value }), placeholder: "CHARIZARD25", required: true })] }), _jsx(Input, { label: "Banner text (optional)", value: values.offerBannerText, onChange: (e) => onChange({ offerBannerText: e.target.value }), placeholder: "Use CHARIZARD25 at checkout" })] })), values.type === "poll" && (_jsxs("div", { className: CLS_PANEL_LG, children: [_jsx(Text, { className: "text-sm font-semibold text-zinc-700 dark:text-zinc-300", children: "Poll configuration" }), _jsxs("div", { className: "space-y-2", children: [_jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "Options (minimum 2)" }), values.pollOptions.map((opt, idx) => (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex-1", children: _jsx(Input, { value: opt.label, onChange: (e) => onChange({ pollOptions: values.pollOptions.map((o) => o.id === opt.id ? { ...o, label: e.target.value } : o) }), placeholder: `Option ${idx + 1}` }) }), values.pollOptions.length > 2 && (_jsx("button", { type: "button", onClick: () => onChange({ pollOptions: values.pollOptions.filter((o) => o.id !== opt.id) }), className: "text-zinc-400 hover:text-red-500 transition-colors px-2 py-1 text-lg leading-none", "aria-label": "Remove option", children: "\u00D7" }))] }, opt.id))), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => onChange({ pollOptions: [...values.pollOptions, { id: `opt${Date.now()}`, label: "" }] }), children: "+ Add option" })] }), _jsx(Select, { label: "Results visibility", value: values.resultsVisibility, options: POLL_VISIBILITY_OPTIONS, onChange: (e) => onChange({ resultsVisibility: e.target.value }) }), _jsxs("div", { className: "space-y-3", children: [_jsx(Toggle, { checked: values.allowMultiSelect, onChange: (v) => onChange({ allowMultiSelect: v }), label: "Allow multi-select" }), _jsx(Toggle, { checked: values.allowComment, onChange: (v) => onChange({ allowComment: v }), label: "Allow comment with vote" })] })] })), values.type === "survey" && (_jsxs("div", { className: CLS_PANEL_LG, children: [_jsx(Text, { className: "text-sm font-semibold text-zinc-700 dark:text-zinc-300", children: "Survey configuration" }), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: [_jsx(Input, { label: "Max entries per user", type: "number", value: values.maxEntriesPerUser, onChange: (e) => onChange({ maxEntriesPerUser: e.target.value }), placeholder: "1" }), values.hasPointSystem && (_jsx(Input, { label: "Points label", value: values.pointsLabel, onChange: (e) => onChange({ pointsLabel: e.target.value }), placeholder: "Points" }))] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Toggle, { checked: values.requireLogin, onChange: (v) => onChange({ requireLogin: v }), label: "Require login to participate" }), _jsx(Toggle, { checked: values.hasLeaderboard, onChange: (v) => onChange({ hasLeaderboard: v }), label: "Show leaderboard" }), _jsx(Toggle, { checked: values.hasPointSystem, onChange: (v) => onChange({ hasPointSystem: v }), label: "Enable point system" }), _jsx(Toggle, { checked: values.entryReviewRequired, onChange: (v) => onChange({ entryReviewRequired: v }), label: "Require employee review before entry is approved" })] }), _jsx(FormFieldBuilder, { fields: values.surveyFields, setFields: (f) => onChange({ surveyFields: f }) })] })), values.type === "feedback" && (_jsxs("div", { className: CLS_PANEL_LG, children: [_jsx(Text, { className: "text-sm font-semibold text-zinc-700 dark:text-zinc-300", children: "Feedback configuration" }), _jsx(Toggle, { checked: values.anonymous, onChange: (v) => onChange({ anonymous: v }), label: "Allow anonymous submissions" }), _jsx(FormFieldBuilder, { fields: values.feedbackFields, setFields: (f) => onChange({ feedbackFields: f }) })] }))] })),
319
+ render: ({ values, onChange }) => (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Event Settings" }), isEdit && (_jsx(Select, { label: "Status", value: values.status, options: EVENT_STATUS_OPTIONS, onChange: (e) => onChange({ status: e.target.value }) })), values.createdBy && (_jsxs(Stack, { gap: "none", children: [_jsx(Text, { size: "sm", weight: "medium", className: "mb-1", children: "Created by" }), _jsx(Text, { size: "sm", color: "muted", children: values.createdBy })] })), values.type === "sale" && (_jsxs(Stack, { gap: "xs", surface: "muted", rounded: "lg", border: "default", padding: "sm", children: [_jsx(Text, { size: "sm", weight: "semibold", color: "muted", children: "Sale configuration" }), _jsxs(Grid, { cols: 2, gap: "sm", children: [_jsx(Input, { label: "Discount %", type: "number", value: values.discountPercent, onChange: (e) => onChange({ discountPercent: e.target.value }), placeholder: "10" }), _jsx(Input, { label: "Banner text (optional)", value: values.saleBannerText, onChange: (e) => onChange({ saleBannerText: e.target.value }), placeholder: "Limited time \u2014 ends Sunday!" })] })] })), values.type === "offer" && (_jsxs(Stack, { gap: "xs", surface: "muted", rounded: "lg", border: "default", padding: "sm", children: [_jsx(Text, { size: "sm", weight: "semibold", color: "muted", children: "Offer configuration" }), _jsxs(Grid, { cols: 2, gap: "sm", children: [_jsx(Input, { label: "Coupon ID", value: values.couponId, onChange: (e) => onChange({ couponId: e.target.value }), placeholder: "Firestore coupon document ID", required: true }), _jsx(Input, { label: "Display code", value: values.displayCode, onChange: (e) => onChange({ displayCode: e.target.value }), placeholder: "CHARIZARD25", required: true })] }), _jsx(Input, { label: "Banner text (optional)", value: values.offerBannerText, onChange: (e) => onChange({ offerBannerText: e.target.value }), placeholder: "Use CHARIZARD25 at checkout" })] })), values.type === "poll" && (_jsxs(Stack, { gap: "md", rounded: "xl", border: "default", padding: "md", children: [_jsx(Text, { size: "sm", weight: "semibold", color: "muted", children: "Poll configuration" }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "xs", color: "muted", children: "Options (minimum 2)" }), values.pollOptions.map((opt, idx) => (_jsxs(Row, { gap: "xs", children: [_jsx(Div, { className: "flex-1", children: _jsx(Input, { value: opt.label, onChange: (e) => onChange({ pollOptions: values.pollOptions.map((o) => o.id === opt.id ? { ...o, label: e.target.value } : o) }), placeholder: `Option ${idx + 1}` }) }), values.pollOptions.length > 2 && (_jsx("button", { type: "button", onClick: () => onChange({ pollOptions: values.pollOptions.filter((o) => o.id !== opt.id) }), className: "text-zinc-400 hover:text-red-500 transition-colors px-2 py-1 text-lg leading-none", "aria-label": "Remove option", children: "\u00D7" }))] }, opt.id))), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => onChange({ pollOptions: [...values.pollOptions, { id: `opt${Date.now()}`, label: "" }] }), children: "+ Add option" })] }), _jsx(Select, { label: "Results visibility", value: values.resultsVisibility, options: POLL_VISIBILITY_OPTIONS, onChange: (e) => onChange({ resultsVisibility: e.target.value }) }), _jsxs(Stack, { gap: "sm", children: [_jsx(Toggle, { checked: values.allowMultiSelect, onChange: (v) => onChange({ allowMultiSelect: v }), label: "Allow multi-select" }), _jsx(Toggle, { checked: values.allowComment, onChange: (v) => onChange({ allowComment: v }), label: "Allow comment with vote" })] })] })), values.type === "survey" && (_jsxs(Stack, { gap: "md", rounded: "xl", border: "default", padding: "md", children: [_jsx(Text, { size: "sm", weight: "semibold", color: "muted", children: "Survey configuration" }), _jsxs(Grid, { cols: 2, gap: "sm", children: [_jsx(Input, { label: "Max entries per user", type: "number", value: values.maxEntriesPerUser, onChange: (e) => onChange({ maxEntriesPerUser: e.target.value }), placeholder: "1" }), values.hasPointSystem && (_jsx(Input, { label: "Points label", value: values.pointsLabel, onChange: (e) => onChange({ pointsLabel: e.target.value }), placeholder: "Points" }))] }), _jsxs(Stack, { gap: "xs", children: [_jsx(Toggle, { checked: values.requireLogin, onChange: (v) => onChange({ requireLogin: v }), label: "Require login to participate" }), _jsx(Toggle, { checked: values.hasLeaderboard, onChange: (v) => onChange({ hasLeaderboard: v }), label: "Show leaderboard" }), _jsx(Toggle, { checked: values.hasPointSystem, onChange: (v) => onChange({ hasPointSystem: v }), label: "Enable point system" }), _jsx(Toggle, { checked: values.entryReviewRequired, onChange: (v) => onChange({ entryReviewRequired: v }), label: "Require employee review before entry is approved" })] }), _jsx(FormFieldBuilder, { fields: values.surveyFields, setFields: (f) => onChange({ surveyFields: f }) })] })), values.type === "feedback" && (_jsxs(Stack, { gap: "md", rounded: "xl", border: "default", padding: "md", children: [_jsx(Text, { size: "sm", weight: "semibold", color: "muted", children: "Feedback configuration" }), _jsx(Toggle, { checked: values.anonymous, onChange: (v) => onChange({ anonymous: v }), label: "Allow anonymous submissions" }), _jsx(FormFieldBuilder, { fields: values.feedbackFields, setFields: (f) => onChange({ feedbackFields: f }) })] }))] })),
323
320
  },
324
321
  {
325
322
  label: "Raffle / Spin",
@@ -327,14 +324,14 @@ export function AdminEventEditorView({ eventId, onSaved, embedded, ...rest }) {
327
324
  const isRaffleType = values.type === "raffle" || values.type === "spin_wheel";
328
325
  const showRaffleConfig = isRaffleType || values.hasRaffle;
329
326
  const isSpinMode = values.type === "spin_wheel" || values.raffleType === "spin_wheel";
330
- return (_jsxs("div", { className: "space-y-5", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Raffle & Spin Wheel" }), !isRaffleType && (_jsx(Toggle, { checked: values.hasRaffle, onChange: (v) => onChange({ hasRaffle: v }), label: "Attach a raffle to this event" })), !isRaffleType && !values.hasRaffle && (_jsx(Text, { className: "text-sm text-[var(--appkit-color-text-muted)]", children: "Enable the toggle above to attach a raffle draw to this event. Not applicable for this event type by default." })), showRaffleConfig && (_jsxs("div", { className: CLS_PANEL_LG, children: [_jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: [_jsx(Select, { label: "Raffle type", value: values.type === "spin_wheel" ? "spin_wheel" : values.raffleType, options: RAFFLE_TYPE_OPTIONS, onChange: (e) => onChange({ raffleType: e.target.value }), disabled: values.type === "spin_wheel" }), _jsx(Input, { label: "Top N (for top-N raffle types)", type: "number", value: values.raffleTopN, onChange: (e) => onChange({ raffleTopN: e.target.value }), placeholder: "10" })] }), _jsx(Input, { label: "Prize description", value: values.rafflePrize, onChange: (e) => onChange({ rafflePrize: e.target.value }), placeholder: "\u20B92,000 store credit + exclusive Pikachu sticker" }), _jsx(Input, { label: "Coupon ID for winner (optional)", value: values.rafflePrizeCouponId, onChange: (e) => onChange({ rafflePrizeCouponId: e.target.value }), placeholder: "coupon-vip-winner-2026" }), isSpinMode && (_jsxs("div", { className: "rounded-lg border border-zinc-200 dark:border-slate-700 p-3 space-y-3", children: [_jsx(Text, { className: "text-xs font-medium text-zinc-600 dark:text-zinc-300", children: "Spin prizes (weighted random)" }), values.spinPrizes.length === 0 && (_jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "No spin prizes yet. Add at least one to enable spinning." })), values.spinPrizes.map((p) => (_jsxs("div", { className: "grid grid-cols-12 gap-2 items-end", children: [_jsx("div", { className: "col-span-5", children: _jsx(Input, { label: "Label", value: p.label, onChange: (e) => onChange({ spinPrizes: values.spinPrizes.map((sp) => sp.id === p.id ? { ...sp, label: e.target.value } : sp) }), placeholder: "\u20B9100 off" }) }), _jsx("div", { className: "col-span-3", children: _jsx(Input, { label: "Coupon ID", value: p.couponId ?? "", onChange: (e) => onChange({ spinPrizes: values.spinPrizes.map((sp) => sp.id === p.id ? { ...sp, couponId: e.target.value || undefined } : sp) }) }) }), _jsx("div", { className: "col-span-2", children: _jsx(Input, { label: "Weight", type: "number", value: String(p.weight), onChange: (e) => onChange({ spinPrizes: values.spinPrizes.map((sp) => sp.id === p.id ? { ...sp, weight: Number(e.target.value) || 0 } : sp) }) }) }), _jsx("div", { className: "col-span-1 flex items-center justify-center pb-2", children: _jsx(Toggle, { checked: p.isActive, onChange: (v) => onChange({ spinPrizes: values.spinPrizes.map((sp) => sp.id === p.id ? { ...sp, isActive: v } : sp) }), label: "" }) }), _jsx("div", { className: "col-span-1 flex items-center justify-center pb-2", children: _jsx("button", { type: "button", onClick: () => onChange({ spinPrizes: values.spinPrizes.filter((sp) => sp.id !== p.id) }), className: "text-zinc-400 hover:text-red-500 text-lg leading-none px-2", "aria-label": "Remove prize", children: "\u00D7" }) })] }, p.id))), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => onChange({ spinPrizes: [...values.spinPrizes, { id: `prize-${Date.now()}`, label: "", couponId: undefined, weight: 1, isActive: true }] }), children: "+ Add spin prize" }), _jsx(Input, { label: "Max spins per user", type: "number", value: values.spinMaxPerUser, onChange: (e) => onChange({ spinMaxPerUser: e.target.value }), placeholder: "1" }), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: [_jsx(Input, { label: "Spin window start", type: "datetime-local", value: values.spinWindowStart, onChange: (e) => onChange({ spinWindowStart: e.target.value }) }), _jsx(Input, { label: "Spin window end", type: "datetime-local", value: values.spinWindowEnd, onChange: (e) => onChange({ spinWindowEnd: e.target.value }) })] })] })), isEdit && (_jsxs("div", { className: "rounded-lg border border-amber-200 bg-amber-50 dark:border-amber-700 dark:bg-amber-900/20 p-3 space-y-2", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx(Text, { className: "text-sm font-medium text-amber-900 dark:text-amber-100", children: raffleWinnerName ? `Winner: ${raffleWinnerName}` : "Raffle not yet triggered" }), _jsx(Button, { type: "button", variant: "primary", size: "sm", onClick: () => triggerRaffleMutation.mutate(), disabled: triggerRaffleMutation.isPending || Boolean(raffleWinnerName), children: triggerRaffleMutation.isPending ? "Triggering…" : raffleWinnerName ? "Already triggered" : "Trigger Raffle Now" })] }), raffleEntryCount !== null && _jsxs(Text, { className: "text-xs text-amber-800 dark:text-amber-200", children: ["Pool size: ", raffleEntryCount] }), raffleGithubUrl && _jsxs(Text, { className: "text-xs text-amber-800 dark:text-amber-200 break-all", children: ["Fairness proof: ", raffleGithubUrl] }), triggerMessage && _jsx(Text, { className: "text-xs text-amber-900 dark:text-amber-100", children: triggerMessage })] }))] }))] }));
327
+ return (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Raffle & Spin Wheel" }), !isRaffleType && (_jsx(Toggle, { checked: values.hasRaffle, onChange: (v) => onChange({ hasRaffle: v }), label: "Attach a raffle to this event" })), !isRaffleType && !values.hasRaffle && (_jsx(Text, { size: "sm", color: "muted", children: "Enable the toggle above to attach a raffle draw to this event. Not applicable for this event type by default." })), showRaffleConfig && (_jsxs(Stack, { gap: "md", rounded: "xl", border: "default", padding: "md", children: [_jsxs(Grid, { cols: 2, gap: "sm", children: [_jsx(Select, { label: "Raffle type", value: values.type === "spin_wheel" ? "spin_wheel" : values.raffleType, options: RAFFLE_TYPE_OPTIONS, onChange: (e) => onChange({ raffleType: e.target.value }), disabled: values.type === "spin_wheel" }), _jsx(Input, { label: "Top N (for top-N raffle types)", type: "number", value: values.raffleTopN, onChange: (e) => onChange({ raffleTopN: e.target.value }), placeholder: "10" })] }), _jsx(Input, { label: "Prize description", value: values.rafflePrize, onChange: (e) => onChange({ rafflePrize: e.target.value }), placeholder: "\u20B92,000 store credit + exclusive Pikachu sticker" }), _jsx(Input, { label: "Coupon ID for winner (optional)", value: values.rafflePrizeCouponId, onChange: (e) => onChange({ rafflePrizeCouponId: e.target.value }), placeholder: "coupon-vip-winner-2026" }), isSpinMode && (_jsxs(Stack, { gap: "sm", rounded: "lg", border: "default", padding: "sm", children: [_jsx(Text, { size: "xs", weight: "medium", color: "muted", children: "Spin prizes (weighted random)" }), values.spinPrizes.length === 0 && (_jsx(Text, { size: "xs", color: "muted", children: "No spin prizes yet. Add at least one to enable spinning." })), values.spinPrizes.map((p) => (_jsxs(Grid, { gap: "xs", className: "grid-cols-12 items-end", children: [_jsx(Div, { className: "col-span-5", children: _jsx(Input, { label: "Label", value: p.label, onChange: (e) => onChange({ spinPrizes: values.spinPrizes.map((sp) => sp.id === p.id ? { ...sp, label: e.target.value } : sp) }), placeholder: "\u20B9100 off" }) }), _jsx(Div, { className: "col-span-3", children: _jsx(Input, { label: "Coupon ID", value: p.couponId ?? "", onChange: (e) => onChange({ spinPrizes: values.spinPrizes.map((sp) => sp.id === p.id ? { ...sp, couponId: e.target.value || undefined } : sp) }) }) }), _jsx(Div, { className: "col-span-2", children: _jsx(Input, { label: "Weight", type: "number", value: String(p.weight), onChange: (e) => onChange({ spinPrizes: values.spinPrizes.map((sp) => sp.id === p.id ? { ...sp, weight: Number(e.target.value) || 0 } : sp) }) }) }), _jsx(Row, { centered: true, className: "col-span-1 pb-2", children: _jsx(Toggle, { checked: p.isActive, onChange: (v) => onChange({ spinPrizes: values.spinPrizes.map((sp) => sp.id === p.id ? { ...sp, isActive: v } : sp) }), label: "" }) }), _jsx(Row, { centered: true, className: "col-span-1 pb-2", children: _jsx("button", { type: "button", onClick: () => onChange({ spinPrizes: values.spinPrizes.filter((sp) => sp.id !== p.id) }), className: "text-zinc-400 hover:text-red-500 text-lg leading-none px-2", "aria-label": "Remove prize", children: "\u00D7" }) })] }, p.id))), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => onChange({ spinPrizes: [...values.spinPrizes, { id: `prize-${Date.now()}`, label: "", couponId: undefined, weight: 1, isActive: true }] }), children: "+ Add spin prize" }), _jsx(Input, { label: "Max spins per user", type: "number", value: values.spinMaxPerUser, onChange: (e) => onChange({ spinMaxPerUser: e.target.value }), placeholder: "1" }), _jsxs(Grid, { cols: 2, gap: "sm", children: [_jsx(Input, { label: "Spin window start", type: "datetime-local", value: values.spinWindowStart, onChange: (e) => onChange({ spinWindowStart: e.target.value }) }), _jsx(Input, { label: "Spin window end", type: "datetime-local", value: values.spinWindowEnd, onChange: (e) => onChange({ spinWindowEnd: e.target.value }) })] })] })), isEdit && (_jsxs(Stack, { gap: "xs", rounded: "lg", padding: "sm", className: "border border-amber-200 bg-amber-50 dark:border-amber-700 dark:bg-amber-900/20", children: [_jsxs(Row, { justify: "between", gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", className: "text-amber-900 dark:text-amber-100", children: raffleWinnerName ? `Winner: ${raffleWinnerName}` : "Raffle not yet triggered" }), _jsx(Button, { type: "button", variant: "primary", size: "sm", onClick: () => triggerRaffleMutation.mutate(), disabled: triggerRaffleMutation.isPending || Boolean(raffleWinnerName), children: triggerRaffleMutation.isPending ? "Triggering…" : raffleWinnerName ? "Already triggered" : "Trigger Raffle Now" })] }), raffleEntryCount !== null && _jsxs(Text, { size: "xs", className: "text-amber-800 dark:text-amber-200", children: ["Pool size: ", raffleEntryCount] }), raffleGithubUrl && _jsxs(Text, { size: "xs", className: "break-all text-amber-800 dark:text-amber-200", children: ["Fairness proof: ", raffleGithubUrl] }), triggerMessage && _jsx(Text, { size: "xs", className: "text-amber-900 dark:text-amber-100", children: triggerMessage })] }))] }))] }));
331
328
  },
332
329
  },
333
330
  ];
334
331
  const alertSection = eventQuery.error ? (_jsx(Alert, { variant: "error", title: "Could not load event", children: eventQuery.error instanceof Error ? eventQuery.error.message : "Unknown error" })) : null;
335
- const formContent = (_jsxs("div", { className: "space-y-4", children: [alertSection, _jsx(StepForm, { steps: steps, values: draft, onChange: update, onComplete: () => { saveMutation.mutate(); }, formId: "admin-event", currentStep: currentStep, onStepChange: setCurrentStep, completeLabel: isEdit ? "Save Changes" : "Create Event", isLoading: isLoading }), saveMessage && (_jsx(Alert, { variant: saveMessage.toLowerCase().includes("fail") || saveMessage.toLowerCase().includes("error") ? "error" : "success", title: "Save status", children: saveMessage }))] }));
332
+ const formContent = (_jsxs(Stack, { gap: "sm", children: [alertSection, _jsx(StepForm, { steps: steps, values: draft, onChange: update, onComplete: () => { saveMutation.mutate(); }, formId: "admin-event", currentStep: currentStep, onStepChange: setCurrentStep, completeLabel: isEdit ? "Save Changes" : "Create Event", isLoading: isLoading }), saveMessage && (_jsx(Alert, { variant: saveMessage.toLowerCase().includes("fail") || saveMessage.toLowerCase().includes("error") ? "error" : "success", title: "Save status", children: saveMessage }))] }));
336
333
  if (embedded) {
337
- return _jsx("div", { className: "overflow-y-auto p-4", children: formContent });
334
+ return _jsx(Div, { className: "overflow-y-auto p-4", children: formContent });
338
335
  }
339
336
  return (_jsx(StackedViewShell, { portal: "admin", ...rest, title: isEdit ? "Edit Event" : "Create Event", sections: [formContent] }));
340
337
  }