@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
@@ -0,0 +1,230 @@
1
+ "use client";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /*
4
+ * WHY: Offers had a seller surface (/store/offers) and a buyer surface
5
+ * (/user/offers) but no admin surface at all — despite the offers
6
+ * collection carrying real money commitments, a 48h locked price, and a
7
+ * lane that can block a buyer's whole cart. There was no way for support
8
+ * to see an offer, let alone clear a stuck one.
9
+ * WHAT: The admin offers list. Cloned from SellerOffersView rather than
10
+ * AdminBidsView: the seller view is already offer-shaped and already
11
+ * satisfies `audit-listing-detail-affordance` (row click -> detail
12
+ * modal), whereas AdminBidsView is itself still on the Root Cause #56
13
+ * backlog and cloning it would have added a tenth violation.
14
+ *
15
+ * Two things differ from the seller view, both deliberate:
16
+ * - the buyer's real name/email is shown UNMASKED (the seller view masks via
17
+ * `maskOfferForSeller`) — an admin investigating a dispute needs identity;
18
+ * - the only mutation is Cancel. Accepting or countering on a seller's behalf
19
+ * is an authority nobody asked for, so `ADMIN_ROW_ACTIONS.offers` is
20
+ * deliberately just [VIEW, CANCEL].
21
+ *
22
+ * EXPORTS:
23
+ * AdminOffersView
24
+ *
25
+ * @tag domain:admin,offers
26
+ * @tag layer:feature-view
27
+ * @tag pattern:slot-shell
28
+ * @tag access:client
29
+ * @tag consumers:src/app/[locale]/admin/offers/page.tsx
30
+ * @tag sideEffects:network
31
+ */
32
+ import { useApiMutation } from "@mohasinac/appkit/client";
33
+ import { sieveFilter, SIEVE_OP } from "@mohasinac/appkit/client";
34
+ import { sortBy } from "@mohasinac/appkit/client";
35
+ import React, { useState } from "react";
36
+ import { useQueryClient } from "@tanstack/react-query";
37
+ import { FilterChipGroup, ListingLayout, RecordDetailModal, RowActionMenu, useToast, } from "../../../ui";
38
+ import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
39
+ import { ADMIN_OFFER_STATUS_TABS } from "../constants/filter-tabs";
40
+ import { OfferPhaseTimeline } from "../../seller/components/OfferPhaseTimeline";
41
+ import { QuickFormDrawer } from "../../shell/QuickFormDrawer";
42
+ import { cancelOfferFormSchema } from "../../seller/schemas/offer-forms";
43
+ import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
44
+ import { ROW_ACTION_META, ROW_ACTION_ID } from "../../products/constants/action-defs";
45
+ import { ROUTES } from "../../../next/routing/route-map";
46
+ import { toRecordArray, toRelativeDate, toCurrency, toStringValue, } from "../hooks/useAdminListingData";
47
+ import { DataListingView } from "./DataListingView";
48
+ import { apiClient } from "../../../http";
49
+ import { normalizeError } from "../../../errors/normalize";
50
+ /** Terminal states — an offer here has nothing left to cancel. */
51
+ const TERMINAL_STATUSES = new Set(["paid", "declined", "expired", "withdrawn"]);
52
+ export function AdminOffersView({ children, ...props }) {
53
+ const queryClient = useQueryClient();
54
+ const { showToast } = useToast();
55
+ const [detailRow, setDetailRow] = useState(null);
56
+ const [cancelOpen, setCancelOpen] = useState(false);
57
+ const [selectedRow, setSelectedRow] = useState(null);
58
+ /**
59
+ * Open on the SINGLE-ITEM response, not the row's cached list blob.
60
+ *
61
+ * Two reasons. The list payload has no `chain`, so a three-round negotiation
62
+ * would render as one orphan round; and a modal opened on a list snapshot
63
+ * shows whatever the last refetch happened to hold, which is the stale-editor
64
+ * shape of Root Cause #38.
65
+ *
66
+ * The row is shown immediately and enriched when the fetch lands, so the
67
+ * modal never blocks on the network.
68
+ */
69
+ const openDetail = async (row) => {
70
+ setDetailRow(row);
71
+ try {
72
+ const full = await apiClient.get(ADMIN_ENDPOINTS.OFFER_BY_ID(row.id));
73
+ const detail = (full?.data ?? full);
74
+ if (detail && typeof detail === "object") {
75
+ setDetailRow((prev) => (prev?.id === row.id ? { ...prev, detail } : prev));
76
+ }
77
+ }
78
+ catch (err) {
79
+ // The row's own data is already on screen, so this degrades to "no
80
+ // chain" rather than to an empty modal. Say so instead of failing silently.
81
+ const normalized = normalizeError(err);
82
+ showToast(normalized.message || "Couldn't load the full offer history.", "error");
83
+ }
84
+ };
85
+ const cancelMutation = useApiMutation({
86
+ mutationFn: async ({ offerId, reason }) => {
87
+ await apiClient.patch(ADMIN_ENDPOINTS.OFFER_BY_ID(offerId), {
88
+ status: "expired",
89
+ reason,
90
+ });
91
+ },
92
+ onSuccess: () => {
93
+ showToast("Offer cancelled and cleared from the buyer's cart.", "success");
94
+ queryClient.invalidateQueries({ queryKey: ["admin", "offers"] });
95
+ setCancelOpen(false);
96
+ setSelectedRow(null);
97
+ },
98
+ onError: (err) => {
99
+ showToast(err?.message ?? "Failed to cancel offer.", "error");
100
+ },
101
+ });
102
+ if (React.Children.count(children) > 0) {
103
+ return (_jsx(ListingLayout, { portal: "admin", ...props, children: children }));
104
+ }
105
+ const config = {
106
+ portal: "admin",
107
+ title: "Offers",
108
+ searchPlaceholder: "Search offers by product, buyer, or store",
109
+ emptyLabel: "No offers found",
110
+ filterKeys: ["status"],
111
+ defaultSort: sortBy("createdAt", "DESC"),
112
+ queryKey: ["admin", "offers", "listing"],
113
+ endpoint: ADMIN_ENDPOINTS.OFFERS,
114
+ sortOptions: [
115
+ { value: sortBy("createdAt", "DESC"), label: "Newest" },
116
+ { value: sortBy("createdAt", "ASC"), label: "Oldest" },
117
+ { value: sortBy("offerAmount", "DESC"), label: "Highest offer" },
118
+ ],
119
+ mapRows: (response) => toRecordArray(response.items).map((item, index) => ({
120
+ id: toStringValue(item.id, `offer-${index}`),
121
+ // The LISTING, not the offer id — a row identified only by
122
+ // `offer-…-20260819-x7y8z9` is unreadable at a glance (Root Cause #52).
123
+ primary: toStringValue(item.productTitle, "Untitled listing"),
124
+ // Admin sees both sides of the negotiation, unmasked.
125
+ secondary: [
126
+ `Offer: ${toCurrency(item.offerAmount)}`,
127
+ `Listed: ${toCurrency(item.listedPrice)}`,
128
+ `${toStringValue(item.buyerName, "Unknown buyer")} → ${toStringValue(item.storeName, "Unknown store")}`,
129
+ ].join(" · "),
130
+ status: toStringValue(item.status, "pending"),
131
+ updatedAt: toRelativeDate(item.updatedAt ?? item.createdAt),
132
+ detail: item,
133
+ })),
134
+ getTotal: (response, mappedRows) => typeof response.total === "number" ? response.total : mappedRows.length,
135
+ // A menu of pure mutations is not a detail affordance (Root Cause #56) —
136
+ // cancelling an offer without first reading it is acting blind.
137
+ onRowClick: (row) => void openDetail(row),
138
+ buildFilters: (state) => state.status && state.status !== "All"
139
+ ? sieveFilter("status", SIEVE_OP.EQ, state.status)
140
+ : undefined,
141
+ // No bulk actions, deliberately. There was a destructively-labelled
142
+ // "Cancel offer" entry here whose onClick only called clearSelection() — a
143
+ // registry-backed control that read as working and did nothing. Cancel now
144
+ // requires a per-offer reason, and one shared reason across a mixed
145
+ // selection is worse audit data than no bulk action at all.
146
+ renderRowActions: (row) => (_jsx(RowActionMenu, { actions: [
147
+ { label: ROW_ACTION_META[ROW_ACTION_ID.VIEW].label, onClick: () => void openDetail(row) },
148
+ {
149
+ label: ACTIONS.ADMIN["cancel-offer"].label,
150
+ destructive: true,
151
+ disabled: TERMINAL_STATUSES.has(row.status),
152
+ onClick: () => {
153
+ setSelectedRow(row);
154
+ setCancelOpen(true);
155
+ },
156
+ },
157
+ ] })),
158
+ renderFilterPanel: ({ pendingFilters, setPendingFilters }) => (_jsx(FilterChipGroup, { label: "Status", tabs: ADMIN_OFFER_STATUS_TABS, value: pendingFilters.status ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, status: id })) })),
159
+ };
160
+ const d = detailRow?.detail ?? {};
161
+ const productSlug = toStringValue(d.productSlug ?? d.productId, "");
162
+ const paidOrderId = toStringValue(d.paidOrderId, "");
163
+ return (_jsxs(_Fragment, { children: [_jsx(DataListingView, { config: config }), _jsx(RecordDetailModal, { isOpen: detailRow !== null, onClose: () => setDetailRow(null), title: detailRow?.primary ?? "Offer", badges: detailRow ? [{ label: detailRow.status }] : undefined, description: toStringValue(d.buyerNote, ""), fields: [
164
+ { label: "Buyer", value: toStringValue(d.buyerName, "Unknown buyer") },
165
+ { label: "Buyer email", value: toStringValue(d.buyerEmail, "—") },
166
+ { label: "Store", value: toStringValue(d.storeName, "Unknown store") },
167
+ { label: "Listed price", value: toCurrency(d.listedPrice) },
168
+ { label: "Offered", value: toCurrency(d.offerAmount) },
169
+ ...(d.counterAmount
170
+ ? [{ label: "Seller counter", value: toCurrency(d.counterAmount) }]
171
+ : []),
172
+ ...(d.lockedPrice
173
+ ? [{ label: "Locked price", value: toCurrency(d.lockedPrice) }]
174
+ : []),
175
+ ...(d.sellerNote
176
+ ? [{ label: "Seller note", value: toStringValue(d.sellerNote, "") }]
177
+ : []),
178
+ { label: "Offer expires", value: toRelativeDate(d.expiresAt) },
179
+ ...(d.checkoutDeadline
180
+ ? [{ label: "Buyer must pay by", value: toRelativeDate(d.checkoutDeadline) }]
181
+ : []),
182
+ { label: "Created", value: toRelativeDate(d.createdAt) },
183
+ { label: "Offer ID", value: detailRow?.id ?? "—" },
184
+ ], items: detailRow
185
+ ? {
186
+ heading: "Listing",
187
+ entries: [
188
+ {
189
+ image: toStringValue(d.productImageUrl, "") || undefined,
190
+ title: detailRow.primary,
191
+ subtitle: toStringValue(d.productId, ""),
192
+ trailing: toCurrency(d.listedPrice),
193
+ href: productSlug
194
+ ? String(ROUTES.PUBLIC.PRODUCT_DETAIL(productSlug))
195
+ : undefined,
196
+ },
197
+ // A paid offer became a real order — link to it, so the
198
+ // "what happened next" question has an answer in one click.
199
+ ...(paidOrderId
200
+ ? [
201
+ {
202
+ title: `Order ${paidOrderId}`,
203
+ subtitle: "Placed from this offer",
204
+ href: String(ROUTES.ADMIN.ORDER_DETAIL(paidOrderId)),
205
+ },
206
+ ]
207
+ : []),
208
+ ],
209
+ }
210
+ : undefined, extra: _jsx(OfferPhaseTimeline, { status: toStringValue(d.status, "pending"), timeline: d.timeline, timelineTruncated: d.timelineTruncated, superseded: Boolean(d.superseded), createdAt: toStringValue(d.createdAt, ""), respondedAt: toStringValue(d.respondedAt, ""), acceptedAt: toStringValue(d.acceptedAt, ""), paidAt: toStringValue(d.paidAt, ""), chain: d.chain }) }), _jsx(QuickFormDrawer, { isOpen: cancelOpen, onClose: () => {
211
+ setCancelOpen(false);
212
+ setSelectedRow(null);
213
+ }, title: ACTIONS.ADMIN["cancel-offer"].confirmation.title, schema: cancelOfferFormSchema, fields: [
214
+ {
215
+ name: "reason",
216
+ label: "Reason for cancelling",
217
+ type: "textarea",
218
+ required: true,
219
+ placeholder: "e.g. Listing withdrawn by the seller after a pricing error",
220
+ helperText: `${ACTIONS.ADMIN["cancel-offer"].confirmation.body} The buyer sees this reason, and it is recorded in the audit log.`,
221
+ },
222
+ ], submitLabel: ACTIONS.ADMIN["cancel-offer"].confirmation.confirmLabel, isLoading: cancelMutation.isPending, onSubmit: (values) => {
223
+ if (!selectedRow)
224
+ return;
225
+ cancelMutation.mutate({
226
+ offerId: selectedRow.id,
227
+ reason: String(values.reason ?? ""),
228
+ });
229
+ } })] }));
230
+ }
@@ -12,6 +12,7 @@ import { ROUTES } from "../../../next/routing/route-map";
12
12
  import { ADMIN_BULK_ACTIONS, ROW_ACTION_META, ROW_ACTION_ID } from "../../products/constants/action-defs";
13
13
  import { ADMIN_ORDER_STATUS_TABS, ADMIN_ORDER_PAYMENT_REVIEW_TABS } from "../constants/filter-tabs";
14
14
  import { isManualPaymentMethod, isPaymentReviewQueueMode } from "../../orders/constants/payment-window";
15
+ import { useOrderScope } from "../../orders/components/OrderScopeTabs";
15
16
  import { toRecordArray, toRelativeDate, toCurrency, toStringValue, } from "../hooks/useAdminListingData";
16
17
  import { DataListingView } from "./DataListingView";
17
18
  import { AdminOrderEditorView } from "./AdminOrderEditorView";
@@ -80,6 +81,7 @@ export function AdminOrdersView({ children, ...props }) {
80
81
  if (React.Children.count(children) > 0) {
81
82
  return (_jsx(ListingLayout, { portal: "admin", ...props, children: children }));
82
83
  }
84
+ const orderScope = useOrderScope();
83
85
  const config = {
84
86
  portal: "admin",
85
87
  title: "Orders",
@@ -147,7 +149,14 @@ export function AdminOrdersView({ children, ...props }) {
147
149
  return undefined;
148
150
  return f.status && f.status !== "All" ? sieveFilter("status", SIEVE_OP.EQ, f.status) : undefined;
149
151
  },
150
- buildExtraParams: (f) => isPaymentReviewQueueMode(f.paymentReview ?? "") ? { paymentReview: f.paymentReview } : undefined,
152
+ // The payment-review queue is its own mode — it already ignores `status`
153
+ // (see buildFilters above), so it must ignore the lifecycle scope too, or
154
+ // an admin opening the queue from the default Active tab would see it
155
+ // silently narrowed.
156
+ buildExtraParams: (f) => isPaymentReviewQueueMode(f.paymentReview ?? "")
157
+ ? { paymentReview: f.paymentReview }
158
+ : orderScope.extraParams,
159
+ renderAboveContent: orderScope.renderAboveContent,
151
160
  // Mirrors the row action's "View full details" entry so the row itself
152
161
  // is clickable, not just the overflow menu.
153
162
  onRowClick: (row) => {
@@ -1,9 +1,10 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { sortBy } from "@mohasinac/appkit/client";
4
+ import { useState } from "react";
4
5
  import { useUrlTable } from "../../../react/hooks/useUrlTable";
5
6
  import { useQueryClient } from "@tanstack/react-query";
6
- import { Badge, Div, FilterChipGroup, Span, Stack, Text, useToast } from "../../../ui";
7
+ import { Badge, Div, FilterChipGroup, Span, Stack, Text, useToast, RecordDetailModal, } from "../../../ui";
7
8
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
8
9
  import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
9
10
  import { toRecordArray, toRelativeDate, toStringValue } from "../hooks/useAdminListingData";
@@ -44,7 +45,10 @@ const PM_COLUMNS = [
44
45
  render: (row) => _jsx(Span, { size: "sm", color: "muted", children: row.updatedAt }),
45
46
  },
46
47
  ];
47
- function buildConfig(onAction) {
48
+ function buildConfig(onAction,
49
+ // Threaded in rather than closed over: this factory sits OUTSIDE the
50
+ // component, so the component's state setter is not in scope here.
51
+ onOpen) {
48
52
  return {
49
53
  portal: "admin",
50
54
  title: "Payment Methods",
@@ -65,6 +69,9 @@ function buildConfig(onAction) {
65
69
  { value: "type", label: "Type" },
66
70
  ],
67
71
  columns: PM_COLUMNS,
72
+ // Opening a row is what makes the destructive actions beside it
73
+ // safe to offer at all.
74
+ onRowClick: onOpen,
68
75
  mapRows: (response) => toRecordArray(response.items).map((item, index) => ({
69
76
  id: toStringValue(item.id, `pm-${index}`),
70
77
  primary: `${toStringValue(item.type, "unknown").toUpperCase()} · ${toStringValue(item.displayLabel, "—")}`,
@@ -72,6 +79,7 @@ function buildConfig(onAction) {
72
79
  status: toStringValue(item.banStatus, ""),
73
80
  updatedAt: toRelativeDate(item.bannedAt ?? item.updatedAt),
74
81
  _raw: item,
82
+ detail: item,
75
83
  })),
76
84
  getTotal: (response, rows) => typeof response.total === "number" ? response.total : rows.length,
77
85
  buildFilters: () => undefined,
@@ -111,6 +119,7 @@ function buildConfig(onAction) {
111
119
  };
112
120
  }
113
121
  export function AdminPaymentMethodsView(_props) {
122
+ const [detail, setDetail] = useState(null);
114
123
  // Independent useUrlTable() against the same URL param the listing reads
115
124
  // via filterKeys (Root Cause #35 pattern).
116
125
  const chipTable = useUrlTable({ defaults: {} });
@@ -132,6 +141,17 @@ export function AdminPaymentMethodsView(_props) {
132
141
  const handleAction = (id, action) => {
133
142
  actionMutation.mutate({ id, action });
134
143
  };
135
- const config = buildConfig(handleAction);
136
- return (_jsxs(Stack, { gap: "md", children: [_jsx(Div, { padding: "inline", border: "default", className: "border-b", children: _jsx(FilterChipGroup, { label: "Status", tabs: BAN_STATUS_TABS, value: banStatus, onChange: (v) => chipTable.set("banStatus", v) }) }), _jsx(DataListingView, { config: config })] }));
144
+ const config = buildConfig(handleAction, setDetail);
145
+ return (_jsxs(Stack, { gap: "md", children: [_jsx(RecordDetailModal, { isOpen: detail !== null, onClose: () => setDetail(null), title: toStringValue(detail?.detail?.displayLabel, "Payment method"), fields: (() => {
146
+ const d = (detail?.detail ?? {});
147
+ return detail ? [
148
+ { label: "Type", value: toStringValue(d.type, "—").toUpperCase() },
149
+ { label: "Label", value: toStringValue(d.displayLabel, "—") },
150
+ { label: "Owner", value: toStringValue(d.userId, "—") },
151
+ { label: "Ban status", value: toStringValue(d.banStatus, "Not banned") },
152
+ { label: "Ban reason", value: toStringValue(d.banReason, "—") },
153
+ { label: "Banned at", value: toRelativeDate(d.bannedAt) },
154
+ { label: "Method ID", value: detail?.id ?? "—" },
155
+ ] : undefined;
156
+ })() }), _jsx(Div, { padding: "inline", border: "default", className: "border-b", children: _jsx(FilterChipGroup, { label: "Status", tabs: BAN_STATUS_TABS, value: banStatus, onChange: (v) => chipTable.set("banStatus", v) }) }), _jsx(DataListingView, { config: config })] }));
137
157
  }
@@ -11,6 +11,8 @@ import { ADMIN_PRODUCT_STATUS_TABS } from "../constants/filter-tabs";
11
11
  import { ROUTES } from "../../../constants";
12
12
  import { toRecordArray, toRelativeDate, toCurrency, toStringValue, } from "../hooks/useAdminListingData";
13
13
  import { DataListingView } from "./DataListingView";
14
+ import { useAvailabilityScope } from "../../products/hooks/useAvailabilityScope";
15
+ const PRIZE_DRAW_TYPES = ["prize-draw"];
14
16
  const STATUS_VARIANT = {
15
17
  published: "success",
16
18
  active: "success",
@@ -57,6 +59,7 @@ export function AdminPrizeDrawsView({ children, ...props }) {
57
59
  if (React.Children.count(children) > 0) {
58
60
  return (_jsx(ListingLayout, { portal: "admin", ...props, children: children }));
59
61
  }
62
+ const scope = useAvailabilityScope(PRIZE_DRAW_TYPES);
60
63
  const config = {
61
64
  portal: "admin",
62
65
  title: "Prize Draws",
@@ -94,6 +97,8 @@ export function AdminPrizeDrawsView({ children, ...props }) {
94
97
  const status = state.status && state.status !== "All" ? sieveFilter("status", SIEVE_OP.EQ, state.status) : null;
95
98
  return ["listingType==prize-draw", status].filter(Boolean).join(",");
96
99
  },
100
+ buildExtraParams: () => scope.extraParams,
101
+ renderAboveContent: scope.renderAboveContent,
97
102
  rowHrefTemplate: String(ROUTES.ADMIN.PRIZE_DRAWS_EDIT("{id}")),
98
103
  // Rule #7: bulk-action array sourced from the ADMIN_BULK_ACTIONS preset.
99
104
  buildBulkActions: (selection) => ADMIN_BULK_ACTIONS.prizeDraws.map((id) => ({
@@ -16,6 +16,8 @@ import { AdminProductEditorView } from "./AdminProductEditorView";
16
16
  import { QuickEditMenu } from "./QuickEditMenu";
17
17
  import { ADMIN_BULK_ACTIONS, ROW_ACTION_META, ROW_ACTION_ID } from "../../products/constants/action-defs";
18
18
  import { parseSelectedListingTypes } from "../../products/utils/listing-type";
19
+ import { useAvailabilityScope } from "../../products/hooks/useAvailabilityScope";
20
+ import { ALL_LISTING_TYPES } from "../../../_internal/shared/listing-types/feature-flags";
19
21
  const FLAG_DEFS = [
20
22
  { key: "featured", label: "Featured" },
21
23
  { key: "isPromoted", label: "Promoted" },
@@ -95,16 +97,15 @@ export function AdminProductsView({ children, ...props }) {
95
97
  void handleToggle(row.id, key, v);
96
98
  } }, key))) })),
97
99
  };
98
- // We need showSold state to be derived from URL — read it via a small inner component
99
- // that uses the listing's own table state. To keep things simple, use a ref into the
100
- // config's render-prop chain via `renderAboveContent` which has no useUrlTable.
101
- // Simplest: use buildFilters which gets the full filterState, and add showSold to filterKeys.
100
+ // Spans every listing type unless the Type chips narrow it, which is what
101
+ // makes the middle tab read "Sold & Ended" here rather than one or the other.
102
+ const scope = useAvailabilityScope(ALL_LISTING_TYPES);
102
103
  const config = {
103
104
  portal: "admin",
104
105
  title: "Products",
105
106
  searchPlaceholder: "Search products, SKUs, or seller names",
106
107
  emptyLabel: "No products found",
107
- filterKeys: ["status", "type", "showSold", "showEnded", "showClosed"],
108
+ filterKeys: ["status", "type"],
108
109
  defaultSort: sortBy("createdAt", "DESC"),
109
110
  queryKey: ["admin", "products", "listing"],
110
111
  endpoint: ADMIN_ENDPOINTS.PRODUCTS,
@@ -169,8 +170,6 @@ export function AdminProductsView({ children, ...props }) {
169
170
  getTotal: (response, mappedRows) => typeof response.total === "number" ? response.total : mappedRows.length,
170
171
  buildFilters: (state) => {
171
172
  const parts = [];
172
- if (state.showSold !== "true")
173
- parts.push("isSold==false");
174
173
  if (state.status && state.status !== "All")
175
174
  parts.push(sieveFilter("status", SIEVE_OP.EQ, state.status));
176
175
  // `state.type` is a pipe-joined set of canonical ListingType values
@@ -181,20 +180,17 @@ export function AdminProductsView({ children, ...props }) {
181
180
  if (selectedTypes.length > 0) {
182
181
  parts.push(sieveFilter("listingType", SIEVE_OP.EQ, selectedTypes.join("|")));
183
182
  }
184
- // Ended/closed are per-type predicates: `auctionEndDate` and
185
- // `prizeRevealWindowEnd` only exist on auctions and prize-draws. Apply
186
- // each only when its type is the ONLY one selected — with a mixed
187
- // selection the inequality would exclude every row of the other types
188
- // (they have no such field at all), which reads as "no results".
189
- const onlyType = selectedTypes.length === 1 ? selectedTypes[0] : null;
190
- if (onlyType === "auction" && state.showEnded !== "true") {
191
- parts.push(sieveFilter("auctionEndDate", SIEVE_OP.GTE, new Date().toISOString()));
192
- }
193
- if (onlyType === "prize-draw" && state.showClosed !== "true") {
194
- parts.push(sieveFilter("prizeRevealWindowEnd", SIEVE_OP.GTE, new Date().toISOString()));
195
- }
183
+ // Three drawer chips (Sold / Ended / Closed) used to live here, each
184
+ // emitting its own clause and each guarded by an `onlyType` check
185
+ // because `auctionEndDate` and `prizeRevealWindowEnd` do not exist on
186
+ // the other seven types. That guard meant the ended/closed filters
187
+ // silently did nothing on any mixed selection. The scope param replaces
188
+ // all three, and resolves the per-type meaning server-side — so it works
189
+ // across a mixed selection, which is the common case here.
196
190
  return parts.join(",") || undefined;
197
191
  },
192
+ buildExtraParams: () => scope.extraParams,
193
+ renderAboveContent: scope.renderAboveContent,
198
194
  primaryAction: {
199
195
  label: "Add Product",
200
196
  onClick: ({ openCreatePanel }) => openCreatePanel(),
@@ -263,16 +259,7 @@ export function AdminProductsView({ children, ...props }) {
263
259
  submitLabel: "Save",
264
260
  },
265
261
  ] })),
266
- renderFilterPanel: ({ pendingFilters, setPendingFilters }) => (_jsxs(_Fragment, { children: [_jsx(FilterChipGroup, { label: "Status", tabs: ADMIN_PRODUCT_STATUS_TABS, value: pendingFilters.status ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, status: id })) }), _jsx(FilterChipGroup, { multiple: true, label: "Type", tabs: ADMIN_PRODUCT_LISTING_TYPE_TABS, value: pendingFilters.type ?? "", onChange: (ids) => setPendingFilters((p) => ({ ...p, type: ids })) }), _jsx(FilterChipGroup, { label: "Sold", tabs: [
267
- { id: "", label: "Hide sold" },
268
- { id: "true", label: "Show sold" },
269
- ], value: pendingFilters.showSold ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, showSold: id })), allId: "" }), _jsx(FilterChipGroup, { label: "Ended", tabs: [
270
- { id: "", label: "Hide ended" },
271
- { id: "true", label: "Show ended" },
272
- ], value: pendingFilters.showEnded ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, showEnded: id })), allId: "" }), _jsx(FilterChipGroup, { label: "Closed", tabs: [
273
- { id: "", label: "Hide closed" },
274
- { id: "true", label: "Show closed" },
275
- ], value: pendingFilters.showClosed ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, showClosed: id })), allId: "" })] })),
262
+ renderFilterPanel: ({ pendingFilters, setPendingFilters }) => (_jsxs(_Fragment, { children: [_jsx(FilterChipGroup, { label: "Status", tabs: ADMIN_PRODUCT_STATUS_TABS, value: pendingFilters.status ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, status: id })) }), _jsx(FilterChipGroup, { multiple: true, label: "Type", tabs: ADMIN_PRODUCT_LISTING_TYPE_TABS, value: pendingFilters.type ?? "", onChange: (ids) => setPendingFilters((p) => ({ ...p, type: ids })) })] })),
276
263
  renderEditor: ({ editId, closePanel }) => (_jsx(AdminProductEditorView, { productId: editId ?? undefined, initialData: editId ? rawByIdRef.current[editId] : undefined, onSaved: closePanel, onDeleted: closePanel, embedded: true })),
277
264
  resolveEditorTitle: ({ isCreate }) => (isCreate ? "Add Product" : "Edit Product"),
278
265
  };
@@ -1,4 +1,5 @@
1
1
  import React from "react";
2
+ import { type ScammerStatus } from "../../scams/schemas/firestore";
2
3
  export interface AdminScammerEditorViewProps {
3
4
  open: boolean;
4
5
  onClose: () => void;
@@ -8,7 +9,7 @@ export interface AdminScammerEditorViewProps {
8
9
  description?: string;
9
10
  phones?: string[];
10
11
  upiIds?: string[];
11
- currentStatus?: string;
12
+ currentStatus?: ScammerStatus;
12
13
  verificationNote?: string;
13
14
  reportedBy?: string;
14
15
  reportedByAnon?: boolean;
@@ -6,23 +6,13 @@ import { useQueryClient } from "@tanstack/react-query";
6
6
  import { Button, Code, Div, FormActions, HorizontalRule, Label, Row, Select, SideDrawer, Span, Stack, Text, Textarea, useToast } from "../../../ui";
7
7
  import { apiClient } from "../../../http";
8
8
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
9
+ import { ScammerStatusValues, } from "../../scams/schemas/firestore";
10
+ import { SCAMMER_STATUS_BADGE, SCAMMER_STATUS_LABEL, SCAMMER_STATUS_OPTIONS, } from "../../scams/constants/scammer-status-display";
9
11
  const __P = {
10
12
  p3: "p-[var(--appkit-space-3)]",
11
13
  p4: "p-[var(--appkit-space-4)]",
12
14
  };
13
15
  const CLS_SECTION_LABEL = "text-[length:var(--appkit-text-xs)] font-medium text-[var(--appkit-color-text-muted)] uppercase tracking-wide";
14
- const STATUS_OPTIONS = [
15
- { label: "Pending review", value: "pending_review" },
16
- { label: "Verified", value: "verified" },
17
- { label: "Rejected", value: "rejected" },
18
- { label: "Removed", value: "removed" },
19
- ];
20
- const STATUS_COLOR = {
21
- pending_review: "bg-warning-surface text-warning",
22
- verified: "bg-success-surface text-success",
23
- rejected: "bg-error-surface text-error",
24
- removed: "bg-[var(--appkit-color-surface)] text-[var(--appkit-color-text-muted)] bg-[var(--appkit-color-surface-elevated)] text-[var(--appkit-color-text-muted)]",
25
- };
26
16
  export function AdminScammerEditorView({ open, onClose, scammerId, displayNames = [], scamType, description, phones = [], upiIds = [], currentStatus, verificationNote, reportedBy, reportedByAnon, }) {
27
17
  const queryClient = useQueryClient();
28
18
  const { showToast } = useToast();
@@ -63,5 +53,5 @@ export function AdminScammerEditorView({ open, onClose, scammerId, displayNames
63
53
  showToast(err?.message ?? "Failed to delete profile.", "error");
64
54
  },
65
55
  });
66
- return (_jsx(SideDrawer, { isOpen: open, onClose: onClose, title: displayNames.length > 0 ? displayNames[0] : "Scammer Profile", children: _jsxs(Stack, { className: `${__P.p4}`, gap: "md", children: [_jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Span, { size: "xs", weight: "medium", className: `inline-flex ${STATUS_COLOR[currentStatus ?? "pending_review"] ?? STATUS_COLOR.pending_review}`, rounded: "full", padding: "pill-sm-tall", children: (currentStatus ?? "pending_review").replace(/_/g, " ") }), scamType && (_jsx(Span, { size: "xs", rounded: "full", padding: "pill-sm-tall", surface: "subtle", color: "muted", children: scamType.replace(/_/g, " ") }))] }), displayNames.length > 0 && (_jsxs(Div, { children: [_jsx(Text, { className: "mb-1 tracking-wide", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: "Names / Aliases" }), _jsx(Row, { wrap: true, gap: "xs", children: displayNames.map((name, i) => (_jsx(Span, { size: "xs", rounded: "full", surface: "subtle", padding: "pill-sm", children: name }, i))) })] })), (phones.length > 0 || upiIds.length > 0) && (_jsxs(Div, { className: `${__P.p3}`, rounded: "lg", surface: "muted", border: "default", children: [phones.length > 0 && (_jsxs(Div, { className: "mb-2", children: [_jsx(Text, { className: CLS_SECTION_LABEL, children: "Phone numbers" }), _jsx(Row, { wrap: true, gap: "xs", children: phones.map((p, i) => (_jsx(Code, { size: "xs", rounded: "default", padding: "sm", surface: "subtle", children: p }, i))) })] })), upiIds.length > 0 && (_jsxs(_Fragment, { children: [_jsx(Text, { className: CLS_SECTION_LABEL, children: "UPI IDs" }), _jsx(Row, { wrap: true, gap: "xs", children: upiIds.map((u, i) => (_jsx(Code, { size: "xs", rounded: "default", padding: "sm", surface: "subtle", children: u }, i))) })] }))] })), description && (_jsxs(Div, { className: `${__P.p3}`, rounded: "lg", surface: "muted", border: "default", children: [_jsx(Text, { className: CLS_SECTION_LABEL, children: "Description" }), _jsx(Text, { className: "whitespace-pre-wrap", color: "primary", size: "sm", children: description })] })), _jsxs(Div, { textSize: "xs", color: "muted", children: ["Reported by:", " ", _jsx(Span, { weight: "medium", color: "muted", children: reportedByAnon ? "Anonymous" : (reportedBy ?? "Unknown") })] }), _jsx(HorizontalRule, { tone: "subtle", spacing: "comfortable" }), _jsx(Select, { label: "Status", options: STATUS_OPTIONS, value: status, onValueChange: setStatus }), _jsxs(Stack, { gap: "xs", children: [_jsx(Label, { className: "uppercase tracking-wide", color: "muted", size: "xs", weight: "semibold", children: "Verification note (internal)" }), _jsx(Textarea, { value: note, onChange: (e) => setNote(e.target.value), rows: 3, placeholder: "e.g. Verified via 3 independent reports\u2026" })] }), _jsxs(FormActions, { align: "right", children: [_jsx(Button, { type: "button", variant: "danger", size: "sm", disabled: !scammerId, isLoading: deleteMutation.isPending, onClick: () => deleteMutation.mutate(), children: "Delete" }), _jsx(Button, { type: "button", variant: "secondary", onClick: onClose, children: "Cancel" }), _jsx(Button, { type: "button", isLoading: updateMutation.isPending, disabled: !scammerId || updateMutation.isPending, onClick: () => updateMutation.mutate(), children: "Save changes" })] })] }) }));
56
+ return (_jsx(SideDrawer, { isOpen: open, onClose: onClose, title: displayNames.length > 0 ? displayNames[0] : "Scammer Profile", children: _jsxs(Stack, { className: `${__P.p4}`, gap: "md", children: [_jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Span, { size: "xs", weight: "medium", className: `inline-flex ${SCAMMER_STATUS_BADGE[currentStatus ?? ScammerStatusValues.PENDING_REVIEW]}`, rounded: "full", padding: "pill-sm-tall", children: SCAMMER_STATUS_LABEL[currentStatus ?? ScammerStatusValues.PENDING_REVIEW] }), scamType && (_jsx(Span, { size: "xs", rounded: "full", padding: "pill-sm-tall", surface: "subtle", color: "muted", children: scamType.replace(/_/g, " ") }))] }), displayNames.length > 0 && (_jsxs(Div, { children: [_jsx(Text, { className: "mb-1 tracking-wide", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: "Names / Aliases" }), _jsx(Row, { wrap: true, gap: "xs", children: displayNames.map((name, i) => (_jsx(Span, { size: "xs", rounded: "full", surface: "subtle", padding: "pill-sm", children: name }, i))) })] })), (phones.length > 0 || upiIds.length > 0) && (_jsxs(Div, { className: `${__P.p3}`, rounded: "lg", surface: "muted", border: "default", children: [phones.length > 0 && (_jsxs(Div, { className: "mb-2", children: [_jsx(Text, { className: CLS_SECTION_LABEL, children: "Phone numbers" }), _jsx(Row, { wrap: true, gap: "xs", children: phones.map((p, i) => (_jsx(Code, { size: "xs", rounded: "default", padding: "sm", surface: "subtle", children: p }, i))) })] })), upiIds.length > 0 && (_jsxs(_Fragment, { children: [_jsx(Text, { className: CLS_SECTION_LABEL, children: "UPI IDs" }), _jsx(Row, { wrap: true, gap: "xs", children: upiIds.map((u, i) => (_jsx(Code, { size: "xs", rounded: "default", padding: "sm", surface: "subtle", children: u }, i))) })] }))] })), description && (_jsxs(Div, { className: `${__P.p3}`, rounded: "lg", surface: "muted", border: "default", children: [_jsx(Text, { className: CLS_SECTION_LABEL, children: "Description" }), _jsx(Text, { className: "whitespace-pre-wrap", color: "primary", size: "sm", children: description })] })), _jsxs(Div, { textSize: "xs", color: "muted", children: ["Reported by:", " ", _jsx(Span, { weight: "medium", color: "muted", children: reportedByAnon ? "Anonymous" : (reportedBy ?? "Unknown") })] }), _jsx(HorizontalRule, { tone: "subtle", spacing: "comfortable" }), _jsx(Select, { label: "Status", options: SCAMMER_STATUS_OPTIONS, value: status, onValueChange: setStatus }), _jsxs(Stack, { gap: "xs", children: [_jsx(Label, { className: "uppercase tracking-wide", color: "muted", size: "xs", weight: "semibold", children: "Verification note (internal)" }), _jsx(Textarea, { value: note, onChange: (e) => setNote(e.target.value), rows: 3, placeholder: "e.g. Verified via 3 independent reports\u2026" })] }), _jsxs(FormActions, { align: "right", children: [_jsx(Button, { type: "button", variant: "danger", size: "sm", disabled: !scammerId, isLoading: deleteMutation.isPending, onClick: () => deleteMutation.mutate(), children: "Delete" }), _jsx(Button, { type: "button", variant: "secondary", onClick: onClose, children: "Cancel" }), _jsx(Button, { type: "button", isLoading: updateMutation.isPending, disabled: !scammerId || updateMutation.isPending, onClick: () => updateMutation.mutate(), children: "Save changes" })] })] }) }));
67
57
  }
@@ -12,12 +12,7 @@ import { ADMIN_SCAMMER_STATUS_TABS } from "../constants/filter-tabs";
12
12
  import { toRecordArray, toRelativeDate, toStringValue, } from "../hooks/useAdminListingData";
13
13
  import { DataListingView } from "./DataListingView";
14
14
  import { AdminScammerEditorView } from "./AdminScammerEditorView";
15
- const STATUS_BADGE = {
16
- pending_review: "bg-warning-surface text-warning",
17
- verified: "bg-success-surface text-success",
18
- rejected: "bg-error-surface text-error",
19
- removed: "bg-[var(--appkit-color-surface)] text-[var(--appkit-color-text-muted)] bg-[var(--appkit-color-surface-elevated)] text-[var(--appkit-color-text-muted)]",
20
- };
15
+ import { SCAMMER_STATUS_BADGE, SCAMMER_STATUS_LABEL, toScammerStatus, } from "../../scams/constants/scammer-status-display";
21
16
  const SCAMMER_COLUMNS = [
22
17
  {
23
18
  key: "primary",
@@ -28,7 +23,7 @@ const SCAMMER_COLUMNS = [
28
23
  key: "status",
29
24
  header: "Status",
30
25
  className: "w-36",
31
- render: (row) => (_jsx(Span, { className: `inline-flex ${STATUS_BADGE[row.status] ?? STATUS_BADGE.pending_review}`, size: "xs", weight: "medium", rounded: "full", padding: "pill-sm-tall", children: row.status.replace(/_/g, " ") })),
26
+ render: (row) => (_jsx(Span, { className: `inline-flex ${SCAMMER_STATUS_BADGE[row.status]}`, size: "xs", weight: "medium", rounded: "full", padding: "pill-sm-tall", children: SCAMMER_STATUS_LABEL[row.status] })),
32
27
  },
33
28
  {
34
29
  key: "updatedAt",
@@ -72,7 +67,7 @@ export function AdminScammersView({ children, ...props }) {
72
67
  ]
73
68
  .filter(Boolean)
74
69
  .join(" · "),
75
- status: toStringValue(item.status, "pending_review"),
70
+ status: toScammerStatus(item.status),
76
71
  updatedAt: toRelativeDate(item.updatedAt ?? item.createdAt),
77
72
  _raw: item,
78
73
  })),