@mohasinac/appkit 2.8.2 → 2.8.4
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 +3 -1
- package/dist/client.js +3 -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/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/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/AdminAllEventEntriesView.js +5 -3
- package/dist/features/admin/components/AdminBidsView.js +6 -4
- package/dist/features/admin/components/AdminBlogEditorView.js +15 -9
- package/dist/features/admin/components/AdminBlogView.js +6 -4
- package/dist/features/admin/components/AdminBrandEditorView.js +10 -4
- package/dist/features/admin/components/AdminBrandsView.js +12 -10
- package/dist/features/admin/components/AdminBundleEditorView.js +4 -5
- package/dist/features/admin/components/AdminBundlesView.js +13 -11
- package/dist/features/admin/components/AdminCarouselEditorView.js +6 -3
- package/dist/features/admin/components/AdminCarouselView.js +6 -6
- package/dist/features/admin/components/AdminCartsView.js +6 -4
- package/dist/features/admin/components/AdminCatalogGuideView.js +2 -1
- package/dist/features/admin/components/AdminCategoriesView.js +12 -10
- package/dist/features/admin/components/AdminCategoryEditorView.js +11 -5
- package/dist/features/admin/components/AdminClassifiedView.js +4 -3
- package/dist/features/admin/components/AdminContactEditorView.js +8 -1
- package/dist/features/admin/components/AdminContactView.js +6 -4
- package/dist/features/admin/components/AdminCouponEditorView.js +23 -5
- package/dist/features/admin/components/AdminCouponsView.js +6 -4
- package/dist/features/admin/components/AdminDigitalCodesView.js +4 -3
- 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 +9 -7
- package/dist/features/admin/components/AdminFeatureEditorView.js +7 -1
- package/dist/features/admin/components/AdminFeatureFlagsView.js +4 -1
- package/dist/features/admin/components/AdminFeaturesView.js +5 -4
- package/dist/features/admin/components/AdminFilterBar.js +4 -4
- package/dist/features/admin/components/AdminGroupedListingsView.js +66 -30
- package/dist/features/admin/components/AdminGuideHubView.js +4 -1
- package/dist/features/admin/components/AdminHistoryView.js +4 -3
- package/dist/features/admin/components/AdminLiveView.js +4 -3
- package/dist/features/admin/components/AdminMediaView.js +4 -1
- package/dist/features/admin/components/AdminNavigationView.js +7 -4
- package/dist/features/admin/components/AdminNewsletterView.js +5 -3
- package/dist/features/admin/components/AdminNotificationsView.js +8 -6
- package/dist/features/admin/components/AdminOrderEditorView.js +2 -2
- package/dist/features/admin/components/AdminOrdersView.js +6 -4
- package/dist/features/admin/components/AdminPageHeader.js +5 -2
- package/dist/features/admin/components/AdminPayoutsView.js +7 -5
- package/dist/features/admin/components/AdminPrizeDrawsView.js +11 -9
- package/dist/features/admin/components/AdminProductEditorView.js +12 -5
- package/dist/features/admin/components/AdminProductsView.js +11 -9
- package/dist/features/admin/components/AdminReturnRequestsView.js +4 -3
- package/dist/features/admin/components/AdminReviewsView.js +10 -8
- package/dist/features/admin/components/AdminScammerEditorView.js +6 -2
- package/dist/features/admin/components/AdminScammersView.js +11 -9
- 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 +8 -6
- 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 +4 -3
- package/dist/features/admin/components/AdminStoreEditorView.js +5 -5
- package/dist/features/admin/components/AdminStoresView.js +6 -4
- package/dist/features/admin/components/AdminSublistingCategoriesView.js +6 -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 +11 -9
- package/dist/features/admin/components/AdminTeamView.js +6 -4
- package/dist/features/admin/components/AdminTrustGuideView.js +3 -3
- package/dist/features/admin/components/AdminUsersGuideView.js +3 -3
- package/dist/features/admin/components/AdminUsersView.js +6 -4
- package/dist/features/admin/components/AdminViewCards.js +12 -6
- package/dist/features/admin/components/AdminWishlistsView.js +4 -3
- 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/constants/filter-tabs.d.ts +1 -1
- package/dist/features/admin/constants/filter-tabs.js +0 -11
- package/dist/features/admin/types/index.d.ts +1 -1
- package/dist/features/auctions/actions/bid-actions.js +4 -2
- package/dist/features/auctions/components/AuctionBidsTable.js +4 -1
- package/dist/features/auctions/components/AuctionDetailPageView.js +14 -6
- package/dist/features/auctions/components/AuctionsListView.js +7 -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/auth/components/RegisterForm.js +2 -2
- package/dist/features/auth/components/VerifyEmailView.js +5 -2
- package/dist/features/before-after/components/BeforeAfterSlider.js +1 -1
- package/dist/features/blog/actions/blog-actions.js +3 -2
- 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/categories/components/BrandDetailPageView.js +15 -10
- 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 +13 -7
- package/dist/features/categories/components/CategoriesIndexPageView.js +5 -4
- package/dist/features/categories/components/CategoryBundlesListing.js +10 -6
- package/dist/features/categories/components/CategoryDetailPageView.js +18 -12
- package/dist/features/categories/components/CategoryDetailTabs.js +5 -1
- package/dist/features/categories/components/CategoryFilters.d.ts +12 -12
- package/dist/features/categories/components/CategoryFilters.js +13 -12
- 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.d.ts +1 -1
- package/dist/features/categories/components/CategoryTree.js +2 -2
- package/dist/features/categories/schemas/firestore.d.ts +2 -2
- package/dist/features/checkout/actions/checkout-actions.d.ts +1 -1
- package/dist/features/checkout/actions/checkout-actions.js +1 -1
- package/dist/features/classified/components/ClassifiedFilters.js +2 -2
- package/dist/features/classified/components/ClassifiedIndexListing.js +9 -3
- package/dist/features/classified/components/ClassifiedListView.js +6 -5
- package/dist/features/collections/components/CollectionCard.js +2 -1
- 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/cron/jobs/auction-expiry.job.d.ts +2 -2
- package/dist/features/cron/jobs/auction-expiry.job.js +2 -1
- package/dist/features/cron/jobs/preorder-reminder.job.d.ts +1 -1
- package/dist/features/cron/jobs/preorder-reminder.job.js +2 -1
- package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +9 -3
- package/dist/features/digital-codes/components/DigitalCodesListView.js +4 -3
- package/dist/features/events/actions/event-actions.js +6 -4
- package/dist/features/events/components/AdminEventEditorView.js +63 -41
- package/dist/features/events/components/AdminEventEntriesView.js +9 -6
- package/dist/features/events/components/AdminEventsView.js +7 -5
- package/dist/features/events/components/EventCard.js +7 -1
- package/dist/features/events/components/EventFilters.d.ts +4 -4
- package/dist/features/events/components/EventFilters.js +2 -2
- 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 +6 -4
- 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/schemas/firestore.d.ts +1 -0
- package/dist/features/events/types/index.d.ts +1 -0
- package/dist/features/faq/actions/faq-actions.js +4 -2
- 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 +7 -6
- package/dist/features/faq/components/FAQSortDropdown.js +2 -2
- 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/MarketplaceHomepageView.js +4 -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/layout/AppLayoutShell.js +2 -1
- package/dist/features/layout/BackToTop.js +1 -1
- package/dist/features/layout/BottomActions.js +4 -30
- package/dist/features/layout/BottomActionsContext.d.ts +0 -36
- package/dist/features/layout/BottomActionsContext.js +0 -36
- 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/live/components/LiveItemsListView.js +6 -5
- package/dist/features/loyalty/components/CoinsDisplay.js +4 -2
- 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/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/components/PreOrdersListView.js +5 -4
- package/dist/features/products/actions/product-actions.js +17 -15
- package/dist/features/products/columns/index.d.ts +1 -1
- package/dist/features/products/columns/index.js +1 -1
- 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 -16
- 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/PrizeDrawsListingView.js +5 -4
- package/dist/features/products/components/PrizeDrawsSection.js +6 -4
- 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/constants/sieve.d.ts +2 -2
- package/dist/features/products/constants/sieve.js +2 -2
- package/dist/features/products/hooks/useRelatedProducts.js +5 -4
- package/dist/features/promotions/components/CouponCard.js +5 -3
- package/dist/features/promotions/components/CouponsIndexListing.js +7 -3
- 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/actions/review-actions.js +2 -1
- 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/ReviewsIndexPageView.js +7 -6
- package/dist/features/reviews/components/ReviewsList.js +1 -1
- package/dist/features/scams/actions/scam-actions.js +3 -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 +11 -8
- package/dist/features/search/actions/search-actions.js +7 -6
- 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/seller/components/CouponInlineSelect.d.ts +22 -0
- package/dist/features/seller/components/CouponInlineSelect.js +104 -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/SellerAuctionsView.js +7 -5
- package/dist/features/seller/components/SellerBidsView.js +12 -10
- package/dist/features/seller/components/SellerBundlesView.js +9 -7
- package/dist/features/seller/components/SellerClassifiedView.js +6 -5
- 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 +7 -5
- package/dist/features/seller/components/SellerDashboardView.js +2 -2
- package/dist/features/seller/components/SellerDigitalCodesView.js +7 -6
- package/dist/features/seller/components/SellerGoogleReviewsView.js +2 -2
- package/dist/features/seller/components/SellerGroupedListingsView.js +10 -9
- package/dist/features/seller/components/SellerLiveView.js +6 -5
- package/dist/features/seller/components/SellerOffersView.js +6 -4
- package/dist/features/seller/components/SellerOrdersView.js +18 -13
- package/dist/features/seller/components/SellerPayoutMethodsView.js +8 -6
- package/dist/features/seller/components/SellerPayoutRequestView.js +5 -1
- package/dist/features/seller/components/SellerPayoutSettingsView.js +5 -2
- package/dist/features/seller/components/SellerPayoutsView.js +6 -4
- package/dist/features/seller/components/SellerPreOrdersView.js +12 -10
- package/dist/features/seller/components/SellerPrizeDrawsView.js +12 -10
- 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 +14 -12
- package/dist/features/seller/components/SellerReviewsView.js +7 -3
- package/dist/features/seller/components/SellerShippingConfigsView.js +7 -6
- 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 +5 -4
- package/dist/features/seller/components/SellerStorefrontView.js +2 -2
- package/dist/features/seller/components/SellerTemplatesView.js +11 -7
- package/dist/features/seller/components/SublistingInlineSelect.d.ts +19 -0
- package/dist/features/seller/components/SublistingInlineSelect.js +84 -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/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/actions/store-query-actions.js +3 -2
- 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/StoreAuctionsPageView.js +4 -2
- package/dist/features/stores/components/StoreDetailLayoutView.d.ts +1 -1
- package/dist/features/stores/components/StoreDetailLayoutView.js +7 -6
- 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/StorePreOrdersPageView.js +4 -2
- package/dist/features/stores/components/StorePrizeDrawsPageView.js +4 -2
- package/dist/features/stores/components/StoreProductsListing.js +6 -3
- package/dist/features/stores/components/StoreProductsPageView.js +2 -1
- package/dist/features/stores/components/StoreProductsView.js +5 -4
- package/dist/features/stores/components/StoreReviewsListing.js +8 -2
- package/dist/features/stores/components/StoresIndexListing.js +16 -9
- 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/components/WishlistView.js +4 -3
- 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
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
4
|
+
const __O = {
|
|
5
|
+
hidden: "overflow-hidden",
|
|
6
|
+
};
|
|
4
7
|
const SVG_PATH_SEARCH = "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z";
|
|
5
8
|
const CLS_HOVER_ROW = "hover:bg-zinc-100 dark:hover:bg-slate-800";
|
|
6
9
|
const CLS_ICON_ROW = "w-4 h-4 flex-shrink-0 text-zinc-500 dark:text-zinc-400";
|
|
7
10
|
const CLS_TRUNCATE = "font-medium truncate";
|
|
8
|
-
import { Button, Input, Li, Row, Span, Text, Ul } from "../../../ui";
|
|
11
|
+
import { Button, Div, Input, Li, Row, Span, Text, Ul } from "../../../ui";
|
|
9
12
|
import { useNavSuggestions } from "../hooks/useNavSuggestions";
|
|
10
13
|
const DEFAULT_TYPE_ICONS = {
|
|
11
14
|
page: "📄",
|
|
@@ -23,7 +26,7 @@ const DEFAULT_TYPE_BADGES = {
|
|
|
23
26
|
};
|
|
24
27
|
function SuggestionItem({ suggestion, itemIndex, activeIndex, onSelect, onHover, typeIcons, typeBadges, }) {
|
|
25
28
|
const isActive = activeIndex === itemIndex;
|
|
26
|
-
return (_jsx(Li, { children: _jsxs(Button, { type: "button", variant: "ghost", onClick: () => onSelect(suggestion), onMouseEnter: () => onHover(itemIndex), className: `w-full flex items-center gap-3 px-4 py-3 text-left transition-colors border-b border-zinc-200 dark:border-slate-700 last:border-b-0 ${isActive ? "bg-zinc-100 dark:bg-slate-800" : CLS_HOVER_ROW}`, children: [_jsx(Span, {
|
|
29
|
+
return (_jsx(Li, { children: _jsxs(Button, { type: "button", variant: "ghost", onClick: () => onSelect(suggestion), onMouseEnter: () => onHover(itemIndex), className: `w-full flex items-center gap-3 px-4 py-3 text-left transition-colors border-b border-zinc-200 dark:border-slate-700 last:border-b-0 ${isActive ? "bg-zinc-100 dark:bg-slate-800" : CLS_HOVER_ROW}`, children: [_jsx(Span, { size: "sm", children: typeIcons[suggestion.type] }), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Text, { size: "sm", className: CLS_TRUNCATE, children: suggestion.title }), suggestion.subtitle && (_jsx(Text, { variant: "secondary", size: "xs", className: "truncate", children: suggestion.subtitle }))] }), _jsx(Span, { size: "xs", className: `px-2 py-0.5 rounded-full ${typeBadges[suggestion.type]}`, children: suggestion.type })] }) }));
|
|
27
30
|
}
|
|
28
31
|
export function Search({ isOpen, onClose, onSearch, onOpen, value, onChange, placeholder, deferred = true, debounceMs = 300, onClear, className, router, quickLinks = [], labels, suggestionTypeIcons, suggestionTypeBadges, resourceTypes, defaultResourceType = "products", storageKey = "letitrip_search_type", }) {
|
|
29
32
|
const isInlineMode = value !== undefined;
|
|
@@ -202,11 +205,11 @@ export function Search({ isOpen, onClose, onSearch, onOpen, value, onChange, pla
|
|
|
202
205
|
if (inlineBlurRef.current)
|
|
203
206
|
clearTimeout(inlineBlurRef.current);
|
|
204
207
|
inlineBlurRef.current = setTimeout(() => setIsInlineOpen(false), 120);
|
|
205
|
-
}, placeholder: placeholder ?? labels.placeholder, className: "w-full rounded-lg border border-zinc-300 bg-white pl-9 text-zinc-900 placeholder:text-zinc-400 focus:border-primary focus:ring-2 focus:ring-primary/20 dark:border-slate-700 dark:bg-slate-900 dark:text-white dark:placeholder:text-slate-500" }), query && (_jsx(Button, { type: "button", variant: "ghost", onClick: handleClear, className: "absolute right-3 p-0.5 rounded-full text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-200 transition-colors", "aria-label": labels.clearAriaLabel, children: _jsx("svg", { className: "w-4 h-4", "aria-hidden": "true", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) }))] }), resourceTypes && resourceTypes.length > 0 && (_jsx("select", { value: selectedType, onChange: (e) => handleTypeChange(e.target.value), "aria-label": labels.resourceTypeLabel ?? "Search in", className: "flex-shrink-0 rounded-lg border border-zinc-300 bg-white px-2 py-2 text-sm text-zinc-700 focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20 dark:border-slate-700 dark:bg-slate-900 dark:text-zinc-300 cursor-pointer", children: resourceTypes.map((opt) => (_jsx("option", { value: opt.value, children: opt.label }, opt.value))) })), deferred && (_jsx(Button, { type: "button", variant: "primary", onClick: handleDeferredSubmit, "aria-label": labels.ariaLabel, className: "flex-shrink-0 px-3 py-2 rounded-lg", children: _jsx("svg", { className: "w-4 h-4", "aria-hidden": "true", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: SVG_PATH_SEARCH }) }) })), isInlineOpen && (filteredQuickLinks.length > 0 || query) && (_jsxs("div", { className: "absolute top-full left-0 right-0 mt-2 rounded-xl overflow-hidden border border-zinc-200 bg-white shadow-lg dark:border-slate-700 dark:bg-slate-900", style: { zIndex: "var(--appkit-z-dropdown)" }, onMouseDown: (event) => event.preventDefault(), children: [filteredQuickLinks.length > 0 && (_jsx(Ul, { children: filteredQuickLinks.map((link, index) => renderInlineQuickLink(link, index)) })), query && suggestionsLoading && (_jsx(
|
|
208
|
+
}, placeholder: placeholder ?? labels.placeholder, className: "w-full rounded-lg border border-zinc-300 bg-white pl-9 text-zinc-900 placeholder:text-zinc-400 focus:border-primary focus:ring-2 focus:ring-primary/20 dark:border-slate-700 dark:bg-slate-900 dark:text-white dark:placeholder:text-slate-500" }), query && (_jsx(Button, { type: "button", variant: "ghost", onClick: handleClear, className: "absolute right-3 p-0.5 rounded-full text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-200 transition-colors", "aria-label": labels.clearAriaLabel, children: _jsx("svg", { className: "w-4 h-4", "aria-hidden": "true", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) }))] }), resourceTypes && resourceTypes.length > 0 && (_jsx("select", { value: selectedType, onChange: (e) => handleTypeChange(e.target.value), "aria-label": labels.resourceTypeLabel ?? "Search in", className: "flex-shrink-0 rounded-lg border border-zinc-300 bg-white px-2 py-2 text-sm text-zinc-700 focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20 dark:border-slate-700 dark:bg-slate-900 dark:text-zinc-300 cursor-pointer", children: resourceTypes.map((opt) => (_jsx("option", { value: opt.value, children: opt.label }, opt.value))) })), deferred && (_jsx(Button, { type: "button", variant: "primary", onClick: handleDeferredSubmit, "aria-label": labels.ariaLabel, className: "flex-shrink-0 px-3 py-2 rounded-lg", children: _jsx("svg", { className: "w-4 h-4", "aria-hidden": "true", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: SVG_PATH_SEARCH }) }) })), isInlineOpen && (filteredQuickLinks.length > 0 || query) && (_jsxs("div", { className: "absolute top-full left-0 right-0 mt-2 rounded-xl overflow-hidden border border-zinc-200 bg-white shadow-lg dark:border-slate-700 dark:bg-slate-900", style: { zIndex: "var(--appkit-z-dropdown)" }, onMouseDown: (event) => event.preventDefault(), children: [filteredQuickLinks.length > 0 && (_jsx(Ul, { children: filteredQuickLinks.map((link, index) => renderInlineQuickLink(link, index)) })), query && suggestionsLoading && (_jsx(Div, { className: "px-4 py-3", children: _jsx(Text, { variant: "secondary", size: "sm", children: labels.searching }) })), query &&
|
|
206
209
|
suggestions.slice(0, 5).map((suggestion, suggestionIndex) => {
|
|
207
210
|
const itemIndex = inlineQuickLinkItems.length + suggestionIndex;
|
|
208
211
|
const isActive = activeIndex === itemIndex;
|
|
209
|
-
return (_jsxs(Button, { type: "button", variant: "ghost", onClick: () => handleSuggestionClick(suggestion), onMouseEnter: () => setActiveIndex(itemIndex), className: `w-full flex items-center gap-3 px-4 py-2.5 text-left transition-colors border-b border-zinc-200 dark:border-slate-700 ${isActive ? "bg-zinc-100 dark:bg-slate-800" : CLS_HOVER_ROW}`, children: [_jsx(Span, {
|
|
212
|
+
return (_jsxs(Button, { type: "button", variant: "ghost", onClick: () => handleSuggestionClick(suggestion), onMouseEnter: () => setActiveIndex(itemIndex), className: `w-full flex items-center gap-3 px-4 py-2.5 text-left transition-colors border-b border-zinc-200 dark:border-slate-700 ${isActive ? "bg-zinc-100 dark:bg-slate-800" : CLS_HOVER_ROW}`, children: [_jsx(Span, { size: "sm", children: typeIcons[suggestion.type] }), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Text, { size: "sm", className: CLS_TRUNCATE, children: suggestion.title }), suggestion.subtitle && (_jsx(Text, { variant: "secondary", size: "xs", className: "truncate", children: suggestion.subtitle }))] })] }, `inline-suggestion-${suggestion.objectID}`));
|
|
210
213
|
}), query.trim() && (_jsxs(Button, { type: "button", variant: "ghost", onClick: () => {
|
|
211
214
|
handleDeferredSubmit();
|
|
212
215
|
setIsInlineOpen(false);
|
|
@@ -278,7 +281,7 @@ export function Search({ isOpen, onClose, onSearch, onOpen, value, onChange, pla
|
|
|
278
281
|
};
|
|
279
282
|
if (!isOpen)
|
|
280
283
|
return null;
|
|
281
|
-
return (_jsx(
|
|
284
|
+
return (_jsx(Div, { className: "border-b border-zinc-200 bg-white shadow-md dark:border-slate-800 dark:bg-slate-950 animate-[fadeIn_150ms_ease-out]", children: _jsxs(Div, { className: "container mx-auto px-4 py-3 md:py-4 relative", children: [_jsxs(Row, { gap: "sm", className: "md:gap-3", children: [_jsx(Div, { className: "flex-1 relative", children: _jsx(Input, { ref: inputRef, bare: true, type: "search", placeholder: placeholder ?? labels.placeholder, value: query, onChange: (event) => setQuery(event.target.value), onKeyDown: handleOverlayKeyDown, className: "w-full rounded-lg border border-zinc-300 bg-white text-zinc-900 placeholder:text-zinc-400 focus:border-primary focus:ring-2 focus:ring-primary/20 dark:border-slate-700 dark:bg-slate-900 dark:text-white dark:placeholder:text-slate-500" }) }), resourceTypes && resourceTypes.length > 0 && (_jsx("select", { value: selectedType, onChange: (e) => handleTypeChange(e.target.value), "aria-label": labels.resourceTypeLabel ?? "Search in", className: "flex-shrink-0 rounded-lg border border-zinc-300 bg-white px-2 py-2 text-sm text-zinc-700 focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20 dark:border-slate-700 dark:bg-slate-900 dark:text-zinc-300 cursor-pointer", children: resourceTypes.map((opt) => (_jsx("option", { value: opt.value, children: opt.label }, opt.value))) })), _jsxs(Button, { onClick: handleOverlaySearch, variant: "primary", size: "md", className: "hidden sm:flex gap-2", children: [_jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: SVG_PATH_SEARCH }) }), labels.title] }), _jsx(Button, { variant: "ghost", onClick: () => onClose?.(), className: "p-2.5 md:p-3 rounded-xl transition-colors text-zinc-500 hover:bg-zinc-100 hover:text-zinc-700 dark:text-zinc-400 dark:hover:bg-slate-800 dark:hover:text-zinc-200 flex-shrink-0", "aria-label": labels.closeAriaLabel, children: _jsx("svg", { className: "w-6 h-6 md:w-7 md:h-7", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }), (filteredSiteLinks.length > 0 || query) && (_jsxs(Div, { className: "absolute top-full left-0 right-0 px-4 pt-2 pb-4 space-y-2 z-50", children: [filteredSiteLinks.length > 0 && !suggestionsLoading && (_jsxs(Div, { className: `rounded-xl ${__O.hidden} border border-zinc-200 bg-white shadow-lg dark:border-slate-700 dark:bg-slate-900`, children: [_jsx(Div, { className: "px-4 py-2 border-b border-zinc-200 dark:border-slate-700", children: _jsx(Text, { variant: "secondary", size: "xs", className: "uppercase tracking-wider font-semibold", children: labels.quickLinks }) }), _jsx(Ul, { children: filteredSiteLinks.map((link) => {
|
|
282
285
|
const Icon = link.icon;
|
|
283
286
|
const itemIndex = quickLinkItems.findIndex((item) => item.link.href === link.href);
|
|
284
287
|
const isActive = activeIndex === itemIndex;
|
|
@@ -286,5 +289,5 @@ export function Search({ isOpen, onClose, onSearch, onOpen, value, onChange, pla
|
|
|
286
289
|
onClose?.();
|
|
287
290
|
router.push(link.href);
|
|
288
291
|
}, onMouseEnter: () => setActiveIndex(itemIndex), className: `w-full flex items-center gap-3 px-4 py-2.5 text-left transition-colors border-b border-zinc-200 dark:border-slate-700 last:border-b-0 ${isActive ? "bg-zinc-100 dark:bg-slate-800" : CLS_HOVER_ROW}`, children: [_jsx(Icon, { className: CLS_ICON_ROW }), _jsx(Text, { size: "sm", className: "font-medium", children: link.label })] }) }, link.href));
|
|
289
|
-
}) })] })), query && (_jsxs(
|
|
292
|
+
}) })] })), query && (_jsxs(Div, { className: `rounded-xl ${__O.hidden} border border-zinc-200 bg-white shadow-lg dark:border-slate-700 dark:bg-slate-900`, children: [suggestionsLoading ? (_jsx(Div, { className: "px-4 py-3", children: _jsx(Text, { variant: "secondary", size: "sm", children: labels.searching }) })) : suggestions.length > 0 ? (_jsx(Ul, { children: suggestions.map((suggestion, suggestionIndex) => (_jsx(SuggestionItem, { suggestion: suggestion, itemIndex: getOverlaySuggestionIndex(suggestionIndex), activeIndex: activeIndex, onSelect: handleSuggestionClick, onHover: setActiveIndex, typeIcons: typeIcons, typeBadges: typeBadges }, suggestion.objectID))) })) : null, _jsxs(Button, { type: "button", variant: "ghost", onClick: handleOverlaySearch, onMouseEnter: () => setActiveIndex(overlayItems.length - 1), className: `w-full flex items-center gap-2 px-4 py-3 text-left transition-colors ${activeIndex === overlayItems.length - 1 ? "bg-zinc-100 dark:bg-slate-800" : CLS_HOVER_ROW}${suggestions.length > 0 ? " border-t border-zinc-200 dark:border-slate-700" : ""}`, children: [_jsx("svg", { className: CLS_ICON_ROW, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: SVG_PATH_SEARCH }) }), _jsx(Text, { size: "sm", className: "font-medium", children: labels.browseProducts(query) })] })] }))] }))] }) }));
|
|
290
293
|
}
|
|
@@ -17,5 +17,5 @@ export function SearchFiltersRow({ urlCategory, categories, urlMinPrice, urlMaxP
|
|
|
17
17
|
return (_jsxs(Row, { wrap: true, gap: "md", align: "end", children: [_jsxs(Div, { className: "flex flex-col gap-1", children: [_jsx(Label, { className: "text-sm font-medium text-zinc-600 dark:text-zinc-400", children: L.categoryFilter }), _jsx(Select, { value: urlCategory, onValueChange: (value) => onCategoryChange(value), options: [
|
|
18
18
|
{ value: "", label: L.allCategories },
|
|
19
19
|
...categories.map((cat) => ({ value: cat.id, label: cat.name })),
|
|
20
|
-
], className: "rounded-lg border border-zinc-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-primary-500/20" })] }), _jsxs(Div, { className: "flex flex-col gap-1", children: [_jsx(Label, { className: "text-sm font-medium text-zinc-600 dark:text-zinc-400", children: L.priceRange }), _jsxs(Div, { className: "flex items-center gap-2", children: [_jsx(Input, { type: "number", min: 0, value: minPrice, onChange: (e) => setMinPrice(e.target.value), placeholder: L.minPrice, className: "w-28 rounded-lg border border-zinc-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-primary-500/20" }), _jsx(Span, {
|
|
20
|
+
], className: "rounded-lg border border-zinc-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-primary-500/20" })] }), _jsxs(Div, { className: "flex flex-col gap-1", children: [_jsx(Label, { className: "text-sm font-medium text-zinc-600 dark:text-zinc-400", children: L.priceRange }), _jsxs(Div, { className: "flex items-center gap-2", children: [_jsx(Input, { type: "number", min: 0, value: minPrice, onChange: (e) => setMinPrice(e.target.value), placeholder: L.minPrice, className: "w-28 rounded-lg border border-zinc-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-primary-500/20" }), _jsx(Span, { size: "sm", className: "text-zinc-500 dark:text-zinc-400", children: "\u2013" }), _jsx(Input, { type: "number", min: 0, value: maxPrice, onChange: (e) => setMaxPrice(e.target.value), placeholder: L.maxPrice, className: "w-28 rounded-lg border border-zinc-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-primary-500/20" }), _jsx(Button, { type: "button", variant: "primary", size: "sm", onClick: () => onPriceFilter(minPrice, maxPrice), className: "h-10 px-4 rounded-lg bg-primary-600 hover:bg-primary-700 text-white text-sm font-medium transition-colors", children: L.apply })] })] }), showClear && (_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: onClearFilters, className: "h-10 px-4 rounded-lg border border-zinc-200 dark:border-slate-700 text-sm text-zinc-700 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-slate-800 transition-colors", children: L.clearFilters }))] }));
|
|
21
21
|
}
|
|
@@ -31,5 +31,5 @@ export function SearchResultsSection({ products, total, totalPages, urlQ, urlSor
|
|
|
31
31
|
urlPage,
|
|
32
32
|
totalPages,
|
|
33
33
|
onPageChange,
|
|
34
|
-
})) : (_jsxs(Div, { className: "flex items-center justify-center gap-2 pt-4", children: [_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => onPageChange(urlPage - 1), disabled: urlPage <= 1, className: "px-4 py-2 rounded-lg border border-zinc-200 dark:border-slate-700 text-sm text-zinc-700 dark:text-zinc-300 disabled:opacity-40 hover:bg-zinc-100 dark:hover:bg-slate-800 transition-colors", children: L.prevPage }), _jsxs(Span, {
|
|
34
|
+
})) : (_jsxs(Div, { className: "flex items-center justify-center gap-2 pt-4", children: [_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => onPageChange(urlPage - 1), disabled: urlPage <= 1, className: "px-4 py-2 rounded-lg border border-zinc-200 dark:border-slate-700 text-sm text-zinc-700 dark:text-zinc-300 disabled:opacity-40 hover:bg-zinc-100 dark:hover:bg-slate-800 transition-colors", children: L.prevPage }), _jsxs(Span, { size: "sm", className: "text-zinc-600 dark:text-zinc-400 tabular-nums", children: [urlPage, " / ", totalPages] }), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => onPageChange(urlPage + 1), disabled: urlPage >= totalPages, className: "px-4 py-2 rounded-lg border border-zinc-200 dark:border-slate-700 text-sm text-zinc-700 dark:text-zinc-300 disabled:opacity-40 hover:bg-zinc-100 dark:hover:bg-slate-800 transition-colors", children: L.nextPage })] })))] }));
|
|
35
35
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
type Scope = "admin" | "store";
|
|
2
|
+
interface BaseProps {
|
|
3
|
+
/** Which API to query. "store" hits the seller's own coupons; "admin" hits the admin pool. */
|
|
4
|
+
scope: Scope;
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
/** Show the "+ Create new coupon" quick-create (store scope only — admin coupons are too complex for inline create). Defaults to scope === "store". */
|
|
8
|
+
allowCreate?: boolean;
|
|
9
|
+
}
|
|
10
|
+
interface SingleProps extends BaseProps {
|
|
11
|
+
multiple?: false;
|
|
12
|
+
value: string;
|
|
13
|
+
onChange: (v: string) => void;
|
|
14
|
+
}
|
|
15
|
+
interface MultiProps extends BaseProps {
|
|
16
|
+
multiple: true;
|
|
17
|
+
value: string[];
|
|
18
|
+
onChange: (v: string[]) => void;
|
|
19
|
+
}
|
|
20
|
+
export type CouponInlineSelectProps = SingleProps | MultiProps;
|
|
21
|
+
export declare function CouponInlineSelect(props: CouponInlineSelectProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { sortBy } from "@mohasinac/appkit";
|
|
4
|
+
import React from "react";
|
|
5
|
+
import { PaginatedSelect } from "../../../ui/components/PaginatedSelect";
|
|
6
|
+
import { apiClient } from "../../../http";
|
|
7
|
+
import { ADMIN_ENDPOINTS, SELLER_ENDPOINTS, } from "../../../constants/api-endpoints";
|
|
8
|
+
function makeLoader(scope) {
|
|
9
|
+
const endpoint = scope === "admin" ? ADMIN_ENDPOINTS.COUPONS : SELLER_ENDPOINTS.COUPONS;
|
|
10
|
+
return async (query, page) => {
|
|
11
|
+
const params = new URLSearchParams({
|
|
12
|
+
page: String(page),
|
|
13
|
+
pageSize: "25",
|
|
14
|
+
sorts: sortBy("createdAt", "DESC"),
|
|
15
|
+
});
|
|
16
|
+
if (query.trim())
|
|
17
|
+
params.set("q", query.trim());
|
|
18
|
+
const res = await apiClient.get(`${endpoint}?${params.toString()}`);
|
|
19
|
+
const raw = res.data ?? res.coupons ?? res.items ?? [];
|
|
20
|
+
const items = raw.map((c) => ({
|
|
21
|
+
value: String(c.id ?? c.code ?? ""),
|
|
22
|
+
label: c.code
|
|
23
|
+
? `${c.code}${c.name && c.name !== c.code ? ` — ${c.name}` : ""}`
|
|
24
|
+
: String(c.name ?? c.id ?? ""),
|
|
25
|
+
}));
|
|
26
|
+
const total = res.total ?? items.length;
|
|
27
|
+
return { items, hasMore: page * 25 < total, nextPage: page + 1 };
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const TODAY_ISO = () => new Date().toISOString().slice(0, 10);
|
|
31
|
+
const NEXT_YEAR_ISO = () => {
|
|
32
|
+
const d = new Date();
|
|
33
|
+
d.setFullYear(d.getFullYear() + 1);
|
|
34
|
+
return d.toISOString().slice(0, 10);
|
|
35
|
+
};
|
|
36
|
+
async function quickCreateStoreCoupon(values) {
|
|
37
|
+
const code = String(values.code ?? "")
|
|
38
|
+
.toUpperCase()
|
|
39
|
+
.replace(/\s+/g, "");
|
|
40
|
+
const valueNum = Number(values.value ?? 0);
|
|
41
|
+
const type = String(values.type ?? "percentage");
|
|
42
|
+
if (!code)
|
|
43
|
+
throw new Error("Code is required");
|
|
44
|
+
if (type === "percentage" && (valueNum < 1 || valueNum > 100)) {
|
|
45
|
+
throw new Error("Percentage must be between 1 and 100");
|
|
46
|
+
}
|
|
47
|
+
const res = await apiClient.post(SELLER_ENDPOINTS.COUPONS, {
|
|
48
|
+
code,
|
|
49
|
+
type,
|
|
50
|
+
value: valueNum,
|
|
51
|
+
totalLimit: 0,
|
|
52
|
+
perUserLimit: 0,
|
|
53
|
+
startDate: TODAY_ISO(),
|
|
54
|
+
endDate: NEXT_YEAR_ISO(),
|
|
55
|
+
isActive: true,
|
|
56
|
+
});
|
|
57
|
+
const id = String(res.data?.id ?? res.id ?? "");
|
|
58
|
+
if (!id)
|
|
59
|
+
throw new Error("Created coupon returned no id");
|
|
60
|
+
return { value: id, label: code };
|
|
61
|
+
}
|
|
62
|
+
export function CouponInlineSelect(props) {
|
|
63
|
+
const { scope, placeholder = "Search coupons…", disabled, allowCreate = scope === "store", } = props;
|
|
64
|
+
const loader = React.useMemo(() => makeLoader(scope), [scope]);
|
|
65
|
+
const sharedCreate = allowCreate && scope === "store"
|
|
66
|
+
? {
|
|
67
|
+
createLabel: "coupon",
|
|
68
|
+
drawerTitle: "Create coupon",
|
|
69
|
+
createFields: [
|
|
70
|
+
{
|
|
71
|
+
name: "code",
|
|
72
|
+
label: "Code",
|
|
73
|
+
type: "text",
|
|
74
|
+
required: true,
|
|
75
|
+
placeholder: "e.g. SAVE10",
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: "type",
|
|
79
|
+
label: "Type",
|
|
80
|
+
type: "select",
|
|
81
|
+
required: true,
|
|
82
|
+
options: [
|
|
83
|
+
{ value: "percentage", label: "Percentage off" },
|
|
84
|
+
{ value: "fixed", label: "Flat amount off (₹)" },
|
|
85
|
+
{ value: "free_shipping", label: "Free shipping" },
|
|
86
|
+
],
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: "value",
|
|
90
|
+
label: "Value (% for percentage, ₹ for flat)",
|
|
91
|
+
type: "number",
|
|
92
|
+
required: true,
|
|
93
|
+
placeholder: "10",
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
onCreateSubmit: quickCreateStoreCoupon,
|
|
97
|
+
createSubmitLabel: "Create coupon",
|
|
98
|
+
}
|
|
99
|
+
: {};
|
|
100
|
+
if (props.multiple) {
|
|
101
|
+
return (_jsx(PaginatedSelect, { multiple: true, value: props.value, onChange: (v) => props.onChange(v), loadOptions: loader, placeholder: placeholder, disabled: disabled, ...sharedCreate }));
|
|
102
|
+
}
|
|
103
|
+
return (_jsx(PaginatedSelect, { value: props.value || null, onChange: (v) => props.onChange(v ?? ""), loadOptions: loader, placeholder: placeholder, disabled: disabled, ...sharedCreate }));
|
|
104
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
interface BaseProps {
|
|
2
|
+
placeholder?: string;
|
|
3
|
+
disabled?: boolean;
|
|
4
|
+
/** Show the "+ Create new group" quick-create. Defaults to true. */
|
|
5
|
+
allowCreate?: boolean;
|
|
6
|
+
/** "store" hits /api/store/grouped-listings; "admin" hits /api/admin/grouped-listings. Defaults to "store". */
|
|
7
|
+
scope?: "store" | "admin";
|
|
8
|
+
/** Optional label rendered above the selector. */
|
|
9
|
+
label?: string;
|
|
10
|
+
}
|
|
11
|
+
interface SingleProps extends BaseProps {
|
|
12
|
+
multiple?: false;
|
|
13
|
+
value: string;
|
|
14
|
+
onChange: (v: string) => void;
|
|
15
|
+
}
|
|
16
|
+
interface MultiProps extends BaseProps {
|
|
17
|
+
multiple: true;
|
|
18
|
+
value: string[];
|
|
19
|
+
onChange: (v: string[]) => void;
|
|
20
|
+
}
|
|
21
|
+
export type GroupInlineSelectProps = SingleProps | MultiProps;
|
|
22
|
+
export declare function GroupInlineSelect(props: GroupInlineSelectProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { PaginatedSelect } from "../../../ui/components/PaginatedSelect";
|
|
5
|
+
import { apiClient } from "../../../http";
|
|
6
|
+
import { ADMIN_ENDPOINTS, SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
7
|
+
import { Text } from "../../../ui";
|
|
8
|
+
function makeLoadOptions(scope) {
|
|
9
|
+
const endpoint = scope === "admin"
|
|
10
|
+
? ADMIN_ENDPOINTS.GROUPED_LISTINGS
|
|
11
|
+
: SELLER_ENDPOINTS.GROUPED_LISTINGS;
|
|
12
|
+
return async function loadGroupOptions(query, _page) {
|
|
13
|
+
const res = await apiClient.get(endpoint);
|
|
14
|
+
const raw = res.data?.items ?? res.items ?? [];
|
|
15
|
+
const all = raw.map((g) => {
|
|
16
|
+
const count = Array.isArray(g.productIds) ? g.productIds.length : 0;
|
|
17
|
+
const label = g.title ?? g.name ?? g.slug ?? String(g.id ?? "");
|
|
18
|
+
return {
|
|
19
|
+
value: String(g.id ?? ""),
|
|
20
|
+
label: count > 0 ? `${label} (${count})` : label,
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
const q = query.trim().toLowerCase();
|
|
24
|
+
const items = q ? all.filter((g) => g.label.toLowerCase().includes(q)) : all;
|
|
25
|
+
return { items, hasMore: false };
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function toGroupSlug(name) {
|
|
29
|
+
const base = name
|
|
30
|
+
.toLowerCase()
|
|
31
|
+
.trim()
|
|
32
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
33
|
+
.replace(/^-+|-+$/g, "");
|
|
34
|
+
return base.startsWith("group-") ? base : `group-${base}`;
|
|
35
|
+
}
|
|
36
|
+
async function quickCreateGroup(values, scope) {
|
|
37
|
+
const title = String(values.title ?? "").trim();
|
|
38
|
+
if (!title)
|
|
39
|
+
throw new Error("Title is required");
|
|
40
|
+
const endpoint = scope === "admin"
|
|
41
|
+
? ADMIN_ENDPOINTS.GROUPED_LISTINGS
|
|
42
|
+
: SELLER_ENDPOINTS.GROUPED_LISTINGS;
|
|
43
|
+
const res = await apiClient.post(endpoint, {
|
|
44
|
+
title,
|
|
45
|
+
slug: toGroupSlug(title),
|
|
46
|
+
productIds: [],
|
|
47
|
+
isActive: true,
|
|
48
|
+
groupTheme: "generic",
|
|
49
|
+
});
|
|
50
|
+
const id = String(res.data?.id ?? res.id ?? "");
|
|
51
|
+
if (!id)
|
|
52
|
+
throw new Error("Created group returned no id");
|
|
53
|
+
return { value: id, label: title };
|
|
54
|
+
}
|
|
55
|
+
export function GroupInlineSelect(props) {
|
|
56
|
+
const { placeholder = "Search groups…", disabled, allowCreate = true, scope = "store", label, } = props;
|
|
57
|
+
const loadOptions = React.useMemo(() => makeLoadOptions(scope), [scope]);
|
|
58
|
+
const sharedCreate = allowCreate
|
|
59
|
+
? {
|
|
60
|
+
createLabel: "group",
|
|
61
|
+
drawerTitle: "Create group",
|
|
62
|
+
createFields: [
|
|
63
|
+
{
|
|
64
|
+
name: "title",
|
|
65
|
+
label: "Group title",
|
|
66
|
+
type: "text",
|
|
67
|
+
required: true,
|
|
68
|
+
placeholder: "e.g. Pokémon Starter Bundle",
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
onCreateSubmit: (values) => quickCreateGroup(values, scope),
|
|
72
|
+
createSubmitLabel: "Create group",
|
|
73
|
+
}
|
|
74
|
+
: {};
|
|
75
|
+
const labelEl = label ? (_jsx(Text, { size: "sm", weight: "medium", className: "mb-1", children: label })) : null;
|
|
76
|
+
if (props.multiple) {
|
|
77
|
+
return (_jsxs(_Fragment, { children: [labelEl, _jsx(PaginatedSelect, { multiple: true, value: props.value, onChange: (v) => props.onChange(v), loadOptions: loadOptions, placeholder: placeholder, disabled: disabled, ...sharedCreate })] }));
|
|
78
|
+
}
|
|
79
|
+
return (_jsxs(_Fragment, { children: [labelEl, _jsx(PaginatedSelect, { value: props.value || null, onChange: (v) => props.onChange(v ?? ""), loadOptions: loadOptions, placeholder: placeholder, disabled: disabled, ...sharedCreate })] }));
|
|
80
|
+
}
|
|
@@ -5,6 +5,7 @@ import { Modal } from "../../../ui/components/Modal";
|
|
|
5
5
|
import { Input } from "../../../ui/components/Input";
|
|
6
6
|
import { Button } from "../../../ui/components/Button";
|
|
7
7
|
import { Row } from "../../../ui/components/Layout";
|
|
8
|
+
import { Div } from "../../../ui/components/Div";
|
|
8
9
|
import { Text } from "../../../ui/components/Typography";
|
|
9
10
|
export function PhysicalLocationModal({ count, onSave, onClose }) {
|
|
10
11
|
const [zone, setZone] = useState("");
|
|
@@ -26,5 +27,5 @@ export function PhysicalLocationModal({ count, onSave, onClose }) {
|
|
|
26
27
|
setSaving(false);
|
|
27
28
|
}
|
|
28
29
|
};
|
|
29
|
-
return (_jsx(Modal, { isOpen: true, onClose: onClose, title: `Set Location — ${count} item${count !== 1 ? "s" : ""}`, size: "sm", actions: _jsxs(Row, { gap: "sm", justify: "end", children: [_jsx(Button, { variant: "ghost", onClick: onClose, disabled: saving, children: "Cancel" }), _jsx(Button, { variant: "primary", onClick: handleSave, disabled: saving, children: saving ? "Saving..." : "Save" })] }), children: _jsxs(
|
|
30
|
+
return (_jsx(Modal, { isOpen: true, onClose: onClose, title: `Set Location — ${count} item${count !== 1 ? "s" : ""}`, size: "sm", actions: _jsxs(Row, { gap: "sm", justify: "end", children: [_jsx(Button, { variant: "ghost", onClick: onClose, disabled: saving, children: "Cancel" }), _jsx(Button, { variant: "primary", onClick: handleSave, disabled: saving, children: saving ? "Saving..." : "Save" })] }), children: _jsxs(Div, { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [_jsx(Text, { variant: "muted", children: "Assign a physical storage location to the selected items. All fields are optional." }), _jsx(Input, { label: "Zone (e.g. A, B, Storage-1)", value: zone, onChange: e => setZone(e.target.value), placeholder: "A" }), _jsx(Input, { label: "Shelf (e.g. 3, Top, Middle)", value: shelf, onChange: e => setShelf(e.target.value), placeholder: "3" }), _jsx(Input, { label: "Bin (e.g. Blue, Box-12)", value: bin, onChange: e => setBin(e.target.value), placeholder: "Blue" }), error && _jsx(Text, { variant: "error", children: error })] }) }));
|
|
30
31
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { Heading, Text } from "../../../ui/components/Typography";
|
|
4
|
+
import { Div } from "../../../ui/components/Div";
|
|
4
5
|
export function PrintCenterView({ store, brandName = "LetItRip" }) {
|
|
5
|
-
return (_jsxs(
|
|
6
|
+
return (_jsxs(Div, { className: "flex flex-col items-center justify-center py-24 text-center gap-4", children: [_jsxs(Heading, { level: 2, children: [brandName, " Print Center"] }), store && _jsx(Text, { size: "sm", variant: "muted", children: store.storeName }), _jsx(Text, { size: "sm", variant: "muted", children: "Print center features are coming soon." })] }));
|
|
6
7
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
type Scope = "admin" | "store";
|
|
2
|
+
interface BaseProps {
|
|
3
|
+
/** Which API to query. "store" lists the seller's own products; "admin" lists all. */
|
|
4
|
+
scope: Scope;
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
/** Filter expression appended to the request, e.g. "listingType==standard". */
|
|
8
|
+
filters?: string;
|
|
9
|
+
/** Override the endpoint (for store-products with a custom path, e.g. `/api/store/products`). */
|
|
10
|
+
endpoint?: string;
|
|
11
|
+
}
|
|
12
|
+
interface SingleProps extends BaseProps {
|
|
13
|
+
multiple?: false;
|
|
14
|
+
value: string | null;
|
|
15
|
+
onChange: (v: string | null) => void;
|
|
16
|
+
}
|
|
17
|
+
interface MultiProps extends BaseProps {
|
|
18
|
+
multiple: true;
|
|
19
|
+
value: string[];
|
|
20
|
+
onChange: (v: string[]) => void;
|
|
21
|
+
}
|
|
22
|
+
export type ProductInlineSelectProps = SingleProps | MultiProps;
|
|
23
|
+
export declare function ProductInlineSelect(props: ProductInlineSelectProps): import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { PaginatedSelect } from "../../../ui/components/PaginatedSelect";
|
|
5
|
+
import { apiClient } from "../../../http";
|
|
6
|
+
import { ADMIN_ENDPOINTS, SELLER_ENDPOINTS, } from "../../../constants/api-endpoints";
|
|
7
|
+
function endpointFor(scope, override) {
|
|
8
|
+
if (override)
|
|
9
|
+
return override;
|
|
10
|
+
return scope === "admin"
|
|
11
|
+
? ADMIN_ENDPOINTS.PRODUCTS
|
|
12
|
+
: SELLER_ENDPOINTS.PRODUCTS;
|
|
13
|
+
}
|
|
14
|
+
function makeLoader(scope, filters, endpoint) {
|
|
15
|
+
const base = endpointFor(scope, endpoint);
|
|
16
|
+
return async (query, page) => {
|
|
17
|
+
const params = new URLSearchParams({
|
|
18
|
+
page: String(page),
|
|
19
|
+
pageSize: "25",
|
|
20
|
+
});
|
|
21
|
+
if (query.trim())
|
|
22
|
+
params.set("q", query.trim());
|
|
23
|
+
if (filters)
|
|
24
|
+
params.set("filters", filters);
|
|
25
|
+
const res = await apiClient.get(`${base}?${params.toString()}`);
|
|
26
|
+
const raw = res.data ?? res.products ?? res.items ?? [];
|
|
27
|
+
const items = raw.map((p) => ({
|
|
28
|
+
value: String(p.id ?? p.slug ?? ""),
|
|
29
|
+
label: String(p.title ?? p.name ?? p.slug ?? p.id ?? ""),
|
|
30
|
+
}));
|
|
31
|
+
const total = res.total ?? items.length;
|
|
32
|
+
return { items, hasMore: page * 25 < total, nextPage: page + 1 };
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export function ProductInlineSelect(props) {
|
|
36
|
+
const { scope, placeholder = "Search products…", disabled, filters, endpoint, } = props;
|
|
37
|
+
const loader = React.useMemo(() => makeLoader(scope, filters, endpoint), [scope, filters, endpoint]);
|
|
38
|
+
if (props.multiple) {
|
|
39
|
+
return (_jsx(PaginatedSelect, { multiple: true, value: props.value, onChange: (v) => props.onChange(v), loadOptions: loader, placeholder: placeholder, disabled: disabled, searchPlaceholder: "Type title or slug\u2026" }));
|
|
40
|
+
}
|
|
41
|
+
return (_jsx(PaginatedSelect, { value: props.value, onChange: (v) => props.onChange(v), loadOptions: loader, placeholder: placeholder, disabled: disabled, searchPlaceholder: "Type title or slug\u2026" }));
|
|
42
|
+
}
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useState } from "react";
|
|
4
4
|
import { Alert, Button, Div, FormField, Stack, Text } from "../../../ui";
|
|
5
|
+
const __P = {
|
|
6
|
+
p5: "p-5",
|
|
7
|
+
};
|
|
5
8
|
function toRupees(paise) {
|
|
6
9
|
return paise != null && paise > 0 ? String(Math.round(paise / 100)) : "";
|
|
7
10
|
}
|
|
@@ -43,7 +46,7 @@ export function QuickProductForm({ values, onChange, onPublish, onSave, onSwitch
|
|
|
43
46
|
}
|
|
44
47
|
onSave();
|
|
45
48
|
};
|
|
46
|
-
return (_jsxs(Stack, { gap: "lg", className:
|
|
49
|
+
return (_jsxs(Stack, { gap: "lg", className: `${__P.p5}`, children: [_jsx(Div, { children: _jsx(Text, { className: "text-sm text-zinc-500 dark:text-zinc-400", children: "Quick add \u2014 fill the essentials and publish. You can add more details later." }) }), touched && Object.keys(errors).length > 0 && (_jsx(Alert, { variant: "error", children: "Please fix the highlighted fields before publishing." })), _jsx(FormField, { name: "title", label: "Product Name", type: "text", value: values.title ?? "", onChange: (v) => onChange({ title: v }), placeholder: "e.g. Charizard Base Set PSA 9", required: true, error: touched ? errors.title : undefined }), renderCategorySelector ? (_jsxs(Div, { children: [_jsx(Text, { className: "text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1", children: "Category" }), renderCategorySelector({
|
|
47
50
|
value: values.category ?? "",
|
|
48
51
|
onChange: (v) => onChange({ category: v }),
|
|
49
52
|
}), touched && errors.category && (_jsx(Text, { className: "text-xs text-[var(--appkit-color-error)] mt-1", children: errors.category }))] })) : (_jsx(FormField, { name: "category", label: "Category", type: "text", value: values.category ?? "", onChange: (v) => onChange({ category: v }), placeholder: "e.g. Trading Cards", error: touched ? errors.category : undefined })), _jsx(FormField, { name: "price", label: "Price (\u20B9)", type: "number", value: toRupees(values.price), onChange: (v) => onChange({ price: toPaise(v) }), placeholder: "e.g. 499", required: true, error: touched ? errors.price : undefined }), _jsx(FormField, { name: "mainImage", label: "Product Image", type: "image", value: values.mainImage ?? "", onChange: (v) => onChange({ mainImage: v }), onUpload: onUploadImage, required: true, error: touched ? errors.mainImage : undefined }), _jsx(FormField, { name: "description", label: "Description", type: "textarea", value: values.description ?? "", onChange: (v) => onChange({ description: v }), placeholder: "Brief description (optional)", rows: 3 }), _jsx(FormField, { name: "stockQuantity", label: "Stock Quantity", type: "number", value: String(values.stockQuantity ?? 1), onChange: (v) => onChange({ stockQuantity: Math.max(0, parseInt(v, 10) || 0) }), placeholder: "1", hint: "How many units are available" }), _jsxs(Div, { className: "flex flex-col gap-3 pt-2", children: [_jsxs(Div, { className: "flex gap-3", children: [_jsx(Button, { variant: "primary", onClick: handlePublish, disabled: isLoading, className: "flex-1", children: isLoading ? "Publishing..." : "Publish" }), _jsx(Button, { variant: "secondary", onClick: handleSave, disabled: isLoading, children: "Save Draft" })] }), _jsx(Button, { variant: "ghost", size: "sm", onClick: onSwitchToFull, className: "self-center text-xs", children: "Show all fields (advanced)" })] })] }));
|
|
@@ -2,11 +2,16 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useCallback, useEffect, useState } from "react";
|
|
4
4
|
import { MapPin, Pencil, Plus, Trash2, Star } from "lucide-react";
|
|
5
|
-
import { Button, ConfirmDeleteModal, Div, Grid, Heading, Label, Row, SideDrawer, Span, Stack, Text } from "../../../ui";
|
|
5
|
+
import { Button, ConfirmDeleteModal, Div, Grid, Heading, Label, Row, SideDrawer, Span, Stack, Table, Thead, Tbody, Tr, Th, Td, Text } from "../../../ui";
|
|
6
6
|
import { ROW_ACTION_META, ROW_ACTION_ID } from "../../../features/products/constants/action-defs";
|
|
7
7
|
import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
8
8
|
import { useEntityDelete } from "../../../react/hooks/useEntityDelete";
|
|
9
|
+
const __O = {
|
|
10
|
+
xAuto: "overflow-x-auto",
|
|
11
|
+
};
|
|
9
12
|
const INPUT_CLS = "w-full rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 placeholder-zinc-400 dark:placeholder-zinc-500 focus:outline-none focus:ring-2 focus:ring-[var(--appkit-color-primary)]";
|
|
13
|
+
const CLS_DEFAULT_PILL = "inline-flex items-center gap-1 rounded-full bg-amber-50 dark:bg-amber-950/40 text-amber-700 dark:text-amber-300 border border-amber-200 dark:border-amber-800 px-2 py-0.5";
|
|
14
|
+
const CLS_DELETE_BTN = "rounded-lg p-1.5 text-zinc-500 dark:text-zinc-400 hover:bg-red-50 dark:hover:bg-red-950/40 hover:text-red-600 dark:hover:text-red-400 transition-colors";
|
|
10
15
|
function Field({ label, hint, children }) {
|
|
11
16
|
return (_jsxs(Stack, { gap: "xs", children: [_jsx(Label, { className: "block text-xs font-medium text-zinc-700 dark:text-zinc-300", children: label }), children, hint && _jsx(Text, { size: "xs", color: "muted", children: hint })] }));
|
|
12
17
|
}
|
|
@@ -42,7 +47,7 @@ function fromDoc(doc) {
|
|
|
42
47
|
};
|
|
43
48
|
}
|
|
44
49
|
function AddressCard({ address, onEdit, onDelete, }) {
|
|
45
|
-
return (_jsxs(Div, { surface: "card", padding: "sm", className: "flex flex-col gap-2", children: [_jsxs(Row, { align: "start", justify: "between", gap: "xs", children: [_jsxs(Row, { gap: "xs", className: "min-w-0", children: [_jsx(MapPin, { className: "h-4 w-4 shrink-0 text-[var(--appkit-color-primary)]" }), _jsx(Span, { weight: "semibold", className: "text-
|
|
50
|
+
return (_jsxs(Div, { surface: "card", padding: "sm", className: "flex flex-col gap-2", children: [_jsxs(Row, { align: "start", justify: "between", gap: "xs", children: [_jsxs(Row, { gap: "xs", className: "min-w-0", children: [_jsx(MapPin, { className: "h-4 w-4 shrink-0 text-[var(--appkit-color-primary)]" }), _jsx(Span, { size: "sm", weight: "semibold", className: "text-zinc-900 dark:text-zinc-100 truncate", children: address.label }), address.isDefault && (_jsxs(Span, { size: "xs", weight: "medium", className: CLS_DEFAULT_PILL, children: [_jsx(Star, { className: "h-3 w-3" }), "Default"] }))] }), _jsxs(Row, { gap: "px", className: "shrink-0", children: [_jsx("button", { type: "button", onClick: onEdit, title: "Edit address", className: "rounded-lg p-1.5 text-zinc-500 dark:text-zinc-400 hover:bg-zinc-100 dark:hover:bg-zinc-800 hover:text-zinc-700 dark:hover:text-zinc-300 transition-colors", children: _jsx(Pencil, { className: "h-4 w-4" }) }), _jsx("button", { type: "button", onClick: onDelete, title: "Delete address", className: CLS_DELETE_BTN, children: _jsx(Trash2, { className: "h-4 w-4" }) })] })] }), _jsxs(Text, { className: "text-sm text-zinc-700 dark:text-zinc-300", children: [address.fullName, " \u00B7 ", address.phone] }), _jsxs(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 leading-relaxed", children: [address.addressLine1, address.addressLine2 ? `, ${address.addressLine2}` : "", address.landmark ? ` (near ${address.landmark})` : "", _jsx("br", {}), address.city, ", ", address.state, " ", address.postalCode, ", ", address.country] })] }));
|
|
46
51
|
}
|
|
47
52
|
// ---------------------------------------------------------------------------
|
|
48
53
|
// Main Component
|
|
@@ -134,5 +139,5 @@ export function SellerAddressesView({ apiBase = SELLER_ENDPOINTS.STORE_ADDRESSES
|
|
|
134
139
|
const handleDelete = (addr) => setDeleteTargetAddr(addr);
|
|
135
140
|
const set = (key, value) => setDraft((p) => ({ ...p, [key]: value }));
|
|
136
141
|
const handleTextField = (key) => (e) => set(key, e.target.value);
|
|
137
|
-
return (_jsxs(Div, { className: "min-h-screen", children: [_jsxs(Row, { justify: "between", className: "sticky z-10 bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-4 py-3", style: { top: "var(--header-height, 0px)" }, children: [_jsxs(Stack, { gap: "none", children: [_jsx(Heading, { level: 2, className: "text-base font-semibold text-zinc-900 dark:text-zinc-100", children: "Pickup Addresses" }), _jsx(Text, { size: "xs", color: "muted", className: "mt-0.5", children: "Manage your store's pickup and return locations" })] }), _jsxs(Button, { size: "sm", onClick: openAdd, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), _jsx(Span, { children: "Add Address" })] })] }), _jsxs(Div, { className: "py-6 px-4 sm:px-6 max-w-2xl", children: [errorMessage && (_jsx(Div, { className: "mb-4 rounded-xl border border-error/20 bg-error-surface px-4 py-3 text-sm text-error", children: errorMessage })), isLoading ? (_jsx(Row, { justify: "center", className: "py-16", children: _jsx(Div, { className: "h-6 w-6 animate-spin rounded-full border-2 border-[var(--appkit-color-primary)] border-t-transparent" }) })) : addresses.length === 0 ? (_jsxs(Div, { className: "rounded-xl border-2 border-dashed border-zinc-200 dark:border-slate-700 py-16 flex flex-col items-center gap-3", children: [_jsx(MapPin, { className: "h-8 w-8 text-zinc-300 dark:text-slate-600" }), _jsx(Text, { className: "text-sm text-zinc-500 dark:text-zinc-400", children: "No pickup addresses yet" }), _jsx(Button, { size: "sm", variant: "outline", onClick: openAdd, children: "Add your first address" })] })) : (_jsxs(_Fragment, { children: [_jsxs(Row, { justify: "end", className: "mb-2", children: [_jsx(Button, { size: "sm", variant: listView === "table" ? "primary" : "ghost", onClick: () => setListView("table"), children: "Table" }), _jsx(Button, { size: "sm", variant: listView === "cards" ? "primary" : "ghost", onClick: () => setListView("cards"), children: "Cards" })] }), listView === "cards" ? (_jsx(Grid, { gap: "sm", children: addresses.map((addr) => (_jsx(Div, { className: deletingId === addr.id ? "opacity-50 pointer-events-none" : "", children: _jsx(AddressCard, { address: addr, onEdit: () => openEdit(addr), onDelete: () => handleDelete(addr) }) }, addr.id))) })) : (_jsx(Div, { className:
|
|
142
|
+
return (_jsxs(Div, { className: "min-h-screen", children: [_jsxs(Row, { justify: "between", className: "sticky z-10 bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-4 py-3", style: { top: "var(--header-height, 0px)" }, children: [_jsxs(Stack, { gap: "none", children: [_jsx(Heading, { level: 2, className: "text-base font-semibold text-zinc-900 dark:text-zinc-100", children: "Pickup Addresses" }), _jsx(Text, { size: "xs", color: "muted", className: "mt-0.5", children: "Manage your store's pickup and return locations" })] }), _jsxs(Button, { size: "sm", onClick: openAdd, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), _jsx(Span, { children: "Add Address" })] })] }), _jsxs(Div, { className: "py-6 px-4 sm:px-6 max-w-2xl", children: [errorMessage && (_jsx(Div, { className: "mb-4 rounded-xl border border-error/20 bg-error-surface px-4 py-3 text-sm text-error", children: errorMessage })), isLoading ? (_jsx(Row, { justify: "center", className: "py-16", children: _jsx(Div, { className: "h-6 w-6 animate-spin rounded-full border-2 border-[var(--appkit-color-primary)] border-t-transparent" }) })) : addresses.length === 0 ? (_jsxs(Div, { className: "rounded-xl border-2 border-dashed border-zinc-200 dark:border-slate-700 py-16 flex flex-col items-center gap-3", children: [_jsx(MapPin, { className: "h-8 w-8 text-zinc-300 dark:text-slate-600" }), _jsx(Text, { className: "text-sm text-zinc-500 dark:text-zinc-400", children: "No pickup addresses yet" }), _jsx(Button, { size: "sm", variant: "outline", onClick: openAdd, children: "Add your first address" })] })) : (_jsxs(_Fragment, { children: [_jsxs(Row, { justify: "end", className: "mb-2", children: [_jsx(Button, { size: "sm", variant: listView === "table" ? "primary" : "ghost", onClick: () => setListView("table"), children: "Table" }), _jsx(Button, { size: "sm", variant: listView === "cards" ? "primary" : "ghost", onClick: () => setListView("cards"), children: "Cards" })] }), listView === "cards" ? (_jsx(Grid, { gap: "sm", children: addresses.map((addr) => (_jsx(Div, { className: deletingId === addr.id ? "opacity-50 pointer-events-none" : "", children: _jsx(AddressCard, { address: addr, onEdit: () => openEdit(addr), onDelete: () => handleDelete(addr) }) }, addr.id))) })) : (_jsx(Div, { className: `${__O.xAuto} rounded-lg border border-zinc-200 dark:border-slate-700`, children: _jsxs(Table, { className: "w-full text-sm", children: [_jsx(Thead, { className: "bg-zinc-50 dark:bg-slate-800", children: _jsxs(Tr, { children: [_jsx(Th, { className: "text-left px-3 py-2 font-semibold", children: "Label" }), _jsx(Th, { className: "text-left px-3 py-2 font-semibold", children: "Name" }), _jsx(Th, { className: "text-left px-3 py-2 font-semibold", children: "City" }), _jsx(Th, { className: "text-left px-3 py-2 font-semibold", children: "Phone" }), _jsx(Th, { className: "text-right px-3 py-2 font-semibold", children: "Actions" })] }) }), _jsx(Tbody, { children: addresses.map((addr) => (_jsxs(Tr, { className: `border-t border-zinc-100 dark:border-slate-700 ${deletingId === addr.id ? "opacity-50" : ""}`, children: [_jsx(Td, { className: "px-3 py-2", children: addr.label }), _jsx(Td, { className: "px-3 py-2", children: addr.fullName }), _jsxs(Td, { className: "px-3 py-2", children: [addr.city, ", ", addr.state] }), _jsx(Td, { className: "px-3 py-2 tabular-nums", children: addr.phone }), _jsx(Td, { className: "px-3 py-2 text-right", children: _jsxs(Row, { justify: "end", className: "gap-1", children: [_jsx(Button, { size: "sm", variant: "ghost", onClick: () => openEdit(addr), children: ROW_ACTION_META[ROW_ACTION_ID.EDIT].label }), _jsx(Button, { size: "sm", variant: "ghost", onClick: () => handleDelete(addr), children: ROW_ACTION_META[ROW_ACTION_ID.DELETE].label })] }) })] }, addr.id))) })] }) }))] }))] }), _jsx(SideDrawer, { isOpen: drawerOpen, onClose: closeDrawer, title: editingId ? "Edit Address" : "Add Address", footer: _jsxs(Row, { gap: "xs", children: [_jsx(Button, { variant: "outline", onClick: closeDrawer, className: "flex-1", children: "Cancel" }), _jsx(Button, { onClick: handleSave, disabled: saving, className: "flex-1", children: saving ? "Saving…" : editingId ? "Save Changes" : "Add Address" })] }), children: _jsxs(Stack, { gap: "md", className: "py-1", children: [saveError && (_jsx(Div, { className: "rounded-lg border border-error/20 bg-error-surface px-3 py-2 text-sm text-error", children: saveError })), _jsx(Field, { label: "Label *", hint: "e.g. Warehouse, Shop, Home", children: _jsx("input", { type: "text", value: draft.label, onChange: handleTextField("label"), placeholder: "Warehouse", maxLength: 60, className: INPUT_CLS }) }), _jsxs(Grid, { cols: 2, gap: "sm", children: [_jsx(Field, { label: "Full Name *", children: _jsx("input", { type: "text", value: draft.fullName, onChange: handleTextField("fullName"), placeholder: "Ravi Kumar", maxLength: 100, className: INPUT_CLS }) }), _jsx(Field, { label: "Phone *", children: _jsx("input", { type: "tel", value: draft.phone, onChange: handleTextField("phone"), placeholder: "+91 98765 43210", maxLength: 20, className: INPUT_CLS }) })] }), _jsx(Field, { label: "Address Line 1 *", children: _jsx("input", { type: "text", value: draft.addressLine1, onChange: handleTextField("addressLine1"), placeholder: "Shop 12, Main Market", maxLength: 200, className: INPUT_CLS }) }), _jsx(Field, { label: "Address Line 2", children: _jsx("input", { type: "text", value: draft.addressLine2, onChange: handleTextField("addressLine2"), placeholder: "Building / Floor (optional)", maxLength: 200, className: INPUT_CLS }) }), _jsx(Field, { label: "Landmark", children: _jsx("input", { type: "text", value: draft.landmark, onChange: handleTextField("landmark"), placeholder: "Near metro station (optional)", maxLength: 100, className: INPUT_CLS }) }), _jsxs(Grid, { cols: 2, gap: "sm", children: [_jsx(Field, { label: "City *", children: _jsx("input", { type: "text", value: draft.city, onChange: handleTextField("city"), placeholder: "Mumbai", maxLength: 100, className: INPUT_CLS }) }), _jsx(Field, { label: "State *", children: _jsx("input", { type: "text", value: draft.state, onChange: handleTextField("state"), placeholder: "Maharashtra", maxLength: 100, className: INPUT_CLS }) })] }), _jsxs(Grid, { cols: 2, gap: "sm", children: [_jsx(Field, { label: "Postal Code *", children: _jsx("input", { type: "text", value: draft.postalCode, onChange: handleTextField("postalCode"), placeholder: "400001", maxLength: 10, className: INPUT_CLS }) }), _jsx(Field, { label: "Country *", children: _jsx("input", { type: "text", value: draft.country, onChange: handleTextField("country"), placeholder: "India", maxLength: 60, className: INPUT_CLS }) })] }), _jsxs("label", { className: "flex items-center gap-3 cursor-pointer", children: [_jsx("input", { type: "checkbox", checked: draft.isDefault, onChange: (e) => set("isDefault", e.target.checked), className: "h-4 w-4 rounded border-zinc-300 dark:border-slate-600 text-[var(--appkit-color-primary)] focus:ring-[var(--appkit-color-primary)]" }), _jsx(Span, { size: "sm", className: "text-zinc-700 dark:text-zinc-300", children: "Set as default pickup address" })] })] }) }), deleteTargetAddr && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete Address", message: `Delete address "${deleteTargetAddr.label}"? This cannot be undone.`, onConfirm: () => { deleteById(deleteTargetAddr.id); setDeleteTargetAddr(null); }, onClose: () => setDeleteTargetAddr(null), isDeleting: deletingId === deleteTargetAddr.id }))] }));
|
|
138
143
|
}
|
|
@@ -5,6 +5,9 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
|
5
5
|
import { Alert, Badge, Button, Div, Form, FormActions, Heading, Input, Row, Section, Select, Text, Toggle, useToast, } from "../../../ui";
|
|
6
6
|
import { apiClient } from "../../../http";
|
|
7
7
|
import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
8
|
+
const __P = {
|
|
9
|
+
p5: "p-5",
|
|
10
|
+
};
|
|
8
11
|
// ---------------------------------------------------------------------------
|
|
9
12
|
// Config
|
|
10
13
|
// ---------------------------------------------------------------------------
|
|
@@ -50,7 +53,7 @@ function AlertCard({ alert, onToggle, onDelete, }) {
|
|
|
50
53
|
const metricLabel = METRIC_OPTIONS.find((m) => m.value === alert.metric)?.label ?? alert.metric;
|
|
51
54
|
const opLabel = OPERATOR_OPTIONS.find((o) => o.value === alert.operator)?.label ?? alert.operator;
|
|
52
55
|
const windowLabel = WINDOW_OPTIONS.find((w) => w.value === String(alert.windowHours))?.label ?? `${alert.windowHours}h`;
|
|
53
|
-
return (_jsxs(Div, { surface: "card", padding: "sm", className: "flex items-start justify-between gap-4", children: [_jsxs(
|
|
56
|
+
return (_jsxs(Div, { surface: "card", padding: "sm", className: "flex items-start justify-between gap-4", children: [_jsxs(Div, { className: "flex-1 min-w-0", children: [_jsxs(Row, { className: "gap-2 mb-1 flex-wrap", children: [_jsx(Text, { className: "font-medium text-zinc-900 dark:text-zinc-100 text-sm", children: alert.label }), _jsx(Badge, { variant: alert.isActive ? "success" : "default", children: alert.isActive ? "Active" : "Paused" })] }), _jsxs(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 mb-1", children: [metricLabel, " ", opLabel, " ", alert.threshold, " \u00B7 ", windowLabel] }), _jsx(Row, { className: "gap-1 flex-wrap", children: alert.notifyChannels.map((ch) => (_jsx(Badge, { variant: OPERATOR_BADGE[alert.operator] ?? "default", children: ch }, ch))) }), alert.lastTriggeredAt && (_jsxs(Text, { className: "text-xs text-zinc-400 dark:text-zinc-400 mt-1", children: ["Last triggered: ", new Date(alert.lastTriggeredAt).toLocaleString("en-IN")] }))] }), _jsxs(Div, { className: "flex items-center gap-2 shrink-0", children: [_jsx(Toggle, { checked: alert.isActive, onChange: (v) => onToggle(alert.id, v), size: "sm" }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => onDelete(alert.id), className: "text-error hover:text-error", children: "Delete" })] })] }));
|
|
54
57
|
}
|
|
55
58
|
const EMPTY_DRAFT = {
|
|
56
59
|
label: "",
|
|
@@ -118,7 +121,7 @@ export function SellerAnalyticsAlertsView({ labels = {}, }) {
|
|
|
118
121
|
: [...d.notifyChannels, ch],
|
|
119
122
|
}));
|
|
120
123
|
}, []);
|
|
121
|
-
return (_jsxs(
|
|
124
|
+
return (_jsxs(Div, { className: "space-y-6", children: [_jsxs(Row, { justify: "between", children: [_jsx(Heading, { level: 2, className: "text-base font-semibold text-zinc-900 dark:text-zinc-100", children: labels.title ?? "Analytics Alerts" }), _jsx(Button, { size: "sm", onClick: () => setShowForm((v) => !v), children: showForm ? "Cancel" : "+ New Alert" })] }), _jsx(Text, { className: "text-sm text-zinc-500 dark:text-zinc-400", children: "Get notified when a key metric crosses a threshold. Alerts check the metric over the selected window and fire through your chosen channels." }), showForm && (_jsxs(Section, { className: `border border-zinc-200 dark:border-zinc-700 rounded-xl ${__P.p5} space-y-4`, children: [_jsx(Heading, { level: 3, className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Create Alert" }), _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); createMutation.mutate(); }, children: [_jsxs(Div, { className: "grid sm:grid-cols-2 gap-4", children: [_jsx(Input, { label: "Alert label", value: draft.label, onChange: (e) => setDraft((d) => ({ ...d, label: e.target.value })), placeholder: "e.g. Low daily orders", required: true }), _jsx(Select, { label: "Metric", value: draft.metric, onValueChange: (v) => setDraft((d) => ({ ...d, metric: v })), options: METRIC_OPTIONS }), _jsx(Select, { label: "Operator", value: draft.operator, onValueChange: (v) => setDraft((d) => ({ ...d, operator: v })), options: OPERATOR_OPTIONS }), _jsx(Input, { label: "Threshold", type: "number", value: draft.threshold, onChange: (e) => setDraft((d) => ({ ...d, threshold: e.target.value })), placeholder: "e.g. 10", required: true }), _jsx(Select, { label: "Check window", value: draft.windowHours, onValueChange: (v) => setDraft((d) => ({ ...d, windowHours: v })), options: WINDOW_OPTIONS })] }), _jsxs(Div, { className: "mt-3", children: [_jsx(Text, { className: "text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-2", children: "Notify via" }), _jsx(Row, { className: "gap-2 flex-wrap", children: CHANNEL_OPTIONS.map((ch) => (_jsx("button", { type: "button", onClick: () => toggleChannel(ch.value), className: `px-3 py-1.5 rounded-full text-xs border transition-colors ${draft.notifyChannels.includes(ch.value)
|
|
122
125
|
? "bg-[var(--appkit-color-primary)] text-white border-transparent"
|
|
123
|
-
: "bg-white dark:bg-zinc-800 text-zinc-700 dark:text-zinc-300 border-zinc-200 dark:border-zinc-700"}`, children: ch.label }, ch.value))) })] }), _jsx(FormActions, { align: "right", className: "mt-4", children: _jsx(Button, { type: "submit", isLoading: createMutation.isPending, children: createMutation.isPending ? "Creating…" : "Create Alert" }) })] })] })), isLoading && (_jsx(
|
|
126
|
+
: "bg-white dark:bg-zinc-800 text-zinc-700 dark:text-zinc-300 border-zinc-200 dark:border-zinc-700"}`, children: ch.label }, ch.value))) })] }), _jsx(FormActions, { align: "right", className: "mt-4", children: _jsx(Button, { type: "submit", isLoading: createMutation.isPending, children: createMutation.isPending ? "Creating…" : "Create Alert" }) })] })] })), isLoading && (_jsx(Div, { className: "space-y-2", children: [1, 2, 3].map((i) => (_jsx(Div, { className: "h-16 rounded-lg bg-zinc-100 dark:bg-zinc-800 animate-pulse" }, i))) })), !isLoading && alerts.length === 0 && !showForm && (_jsx(Alert, { variant: "info", children: "No alerts configured. Create an alert to get notified when a key metric crosses a threshold." })), !isLoading && alerts.length > 0 && (_jsx(Div, { className: "space-y-3", children: alerts.map((alert) => (_jsx(AlertCard, { alert: alert, onToggle: (id, isActive) => toggleMutation.mutate({ id, isActive }), onDelete: (id) => deleteMutation.mutate(id) }, alert.id))) }))] }));
|
|
124
127
|
}
|