@mohasinac/appkit 4.30.19 → 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 (417) hide show
  1. package/dist/_internal/client/features/layout/useSidebarSearch.d.ts +21 -5
  2. package/dist/_internal/client/features/layout/useSidebarSearch.js +27 -6
  3. package/dist/_internal/client/features/lottery/LotteryAdminEditView.d.ts +23 -3
  4. package/dist/_internal/client/features/lottery/LotteryAdminEditView.js +106 -87
  5. package/dist/_internal/client/features/lottery/LotteryPullForm.d.ts +16 -5
  6. package/dist/_internal/client/features/lottery/LotteryPullForm.js +65 -40
  7. package/dist/_internal/server/features/auth/permissions.d.ts +2 -0
  8. package/dist/_internal/server/features/auth/permissions.js +3 -2
  9. package/dist/_internal/server/features/categories/data.js +15 -4
  10. package/dist/_internal/server/features/classified/index.d.ts +0 -1
  11. package/dist/_internal/server/features/classified/index.js +0 -1
  12. package/dist/_internal/server/features/digital-code/index.d.ts +0 -1
  13. package/dist/_internal/server/features/digital-code/index.js +0 -1
  14. package/dist/_internal/server/features/live/index.d.ts +0 -1
  15. package/dist/_internal/server/features/live/index.js +0 -1
  16. package/dist/_internal/server/features/products/data.js +15 -5
  17. package/dist/_internal/server/features/products/list-public.d.ts +9 -0
  18. package/dist/_internal/server/features/products/list-public.js +95 -7
  19. package/dist/_internal/server/features/site-settings/adapters.d.ts +2 -2
  20. package/dist/_internal/server/features/site-settings/adapters.js +8 -5
  21. package/dist/_internal/server/features/tester/visibility.d.ts +2 -1
  22. package/dist/_internal/server/features/tester/visibility.js +2 -2
  23. package/dist/_internal/server/functions/scheduled.d.ts +3 -1
  24. package/dist/_internal/server/functions/scheduled.js +27 -1
  25. package/dist/_internal/server/jobs/core/hardBanCascade.js +4 -0
  26. package/dist/_internal/server/jobs/core/index.d.ts +2 -0
  27. package/dist/_internal/server/jobs/core/index.js +2 -0
  28. package/dist/_internal/server/jobs/core/pageViewPrune.d.ts +10 -0
  29. package/dist/_internal/server/jobs/core/pageViewPrune.js +44 -0
  30. package/dist/_internal/server/jobs/core/pageViewRollup.d.ts +2 -0
  31. package/dist/_internal/server/jobs/core/pageViewRollup.js +87 -0
  32. package/dist/_internal/server/jobs/handlers/index.d.ts +2 -0
  33. package/dist/_internal/server/jobs/handlers/index.js +2 -0
  34. package/dist/_internal/server/jobs/handlers/pageViewPrune.d.ts +2 -0
  35. package/dist/_internal/server/jobs/handlers/pageViewPrune.js +2 -0
  36. package/dist/_internal/server/jobs/handlers/pageViewRollup.d.ts +2 -0
  37. package/dist/_internal/server/jobs/handlers/pageViewRollup.js +2 -0
  38. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  39. package/dist/_internal/shared/actions/action-registry.js +69 -22
  40. package/dist/_internal/shared/checkout/rules/classified.rule.d.ts +9 -4
  41. package/dist/_internal/shared/checkout/rules/classified.rule.js +7 -2
  42. package/dist/_internal/shared/features/layout/matchesNavQuery.d.ts +14 -0
  43. package/dist/_internal/shared/features/layout/matchesNavQuery.js +72 -0
  44. package/dist/_internal/shared/features/layout/types.d.ts +37 -1
  45. package/dist/_internal/shared/features/layout/types.js +19 -1
  46. package/dist/_internal/shared/features/notifications/action-url.d.ts +9 -1
  47. package/dist/_internal/shared/features/notifications/action-url.js +47 -0
  48. package/dist/_internal/shared/features/offers/config.d.ts +65 -0
  49. package/dist/_internal/shared/features/offers/config.js +73 -2
  50. package/dist/_internal/shared/features/orders/schema.d.ts +19 -1
  51. package/dist/_internal/shared/features/orders/schema.js +22 -2
  52. package/dist/_internal/shared/features/site-settings/types.d.ts +12 -3
  53. package/dist/_internal/shared/listing-types/capabilities.d.ts +8 -2
  54. package/dist/_internal/shared/listing-types/capabilities.js +6 -1
  55. package/dist/_internal/shared/listing-types/classified/ctas.js +6 -1
  56. package/dist/_internal/shared/listing-types/feature-flags.d.ts +10 -5
  57. package/dist/_internal/shared/listing-types/feature-flags.js +11 -6
  58. package/dist/client.d.ts +37 -20
  59. package/dist/client.js +36 -14
  60. package/dist/configs/next.js +10 -2
  61. package/dist/constants/api-endpoints.d.ts +18 -54
  62. package/dist/constants/api-endpoints.js +6 -26
  63. package/dist/constants/field-names.d.ts +6 -24
  64. package/dist/constants/field-names.js +10 -27
  65. package/dist/constants/geo/countries.d.ts +50 -0
  66. package/dist/constants/geo/countries.js +129 -0
  67. package/dist/constants/geo/subdivisions.d.ts +13 -0
  68. package/dist/constants/geo/subdivisions.js +104 -0
  69. package/dist/constants/index.d.ts +2 -2
  70. package/dist/constants/index.js +2 -2
  71. package/dist/constants/table-keys.d.ts +24 -0
  72. package/dist/constants/table-keys.js +28 -0
  73. package/dist/contracts/extend.d.ts +0 -9
  74. package/dist/contracts/index.d.ts +1 -1
  75. package/dist/contracts/realtime-session.js +7 -0
  76. package/dist/core/browser.d.ts +1 -1
  77. package/dist/core/browser.js +1 -1
  78. package/dist/core/index.d.ts +1 -1
  79. package/dist/core/index.js +1 -1
  80. package/dist/core/site-config.d.ts +0 -3
  81. package/dist/core/site-config.js +0 -3
  82. package/dist/errors/messages.d.ts +0 -8
  83. package/dist/errors/messages.js +0 -9
  84. package/dist/features/about/schemas/index.d.ts +8 -8
  85. package/dist/features/account/components/AddressFilters.js +32 -11
  86. package/dist/features/account/components/AddressForm.d.ts +26 -25
  87. package/dist/features/account/components/AddressForm.js +81 -103
  88. package/dist/features/account/components/AddressesIndexListing.js +8 -4
  89. package/dist/features/account/components/UserSidebar.d.ts +3 -4
  90. package/dist/features/account/components/UserSupportView.js +89 -58
  91. package/dist/features/account/components/index.d.ts +1 -7
  92. package/dist/features/account/components/index.js +0 -3
  93. package/dist/features/account/hooks/useAddresses.d.ts +4 -3
  94. package/dist/features/account/hooks/useAddresses.js +4 -6
  95. package/dist/features/account/hooks/useCollapsedSections.d.ts +51 -10
  96. package/dist/features/account/hooks/useCollapsedSections.js +211 -38
  97. package/dist/features/account/hooks/useProfile.d.ts +8 -0
  98. package/dist/features/account/index.d.ts +0 -3
  99. package/dist/features/account/index.js +0 -3
  100. package/dist/features/account/schemas/index.d.ts +0 -92
  101. package/dist/features/account/schemas/index.js +42 -20
  102. package/dist/features/addresses/components/AddressLocationFields.d.ts +13 -0
  103. package/dist/features/addresses/components/AddressLocationFields.js +41 -0
  104. package/dist/features/addresses/hooks/usePostalLookup.d.ts +17 -0
  105. package/dist/features/addresses/hooks/usePostalLookup.js +133 -0
  106. package/dist/features/addresses/schemas/address-form.d.ts +423 -0
  107. package/dist/features/addresses/schemas/address-form.js +212 -0
  108. package/dist/features/addresses/schemas/index.d.ts +1 -0
  109. package/dist/features/addresses/schemas/index.js +8 -0
  110. package/dist/features/admin/actions/admin-read-actions.d.ts +1 -1
  111. package/dist/features/admin/actions/index.d.ts +0 -1
  112. package/dist/features/admin/actions/index.js +0 -1
  113. package/dist/features/admin/actions/notification-actions.js +1 -41
  114. package/dist/features/admin/components/AdminActionIndexView.d.ts +32 -0
  115. package/dist/features/admin/components/AdminActionIndexView.js +128 -0
  116. package/dist/features/admin/components/AdminAdEditorView.js +159 -163
  117. package/dist/features/admin/components/AdminAddressEditorView.js +97 -55
  118. package/dist/features/admin/components/AdminBrandEditorView.d.ts +15 -0
  119. package/dist/features/admin/components/AdminBrandEditorView.js +113 -77
  120. package/dist/features/admin/components/AdminBundleEditorView.d.ts +19 -9
  121. package/dist/features/admin/components/AdminBundleEditorView.js +136 -168
  122. package/dist/features/admin/components/AdminCategoryEditorView.js +120 -43
  123. package/dist/features/admin/components/AdminCouponEditorView.js +145 -109
  124. package/dist/features/admin/components/AdminEmployeeEditorView.js +125 -56
  125. package/dist/features/admin/components/AdminFaqEditorView.js +112 -58
  126. package/dist/features/admin/components/AdminFeatureEditorView.js +108 -68
  127. package/dist/features/admin/components/AdminNavEditorView.js +69 -44
  128. package/dist/features/admin/components/AdminOrderEditorView.js +47 -10
  129. package/dist/features/admin/components/AdminPrizeDrawsView.js +16 -2
  130. package/dist/features/admin/components/AdminSidebar.d.ts +11 -7
  131. package/dist/features/admin/components/AdminSiteSettingsView.js +37 -37
  132. package/dist/features/admin/components/AdminStoreEditorView.js +75 -52
  133. package/dist/features/admin/components/AdminSublistingCategoryEditorView.js +71 -30
  134. package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +95 -65
  135. package/dist/features/admin/components/BrandQuickCreateForm.d.ts +10 -0
  136. package/dist/features/admin/components/BrandQuickCreateForm.js +49 -26
  137. package/dist/features/admin/components/CategoryQuickCreateForm.d.ts +11 -0
  138. package/dist/features/admin/components/CategoryQuickCreateForm.js +48 -26
  139. package/dist/features/admin/components/index.d.ts +2 -2
  140. package/dist/features/admin/components/index.js +1 -1
  141. package/dist/features/admin/constants/site-settings-tabs.d.ts +120 -0
  142. package/dist/features/admin/constants/site-settings-tabs.js +152 -0
  143. package/dist/features/admin/index.d.ts +0 -3
  144. package/dist/features/admin/index.js +0 -2
  145. package/dist/features/admin/repository/analytics-rollup.repository.d.ts +35 -0
  146. package/dist/features/admin/repository/analytics-rollup.repository.js +30 -0
  147. package/dist/features/admin/schemas/admin-editor-forms.d.ts +56 -57
  148. package/dist/features/admin/schemas/admin-editor-forms.js +97 -54
  149. package/dist/features/admin/schemas/admin-ops-forms.d.ts +57 -5
  150. package/dist/features/admin/schemas/admin-ops-forms.js +104 -20
  151. package/dist/features/admin/schemas/admin-user-form.js +7 -0
  152. package/dist/features/admin/schemas/firestore.d.ts +48 -95
  153. package/dist/features/admin/schemas/firestore.js +15 -151
  154. package/dist/features/admin/schemas/nav-item-form.js +9 -2
  155. package/dist/features/admin/server.d.ts +0 -4
  156. package/dist/features/admin/server.js +0 -2
  157. package/dist/features/admin/types/index.d.ts +0 -7
  158. package/dist/features/analytics/repository/page-views.repository.d.ts +14 -0
  159. package/dist/features/analytics/repository/page-views.repository.js +24 -0
  160. package/dist/features/auth/actions/index.d.ts +0 -1
  161. package/dist/features/auth/actions/index.js +0 -1
  162. package/dist/features/auth/actions/realtime-token-actions.js +1 -12
  163. package/dist/features/auth/auth-helpers.js +5 -7
  164. package/dist/features/auth/components/Guards.js +2 -1
  165. package/dist/features/auth/components/LoginForm.d.ts +0 -2
  166. package/dist/features/auth/components/LoginForm.js +1 -3
  167. package/dist/features/auth/components/RegisterForm.js +62 -19
  168. package/dist/features/auth/permissions/constants.d.ts +27 -1
  169. package/dist/features/auth/role-predicates.d.ts +75 -7
  170. package/dist/features/auth/role-predicates.js +28 -2
  171. package/dist/features/auth/schemas/firestore.d.ts +22 -0
  172. package/dist/features/auth/schemas/index.d.ts +1 -1
  173. package/dist/features/auth/schemas/index.js +44 -8
  174. package/dist/features/auth/types/index.d.ts +14 -1
  175. package/dist/features/blog/api/route.js +10 -2
  176. package/dist/features/blog/components/BlogIndexListing.js +1 -1
  177. package/dist/features/blog/hooks/useBlog.js +2 -2
  178. package/dist/features/blog/schemas/index.d.ts +4 -0
  179. package/dist/features/blog/schemas/index.js +2 -0
  180. package/dist/features/blog/types/index.d.ts +1 -1
  181. package/dist/features/catalogue/components/CatalogueItemEditorView.d.ts +22 -0
  182. package/dist/features/catalogue/components/CatalogueItemEditorView.js +112 -52
  183. package/dist/features/catalogue/schemas/validation.d.ts +4 -4
  184. package/dist/features/catalogue/schemas/validation.js +47 -10
  185. package/dist/features/categories/schemas/bundle-form.d.ts +142 -0
  186. package/dist/features/categories/schemas/bundle-form.js +149 -0
  187. package/dist/features/classified/components/ClassifiedDetailPageView.d.ts +5 -4
  188. package/dist/features/classified/components/ClassifiedDetailPageView.js +37 -16
  189. package/dist/features/consultation/components/ConsultationForm.js +1 -1
  190. package/dist/features/consultation/schemas/index.js +34 -10
  191. package/dist/features/corporate/schemas/index.js +36 -15
  192. package/dist/features/filters/FilterPanel.js +3 -3
  193. package/dist/features/filters/RangeFilter.d.ts +10 -0
  194. package/dist/features/filters/RangeFilter.js +41 -4
  195. package/dist/features/homepage/components/MarketplaceHomepageView.js +24 -5
  196. package/dist/features/homepage/hooks/useBlogArticles.js +1 -1
  197. package/dist/features/layout/BottomActions.js +84 -11
  198. package/dist/features/layout/BottomActionsContext.d.ts +1 -6
  199. package/dist/features/layout/BottomActionsContext.js +1 -1
  200. package/dist/features/layout/hooks/useBottomActions.js +2 -2
  201. package/dist/features/layout/hooks/useFormBottomActions.d.ts +12 -1
  202. package/dist/features/layout/hooks/useFormBottomActions.js +12 -6
  203. package/dist/features/lottery/schemas/config-write.d.ts +9 -5
  204. package/dist/features/lottery/schemas/config-write.js +69 -9
  205. package/dist/features/orders/schemas/buyer-forms.d.ts +6 -3
  206. package/dist/features/orders/schemas/buyer-forms.js +31 -3
  207. package/dist/features/orders/schemas/index.d.ts +2 -2
  208. package/dist/features/products/components/GroupSettingsPanel.js +3 -1
  209. package/dist/features/products/components/MakeOfferButton.d.ts +13 -2
  210. package/dist/features/products/components/MakeOfferButton.js +33 -11
  211. package/dist/features/products/components/ProductDetailActions.js +0 -1
  212. package/dist/features/products/components/ProductDetailPageView.d.ts +7 -3
  213. package/dist/features/products/components/ProductDetailPageView.js +8 -5
  214. package/dist/features/products/constants/action-defs.d.ts +1 -2
  215. package/dist/features/products/constants/action-defs.js +40 -43
  216. package/dist/features/products/repository/products.repository.d.ts +5 -1
  217. package/dist/features/products/repository/products.repository.js +23 -1
  218. package/dist/features/products/schemas/firestore.d.ts +7 -3
  219. package/dist/features/products/schemas/product-features.validators.js +3 -0
  220. package/dist/features/promotions/components/CouponCard.js +8 -7
  221. package/dist/features/scams/schemas/firestore.d.ts +15 -1
  222. package/dist/features/scams/schemas/report-form.d.ts +5 -5
  223. package/dist/features/scams/schemas/report-form.js +18 -3
  224. package/dist/features/search/action-index/derive.d.ts +49 -0
  225. package/dist/features/search/action-index/derive.js +121 -0
  226. package/dist/features/search/action-index/repository.d.ts +42 -0
  227. package/dist/features/search/action-index/repository.js +100 -0
  228. package/dist/features/search/action-index/settings-entries.d.ts +41 -0
  229. package/dist/features/search/action-index/settings-entries.js +268 -0
  230. package/dist/features/search/action-index/types.d.ts +81 -0
  231. package/dist/features/search/action-index/types.js +102 -0
  232. package/dist/features/search/action-index/validate-entry.d.ts +34 -0
  233. package/dist/features/search/action-index/validate-entry.js +114 -0
  234. package/dist/features/search/hooks/useNavSuggestions.d.ts +5 -1
  235. package/dist/features/search/hooks/useNavSuggestions.js +23 -3
  236. package/dist/features/search/repository/search.repository.js +3 -1
  237. package/dist/features/seller/actions/offer-actions.js +43 -24
  238. package/dist/features/seller/actions/seller-actions.js +29 -5
  239. package/dist/features/seller/components/CategoryChipPicker.d.ts +9 -0
  240. package/dist/features/seller/components/CategoryChipPicker.js +12 -0
  241. package/dist/features/seller/components/SellerAddressesView.js +5 -1
  242. package/dist/features/seller/components/SellerAnalyticsAlertsView.js +83 -43
  243. package/dist/features/seller/components/SellerArtView.d.ts +14 -7
  244. package/dist/features/seller/components/SellerArtView.js +4 -119
  245. package/dist/features/seller/components/SellerClassifiedView.d.ts +14 -7
  246. package/dist/features/seller/components/SellerClassifiedView.js +4 -124
  247. package/dist/features/seller/components/SellerCouponEditorView.d.ts +22 -1
  248. package/dist/features/seller/components/SellerCouponEditorView.js +91 -45
  249. package/dist/features/seller/components/SellerDigitalCodesView.d.ts +14 -7
  250. package/dist/features/seller/components/SellerDigitalCodesView.js +4 -126
  251. package/dist/features/seller/components/SellerListingTypeView.d.ts +66 -0
  252. package/dist/features/seller/components/SellerListingTypeView.js +277 -0
  253. package/dist/features/seller/components/SellerLiveView.d.ts +14 -7
  254. package/dist/features/seller/components/SellerLiveView.js +4 -126
  255. package/dist/features/seller/components/SellerSidebar.d.ts +3 -6
  256. package/dist/features/seller/components/SellerStickersView.d.ts +14 -7
  257. package/dist/features/seller/components/SellerStickersView.js +4 -119
  258. package/dist/features/seller/components/SellerSupportView.d.ts +31 -0
  259. package/dist/features/seller/components/SellerSupportView.js +100 -0
  260. package/dist/features/seller/components/index.d.ts +4 -8
  261. package/dist/features/seller/components/index.js +2 -4
  262. package/dist/features/seller/index.d.ts +0 -1
  263. package/dist/features/seller/index.js +0 -1
  264. package/dist/features/seller/schemas/coupon-form.d.ts +214 -0
  265. package/dist/features/seller/schemas/coupon-form.js +155 -23
  266. package/dist/features/seller/schemas/offer-forms.d.ts +16 -7
  267. package/dist/features/seller/schemas/offer-forms.js +28 -12
  268. package/dist/features/shell/FormShell.js +2 -2
  269. package/dist/features/shell/QuickFormDrawer.js +2 -2
  270. package/dist/features/shell/SectionForm.d.ts +19 -1
  271. package/dist/features/shell/SectionForm.js +104 -17
  272. package/dist/features/shell/build-sections.d.ts +23 -0
  273. package/dist/features/shell/build-sections.js +106 -8
  274. package/dist/features/shell/field-ui-meta.d.ts +44 -0
  275. package/dist/features/shell/field-ui-meta.js +14 -7
  276. package/dist/features/shell/form-sections.d.ts +46 -0
  277. package/dist/features/shell/form-sections.js +114 -0
  278. package/dist/features/shipments/components/AdminShipmentEditorView.js +87 -64
  279. package/dist/features/shipments/schemas/validation.d.ts +2 -2
  280. package/dist/features/shipments/schemas/validation.js +44 -13
  281. package/dist/features/store-extensions/schemas/custom-role-form.js +6 -2
  282. package/dist/features/store-extensions/schemas/listing-template-form.d.ts +7 -7
  283. package/dist/features/store-extensions/schemas/payout-method-form.js +14 -0
  284. package/dist/features/stores/actions/store-query-actions.js +3 -2
  285. package/dist/features/stores/api/[storeSlug]/auctions/route.js +3 -1
  286. package/dist/features/stores/api/[storeSlug]/products/route.js +3 -1
  287. package/dist/features/support/repository/support.repository.d.ts +21 -0
  288. package/dist/features/support/repository/support.repository.js +63 -0
  289. package/dist/features/support/schemas/firestore.d.ts +27 -2
  290. package/dist/features/support/schemas/firestore.js +2 -0
  291. package/dist/features/support/schemas/ticket-create-form.js +7 -0
  292. package/dist/features/tester/schemas/checklist-item-form.d.ts +43 -0
  293. package/dist/features/tester/schemas/checklist-item-form.js +109 -0
  294. package/dist/features/tester/seed-data/blog-tester-seed-data.js +2 -2
  295. package/dist/features/tester/seed-data/categories-tester-seed-data.js +2 -2
  296. package/dist/features/tester/seed-data/events-tester-seed-data.js +5 -5
  297. package/dist/features/tester/seed-data/orders-tester-seed-data.js +2 -2
  298. package/dist/features/tester/seed-data/products-tester-seed-data.js +48 -49
  299. package/dist/features/tester/seed-data/stores-tester-seed-data.js +3 -3
  300. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +275 -29
  301. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +48 -12
  302. package/dist/http/api-handler.js +2 -1
  303. package/dist/index.d.ts +24 -103
  304. package/dist/index.js +33 -141
  305. package/dist/jobs.d.ts +1 -1
  306. package/dist/jobs.js +1 -1
  307. package/dist/monitoring/browser.d.ts +0 -2
  308. package/dist/monitoring/browser.js +12 -1
  309. package/dist/monitoring/index.d.ts +0 -2
  310. package/dist/monitoring/index.js +0 -1
  311. package/dist/next/api/routeHandler.js +6 -3
  312. package/dist/next/index.d.ts +1 -2
  313. package/dist/next/index.js +0 -1
  314. package/dist/next/middleware/index.d.ts +0 -2
  315. package/dist/next/middleware/index.js +0 -1
  316. package/dist/next/routing/route-map.d.ts +8 -7
  317. package/dist/next/routing/route-map.js +10 -3
  318. package/dist/providers/db-firebase/admin.js +15 -1
  319. package/dist/providers/db-firebase/sieve.d.ts +22 -0
  320. package/dist/react/hooks/useListingTypeFlags.d.ts +1 -1
  321. package/dist/react/hooks/useListingTypeFlags.js +1 -1
  322. package/dist/react/hooks/usePendingFilters.js +5 -3
  323. package/dist/react/hooks/usePendingTable.js +15 -3
  324. package/dist/repositories/index.d.ts +0 -1
  325. package/dist/repositories/index.js +0 -1
  326. package/dist/schemas/registry.d.ts +197 -232
  327. package/dist/schemas/registry.js +5 -6
  328. package/dist/schemas/webhooks/razorpay.d.ts +50 -50
  329. package/dist/security/authorization.d.ts +9 -0
  330. package/dist/security/authorization.js +16 -2
  331. package/dist/security/browser.d.ts +1 -3
  332. package/dist/security/browser.js +5 -2
  333. package/dist/security/index.d.ts +1 -3
  334. package/dist/security/index.js +19 -2
  335. package/dist/security/pii-encrypt.js +16 -0
  336. package/dist/security/pii-schemas.d.ts +0 -14
  337. package/dist/security/pii-schemas.js +7 -15
  338. package/dist/seed/_helpers/category-forest.js +2 -2
  339. package/dist/seed/_helpers/media.d.ts +19 -0
  340. package/dist/seed/_helpers/media.js +75 -0
  341. package/dist/seed/blog-posts-seed-data.js +17 -17
  342. package/dist/seed/carousel-slides-seed-data.js +7 -7
  343. package/dist/seed/cart-seed-data.js +13 -13
  344. package/dist/seed/categories-seed-data.js +10 -10
  345. package/dist/seed/events-seed-data.js +24 -24
  346. package/dist/seed/factories/product.factory.js +4 -4
  347. package/dist/seed/factories/store.factory.js +3 -3
  348. package/dist/seed/factories/user.factory.js +2 -2
  349. package/dist/seed/grouped-listings-seed-data.js +11 -11
  350. package/dist/seed/homepage-sections-seed-data.js +2 -2
  351. package/dist/seed/index.d.ts +0 -1
  352. package/dist/seed/index.js +0 -1
  353. package/dist/seed/manifest.d.ts +1 -1
  354. package/dist/seed/manifest.js +0 -5
  355. package/dist/seed/notifications-seed-data.js +20 -1
  356. package/dist/seed/orders-seed-data.js +2 -2
  357. package/dist/seed/products-art-seed-data.js +16 -16
  358. package/dist/seed/products-auctions-seed-data.js +34 -34
  359. package/dist/seed/products-classifieds-seed-data.js +35 -37
  360. package/dist/seed/products-digital-codes-seed-data.js +20 -20
  361. package/dist/seed/products-live-items-seed-data.js +11 -11
  362. package/dist/seed/products-preorders-seed-data.js +13 -13
  363. package/dist/seed/products-prize-draws-seed-data.js +43 -43
  364. package/dist/seed/products-standard-seed-data.js +54 -54
  365. package/dist/seed/products-stickers-seed-data.js +15 -15
  366. package/dist/seed/reviews-seed-data.js +4 -4
  367. package/dist/seed/scammers-seed-data.js +3 -3
  368. package/dist/seed/site-settings-seed-data.js +11 -24
  369. package/dist/seed/store-extensions-seed-data.js +10 -10
  370. package/dist/seed/stores-seed-data.js +11 -11
  371. package/dist/seed/support-tickets-seed-data.d.ts +14 -0
  372. package/dist/seed/support-tickets-seed-data.js +20 -1
  373. package/dist/seed/users-seed-data.js +20 -20
  374. package/dist/server-entry.d.ts +0 -1
  375. package/dist/server-entry.js +0 -1
  376. package/dist/server.d.ts +9 -6
  377. package/dist/server.js +7 -13
  378. package/dist/styles.css +248 -68
  379. package/dist/tailwind-utilities.css +1 -1
  380. package/dist/tokens/themes/default-dark.js +2 -2
  381. package/dist/tokens/themes/default-light.js +2 -2
  382. package/dist/tokens/tokens.css +24 -4
  383. package/dist/ui/components/ActionRow.d.ts +50 -0
  384. package/dist/ui/components/ActionRow.js +53 -0
  385. package/dist/ui/components/ActionRow.style.css +145 -0
  386. package/dist/ui/components/Drawer.d.ts +10 -0
  387. package/dist/ui/components/Drawer.js +2 -1
  388. package/dist/ui/components/FilterDrawer.js +4 -1
  389. package/dist/ui/components/FilterDrawer.style.css +6 -12
  390. package/dist/ui/components/FormActionBar.js +14 -1
  391. package/dist/ui/components/FormActionBar.style.css +12 -11
  392. package/dist/ui/components/ListingLayout.js +8 -1
  393. package/dist/ui/components/ListingLayout.style.css +6 -13
  394. package/dist/ui/components/Modal.d.ts +15 -1
  395. package/dist/ui/components/Modal.js +17 -3
  396. package/dist/ui/components/QuickCreateModal.js +2 -2
  397. package/dist/ui/components/QuickCreateModal.style.css +78 -84
  398. package/dist/ui/components/RecordDetailModal.js +2 -2
  399. package/dist/ui/components/SideDrawer.d.ts +8 -0
  400. package/dist/ui/components/SideDrawer.js +2 -1
  401. package/dist/ui/components/SideDrawer.style.css +6 -3
  402. package/dist/ui/components/SideModal.d.ts +11 -1
  403. package/dist/ui/components/SideModal.js +3 -2
  404. package/dist/ui/components/SideModal.style.css +14 -0
  405. package/dist/ui/components/Typography.style.css +33 -24
  406. package/dist/ui/components/index.style.css +1 -0
  407. package/dist/ui/forms/FormShell.style.css +260 -311
  408. package/dist/ui/index.d.ts +2 -0
  409. package/dist/ui/index.js +1 -0
  410. package/dist/utils/index.d.ts +0 -1
  411. package/dist/utils/index.js +0 -1
  412. package/dist/validation/index.d.ts +1 -1
  413. package/dist/validation/index.js +1 -1
  414. package/dist/validation/schemas.d.ts +0 -19
  415. package/dist/validation/schemas.js +8 -19
  416. package/package.json +1 -1
  417. package/scripts/seed-cli.mjs +3 -6
@@ -153,50 +153,6 @@ export const notificationQueryHelpers = {
153
153
  ],
154
154
  byType: (type) => ["type", "==", type],
155
155
  };
156
- export const CHAT_ROOM_COLLECTION = "chatRooms";
157
- export const CHAT_ROOM_INDEXED_FIELDS = [
158
- "buyerId",
159
- "ownerId",
160
- "orderId",
161
- "participantIds",
162
- "adminDeleted",
163
- "updatedAt",
164
- ];
165
- export const CHAT_ROOM_FIELDS = {
166
- ID: "id",
167
- BUYER_ID: "buyerId",
168
- OWNER_ID: "ownerId",
169
- ORDER_ID: "orderId",
170
- PRODUCT_ID: "productId",
171
- PRODUCT_TITLE: "productTitle",
172
- BUYER_NAME: "buyerName",
173
- OWNER_NAME: "ownerName",
174
- LAST_MESSAGE: "lastMessage",
175
- LAST_MESSAGE_AT: "lastMessageAt",
176
- CREATED_AT: "createdAt",
177
- UPDATED_AT: "updatedAt",
178
- DELETED_BY: "deletedBy",
179
- IS_GROUP: "isGroup",
180
- PARTICIPANT_IDS: "participantIds",
181
- ADMIN_DELETED: "adminDeleted",
182
- };
183
- export const DEFAULT_CHAT_ROOM_DATA = {
184
- buyerId: "",
185
- ownerId: "",
186
- orderId: "",
187
- buyerName: "",
188
- ownerName: "",
189
- deletedBy: [],
190
- isGroup: false,
191
- participantIds: [],
192
- adminDeleted: false,
193
- };
194
- export const chatRoomQueryHelpers = {
195
- byBuyer: (buyerId) => ["buyerId", "==", buyerId],
196
- byOwner: (ownerId) => ["ownerId", "==", ownerId],
197
- byOrder: (orderId) => ["orderId", "==", orderId],
198
- active: () => ["adminDeleted", "==", false],
199
- };
200
156
  export const DEFAULT_NOTIFICATION_CHANNELS = {
201
157
  inApp: { enabled: true, readOnly: true },
202
158
  email: { enabled: false, minPriority: "normal" },
@@ -212,6 +168,11 @@ const PRIORITY_ORDER = {
212
168
  export function meetsMinPriority(priority, minPriority = "normal") {
213
169
  return PRIORITY_ORDER[priority] >= PRIORITY_ORDER[minPriority];
214
170
  }
171
+ // `FeatureFlagKey` / `FeatureFlagMeta` / `FEATURE_FLAG_META` were deleted with
172
+ // the `featureFlags` group on 2026-08-29. They described 14 toggles of which 11
173
+ // had no reader anywhere — an admin could switch "Wishlists" or "Reviews" off
174
+ // and watch nothing happen, which is worse than the feature not being
175
+ // configurable at all.
215
176
  export const SITE_SETTINGS_COLLECTION = "siteSettings";
216
177
  export const SITE_SETTINGS_INDEXED_FIELDS = [];
217
178
  /**
@@ -235,6 +196,8 @@ export const DEFAULT_SITE_SETTINGS_DATA = {
235
196
  upiManualEnabled: true,
236
197
  codEnabled: true,
237
198
  otpCheckoutThreshold: 5000,
199
+ smsVerification: false,
200
+ adminCheckoutBypass: false,
238
201
  },
239
202
  emi: {
240
203
  enabled: false,
@@ -293,35 +256,22 @@ export const DEFAULT_SITE_SETTINGS_DATA = {
293
256
  autoExtendWindowMinutes: 5,
294
257
  settlementGracePeriodHours: 24,
295
258
  },
296
- featureFlags: {
297
- chats: true,
298
- // Real per-SMS cost via the Firebase phone-auth quota — kept off by
299
- // default even though every other flag defaults on. Admin opts in
300
- // explicitly; PATCH /api/site-settings resets all users' phoneVerified +
301
- // rate-limit state on the false->true transition (resetOtpVerification job).
302
- smsVerification: false,
303
- translations: true,
304
- wishlists: true,
305
- auctions: true,
306
- reviews: true,
307
- events: true,
308
- blog: true,
309
- coupons: true,
310
- notifications: true,
311
- sellerRegistration: true,
312
- preOrders: true,
313
- offers: true,
314
- // W1-37 2026-05-23 — Phase 2 listing types enabled by default; all per-type
315
- // surfaces (seller + admin via W1-29 + public) are now shipped.
259
+ // Every type on by default. `isListingTypeEnabled` treats a MISSING key as
260
+ // enabled, so this block is documentation of the full set rather than the
261
+ // mechanism — a type absent here still renders. `art` and `stickers` were
262
+ // missing from the old `featureFlags.listingTypes` literal for exactly that
263
+ // reason: nothing broke, so nobody noticed (Root Cause #58).
264
+ listings: {
316
265
  listingTypes: {
317
266
  standard: true,
318
267
  auction: true,
319
268
  "pre-order": true,
320
269
  "prize-draw": true,
321
- bundle: true,
322
270
  classified: true,
323
271
  "digital-code": true,
324
272
  live: true,
273
+ art: true,
274
+ stickers: true,
325
275
  },
326
276
  categoryTypes: {
327
277
  category: true,
@@ -371,89 +321,3 @@ export const DEFAULT_TRUST_BAR_ITEMS = [
371
321
  // NOTE: labelKey/descKey hold plain display text (not i18n message keys) —
372
322
  // this feature-flag list has no matching next-intl namespace, so the admin
373
323
  // UI reads these two fields directly rather than through getTranslations().
374
- export const FEATURE_FLAG_META = [
375
- {
376
- key: "chats",
377
- labelKey: "In-app chats",
378
- descKey: "Buyer/seller direct messaging.",
379
- icon: "\u{1F4AC}",
380
- category: "platform",
381
- },
382
- {
383
- key: "smsVerification",
384
- labelKey: "SMS verification",
385
- descKey: "Phone-number OTP verification during signup/checkout.",
386
- icon: "\u{1F4F1}",
387
- category: "platform",
388
- },
389
- {
390
- key: "translations",
391
- labelKey: "Translations",
392
- descKey: "Locale switcher and translated UI strings.",
393
- icon: "\u{1F310}",
394
- category: "platform",
395
- },
396
- {
397
- key: "auctions",
398
- labelKey: "Auctions",
399
- descKey: "Auction listings and bidding.",
400
- icon: "\u{1F528}",
401
- category: "platform",
402
- },
403
- {
404
- key: "reviews",
405
- labelKey: "Reviews",
406
- descKey: "Product and store reviews.",
407
- icon: "⭐",
408
- category: "platform",
409
- },
410
- {
411
- key: "notifications",
412
- labelKey: "Notifications",
413
- descKey: "In-app notification bell and inbox.",
414
- icon: "\u{1F514}",
415
- category: "platform",
416
- },
417
- {
418
- key: "sellerRegistration",
419
- labelKey: "Seller registration",
420
- descKey: "\"Become a seller\" signup flow.",
421
- icon: "\u{1F3EA}",
422
- category: "platform",
423
- },
424
- {
425
- key: "preOrders",
426
- labelKey: "Pre-orders",
427
- descKey: "Pre-order listings and deposit checkout.",
428
- icon: "\u{1F4E6}",
429
- category: "platform",
430
- },
431
- {
432
- key: "wishlists",
433
- labelKey: "Wishlists",
434
- descKey: "Save-for-later wishlist feature.",
435
- icon: "❤️",
436
- category: "platform",
437
- },
438
- {
439
- key: "events",
440
- labelKey: "Events",
441
- descKey: "Sales, raffles, spin-wheel, and lottery events.",
442
- icon: "\u{1F389}",
443
- category: "platform",
444
- },
445
- {
446
- key: "blog",
447
- labelKey: "Blog",
448
- descKey: "Blog posts section.",
449
- icon: "\u{1F4DD}",
450
- category: "platform",
451
- },
452
- {
453
- key: "coupons",
454
- labelKey: "Coupons",
455
- descKey: "Coupon codes and discounts.",
456
- icon: "\u{1F3AB}",
457
- category: "platform",
458
- },
459
- ];
@@ -53,9 +53,16 @@ export const navItemFormSchema = z.object({
53
53
  section: "basics", sectionLabel: "Nav item", sectionRequired: true,
54
54
  quick: true, order: 1, row: "pair",
55
55
  }),
56
- href: annotate(hrefSchema, { section: "basics", quick: true, order: 2, row: "pair" }),
56
+ href: annotate(hrefSchema, {
57
+ section: "basics", quick: true, order: 2, row: "pair",
58
+ label: "URL / href",
59
+ // On the schema rather than the control, so every surface that renders this
60
+ // field gets it — the editor used to carry it as a local `helperText`.
61
+ help: "Use relative paths (e.g. /products) or full URLs.",
62
+ }),
57
63
  icon: annotate(z.string().max(60).optional(), {
58
- section: "basics", order: 3, row: "pair",
64
+ section: "basics", order: 3, row: "pair", kind: "select",
65
+ label: "Icon (optional)",
59
66
  }),
60
67
  order: annotate(z.coerce.number().int("Order must be a whole number.").min(0, "Order cannot be negative.").optional(), { section: "placement", sectionLabel: "Placement", order: 1, row: "pair" }),
61
68
  parentId: annotate(z.string().max(80).optional(), {
@@ -5,11 +5,7 @@
5
5
  */
6
6
  export * from "./actions";
7
7
  export { notificationRepository } from "./repository/notification.repository";
8
- export { chatRepository } from "./repository/chat.repository";
9
8
  export { contactSubmissionsRepository } from "../../core/contact-submissions.repository";
10
- export type { ContactSubmissionDocument, ContactSubmissionCreateInput } from "../../core/contact-submissions.repository";
11
- export { newsletterRepository } from "../../core/newsletter.repository";
12
- export type { ChatRoomDocument, ChatRoomCreateInput, } from "./repository/chat.repository";
13
9
  export { siteSettingsRepository } from "./repository/site-settings.repository";
14
10
  export { GET as adminProductsGET } from "./api/products/route";
15
11
  export { GET as adminCouponsGET } from "./api/coupons/route";
@@ -5,9 +5,7 @@
5
5
  */
6
6
  export * from "./actions";
7
7
  export { notificationRepository } from "./repository/notification.repository";
8
- export { chatRepository } from "./repository/chat.repository";
9
8
  export { contactSubmissionsRepository } from "../../core/contact-submissions.repository";
10
- export { newsletterRepository } from "../../core/newsletter.repository";
11
9
  export { siteSettingsRepository } from "./repository/site-settings.repository";
12
10
  export { GET as adminProductsGET } from "./api/products/route";
13
11
  export { GET as adminCouponsGET } from "./api/coupons/route";
@@ -27,13 +27,6 @@ export interface AdminListParams {
27
27
  sort?: string;
28
28
  filters?: string;
29
29
  }
30
- export interface AdminListResponse<T> {
31
- items: T[];
32
- total: number;
33
- page: number;
34
- perPage: number;
35
- totalPages: number;
36
- }
37
30
  export interface AnalyticsMonthEntry {
38
31
  month: string;
39
32
  orders: number;
@@ -28,5 +28,19 @@ export declare class PageViewsRepository extends BaseRepository<PageViewDocument
28
28
  /** All day-buckets in [startDate, endDate] (inclusive, YYYY-MM-DD), optionally
29
29
  * scoped to one entityType. Used by the admin page-views report tab. */
30
30
  listInRange(startDate: string, endDate: string, entityType?: PageViewEntityType): Promise<PageViewDocument[]>;
31
+ /**
32
+ * Day-buckets older than `days`, as refs for `batchDelete`.
33
+ *
34
+ * 🛑 This collection had NO prune and NO rollup until 2026-08-31. It writes
35
+ * one document per entity per day, forever, and 27 scheduled functions
36
+ * existed without one of them touching it — so its growth was bounded only by
37
+ * how many distinct pages the catalogue had times how long the site had been
38
+ * up. See `pageViewPrune`.
39
+ *
40
+ * Returns refs rather than documents, matching `getOldReadRefs` on
41
+ * notifications: a prune needs the id, and hydrating the body of every doc it
42
+ * is about to delete is read budget spent on nothing (Rule #6).
43
+ */
44
+ getOlderThanRefs(days: number): Promise<FirebaseFirestore.DocumentReference[]>;
31
45
  }
32
46
  export declare const pageViewsRepository: PageViewsRepository;
@@ -39,5 +39,29 @@ export class PageViewsRepository extends BaseRepository {
39
39
  const snap = await query.get();
40
40
  return snap.docs.map((d) => this.mapDoc(d));
41
41
  }
42
+ /**
43
+ * Day-buckets older than `days`, as refs for `batchDelete`.
44
+ *
45
+ * 🛑 This collection had NO prune and NO rollup until 2026-08-31. It writes
46
+ * one document per entity per day, forever, and 27 scheduled functions
47
+ * existed without one of them touching it — so its growth was bounded only by
48
+ * how many distinct pages the catalogue had times how long the site had been
49
+ * up. See `pageViewPrune`.
50
+ *
51
+ * Returns refs rather than documents, matching `getOldReadRefs` on
52
+ * notifications: a prune needs the id, and hydrating the body of every doc it
53
+ * is about to delete is read budget spent on nothing (Rule #6).
54
+ */
55
+ async getOlderThanRefs(days) {
56
+ const cutoff = new Date();
57
+ cutoff.setUTCDate(cutoff.getUTCDate() - days);
58
+ const cutoffKey = cutoff.toISOString().slice(0, 10);
59
+ // `<` and not `<=`: the cutoff day itself is still inside the window.
60
+ const snap = await this.getCollection()
61
+ .where(PAGE_VIEW_FIELDS.DATE, "<", cutoffKey)
62
+ .select()
63
+ .get();
64
+ return snap.docs.map((d) => d.ref);
65
+ }
42
66
  }
43
67
  export const pageViewsRepository = new PageViewsRepository();
@@ -1,2 +1 @@
1
1
  export * from "./profile-actions";
2
- export * from "./realtime-token-actions";
@@ -1,2 +1 @@
1
1
  export * from "./profile-actions";
2
- export * from "./realtime-token-actions";
@@ -5,21 +5,11 @@
5
5
  * Called by letitrip thin wrapper which handles auth + rate limiting.
6
6
  */
7
7
  import { getAdminAuth } from "../../../providers/db-firebase/index";
8
- import { chatRepository } from "../../admin/repository/chat.repository";
9
8
  import { conversationsRepository } from "../../messages/repository/conversations.repository";
10
9
  import { storeRepository } from "../../stores/repository/store.repository";
11
10
  import { serverLogger } from "../../../monitoring/index";
12
11
  import { normalizeError } from "../../../errors/normalize";
13
12
  export async function issueRealtimeToken(userId, userRole) {
14
- let chatIds = {};
15
- try {
16
- const userChatIds = await chatRepository.getChatIdsForUser(userId);
17
- chatIds = Object.fromEntries(userChatIds.map((id) => [id, true]));
18
- }
19
- catch (err) {
20
- void normalizeError(err);
21
- serverLogger.warn("Could not resolve chatIds for realtime token", { userId, err });
22
- }
23
13
  const conversationIds = {};
24
14
  try {
25
15
  const buyerConvs = await conversationsRepository.listByBuyer(userId);
@@ -38,12 +28,11 @@ export async function issueRealtimeToken(userId, userRole) {
38
28
  }
39
29
  const customToken = await getAdminAuth().createCustomToken(userId, {
40
30
  role: userRole,
41
- chatIds,
42
31
  conversationIds,
43
32
  });
44
33
  serverLogger.info("issueRealtimeToken: token issued", {
45
34
  userId,
46
- chatCount: Object.keys(chatIds).length,
35
+ conversationCount: Object.keys(conversationIds).length,
47
36
  });
48
37
  return { customToken, expiresAt: Date.now() + 3600000 };
49
38
  }
@@ -1,11 +1,9 @@
1
1
  import { getTokenTimeRemaining, isTokenExpired } from "./token-helpers";
2
- const ROLE_HIERARCHY = {
3
- user: 0,
4
- seller: 1,
5
- employee: 2,
6
- moderator: 2,
7
- admin: 3,
8
- };
2
+ // Was a SECOND, disagreeing copy of the hierarchy (employee and moderator both
3
+ // ranked 2, where the canonical one puts moderator above employee), so
4
+ // `hasRole` gave a different answer depending on which module you imported.
5
+ // Deleted 2026-08-29 in favour of the one in security/authorization.
6
+ import { ROLE_HIERARCHY } from "../../security/authorization";
9
7
  export function hasRole(userRole, requiredRole) {
10
8
  return ROLE_HIERARCHY[userRole] >= ROLE_HIERARCHY[requiredRole];
11
9
  }
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useMemo } from "react";
4
+ import { isAccountDisabled } from "../role-predicates";
4
5
  import { Button, Div, Heading, Row, Text } from "../../../ui";
5
6
  export function RoleGate({ children, user, allowedRoles, fallback = null, }) {
6
7
  if (!user?.role) {
@@ -31,7 +32,7 @@ export function ProtectedRoute({ children, user, loading = false, requireAuth =
31
32
  }
32
33
  if (user) {
33
34
  // Check account status
34
- if (requireActiveAccount && user.disabled) {
35
+ if (requireActiveAccount && isAccountDisabled(user)) {
35
36
  return { isAuthorized: false, redirectPath: unauthorizedPath };
36
37
  }
37
38
  // Check email verification
@@ -2,7 +2,6 @@ import React from "react";
2
2
  export interface LoginFormValues {
3
3
  email: string;
4
4
  password: string;
5
- rememberMe?: boolean;
6
5
  }
7
6
  export interface LoginFormProps {
8
7
  onSubmit: (values: LoginFormValues) => Promise<void>;
@@ -17,7 +16,6 @@ export interface LoginFormProps {
17
16
  emailPlaceholder?: string;
18
17
  passwordLabel?: string;
19
18
  passwordPlaceholder?: string;
20
- rememberMe?: string;
21
19
  forgotPasswordLabel?: string;
22
20
  submitLabel?: string;
23
21
  submittingLabel?: string;
@@ -5,7 +5,6 @@ import { useState } from "react";
5
5
  import { Alert, Button, Div, Heading, Row, SiteMark, Stack, Text, useToast } from "../../../ui";
6
6
  import { Form } from "../../../ui/components/Form";
7
7
  import { FieldInput } from "../../../ui/forms/FieldInput";
8
- import { FieldCheckbox } from "../../../ui/forms/FieldCheckbox";
9
8
  import { applyZodIssues } from "../../../ui/forms/apply-zod-issues";
10
9
  import { loginSchema } from "../schemas";
11
10
  import { SocialAuthButtons } from "./SocialAuthButtons";
@@ -15,9 +14,8 @@ export function LoginForm({ onSubmit, onGoogleLogin, isLoading = false, error, l
15
14
  const [values, setValues] = useState({
16
15
  email: "",
17
16
  password: "",
18
- rememberMe: false,
19
17
  });
20
- return (_jsx(Row, { className: `min-h-[60vh] ${className}`, align: "center", justify: "center", padding: "x-md", children: _jsxs(Stack, { className: "max-w-md w-full", gap: "lg", children: [_jsxs(Div, { className: "text-center", children: [_jsx(Row, { justify: "center", className: "mb-3", children: _jsx(SiteMark, { size: "lg" }) }), _jsx(Heading, { level: 1, className: "font-extrabold", size: "3xl", children: labels.title ?? "Sign In" }), (labels.subtitle || renderCreateAccountLink) && (_jsxs(Text, { className: "mt-2", color: "muted", size: "sm", children: [labels.subtitle ?? "Or", " ", renderCreateAccountLink?.()] }))] }), error && (_jsx(Alert, { variant: "error", compact: true, children: error })), _jsx(Form, { schema: loginSchema, noValidate: true, onSubmit: (e) => e.preventDefault(), spacing: "md", children: ({ setFieldError, clearErrors }) => (_jsxs(_Fragment, { children: [_jsx(FormErrorSummary, {}), _jsx(FieldInput, { name: "email", label: labels.emailLabel ?? "Email address", type: "email", autoComplete: "username", required: true, placeholder: labels.emailPlaceholder ?? "you@example.com", value: values.email, onChange: (v) => setValues({ ...values, email: v }) }), _jsx(FieldInput, { name: "password", label: labels.passwordLabel ?? "Password", type: "password", autoComplete: "current-password", required: true, placeholder: labels.passwordPlaceholder ?? "••••••••", value: values.password, onChange: (v) => setValues({ ...values, password: v }) }), _jsxs(Row, { justify: "between", children: [_jsx(FieldCheckbox, { name: "rememberMe", label: labels.rememberMe ?? "Remember me", checked: values.rememberMe ?? false, onChange: (c) => setValues({ ...values, rememberMe: c }) }), renderForgotPasswordLink?.()] }), _jsx(Button, { type: "submit", isLoading: isLoading, disabled: isLoading, className: "w-full", onClick: async () => {
18
+ return (_jsx(Row, { className: `min-h-[60vh] ${className}`, align: "center", justify: "center", padding: "x-md", children: _jsxs(Stack, { className: "max-w-md w-full", gap: "lg", children: [_jsxs(Div, { className: "text-center", children: [_jsx(Row, { justify: "center", className: "mb-3", children: _jsx(SiteMark, { size: "lg" }) }), _jsx(Heading, { level: 1, className: "font-extrabold", size: "3xl", children: labels.title ?? "Sign In" }), (labels.subtitle || renderCreateAccountLink) && (_jsxs(Text, { className: "mt-2", color: "muted", size: "sm", children: [labels.subtitle ?? "Or", " ", renderCreateAccountLink?.()] }))] }), error && (_jsx(Alert, { variant: "error", compact: true, children: error })), _jsx(Form, { schema: loginSchema, noValidate: true, onSubmit: (e) => e.preventDefault(), spacing: "md", children: ({ setFieldError, clearErrors }) => (_jsxs(_Fragment, { children: [_jsx(FormErrorSummary, {}), _jsx(FieldInput, { name: "email", label: labels.emailLabel ?? "Email address", type: "email", autoComplete: "username", required: true, placeholder: labels.emailPlaceholder ?? "you@example.com", value: values.email, onChange: (v) => setValues({ ...values, email: v }) }), _jsx(FieldInput, { name: "password", label: labels.passwordLabel ?? "Password", type: "password", autoComplete: "current-password", required: true, placeholder: labels.passwordPlaceholder ?? "••••••••", value: values.password, onChange: (v) => setValues({ ...values, password: v }) }), _jsx(Row, { justify: "end", children: renderForgotPasswordLink?.() }), _jsx(Button, { type: "submit", isLoading: isLoading, disabled: isLoading, className: "w-full", onClick: async () => {
21
19
  clearErrors();
22
20
  const parsed = loginSchema.safeParse(values);
23
21
  if (!parsed.success)
@@ -1,15 +1,16 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { normalizeError } from "../../../errors/normalize";
4
- import { useState } from "react";
4
+ import React, { useState } from "react";
5
5
  import { z } from "zod";
6
- import { Alert, Button, Div, Heading, Row, SiteMark, Stack, Text, useToast } from "../../../ui";
7
- import { Form } from "../../../ui/components/Form";
6
+ import { Alert, Div, Heading, Row, SiteMark, Stack, Text } from "../../../ui";
8
7
  import { FieldInput } from "../../../ui/forms/FieldInput";
9
8
  import { FieldCheckbox } from "../../../ui/forms/FieldCheckbox";
10
9
  import { applyZodIssues } from "../../../ui/forms/apply-zod-issues";
10
+ import { FormShellContext, useFormShellState } from "../../../ui/forms/FormShell";
11
11
  import { registerSchema, registerPasswordSchema } from "../schemas";
12
12
  import { FormErrorSummary } from "../../../ui/forms/FormErrorSummary";
13
+ import { SectionForm, useSectionFormNav } from "../../shell/SectionForm";
13
14
  const registerClientSchema = registerSchema.extend({
14
15
  displayName: z.string().min(1, "Enter your name"),
15
16
  confirmPassword: registerPasswordSchema,
@@ -20,8 +21,35 @@ const registerClientSchema = registerSchema.extend({
20
21
  message: "Passwords do not match",
21
22
  path: ["confirmPassword"],
22
23
  });
24
+ /*
25
+ * Hand-authored rather than derived from the schema, which is the exception
26
+ * here and not the rule.
27
+ *
28
+ * Two reasons the generator is the wrong tool for this one form. `labels` is a
29
+ * PUBLIC prop of a published component — every string below is consumer
30
+ * overridable, and moving them into schema annotations would silently drop that
31
+ * override for anyone outside this repo. And `renderPasswordStrength` /
32
+ * `renderTermsLink` are POSITIONAL slots: a meter that must sit under the
33
+ * password box, a terms line that must sit under the checkbox. The generator
34
+ * places fields, not arbitrary nodes between them.
35
+ *
36
+ * One section, `required: true` — so it renders open, without a collapse
37
+ * control, i.e. exactly the flat list it has always been. A five-field signup
38
+ * form has nothing to group; what it gains here is the error→section
39
+ * attribution that makes `<FormErrorSummary>` able to jump to a field.
40
+ */
41
+ function buildSections(labels, renderPasswordStrength, renderTermsLink) {
42
+ return [
43
+ {
44
+ id: "account",
45
+ label: labels.title ?? "Create Account",
46
+ required: true,
47
+ fields: ["displayName", "email", "password", "confirmPassword", "acceptTerms"],
48
+ render: ({ values, onChange }) => (_jsxs(_Fragment, { children: [_jsx(FieldInput, { name: "displayName", label: labels.displayNameLabel ?? "Full name", type: "text", autoComplete: "name", required: true, placeholder: labels.displayNamePlaceholder ?? "Your name", value: values.displayName, onChange: (v) => onChange({ displayName: v }) }), _jsx(FieldInput, { name: "email", label: labels.emailLabel ?? "Email address", type: "email", autoComplete: "username", required: true, placeholder: labels.emailPlaceholder ?? "you@example.com", value: values.email, onChange: (v) => onChange({ email: v }) }), _jsxs(Div, { children: [_jsx(FieldInput, { name: "password", label: labels.passwordLabel ?? "Password", type: "password", autoComplete: "new-password", required: true, placeholder: labels.passwordPlaceholder ?? "••••••••", value: values.password, onChange: (v) => onChange({ password: v }) }), renderPasswordStrength?.(values.password)] }), _jsx(FieldInput, { name: "confirmPassword", label: labels.confirmPasswordLabel ?? "Confirm password", type: "password", autoComplete: "new-password", required: true, placeholder: labels.confirmPasswordPlaceholder ?? "••••••••", value: values.confirmPassword, onChange: (v) => onChange({ confirmPassword: v }) }), _jsx(FieldCheckbox, { name: "acceptTerms", label: `${labels.acceptTermsLabel ?? "I accept the terms"}`, checked: values.acceptTerms, onChange: (c) => onChange({ acceptTerms: c }) }), renderTermsLink && (_jsx(Text, { size: "xs", variant: "secondary", children: renderTermsLink() }))] })),
49
+ },
50
+ ];
51
+ }
23
52
  export function RegisterForm({ onSubmit, isLoading = false, error, success, labels = {}, renderSocialButtons, renderLoginLink, renderTermsLink, renderPasswordStrength, className = "", }) {
24
- const { showToast } = useToast();
25
53
  const [values, setValues] = useState({
26
54
  email: "",
27
55
  password: "",
@@ -29,19 +57,34 @@ export function RegisterForm({ onSubmit, isLoading = false, error, success, labe
29
57
  displayName: "",
30
58
  acceptTerms: false,
31
59
  });
32
- return (_jsx(Row, { className: `min-h-[60vh] ${className}`, align: "center", justify: "center", padding: "x-md", children: _jsxs(Stack, { className: "max-w-md w-full", gap: "lg", children: [_jsxs(Div, { className: "text-center", children: [_jsx(Row, { justify: "center", className: "mb-3", children: _jsx(SiteMark, { size: "lg" }) }), _jsx(Heading, { level: 1, className: "font-extrabold", size: "3xl", children: labels.title ?? "Create Account" }), (labels.subtitle || renderLoginLink) && (_jsxs(Text, { className: "mt-2 text-[var(--appkit-color-text-muted)]", size: "sm", children: [labels.subtitle ?? "Already have an account?", " ", renderLoginLink?.()] }))] }), success && (_jsx(Alert, { variant: "success", compact: true, children: success })), error && (_jsx(Alert, { variant: "error", compact: true, children: error })), _jsx(Form, { schema: registerClientSchema, noValidate: true, onSubmit: (e) => e.preventDefault(), spacing: "md", children: ({ setFieldError, clearErrors }) => (_jsxs(_Fragment, { children: [_jsx(FormErrorSummary, {}), _jsx(FieldInput, { name: "displayName", label: labels.displayNameLabel ?? "Full name", type: "text", autoComplete: "name", required: true, placeholder: labels.displayNamePlaceholder ?? "Your name", value: values.displayName, onChange: (v) => setValues({ ...values, displayName: v }) }), _jsx(FieldInput, { name: "email", label: labels.emailLabel ?? "Email address", type: "email", autoComplete: "username", required: true, placeholder: labels.emailPlaceholder ?? "you@example.com", value: values.email, onChange: (v) => setValues({ ...values, email: v }) }), _jsxs(Div, { children: [_jsx(FieldInput, { name: "password", label: labels.passwordLabel ?? "Password", type: "password", autoComplete: "new-password", required: true, placeholder: labels.passwordPlaceholder ?? "••••••••", value: values.password, onChange: (v) => setValues({ ...values, password: v }) }), renderPasswordStrength?.(values.password)] }), _jsx(FieldInput, { name: "confirmPassword", label: labels.confirmPasswordLabel ?? "Confirm password", type: "password", autoComplete: "new-password", required: true, placeholder: labels.confirmPasswordPlaceholder ?? "••••••••", value: values.confirmPassword, onChange: (v) => setValues({ ...values, confirmPassword: v }) }), _jsx(FieldCheckbox, { name: "acceptTerms", label: `${labels.acceptTermsLabel ?? "I accept the terms"}`, checked: values.acceptTerms, onChange: (c) => setValues({ ...values, acceptTerms: c }) }), renderTermsLink && (_jsx(Text, { size: "xs", variant: "secondary", children: renderTermsLink() })), _jsx(Button, { type: "submit", isLoading: isLoading, disabled: isLoading, className: "w-full", onClick: async () => {
33
- clearErrors();
34
- const parsed = registerClientSchema.safeParse(values);
35
- if (!parsed.success)
36
- return applyZodIssues(parsed.error.issues, setFieldError);
37
- try {
38
- await onSubmit(values);
39
- }
40
- catch (err) {
41
- void normalizeError(err);
42
- showToast("Registration failed", "error");
43
- }
44
- }, children: isLoading
45
- ? (labels.submittingLabel ?? "Creating account…")
46
- : (labels.submitLabel ?? "Create account") })] })) }), renderSocialButtons?.()] }) }));
60
+ const sections = React.useMemo(() => buildSections(labels, renderPasswordStrength, renderTermsLink), [labels, renderPasswordStrength, renderTermsLink]);
61
+ const nav = useSectionFormNav(sections, values, { scope: "auth:register" });
62
+ const { shellCtx, setFieldError, clearErrors } = useFormShellState(registerClientSchema, {
63
+ sections: nav.sectionMeta,
64
+ onGoToSection: nav.goToSection,
65
+ fieldToSectionIndex: nav.fieldToSectionIndex,
66
+ });
67
+ const handleSubmit = async () => {
68
+ clearErrors();
69
+ const parsed = registerClientSchema.safeParse(values);
70
+ if (!parsed.success) {
71
+ applyZodIssues(parsed.error.issues, setFieldError);
72
+ return;
73
+ }
74
+ try {
75
+ await onSubmit(values);
76
+ }
77
+ catch (err) {
78
+ /*
79
+ * On a field, not a toast. "Registration failed" told the user nothing
80
+ * and discarded whatever the caller actually objected to — a taken
81
+ * email, a rejected password — which is the one thing they can act on.
82
+ */
83
+ const normalized = normalizeError(err);
84
+ setFieldError("email", normalized.message || "Registration failed");
85
+ }
86
+ };
87
+ return (_jsx(Row, { className: `min-h-[60vh] ${className}`, align: "center", justify: "center", padding: "x-md", children: _jsxs(Stack, { className: "max-w-md w-full", gap: "lg", children: [_jsxs(Div, { className: "text-center", children: [_jsx(Row, { justify: "center", className: "mb-3", children: _jsx(SiteMark, { size: "lg" }) }), _jsx(Heading, { level: 1, className: "font-extrabold", size: "3xl", children: labels.title ?? "Create Account" }), (labels.subtitle || renderLoginLink) && (_jsxs(Text, { className: "mt-2 text-[var(--appkit-color-text-muted)]", size: "sm", children: [labels.subtitle ?? "Already have an account?", " ", renderLoginLink?.()] }))] }), success && (_jsx(Alert, { variant: "success", compact: true, children: success })), error && (_jsx(Alert, { variant: "error", compact: true, children: error })), _jsxs(FormShellContext.Provider, { value: shellCtx, children: [_jsx(FormErrorSummary, {}), _jsx(SectionForm, { sections: sections, values: values, onChange: (partial) => setValues((prev) => Object.assign({}, prev, partial)), onSubmit: handleSubmit, schema: registerClientSchema, openIds: nav.openIds, onOpenChange: nav.setOpenIds, isLoading: isLoading, submitLabel: isLoading
88
+ ? (labels.submittingLabel ?? "Creating account…")
89
+ : (labels.submitLabel ?? "Create account") })] }), renderSocialButtons?.()] }) }));
47
90
  }
@@ -11,7 +11,33 @@
11
11
  * Permission naming: admin:resource:action
12
12
  * Ban action naming: plain verb phrase — write_reviews, place_bids, etc.
13
13
  */
14
- export type Permission = "admin:dashboard:view" | "admin:users:read" | "admin:users:write" | "admin:users:delete" | "admin:user-bans:read" | "admin:user-bans:write" | "admin:products:read" | "admin:products:write" | "admin:products:delete" | "admin:orders:read" | "admin:orders:write" | "admin:returns:read" | "admin:returns:write" | "admin:stores:read" | "admin:stores:write" | "admin:store-addresses:read" | "admin:addresses:read" | "admin:addresses:write" | "admin:analytics:view" | "admin:payouts:read" | "admin:payouts:write" | "admin:audit-log:read" | "admin:categories:read" | "admin:categories:write" | "admin:categories:delete" | "admin:brands:read" | "admin:brands:write" | "admin:brands:delete" | "admin:coupons:read" | "admin:coupons:write" | "admin:coupons:delete" | "admin:deals:read" | "admin:deals:write" | "admin:featured:read" | "admin:featured:write" | "admin:reviews:read" | "admin:reviews:write" | "admin:reviews:delete" | "admin:blog:read" | "admin:blog:write" | "admin:blog:delete" | "admin:blog:publish" | "admin:bids:read" | "admin:bids:write" | "admin:offers:read" | "admin:offers:write" | "admin:media:read" | "admin:media:write" | "admin:media:delete" | "admin:site:read" | "admin:site:write" | "admin:settings:write" | "admin:navigation:read" | "admin:navigation:write" | "admin:sections:read" | "admin:sections:write" | "admin:carousel:read" | "admin:carousel:write" | "admin:carousel:delete" | "admin:ads:read" | "admin:ads:write" | "admin:ads:delete" | "admin:faqs:read" | "admin:faqs:write" | "admin:faqs:delete" | "admin:tester-checklist:read" | "admin:tester-checklist:write" | "admin:tester-checklist:delete" | "admin:tester-feedback:read" | "admin:tester-feedback:write" | "admin:newsletter:read" | "admin:newsletter:write" | "admin:contact:read" | "admin:events:read" | "admin:events:write" | "admin:events:delete" | "admin:event-entries:read" | "admin:event-entries:write" | "admin:support-tickets:read" | "admin:support-tickets:write" | "admin:shipments:read" | "admin:shipments:write" | "admin:catalogue:read" | "admin:catalogue:write" | "admin:grouped-listings:read" | "admin:grouped-listings:write" | "admin:support-tickets:assign" | "admin:support-tickets:close" | "admin:scammers:read" | "admin:scammers:write" | "admin:scammers:verify" | "admin:scammers:delete" | "admin:sessions:read" | "admin:sessions:delete" | "admin:notifications:read" | "admin:notifications:write" | "admin:carts:read" | "admin:wishlists:read" | "admin:feature-flags:read" | "admin:feature-flags:write" | "admin:copilot:view" | "admin:team:read" | "admin:team:write" | "admin:maintenance:view-server-errors" | "admin:maintenance:view-client-errors" | "admin:maintenance:view-function-errors" | "admin:maintenance:view-cloud-logs" | "admin:maintenance:view-payment-rollbacks" | "admin:maintenance:run-analysis" | "admin:maintenance:purge-errors";
14
+ export type Permission = "admin:dashboard:view" | "admin:users:read" | "admin:users:write" | "admin:users:delete" | "admin:user-bans:read" | "admin:user-bans:write" | "admin:products:read" | "admin:products:write" | "admin:products:delete" | "admin:orders:read" | "admin:orders:write" | "admin:returns:read" | "admin:returns:write" | "admin:stores:read" | "admin:stores:write" | "admin:store-addresses:read" | "admin:addresses:read" | "admin:addresses:write" | "admin:analytics:view" | "admin:payouts:read" | "admin:payouts:write" | "admin:audit-log:read" | "admin:categories:read" | "admin:categories:write" | "admin:categories:delete" | "admin:brands:read" | "admin:brands:write" | "admin:brands:delete" | "admin:coupons:read" | "admin:coupons:write" | "admin:coupons:delete" | "admin:deals:read" | "admin:deals:write" | "admin:featured:read" | "admin:featured:write" | "admin:reviews:read" | "admin:reviews:write" | "admin:reviews:delete" | "admin:blog:read" | "admin:blog:write" | "admin:blog:delete" | "admin:blog:publish" | "admin:bids:read" | "admin:bids:write" | "admin:offers:read" | "admin:offers:write" | "admin:media:read" | "admin:media:write" | "admin:media:delete" | "admin:site:read" | "admin:site:write" | "admin:settings:write" | "admin:navigation:read" | "admin:navigation:write" | "admin:sections:read" | "admin:sections:write" | "admin:carousel:read" | "admin:carousel:write" | "admin:carousel:delete" | "admin:ads:read" | "admin:ads:write" | "admin:ads:delete" | "admin:faqs:read" | "admin:faqs:write" | "admin:faqs:delete" | "admin:tester-checklist:read" | "admin:tester-checklist:write" | "admin:tester-checklist:delete" | "admin:tester-feedback:read" | "admin:tester-feedback:write" | "admin:newsletter:read" | "admin:newsletter:write" | "admin:contact:read"
15
+ /** Destructive/mutating contact-submission actions. Added 2026-08-29 —
16
+ * `DELETE /api/admin/contact-submissions/[id]` declared `admin:contact:delete`,
17
+ * which is not a member of this union and therefore could never be granted. */
18
+ | "admin:contact:write" | "admin:moderation:read" | "admin:roles:read"
19
+ /**
20
+ * Skip OTP + payment when placing an order. Replaces
21
+ * `siteSettings.featureFlags.adminCheckoutBypass`: a capability granted to a
22
+ * person belongs in the permission system, not in a site-wide toggle that is
23
+ * either on for every admin or off for all of them.
24
+ *
25
+ * Named `admin:checkout:bypass` rather than the bare `checkout:bypass` so it
26
+ * matches the `admin:resource:action` convention every other member follows
27
+ * and is picked up by PERMISSION_DOMAINS prefix matching.
28
+ */
29
+ | "admin:checkout:bypass"
30
+ /**
31
+ * Lets a `tester` reach `/admin/**` with real read/write access.
32
+ *
33
+ * Replaces the `canTestAdmin` boolean. Not a second role: the hierarchy is
34
+ * linear, so there is no level meaning "seller-level, plus read admin" that
35
+ * would not also outrank moderator and employee. Granted through the same
36
+ * `permissions[]` array employees already use, so there is one grant
37
+ * mechanism — and revoking it is a permission change, which the admin audit
38
+ * log already records.
39
+ */
40
+ | "tester:admin-surfaces" | "admin:events:read" | "admin:events:write" | "admin:events:delete" | "admin:event-entries:read" | "admin:event-entries:write" | "admin:support-tickets:read" | "admin:support-tickets:write" | "admin:shipments:read" | "admin:shipments:write" | "admin:catalogue:read" | "admin:catalogue:write" | "admin:grouped-listings:read" | "admin:grouped-listings:write" | "admin:support-tickets:assign" | "admin:support-tickets:close" | "admin:scammers:read" | "admin:scammers:write" | "admin:scammers:verify" | "admin:scammers:delete" | "admin:sessions:read" | "admin:sessions:delete" | "admin:notifications:read" | "admin:notifications:write" | "admin:carts:read" | "admin:wishlists:read" | "admin:feature-flags:read" | "admin:feature-flags:write" | "admin:copilot:view" | "admin:team:read" | "admin:team:write" | "admin:maintenance:view-server-errors" | "admin:maintenance:view-client-errors" | "admin:maintenance:view-function-errors" | "admin:maintenance:view-cloud-logs" | "admin:maintenance:view-payment-rollbacks" | "admin:maintenance:run-analysis" | "admin:maintenance:purge-errors";
15
41
  /**
16
42
  * Granular user actions that can be soft-banned individually.
17
43
  * A user may have multiple simultaneous soft bans of different types.