@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
@@ -8,7 +8,7 @@ import { MediaImage } from "../../../../features/media/MediaImage";
8
8
  import { ROUTES } from "../../../../next/routing/route-map";
9
9
  import { formatCurrency } from "../../../../utils/number.formatter";
10
10
  const __P = {
11
- p4: "p-4",
11
+ p4: "p-[var(--appkit-space-4)]",
12
12
  };
13
13
  const __O = {
14
14
  hidden: "overflow-hidden",
@@ -4,7 +4,7 @@ import { normalizeError } from "../../../../errors/normalize";
4
4
  import { useState } from "react";
5
5
  import { Button, Div, Row, Span, Stack, Text } from "../../../../ui";
6
6
  const __P = {
7
- p4: "p-4",
7
+ p4: "p-[var(--appkit-space-4)]",
8
8
  };
9
9
  export function CodeRevealPanel({ orderId, redemptionInstructions, fetchCode, }) {
10
10
  const [pending, setPending] = useState(false);
@@ -5,7 +5,7 @@ import { MediaImage } from "../../../../features/media/MediaImage";
5
5
  import { formatCurrency } from "../../../../utils/number.formatter";
6
6
  import { CodeRevealPanel } from "./CodeRevealPanel";
7
7
  const __P = {
8
- p4: "p-4",
8
+ p4: "p-[var(--appkit-space-4)]",
9
9
  };
10
10
  const __O = {
11
11
  hidden: "overflow-hidden",
@@ -11,6 +11,7 @@
11
11
  */
12
12
  import { apiClient } from "../../../../http/ApiClient";
13
13
  import { normalizeError } from "../../../../errors/normalize";
14
+ import { ADMIN_ENDPOINTS, CATEGORY_ENDPOINTS, BRAND_ENDPOINTS } from "../../../../constants/api-endpoints";
14
15
  const PAGE_SIZE = 25;
15
16
  function buildUrl(base, q, page, extra) {
16
17
  const params = new URLSearchParams({
@@ -41,7 +42,7 @@ async function fetchPage(url, mapItem) {
41
42
  * @param categoryType Optional filter to narrow to a specific category type (e.g. "brand").
42
43
  */
43
44
  export function makeCategoryLoadOptions(variant = "admin", categoryType) {
44
- const base = variant === "admin" ? "/api/admin/categories" : "/api/categories";
45
+ const base = variant === "admin" ? ADMIN_ENDPOINTS.CATEGORIES : CATEGORY_ENDPOINTS.LIST;
45
46
  return async (q, page) => fetchPage(buildUrl(base, q, page, categoryType ? { categoryType } : undefined), (item) => ({
46
47
  value: String(item.id ?? item.slug ?? ""),
47
48
  label: String(item.name ?? item.id ?? ""),
@@ -49,7 +50,7 @@ export function makeCategoryLoadOptions(variant = "admin", categoryType) {
49
50
  }));
50
51
  }
51
52
  export function makeCategoryFacetLoadOptions(variant = "public", categoryType) {
52
- const base = variant === "admin" ? "/api/admin/categories" : "/api/categories";
53
+ const base = variant === "admin" ? ADMIN_ENDPOINTS.CATEGORIES : CATEGORY_ENDPOINTS.LIST;
53
54
  return async (q, page) => fetchPage(buildUrl(base, q, page, categoryType ? { categoryType } : undefined), (item) => ({
54
55
  value: String(item.id ?? item.slug ?? ""),
55
56
  label: String(item.name ?? item.id ?? ""),
@@ -57,7 +58,7 @@ export function makeCategoryFacetLoadOptions(variant = "public", categoryType) {
57
58
  }
58
59
  // ── Brands ────────────────────────────────────────────────────────────────────
59
60
  export function makeBrandLoadOptions(variant = "admin") {
60
- const base = variant === "admin" ? "/api/admin/brands" : "/api/brands";
61
+ const base = variant === "admin" ? ADMIN_ENDPOINTS.BRANDS : BRAND_ENDPOINTS.LIST;
61
62
  return async (q, page) => fetchPage(buildUrl(base, q, page), (item) => ({
62
63
  value: String(item.id ?? item.slug ?? ""),
63
64
  label: String(item.name ?? item.id ?? ""),
@@ -65,7 +66,7 @@ export function makeBrandLoadOptions(variant = "admin") {
65
66
  }));
66
67
  }
67
68
  export function makeBrandFacetLoadOptions(variant = "public") {
68
- const base = variant === "admin" ? "/api/admin/brands" : "/api/brands";
69
+ const base = variant === "admin" ? ADMIN_ENDPOINTS.BRANDS : BRAND_ENDPOINTS.LIST;
69
70
  return async (q, page) => fetchPage(buildUrl(base, q, page), (item) => ({
70
71
  value: String(item.id ?? item.slug ?? ""),
71
72
  label: String(item.name ?? item.id ?? ""),
@@ -73,21 +74,21 @@ export function makeBrandFacetLoadOptions(variant = "public") {
73
74
  }
74
75
  // ── Stores ────────────────────────────────────────────────────────────────────
75
76
  export function makeStoreLoadOptions() {
76
- return async (q, page) => fetchPage(buildUrl("/api/admin/stores", q, page), (item) => ({
77
+ return async (q, page) => fetchPage(buildUrl(ADMIN_ENDPOINTS.STORES, q, page), (item) => ({
77
78
  value: String(item.id ?? item.slug ?? ""),
78
79
  label: String(item.storeName ?? item.name ?? item.id ?? ""),
79
80
  meta: item,
80
81
  }));
81
82
  }
82
83
  export function makeStoreFacetLoadOptions() {
83
- return async (q, page) => fetchPage(buildUrl("/api/admin/stores", q, page), (item) => ({
84
+ return async (q, page) => fetchPage(buildUrl(ADMIN_ENDPOINTS.STORES, q, page), (item) => ({
84
85
  value: String(item.id ?? item.slug ?? ""),
85
86
  label: String(item.storeName ?? item.name ?? item.id ?? ""),
86
87
  }));
87
88
  }
88
89
  // ── Products ──────────────────────────────────────────────────────────────────
89
90
  export function makeProductLoadOptions(storeId) {
90
- return async (q, page) => fetchPage(buildUrl("/api/admin/products", q, page, storeId ? { storeId } : undefined), (item) => ({
91
+ return async (q, page) => fetchPage(buildUrl(ADMIN_ENDPOINTS.PRODUCTS, q, page, storeId ? { storeId } : undefined), (item) => ({
91
92
  value: String(item.id ?? item.slug ?? ""),
92
93
  label: String(item.title ?? item.name ?? item.id ?? ""),
93
94
  meta: item,
@@ -95,7 +96,7 @@ export function makeProductLoadOptions(storeId) {
95
96
  }
96
97
  // ── Users ─────────────────────────────────────────────────────────────────────
97
98
  export function makeUserLoadOptions(role) {
98
- return async (q, page) => fetchPage(buildUrl("/api/admin/users", q, page, role ? { role } : undefined), (item) => ({
99
+ return async (q, page) => fetchPage(buildUrl(ADMIN_ENDPOINTS.USERS, q, page, role ? { role } : undefined), (item) => ({
99
100
  value: String(item.id ?? item.uid ?? ""),
100
101
  label: String(item.displayName ?? item.email ?? item.id ?? ""),
101
102
  meta: item,
@@ -103,7 +104,7 @@ export function makeUserLoadOptions(role) {
103
104
  }
104
105
  // ── Addresses ─────────────────────────────────────────────────────────────────
105
106
  export function makeAddressLoadOptions(ownerType) {
106
- return async (q, page) => fetchPage(buildUrl("/api/admin/addresses", q, page, ownerType ? { ownerType } : undefined), (item) => ({
107
+ return async (q, page) => fetchPage(buildUrl(ADMIN_ENDPOINTS.ADDRESSES, q, page, ownerType ? { ownerType } : undefined), (item) => ({
107
108
  value: String(item.id ?? ""),
108
109
  label: [item.label, item.city, item.state].filter(Boolean).join(", "),
109
110
  meta: item,
@@ -20,6 +20,7 @@
20
20
  */
21
21
  import { type ReactNode } from "react";
22
22
  import type { DashboardVariant, SidebarNavGroup, SectionResponsive } from "../../../shared/features/layout/types";
23
+ import { type BackgroundConfig } from "../../../../ui";
23
24
  export interface DashboardLayoutClientProps {
24
25
  /** Drives sidebar component selection + accent colour. */
25
26
  variant: DashboardVariant;
@@ -46,6 +47,10 @@ export interface DashboardLayoutClientProps {
46
47
  contentSurface?: string;
47
48
  /** Override the max-width class on the inner content wrapper. */
48
49
  contentMaxWidth?: string;
50
+ /** Background rendered behind the sidebar + content when the light theme is active. Mirrors `AppLayoutShell`'s prop of the same shape. */
51
+ lightBackground?: BackgroundConfig;
52
+ /** Background rendered behind the sidebar + content when the dark theme is active. */
53
+ darkBackground?: BackgroundConfig;
49
54
  children: ReactNode;
50
55
  }
51
- export declare function DashboardLayoutClient({ variant, groups, permissions, activeHref: explicitActiveHref, responsive: _responsive, className, contentPadding, contentSurface, contentMaxWidth, children, }: DashboardLayoutClientProps): import("react").JSX.Element;
56
+ export declare function DashboardLayoutClient({ variant, groups, permissions, activeHref: explicitActiveHref, responsive: _responsive, className, contentPadding, contentSurface, contentMaxWidth, lightBackground, darkBackground, children, }: DashboardLayoutClientProps): import("react").JSX.Element;
@@ -30,7 +30,8 @@ import { UserSidebar } from "../../../../features/account/components/UserSidebar
30
30
  import { DASHBOARD_DESKTOP_MEDIA_QUERY } from "../../../shared/features/layout/config";
31
31
  import { filterNavItems } from "./filterNavItems";
32
32
  import { useSiteSettings } from "../../../../core/hooks/useSiteSettings";
33
- import { Div } from "../../../../ui";
33
+ import { useTheme } from "../../theme";
34
+ import { BackgroundRenderer, Div } from "../../../../ui";
34
35
  /**
35
36
  * Hoisted drawer-state hook — the matchMedia-aware open/close logic that was
36
37
  * triplicated across admin/store/user layouts. Used internally by
@@ -124,9 +125,9 @@ function filterGroups(groups, navConfig, permissions) {
124
125
  }))
125
126
  .filter((group) => group.items.length > 0);
126
127
  }
127
- const DEFAULT_CONTENT_PADDING = "px-5 py-8 lg:pl-14 lg:pr-6 xl:pl-16 xl:pr-10";
128
+ const DEFAULT_CONTENT_PADDING = "px-[var(--appkit-space-5)] py-[var(--appkit-space-8)] lg:pl-14 lg:pr-6 xl:pl-16 xl:pr-10";
128
129
  const DEFAULT_CONTENT_MAX_WIDTH = "max-w-screen-2xl";
129
- export function DashboardLayoutClient({ variant, groups, permissions, activeHref: explicitActiveHref, responsive: _responsive, className, contentPadding, contentSurface, contentMaxWidth, children, }) {
130
+ export function DashboardLayoutClient({ variant, groups, permissions, activeHref: explicitActiveHref, responsive: _responsive, className, contentPadding, contentSurface, contentMaxWidth, lightBackground, darkBackground, children, }) {
130
131
  const pathname = usePathname();
131
132
  const activeHref = explicitActiveHref ?? pathname ?? "";
132
133
  const storageKey = `appkit:sidebar-open:${variant}`;
@@ -134,11 +135,17 @@ export function DashboardLayoutClient({ variant, groups, permissions, activeHref
134
135
  useEffect(() => { closeMobile(); }, [pathname, closeMobile]);
135
136
  const { data: settings } = useSiteSettings();
136
137
  const navConfig = settings?.navConfig;
138
+ const { theme } = useTheme();
139
+ // Explicit props win; otherwise fall back to the same siteSettings.background
140
+ // the public shell reads, so admin/store/user dashboards match it by default.
141
+ const resolvedLightBackground = lightBackground ?? settings?.background?.light;
142
+ const resolvedDarkBackground = darkBackground ?? settings?.background?.dark;
143
+ const hasBackground = Boolean(resolvedLightBackground?.value || resolvedDarkBackground?.value);
137
144
  const filteredGroups = filterGroups(groups, navConfig, permissions);
138
145
  const adminGroups = variant === "admin"
139
146
  ? filteredGroups
140
147
  : groups;
141
- return (_jsxs(_Fragment, { children: [variant === "admin" && (_jsx(AdminSidebar, { variant: "sidebar", desktopOpen: desktopOpen, mobileOpen: mobileOpen, activePath: activeHref, groups: adminGroups, onCloseMobile: close, onToggle: toggle, className: className })), variant === "store" && (_jsx(StoreSidebar, { variant: "sidebar", desktopOpen: desktopOpen, mobileOpen: mobileOpen, activeHref: activeHref, items: [], groups: filteredGroups, onCloseMobile: close, onToggle: toggle, className: className })), variant === "user" && (_jsx(UserSidebar, { variant: "sidebar", desktopOpen: desktopOpen, mobileOpen: mobileOpen, items: filteredGroups.flatMap((g) => g.items), groups: filteredGroups, onCloseMobile: close, onToggle: toggle, className: className })), _jsx(Div, { className: [
148
+ return (_jsxs(_Fragment, { children: [hasBackground && (_jsx(BackgroundRenderer, { mode: theme === "dark" ? "dark" : "light", lightMode: resolvedLightBackground ?? { type: "color", value: "" }, darkMode: resolvedDarkBackground ?? { type: "color", value: "" } })), variant === "admin" && (_jsx(AdminSidebar, { variant: "sidebar", desktopOpen: desktopOpen, mobileOpen: mobileOpen, activePath: activeHref, groups: adminGroups, onCloseMobile: close, onToggle: toggle, className: className })), variant === "store" && (_jsx(StoreSidebar, { variant: "sidebar", desktopOpen: desktopOpen, mobileOpen: mobileOpen, activeHref: activeHref, items: [], groups: filteredGroups, onCloseMobile: close, onToggle: toggle, className: className })), variant === "user" && (_jsx(UserSidebar, { variant: "sidebar", desktopOpen: desktopOpen, mobileOpen: mobileOpen, items: filteredGroups.flatMap((g) => g.items), groups: filteredGroups, onCloseMobile: close, onToggle: toggle, className: className })), _jsx(Div, { className: [
142
149
  "w-full flex-1 flex flex-col min-h-[calc(100dvh-var(--header-height,3.5rem))]",
143
150
  contentPadding ?? DEFAULT_CONTENT_PADDING,
144
151
  contentSurface,
@@ -4,12 +4,12 @@ import { Badge, Container, Div, Heading, Row, Section, Stack, Text, } from "../.
4
4
  import { MediaImage } from "../../../../features/media/MediaImage";
5
5
  import { formatCurrency } from "../../../../utils/number.formatter";
6
6
  const __P = {
7
- p4: "p-4",
7
+ p4: "p-[var(--appkit-space-4)]",
8
8
  };
9
9
  const __O = {
10
10
  hidden: "overflow-hidden",
11
11
  };
12
- const CLS_WARN_BOX = "rounded-lg border border-warning bg-warning-surface p-4 text-sm";
12
+ const CLS_WARN_BOX = "rounded-lg border border-warning bg-warning-surface p-[var(--appkit-space-4)] text-[length:var(--appkit-text-sm)]";
13
13
  const CLS_WARN_TITLE = "font-medium text-warning";
14
14
  const CLS_WARN_BODY = "mt-1 text-warning";
15
15
  export function LiveItemDetailView({ product, isLoading = false, renderActions, }) {
@@ -2,7 +2,9 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { normalizeError } from "../../../../../errors/normalize";
4
4
  import * as React from "react";
5
- import { Button, Div, Heading, Li, Section, Span, Table, Tbody, Td, Text, Th, Thead, Tr, Ul } from "@mohasinac/appkit";
5
+ import { Button, Div, Heading, Input, Li, Section, Span, Table, Tbody, Td, Text, Th, Thead, Tr, Ul } from "@mohasinac/appkit";
6
+ import { Select } from "@mohasinac/appkit/ui";
7
+ import { ADMIN_ENDPOINTS } from "../../../../../constants/api-endpoints";
6
8
  export function AnalysisRunnerView() {
7
9
  const [days, setDays] = React.useState(7);
8
10
  const [source, setSource] = React.useState("all");
@@ -13,7 +15,7 @@ export function AnalysisRunnerView() {
13
15
  setRunning(true);
14
16
  setError(null);
15
17
  try {
16
- const res = await fetch("/api/admin/maintenance/analysis", {
18
+ const res = await fetch(ADMIN_ENDPOINTS.MAINTENANCE_ANALYSIS, {
17
19
  method: "POST",
18
20
  headers: { "Content-Type": "application/json" },
19
21
  body: JSON.stringify({ days, source }),
@@ -34,7 +36,12 @@ export function AnalysisRunnerView() {
34
36
  setRunning(false);
35
37
  }
36
38
  }
37
- return (_jsxs(Div, { style: { padding: "1.5rem", maxWidth: "1200px", margin: "0 auto" }, children: [_jsx(Heading, { level: 1, style: { fontSize: "1.5rem", fontWeight: 600 }, children: "Maintenance analysis" }), _jsxs(Div, { style: { display: "flex", gap: "1rem", alignItems: "center", margin: "1rem 0" }, children: [_jsxs("label", { children: ["Days back:\u00A0", _jsx("input", { type: "number", min: 1, max: 30, value: days, onChange: (e) => setDays(Math.max(1, Math.min(30, Number(e.target.value) || 7))), style: { width: 80, padding: "0.35rem 0.5rem", border: "1px solid var(--appkit-color-border)", borderRadius: 4 } })] }), _jsxs("label", { children: ["Source:\u00A0", _jsxs("select", { value: source, onChange: (e) => setSource(e.target.value), style: { padding: "0.35rem 0.5rem", border: "1px solid var(--appkit-color-border)", borderRadius: 4 }, children: [_jsx("option", { value: "all", children: "all" }), _jsx("option", { value: "vercel", children: "server (vercel)" }), _jsx("option", { value: "client", children: "client" }), _jsx("option", { value: "function", children: "function" })] })] }), _jsx(Button, { type: "button", onClick: run, isLoading: running, children: "Run analysis" })] }), error ? _jsx(Text, { as: "p", style: { color: "var(--appkit-color-error)" }, children: error }) : null, report ? _jsx(ReportView, { report: report }) : null] }));
39
+ return (_jsxs(Div, { style: { padding: "1.5rem", maxWidth: "1200px", margin: "0 auto" }, children: [_jsx(Heading, { level: 1, style: { fontSize: "1.5rem", fontWeight: 600 }, children: "Maintenance analysis" }), _jsxs(Div, { style: { display: "flex", gap: "1rem", alignItems: "center", margin: "1rem 0" }, children: [_jsxs("label", { children: ["Days back:\u00A0", _jsx(Input, { bare: true, type: "number", min: 1, max: 30, value: days, onChange: (e) => setDays(Math.max(1, Math.min(30, Number(e.target.value) || 7))), style: { width: 80, padding: "0.35rem 0.5rem", border: "1px solid var(--appkit-color-border)", borderRadius: 4 } })] }), _jsxs("label", { children: ["Source:\u00A0", _jsx(Select, { options: [
40
+ { value: "all", label: "all" },
41
+ { value: "vercel", label: "server (vercel)" },
42
+ { value: "client", label: "client" },
43
+ { value: "function", label: "function" },
44
+ ], value: source, onValueChange: (v) => setSource(v), style: { padding: "0.35rem 0.5rem", border: "1px solid var(--appkit-color-border)", borderRadius: 4 } })] }), _jsx(Button, { type: "button", onClick: run, isLoading: running, children: "Run analysis" })] }), error ? _jsx(Text, { as: "p", style: { color: "var(--appkit-color-error)" }, children: error }) : null, report ? _jsx(ReportView, { report: report }) : null] }));
38
45
  }
39
46
  function ReportView({ report }) {
40
47
  return (_jsxs(Div, { children: [_jsxs(Text, { as: "p", style: { color: "var(--appkit-color-text-muted)" }, children: ["Generated ", report.generatedAt, ". Window: ", report.window.days, "d. Total: ", report.totalErrors, ". Unique users: ", report.uniqueUsers, "."] }), _jsx(ReportSection, { title: "Top codes", children: _jsxs(Table, { style: { width: "100%", fontSize: "0.85rem" }, children: [_jsx(Thead, { children: _jsxs(Tr, { children: [_jsx(Th, { align: "left", children: "Code" }), _jsx(Th, { align: "right", children: "Count" }), _jsx(Th, { align: "right", children: "User impact" })] }) }), _jsx(Tbody, { children: report.topCodes.map((c) => (_jsxs(Tr, { children: [_jsx(Td, { style: { fontFamily: "monospace" }, children: c.code }), _jsx(Td, { align: "right", children: c.count }), _jsx(Td, { align: "right", children: c.userImpact })] }, c.code))) })] }) }), _jsx(ReportSection, { title: "Top routes", children: _jsxs(Table, { style: { width: "100%", fontSize: "0.85rem" }, children: [_jsx(Thead, { children: _jsxs(Tr, { children: [_jsx(Th, { align: "left", children: "Route" }), _jsx(Th, { align: "left", children: "Source" }), _jsx(Th, { align: "right", children: "Count" })] }) }), _jsx(Tbody, { children: report.topRoutes.map((r) => (_jsxs(Tr, { children: [_jsx(Td, { style: { fontFamily: "monospace" }, children: r.route }), _jsx(Td, { children: r.source }), _jsx(Td, { align: "right", children: r.count })] }, `${r.source}:${r.route}`))) })] }) }), report.stackClusters.length > 0 ? (_jsx(ReportSection, { title: `Stack clusters (≥5)`, children: _jsx(Ul, { children: report.stackClusters.map((c) => (_jsxs(Li, { style: { marginBottom: "0.5rem", fontSize: "0.82rem" }, children: [_jsxs(Span, { weight: "bold", children: [c.count, "\u00D7"] }), " ", _jsx(Span, { style: { fontFamily: "monospace" }, children: c.signature }), _jsxs(Div, { style: { color: "var(--appkit-color-text-muted)" }, children: ["sample: ", c.sampleMessage] })] }, c.signature))) }) })) : null, report.burstWindows.length > 0 ? (_jsx(ReportSection, { title: "5xx burst windows", children: _jsx(Ul, { children: report.burstWindows.map((b) => (_jsxs(Li, { children: [b.start, " \u2014 ", b.count, " errors (", b.multiplier, "\u00D7 avg)"] }, b.start))) }) })) : null, _jsx(ReportSection, { title: "Recommendations", children: _jsx(Ul, { children: report.recommendations.map((r, i) => _jsx(Li, { children: r }, i)) }) })] }));
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
- import { Anchor, Div, Heading, Label, Span, Table, Tbody, Td, Text, Th, Thead, Tr } from "@mohasinac/appkit";
4
+ import { Anchor, Div, Heading, Input, Label, Span, Table, Tbody, Td, Text, Th, Thead, Tr } from "@mohasinac/appkit";
5
5
  const BORDER_STYLE = "1px solid var(--appkit-color-border)";
6
6
  const COLUMNS = [
7
7
  { key: "occurredAtFmt", label: "When", width: "180px" },
@@ -25,7 +25,7 @@ export function ServerErrorsListView({ title, subtitle, source, rows, detailHref
25
25
  return rows.filter((r) => (!codeFilter || r.code.toLowerCase().includes(codeFilter.toLowerCase())) &&
26
26
  (!routeFilter || r.route.toLowerCase().includes(routeFilter.toLowerCase())));
27
27
  }, [rows, codeFilter, routeFilter]);
28
- return (_jsxs(Div, { style: { padding: "1.5rem", maxWidth: "1400px", margin: "0 auto" }, children: [_jsx(Heading, { level: 1, style: { fontSize: "1.5rem", fontWeight: 600 }, children: title }), subtitle ? (_jsx(Text, { as: "p", style: { color: "var(--appkit-color-text-muted)", marginBottom: "1rem" }, children: subtitle })) : null, _jsxs(Div, { style: { display: "flex", gap: "0.75rem", marginBottom: "1rem", alignItems: "center" }, children: [_jsxs(Label, { style: { fontSize: "0.85rem" }, children: ["Code", _jsx("input", { type: "search", value: codeFilter, onChange: (e) => setCodeFilter(e.target.value), placeholder: "e.g. NOT_FOUND", style: { marginLeft: "0.5rem", padding: "0.35rem 0.5rem", border: BORDER_STYLE, borderRadius: 4 } })] }), _jsxs(Label, { style: { fontSize: "0.85rem" }, children: ["Route", _jsx("input", { type: "search", value: routeFilter, onChange: (e) => setRouteFilter(e.target.value), placeholder: "e.g. /api/orders", style: { marginLeft: "0.5rem", padding: "0.35rem 0.5rem", border: BORDER_STYLE, borderRadius: 4 } })] }), _jsxs(Span, { style: { marginLeft: "auto", fontSize: "0.85rem", color: "var(--appkit-color-text-muted)" }, children: [filtered.length, " of ", rows.length, " (source=", source, ")"] })] }), _jsx(Div, { style: { overflowX: "auto", border: BORDER_STYLE, borderRadius: 6 }, children: _jsxs(Table, { style: { width: "100%", borderCollapse: "collapse", fontSize: "0.85rem" }, children: [_jsx(Thead, { style: { background: "var(--appkit-color-bg)" }, children: _jsx(Tr, { children: COLUMNS.map((c) => (_jsx(Th, { style: {
28
+ return (_jsxs(Div, { style: { padding: "1.5rem", maxWidth: "1400px", margin: "0 auto" }, children: [_jsx(Heading, { level: 1, style: { fontSize: "1.5rem", fontWeight: 600 }, children: title }), subtitle ? (_jsx(Text, { as: "p", style: { color: "var(--appkit-color-text-muted)", marginBottom: "1rem" }, children: subtitle })) : null, _jsxs(Div, { style: { display: "flex", gap: "0.75rem", marginBottom: "1rem", alignItems: "center" }, children: [_jsxs(Label, { style: { fontSize: "0.85rem" }, children: ["Code", _jsx(Input, { bare: true, type: "search", value: codeFilter, onChange: (e) => setCodeFilter(e.target.value), placeholder: "e.g. NOT_FOUND", style: { marginLeft: "0.5rem", padding: "0.35rem 0.5rem", border: BORDER_STYLE, borderRadius: 4 } })] }), _jsxs(Label, { style: { fontSize: "0.85rem" }, children: ["Route", _jsx(Input, { bare: true, type: "search", value: routeFilter, onChange: (e) => setRouteFilter(e.target.value), placeholder: "e.g. /api/orders", style: { marginLeft: "0.5rem", padding: "0.35rem 0.5rem", border: BORDER_STYLE, borderRadius: 4 } })] }), _jsxs(Span, { style: { marginLeft: "auto", fontSize: "0.85rem", color: "var(--appkit-color-text-muted)" }, children: [filtered.length, " of ", rows.length, " (source=", source, ")"] })] }), _jsx(Div, { style: { overflowX: "auto", border: BORDER_STYLE, borderRadius: 6 }, children: _jsxs(Table, { style: { width: "100%", borderCollapse: "collapse", fontSize: "0.85rem" }, children: [_jsx(Thead, { style: { background: "var(--appkit-color-bg)" }, children: _jsx(Tr, { children: COLUMNS.map((c) => (_jsx(Th, { style: {
29
29
  textAlign: "left",
30
30
  padding: "0.5rem 0.75rem",
31
31
  borderBottom: BORDER_STYLE,
@@ -14,11 +14,13 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
14
  */
15
15
  import * as React from "react";
16
16
  import { Div, Main, Nav, Span, Stack } from "../../../ui";
17
+ import { useVisualViewportInset } from "../../../react/hooks/useVisualViewportInset";
17
18
  export function DashboardScaffold({ children, slotPageHeader, renderNav, renderBottomNav, slotMenuToggle, initialDrawerOpen = false, className, }) {
18
19
  const [drawerOpen, setDrawerOpen] = React.useState(initialDrawerOpen);
19
20
  const toggleDrawer = React.useCallback(() => setDrawerOpen((v) => !v), []);
20
21
  const ctx = { drawerOpen, toggleDrawer };
22
+ const isKeyboardOpen = useVisualViewportInset();
21
23
  const nav = renderNav ? renderNav(ctx) : null;
22
24
  const bottomNav = renderBottomNav ? renderBottomNav(ctx) : nav;
23
- return (_jsxs(Div, { layout: "flex", className: `appkit-dashboard-scaffold min-h-screen ${className ?? ""}`, children: [nav ? (_jsx("aside", { className: "sticky top-0 hidden h-screen w-64 shrink-0 overflow-y-auto border-r border-[var(--appkit-color-border)] lg:block", "data-dashboard-slot": "sidebar", children: nav })) : null, nav ? (_jsxs("div", { className: `fixed inset-0 z-40 transition-transform md:block lg:hidden ${drawerOpen ? "translate-x-0" : "-translate-x-full"}`, "data-dashboard-slot": "drawer", "aria-hidden": !drawerOpen, children: [_jsx("div", { className: "absolute inset-0 bg-black/40", onClick: () => setDrawerOpen(false), role: "presentation" }), _jsx(Nav, { "aria-label": "Dashboard sidebar", className: "relative h-full w-64 overflow-y-auto bg-[var(--appkit-color-surface)] shadow-xl", children: nav })] })) : null, _jsxs(Stack, { className: "min-w-0 flex-1", children: [(slotPageHeader || slotMenuToggle) && (_jsxs("div", { className: "sticky top-0 z-20 flex items-center gap-3 border-b border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-4 py-2", "data-dashboard-slot": "page-header", children: [slotMenuToggle ? (_jsx(Span, { className: "lg:hidden", onClick: toggleDrawer, role: "presentation", children: slotMenuToggle })) : null, _jsx(Div, { className: "min-w-0 flex-1", children: slotPageHeader })] })), _jsx(Main, { className: "min-w-0 flex-1 pb-20 lg:pb-0", "data-dashboard-slot": "main", children: children }), bottomNav ? (_jsx(Nav, { "aria-label": "Bottom navigation", className: "fixed bottom-0 left-0 right-0 z-30 border-t border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] lg:hidden", "data-dashboard-slot": "bottom-nav", children: bottomNav })) : null] })] }));
25
+ return (_jsxs(Div, { layout: "flex", className: `appkit-dashboard-scaffold min-h-screen ${className ?? ""}`, children: [nav ? (_jsx("aside", { className: "sticky top-0 hidden h-screen w-64 shrink-0 overflow-y-auto border-r border-[var(--appkit-color-border)] lg:block", "data-dashboard-slot": "sidebar", children: nav })) : null, nav ? (_jsxs("div", { className: `fixed inset-0 z-40 transition-transform md:block lg:hidden ${drawerOpen ? "translate-x-0" : "-translate-x-full"}`, "data-dashboard-slot": "drawer", "aria-hidden": !drawerOpen, children: [_jsx("div", { className: "absolute inset-0 bg-black/40", onClick: () => setDrawerOpen(false), role: "presentation" }), _jsx(Nav, { "aria-label": "Dashboard sidebar", className: "relative h-full w-64 overflow-y-auto bg-[var(--appkit-color-surface)] shadow-xl", children: nav })] })) : null, _jsxs(Stack, { className: "min-w-0 flex-1", children: [(slotPageHeader || slotMenuToggle) && (_jsxs("div", { className: "sticky top-0 z-20 flex items-center gap-[var(--appkit-space-3)] border-b border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-[var(--appkit-space-4)] py-[var(--appkit-space-2)]", "data-dashboard-slot": "page-header", children: [slotMenuToggle ? (_jsx(Span, { className: "lg:hidden", onClick: toggleDrawer, role: "presentation", children: slotMenuToggle })) : null, _jsx(Div, { className: "min-w-0 flex-1", children: slotPageHeader })] })), _jsx(Main, { className: "min-w-0 flex-1 pb-[var(--appkit-space-20)] lg:pb-[var(--appkit-space-0)]", "data-dashboard-slot": "main", children: children }), bottomNav ? (_jsx(Nav, { "aria-label": "Bottom navigation", "aria-hidden": isKeyboardOpen, className: `fixed bottom-0 left-0 right-0 z-[var(--appkit-z-bottom-nav)] border-t border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] lg:hidden transition-transform duration-200 ease-out ${isKeyboardOpen ? "translate-y-full pointer-events-none" : "translate-y-0"}`, "data-dashboard-slot": "bottom-nav", children: bottomNav })) : null] })] }));
24
26
  }
@@ -1,3 +1,4 @@
1
+ import type { OutOfStockPolicy } from "../../../../features/orders/schemas/index";
1
2
  import { type CheckoutPaymentMethod } from "../../../shared/features/checkout/config";
2
3
  import { type CheckoutOrderResult } from "./data";
3
4
  export interface CreateCheckoutOrderInput {
@@ -15,6 +16,13 @@ export interface CreateCheckoutOrderInput {
15
16
  adminBypass?: boolean;
16
17
  /** UID of the admin who triggered the bypass. Set when adminBypass is true. */
17
18
  adminBypassBy?: string;
19
+ /**
20
+ * Buyer's choice for what to do when a cart item is unavailable at
21
+ * checkout time. Defaults to "skip_items" — preserves this path's
22
+ * historical behavior (ship the rest of the order) for any caller that
23
+ * omits the field.
24
+ */
25
+ outOfStockPolicy?: OutOfStockPolicy;
18
26
  }
19
27
  /**
20
28
  * Place order(s) from the user's cart in a single Firestore transaction.
@@ -42,6 +50,14 @@ export interface VerifyAndPlaceRazorpayOrderInput {
42
50
  /** Required for physical carts; omitted for digital-code-only carts. */
43
51
  addressId?: string;
44
52
  notes?: string;
53
+ /**
54
+ * Buyer's choice for what to do when a cart item is unavailable at
55
+ * checkout time. Defaults to "cancel_order" — matches this path's
56
+ * historical (only) behavior for any caller/old-client that omits the
57
+ * field, since "skip_items" partial fulfillment has no prior precedent
58
+ * on the Razorpay path.
59
+ */
60
+ outOfStockPolicy?: OutOfStockPolicy;
45
61
  }
46
62
  /**
47
63
  * Place order(s) from the user's cart after a Razorpay payment is verified.
@@ -21,9 +21,9 @@ import { getAdminDb, getAdminRealtimeDb, RTDB_PATHS, } from "../../../../provide
21
21
  import { PRODUCT_COLLECTION, PRODUCT_CODES_SUBCOLLECTION } from "../../../../features/products/schemas/firestore";
22
22
  import { CART_COLLECTION } from "../../../../features/cart/schemas/index";
23
23
  // S-SBUNI-RULES 2026-05-13 — bundle cart-line stock fan-out helpers.
24
- import { getCartItemMemberIds, getExpandedDecrements, validateCartItemStock, } from "./bundle-expansion";
24
+ import { getCartItemMemberIds, getExpandedDecrements, bucketCartItemsByStock, } from "./bundle-expansion";
25
25
  import { consentOtpRef, consentOtpRateLimitRef, CONSENT_OTP_MAX_BYPASS_CREDITS, } from "../../../../features/auth/server";
26
- import { OrderStatusValues, PaymentStatusValues, PaymentMethodValues, } from "../../../../features/orders/schemas/index";
26
+ import { OrderStatusValues, PaymentStatusValues, PaymentMethodValues, OutOfStockPolicyValues, } from "../../../../features/orders/schemas/index";
27
27
  import { getDefaultCurrency } from "../../../../core/index";
28
28
  import { verifyPaymentSignatureWithKeys, fetchRazorpayOrder, paiseToRupees, } from "../../../../providers/payment-razorpay/index";
29
29
  import { CHECKOUT_DEFAULT_COMMISSIONS, CHECKOUT_DEFAULT_EMI_SETTINGS } from "../../../shared/features/checkout/config";
@@ -32,6 +32,8 @@ import { formatShippingAddress } from "./data";
32
32
  import { enforceMaxPerUserForCart, computePrizeRevealDeadline, } from "./prize-bundle-gates";
33
33
  import { getListingRule, runSyncPreflight, } from "../../../shared/checkout/rules";
34
34
  import { cartIsDigitalOnly } from "../../../shared/listing-types/cart-shipping";
35
+ import { processRefundAction } from "../refunds/actions";
36
+ import { sendNotification } from "../../../../features/admin/actions/notification-actions";
35
37
  const AUDIT_LOG_FAIL_MSG = "checkout: audit log failed (non-critical)";
36
38
  /**
37
39
  * SB-UNI-N — Atomically claim the next available digital code for a confirmed
@@ -236,7 +238,7 @@ function unitPriceFor(item, product) {
236
238
  * so the caller can accumulate the checkout-wide `total`.
237
239
  */
238
240
  async function createOrderForGroup(group, orderType, ctx) {
239
- const { paymentMethod, emiTenureMonths, emiSettings, commissions, appliedCoupons, cartSubtotal, couponUsageAccumulator, uid, userName, userEmail, shippingAddress, notes, adminBypass, adminBypassBy, adminBatchId, orderIds, emailsToSend, } = ctx;
241
+ const { paymentMethod, emiTenureMonths, emiSettings, commissions, appliedCoupons, cartSubtotal, couponUsageAccumulator, uid, userName, userEmail, shippingAddress, notes, adminBypass, adminBypassBy, adminBatchId, orderIds, emailsToSend, outOfStockPolicy, droppedItems, } = ctx;
240
242
  const firstItem = group[0].item;
241
243
  const firstProduct = group[0].product;
242
244
  const groupTotal = group.reduce((sum, { item, product }) => sum + unitPriceFor(item, product) * item.quantity, 0);
@@ -381,6 +383,8 @@ async function createOrderForGroup(group, orderType, ctx) {
381
383
  couponDiscount: couponDiscount > 0 ? couponDiscount : undefined,
382
384
  appliedDiscounts: appliedDiscounts.length > 0 ? appliedDiscounts : undefined,
383
385
  imageUrls: imageUrls.length > 0 ? imageUrls : undefined,
386
+ outOfStockPolicy,
387
+ droppedItems: droppedItems.length > 0 ? droppedItems : undefined,
384
388
  ...extraOrderFields,
385
389
  });
386
390
  orderIds.push(order.id);
@@ -429,7 +433,7 @@ async function createOrderForGroup(group, orderType, ctx) {
429
433
  * auth + rate-limiting before calling this and supply the resolved user fields.
430
434
  */
431
435
  export async function createCheckoutOrderAction(input) {
432
- const { userId: uid, userName, userEmail, addressId, paymentMethod, emiTenureMonths, notes, excludedProductIds = [], adminBypass = false, adminBypassBy, } = input;
436
+ const { userId: uid, userName, userEmail, addressId, paymentMethod, emiTenureMonths, notes, excludedProductIds = [], adminBypass = false, adminBypassBy, outOfStockPolicy = OutOfStockPolicyValues.SKIP_ITEMS, } = input;
433
437
  const siteSettings = await siteSettingsRepository.getSingleton();
434
438
  const commissions = siteSettings?.commissions ?? CHECKOUT_DEFAULT_COMMISSIONS;
435
439
  const emiSettings = siteSettings?.emi ?? CHECKOUT_DEFAULT_EMI_SETTINGS;
@@ -555,30 +559,26 @@ export async function createCheckoutOrderAction(input) {
555
559
  productById.set(expansion.productIds[i], doc.data());
556
560
  }
557
561
  }
562
+ // Bundle cart-lines surface the first member as the "product" so
563
+ // downstream listingType branching (prize-draw) stays sound — bundle
564
+ // pricing is always "standard" so the prize-draw cap isn't enforced.
565
+ const bucketed = bucketCartItemsByStock(cartItems, productById, expansion.decrements, (item) => productById.get(getCartItemMemberIds(item)[0]) ?? null);
566
+ const unavailableItems = bucketed.unavailable;
567
+ // outOfStockPolicy: "cancel_order" — abort the WHOLE checkout batch if
568
+ // anything is short. This throw happens before any tx.update/tx.set
569
+ // below, so Firestore's transaction semantics guarantee zero writes
570
+ // land — no compensating rollback logic needed.
571
+ if (outOfStockPolicy === OutOfStockPolicyValues.CANCEL_ORDER && unavailableItems.length > 0) {
572
+ throw new ValidationError(ERROR_MESSAGES.CHECKOUT.INSUFFICIENT_STOCK);
573
+ }
558
574
  const availableItems = [];
559
- const unavailableItems = [];
560
- for (const item of cartItems) {
561
- const shortfall = validateCartItemStock(item, productById, expansion.decrements);
562
- if (shortfall) {
563
- unavailableItems.push({
564
- productId: shortfall.productId,
565
- productTitle: item.productTitle,
566
- requestedQty: item.quantity,
567
- availableQty: shortfall.availableQty,
568
- });
569
- continue;
570
- }
571
- // Bundle cart-lines surface the first member as the "product" so
572
- // downstream listingType branching (prize-draw) stays sound — bundle
573
- // pricing is always "standard" so the prize-draw cap isn't enforced.
574
- const memberIds = getCartItemMemberIds(item);
575
- const representative = productById.get(memberIds[0]);
575
+ for (const { item, product } of bucketed.available) {
576
576
  // S-SBUNI-RULES 2026-05-13 — sync preflight (prize-pool cap, pre-order
577
577
  // quota) via rule registry. Bundles skip — they bypass the cart path.
578
578
  if (!item.bundleProductIds?.length) {
579
- runSyncPreflight([{ item, product: representative }]);
579
+ runSyncPreflight([{ item, product }]);
580
580
  }
581
- availableItems.push({ item, product: representative });
581
+ availableItems.push({ item, product });
582
582
  }
583
583
  // Apply per-product decrements ONCE per unique product (sums across the
584
584
  // cart) so two cart lines sharing a product don't double-decrement.
@@ -664,6 +664,8 @@ export async function createCheckoutOrderAction(input) {
664
664
  adminBatchId,
665
665
  orderIds,
666
666
  emailsToSend,
667
+ outOfStockPolicy,
668
+ droppedItems: unavailable,
667
669
  };
668
670
  for (const { items: group, orderType } of orderGroups) {
669
671
  total += await createOrderForGroup(group, orderType, groupCtx);
@@ -708,7 +710,7 @@ export async function attachPaymentAction(input) {
708
710
  * 7. Confirmation email + RTDB success signal (both fire-and-forget)
709
711
  */
710
712
  export async function verifyAndPlaceRazorpayOrderAction(input) {
711
- const { userId: uid, userName, userEmail, razorpay_order_id, razorpay_payment_id, razorpay_signature, addressId, notes, } = input;
713
+ const { userId: uid, userName, userEmail, razorpay_order_id, razorpay_payment_id, razorpay_signature, addressId, notes, outOfStockPolicy = OutOfStockPolicyValues.CANCEL_ORDER, } = input;
712
714
  const siteSettings = await siteSettingsRepository.getSingleton();
713
715
  const platformFeePercent = siteSettings?.commissions?.platformFeePercent ?? 5;
714
716
  const gstPercent = siteSettings?.commissions?.gstPercent ?? 18;
@@ -809,25 +811,39 @@ export async function verifyAndPlaceRazorpayOrderAction(input) {
809
811
  // SB-UNI-5 — validate every required member product across the cart with
810
812
  // cumulative decrement awareness (two bundles sharing a member must NOT
811
813
  // both succeed unless the product has enough stock for the sum).
812
- for (const item of cart.items) {
813
- const shortfall = validateCartItemStock(item, productByIdPaid, expansionPaid.decrements);
814
- if (shortfall) {
815
- const exists = productByIdPaid.has(shortfall.productId);
814
+ //
815
+ // Out-of-stock policy: unlike the COD/UPI path, Razorpay payment has
816
+ // ALREADY been captured for the full cart by the time this runs — so
817
+ // "skip_items" here means placing orders for the available items only and
818
+ // auto-refunding the dropped items' value (below), not skipping payment.
819
+ const bucketedPaid = bucketCartItemsByStock(cart.items, productByIdPaid, expansionPaid.decrements, (item) => productByIdPaid.get(getCartItemMemberIds(item)[0]) ?? null);
820
+ const unavailablePaid = bucketedPaid.unavailable;
821
+ if (unavailablePaid.length > 0) {
822
+ for (const u of unavailablePaid) {
823
+ const exists = productByIdPaid.has(u.productId);
816
824
  const reason = exists ? "stock_insufficient" : "product_unavailable";
817
825
  failedCheckoutRepository
818
826
  .logPayment(uid, reason, exists
819
- ? `Product ${shortfall.productId} has ${shortfall.availableQty} left, requested ${item.quantity}`
820
- : `Product ${shortfall.productId} not published`, {
827
+ ? `Product ${u.productId} has ${u.availableQty} left, requested ${u.requestedQty}`
828
+ : `Product ${u.productId} not published`, {
821
829
  gatewayOrderId: razorpay_order_id,
822
830
  gatewayPaymentId: razorpay_payment_id,
823
831
  addressId,
824
832
  })
825
833
  .catch((err) => { void normalizeError(err); serverLogger.warn(AUDIT_LOG_FAIL_MSG, { error: err instanceof Error ? err.message : String(err) }); });
826
- throw new ValidationError(exists
827
- ? ERROR_MESSAGES.CHECKOUT.INSUFFICIENT_STOCK
828
- : ERROR_MESSAGES.CHECKOUT.PRODUCT_UNAVAILABLE);
829
834
  }
830
835
  }
836
+ // outOfStockPolicy: "cancel_order" (also the default for old clients that
837
+ // omit the field) — reject the whole checkout batch, exactly like every
838
+ // Razorpay checkout behaved before this policy existed.
839
+ if (outOfStockPolicy === OutOfStockPolicyValues.CANCEL_ORDER && unavailablePaid.length > 0) {
840
+ throw new ValidationError(ERROR_MESSAGES.CHECKOUT.INSUFFICIENT_STOCK);
841
+ }
842
+ // Mirrors the COD/UPI path's all-unavailable guard — regardless of policy,
843
+ // there is nothing to place an order for.
844
+ if (bucketedPaid.available.length === 0) {
845
+ throw new ValidationError(ERROR_MESSAGES.CHECKOUT.INSUFFICIENT_STOCK);
846
+ }
831
847
  {
832
848
  // SB-UNI-5 2026-05-13 — bundle cart-lines use item.price (locked
833
849
  // bundlePriceInPaise) instead of the representative member's product.price.
@@ -855,7 +871,11 @@ export async function verifyAndPlaceRazorpayOrderAction(input) {
855
871
  }
856
872
  }
857
873
  const appliedCoupons = cart.appliedCoupons ?? [];
858
- const orderGroups = splitCartIntoOrderGroups(productChecks);
874
+ // "skip_items" (or an all-available cart under any policy) — build order
875
+ // groups from the available bucket only. Dropped items are never ordered;
876
+ // their value is refunded below since Razorpay already captured payment
877
+ // for the full cart before this stock check ran.
878
+ const orderGroups = splitCartIntoOrderGroups(bucketedPaid.available);
859
879
  const orderIds = [];
860
880
  let total = 0;
861
881
  const emailsToSend = [];
@@ -975,6 +995,19 @@ export async function verifyAndPlaceRazorpayOrderAction(input) {
975
995
  paymentStatus: PaymentStatusValues.PAID,
976
996
  paymentMethod: PaymentMethodValues.ONLINE,
977
997
  paymentId: razorpay_payment_id,
998
+ paymentRecord: {
999
+ method: "razorpay",
1000
+ transactionId: razorpay_payment_id,
1001
+ amountPaise: orderTotal,
1002
+ paidAt: new Date(),
1003
+ verifiedBy: "razorpay-webhook",
1004
+ verificationMethod: "webhook",
1005
+ gatewayRef: {
1006
+ orderId: razorpay_order_id,
1007
+ paymentId: razorpay_payment_id,
1008
+ signature: razorpay_signature,
1009
+ },
1010
+ },
978
1011
  shippingAddress,
979
1012
  notes,
980
1013
  platformFee,
@@ -983,6 +1016,8 @@ export async function verifyAndPlaceRazorpayOrderAction(input) {
983
1016
  couponDiscount: couponDiscount > 0 ? couponDiscount : undefined,
984
1017
  appliedDiscounts: appliedDiscounts.length > 0 ? appliedDiscounts : undefined,
985
1018
  imageUrls: imageUrls.length > 0 ? imageUrls : undefined,
1019
+ outOfStockPolicy,
1020
+ droppedItems: unavailablePaid.length > 0 ? unavailablePaid : undefined,
986
1021
  ...extraOrderFields,
987
1022
  });
988
1023
  orderIds.push(order.id);
@@ -1044,6 +1079,80 @@ export async function verifyAndPlaceRazorpayOrderAction(input) {
1044
1079
  const otpRefForDelete = consentOtpRef(db, uid, addressId);
1045
1080
  safeFireAndForget(otpRefForDelete.delete(), "checkout: delete OTP consent ref after Razorpay payment");
1046
1081
  }
1082
+ // outOfStockPolicy: "skip_items" — auto-refund the dropped items' value.
1083
+ // Razorpay already captured payment for the FULL cart before this stock
1084
+ // check ran, so anything not placed as an order must be given back.
1085
+ // AWAITED (not fire-and-forget) — this moves money. On failure the orders
1086
+ // themselves are NOT rolled back (they're already validly created and
1087
+ // paid); instead the failure is surfaced via order.refundPending + an
1088
+ // admin notification, never silently dropped (Rule #8).
1089
+ if (unavailablePaid.length > 0 && orderIds.length > 0) {
1090
+ const droppedValueInPaise = unavailablePaid.reduce((sum, u) => sum + (productByIdPaid.get(u.productId)?.price ?? 0) * u.requestedQty, 0);
1091
+ const primaryOrderId = orderIds[0];
1092
+ if (droppedValueInPaise > 0) {
1093
+ try {
1094
+ const primaryOrder = await unitOfWork.orders.findById(primaryOrderId);
1095
+ // Cap defensively at the primary order's total — processRefundAction
1096
+ // rejects any amount exceeding order.totalPrice, and a multi-order
1097
+ // batch's dropped-items value isn't cleanly attributable to a single
1098
+ // order (Razorpay refunds are keyed by paymentId, not orderId; the
1099
+ // FIRST order created in this batch is used as the refund's book-
1100
+ // keeping anchor).
1101
+ const refundAmount = primaryOrder
1102
+ ? Math.min(droppedValueInPaise, primaryOrder.totalPrice)
1103
+ : droppedValueInPaise;
1104
+ const refundResult = await processRefundAction({
1105
+ orderId: primaryOrderId,
1106
+ type: "partial",
1107
+ amountInPaise: refundAmount,
1108
+ reason: `Automatic refund — ${unavailablePaid.length} item(s) unavailable at checkout: ${unavailablePaid.map((u) => u.productTitle).join(", ")}`,
1109
+ method: "razorpay",
1110
+ razorpayPaymentId: razorpay_payment_id,
1111
+ confirmIrrevocable: true,
1112
+ refundedBy: "system:checkout-auto-refund",
1113
+ });
1114
+ if (!refundResult.ok) {
1115
+ throw new Error(refundResult.error ?? "Automatic refund failed");
1116
+ }
1117
+ }
1118
+ catch (refundErr) {
1119
+ void normalizeError(refundErr);
1120
+ serverLogger.warn("verifyAndPlaceRazorpayOrderAction: automatic partial refund for dropped items failed — flagging for manual follow-up", {
1121
+ orderId: primaryOrderId,
1122
+ droppedValueInPaise,
1123
+ err: refundErr instanceof Error ? refundErr.message : String(refundErr),
1124
+ });
1125
+ await unitOfWork.orders
1126
+ .update(primaryOrderId, { refundPending: true })
1127
+ .catch((updErr) => {
1128
+ void normalizeError(updErr);
1129
+ serverLogger.error("verifyAndPlaceRazorpayOrderAction: failed to flag refundPending after auto-refund failure", { orderId: primaryOrderId, err: updErr instanceof Error ? updErr.message : String(updErr) });
1130
+ });
1131
+ // Best-effort admin fan-out — mirrors onScamReportCreate's employee
1132
+ // notification pattern. Never allowed to throw past this point.
1133
+ try {
1134
+ const admins = await userRepository.list({ filters: "role==admin", page: 1, pageSize: 100 });
1135
+ await Promise.all(admins.items
1136
+ .filter((a) => !!a.id)
1137
+ .map((admin) => sendNotification({
1138
+ userId: admin.id,
1139
+ type: "system",
1140
+ priority: "high",
1141
+ title: "Automatic refund failed",
1142
+ message: `Automatic refund failed for order ${primaryOrderId} (${unavailablePaid.length} unavailable item(s)) — manual refund required.`,
1143
+ relatedId: primaryOrderId,
1144
+ relatedType: "order",
1145
+ userEmail: admin.email ?? undefined,
1146
+ userPhone: admin.phoneNumber ?? undefined,
1147
+ }).catch((notifErr) => serverLogger.error("Failed to notify admin of failed auto-refund (non-fatal)", notifErr))));
1148
+ }
1149
+ catch (notifyErr) {
1150
+ void normalizeError(notifyErr);
1151
+ serverLogger.error("verifyAndPlaceRazorpayOrderAction: failed to query admins for failed auto-refund notification", { orderId: primaryOrderId });
1152
+ }
1153
+ }
1154
+ }
1155
+ }
1047
1156
  if (emailsToSend.length > 0) {
1048
1157
  Promise.all(emailsToSend.map((e) => sendOrderConfirmationEmail(e))).catch((err) => serverLogger.error("Order confirmation email error:", err));
1049
1158
  }
@@ -1052,5 +1161,10 @@ export async function verifyAndPlaceRazorpayOrderAction(input) {
1052
1161
  .ref(`${RTDB_PATHS.PAYMENT_EVENTS}/${razorpay_order_id}`)
1053
1162
  .update({ status: "success", orderIds, updatedAt: Date.now() })
1054
1163
  .catch((err) => serverLogger.warn("Payment event RTDB signal failed (non-critical)", { err }));
1055
- return { orderIds, total, itemCount: orderIds.length };
1164
+ return {
1165
+ orderIds,
1166
+ total,
1167
+ itemCount: orderIds.length,
1168
+ ...(unavailablePaid.length > 0 ? { unavailableItems: unavailablePaid } : {}),
1169
+ };
1056
1170
  }