@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
@@ -35,7 +35,12 @@ export interface DashboardLayoutClientProps {
35
35
  permissions?: string[] | null;
36
36
  /** Override active-link highlight. Defaults to usePathname(). */
37
37
  activeHref?: string;
38
- /** Responsive controls — currently only hideAt is honoured. */
38
+ /**
39
+ * Responsive controls — accepted for interface parity with the generic
40
+ * `SectionResponsive` shape used elsewhere, but not currently honoured by
41
+ * this component (no caller passes it today). Wire `hideAt`/`showAt`/
42
+ * `compactAt` to real chrome behaviour before relying on this prop.
43
+ */
39
44
  responsive?: SectionResponsive;
40
45
  /**
41
46
  * Cross-dashboard nav links shown in the sidebar footer. Plain hrefs
@@ -155,7 +155,10 @@ function DashboardBottomNav({ items, activeHref }) {
155
155
  const DEFAULT_CONTENT_PADDING_RIGHT = "px-[var(--appkit-space-5)] py-[var(--appkit-space-8)] lg:pl-14 lg:pr-6 xl:pl-16 xl:pr-10";
156
156
  const DEFAULT_CONTENT_PADDING_LEFT = "px-[var(--appkit-space-5)] py-[var(--appkit-space-8)] lg:pr-14 lg:pl-6 xl:pr-16 xl:pl-10";
157
157
  const DEFAULT_CONTENT_MAX_WIDTH = "max-w-screen-2xl";
158
- export function DashboardLayoutClient({ variant, groups, permissions, activeHref: explicitActiveHref, responsive: _responsive, crossNav, className, contentPadding, contentSurface, contentMaxWidth, lightBackground, darkBackground, children, }) {
158
+ export function DashboardLayoutClient({ variant, groups, permissions, activeHref: explicitActiveHref,
159
+ // audit-dead-underscore-prop-ok: accepted for interface parity, not yet
160
+ // wired — see the doc comment on `responsive` above; no caller passes it.
161
+ responsive: _responsive, crossNav, className, contentPadding, contentSurface, contentMaxWidth, lightBackground, darkBackground, children, }) {
159
162
  const pathname = usePathname();
160
163
  const activeHref = explicitActiveHref ?? pathname ?? "";
161
164
  const storageKey = `appkit:sidebar-open:${variant}`;
@@ -16,5 +16,5 @@ interface LotteryPullFormProps {
16
16
  * Submits TX ID + phone + payment time + item number.
17
17
  * On success, shows the user their lottery number and assigned prize slot.
18
18
  */
19
- export declare function LotteryPullForm({ sourceType, eventId, productId, totalSlots, maxPullsPerUser: _maxPullsPerUser, onSuccess, }: LotteryPullFormProps): React.JSX.Element;
19
+ export declare function LotteryPullForm({ sourceType, eventId, productId, totalSlots, maxPullsPerUser, onSuccess, }: LotteryPullFormProps): React.JSX.Element;
20
20
  export {};
@@ -10,7 +10,7 @@ import { apiClient } from "../../../../http";
10
10
  * Submits TX ID + phone + payment time + item number.
11
11
  * On success, shows the user their lottery number and assigned prize slot.
12
12
  */
13
- export function LotteryPullForm({ sourceType, eventId, productId, totalSlots, maxPullsPerUser: _maxPullsPerUser, onSuccess, }) {
13
+ export function LotteryPullForm({ sourceType, eventId, productId, totalSlots, maxPullsPerUser, onSuccess, }) {
14
14
  const [result, setResult] = useState(null);
15
15
  const [transactionId, setTransactionId] = useState("");
16
16
  const [paymentTime, setPaymentTime] = useState("");
@@ -39,7 +39,7 @@ export function LotteryPullForm({ sourceType, eventId, productId, totalSlots, ma
39
39
  if (result) {
40
40
  return (_jsxs(Stack, { gap: "sm", padding: "md", rounded: "2xl", surface: "success-surface", className: "border border-success/20", children: [_jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Span, { layout: "inline-flex", color: "inverse", weight: "semibold", className: "bg-success text-[11px] tracking-wide", padding: "pill-sm", rounded: "full", transform: "uppercase", children: "Entry Confirmed" }), _jsxs(Heading, { level: 2, className: "text-success", size: "lg", weight: "bold", children: ["You're #", result.userLotteryNumber, "!"] })] }), _jsxs(Text, { className: "text-success", size: "sm", children: ["You've been assigned", " ", _jsxs(Span, { weight: "bold", children: ["Slot #", result.assignedPrizeSlotNumber] }), result.slotName ? ` — ${result.slotName}` : "", ". Good luck!"] })] }));
41
41
  }
42
- return (_jsx(Form, { onSubmit: (e) => e.preventDefault(), className: "space-y-4", children: ({ setFieldError, clearErrors }) => (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, size: "lg", weight: "semibold", children: "Submit Your Entry" }), _jsx(Text, { size: "sm", color: "muted", children: "Enter your UPI Transaction ID and payment details to claim your slot." }), _jsx(FieldInput, { name: "transactionId", label: "Transaction ID (UPI Ref / Payment Ref)", placeholder: "e.g. 123456789012", required: true, value: transactionId, onChange: (v) => { setTransactionId(v); clearErrors(); } }), _jsx(FieldInput, { name: "paymentTime", label: "Payment Date & Time", type: "datetime-local", required: true, value: paymentTime, onChange: (v) => { setPaymentTime(v); clearErrors(); } }), _jsx(FieldInput, { name: "itemNumber", label: `Slot Number (1 – ${totalSlots})`, type: "number", placeholder: `Enter a number between 1 and ${totalSlots}`, required: true, value: itemNumber, onChange: (v) => { setItemNumber(v); clearErrors(); } }), _jsx(FieldInput, { name: "userPhone", label: "Your Phone Number", type: "tel", placeholder: "e.g. 9876543210", required: true, value: userPhone, onChange: (v) => { setUserPhone(v); clearErrors(); } }), _jsx(Button, { type: "submit", variant: "primary", isLoading: mutation.isPending, onClick: () => {
42
+ return (_jsx(Form, { onSubmit: (e) => e.preventDefault(), className: "space-y-4", children: ({ setFieldError, clearErrors }) => (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, size: "lg", weight: "semibold", children: "Submit Your Entry" }), _jsxs(Text, { size: "sm", color: "muted", children: ["Enter your UPI Transaction ID and payment details to claim your slot.", " ", "You may enter up to ", maxPullsPerUser, " time", maxPullsPerUser === 1 ? "" : "s", "."] }), _jsx(FieldInput, { name: "transactionId", label: "Transaction ID (UPI Ref / Payment Ref)", placeholder: "e.g. 123456789012", required: true, value: transactionId, onChange: (v) => { setTransactionId(v); clearErrors(); } }), _jsx(FieldInput, { name: "paymentTime", label: "Payment Date & Time", type: "datetime-local", required: true, value: paymentTime, onChange: (v) => { setPaymentTime(v); clearErrors(); } }), _jsx(FieldInput, { name: "itemNumber", label: `Slot Number (1 – ${totalSlots})`, type: "number", placeholder: `Enter a number between 1 and ${totalSlots}`, required: true, value: itemNumber, onChange: (v) => { setItemNumber(v); clearErrors(); } }), _jsx(FieldInput, { name: "userPhone", label: "Your Phone Number", type: "tel", placeholder: "e.g. 9876543210", required: true, value: userPhone, onChange: (v) => { setUserPhone(v); clearErrors(); } }), _jsx(Button, { type: "submit", variant: "primary", isLoading: mutation.isPending, onClick: () => {
43
43
  clearErrors();
44
44
  const num = parseInt(itemNumber, 10);
45
45
  let valid = true;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Manual trigger for the daily status digest.
3
+ *
4
+ * The digest normally runs from the `dailyStatusDigest` scheduled Firebase
5
+ * Function (10:00 IST). Firebase has no "run on first deploy" trigger, so
6
+ * this exists to fire the exact same core function on demand — e.g. right
7
+ * after a fresh deploy, to confirm the whole chain works without waiting
8
+ * for the next morning. Both paths share one implementation; there is no
9
+ * second copy of the digest logic.
10
+ */
11
+ import { type DailyStatusDigestResult } from "../../jobs/core/dailyStatusDigest";
12
+ export declare function triggerDailyStatusDigest(): Promise<DailyStatusDigestResult>;
13
+ /**
14
+ * Fires the digest once per deployment version, from server startup.
15
+ * Safe to call on every cold start — `runDeploymentDigest` claims the
16
+ * version in a Firestore transaction and no-ops if it's already been sent.
17
+ */
18
+ export declare function triggerDeploymentDigest(version: string): Promise<DailyStatusDigestResult>;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Manual trigger for the daily status digest.
3
+ *
4
+ * The digest normally runs from the `dailyStatusDigest` scheduled Firebase
5
+ * Function (10:00 IST). Firebase has no "run on first deploy" trigger, so
6
+ * this exists to fire the exact same core function on demand — e.g. right
7
+ * after a fresh deploy, to confirm the whole chain works without waiting
8
+ * for the next morning. Both paths share one implementation; there is no
9
+ * second copy of the digest logic.
10
+ */
11
+ import { getAdminDb } from "../../../../providers/db-firebase";
12
+ import { serverLogger } from "../../../../monitoring";
13
+ import { runDailyStatusDigest, runDeploymentDigest, } from "../../jobs/core/dailyStatusDigest";
14
+ function buildManualJobContext(job) {
15
+ return {
16
+ job,
17
+ db: getAdminDb(),
18
+ logger: {
19
+ info: (message, meta) => serverLogger.info(message, meta),
20
+ warn: (message, meta) => serverLogger.warn(message, meta),
21
+ error: (message, err, meta) => serverLogger.error(message, { err, ...(meta ?? {}) }),
22
+ },
23
+ env: (key) => process.env[key],
24
+ now: new Date(),
25
+ };
26
+ }
27
+ export async function triggerDailyStatusDigest() {
28
+ return runDailyStatusDigest(buildManualJobContext("dailyStatusDigest:manual"));
29
+ }
30
+ /**
31
+ * Fires the digest once per deployment version, from server startup.
32
+ * Safe to call on every cold start — `runDeploymentDigest` claims the
33
+ * version in a Firestore transaction and no-ops if it's already been sent.
34
+ */
35
+ export async function triggerDeploymentDigest(version) {
36
+ return runDeploymentDigest(buildManualJobContext("dailyStatusDigest:deploy"), version);
37
+ }
@@ -1,6 +1,6 @@
1
1
  "use server";
2
2
  import { wrapAction } from "@mohasinac/appkit/server";
3
- import { bidRepository, productRepository, userRepository } from "../../../../repositories";
3
+ import { bidRepository, productRepository, userRepository, siteSettingsRepository } from "../../../../repositories";
4
4
  import { requireRoleUser } from "../../../../providers/auth-firebase/helpers";
5
5
  import { placeBidSchema } from "../../../shared/features/auctions/schema";
6
6
  import { assertAuctionActive, assertBidAmount, assertNotAuctionOwner, shouldAutoExtend, computeExtendedEndDate, } from "./service";
@@ -14,7 +14,8 @@ export async function placeBidAction(input) {
14
14
  const { auctionId, amount } = parsed.data;
15
15
  const product = await assertAuctionActive(auctionId);
16
16
  assertNotAuctionOwner(product, user.uid);
17
- assertBidAmount(product, amount);
17
+ const settings = await siteSettingsRepository.getSingleton();
18
+ assertBidAmount(product, amount, settings.auctionConfig?.bidIncrementTiers ?? []);
18
19
  const profile = await userRepository.findById(user.uid).catch(() => null);
19
20
  const userName = profile?.displayName ?? user.name ?? "Anonymous";
20
21
  // Mark all current bids for this auction as outbid, then set new winning bid
@@ -1,10 +1,11 @@
1
+ import { type BidIncrementTier } from "../../../shared/features/auctions/config";
1
2
  import type { ProductDocument } from "../../../shared/features/products/types";
2
3
  /** Assert an auction exists, is published, and is still active. Returns the product. */
3
4
  export declare function assertAuctionActive(auctionId: string): Promise<ProductDocument>;
4
- /** Compute the minimum valid bid given the current state. */
5
- export declare function computeMinBid(product: ProductDocument): number;
5
+ /** Compute the minimum valid bid given the current state and the admin's tier table. */
6
+ export declare function computeMinBid(product: ProductDocument, tiers: BidIncrementTier[]): number;
6
7
  /** Assert a bid amount is valid against the current auction state. */
7
- export declare function assertBidAmount(product: ProductDocument, amount: number): void;
8
+ export declare function assertBidAmount(product: ProductDocument, amount: number, tiers: BidIncrementTier[]): void;
8
9
  /** Assert the bidder is not the auction owner. */
9
10
  export declare function assertNotAuctionOwner(product: ProductDocument, bidderId: string): void;
10
11
  /** Return true if the bid was placed within the sniping window and the auction should auto-extend. */
@@ -1,7 +1,7 @@
1
1
  import { productRepository } from "../../../../repositories";
2
2
  import { isAuctionListing } from "../../../../features/products/utils/listing-type";
3
3
  import { AuctionNotFoundError, AuctionEndedError, BidTooLowError, BidOnOwnAuctionError, } from "../../../shared/features/auctions/errors";
4
- import { AUCTION_MIN_BID_INCREMENT, AUCTION_SNIPING_WINDOW_SECONDS, AUCTION_DEFAULT_EXTENSION_MINUTES, } from "../../../shared/features/auctions/config";
4
+ import { AUCTION_SNIPING_WINDOW_SECONDS, AUCTION_DEFAULT_EXTENSION_MINUTES, resolveMinBidIncrement, } from "../../../shared/features/auctions/config";
5
5
  /** Assert an auction exists, is published, and is still active. Returns the product. */
6
6
  export async function assertAuctionActive(auctionId) {
7
7
  const product = await productRepository.findByIdOrSlug(auctionId).catch(() => null);
@@ -16,15 +16,15 @@ export async function assertAuctionActive(auctionId) {
16
16
  throw new AuctionEndedError(auctionId);
17
17
  return product;
18
18
  }
19
- /** Compute the minimum valid bid given the current state. */
20
- export function computeMinBid(product) {
19
+ /** Compute the minimum valid bid given the current state and the admin's tier table. */
20
+ export function computeMinBid(product, tiers) {
21
21
  const current = product.currentBid ?? product.startingBid ?? 0;
22
- const increment = product.minBidIncrement ?? AUCTION_MIN_BID_INCREMENT;
22
+ const increment = resolveMinBidIncrement(current, tiers, product.minBidIncrement);
23
23
  return current + increment;
24
24
  }
25
25
  /** Assert a bid amount is valid against the current auction state. */
26
- export function assertBidAmount(product, amount) {
27
- const minBid = computeMinBid(product);
26
+ export function assertBidAmount(product, amount, tiers) {
27
+ const minBid = computeMinBid(product, tiers);
28
28
  if (amount < minBid)
29
29
  throw new BidTooLowError(minBid);
30
30
  }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * recordAdminAction — the single write-site for the admin audit trail.
3
+ *
4
+ * MVP scope: instruments the highest-value already-privileged admin actions
5
+ * (bans, checkout bypass, coupon edits, payout mark-paid, store status
6
+ * changes, role changes) rather than sweeping every write path in the app —
7
+ * see CLAUDE.md's "Admin Audit Log" section for the full instrumented-action
8
+ * list and rationale.
9
+ *
10
+ * Callers should treat this as best-effort/non-blocking — a failure to write
11
+ * an audit entry must never fail the underlying privileged action itself.
12
+ */
13
+ import type { AdminAuditAction } from "../../../../features/audit-log/schemas/firestore";
14
+ import type { JsonValue } from "../../../../schemas/types";
15
+ export interface RecordAdminActionInput {
16
+ actorUid: string;
17
+ actorName?: string;
18
+ action: AdminAuditAction;
19
+ targetType: string;
20
+ targetId: string;
21
+ targetLabel?: string;
22
+ reason?: string;
23
+ metadata?: Record<string, JsonValue>;
24
+ }
25
+ export declare function recordAdminAction(input: RecordAdminActionInput): Promise<void>;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * recordAdminAction — the single write-site for the admin audit trail.
3
+ *
4
+ * MVP scope: instruments the highest-value already-privileged admin actions
5
+ * (bans, checkout bypass, coupon edits, payout mark-paid, store status
6
+ * changes, role changes) rather than sweeping every write path in the app —
7
+ * see CLAUDE.md's "Admin Audit Log" section for the full instrumented-action
8
+ * list and rationale.
9
+ *
10
+ * Callers should treat this as best-effort/non-blocking — a failure to write
11
+ * an audit entry must never fail the underlying privileged action itself.
12
+ */
13
+ import { adminAuditLogRepository } from "../../../../features/audit-log/repository/audit-log.repository";
14
+ import { normalizeError } from "../../../../errors/normalize";
15
+ import { serverLogger } from "../../../../monitoring";
16
+ export async function recordAdminAction(input) {
17
+ try {
18
+ await adminAuditLogRepository.create({
19
+ actorUid: input.actorUid,
20
+ actorName: input.actorName,
21
+ action: input.action,
22
+ targetType: input.targetType,
23
+ targetId: input.targetId,
24
+ targetLabel: input.targetLabel,
25
+ reason: input.reason,
26
+ metadata: input.metadata,
27
+ });
28
+ }
29
+ catch (err) {
30
+ const normalized = normalizeError(err);
31
+ serverLogger.warn("recordAdminAction failed (non-critical)", {
32
+ action: input.action,
33
+ targetType: input.targetType,
34
+ targetId: input.targetId,
35
+ error: normalized.message,
36
+ });
37
+ }
38
+ }
@@ -26,8 +26,6 @@ function brandInputToCategoryFields(input) {
26
26
  out.brandCountry = input.country;
27
27
  if (input.founded !== undefined)
28
28
  out.brandFounded = input.founded;
29
- if (input.bannerURL !== undefined)
30
- out.brandBannerImage = input.bannerURL;
31
29
  if (input.logoURL !== undefined) {
32
30
  out.display = { coverImage: input.logoURL, showInMenu: false, showInFooter: false };
33
31
  }
@@ -7,7 +7,10 @@ export interface BrandOgData {
7
7
  interface BrandDocLike {
8
8
  name?: string | null;
9
9
  description?: string | null;
10
- logoURL?: string | null;
10
+ /** CategoryDocument has no `logoURL` field the brand's image lives at `display.coverImage`, the same field the hero banner and generateMetadata's OG meta tag already use. */
11
+ display?: {
12
+ coverImage?: string | null;
13
+ } | null;
11
14
  }
12
15
  /** High-level OG renderer — accepts the raw brand document from `getBrandForDetail`. */
13
16
  export declare function renderBrandOg(doc: BrandDocLike | null | undefined, opts: {
@@ -7,7 +7,7 @@ export function renderBrandOg(doc, opts) {
7
7
  name,
8
8
  description: doc?.description?.slice(0, 120) ??
9
9
  `Shop authentic ${name} collectibles on ${opts.siteName}.`,
10
- logoUrl: resolveOgImageUrl(doc?.logoURL ?? null, opts.baseUrl),
10
+ logoUrl: resolveOgImageUrl(doc?.display?.coverImage ?? null, opts.baseUrl),
11
11
  }, opts.siteName);
12
12
  }
13
13
  export function renderBrandOgImage(data, siteName) {
@@ -45,3 +45,12 @@ export declare function resolveBundleOriginalTotal(productIds: string[]): Promis
45
45
  * `limit` (default 8) and filtered to `isActive: true` server-side.
46
46
  */
47
47
  export declare const listFeaturedBundles: (limit?: number, _opts?: BundleDataOptions) => Promise<CategoryDocument[]>;
48
+ /**
49
+ * "Related Bundles" for the bundle detail page — every other active bundle,
50
+ * excluding the current one. Bundles are a CategoryDocument, not a
51
+ * ProductDocument, so this mirrors BrandDetailPageView's "Related Brands"
52
+ * pattern (all active siblings of the same categoryType) rather than the
53
+ * product-based 4-signal computeRelatedItems() used elsewhere — bundle
54
+ * detail pages had no related section at all before this.
55
+ */
56
+ export declare const getRelatedBundles: (bundle: Pick<CategoryDocument, "id">, limit?: number) => Promise<CategoryDocument[]>;
@@ -79,3 +79,17 @@ export const listFeaturedBundles = cache(async (limit = 8, _opts) => {
79
79
  .catch(() => []);
80
80
  return all;
81
81
  });
82
+ /**
83
+ * "Related Bundles" for the bundle detail page — every other active bundle,
84
+ * excluding the current one. Bundles are a CategoryDocument, not a
85
+ * ProductDocument, so this mirrors BrandDetailPageView's "Related Brands"
86
+ * pattern (all active siblings of the same categoryType) rather than the
87
+ * product-based 4-signal computeRelatedItems() used elsewhere — bundle
88
+ * detail pages had no related section at all before this.
89
+ */
90
+ export const getRelatedBundles = cache(async (bundle, limit = 8) => {
91
+ const all = await categoriesRepository
92
+ .listByType("bundle", { activeOnly: true, limit: limit + 1 })
93
+ .catch(() => []);
94
+ return all.filter((b) => b.id !== bundle.id).slice(0, limit);
95
+ });
@@ -1,4 +1,4 @@
1
- export { getBundleForDetail, listBundleMembers, listFeaturedBundles, resolveBundleMemberIds, resolveBundleOriginalTotal, type BundleDataOptions, } from "./data";
1
+ export { getBundleForDetail, listBundleMembers, listFeaturedBundles, getRelatedBundles, resolveBundleMemberIds, resolveBundleOriginalTotal, type BundleDataOptions, } from "./data";
2
2
  export { buildBundleMetadata, type BundleMetadataOptions } from "./metadata";
3
3
  export { renderBundleOg, renderBundleOgImage, type BundleOgData, } from "./og";
4
4
  export { addBundleToCartAction } from "./actions";
@@ -1,4 +1,4 @@
1
- export { getBundleForDetail, listBundleMembers, listFeaturedBundles, resolveBundleMemberIds, resolveBundleOriginalTotal, } from "./data";
1
+ export { getBundleForDetail, listBundleMembers, listFeaturedBundles, getRelatedBundles, resolveBundleMemberIds, resolveBundleOriginalTotal, } from "./data";
2
2
  export { buildBundleMetadata } from "./metadata";
3
3
  // S-SBUNI-4 2026-05-13 — bundle OG renderer.
4
4
  export { renderBundleOg, renderBundleOgImage, } from "./og";
@@ -0,0 +1,20 @@
1
+ import type { ReactElement } from "react";
2
+ export interface CatalogueItemOgData {
3
+ title: string;
4
+ ownerName?: string | null;
5
+ priceLabel?: string | null;
6
+ imageUrl?: string | null;
7
+ }
8
+ interface CatalogueItemDocLike {
9
+ title?: string | null;
10
+ price?: number | null;
11
+ mainImage?: string | null;
12
+ images?: (string | null | undefined)[] | null;
13
+ }
14
+ export declare function renderCatalogueItemOg(doc: CatalogueItemDocLike | null | undefined, opts: {
15
+ siteName: string;
16
+ baseUrl?: string;
17
+ ownerName?: string | null;
18
+ }): ReactElement;
19
+ export declare function renderCatalogueItemOgImage(data: CatalogueItemOgData, siteName: string): ReactElement;
20
+ export {};
@@ -0,0 +1,27 @@
1
+ import { renderOgLayout } from "../seo/og-layout";
2
+ import { resolveOgImageUrl } from "../seo/og";
3
+ export function renderCatalogueItemOg(doc, opts) {
4
+ const priceLabel = doc?.price != null && doc.price > 0
5
+ ? new Intl.NumberFormat("en-IN", {
6
+ style: "currency",
7
+ currency: "INR",
8
+ maximumFractionDigits: 0,
9
+ }).format(doc.price)
10
+ : null;
11
+ return renderCatalogueItemOgImage({
12
+ title: doc?.title ?? "Catalogue Item",
13
+ ownerName: opts.ownerName,
14
+ priceLabel,
15
+ imageUrl: resolveOgImageUrl(doc?.mainImage || doc?.images?.[0] || null, opts.baseUrl),
16
+ }, opts.siteName);
17
+ }
18
+ export function renderCatalogueItemOgImage(data, siteName) {
19
+ return renderOgLayout({
20
+ title: data.title,
21
+ subtitle: data.ownerName ? `Owned by ${data.ownerName}` : undefined,
22
+ imageUrl: data.imageUrl,
23
+ siteName: `${siteName} · Catalogue`,
24
+ accentSlot: data.priceLabel,
25
+ theme: { accentColor: "#a78bfa" },
26
+ });
27
+ }
@@ -18,6 +18,22 @@ export interface ListGroupedListingsParams {
18
18
  export declare function listGroupedListings(params?: ListGroupedListingsParams): Promise<GroupedListingDocument[]>;
19
19
  /** Featured grouped listings for homepage strips. */
20
20
  export declare const listFeaturedGroupedListings: (limit?: number) => Promise<GroupedListingDocument[]>;
21
+ /**
22
+ * Groups a product belongs to that are eligible to render publicly —
23
+ * powers the "You might also like" / "Same character" / etc. carousel
24
+ * on product-based listing detail pages. Deduped per request.
25
+ */
26
+ export declare const getGroupsForProduct: (productId: string) => Promise<GroupedListingDocument[]>;
27
+ /**
28
+ * Groups a product belongs to, each hydrated with its OTHER member products
29
+ * (the current product is excluded from its own group's item list) — ready
30
+ * to render directly as a public GroupedListingsCarousel section.
31
+ */
32
+ export declare const getGroupsWithItemsForProduct: (productId: string) => Promise<GroupedListingWithItems[]>;
33
+ /** Groups tagged to a category, hydrated with all member products — for the category detail page's GroupedListingsCarousel. */
34
+ export declare const getGroupsForCategory: (categorySlug: string) => Promise<GroupedListingWithItems[]>;
35
+ /** Groups tagged to a brand, hydrated with all member products — for the brand detail page's GroupedListingsCarousel. */
36
+ export declare const getGroupsForBrand: (brandSlug: string) => Promise<GroupedListingWithItems[]>;
21
37
  export interface SitemapGroupedListing {
22
38
  slug: string;
23
39
  updatedAt: Date;
@@ -3,7 +3,7 @@ import { getAdminDb } from "../../../../providers/db-firebase";
3
3
  import { normalizeError } from "../../../../errors/normalize";
4
4
  import { serverLogger } from "../../../../monitoring/server-logger";
5
5
  import { GROUPED_LISTINGS_COLLECTION, } from "../../../../features/grouped/schemas/firestore";
6
- import { productRepository } from "../../../../repositories";
6
+ import { productRepository, groupedListingsRepository } from "../../../../repositories";
7
7
  import { PRODUCT_FIELDS, CATEGORY_FIELDS } from "../../../../constants/field-names";
8
8
  import { GROUPED_LISTINGS_FEATURED_LIMIT, GROUPED_LISTINGS_PAGE_SIZE, GROUPED_LISTINGS_SITEMAP_LIMIT, } from "../../../shared/features/grouped/config";
9
9
  function mapDoc(doc) {
@@ -107,6 +107,55 @@ export async function listGroupedListings(params = {}) {
107
107
  export const listFeaturedGroupedListings = cache(async (limit = GROUPED_LISTINGS_FEATURED_LIMIT) => {
108
108
  return listGroupedListings({ featuredOnly: true, limit });
109
109
  });
110
+ /**
111
+ * Groups a product belongs to that are eligible to render publicly —
112
+ * powers the "You might also like" / "Same character" / etc. carousel
113
+ * on product-based listing detail pages. Deduped per request.
114
+ */
115
+ export const getGroupsForProduct = cache(async (productId) => {
116
+ return groupedListingsRepository.findByProductId(productId).catch((err) => {
117
+ void normalizeError(err);
118
+ serverLogger.warn("grouped-data: getGroupsForProduct failed — returning empty", { productId, error: err instanceof Error ? err.message : String(err) });
119
+ return [];
120
+ });
121
+ });
122
+ /**
123
+ * Groups a product belongs to, each hydrated with its OTHER member products
124
+ * (the current product is excluded from its own group's item list) — ready
125
+ * to render directly as a public GroupedListingsCarousel section.
126
+ */
127
+ export const getGroupsWithItemsForProduct = cache(async (productId) => {
128
+ const groups = await getGroupsForProduct(productId);
129
+ return Promise.all(groups.map(async (group) => {
130
+ const otherIds = group.productIds.filter((id) => id !== productId);
131
+ const items = await Promise.all(otherIds.map((id) => productRepository.findByIdOrSlug(id).catch(() => null)));
132
+ return { ...group, items: items.filter((p) => p !== null) };
133
+ }));
134
+ });
135
+ /** Groups tagged to a category, hydrated with all member products — for the category detail page's GroupedListingsCarousel. */
136
+ export const getGroupsForCategory = cache(async (categorySlug) => {
137
+ const groups = await groupedListingsRepository.findByCategorySlug(categorySlug).catch((err) => {
138
+ void normalizeError(err);
139
+ serverLogger.warn("grouped-data: getGroupsForCategory failed — returning empty", { categorySlug, error: err instanceof Error ? err.message : String(err) });
140
+ return [];
141
+ });
142
+ return Promise.all(groups.map(async (group) => {
143
+ const items = await Promise.all(group.productIds.map((id) => productRepository.findByIdOrSlug(id).catch(() => null)));
144
+ return { ...group, items: items.filter((p) => p !== null) };
145
+ }));
146
+ });
147
+ /** Groups tagged to a brand, hydrated with all member products — for the brand detail page's GroupedListingsCarousel. */
148
+ export const getGroupsForBrand = cache(async (brandSlug) => {
149
+ const groups = await groupedListingsRepository.findByBrandSlug(brandSlug).catch((err) => {
150
+ void normalizeError(err);
151
+ serverLogger.warn("grouped-data: getGroupsForBrand failed — returning empty", { brandSlug, error: err instanceof Error ? err.message : String(err) });
152
+ return [];
153
+ });
154
+ return Promise.all(groups.map(async (group) => {
155
+ const items = await Promise.all(group.productIds.map((id) => productRepository.findByIdOrSlug(id).catch(() => null)));
156
+ return { ...group, items: items.filter((p) => p !== null) };
157
+ }));
158
+ });
110
159
  export async function listSitemapGroupedListings() {
111
160
  try {
112
161
  const db = getAdminDb();
@@ -1,2 +1,2 @@
1
- export { getGroupedListingForDetail, getGroupedListingWithItems, listGroupedListings, listFeaturedGroupedListings, listSitemapGroupedListings, type GroupedListingWithItems, type ListGroupedListingsParams, type SitemapGroupedListing, } from "./data";
1
+ export { getGroupedListingForDetail, getGroupedListingWithItems, listGroupedListings, listFeaturedGroupedListings, listSitemapGroupedListings, getGroupsForProduct, getGroupsWithItemsForProduct, getGroupsForCategory, getGroupsForBrand, type GroupedListingWithItems, type ListGroupedListingsParams, type SitemapGroupedListing, } from "./data";
2
2
  export { GROUPED_LISTINGS_PAGE_SIZE, GROUPED_LISTINGS_FEATURED_LIMIT, GROUPED_LISTINGS_SITEMAP_LIMIT, } from "../../../shared/features/grouped/config";
@@ -1,2 +1,2 @@
1
- export { getGroupedListingForDetail, getGroupedListingWithItems, listGroupedListings, listFeaturedGroupedListings, listSitemapGroupedListings, } from "./data";
1
+ export { getGroupedListingForDetail, getGroupedListingWithItems, listGroupedListings, listFeaturedGroupedListings, listSitemapGroupedListings, getGroupsForProduct, getGroupsWithItemsForProduct, getGroupsForCategory, getGroupsForBrand, } from "./data";
2
2
  export { GROUPED_LISTINGS_PAGE_SIZE, GROUPED_LISTINGS_FEATURED_LIMIT, GROUPED_LISTINGS_SITEMAP_LIMIT, } from "../../../shared/features/grouped/config";
@@ -161,6 +161,15 @@ export async function attachPaymentProofAction(orderId, proof) {
161
161
  buyerFraudAgreementAcceptedAt: new Date(),
162
162
  buyerReportedUpiId: proof.buyerReportedUpiId,
163
163
  paymentUpiMismatch,
164
+ // A re-upload after `adminRequestProofReuploadAction` must clear the
165
+ // stale `reupload_requested` outcome. Both the 2-hour auto-approve
166
+ // sweep (`getUnreviewedProofPastDeadline`) and the admin
167
+ // "Awaiting verification" queue treat *any* set outcome as "already
168
+ // decided" — leaving it set meant a corrected proof was invisible to
169
+ // both: never auto-approved, never surfaced for manual review.
170
+ paymentReviewOutcome: null,
171
+ paymentReviewedBy: null,
172
+ paymentReviewedAt: null,
164
173
  });
165
174
  notifyAdminsOfPaymentProof({
166
175
  id: orderId,
@@ -1,3 +1,6 @@
1
+ function toIsoOrUndefined(value) {
2
+ return value instanceof Date ? value.toISOString() : undefined;
3
+ }
1
4
  export function orderDocumentToOrder(doc) {
2
5
  const items = doc.items?.length
3
6
  ? doc.items.map((item) => ({
@@ -55,10 +58,32 @@ export function orderDocumentToOrder(doc) {
55
58
  couponCode: doc.couponCode,
56
59
  trackingNumber: doc.trackingNumber,
57
60
  shippingCarrier: doc.shippingCarrier,
61
+ trackingUrl: doc.trackingUrl,
58
62
  notes: doc.notes,
63
+ orderDate: toIsoOrUndefined(doc.orderDate),
64
+ shippingDate: toIsoOrUndefined(doc.shippingDate),
65
+ deliveryDate: toIsoOrUndefined(doc.deliveryDate),
66
+ cancellationDate: toIsoOrUndefined(doc.cancellationDate),
59
67
  autoApproved: doc.autoApproved,
60
68
  disputeRaised: doc.disputeRaised,
61
69
  disputeStatus: doc.disputeStatus,
70
+ // Manual-payment (cash / UPI / EMI) passthrough. These were previously
71
+ // dropped here, which silently disabled the entire buyer proof-upload
72
+ // flow: `/user/orders/[id]/payment` branches on `paymentMethod` and so
73
+ // rendered "this order does not require manual payment upload" for every
74
+ // order, with no UPI ID and no countdown.
75
+ paymentMethod: doc.paymentMethod,
76
+ displayedUpiId: doc.displayedUpiId,
77
+ paymentDeadline: toIsoOrUndefined(doc.paymentDeadline),
78
+ paymentProofUrl: doc.paymentProofUrl,
79
+ paymentProofUploadedAt: toIsoOrUndefined(doc.paymentProofUploadedAt),
80
+ paymentTransactionId: doc.paymentTransactionId,
81
+ buyerReportedUpiId: doc.buyerReportedUpiId,
82
+ buyerMarkedPaid: doc.buyerMarkedPaid,
83
+ paymentUpiMismatch: doc.paymentUpiMismatch,
84
+ paymentReviewOutcome: doc.paymentReviewOutcome,
85
+ paymentReviewNote: doc.paymentReviewNote,
86
+ cancellationReason: doc.cancellationReason,
62
87
  createdAt: doc.createdAt instanceof Date
63
88
  ? doc.createdAt.toISOString()
64
89
  : String(doc.createdAt),
@@ -1,9 +1,16 @@
1
1
  import type { ProductDocument } from "../../../../features/products/schemas/firestore";
2
2
  import type { ListingType } from "../../../../features/products/types";
3
+ import type { ProductItem } from "../../../../features/products/types";
4
+ import type { FirestoreDocument } from "../../../../schemas/types";
5
+ import type { Review } from "../../../../features/reviews/types";
3
6
  /** Fetch a single product by slug or id, deduped per request. */
4
7
  export declare const getProductForDetail: (slugOrId: string) => Promise<ProductDocument | null>;
5
8
  /** Fetch the first page of approved reviews for a product, deduped per request. */
6
9
  export declare const getReviewsForProduct: (productId: string) => Promise<unknown[]>;
10
+ /** Firestore review doc → client Review shape. Shared by every listing-type detail page's reviews tab. */
11
+ export declare function toReview(doc: FirestoreDocument): Review;
12
+ /** Fetch + map approved reviews for a product straight to the client Review shape, deduped per request. */
13
+ export declare const getReviewItemsForProduct: (productId: string) => Promise<Review[]>;
7
14
  /** Minimal product fields needed for sitemap generation. */
8
15
  export interface SitemapProduct {
9
16
  slugOrId: string;
@@ -13,3 +20,19 @@ export interface SitemapProduct {
13
20
  }
14
21
  /** List all published products for sitemap generation. */
15
22
  export declare function listSitemapProducts(): Promise<SitemapProduct[]>;
23
+ export interface RelatedItemsResult {
24
+ relatedItems: ProductItem[];
25
+ relatedByBrand: ProductItem[];
26
+ relatedByTags: ProductItem[];
27
+ relatedByStore: ProductItem[];
28
+ }
29
+ /** Firestore doc → card-grid shape. Shared by every related/similar-items carousel. */
30
+ export declare function toProductItem(doc: FirestoreDocument): ProductItem;
31
+ /**
32
+ * Same 4-signal related-items computation used across every listing-type
33
+ * detail page (category / brand / tag-overlap / same-store), each excluding
34
+ * invalid states for that item's own listing type. Extracted from
35
+ * ProductDetailPageView so pre-order/prize-draw/classified/digital-code/live
36
+ * pages can reuse it instead of having no related section at all.
37
+ */
38
+ export declare const computeRelatedItems: (product: ProductDocument) => Promise<RelatedItemsResult>;