@mohasinac/appkit 4.30.18 → 4.31.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 (557) hide show
  1. package/dist/_internal/client/features/digital-code/CodeRevealPanel.js +5 -2
  2. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +3 -3
  3. package/dist/_internal/client/features/layout/useSidebarSearch.d.ts +21 -5
  4. package/dist/_internal/client/features/layout/useSidebarSearch.js +27 -6
  5. package/dist/_internal/client/features/lottery/LotteryAdminEditView.d.ts +23 -3
  6. package/dist/_internal/client/features/lottery/LotteryAdminEditView.js +106 -86
  7. package/dist/_internal/client/features/lottery/LotteryPullForm.d.ts +16 -5
  8. package/dist/_internal/client/features/lottery/LotteryPullForm.js +65 -40
  9. package/dist/_internal/client/features/maintenance/views/AnalysisRunnerView.js +5 -2
  10. package/dist/_internal/client/features/maintenance/views/CloudLogsListView.js +11 -3
  11. package/dist/_internal/client/hand-mode/HandModeProvider.js +2 -0
  12. package/dist/_internal/server/features/auctions/actions.js +14 -3
  13. package/dist/_internal/server/features/auctions/service.js +1 -1
  14. package/dist/_internal/server/features/auth/permissions.d.ts +2 -0
  15. package/dist/_internal/server/features/auth/permissions.js +3 -2
  16. package/dist/_internal/server/features/blog/data.js +2 -2
  17. package/dist/_internal/server/features/blog/service.js +3 -3
  18. package/dist/_internal/server/features/brands/data.js +1 -1
  19. package/dist/_internal/server/features/brands/service.js +3 -3
  20. package/dist/_internal/server/features/bundles/actions.js +6 -1
  21. package/dist/_internal/server/features/bundles/data.js +21 -4
  22. package/dist/_internal/server/features/cart/data.js +3 -1
  23. package/dist/_internal/server/features/cart/service.js +13 -2
  24. package/dist/_internal/server/features/categories/data.js +26 -6
  25. package/dist/_internal/server/features/classified/index.d.ts +0 -1
  26. package/dist/_internal/server/features/classified/index.js +0 -1
  27. package/dist/_internal/server/features/digital-code/index.d.ts +0 -1
  28. package/dist/_internal/server/features/digital-code/index.js +0 -1
  29. package/dist/_internal/server/features/events/actions.js +17 -4
  30. package/dist/_internal/server/features/events/data.js +1 -1
  31. package/dist/_internal/server/features/events/service.js +1 -1
  32. package/dist/_internal/server/features/grouped/data.js +7 -2
  33. package/dist/_internal/server/features/item-requests/data.js +1 -1
  34. package/dist/_internal/server/features/live/index.d.ts +0 -1
  35. package/dist/_internal/server/features/live/index.js +0 -1
  36. package/dist/_internal/server/features/lottery/actions.js +2 -2
  37. package/dist/_internal/server/features/lottery/data.js +1 -1
  38. package/dist/_internal/server/features/orders/actions.js +7 -7
  39. package/dist/_internal/server/features/orders/data.d.ts +1 -1
  40. package/dist/_internal/server/features/orders/data.js +14 -2
  41. package/dist/_internal/server/features/orders/service.js +1 -1
  42. package/dist/_internal/server/features/pre-orders/service.js +1 -1
  43. package/dist/_internal/server/features/prize-draws/actions.js +1 -1
  44. package/dist/_internal/server/features/products/data.js +21 -6
  45. package/dist/_internal/server/features/products/list-public.d.ts +9 -0
  46. package/dist/_internal/server/features/products/list-public.js +95 -7
  47. package/dist/_internal/server/features/products/service.js +1 -1
  48. package/dist/_internal/server/features/promotions/actions.js +1 -1
  49. package/dist/_internal/server/features/promotions/data.js +1 -1
  50. package/dist/_internal/server/features/promotions/service.js +1 -1
  51. package/dist/_internal/server/features/reviews/data.d.ts +1 -1
  52. package/dist/_internal/server/features/reviews/data.js +6 -1
  53. package/dist/_internal/server/features/reviews/og-data.js +1 -1
  54. package/dist/_internal/server/features/shared/listing-data-factory.js +7 -2
  55. package/dist/_internal/server/features/site-settings/adapters.d.ts +2 -2
  56. package/dist/_internal/server/features/site-settings/adapters.js +8 -5
  57. package/dist/_internal/server/features/stores/data.js +1 -1
  58. package/dist/_internal/server/features/sublisting-categories/data.js +1 -1
  59. package/dist/_internal/server/features/tester/visibility.d.ts +2 -1
  60. package/dist/_internal/server/features/tester/visibility.js +2 -2
  61. package/dist/_internal/server/functions/scheduled.d.ts +3 -1
  62. package/dist/_internal/server/functions/scheduled.js +27 -1
  63. package/dist/_internal/server/jobs/core/auctionSettlement.js +6 -1
  64. package/dist/_internal/server/jobs/core/hardBanCascade.js +4 -0
  65. package/dist/_internal/server/jobs/core/index.d.ts +2 -0
  66. package/dist/_internal/server/jobs/core/index.js +2 -0
  67. package/dist/_internal/server/jobs/core/onOrderStatusChange.js +7 -15
  68. package/dist/_internal/server/jobs/core/pageViewPrune.d.ts +10 -0
  69. package/dist/_internal/server/jobs/core/pageViewPrune.js +44 -0
  70. package/dist/_internal/server/jobs/core/pageViewRollup.d.ts +2 -0
  71. package/dist/_internal/server/jobs/core/pageViewRollup.js +87 -0
  72. package/dist/_internal/server/jobs/core/revenueRollup.js +7 -1
  73. package/dist/_internal/server/jobs/handlers/index.d.ts +2 -0
  74. package/dist/_internal/server/jobs/handlers/index.js +2 -0
  75. package/dist/_internal/server/jobs/handlers/pageViewPrune.d.ts +2 -0
  76. package/dist/_internal/server/jobs/handlers/pageViewPrune.js +2 -0
  77. package/dist/_internal/server/jobs/handlers/pageViewRollup.d.ts +2 -0
  78. package/dist/_internal/server/jobs/handlers/pageViewRollup.js +2 -0
  79. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  80. package/dist/_internal/shared/actions/action-registry.js +69 -22
  81. package/dist/_internal/shared/checkout/rules/classified.rule.d.ts +9 -4
  82. package/dist/_internal/shared/checkout/rules/classified.rule.js +7 -2
  83. package/dist/_internal/shared/features/layout/matchesNavQuery.d.ts +14 -0
  84. package/dist/_internal/shared/features/layout/matchesNavQuery.js +72 -0
  85. package/dist/_internal/shared/features/layout/types.d.ts +37 -1
  86. package/dist/_internal/shared/features/layout/types.js +19 -1
  87. package/dist/_internal/shared/features/notifications/action-url.d.ts +9 -1
  88. package/dist/_internal/shared/features/notifications/action-url.js +47 -0
  89. package/dist/_internal/shared/features/offers/config.d.ts +65 -0
  90. package/dist/_internal/shared/features/offers/config.js +73 -2
  91. package/dist/_internal/shared/features/orders/schema.d.ts +19 -1
  92. package/dist/_internal/shared/features/orders/schema.js +22 -2
  93. package/dist/_internal/shared/features/site-settings/types.d.ts +12 -3
  94. package/dist/_internal/shared/listing-types/capabilities.d.ts +8 -2
  95. package/dist/_internal/shared/listing-types/capabilities.js +6 -1
  96. package/dist/_internal/shared/listing-types/classified/ctas.js +6 -1
  97. package/dist/_internal/shared/listing-types/feature-flags.d.ts +10 -5
  98. package/dist/_internal/shared/listing-types/feature-flags.js +11 -6
  99. package/dist/client/api/useApiQuery.js +17 -6
  100. package/dist/client.d.ts +38 -20
  101. package/dist/client.js +39 -14
  102. package/dist/configs/next.js +10 -2
  103. package/dist/constants/api-endpoints.d.ts +18 -54
  104. package/dist/constants/api-endpoints.js +6 -26
  105. package/dist/constants/field-names.d.ts +6 -24
  106. package/dist/constants/field-names.js +10 -27
  107. package/dist/constants/geo/countries.d.ts +50 -0
  108. package/dist/constants/geo/countries.js +129 -0
  109. package/dist/constants/geo/subdivisions.d.ts +13 -0
  110. package/dist/constants/geo/subdivisions.js +104 -0
  111. package/dist/constants/index.d.ts +2 -2
  112. package/dist/constants/index.js +2 -2
  113. package/dist/constants/table-keys.d.ts +24 -0
  114. package/dist/constants/table-keys.js +28 -0
  115. package/dist/contracts/client-realtime.d.ts +6 -0
  116. package/dist/contracts/extend.d.ts +0 -9
  117. package/dist/contracts/index.d.ts +1 -1
  118. package/dist/contracts/realtime-session.d.ts +12 -12
  119. package/dist/contracts/realtime-session.js +79 -77
  120. package/dist/core/browser.d.ts +1 -1
  121. package/dist/core/browser.js +1 -1
  122. package/dist/core/index.d.ts +1 -1
  123. package/dist/core/index.js +1 -1
  124. package/dist/core/site-config.d.ts +0 -3
  125. package/dist/core/site-config.js +0 -3
  126. package/dist/errors/index.d.ts +1 -1
  127. package/dist/errors/index.js +1 -1
  128. package/dist/errors/messages.d.ts +0 -8
  129. package/dist/errors/messages.js +0 -9
  130. package/dist/features/about/components/DeveloperView.js +7 -2
  131. package/dist/features/about/components/PolicyPageView.js +9 -1
  132. package/dist/features/about/components/PublicProfileView.js +23 -5
  133. package/dist/features/about/schemas/index.d.ts +8 -8
  134. package/dist/features/account/components/AddressFilters.js +32 -11
  135. package/dist/features/account/components/AddressForm.d.ts +26 -25
  136. package/dist/features/account/components/AddressForm.js +81 -103
  137. package/dist/features/account/components/AddressesIndexListing.js +8 -4
  138. package/dist/features/account/components/NotificationBell.js +4 -3
  139. package/dist/features/account/components/NotificationPreferencesPanel.js +1 -1
  140. package/dist/features/account/components/UserOffersPanel.js +1 -1
  141. package/dist/features/account/components/UserSidebar.d.ts +3 -4
  142. package/dist/features/account/components/UserSupportView.js +89 -58
  143. package/dist/features/account/components/index.d.ts +1 -7
  144. package/dist/features/account/components/index.js +0 -3
  145. package/dist/features/account/hooks/useAddresses.d.ts +4 -3
  146. package/dist/features/account/hooks/useAddresses.js +4 -6
  147. package/dist/features/account/hooks/useCollapsedSections.d.ts +51 -10
  148. package/dist/features/account/hooks/useCollapsedSections.js +211 -38
  149. package/dist/features/account/hooks/useProfile.d.ts +8 -0
  150. package/dist/features/account/index.d.ts +0 -3
  151. package/dist/features/account/index.js +0 -3
  152. package/dist/features/account/schemas/index.d.ts +0 -92
  153. package/dist/features/account/schemas/index.js +42 -20
  154. package/dist/features/addresses/components/AddressLocationFields.d.ts +13 -0
  155. package/dist/features/addresses/components/AddressLocationFields.js +41 -0
  156. package/dist/features/addresses/hooks/usePostalLookup.d.ts +17 -0
  157. package/dist/features/addresses/hooks/usePostalLookup.js +133 -0
  158. package/dist/features/addresses/schemas/address-form.d.ts +423 -0
  159. package/dist/features/addresses/schemas/address-form.js +212 -0
  160. package/dist/features/addresses/schemas/index.d.ts +1 -0
  161. package/dist/features/addresses/schemas/index.js +8 -0
  162. package/dist/features/admin/actions/admin-read-actions.d.ts +1 -1
  163. package/dist/features/admin/actions/index.d.ts +0 -1
  164. package/dist/features/admin/actions/index.js +0 -1
  165. package/dist/features/admin/actions/notification-actions.js +1 -41
  166. package/dist/features/admin/components/AdminActionIndexView.d.ts +32 -0
  167. package/dist/features/admin/components/AdminActionIndexView.js +128 -0
  168. package/dist/features/admin/components/AdminAdEditorView.js +159 -163
  169. package/dist/features/admin/components/AdminAddressEditorView.js +97 -55
  170. package/dist/features/admin/components/AdminBrandEditorView.d.ts +15 -0
  171. package/dist/features/admin/components/AdminBrandEditorView.js +113 -77
  172. package/dist/features/admin/components/AdminBundleEditorView.d.ts +19 -9
  173. package/dist/features/admin/components/AdminBundleEditorView.js +136 -168
  174. package/dist/features/admin/components/AdminCategoryEditorView.js +120 -43
  175. package/dist/features/admin/components/AdminCouponEditorView.js +145 -109
  176. package/dist/features/admin/components/AdminEmployeeEditorView.js +125 -56
  177. package/dist/features/admin/components/AdminFaqEditorView.js +112 -58
  178. package/dist/features/admin/components/AdminFeatureEditorView.js +108 -68
  179. package/dist/features/admin/components/AdminFulfillmentView.js +5 -2
  180. package/dist/features/admin/components/AdminMediaView.js +3 -3
  181. package/dist/features/admin/components/AdminNavEditorView.js +69 -44
  182. package/dist/features/admin/components/AdminOrderEditorView.js +47 -10
  183. package/dist/features/admin/components/AdminPrizeDrawsView.js +16 -2
  184. package/dist/features/admin/components/AdminSidebar.d.ts +11 -7
  185. package/dist/features/admin/components/AdminSiteSettingsView.js +37 -37
  186. package/dist/features/admin/components/AdminStoreEditorView.js +75 -52
  187. package/dist/features/admin/components/AdminSublistingCategoryEditorView.js +71 -30
  188. package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +95 -65
  189. package/dist/features/admin/components/BrandQuickCreateForm.d.ts +10 -0
  190. package/dist/features/admin/components/BrandQuickCreateForm.js +49 -26
  191. package/dist/features/admin/components/CategoryQuickCreateForm.d.ts +11 -0
  192. package/dist/features/admin/components/CategoryQuickCreateForm.js +48 -26
  193. package/dist/features/admin/components/index.d.ts +2 -2
  194. package/dist/features/admin/components/index.js +1 -1
  195. package/dist/features/admin/constants/site-settings-tabs.d.ts +120 -0
  196. package/dist/features/admin/constants/site-settings-tabs.js +152 -0
  197. package/dist/features/admin/index.d.ts +0 -3
  198. package/dist/features/admin/index.js +0 -2
  199. package/dist/features/admin/repository/analytics-rollup.repository.d.ts +35 -0
  200. package/dist/features/admin/repository/analytics-rollup.repository.js +30 -0
  201. package/dist/features/admin/schemas/admin-editor-forms.d.ts +56 -57
  202. package/dist/features/admin/schemas/admin-editor-forms.js +97 -54
  203. package/dist/features/admin/schemas/admin-ops-forms.d.ts +57 -5
  204. package/dist/features/admin/schemas/admin-ops-forms.js +104 -20
  205. package/dist/features/admin/schemas/admin-user-form.js +7 -0
  206. package/dist/features/admin/schemas/firestore.d.ts +48 -95
  207. package/dist/features/admin/schemas/firestore.js +15 -151
  208. package/dist/features/admin/schemas/nav-item-form.js +9 -2
  209. package/dist/features/admin/server.d.ts +0 -4
  210. package/dist/features/admin/server.js +0 -2
  211. package/dist/features/admin/types/index.d.ts +0 -7
  212. package/dist/features/analytics/repository/page-views.repository.d.ts +14 -0
  213. package/dist/features/analytics/repository/page-views.repository.js +24 -0
  214. package/dist/features/analytics/types.d.ts +1 -1
  215. package/dist/features/analytics/types.js +13 -0
  216. package/dist/features/auctions/components/AuctionDetailPageView.js +6 -2
  217. package/dist/features/auctions/components/MarketplaceAuctionCard.js +3 -1
  218. package/dist/features/auth/actions/index.d.ts +0 -1
  219. package/dist/features/auth/actions/index.js +0 -1
  220. package/dist/features/auth/actions/profile-actions.js +4 -3
  221. package/dist/features/auth/actions/realtime-token-actions.js +1 -12
  222. package/dist/features/auth/auth-helpers.js +5 -7
  223. package/dist/features/auth/components/ForgotPasswordView.js +1 -1
  224. package/dist/features/auth/components/Guards.js +2 -1
  225. package/dist/features/auth/components/LoginForm.d.ts +0 -2
  226. package/dist/features/auth/components/LoginForm.js +2 -4
  227. package/dist/features/auth/components/RegisterForm.js +62 -19
  228. package/dist/features/auth/components/ResetPasswordView.js +1 -1
  229. package/dist/features/auth/hooks/useAuth.js +3 -0
  230. package/dist/features/auth/permissions/constants.d.ts +27 -1
  231. package/dist/features/auth/role-predicates.d.ts +75 -7
  232. package/dist/features/auth/role-predicates.js +28 -2
  233. package/dist/features/auth/schemas/firestore.d.ts +22 -0
  234. package/dist/features/auth/schemas/index.d.ts +1 -1
  235. package/dist/features/auth/schemas/index.js +44 -8
  236. package/dist/features/auth/types/index.d.ts +14 -1
  237. package/dist/features/blog/api/route.js +10 -2
  238. package/dist/features/blog/components/BlogIndexListing.js +1 -1
  239. package/dist/features/blog/hooks/useBlog.js +2 -2
  240. package/dist/features/blog/repository/blog.repository.js +3 -1
  241. package/dist/features/blog/schemas/index.d.ts +4 -0
  242. package/dist/features/blog/schemas/index.js +2 -0
  243. package/dist/features/blog/types/index.d.ts +1 -1
  244. package/dist/features/cart/actions/cart-actions.js +13 -4
  245. package/dist/features/cart/utils/pending-ops.js +1 -1
  246. package/dist/features/catalogue/components/CatalogueItemEditorView.d.ts +22 -0
  247. package/dist/features/catalogue/components/CatalogueItemEditorView.js +112 -52
  248. package/dist/features/catalogue/schemas/validation.d.ts +4 -4
  249. package/dist/features/catalogue/schemas/validation.js +47 -10
  250. package/dist/features/categories/components/BrandDetailPageView.js +28 -12
  251. package/dist/features/categories/components/CategoryDetailPageView.js +37 -20
  252. package/dist/features/categories/repository/categories.repository.js +3 -1
  253. package/dist/features/categories/schemas/bundle-form.d.ts +142 -0
  254. package/dist/features/categories/schemas/bundle-form.js +149 -0
  255. package/dist/features/checkout/actions/checkout-value-otp-actions.js +10 -1
  256. package/dist/features/classified/components/ClassifiedContactSellerPanel.js +1 -1
  257. package/dist/features/classified/components/ClassifiedDetailPageView.d.ts +5 -4
  258. package/dist/features/classified/components/ClassifiedDetailPageView.js +47 -18
  259. package/dist/features/consultation/components/ConsultationForm.js +1 -1
  260. package/dist/features/consultation/schemas/index.js +34 -10
  261. package/dist/features/corporate/schemas/index.js +36 -15
  262. package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +4 -1
  263. package/dist/features/events/components/EventBanner.js +5 -2
  264. package/dist/features/events/components/EventOfferCard.js +3 -1
  265. package/dist/features/events/components/EventPollWidget.js +1 -1
  266. package/dist/features/events/components/SpinWheelView.js +3 -2
  267. package/dist/features/filters/FilterPanel.js +3 -3
  268. package/dist/features/filters/RangeFilter.d.ts +10 -0
  269. package/dist/features/filters/RangeFilter.js +41 -4
  270. package/dist/features/grouped/components/GroupedListingEditorView.js +2 -1
  271. package/dist/features/history/hooks/useHistory.js +29 -27
  272. package/dist/features/homepage/components/AdSlot.js +3 -1
  273. package/dist/features/homepage/components/GoogleReviewsSection.js +8 -2
  274. package/dist/features/homepage/components/MarketplaceHomepageView.js +58 -15
  275. package/dist/features/homepage/components/SocialFeedSection.js +4 -1
  276. package/dist/features/homepage/hooks/useBlogArticles.js +1 -1
  277. package/dist/features/homepage/lib/live-stats.js +8 -1
  278. package/dist/features/homepage/repository/carousel.repository.js +2 -1
  279. package/dist/features/layout/BottomActions.js +84 -11
  280. package/dist/features/layout/BottomActionsContext.d.ts +1 -6
  281. package/dist/features/layout/BottomActionsContext.js +1 -1
  282. package/dist/features/layout/hooks/useBottomActions.js +2 -2
  283. package/dist/features/layout/hooks/useFormBottomActions.d.ts +12 -1
  284. package/dist/features/layout/hooks/useFormBottomActions.js +12 -6
  285. package/dist/features/live/components/LiveItemDetailPageView.js +4 -1
  286. package/dist/features/lottery/schemas/config-write.d.ts +9 -5
  287. package/dist/features/lottery/schemas/config-write.js +69 -9
  288. package/dist/features/media/finalize.js +3 -1
  289. package/dist/features/media/modals/ImageEditor.js +1 -1
  290. package/dist/features/media/modals/VideoThumbnailSelector.js +5 -2
  291. package/dist/features/media/modals/VideoTrimModal.js +5 -2
  292. package/dist/features/media/upload/MediaUploadField.js +2 -2
  293. package/dist/features/messages/hooks/useConversation.js +18 -4
  294. package/dist/features/messages/hooks/useConversations.js +25 -8
  295. package/dist/features/orders/components/RefundRequestView.js +5 -2
  296. package/dist/features/orders/schemas/buyer-forms.d.ts +6 -3
  297. package/dist/features/orders/schemas/buyer-forms.js +31 -3
  298. package/dist/features/orders/schemas/index.d.ts +2 -2
  299. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +3 -1
  300. package/dist/features/pre-orders/components/PreOrderActionsClient.js +1 -1
  301. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +4 -1
  302. package/dist/features/products/components/GroupSettingsPanel.js +3 -1
  303. package/dist/features/products/components/MakeOfferButton.d.ts +13 -2
  304. package/dist/features/products/components/MakeOfferButton.js +33 -11
  305. package/dist/features/products/components/PrizeDrawDetailPageView.js +4 -1
  306. package/dist/features/products/components/ProductDetailActions.js +0 -1
  307. package/dist/features/products/components/ProductDetailPageView.d.ts +7 -3
  308. package/dist/features/products/components/ProductDetailPageView.js +16 -7
  309. package/dist/features/products/components/ShareButton.js +3 -1
  310. package/dist/features/products/constants/action-defs.d.ts +1 -2
  311. package/dist/features/products/constants/action-defs.js +40 -43
  312. package/dist/features/products/repository/loadProductFeatures.js +10 -2
  313. package/dist/features/products/repository/products.repository.d.ts +5 -1
  314. package/dist/features/products/repository/products.repository.js +25 -2
  315. package/dist/features/products/schemas/firestore.d.ts +7 -3
  316. package/dist/features/products/schemas/product-features.validators.js +3 -0
  317. package/dist/features/promotions/components/CouponCard.js +11 -8
  318. package/dist/features/reviews/actions/review-actions.js +8 -1
  319. package/dist/features/reviews/components/ReviewDetailPageView.js +13 -3
  320. package/dist/features/reviews/components/ReviewDetailShell.js +3 -1
  321. package/dist/features/scams/actions/scam-actions.d.ts +9 -1
  322. package/dist/features/scams/actions/scam-actions.js +52 -12
  323. package/dist/features/scams/components/SellerTrustBadge.d.ts +1 -1
  324. package/dist/features/scams/components/SellerTrustBadge.js +13 -0
  325. package/dist/features/scams/repository/scammer.repository.js +2 -1
  326. package/dist/features/scams/schemas/firestore.d.ts +15 -1
  327. package/dist/features/scams/schemas/report-form.d.ts +5 -5
  328. package/dist/features/scams/schemas/report-form.js +18 -3
  329. package/dist/features/search/action-index/derive.d.ts +49 -0
  330. package/dist/features/search/action-index/derive.js +121 -0
  331. package/dist/features/search/action-index/repository.d.ts +42 -0
  332. package/dist/features/search/action-index/repository.js +100 -0
  333. package/dist/features/search/action-index/settings-entries.d.ts +41 -0
  334. package/dist/features/search/action-index/settings-entries.js +268 -0
  335. package/dist/features/search/action-index/types.d.ts +81 -0
  336. package/dist/features/search/action-index/types.js +102 -0
  337. package/dist/features/search/action-index/validate-entry.d.ts +34 -0
  338. package/dist/features/search/action-index/validate-entry.js +114 -0
  339. package/dist/features/search/hooks/useNavSuggestions.d.ts +5 -1
  340. package/dist/features/search/hooks/useNavSuggestions.js +23 -3
  341. package/dist/features/search/repository/search.repository.js +3 -1
  342. package/dist/features/seller/actions/offer-actions.js +43 -19
  343. package/dist/features/seller/actions/seller-actions.js +29 -5
  344. package/dist/features/seller/components/CategoryChipPicker.d.ts +9 -0
  345. package/dist/features/seller/components/CategoryChipPicker.js +12 -0
  346. package/dist/features/seller/components/FulfillmentView.js +5 -2
  347. package/dist/features/seller/components/PhysicalLocationModal.js +1 -1
  348. package/dist/features/seller/components/PrintCenterView.js +3 -1
  349. package/dist/features/seller/components/SellerAddressesView.js +5 -1
  350. package/dist/features/seller/components/SellerAnalyticsAlertsView.js +83 -43
  351. package/dist/features/seller/components/SellerArtView.d.ts +14 -7
  352. package/dist/features/seller/components/SellerArtView.js +4 -119
  353. package/dist/features/seller/components/SellerBidsView.js +1 -1
  354. package/dist/features/seller/components/SellerClassifiedView.d.ts +14 -7
  355. package/dist/features/seller/components/SellerClassifiedView.js +4 -124
  356. package/dist/features/seller/components/SellerCouponEditorView.d.ts +22 -1
  357. package/dist/features/seller/components/SellerCouponEditorView.js +91 -45
  358. package/dist/features/seller/components/SellerCouponsView.js +1 -1
  359. package/dist/features/seller/components/SellerDigitalCodesView.d.ts +14 -7
  360. package/dist/features/seller/components/SellerDigitalCodesView.js +4 -126
  361. package/dist/features/seller/components/SellerGoogleReviewsView.js +2 -2
  362. package/dist/features/seller/components/SellerListingTypeView.d.ts +66 -0
  363. package/dist/features/seller/components/SellerListingTypeView.js +277 -0
  364. package/dist/features/seller/components/SellerLiveView.d.ts +14 -7
  365. package/dist/features/seller/components/SellerLiveView.js +4 -126
  366. package/dist/features/seller/components/SellerOrdersView.js +3 -3
  367. package/dist/features/seller/components/SellerPayoutMethodsView.js +2 -2
  368. package/dist/features/seller/components/SellerProductShell.d.ts +5 -0
  369. package/dist/features/seller/components/SellerProductShell.js +15 -5
  370. package/dist/features/seller/components/SellerProductsView.js +24 -10
  371. package/dist/features/seller/components/SellerReviewsView.js +47 -16
  372. package/dist/features/seller/components/SellerShippingConfigsView.js +5 -4
  373. package/dist/features/seller/components/SellerSidebar.d.ts +3 -6
  374. package/dist/features/seller/components/SellerStickersView.d.ts +14 -7
  375. package/dist/features/seller/components/SellerStickersView.js +4 -119
  376. package/dist/features/seller/components/SellerStoreCategoriesView.js +3 -2
  377. package/dist/features/seller/components/SellerSupportView.d.ts +31 -0
  378. package/dist/features/seller/components/SellerSupportView.js +100 -0
  379. package/dist/features/seller/components/index.d.ts +4 -8
  380. package/dist/features/seller/components/index.js +2 -4
  381. package/dist/features/seller/index.d.ts +0 -1
  382. package/dist/features/seller/index.js +0 -1
  383. package/dist/features/seller/schemas/coupon-form.d.ts +214 -0
  384. package/dist/features/seller/schemas/coupon-form.js +155 -23
  385. package/dist/features/seller/schemas/offer-forms.d.ts +16 -7
  386. package/dist/features/seller/schemas/offer-forms.js +28 -12
  387. package/dist/features/shell/FormShell.js +2 -2
  388. package/dist/features/shell/QuickFormDrawer.js +2 -2
  389. package/dist/features/shell/SectionForm.d.ts +19 -1
  390. package/dist/features/shell/SectionForm.js +104 -17
  391. package/dist/features/shell/build-sections.d.ts +23 -0
  392. package/dist/features/shell/build-sections.js +106 -8
  393. package/dist/features/shell/field-ui-meta.d.ts +44 -0
  394. package/dist/features/shell/field-ui-meta.js +14 -7
  395. package/dist/features/shell/form-sections.d.ts +46 -0
  396. package/dist/features/shell/form-sections.js +114 -0
  397. package/dist/features/shipments/components/AdminShipmentEditorView.js +87 -64
  398. package/dist/features/shipments/schemas/validation.d.ts +2 -2
  399. package/dist/features/shipments/schemas/validation.js +44 -13
  400. package/dist/features/store-extensions/schemas/custom-role-form.js +6 -2
  401. package/dist/features/store-extensions/schemas/listing-template-form.d.ts +7 -7
  402. package/dist/features/store-extensions/schemas/payout-method-form.js +14 -0
  403. package/dist/features/stores/actions/store-query-actions.js +3 -2
  404. package/dist/features/stores/api/[storeSlug]/auctions/route.js +3 -1
  405. package/dist/features/stores/api/[storeSlug]/products/route.js +3 -1
  406. package/dist/features/stores/components/StoreDetailLayoutView.d.ts +1 -1
  407. package/dist/features/stores/components/StoreDetailLayoutView.js +12 -3
  408. package/dist/features/support/repository/support.repository.d.ts +21 -0
  409. package/dist/features/support/repository/support.repository.js +63 -0
  410. package/dist/features/support/schemas/firestore.d.ts +27 -2
  411. package/dist/features/support/schemas/firestore.js +2 -0
  412. package/dist/features/support/schemas/ticket-create-form.js +7 -0
  413. package/dist/features/tester/schemas/checklist-item-form.d.ts +43 -0
  414. package/dist/features/tester/schemas/checklist-item-form.js +109 -0
  415. package/dist/features/tester/seed-data/blog-tester-seed-data.js +2 -2
  416. package/dist/features/tester/seed-data/categories-tester-seed-data.js +2 -2
  417. package/dist/features/tester/seed-data/events-tester-seed-data.js +5 -5
  418. package/dist/features/tester/seed-data/orders-tester-seed-data.js +2 -2
  419. package/dist/features/tester/seed-data/products-tester-seed-data.js +48 -49
  420. package/dist/features/tester/seed-data/stores-tester-seed-data.js +3 -3
  421. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +291 -30
  422. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +51 -14
  423. package/dist/features/wishlist/hooks/useWishlistToggle.js +8 -1
  424. package/dist/http/api-handler.js +2 -1
  425. package/dist/index.d.ts +25 -104
  426. package/dist/index.js +38 -143
  427. package/dist/jobs.d.ts +1 -1
  428. package/dist/jobs.js +1 -1
  429. package/dist/monitoring/browser.d.ts +0 -2
  430. package/dist/monitoring/browser.js +12 -1
  431. package/dist/monitoring/index.d.ts +0 -2
  432. package/dist/monitoring/index.js +0 -1
  433. package/dist/next/api/routeHandler.js +9 -4
  434. package/dist/next/index.d.ts +1 -2
  435. package/dist/next/index.js +0 -1
  436. package/dist/next/middleware/index.d.ts +0 -2
  437. package/dist/next/middleware/index.js +0 -1
  438. package/dist/next/routing/route-map.d.ts +8 -7
  439. package/dist/next/routing/route-map.js +10 -3
  440. package/dist/providers/auth-firebase/session.js +3 -1
  441. package/dist/providers/db-firebase/admin-app-lite.js +8 -8
  442. package/dist/providers/db-firebase/admin.js +27 -13
  443. package/dist/providers/db-firebase/browser-stub.d.ts +1 -11
  444. package/dist/providers/db-firebase/browser-stub.js +6 -11
  445. package/dist/providers/db-firebase/index.d.ts +0 -1
  446. package/dist/providers/db-firebase/index.js +0 -1
  447. package/dist/providers/db-firebase/rtdb-paths.d.ts +15 -6
  448. package/dist/providers/db-firebase/rtdb-paths.js +15 -6
  449. package/dist/providers/db-firebase/rtdb-url.d.ts +27 -0
  450. package/dist/providers/db-firebase/rtdb-url.js +50 -0
  451. package/dist/providers/db-firebase/sieve.d.ts +22 -0
  452. package/dist/providers/firebase-client/realtime.d.ts +20 -0
  453. package/dist/providers/firebase-client/realtime.js +34 -1
  454. package/dist/providers.d.ts +1 -1
  455. package/dist/providers.js +1 -1
  456. package/dist/react/hooks/use-action-dispatch.js +8 -2
  457. package/dist/react/hooks/useFormStatePreservation.js +3 -1
  458. package/dist/react/hooks/useListingTypeFlags.d.ts +1 -1
  459. package/dist/react/hooks/useListingTypeFlags.js +1 -1
  460. package/dist/react/hooks/usePendingFilters.js +5 -3
  461. package/dist/react/hooks/usePendingTable.js +15 -3
  462. package/dist/react/hooks/useRealtimeEvent.js +20 -9
  463. package/dist/repositories/index.d.ts +0 -1
  464. package/dist/repositories/index.js +0 -1
  465. package/dist/schemas/registry.d.ts +197 -232
  466. package/dist/schemas/registry.js +5 -6
  467. package/dist/schemas/webhooks/razorpay.d.ts +50 -50
  468. package/dist/security/authorization.d.ts +9 -0
  469. package/dist/security/authorization.js +16 -2
  470. package/dist/security/browser.d.ts +1 -3
  471. package/dist/security/browser.js +5 -2
  472. package/dist/security/index.d.ts +1 -3
  473. package/dist/security/index.js +19 -2
  474. package/dist/security/pii-encrypt.js +16 -0
  475. package/dist/security/pii-schemas.d.ts +0 -14
  476. package/dist/security/pii-schemas.js +7 -15
  477. package/dist/seed/_helpers/category-forest.js +2 -2
  478. package/dist/seed/_helpers/media.d.ts +19 -0
  479. package/dist/seed/_helpers/media.js +75 -0
  480. package/dist/seed/blog-posts-seed-data.js +17 -17
  481. package/dist/seed/carousel-slides-seed-data.js +7 -7
  482. package/dist/seed/cart-seed-data.js +13 -13
  483. package/dist/seed/categories-seed-data.js +10 -10
  484. package/dist/seed/events-seed-data.js +24 -24
  485. package/dist/seed/factories/product.factory.js +4 -4
  486. package/dist/seed/factories/store.factory.js +3 -3
  487. package/dist/seed/factories/user.factory.js +2 -2
  488. package/dist/seed/grouped-listings-seed-data.js +11 -11
  489. package/dist/seed/homepage-sections-seed-data.js +2 -2
  490. package/dist/seed/index.d.ts +0 -1
  491. package/dist/seed/index.js +0 -1
  492. package/dist/seed/manifest.d.ts +1 -1
  493. package/dist/seed/manifest.js +0 -5
  494. package/dist/seed/notifications-seed-data.js +20 -1
  495. package/dist/seed/orders-seed-data.js +2 -2
  496. package/dist/seed/products-art-seed-data.js +16 -16
  497. package/dist/seed/products-auctions-seed-data.js +34 -34
  498. package/dist/seed/products-classifieds-seed-data.js +35 -37
  499. package/dist/seed/products-digital-codes-seed-data.js +20 -20
  500. package/dist/seed/products-live-items-seed-data.js +11 -11
  501. package/dist/seed/products-preorders-seed-data.js +13 -13
  502. package/dist/seed/products-prize-draws-seed-data.js +43 -43
  503. package/dist/seed/products-standard-seed-data.js +54 -54
  504. package/dist/seed/products-stickers-seed-data.js +15 -15
  505. package/dist/seed/reviews-seed-data.js +4 -4
  506. package/dist/seed/scammers-seed-data.js +3 -3
  507. package/dist/seed/site-settings-seed-data.js +11 -24
  508. package/dist/seed/store-extensions-seed-data.js +10 -10
  509. package/dist/seed/stores-seed-data.js +11 -11
  510. package/dist/seed/support-tickets-seed-data.d.ts +14 -0
  511. package/dist/seed/support-tickets-seed-data.js +20 -1
  512. package/dist/seed/users-seed-data.js +20 -20
  513. package/dist/server-entry.d.ts +0 -1
  514. package/dist/server-entry.js +0 -1
  515. package/dist/server.d.ts +9 -6
  516. package/dist/server.js +7 -13
  517. package/dist/styles.css +248 -68
  518. package/dist/tailwind-utilities.css +1 -1
  519. package/dist/tokens/themes/default-dark.js +2 -2
  520. package/dist/tokens/themes/default-light.js +2 -2
  521. package/dist/tokens/tokens.css +24 -4
  522. package/dist/ui/components/ActionRow.d.ts +50 -0
  523. package/dist/ui/components/ActionRow.js +53 -0
  524. package/dist/ui/components/ActionRow.style.css +145 -0
  525. package/dist/ui/components/Drawer.d.ts +10 -0
  526. package/dist/ui/components/Drawer.js +2 -1
  527. package/dist/ui/components/FilterDrawer.js +4 -1
  528. package/dist/ui/components/FilterDrawer.style.css +6 -12
  529. package/dist/ui/components/FormActionBar.js +14 -1
  530. package/dist/ui/components/FormActionBar.style.css +12 -11
  531. package/dist/ui/components/ListingLayout.js +8 -1
  532. package/dist/ui/components/ListingLayout.style.css +6 -13
  533. package/dist/ui/components/Modal.d.ts +15 -1
  534. package/dist/ui/components/Modal.js +17 -3
  535. package/dist/ui/components/QuickCreateModal.js +2 -2
  536. package/dist/ui/components/QuickCreateModal.style.css +78 -84
  537. package/dist/ui/components/RecordDetailModal.js +2 -2
  538. package/dist/ui/components/SideDrawer.d.ts +8 -0
  539. package/dist/ui/components/SideDrawer.js +2 -1
  540. package/dist/ui/components/SideDrawer.style.css +6 -3
  541. package/dist/ui/components/SideModal.d.ts +11 -1
  542. package/dist/ui/components/SideModal.js +3 -2
  543. package/dist/ui/components/SideModal.style.css +14 -0
  544. package/dist/ui/components/Typography.style.css +33 -24
  545. package/dist/ui/components/index.style.css +1 -0
  546. package/dist/ui/components/toolbar-collapse.js +1 -2
  547. package/dist/ui/forms/FormShell.style.css +260 -311
  548. package/dist/ui/index.d.ts +2 -0
  549. package/dist/ui/index.js +1 -0
  550. package/dist/utils/index.d.ts +0 -1
  551. package/dist/utils/index.js +0 -1
  552. package/dist/validation/index.d.ts +1 -1
  553. package/dist/validation/index.js +1 -1
  554. package/dist/validation/schemas.d.ts +0 -19
  555. package/dist/validation/schemas.js +8 -19
  556. package/package.json +1 -1
  557. package/scripts/seed-cli.mjs +3 -6
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { normalizeError } from "../../../../errors/normalize";
4
+ import { toUserMessage } from "../../../../errors/error-display-map";
4
5
  import { useState } from "react";
5
6
  import { Button, Div, Row, Span, Stack, Text } from "../../../../ui";
6
7
  const __P = {
@@ -19,8 +20,10 @@ export function CodeRevealPanel({ orderId, redemptionInstructions, fetchCode, })
19
20
  setRevealed(data);
20
21
  }
21
22
  catch (e) {
22
- void normalizeError(e);
23
- setError(e instanceof Error ? e.message : "Could not retrieve code");
23
+ const normalized = normalizeError(e);
24
+ setError(toUserMessage(normalized.code, undefined, {
25
+ fallback: "Could not retrieve your code. Please try again.",
26
+ }));
24
27
  }
25
28
  finally {
26
29
  setPending(false);
@@ -69,7 +69,7 @@ function useResponsiveDrawer(storageKey) {
69
69
  localStorage.setItem(storageKey, "true");
70
70
  }
71
71
  catch (_err) {
72
- void normalizeError(_err);
72
+ void normalizeError(_err); /* localStorage unavailable (private-browse / quota) — the sidebar still opens, only the preference is not remembered */
73
73
  }
74
74
  setDesktopOpen(true);
75
75
  }
@@ -84,7 +84,7 @@ function useResponsiveDrawer(storageKey) {
84
84
  localStorage.setItem(storageKey, "false");
85
85
  }
86
86
  catch (_err) {
87
- void normalizeError(_err);
87
+ void normalizeError(_err); /* localStorage unavailable (private-browse / quota) — the sidebar still closes, only the preference is not remembered */
88
88
  }
89
89
  setDesktopOpen(false);
90
90
  }
@@ -105,7 +105,7 @@ function useResponsiveDrawer(storageKey) {
105
105
  localStorage.setItem(storageKey, String(next));
106
106
  }
107
107
  catch (_err) {
108
- void normalizeError(_err);
108
+ void normalizeError(_err); /* localStorage unavailable (private-browse / quota) — the toggle still applies, only the preference is not remembered */
109
109
  }
110
110
  return next;
111
111
  });
@@ -1,13 +1,29 @@
1
+ import { type NavSearchable } from "../../../shared/features/layout/matchesNavQuery";
1
2
  /**
2
- * Shared inline-filter logic for the Admin/Store/User sidebars — lowercase
3
- * substring match against item labels, collapsing to only groups with a
4
- * surviving match. Each sidebar keeps its own accordion/markup; only this
5
- * pure filtering algorithm is shared so it isn't rewritten three times.
3
+ * Shared inline-filter logic for the Admin/Store/User sidebars. Each sidebar
4
+ * keeps its own accordion/markup; only this filtering is shared so it is not
5
+ * rewritten three times.
6
+ *
7
+ * ## It searches what a screen is FOR, not just what it is called
8
+ *
9
+ * This was `item.label.toLowerCase().includes(q)`, which could only find a
10
+ * screen by the name already on the button. "refund" found nothing, because
11
+ * the screen is called Payouts. "postcode" found nothing, because the field is
12
+ * called PIN code. "maintenance" found nothing, because that toggle lives
13
+ * inside Site Settings. W6 gave every nav item a `description` and `keywords`;
14
+ * `matchesNavQuery` reads all three.
15
+ *
16
+ * ## Results are RANKED, and within a group only
17
+ *
18
+ * A label hit beats a keyword hit beats a description hit, so typing "orders"
19
+ * puts **Orders** above the guide that merely mentions orders. Groups keep
20
+ * their declared order — reordering them by best score would move the sidebar
21
+ * around under the reader's cursor while they type.
6
22
  */
7
23
  export declare function useSidebarSearch<Item extends {
8
24
  href: string;
9
25
  label: string;
10
- }, Group extends {
26
+ } & Partial<NavSearchable>, Group extends {
11
27
  title: string;
12
28
  items: Item[];
13
29
  defaultOpen?: boolean;
@@ -1,10 +1,26 @@
1
1
  "use client";
2
2
  import { useMemo, useState } from "react";
3
+ import { matchesNavQuery } from "../../../shared/features/layout/matchesNavQuery";
3
4
  /**
4
- * Shared inline-filter logic for the Admin/Store/User sidebars — lowercase
5
- * substring match against item labels, collapsing to only groups with a
6
- * surviving match. Each sidebar keeps its own accordion/markup; only this
7
- * pure filtering algorithm is shared so it isn't rewritten three times.
5
+ * Shared inline-filter logic for the Admin/Store/User sidebars. Each sidebar
6
+ * keeps its own accordion/markup; only this filtering is shared so it is not
7
+ * rewritten three times.
8
+ *
9
+ * ## It searches what a screen is FOR, not just what it is called
10
+ *
11
+ * This was `item.label.toLowerCase().includes(q)`, which could only find a
12
+ * screen by the name already on the button. "refund" found nothing, because
13
+ * the screen is called Payouts. "postcode" found nothing, because the field is
14
+ * called PIN code. "maintenance" found nothing, because that toggle lives
15
+ * inside Site Settings. W6 gave every nav item a `description` and `keywords`;
16
+ * `matchesNavQuery` reads all three.
17
+ *
18
+ * ## Results are RANKED, and within a group only
19
+ *
20
+ * A label hit beats a keyword hit beats a description hit, so typing "orders"
21
+ * puts **Orders** above the guide that merely mentions orders. Groups keep
22
+ * their declared order — reordering them by best score would move the sidebar
23
+ * around under the reader's cursor while they type.
8
24
  */
9
25
  export function useSidebarSearch(groups) {
10
26
  const [query, setQuery] = useState("");
@@ -12,9 +28,14 @@ export function useSidebarSearch(groups) {
12
28
  const filteredGroups = useMemo(() => {
13
29
  if (!isSearching)
14
30
  return groups;
15
- const q = query.trim().toLowerCase();
16
31
  return groups
17
- .map((group) => ({ ...group, items: group.items.filter((item) => item.label.toLowerCase().includes(q)) }))
32
+ .map((group) => {
33
+ const scored = group.items
34
+ .map((item) => ({ item, score: matchesNavQuery(item, query) }))
35
+ .filter((entry) => entry.score > 0)
36
+ .sort((a, b) => b.score - a.score);
37
+ return { ...group, items: scored.map((entry) => entry.item) };
38
+ })
18
39
  .filter((group) => group.items.length > 0);
19
40
  }, [groups, query, isSearching]);
20
41
  return { query, setQuery, isSearching, filteredGroups };
@@ -1,5 +1,28 @@
1
+ /**
2
+ * LotteryAdminEditView — the slot configuration for one lottery. Sectionised
3
+ * 2026-08-30.
4
+ *
5
+ * ## Two schemas became one
6
+ *
7
+ * It declared `lotteryConfigFormSchema` on `<Form>` and parsed
8
+ * `lotteryConfigWriteSchema` in the submit handler, so the form schema's
9
+ * duplicate-slot and free-lottery rules had never executed. The form schema is
10
+ * deleted; `lotteryConfigWriteSchema` carries the annotations now and is both
11
+ * what this form renders from and what the route parses.
12
+ *
13
+ * ## Title and description are gone, not moved
14
+ *
15
+ * They were editable here and reached nothing: `LotteryConfigClient` posts
16
+ * `data.lotteryConfig` to `PUT .../lottery-config` and ignores the rest, and
17
+ * that route accepts only the config. An event's title, dates, status and
18
+ * media are edited in the ordinary event editor — this page is the slots. Two
19
+ * inputs that saved silently into nowhere are worse than their absence, which
20
+ * is the same call made on `rememberMe`. The title still appears, as the
21
+ * heading, so it is obvious which lottery is open.
22
+ */
1
23
  import React from "react";
2
24
  import type { LotteryConfigWriteInput } from "../../../../features/lottery/schemas/config-write";
25
+ /** One editable row of the slot table. */
3
26
  interface LotterySlotRow {
4
27
  slotNumber: number;
5
28
  name: string;
@@ -22,9 +45,6 @@ interface LotterySlotRow {
22
45
  * fullness check reads.
23
46
  */
24
47
  interface LotteryEventFormData {
25
- title: string;
26
- description?: string;
27
- type: "lottery";
28
48
  lotteryConfig: LotteryConfigWriteInput;
29
49
  }
30
50
  interface LotteryAdminEditViewProps {
@@ -1,97 +1,121 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useState, useTransition } from "react";
4
- import { normalizeError } from "../../../../errors/normalize";
5
- import { Stack, Row, Text, Heading, Section, Container, Button, DataTable, } from "../../../../ui";
6
- import { Form, FieldInput, FieldSelect, Input } from "../../../../ui";
7
- import { lotteryConfigFormSchema } from "../../../shared/features/lottery/config-form";
8
- import { lotteryConfigWriteSchema } from "../../../../features/lottery/schemas/config-write";
3
+ /**
4
+ * LotteryAdminEditView — the slot configuration for one lottery. Sectionised
5
+ * 2026-08-30.
6
+ *
7
+ * ## Two schemas became one
8
+ *
9
+ * It declared `lotteryConfigFormSchema` on `<Form>` and parsed
10
+ * `lotteryConfigWriteSchema` in the submit handler, so the form schema's
11
+ * duplicate-slot and free-lottery rules had never executed. The form schema is
12
+ * deleted; `lotteryConfigWriteSchema` carries the annotations now and is both
13
+ * what this form renders from and what the route parses.
14
+ *
15
+ * ## Title and description are gone, not moved
16
+ *
17
+ * They were editable here and reached nothing: `LotteryConfigClient` posts
18
+ * `data.lotteryConfig` to `PUT .../lottery-config` and ignores the rest, and
19
+ * that route accepts only the config. An event's title, dates, status and
20
+ * media are edited in the ordinary event editor — this page is the slots. Two
21
+ * inputs that saved silently into nowhere are worse than their absence, which
22
+ * is the same call made on `rememberMe`. The title still appears, as the
23
+ * heading, so it is obvious which lottery is open.
24
+ */
25
+ import React from "react";
26
+ import { Button, DataTable, Input, Row, Stack, Text, } from "../../../../ui";
9
27
  import { FormErrorSummary } from "../../../../ui/forms/FormErrorSummary";
28
+ import { FormShellContext, useFormShellState } from "../../../../ui/forms/FormShell";
29
+ import { applyZodIssues } from "../../../../ui/forms/apply-zod-issues";
30
+ import { StackedViewShell } from "../../../../ui";
31
+ import { buildSectionsFromSchema, visibleValues } from "../../../../features/shell/build-sections";
32
+ import { SectionForm, useSectionFormNav } from "../../../../features/shell/SectionForm";
33
+ import { lotteryConfigWriteSchema } from "../../../../features/lottery/schemas/config-write";
34
+ const MAX_SLOTS = 200;
10
35
  export function LotteryAdminEditView({ eventId, initialData, onSubmit, }) {
11
- const [isPending, startTransition] = useTransition();
12
- const [error, setError] = useState(null);
13
- const [title, setTitle] = useState(initialData?.title ?? "");
14
- const [description, setDescription] = useState(initialData?.description ?? "");
15
- const [pricingMode, setPricingMode] = useState(initialData?.pricingMode ?? "uniform");
16
- const [uniformPrice, setUniformPrice] = useState(String(initialData?.uniformPrice ?? 0));
17
- const [drawWindowMinutes, setDrawWindowMinutes] = useState(String(initialData?.drawWindowDurationMinutes ?? 5));
18
- const [maxPullsPerTx, setMaxPullsPerTx] = useState(String(initialData?.maxPullsPerTransaction ?? 1));
19
- const [maxPullsPerUser, setMaxPullsPerUser] = useState(String(initialData?.maxPullsPerUser ?? 1));
20
- const [slots, setSlots] = useState(initialData?.slots ?? [{ slotNumber: 1, name: "", price: 0 }]);
21
- const addSlot = () => {
22
- setSlots((prev) => [
23
- ...prev,
24
- { slotNumber: prev.length + 1, name: "", price: 0 },
25
- ]);
26
- };
27
- const removeSlot = (idx) => {
28
- setSlots((prev) => prev.filter((_, i) => i !== idx).map((s, i) => ({ ...s, slotNumber: i + 1 })));
29
- };
30
- const updateSlot = (idx, field, value) => {
31
- setSlots((prev) => prev.map((s, i) => i === idx
32
- ? { ...s, [field]: field === "price" ? Math.round(parseFloat(value) * 100) / 100 || 0 : value }
33
- : s));
34
- };
36
+ const [isPending, startTransition] = React.useTransition();
37
+ const [form, setForm] = React.useState({
38
+ pricingMode: initialData?.pricingMode ?? "uniform",
39
+ uniformPrice: initialData?.uniformPrice ?? 0,
40
+ drawWindowDurationMinutes: initialData?.drawWindowDurationMinutes ?? 5,
41
+ maxPullsPerTransaction: initialData?.maxPullsPerTransaction ?? 1,
42
+ maxPullsPerUser: initialData?.maxPullsPerUser ?? 1,
43
+ slots: initialData?.slots ?? [{ slotNumber: 1, name: "", price: 0 }],
44
+ });
45
+ const patch = (partial) => setForm((prev) => Object.assign({}, prev, partial));
46
+ const sections = React.useMemo(() => buildSectionsFromSchema(lotteryConfigWriteSchema, {
47
+ renderers: {
48
+ slots: ({ values, onChange }) => (_jsx(SlotTable, { slots: values.slots, showPrice: values.pricingMode === "variable", onSlotsChange: (next) => onChange({ slots: next }) })),
49
+ },
50
+ }), []);
51
+ const nav = useSectionFormNav(sections, form, { scope: "admin:lottery-config" });
52
+ const { shellCtx, setFieldError, clearErrors } = useFormShellState(lotteryConfigWriteSchema, {
53
+ sections: nav.sectionMeta,
54
+ onGoToSection: nav.goToSection,
55
+ fieldToSectionIndex: nav.fieldToSectionIndex,
56
+ });
35
57
  const handleSubmit = () => {
36
- setError(null);
58
+ clearErrors();
59
+ /*
60
+ * Per-slot prices are dropped under uniform pricing, where the price of a
61
+ * slot IS `uniformPrice`. They used to be sent in both modes, so a figure
62
+ * loaded from `initialData` survived a switch to uniform — unreachable on
63
+ * screen, still written on save. `visibleValues` cannot reach inside an
64
+ * array, so this one masking stays explicit.
65
+ */
66
+ const draft = visibleValues(lotteryConfigWriteSchema, form);
67
+ const candidate = {
68
+ ...draft,
69
+ slots: form.slots.map((s) => ({
70
+ slotNumber: s.slotNumber,
71
+ name: s.name,
72
+ image: s.image?.trim() || undefined,
73
+ price: form.pricingMode === "variable" ? s.price : 0,
74
+ })),
75
+ };
76
+ const parsed = lotteryConfigWriteSchema.safeParse(candidate);
77
+ if (!parsed.success) {
78
+ applyZodIssues(parsed.error.issues, setFieldError);
79
+ return;
80
+ }
37
81
  startTransition(async () => {
38
- try {
39
- /*
40
- * 🛑 This used to send `isBooked: false` and `weight: 0` on every slot,
41
- * and drop `bookedByUserId` / `bookedByDisplayName` /
42
- * `bookedByUserLotteryNumber` entirely — against a `.passthrough()`
43
- * PATCH, which made the first save of a live lottery erase every
44
- * purchased slot, silently, with a 200.
45
- *
46
- * The write shape now has NO booking fields at all and is `.strict()`,
47
- * so a slot's buyer is not something this form can express, let alone
48
- * overwrite. `PUT /lottery-config` merges by `slotNumber` against the
49
- * stored config and is the only writer.
50
- */
51
- const candidate = {
52
- slots: slots.map((s) => ({
53
- slotNumber: s.slotNumber,
54
- name: s.name,
55
- image: s.image?.trim() || undefined,
56
- price: s.price,
57
- })),
58
- pricingMode,
59
- uniformPrice: pricingMode === "uniform"
60
- ? Math.round(parseFloat(uniformPrice) * 100) / 100 || 0
61
- : undefined,
62
- drawWindowDurationMinutes: parseInt(drawWindowMinutes, 10) || 5,
63
- maxPullsPerTransaction: parseInt(maxPullsPerTx, 10) || 1,
64
- maxPullsPerUser: parseInt(maxPullsPerUser, 10) || 1,
65
- };
66
- /*
67
- * The schema was passed to `<Form>` and never actually run — so the
68
- * `parseFloat(x) || 0` coercions above, which it exists to catch, were
69
- * still live. Parsed here so a bad slot is refused on the client
70
- * rather than discovered as a 400.
71
- */
72
- const parsed = lotteryConfigWriteSchema.safeParse(candidate);
73
- if (!parsed.success) {
74
- setError(parsed.error.issues[0]?.message ?? "Check the lottery settings.");
75
- return;
76
- }
77
- await onSubmit({ title, description, type: "lottery", lotteryConfig: parsed.data });
78
- }
79
- catch (err) {
80
- void normalizeError(err);
81
- setError(err instanceof Error ? err.message : "Failed to save lottery");
82
- }
82
+ await onSubmit({ lotteryConfig: parsed.data });
83
83
  });
84
84
  };
85
- // Slot table columns
86
- const slotColumns = [
85
+ return (_jsx(StackedViewShell, { portal: "admin", title: eventId
86
+ ? `Edit lottery${initialData?.title ? ` — ${initialData.title}` : ""}`
87
+ : "Create lottery", sections: [
88
+ _jsxs(FormShellContext.Provider, { value: shellCtx, children: [_jsx(FormErrorSummary, {}), _jsx(SectionForm, { sections: sections, values: form, onChange: patch, onSubmit: handleSubmit, schema: lotteryConfigWriteSchema, openIds: nav.openIds, onOpenChange: nav.setOpenIds, isLoading: isPending, submitLabel: eventId ? "Update lottery" : "Create lottery" })] }, "lottery-config-form"),
89
+ ] }));
90
+ }
91
+ /**
92
+ * The repeatable slot rows.
93
+ *
94
+ * A module-level component rather than an inline renderer: its handlers would
95
+ * otherwise sit six braces deep inside `useMemo`, which is what
96
+ * `audit-code-quality`'s DEEP_NESTING rule exists to stop.
97
+ */
98
+ function SlotTable({ slots, showPrice, onSlotsChange, }) {
99
+ const addSlot = () => onSlotsChange([...slots, { slotNumber: slots.length + 1, name: "", price: 0 }]);
100
+ const removeSlot = (idx) => onSlotsChange(slots.filter((_, i) => i !== idx).map((s, i) => ({ ...s, slotNumber: i + 1 })));
101
+ const updateSlot = (idx, field, value) => onSlotsChange(slots.map((s, i) => i === idx
102
+ ? {
103
+ ...s,
104
+ [field]: field === "price"
105
+ ? Math.round(parseFloat(value) * 100) / 100 || 0
106
+ : value,
107
+ }
108
+ : s));
109
+ const rows = slots.map((s, i) => ({ ...s, _idx: i }));
110
+ const columns = [
87
111
  {
88
112
  key: "slotNumber",
89
113
  header: "#",
90
- render: (s) => _jsx(Text, { size: "xs", color: "muted", family: "mono", children: s.slotNumber }),
114
+ render: (s) => (_jsx(Text, { size: "xs", color: "muted", family: "mono", children: s.slotNumber })),
91
115
  },
92
116
  {
93
117
  key: "name",
94
- header: "Prize Name",
118
+ header: "Prize name",
95
119
  render: (s) => (_jsx(Input, { type: "text", className: "w-full", placeholder: `Prize for slot ${s.slotNumber}`, value: s.name, onChange: (e) => updateSlot(s._idx, "name", e.target.value), "aria-label": `Slot ${s.slotNumber} prize name` })),
96
120
  },
97
121
  {
@@ -99,7 +123,7 @@ export function LotteryAdminEditView({ eventId, initialData, onSubmit, }) {
99
123
  header: "Image",
100
124
  render: (s) => (_jsx(Input, { type: "text", className: "w-full", placeholder: "/media/\u2026 or https://\u2026", value: s.image ?? "", onChange: (e) => updateSlot(s._idx, "image", e.target.value), "aria-label": `Slot ${s.slotNumber} prize image URL` })),
101
125
  },
102
- ...(pricingMode === "variable"
126
+ ...(showPrice
103
127
  ? [
104
128
  {
105
129
  key: "price",
@@ -109,9 +133,5 @@ export function LotteryAdminEditView({ eventId, initialData, onSubmit, }) {
109
133
  ]
110
134
  : []),
111
135
  ];
112
- const slotsWithIdx = slots.map((s, i) => ({ ...s, _idx: i }));
113
- return (_jsx(Container, { children: _jsx(Section, { children: _jsx(Form, { schema: lotteryConfigFormSchema, onSubmit: (e) => e.preventDefault(), className: "space-y-6", children: ({ clearErrors }) => (_jsxs(Stack, { gap: "xl", children: [_jsx(FormErrorSummary, {}), _jsx(Heading, { level: 1, size: "2xl", weight: "bold", children: eventId ? "Edit Lottery" : "Create Lottery" }), _jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 2, size: "lg", weight: "semibold", children: "Basic Info" }), _jsx(FieldInput, { name: "title", label: "Title", required: true, value: title, onChange: (v) => { setTitle(v); clearErrors(); } }), _jsx(FieldInput, { name: "description", label: "Description", value: description, onChange: (v) => { setDescription(v); clearErrors(); } })] }), _jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 2, size: "lg", weight: "semibold", children: "Configuration" }), _jsx(FieldSelect, { name: "pricingMode", label: "Pricing Mode", value: pricingMode, options: [
114
- { label: "Uniform (all slots same price)", value: "uniform" },
115
- { label: "Variable (per-slot pricing)", value: "variable" },
116
- ], onChange: (v) => setPricingMode(v) }), pricingMode === "uniform" && (_jsx(FieldInput, { name: "uniformPrice", label: "Price per Slot (\u20B9)", type: "number", value: uniformPrice, onChange: (v) => setUniformPrice(v) })), _jsx(FieldInput, { name: "drawWindowMinutes", label: "Draw Window (minutes)", type: "number", value: drawWindowMinutes, onChange: (v) => setDrawWindowMinutes(v) }), _jsx(FieldInput, { name: "maxPullsPerTx", label: "Max Pulls per Transaction", type: "number", value: maxPullsPerTx, onChange: (v) => setMaxPullsPerTx(v) }), _jsx(FieldInput, { name: "maxPullsPerUser", label: "Max Pulls per User", type: "number", value: maxPullsPerUser, onChange: (v) => setMaxPullsPerUser(v) })] }), _jsxs(Stack, { gap: "md", children: [_jsxs(Row, { align: "center", justify: "between", children: [_jsxs(Heading, { level: 2, size: "lg", weight: "semibold", children: ["Slots (", slots.length, ")"] }), _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: addSlot, disabled: slots.length >= 200, children: "+ Add Slot" })] }), _jsx(DataTable, { data: slotsWithIdx, columns: slotColumns, keyExtractor: (s) => String(s.slotNumber), emptyMessage: "No slots yet.", actions: (s) => slots.length > 1 ? (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => removeSlot(s._idx), "aria-label": `Remove slot ${s.slotNumber}`, children: "\u00D7" })) : null })] }), error && _jsx(Text, { className: "text-error", size: "sm", role: "alert", children: error }), _jsx(Button, { type: "submit", variant: "primary", isLoading: isPending, onClick: handleSubmit, className: "w-full sm:w-auto", children: isPending ? "Saving…" : eventId ? "Update Lottery" : "Create Lottery" })] })) }) }) }));
136
+ return (_jsxs(Stack, { gap: "md", children: [_jsxs(Row, { align: "center", justify: "between", children: [_jsxs(Text, { size: "sm", color: "muted", children: [slots.length, " slot", slots.length === 1 ? "" : "s"] }), _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: addSlot, disabled: slots.length >= MAX_SLOTS, children: "+ Add slot" })] }), _jsx(DataTable, { data: rows, columns: columns, keyExtractor: (s) => String(s.slotNumber), emptyMessage: "No slots yet.", actions: (s) => slots.length > 1 ? (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => removeSlot(s._idx), "aria-label": `Remove slot ${s.slotNumber}`, children: "\u00D7" })) : null })] }));
117
137
  }
@@ -1,3 +1,19 @@
1
+ /**
2
+ * User-facing lottery pull form — claim a slot with a UPI reference.
3
+ *
4
+ * Fields come from `lotteryPullSchema`. Two need a `renderers` entry because
5
+ * their labels depend on `totalSlots`, which a static annotation cannot know,
6
+ * and one needs `datetime-local` rather than a plain date.
7
+ *
8
+ * ## The upper bound stays a runtime check, on purpose
9
+ *
10
+ * `purchasedItemNumber` is `.min(1)` in the schema and has no `.max()`: the
11
+ * ceiling is `totalSlots`, a prop that varies per lottery. A schema shared with
12
+ * the route cannot carry it, so it is checked after the parse rather than
13
+ * pretended into the annotation. Everything else the hand-written validation
14
+ * used to duplicate — the reference length, the phone shape, the date — now
15
+ * comes from the schema, which is where those rules already lived.
16
+ */
1
17
  import React from "react";
2
18
  interface LotteryPullFormProps {
3
19
  sourceType: "event" | "product";
@@ -11,10 +27,5 @@ interface LotteryPullFormProps {
11
27
  slotName: string;
12
28
  }) => void;
13
29
  }
14
- /**
15
- * User-facing lottery pull form.
16
- * Submits TX ID + phone + payment time + item number.
17
- * On success, shows the user their lottery number and assigned prize slot.
18
- */
19
30
  export declare function LotteryPullForm({ sourceType, eventId, productId, totalSlots, maxPullsPerUser, onSuccess, }: LotteryPullFormProps): React.JSX.Element;
20
31
  export {};
@@ -1,34 +1,67 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useState } from "react";
4
- import { Stack, Row, Text, Heading, Span, } from "../../../../ui";
5
- import { Form, FieldInput, Button } from "../../../../ui";
3
+ /**
4
+ * User-facing lottery pull form — claim a slot with a UPI reference.
5
+ *
6
+ * Fields come from `lotteryPullSchema`. Two need a `renderers` entry because
7
+ * their labels depend on `totalSlots`, which a static annotation cannot know,
8
+ * and one needs `datetime-local` rather than a plain date.
9
+ *
10
+ * ## The upper bound stays a runtime check, on purpose
11
+ *
12
+ * `purchasedItemNumber` is `.min(1)` in the schema and has no `.max()`: the
13
+ * ceiling is `totalSlots`, a prop that varies per lottery. A schema shared with
14
+ * the route cannot carry it, so it is checked after the parse rather than
15
+ * pretended into the annotation. Everything else the hand-written validation
16
+ * used to duplicate — the reference length, the phone shape, the date — now
17
+ * comes from the schema, which is where those rules already lived.
18
+ */
19
+ import { useMemo, useState } from "react";
6
20
  import { useApiMutation } from "../../../../client/api/useApiMutation";
7
- import { apiClient } from "../../../../http";
8
21
  import { lotteryPullSchema } from "../../../../features/admin/schemas/admin-user-form";
22
+ import { buildSectionsFromSchema } from "../../../../features/shell/build-sections";
23
+ import { SectionForm, useSectionFormNav } from "../../../../features/shell/SectionForm";
24
+ import { apiClient } from "../../../../http";
25
+ import { FieldInput, Heading, Row, Span, Stack, Text } from "../../../../ui";
26
+ import { applyZodIssues } from "../../../../ui/forms/apply-zod-issues";
9
27
  import { FormErrorSummary } from "../../../../ui/forms/FormErrorSummary";
10
- /**
11
- * User-facing lottery pull form.
12
- * Submits TX ID + phone + payment time + item number.
13
- * On success, shows the user their lottery number and assigned prize slot.
14
- */
28
+ import { FormShellContext, useFormShellState } from "../../../../ui/forms/FormShell";
15
29
  export function LotteryPullForm({ sourceType, eventId, productId, totalSlots, maxPullsPerUser, onSuccess, }) {
16
30
  const [result, setResult] = useState(null);
17
- const [transactionId, setTransactionId] = useState("");
18
- const [paymentTime, setPaymentTime] = useState("");
19
- const [itemNumber, setItemNumber] = useState("");
20
- const [userPhone, setUserPhone] = useState("");
31
+ const [form, setForm] = useState({
32
+ sourceType,
33
+ transactionId: "",
34
+ paymentTime: "",
35
+ purchasedItemNumber: "",
36
+ userPhone: "",
37
+ });
21
38
  const apiRoute = sourceType === "event"
22
39
  ? `/api/events/${eventId ?? ""}/lottery-pull`
23
40
  : `/api/products/${productId ?? ""}/lottery-pull`;
41
+ const sections = useMemo(() => buildSectionsFromSchema(lotteryPullSchema, {
42
+ renderers: {
43
+ paymentTime: ({ values, onChange, errors }) => (_jsx(FieldInput, { name: "paymentTime", label: "Payment Date & Time",
44
+ // `datetime-local`, not `date` — the pull is matched against a
45
+ // bank timestamp, so the time of day is part of the evidence.
46
+ type: "datetime-local", required: true, value: values.paymentTime, error: errors.paymentTime, onChange: (v) => onChange({ paymentTime: v }) })),
47
+ purchasedItemNumber: ({ values, onChange, errors }) => (_jsx(FieldInput, { name: "purchasedItemNumber", label: `Slot Number (1 – ${totalSlots})`, type: "number", placeholder: `Enter a number between 1 and ${totalSlots}`, required: true, value: values.purchasedItemNumber, error: errors.purchasedItemNumber, onChange: (v) => onChange({ purchasedItemNumber: v }) })),
48
+ },
49
+ }), [totalSlots]);
50
+ const nav = useSectionFormNav(sections, form, { scope: "lottery:pull" });
51
+ const { shellCtx, setFieldError, clearErrors } = useFormShellState(lotteryPullSchema, {
52
+ sections: nav.sectionMeta,
53
+ onGoToSection: nav.goToSection,
54
+ fieldToSectionIndex: nav.fieldToSectionIndex,
55
+ });
24
56
  const mutation = useApiMutation({
57
+ errorMessage: "Could not submit your entry.",
25
58
  mutationFn: () => apiClient.post(apiRoute, {
26
59
  sourceType,
27
60
  ...(sourceType === "event" ? { eventId } : { productId }),
28
- transactionId,
29
- paymentTime: new Date(paymentTime).toISOString(),
30
- purchasedItemNumber: parseInt(itemNumber, 10),
31
- userPhone,
61
+ transactionId: form.transactionId,
62
+ paymentTime: new Date(form.paymentTime).toISOString(),
63
+ purchasedItemNumber: parseInt(form.purchasedItemNumber, 10),
64
+ userPhone: form.userPhone,
32
65
  }),
33
66
  successMessage: "Your lottery entry has been submitted!",
34
67
  onSuccess: (data) => {
@@ -38,30 +71,22 @@ export function LotteryPullForm({ sourceType, eventId, productId, totalSlots, ma
38
71
  }
39
72
  },
40
73
  });
74
+ const onSubmit = () => {
75
+ clearErrors();
76
+ const parsed = lotteryPullSchema.safeParse(form);
77
+ if (!parsed.success) {
78
+ applyZodIssues(parsed.error.issues, setFieldError);
79
+ return;
80
+ }
81
+ // Data-dependent ceiling — see the header.
82
+ if (parsed.data.purchasedItemNumber > totalSlots) {
83
+ setFieldError("purchasedItemNumber", `This lottery has ${totalSlots} slots.`);
84
+ return;
85
+ }
86
+ mutation.mutate();
87
+ };
41
88
  if (result) {
42
89
  return (_jsxs(Stack, { gap: "sm", padding: "md", rounded: "2xl", surface: "success-surface", className: "border border-success/20", children: [_jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Span, { layout: "inline-flex", color: "inverse", weight: "semibold", className: "bg-success text-[11px] tracking-wide", padding: "pill-sm", rounded: "full", transform: "uppercase", children: "Entry Confirmed" }), _jsxs(Heading, { level: 2, className: "text-success", size: "lg", weight: "bold", children: ["You're #", result.userLotteryNumber, "!"] })] }), _jsxs(Text, { className: "text-success", size: "sm", children: ["You've been assigned", " ", _jsxs(Span, { weight: "bold", children: ["Slot #", result.assignedPrizeSlotNumber] }), result.slotName ? ` — ${result.slotName}` : "", ". Good luck!"] })] }));
43
90
  }
44
- return (_jsx(Form, { schema: lotteryPullSchema, onSubmit: (e) => e.preventDefault(), className: "space-y-4", children: ({ setFieldError, clearErrors }) => (_jsxs(Stack, { gap: "md", children: [_jsx(FormErrorSummary, {}), _jsx(Heading, { level: 3, size: "lg", weight: "semibold", children: "Submit Your Entry" }), _jsxs(Text, { size: "sm", color: "muted", children: ["Enter your UPI Transaction ID and payment details to claim your slot.", " ", "You may enter up to ", maxPullsPerUser, " time", maxPullsPerUser === 1 ? "" : "s", "."] }), _jsx(FieldInput, { name: "transactionId", label: "Transaction ID (UPI Ref / Payment Ref)", placeholder: "e.g. 123456789012", required: true, value: transactionId, onChange: (v) => { setTransactionId(v); clearErrors(); } }), _jsx(FieldInput, { name: "paymentTime", label: "Payment Date & Time", type: "datetime-local", required: true, value: paymentTime, onChange: (v) => { setPaymentTime(v); clearErrors(); } }), _jsx(FieldInput, { name: "itemNumber", label: `Slot Number (1 – ${totalSlots})`, type: "number", placeholder: `Enter a number between 1 and ${totalSlots}`, required: true, value: itemNumber, onChange: (v) => { setItemNumber(v); clearErrors(); } }), _jsx(FieldInput, { name: "userPhone", label: "Your Phone Number", type: "tel", placeholder: "e.g. 9876543210", required: true, value: userPhone, onChange: (v) => { setUserPhone(v); clearErrors(); } }), _jsx(Button, { type: "submit", variant: "primary", isLoading: mutation.isPending, onClick: () => {
45
- clearErrors();
46
- const num = parseInt(itemNumber, 10);
47
- let valid = true;
48
- if (!transactionId || transactionId.length < 4) {
49
- setFieldError("transactionId", "Transaction ID must be at least 4 characters");
50
- valid = false;
51
- }
52
- if (!paymentTime) {
53
- setFieldError("paymentTime", "Payment date & time is required");
54
- valid = false;
55
- }
56
- if (isNaN(num) || num < 1 || num > totalSlots) {
57
- setFieldError("itemNumber", `Slot number must be between 1 and ${totalSlots}`);
58
- valid = false;
59
- }
60
- if (!userPhone || userPhone.replace(/\D/g, "").length < 10) {
61
- setFieldError("userPhone", "Enter a valid phone number (minimum 10 digits)");
62
- valid = false;
63
- }
64
- if (valid)
65
- mutation.mutate();
66
- }, className: "w-full", children: mutation.isPending ? "Submitting…" : "Submit Entry" })] })) }));
91
+ return (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, size: "lg", weight: "semibold", children: "Submit Your Entry" }), _jsxs(Text, { size: "sm", color: "muted", children: ["Enter your UPI Transaction ID and payment details to claim your slot. You may enter up to", " ", maxPullsPerUser, " time", maxPullsPerUser === 1 ? "" : "s", "."] }), _jsxs(FormShellContext.Provider, { value: shellCtx, children: [_jsx(FormErrorSummary, {}), _jsx(SectionForm, { sections: sections, values: form, onChange: (partial) => setForm((prev) => Object.assign({}, prev, partial)), onSubmit: onSubmit, schema: lotteryPullSchema, openIds: nav.openIds, onOpenChange: nav.setOpenIds, isLoading: mutation.isPending, submitLabel: "Submit Entry" })] })] }));
67
92
  }
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { normalizeError } from "../../../../../errors/normalize";
4
+ import { toUserMessage } from "../../../../../errors/error-display-map";
4
5
  import * as React from "react";
5
6
  import { Button, Div, Heading, Input, Li, Section, Span, Table, Tbody, Td, Text, Th, Thead, Tr, Ul } from "@mohasinac/appkit/client";
6
7
  import { Select } from "@mohasinac/appkit/ui";
@@ -29,8 +30,10 @@ export function AnalysisRunnerView() {
29
30
  setReport(body.data);
30
31
  }
31
32
  catch (err) {
32
- void normalizeError(err);
33
- setError(err instanceof Error ? err.message : String(err));
33
+ const e = normalizeError(err);
34
+ setError(toUserMessage(e.code, undefined, {
35
+ fallback: "Could not run the analysis. Check the server logs for detail.",
36
+ }));
34
37
  }
35
38
  finally {
36
39
  setRunning(false);
@@ -4,6 +4,7 @@ import * as React from "react";
4
4
  import { Button, Div, Heading, Span, Table, Tbody, Td, Text, Th, Thead, Tr } from "@mohasinac/appkit/client";
5
5
  import { ADMIN_ENDPOINTS } from "../../../../../constants/api-endpoints";
6
6
  import { normalizeError } from "../../../../../errors/normalize";
7
+ import { toUserMessage } from "../../../../../errors/error-display-map";
7
8
  const BORDER_STYLE = "1px solid var(--appkit-color-border)";
8
9
  const COLUMNS = [
9
10
  { key: "timestampFmt", label: "When", width: "180px" },
@@ -38,8 +39,10 @@ export function CloudLogsListView({ title, subtitle, initialEntries, initialNext
38
39
  setNextPageToken(body.data.nextPageToken);
39
40
  }
40
41
  catch (err) {
41
- void normalizeError(err);
42
- setError(err instanceof Error ? err.message : String(err));
42
+ const e = normalizeError(err);
43
+ setError(toUserMessage(e.code, undefined, {
44
+ fallback: "Could not load more log entries. Please try again.",
45
+ }));
43
46
  }
44
47
  finally {
45
48
  setLoadingMore(false);
@@ -51,5 +54,10 @@ export function CloudLogsListView({ title, subtitle, initialEntries, initialNext
51
54
  borderBottom: BORDER_STYLE,
52
55
  width: c.width,
53
56
  whiteSpace: "nowrap",
54
- }, children: c.label }, c.key))) }) }), _jsx(Tbody, { children: entries.length === 0 ? (_jsx(Tr, { children: _jsx(Td, { colSpan: COLUMNS.length, style: { padding: "2rem", textAlign: "center", color: "var(--appkit-color-text-muted)" }, children: "No log entries in the selected window." }) })) : (entries.map((e) => (_jsxs(Tr, { style: { borderBottom: "1px solid var(--appkit-color-border-subtle)" }, children: [_jsx(Td, { style: { padding: "0.5rem 0.75rem", verticalAlign: "top", whiteSpace: "nowrap" }, children: fmt(e.timestamp) }), _jsx(Td, { style: { padding: "0.5rem 0.75rem", verticalAlign: "top" }, children: e.severity }), _jsx(Td, { style: { padding: "0.5rem 0.75rem", verticalAlign: "top" }, children: e.resourceType }), _jsx(Td, { style: { padding: "0.5rem 0.75rem", verticalAlign: "top", fontFamily: "monospace" }, children: e.message })] }, e.id)))) })] }) }), _jsx(Div, { style: { marginTop: "1rem", textAlign: "center" }, children: nextPageToken ? (_jsx(Button, { type: "button", onClick: loadMore, isLoading: loadingMore, children: "Load more" })) : entries.length > 0 ? (_jsx(Text, { style: { color: "var(--appkit-color-text-muted)", fontSize: "0.85rem" }, children: "No more entries." })) : null })] }));
57
+ }, children: c.label }, c.key))) }) }), _jsx(Tbody, { children: entries.length === 0 ? (_jsx(Tr, { children: _jsx(Td, { colSpan: COLUMNS.length, style: { padding: "2rem", textAlign: "center", color: "var(--appkit-color-text-muted)" }, children: "No log entries in the selected window." }) })) : (
58
+ // Named `entry`, not `e`: this is a Cloud Logging record, not a
59
+ // caught error, and rendering its `.message` is the entire point
60
+ // of this admin viewer. The short name read as the defect
61
+ // audit-raw-error-text exists to catch.
62
+ entries.map((entry) => (_jsxs(Tr, { style: { borderBottom: "1px solid var(--appkit-color-border-subtle)" }, children: [_jsx(Td, { style: { padding: "0.5rem 0.75rem", verticalAlign: "top", whiteSpace: "nowrap" }, children: fmt(entry.timestamp) }), _jsx(Td, { style: { padding: "0.5rem 0.75rem", verticalAlign: "top" }, children: entry.severity }), _jsx(Td, { style: { padding: "0.5rem 0.75rem", verticalAlign: "top" }, children: entry.resourceType }), _jsx(Td, { style: { padding: "0.5rem 0.75rem", verticalAlign: "top", fontFamily: "monospace" }, children: entry.message })] }, entry.id)))) })] }) }), _jsx(Div, { style: { marginTop: "1rem", textAlign: "center" }, children: nextPageToken ? (_jsx(Button, { type: "button", onClick: loadMore, isLoading: loadingMore, children: "Load more" })) : entries.length > 0 ? (_jsx(Text, { style: { color: "var(--appkit-color-text-muted)", fontSize: "0.85rem" }, children: "No more entries." })) : null })] }));
55
63
  }