@mohasinac/appkit 3.4.8 → 3.5.1

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 (605) hide show
  1. package/dist/_internal/client/features/classified/ClassifiedDetailView.js +1 -1
  2. package/dist/_internal/client/features/digital-code/CodeRevealPanel.js +1 -1
  3. package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.js +1 -1
  4. package/dist/_internal/client/features/filters/filter-load-options.js +10 -9
  5. package/dist/_internal/client/features/layout/DashboardLayoutClient.d.ts +6 -1
  6. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +11 -4
  7. package/dist/_internal/client/features/live/LiveItemDetailView.js +2 -2
  8. package/dist/_internal/client/features/maintenance/views/AnalysisRunnerView.js +10 -3
  9. package/dist/_internal/client/features/maintenance/views/ServerErrorsListView.js +2 -2
  10. package/dist/_internal/client/scaffolds/DashboardScaffold.js +3 -1
  11. package/dist/_internal/server/features/checkout/actions.d.ts +16 -0
  12. package/dist/_internal/server/features/checkout/actions.js +149 -35
  13. package/dist/_internal/server/features/checkout/bundle-expansion.d.ts +31 -0
  14. package/dist/_internal/server/features/checkout/bundle-expansion.js +41 -0
  15. package/dist/_internal/server/features/lottery/actions.js +14 -4
  16. package/dist/_internal/server/features/maintenance/analyze.js +4 -2
  17. package/dist/_internal/server/features/orders/actions.js +9 -0
  18. package/dist/_internal/server/features/orders/adapters.js +19 -0
  19. package/dist/_internal/server/features/seo/robots.js +1 -1
  20. package/dist/_internal/server/functions/firestore.d.ts +47 -1
  21. package/dist/_internal/server/functions/firestore.js +56 -1
  22. package/dist/_internal/server/functions/scheduled.d.ts +2 -1
  23. package/dist/_internal/server/functions/scheduled.js +9 -1
  24. package/dist/_internal/server/jobs/core/catalogueImageStalenessReminder.d.ts +10 -0
  25. package/dist/_internal/server/jobs/core/catalogueImageStalenessReminder.js +49 -0
  26. package/dist/_internal/server/jobs/core/cleanupRtdbEvents.js +32 -0
  27. package/dist/_internal/server/jobs/core/hardBanCascade.d.ts +26 -0
  28. package/dist/_internal/server/jobs/core/hardBanCascade.js +181 -0
  29. package/dist/_internal/server/jobs/core/index.d.ts +4 -1
  30. package/dist/_internal/server/jobs/core/index.js +4 -1
  31. package/dist/_internal/server/jobs/core/jobRunners.d.ts +28 -0
  32. package/dist/_internal/server/jobs/core/jobRunners.js +37 -0
  33. package/dist/_internal/server/jobs/core/onCatalogueSubmittedForApproval.d.ts +15 -0
  34. package/dist/_internal/server/jobs/core/onCatalogueSubmittedForApproval.js +38 -0
  35. package/dist/_internal/server/jobs/core/onJobCreated.d.ts +22 -0
  36. package/dist/_internal/server/jobs/core/onJobCreated.js +59 -0
  37. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.d.ts +6 -1
  38. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +5 -2
  39. package/dist/_internal/server/jobs/handlers/catalogueImageStalenessReminder.d.ts +2 -0
  40. package/dist/_internal/server/jobs/handlers/catalogueImageStalenessReminder.js +2 -0
  41. package/dist/_internal/server/jobs/handlers/index.d.ts +6 -0
  42. package/dist/_internal/server/jobs/handlers/index.js +8 -0
  43. package/dist/_internal/server/jobs/handlers/onCatalogueSubmittedForApproval.d.ts +12 -0
  44. package/dist/_internal/server/jobs/handlers/onCatalogueSubmittedForApproval.js +20 -0
  45. package/dist/_internal/server/jobs/handlers/onJobCreated.d.ts +3 -0
  46. package/dist/_internal/server/jobs/handlers/onJobCreated.js +9 -0
  47. package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.d.ts +25 -0
  48. package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.js +71 -0
  49. package/dist/_internal/server/jobs/handlers/onShipmentDeleted.d.ts +14 -0
  50. package/dist/_internal/server/jobs/handlers/onShipmentDeleted.js +23 -0
  51. package/dist/_internal/server/jobs/handlers/onShipmentItemWrite.d.ts +17 -0
  52. package/dist/_internal/server/jobs/handlers/onShipmentItemWrite.js +26 -0
  53. package/dist/_internal/server/jobs/handlers/weeklyPayoutEligibility.js +3 -1
  54. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  55. package/dist/_internal/shared/actions/action-registry.js +136 -0
  56. package/dist/_internal/shared/features/blog/schema.d.ts +8 -8
  57. package/dist/_internal/shared/features/brands/schema.d.ts +4 -4
  58. package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +8 -8
  59. package/dist/_internal/shared/features/events/schema.d.ts +4 -4
  60. package/dist/_internal/shared/features/products/schema.d.ts +8 -8
  61. package/dist/_internal/shared/features/promotions/schema.d.ts +4 -4
  62. package/dist/_internal/shared/features/reviews/schema.d.ts +4 -4
  63. package/dist/client/api/useFeatureFlags.d.ts +22 -0
  64. package/dist/client/api/useFeatureFlags.js +27 -0
  65. package/dist/client/observability/reportClientError.js +3 -2
  66. package/dist/client.d.ts +4 -2
  67. package/dist/client.js +2 -1
  68. package/dist/configs/next.js +1 -0
  69. package/dist/constants/api-endpoints.d.ts +279 -3
  70. package/dist/constants/api-endpoints.js +130 -2
  71. package/dist/core/hooks/useSyncManager.js +5 -4
  72. package/dist/errors/conflict-error.d.ts +4 -0
  73. package/dist/errors/conflict-error.js +6 -0
  74. package/dist/errors/index.d.ts +1 -0
  75. package/dist/errors/index.js +1 -0
  76. package/dist/features/about/components/FeesView.js +2 -2
  77. package/dist/features/about/components/HelpPageView.js +2 -2
  78. package/dist/features/about/components/HowAuctionsWorkView.js +2 -2
  79. package/dist/features/about/components/HowCheckoutWorksView.js +2 -2
  80. package/dist/features/about/components/HowEmiWorksView.js +2 -2
  81. package/dist/features/about/components/HowOffersWorkView.js +3 -3
  82. package/dist/features/about/components/HowOrdersWorkView.js +3 -3
  83. package/dist/features/about/components/HowPayoutsWorkView.js +2 -2
  84. package/dist/features/about/components/HowPreOrdersWorkView.js +2 -2
  85. package/dist/features/about/components/HowReviewsWorkView.js +2 -2
  86. package/dist/features/about/components/PublicProfileView.d.ts +8 -1
  87. package/dist/features/about/components/PublicProfileView.js +11 -9
  88. package/dist/features/about/components/SecurityPrivacyView.js +2 -2
  89. package/dist/features/about/components/UnauthorizedView.js +2 -2
  90. package/dist/features/account/components/AddressBook.js +1 -1
  91. package/dist/features/account/components/AddressesIndexListing.js +1 -1
  92. package/dist/features/account/components/NotificationBell.js +5 -5
  93. package/dist/features/account/components/NotificationPreferencesPanel.js +5 -2
  94. package/dist/features/account/components/UserOffersPanel.js +5 -4
  95. package/dist/features/account/components/UserSidebar.js +2 -2
  96. package/dist/features/account/components/UserSupportView.js +3 -3
  97. package/dist/features/account/schemas/index.d.ts +12 -12
  98. package/dist/features/addresses/schemas/index.d.ts +6 -6
  99. package/dist/features/admin/components/AdminAdEditorView.js +3 -3
  100. package/dist/features/admin/components/AdminAddressEditorView.js +3 -3
  101. package/dist/features/admin/components/AdminAdsView.js +3 -3
  102. package/dist/features/admin/components/AdminBlogEditorView.js +1 -1
  103. package/dist/features/admin/components/AdminBlogView.js +12 -15
  104. package/dist/features/admin/components/AdminBrandEditorView.js +1 -1
  105. package/dist/features/admin/components/AdminBrandsView.js +12 -13
  106. package/dist/features/admin/components/AdminBundleEditorView.js +5 -4
  107. package/dist/features/admin/components/AdminBundlesView.js +32 -23
  108. package/dist/features/admin/components/AdminCarouselEditorView.js +5 -5
  109. package/dist/features/admin/components/AdminCarouselView.js +2 -2
  110. package/dist/features/admin/components/AdminCatalogGuideView.js +1 -1
  111. package/dist/features/admin/components/AdminCategoriesView.js +12 -13
  112. package/dist/features/admin/components/AdminCategoryEditorView.js +2 -2
  113. package/dist/features/admin/components/AdminContactEditorView.js +2 -2
  114. package/dist/features/admin/components/AdminCouponEditorView.d.ts +10 -1
  115. package/dist/features/admin/components/AdminCouponEditorView.js +7 -2
  116. package/dist/features/admin/components/AdminCouponsView.js +32 -27
  117. package/dist/features/admin/components/AdminEmployeeEditorView.js +3 -3
  118. package/dist/features/admin/components/AdminFaqEditorView.js +1 -1
  119. package/dist/features/admin/components/AdminFaqsView.js +20 -20
  120. package/dist/features/admin/components/AdminFeatureEditorView.js +5 -5
  121. package/dist/features/admin/components/AdminFeaturesView.js +9 -10
  122. package/dist/features/admin/components/AdminFilterBar.js +1 -1
  123. package/dist/features/admin/components/AdminFulfillmentView.js +4 -4
  124. package/dist/features/admin/components/AdminGuideHubView.js +2 -2
  125. package/dist/features/admin/components/AdminMediaView.js +3 -2
  126. package/dist/features/admin/components/AdminNavigationView.js +1 -1
  127. package/dist/features/admin/components/AdminOrderEditorView.js +3 -3
  128. package/dist/features/admin/components/AdminOrdersView.js +21 -30
  129. package/dist/features/admin/components/AdminPageHeader.js +3 -3
  130. package/dist/features/admin/components/AdminPayoutsView.js +8 -8
  131. package/dist/features/admin/components/AdminPrizeDrawsView.js +8 -9
  132. package/dist/features/admin/components/AdminProductEditorView.d.ts +9 -1
  133. package/dist/features/admin/components/AdminProductEditorView.js +7 -4
  134. package/dist/features/admin/components/AdminProductsView.js +30 -41
  135. package/dist/features/admin/components/AdminReviewsView.js +14 -17
  136. package/dist/features/admin/components/AdminScammerEditorView.js +5 -5
  137. package/dist/features/admin/components/AdminSectionsView.js +3 -3
  138. package/dist/features/admin/components/AdminSessionsView.js +8 -10
  139. package/dist/features/admin/components/AdminSidebar.js +2 -2
  140. package/dist/features/admin/components/AdminSiteSettingsView.js +10 -3
  141. package/dist/features/admin/components/AdminStoreEditorView.js +4 -5
  142. package/dist/features/admin/components/AdminStoresView.js +18 -13
  143. package/dist/features/admin/components/AdminSupportTicketDetailView.js +7 -7
  144. package/dist/features/admin/components/AdminTeamView.js +9 -5
  145. package/dist/features/admin/components/AdminUsersView.js +19 -15
  146. package/dist/features/admin/components/AdminViewCards.js +5 -5
  147. package/dist/features/admin/components/DashboardStats.js +1 -1
  148. package/dist/features/admin/components/DataListingView.js +2 -2
  149. package/dist/features/admin/components/DataTable.js +2 -2
  150. package/dist/features/admin/components/DrawerFormFooter.js +1 -1
  151. package/dist/features/admin/components/analytics/AdminAnalyticsCharts.js +2 -2
  152. package/dist/features/admin/components/analytics/AdminStatCard.js +1 -1
  153. package/dist/features/admin/hooks/useAdminListing.d.ts +3 -2
  154. package/dist/features/admin/hooks/useAdminListing.js +8 -2
  155. package/dist/features/admin/permission-map.js +2 -0
  156. package/dist/features/admin/schemas/firestore.d.ts +7 -0
  157. package/dist/features/admin/schemas/firestore.js +4 -0
  158. package/dist/features/auctions/components/AuctionBidsTable.js +1 -1
  159. package/dist/features/auctions/components/AuctionDetailPageView.js +7 -7
  160. package/dist/features/auctions/components/MarketplaceAuctionCard.js +3 -3
  161. package/dist/features/auctions/components/MarketplaceAuctionGrid.js +4 -4
  162. package/dist/features/auctions/components/PlaceBidFormClient.js +1 -1
  163. package/dist/features/auctions/schemas/index.d.ts +16 -16
  164. package/dist/features/auth/permissions/constants.d.ts +1 -1
  165. package/dist/features/auth/permissions/constants.js +2 -0
  166. package/dist/features/auth/schemas/index.d.ts +6 -6
  167. package/dist/features/before-after/schemas/index.d.ts +3 -3
  168. package/dist/features/blog/actions/blog-actions.d.ts +32 -32
  169. package/dist/features/blog/components/BlogFeaturedCard.js +2 -2
  170. package/dist/features/blog/components/BlogIndexListing.js +2 -2
  171. package/dist/features/blog/components/BlogListView.js +4 -4
  172. package/dist/features/blog/components/BlogPostView.js +4 -4
  173. package/dist/features/blog/schemas/index.d.ts +77 -77
  174. package/dist/features/cart/components/CartDrawer.js +2 -2
  175. package/dist/features/catalogue/actions/approve-catalogue-listing.d.ts +12 -0
  176. package/dist/features/catalogue/actions/approve-catalogue-listing.js +50 -0
  177. package/dist/features/catalogue/actions/list-from-catalogue.d.ts +17 -0
  178. package/dist/features/catalogue/actions/list-from-catalogue.js +50 -0
  179. package/dist/features/catalogue/actions/submit-for-approval.d.ts +8 -0
  180. package/dist/features/catalogue/actions/submit-for-approval.js +30 -0
  181. package/dist/features/catalogue/components/AdminCatalogueApprovalsView.d.ts +2 -0
  182. package/dist/features/catalogue/components/AdminCatalogueApprovalsView.js +53 -0
  183. package/dist/features/catalogue/components/CatalogueItemEditorView.d.ts +7 -0
  184. package/dist/features/catalogue/components/CatalogueItemEditorView.js +79 -0
  185. package/dist/features/catalogue/components/PublicCatalogueView.d.ts +5 -0
  186. package/dist/features/catalogue/components/PublicCatalogueView.js +22 -0
  187. package/dist/features/catalogue/components/UserCatalogueView.d.ts +12 -0
  188. package/dist/features/catalogue/components/UserCatalogueView.js +51 -0
  189. package/dist/features/catalogue/index.d.ts +12 -0
  190. package/dist/features/catalogue/index.js +9 -0
  191. package/dist/features/catalogue/repository/catalogue.repository.d.ts +39 -0
  192. package/dist/features/catalogue/repository/catalogue.repository.js +68 -0
  193. package/dist/features/catalogue/schemas/firestore.d.ts +47 -0
  194. package/dist/features/catalogue/schemas/firestore.js +22 -0
  195. package/dist/features/catalogue/schemas/index.d.ts +2 -0
  196. package/dist/features/catalogue/schemas/index.js +2 -0
  197. package/dist/features/catalogue/schemas/validation.d.ts +71 -0
  198. package/dist/features/catalogue/schemas/validation.js +25 -0
  199. package/dist/features/catalogue/utils/freshness.d.ts +10 -0
  200. package/dist/features/catalogue/utils/freshness.js +15 -0
  201. package/dist/features/catalogue/utils/product-from-item.d.ts +15 -0
  202. package/dist/features/catalogue/utils/product-from-item.js +34 -0
  203. package/dist/features/categories/components/BrandDetailPageView.js +1 -1
  204. package/dist/features/categories/components/BrandDetailTabs.js +2 -2
  205. package/dist/features/categories/components/BundleCollage.js +2 -2
  206. package/dist/features/categories/components/BundleItemsPicker.js +3 -2
  207. package/dist/features/categories/components/CategoriesIndexListing.js +8 -6
  208. package/dist/features/categories/components/CategoryBundlesListing.js +10 -4
  209. package/dist/features/categories/components/CategoryDetailPageView.js +1 -1
  210. package/dist/features/categories/components/CategoryDetailTabs.js +2 -2
  211. package/dist/features/categories/components/CategoryGrid.js +3 -3
  212. package/dist/features/categories/components/CategoryProductsListing.js +1 -1
  213. package/dist/features/categories/components/CategorySortSelect.js +1 -1
  214. package/dist/features/categories/components/CategoryStoresListing.js +1 -1
  215. package/dist/features/categories/components/CategoryTableColumns.js +1 -1
  216. package/dist/features/categories/components/CategoryTree.js +2 -2
  217. package/dist/features/categories/components/ConcernCard.js +1 -1
  218. package/dist/features/categories/hooks/useCategories.js +1 -1
  219. package/dist/features/categories/schemas/index.d.ts +32 -32
  220. package/dist/features/classified/components/ClassifiedFilters.js +2 -2
  221. package/dist/features/classified/components/ClassifiedIndexListing.js +9 -3
  222. package/dist/features/collections/schemas/index.d.ts +2 -2
  223. package/dist/features/consultation/components/ConsultationForm.js +1 -1
  224. package/dist/features/consultation/schemas/index.d.ts +10 -10
  225. package/dist/features/contact/components/ContactForm.js +4 -4
  226. package/dist/features/contact/components/ContactInfoSidebar.js +1 -1
  227. package/dist/features/contact/components/ContactPageView.js +2 -1
  228. package/dist/features/copilot/components/AdminCopilotView.js +5 -4
  229. package/dist/features/corporate/schemas/index.d.ts +2 -2
  230. package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +3 -3
  231. package/dist/features/events/components/AdminEventEditorView.js +4 -4
  232. package/dist/features/events/components/AdminEventEntriesView.js +2 -2
  233. package/dist/features/events/components/AdminEventsView.js +8 -8
  234. package/dist/features/events/components/EventBanner.js +1 -1
  235. package/dist/features/events/components/EventCard.js +3 -3
  236. package/dist/features/events/components/EventLeaderboard.js +1 -1
  237. package/dist/features/events/components/EventOfferCard.js +1 -1
  238. package/dist/features/events/components/EventPollWidget.js +6 -5
  239. package/dist/features/events/components/EventRaffleEntryForm.js +1 -1
  240. package/dist/features/events/components/EventRaffleWinnerView.js +5 -5
  241. package/dist/features/events/components/EventRafflesSection.js +1 -1
  242. package/dist/features/events/components/EventSaleBanner.js +1 -1
  243. package/dist/features/events/components/EventsIndexListing.js +4 -2
  244. package/dist/features/events/components/EventsListView.js +2 -2
  245. package/dist/features/events/components/SpinWheelView.js +11 -5
  246. package/dist/features/events/schemas/index.d.ts +100 -100
  247. package/dist/features/faq/actions/faq-actions.d.ts +6 -6
  248. package/dist/features/faq/components/ContactCTA.js +3 -3
  249. package/dist/features/faq/components/FAQCategorySidebar.js +2 -2
  250. package/dist/features/faq/components/FAQHelpfulButtons.js +3 -3
  251. package/dist/features/faq/schemas/index.d.ts +12 -12
  252. package/dist/features/filters/AsyncFacetSection.js +4 -4
  253. package/dist/features/filters/FilterFacetSection.js +8 -8
  254. package/dist/features/filters/RangeFilter.js +2 -2
  255. package/dist/features/filters/SwitchFilter.js +1 -1
  256. package/dist/features/forms/Checkbox.js +2 -8
  257. package/dist/features/forms/Input.js +2 -1
  258. package/dist/features/forms/Radio.js +3 -3
  259. package/dist/features/forms/Select.d.ts +1 -1
  260. package/dist/features/forms/Select.js +3 -2
  261. package/dist/features/forms/Slider.js +5 -11
  262. package/dist/features/forms/Textarea.js +2 -1
  263. package/dist/features/grouped/schemas/index.d.ts +6 -6
  264. package/dist/features/homepage/actions/homepage-section-actions.d.ts +4 -4
  265. package/dist/features/homepage/components/AdvertisementBanner.js +4 -4
  266. package/dist/features/homepage/components/AnnouncementBar.js +3 -3
  267. package/dist/features/homepage/components/BeforeAfterCard.js +1 -1
  268. package/dist/features/homepage/components/BrandsSection.js +9 -9
  269. package/dist/features/homepage/components/CTABannerSection.js +1 -1
  270. package/dist/features/homepage/components/CharacterHotspot.js +4 -4
  271. package/dist/features/homepage/components/CharacterHotspotForm.js +15 -13
  272. package/dist/features/homepage/components/CollectionCardsSection.js +1 -1
  273. package/dist/features/homepage/components/CustomCardsSection.js +6 -6
  274. package/dist/features/homepage/components/CustomerReviewsSection.js +2 -2
  275. package/dist/features/homepage/components/FAQSection.js +2 -2
  276. package/dist/features/homepage/components/FeaturedBundlesSection.js +3 -3
  277. package/dist/features/homepage/components/FeaturedResultsSection.js +2 -2
  278. package/dist/features/homepage/components/GoogleReviewsSection.js +6 -6
  279. package/dist/features/homepage/components/HeroBanner.js +1 -1
  280. package/dist/features/homepage/components/HeroCarousel.js +5 -4
  281. package/dist/features/homepage/components/HeroSection.js +1 -7
  282. package/dist/features/homepage/components/HomepageSkeleton.js +1 -1
  283. package/dist/features/homepage/components/HowItWorksInfoView.js +1 -1
  284. package/dist/features/homepage/components/HowItWorksSection.js +2 -2
  285. package/dist/features/homepage/components/NewsletterBanner.js +2 -2
  286. package/dist/features/homepage/components/NewsletterSection.js +1 -1
  287. package/dist/features/homepage/components/PromoGrid.js +1 -1
  288. package/dist/features/homepage/components/SectionCarousel.js +6 -6
  289. package/dist/features/homepage/components/SecurityHighlightsSection.js +2 -2
  290. package/dist/features/homepage/components/ShopByCategorySection.js +10 -10
  291. package/dist/features/homepage/components/SiteFeaturesSection.js +2 -2
  292. package/dist/features/homepage/components/SocialFeedSection.js +5 -5
  293. package/dist/features/homepage/components/SocialPostCard.js +1 -1
  294. package/dist/features/homepage/components/StatsCounterSection.js +1 -1
  295. package/dist/features/homepage/components/TestimonialsCarousel.js +1 -1
  296. package/dist/features/homepage/components/TrustBadges.js +1 -1
  297. package/dist/features/homepage/components/TrustFeaturesSection.js +2 -2
  298. package/dist/features/homepage/components/TrustIndicatorsSection.js +2 -2
  299. package/dist/features/homepage/components/WelcomeSection.js +2 -2
  300. package/dist/features/homepage/components/WhatsAppCommunitySection.js +1 -1
  301. package/dist/features/homepage/hooks/useActiveAd.js +2 -1
  302. package/dist/features/homepage/schemas/firestore.d.ts +10 -0
  303. package/dist/features/homepage/schemas/index.d.ts +116 -116
  304. package/dist/features/jobs/actions/enqueue-job.d.ts +24 -0
  305. package/dist/features/jobs/actions/enqueue-job.js +44 -0
  306. package/dist/features/jobs/repository/jobs.repository.d.ts +21 -0
  307. package/dist/features/jobs/repository/jobs.repository.js +48 -0
  308. package/dist/features/jobs/schemas/firestore.d.ts +54 -0
  309. package/dist/features/jobs/schemas/firestore.js +24 -0
  310. package/dist/features/layout/AppLayoutShell.js +17 -11
  311. package/dist/features/layout/AutoBreadcrumbs.js +1 -1
  312. package/dist/features/layout/BackToTop.js +2 -2
  313. package/dist/features/layout/BottomActions.js +7 -7
  314. package/dist/features/layout/BottomNavItem.js +2 -2
  315. package/dist/features/layout/BottomNavLayout.js +13 -4
  316. package/dist/features/layout/BottomNavbar.d.ts +9 -1
  317. package/dist/features/layout/BottomNavbar.js +12 -5
  318. package/dist/features/layout/BottomSheet.js +1 -1
  319. package/dist/features/layout/Breadcrumbs.js +1 -1
  320. package/dist/features/layout/FooterLayout.js +2 -2
  321. package/dist/features/layout/NavItem.js +3 -3
  322. package/dist/features/layout/NavbarLayout.js +6 -6
  323. package/dist/features/layout/SidebarLayout.d.ts +3 -0
  324. package/dist/features/layout/SidebarLayout.js +3 -3
  325. package/dist/features/layout/TitleBarLayout.js +4 -4
  326. package/dist/features/live/components/LiveItemFilters.js +2 -2
  327. package/dist/features/live/components/LiveItemsIndexListing.js +3 -3
  328. package/dist/features/lottery/types/index.d.ts +3 -1
  329. package/dist/features/lottery/types/index.js +16 -3
  330. package/dist/features/loyalty/components/CoinsDisplay.js +2 -2
  331. package/dist/features/media/MediaImage.d.ts +6 -1
  332. package/dist/features/media/MediaImage.js +10 -4
  333. package/dist/features/media/MediaLightbox.js +1 -1
  334. package/dist/features/media/MediaPickerModal.js +4 -3
  335. package/dist/features/media/MediaVideo.js +1 -1
  336. package/dist/features/media/modals/ImageCropModal.js +1 -1
  337. package/dist/features/media/modals/ImageEditor.js +1 -1
  338. package/dist/features/media/repository/media-assets.repository.d.ts +9 -0
  339. package/dist/features/media/types/index.d.ts +4 -4
  340. package/dist/features/media/upload/MediaUploadField.js +3 -3
  341. package/dist/features/media/upload/MediaUploadList.js +1 -1
  342. package/dist/features/messages/hooks/useConversation.js +4 -3
  343. package/dist/features/messages/hooks/useConversations.js +2 -1
  344. package/dist/features/messages/schemas/index.d.ts +6 -6
  345. package/dist/features/orders/components/MarketplaceOrderCard.js +1 -1
  346. package/dist/features/orders/components/OrderPaymentSummary.d.ts +16 -0
  347. package/dist/features/orders/components/OrderPaymentSummary.js +32 -0
  348. package/dist/features/orders/components/OrderSiblingPayments.js +1 -1
  349. package/dist/features/orders/components/OrdersList.d.ts +7 -2
  350. package/dist/features/orders/components/OrdersList.js +5 -5
  351. package/dist/features/orders/components/RefundHistoryTable.js +1 -1
  352. package/dist/features/orders/components/RefundRequestView.js +1 -1
  353. package/dist/features/orders/components/index.d.ts +2 -0
  354. package/dist/features/orders/components/index.js +1 -0
  355. package/dist/features/orders/repository/orders.repository.d.ts +8 -0
  356. package/dist/features/orders/repository/orders.repository.js +24 -0
  357. package/dist/features/orders/schemas/firestore.d.ts +59 -0
  358. package/dist/features/orders/schemas/firestore.js +5 -0
  359. package/dist/features/orders/schemas/index.d.ts +91 -40
  360. package/dist/features/orders/schemas/index.js +10 -0
  361. package/dist/features/orders/types/index.d.ts +15 -0
  362. package/dist/features/payments/schemas/index.d.ts +12 -12
  363. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +5 -5
  364. package/dist/features/pre-orders/components/PreOrderActionsClient.js +1 -1
  365. package/dist/features/pre-orders/components/PreOrderBadge.js +1 -1
  366. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +7 -7
  367. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +3 -3
  368. package/dist/features/pre-orders/schemas/index.d.ts +12 -12
  369. package/dist/features/products/columns/productTableColumns.js +2 -2
  370. package/dist/features/products/components/AuctionsIndexListing.js +3 -3
  371. package/dist/features/products/components/CompareOverlay.js +15 -10
  372. package/dist/features/products/components/CustomFieldsEditor.js +2 -2
  373. package/dist/features/products/components/CustomSectionsEditor.js +3 -3
  374. package/dist/features/products/components/FeatureBadge.js +2 -2
  375. package/dist/features/products/components/GroupSettingsPanel.js +5 -4
  376. package/dist/features/products/components/MakeOfferButton.js +4 -4
  377. package/dist/features/products/components/MarketplaceBundleCard.js +3 -2
  378. package/dist/features/products/components/MarketplacePrizeDrawCard.js +1 -1
  379. package/dist/features/products/components/PrizeDrawCollage.js +6 -6
  380. package/dist/features/products/components/PrizeDrawDetailPageView.js +5 -5
  381. package/dist/features/products/components/PrizeDrawEntryActions.js +1 -1
  382. package/dist/features/products/components/PrizeDrawItemsEditor.js +4 -4
  383. package/dist/features/products/components/PrizeDrawsIndexListing.js +11 -4
  384. package/dist/features/products/components/PrizeDrawsSection.js +1 -1
  385. package/dist/features/products/components/PrizeRevealModal.js +9 -4
  386. package/dist/features/products/components/ProductDetailActions.js +2 -1
  387. package/dist/features/products/components/ProductDetailPageView.js +16 -16
  388. package/dist/features/products/components/ProductFeaturesSelector.js +5 -5
  389. package/dist/features/products/components/ProductForm.js +1 -1
  390. package/dist/features/products/components/ProductGalleryClient.js +5 -3
  391. package/dist/features/products/components/ProductGrid.js +11 -11
  392. package/dist/features/products/components/ProductTabs.js +2 -2
  393. package/dist/features/products/components/ProductTabsShell.js +2 -1
  394. package/dist/features/products/components/ProductsIndexListing.js +6 -1
  395. package/dist/features/products/components/ShareButton.js +2 -1
  396. package/dist/features/products/components/ShowGroupSection.js +9 -5
  397. package/dist/features/products/components/SublistingCarouselSection.js +8 -4
  398. package/dist/features/products/constants/action-defs.d.ts +10 -2
  399. package/dist/features/products/constants/action-defs.js +20 -2
  400. package/dist/features/products/schemas/firestore.d.ts +5 -0
  401. package/dist/features/products/schemas/index.d.ts +40 -40
  402. package/dist/features/products/schemas/product-features.validators.d.ts +14 -14
  403. package/dist/features/promotions/components/CouponCard.js +13 -7
  404. package/dist/features/promotions/components/CouponsIndexListing.js +4 -6
  405. package/dist/features/promotions/components/PromotionsView.js +2 -2
  406. package/dist/features/promotions/schemas/index.d.ts +26 -26
  407. package/dist/features/reviews/components/ReviewDetailPageView.js +1 -1
  408. package/dist/features/reviews/components/ReviewDetailShell.js +11 -11
  409. package/dist/features/reviews/components/ReviewModal.js +1 -1
  410. package/dist/features/reviews/components/ReviewsIndexListing.js +2 -2
  411. package/dist/features/reviews/components/ReviewsList.js +2 -2
  412. package/dist/features/reviews/schemas/index.d.ts +22 -22
  413. package/dist/features/scams/components/ScamAwarenessModal.js +2 -2
  414. package/dist/features/scams/components/ScamProfileView.js +3 -3
  415. package/dist/features/scams/components/ScamRegistryView.js +2 -2
  416. package/dist/features/scams/schemas/index.d.ts +20 -20
  417. package/dist/features/search/components/Search.js +9 -9
  418. package/dist/features/search/components/SearchFiltersRow.js +1 -1
  419. package/dist/features/search/components/SearchResultsSection.js +3 -3
  420. package/dist/features/search/components/SearchView.js +1 -1
  421. package/dist/features/search/hooks/useNavSuggestions.js +2 -1
  422. package/dist/features/search/hooks/useSearch.js +2 -2
  423. package/dist/features/search/schemas/index.d.ts +3 -3
  424. package/dist/features/seller/components/BrandInlineSelect.js +2 -2
  425. package/dist/features/seller/components/CategoryInlineSelect.js +2 -2
  426. package/dist/features/seller/components/QuickProductForm.js +1 -1
  427. package/dist/features/seller/components/SellerAddressesView.js +4 -4
  428. package/dist/features/seller/components/SellerAnalyticsAlertsView.js +3 -3
  429. package/dist/features/seller/components/SellerAnalyticsView.js +2 -2
  430. package/dist/features/seller/components/SellerArtView.js +11 -11
  431. package/dist/features/seller/components/SellerAuctionsView.js +11 -11
  432. package/dist/features/seller/components/SellerBidsView.js +3 -3
  433. package/dist/features/seller/components/SellerBundlesView.js +12 -12
  434. package/dist/features/seller/components/SellerClassifiedView.js +11 -11
  435. package/dist/features/seller/components/SellerCouponEditorView.js +2 -2
  436. package/dist/features/seller/components/SellerDigitalCodesView.js +11 -11
  437. package/dist/features/seller/components/SellerFeaturesView.js +4 -4
  438. package/dist/features/seller/components/SellerLiveView.js +11 -11
  439. package/dist/features/seller/components/SellerOffersPanel.js +3 -2
  440. package/dist/features/seller/components/SellerOrdersView.js +2 -2
  441. package/dist/features/seller/components/SellerPayoutMethodsView.js +1 -1
  442. package/dist/features/seller/components/SellerPayoutRequestView.js +6 -5
  443. package/dist/features/seller/components/SellerPayoutSettingsView.js +5 -4
  444. package/dist/features/seller/components/SellerPreOrdersView.js +1 -1
  445. package/dist/features/seller/components/SellerPrizeDrawsView.js +1 -1
  446. package/dist/features/seller/components/SellerProductShell.js +20 -6
  447. package/dist/features/seller/components/SellerProductsCards.js +3 -3
  448. package/dist/features/seller/components/SellerProductsView.js +4 -4
  449. package/dist/features/seller/components/SellerReviewsView.js +7 -6
  450. package/dist/features/seller/components/SellerShippingView.js +2 -1
  451. package/dist/features/seller/components/SellerSidebar.js +5 -5
  452. package/dist/features/seller/components/SellerStickersView.js +11 -11
  453. package/dist/features/seller/components/SellerTemplatesView.js +1 -1
  454. package/dist/features/seller/schemas/index.d.ts +20 -20
  455. package/dist/features/server-errors/schemas/index.d.ts +6 -6
  456. package/dist/features/shell/CommandPalette.d.ts +27 -0
  457. package/dist/features/shell/CommandPalette.js +92 -0
  458. package/dist/features/shell/FormShell.js +4 -3
  459. package/dist/features/shell/QuickFormDrawer.js +3 -2
  460. package/dist/features/shell/StepForm.js +2 -2
  461. package/dist/features/shell/index.d.ts +2 -0
  462. package/dist/features/shell/index.js +1 -0
  463. package/dist/features/shipments/components/AdminShipmentEditorView.d.ts +7 -0
  464. package/dist/features/shipments/components/AdminShipmentEditorView.js +123 -0
  465. package/dist/features/shipments/components/AdminShipmentLotItemsView.d.ts +6 -0
  466. package/dist/features/shipments/components/AdminShipmentLotItemsView.js +96 -0
  467. package/dist/features/shipments/components/AdminShipmentProjectionsView.d.ts +9 -0
  468. package/dist/features/shipments/components/AdminShipmentProjectionsView.js +44 -0
  469. package/dist/features/shipments/components/AdminShipmentsView.d.ts +8 -0
  470. package/dist/features/shipments/components/AdminShipmentsView.js +82 -0
  471. package/dist/features/shipments/components/ShipmentItemLinkModal.d.ts +15 -0
  472. package/dist/features/shipments/components/ShipmentItemLinkModal.js +37 -0
  473. package/dist/features/shipments/hooks/useShipments.d.ts +69 -0
  474. package/dist/features/shipments/hooks/useShipments.js +96 -0
  475. package/dist/features/shipments/index.d.ts +10 -0
  476. package/dist/features/shipments/index.js +7 -0
  477. package/dist/features/shipments/manifest.d.ts +2 -0
  478. package/dist/features/shipments/manifest.js +26 -0
  479. package/dist/features/shipments/repository/shipment-items.repository.d.ts +56 -0
  480. package/dist/features/shipments/repository/shipment-items.repository.js +78 -0
  481. package/dist/features/shipments/repository/shipment-lots.repository.d.ts +48 -0
  482. package/dist/features/shipments/repository/shipment-lots.repository.js +55 -0
  483. package/dist/features/shipments/repository/shipments.repository.d.ts +50 -0
  484. package/dist/features/shipments/repository/shipments.repository.js +77 -0
  485. package/dist/features/shipments/schemas/firestore.d.ts +150 -0
  486. package/dist/features/shipments/schemas/firestore.js +76 -0
  487. package/dist/features/shipments/schemas/index.d.ts +2 -0
  488. package/dist/features/shipments/schemas/index.js +2 -0
  489. package/dist/features/shipments/schemas/validation.d.ts +350 -0
  490. package/dist/features/shipments/schemas/validation.js +96 -0
  491. package/dist/features/shipments/utils/cost-allocation.d.ts +25 -0
  492. package/dist/features/shipments/utils/cost-allocation.js +83 -0
  493. package/dist/features/site-settings/components/ActionPermissionsManager.js +2 -2
  494. package/dist/features/stores/components/InteractiveStoreCard.js +2 -2
  495. package/dist/features/stores/components/StoreAboutView.js +1 -1
  496. package/dist/features/stores/components/StoreAuctionsListing.js +3 -3
  497. package/dist/features/stores/components/StoreAuctionsView.js +1 -1
  498. package/dist/features/stores/components/StoreCapabilitiesGuideView.js +1 -1
  499. package/dist/features/stores/components/StoreClassifiedsListing.js +2 -2
  500. package/dist/features/stores/components/StoreDetailLayoutView.js +1 -1
  501. package/dist/features/stores/components/StoreDigitalCodesListing.js +2 -2
  502. package/dist/features/stores/components/StoreFinanceGuideView.js +2 -2
  503. package/dist/features/stores/components/StoreGuideHubView.js +2 -2
  504. package/dist/features/stores/components/StoreHeader.js +4 -4
  505. package/dist/features/stores/components/StoreLiveItemsListing.js +2 -2
  506. package/dist/features/stores/components/StoreNavTabs.js +2 -2
  507. package/dist/features/stores/components/StoreOrdersGuideView.js +1 -1
  508. package/dist/features/stores/components/StorePreOrdersListing.js +3 -3
  509. package/dist/features/stores/components/StoreProductsListing.js +1 -1
  510. package/dist/features/stores/components/StoreReviewsListing.js +2 -2
  511. package/dist/features/stores/components/StoreReviewsView.js +1 -1
  512. package/dist/features/stores/components/StoreSettingsGuideView.js +1 -1
  513. package/dist/features/stores/components/StoresIndexListing.js +9 -3
  514. package/dist/features/stores/schemas/index.d.ts +10 -10
  515. package/dist/features/support/schemas/index.d.ts +22 -22
  516. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +3 -3
  517. package/dist/features/whatsapp-bot/components/WhatsAppChatButton.js +1 -1
  518. package/dist/features/wishlist/hooks/useWishlistCount.js +1 -2
  519. package/dist/index.d.ts +44 -1
  520. package/dist/index.js +37 -1
  521. package/dist/next/routing/route-map.d.ts +18 -0
  522. package/dist/next/routing/route-map.js +9 -0
  523. package/dist/react/hooks/useVisualViewportInset.d.ts +1 -0
  524. package/dist/react/hooks/useVisualViewportInset.js +59 -0
  525. package/dist/react/index.d.ts +1 -0
  526. package/dist/react/index.js +1 -0
  527. package/dist/repositories/index.d.ts +5 -0
  528. package/dist/repositories/index.js +5 -0
  529. package/dist/schemas/registry.d.ts +398 -364
  530. package/dist/schemas/sieve.d.ts +2 -2
  531. package/dist/schemas/webhooks/google-oauth.d.ts +2 -2
  532. package/dist/schemas/webhooks/razorpay.d.ts +100 -100
  533. package/dist/seed/_helpers/media.js +1 -0
  534. package/dist/seed/actions/demo-seed-actions.d.ts +1 -1
  535. package/dist/seed/catalogue-seed-data.d.ts +2 -0
  536. package/dist/seed/catalogue-seed-data.js +112 -0
  537. package/dist/seed/grouped-listings-seed-data.d.ts +5 -0
  538. package/dist/seed/homepage-sections-seed-data.js +0 -1
  539. package/dist/seed/index.d.ts +2 -0
  540. package/dist/seed/index.js +2 -0
  541. package/dist/seed/manifest.js +6 -0
  542. package/dist/seed/products-preorders-seed-data.d.ts +5 -0
  543. package/dist/seed/shipments-seed-data.d.ts +5 -0
  544. package/dist/seed/shipments-seed-data.js +185 -0
  545. package/dist/server.d.ts +4 -0
  546. package/dist/server.js +5 -0
  547. package/dist/styles.css +75 -19
  548. package/dist/tailwind-utilities.css +1 -1
  549. package/dist/tokens/index.d.ts +0 -2
  550. package/dist/tokens/index.js +0 -2
  551. package/dist/tokens/tokens.css +12 -2
  552. package/dist/ui/DataTable.js +4 -3
  553. package/dist/ui/components/Button.d.ts +4 -1
  554. package/dist/ui/components/Button.js +11 -5
  555. package/dist/ui/components/Checkbox.d.ts +9 -1
  556. package/dist/ui/components/Checkbox.js +5 -2
  557. package/dist/ui/components/ClaimCouponButton.js +2 -1
  558. package/dist/ui/components/ConfirmDeleteModal.style.css +1 -1
  559. package/dist/ui/components/Drawer.style.css +13 -1
  560. package/dist/ui/components/Dropdown.style.css +2 -2
  561. package/dist/ui/components/FilterDrawer.d.ts +4 -1
  562. package/dist/ui/components/FilterDrawer.js +8 -2
  563. package/dist/ui/components/Form.d.ts +1 -1
  564. package/dist/ui/components/Form.js +2 -2
  565. package/dist/ui/components/FormActionBar.style.css +6 -1
  566. package/dist/ui/components/IconButton.d.ts +6 -1
  567. package/dist/ui/components/IconButton.js +5 -2
  568. package/dist/ui/components/IconButton.style.css +11 -0
  569. package/dist/ui/components/ImageGallery.style.css +2 -0
  570. package/dist/ui/components/ImageLightbox.style.css +1 -0
  571. package/dist/ui/components/ListingFilterDrawer.d.ts +4 -1
  572. package/dist/ui/components/ListingFilterDrawer.js +4 -3
  573. package/dist/ui/components/ListingLayout.style.css +2 -2
  574. package/dist/ui/components/Modal.style.css +1 -1
  575. package/dist/ui/components/Pagination.d.ts +5 -1
  576. package/dist/ui/components/Pagination.js +4 -2
  577. package/dist/ui/components/RowActionMenu.js +1 -1
  578. package/dist/ui/components/RowActionMenu.style.css +1 -1
  579. package/dist/ui/components/Select.d.ts +6 -1
  580. package/dist/ui/components/Select.js +18 -13
  581. package/dist/ui/components/Select.style.css +1 -1
  582. package/dist/ui/components/Semantic.d.ts +13 -0
  583. package/dist/ui/components/Semantic.js +16 -3
  584. package/dist/ui/components/SideDrawer.style.css +16 -4
  585. package/dist/ui/components/SideModal.style.css +1 -1
  586. package/dist/ui/components/StickyToolbar.d.ts +3 -2
  587. package/dist/ui/components/StickyToolbar.js +1 -1
  588. package/dist/ui/components/Textarea.d.ts +5 -0
  589. package/dist/ui/components/Textarea.js +8 -4
  590. package/dist/ui/components/Toast.style.css +3 -0
  591. package/dist/ui/components/UnsavedChangesModal.style.css +1 -1
  592. package/dist/ui/components/surface-tokens.d.ts +121 -113
  593. package/dist/ui/components/surface-tokens.js +110 -104
  594. package/dist/ui/forms/FormShell.d.ts +8 -27
  595. package/dist/ui/forms/FormShell.js +1 -194
  596. package/dist/ui/forms/index.d.ts +2 -2
  597. package/dist/ui/forms/index.js +1 -1
  598. package/dist/ui/index.d.ts +8 -4
  599. package/dist/ui/index.js +4 -2
  600. package/dist/utils/id-generators.d.ts +27 -0
  601. package/dist/utils/id-generators.js +45 -0
  602. package/dist/utils/number.formatter.d.ts +7 -0
  603. package/dist/utils/number.formatter.js +9 -0
  604. package/dist/validation/schemas.d.ts +5 -5
  605. package/package.json +1 -1
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Core: hard-ban cascade — disables Auth login, marks the user banned,
3
+ * revokes sessions, suspends any owned store + archives its products,
4
+ * cancels active bids, and cascades the ban across any address / payment
5
+ * clusters shared with other accounts (fraud-ring containment).
6
+ *
7
+ * Extracted verbatim (stage-for-stage) from the former synchronous
8
+ * `POST /api/admin/users/[uid]/hard-ban` route body — that route now only
9
+ * runs the cheap pre-flight guards (self-ban / target-exists / admin-target)
10
+ * and enqueues this as a `hardBanCascade` job (see `./jobRunners.ts`) so the
11
+ * cascade runs inside a Firebase Function instead of the Vercel 10s sync
12
+ * ceiling (CLAUDE.md Rule #6).
13
+ *
14
+ * Each stage keeps its original non-fatal try/catch-log-continue behavior,
15
+ * EXCEPT stage 2 (marking the user banned on Firestore), which is the one
16
+ * write that must succeed for the ban to take effect — if it throws, the job
17
+ * is marked failed so an admin can retry.
18
+ */
19
+ import { normalizeError } from "../../../../errors/normalize";
20
+ import { userRepository, sessionRepository, storeRepository, productRepository, bidRepository, addressesRepository, savedPaymentMethodsRepository, siteSettingsRepository, } from "../../../../repositories";
21
+ import { sendNotification } from "../../../../features/admin/actions/notification-actions";
22
+ import { isSellerUser } from "../../../../features/auth/role-predicates";
23
+ import { getAdminAuth } from "../../../../providers/db-firebase";
24
+ async function cascadeAddressClusterBan(uid, banData) {
25
+ const userAddresses = await addressesRepository.listByOwner("user", uid);
26
+ const uniqueHashes = [...new Set(userAddresses.map((a) => a.addressHash).filter(Boolean))];
27
+ for (const hash of uniqueHashes) {
28
+ const cluster = await addressesRepository.listByAddressHash(hash);
29
+ const hasBannedAccount = cluster.some((a) => a.ownerId !== uid && a.banStatus === "banned");
30
+ if (!hasBannedAccount)
31
+ continue;
32
+ const otherOwners = [...new Set(cluster.filter((a) => a.ownerId !== uid).map((a) => `${a.ownerType}|${a.ownerId}`))];
33
+ for (const ownerKey of otherOwners) {
34
+ const [ownerType, ownerId] = ownerKey.split("|");
35
+ await addressesRepository.banAllForOwner(ownerType, ownerId, banData);
36
+ }
37
+ }
38
+ }
39
+ async function cascadePaymentClusterBan(uid, banData) {
40
+ const userMethods = await savedPaymentMethodsRepository.listByUser(uid);
41
+ for (const method of userMethods) {
42
+ if (!method.identifierHash)
43
+ continue;
44
+ const cluster = await savedPaymentMethodsRepository.listByIdentifierHash(method.identifierHash);
45
+ const hasBannedAccount = cluster.some((m) => m.userId !== uid && m.banStatus === "banned");
46
+ if (!hasBannedAccount)
47
+ continue;
48
+ const otherUserIds = [...new Set(cluster.filter((m) => m.userId !== uid).map((m) => m.userId))];
49
+ for (const otherId of otherUserIds) {
50
+ await savedPaymentMethodsRepository.banAllForUser(otherId, banData);
51
+ }
52
+ }
53
+ }
54
+ export async function runHardBanCascade(input, ctx) {
55
+ const { uid, reason, bannedBy } = input;
56
+ const target = await userRepository.findById(uid);
57
+ if (!target) {
58
+ return {
59
+ summary: { total: 1, succeeded: 0, skipped: 1, failed: 0 },
60
+ succeeded: [],
61
+ skipped: [uid],
62
+ failed: [],
63
+ };
64
+ }
65
+ // 1. Disable Firebase Auth login
66
+ try {
67
+ await getAdminAuth().updateUser(uid, { disabled: true });
68
+ }
69
+ catch (err) {
70
+ void normalizeError(err);
71
+ ctx.logger.warn("hard-ban: Auth disable failed (user may lack Auth record)", {
72
+ uid,
73
+ error: err instanceof Error ? err.message : String(err),
74
+ });
75
+ }
76
+ // 2. Mark banned on Firestore doc — the one write that must succeed for the
77
+ // ban to take effect. Left unguarded so a failure here marks the whole job
78
+ // failed (matches the original route's behavior of surfacing a 500).
79
+ await userRepository.update(uid, {
80
+ isDisabled: true,
81
+ hardBanReason: reason,
82
+ hardBannedAt: new Date(),
83
+ hardBannedBy: bannedBy,
84
+ });
85
+ // 3. Delete active sessions
86
+ try {
87
+ const sessions = await sessionRepository.findActiveByUser(uid);
88
+ await Promise.all(sessions.map((s) => sessionRepository.delete(s.id)));
89
+ }
90
+ catch (err) {
91
+ void normalizeError(err);
92
+ ctx.logger.warn("hard-ban: session cleanup failed (non-fatal)", {
93
+ uid,
94
+ error: err instanceof Error ? err.message : String(err),
95
+ });
96
+ }
97
+ // 4. Cascade to store if seller
98
+ if (isSellerUser(target)) {
99
+ try {
100
+ const store = await storeRepository.findByOwnerId(uid);
101
+ if (store) {
102
+ await storeRepository.update(store.id, { status: "suspended" });
103
+ const products = await productRepository.findByStore(store.id);
104
+ await Promise.all(products.map((p) => productRepository.update(p.id, { status: "archived" })));
105
+ }
106
+ }
107
+ catch (err) {
108
+ void normalizeError(err);
109
+ ctx.logger.warn("hard-ban: store/product cascade failed (non-fatal)", {
110
+ uid,
111
+ error: err instanceof Error ? err.message : String(err),
112
+ });
113
+ }
114
+ }
115
+ // 5. Cancel active bids
116
+ try {
117
+ const bids = await bidRepository.findBy("bidderId", uid);
118
+ const activeBids = bids.filter((b) => b.status === "active");
119
+ await Promise.all(activeBids.map((b) => bidRepository.update(b.id, { status: "cancelled" })));
120
+ }
121
+ catch (err) {
122
+ void normalizeError(err);
123
+ ctx.logger.warn("hard-ban: bid cancellation failed (non-fatal)", {
124
+ uid,
125
+ error: err instanceof Error ? err.message : String(err),
126
+ });
127
+ }
128
+ // 6. Cascade address ban + cross-account cluster ban
129
+ try {
130
+ const banData = { banReason: `User hard-banned: ${reason}`, bannedBy };
131
+ await addressesRepository.banAllForOwner("user", uid, banData);
132
+ await cascadeAddressClusterBan(uid, banData);
133
+ }
134
+ catch (err) {
135
+ void normalizeError(err);
136
+ ctx.logger.warn("hard-ban: address cluster ban failed (non-fatal)", {
137
+ uid,
138
+ error: err instanceof Error ? err.message : String(err),
139
+ });
140
+ }
141
+ // 7. Cascade payment method ban + cross-account cluster ban
142
+ try {
143
+ const banData = { banReason: `User hard-banned: ${reason}`, bannedBy };
144
+ await savedPaymentMethodsRepository.banAllForUser(uid, banData);
145
+ await cascadePaymentClusterBan(uid, banData);
146
+ }
147
+ catch (err) {
148
+ void normalizeError(err);
149
+ ctx.logger.warn("hard-ban: payment method cluster ban failed (non-fatal)", {
150
+ uid,
151
+ error: err instanceof Error ? err.message : String(err),
152
+ });
153
+ }
154
+ // 8. Notify user
155
+ try {
156
+ const siteSettings = await siteSettingsRepository.getSingleton();
157
+ const supportEmail = siteSettings.contact?.email || "support@example.com";
158
+ await sendNotification({
159
+ userId: uid,
160
+ type: "account_action",
161
+ priority: "high",
162
+ title: "Account permanently suspended",
163
+ message: `Your account has been permanently suspended. Reason: ${reason}. You may appeal by emailing ${supportEmail}.`,
164
+ relatedId: uid,
165
+ relatedType: "user",
166
+ });
167
+ }
168
+ catch (err) {
169
+ void normalizeError(err);
170
+ ctx.logger.warn("hard-ban: user notification failed (non-fatal)", {
171
+ uid,
172
+ error: err instanceof Error ? err.message : String(err),
173
+ });
174
+ }
175
+ return {
176
+ summary: { total: 1, succeeded: 1, skipped: 0, failed: 0 },
177
+ succeeded: [uid],
178
+ skipped: [],
179
+ failed: [],
180
+ };
181
+ }
@@ -22,7 +22,9 @@ export { runPayoutBatch } from "./payoutBatch";
22
22
  export { runAutoPayoutEligibility } from "./autoPayoutEligibility";
23
23
  export { runProductStatsSync } from "./productStatsSync";
24
24
  export { runPositionsReconcile } from "./positionsReconcile";
25
- export { runWeeklyPayoutEligibility } from "./weeklyPayoutEligibility";
25
+ export { runWeeklyPayoutEligibility, type WeeklyPayoutEligibilityResult, } from "./weeklyPayoutEligibility";
26
+ export { runHardBanCascade } from "./hardBanCascade";
27
+ export { JOB_RUNNERS, type JobRunner, type JobRunResult, } from "./jobRunners";
26
28
  export { runAuctionSettlement } from "./auctionSettlement";
27
29
  export { runPrizeRevealOpen } from "./prizeRevealOpen";
28
30
  export { runPrizeRevealClose } from "./prizeRevealClose";
@@ -42,3 +44,4 @@ export { handleProductStockChange, type HandleProductStockChangeInput, syncBundl
42
44
  export { handleReviewWrite, type HandleReviewWriteInput } from "./onReviewWrite";
43
45
  export { handleCategoryWrite, type HandleCategoryWriteInput, type CategoryDoc, } from "./onCategoryWrite";
44
46
  export { handleStoreWrite, type HandleStoreWriteInput, type StoreDoc, } from "./onStoreWrite";
47
+ export { handleJobCreated, type HandleJobCreatedInput } from "./onJobCreated";
@@ -23,7 +23,9 @@ export { runPayoutBatch } from "./payoutBatch";
23
23
  export { runAutoPayoutEligibility } from "./autoPayoutEligibility";
24
24
  export { runProductStatsSync } from "./productStatsSync";
25
25
  export { runPositionsReconcile } from "./positionsReconcile";
26
- export { runWeeklyPayoutEligibility } from "./weeklyPayoutEligibility";
26
+ export { runWeeklyPayoutEligibility, } from "./weeklyPayoutEligibility";
27
+ export { runHardBanCascade } from "./hardBanCascade";
28
+ export { JOB_RUNNERS, } from "./jobRunners";
27
29
  export { runAuctionSettlement } from "./auctionSettlement";
28
30
  export { runPrizeRevealOpen } from "./prizeRevealOpen";
29
31
  export { runPrizeRevealClose } from "./prizeRevealClose";
@@ -45,3 +47,4 @@ export { handleProductStockChange, syncBundlesForProduct, syncGroupedListingsFor
45
47
  export { handleReviewWrite } from "./onReviewWrite";
46
48
  export { handleCategoryWrite, } from "./onCategoryWrite";
47
49
  export { handleStoreWrite, } from "./onStoreWrite";
50
+ export { handleJobCreated } from "./onJobCreated";
@@ -0,0 +1,28 @@
1
+ /**
2
+ * JOB_RUNNERS — registry of `jobType` → runner function for the
3
+ * `onJobCreated` Firestore trigger (see `./onJobCreated.ts`).
4
+ *
5
+ * Every runner takes the job's opaque `payload` + a `JobContext` and returns
6
+ * a `JobRunResult` shaped like the client-facing `BulkActionResult` (see
7
+ * `appkit/src/react/hooks/useBulkAction.ts`) so it can be written verbatim to
8
+ * both the `jobs/{jobId}.result` field and the `bulk_events/{jobId}` RTDB
9
+ * ping channel the client subscribes to via `useBulkEvent`.
10
+ */
11
+ import type { JobContext } from "../runtime/types";
12
+ export interface JobRunResult {
13
+ summary: {
14
+ total: number;
15
+ succeeded: number;
16
+ skipped: number;
17
+ failed: number;
18
+ };
19
+ succeeded: string[];
20
+ skipped: string[];
21
+ failed: {
22
+ id: string;
23
+ reason: string;
24
+ }[];
25
+ data?: Record<string, unknown>;
26
+ }
27
+ export type JobRunner = (payload: Record<string, unknown>, ctx: JobContext) => Promise<JobRunResult>;
28
+ export declare const JOB_RUNNERS: Record<string, JobRunner>;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * JOB_RUNNERS — registry of `jobType` → runner function for the
3
+ * `onJobCreated` Firestore trigger (see `./onJobCreated.ts`).
4
+ *
5
+ * Every runner takes the job's opaque `payload` + a `JobContext` and returns
6
+ * a `JobRunResult` shaped like the client-facing `BulkActionResult` (see
7
+ * `appkit/src/react/hooks/useBulkAction.ts`) so it can be written verbatim to
8
+ * both the `jobs/{jobId}.result` field and the `bulk_events/{jobId}` RTDB
9
+ * ping channel the client subscribes to via `useBulkEvent`.
10
+ */
11
+ import { runWeeklyPayoutEligibility } from "./weeklyPayoutEligibility";
12
+ import { runHardBanCascade } from "./hardBanCascade";
13
+ async function runPayoutsWeeklyJob(_payload, ctx) {
14
+ const { payoutsCreated, ordersProcessed, payoutIds } = await runWeeklyPayoutEligibility(ctx);
15
+ return {
16
+ summary: {
17
+ total: payoutsCreated,
18
+ succeeded: payoutsCreated,
19
+ skipped: 0,
20
+ failed: 0,
21
+ },
22
+ succeeded: payoutIds,
23
+ skipped: [],
24
+ failed: [],
25
+ data: { payoutsCreated, ordersProcessed },
26
+ };
27
+ }
28
+ async function runHardBanCascadeJob(payload, ctx) {
29
+ const uid = String(payload.uid ?? "");
30
+ const reason = String(payload.reason ?? "");
31
+ const bannedBy = String(payload.bannedBy ?? "");
32
+ return runHardBanCascade({ uid, reason, bannedBy }, ctx);
33
+ }
34
+ export const JOB_RUNNERS = {
35
+ payoutsWeekly: runPayoutsWeeklyJob,
36
+ hardBanCascade: runHardBanCascadeJob,
37
+ };
@@ -0,0 +1,15 @@
1
+ import type { JobContext } from "../runtime/types";
2
+ import type { CatalogueItemDocument } from "../../../../features/catalogue/schemas/firestore";
3
+ export interface CatalogueApprovalEvent {
4
+ itemId: string;
5
+ before: CatalogueItemDocument;
6
+ after: CatalogueItemDocument;
7
+ }
8
+ /**
9
+ * Fires when a catalogue item's `listingStatus` transitions to
10
+ * "pending_admin_approval" (a buyer's "Request to sell"). Notifies every
11
+ * admin so the approvals queue doesn't go unnoticed. Kept out of the
12
+ * synchronous submit action per Rule #6 — the buyer-facing request stays
13
+ * fast regardless of how many admins there are to fan out to.
14
+ */
15
+ export declare function handleCatalogueSubmittedForApproval(event: CatalogueApprovalEvent, ctx: JobContext): Promise<void>;
@@ -0,0 +1,38 @@
1
+ import { userRepository } from "../../../../features/auth/repository/user.repository";
2
+ import { sendNotification } from "../../../../features/admin/actions/notification-actions";
3
+ import { normalizeError } from "../../../../errors/normalize";
4
+ /**
5
+ * Fires when a catalogue item's `listingStatus` transitions to
6
+ * "pending_admin_approval" (a buyer's "Request to sell"). Notifies every
7
+ * admin so the approvals queue doesn't go unnoticed. Kept out of the
8
+ * synchronous submit action per Rule #6 — the buyer-facing request stays
9
+ * fast regardless of how many admins there are to fan out to.
10
+ */
11
+ export async function handleCatalogueSubmittedForApproval(event, ctx) {
12
+ const becamePending = event.before.listingStatus !== "pending_admin_approval" &&
13
+ event.after.listingStatus === "pending_admin_approval";
14
+ if (!becamePending)
15
+ return;
16
+ const admins = await userRepository.findByRole("admin");
17
+ for (const admin of admins) {
18
+ try {
19
+ await sendNotification({
20
+ userId: admin.uid,
21
+ type: "system",
22
+ priority: "normal",
23
+ title: "New catalogue listing request",
24
+ message: `"${event.after.title}" was submitted for approval to list under LetItRip Official.`,
25
+ actionUrl: "/admin/catalogue-approvals",
26
+ actionLabel: "Review request",
27
+ relatedId: event.itemId,
28
+ });
29
+ }
30
+ catch (err) {
31
+ void normalizeError(err);
32
+ ctx.logger.error("onCatalogueSubmittedForApproval: failed to notify admin", {
33
+ itemId: event.itemId,
34
+ adminUid: admin.uid,
35
+ });
36
+ }
37
+ }
38
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Core: `jobs/{jobId}` document-created trigger.
3
+ *
4
+ * This is the single dispatch point for the async-job primitive
5
+ * (CLAUDE.md Rule #6 — Vercel routes never do heavy work; they write a
6
+ * `jobs` doc and return, this Function does the actual processing).
7
+ *
8
+ * Flow:
9
+ * 1. Mark the job "processing".
10
+ * 2. Look up a runner in `JOB_RUNNERS` by `job.jobType`.
11
+ * 3. Run it, mark the job "done"/"failed", and best-effort ping the
12
+ * `bulk_events/{jobId}` RTDB channel the client is subscribed to via
13
+ * `useBulkEvent` — every RTDB write is its own try/catch so a ping
14
+ * failure never masks the real Firestore result.
15
+ */
16
+ import type { JobDocument } from "../../../../features/jobs/schemas/firestore";
17
+ import type { JobContext } from "../runtime/types";
18
+ export interface HandleJobCreatedInput {
19
+ jobId: string;
20
+ job: JobDocument;
21
+ }
22
+ export declare function handleJobCreated(input: HandleJobCreatedInput, ctx: JobContext): Promise<void>;
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Core: `jobs/{jobId}` document-created trigger.
3
+ *
4
+ * This is the single dispatch point for the async-job primitive
5
+ * (CLAUDE.md Rule #6 — Vercel routes never do heavy work; they write a
6
+ * `jobs` doc and return, this Function does the actual processing).
7
+ *
8
+ * Flow:
9
+ * 1. Mark the job "processing".
10
+ * 2. Look up a runner in `JOB_RUNNERS` by `job.jobType`.
11
+ * 3. Run it, mark the job "done"/"failed", and best-effort ping the
12
+ * `bulk_events/{jobId}` RTDB channel the client is subscribed to via
13
+ * `useBulkEvent` — every RTDB write is its own try/catch so a ping
14
+ * failure never masks the real Firestore result.
15
+ */
16
+ import { normalizeError } from "../../../../errors/normalize";
17
+ import { jobsRepository } from "../../../../repositories";
18
+ import { getAdminRealtimeDb } from "../../../../providers/db-firebase";
19
+ import { RTDB_PATHS } from "../../../../providers/db-firebase/rtdb-paths";
20
+ import { JOB_RUNNERS } from "./jobRunners";
21
+ async function pingBulkEvent(jobId, payload, ctx) {
22
+ try {
23
+ await getAdminRealtimeDb()
24
+ .ref(`${RTDB_PATHS.BULK_EVENTS}/${jobId}`)
25
+ .set({ ...payload, updatedAt: Date.now() });
26
+ }
27
+ catch (err) {
28
+ void normalizeError(err);
29
+ ctx.logger.warn("onJobCreated: RTDB ping failed (non-fatal)", {
30
+ jobId,
31
+ error: err instanceof Error ? err.message : String(err),
32
+ });
33
+ }
34
+ }
35
+ export async function handleJobCreated(input, ctx) {
36
+ const { jobId, job } = input;
37
+ await jobsRepository.markProcessing(jobId);
38
+ const runner = JOB_RUNNERS[job.jobType];
39
+ if (!runner) {
40
+ const error = `Unknown jobType: ${job.jobType}`;
41
+ await jobsRepository.markFailed(jobId, error);
42
+ await pingBulkEvent(jobId, { status: "failed", action: job.jobType, error }, ctx);
43
+ ctx.logger.error("onJobCreated: unknown jobType", null, { jobId, jobType: job.jobType });
44
+ return;
45
+ }
46
+ try {
47
+ const result = await runner(job.payload, ctx);
48
+ await jobsRepository.markDone(jobId, result);
49
+ await pingBulkEvent(jobId, { status: "success", action: job.jobType, ...result }, ctx);
50
+ ctx.logger.info("onJobCreated: job complete", { jobId, jobType: job.jobType, summary: result.summary });
51
+ }
52
+ catch (err) {
53
+ void normalizeError(err);
54
+ const message = err instanceof Error ? err.message : String(err);
55
+ await jobsRepository.markFailed(jobId, message);
56
+ await pingBulkEvent(jobId, { status: "failed", action: job.jobType, error: message }, ctx);
57
+ ctx.logger.error("onJobCreated: job failed", err, { jobId, jobType: job.jobType });
58
+ }
59
+ }
@@ -3,4 +3,9 @@
3
3
  * `payoutStatus=eligible` into pending payout documents grouped by seller.
4
4
  */
5
5
  import type { JobContext } from "../runtime/types";
6
- export declare function runWeeklyPayoutEligibility(ctx: JobContext): Promise<void>;
6
+ export interface WeeklyPayoutEligibilityResult {
7
+ payoutsCreated: number;
8
+ ordersProcessed: number;
9
+ payoutIds: string[];
10
+ }
11
+ export declare function runWeeklyPayoutEligibility(ctx: JobContext): Promise<WeeklyPayoutEligibilityResult>;
@@ -9,7 +9,7 @@ import { computePayoutDeduction } from "../../../shared/fees/calculator";
9
9
  export async function runWeeklyPayoutEligibility(ctx) {
10
10
  if (ctx.env("FEATURE_PAYOUTS") !== "true") {
11
11
  ctx.logger.info("FEATURE_PAYOUTS disabled — skipping weekly payout eligibility");
12
- return;
12
+ return { payoutsCreated: 0, ordersProcessed: 0, payoutIds: [] };
13
13
  }
14
14
  ctx.logger.info("Starting weekly payout eligibility sweep");
15
15
  const siteSettings = await siteSettingsRepository.getSingleton();
@@ -17,7 +17,7 @@ export async function runWeeklyPayoutEligibility(ctx) {
17
17
  const eligible = await orderRepository.getEligibleForPayoutSweep();
18
18
  if (eligible.length === 0) {
19
19
  ctx.logger.info("No eligible delivered orders found");
20
- return;
20
+ return { payoutsCreated: 0, ordersProcessed: 0, payoutIds: [] };
21
21
  }
22
22
  ctx.logger.info(`Found ${eligible.length} eligible order(s) — grouping by seller`);
23
23
  const byStore = new Map();
@@ -33,6 +33,7 @@ export async function runWeeklyPayoutEligibility(ctx) {
33
33
  }
34
34
  let payoutsCreated = 0;
35
35
  let ordersProcessed = 0;
36
+ const payoutIds = [];
36
37
  const defaultCurrency = getDefaultCurrency();
37
38
  for (const [storeId, orders] of byStore.entries()) {
38
39
  const store = await storeRepository.findBySlug(storeId);
@@ -82,6 +83,7 @@ export async function runWeeklyPayoutEligibility(ctx) {
82
83
  }
83
84
  payoutsCreated++;
84
85
  ordersProcessed += orders.length;
86
+ payoutIds.push(payoutId);
85
87
  ctx.logger.info(`Payout created for store ${storeId}`, {
86
88
  payoutId,
87
89
  orderCount: orders.length,
@@ -91,4 +93,5 @@ export async function runWeeklyPayoutEligibility(ctx) {
91
93
  });
92
94
  }
93
95
  ctx.logger.info("Weekly payout eligibility sweep complete", { payoutsCreated, ordersProcessed });
96
+ return { payoutsCreated, ordersProcessed, payoutIds };
94
97
  }
@@ -0,0 +1,2 @@
1
+ import type { ScheduleHandler } from "../runtime/types";
2
+ export declare const catalogueImageStalenessReminderHandler: ScheduleHandler;
@@ -0,0 +1,2 @@
1
+ import { runCatalogueImageStalenessReminder } from "../core/catalogueImageStalenessReminder";
2
+ export const catalogueImageStalenessReminderHandler = runCatalogueImageStalenessReminder;
@@ -19,6 +19,7 @@ export { countersReconcileHandler } from "./countersReconcile";
19
19
  export { onOrderCreateHandler } from "./onOrderCreate";
20
20
  export { onOrderStatusChangeHandler } from "./onOrderStatusChange";
21
21
  export { onBidPlacedHandler } from "./onBidPlaced";
22
+ export { onJobCreatedHandler } from "./onJobCreated";
22
23
  export { onReviewWriteHandler } from "./onReviewWrite";
23
24
  export { promotionsHandler, type PromotionsCallableResult } from "./promotions";
24
25
  export { mediaTmpCleanupHandler } from "./mediaTmpCleanup";
@@ -48,3 +49,8 @@ export { onScamReportCreateHandler } from "./onScamReportCreate";
48
49
  export { onScamReportUpdateHandler } from "./onScamReportUpdate";
49
50
  export { draftPruneHandler } from "./draftPrune";
50
51
  export { emiInstallmentReminderHandler } from "./emiInstallmentReminder";
52
+ export { onShipmentItemWriteHandler } from "./onShipmentItemWrite";
53
+ export { onShipmentLotWriteHandler, onShipmentHeaderWriteHandler } from "./onShipmentAllocationSync";
54
+ export { onShipmentDeletedHandler } from "./onShipmentDeleted";
55
+ export { catalogueImageStalenessReminderHandler } from "./catalogueImageStalenessReminder";
56
+ export { onCatalogueSubmittedForApprovalHandler } from "./onCatalogueSubmittedForApproval";
@@ -19,6 +19,7 @@ export { countersReconcileHandler } from "./countersReconcile";
19
19
  export { onOrderCreateHandler } from "./onOrderCreate";
20
20
  export { onOrderStatusChangeHandler } from "./onOrderStatusChange";
21
21
  export { onBidPlacedHandler } from "./onBidPlaced";
22
+ export { onJobCreatedHandler } from "./onJobCreated";
22
23
  export { onReviewWriteHandler } from "./onReviewWrite";
23
24
  export { promotionsHandler } from "./promotions";
24
25
  export { mediaTmpCleanupHandler } from "./mediaTmpCleanup";
@@ -57,3 +58,10 @@ export { onScamReportUpdateHandler } from "./onScamReportUpdate";
57
58
  export { draftPruneHandler } from "./draftPrune";
58
59
  // EMI — installment reminder + overdue-flagging sweep
59
60
  export { emiInstallmentReminderHandler } from "./emiInstallmentReminder";
61
+ // Procurement Shipments — 3-function recompute cascade (item→lot, lot/header→shipment allocation, cascade-delete)
62
+ export { onShipmentItemWriteHandler } from "./onShipmentItemWrite";
63
+ export { onShipmentLotWriteHandler, onShipmentHeaderWriteHandler } from "./onShipmentAllocationSync";
64
+ export { onShipmentDeletedHandler } from "./onShipmentDeleted";
65
+ // Personal Catalogue (Feature B) — freshness reminder + admin approval-request notification
66
+ export { catalogueImageStalenessReminderHandler } from "./catalogueImageStalenessReminder";
67
+ export { onCatalogueSubmittedForApprovalHandler } from "./onCatalogueSubmittedForApproval";
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Fires on any write to catalogueItems/{itemId} where listingStatus
3
+ * transitions into "pending_admin_approval" (the buyer "Request to sell"
4
+ * action). Sends one admin-inbox notification — kept out of the fast
5
+ * user-facing action per Rule #6, so the buyer's request doesn't wait on
6
+ * how many admins exist.
7
+ */
8
+ import type { FirestoreTriggerHandler } from "../runtime/types";
9
+ import type { JsonValue } from "@mohasinac/appkit";
10
+ type Doc = Record<string, JsonValue>;
11
+ export declare const onCatalogueSubmittedForApprovalHandler: FirestoreTriggerHandler<Doc, Doc>;
12
+ export {};
@@ -0,0 +1,20 @@
1
+ import { adminNotificationsRepository } from "../../../../repositories";
2
+ export const onCatalogueSubmittedForApprovalHandler = async (event, ctx) => {
3
+ const before = event.before?.listingStatus;
4
+ const after = event.after?.listingStatus;
5
+ if (before === "pending_admin_approval" || after !== "pending_admin_approval")
6
+ return;
7
+ const itemId = event.params.itemId ?? event.after?.id;
8
+ const title = event.after?.title ?? "Untitled item";
9
+ await adminNotificationsRepository.create({
10
+ category: "moderation",
11
+ title: "Catalogue listing pending approval",
12
+ body: `A buyer requested "${title}" be listed on their behalf.`,
13
+ severity: "info",
14
+ isRead: false,
15
+ entityType: "catalogueItem",
16
+ entityId: itemId,
17
+ audienceUserIds: [],
18
+ createdAt: ctx.now,
19
+ });
20
+ };
@@ -0,0 +1,3 @@
1
+ import type { FirestoreTriggerHandler } from "../runtime/types";
2
+ import type { JobDocument } from "../../../../features/jobs/schemas/firestore";
3
+ export declare const onJobCreatedHandler: FirestoreTriggerHandler<null, JobDocument>;
@@ -0,0 +1,9 @@
1
+ import { handleJobCreated } from "../core/onJobCreated";
2
+ export const onJobCreatedHandler = async (event, ctx) => {
3
+ const job = event.after;
4
+ if (!job) {
5
+ ctx.logger.error("No snapshot data", null);
6
+ return;
7
+ }
8
+ await handleJobCreated({ jobId: event.params.jobId, job }, ctx);
9
+ };
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Function #2 of the procurement-shipments cascade — the allocation engine.
3
+ *
4
+ * Fires on:
5
+ * (a) any write to shipmentLots/{lotId} (itemCount/revenue changed via
6
+ * Function #1, or the admin edited weight/cost/remainder fields)
7
+ * (b) any write to procurementShipments/{shipmentId} (admin edited
8
+ * customsTotalPaise/shippingTotalPaise/laborHoursSpent/status)
9
+ *
10
+ * Both re-run the same cross-lot allocation: read every sibling lot
11
+ * (bounded ≤10), call the shared pure allocateShipmentCosts(), batch-write
12
+ * each lot's customsAllocatedPaise/shippingAllocatedPaise/totalLandedCostPaise/
13
+ * projectedRevenuePaise/projectedProfitPaise plus the shipment's persisted
14
+ * `totals` + `totalsComputedAt`. Also keeps ShipmentLot.shipmentStatus in
15
+ * sync with its parent so the Projections list can filter on it directly.
16
+ *
17
+ * Skips writes that would be no-ops (value-identical) so the cascade
18
+ * terminates instead of re-triggering itself indefinitely.
19
+ */
20
+ import type { FirestoreTriggerHandler } from "../runtime/types";
21
+ import type { JsonValue } from "@mohasinac/appkit";
22
+ type Doc = Record<string, JsonValue>;
23
+ export declare const onShipmentLotWriteHandler: FirestoreTriggerHandler<Doc, Doc>;
24
+ export declare const onShipmentHeaderWriteHandler: FirestoreTriggerHandler<Doc, Doc>;
25
+ export {};