@mohasinac/appkit 4.9.5 → 4.11.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 (395) hide show
  1. package/dist/_internal/client/features/layout/DashboardLayoutClient.d.ts +6 -1
  2. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +4 -1
  3. package/dist/_internal/client/features/lottery/LotteryPullForm.d.ts +1 -1
  4. package/dist/_internal/client/features/lottery/LotteryPullForm.js +2 -2
  5. package/dist/_internal/server/features/admin/daily-digest-actions.d.ts +18 -0
  6. package/dist/_internal/server/features/admin/daily-digest-actions.js +37 -0
  7. package/dist/_internal/server/features/auctions/actions.js +3 -2
  8. package/dist/_internal/server/features/auctions/service.d.ts +4 -3
  9. package/dist/_internal/server/features/auctions/service.js +6 -6
  10. package/dist/_internal/server/features/audit-log/actions.d.ts +25 -0
  11. package/dist/_internal/server/features/audit-log/actions.js +38 -0
  12. package/dist/_internal/server/features/brands/actions.js +0 -2
  13. package/dist/_internal/server/features/brands/og.d.ts +4 -1
  14. package/dist/_internal/server/features/brands/og.js +1 -1
  15. package/dist/_internal/server/features/bundles/data.d.ts +9 -0
  16. package/dist/_internal/server/features/bundles/data.js +14 -0
  17. package/dist/_internal/server/features/bundles/index.d.ts +1 -1
  18. package/dist/_internal/server/features/bundles/index.js +1 -1
  19. package/dist/_internal/server/features/catalogue/og.d.ts +20 -0
  20. package/dist/_internal/server/features/catalogue/og.js +27 -0
  21. package/dist/_internal/server/features/grouped/data.d.ts +16 -0
  22. package/dist/_internal/server/features/grouped/data.js +50 -1
  23. package/dist/_internal/server/features/grouped/index.d.ts +1 -1
  24. package/dist/_internal/server/features/grouped/index.js +1 -1
  25. package/dist/_internal/server/features/orders/actions.js +9 -0
  26. package/dist/_internal/server/features/orders/adapters.js +25 -0
  27. package/dist/_internal/server/features/products/data.d.ts +23 -0
  28. package/dist/_internal/server/features/products/data.js +159 -0
  29. package/dist/_internal/server/features/products/index.d.ts +1 -1
  30. package/dist/_internal/server/features/products/index.js +1 -1
  31. package/dist/_internal/server/functions/scheduled.d.ts +3 -1
  32. package/dist/_internal/server/functions/scheduled.js +17 -1
  33. package/dist/_internal/server/jobs/core/dailyStatusDigest.d.ts +40 -0
  34. package/dist/_internal/server/jobs/core/dailyStatusDigest.js +164 -0
  35. package/dist/_internal/server/jobs/core/hardBanCascade.js +11 -0
  36. package/dist/_internal/server/jobs/core/testerSandboxCleanup.d.ts +1 -0
  37. package/dist/_internal/server/jobs/core/testerSandboxCleanup.js +4 -1
  38. package/dist/_internal/server/jobs/core/testerSandboxRefresh.d.ts +12 -0
  39. package/dist/_internal/server/jobs/core/testerSandboxRefresh.js +85 -0
  40. package/dist/_internal/server/jobs/core/whatsappNotify.js +16 -0
  41. package/dist/_internal/server/jobs/handlers/dailyStatusDigest.d.ts +2 -0
  42. package/dist/_internal/server/jobs/handlers/dailyStatusDigest.js +4 -0
  43. package/dist/_internal/server/jobs/handlers/index.d.ts +2 -0
  44. package/dist/_internal/server/jobs/handlers/index.js +3 -0
  45. package/dist/_internal/server/jobs/handlers/testerSandboxRefresh.d.ts +2 -0
  46. package/dist/_internal/server/jobs/handlers/testerSandboxRefresh.js +2 -0
  47. package/dist/_internal/server/notifications/channel-health.d.ts +27 -0
  48. package/dist/_internal/server/notifications/channel-health.js +101 -0
  49. package/dist/_internal/shared/features/auctions/config.d.ts +20 -0
  50. package/dist/_internal/shared/features/auctions/config.js +31 -1
  51. package/dist/_internal/shared/features/brands/schema.d.ts +0 -6
  52. package/dist/_internal/shared/features/brands/schema.js +0 -1
  53. package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +7 -0
  54. package/dist/_internal/shared/features/categories/bundle-schemas.js +3 -0
  55. package/dist/_internal/shared/features/orders/schema.d.ts +8 -8
  56. package/dist/_internal/shared/listing-types/art/config.d.ts +1 -1
  57. package/dist/_internal/shared/listing-types/art/config.js +1 -1
  58. package/dist/_internal/shared/listing-types/classified/config.d.ts +1 -1
  59. package/dist/_internal/shared/listing-types/classified/config.js +1 -1
  60. package/dist/_internal/shared/listing-types/digital-code/config.d.ts +1 -1
  61. package/dist/_internal/shared/listing-types/digital-code/config.js +1 -1
  62. package/dist/_internal/shared/listing-types/live/config.d.ts +1 -1
  63. package/dist/_internal/shared/listing-types/live/config.js +1 -1
  64. package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +1 -1
  65. package/dist/_internal/shared/listing-types/prize-draw/config.js +1 -1
  66. package/dist/_internal/shared/listing-types/stickers/config.d.ts +1 -1
  67. package/dist/_internal/shared/listing-types/stickers/config.js +1 -1
  68. package/dist/client.d.ts +21 -12
  69. package/dist/client.js +14 -7
  70. package/dist/constants/api-endpoints.d.ts +9 -9
  71. package/dist/constants/api-endpoints.js +3 -3
  72. package/dist/contracts/client-auth.d.ts +3 -7
  73. package/dist/contracts/email.d.ts +1 -0
  74. package/dist/features/account/components/AddressForm.js +24 -2
  75. package/dist/features/account/components/BecomeSellerView.d.ts +1 -2
  76. package/dist/features/account/components/BecomeSellerView.js +1 -1
  77. package/dist/features/account/components/NotificationBell.js +1 -1
  78. package/dist/features/account/components/UserBidsView.d.ts +1 -0
  79. package/dist/features/account/components/UserBidsView.js +47 -0
  80. package/dist/features/account/components/UserOrdersView.d.ts +4 -11
  81. package/dist/features/account/components/UserOrdersView.js +54 -4
  82. package/dist/features/account/components/UserReturnsView.d.ts +4 -9
  83. package/dist/features/account/components/UserReturnsView.js +37 -3
  84. package/dist/features/account/components/index.d.ts +3 -2
  85. package/dist/features/account/components/index.js +1 -0
  86. package/dist/features/admin/actions/admin-actions.js +22 -0
  87. package/dist/features/admin/actions/admin-coupon-actions.js +10 -0
  88. package/dist/features/admin/actions/notification-actions.js +4 -3
  89. package/dist/features/admin/components/AdminAdsView.d.ts +2 -3
  90. package/dist/features/admin/components/AdminAdsView.js +86 -89
  91. package/dist/features/admin/components/AdminAllEventEntriesView.js +18 -3
  92. package/dist/features/admin/components/AdminAuditLogView.d.ts +11 -0
  93. package/dist/features/admin/components/AdminAuditLogView.js +95 -0
  94. package/dist/features/admin/components/AdminBlogEditorView.js +37 -3
  95. package/dist/features/admin/components/AdminBrandEditorView.js +10 -6
  96. package/dist/features/admin/components/AdminBundleEditorView.js +18 -2
  97. package/dist/features/admin/components/AdminCarouselEditorView.js +2 -2
  98. package/dist/features/admin/components/AdminCarouselGroupEditorView.js +2 -2
  99. package/dist/features/admin/components/AdminCartsView.js +34 -4
  100. package/dist/features/admin/components/AdminCategoryEditorView.js +5 -4
  101. package/dist/features/admin/components/AdminCouponEditorView.js +2 -2
  102. package/dist/features/admin/components/AdminFaqEditorView.js +2 -2
  103. package/dist/features/admin/components/AdminHistoryView.js +11 -1
  104. package/dist/features/admin/components/AdminNotificationsView.js +27 -1
  105. package/dist/features/admin/components/AdminOrderEditorView.d.ts +10 -1
  106. package/dist/features/admin/components/AdminOrderEditorView.js +4 -3
  107. package/dist/features/admin/components/AdminOrdersView.js +92 -24
  108. package/dist/features/admin/components/AdminPayoutMarkPaidModal.d.ts +7 -0
  109. package/dist/features/admin/components/AdminPayoutMarkPaidModal.js +47 -0
  110. package/dist/features/admin/components/AdminPayoutsView.js +15 -31
  111. package/dist/features/admin/components/AdminProductEditorView.js +26 -3
  112. package/dist/features/admin/components/AdminSiteSettingsView.js +31 -4
  113. package/dist/features/admin/components/AdminStoreAddressesView.js +22 -2
  114. package/dist/features/admin/components/AdminStoresView.js +7 -0
  115. package/dist/features/admin/components/AdminSublistingCategoryEditorView.js +2 -2
  116. package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +2 -2
  117. package/dist/features/admin/components/AdminUserEditorView.d.ts +2 -2
  118. package/dist/features/admin/components/AdminUserEditorView.js +4 -2
  119. package/dist/features/admin/components/AdminUsersView.js +1 -1
  120. package/dist/features/admin/components/AdminWishlistsView.js +14 -1
  121. package/dist/features/admin/components/DataListingView.d.ts +2 -2
  122. package/dist/features/admin/components/ViewAuditLogEntryModal.d.ts +19 -0
  123. package/dist/features/admin/components/ViewAuditLogEntryModal.js +22 -0
  124. package/dist/features/admin/components/ViewNotificationModal.d.ts +21 -0
  125. package/dist/features/admin/components/ViewNotificationModal.js +15 -0
  126. package/dist/features/admin/components/analytics/AdminPageViewsReportView.d.ts +4 -7
  127. package/dist/features/admin/components/analytics/AdminPageViewsReportView.js +56 -36
  128. package/dist/features/admin/components/index.d.ts +8 -1
  129. package/dist/features/admin/components/index.js +4 -0
  130. package/dist/features/admin/constants/filter-tabs.d.ts +49 -0
  131. package/dist/features/admin/constants/filter-tabs.js +27 -0
  132. package/dist/features/admin/hooks/useAdminListing.d.ts +6 -0
  133. package/dist/features/admin/hooks/useAdminListing.js +3 -1
  134. package/dist/features/admin/hooks/useAdminListingData.d.ts +9 -1
  135. package/dist/features/admin/hooks/useAdminListingData.js +9 -2
  136. package/dist/features/admin/repository/site-settings.repository.d.ts +5 -0
  137. package/dist/features/admin/schemas/firestore.d.ts +21 -0
  138. package/dist/features/admin/schemas/firestore.js +6 -0
  139. package/dist/features/analytics/types.d.ts +1 -1
  140. package/dist/features/analytics/types.js +8 -0
  141. package/dist/features/auctions/actions/bid-actions.js +4 -1
  142. package/dist/features/auctions/components/AuctionBottomActions.d.ts +2 -1
  143. package/dist/features/auctions/components/AuctionBottomActions.js +14 -1
  144. package/dist/features/auctions/components/AuctionDetailPageView.js +21 -9
  145. package/dist/features/auctions/components/LiveMinIncrement.d.ts +18 -0
  146. package/dist/features/auctions/components/LiveMinIncrement.js +17 -0
  147. package/dist/features/auctions/components/PlaceBidFormClient.d.ts +5 -2
  148. package/dist/features/auctions/components/PlaceBidFormClient.js +7 -3
  149. package/dist/features/auctions/schemas/index.d.ts +5 -0
  150. package/dist/features/audit-log/repository/audit-log.repository.d.ts +45 -0
  151. package/dist/features/audit-log/repository/audit-log.repository.js +30 -0
  152. package/dist/features/audit-log/schemas/firestore.d.ts +59 -0
  153. package/dist/features/audit-log/schemas/firestore.js +35 -0
  154. package/dist/features/auth/actions/index.d.ts +0 -1
  155. package/dist/features/auth/actions/index.js +0 -1
  156. package/dist/features/auth/hooks/useAuth.d.ts +8 -35
  157. package/dist/features/auth/hooks/useAuth.js +21 -37
  158. package/dist/features/auth/permissions/constants.d.ts +1 -1
  159. package/dist/features/auth/permissions/constants.js +2 -0
  160. package/dist/features/blog/schemas/index.d.ts +32 -0
  161. package/dist/features/catalogue/components/AdminCatalogueApprovalsView.js +31 -3
  162. package/dist/features/catalogue/components/CatalogueItemEditorView.js +2 -1
  163. package/dist/features/catalogue/components/PublicCatalogueItemDetailView.d.ts +11 -0
  164. package/dist/features/catalogue/components/PublicCatalogueItemDetailView.js +33 -0
  165. package/dist/features/catalogue/components/PublicCatalogueView.js +2 -1
  166. package/dist/features/catalogue/index.d.ts +2 -0
  167. package/dist/features/catalogue/index.js +1 -0
  168. package/dist/features/categories/components/BrandDetailPageView.js +14 -12
  169. package/dist/features/categories/components/BundleDetailView.d.ts +3 -1
  170. package/dist/features/categories/components/BundleDetailView.js +3 -2
  171. package/dist/features/categories/components/CategoryDetailPageView.js +7 -3
  172. package/dist/features/categories/components/CategoryHighlightsAndFaqSection.d.ts +14 -0
  173. package/dist/features/categories/components/CategoryHighlightsAndFaqSection.js +22 -0
  174. package/dist/features/categories/components/CategoryProductsView.d.ts +1 -5
  175. package/dist/features/categories/components/CategoryProductsView.js +1 -1
  176. package/dist/features/categories/components/CategorySelectorCreate.js +16 -2
  177. package/dist/features/categories/schemas/firestore.d.ts +19 -2
  178. package/dist/features/categories/schemas/index.d.ts +24 -3
  179. package/dist/features/categories/schemas/index.js +3 -1
  180. package/dist/features/categories/types/index.d.ts +7 -0
  181. package/dist/features/checkout/actions/checkout-value-otp-actions.d.ts +17 -3
  182. package/dist/features/checkout/actions/checkout-value-otp-actions.js +101 -22
  183. package/dist/features/classified/components/ClassifiedContactSellerPanel.d.ts +12 -0
  184. package/dist/features/classified/components/ClassifiedContactSellerPanel.js +49 -0
  185. package/dist/features/classified/components/ClassifiedDetailPageView.d.ts +7 -0
  186. package/dist/features/classified/components/ClassifiedDetailPageView.js +69 -0
  187. package/dist/features/contact/components/ContactForm.js +17 -4
  188. package/dist/features/contact/components/ContactPageView.js +8 -2
  189. package/dist/features/contact/email.d.ts +1 -0
  190. package/dist/features/contact/email.js +3 -0
  191. package/dist/features/digital-codes/components/DigitalCodeDetailPageView.d.ts +19 -0
  192. package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +79 -0
  193. package/dist/features/events/components/AdminEventEditorView.js +54 -2
  194. package/dist/features/events/components/AdminEventEntriesView.d.ts +2 -16
  195. package/dist/features/events/components/AdminEventEntriesView.js +56 -89
  196. package/dist/features/events/components/EventFormDrawer.js +5 -1
  197. package/dist/features/events/components/EventRaffleEntryForm.d.ts +1 -3
  198. package/dist/features/events/components/EventRaffleEntryForm.js +1 -1
  199. package/dist/features/events/schemas/index.d.ts +22 -0
  200. package/dist/features/grouped/components/GroupedListingsCarousel.d.ts +13 -0
  201. package/dist/features/grouped/components/GroupedListingsCarousel.js +31 -0
  202. package/dist/features/grouped/repository/grouped-listings.repository.d.ts +12 -0
  203. package/dist/features/grouped/repository/grouped-listings.repository.js +34 -0
  204. package/dist/features/homepage/components/CharacterHotspotForm.js +202 -187
  205. package/dist/features/homepage/components/SectionCarousel.d.ts +1 -7
  206. package/dist/features/homepage/components/SectionCarousel.js +1 -1
  207. package/dist/features/layout/BottomActions.js +4 -3
  208. package/dist/features/layout/BottomActionsContext.d.ts +10 -0
  209. package/dist/features/layout/BottomActionsContext.js +5 -1
  210. package/dist/features/layout/TitleBarLayout.d.ts +1 -1
  211. package/dist/features/layout/TitleBarLayout.js +3 -3
  212. package/dist/features/layout/hooks/useBottomActions.d.ts +2 -0
  213. package/dist/features/layout/hooks/useBottomActions.js +4 -1
  214. package/dist/features/live/components/LiveItemDetailPageView.d.ts +9 -0
  215. package/dist/features/live/components/LiveItemDetailPageView.js +74 -0
  216. package/dist/features/media/MediaImage.js +39 -3
  217. package/dist/features/media/MediaVideo.js +17 -1
  218. package/dist/features/media/types/index.d.ts +10 -0
  219. package/dist/features/media/types/index.js +1 -0
  220. package/dist/features/media/upload/MediaUploadField.d.ts +7 -1
  221. package/dist/features/media/upload/MediaUploadField.js +11 -7
  222. package/dist/features/media/upload/video-poster.d.ts +2 -0
  223. package/dist/features/media/upload/video-poster.js +16 -1
  224. package/dist/features/media/upload/video-poster.test.js +1 -1
  225. package/dist/features/orders/components/OrderStatusTimeline.d.ts +12 -0
  226. package/dist/features/orders/components/OrderStatusTimeline.js +55 -0
  227. package/dist/features/orders/components/index.d.ts +2 -0
  228. package/dist/features/orders/components/index.js +1 -0
  229. package/dist/features/orders/constants/payment-window.d.ts +25 -0
  230. package/dist/features/orders/constants/payment-window.js +25 -0
  231. package/dist/features/orders/repository/orders.repository.d.ts +32 -0
  232. package/dist/features/orders/repository/orders.repository.js +56 -0
  233. package/dist/features/orders/schemas/index.d.ts +24 -24
  234. package/dist/features/orders/types/index.d.ts +33 -0
  235. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +9 -1
  236. package/dist/features/pre-orders/schemas/index.d.ts +5 -0
  237. package/dist/features/products/components/BidHistory.js +9 -1
  238. package/dist/features/products/components/GroupSettingsPanel.js +25 -3
  239. package/dist/features/products/components/PrizeDrawDetailPageView.js +11 -1
  240. package/dist/features/products/components/PrizeDrawEntryActions.d.ts +1 -4
  241. package/dist/features/products/components/PrizeDrawEntryActions.js +1 -1
  242. package/dist/features/products/components/ProductDetailActions.d.ts +1 -2
  243. package/dist/features/products/components/ProductDetailActions.js +1 -1
  244. package/dist/features/products/components/ProductDetailPageView.js +11 -116
  245. package/dist/features/products/components/ProductGrid.js +15 -1
  246. package/dist/features/products/components/RelatedItemsSection.d.ts +16 -0
  247. package/dist/features/products/components/RelatedItemsSection.js +17 -0
  248. package/dist/features/products/constants/action-defs.d.ts +1 -0
  249. package/dist/features/products/constants/action-defs.js +1 -0
  250. package/dist/features/products/schemas/index.d.ts +5 -0
  251. package/dist/features/promotions/components/CouponsIndexListing.d.ts +1 -3
  252. package/dist/features/promotions/components/CouponsIndexListing.js +1 -1
  253. package/dist/features/search/components/SearchView.d.ts +1 -3
  254. package/dist/features/search/components/SearchView.js +1 -1
  255. package/dist/features/seller/components/QuickProductForm.js +2 -1
  256. package/dist/features/seller/components/SellerBidsView.js +66 -107
  257. package/dist/features/seller/components/SellerGoogleReviewsView.js +17 -1
  258. package/dist/features/seller/components/SellerOrdersView.d.ts +15 -3
  259. package/dist/features/seller/components/SellerOrdersView.js +134 -163
  260. package/dist/features/seller/components/SellerPayoutMethodsView.js +60 -48
  261. package/dist/features/seller/components/SellerPayoutSettingsView.js +69 -4
  262. package/dist/features/seller/components/SellerPayoutsView.d.ts +12 -0
  263. package/dist/features/seller/components/SellerPayoutsView.js +25 -5
  264. package/dist/features/seller/components/SellerProductShell.d.ts +10 -3
  265. package/dist/features/seller/components/SellerProductShell.js +90 -37
  266. package/dist/features/seller/components/SellerProductsFilterDrawer.d.ts +2 -7
  267. package/dist/features/seller/components/SellerProductsFilterDrawer.js +4 -4
  268. package/dist/features/seller/components/SellerProductsView.d.ts +2 -4
  269. package/dist/features/seller/components/SellerProductsView.js +131 -189
  270. package/dist/features/seller/components/SellerReviewsView.js +95 -133
  271. package/dist/features/seller/components/SellerShippingConfigsView.js +47 -67
  272. package/dist/features/seller/components/SellerShippingView.js +41 -4
  273. package/dist/features/seller/components/SellerStoreCategoriesView.js +51 -59
  274. package/dist/features/seller/components/SellerStorefrontView.d.ts +6 -1
  275. package/dist/features/seller/components/SellerStorefrontView.js +42 -5
  276. package/dist/features/seller/components/index.d.ts +2 -2
  277. package/dist/features/seller/components/index.js +2 -2
  278. package/dist/features/shell/FormShell.d.ts +24 -4
  279. package/dist/features/shell/FormShell.js +12 -6
  280. package/dist/features/shell/QuickFormDrawer.js +67 -12
  281. package/dist/features/shell/StepForm.d.ts +30 -1
  282. package/dist/features/shell/StepForm.js +47 -4
  283. package/dist/features/shell/index.d.ts +1 -1
  284. package/dist/features/shell/index.js +1 -1
  285. package/dist/features/shipments/components/AdminShipmentEditorView.js +2 -2
  286. package/dist/features/shipments/schemas/validation.d.ts +14 -4
  287. package/dist/features/tester/components/AdminTesterFeedbackListView.js +23 -2
  288. package/dist/features/tester/components/TesterChecklistStepRow.js +1 -1
  289. package/dist/features/tester/components/TesterHubView.js +3 -2
  290. package/dist/features/tester/seed-data/orders-tester-seed-data.js +9 -1
  291. package/dist/features/tester/seed-data/products-tester-seed-data.js +43 -32
  292. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +487 -18
  293. package/dist/index.d.ts +17 -3
  294. package/dist/index.js +23 -5
  295. package/dist/next/routing/route-map.d.ts +13 -0
  296. package/dist/next/routing/route-map.js +12 -0
  297. package/dist/providers/email-resend/provider.js +1 -0
  298. package/dist/providers/firebase-client/auth.d.ts +1 -0
  299. package/dist/providers/firebase-client/auth.js +7 -1
  300. package/dist/repositories/index.d.ts +1 -0
  301. package/dist/repositories/index.js +1 -0
  302. package/dist/schemas/registry.d.ts +61 -25
  303. package/dist/security/pii-mask.js +1 -1
  304. package/dist/seed/bids-seed-data.js +48 -3
  305. package/dist/seed/categories-seed-data.js +69 -0
  306. package/dist/seed/grouped-listings-seed-data.js +167 -0
  307. package/dist/seed/payouts-seed-data.js +4 -4
  308. package/dist/seed/products-art-seed-data.js +188 -5
  309. package/dist/seed/products-auctions-seed-data.js +226 -6
  310. package/dist/seed/products-classifieds-seed-data.js +255 -8
  311. package/dist/seed/products-digital-codes-seed-data.js +258 -19
  312. package/dist/seed/products-live-items-seed-data.js +143 -10
  313. package/dist/seed/products-preorders-seed-data.js +213 -8
  314. package/dist/seed/products-prize-draws-seed-data.js +198 -0
  315. package/dist/seed/products-standard-seed-data.js +234 -4
  316. package/dist/seed/products-stickers-seed-data.js +178 -5
  317. package/dist/seed/site-settings-seed-data.js +23 -30
  318. package/dist/seed/store-extensions-seed-data.js +2 -2
  319. package/dist/server-entry.d.ts +6 -2
  320. package/dist/server-entry.js +24 -3
  321. package/dist/server.d.ts +10 -3
  322. package/dist/server.js +11 -4
  323. package/dist/styles.css +29 -1
  324. package/dist/tailwind-utilities.css +1 -1
  325. package/dist/ui/components/Form.d.ts +11 -2
  326. package/dist/ui/components/Form.js +4 -3
  327. package/dist/ui/components/FormField.d.ts +3 -1
  328. package/dist/ui/components/FormField.js +22 -4
  329. package/dist/ui/components/ImageLightbox.js +37 -3
  330. package/dist/ui/components/ImageLightbox.style.css +28 -0
  331. package/dist/ui/components/ListingLayout.d.ts +1 -2
  332. package/dist/ui/components/ListingLayout.js +1 -1
  333. package/dist/ui/components/RecordDetailModal.d.ts +68 -0
  334. package/dist/ui/components/RecordDetailModal.js +8 -0
  335. package/dist/ui/components/SlottedListingView.js +9 -1
  336. package/dist/ui/forms/FormErrorSummary.d.ts +25 -0
  337. package/dist/ui/forms/FormErrorSummary.js +37 -0
  338. package/dist/ui/forms/FormShell.d.ts +37 -2
  339. package/dist/ui/forms/FormShell.js +37 -7
  340. package/dist/ui/forms/FormShell.style.css +17 -0
  341. package/dist/ui/forms/index.d.ts +2 -0
  342. package/dist/ui/forms/index.js +1 -0
  343. package/dist/ui/index.d.ts +4 -0
  344. package/dist/ui/index.js +5 -0
  345. package/dist/utils/media-url.d.ts +12 -1
  346. package/dist/utils/media-url.js +59 -1
  347. package/dist/validation/schemas.d.ts +4 -4
  348. package/package.json +1 -1
  349. package/dist/_internal/client/features/classified/ClassifiedDetailView.d.ts +0 -9
  350. package/dist/_internal/client/features/classified/ClassifiedDetailView.js +0 -55
  351. package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.d.ts +0 -18
  352. package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.js +0 -21
  353. package/dist/_internal/client/features/live/LiveItemDetailView.d.ts +0 -9
  354. package/dist/_internal/client/features/live/LiveItemDetailView.js +0 -25
  355. package/dist/_internal/server/jobs/core/prizeRevealClose.d.ts +0 -2
  356. package/dist/_internal/server/jobs/core/prizeRevealClose.js +0 -28
  357. package/dist/_internal/server/jobs/core/prizeRevealExpiry.d.ts +0 -2
  358. package/dist/_internal/server/jobs/core/prizeRevealExpiry.js +0 -61
  359. package/dist/_internal/server/jobs/core/prizeRevealOpen.d.ts +0 -2
  360. package/dist/_internal/server/jobs/core/prizeRevealOpen.js +0 -68
  361. package/dist/_internal/server/jobs/core/prizeRevealReminder.d.ts +0 -2
  362. package/dist/_internal/server/jobs/core/prizeRevealReminder.js +0 -49
  363. package/dist/_internal/server/jobs/handlers/prizeRevealClose.d.ts +0 -2
  364. package/dist/_internal/server/jobs/handlers/prizeRevealClose.js +0 -2
  365. package/dist/_internal/server/jobs/handlers/prizeRevealExpiry.d.ts +0 -2
  366. package/dist/_internal/server/jobs/handlers/prizeRevealExpiry.js +0 -2
  367. package/dist/_internal/server/jobs/handlers/prizeRevealOpen.d.ts +0 -2
  368. package/dist/_internal/server/jobs/handlers/prizeRevealOpen.js +0 -2
  369. package/dist/_internal/server/jobs/handlers/prizeRevealReminder.d.ts +0 -2
  370. package/dist/_internal/server/jobs/handlers/prizeRevealReminder.js +0 -2
  371. package/dist/features/auth/consent-otp.d.ts +0 -57
  372. package/dist/features/auth/consent-otp.js +0 -127
  373. package/dist/features/cart/components/CheckoutOtpModal.d.ts +0 -15
  374. package/dist/features/cart/components/CheckoutOtpModal.js +0 -12
  375. package/dist/features/checkout/actions/checkout-actions.d.ts +0 -31
  376. package/dist/features/checkout/actions/checkout-actions.js +0 -124
  377. package/dist/features/classified/components/ClassifiedIndexListing.d.ts +0 -5
  378. package/dist/features/classified/components/ClassifiedIndexListing.js +0 -123
  379. package/dist/features/classified/components/ClassifiedListView.d.ts +0 -6
  380. package/dist/features/classified/components/ClassifiedListView.js +0 -44
  381. package/dist/features/digital-codes/components/DigitalCodesIndexListing.d.ts +0 -5
  382. package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +0 -114
  383. package/dist/features/digital-codes/components/DigitalCodesListView.d.ts +0 -6
  384. package/dist/features/digital-codes/components/DigitalCodesListView.js +0 -38
  385. package/dist/features/live/components/LiveItemsIndexListing.d.ts +0 -5
  386. package/dist/features/live/components/LiveItemsIndexListing.js +0 -115
  387. package/dist/features/live/components/LiveItemsListView.d.ts +0 -6
  388. package/dist/features/live/components/LiveItemsListView.js +0 -44
  389. package/dist/features/seller/components/SellerTemplatesView.d.ts +0 -12
  390. package/dist/features/seller/components/SellerTemplatesView.js +0 -276
  391. package/dist/react/hooks/useVisibleItems.d.ts +0 -37
  392. package/dist/react/hooks/useVisibleItems.js +0 -59
  393. package/dist/ui/components/TabStrip.d.ts +0 -34
  394. package/dist/ui/components/TabStrip.js +0 -56
  395. package/dist/ui/components/TabStrip.style.css +0 -97
@@ -16,7 +16,9 @@ import { getDefaultCurrency } from "../../../core/baseline-resolver";
16
16
  import { formatCurrency } from "../../../utils/number.formatter";
17
17
  import { normalizeRichTextHtml } from "../../../utils/string.formatter";
18
18
  import { safeDisplayName } from "../../../security";
19
- import { Button, Container, Div, Heading, Input, Main, Nav, RichText, Row, Section, Span, Stack, Text, Ul, Li, Dl, Dt, Dd, } from "../../../ui";
19
+ import { getSiteSettingsGlobal } from "../../admin/utils/getSiteSettingsGlobal";
20
+ import { resolveMinBidIncrement, } from "../../../_internal/shared/features/auctions/config";
21
+ import { Button, Container, CountdownDisplay, Div, Heading, Input, Main, Nav, RichText, Row, Section, Span, Stack, Text, Ul, Li, Dl, Dt, Dd, } from "../../../ui";
20
22
  import { AuctionDetailView } from "../../products/components/AuctionDetailView";
21
23
  import { ProductTabsShell } from "../../products/components/ProductTabsShell";
22
24
  import { CustomSectionTabContent } from "../../products/components/CustomSectionTabContent";
@@ -32,6 +34,11 @@ import { listReviewsBySeller } from "../../reviews/actions/review-actions";
32
34
  import { PlaceBidModalButton } from "./PlaceBidFormClient";
33
35
  import { CollapsibleBidHistory } from "./CollapsibleBidHistory";
34
36
  import { LiveBidPrice } from "./LiveBidPrice";
37
+ import { LiveMinIncrement } from "./LiveMinIncrement";
38
+ import { RelatedItemsSection } from "../../products/components/RelatedItemsSection";
39
+ import { computeRelatedItems } from "../../../_internal/server/features/products/data";
40
+ import { GroupedListingsCarousel } from "../../grouped/components/GroupedListingsCarousel";
41
+ import { getGroupsWithItemsForProduct } from "../../../_internal/server/features/grouped/data";
35
42
  import { SublistingCarouselSection } from "../../products/components/SublistingCarouselSection";
36
43
  function toDescriptionHtml(raw) {
37
44
  if (!raw)
@@ -41,7 +48,7 @@ function toDescriptionHtml(raw) {
41
48
  }
42
49
  function renderAuctionInfoPanel(props) {
43
50
  const { productId, title, currentBid, currency, bidCount, isEnded, endDate, buyNowPrice, featured, freeShipping, condition, category, categoryName, brand, brandSlug, productFeatures, features, descriptionHtml, safeSeller, storeHref } = props;
44
- return (_jsxs(Stack, { gap: "md", children: [_jsxs(Div, { children: [_jsxs(Row, { gap: "xs", wrap: true, className: "mb-2", children: [_jsx(Span, { size: "xs", weight: "semibold", className: CLS_LIVE_BADGE, children: "\uD83C\uDFF7\uFE0F Live Auction" }), isEnded ? (_jsx(Span, { color: "error", surface: "danger-surface", size: "xs", weight: "medium", className: "inline-block", padding: "pill-sm", rounded: "full", children: "Ended" })) : (_jsx(Span, { color: "success", surface: "success-surface", size: "xs", weight: "medium", className: "inline-block", padding: "pill-sm", rounded: "full", children: "Active" }))] }), _jsx(Heading, { level: 1, className: "leading-snug", smSize: "2xl", color: "primary", size: "xl", weight: "bold", children: title })] }), _jsxs(Div, { children: [_jsx(Text, { className: "mb-0.5", color: "muted", size: "xs", children: "Current bid" }), _jsx(LiveBidPrice, { productId: productId, currentBid: currentBid, bidCount: bidCount, currency: currency, isEnded: isEnded, priceSize: "2xl", badgeSize: "sm" }), endDate && _jsxs(Text, { className: "mt-1.5", color: "muted", size: "sm", children: [isEnded ? "Ended" : "Ends", " ", _jsx(Span, { weight: "medium", color: "muted", children: endDate.toLocaleString() })] })] }), buyNowPrice !== null && !isEnded && (_jsxs(Row, { align: "center", gap: "sm", className: "border border-[var(--appkit-color-primary-200)] dark:border-[var(--appkit-color-primary-800)] bg-primary-50 dark:bg-primary-900/20", padding: "inlineSm", rounded: "lg", children: [_jsx(Span, { size: "xs", color: "muted", children: "Buy Now:" }), _jsx(Span, { size: "base", weight: "bold", className: "text-primary-700 dark:text-primary-300", children: formatCurrency(buyNowPrice, currency) })] })), _jsx(ProductFeatureBadges, { featured: featured, freeShipping: freeShipping, condition: condition ?? undefined, labels: { featured: "Featured", fasterDelivery: "Faster Delivery", ratedSeller: "Rated Seller", condition: "Condition", conditionNew: "New", conditionUsed: "Used", conditionBroken: "For Parts", conditionRefurbished: "Refurbished", returnable: "Returnable", freeShipping: "Free Shipping", codAvailable: "Cash on Delivery", emiAvailable: "EMI Available", wishlistCount: (n) => `${n} wishlisted`, categoryProductCount: (n, cat) => `${n} in ${cat}` } }), (categoryName || category || brand) && (_jsxs(Row, { gap: "sm", wrap: true, children: [category && _jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(category)), className: "inline-flex items-center rounded-full border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-[var(--appkit-space-2-5)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)] font-medium text-[var(--appkit-color-text-muted)] transition-colors hover:border-primary-300 hover:bg-primary-50 hover:text-primary-700 dark:hover:border-primary-700/60 dark:hover:bg-primary-900/20 dark:hover:text-primary-400", children: categoryName || category }), !category && categoryName && _jsx(Span, { layout: "inline-flex", size: "xs", weight: "medium", border: "subtle", rounded: "full", padding: "pill-sm-tall", surface: "muted", color: "muted", children: categoryName }), brand && brandSlug && _jsx(Link, { href: String(ROUTES.PUBLIC.BRAND_DETAIL(brandSlug)), className: "inline-flex items-center rounded-full border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-[var(--appkit-space-2-5)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)] font-medium text-[var(--appkit-color-text-muted)] transition-colors hover:border-primary-300 hover:bg-primary-50 hover:text-primary-700 dark:hover:border-primary-700/60 dark:hover:bg-primary-900/20 dark:hover:text-primary-400", children: brand }), brand && !brandSlug && _jsx(Span, { layout: "inline-flex", size: "xs", weight: "medium", border: "subtle", rounded: "full", padding: "pill-sm-tall", surface: "muted", color: "muted", children: brand })] })), productFeatures && features.length > 0 && _jsx(FeatureBadgeList, { productFeatureIds: features, features: productFeatures }), !productFeatures && features.length > 0 && (_jsxs(Div, { border: "subtle", surface: "muted", padding: "inline", rounded: "xl", children: [_jsx(Text, { className: "mb-2 tracking-wide", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: "About this item" }), _jsx(Ul, { spacing: "comfortable", size: "sm", color: "primary", children: features.map((f, i) => _jsxs(Li, { layout: "flex-start", gap: "2", children: [_jsx(Span, { className: "mt-0.5 flex-shrink-0 text-primary-500", children: "\u2022" }), f] }, i)) })] })), descriptionHtml && _jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "text-[length:var(--appkit-text-sm)] leading-relaxed text-[var(--appkit-color-text-muted)] line-clamp-4" }), safeSeller && (_jsx(Div, { className: `${__P.p3}`, border: "subtle", rounded: "xl", surface: "muted", children: _jsxs(Row, { justify: "between", align: "center", children: [_jsxs(Div, { children: [_jsx(Text, { className: "text-[10px] tracking-wide mb-0.5", color: "faint", transform: "uppercase", children: "Listed by" }), _jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: safeSeller })] }), storeHref && _jsx(Link, { href: storeHref, className: "shrink-0 rounded-lg bg-primary/10 dark:bg-primary/20 px-[var(--appkit-space-3)] py-[var(--appkit-space-1-5)] text-[length:var(--appkit-text-xs)] font-semibold text-primary-700 dark:text-primary-300 hover:bg-primary/20 dark:hover:bg-primary/30 transition-colors", children: "Visit Store \u2192" })] }) }))] }));
51
+ return (_jsxs(Stack, { gap: "md", children: [_jsxs(Div, { children: [_jsxs(Row, { gap: "xs", wrap: true, className: "mb-2", children: [_jsx(Span, { size: "xs", weight: "semibold", className: CLS_LIVE_BADGE, children: "\uD83C\uDFF7\uFE0F Live Auction" }), isEnded ? (_jsx(Span, { color: "error", surface: "danger-surface", size: "xs", weight: "medium", className: "inline-block", padding: "pill-sm", rounded: "full", children: "Ended" })) : (_jsx(Span, { color: "success", surface: "success-surface", size: "xs", weight: "medium", className: "inline-block", padding: "pill-sm", rounded: "full", children: "Active" }))] }), _jsx(Heading, { level: 1, className: "leading-snug", smSize: "2xl", color: "primary", size: "xl", weight: "bold", children: title })] }), _jsxs(Div, { children: [_jsx(Text, { className: "mb-0.5", color: "muted", size: "xs", children: "Current bid" }), _jsx(LiveBidPrice, { productId: productId, currentBid: currentBid, bidCount: bidCount, currency: currency, isEnded: isEnded, priceSize: "2xl", badgeSize: "sm" }), endDate && !isEnded && (_jsxs(Text, { className: "mt-1.5", color: "muted", size: "sm", children: ["Ends in ", _jsx(Span, { weight: "medium", color: "muted", children: _jsx(CountdownDisplay, { targetDate: endDate, format: "auto", expiredLabel: "Ended" }) })] })), endDate && _jsxs(Text, { className: "mt-0.5", color: "faint", size: "xs", children: [isEnded ? "Ended" : "Ends", " ", endDate.toLocaleString()] })] }), buyNowPrice !== null && !isEnded && (_jsxs(Row, { align: "center", gap: "sm", className: "border border-[var(--appkit-color-primary-200)] dark:border-[var(--appkit-color-primary-800)] bg-primary-50 dark:bg-primary-900/20", padding: "inlineSm", rounded: "lg", children: [_jsx(Span, { size: "xs", color: "muted", children: "Buy Now:" }), _jsx(Span, { size: "base", weight: "bold", className: "text-primary-700 dark:text-primary-300", children: formatCurrency(buyNowPrice, currency) })] })), _jsx(ProductFeatureBadges, { featured: featured, freeShipping: freeShipping, condition: condition ?? undefined, labels: { featured: "Featured", fasterDelivery: "Faster Delivery", ratedSeller: "Rated Seller", condition: "Condition", conditionNew: "New", conditionUsed: "Used", conditionBroken: "For Parts", conditionRefurbished: "Refurbished", returnable: "Returnable", freeShipping: "Free Shipping", codAvailable: "Cash on Delivery", emiAvailable: "EMI Available", wishlistCount: (n) => `${n} wishlisted`, categoryProductCount: (n, cat) => `${n} in ${cat}` } }), (categoryName || category || brand) && (_jsxs(Row, { gap: "sm", wrap: true, children: [category && _jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(category)), className: "inline-flex items-center rounded-full border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-[var(--appkit-space-2-5)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)] font-medium text-[var(--appkit-color-text-muted)] transition-colors hover:border-primary-300 hover:bg-primary-50 hover:text-primary-700 dark:hover:border-primary-700/60 dark:hover:bg-primary-900/20 dark:hover:text-primary-400", children: categoryName || category }), !category && categoryName && _jsx(Span, { layout: "inline-flex", size: "xs", weight: "medium", border: "subtle", rounded: "full", padding: "pill-sm-tall", surface: "muted", color: "muted", children: categoryName }), brand && brandSlug && _jsx(Link, { href: String(ROUTES.PUBLIC.BRAND_DETAIL(brandSlug)), className: "inline-flex items-center rounded-full border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-[var(--appkit-space-2-5)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)] font-medium text-[var(--appkit-color-text-muted)] transition-colors hover:border-primary-300 hover:bg-primary-50 hover:text-primary-700 dark:hover:border-primary-700/60 dark:hover:bg-primary-900/20 dark:hover:text-primary-400", children: brand }), brand && !brandSlug && _jsx(Span, { layout: "inline-flex", size: "xs", weight: "medium", border: "subtle", rounded: "full", padding: "pill-sm-tall", surface: "muted", color: "muted", children: brand })] })), productFeatures && features.length > 0 && _jsx(FeatureBadgeList, { productFeatureIds: features, features: productFeatures }), !productFeatures && features.length > 0 && (_jsxs(Div, { border: "subtle", surface: "muted", padding: "inline", rounded: "xl", children: [_jsx(Text, { className: "mb-2 tracking-wide", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: "About this item" }), _jsx(Ul, { spacing: "comfortable", size: "sm", color: "primary", children: features.map((f, i) => _jsxs(Li, { layout: "flex-start", gap: "2", children: [_jsx(Span, { className: "mt-0.5 flex-shrink-0 text-primary-500", children: "\u2022" }), f] }, i)) })] })), descriptionHtml && _jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "text-[length:var(--appkit-text-sm)] leading-relaxed text-[var(--appkit-color-text-muted)] line-clamp-4" }), safeSeller && (_jsx(Div, { className: `${__P.p3}`, border: "subtle", rounded: "xl", surface: "muted", children: _jsxs(Row, { justify: "between", align: "center", children: [_jsxs(Div, { children: [_jsx(Text, { className: "text-[10px] tracking-wide mb-0.5", color: "faint", transform: "uppercase", children: "Listed by" }), _jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: safeSeller })] }), storeHref && _jsx(Link, { href: storeHref, className: "shrink-0 rounded-lg bg-primary/10 dark:bg-primary/20 px-[var(--appkit-space-3)] py-[var(--appkit-space-1-5)] text-[length:var(--appkit-text-xs)] font-semibold text-primary-700 dark:text-primary-300 hover:bg-primary/20 dark:hover:bg-primary/30 transition-colors", children: "Visit Store \u2192" })] }) }))] }));
45
52
  }
46
53
  function renderAuctionStoreReviews(storeReviews) {
47
54
  if (storeReviews.length === 0)
@@ -78,7 +85,7 @@ export async function AuctionDetailPageView({ id, initialAuction, onPlaceBid, on
78
85
  : typeof p.price === "number"
79
86
  ? p.price
80
87
  : 0;
81
- const minBidIncrement = typeof p.minBidIncrement === "number" ? p.minBidIncrement : 1;
88
+ const minBidIncrementOverride = typeof p.minBidIncrement === "number" ? p.minBidIncrement : undefined;
82
89
  const images = Array.isArray(p.images)
83
90
  ? p.images
84
91
  : typeof p.mainImage === "string"
@@ -117,6 +124,13 @@ export async function AuctionDetailPageView({ id, initialAuction, onPlaceBid, on
117
124
  const relatedDocs = await productRepository
118
125
  .findByCategory(String(p.category ?? ""))
119
126
  .catch(() => []);
127
+ const [{ relatedItems, relatedByBrand, relatedByTags, relatedByStore }, groups, siteSettings] = await Promise.all([
128
+ computeRelatedItems(product),
129
+ getGroupsWithItemsForProduct(product.id),
130
+ getSiteSettingsGlobal(),
131
+ ]);
132
+ const bidIncrementTiers = siteSettings.auctionConfig?.bidIncrementTiers ?? [];
133
+ const initialMinBidIncrement = resolveMinBidIncrement(currentBid, bidIncrementTiers, minBidIncrementOverride);
120
134
  return (_jsxs(Main, { children: [_jsx(HistoryTracker, { productId: String(p.id ?? p.slug ?? ""), productType: "auction", snapshot: {
121
135
  title: typeof p.title === "string" ? p.title : undefined,
122
136
  thumb: typeof p.mainImage === "string"
@@ -127,9 +141,9 @@ export async function AuctionDetailPageView({ id, initialAuction, onPlaceBid, on
127
141
  price: typeof p.price === "number" ? p.price : undefined,
128
142
  storeId: typeof p.storeId === "string" ? p.storeId : undefined,
129
143
  storeName: typeof p.storeName === "string" ? p.storeName : undefined,
130
- } }), _jsxs(Container, { size: "xl", padding: "y-lg", children: [_jsxs(Row, { className: "mb-4", align: "center", justify: "between", gap: "sm", wrap: true, children: [_jsxs(Nav, { "aria-label": "Breadcrumb", layout: "flex-wrap", gap: "2xs", textSize: "xs", color: "muted", children: [_jsx(Link, { href: String(ROUTES.HOME), className: CLS_BREADCRUMB_LINK, children: "Home" }), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.AUCTIONS), className: CLS_BREADCRUMB_LINK, children: "Auctions" }), category && (_jsxs(_Fragment, { children: [_jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(category)), className: CLS_BREADCRUMB_LINK, children: categoryName || category })] })), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Span, { className: "truncate max-w-[200px]", color: "muted", children: title })] }), _jsx(ShareButton, { title: title })] }), _jsx(AuctionDetailView, { renderGallery: () => (_jsx(ProductGalleryClient, { images: images, video: productVideo, productName: title })), renderInfo: () => renderAuctionInfoPanel({ productId: String(product.id), title, currentBid, currency, bidCount, isEnded, endDate, buyNowPrice, featured, freeShipping, condition, category, categoryName, brand, brandSlug, productFeatures, features, descriptionHtml, safeSeller, storeHref }), renderBidForm: () => onPlaceBid ? (_jsx(Stack, { id: "auction-bid-form", gap: "3", children: _jsxs(Stack, { className: `${__P.p5}`, border: "subtle", gap: "3", rounded: "xl", surface: "muted", children: [_jsxs(Row, { justify: "between", align: "baseline", children: [_jsx(LiveBidPrice, { productId: String(product.id), currentBid: currentBid, bidCount: bidCount, currency: currency, isEnded: isEnded, priceSize: "xl", badgeSize: "xs" }), !isEnded && (_jsxs(Span, { size: "xs", color: "muted", children: ["min increment ", formatCurrency(minBidIncrement, currency)] }))] }), _jsx(PlaceBidModalButton, { productId: String(product.id), currentBid: currentBid, startingBid: startingBid, minBidIncrement: minBidIncrement, currency: currency, isEnded: isEnded, buyNowPrice: buyNowPrice, bidsHaveStarted: bidsHaveStarted, bidCount: bidCount, tags: tags, onPlaceBid: onPlaceBid, onBuyNow: onBuyNow, triggerClassName: "w-full" })] }) })) : (
144
+ } }), _jsxs(Container, { size: "xl", padding: "y-lg", children: [_jsxs(Row, { className: "mb-4", align: "center", justify: "between", gap: "sm", wrap: true, children: [_jsxs(Nav, { "aria-label": "Breadcrumb", layout: "flex-wrap", gap: "2xs", textSize: "xs", color: "muted", children: [_jsx(Link, { href: String(ROUTES.HOME), className: CLS_BREADCRUMB_LINK, children: "Home" }), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.AUCTIONS), className: CLS_BREADCRUMB_LINK, children: "Auctions" }), category && (_jsxs(_Fragment, { children: [_jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(category)), className: CLS_BREADCRUMB_LINK, children: categoryName || category })] })), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Span, { className: "truncate max-w-[200px]", color: "muted", children: title })] }), _jsx(ShareButton, { title: title })] }), _jsx(AuctionDetailView, { renderGallery: () => (_jsx(ProductGalleryClient, { images: images, video: productVideo, productName: title })), renderInfo: () => renderAuctionInfoPanel({ productId: String(product.id), title, currentBid, currency, bidCount, isEnded, endDate, buyNowPrice, featured, freeShipping, condition, category, categoryName, brand, brandSlug, productFeatures, features, descriptionHtml, safeSeller, storeHref }), renderBidForm: () => onPlaceBid ? (_jsx(Stack, { id: "auction-bid-form", gap: "3", children: _jsxs(Stack, { className: `${__P.p5}`, border: "subtle", gap: "3", rounded: "xl", surface: "muted", children: [_jsxs(Row, { justify: "between", align: "baseline", children: [_jsx(LiveBidPrice, { productId: String(product.id), currentBid: currentBid, bidCount: bidCount, currency: currency, isEnded: isEnded, priceSize: "xl", badgeSize: "xs" }), !isEnded && (_jsx(LiveMinIncrement, { productId: String(product.id), currentBid: currentBid, bidCount: bidCount, currency: currency, isEnded: isEnded, tiers: bidIncrementTiers, minBidIncrementOverride: minBidIncrementOverride }))] }), !isEnded && endDate && (_jsxs(Text, { align: "center", size: "xs", color: "muted", children: ["Ends in ", _jsx(CountdownDisplay, { targetDate: endDate, format: "auto", expiredLabel: "Ended" })] })), _jsx(PlaceBidModalButton, { productId: String(product.id), currentBid: currentBid, startingBid: startingBid, tiers: bidIncrementTiers, minBidIncrementOverride: minBidIncrementOverride, currency: currency, isEnded: isEnded, auctionEndDate: endDate, buyNowPrice: buyNowPrice, bidsHaveStarted: bidsHaveStarted, bidCount: bidCount, tags: tags, onPlaceBid: onPlaceBid, onBuyNow: onBuyNow, triggerClassName: "w-full" })] }) })) : (
131
145
  /* Read-only bid panel — shown when no bid action is wired (preview/demo) */
132
- _jsxs(Stack, { className: `${__P.p5}`, border: "subtle", gap: "md", rounded: "xl", surface: "muted", children: [_jsx(Stack, { gap: "xs", children: _jsxs(Text, { size: "xs", color: "muted", children: ["Starting bid: ", formatCurrency(startingBid, currency), !isEnded && _jsxs(_Fragment, { children: [" \u00B7 min increment ", formatCurrency(minBidIncrement, currency)] })] }) }), _jsxs(Stack, { gap: "sm", children: [_jsx(Input, { type: "number", placeholder: `At least ${formatCurrency(currentBid + minBidIncrement, currency)}`, min: currentBid + minBidIncrement, "aria-label": "Your bid amount", disabled: isEnded }), _jsx(Button, { variant: "primary", size: "md", className: "w-full", disabled: isEnded, children: isEnded ? "Auction Ended" : "Place Bid" }), buyNowPrice !== null && !isEnded && !bidsHaveStarted && (_jsxs(Button, { variant: "secondary", size: "md", className: "w-full", disabled: true, children: ["Buy Now \u2014 ", formatCurrency(buyNowPrice, currency)] }))] }), tags.length > 0 && (_jsx(Div, { border: "default", className: "border-t", padding: "t-md", children: _jsx(Row, { wrap: true, gap: "xs", children: tags.map((tag) => (_jsx(Span, { size: "xs", rounded: "full", padding: "pill-sm-tall", surface: "subtle", color: "muted", children: tag }, tag))) }) }))] })), renderMobileBidForm: () => !isEnded && onPlaceBid ? (_jsxs(Stack, { className: `lg:hidden ${__P.p4}`, border: "subtle", gap: "3", rounded: "xl", surface: "muted", children: [_jsx(LiveBidPrice, { productId: String(product.id), currentBid: currentBid, bidCount: bidCount, currency: currency, isEnded: isEnded, priceSize: "base", badgeSize: "xs" }), _jsx(PlaceBidModalButton, { productId: String(product.id), currentBid: currentBid, startingBid: startingBid, minBidIncrement: minBidIncrement, currency: currency, isEnded: isEnded, buyNowPrice: buyNowPrice, bidsHaveStarted: bidsHaveStarted, bidCount: bidCount, tags: tags, onPlaceBid: onPlaceBid, onBuyNow: onBuyNow, triggerClassName: "w-full" })] })) : !isEnded ? (_jsxs(Div, { className: `${__P.p4} lg:hidden`, border: "subtle", rounded: "xl", surface: "muted", children: [_jsxs(Row, { align: "center", gap: "sm", className: "mb-3", children: [_jsx(Span, { size: "base", weight: "bold", className: "text-primary-600 dark:text-primary-400", children: formatCurrency(currentBid, currency) }), _jsxs(Span, { size: "xs", color: "muted", children: [bidCount, " bids"] })] }), _jsx(Button, { variant: "primary", size: "md", className: "w-full", children: "Place Bid" })] })) : null, renderSublistingSection: sublistingCategoryId
146
+ _jsxs(Stack, { className: `${__P.p5}`, border: "subtle", gap: "md", rounded: "xl", surface: "muted", children: [_jsx(Stack, { gap: "xs", children: _jsxs(Text, { size: "xs", color: "muted", children: ["Starting bid: ", formatCurrency(startingBid, currency), !isEnded && _jsxs(_Fragment, { children: [" \u00B7 min increment ", formatCurrency(initialMinBidIncrement, currency)] })] }) }), _jsxs(Stack, { gap: "sm", children: [_jsx(Input, { type: "number", placeholder: `At least ${formatCurrency(currentBid + initialMinBidIncrement, currency)}`, min: currentBid + initialMinBidIncrement, "aria-label": "Your bid amount", disabled: isEnded }), !isEnded && endDate && (_jsxs(Text, { align: "center", size: "xs", color: "muted", children: ["Ends in ", _jsx(CountdownDisplay, { targetDate: endDate, format: "auto", expiredLabel: "Ended" })] })), _jsx(Button, { variant: "primary", size: "md", className: "w-full", disabled: isEnded, children: isEnded ? "Auction Ended" : "Place Bid" }), buyNowPrice !== null && !isEnded && !bidsHaveStarted && (_jsxs(Button, { variant: "secondary", size: "md", className: "w-full", disabled: true, children: ["Buy Now \u2014 ", formatCurrency(buyNowPrice, currency)] }))] }), tags.length > 0 && (_jsx(Div, { border: "default", className: "border-t", padding: "t-md", children: _jsx(Row, { wrap: true, gap: "xs", children: tags.map((tag) => (_jsx(Span, { size: "xs", rounded: "full", padding: "pill-sm-tall", surface: "subtle", color: "muted", children: tag }, tag))) }) }))] })), renderMobileBidForm: () => !isEnded && onPlaceBid ? (_jsxs(Stack, { className: `lg:hidden ${__P.p4}`, border: "subtle", gap: "3", rounded: "xl", surface: "muted", children: [_jsx(LiveBidPrice, { productId: String(product.id), currentBid: currentBid, bidCount: bidCount, currency: currency, isEnded: isEnded, priceSize: "base", badgeSize: "xs" }), endDate && (_jsxs(Text, { align: "center", size: "xs", color: "muted", children: ["Ends in ", _jsx(CountdownDisplay, { targetDate: endDate, format: "auto", expiredLabel: "Ended" })] })), _jsx(PlaceBidModalButton, { productId: String(product.id), currentBid: currentBid, startingBid: startingBid, tiers: bidIncrementTiers, minBidIncrementOverride: minBidIncrementOverride, currency: currency, isEnded: isEnded, auctionEndDate: endDate, buyNowPrice: buyNowPrice, bidsHaveStarted: bidsHaveStarted, bidCount: bidCount, tags: tags, onPlaceBid: onPlaceBid, onBuyNow: onBuyNow, triggerClassName: "w-full" })] })) : !isEnded ? (_jsxs(Div, { className: `${__P.p4} lg:hidden`, border: "subtle", rounded: "xl", surface: "muted", children: [_jsxs(Row, { align: "center", gap: "sm", className: "mb-3", children: [_jsx(Span, { size: "base", weight: "bold", className: "text-primary-600 dark:text-primary-400", children: formatCurrency(currentBid, currency) }), _jsxs(Span, { size: "xs", color: "muted", children: [bidCount, " bids"] })] }), endDate && (_jsxs(Text, { align: "center", className: "mb-3", size: "xs", color: "muted", children: ["Ends in ", _jsx(CountdownDisplay, { targetDate: endDate, format: "auto", expiredLabel: "Ended" })] })), _jsx(Button, { variant: "primary", size: "md", className: "w-full", children: "Place Bid" })] })) : null, renderSublistingSection: sublistingCategoryId
133
147
  ? () => (_jsx(SublistingCarouselSection, { sublistingCategoryId: sublistingCategoryId, currentListingId: String(product.id) }))
134
148
  : undefined, renderTabs: () => (_jsx(ProductTabsShell, { descriptionContent: descriptionHtml ? (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm sm:prose max-w-none dark:prose-invert", className: "text-[var(--appkit-color-text-muted)]" })) : undefined, specsContent: specs.length > 0 ? (_jsx(Dl, { divide: "subtle", rounded: "xl", border: "subtle", className: "overflow-hidden", children: specs.map((s, i) => (_jsxs(Row, { gap: "md", oddEven: "zebra", surface: "default", padding: "inline", children: [_jsx(Dt, { className: "w-36 flex-shrink-0", color: "primary", weight: "medium", children: s.name }), _jsxs(Dd, { className: "flex-1", color: "muted", children: [s.value, s.unit ? ` ${s.unit}` : ""] })] }, i))) })) : undefined, customTabs: customSections.map((s) => ({
135
149
  id: s.id,
@@ -176,8 +190,6 @@ export async function AuctionDetailPageView({ id, initialAuction, onPlaceBid, on
176
190
  bidCount: typeof r.bidCount === "number" ? r.bidCount : undefined,
177
191
  slug: typeof r.slug === "string" ? r.slug : undefined,
178
192
  }));
179
- if (related.length === 0)
180
- return null;
181
- return (_jsx(RelatedProducts, { labels: { title: "Similar Auctions" }, renderGrid: () => (_jsx(MarketplaceAuctionGrid, { auctions: related, gridClassName: "grid grid-cols-2 gap-[var(--appkit-space-4)] sm:grid-cols-3 lg:grid-cols-4" })) }));
182
- } }), renderAuctionStoreReviews(storeReviews), _jsx(AuctionBottomActions, { currentBid: currentBid, currency: currency, bidCount: bidCount, isEnded: isEnded })] })] }));
193
+ return (_jsxs(Stack, { gap: "xl", children: [related.length > 0 && (_jsx(RelatedProducts, { labels: { title: "Similar Auctions" }, renderGrid: () => (_jsx(MarketplaceAuctionGrid, { auctions: related, gridClassName: "grid grid-cols-2 gap-[var(--appkit-space-4)] sm:grid-cols-3 lg:grid-cols-4" })) })), _jsx(GroupedListingsCarousel, { groups: groups }), _jsx(RelatedItemsSection, { relatedItems: relatedItems, relatedByBrand: relatedByBrand, relatedByTags: relatedByTags, relatedByStore: relatedByStore, categoryLabel: categoryName || category || undefined, brandLabel: brand || undefined, storeLabel: storeName || undefined })] }));
194
+ } }), renderAuctionStoreReviews(storeReviews), _jsx(AuctionBottomActions, { currentBid: currentBid, currency: currency, bidCount: bidCount, isEnded: isEnded, auctionEndDate: endDate })] })] }));
183
195
  }
@@ -0,0 +1,18 @@
1
+ import { type BidIncrementTier } from "../../../_internal/shared/features/auctions/config";
2
+ export interface LiveMinIncrementProps {
3
+ productId: string;
4
+ currentBid: number;
5
+ bidCount: number;
6
+ currency: string;
7
+ isEnded: boolean;
8
+ tiers: BidIncrementTier[];
9
+ minBidIncrementOverride?: number;
10
+ size?: "xs" | "sm";
11
+ }
12
+ /**
13
+ * LiveMinIncrement — the "min increment ₹X" text, kept live via the same
14
+ * `/auction-bids/{id}` SSE channel `LiveBidPrice` uses. The effective
15
+ * increment depends on the current bid amount (tiered), so it must keep
16
+ * resolving against the live current bid, not just the SSR snapshot.
17
+ */
18
+ export declare function LiveMinIncrement({ productId, currentBid, bidCount, currency, isEnded, tiers, minBidIncrementOverride, size, }: LiveMinIncrementProps): import("react").JSX.Element;
@@ -0,0 +1,17 @@
1
+ "use client";
2
+ import { jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Span } from "../../../ui";
4
+ import { formatCurrency } from "../../../utils/number.formatter";
5
+ import { useLiveAuctionBid } from "../hooks/useLiveAuctionBid";
6
+ import { resolveMinBidIncrement, } from "../../../_internal/shared/features/auctions/config";
7
+ /**
8
+ * LiveMinIncrement — the "min increment ₹X" text, kept live via the same
9
+ * `/auction-bids/{id}` SSE channel `LiveBidPrice` uses. The effective
10
+ * increment depends on the current bid amount (tiered), so it must keep
11
+ * resolving against the live current bid, not just the SSR snapshot.
12
+ */
13
+ export function LiveMinIncrement({ productId, currentBid, bidCount, currency, isEnded, tiers, minBidIncrementOverride, size = "xs", }) {
14
+ const live = useLiveAuctionBid(productId, currentBid, bidCount, { enabled: !isEnded });
15
+ const increment = resolveMinBidIncrement(live.currentBid, tiers, minBidIncrementOverride);
16
+ return (_jsxs(Span, { size: size, color: "muted", children: ["min increment ", formatCurrency(increment, currency)] }));
17
+ }
@@ -1,4 +1,5 @@
1
1
  import React from "react";
2
+ import { type BidIncrementTier } from "../../../_internal/shared/features/auctions/config";
2
3
  export interface PlaceBidInput {
3
4
  productId: string;
4
5
  bidAmount: number;
@@ -8,9 +9,11 @@ export interface PlaceBidFormClientProps {
8
9
  productId: string;
9
10
  currentBid: number;
10
11
  startingBid: number;
11
- minBidIncrement: number;
12
+ tiers: BidIncrementTier[];
13
+ minBidIncrementOverride?: number;
12
14
  currency: string;
13
15
  isEnded: boolean;
16
+ auctionEndDate: Date | null;
14
17
  buyNowPrice: number | null;
15
18
  bidsHaveStarted?: boolean;
16
19
  bidCount: number;
@@ -18,7 +21,7 @@ export interface PlaceBidFormClientProps {
18
21
  onPlaceBid: (input: PlaceBidInput) => Promise<unknown>;
19
22
  onBuyNow?: () => Promise<unknown>;
20
23
  }
21
- export declare function PlaceBidFormClient({ productId, currentBid: ssrCurrentBid, startingBid, minBidIncrement, currency, isEnded, buyNowPrice, bidsHaveStarted, bidCount: ssrBidCount, tags, onPlaceBid, onBuyNow, }: PlaceBidFormClientProps): React.JSX.Element;
24
+ export declare function PlaceBidFormClient({ productId, currentBid: ssrCurrentBid, startingBid, tiers, minBidIncrementOverride, currency, isEnded, auctionEndDate, buyNowPrice, bidsHaveStarted, bidCount: ssrBidCount, tags, onPlaceBid, onBuyNow, }: PlaceBidFormClientProps): React.JSX.Element;
22
25
  /**
23
26
  * `PlaceBidModalButton` — opens a modal that hosts the same PlaceBidFormClient.
24
27
  *
@@ -4,12 +4,13 @@ import { useState, useTransition } from "react";
4
4
  import { useRouter } from "next/navigation";
5
5
  import { formatCurrency } from "../../../utils/number.formatter";
6
6
  import { isAuthError } from "../../../utils/auth-error";
7
- import { Button, Div, LoginRequiredModal, Modal, Row, Span, Stack, Text } from "../../../ui";
7
+ import { Button, CountdownDisplay, Div, LoginRequiredModal, Modal, Row, Span, Stack, Text } from "../../../ui";
8
8
  import { Form } from "../../../ui/components/Form";
9
9
  import { FieldInput } from "../../../ui/forms/FieldInput";
10
10
  import { applyZodIssues } from "../../../ui/forms/FormShell";
11
11
  import { placeBidSchema } from "../schemas/bid-input";
12
12
  import { useLiveAuctionBid } from "../hooks/useLiveAuctionBid";
13
+ import { resolveMinBidIncrement, } from "../../../_internal/shared/features/auctions/config";
13
14
  import { normalizeError } from "../../../errors/normalize";
14
15
  const __P = {
15
16
  p5: "p-[var(--appkit-space-5)]",
@@ -21,13 +22,16 @@ const BID_ERROR_DISPLAY = {
21
22
  BID_SELF_BID: "You cannot bid on your own listing.",
22
23
  BID_USER_BANNED: "Your account is currently restricted from bidding. Contact support.",
23
24
  };
24
- export function PlaceBidFormClient({ productId, currentBid: ssrCurrentBid, startingBid, minBidIncrement, currency, isEnded, buyNowPrice, bidsHaveStarted = false, bidCount: ssrBidCount, tags = [], onPlaceBid, onBuyNow, }) {
25
+ export function PlaceBidFormClient({ productId, currentBid: ssrCurrentBid, startingBid, tiers, minBidIncrementOverride, currency, isEnded, auctionEndDate, buyNowPrice, bidsHaveStarted = false, bidCount: ssrBidCount, tags = [], onPlaceBid, onBuyNow, }) {
25
26
  const router = useRouter();
26
27
  // Live-updates while the bid card is open — reflects other bidders'
27
28
  // activity on this auction, not just the bidder's own submission.
28
29
  const live = useLiveAuctionBid(productId, ssrCurrentBid, ssrBidCount, { enabled: !isEnded });
29
30
  const currentBid = live.currentBid;
30
31
  const bidCount = live.bidCount;
32
+ // Tiered, floor-raising: resolves fresh whenever the live current bid
33
+ // crosses a tier boundary while this modal is open.
34
+ const minBidIncrement = resolveMinBidIncrement(currentBid, tiers, minBidIncrementOverride);
31
35
  const minBid = currentBid + minBidIncrement;
32
36
  const [bidAmount, setBidAmount] = useState(String(minBid));
33
37
  const [stepMul, setStepMul] = useState(1);
@@ -110,7 +114,7 @@ export function PlaceBidFormClient({ productId, currentBid: ssrCurrentBid, start
110
114
  }, children: ["+", formatCurrency(minBidIncrement * n, currency)] }, n))), _jsx(Button, { type: "button", variant: stepMul === "custom" ? "primary" : "ghost", size: "sm", role: "radio", "aria-checked": stepMul === "custom", disabled: isEnded || isPending, onClick: () => setStepMul("custom"), children: "Custom" })] }), _jsx(FieldInput, { name: "bidAmount", type: "number", value: bidAmount, readOnly: stepMul !== "custom", onChange: (value) => {
111
115
  setBidAmount(value);
112
116
  clearErrors();
113
- }, placeholder: `At least ${formatCurrency(minBid, currency)}`, min: minBid, "aria-label": "Your bid amount", disabled: isEnded || isPending }), stepMul === "custom" && (_jsxs(Text, { size: "xs", color: "muted", "aria-live": "polite", children: ["Any amount \u2265 ", formatCurrency(minBid, currency), " is accepted."] })), success && (_jsx(Text, { className: "text-success", size: "xs", children: "\u2713 Bid placed successfully!" })), _jsx(Button, { variant: "primary", size: "md", className: "w-full", disabled: isEnded || isPending, isLoading: isPending, type: "button", onClick: () => {
117
+ }, placeholder: `At least ${formatCurrency(minBid, currency)}`, min: minBid, "aria-label": "Your bid amount", disabled: isEnded || isPending }), stepMul === "custom" && (_jsxs(Text, { size: "xs", color: "muted", "aria-live": "polite", children: ["Any amount \u2265 ", formatCurrency(minBid, currency), " is accepted."] })), success && (_jsx(Text, { className: "text-success", size: "xs", children: "\u2713 Bid placed successfully!" })), !isEnded && auctionEndDate && (_jsxs(Text, { align: "center", size: "xs", color: "muted", children: ["Ends in ", _jsx(CountdownDisplay, { targetDate: auctionEndDate, format: "auto", expiredLabel: "Ended" })] })), _jsx(Button, { variant: "primary", size: "md", className: "w-full", disabled: isEnded || isPending, isLoading: isPending, type: "button", onClick: () => {
114
118
  clearErrors();
115
119
  const parsed = schema.safeParse({ bidAmount });
116
120
  if (!parsed.success)
@@ -28,6 +28,7 @@ export declare const auctionItemSchema: z.ZodObject<{
28
28
  thumbnailUrl: z.ZodOptional<z.ZodString>;
29
29
  source: z.ZodOptional<z.ZodEnum<["upload", "youtube", "external"]>>;
30
30
  youtubeId: z.ZodOptional<z.ZodString>;
31
+ duration: z.ZodOptional<z.ZodNumber>;
31
32
  }, "strip", z.ZodTypeAny, {
32
33
  type: "video" | "image" | "file";
33
34
  url: string;
@@ -35,6 +36,7 @@ export declare const auctionItemSchema: z.ZodObject<{
35
36
  alt?: string | undefined;
36
37
  thumbnailUrl?: string | undefined;
37
38
  youtubeId?: string | undefined;
39
+ duration?: number | undefined;
38
40
  }, {
39
41
  type: "video" | "image" | "file";
40
42
  url: string;
@@ -42,6 +44,7 @@ export declare const auctionItemSchema: z.ZodObject<{
42
44
  alt?: string | undefined;
43
45
  thumbnailUrl?: string | undefined;
44
46
  youtubeId?: string | undefined;
47
+ duration?: number | undefined;
45
48
  }>, "many">>;
46
49
  currency: z.ZodString;
47
50
  price: z.ZodNumber;
@@ -84,6 +87,7 @@ export declare const auctionItemSchema: z.ZodObject<{
84
87
  alt?: string | undefined;
85
88
  thumbnailUrl?: string | undefined;
86
89
  youtubeId?: string | undefined;
90
+ duration?: number | undefined;
87
91
  }[] | undefined;
88
92
  storeSlug?: string | undefined;
89
93
  }, {
@@ -113,6 +117,7 @@ export declare const auctionItemSchema: z.ZodObject<{
113
117
  alt?: string | undefined;
114
118
  thumbnailUrl?: string | undefined;
115
119
  youtubeId?: string | undefined;
120
+ duration?: number | undefined;
116
121
  }[] | undefined;
117
122
  storeSlug?: string | undefined;
118
123
  }>;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * AdminAuditLogRepository — thin wrapper over the `adminAuditLog` collection.
3
+ * See `appkit/src/features/audit-log/schemas/firestore.ts` for the doc shape.
4
+ */
5
+ import { BaseRepository, parseSieveDateValue, type SieveModel, type FirebaseSieveResult } from "../../../providers/db-firebase";
6
+ import { type AdminAuditLogDocument } from "../schemas/firestore";
7
+ export declare class AdminAuditLogRepository extends BaseRepository<AdminAuditLogDocument> {
8
+ constructor();
9
+ static readonly SIEVE_FIELDS: {
10
+ id: {
11
+ canFilter: boolean;
12
+ canSort: boolean;
13
+ };
14
+ actorUid: {
15
+ canFilter: boolean;
16
+ canSort: boolean;
17
+ };
18
+ actorName: {
19
+ canFilter: boolean;
20
+ canSort: boolean;
21
+ };
22
+ action: {
23
+ canFilter: boolean;
24
+ canSort: boolean;
25
+ };
26
+ targetType: {
27
+ canFilter: boolean;
28
+ canSort: boolean;
29
+ };
30
+ targetId: {
31
+ canFilter: boolean;
32
+ canSort: boolean;
33
+ };
34
+ createdAt: {
35
+ canFilter: boolean;
36
+ canSort: boolean;
37
+ parseValue: typeof parseSieveDateValue;
38
+ };
39
+ };
40
+ /**
41
+ * Paginated, Firestore-native audit-log list (admin use).
42
+ */
43
+ list(model: SieveModel): Promise<FirebaseSieveResult<AdminAuditLogDocument>>;
44
+ }
45
+ export declare const adminAuditLogRepository: AdminAuditLogRepository;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * AdminAuditLogRepository — thin wrapper over the `adminAuditLog` collection.
3
+ * See `appkit/src/features/audit-log/schemas/firestore.ts` for the doc shape.
4
+ */
5
+ import { BaseRepository, parseSieveDateValue, } from "../../../providers/db-firebase";
6
+ import { ADMIN_AUDIT_LOG_COLLECTION } from "../schemas/firestore";
7
+ export class AdminAuditLogRepository extends BaseRepository {
8
+ constructor() {
9
+ super(ADMIN_AUDIT_LOG_COLLECTION);
10
+ }
11
+ /**
12
+ * Paginated, Firestore-native audit-log list (admin use).
13
+ */
14
+ async list(model) {
15
+ return this.sieveQuery(model, AdminAuditLogRepository.SIEVE_FIELDS, {
16
+ defaultPageSize: 50,
17
+ maxPageSize: 200,
18
+ });
19
+ }
20
+ }
21
+ AdminAuditLogRepository.SIEVE_FIELDS = {
22
+ id: { canFilter: true, canSort: false },
23
+ actorUid: { canFilter: true, canSort: false },
24
+ actorName: { canFilter: true, canSort: false },
25
+ action: { canFilter: true, canSort: true },
26
+ targetType: { canFilter: true, canSort: false },
27
+ targetId: { canFilter: true, canSort: false },
28
+ createdAt: { canFilter: true, canSort: true, parseValue: parseSieveDateValue },
29
+ };
30
+ export const adminAuditLogRepository = new AdminAuditLogRepository();
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Admin Audit Log Firestore Document Types & Constants
3
+ *
4
+ * Collection: adminAuditLog
5
+ * Document ID: Firestore auto-ID (no slug prefix — see CLAUDE.md "True
6
+ * Firestore auto-IDs" list, same convention as `notifications`/`sessions`/`jobs`).
7
+ *
8
+ * A queryable record of high-value privileged admin actions — bans, checkout
9
+ * bypass, coupon edits, payout mark-paid, store status changes, role changes.
10
+ * This is deliberately an MVP scope (instrumenting existing high-value call
11
+ * sites), not an exhaustive every-write-path audit trail — see CLAUDE.md's
12
+ * "Admin Audit Log" section for the full instrumented-action list.
13
+ */
14
+ import type { BaseDocument } from "../../../_internal/shared/types/base-document";
15
+ import type { JsonValue } from "../../../schemas/types";
16
+ export declare const ADMIN_AUDIT_LOG_COLLECTION = "adminAuditLog";
17
+ export declare const AdminAuditActionValues: {
18
+ readonly USER_HARD_BAN: "user_hard_ban";
19
+ readonly USER_SOFT_BAN: "user_soft_ban";
20
+ readonly USER_UNBAN: "user_unban";
21
+ readonly CHECKOUT_BYPASS: "checkout_bypass";
22
+ readonly COUPON_UPDATE: "coupon_update";
23
+ readonly PAYOUT_MARK_PAID: "payout_mark_paid";
24
+ readonly STORE_STATUS_CHANGE: "store_status_change";
25
+ readonly USER_ROLE_CHANGE: "user_role_change";
26
+ };
27
+ export type AdminAuditAction = (typeof AdminAuditActionValues)[keyof typeof AdminAuditActionValues];
28
+ export interface AdminAuditLogDocument extends BaseDocument {
29
+ actorUid: string;
30
+ actorName?: string;
31
+ action: AdminAuditAction;
32
+ /** e.g. "user" | "store" | "coupon" | "payout" — the kind of entity affected. */
33
+ targetType: string;
34
+ targetId: string;
35
+ /** Denormalized human-readable label (display name, coupon code, etc.) so the log list never needs a join. */
36
+ targetLabel?: string;
37
+ reason?: string;
38
+ metadata?: Record<string, JsonValue>;
39
+ }
40
+ export declare const ADMIN_AUDIT_LOG_FIELDS: {
41
+ readonly ACTOR_UID: "actorUid";
42
+ readonly ACTOR_NAME: "actorName";
43
+ readonly ACTION: "action";
44
+ readonly TARGET_TYPE: "targetType";
45
+ readonly TARGET_ID: "targetId";
46
+ readonly TARGET_LABEL: "targetLabel";
47
+ readonly REASON: "reason";
48
+ readonly CREATED_AT: "createdAt";
49
+ readonly ACTION_VALUES: {
50
+ readonly USER_HARD_BAN: "user_hard_ban";
51
+ readonly USER_SOFT_BAN: "user_soft_ban";
52
+ readonly USER_UNBAN: "user_unban";
53
+ readonly CHECKOUT_BYPASS: "checkout_bypass";
54
+ readonly COUPON_UPDATE: "coupon_update";
55
+ readonly PAYOUT_MARK_PAID: "payout_mark_paid";
56
+ readonly STORE_STATUS_CHANGE: "store_status_change";
57
+ readonly USER_ROLE_CHANGE: "user_role_change";
58
+ };
59
+ };
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Admin Audit Log Firestore Document Types & Constants
3
+ *
4
+ * Collection: adminAuditLog
5
+ * Document ID: Firestore auto-ID (no slug prefix — see CLAUDE.md "True
6
+ * Firestore auto-IDs" list, same convention as `notifications`/`sessions`/`jobs`).
7
+ *
8
+ * A queryable record of high-value privileged admin actions — bans, checkout
9
+ * bypass, coupon edits, payout mark-paid, store status changes, role changes.
10
+ * This is deliberately an MVP scope (instrumenting existing high-value call
11
+ * sites), not an exhaustive every-write-path audit trail — see CLAUDE.md's
12
+ * "Admin Audit Log" section for the full instrumented-action list.
13
+ */
14
+ export const ADMIN_AUDIT_LOG_COLLECTION = "adminAuditLog";
15
+ export const AdminAuditActionValues = {
16
+ USER_HARD_BAN: "user_hard_ban",
17
+ USER_SOFT_BAN: "user_soft_ban",
18
+ USER_UNBAN: "user_unban",
19
+ CHECKOUT_BYPASS: "checkout_bypass",
20
+ COUPON_UPDATE: "coupon_update",
21
+ PAYOUT_MARK_PAID: "payout_mark_paid",
22
+ STORE_STATUS_CHANGE: "store_status_change",
23
+ USER_ROLE_CHANGE: "user_role_change",
24
+ };
25
+ export const ADMIN_AUDIT_LOG_FIELDS = {
26
+ ACTOR_UID: "actorUid",
27
+ ACTOR_NAME: "actorName",
28
+ ACTION: "action",
29
+ TARGET_TYPE: "targetType",
30
+ TARGET_ID: "targetId",
31
+ TARGET_LABEL: "targetLabel",
32
+ REASON: "reason",
33
+ CREATED_AT: "createdAt",
34
+ ACTION_VALUES: AdminAuditActionValues,
35
+ };
@@ -1,3 +1,2 @@
1
1
  export * from "./profile-actions";
2
2
  export * from "./realtime-token-actions";
3
- export * from "./password-change-otp-actions";
@@ -1,3 +1,2 @@
1
1
  export * from "./profile-actions";
2
2
  export * from "./realtime-token-actions";
3
- export * from "./password-change-otp-actions";
@@ -21,10 +21,6 @@ export interface RegisterData {
21
21
  displayName?: string;
22
22
  acceptTerms: boolean;
23
23
  }
24
- export interface ChangePasswordData {
25
- currentPassword: string;
26
- newPassword: string;
27
- }
28
24
  export interface ChangeEmailData {
29
25
  currentPassword: string;
30
26
  newEmail: string;
@@ -91,38 +87,15 @@ export declare function useResetPassword(options?: {
91
87
  onError?: (error: Error) => void;
92
88
  }): import("@tanstack/react-query").UseMutationResult<JsonValue, Error, ResetPasswordData, unknown>;
93
89
  /**
94
- * Password change is now a 3-step flow (root-caused 2026-08-20see
95
- * appkit/src/features/auth/password-change-otp.ts): the old single-step
96
- * reauthenticateAndChangePassword() applied the new password immediately
97
- * client-side, before any server-verified identity check beyond the
98
- * session cookie. Step order:
99
- * 1. useRequestPasswordChangeOtp verifies currentPassword via Firebase
100
- * reauth (proves the caller actually knows it, without changing
101
- * anything yet), then emails a 6-digit code.
102
- * 2. useVerifyPasswordChangeOtp — verifies the code server-side.
103
- * 3. useChangePassword — only now actually applies newPassword; the API
104
- * route rejects this call unless step 2 already succeeded.
90
+ * Password change is Firebase-only (no custom OTP code, no Resend) the
91
+ * "Change Password" settings action sends the exact same reset-link email
92
+ * as "Forgot Password" (see useForgotPassword above), to the signed-in
93
+ * user's own address. Completing the link requires access to that inbox,
94
+ * which a stolen session cookie alone can't provide — closing the same gap
95
+ * the older OTP-code system existed for, through inbox possession instead
96
+ * of a typed code. There is no separate hook for this: consumers call
97
+ * useForgotPassword({ email: user.email }) directly from the settings page.
105
98
  */
106
- export declare function useRequestPasswordChangeOtp(options?: {
107
- onSuccess?: (data: {
108
- maskedEmail: string;
109
- }) => void;
110
- onError?: (error: Error) => void;
111
- }): import("@tanstack/react-query").UseMutationResult<{
112
- maskedEmail: string;
113
- }, Error, {
114
- currentPassword: string;
115
- }, unknown>;
116
- export declare function useVerifyPasswordChangeOtp(options?: {
117
- onSuccess?: (data: JsonValue) => void;
118
- onError?: (error: Error) => void;
119
- }): import("@tanstack/react-query").UseMutationResult<JsonValue, Error, {
120
- code: string;
121
- }, unknown>;
122
- export declare function useChangePassword(options?: {
123
- onSuccess?: (data: JsonValue) => void;
124
- onError?: (error: Error) => void;
125
- }): import("@tanstack/react-query").UseMutationResult<JsonValue, Error, ChangePasswordData, unknown>;
126
99
  export declare function useChangeEmail(options?: {
127
100
  onSuccess?: (data: JsonValue) => void;
128
101
  onError?: (error: Error) => void;
@@ -7,7 +7,7 @@ import { getClientSessionAdapter } from "../../../contracts/client-session";
7
7
  import { apiClient } from "../../../http";
8
8
  import { useAuthEvent } from "./useAuthEvent";
9
9
  import { RealtimeEventStatus } from "../../../react/hooks/useRealtimeEvent";
10
- import { AUTH_ENDPOINTS, ACCOUNT_ENDPOINTS, } from "../../../constants/api-endpoints";
10
+ import { AUTH_ENDPOINTS, } from "../../../constants/api-endpoints";
11
11
  export function useCurrentUser(opts) {
12
12
  const query = useQuery({
13
13
  queryKey: ["auth", "me"],
@@ -307,7 +307,18 @@ export function useRegister(options) {
307
307
  // `auth.currentUser` is populated for client-side Firebase usage
308
308
  // (RTDB presence, etc) — do NOT call /api/auth/session again here,
309
309
  // that would create a second, orphaned session document.
310
- await getClientAuthProvider().signInWithEmailAndPassword(data.email.trim(), data.password);
310
+ const authProvider = getClientAuthProvider();
311
+ await authProvider.signInWithEmailAndPassword(data.email.trim(), data.password);
312
+ // Verification email is Firebase-native only (no Resend) — see project
313
+ // policy on "profile related auth changes". Deliberately non-fatal:
314
+ // the account already exists at this point, so a send failure must not
315
+ // fail registration — the user can re-request verification later.
316
+ try {
317
+ await authProvider.sendEmailVerification();
318
+ }
319
+ catch (err) {
320
+ void normalizeError(err);
321
+ }
311
322
  return { success: true, ...response };
312
323
  },
313
324
  onSuccess: options?.onSuccess,
@@ -354,42 +365,15 @@ export function useResetPassword(options) {
354
365
  });
355
366
  }
356
367
  /**
357
- * Password change is now a 3-step flow (root-caused 2026-08-20see
358
- * appkit/src/features/auth/password-change-otp.ts): the old single-step
359
- * reauthenticateAndChangePassword() applied the new password immediately
360
- * client-side, before any server-verified identity check beyond the
361
- * session cookie. Step order:
362
- * 1. useRequestPasswordChangeOtp verifies currentPassword via Firebase
363
- * reauth (proves the caller actually knows it, without changing
364
- * anything yet), then emails a 6-digit code.
365
- * 2. useVerifyPasswordChangeOtp — verifies the code server-side.
366
- * 3. useChangePassword — only now actually applies newPassword; the API
367
- * route rejects this call unless step 2 already succeeded.
368
+ * Password change is Firebase-only (no custom OTP code, no Resend) the
369
+ * "Change Password" settings action sends the exact same reset-link email
370
+ * as "Forgot Password" (see useForgotPassword above), to the signed-in
371
+ * user's own address. Completing the link requires access to that inbox,
372
+ * which a stolen session cookie alone can't provide — closing the same gap
373
+ * the older OTP-code system existed for, through inbox possession instead
374
+ * of a typed code. There is no separate hook for this: consumers call
375
+ * useForgotPassword({ email: user.email }) directly from the settings page.
368
376
  */
369
- export function useRequestPasswordChangeOtp(options) {
370
- return useMutation({
371
- mutationFn: async ({ currentPassword }) => {
372
- await getClientAuthProvider().reauthenticateOnly(currentPassword);
373
- return apiClient.post(ACCOUNT_ENDPOINTS.CHANGE_PASSWORD_OTP_REQUEST, {});
374
- },
375
- onSuccess: options?.onSuccess,
376
- onError: options?.onError,
377
- });
378
- }
379
- export function useVerifyPasswordChangeOtp(options) {
380
- return useMutation({
381
- mutationFn: async ({ code }) => apiClient.post(ACCOUNT_ENDPOINTS.CHANGE_PASSWORD_OTP_VERIFY, { code }),
382
- onSuccess: options?.onSuccess,
383
- onError: options?.onError,
384
- });
385
- }
386
- export function useChangePassword(options) {
387
- return useMutation({
388
- mutationFn: async (data) => apiClient.post(ACCOUNT_ENDPOINTS.CHANGE_PASSWORD, data),
389
- onSuccess: options?.onSuccess,
390
- onError: options?.onError,
391
- });
392
- }
393
377
  export function useChangeEmail(options) {
394
378
  return useMutation({
395
379
  mutationFn: async (data) => {