@mohasinac/appkit 3.4.8 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_internal/client/features/classified/ClassifiedDetailView.js +1 -1
- package/dist/_internal/client/features/digital-code/CodeRevealPanel.js +1 -1
- package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.js +1 -1
- package/dist/_internal/client/features/filters/filter-load-options.js +10 -9
- package/dist/_internal/client/features/layout/DashboardLayoutClient.d.ts +6 -1
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +11 -4
- package/dist/_internal/client/features/live/LiveItemDetailView.js +2 -2
- package/dist/_internal/client/features/maintenance/views/AnalysisRunnerView.js +10 -3
- package/dist/_internal/client/features/maintenance/views/ServerErrorsListView.js +2 -2
- package/dist/_internal/client/scaffolds/DashboardScaffold.js +3 -1
- package/dist/_internal/server/features/checkout/actions.d.ts +16 -0
- package/dist/_internal/server/features/checkout/actions.js +149 -35
- package/dist/_internal/server/features/checkout/bundle-expansion.d.ts +31 -0
- package/dist/_internal/server/features/checkout/bundle-expansion.js +41 -0
- package/dist/_internal/server/features/lottery/actions.js +14 -4
- package/dist/_internal/server/features/maintenance/analyze.js +4 -2
- package/dist/_internal/server/features/orders/actions.js +9 -0
- package/dist/_internal/server/features/orders/adapters.js +19 -0
- package/dist/_internal/server/features/seo/robots.js +1 -1
- package/dist/_internal/server/functions/firestore.d.ts +47 -1
- package/dist/_internal/server/functions/firestore.js +56 -1
- package/dist/_internal/server/functions/scheduled.d.ts +2 -1
- package/dist/_internal/server/functions/scheduled.js +9 -1
- package/dist/_internal/server/jobs/core/catalogueImageStalenessReminder.d.ts +10 -0
- package/dist/_internal/server/jobs/core/catalogueImageStalenessReminder.js +49 -0
- package/dist/_internal/server/jobs/core/cleanupRtdbEvents.js +32 -0
- package/dist/_internal/server/jobs/core/hardBanCascade.d.ts +26 -0
- package/dist/_internal/server/jobs/core/hardBanCascade.js +179 -0
- package/dist/_internal/server/jobs/core/index.d.ts +4 -1
- package/dist/_internal/server/jobs/core/index.js +4 -1
- package/dist/_internal/server/jobs/core/jobRunners.d.ts +28 -0
- package/dist/_internal/server/jobs/core/jobRunners.js +37 -0
- package/dist/_internal/server/jobs/core/onCatalogueSubmittedForApproval.d.ts +15 -0
- package/dist/_internal/server/jobs/core/onCatalogueSubmittedForApproval.js +38 -0
- package/dist/_internal/server/jobs/core/onJobCreated.d.ts +22 -0
- package/dist/_internal/server/jobs/core/onJobCreated.js +59 -0
- package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.d.ts +6 -1
- package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +5 -2
- package/dist/_internal/server/jobs/handlers/catalogueImageStalenessReminder.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/catalogueImageStalenessReminder.js +2 -0
- package/dist/_internal/server/jobs/handlers/index.d.ts +6 -0
- package/dist/_internal/server/jobs/handlers/index.js +8 -0
- package/dist/_internal/server/jobs/handlers/onCatalogueSubmittedForApproval.d.ts +12 -0
- package/dist/_internal/server/jobs/handlers/onCatalogueSubmittedForApproval.js +20 -0
- package/dist/_internal/server/jobs/handlers/onJobCreated.d.ts +3 -0
- package/dist/_internal/server/jobs/handlers/onJobCreated.js +9 -0
- package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.d.ts +25 -0
- package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.js +71 -0
- package/dist/_internal/server/jobs/handlers/onShipmentDeleted.d.ts +14 -0
- package/dist/_internal/server/jobs/handlers/onShipmentDeleted.js +23 -0
- package/dist/_internal/server/jobs/handlers/onShipmentItemWrite.d.ts +17 -0
- package/dist/_internal/server/jobs/handlers/onShipmentItemWrite.js +26 -0
- package/dist/_internal/server/jobs/handlers/weeklyPayoutEligibility.js +3 -1
- package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
- package/dist/_internal/shared/actions/action-registry.js +136 -0
- package/dist/_internal/shared/features/blog/schema.d.ts +8 -8
- package/dist/_internal/shared/features/brands/schema.d.ts +4 -4
- package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +8 -8
- package/dist/_internal/shared/features/events/schema.d.ts +4 -4
- package/dist/_internal/shared/features/products/schema.d.ts +8 -8
- package/dist/_internal/shared/features/promotions/schema.d.ts +4 -4
- package/dist/_internal/shared/features/reviews/schema.d.ts +4 -4
- package/dist/client/api/useFeatureFlags.d.ts +22 -0
- package/dist/client/api/useFeatureFlags.js +27 -0
- package/dist/client/observability/reportClientError.js +3 -2
- package/dist/client.d.ts +4 -2
- package/dist/client.js +2 -1
- package/dist/configs/next.js +1 -0
- package/dist/constants/api-endpoints.d.ts +279 -3
- package/dist/constants/api-endpoints.js +130 -2
- package/dist/core/hooks/useSyncManager.js +5 -4
- package/dist/errors/conflict-error.d.ts +4 -0
- package/dist/errors/conflict-error.js +6 -0
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.js +1 -0
- package/dist/features/about/components/FeesView.js +2 -2
- package/dist/features/about/components/HelpPageView.js +2 -2
- package/dist/features/about/components/HowAuctionsWorkView.js +2 -2
- package/dist/features/about/components/HowCheckoutWorksView.js +2 -2
- package/dist/features/about/components/HowEmiWorksView.js +2 -2
- package/dist/features/about/components/HowOffersWorkView.js +3 -3
- package/dist/features/about/components/HowOrdersWorkView.js +3 -3
- package/dist/features/about/components/HowPayoutsWorkView.js +2 -2
- package/dist/features/about/components/HowPreOrdersWorkView.js +2 -2
- package/dist/features/about/components/HowReviewsWorkView.js +2 -2
- package/dist/features/about/components/PublicProfileView.d.ts +8 -1
- package/dist/features/about/components/PublicProfileView.js +11 -9
- package/dist/features/about/components/SecurityPrivacyView.js +2 -2
- package/dist/features/about/components/UnauthorizedView.js +2 -2
- package/dist/features/account/components/AddressBook.js +1 -1
- package/dist/features/account/components/AddressesIndexListing.js +1 -1
- package/dist/features/account/components/NotificationBell.js +5 -5
- package/dist/features/account/components/NotificationPreferencesPanel.js +5 -2
- package/dist/features/account/components/UserOffersPanel.js +5 -4
- package/dist/features/account/components/UserSidebar.js +2 -2
- package/dist/features/account/components/UserSupportView.js +3 -3
- package/dist/features/account/schemas/index.d.ts +12 -12
- package/dist/features/addresses/schemas/index.d.ts +6 -6
- package/dist/features/admin/components/AdminAdEditorView.js +3 -3
- package/dist/features/admin/components/AdminAddressEditorView.js +3 -3
- package/dist/features/admin/components/AdminAdsView.js +3 -3
- package/dist/features/admin/components/AdminBlogEditorView.js +1 -1
- package/dist/features/admin/components/AdminBlogView.js +12 -15
- package/dist/features/admin/components/AdminBrandEditorView.js +1 -1
- package/dist/features/admin/components/AdminBrandsView.js +12 -13
- package/dist/features/admin/components/AdminBundleEditorView.js +5 -4
- package/dist/features/admin/components/AdminBundlesView.js +32 -23
- package/dist/features/admin/components/AdminCarouselEditorView.js +5 -5
- package/dist/features/admin/components/AdminCarouselView.js +2 -2
- package/dist/features/admin/components/AdminCatalogGuideView.js +1 -1
- package/dist/features/admin/components/AdminCategoriesView.js +12 -13
- package/dist/features/admin/components/AdminCategoryEditorView.js +2 -2
- package/dist/features/admin/components/AdminContactEditorView.js +2 -2
- package/dist/features/admin/components/AdminCouponEditorView.d.ts +10 -1
- package/dist/features/admin/components/AdminCouponEditorView.js +7 -2
- package/dist/features/admin/components/AdminCouponsView.js +32 -27
- package/dist/features/admin/components/AdminEmployeeEditorView.js +3 -3
- package/dist/features/admin/components/AdminFaqEditorView.js +1 -1
- package/dist/features/admin/components/AdminFaqsView.js +20 -20
- package/dist/features/admin/components/AdminFeatureEditorView.js +5 -5
- package/dist/features/admin/components/AdminFeaturesView.js +9 -10
- package/dist/features/admin/components/AdminFilterBar.js +1 -1
- package/dist/features/admin/components/AdminFulfillmentView.js +4 -4
- package/dist/features/admin/components/AdminGuideHubView.js +2 -2
- package/dist/features/admin/components/AdminMediaView.js +3 -2
- package/dist/features/admin/components/AdminNavigationView.js +1 -1
- package/dist/features/admin/components/AdminOrderEditorView.js +3 -3
- package/dist/features/admin/components/AdminOrdersView.js +21 -30
- package/dist/features/admin/components/AdminPageHeader.js +3 -3
- package/dist/features/admin/components/AdminPayoutsView.js +8 -8
- package/dist/features/admin/components/AdminPrizeDrawsView.js +8 -9
- package/dist/features/admin/components/AdminProductEditorView.d.ts +9 -1
- package/dist/features/admin/components/AdminProductEditorView.js +7 -4
- package/dist/features/admin/components/AdminProductsView.js +30 -41
- package/dist/features/admin/components/AdminReviewsView.js +14 -17
- package/dist/features/admin/components/AdminScammerEditorView.js +5 -5
- package/dist/features/admin/components/AdminSectionsView.js +3 -3
- package/dist/features/admin/components/AdminSessionsView.js +8 -10
- package/dist/features/admin/components/AdminSidebar.js +2 -2
- package/dist/features/admin/components/AdminSiteSettingsView.js +10 -3
- package/dist/features/admin/components/AdminStoreEditorView.js +4 -5
- package/dist/features/admin/components/AdminStoresView.js +18 -13
- package/dist/features/admin/components/AdminSupportTicketDetailView.js +7 -7
- package/dist/features/admin/components/AdminTeamView.js +9 -5
- package/dist/features/admin/components/AdminUsersView.js +19 -15
- package/dist/features/admin/components/AdminViewCards.js +5 -5
- package/dist/features/admin/components/DashboardStats.js +1 -1
- package/dist/features/admin/components/DataListingView.js +2 -2
- package/dist/features/admin/components/DataTable.js +2 -2
- package/dist/features/admin/components/DrawerFormFooter.js +1 -1
- package/dist/features/admin/components/analytics/AdminAnalyticsCharts.js +2 -2
- package/dist/features/admin/components/analytics/AdminStatCard.js +1 -1
- package/dist/features/admin/hooks/useAdminListing.d.ts +3 -2
- package/dist/features/admin/hooks/useAdminListing.js +8 -2
- package/dist/features/admin/permission-map.js +2 -0
- package/dist/features/admin/schemas/firestore.d.ts +7 -0
- package/dist/features/admin/schemas/firestore.js +4 -0
- package/dist/features/auctions/components/AuctionBidsTable.js +1 -1
- package/dist/features/auctions/components/AuctionDetailPageView.js +7 -7
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +3 -3
- package/dist/features/auctions/components/MarketplaceAuctionGrid.js +4 -4
- package/dist/features/auctions/components/PlaceBidFormClient.js +1 -1
- package/dist/features/auctions/schemas/index.d.ts +16 -16
- package/dist/features/auth/permissions/constants.d.ts +1 -1
- package/dist/features/auth/permissions/constants.js +2 -0
- package/dist/features/auth/schemas/index.d.ts +6 -6
- package/dist/features/before-after/schemas/index.d.ts +3 -3
- package/dist/features/blog/actions/blog-actions.d.ts +32 -32
- package/dist/features/blog/components/BlogFeaturedCard.js +2 -2
- package/dist/features/blog/components/BlogIndexListing.js +2 -2
- package/dist/features/blog/components/BlogListView.js +4 -4
- package/dist/features/blog/components/BlogPostView.js +4 -4
- package/dist/features/blog/schemas/index.d.ts +77 -77
- package/dist/features/cart/components/CartDrawer.js +2 -2
- package/dist/features/catalogue/actions/approve-catalogue-listing.d.ts +12 -0
- package/dist/features/catalogue/actions/approve-catalogue-listing.js +50 -0
- package/dist/features/catalogue/actions/list-from-catalogue.d.ts +17 -0
- package/dist/features/catalogue/actions/list-from-catalogue.js +50 -0
- package/dist/features/catalogue/actions/submit-for-approval.d.ts +8 -0
- package/dist/features/catalogue/actions/submit-for-approval.js +30 -0
- package/dist/features/catalogue/components/AdminCatalogueApprovalsView.d.ts +2 -0
- package/dist/features/catalogue/components/AdminCatalogueApprovalsView.js +53 -0
- package/dist/features/catalogue/components/CatalogueItemEditorView.d.ts +7 -0
- package/dist/features/catalogue/components/CatalogueItemEditorView.js +79 -0
- package/dist/features/catalogue/components/PublicCatalogueView.d.ts +5 -0
- package/dist/features/catalogue/components/PublicCatalogueView.js +22 -0
- package/dist/features/catalogue/components/UserCatalogueView.d.ts +12 -0
- package/dist/features/catalogue/components/UserCatalogueView.js +51 -0
- package/dist/features/catalogue/index.d.ts +12 -0
- package/dist/features/catalogue/index.js +9 -0
- package/dist/features/catalogue/repository/catalogue.repository.d.ts +39 -0
- package/dist/features/catalogue/repository/catalogue.repository.js +68 -0
- package/dist/features/catalogue/schemas/firestore.d.ts +47 -0
- package/dist/features/catalogue/schemas/firestore.js +22 -0
- package/dist/features/catalogue/schemas/index.d.ts +2 -0
- package/dist/features/catalogue/schemas/index.js +2 -0
- package/dist/features/catalogue/schemas/validation.d.ts +71 -0
- package/dist/features/catalogue/schemas/validation.js +25 -0
- package/dist/features/catalogue/utils/freshness.d.ts +10 -0
- package/dist/features/catalogue/utils/freshness.js +15 -0
- package/dist/features/catalogue/utils/product-from-item.d.ts +15 -0
- package/dist/features/catalogue/utils/product-from-item.js +34 -0
- package/dist/features/categories/components/BrandDetailPageView.js +1 -1
- package/dist/features/categories/components/BrandDetailTabs.js +2 -2
- package/dist/features/categories/components/BundleCollage.js +2 -2
- package/dist/features/categories/components/BundleItemsPicker.js +3 -2
- package/dist/features/categories/components/CategoriesIndexListing.js +8 -6
- package/dist/features/categories/components/CategoryBundlesListing.js +10 -4
- package/dist/features/categories/components/CategoryDetailPageView.js +1 -1
- package/dist/features/categories/components/CategoryDetailTabs.js +2 -2
- package/dist/features/categories/components/CategoryGrid.js +3 -3
- package/dist/features/categories/components/CategoryProductsListing.js +1 -1
- package/dist/features/categories/components/CategorySortSelect.js +1 -1
- package/dist/features/categories/components/CategoryStoresListing.js +1 -1
- package/dist/features/categories/components/CategoryTableColumns.js +1 -1
- package/dist/features/categories/components/CategoryTree.js +2 -2
- package/dist/features/categories/components/ConcernCard.js +1 -1
- package/dist/features/categories/hooks/useCategories.js +1 -1
- package/dist/features/categories/schemas/index.d.ts +32 -32
- package/dist/features/classified/components/ClassifiedFilters.js +2 -2
- package/dist/features/classified/components/ClassifiedIndexListing.js +9 -3
- package/dist/features/collections/schemas/index.d.ts +2 -2
- package/dist/features/consultation/components/ConsultationForm.js +1 -1
- package/dist/features/consultation/schemas/index.d.ts +10 -10
- package/dist/features/contact/components/ContactForm.js +4 -4
- package/dist/features/contact/components/ContactInfoSidebar.js +1 -1
- package/dist/features/contact/components/ContactPageView.js +2 -1
- package/dist/features/copilot/components/AdminCopilotView.js +5 -4
- package/dist/features/corporate/schemas/index.d.ts +2 -2
- package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +3 -3
- package/dist/features/events/components/AdminEventEditorView.js +4 -4
- package/dist/features/events/components/AdminEventEntriesView.js +2 -2
- package/dist/features/events/components/AdminEventsView.js +8 -8
- package/dist/features/events/components/EventBanner.js +1 -1
- package/dist/features/events/components/EventCard.js +3 -3
- package/dist/features/events/components/EventLeaderboard.js +1 -1
- package/dist/features/events/components/EventOfferCard.js +1 -1
- package/dist/features/events/components/EventPollWidget.js +6 -5
- package/dist/features/events/components/EventRaffleEntryForm.js +1 -1
- package/dist/features/events/components/EventRaffleWinnerView.js +5 -5
- package/dist/features/events/components/EventRafflesSection.js +1 -1
- package/dist/features/events/components/EventSaleBanner.js +1 -1
- package/dist/features/events/components/EventsIndexListing.js +4 -2
- package/dist/features/events/components/EventsListView.js +2 -2
- package/dist/features/events/components/SpinWheelView.js +11 -5
- package/dist/features/events/schemas/index.d.ts +100 -100
- package/dist/features/faq/actions/faq-actions.d.ts +6 -6
- package/dist/features/faq/components/ContactCTA.js +3 -3
- package/dist/features/faq/components/FAQCategorySidebar.js +2 -2
- package/dist/features/faq/components/FAQHelpfulButtons.js +3 -3
- package/dist/features/faq/schemas/index.d.ts +12 -12
- package/dist/features/filters/AsyncFacetSection.js +4 -4
- package/dist/features/filters/FilterFacetSection.js +8 -8
- package/dist/features/filters/RangeFilter.js +2 -2
- package/dist/features/filters/SwitchFilter.js +1 -1
- package/dist/features/forms/Checkbox.js +2 -8
- package/dist/features/forms/Input.js +2 -1
- package/dist/features/forms/Radio.js +3 -3
- package/dist/features/forms/Select.d.ts +1 -1
- package/dist/features/forms/Select.js +3 -2
- package/dist/features/forms/Slider.js +5 -11
- package/dist/features/forms/Textarea.js +2 -1
- package/dist/features/grouped/schemas/index.d.ts +6 -6
- package/dist/features/homepage/actions/homepage-section-actions.d.ts +4 -4
- package/dist/features/homepage/components/AdvertisementBanner.js +4 -4
- package/dist/features/homepage/components/AnnouncementBar.js +3 -3
- package/dist/features/homepage/components/BeforeAfterCard.js +1 -1
- package/dist/features/homepage/components/BrandsSection.js +9 -9
- package/dist/features/homepage/components/CTABannerSection.js +1 -1
- package/dist/features/homepage/components/CharacterHotspot.js +4 -4
- package/dist/features/homepage/components/CharacterHotspotForm.js +15 -13
- package/dist/features/homepage/components/CollectionCardsSection.js +1 -1
- package/dist/features/homepage/components/CustomCardsSection.js +6 -6
- package/dist/features/homepage/components/CustomerReviewsSection.js +2 -2
- package/dist/features/homepage/components/FAQSection.js +2 -2
- package/dist/features/homepage/components/FeaturedBundlesSection.js +3 -3
- package/dist/features/homepage/components/FeaturedResultsSection.js +2 -2
- package/dist/features/homepage/components/GoogleReviewsSection.js +6 -6
- package/dist/features/homepage/components/HeroBanner.js +1 -1
- package/dist/features/homepage/components/HeroCarousel.js +5 -4
- package/dist/features/homepage/components/HeroSection.js +1 -7
- package/dist/features/homepage/components/HomepageSkeleton.js +1 -1
- package/dist/features/homepage/components/HowItWorksInfoView.js +1 -1
- package/dist/features/homepage/components/HowItWorksSection.js +2 -2
- package/dist/features/homepage/components/NewsletterBanner.js +2 -2
- package/dist/features/homepage/components/NewsletterSection.js +1 -1
- package/dist/features/homepage/components/PromoGrid.js +1 -1
- package/dist/features/homepage/components/SectionCarousel.js +6 -6
- package/dist/features/homepage/components/SecurityHighlightsSection.js +2 -2
- package/dist/features/homepage/components/ShopByCategorySection.js +10 -10
- package/dist/features/homepage/components/SiteFeaturesSection.js +2 -2
- package/dist/features/homepage/components/SocialFeedSection.js +5 -5
- package/dist/features/homepage/components/SocialPostCard.js +1 -1
- package/dist/features/homepage/components/StatsCounterSection.js +1 -1
- package/dist/features/homepage/components/TestimonialsCarousel.js +1 -1
- package/dist/features/homepage/components/TrustBadges.js +1 -1
- package/dist/features/homepage/components/TrustFeaturesSection.js +2 -2
- package/dist/features/homepage/components/TrustIndicatorsSection.js +2 -2
- package/dist/features/homepage/components/WelcomeSection.js +2 -2
- package/dist/features/homepage/components/WhatsAppCommunitySection.js +1 -1
- package/dist/features/homepage/hooks/useActiveAd.js +2 -1
- package/dist/features/homepage/schemas/firestore.d.ts +10 -0
- package/dist/features/homepage/schemas/index.d.ts +116 -116
- package/dist/features/jobs/actions/enqueue-job.d.ts +24 -0
- package/dist/features/jobs/actions/enqueue-job.js +44 -0
- package/dist/features/jobs/repository/jobs.repository.d.ts +21 -0
- package/dist/features/jobs/repository/jobs.repository.js +48 -0
- package/dist/features/jobs/schemas/firestore.d.ts +54 -0
- package/dist/features/jobs/schemas/firestore.js +24 -0
- package/dist/features/layout/AppLayoutShell.js +17 -11
- package/dist/features/layout/AutoBreadcrumbs.js +1 -1
- package/dist/features/layout/BackToTop.js +2 -2
- package/dist/features/layout/BottomActions.js +7 -7
- package/dist/features/layout/BottomNavItem.js +2 -2
- package/dist/features/layout/BottomNavLayout.js +13 -4
- package/dist/features/layout/BottomNavbar.d.ts +9 -1
- package/dist/features/layout/BottomNavbar.js +12 -5
- package/dist/features/layout/BottomSheet.js +1 -1
- package/dist/features/layout/Breadcrumbs.js +1 -1
- package/dist/features/layout/FooterLayout.js +2 -2
- package/dist/features/layout/NavItem.js +3 -3
- package/dist/features/layout/NavbarLayout.js +6 -6
- package/dist/features/layout/SidebarLayout.d.ts +3 -0
- package/dist/features/layout/SidebarLayout.js +3 -3
- package/dist/features/layout/TitleBarLayout.js +4 -4
- package/dist/features/live/components/LiveItemFilters.js +2 -2
- package/dist/features/live/components/LiveItemsIndexListing.js +3 -3
- package/dist/features/lottery/types/index.d.ts +3 -1
- package/dist/features/lottery/types/index.js +16 -3
- package/dist/features/loyalty/components/CoinsDisplay.js +2 -2
- package/dist/features/media/MediaImage.d.ts +6 -1
- package/dist/features/media/MediaImage.js +10 -4
- package/dist/features/media/MediaLightbox.js +1 -1
- package/dist/features/media/MediaPickerModal.js +4 -3
- package/dist/features/media/MediaVideo.js +1 -1
- package/dist/features/media/modals/ImageCropModal.js +1 -1
- package/dist/features/media/modals/ImageEditor.js +1 -1
- package/dist/features/media/repository/media-assets.repository.d.ts +9 -0
- package/dist/features/media/types/index.d.ts +4 -4
- package/dist/features/media/upload/MediaUploadField.js +3 -3
- package/dist/features/media/upload/MediaUploadList.js +1 -1
- package/dist/features/messages/hooks/useConversation.js +4 -3
- package/dist/features/messages/hooks/useConversations.js +2 -1
- package/dist/features/messages/schemas/index.d.ts +6 -6
- package/dist/features/orders/components/MarketplaceOrderCard.js +1 -1
- package/dist/features/orders/components/OrderPaymentSummary.d.ts +16 -0
- package/dist/features/orders/components/OrderPaymentSummary.js +32 -0
- package/dist/features/orders/components/OrderSiblingPayments.js +1 -1
- package/dist/features/orders/components/OrdersList.d.ts +7 -2
- package/dist/features/orders/components/OrdersList.js +5 -5
- package/dist/features/orders/components/RefundHistoryTable.js +1 -1
- package/dist/features/orders/components/RefundRequestView.js +1 -1
- package/dist/features/orders/components/index.d.ts +2 -0
- package/dist/features/orders/components/index.js +1 -0
- package/dist/features/orders/repository/orders.repository.d.ts +8 -0
- package/dist/features/orders/repository/orders.repository.js +24 -0
- package/dist/features/orders/schemas/firestore.d.ts +59 -0
- package/dist/features/orders/schemas/firestore.js +5 -0
- package/dist/features/orders/schemas/index.d.ts +91 -40
- package/dist/features/orders/schemas/index.js +10 -0
- package/dist/features/orders/types/index.d.ts +15 -0
- package/dist/features/payments/schemas/index.d.ts +12 -12
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +5 -5
- package/dist/features/pre-orders/components/PreOrderActionsClient.js +1 -1
- package/dist/features/pre-orders/components/PreOrderBadge.js +1 -1
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +7 -7
- package/dist/features/pre-orders/components/PreOrdersIndexListing.js +3 -3
- package/dist/features/pre-orders/schemas/index.d.ts +12 -12
- package/dist/features/products/columns/productTableColumns.js +2 -2
- package/dist/features/products/components/AuctionsIndexListing.js +3 -3
- package/dist/features/products/components/CompareOverlay.js +15 -10
- package/dist/features/products/components/CustomFieldsEditor.js +2 -2
- package/dist/features/products/components/CustomSectionsEditor.js +3 -3
- package/dist/features/products/components/FeatureBadge.js +2 -2
- package/dist/features/products/components/GroupSettingsPanel.js +5 -4
- package/dist/features/products/components/MakeOfferButton.js +4 -4
- package/dist/features/products/components/MarketplaceBundleCard.js +3 -2
- package/dist/features/products/components/MarketplacePrizeDrawCard.js +1 -1
- package/dist/features/products/components/PrizeDrawCollage.js +6 -6
- package/dist/features/products/components/PrizeDrawDetailPageView.js +5 -5
- package/dist/features/products/components/PrizeDrawEntryActions.js +1 -1
- package/dist/features/products/components/PrizeDrawItemsEditor.js +4 -4
- package/dist/features/products/components/PrizeDrawsIndexListing.js +11 -4
- package/dist/features/products/components/PrizeDrawsSection.js +1 -1
- package/dist/features/products/components/PrizeRevealModal.js +9 -4
- package/dist/features/products/components/ProductDetailActions.js +2 -1
- package/dist/features/products/components/ProductDetailPageView.js +16 -16
- package/dist/features/products/components/ProductFeaturesSelector.js +5 -5
- package/dist/features/products/components/ProductForm.js +1 -1
- package/dist/features/products/components/ProductGalleryClient.js +5 -3
- package/dist/features/products/components/ProductGrid.js +11 -11
- package/dist/features/products/components/ProductTabs.js +2 -2
- package/dist/features/products/components/ProductTabsShell.js +2 -1
- package/dist/features/products/components/ProductsIndexListing.js +6 -1
- package/dist/features/products/components/ShareButton.js +2 -1
- package/dist/features/products/components/ShowGroupSection.js +9 -5
- package/dist/features/products/components/SublistingCarouselSection.js +8 -4
- package/dist/features/products/constants/action-defs.d.ts +10 -2
- package/dist/features/products/constants/action-defs.js +20 -2
- package/dist/features/products/schemas/firestore.d.ts +5 -0
- package/dist/features/products/schemas/index.d.ts +40 -40
- package/dist/features/products/schemas/product-features.validators.d.ts +14 -14
- package/dist/features/promotions/components/CouponCard.js +13 -7
- package/dist/features/promotions/components/CouponsIndexListing.js +4 -6
- package/dist/features/promotions/components/PromotionsView.js +2 -2
- package/dist/features/promotions/schemas/index.d.ts +26 -26
- package/dist/features/reviews/components/ReviewDetailPageView.js +1 -1
- package/dist/features/reviews/components/ReviewDetailShell.js +11 -11
- package/dist/features/reviews/components/ReviewModal.js +1 -1
- package/dist/features/reviews/components/ReviewsIndexListing.js +2 -2
- package/dist/features/reviews/components/ReviewsList.js +2 -2
- package/dist/features/reviews/schemas/index.d.ts +22 -22
- package/dist/features/scams/components/ScamAwarenessModal.js +2 -2
- package/dist/features/scams/components/ScamProfileView.js +3 -3
- package/dist/features/scams/components/ScamRegistryView.js +2 -2
- package/dist/features/scams/schemas/index.d.ts +20 -20
- package/dist/features/search/components/Search.js +9 -9
- package/dist/features/search/components/SearchFiltersRow.js +1 -1
- package/dist/features/search/components/SearchResultsSection.js +3 -3
- package/dist/features/search/components/SearchView.js +1 -1
- package/dist/features/search/hooks/useNavSuggestions.js +2 -1
- package/dist/features/search/hooks/useSearch.js +2 -2
- package/dist/features/search/schemas/index.d.ts +3 -3
- package/dist/features/seller/components/BrandInlineSelect.js +2 -2
- package/dist/features/seller/components/CategoryInlineSelect.js +2 -2
- package/dist/features/seller/components/QuickProductForm.js +1 -1
- package/dist/features/seller/components/SellerAddressesView.js +4 -4
- package/dist/features/seller/components/SellerAnalyticsAlertsView.js +3 -3
- package/dist/features/seller/components/SellerAnalyticsView.js +2 -2
- package/dist/features/seller/components/SellerArtView.js +11 -11
- package/dist/features/seller/components/SellerAuctionsView.js +11 -11
- package/dist/features/seller/components/SellerBidsView.js +3 -3
- package/dist/features/seller/components/SellerBundlesView.js +12 -12
- package/dist/features/seller/components/SellerClassifiedView.js +11 -11
- package/dist/features/seller/components/SellerCouponEditorView.js +2 -2
- package/dist/features/seller/components/SellerDigitalCodesView.js +11 -11
- package/dist/features/seller/components/SellerFeaturesView.js +4 -4
- package/dist/features/seller/components/SellerLiveView.js +11 -11
- package/dist/features/seller/components/SellerOffersPanel.js +3 -2
- package/dist/features/seller/components/SellerOrdersView.js +2 -2
- package/dist/features/seller/components/SellerPayoutMethodsView.js +1 -1
- package/dist/features/seller/components/SellerPayoutRequestView.js +6 -5
- package/dist/features/seller/components/SellerPayoutSettingsView.js +5 -4
- package/dist/features/seller/components/SellerPreOrdersView.js +1 -1
- package/dist/features/seller/components/SellerPrizeDrawsView.js +1 -1
- package/dist/features/seller/components/SellerProductShell.js +20 -6
- package/dist/features/seller/components/SellerProductsCards.js +3 -3
- package/dist/features/seller/components/SellerProductsView.js +4 -4
- package/dist/features/seller/components/SellerReviewsView.js +7 -6
- package/dist/features/seller/components/SellerShippingView.js +2 -1
- package/dist/features/seller/components/SellerSidebar.js +5 -5
- package/dist/features/seller/components/SellerStickersView.js +11 -11
- package/dist/features/seller/components/SellerTemplatesView.js +1 -1
- package/dist/features/seller/schemas/index.d.ts +20 -20
- package/dist/features/server-errors/schemas/index.d.ts +6 -6
- package/dist/features/shell/CommandPalette.d.ts +27 -0
- package/dist/features/shell/CommandPalette.js +92 -0
- package/dist/features/shell/FormShell.js +4 -3
- package/dist/features/shell/QuickFormDrawer.js +3 -2
- package/dist/features/shell/StepForm.js +2 -2
- package/dist/features/shell/index.d.ts +2 -0
- package/dist/features/shell/index.js +1 -0
- package/dist/features/shipments/components/AdminShipmentEditorView.d.ts +7 -0
- package/dist/features/shipments/components/AdminShipmentEditorView.js +123 -0
- package/dist/features/shipments/components/AdminShipmentLotItemsView.d.ts +6 -0
- package/dist/features/shipments/components/AdminShipmentLotItemsView.js +96 -0
- package/dist/features/shipments/components/AdminShipmentProjectionsView.d.ts +9 -0
- package/dist/features/shipments/components/AdminShipmentProjectionsView.js +44 -0
- package/dist/features/shipments/components/AdminShipmentsView.d.ts +8 -0
- package/dist/features/shipments/components/AdminShipmentsView.js +82 -0
- package/dist/features/shipments/components/ShipmentItemLinkModal.d.ts +15 -0
- package/dist/features/shipments/components/ShipmentItemLinkModal.js +37 -0
- package/dist/features/shipments/hooks/useShipments.d.ts +69 -0
- package/dist/features/shipments/hooks/useShipments.js +96 -0
- package/dist/features/shipments/index.d.ts +10 -0
- package/dist/features/shipments/index.js +7 -0
- package/dist/features/shipments/manifest.d.ts +2 -0
- package/dist/features/shipments/manifest.js +26 -0
- package/dist/features/shipments/repository/shipment-items.repository.d.ts +56 -0
- package/dist/features/shipments/repository/shipment-items.repository.js +78 -0
- package/dist/features/shipments/repository/shipment-lots.repository.d.ts +48 -0
- package/dist/features/shipments/repository/shipment-lots.repository.js +55 -0
- package/dist/features/shipments/repository/shipments.repository.d.ts +50 -0
- package/dist/features/shipments/repository/shipments.repository.js +77 -0
- package/dist/features/shipments/schemas/firestore.d.ts +150 -0
- package/dist/features/shipments/schemas/firestore.js +76 -0
- package/dist/features/shipments/schemas/index.d.ts +2 -0
- package/dist/features/shipments/schemas/index.js +2 -0
- package/dist/features/shipments/schemas/validation.d.ts +350 -0
- package/dist/features/shipments/schemas/validation.js +96 -0
- package/dist/features/shipments/utils/cost-allocation.d.ts +25 -0
- package/dist/features/shipments/utils/cost-allocation.js +83 -0
- package/dist/features/site-settings/components/ActionPermissionsManager.js +2 -2
- package/dist/features/stores/components/InteractiveStoreCard.js +2 -2
- package/dist/features/stores/components/StoreAboutView.js +1 -1
- package/dist/features/stores/components/StoreAuctionsListing.js +3 -3
- package/dist/features/stores/components/StoreAuctionsView.js +1 -1
- package/dist/features/stores/components/StoreCapabilitiesGuideView.js +1 -1
- package/dist/features/stores/components/StoreClassifiedsListing.js +2 -2
- package/dist/features/stores/components/StoreDetailLayoutView.js +1 -1
- package/dist/features/stores/components/StoreDigitalCodesListing.js +2 -2
- package/dist/features/stores/components/StoreFinanceGuideView.js +2 -2
- package/dist/features/stores/components/StoreGuideHubView.js +2 -2
- package/dist/features/stores/components/StoreHeader.js +4 -4
- package/dist/features/stores/components/StoreLiveItemsListing.js +2 -2
- package/dist/features/stores/components/StoreNavTabs.js +2 -2
- package/dist/features/stores/components/StoreOrdersGuideView.js +1 -1
- package/dist/features/stores/components/StorePreOrdersListing.js +3 -3
- package/dist/features/stores/components/StoreProductsListing.js +1 -1
- package/dist/features/stores/components/StoreReviewsListing.js +2 -2
- package/dist/features/stores/components/StoreReviewsView.js +1 -1
- package/dist/features/stores/components/StoreSettingsGuideView.js +1 -1
- package/dist/features/stores/components/StoresIndexListing.js +9 -3
- package/dist/features/stores/schemas/index.d.ts +10 -10
- package/dist/features/support/schemas/index.d.ts +22 -22
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +3 -3
- package/dist/features/whatsapp-bot/components/WhatsAppChatButton.js +1 -1
- package/dist/features/wishlist/hooks/useWishlistCount.js +1 -2
- package/dist/index.d.ts +44 -1
- package/dist/index.js +37 -1
- package/dist/next/routing/route-map.d.ts +18 -0
- package/dist/next/routing/route-map.js +9 -0
- package/dist/react/hooks/useVisualViewportInset.d.ts +1 -0
- package/dist/react/hooks/useVisualViewportInset.js +59 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +1 -0
- package/dist/repositories/index.d.ts +5 -0
- package/dist/repositories/index.js +5 -0
- package/dist/schemas/registry.d.ts +398 -364
- package/dist/schemas/sieve.d.ts +2 -2
- package/dist/schemas/webhooks/google-oauth.d.ts +2 -2
- package/dist/schemas/webhooks/razorpay.d.ts +100 -100
- package/dist/seed/_helpers/media.js +1 -0
- package/dist/seed/actions/demo-seed-actions.d.ts +1 -1
- package/dist/seed/catalogue-seed-data.d.ts +2 -0
- package/dist/seed/catalogue-seed-data.js +112 -0
- package/dist/seed/grouped-listings-seed-data.d.ts +5 -0
- package/dist/seed/homepage-sections-seed-data.js +0 -1
- package/dist/seed/index.d.ts +2 -0
- package/dist/seed/index.js +2 -0
- package/dist/seed/manifest.js +6 -0
- package/dist/seed/products-preorders-seed-data.d.ts +5 -0
- package/dist/seed/shipments-seed-data.d.ts +5 -0
- package/dist/seed/shipments-seed-data.js +185 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.js +5 -0
- package/dist/styles.css +75 -19
- package/dist/tailwind-utilities.css +1 -1
- package/dist/tokens/index.d.ts +0 -2
- package/dist/tokens/index.js +0 -2
- package/dist/tokens/tokens.css +12 -2
- package/dist/ui/DataTable.js +4 -3
- package/dist/ui/components/Button.d.ts +4 -1
- package/dist/ui/components/Button.js +11 -5
- package/dist/ui/components/Checkbox.d.ts +9 -1
- package/dist/ui/components/Checkbox.js +5 -2
- package/dist/ui/components/ClaimCouponButton.js +2 -1
- package/dist/ui/components/ConfirmDeleteModal.style.css +1 -1
- package/dist/ui/components/Drawer.style.css +13 -1
- package/dist/ui/components/Dropdown.style.css +2 -2
- package/dist/ui/components/FilterDrawer.d.ts +4 -1
- package/dist/ui/components/FilterDrawer.js +8 -2
- package/dist/ui/components/Form.d.ts +1 -1
- package/dist/ui/components/Form.js +2 -2
- package/dist/ui/components/FormActionBar.style.css +6 -1
- package/dist/ui/components/IconButton.d.ts +6 -1
- package/dist/ui/components/IconButton.js +5 -2
- package/dist/ui/components/IconButton.style.css +11 -0
- package/dist/ui/components/ImageGallery.style.css +2 -0
- package/dist/ui/components/ImageLightbox.style.css +1 -0
- package/dist/ui/components/ListingFilterDrawer.d.ts +4 -1
- package/dist/ui/components/ListingFilterDrawer.js +4 -3
- package/dist/ui/components/ListingLayout.style.css +2 -2
- package/dist/ui/components/Modal.style.css +1 -1
- package/dist/ui/components/Pagination.d.ts +5 -1
- package/dist/ui/components/Pagination.js +4 -2
- package/dist/ui/components/RowActionMenu.js +1 -1
- package/dist/ui/components/RowActionMenu.style.css +1 -1
- package/dist/ui/components/Select.d.ts +6 -1
- package/dist/ui/components/Select.js +18 -13
- package/dist/ui/components/Select.style.css +1 -1
- package/dist/ui/components/Semantic.d.ts +13 -0
- package/dist/ui/components/Semantic.js +16 -3
- package/dist/ui/components/SideDrawer.style.css +16 -4
- package/dist/ui/components/SideModal.style.css +1 -1
- package/dist/ui/components/StickyToolbar.d.ts +3 -2
- package/dist/ui/components/StickyToolbar.js +1 -1
- package/dist/ui/components/Textarea.d.ts +5 -0
- package/dist/ui/components/Textarea.js +8 -4
- package/dist/ui/components/Toast.style.css +3 -0
- package/dist/ui/components/UnsavedChangesModal.style.css +1 -1
- package/dist/ui/components/surface-tokens.d.ts +121 -113
- package/dist/ui/components/surface-tokens.js +110 -104
- package/dist/ui/forms/FormShell.d.ts +8 -27
- package/dist/ui/forms/FormShell.js +1 -194
- package/dist/ui/forms/index.d.ts +2 -2
- package/dist/ui/forms/index.js +1 -1
- package/dist/ui/index.d.ts +8 -4
- package/dist/ui/index.js +4 -2
- package/dist/utils/id-generators.d.ts +27 -0
- package/dist/utils/id-generators.js +45 -0
- package/dist/utils/number.formatter.d.ts +7 -0
- package/dist/utils/number.formatter.js +9 -0
- package/dist/validation/schemas.d.ts +5 -5
- 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" ?
|
|
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" ?
|
|
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" ?
|
|
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" ?
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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 {
|
|
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(
|
|
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(
|
|
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(
|
|
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:
|
|
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,
|
|
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
|
|
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
|
|
579
|
+
runSyncPreflight([{ item, product }]);
|
|
580
580
|
}
|
|
581
|
-
availableItems.push({ item, product
|
|
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
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
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 ${
|
|
820
|
-
: `Product ${
|
|
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
|
-
|
|
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 {
|
|
1164
|
+
return {
|
|
1165
|
+
orderIds,
|
|
1166
|
+
total,
|
|
1167
|
+
itemCount: orderIds.length,
|
|
1168
|
+
...(unavailablePaid.length > 0 ? { unavailableItems: unavailablePaid } : {}),
|
|
1169
|
+
};
|
|
1056
1170
|
}
|