@mohasinac/appkit 4.13.1 → 4.15.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 (493) hide show
  1. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +14 -5
  2. package/dist/_internal/client/features/lottery/LotteryAdminEditView.d.ts +3 -0
  3. package/dist/_internal/client/features/lottery/LotteryAdminEditView.js +6 -0
  4. package/dist/_internal/client/features/lottery/LotteryDetailView.d.ts +8 -0
  5. package/dist/_internal/client/features/lottery/LotteryDetailView.js +4 -1
  6. package/dist/_internal/client/features/lottery/LotteryListView.d.ts +7 -0
  7. package/dist/_internal/client/features/lottery/LotteryListView.js +1 -1
  8. package/dist/_internal/client/features/lottery/PrizeDrawLotteryDetailView.js +4 -1
  9. package/dist/_internal/client/features/lottery/slot-collage-items.d.ts +15 -0
  10. package/dist/_internal/client/features/lottery/slot-collage-items.js +13 -0
  11. package/dist/_internal/server/features/auctions/actions.js +8 -2
  12. package/dist/_internal/server/features/bundles/data.d.ts +16 -0
  13. package/dist/_internal/server/features/bundles/data.js +26 -0
  14. package/dist/_internal/server/features/bundles/index.d.ts +1 -1
  15. package/dist/_internal/server/features/bundles/index.js +1 -1
  16. package/dist/_internal/server/features/cart/service.d.ts +3 -3
  17. package/dist/_internal/server/features/checkout/actions.js +25 -0
  18. package/dist/_internal/server/features/checkout/locked-lines.d.ts +38 -0
  19. package/dist/_internal/server/features/checkout/locked-lines.js +171 -0
  20. package/dist/_internal/server/features/checkout/source-context.d.ts +5 -0
  21. package/dist/_internal/server/features/checkout/source-context.js +157 -0
  22. package/dist/_internal/server/features/homepage/index.d.ts +0 -1
  23. package/dist/_internal/server/features/homepage/index.js +7 -1
  24. package/dist/_internal/server/features/lottery/adapters.js +4 -0
  25. package/dist/_internal/server/features/offers/adapters.d.ts +103 -0
  26. package/dist/_internal/server/features/offers/adapters.js +88 -0
  27. package/dist/_internal/server/features/offers/index.d.ts +2 -0
  28. package/dist/_internal/server/features/offers/index.js +1 -0
  29. package/dist/_internal/server/features/orders/adapters.js +24 -0
  30. package/dist/_internal/server/features/products/data.js +15 -37
  31. package/dist/_internal/server/features/products/index.d.ts +1 -1
  32. package/dist/_internal/server/features/products/index.js +1 -1
  33. package/dist/_internal/server/features/products/list-public.d.ts +46 -20
  34. package/dist/_internal/server/features/products/list-public.js +266 -90
  35. package/dist/_internal/server/features/products/listing-tab-counts.d.ts +44 -0
  36. package/dist/_internal/server/features/products/listing-tab-counts.js +97 -0
  37. package/dist/_internal/server/features/site-settings/adapters.d.ts +51 -0
  38. package/dist/_internal/server/features/site-settings/adapters.js +75 -0
  39. package/dist/_internal/server/features/site-settings/index.d.ts +1 -0
  40. package/dist/_internal/server/features/site-settings/index.js +1 -0
  41. package/dist/_internal/server/features/stores/adapters.d.ts +56 -0
  42. package/dist/_internal/server/features/stores/adapters.js +91 -0
  43. package/dist/_internal/server/features/stores/index.d.ts +1 -0
  44. package/dist/_internal/server/features/stores/index.js +1 -0
  45. package/dist/_internal/server/jobs/core/auctionSettlement.js +56 -2
  46. package/dist/_internal/server/jobs/core/offerExpiry.js +55 -19
  47. package/dist/_internal/server/jobs/core/paymentReviewAutoApprove.d.ts +5 -0
  48. package/dist/_internal/server/jobs/core/paymentReviewAutoApprove.js +33 -1
  49. package/dist/_internal/server/jobs/handlers/messages.d.ts +7 -0
  50. package/dist/_internal/server/jobs/handlers/messages.js +10 -0
  51. package/dist/_internal/shared/actions/action-registry.js +17 -1
  52. package/dist/_internal/shared/checkout/lanes.d.ts +25 -0
  53. package/dist/_internal/shared/checkout/lanes.js +26 -0
  54. package/dist/_internal/shared/features/auctions/config.d.ts +27 -0
  55. package/dist/_internal/shared/features/auctions/config.js +27 -0
  56. package/dist/_internal/shared/features/auctions/schema.d.ts +14 -2
  57. package/dist/_internal/shared/features/auctions/schema.js +13 -1
  58. package/dist/_internal/shared/features/blog/schema.d.ts +2 -2
  59. package/dist/_internal/shared/features/cart/schema.d.ts +20 -15
  60. package/dist/_internal/shared/features/cart/schema.js +15 -0
  61. package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +32 -32
  62. package/dist/_internal/shared/features/emi/schedule.d.ts +24 -3
  63. package/dist/_internal/shared/features/emi/schedule.js +20 -5
  64. package/dist/_internal/shared/features/events/schema.d.ts +2 -2
  65. package/dist/_internal/shared/features/homepage/section-gate.d.ts +14 -0
  66. package/dist/_internal/shared/features/homepage/section-gate.js +51 -0
  67. package/dist/_internal/shared/features/offers/config.d.ts +30 -0
  68. package/dist/_internal/shared/features/offers/config.js +59 -0
  69. package/dist/_internal/shared/features/orders/schema.d.ts +8 -8
  70. package/dist/_internal/shared/features/products/schema.d.ts +30 -30
  71. package/dist/_internal/shared/features/products/to-product-item.js +6 -0
  72. package/dist/_internal/shared/features/reviews/schema.d.ts +2 -2
  73. package/dist/_internal/shared/features/site-settings/fees.d.ts +60 -0
  74. package/dist/_internal/shared/features/site-settings/fees.js +39 -0
  75. package/dist/_internal/shared/features/site-settings/types.d.ts +40 -0
  76. package/dist/_internal/shared/features/site-settings/types.js +1 -0
  77. package/dist/_internal/shared/history/history.d.ts +88 -0
  78. package/dist/_internal/shared/history/history.js +198 -0
  79. package/dist/_internal/shared/history/index.d.ts +4 -0
  80. package/dist/_internal/shared/history/index.js +2 -0
  81. package/dist/_internal/shared/history/types.d.ts +61 -0
  82. package/dist/_internal/shared/history/types.js +6 -0
  83. package/dist/_internal/shared/listing-types/_registry.d.ts +54 -1
  84. package/dist/_internal/shared/listing-types/_registry.js +67 -0
  85. package/dist/_internal/shared/listing-types/art/config.d.ts +3 -0
  86. package/dist/_internal/shared/listing-types/art/config.js +5 -0
  87. package/dist/_internal/shared/listing-types/auction/config.d.ts +13 -0
  88. package/dist/_internal/shared/listing-types/auction/config.js +21 -0
  89. package/dist/_internal/shared/listing-types/availability.d.ts +79 -0
  90. package/dist/_internal/shared/listing-types/availability.js +104 -0
  91. package/dist/_internal/shared/listing-types/capabilities.d.ts +15 -0
  92. package/dist/_internal/shared/listing-types/capabilities.js +12 -0
  93. package/dist/_internal/shared/listing-types/classified/config.d.ts +3 -0
  94. package/dist/_internal/shared/listing-types/classified/config.js +5 -0
  95. package/dist/_internal/shared/listing-types/digital-code/config.d.ts +11 -0
  96. package/dist/_internal/shared/listing-types/digital-code/config.js +22 -2
  97. package/dist/_internal/shared/listing-types/live/config.d.ts +3 -0
  98. package/dist/_internal/shared/listing-types/live/config.js +5 -0
  99. package/dist/_internal/shared/listing-types/pre-order/config.d.ts +3 -0
  100. package/dist/_internal/shared/listing-types/pre-order/config.js +19 -0
  101. package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +11 -0
  102. package/dist/_internal/shared/listing-types/prize-draw/config.js +15 -0
  103. package/dist/_internal/shared/listing-types/standard/config.d.ts +3 -0
  104. package/dist/_internal/shared/listing-types/standard/config.js +5 -0
  105. package/dist/_internal/shared/listing-types/stickers/config.d.ts +3 -0
  106. package/dist/_internal/shared/listing-types/stickers/config.js +5 -0
  107. package/dist/client.d.ts +20 -7
  108. package/dist/client.js +22 -4
  109. package/dist/constants/api-endpoints.d.ts +6 -0
  110. package/dist/constants/api-endpoints.js +2 -0
  111. package/dist/constants/field-names.d.ts +57 -8
  112. package/dist/constants/field-names.js +101 -8
  113. package/dist/constants/table-keys.d.ts +17 -0
  114. package/dist/constants/table-keys.js +17 -0
  115. package/dist/errors/error-codes.d.ts +13 -1
  116. package/dist/errors/error-codes.js +13 -1
  117. package/dist/errors/error-display-map.js +12 -3
  118. package/dist/errors/messages.d.ts +10 -2
  119. package/dist/errors/messages.js +10 -2
  120. package/dist/features/about/components/AboutView.d.ts +3 -0
  121. package/dist/features/about/components/AboutView.js +3 -2
  122. package/dist/features/about/components/PolicyPageView.d.ts +2 -1
  123. package/dist/features/about/components/PolicyPageView.js +61 -23
  124. package/dist/features/about/components/PublicProfileView.js +5 -0
  125. package/dist/features/about/schemas/firestore.d.ts +3 -0
  126. package/dist/features/account/components/UserBidsView.js +12 -4
  127. package/dist/features/account/components/UserOrdersView.js +7 -0
  128. package/dist/features/account/components/UserReturnsView.d.ts +3 -0
  129. package/dist/features/account/components/UserReturnsView.js +17 -1
  130. package/dist/features/account/components/index.d.ts +0 -2
  131. package/dist/features/account/components/index.js +0 -1
  132. package/dist/features/account/schemas/index.d.ts +2 -2
  133. package/dist/features/account/types/index.d.ts +21 -2
  134. package/dist/features/addresses/schemas/index.d.ts +4 -4
  135. package/dist/features/admin/components/AdminArtView.js +8 -3
  136. package/dist/features/admin/components/AdminAuditLogView.js +1 -0
  137. package/dist/features/admin/components/AdminBidsView.js +15 -2
  138. package/dist/features/admin/components/AdminBlogEditorView.js +65 -33
  139. package/dist/features/admin/components/AdminClassifiedView.js +8 -3
  140. package/dist/features/admin/components/AdminDigitalCodesView.js +8 -3
  141. package/dist/features/admin/components/AdminFeatureEditorView.js +35 -6
  142. package/dist/features/admin/components/AdminFeatureFlagsView.js +1 -0
  143. package/dist/features/admin/components/AdminLiveView.js +8 -3
  144. package/dist/features/admin/components/AdminNavEditorView.js +15 -5
  145. package/dist/features/admin/components/AdminNewsletterView.js +18 -2
  146. package/dist/features/admin/components/AdminOffersView.d.ts +4 -0
  147. package/dist/features/admin/components/AdminOffersView.js +230 -0
  148. package/dist/features/admin/components/AdminOrdersView.js +10 -1
  149. package/dist/features/admin/components/AdminPaymentMethodsView.js +24 -4
  150. package/dist/features/admin/components/AdminPrizeDrawsView.js +5 -0
  151. package/dist/features/admin/components/AdminProductsView.js +16 -29
  152. package/dist/features/admin/components/AdminScammerEditorView.d.ts +2 -1
  153. package/dist/features/admin/components/AdminScammerEditorView.js +3 -13
  154. package/dist/features/admin/components/AdminScammersView.js +3 -8
  155. package/dist/features/admin/components/AdminSectionsView.js +32 -23
  156. package/dist/features/admin/components/AdminSessionsView.js +17 -2
  157. package/dist/features/admin/components/AdminSiteSettingsView.js +31 -13
  158. package/dist/features/admin/components/AdminSiteView.js +6 -2
  159. package/dist/features/admin/components/AdminStickersView.js +8 -3
  160. package/dist/features/admin/components/ViewAuditLogEntryModal.js +1 -0
  161. package/dist/features/admin/components/index.d.ts +2 -0
  162. package/dist/features/admin/components/index.js +1 -0
  163. package/dist/features/admin/components/sections/adminSectionsTypes.d.ts +4 -2
  164. package/dist/features/admin/components/sections/adminSectionsTypes.js +45 -27
  165. package/dist/features/admin/constants/filter-tabs.d.ts +89 -0
  166. package/dist/features/admin/constants/filter-tabs.js +56 -0
  167. package/dist/features/admin/schemas/firestore.d.ts +122 -3
  168. package/dist/features/admin/schemas/firestore.js +1 -0
  169. package/dist/features/admin/schemas/homepage-section-form.d.ts +22 -0
  170. package/dist/features/admin/schemas/homepage-section-form.js +68 -0
  171. package/dist/features/admin/schemas/nav-item-form.d.ts +74 -0
  172. package/dist/features/admin/schemas/nav-item-form.js +72 -0
  173. package/dist/features/auctions/actions/bid-actions.d.ts +20 -5
  174. package/dist/features/auctions/actions/bid-actions.js +93 -20
  175. package/dist/features/auctions/components/AuctionBidsTable.d.ts +10 -1
  176. package/dist/features/auctions/components/AuctionBidsTable.js +22 -4
  177. package/dist/features/auctions/components/AuctionDetailPageView.js +11 -6
  178. package/dist/features/auctions/components/AuctionsListView.js +5 -6
  179. package/dist/features/auctions/components/MarketplaceAuctionCard.d.ts +7 -0
  180. package/dist/features/auctions/components/MarketplaceAuctionCard.js +19 -2
  181. package/dist/features/auctions/components/PlaceBidFormClient.d.ts +1 -2
  182. package/dist/features/auctions/components/PlaceBidFormClient.js +8 -4
  183. package/dist/features/auctions/components/bid-detail-fields.d.ts +29 -0
  184. package/dist/features/auctions/components/bid-detail-fields.js +103 -0
  185. package/dist/features/auctions/repository/bid.repository.d.ts +13 -0
  186. package/dist/features/auctions/repository/bid.repository.js +23 -0
  187. package/dist/features/auctions/schemas/firestore.d.ts +17 -0
  188. package/dist/features/auctions/schemas/index.d.ts +12 -12
  189. package/dist/features/audit-log/schemas/firestore.d.ts +14 -0
  190. package/dist/features/audit-log/schemas/firestore.js +7 -0
  191. package/dist/features/auth/permissions/constants.d.ts +1 -1
  192. package/dist/features/auth/permissions/constants.js +10 -1
  193. package/dist/features/blog/actions/blog-actions.d.ts +7 -7
  194. package/dist/features/blog/schemas/blog-form.d.ts +80 -0
  195. package/dist/features/blog/schemas/blog-form.js +100 -0
  196. package/dist/features/blog/schemas/index.d.ts +6 -6
  197. package/dist/features/cart/repository/cart.repository.js +1 -0
  198. package/dist/features/cart/schemas/firestore.d.ts +15 -0
  199. package/dist/features/catalogue/schemas/validation.d.ts +4 -4
  200. package/dist/features/categories/components/BrandDetailPageView.js +23 -40
  201. package/dist/features/categories/components/BrandDetailTabs.d.ts +7 -7
  202. package/dist/features/categories/components/BrandDetailTabs.js +8 -12
  203. package/dist/features/categories/components/BundleCollage.js +1 -1
  204. package/dist/features/categories/components/CategoryDetailPageView.js +53 -57
  205. package/dist/features/categories/components/CategoryDetailTabs.d.ts +10 -8
  206. package/dist/features/categories/components/CategoryDetailTabs.js +11 -16
  207. package/dist/features/categories/components/CategoryProductsListing.js +11 -1
  208. package/dist/features/categories/components/ConcernCard.js +7 -1
  209. package/dist/features/categories/schemas/firestore.d.ts +13 -0
  210. package/dist/features/categories/schemas/index.d.ts +26 -26
  211. package/dist/features/classified/components/ClassifiedDetailPageView.d.ts +16 -1
  212. package/dist/features/classified/components/ClassifiedDetailPageView.js +23 -3
  213. package/dist/features/events/components/AdminEventEditorView.js +32 -54
  214. package/dist/features/events/components/AdminEventEntriesView.js +22 -3
  215. package/dist/features/events/components/AdminEventsView.js +15 -11
  216. package/dist/features/events/components/EventFilters.d.ts +9 -1
  217. package/dist/features/events/components/EventFilters.js +45 -21
  218. package/dist/features/events/components/EventsIndexListing.d.ts +6 -1
  219. package/dist/features/events/components/EventsIndexListing.js +2 -2
  220. package/dist/features/events/components/EventsListPageView.js +13 -4
  221. package/dist/features/events/repository/events.repository.d.ts +17 -0
  222. package/dist/features/events/repository/events.repository.js +27 -0
  223. package/dist/features/events/schemas/event-form.d.ts +113 -0
  224. package/dist/features/events/schemas/event-form.js +82 -0
  225. package/dist/features/events/schemas/firestore.d.ts +12 -0
  226. package/dist/features/events/schemas/firestore.js +12 -0
  227. package/dist/features/events/schemas/index.d.ts +50 -50
  228. package/dist/features/events/types/index.d.ts +11 -0
  229. package/dist/features/events/types/index.js +57 -1
  230. package/dist/features/faq/actions/faq-actions.d.ts +12 -12
  231. package/dist/features/faq/schemas/index.d.ts +8 -8
  232. package/dist/features/filters/FilterFacetSection.d.ts +7 -1
  233. package/dist/features/filters/FilterFacetSection.js +11 -3
  234. package/dist/features/grouped/schemas/grouped-listing-form.d.ts +101 -0
  235. package/dist/features/grouped/schemas/grouped-listing-form.js +89 -0
  236. package/dist/features/grouped/schemas/index.d.ts +4 -4
  237. package/dist/features/homepage/actions/homepage-section-actions.d.ts +11 -3
  238. package/dist/features/homepage/actions/homepage-section-actions.js +33 -1
  239. package/dist/features/homepage/components/AnnouncementBar.d.ts +7 -1
  240. package/dist/features/homepage/components/AnnouncementBar.js +3 -3
  241. package/dist/features/homepage/components/MarketplaceHomepageView.js +20 -6
  242. package/dist/features/homepage/hooks/homepage-query.d.ts +16 -0
  243. package/dist/features/homepage/hooks/homepage-query.js +45 -0
  244. package/dist/features/homepage/hooks/useFeaturedAuctions.d.ts +10 -0
  245. package/dist/features/homepage/hooks/useFeaturedAuctions.js +28 -8
  246. package/dist/features/homepage/hooks/useFeaturedPreOrders.js +17 -8
  247. package/dist/features/homepage/hooks/useFeaturedProducts.js +15 -8
  248. package/dist/features/homepage/schemas/index.d.ts +33 -2
  249. package/dist/features/homepage/schemas/index.js +24 -0
  250. package/dist/features/layout/AppLayoutShell.d.ts +11 -1
  251. package/dist/features/layout/AppLayoutShell.js +15 -14
  252. package/dist/features/layout/BackToTop.d.ts +9 -0
  253. package/dist/features/layout/BackToTop.js +10 -1
  254. package/dist/features/layout/BottomActions.js +28 -25
  255. package/dist/features/layout/BottomChrome.d.ts +34 -0
  256. package/dist/features/layout/BottomChrome.js +55 -0
  257. package/dist/features/layout/BottomNavLayout.d.ts +6 -0
  258. package/dist/features/layout/BottomNavLayout.js +7 -1
  259. package/dist/features/layout/BottomNavbar.js +15 -2
  260. package/dist/features/layout/FooterLayout.js +11 -1
  261. package/dist/features/layout/NavbarLayout.js +1 -1
  262. package/dist/features/layout/TitleBarLayout.d.ts +7 -0
  263. package/dist/features/layout/TitleBarLayout.js +28 -5
  264. package/dist/features/layout/index.d.ts +2 -0
  265. package/dist/features/layout/index.js +1 -0
  266. package/dist/features/lottery/types/index.d.ts +3 -0
  267. package/dist/features/media/MediaPickerModal.js +5 -1
  268. package/dist/features/messages/schemas/index.d.ts +2 -2
  269. package/dist/features/orders/components/OrderScopeTabs.d.ts +20 -0
  270. package/dist/features/orders/components/OrderScopeTabs.js +31 -0
  271. package/dist/features/orders/components/OrderStatusTimeline.d.ts +5 -1
  272. package/dist/features/orders/components/OrderStatusTimeline.js +39 -20
  273. package/dist/features/orders/constants/order-scope.d.ts +48 -0
  274. package/dist/features/orders/constants/order-scope.js +111 -0
  275. package/dist/features/orders/repository/orders.repository.d.ts +54 -7
  276. package/dist/features/orders/repository/orders.repository.js +121 -22
  277. package/dist/features/orders/schemas/firestore.d.ts +152 -0
  278. package/dist/features/orders/schemas/firestore.js +30 -0
  279. package/dist/features/orders/schemas/index.d.ts +18 -18
  280. package/dist/features/orders/types/index.d.ts +35 -7
  281. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +14 -9
  282. package/dist/features/pre-orders/components/PreOrdersListView.js +6 -5
  283. package/dist/features/pre-orders/schemas/index.d.ts +1 -1
  284. package/dist/features/products/actions/product-actions.d.ts +14 -0
  285. package/dist/features/products/actions/product-actions.js +49 -11
  286. package/dist/features/products/api/route.d.ts +12 -0
  287. package/dist/features/products/api/route.js +42 -100
  288. package/dist/features/products/components/ArtStickersListView.js +2 -2
  289. package/dist/features/products/components/AuctionsIndexListing.js +13 -11
  290. package/dist/features/products/components/AvailabilityTabs.d.ts +11 -0
  291. package/dist/features/products/components/AvailabilityTabs.js +47 -0
  292. package/dist/features/products/components/GroupSettingsPanel.js +5 -1
  293. package/dist/features/products/components/MakeOfferButton.js +48 -49
  294. package/dist/features/products/components/PrizeDrawCollage.d.ts +20 -4
  295. package/dist/features/products/components/PrizeDrawCollage.js +9 -1
  296. package/dist/features/products/components/PrizeDrawsIndexListing.js +14 -12
  297. package/dist/features/products/components/PrizeDrawsListingView.js +2 -2
  298. package/dist/features/products/components/PrizeDrawsSection.d.ts +7 -1
  299. package/dist/features/products/components/PrizeDrawsSection.js +23 -18
  300. package/dist/features/products/components/ProductDetailPageView.d.ts +4 -1
  301. package/dist/features/products/components/ProductDetailPageView.js +18 -4
  302. package/dist/features/products/components/ProductForm.js +5 -2
  303. package/dist/features/products/components/ProductGrid.js +6 -1
  304. package/dist/features/products/components/ProductsIndexListing.js +22 -32
  305. package/dist/features/products/components/ProductsIndexPageView.js +6 -9
  306. package/dist/features/products/components/index.d.ts +2 -2
  307. package/dist/features/products/components/index.js +1 -1
  308. package/dist/features/products/config/listing-type-listing-config.d.ts +20 -0
  309. package/dist/features/products/config/listing-type-listing-config.js +22 -10
  310. package/dist/features/products/constants/action-defs.d.ts +2 -0
  311. package/dist/features/products/constants/action-defs.js +6 -0
  312. package/dist/features/products/hooks/useAvailabilityScope.d.ts +13 -0
  313. package/dist/features/products/hooks/useAvailabilityScope.js +19 -0
  314. package/dist/features/products/hooks/useProducts.d.ts +5 -0
  315. package/dist/features/products/hooks/useProducts.js +13 -2
  316. package/dist/features/products/repository/products.repository.d.ts +31 -2
  317. package/dist/features/products/repository/products.repository.js +53 -21
  318. package/dist/features/products/schemas/firestore.d.ts +17 -3
  319. package/dist/features/products/schemas/firestore.js +7 -2
  320. package/dist/features/products/schemas/index.d.ts +64 -64
  321. package/dist/features/products/schemas/product-features.validators.d.ts +79 -6
  322. package/dist/features/products/schemas/product-features.validators.js +63 -0
  323. package/dist/features/products/types/index.d.ts +16 -1
  324. package/dist/features/promotions/schemas/index.d.ts +2 -2
  325. package/dist/features/reviews/schemas/index.d.ts +16 -16
  326. package/dist/features/scams/constants/scammer-status-display.d.ts +28 -0
  327. package/dist/features/scams/constants/scammer-status-display.js +79 -0
  328. package/dist/features/search/schemas/index.d.ts +4 -4
  329. package/dist/features/seller/actions/offer-actions.js +57 -4
  330. package/dist/features/seller/components/OfferPhaseTimeline.d.ts +59 -0
  331. package/dist/features/seller/components/OfferPhaseTimeline.js +107 -0
  332. package/dist/features/seller/components/SellerArtView.js +5 -0
  333. package/dist/features/seller/components/SellerAuctionsView.js +13 -15
  334. package/dist/features/seller/components/SellerBidsView.js +11 -4
  335. package/dist/features/seller/components/SellerClassifiedView.js +5 -0
  336. package/dist/features/seller/components/SellerCouponEditorView.js +17 -17
  337. package/dist/features/seller/components/SellerDigitalCodesView.js +5 -0
  338. package/dist/features/seller/components/SellerLiveView.js +5 -0
  339. package/dist/features/seller/components/SellerOffersView.js +2 -1
  340. package/dist/features/seller/components/SellerOrdersView.js +31 -9
  341. package/dist/features/seller/components/SellerPayoutSettingsView.js +56 -31
  342. package/dist/features/seller/components/SellerPreOrdersView.js +5 -0
  343. package/dist/features/seller/components/SellerPrizeDrawsView.js +14 -16
  344. package/dist/features/seller/components/SellerProductShell.js +7 -1
  345. package/dist/features/seller/components/SellerProductsView.js +11 -8
  346. package/dist/features/seller/components/SellerStickersView.js +5 -0
  347. package/dist/features/seller/components/index.d.ts +0 -2
  348. package/dist/features/seller/components/index.js +0 -1
  349. package/dist/features/seller/repository/offer.repository.d.ts +142 -24
  350. package/dist/features/seller/repository/offer.repository.js +165 -26
  351. package/dist/features/seller/schemas/coupon-form.d.ts +72 -0
  352. package/dist/features/seller/schemas/coupon-form.js +116 -0
  353. package/dist/features/seller/schemas/firestore.d.ts +56 -2
  354. package/dist/features/seller/schemas/firestore.js +27 -0
  355. package/dist/features/seller/schemas/index.d.ts +2 -2
  356. package/dist/features/seller/schemas/offer-forms.d.ts +46 -0
  357. package/dist/features/seller/schemas/offer-forms.js +42 -0
  358. package/dist/features/seller/server.d.ts +0 -1
  359. package/dist/features/seller/server.js +0 -1
  360. package/dist/features/shell/SectionForm.d.ts +99 -0
  361. package/dist/features/shell/SectionForm.js +128 -0
  362. package/dist/features/shell/build-sections.d.ts +63 -0
  363. package/dist/features/shell/build-sections.js +207 -0
  364. package/dist/features/shell/entity-form.d.ts +109 -0
  365. package/dist/features/shell/entity-form.js +96 -0
  366. package/dist/features/shell/field-ui-meta.d.ts +115 -0
  367. package/dist/features/shell/field-ui-meta.js +324 -0
  368. package/dist/features/shell/index.d.ts +8 -0
  369. package/dist/features/shell/index.js +4 -0
  370. package/dist/features/status-history/components/StatusTimeline.d.ts +74 -0
  371. package/dist/features/status-history/components/StatusTimeline.js +46 -0
  372. package/dist/features/status-history/index.d.ts +11 -0
  373. package/dist/features/status-history/index.js +10 -0
  374. package/dist/features/store-extensions/components/ReviewDecisionModal.d.ts +27 -0
  375. package/dist/features/store-extensions/components/ReviewDecisionModal.js +82 -0
  376. package/dist/features/store-extensions/index.d.ts +12 -0
  377. package/dist/features/store-extensions/index.js +12 -0
  378. package/dist/features/store-extensions/schemas/admin-notification-form.d.ts +36 -0
  379. package/dist/features/store-extensions/schemas/admin-notification-form.js +114 -0
  380. package/dist/features/store-extensions/schemas/analytics-forms.d.ts +57 -0
  381. package/dist/features/store-extensions/schemas/analytics-forms.js +158 -0
  382. package/dist/features/store-extensions/schemas/custom-role-form.d.ts +85 -0
  383. package/dist/features/store-extensions/schemas/custom-role-form.js +118 -0
  384. package/dist/features/store-extensions/schemas/firestore.d.ts +21 -1
  385. package/dist/features/store-extensions/schemas/firestore.js +60 -0
  386. package/dist/features/store-extensions/schemas/google-config-form.d.ts +53 -0
  387. package/dist/features/store-extensions/schemas/google-config-form.js +105 -0
  388. package/dist/features/store-extensions/schemas/item-request-create-form.d.ts +28 -0
  389. package/dist/features/store-extensions/schemas/item-request-create-form.js +80 -0
  390. package/dist/features/store-extensions/schemas/listing-template-form.d.ts +78 -0
  391. package/dist/features/store-extensions/schemas/listing-template-form.js +87 -0
  392. package/dist/features/store-extensions/schemas/moderation-review-form.d.ts +49 -0
  393. package/dist/features/store-extensions/schemas/moderation-review-form.js +101 -0
  394. package/dist/features/store-extensions/schemas/payout-method-form.d.ts +153 -0
  395. package/dist/features/store-extensions/schemas/payout-method-form.js +155 -0
  396. package/dist/features/store-extensions/schemas/report-create-form.d.ts +25 -0
  397. package/dist/features/store-extensions/schemas/report-create-form.js +79 -0
  398. package/dist/features/store-extensions/schemas/report-review-form.d.ts +47 -0
  399. package/dist/features/store-extensions/schemas/report-review-form.js +111 -0
  400. package/dist/features/store-extensions/schemas/shipping-config-form.d.ts +148 -0
  401. package/dist/features/store-extensions/schemas/shipping-config-form.js +104 -0
  402. package/dist/features/store-extensions/schemas/store-category-form.d.ts +54 -0
  403. package/dist/features/store-extensions/schemas/store-category-form.js +73 -0
  404. package/dist/features/stores/api/[storeSlug]/route.js +2 -25
  405. package/dist/features/stores/components/StoreAuctionsListing.js +15 -1
  406. package/dist/features/stores/components/StoreClassifiedsListing.js +12 -2
  407. package/dist/features/stores/components/StoreDetailLayoutView.js +24 -71
  408. package/dist/features/stores/components/StoreDigitalCodesListing.js +12 -2
  409. package/dist/features/stores/components/StoreLiveItemsListing.js +12 -2
  410. package/dist/features/stores/components/StorePreOrdersListing.js +12 -1
  411. package/dist/features/stores/components/StoreProductsListing.js +11 -1
  412. package/dist/features/stores/repository/store.repository.js +6 -0
  413. package/dist/features/stores/schemas/index.d.ts +6 -6
  414. package/dist/features/support/schemas/index.d.ts +4 -4
  415. package/dist/features/tester/actions/checklist-item-actions.d.ts +4 -4
  416. package/dist/features/tester/seed-data/offers-tester-seed-data.js +119 -3
  417. package/dist/features/tester/seed-data/products-tester-seed-data.js +131 -1
  418. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +431 -1
  419. package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
  420. package/dist/index.d.ts +25 -12
  421. package/dist/index.js +26 -11
  422. package/dist/next/routing/route-map.d.ts +23 -3
  423. package/dist/next/routing/route-map.js +14 -2
  424. package/dist/providers/db-firebase/base.repository.d.ts +30 -0
  425. package/dist/providers/db-firebase/base.repository.js +50 -1
  426. package/dist/providers/db-firebase/index.d.ts +1 -1
  427. package/dist/providers/db-firebase/index.js +1 -1
  428. package/dist/providers/db-firebase/sieve.d.ts +25 -0
  429. package/dist/providers/db-firebase/sieve.js +52 -18
  430. package/dist/react/hooks/useUrlTable.js +10 -1
  431. package/dist/schemas/firestore-value.d.ts +8 -0
  432. package/dist/schemas/firestore-value.js +44 -0
  433. package/dist/schemas/index.d.ts +1 -1
  434. package/dist/schemas/index.js +1 -1
  435. package/dist/schemas/registry.d.ts +702 -69
  436. package/dist/schemas/registry.js +64 -1
  437. package/dist/seed/_helpers/category-forest.d.ts +2 -0
  438. package/dist/seed/_helpers/category-forest.js +309 -0
  439. package/dist/seed/_helpers/category-tree.d.ts +27 -0
  440. package/dist/seed/_helpers/category-tree.js +103 -0
  441. package/dist/seed/bids-seed-data.js +30 -0
  442. package/dist/seed/catalogue-seed-data.js +12 -12
  443. package/dist/seed/categories-seed-data.js +177 -162
  444. package/dist/seed/events-seed-data.js +61 -10
  445. package/dist/seed/homepage-sections-seed-data.js +5 -1
  446. package/dist/seed/offers-seed-data.js +244 -34
  447. package/dist/seed/orders-seed-data.js +336 -1
  448. package/dist/seed/products-art-seed-data.js +50 -12
  449. package/dist/seed/products-auctions-seed-data.js +138 -18
  450. package/dist/seed/products-classifieds-seed-data.js +80 -16
  451. package/dist/seed/products-digital-codes-seed-data.js +66 -18
  452. package/dist/seed/products-live-items-seed-data.js +64 -13
  453. package/dist/seed/products-preorders-seed-data.d.ts +0 -1
  454. package/dist/seed/products-preorders-seed-data.js +52 -13
  455. package/dist/seed/products-prize-draws-seed-data.js +63 -14
  456. package/dist/seed/products-standard-seed-data.js +99 -26
  457. package/dist/seed/products-stickers-seed-data.js +47 -12
  458. package/dist/seed/reviews-seed-data.js +6 -1
  459. package/dist/seed/site-settings-seed-data.d.ts +1 -38
  460. package/dist/seed/site-settings-seed-data.js +38 -76
  461. package/dist/seed/stores-seed-data.js +71 -1
  462. package/dist/seed/users-seed-data.js +15 -5
  463. package/dist/server-entry.d.ts +1 -2
  464. package/dist/server-entry.js +4 -3
  465. package/dist/server.d.ts +6 -3
  466. package/dist/server.js +13 -4
  467. package/dist/styles.css +78 -12
  468. package/dist/tailwind-utilities.css +1 -1
  469. package/dist/ui/components/Button.style.css +19 -4
  470. package/dist/ui/components/CollapsibleSection.d.ts +17 -1
  471. package/dist/ui/components/CollapsibleSection.js +6 -2
  472. package/dist/ui/components/FilterChipGroup.d.ts +25 -1
  473. package/dist/ui/components/FilterChipGroup.js +21 -4
  474. package/dist/ui/components/HandMode.style.css +47 -0
  475. package/dist/ui/components/Layout.d.ts +9 -2
  476. package/dist/ui/components/Layout.js +1 -1
  477. package/dist/ui/components/ListingLayout.js +8 -8
  478. package/dist/ui/components/ListingLayout.style.css +8 -7
  479. package/dist/ui/components/RecordDetailModal.d.ts +10 -1
  480. package/dist/ui/components/RecordDetailModal.js +2 -2
  481. package/dist/ui/components/StickyToolbar.d.ts +3 -1
  482. package/dist/ui/components/StickyToolbar.js +62 -20
  483. package/dist/ui/components/bottom-chrome-slot.d.ts +21 -0
  484. package/dist/ui/components/bottom-chrome-slot.js +29 -0
  485. package/dist/ui/components/index.style.css +3 -0
  486. package/dist/ui/forms/FormShell.d.ts +43 -13
  487. package/dist/ui/forms/FormShell.js +22 -11
  488. package/dist/ui/forms/index.d.ts +1 -1
  489. package/dist/ui/index.d.ts +1 -1
  490. package/package.json +2 -1
  491. package/scripts/node-esm-loader.mjs +65 -0
  492. package/scripts/seed-cli-loader.mjs +6 -49
  493. package/scripts/seed-cli.mjs +1 -1
@@ -2,25 +2,15 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { normalizeError } from "../../../errors/normalize";
4
4
  import { useApiMutation } from "@mohasinac/appkit/client";
5
- import React, { useEffect, useMemo } from "react";
6
- import { z } from "zod";
5
+ import React, { useEffect } from "react";
7
6
  import { useQuery } from "@tanstack/react-query";
8
7
  import { Button, ConfirmDeleteModal, Div, Heading, Input, RichTextEditor, RichTextRenderer, Row, Select, Span, Stack, StackedViewShell, TagInput, Text, Toggle, useToast } from "../../../ui";
9
8
  import { FormShellContext, useFormShellState, applyZodIssues, FormErrorSummary } from "../../../ui/forms";
10
9
  import { ImageUpload, MediaImage, useMediaUpload } from "../../media";
11
10
  import { apiClient } from "../../../http";
12
11
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
13
- import { blogPostCategorySchema } from "../../blog/schemas";
14
- import { StepForm } from "../../shell";
15
- // Form-input subset — `blogPostSchema` (blog schemas) requires `id` and uses
16
- // a `MediaField` shape for `coverImage`, neither of which this draft has
17
- // (coverImage here is a plain uploaded-URL string; id doesn't exist pre-save).
18
- const blogDraftSchema = z.object({
19
- title: z.string().min(1, "Title is required"),
20
- slug: z.string().min(1, "Slug is required").regex(/^blog-/, "Slug must start with 'blog-'"),
21
- category: blogPostCategorySchema,
22
- metaDescription: z.string().max(160).optional().or(z.literal("")),
23
- }).passthrough();
12
+ import { blogDraftSchema } from "../../blog/schemas/blog-form";
13
+ import { SectionForm, useSectionFormNav } from "../../shell";
24
14
  const __P = {
25
15
  p4: "p-[var(--appkit-space-4)]",
26
16
  };
@@ -62,7 +52,12 @@ function toSlug(str) {
62
52
  .trim()
63
53
  .replace(/[^a-z0-9]+/g, "-")
64
54
  .replace(/^-+|-+$/g, "");
65
- return base.startsWith("blog-") ? base : `blog-${base}`;
55
+ // Deliberately NOT prefixed with `blog-`. That prefix belongs to the
56
+ // document ID (`generateBlogPostId` adds it); the `slug` FIELD is what
57
+ // `findBySlug` queries and what appears in the public URL, and all 20 stored
58
+ // posts hold it bare. Prefixing here made every newly created post's URL
59
+ // disagree with every existing one.
60
+ return base;
66
61
  }
67
62
  function toDateInputValue(val) {
68
63
  if (!val)
@@ -80,15 +75,9 @@ export function AdminBlogEditorView({ postId, onSaved, onDeleted, embedded, ...r
80
75
  const isEdit = Boolean(postId);
81
76
  const [draft, setDraft] = React.useState(DEFAULT_DRAFT);
82
77
  const [slugManual, setSlugManual] = React.useState(false);
83
- const [currentStep, setCurrentStep] = React.useState(0);
84
78
  const [showDeleteConfirm, setShowDeleteConfirm] = React.useState(false);
85
79
  const { showToast } = useToast();
86
80
  const { upload } = useMediaUpload();
87
- const { shellCtx, setFieldError, validate } = useFormShellState(blogDraftSchema);
88
- useEffect(() => {
89
- validate(draft);
90
- // eslint-disable-next-line react-hooks/exhaustive-deps
91
- }, [draft, validate]);
92
81
  const update = React.useCallback((partial) => {
93
82
  setDraft((prev) => ({ ...prev, ...partial }));
94
83
  }, []);
@@ -146,13 +135,21 @@ export function AdminBlogEditorView({ postId, onSaved, onDeleted, embedded, ...r
146
135
  metaTitle: draft.metaTitle || undefined,
147
136
  metaDescription: draft.metaDescription || undefined,
148
137
  };
138
+ // T1 calculated field. It used to be computed ONLY on create, so editing
139
+ // a post's body left its "N min read" frozen at whatever the first draft
140
+ // happened to be — Root Cause #39, a CREATE transform with no UPDATE
141
+ // counterpart. Computed once here and sent on both paths.
142
+ const readTimeMinutes = Math.max(1, Math.round(draft.content.replace(/<[^>]*>/g, "").split(/\s+/).filter(Boolean).length / 200));
149
143
  if (isEdit) {
150
- return apiClient.patch(ADMIN_ENDPOINTS.BLOG_BY_ID(postId), payload);
144
+ return apiClient.patch(ADMIN_ENDPOINTS.BLOG_BY_ID(postId), {
145
+ ...payload,
146
+ readTimeMinutes,
147
+ });
151
148
  }
152
149
  return apiClient.post(ADMIN_ENDPOINTS.BLOG, {
153
150
  ...payload,
154
151
  authorId: "admin",
155
- readTimeMinutes: Math.max(1, Math.round(draft.content.replace(/<[^>]*>/g, "").split(/\s+/).filter(Boolean).length / 200)),
152
+ readTimeMinutes,
156
153
  views: 0,
157
154
  });
158
155
  },
@@ -181,11 +178,29 @@ export function AdminBlogEditorView({ postId, onSaved, onDeleted, embedded, ...r
181
178
  onError: (err) => showToast(err?.message ?? "Failed to delete post.", "error"),
182
179
  });
183
180
  const isLoading = saveMutation.isPending || postQuery.isLoading;
184
- const steps = [
181
+ /**
182
+ * Sections, not steps. Every field is reachable at once and one submit at
183
+ * the bottom saves the lot — the old wizard blocked step 2 until step 1
184
+ * validated, so a typo in the title made the whole post uneditable.
185
+ *
186
+ * The `render` bodies are unchanged: this form's controls are genuinely
187
+ * bespoke (a slug that auto-follows the title until touched, a read-time
188
+ * estimate, a live preview). What is no longer hand-written is which field
189
+ * belongs where — that is read off the schema's annotations, and the ids
190
+ * below match them exactly so `<FormErrorSummary>` can jump to the right
191
+ * section.
192
+ *
193
+ * The per-step `validate` callbacks are gone: they duplicated rules the Zod
194
+ * schema already states, and only ran as a gate to the NEXT step, which no
195
+ * longer exists.
196
+ */
197
+ const sections = [
185
198
  {
199
+ id: "content",
186
200
  label: "Content",
201
+ required: true,
202
+ quick: true,
187
203
  fields: ["title", "slug", "excerpt", "content"],
188
- validate: (values) => !values.title.trim() ? "Title is required" : null,
189
204
  render: ({ values, onChange }) => (_jsxs(Stack, { gap: "5", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Content" }), _jsx(Input, { label: "Title", value: values.title, onChange: (e) => {
190
205
  const v = e.target.value;
191
206
  onChange({ title: v, ...(!slugManual && { slug: toSlug(v) }) });
@@ -195,7 +210,11 @@ export function AdminBlogEditorView({ postId, onSaved, onDeleted, embedded, ...r
195
210
  }, placeholder: "blog-how-to-grade-pokemon-cards", helperText: "Auto-generated from title. Must start with 'blog-'." }), _jsx(Input, { label: "Excerpt", value: values.excerpt, onChange: (e) => onChange({ excerpt: e.target.value }), placeholder: "Short summary shown in listings and cards" }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "Content" }), _jsx(RichTextEditor, { value: values.content, onChange: (v) => onChange({ content: v }), placeholder: "Write your article here...", minHeightClassName: "min-h-[320px]" })] })] })),
196
211
  },
197
212
  {
213
+ id: "media",
198
214
  label: "Media",
215
+ // Media sections MUST stay mounted while collapsed: <Collapse> unmounts
216
+ // its children, which would abort an in-flight upload.
217
+ keepMounted: true,
199
218
  fields: ["coverImage", "youtubeId"],
200
219
  render: ({ values, onChange }) => (_jsxs(Stack, { gap: "5", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Media" }), _jsx(ImageUpload, { label: "Cover Image", currentImage: values.coverImage, onUpload: (file) => upload(file, "blog", true, {
201
220
  type: "blog-cover",
@@ -204,7 +223,9 @@ export function AdminBlogEditorView({ postId, onSaved, onDeleted, embedded, ...r
204
223
  }), onChange: (url) => onChange({ coverImage: url }) }), _jsx(Input, { label: "YouTube Video ID (optional)", value: values.youtubeId, onChange: (e) => onChange({ youtubeId: e.target.value }), placeholder: "e.g. dQw4w9WgXcQ", helperText: "The 11-character video ID from the YouTube URL." })] })),
205
224
  },
206
225
  {
226
+ id: "seo",
207
227
  label: "SEO & Tags",
228
+ quick: true,
208
229
  fields: ["category", "tags", "metaTitle", "metaDescription"],
209
230
  render: ({ values, onChange }) => {
210
231
  const readTime = Math.max(1, Math.round(values.content.replace(/<[^>]*>/g, "").split(/\s+/).filter(Boolean).length / 200));
@@ -212,7 +233,9 @@ export function AdminBlogEditorView({ postId, onSaved, onDeleted, embedded, ...r
212
233
  },
213
234
  },
214
235
  {
236
+ id: "publish",
215
237
  label: "Publish",
238
+ quick: true,
216
239
  fields: ["status", "publishedAt", "authorName", "isFeatured"],
217
240
  render: ({ values, onChange }) => (_jsxs(Stack, { gap: "5", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Publish Settings" }), _jsxs(Div, { layout: "grid", gap: "4", className: "grid-cols-2", children: [_jsx(Select, { label: "Status", options: STATUS_OPTIONS, value: values.status, onValueChange: (v) => onChange({ status: v }) }), _jsx(Input, { label: "Publish date (optional)", value: values.publishedAt, onChange: (e) => onChange({ publishedAt: e.target.value }), type: "date", helperText: "Auto-set to now when publishing." })] }), _jsx(Input, { label: "Author Name", value: values.authorName, onChange: (e) => onChange({ authorName: e.target.value }), placeholder: "Author display name" }), _jsx(Toggle, { label: "Featured post", checked: values.isFeatured, onChange: (checked) => onChange({ isFeatured: checked }) }), isEdit && (_jsx(Div, { className: "border-t border-[var(--appkit-color-border)]", padding: "t-md", children: _jsx(Button, { type: "button", variant: "danger", size: "sm", onClick: () => setShowDeleteConfirm(true), isLoading: deleteMutation.isPending, children: "Delete post" }) }))] })),
218
241
  },
@@ -221,16 +244,25 @@ export function AdminBlogEditorView({ postId, onSaved, onDeleted, embedded, ...r
221
244
  setShowDeleteConfirm(false);
222
245
  deleteMutation.mutate();
223
246
  }, onClose: () => setShowDeleteConfirm(false), title: "Delete post", message: "This will permanently delete the blog post. This cannot be undone." }));
224
- const fieldToStepIndex = useMemo(() => {
225
- const map = {};
226
- steps.forEach((step, i) => {
227
- step.fields?.forEach((field) => { map[field] = i; });
228
- });
229
- return map;
247
+ // Replaces the hand-rolled fieldToStepIndex + goToStep pair. The hook owns
248
+ // expand-then-scroll ordering, which a raw setState could not: a collapsed
249
+ // panel has to MOUNT before scrollIntoView/focus can reach the field. That
250
+ // jump was dead before W0 — `steps: []` was hardcoded in both context paths,
251
+ // so FormErrorSummary's label resolved to undefined for every form.
252
+ const { openIds, setOpenIds, goToSection, fieldToSectionIndex, sectionMeta } = useSectionFormNav(sections, draft);
253
+ const { shellCtx, setFieldError, validate } = useFormShellState(blogDraftSchema, {
254
+ sections: sectionMeta,
255
+ onGoToSection: goToSection,
256
+ fieldToSectionIndex,
257
+ });
258
+ // Live validation. Must sit AFTER useFormShellState — it used to run above
259
+ // the hook, which only compiled because the wizard declared the hook higher
260
+ // up the component.
261
+ useEffect(() => {
262
+ validate(draft);
230
263
  // eslint-disable-next-line react-hooks/exhaustive-deps
231
- }, [steps.length]);
232
- const wizardShellCtx = useMemo(() => ({ ...shellCtx, fieldToStepIndex, goToStep: (n) => setCurrentStep(n) }), [shellCtx, fieldToStepIndex, setCurrentStep]);
233
- const formContent = (_jsxs(FormShellContext.Provider, { value: wizardShellCtx, children: [_jsx(FormErrorSummary, {}), _jsx(StepForm, { steps: steps, values: draft, onChange: update, onComplete: () => { saveMutation.mutate(); }, formId: "admin-blog", currentStep: currentStep, onStepChange: setCurrentStep, completeLabel: isEdit ? "Save Changes" : "Create Post", isLoading: isLoading }), deleteModal] }));
264
+ }, [draft, validate]);
265
+ const formContent = (_jsxs(FormShellContext.Provider, { value: shellCtx, children: [_jsx(FormErrorSummary, {}), _jsx(SectionForm, { sections: sections, values: draft, onChange: update, onSubmit: () => { saveMutation.mutate(); }, schema: blogDraftSchema, openIds: openIds, onOpenChange: setOpenIds, submitLabel: isEdit ? "Save Changes" : "Create Post", isLoading: isLoading }), deleteModal] }));
234
266
  if (embedded) {
235
267
  return _jsx(Div, { className: `${__O.yAuto} ${__P.p4}`, children: formContent });
236
268
  }
@@ -13,14 +13,19 @@ import React from "react";
13
13
  import { ListingLayout } from "../../../ui";
14
14
  import { buildListingTypeListingConfig } from "../../products/config/listing-type-listing-config";
15
15
  import { DataListingView } from "./DataListingView";
16
- const CONFIG = buildListingTypeListingConfig("classified", {
16
+ import { useAvailabilityScope } from "../../products/hooks/useAvailabilityScope";
17
+ const LISTING_TYPES = ["classified"];
18
+ const CONFIG_OPTS = {
17
19
  title: "Classified",
18
20
  searchPlaceholder: "Search classified by name or seller",
19
21
  emptyLabel: "No classified listings",
20
- });
22
+ };
21
23
  export function AdminClassifiedView({ children, ...props }) {
24
+ const scope = useAvailabilityScope(LISTING_TYPES);
22
25
  if (React.Children.count(children) > 0) {
23
26
  return (_jsx(ListingLayout, { portal: "admin", ...props, children: children }));
24
27
  }
25
- return _jsx(DataListingView, { config: CONFIG });
28
+ // Built per-render rather than at module scope: the availability scope
29
+ // reads the URL through a hook, which cannot run outside a component.
30
+ return (_jsx(DataListingView, { config: buildListingTypeListingConfig("classified", { ...CONFIG_OPTS, scope }) }));
26
31
  }
@@ -13,14 +13,19 @@ import React from "react";
13
13
  import { ListingLayout } from "../../../ui";
14
14
  import { buildListingTypeListingConfig } from "../../products/config/listing-type-listing-config";
15
15
  import { DataListingView } from "./DataListingView";
16
- const CONFIG = buildListingTypeListingConfig("digital-code", {
16
+ import { useAvailabilityScope } from "../../products/hooks/useAvailabilityScope";
17
+ const LISTING_TYPES = ["digital-code"];
18
+ const CONFIG_OPTS = {
17
19
  title: "Digital Codes",
18
20
  searchPlaceholder: "Search digital code listings",
19
21
  emptyLabel: "No digital code listings",
20
- });
22
+ };
21
23
  export function AdminDigitalCodesView({ children, ...props }) {
24
+ const scope = useAvailabilityScope(LISTING_TYPES);
22
25
  if (React.Children.count(children) > 0) {
23
26
  return (_jsx(ListingLayout, { portal: "admin", ...props, children: children }));
24
27
  }
25
- return _jsx(DataListingView, { config: CONFIG });
28
+ // Built per-render rather than at module scope: the availability scope
29
+ // reads the URL through a hook, which cannot run outside a component.
30
+ return (_jsx(DataListingView, { config: buildListingTypeListingConfig("digital-code", { ...CONFIG_OPTS, scope }) }));
26
31
  }
@@ -8,6 +8,8 @@ import { Button, Checkbox, ConfirmDeleteModal, Div, Form, Grid, Input, Label, Se
8
8
  import { apiClient } from "../../../http";
9
9
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
10
10
  import { ERROR_MESSAGES } from "../../../errors/messages";
11
+ import { FormErrorSummary, applyZodIssues } from "../../../ui/forms";
12
+ import { productFeatureFormSchema } from "../../products/schemas/product-features.validators";
11
13
  import { PRODUCT_FEATURE_CATEGORY_OPTIONS, PRODUCT_FEATURE_DEFAULT_DISPLAY_ORDER, PRODUCT_FEATURE_ICON_COLOR_OPTIONS, PRODUCT_FEATURE_PRODUCT_TYPE_OPTIONS, PRODUCT_FEATURE_SCOPE_OPTIONS, } from "../../products/constants/product-features.constants";
12
14
  const __P = {
13
15
  p4: "p-[var(--appkit-space-4)]",
@@ -139,15 +141,42 @@ export function AdminFeatureEditorView({ featureId, fixedScope, fixedStoreId, em
139
141
  label: s.storeName ?? s.id,
140
142
  })),
141
143
  ], [storesQuery.data]);
142
- const isDisabled = !label || !icon || (scope === "store" && !storeId) || isSubmitting;
143
- const formSection = (_jsx(Form, { onSubmit: (e) => {
144
- e.preventDefault();
145
- saveMutation.mutate();
146
- }, children: _jsxs(Stack, { gap: "md", children: [_jsx(Input, { label: "Label", value: label, onChange: (e) => setLabel(e.target.value), required: true, placeholder: "e.g. Free Shipping", helperText: "Shown on product cards and detail pages." }), _jsx(Input, { label: "Description", value: description, onChange: (e) => setDescription(e.target.value), placeholder: "Optional \u2014 shown as a tooltip on the badge." }), _jsxs(Grid, { cols: "halves", gap: "md", children: [_jsx(Input, { label: "Icon", value: icon, onChange: (e) => setIcon(e.target.value), required: true, placeholder: "truck", helperText: "Icon-set name key (e.g. truck, star, trophy) OR an SVG path starting with M." }), _jsx(Select, { label: "Icon colour", value: iconColor, onChange: (e) => setIconColor(e.target.value), options: PRODUCT_FEATURE_ICON_COLOR_OPTIONS })] }), _jsxs(Grid, { cols: "halves", gap: "md", children: [_jsx(Select, { label: "Category", value: category, onChange: (e) => setCategory(e.target.value), options: PRODUCT_FEATURE_CATEGORY_OPTIONS, required: true }), _jsx(Input, { label: "Display order", value: displayOrder, onChange: (e) => setDisplayOrder(e.target.value), type: "number", min: 0 })] }), _jsxs(Div, { children: [_jsx(Text, { className: FIELD_LABEL_CLASS, children: "Applies to" }), _jsx(Row, { gap: "sm", wrap: true, className: "mt-2", children: PRODUCT_FEATURE_PRODUCT_TYPE_OPTIONS.map((opt) => {
144
+ /**
145
+ * Submit is gated on SUBMISSION, not on a truthiness guess.
146
+ *
147
+ * This used to be `!label || !icon || (scope === "store" && !storeId)` — a
148
+ * hand-rolled restatement of three of the schema's rules, which silently
149
+ * disagreed with it on every other rule (max lengths, displayOrder bounds,
150
+ * the productTypes minimum). The button now stays enabled and the schema
151
+ * reports what is actually wrong, on the field itself.
152
+ */
153
+ const isDisabled = isSubmitting;
154
+ const formSection = (_jsx(Form, { schema: productFeatureFormSchema, onSubmit: (e) => e.preventDefault(), children: ({ setFieldError, clearErrors }) => (_jsxs(Stack, { gap: "md", children: [_jsx(FormErrorSummary, {}), _jsx(Input, { label: "Label", value: label, onChange: (e) => setLabel(e.target.value), required: true, placeholder: "e.g. Free Shipping", helperText: "Shown on product cards and detail pages." }), _jsx(Input, { label: "Description", value: description, onChange: (e) => setDescription(e.target.value), placeholder: "Optional \u2014 shown as a tooltip on the badge." }), _jsxs(Grid, { cols: "halves", gap: "md", children: [_jsx(Input, { label: "Icon", value: icon, onChange: (e) => setIcon(e.target.value), required: true, placeholder: "truck", helperText: "Icon-set name key (e.g. truck, star, trophy) OR an SVG path starting with M." }), _jsx(Select, { label: "Icon colour", value: iconColor, onChange: (e) => setIconColor(e.target.value), options: PRODUCT_FEATURE_ICON_COLOR_OPTIONS })] }), _jsxs(Grid, { cols: "halves", gap: "md", children: [_jsx(Select, { label: "Category", value: category, onChange: (e) => setCategory(e.target.value), options: PRODUCT_FEATURE_CATEGORY_OPTIONS, required: true }), _jsx(Input, { label: "Display order", value: displayOrder, onChange: (e) => setDisplayOrder(e.target.value), type: "number", min: 0 })] }), _jsxs(Div, { children: [_jsx(Text, { className: FIELD_LABEL_CLASS, children: "Applies to" }), _jsx(Row, { gap: "sm", wrap: true, className: "mt-2", children: PRODUCT_FEATURE_PRODUCT_TYPE_OPTIONS.map((opt) => {
147
155
  const checked = productTypes.includes(opt.value);
148
156
  const pillClass = `${PILL_BASE_CLASS} ${checked ? PILL_CHECKED_CLASS : PILL_UNCHECKED_CLASS}`;
149
157
  return (_jsxs(Label, { className: pillClass, children: [_jsx(Checkbox, { bare: true, className: "sr-only", checked: checked, onChange: () => toggleProductType(opt.value) }), opt.label] }, opt.value));
150
- }) })] }), !fixedScope && (_jsx(Select, { label: "Scope", value: scope, onChange: (e) => setScope(e.target.value), options: PRODUCT_FEATURE_SCOPE_OPTIONS })), scope === "store" && !fixedStoreId && (_jsx(Select, { label: "Store", value: storeId, onChange: (e) => setStoreId(e.target.value), options: storeOptions, required: true, helperText: "Store-scope features are visible only on this store's listings." })), _jsx(Toggle, { label: "Active", checked: isActive, onChange: setIsActive }), _jsxs(Row, { gap: "3", padding: "t-xs", children: [_jsx(Button, { type: "submit", isLoading: isSubmitting, disabled: isDisabled, children: isEdit ? "Save changes" : "Create feature" }), isEdit && (_jsx(Button, { type: "button", variant: "danger", isLoading: deleteMutation.isPending, onClick: () => setDeleteConfirmOpen(true), children: "Delete" }))] })] }) }, "feature-form"));
158
+ }) })] }), !fixedScope && (_jsx(Select, { label: "Scope", value: scope, onChange: (e) => setScope(e.target.value), options: PRODUCT_FEATURE_SCOPE_OPTIONS })), scope === "store" && !fixedStoreId && (_jsx(Select, { label: "Store", value: storeId, onChange: (e) => setStoreId(e.target.value), options: storeOptions, required: true, helperText: "Store-scope features are visible only on this store's listings." })), _jsx(Toggle, { label: "Active", checked: isActive, onChange: setIsActive }), _jsxs(Row, { gap: "3", padding: "t-xs", children: [_jsx(Button, { type: "submit", isLoading: isSubmitting, disabled: isDisabled, onClick: () => {
159
+ // Parse before saving. This form had NO validation at all: the
160
+ // only guard was `required` on the inputs, an HTML attribute
161
+ // that any programmatic submit bypasses, and the max lengths /
162
+ // displayOrder bounds / productTypes minimum were never checked
163
+ // client-side at all.
164
+ clearErrors();
165
+ const parsed = productFeatureFormSchema.safeParse({
166
+ label, description: description || undefined,
167
+ icon, iconColor: iconColor || undefined,
168
+ category, scope,
169
+ productTypes: productTypes.length === 0 ? ["all"] : productTypes,
170
+ storeId: scope === "store" ? storeId || undefined : undefined,
171
+ isActive,
172
+ displayOrder: Number(displayOrder) || PRODUCT_FEATURE_DEFAULT_DISPLAY_ORDER,
173
+ });
174
+ if (!parsed.success) {
175
+ applyZodIssues(parsed.error.issues, setFieldError);
176
+ return;
177
+ }
178
+ saveMutation.mutate();
179
+ }, children: isEdit ? "Save changes" : "Create feature" }), isEdit && (_jsx(Button, { type: "button", variant: "danger", isLoading: deleteMutation.isPending, onClick: () => setDeleteConfirmOpen(true), children: "Delete" }))] })] })) }, "feature-form"));
151
180
  const deleteModal = deleteConfirmOpen && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete Feature", message: DELETE_CONFIRM_TEXT, onConfirm: () => { deleteMutation.mutate(); setDeleteConfirmOpen(false); }, onClose: () => setDeleteConfirmOpen(false), isDeleting: deleteMutation.isPending }));
152
181
  if (embedded) {
153
182
  return _jsxs(Div, { className: `${__O.yAuto} ${__P.p4}`, children: [formSection, deleteModal] });
@@ -16,6 +16,7 @@ const PLATFORM_FLAGS = [
16
16
  { key: "reviews", label: "Reviews", desc: "Product review system" },
17
17
  { key: "wishlists", label: "Wishlists", desc: "Per-user saved lists" },
18
18
  { key: "coupons", label: "Coupons", desc: "Discount code system" },
19
+ { key: "offers", label: "Buyer Offers", desc: "Make-an-offer price negotiation" },
19
20
  { key: "notifications", label: "Notifications", desc: "In-app notification feed" },
20
21
  { key: "chats", label: "Live Chat", desc: "Buyer-seller messaging" },
21
22
  { key: "sellerRegistration", label: "Seller Reg.", desc: "New vendor registration" },
@@ -13,14 +13,19 @@ import React from "react";
13
13
  import { ListingLayout } from "../../../ui";
14
14
  import { buildListingTypeListingConfig } from "../../products/config/listing-type-listing-config";
15
15
  import { DataListingView } from "./DataListingView";
16
- const CONFIG = buildListingTypeListingConfig("live", {
16
+ import { useAvailabilityScope } from "../../products/hooks/useAvailabilityScope";
17
+ const LISTING_TYPES = ["live"];
18
+ const CONFIG_OPTS = {
17
19
  title: "Live Items",
18
20
  searchPlaceholder: "Search live items",
19
21
  emptyLabel: "No live item listings",
20
- });
22
+ };
21
23
  export function AdminLiveView({ children, ...props }) {
24
+ const scope = useAvailabilityScope(LISTING_TYPES);
22
25
  if (React.Children.count(children) > 0) {
23
26
  return (_jsx(ListingLayout, { portal: "admin", ...props, children: children }));
24
27
  }
25
- return _jsx(DataListingView, { config: CONFIG });
28
+ // Built per-render rather than at module scope: the availability scope
29
+ // reads the URL through a hook, which cannot run outside a component.
30
+ return (_jsx(DataListingView, { config: buildListingTypeListingConfig("live", { ...CONFIG_OPTS, scope }) }));
26
31
  }
@@ -1,8 +1,10 @@
1
1
  "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { useApiMutation } from "@mohasinac/appkit/client";
4
4
  import React from "react";
5
5
  import { Button, Form, FormActions, Input, Select, SideDrawer, Toggle, useToast, } from "../../../ui";
6
+ import { FormErrorSummary, applyZodIssues } from "../../../ui/forms";
7
+ import { navItemFormSchema } from "../schemas/nav-item-form";
6
8
  import { apiClient } from "../../../http";
7
9
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
8
10
  import { ROUTES } from "../../../next/routing/route-map";
@@ -78,8 +80,16 @@ export function AdminNavEditorView({ open, onClose, onSaved, item, parentOptions
78
80
  { label: "None (top-level)", value: "" },
79
81
  ...parentOptions,
80
82
  ];
81
- return (_jsx(SideDrawer, { isOpen: open, onClose: onClose, title: isEdit ? "Edit Nav Item" : "New Nav Item", children: _jsxs(Form, { onSubmit: (e) => {
82
- e.preventDefault();
83
- saveMutation.mutate();
84
- }, spacing: "md", padding: "md", children: [_jsx(Input, { label: "Label", value: label, onChange: (e) => setLabel(e.target.value), required: true, placeholder: "e.g. Products" }), _jsx(Input, { label: "URL / href", value: href, onChange: (e) => setHref(e.target.value), required: true, placeholder: String(ROUTES.PUBLIC.PRODUCTS), helperText: "Use relative paths (e.g. /products) or full URLs." }), _jsx(Select, { label: "Icon (optional)", options: ICON_OPTIONS, value: icon, onValueChange: setIcon }), parentOptions.length > 0 && (_jsx(Select, { label: "Parent item (for nested nav)", options: parentSelectOptions, value: parentId, onValueChange: setParentId })), _jsx(Input, { label: "Order", value: String(order), onChange: (e) => setOrder(parseInt(e.target.value, 10) || 0), type: "number", min: 0, helperText: "Lower numbers appear first." }), _jsx(Toggle, { label: "Visible in navigation", checked: isVisible, onChange: setIsVisible }), _jsxs(FormActions, { align: "right", children: [_jsx(Button, { type: "button", variant: "secondary", onClick: onClose, children: "Cancel" }), _jsx(Button, { type: "submit", isLoading: saveMutation.isPending, disabled: !canSave || saveMutation.isPending, children: isEdit ? "Save changes" : "Create item" })] })] }) }));
83
+ return (_jsx(SideDrawer, { isOpen: open, onClose: onClose, title: isEdit ? "Edit Nav Item" : "New Nav Item", children: _jsx(Form, { schema: navItemFormSchema, onSubmit: (e) => e.preventDefault(), spacing: "md", padding: "md", children: ({ setFieldError, clearErrors }) => (_jsxs(_Fragment, { children: [_jsx(FormErrorSummary, {}), _jsx(Input, { label: "Label", value: label, onChange: (e) => setLabel(e.target.value), required: true, placeholder: "e.g. Products" }), _jsx(Input, { label: "URL / href", value: href, onChange: (e) => setHref(e.target.value), required: true, placeholder: String(ROUTES.PUBLIC.PRODUCTS), helperText: "Use relative paths (e.g. /products) or full URLs." }), _jsx(Select, { label: "Icon (optional)", options: ICON_OPTIONS, value: icon, onValueChange: setIcon }), parentOptions.length > 0 && (_jsx(Select, { label: "Parent item (for nested nav)", options: parentSelectOptions, value: parentId, onValueChange: setParentId })), _jsx(Input, { label: "Order", value: String(order), onChange: (e) => setOrder(parseInt(e.target.value, 10) || 0), type: "number", min: 0, helperText: "Lower numbers appear first." }), _jsx(Toggle, { label: "Visible in navigation", checked: isVisible, onChange: setIsVisible }), _jsxs(FormActions, { align: "right", children: [_jsx(Button, { type: "button", variant: "secondary", onClick: onClose, children: "Cancel" }), _jsx(Button, { type: "submit", isLoading: saveMutation.isPending, disabled: saveMutation.isPending, onClick: () => {
84
+ clearErrors();
85
+ const parsed = navItemFormSchema.safeParse({
86
+ label, href, icon: icon || undefined, order,
87
+ parentId: parentId || undefined, isVisible,
88
+ });
89
+ if (!parsed.success) {
90
+ applyZodIssues(parsed.error.issues, setFieldError);
91
+ return;
92
+ }
93
+ saveMutation.mutate();
94
+ }, children: isEdit ? "Save changes" : "Create item" })] })] })) }) }));
85
95
  }
@@ -6,7 +6,7 @@ import { sieveFilter, SIEVE_OP } from "@mohasinac/appkit/client";
6
6
  import { sortBy } from "@mohasinac/appkit/client";
7
7
  import React, { useCallback, useEffect, useState } from "react";
8
8
  import { useQueryClient } from "@tanstack/react-query";
9
- import { Button, ConfirmDeleteModal, FilterChipGroup, ListingLayout, RowActionMenu, useToast } from "../../../ui";
9
+ import { Button, ConfirmDeleteModal, FilterChipGroup, ListingLayout, RowActionMenu, useToast, RecordDetailModal, } from "../../../ui";
10
10
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
11
11
  import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
12
12
  import { buildBulkAction } from "../../../_internal/shared/actions/bulk-helpers";
@@ -15,6 +15,7 @@ import { toRecordArray, toRelativeDate, toStringValue, } from "../hooks/useAdmin
15
15
  import { DataListingView } from "./DataListingView";
16
16
  import { apiClient } from "../../../http";
17
17
  export function AdminNewsletterView({ children, onBulkUnsubscribe, ...props }) {
18
+ const [detail, setDetail] = useState(null);
18
19
  const queryClient = useQueryClient();
19
20
  const { showToast } = useToast();
20
21
  const [unsubscribeOpen, setUnsubscribeOpen] = useState(false);
@@ -98,6 +99,9 @@ export function AdminNewsletterView({ children, onBulkUnsubscribe, ...props }) {
98
99
  { value: sortBy("subscribedAt", "DESC"), label: "Newest" },
99
100
  { value: "subscribedAt", label: "Oldest" },
100
101
  ],
102
+ // Opening a row is what makes the destructive actions beside it
103
+ // safe to offer at all.
104
+ onRowClick: (row) => setDetail(row),
101
105
  mapRows: (response) => toRecordArray(response.subscribers).map((item, index) => ({
102
106
  id: toStringValue(item.id, `sub-${index}`),
103
107
  primary: toStringValue(item.email, "Unknown email"),
@@ -105,6 +109,7 @@ export function AdminNewsletterView({ children, onBulkUnsubscribe, ...props }) {
105
109
  .filter(Boolean)
106
110
  .join(" · ") || "—",
107
111
  status: toStringValue(item.status, "unknown"),
112
+ detail: item,
108
113
  updatedAt: toRelativeDate(item.subscribedAt ??
109
114
  item.createdAt),
110
115
  })),
@@ -138,7 +143,18 @@ export function AdminNewsletterView({ children, onBulkUnsubscribe, ...props }) {
138
143
  ] })),
139
144
  renderFilterPanel: ({ pendingFilters, setPendingFilters }) => (_jsx(FilterChipGroup, { label: "Status", tabs: ADMIN_NEWSLETTER_STATUS_TABS, value: pendingFilters.status ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, status: id })) })),
140
145
  };
141
- return (_jsxs(_Fragment, { children: [_jsx(DataListingView, { config: config }), _jsx(ConfirmDeleteModal, { isOpen: unsubscribeOpen, onClose: () => {
146
+ return (_jsxs(_Fragment, { children: [_jsx(DataListingView, { config: config }), _jsx(RecordDetailModal, { isOpen: detail !== null, onClose: () => setDetail(null), title: toStringValue(detail?.detail?.email, "Subscriber"), fields: (() => {
147
+ const d = (detail?.detail ?? {});
148
+ return detail ? [
149
+ { label: "Email", value: toStringValue(d.email, "—") },
150
+ { label: "Status", value: toStringValue(d.status, "—") },
151
+ { label: "Source", value: toStringValue(d.source, "—") },
152
+ { label: "Subscribed", value: toRelativeDate(d.subscribedAt ?? d.createdAt) },
153
+ { label: "Unsubscribed", value: toRelativeDate(d.unsubscribedAt) },
154
+ { label: "IP address", value: d.ipAddress ? "Logged" : "Not logged" },
155
+ { label: "Subscriber ID", value: detail?.id ?? "—" },
156
+ ] : undefined;
157
+ })() }), _jsx(ConfirmDeleteModal, { isOpen: unsubscribeOpen, onClose: () => {
142
158
  setUnsubscribeOpen(false);
143
159
  setSelectedRow(null);
144
160
  }, onConfirm: () => {
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ import type { ListingLayoutProps } from "../../../ui";
3
+ export type AdminOffersViewProps = ListingLayoutProps;
4
+ export declare function AdminOffersView({ children, ...props }: AdminOffersViewProps): React.JSX.Element;