@mohasinac/appkit 2.8.2 → 2.8.3
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 +7 -1
- package/dist/_internal/client/features/digital-code/CodeRevealPanel.js +4 -1
- package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.js +7 -1
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +3 -2
- package/dist/_internal/client/features/live/LiveItemDetailView.js +11 -2
- package/dist/_internal/client/scaffolds/AppShell.js +2 -1
- package/dist/_internal/client/scaffolds/DashboardScaffold.js +2 -1
- package/dist/_internal/server/features/checkout/actions.js +40 -39
- package/dist/_internal/shared/actions/action-registry.js +6 -0
- package/dist/_internal/shared/config/index.d.ts +1 -1
- package/dist/_internal/shared/config/schema.d.ts +0 -8
- package/dist/client-entry.d.ts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/configs/next.js +12 -22
- package/dist/constants/api-endpoints.d.ts +6 -0
- package/dist/constants/api-endpoints.js +2 -0
- package/dist/core/hooks/useSiteSettings.d.ts +1 -1
- package/dist/features/about/components/AboutView.js +5 -2
- package/dist/features/about/components/FAQPageView.js +3 -3
- package/dist/features/about/components/FeesView.js +13 -5
- package/dist/features/about/components/HelpPageView.js +9 -5
- package/dist/features/about/components/HowAuctionsWorkView.js +9 -5
- package/dist/features/about/components/HowCheckoutWorksView.js +9 -5
- package/dist/features/about/components/HowOffersWorkView.js +10 -5
- package/dist/features/about/components/HowOrdersWorkView.js +10 -5
- package/dist/features/about/components/HowPayoutsWorkView.js +9 -5
- package/dist/features/about/components/HowPreOrdersWorkView.js +9 -5
- package/dist/features/about/components/HowReviewsWorkView.js +9 -5
- package/dist/features/about/components/PolicyPageView.js +3 -3
- package/dist/features/about/components/PublicProfileView.js +11 -4
- package/dist/features/about/components/SecurityPrivacyView.js +8 -4
- package/dist/features/about/components/ShippingPolicyView.js +3 -2
- package/dist/features/about/components/TrackOrderView.js +2 -2
- package/dist/features/about/components/UnauthorizedView.js +3 -3
- package/dist/features/account/components/AddressBook.js +1 -1
- package/dist/features/account/components/AddressForm.js +2 -2
- package/dist/features/account/components/AddressInlineSelect.d.ts +24 -0
- package/dist/features/account/components/AddressInlineSelect.js +78 -0
- package/dist/features/account/components/AddressSelectorCreate.d.ts +2 -1
- package/dist/features/account/components/AddressSelectorCreate.js +5 -32
- package/dist/features/account/components/AddressesIndexListing.js +3 -3
- package/dist/features/account/components/ChatWindow.js +2 -1
- package/dist/features/account/components/NotificationBell.js +13 -7
- package/dist/features/account/components/NotificationPreferencesPanel.js +4 -1
- package/dist/features/account/components/UserOffersPanel.js +2 -1
- package/dist/features/account/components/UserSidebar.js +11 -7
- package/dist/features/account/components/UserSupportView.js +13 -4
- package/dist/features/account/components/index.d.ts +2 -0
- package/dist/features/account/components/index.js +1 -0
- package/dist/features/account/hooks/useAccount.d.ts +2 -2
- package/dist/features/account/hooks/useAddressSelector.d.ts +1 -1
- package/dist/features/account/hooks/useAddresses.d.ts +2 -2
- package/dist/features/account/hooks/useNotifications.d.ts +1 -1
- package/dist/features/account/hooks/useProfile.d.ts +1 -1
- package/dist/features/account/hooks/usePublicProfile.d.ts +2 -2
- package/dist/features/addresses/repository/addresses.repository.d.ts +1 -0
- package/dist/features/addresses/repository/addresses.repository.js +13 -0
- package/dist/features/admin/components/AdminAdEditorView.js +8 -5
- package/dist/features/admin/components/AdminAddressEditorView.js +5 -5
- package/dist/features/admin/components/AdminAdsView.js +10 -7
- package/dist/features/admin/components/AdminBlogEditorView.js +15 -9
- package/dist/features/admin/components/AdminBrandEditorView.js +10 -4
- package/dist/features/admin/components/AdminBrandsView.js +4 -4
- package/dist/features/admin/components/AdminBundleEditorView.js +4 -5
- package/dist/features/admin/components/AdminBundlesView.js +3 -3
- package/dist/features/admin/components/AdminCarouselEditorView.js +6 -3
- package/dist/features/admin/components/AdminCarouselView.js +6 -6
- package/dist/features/admin/components/AdminCatalogGuideView.js +2 -1
- package/dist/features/admin/components/AdminCategoriesView.js +5 -5
- package/dist/features/admin/components/AdminCategoryEditorView.js +11 -5
- package/dist/features/admin/components/AdminContactEditorView.js +8 -1
- package/dist/features/admin/components/AdminCouponEditorView.js +23 -5
- package/dist/features/admin/components/AdminEmployeeEditorView.js +7 -4
- package/dist/features/admin/components/AdminFaqEditorView.js +9 -3
- package/dist/features/admin/components/AdminFaqsView.js +4 -4
- package/dist/features/admin/components/AdminFeatureEditorView.js +7 -1
- package/dist/features/admin/components/AdminFeatureFlagsView.js +4 -1
- package/dist/features/admin/components/AdminFilterBar.js +4 -4
- package/dist/features/admin/components/AdminGroupedListingsView.js +65 -30
- package/dist/features/admin/components/AdminGuideHubView.js +4 -1
- package/dist/features/admin/components/AdminMediaView.js +4 -1
- package/dist/features/admin/components/AdminNavigationView.js +7 -4
- package/dist/features/admin/components/AdminNotificationsView.js +2 -2
- package/dist/features/admin/components/AdminOrderEditorView.js +2 -2
- package/dist/features/admin/components/AdminPageHeader.js +5 -2
- package/dist/features/admin/components/AdminPrizeDrawsView.js +5 -5
- package/dist/features/admin/components/AdminProductEditorView.js +12 -5
- package/dist/features/admin/components/AdminProductsView.js +4 -4
- package/dist/features/admin/components/AdminReviewsView.js +2 -2
- package/dist/features/admin/components/AdminScammerEditorView.js +6 -2
- package/dist/features/admin/components/AdminScammersView.js +3 -3
- package/dist/features/admin/components/AdminSectionsView.js +20 -22
- package/dist/features/admin/components/AdminSessionsManager.js +2 -1
- package/dist/features/admin/components/AdminSessionsView.js +2 -2
- package/dist/features/admin/components/AdminSidebar.js +11 -7
- package/dist/features/admin/components/AdminSiteConfigGuideView.js +2 -1
- package/dist/features/admin/components/AdminSiteSettingsView.js +5 -1
- package/dist/features/admin/components/AdminStoreAddressesView.js +2 -2
- package/dist/features/admin/components/AdminStoreEditorView.js +5 -5
- package/dist/features/admin/components/AdminSublistingCategoryEditorView.js +3 -3
- package/dist/features/admin/components/AdminSupportTicketDetailView.js +10 -3
- package/dist/features/admin/components/AdminSupportTicketsView.js +3 -3
- package/dist/features/admin/components/AdminTrustGuideView.js +3 -3
- package/dist/features/admin/components/AdminUsersGuideView.js +3 -3
- package/dist/features/admin/components/AdminViewCards.js +12 -6
- package/dist/features/admin/components/BrandQuickCreateForm.js +2 -2
- package/dist/features/admin/components/CategoryQuickCreateForm.js +2 -2
- package/dist/features/admin/components/DashboardStats.js +9 -3
- package/dist/features/admin/components/DataListingView.js +3 -3
- package/dist/features/admin/components/DataTable.js +11 -7
- package/dist/features/admin/components/DrawerFormFooter.js +2 -2
- package/dist/features/admin/components/QuickEditMenu.js +2 -1
- package/dist/features/admin/components/analytics/AdminAnalyticsCharts.js +5 -1
- package/dist/features/admin/hooks/useAdmin.d.ts +1 -1
- package/dist/features/admin/hooks/useAdminSectionsListing.d.ts +1 -1
- package/dist/features/admin/hooks/useChat.d.ts +1 -1
- package/dist/features/auctions/components/AuctionBidsTable.js +4 -1
- package/dist/features/auctions/components/AuctionDetailPageView.js +14 -6
- package/dist/features/auctions/components/CollapsibleBidHistory.js +5 -1
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +9 -3
- package/dist/features/auctions/components/MarketplaceAuctionGrid.js +8 -2
- package/dist/features/auctions/components/PlaceBidFormClient.js +4 -1
- package/dist/features/auctions/hooks/useAuctions.d.ts +8 -8
- package/dist/features/auth/components/RegisterForm.js +2 -2
- package/dist/features/auth/components/VerifyEmailView.js +5 -2
- package/dist/features/auth/hooks/useAuth.d.ts +2 -2
- package/dist/features/before-after/components/BeforeAfterSlider.js +1 -1
- package/dist/features/blog/components/BlogFeaturedCard.js +8 -1
- package/dist/features/blog/components/BlogIndexListing.js +11 -5
- package/dist/features/blog/components/BlogListView.js +11 -3
- package/dist/features/blog/components/BlogPostView.js +10 -3
- package/dist/features/cart/components/CartDrawer.js +11 -3
- package/dist/features/cart/components/CartSummary.js +2 -2
- package/dist/features/cart/components/CheckoutOtpModal.js +2 -1
- package/dist/features/cart/hooks/useCart.d.ts +1 -1
- package/dist/features/cart/hooks/useCartQuery.d.ts +1 -1
- package/dist/features/cart/hooks/useCheckoutReadQueries.d.ts +2 -2
- package/dist/features/cart/hooks/useOrder.d.ts +2 -2
- package/dist/features/categories/components/BrandDetailPageView.js +5 -2
- package/dist/features/categories/components/BrandDetailTabs.js +5 -1
- package/dist/features/categories/components/BundleDetailView.js +6 -3
- package/dist/features/categories/components/BundleDynamicRuleEditor.js +3 -1
- package/dist/features/categories/components/BundleItemsPicker.js +10 -3
- package/dist/features/categories/components/CategoriesIndexListing.js +12 -6
- package/dist/features/categories/components/CategoryBundlesListing.js +5 -2
- package/dist/features/categories/components/CategoryDetailPageView.js +6 -2
- package/dist/features/categories/components/CategoryDetailTabs.js +5 -1
- package/dist/features/categories/components/CategoryForm.js +6 -3
- package/dist/features/categories/components/CategoryGrid.js +9 -2
- package/dist/features/categories/components/CategoryProductsListing.js +10 -4
- package/dist/features/categories/components/CategorySelectorCreate.js +3 -3
- package/dist/features/categories/components/CategorySortSelect.js +1 -1
- package/dist/features/categories/components/CategoryStoresListing.js +3 -3
- package/dist/features/categories/components/CategoryTableColumns.js +10 -6
- package/dist/features/categories/components/CategoryTree.js +1 -1
- package/dist/features/categories/hooks/useCategories.d.ts +3 -3
- package/dist/features/categories/hooks/useCategorySelector.d.ts +3 -3
- package/dist/features/categories/hooks/useCategoryTree.d.ts +1 -1
- package/dist/features/checkout/hooks/useCheckoutApi.d.ts +2 -2
- package/dist/features/classified/components/ClassifiedFilters.js +2 -2
- package/dist/features/classified/components/ClassifiedIndexListing.js +9 -3
- package/dist/features/collections/components/CollectionCard.js +2 -1
- package/dist/features/collections/hooks/useCollections.d.ts +2 -2
- package/dist/features/contact/components/ContactForm.js +4 -2
- package/dist/features/contact/components/ContactInfoSidebar.js +4 -1
- package/dist/features/copilot/components/AdminCopilotView.js +13 -5
- package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +9 -3
- package/dist/features/events/components/AdminEventEditorView.js +62 -40
- package/dist/features/events/components/AdminEventEntriesView.js +9 -6
- package/dist/features/events/components/EventCard.js +7 -1
- package/dist/features/events/components/EventFormDrawer.js +2 -1
- package/dist/features/events/components/EventLeaderboard.js +4 -4
- package/dist/features/events/components/EventOfferCard.js +4 -1
- package/dist/features/events/components/EventParticipateView.js +3 -2
- package/dist/features/events/components/EventPollWidget.js +6 -5
- package/dist/features/events/components/EventRaffleEntryForm.js +5 -2
- package/dist/features/events/components/EventRaffleWinnerView.js +7 -1
- package/dist/features/events/components/EventRafflesSection.js +2 -2
- package/dist/features/events/components/EventSaleBanner.js +5 -2
- package/dist/features/events/components/EventsIndexListing.js +8 -2
- package/dist/features/events/components/EventsListView.js +4 -1
- package/dist/features/events/components/SpinWheelView.js +7 -2
- package/dist/features/events/hooks/useEvent.d.ts +3 -3
- package/dist/features/events/hooks/useEvents.d.ts +1 -1
- package/dist/features/events/schemas/firestore.d.ts +1 -0
- package/dist/features/events/types/index.d.ts +1 -0
- package/dist/features/faq/components/ContactCTA.js +4 -1
- package/dist/features/faq/components/FAQCategorySidebar.js +2 -2
- package/dist/features/faq/components/FAQHelpfulButtons.js +8 -5
- package/dist/features/faq/components/FAQPageContent.js +5 -5
- package/dist/features/faq/components/FAQSortDropdown.js +2 -2
- package/dist/features/faq/hooks/useFAQs.d.ts +1 -1
- package/dist/features/faq/hooks/useFaqList.d.ts +15 -15
- package/dist/features/filters/AsyncFacetSection.js +4 -2
- package/dist/features/filters/FilterFacetSection.js +14 -6
- package/dist/features/filters/RangeFilter.js +4 -2
- package/dist/features/filters/SwitchFilter.js +2 -1
- package/dist/features/forms/Checkbox.js +1 -1
- package/dist/features/forms/Radio.js +1 -1
- package/dist/features/forms/Slider.js +1 -1
- package/dist/features/homepage/components/AdSlot.js +4 -4
- package/dist/features/homepage/components/AdvertisementBanner.js +13 -4
- package/dist/features/homepage/components/AnnouncementBar.js +2 -1
- package/dist/features/homepage/components/BeforeAfterCard.js +8 -2
- package/dist/features/homepage/components/BrandsSection.js +6 -3
- package/dist/features/homepage/components/CTABannerSection.js +2 -2
- package/dist/features/homepage/components/CharacterHotspot.js +5 -2
- package/dist/features/homepage/components/CharacterHotspotForm.js +8 -4
- package/dist/features/homepage/components/CustomCardsSection.js +13 -7
- package/dist/features/homepage/components/CustomerReviewsSection.js +9 -3
- package/dist/features/homepage/components/FAQSection.js +7 -4
- package/dist/features/homepage/components/FeaturedBundlesSection.js +8 -2
- package/dist/features/homepage/components/FeaturedResultsSection.js +1 -1
- package/dist/features/homepage/components/GoogleReviewsSection.js +14 -8
- package/dist/features/homepage/components/HeroCarousel.js +1 -1
- package/dist/features/homepage/components/HomepageSkeleton.js +7 -1
- package/dist/features/homepage/components/HowItWorksInfoView.js +2 -2
- package/dist/features/homepage/components/HowItWorksSection.js +2 -2
- package/dist/features/homepage/components/NewsletterBanner.js +3 -2
- package/dist/features/homepage/components/NewsletterSection.js +5 -2
- package/dist/features/homepage/components/PromoGrid.js +4 -1
- package/dist/features/homepage/components/SectionCarousel.js +7 -4
- package/dist/features/homepage/components/SecurityHighlightsSection.js +3 -3
- package/dist/features/homepage/components/ShopByCategorySection.js +10 -4
- package/dist/features/homepage/components/SiteFeaturesSection.js +5 -2
- package/dist/features/homepage/components/SocialFeedSection.js +4 -4
- package/dist/features/homepage/components/SocialPostCard.js +6 -3
- package/dist/features/homepage/components/TrustFeaturesSection.js +5 -5
- package/dist/features/homepage/components/TrustIndicatorsSection.js +5 -2
- package/dist/features/homepage/components/WelcomeSection.js +1 -1
- package/dist/features/homepage/components/WhatsAppCommunitySection.js +3 -3
- package/dist/features/homepage/hooks/useBlogArticles.d.ts +1 -1
- package/dist/features/homepage/hooks/useFeaturedAuctions.d.ts +1 -1
- package/dist/features/homepage/hooks/useFeaturedPreOrders.d.ts +1 -1
- package/dist/features/homepage/hooks/useFeaturedProducts.d.ts +1 -1
- package/dist/features/homepage/hooks/useFeaturedStores.d.ts +1 -1
- package/dist/features/homepage/hooks/useHeroCarousel.d.ts +1 -1
- package/dist/features/homepage/hooks/useHomepageEvents.d.ts +1 -1
- package/dist/features/homepage/hooks/useHomepageReviews.d.ts +1 -1
- package/dist/features/homepage/hooks/useHomepageSections.d.ts +1 -1
- package/dist/features/homepage/hooks/useTopBrands.d.ts +1 -1
- package/dist/features/homepage/hooks/useTopCategories.d.ts +1 -1
- package/dist/features/layout/AppLayoutShell.js +2 -1
- package/dist/features/layout/BackToTop.js +1 -1
- package/dist/features/layout/BottomActions.js +4 -3
- package/dist/features/layout/BottomNavItem.js +1 -1
- package/dist/features/layout/BottomSheet.js +4 -1
- package/dist/features/layout/FooterLayout.js +1 -1
- package/dist/features/layout/NavbarLayout.js +4 -1
- package/dist/features/layout/SidebarLayout.js +5 -2
- package/dist/features/live/components/LiveItemFilters.js +2 -2
- package/dist/features/live/components/LiveItemsIndexListing.js +9 -3
- package/dist/features/loyalty/components/CoinsDisplay.js +4 -2
- package/dist/features/loyalty/hooks/useLoyaltyBalance.d.ts +1 -1
- package/dist/features/media/AvatarUpload.js +2 -2
- package/dist/features/media/MediaLightbox.js +3 -2
- package/dist/features/media/modals/VideoThumbnailSelector.js +4 -1
- package/dist/features/media/modals/VideoTrimModal.js +1 -1
- package/dist/features/media/upload/CameraCapture.js +1 -1
- package/dist/features/media/upload/ImageUpload.js +4 -1
- package/dist/features/media/upload/MediaUploadField.js +11 -2
- package/dist/features/media/upload/MediaUploadList.js +5 -1
- package/dist/features/orders/components/MarketplaceOrderCard.js +2 -2
- package/dist/features/orders/components/OrdersList.js +2 -1
- package/dist/features/orders/components/RefundHistoryTable.js +4 -1
- package/dist/features/orders/components/RefundRequestView.js +2 -1
- package/dist/features/orders/hooks/useOrders.d.ts +2 -2
- package/dist/features/payments/hooks/usePayments.d.ts +1 -1
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +5 -1
- package/dist/features/pre-orders/components/PreOrderActionsClient.js +3 -3
- package/dist/features/pre-orders/components/PreOrderBadge.js +2 -1
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +16 -7
- package/dist/features/pre-orders/components/PreOrdersIndexListing.js +32 -24
- package/dist/features/pre-orders/hooks/usePreOrders.d.ts +2 -2
- package/dist/features/products/columns/productTableColumns.js +9 -4
- package/dist/features/products/components/AuctionsIndexListing.js +9 -3
- package/dist/features/products/components/BidHistory.js +4 -4
- package/dist/features/products/components/CompareOverlay.js +10 -2
- package/dist/features/products/components/CustomFieldsEditor.js +2 -1
- package/dist/features/products/components/CustomSectionTabContent.js +2 -2
- package/dist/features/products/components/CustomSectionsEditor.js +3 -2
- package/dist/features/products/components/GroupSettingsPanel.js +34 -26
- package/dist/features/products/components/MakeOfferButton.js +6 -2
- package/dist/features/products/components/MakeOfferForm.js +2 -1
- package/dist/features/products/components/MarketplaceBundleCard.js +6 -3
- package/dist/features/products/components/MarketplacePrizeDrawCard.js +3 -2
- package/dist/features/products/components/PlaceBidForm.js +2 -1
- package/dist/features/products/components/PrizeDrawCollage.js +6 -2
- package/dist/features/products/components/PrizeDrawDetailPageView.js +6 -1
- package/dist/features/products/components/PrizeDrawItemsEditor.js +4 -2
- package/dist/features/products/components/PrizeDrawsIndexListing.js +6 -3
- package/dist/features/products/components/PrizeDrawsSection.js +2 -2
- package/dist/features/products/components/PrizeRevealModal.js +5 -1
- package/dist/features/products/components/ProductDetailPageView.js +32 -16
- package/dist/features/products/components/ProductFeatureBadges.js +9 -9
- package/dist/features/products/components/ProductForm.d.ts +11 -1
- package/dist/features/products/components/ProductForm.js +10 -5
- package/dist/features/products/components/ProductGalleryClient.js +8 -4
- package/dist/features/products/components/ProductGradingTab.js +4 -1
- package/dist/features/products/components/ProductGrid.js +35 -14
- package/dist/features/products/components/ProductInfo.js +2 -1
- package/dist/features/products/components/ProductTabs.js +2 -1
- package/dist/features/products/components/ProductTabsShell.js +5 -1
- package/dist/features/products/components/ProductsIndexListing.js +32 -24
- package/dist/features/products/components/ProductsIndexPageView.js +2 -2
- package/dist/features/products/components/RelatedProducts.js +3 -3
- package/dist/features/products/components/ShowGroupSection.js +10 -6
- package/dist/features/products/components/SublistingCarouselSection.js +7 -3
- package/dist/features/products/components/SublistingCategorySelect.d.ts +3 -1
- package/dist/features/products/components/SublistingCategorySelect.js +4 -37
- package/dist/features/products/constants/action-defs.js +3 -3
- package/dist/features/products/hooks/useProductDetail.d.ts +1 -1
- package/dist/features/products/hooks/useRelatedProducts.d.ts +1 -1
- package/dist/features/promotions/components/CouponCard.js +5 -3
- package/dist/features/promotions/components/CouponsIndexListing.js +7 -3
- package/dist/features/promotions/hooks/usePromotions.d.ts +2 -2
- package/dist/features/promotions/repository/coupons.repository.d.ts +8 -0
- package/dist/features/promotions/repository/coupons.repository.js +2 -0
- package/dist/features/reviews/components/ReviewDetailPageView.js +3 -3
- package/dist/features/reviews/components/ReviewDetailShell.js +15 -3
- package/dist/features/reviews/components/ReviewSummary.js +4 -2
- package/dist/features/reviews/components/ReviewsIndexListing.js +8 -2
- package/dist/features/reviews/components/ReviewsList.js +1 -1
- package/dist/features/reviews/hooks/useReviews.d.ts +2 -2
- 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 +6 -4
- package/dist/features/search/components/Search.js +9 -6
- package/dist/features/search/components/SearchFiltersRow.js +1 -1
- package/dist/features/search/components/SearchResultsSection.js +1 -1
- package/dist/features/search/hooks/useSearch.d.ts +2 -2
- package/dist/features/seller/components/CouponInlineSelect.d.ts +22 -0
- package/dist/features/seller/components/CouponInlineSelect.js +103 -0
- package/dist/features/seller/components/GroupInlineSelect.d.ts +23 -0
- package/dist/features/seller/components/GroupInlineSelect.js +80 -0
- package/dist/features/seller/components/PhysicalLocationModal.js +2 -1
- package/dist/features/seller/components/PrintCenterView.js +2 -1
- package/dist/features/seller/components/ProductInlineSelect.d.ts +24 -0
- package/dist/features/seller/components/ProductInlineSelect.js +42 -0
- package/dist/features/seller/components/QuickProductForm.js +4 -1
- package/dist/features/seller/components/SellerAddressesView.js +8 -3
- package/dist/features/seller/components/SellerAnalyticsAlertsView.js +6 -3
- package/dist/features/seller/components/SellerAnalyticsView.js +2 -2
- package/dist/features/seller/components/SellerBidsView.js +7 -7
- package/dist/features/seller/components/SellerBundlesView.js +2 -1
- package/dist/features/seller/components/SellerCouponEditorView.d.ts +2 -0
- package/dist/features/seller/components/SellerCouponEditorView.js +15 -3
- package/dist/features/seller/components/SellerCouponsView.js +1 -1
- package/dist/features/seller/components/SellerDashboardView.js +2 -2
- package/dist/features/seller/components/SellerDigitalCodesView.js +2 -2
- package/dist/features/seller/components/SellerGoogleReviewsView.js +2 -2
- package/dist/features/seller/components/SellerGroupedListingsView.js +5 -5
- package/dist/features/seller/components/SellerOrdersView.js +13 -10
- package/dist/features/seller/components/SellerPayoutMethodsView.js +5 -4
- package/dist/features/seller/components/SellerPayoutRequestView.js +5 -1
- package/dist/features/seller/components/SellerPayoutSettingsView.js +5 -2
- package/dist/features/seller/components/SellerPreOrdersView.js +6 -6
- package/dist/features/seller/components/SellerPrizeDrawsView.js +6 -6
- package/dist/features/seller/components/SellerProductShell.js +1 -1
- package/dist/features/seller/components/SellerProductsCards.js +4 -1
- package/dist/features/seller/components/SellerProductsView.js +5 -5
- package/dist/features/seller/components/SellerReviewsView.js +7 -3
- package/dist/features/seller/components/SellerShippingConfigsView.js +4 -4
- package/dist/features/seller/components/SellerShippingView.js +1 -1
- package/dist/features/seller/components/SellerSidebar.js +15 -8
- package/dist/features/seller/components/SellerStoreCategoriesView.js +1 -1
- package/dist/features/seller/components/SellerStorefrontView.js +2 -2
- package/dist/features/seller/components/SellerTemplatesView.js +7 -4
- package/dist/features/seller/components/SublistingInlineSelect.d.ts +19 -0
- package/dist/features/seller/components/SublistingInlineSelect.js +83 -0
- package/dist/features/seller/components/analytics/SellerTopProducts.js +1 -1
- package/dist/features/seller/components/index.d.ts +8 -0
- package/dist/features/seller/components/index.js +4 -0
- package/dist/features/seller/hooks/useSellerPayouts.d.ts +3 -3
- package/dist/features/seller/hooks/useSellerStore.d.ts +6 -6
- package/dist/features/seller/hooks/useSellerStorefront.d.ts +2 -2
- package/dist/features/shell/FormShell.js +10 -2
- package/dist/features/shell/QuickFormDrawer.js +5 -5
- package/dist/features/shell/StepForm.js +6 -6
- package/dist/features/site-settings/components/ActionPermissionsManager.js +8 -4
- package/dist/features/site-settings/components/NavPermissionsManager.js +7 -4
- package/dist/features/stores/components/InteractiveStoreCard.js +5 -1
- package/dist/features/stores/components/StoreAboutView.js +4 -1
- package/dist/features/stores/components/StoreAddressSelectorCreate.d.ts +2 -1
- package/dist/features/stores/components/StoreAddressSelectorCreate.js +5 -31
- package/dist/features/stores/components/StoreAuctionsListing.js +6 -3
- package/dist/features/stores/components/StoreGuideHubView.js +5 -2
- package/dist/features/stores/components/StoreHeader.js +8 -1
- package/dist/features/stores/components/StorePreOrdersListing.js +6 -3
- package/dist/features/stores/components/StoreProductsListing.js +6 -3
- package/dist/features/stores/components/StoreReviewsListing.js +8 -2
- package/dist/features/stores/components/StoresIndexListing.js +12 -6
- package/dist/features/stores/hooks/useStoreAddressSelector.d.ts +1 -1
- package/dist/features/stores/hooks/useStores.d.ts +6 -6
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +7 -1
- package/dist/features/whatsapp-bot/components/WhatsAppChatButton.js +2 -1
- package/dist/features/wishlist/components/WishlistPage.js +2 -1
- package/dist/features/wishlist/hooks/useUserWishlist.d.ts +15 -15
- package/dist/features/wishlist/hooks/useWishlist.d.ts +1 -1
- package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.js +13 -1
- package/dist/next/components/GlobalError.js +2 -2
- package/dist/next/routing/route-map.d.ts +2 -0
- package/dist/next/routing/route-map.js +1 -0
- package/dist/react/ErrorBoundary.js +2 -2
- package/dist/styles.css +2 -1
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/DataTable.js +17 -16
- package/dist/ui/components/DateInput.js +2 -2
- package/dist/ui/components/DetailPageGallery.js +4 -1
- package/dist/ui/components/DetailPageTabs.js +6 -2
- package/dist/ui/components/ImageLightbox.js +5 -3
- package/dist/ui/components/Input.js +6 -3
- package/dist/ui/components/Layout.d.ts +4 -0
- package/dist/ui/components/Layout.js +1 -1
- package/dist/ui/components/Layout.style.css +1 -0
- package/dist/ui/components/ListingFilterDrawer.js +4 -1
- package/dist/ui/components/ListingLayout.js +9 -8
- package/dist/ui/components/ListingToolbar.js +5 -1
- package/dist/ui/components/PaginatedSelect.d.ts +1 -2
- package/dist/ui/components/PaginatedSelect.js +1 -2
- package/dist/ui/components/Radio.js +1 -1
- package/dist/ui/components/Select.js +2 -1
- package/dist/ui/components/Slider.js +1 -1
- package/dist/ui/components/VacationBanner.js +2 -1
- package/dist/ui/components/surface-tokens.d.ts +1 -0
- package/dist/ui/components/surface-tokens.js +1 -0
- package/package.json +11 -2
|
@@ -18,7 +18,7 @@ export declare function useAddressSelector(options?: {
|
|
|
18
18
|
}): {
|
|
19
19
|
addresses: SavedAddress[];
|
|
20
20
|
isLoading: boolean;
|
|
21
|
-
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<SavedAddress[]
|
|
21
|
+
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<NoInfer<SavedAddress[]>, Error>>;
|
|
22
22
|
createAddress: import("@tanstack/react-query").UseMutateFunction<CreateAddressApiResponse, Error, AddressFormData, unknown>;
|
|
23
23
|
isSaving: boolean;
|
|
24
24
|
};
|
|
@@ -36,11 +36,11 @@ export declare function useAddresses(options?: {
|
|
|
36
36
|
enabled?: boolean;
|
|
37
37
|
listEndpoint?: string;
|
|
38
38
|
filters?: AddressFilterParams;
|
|
39
|
-
}): import("@tanstack/react-query").UseQueryResult<Address[]
|
|
39
|
+
}): import("@tanstack/react-query").UseQueryResult<NoInfer<Address[]>, Error>;
|
|
40
40
|
export declare function useAddress(id: string, options?: {
|
|
41
41
|
enabled?: boolean;
|
|
42
42
|
byIdEndpoint?: (id: string) => string;
|
|
43
|
-
}): import("@tanstack/react-query").UseQueryResult<Address
|
|
43
|
+
}): import("@tanstack/react-query").UseQueryResult<NoInfer<Address>, Error>;
|
|
44
44
|
export declare function useCreateAddress(options?: {
|
|
45
45
|
listEndpoint?: string;
|
|
46
46
|
onSuccess?: (data: Address) => void;
|
|
@@ -16,7 +16,7 @@ export declare function useNotifications<TNotification = any>(limit?: number, op
|
|
|
16
16
|
notifications: TNotification[];
|
|
17
17
|
unreadCount: number;
|
|
18
18
|
isLoading: boolean;
|
|
19
|
-
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<NotificationsResponse<TNotification
|
|
19
|
+
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<NoInfer<NotificationsResponse<TNotification>>, Error>>;
|
|
20
20
|
markRead: import("@tanstack/react-query").UseMutateFunction<unknown, Error, string, unknown>;
|
|
21
21
|
markAllRead: import("@tanstack/react-query").UseMutateFunction<unknown, Error, void, unknown>;
|
|
22
22
|
isMarkingAll: boolean;
|
|
@@ -19,7 +19,7 @@ export interface UpdateCurrentProfileInput {
|
|
|
19
19
|
export declare function useCurrentProfile(options?: {
|
|
20
20
|
enabled?: boolean;
|
|
21
21
|
endpoint?: string;
|
|
22
|
-
}): import("@tanstack/react-query").UseQueryResult<UserProfile
|
|
22
|
+
}): import("@tanstack/react-query").UseQueryResult<NoInfer<UserProfile>, Error>;
|
|
23
23
|
export declare function useUpdateCurrentProfile(options?: {
|
|
24
24
|
onSuccess?: (data: unknown) => void;
|
|
25
25
|
onError?: (error: Error) => void;
|
|
@@ -71,8 +71,8 @@ export declare function usePublicProfile(userId: string, options?: PublicProfile
|
|
|
71
71
|
loading: boolean;
|
|
72
72
|
profileError: string;
|
|
73
73
|
isSeller: boolean;
|
|
74
|
-
productsData: ProductsApiResponse | undefined;
|
|
74
|
+
productsData: NoInfer<ProductsApiResponse> | undefined;
|
|
75
75
|
productsLoading: boolean;
|
|
76
|
-
reviewsData: SellerReviewsData | undefined;
|
|
76
|
+
reviewsData: NoInfer<SellerReviewsData> | undefined;
|
|
77
77
|
reviewsLoading: boolean;
|
|
78
78
|
};
|
|
@@ -18,6 +18,7 @@ export declare class AddressesRepository extends BaseRepository<AddressDocument>
|
|
|
18
18
|
createWithId(id: string, data: Partial<AddressDocument>): Promise<AddressDocument>;
|
|
19
19
|
update(id: string, data: Partial<AddressDocument>): Promise<AddressDocument>;
|
|
20
20
|
listByOwner(ownerType: AddressOwnerType, ownerId: string): Promise<AddressDocument[]>;
|
|
21
|
+
listByOwnerType(ownerType: AddressOwnerType, limit?: number): Promise<AddressDocument[]>;
|
|
21
22
|
countByOwner(ownerType: AddressOwnerType, ownerId: string): Promise<number>;
|
|
22
23
|
createForOwner(ownerType: AddressOwnerType, ownerId: string, input: AddressCreateInput): Promise<AddressDocument>;
|
|
23
24
|
updateForOwner(ownerType: AddressOwnerType, ownerId: string, addressId: string, input: AddressUpdateInput): Promise<AddressDocument>;
|
|
@@ -50,6 +50,19 @@ export class AddressesRepository extends BaseRepository {
|
|
|
50
50
|
throw new DatabaseError(`Failed to list addresses for ${ownerType}:${ownerId}`, error);
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
+
async listByOwnerType(ownerType, limit = 500) {
|
|
54
|
+
try {
|
|
55
|
+
const snapshot = await this.getCollection()
|
|
56
|
+
.where(ADDRESS_FIELDS.OWNER_TYPE, "==", ownerType)
|
|
57
|
+
.orderBy(ADDRESS_FIELDS.CREATED_AT, "desc")
|
|
58
|
+
.limit(limit)
|
|
59
|
+
.get();
|
|
60
|
+
return snapshot.docs.map((doc) => this.mapDoc(doc));
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
throw new DatabaseError(`Failed to list addresses by ownerType=${ownerType}`, error);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
53
66
|
async countByOwner(ownerType, ownerId) {
|
|
54
67
|
try {
|
|
55
68
|
return await getFirestoreCount(this.getCollection()
|
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import React from "react";
|
|
4
4
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
|
5
|
-
import { Alert, Button, Form, FormActions, Input, Select, StackedViewShell, Text, Toggle, useToast, } from "../../../ui";
|
|
5
|
+
import { Alert, Button, Div, Form, FormActions, Input, Select, Span, StackedViewShell, Text, Toggle, useToast, } from "../../../ui";
|
|
6
6
|
import { apiClient } from "../../../http";
|
|
7
7
|
import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
8
|
+
const __P = {
|
|
9
|
+
p3: "p-3",
|
|
10
|
+
};
|
|
8
11
|
function validateThirdPartyUrl(url, issues) {
|
|
9
12
|
if (!url.trim()) {
|
|
10
13
|
issues.push("Third-party ads require a third-party URL");
|
|
@@ -21,10 +24,10 @@ function validateThirdPartyUrl(url, issues) {
|
|
|
21
24
|
}
|
|
22
25
|
}
|
|
23
26
|
function renderAdScheduleSection({ startAt, setStartAt, endAt, setEndAt }) {
|
|
24
|
-
return (_jsxs(
|
|
27
|
+
return (_jsxs(Div, { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: [_jsx(Input, { label: "Start at (ISO)", value: startAt, onChange: (event) => setStartAt(event.target.value), placeholder: "2026-05-01T00:00:00.000Z" }), _jsx(Input, { label: "End at (ISO)", value: endAt, onChange: (event) => setEndAt(event.target.value), placeholder: "2026-05-30T23:59:59.000Z" })] }));
|
|
25
28
|
}
|
|
26
29
|
function renderAdCreativeSection({ title, setTitle, body, setBody, imageUrl, setImageUrl, ctaLabel, setCtaLabel, ctaHref, setCtaHref, adsenseSlot, setAdsenseSlot, thirdPartyUrl, setThirdPartyUrl, provider, }) {
|
|
27
|
-
return (_jsxs(
|
|
30
|
+
return (_jsxs(Div, { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: [_jsx(Input, { label: "Creative title", value: title, onChange: (e) => setTitle(e.target.value), placeholder: "Catch the mega sale" }), _jsx(Input, { label: "Creative body", value: body, onChange: (e) => setBody(e.target.value), placeholder: "Up to 40% off this weekend" }), _jsx(Input, { label: "Image URL", value: imageUrl, onChange: (e) => setImageUrl(e.target.value), placeholder: "https://..." }), _jsx(Input, { label: "CTA label", value: ctaLabel, onChange: (e) => setCtaLabel(e.target.value), placeholder: "Shop now" }), _jsx(Input, { label: "CTA URL", value: ctaHref, onChange: (e) => setCtaHref(e.target.value), placeholder: "/promotions/deals" }), provider === "adsense" ? (_jsx(Input, { label: "AdSense slot", value: adsenseSlot, onChange: (e) => setAdsenseSlot(e.target.value), placeholder: "1234567890" })) : null, provider === "thirdParty" ? (_jsx(Input, { label: "Third-party URL", value: thirdPartyUrl, onChange: (e) => setThirdPartyUrl(e.target.value), placeholder: "https://adnetwork.example/slot" })) : null] }));
|
|
28
31
|
}
|
|
29
32
|
export function AdminAdEditorView({ adId, endpointBase = ADMIN_ENDPOINTS.ADS, labels = {}, onSaved, ...rest }) {
|
|
30
33
|
const [name, setName] = React.useState("");
|
|
@@ -224,7 +227,7 @@ export function AdminAdEditorView({ adId, endpointBase = ADMIN_ENDPOINTS.ADS, la
|
|
|
224
227
|
return;
|
|
225
228
|
}
|
|
226
229
|
saveMutation.mutate();
|
|
227
|
-
}, className: "space-y-4", children: [_jsx(Input, { label: "Ad name", value: name, onChange: (event) => setName(event.target.value), placeholder: "Summer Campaign" }), _jsxs(
|
|
230
|
+
}, className: "space-y-4", children: [_jsx(Input, { label: "Ad name", value: name, onChange: (event) => setName(event.target.value), placeholder: "Summer Campaign" }), _jsxs(Div, { className: "grid grid-cols-1 md:grid-cols-3 gap-3", children: [_jsx(Select, { label: "Provider", value: provider, options: [
|
|
228
231
|
{ label: "Manual", value: "manual" },
|
|
229
232
|
{ label: "AdSense", value: "adsense" },
|
|
230
233
|
{ label: "Third Party", value: "thirdParty" },
|
|
@@ -233,6 +236,6 @@ export function AdminAdEditorView({ adId, endpointBase = ADMIN_ENDPOINTS.ADS, la
|
|
|
233
236
|
{ label: "Active", value: "active" },
|
|
234
237
|
{ label: "Scheduled", value: "scheduled" },
|
|
235
238
|
{ label: "Paused", value: "paused" },
|
|
236
|
-
], onChange: (event) => setStatus(event.target.value) }), _jsx(Input, { label: "Priority", type: "number", value: String(priority), onChange: (event) => setPriority(Number(event.target.value || 0)) })] }), _jsx(Toggle, { checked: requiresConsent, onChange: setRequiresConsent, label: "Require user ad-consent for this ad" }), _jsxs(
|
|
239
|
+
], onChange: (event) => setStatus(event.target.value) }), _jsx(Input, { label: "Priority", type: "number", value: String(priority), onChange: (event) => setPriority(Number(event.target.value || 0)) })] }), _jsx(Toggle, { checked: requiresConsent, onChange: setRequiresConsent, label: "Require user ad-consent for this ad" }), _jsxs(Div, { className: "space-y-2", children: [_jsx(Text, { className: "text-sm font-medium", children: "Placements" }), _jsx(Div, { className: "grid grid-cols-1 md:grid-cols-2 gap-2", children: placements.map((placement) => (_jsxs("label", { className: "flex items-center gap-2 rounded-md border border-neutral-200 dark:border-slate-700 px-3 py-2", children: [_jsx("input", { type: "checkbox", checked: selectedPlacements.includes(placement.id), onChange: () => togglePlacement(placement.id) }), _jsx(Span, { size: "sm", children: placement.label })] }, placement.id))) })] }), scheduleSection, creativeSection, _jsxs(Div, { className: `rounded-lg border border-neutral-200 dark:border-slate-700 ${__P.p3}`, children: [_jsx(Text, { className: "text-sm font-medium mb-1", children: "Preview" }), _jsx(Text, { className: "text-xs text-neutral-500 dark:text-zinc-400", children: title || name || "Untitled ad" }), body ? _jsx(Text, { className: "text-sm mt-1", children: body }) : null, ctaLabel ? _jsxs(Text, { className: "text-xs mt-1", children: ["CTA: ", ctaLabel, " (", ctaHref || "#", ")"] }) : null] }), publishHardeningRequired && publishIssues.length > 0 ? (_jsx(Alert, { variant: "warning", title: "Publish readiness issues", children: publishIssues.join("; ") })) : null, _jsx(FormActions, { align: "right", children: _jsx(Button, { type: "submit", disabled: saveMutation.isPending || blockedByPublishValidation || !name.trim() || selectedPlacements.length === 0, children: saveMutation.isPending ? "Saving..." : status === "active" ? "Publish ad" : adId ? "Save changes" : "Create ad" }) })] }),
|
|
237
240
|
] }));
|
|
238
241
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import React from "react";
|
|
4
4
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
|
5
|
-
import { Button, Card, CardBody, ConfirmDeleteModal, Form, Input, Select, StackedViewShell, Text, Toggle, useToast, } from "../../../ui";
|
|
5
|
+
import { Button, Card, CardBody, ConfirmDeleteModal, Div, Form, Input, Select, Span, StackedViewShell, Text, Toggle, useToast, } from "../../../ui";
|
|
6
6
|
import { apiClient } from "../../../http";
|
|
7
7
|
import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
8
8
|
import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
|
|
@@ -106,12 +106,12 @@ export function AdminAddressEditorView({ addressId, onSaved, onDeleted, ...rest
|
|
|
106
106
|
const formContent = (_jsxs(Form, { id: "address-editor-form", onSubmit: (e) => {
|
|
107
107
|
e.preventDefault();
|
|
108
108
|
saveMutation.mutate();
|
|
109
|
-
}, className: "space-y-6", children: [_jsxs(Card, { variant: "outlined", padding: "lg", children: [_jsx(SectionHeading, { children: "Ownership" }), _jsxs(
|
|
109
|
+
}, className: "space-y-6", children: [_jsxs(Card, { variant: "outlined", padding: "lg", children: [_jsx(SectionHeading, { children: "Ownership" }), _jsxs(Div, { className: "space-y-4", children: [_jsx(Div, { className: "flex gap-6", children: ["user", "store"].map((type) => (_jsxs("label", { className: "flex cursor-pointer items-center gap-2", children: [_jsx("input", { type: "radio", name: "ownerType", value: type, checked: form.ownerType === type, onChange: () => {
|
|
110
110
|
set("ownerType", type);
|
|
111
111
|
set("ownerId", "");
|
|
112
|
-
}, className: "accent-[var(--appkit-color-primary)]" }), _jsx(
|
|
112
|
+
}, className: "accent-[var(--appkit-color-primary)]" }), _jsx(Span, { size: "sm", className: "capitalize text-[var(--appkit-color-text)]", children: type })] }, type))) }), _jsx(Input, { label: form.ownerType === "user" ? "User ID" : "Store ID (slug)", value: form.ownerId, onChange: (e) => set("ownerId", e.target.value), required: true, placeholder: form.ownerType === "user" ? "user-mohsin-c" : "store-pokemon-palace", helperText: form.ownerType === "user"
|
|
113
113
|
? "Firebase Auth UID or user slug"
|
|
114
|
-
: "Store slug (e.g. store-pokemon-palace)" })] })] }), _jsxs(Card, { variant: "outlined", padding: "lg", children: [_jsx(SectionHeading, { children: "Contact & Location" }), _jsxs(
|
|
115
|
-
const twoPanel = (_jsxs(
|
|
114
|
+
: "Store slug (e.g. store-pokemon-palace)" })] })] }), _jsxs(Card, { variant: "outlined", padding: "lg", children: [_jsx(SectionHeading, { children: "Contact & Location" }), _jsxs(Div, { className: "space-y-4", children: [_jsxs(Div, { className: "grid gap-4 sm:grid-cols-2", children: [_jsx(Input, { label: "Label", value: form.label, onChange: (e) => set("label", e.target.value), required: true, placeholder: "Home / Office / Pickup" }), _jsx(Input, { label: "Full Name", value: form.fullName, onChange: (e) => set("fullName", e.target.value), required: true, placeholder: "Recipient name (PII)" })] }), _jsx(Input, { label: "Phone", value: form.phone, onChange: (e) => set("phone", e.target.value), required: true, type: "tel", placeholder: "+91 9876543210 (PII)" }), _jsx(Input, { label: "Address Line 1", value: form.addressLine1, onChange: (e) => set("addressLine1", e.target.value), required: true, placeholder: "House/flat no., street (PII)" }), _jsxs(Div, { className: "grid gap-4 sm:grid-cols-2", children: [_jsx(Input, { label: "Address Line 2", value: form.addressLine2 ?? "", onChange: (e) => set("addressLine2", e.target.value), placeholder: "Area, locality (optional)" }), _jsx(Input, { label: "Landmark", value: form.landmark ?? "", onChange: (e) => set("landmark", e.target.value), placeholder: "Near hospital, etc. (optional)" })] }), _jsxs(Div, { className: "grid gap-4 sm:grid-cols-3", children: [_jsx(Input, { label: "City", value: form.city, onChange: (e) => set("city", e.target.value), required: true, placeholder: "Mumbai" }), _jsx(Select, { label: "State", value: form.state, onValueChange: (val) => set("state", val), options: STATE_OPTIONS, placeholder: "Select state", required: true }), _jsx(Input, { label: "Postal Code", value: form.postalCode, onChange: (e) => set("postalCode", e.target.value), required: true, placeholder: "400001", maxLength: 6 })] }), _jsx(Input, { label: "Country", value: form.country, onChange: (e) => set("country", e.target.value), placeholder: "India" })] })] }), _jsxs(Card, { variant: "outlined", padding: "lg", children: [_jsx(SectionHeading, { children: "Flags" }), _jsx(Toggle, { label: "Set as default address", checked: form.isDefault, onChange: (v) => set("isDefault", v) })] }), _jsxs(Div, { className: "flex gap-3 lg:hidden", children: [_jsx(Button, { type: "submit", isLoading: isSubmitting, disabled: !canSave || isSubmitting, children: isEdit ? ACTIONS.ADMIN["save-changes"].label : "Create address" }), isEdit && (_jsx(Button, { type: "button", variant: "danger", isLoading: deleteMutation.isPending, onClick: () => setDeleteOpen(true), children: "Delete address" }))] })] }, "address-form"));
|
|
115
|
+
const twoPanel = (_jsxs(Div, { className: "grid gap-6 lg:grid-cols-[1fr_280px] lg:items-start", children: [_jsx(CardBody, { className: "min-w-0 space-y-6 p-0", children: formContent }), _jsx(Div, { className: "hidden lg:block lg:sticky lg:top-[var(--header-height,0px)]", children: actionSidebar })] }));
|
|
116
116
|
return (_jsxs(_Fragment, { children: [_jsx(StackedViewShell, { portal: "admin", ...rest, title: isEdit ? "Edit Address" : "New Address", sections: [twoPanel] }), _jsx(ConfirmDeleteModal, { isOpen: deleteOpen, onClose: () => setDeleteOpen(false), onConfirm: () => deleteMutation.mutate(), isDeleting: deleteMutation.isPending, title: "Delete this address?", message: "This address will be permanently removed. This action cannot be undone.", confirmText: "Delete address", variant: "danger" })] }));
|
|
117
117
|
}
|
|
@@ -2,15 +2,18 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import React from "react";
|
|
4
4
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
5
|
-
import { Alert, Button, Input, Select, StackedViewShell, Text } from "../../../ui";
|
|
5
|
+
import { Alert, Button, Div, Input, Label, Select, StackedViewShell, Text } from "../../../ui";
|
|
6
6
|
import { apiClient } from "../../../http";
|
|
7
7
|
import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
8
8
|
import { DataTable } from "./DataTable";
|
|
9
|
+
const __P = {
|
|
10
|
+
p3: "p-3",
|
|
11
|
+
};
|
|
9
12
|
function AdsSettingsPanel({ adsenseClientId, setAdsenseClientId, thirdPartyScriptUrl, setThirdPartyScriptUrl, consentRequired, setConsentRequired, serverCredentialIssues, localCredentialIssues, credentialStatus, providerCredentialsMasked, settingsMutation, hasPendingCredentialInput, currentConsentRequired, settingsMessage, onSave, }) {
|
|
10
|
-
return (_jsxs(
|
|
13
|
+
return (_jsxs(Div, { className: `rounded-lg border border-neutral-200 dark:border-slate-700 ${__P.p3} space-y-3`, children: [_jsx(Text, { className: "text-sm font-semibold", children: "Provider and publish settings" }), _jsx(Text, { className: "text-xs text-neutral-500 dark:text-zinc-400", children: "Save provider credentials here before publishing AdSense or third-party inventory." }), serverCredentialIssues.length > 0 ? (_jsx(Alert, { variant: "warning", title: "Provider credentials need attention", children: serverCredentialIssues.join("; ") })) : null, _jsxs(Div, { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: [_jsx(Input, { label: "AdSense client id", value: adsenseClientId, onChange: (event) => setAdsenseClientId(event.target.value), placeholder: providerCredentialsMasked?.adsenseClientId || "ca-pub-XXXXXXXXXX" }), _jsx(Input, { label: "Third-party script URL", value: thirdPartyScriptUrl, onChange: (event) => setThirdPartyScriptUrl(event.target.value), placeholder: providerCredentialsMasked?.thirdPartyScriptUrl || "https://..." })] }), _jsxs(Text, { className: "text-xs text-neutral-500 dark:text-zinc-400", children: ["Stored credentials: AdSense ", credentialStatus?.hasAdsenseClientId ? "configured" : "missing", " \u00B7 Third-party ", credentialStatus?.hasThirdPartyScriptUrl ? "configured" : "missing"] }), _jsxs(Div, { className: "flex items-center justify-between gap-3", children: [_jsxs(Label, { className: "flex items-center gap-2 text-sm", children: [_jsx("input", { type: "checkbox", checked: consentRequired, onChange: (event) => setConsentRequired(event.target.checked) }), "Require consent globally for ad rendering"] }), _jsx(Button, { size: "sm", variant: "outline", disabled: settingsMutation.isPending || localCredentialIssues.length > 0 || (!hasPendingCredentialInput && consentRequired === Boolean(currentConsentRequired)), onClick: onSave, children: settingsMutation.isPending ? "Saving..." : "Save settings" })] }), localCredentialIssues.length > 0 ? (_jsx(Alert, { variant: "error", title: "Fix settings before saving", children: localCredentialIssues.join("; ") })) : null, settingsMessage ? (_jsx(Alert, { variant: settingsMessage.toLowerCase().includes("failed") ? "error" : "success", title: "Settings", children: settingsMessage })) : null] }));
|
|
11
14
|
}
|
|
12
15
|
function AdsFilterRow({ q, setQ, status, setStatus, provider, setProvider, placement, setPlacement, placements, onPageReset }) {
|
|
13
|
-
return (_jsxs(
|
|
16
|
+
return (_jsxs(Div, { className: "grid grid-cols-1 md:grid-cols-4 gap-3", children: [_jsx(Input, { label: "Search", value: q, onChange: (event) => { onPageReset(); setQ(event.target.value); }, placeholder: "Search ads" }), _jsx(Select, { label: "Status", value: status, options: [
|
|
14
17
|
{ label: "All", value: "all" },
|
|
15
18
|
{ label: "Draft", value: "draft" },
|
|
16
19
|
{ label: "Active", value: "active" },
|
|
@@ -89,7 +92,7 @@ export function AdminAdsView({ endpoint = ADMIN_ENDPOINTS.ADS, labels = {}, crea
|
|
|
89
92
|
{
|
|
90
93
|
key: "name",
|
|
91
94
|
header: "Ad",
|
|
92
|
-
render: (row) => (_jsxs(
|
|
95
|
+
render: (row) => (_jsxs(Div, { children: [_jsx(Text, { className: "font-medium", children: row.name }), _jsx(Text, { className: "text-xs text-neutral-500 dark:text-zinc-400", children: row.id })] })),
|
|
93
96
|
},
|
|
94
97
|
{
|
|
95
98
|
key: "provider",
|
|
@@ -99,7 +102,7 @@ export function AdminAdsView({ endpoint = ADMIN_ENDPOINTS.ADS, labels = {}, crea
|
|
|
99
102
|
{
|
|
100
103
|
key: "status",
|
|
101
104
|
header: "Status",
|
|
102
|
-
render: (row) => (_jsxs(
|
|
105
|
+
render: (row) => (_jsxs(Div, { children: [_jsx(Text, { className: "text-xs uppercase tracking-wide", children: row.status }), row.publishReady === false ? (_jsx(Text, { className: "text-[11px] text-error", children: "Publish blocked" })) : null] })),
|
|
103
106
|
},
|
|
104
107
|
{
|
|
105
108
|
key: "placementIds",
|
|
@@ -112,7 +115,7 @@ export function AdminAdsView({ endpoint = ADMIN_ENDPOINTS.ADS, labels = {}, crea
|
|
|
112
115
|
render: (row) => {
|
|
113
116
|
const nextStatus = row.status === "active" ? "paused" : "active";
|
|
114
117
|
const cannotPublish = nextStatus === "active" && row.publishReady === false;
|
|
115
|
-
return (_jsxs(
|
|
118
|
+
return (_jsxs(Div, { className: "flex items-center gap-2", children: [renderEditLink ? renderEditLink(row) : (_jsx("a", { className: "inline-flex h-8 items-center rounded-md border border-neutral-200 px-3 text-xs dark:border-slate-700", href: `/admin/ads/${row.id}/edit`, children: "Edit" })), _jsx(Button, { size: "sm", variant: "outline", disabled: statusMutation.isPending || cannotPublish, onClick: () => statusMutation.mutate({ id: row.id, nextStatus }), children: row.status === "active" ? "Pause" : "Publish" })] }));
|
|
116
119
|
},
|
|
117
120
|
},
|
|
118
121
|
], [renderEditLink, statusMutation]);
|
|
@@ -150,7 +153,7 @@ export function AdminAdsView({ endpoint = ADMIN_ENDPOINTS.ADS, labels = {}, crea
|
|
|
150
153
|
settingsMutation.mutate(payload);
|
|
151
154
|
};
|
|
152
155
|
return (_jsx(StackedViewShell, { portal: "admin", ...rest, title: labels.title ?? "Ad Inventory", sections: [
|
|
153
|
-
_jsxs(
|
|
156
|
+
_jsxs(Div, { className: "flex items-center justify-between gap-3", children: [_jsx(Text, { variant: "secondary", children: "Manage ad inventory, placement mapping, and publishing state." }), _jsx("a", { href: createHref, className: "inline-flex h-9 items-center rounded-md bg-neutral-900 px-3 text-sm font-medium text-white dark:bg-zinc-100 dark:text-zinc-900", children: "New ad" })] }),
|
|
154
157
|
adsQuery.error ? (_jsx(Alert, { variant: "error", title: "Could not load ads", children: adsQuery.error instanceof Error ? adsQuery.error.message : "Unknown error" })) : null,
|
|
155
158
|
_jsx(AdsSettingsPanel, { adsenseClientId: adsenseClientId, setAdsenseClientId: setAdsenseClientId, thirdPartyScriptUrl: thirdPartyScriptUrl, setThirdPartyScriptUrl: setThirdPartyScriptUrl, consentRequired: consentRequired, setConsentRequired: setConsentRequired, serverCredentialIssues: serverCredentialIssues, localCredentialIssues: localCredentialIssues, credentialStatus: credentialStatus, providerCredentialsMasked: adsQuery.data?.providerCredentialsMasked, settingsMutation: settingsMutation, hasPendingCredentialInput: hasPendingCredentialInput, currentConsentRequired: Boolean(adsQuery.data?.consentRequired), settingsMessage: settingsMessage, onSave: saveSettings }),
|
|
156
159
|
_jsx(AdsFilterRow, { q: q, setQ: setQ, status: status, setStatus: setStatus, provider: provider, setProvider: setProvider, placement: placement, setPlacement: setPlacement, placements: placements, onPageReset: () => setPage(1) }),
|
|
@@ -2,11 +2,17 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import React from "react";
|
|
4
4
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
|
5
|
-
import { Button, ConfirmDeleteModal, Div, Heading, Input, RichTextEditor, RichTextRenderer, Select, StackedViewShell, TagInput, Text, Toggle, useToast, } from "../../../ui";
|
|
5
|
+
import { Button, ConfirmDeleteModal, Div, Heading, Input, RichTextEditor, RichTextRenderer, Select, Span, StackedViewShell, TagInput, Text, Toggle, useToast, } from "../../../ui";
|
|
6
6
|
import { ImageUpload, useMediaUpload } from "../../media";
|
|
7
7
|
import { apiClient } from "../../../http";
|
|
8
8
|
import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
9
9
|
import { StepForm } from "../../shell";
|
|
10
|
+
const __P = {
|
|
11
|
+
p4: "p-4",
|
|
12
|
+
};
|
|
13
|
+
const __O = {
|
|
14
|
+
yAuto: "overflow-y-auto",
|
|
15
|
+
};
|
|
10
16
|
// --- Helpers -----------------------------------------------------------------
|
|
11
17
|
const STATUS_OPTIONS = [
|
|
12
18
|
{ label: "Draft", value: "draft" },
|
|
@@ -155,17 +161,17 @@ export function AdminBlogEditorView({ postId, onSaved, onDeleted, embedded, ...r
|
|
|
155
161
|
{
|
|
156
162
|
label: "Content",
|
|
157
163
|
validate: (values) => !values.title.trim() ? "Title is required" : null,
|
|
158
|
-
render: ({ values, onChange }) => (_jsxs(
|
|
164
|
+
render: ({ values, onChange }) => (_jsxs(Div, { className: "space-y-5", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Content" }), _jsx(Input, { label: "Title", value: values.title, onChange: (e) => {
|
|
159
165
|
const v = e.target.value;
|
|
160
166
|
onChange({ title: v, ...(!slugManual && { slug: toSlug(v) }) });
|
|
161
167
|
}, placeholder: "e.g. How to Grade Pok\u00E9mon Cards" }), _jsx(Input, { label: "Slug", value: values.slug, onChange: (e) => {
|
|
162
168
|
setSlugManual(true);
|
|
163
169
|
onChange({ slug: e.target.value });
|
|
164
|
-
}, placeholder: "blog-how-to-grade-pokemon-cards", helperText: "Auto-generated from title. Must start with 'blog-'." }), _jsx(Input, { label: "Excerpt", value: values.excerpt, onChange: (e) => onChange({ excerpt: e.target.value }), placeholder: "Short summary shown in listings and cards" }), _jsxs(
|
|
170
|
+
}, placeholder: "blog-how-to-grade-pokemon-cards", helperText: "Auto-generated from title. Must start with 'blog-'." }), _jsx(Input, { label: "Excerpt", value: values.excerpt, onChange: (e) => onChange({ excerpt: e.target.value }), placeholder: "Short summary shown in listings and cards" }), _jsxs(Div, { className: "space-y-1", children: [_jsx(Text, { className: "text-sm font-medium text-zinc-700 dark:text-zinc-300", children: "Content" }), _jsx(RichTextEditor, { value: values.content, onChange: (v) => onChange({ content: v }), placeholder: "Write your article here...", minHeightClassName: "min-h-[320px]" })] })] })),
|
|
165
171
|
},
|
|
166
172
|
{
|
|
167
173
|
label: "Media",
|
|
168
|
-
render: ({ values, onChange }) => (_jsxs(
|
|
174
|
+
render: ({ values, onChange }) => (_jsxs(Div, { className: "space-y-5", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Media" }), _jsx(ImageUpload, { label: "Cover Image", currentImage: values.coverImage, onUpload: (file) => upload(file, "blog", true, {
|
|
169
175
|
type: "blog-cover",
|
|
170
176
|
title: values.title || values.slug,
|
|
171
177
|
category: values.category,
|
|
@@ -175,12 +181,12 @@ export function AdminBlogEditorView({ postId, onSaved, onDeleted, embedded, ...r
|
|
|
175
181
|
label: "SEO & Tags",
|
|
176
182
|
render: ({ values, onChange }) => {
|
|
177
183
|
const readTime = Math.max(1, Math.round(values.content.replace(/<[^>]*>/g, "").split(/\s+/).filter(Boolean).length / 200));
|
|
178
|
-
return (_jsxs(
|
|
184
|
+
return (_jsxs(Div, { className: "space-y-5", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "SEO & Tags" }), _jsxs(Div, { className: "grid grid-cols-2 gap-4", children: [_jsx(Select, { label: "Category", options: CATEGORY_OPTIONS, value: values.category, onValueChange: (v) => onChange({ category: v }) }), _jsxs(Div, { children: [_jsx(Text, { className: "text-sm font-medium mb-1.5", children: "Estimated Read Time" }), _jsxs(Text, { className: "text-sm text-[var(--appkit-color-text-muted)]", children: ["~", readTime, " min (auto-calculated from content)"] })] })] }), _jsx(TagInput, { label: "Tags", value: values.tags, onChange: (t) => onChange({ tags: t }), placeholder: "e.g. pokemon, grading, tcg" }), _jsx(Input, { label: "Meta Title (optional)", value: values.metaTitle, onChange: (e) => onChange({ metaTitle: e.target.value }), placeholder: "Defaults to post title" }), _jsx(Input, { label: "Meta Description (optional)", value: values.metaDescription, onChange: (e) => onChange({ metaDescription: e.target.value }), placeholder: "SEO description \u2014 max 160 chars", maxLength: 160 })] }));
|
|
179
185
|
},
|
|
180
186
|
},
|
|
181
187
|
{
|
|
182
188
|
label: "Publish",
|
|
183
|
-
render: ({ values, onChange }) => (_jsxs(
|
|
189
|
+
render: ({ values, onChange }) => (_jsxs(Div, { className: "space-y-5", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Publish Settings" }), _jsxs(Div, { className: "grid grid-cols-2 gap-4", children: [_jsx(Select, { label: "Status", options: STATUS_OPTIONS, value: values.status, onValueChange: (v) => onChange({ status: v }) }), _jsx(Input, { label: "Publish date (optional)", value: values.publishedAt, onChange: (e) => onChange({ publishedAt: e.target.value }), type: "date", helperText: "Auto-set to now when publishing." })] }), _jsx(Input, { label: "Author Name", value: values.authorName, onChange: (e) => onChange({ authorName: e.target.value }), placeholder: "Author display name" }), _jsx(Toggle, { label: "Featured post", checked: values.isFeatured, onChange: (checked) => onChange({ isFeatured: checked }) }), isEdit && (_jsx(Div, { className: "pt-4 border-t border-[var(--appkit-color-border)]", children: _jsx(Button, { type: "button", variant: "danger", size: "sm", onClick: () => setShowDeleteConfirm(true), isLoading: deleteMutation.isPending, children: "Delete post" }) }))] })),
|
|
184
190
|
},
|
|
185
191
|
];
|
|
186
192
|
const deleteModal = (_jsx(ConfirmDeleteModal, { isOpen: showDeleteConfirm, onConfirm: () => {
|
|
@@ -189,10 +195,10 @@ export function AdminBlogEditorView({ postId, onSaved, onDeleted, embedded, ...r
|
|
|
189
195
|
}, onClose: () => setShowDeleteConfirm(false), title: "Delete post", message: "This will permanently delete the blog post. This cannot be undone." }));
|
|
190
196
|
const formContent = (_jsxs(_Fragment, { children: [_jsx(StepForm, { steps: steps, values: draft, onChange: update, onComplete: () => { saveMutation.mutate(); }, formId: "admin-blog", currentStep: currentStep, onStepChange: setCurrentStep, completeLabel: isEdit ? "Save Changes" : "Create Post", isLoading: isLoading }), deleteModal] }));
|
|
191
197
|
if (embedded) {
|
|
192
|
-
return _jsx(
|
|
198
|
+
return _jsx(Div, { className: `${__O.yAuto} ${__P.p4}`, children: formContent });
|
|
193
199
|
}
|
|
194
|
-
const previewSection = (_jsxs("div", { className: "rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-raised)] p-5 max-h-[calc(100vh-12rem)] overflow-y-auto", children: [_jsx(
|
|
200
|
+
const previewSection = (_jsxs("div", { className: "rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-raised)] p-5 max-h-[calc(100vh-12rem)] overflow-y-auto", children: [_jsx(Div, { className: "flex items-center gap-2 mb-3 text-xs font-semibold uppercase tracking-wide text-[var(--appkit-color-text-muted)]", children: _jsx("span", { children: "Live preview" }) }), draft.coverImage ? (_jsx("img", { src: draft.coverImage, alt: "", className: "w-full rounded-md mb-4 object-cover max-h-64" })) : null, _jsx(Heading, { level: 1, className: "text-2xl font-bold mb-1", children: draft.title || "Untitled post" }), _jsxs(Text, { className: "text-xs text-[var(--appkit-color-text-muted)] mb-4", children: [draft.authorName || "Anonymous", draft.category ? ` · ${draft.category}` : ""] }), draft.excerpt ? (_jsx(Text, { className: "italic text-[var(--appkit-color-text-secondary)] mb-4", children: draft.excerpt })) : null, _jsx(RichTextRenderer, { html: draft.content || "<em>No content yet…</em>" }), draft.tags.length > 0 ? (_jsx(Div, { className: "mt-6 flex flex-wrap gap-1.5", children: draft.tags.map((t) => (_jsxs(Span, { size: "xs", className: "px-2 py-0.5 rounded-full bg-[var(--appkit-color-surface)] border border-[var(--appkit-color-border)]", children: ["#", t] }, t))) })) : null] }, "preview"));
|
|
195
201
|
return (_jsx(StackedViewShell, { portal: "admin", ...rest, title: isEdit ? "Edit Post" : "New Blog Post", sections: [
|
|
196
|
-
_jsxs(
|
|
202
|
+
_jsxs(Div, { className: "lg:grid lg:grid-cols-[3fr_2fr] lg:gap-6", children: [_jsx(Div, { children: formContent }), _jsx(Div, { className: "mt-6 lg:mt-0 lg:sticky lg:top-4 lg:self-start", children: previewSection })] }, "split"),
|
|
197
203
|
] }));
|
|
198
204
|
}
|
|
@@ -2,12 +2,18 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import React from "react";
|
|
4
4
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
|
5
|
-
import { Button, ConfirmDeleteModal, Form, Input, StackedViewShell, Toggle, useToast, } from "../../../ui";
|
|
5
|
+
import { Button, ConfirmDeleteModal, Div, Form, Input, StackedViewShell, Toggle, useToast, } from "../../../ui";
|
|
6
6
|
import { FieldInput, FormShellContext, useFormShellState } from "../../../ui/forms";
|
|
7
7
|
import { ImageUpload } from "../../media/upload/ImageUpload";
|
|
8
8
|
import { useMediaUpload } from "../../media";
|
|
9
9
|
import { apiClient } from "../../../http";
|
|
10
10
|
import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
11
|
+
const __P = {
|
|
12
|
+
p4: "p-4",
|
|
13
|
+
};
|
|
14
|
+
const __O = {
|
|
15
|
+
yAuto: "overflow-y-auto",
|
|
16
|
+
};
|
|
11
17
|
function toBrandSlug(str) {
|
|
12
18
|
const base = str.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
13
19
|
return base.startsWith("brand-") ? base : `brand-${base}`;
|
|
@@ -99,12 +105,12 @@ export function AdminBrandEditorView({ brandId, onSaved, onDeleted, embedded, ..
|
|
|
99
105
|
return;
|
|
100
106
|
}
|
|
101
107
|
saveMutation.mutate();
|
|
102
|
-
}, className: "space-y-4", children: [_jsxs(
|
|
108
|
+
}, className: "space-y-4", children: [_jsxs(Div, { className: "grid sm:grid-cols-2 gap-4", children: [_jsx(FieldInput, { name: "name", label: "Brand name", value: name, onChange: (v) => handleNameChange(v), required: true, placeholder: "e.g. Hot Wheels" }), _jsx(Input, { label: "Slug", value: slug, onChange: (e) => {
|
|
103
109
|
setSlug(e.target.value);
|
|
104
110
|
setSlugManual(true);
|
|
105
|
-
}, placeholder: "brand-hot-wheels", helperText: "Auto-generated from name. Must start with 'brand-'." })] }), _jsx(Input, { label: "Description", value: description, onChange: (e) => setDescription(e.target.value), placeholder: "Brief description of the brand" }), _jsxs(
|
|
111
|
+
}, placeholder: "brand-hot-wheels", helperText: "Auto-generated from name. Must start with 'brand-'." })] }), _jsx(Input, { label: "Description", value: description, onChange: (e) => setDescription(e.target.value), placeholder: "Brief description of the brand" }), _jsxs(Div, { className: "grid sm:grid-cols-2 gap-4", children: [_jsx(ImageUpload, { label: "Logo", currentImage: logoURL, onUpload: (file) => upload(file, "brands", true, { type: "brand-logo", brand: name || slug }), onChange: setLogoURL }), _jsx(ImageUpload, { label: "Banner", currentImage: bannerURL, onUpload: (file) => upload(file, "brands", true, { type: "brand-banner", brand: name || slug }), onChange: setBannerURL })] }), _jsxs(Div, { className: "grid sm:grid-cols-2 gap-4", children: [_jsx(Input, { label: "Website", value: website, onChange: (e) => setWebsite(e.target.value), placeholder: "https://brand.com", type: "url" }), _jsx(Input, { label: "Display order", value: displayOrder, onChange: (e) => setDisplayOrder(e.target.value), type: "number", min: 0, placeholder: "0" })] }), _jsx(Toggle, { label: "Active", checked: isActive, onChange: setIsActive }), _jsxs(Div, { className: "flex gap-3 pt-2", children: [_jsx(Button, { type: "submit", isLoading: isSubmitting, disabled: !name || isSubmitting, children: isEdit ? "Save changes" : "Create brand" }), isEdit && (_jsx(Button, { type: "button", variant: "danger", onClick: () => setDeleteConfirmOpen(true), children: "Delete brand" }))] })] }, "brand-form"), deleteConfirmOpen && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete Brand", message: "Delete this brand? This cannot be undone.", onConfirm: () => { deleteMutation.mutate(); setDeleteConfirmOpen(false); }, onClose: () => setDeleteConfirmOpen(false), isDeleting: deleteMutation.isPending }))] }));
|
|
106
112
|
if (embedded) {
|
|
107
|
-
return _jsx(
|
|
113
|
+
return _jsx(Div, { className: `${__O.yAuto} ${__P.p4}`, children: formSection });
|
|
108
114
|
}
|
|
109
115
|
return (_jsx(StackedViewShell, { portal: "admin", ...rest, title: isEdit ? "Edit Brand" : "Create Brand", sections: [formSection] }));
|
|
110
116
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import React from "react";
|
|
4
|
-
import { ListingLayout, Text } from "../../../ui";
|
|
4
|
+
import { Div, ListingLayout, Text } from "../../../ui";
|
|
5
5
|
import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
6
6
|
import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
|
|
7
7
|
import { toRecordArray, toRelativeDate, toStringValue, } from "../hooks/useAdminListingData";
|
|
@@ -13,13 +13,13 @@ const COLUMNS = [
|
|
|
13
13
|
key: "primary",
|
|
14
14
|
header: "Brand",
|
|
15
15
|
sortable: true,
|
|
16
|
-
render: (row) => (_jsxs(
|
|
16
|
+
render: (row) => (_jsxs(Div, { className: "space-y-1", children: [_jsx(Text, { className: "font-semibold text-zinc-900 dark:text-zinc-100", children: row.primary }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: row.secondary })] })),
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
19
|
key: "status",
|
|
20
20
|
header: "Status",
|
|
21
21
|
className: "w-32",
|
|
22
|
-
render: (row) => (_jsx(Span, { className: "inline-flex rounded-full bg-primary-50 px-2.5 py-1 text-
|
|
22
|
+
render: (row) => (_jsx(Span, { size: "xs", weight: "medium", className: "inline-flex rounded-full bg-primary-50 px-2.5 py-1 text-primary-800 dark:bg-secondary-900/30 dark:text-secondary-300", children: row.status })),
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
key: "updatedAt",
|
|
@@ -74,7 +74,7 @@ const ADMIN_BRANDS_CONFIG = {
|
|
|
74
74
|
},
|
|
75
75
|
},
|
|
76
76
|
],
|
|
77
|
-
renderFilterPanel: ({ pendingFilters, setPendingFilters }) => (_jsxs(
|
|
77
|
+
renderFilterPanel: ({ pendingFilters, setPendingFilters }) => (_jsxs(Div, { className: "space-y-2", children: [_jsx(Text, { className: "text-xs font-semibold uppercase tracking-widest text-zinc-500 dark:text-zinc-400", children: "Status" }), _jsx(Div, { className: "flex flex-wrap gap-2", children: [
|
|
78
78
|
{ label: "All", value: "" },
|
|
79
79
|
{ label: "Active", value: "true" },
|
|
80
80
|
{ label: "Inactive", value: "false" },
|
|
@@ -12,12 +12,13 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
12
12
|
* in the picker but the rule itself stays unchanged until they switch to
|
|
13
13
|
* static).
|
|
14
14
|
*/
|
|
15
|
-
import { useCallback, useEffect,
|
|
15
|
+
import { useCallback, useEffect, useState } from "react";
|
|
16
16
|
import { Button, Checkbox, ConfirmDeleteModal, Container, Heading, Input, Row, Section, Select, Stack, Text, Textarea, useToast, } from "../../../ui";
|
|
17
17
|
import { FieldInput, FormShellContext, useFormShellState } from "../../../ui/forms";
|
|
18
|
-
import { BundleItemsPicker, defaultBundleItemsFetch, } from "../../categories/components/BundleItemsPicker";
|
|
19
18
|
import { BundleDynamicRuleEditor } from "../../categories/components/BundleDynamicRuleEditor";
|
|
19
|
+
import { ProductInlineSelect } from "../../seller/components/ProductInlineSelect";
|
|
20
20
|
import { BUNDLE_COPY } from "../../../_internal/shared/features/categories/bundle-copy";
|
|
21
|
+
import { BUNDLE_MIN_ITEMS, BUNDLE_MAX_ITEMS, } from "../../../_internal/shared/features/categories/bundle-config";
|
|
21
22
|
const DEFAULT_DYNAMIC_RULE = {
|
|
22
23
|
type: "dynamic",
|
|
23
24
|
filter: {},
|
|
@@ -79,7 +80,6 @@ export function AdminBundleEditorView({ bundleId, onSaved, onDeleted, }) {
|
|
|
79
80
|
const [deleting, setDeleting] = useState(false);
|
|
80
81
|
const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false);
|
|
81
82
|
const [apiError, setApiError] = useState(null);
|
|
82
|
-
const [metadata, setMetadata] = useState({});
|
|
83
83
|
const { shellCtx, setFieldError, clearErrors } = useFormShellState();
|
|
84
84
|
const { showToast } = useToast();
|
|
85
85
|
// Load existing bundle on mount when editing
|
|
@@ -211,11 +211,10 @@ export function AdminBundleEditorView({ bundleId, onSaved, onDeleted, }) {
|
|
|
211
211
|
setDeleting(false);
|
|
212
212
|
}
|
|
213
213
|
}, [bundleId, onDeleted, showToast]);
|
|
214
|
-
const fetchProducts = useMemo(() => defaultBundleItemsFetch, []);
|
|
215
214
|
if (loading) {
|
|
216
215
|
return (_jsx(Section, { className: "py-10", children: _jsx(Container, { size: "lg", children: _jsx(Text, { children: BUNDLE_COPY.adminEditor.loading }) }) }));
|
|
217
216
|
}
|
|
218
217
|
return (_jsx(FormShellContext.Provider, { value: shellCtx, children: _jsx(Section, { className: "py-10", children: _jsx(Container, { size: "lg", children: _jsxs(Stack, { gap: "lg", children: [_jsxs(Row, { gap: "sm", align: "center", justify: "between", className: "flex-wrap", children: [_jsx(Heading, { level: 1, className: "text-2xl font-semibold text-zinc-900 dark:text-zinc-100", children: isEdit
|
|
219
218
|
? BUNDLE_COPY.adminEditorTitleEdit
|
|
220
|
-
: BUNDLE_COPY.adminEditorTitleNew }), isEdit && (_jsx(Button, { variant: "danger", onClick: () => setDeleteConfirmOpen(true), disabled: deleting, children: BUNDLE_COPY.adminEditor.deleteButton(deleting) }))] }), _jsx(ConfirmDeleteModal, { isOpen: deleteConfirmOpen, onClose: () => setDeleteConfirmOpen(false), onConfirm: handleDelete, title: "Delete this bundle?", message: BUNDLE_COPY.adminEditor.deleteConfirm, isDeleting: deleting }), apiError && (_jsx(Text, { color: "danger", role: "alert", children: apiError })), _jsxs(Stack, { gap: "md", children: [_jsx(FieldInput, { name: "name", label: BUNDLE_COPY.adminEditor.fields.nameLabel, value: form.name, onChange: (v) => setForm((f) => ({ ...f, name: v })), placeholder: BUNDLE_COPY.adminEditor.fields.namePlaceholder, disabled: saving, required: true }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "sm", weight: "semibold", children: BUNDLE_COPY.adminEditor.fields.descriptionLabel }), _jsx(Textarea, { value: form.description, onChange: (e) => setForm((f) => ({ ...f, description: e.target.value })), placeholder: BUNDLE_COPY.adminEditor.fields.descriptionPlaceholder, rows: 4, disabled: saving })] }), _jsxs(Stack, { gap: "xs", children: [_jsx(FieldInput, { name: "price", label: BUNDLE_COPY.adminEditor.fields.priceLabel, type: "number", inputMode: "decimal", min: 1, step: 1, value: form.priceRupees, onChange: (v) => setForm((f) => ({ ...f, priceRupees: v })), placeholder: BUNDLE_COPY.adminEditor.fields.pricePlaceholder, disabled: saving, required: true }), _jsx(Text, { size: "xs", color: "muted", children: BUNDLE_COPY.adminEditor.fields.pricePaiseHint(parsePriceRupees(form.priceRupees)) })] }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "sm", weight: "semibold", children: BUNDLE_COPY.adminEditor.fields.coverImageLabel }), _jsx(Input, { type: "url", value: form.coverImage, onChange: (e) => setForm((f) => ({ ...f, coverImage: e.target.value })), placeholder: "https://\u2026", disabled: saving })] }), _jsx(Checkbox, { checked: form.isActive, onChange: (e) => setForm((f) => ({ ...f, isActive: e.target.checked })), disabled: saving, label: BUNDLE_COPY.adminEditor.fields.activeLabel }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "sm", weight: "semibold", children: BUNDLE_COPY.adminEditor.ruleTypeLabel }), _jsx(Select, { options: RULE_TYPE_OPTIONS, value: form.ruleType, onValueChange: (next) => setForm((f) => ({ ...f, ruleType: next })), disabled: saving, "aria-label": BUNDLE_COPY.adminEditor.ruleTypeLabel })] }), form.ruleType === "static" ? (_jsx(
|
|
219
|
+
: BUNDLE_COPY.adminEditorTitleNew }), isEdit && (_jsx(Button, { variant: "danger", onClick: () => setDeleteConfirmOpen(true), disabled: deleting, children: BUNDLE_COPY.adminEditor.deleteButton(deleting) }))] }), _jsx(ConfirmDeleteModal, { isOpen: deleteConfirmOpen, onClose: () => setDeleteConfirmOpen(false), onConfirm: handleDelete, title: "Delete this bundle?", message: BUNDLE_COPY.adminEditor.deleteConfirm, isDeleting: deleting }), apiError && (_jsx(Text, { color: "danger", role: "alert", children: apiError })), _jsxs(Stack, { gap: "md", children: [_jsx(FieldInput, { name: "name", label: BUNDLE_COPY.adminEditor.fields.nameLabel, value: form.name, onChange: (v) => setForm((f) => ({ ...f, name: v })), placeholder: BUNDLE_COPY.adminEditor.fields.namePlaceholder, disabled: saving, required: true }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "sm", weight: "semibold", children: BUNDLE_COPY.adminEditor.fields.descriptionLabel }), _jsx(Textarea, { value: form.description, onChange: (e) => setForm((f) => ({ ...f, description: e.target.value })), placeholder: BUNDLE_COPY.adminEditor.fields.descriptionPlaceholder, rows: 4, disabled: saving })] }), _jsxs(Stack, { gap: "xs", children: [_jsx(FieldInput, { name: "price", label: BUNDLE_COPY.adminEditor.fields.priceLabel, type: "number", inputMode: "decimal", min: 1, step: 1, value: form.priceRupees, onChange: (v) => setForm((f) => ({ ...f, priceRupees: v })), placeholder: BUNDLE_COPY.adminEditor.fields.pricePlaceholder, disabled: saving, required: true }), _jsx(Text, { size: "xs", color: "muted", children: BUNDLE_COPY.adminEditor.fields.pricePaiseHint(parsePriceRupees(form.priceRupees)) })] }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "sm", weight: "semibold", children: BUNDLE_COPY.adminEditor.fields.coverImageLabel }), _jsx(Input, { type: "url", value: form.coverImage, onChange: (e) => setForm((f) => ({ ...f, coverImage: e.target.value })), placeholder: "https://\u2026", disabled: saving })] }), _jsx(Checkbox, { checked: form.isActive, onChange: (e) => setForm((f) => ({ ...f, isActive: e.target.checked })), disabled: saving, label: BUNDLE_COPY.adminEditor.fields.activeLabel }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "sm", weight: "semibold", children: BUNDLE_COPY.adminEditor.ruleTypeLabel }), _jsx(Select, { options: RULE_TYPE_OPTIONS, value: form.ruleType, onValueChange: (next) => setForm((f) => ({ ...f, ruleType: next })), disabled: saving, "aria-label": BUNDLE_COPY.adminEditor.ruleTypeLabel })] }), form.ruleType === "static" ? (_jsxs(Stack, { gap: "xs", children: [_jsxs(Text, { size: "sm", weight: "semibold", children: [BUNDLE_COPY.adminEditor.ruleTypeStatic, " products (", BUNDLE_MIN_ITEMS, "\u2013", BUNDLE_MAX_ITEMS, ")"] }), _jsx(ProductInlineSelect, { scope: "admin", multiple: true, value: form.productIds, onChange: (ids) => setForm((f) => ({ ...f, productIds: ids })), disabled: saving, placeholder: "Search and select products\u2026" }), form.productIds.length > 0 && form.productIds.length < BUNDLE_MIN_ITEMS && (_jsxs(Text, { size: "xs", color: "danger", children: ["Select at least ", BUNDLE_MIN_ITEMS, " products (currently ", form.productIds.length, ")."] })), form.productIds.length > BUNDLE_MAX_ITEMS && (_jsxs(Text, { size: "xs", color: "danger", children: ["Maximum ", BUNDLE_MAX_ITEMS, " products allowed (currently ", form.productIds.length, ")."] }))] })) : (_jsx(BundleDynamicRuleEditor, { value: form.dynamicRule, onChange: (next) => setForm((f) => ({ ...f, dynamicRule: next })), disabled: saving }))] }), _jsx(Row, { gap: "sm", align: "center", justify: "end", children: _jsx(Button, { variant: "primary", onClick: handleSave, disabled: saving, "aria-busy": saving, children: BUNDLE_COPY.adminEditor.saveButton(saving, isEdit) }) })] }) }) }) }));
|
|
221
220
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useCallback } from "react";
|
|
4
|
-
import { Badge, Button, Stack, Text, useToast } from "../../../ui";
|
|
4
|
+
import { Badge, Button, Div, Stack, Text, useToast } from "../../../ui";
|
|
5
5
|
import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
6
6
|
import { toRecordArray, toRelativeDate, toStringValue, } from "../hooks/useAdminListingData";
|
|
7
7
|
import { DataListingView } from "./DataListingView";
|
|
@@ -120,13 +120,13 @@ export function AdminBundlesView({ getEditHref, newHref }) {
|
|
|
120
120
|
}),
|
|
121
121
|
],
|
|
122
122
|
renderRowActions: (row) => (_jsx(Button, { variant: "ghost", size: "sm", isLoading: rebuildingId === row.id, disabled: rebuildingId === row.id, onClick: () => void handleRebuild(row.id), children: ACTIONS.ADMIN["rebuild-bundle"].label })),
|
|
123
|
-
renderFilterPanel: ({ pendingFilters, setPendingFilters }) => (_jsxs(_Fragment, { children: [_jsxs(
|
|
123
|
+
renderFilterPanel: ({ pendingFilters, setPendingFilters }) => (_jsxs(_Fragment, { children: [_jsxs(Div, { className: "space-y-2", children: [_jsx(Text, { className: "text-xs font-semibold uppercase tracking-widest text-zinc-500 dark:text-zinc-400", children: "Status" }), _jsx(Div, { className: "flex flex-wrap gap-2", children: [
|
|
124
124
|
{ label: "All", value: "" },
|
|
125
125
|
{ label: "Active", value: "true" },
|
|
126
126
|
{ label: "Inactive", value: "false" },
|
|
127
127
|
].map((opt) => (_jsx("button", { type: "button", onClick: () => setPendingFilters((p) => ({ ...p, isActive: opt.value })), className: `rounded-full px-3 py-1 text-xs font-medium border transition-colors ${(pendingFilters.isActive || "") === opt.value
|
|
128
128
|
? "bg-primary text-white border-primary"
|
|
129
|
-
: "border-zinc-300 dark:border-slate-600 text-zinc-700 dark:text-zinc-300 hover:bg-zinc-50 dark:hover:bg-slate-800"}`, children: opt.label }, opt.label))) })] }), _jsxs(
|
|
129
|
+
: "border-zinc-300 dark:border-slate-600 text-zinc-700 dark:text-zinc-300 hover:bg-zinc-50 dark:hover:bg-slate-800"}`, children: opt.label }, opt.label))) })] }), _jsxs(Div, { className: "space-y-2", children: [_jsx(Text, { className: "text-xs font-semibold uppercase tracking-widest text-zinc-500 dark:text-zinc-400", children: "Stock" }), _jsx(Div, { className: "flex flex-wrap gap-2", children: [
|
|
130
130
|
{ label: "All", value: "" },
|
|
131
131
|
{ label: "Sold out", value: "out_of_stock" },
|
|
132
132
|
].map((opt) => (_jsx("button", { type: "button", onClick: () => setPendingFilters((p) => ({ ...p, bundleStockStatus: opt.value })), className: `rounded-full px-3 py-1 text-xs font-medium border transition-colors ${(pendingFilters.bundleStockStatus || "") === opt.value
|