@mohasinac/appkit 2.7.56 → 2.7.58
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/layout/DashboardLayoutClient.d.ts +7 -1
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +8 -2
- package/dist/_internal/shared/actions/action-registry.js +31 -5
- package/dist/client.d.ts +2 -4
- package/dist/client.js +2 -3
- package/dist/configs/tailwind.d.ts +16 -3
- package/dist/configs/tailwind.js +18 -5
- package/dist/constants/field-names.d.ts +3 -0
- package/dist/constants/field-names.js +3 -0
- package/dist/features/about/components/FAQPageView.js +2 -2
- package/dist/features/about/components/FeesView.js +1 -1
- package/dist/features/about/components/PolicyPageView.js +1 -1
- package/dist/features/about/components/PublicProfileView.js +1 -1
- package/dist/features/account/components/AddressBook.js +1 -1
- package/dist/features/account/components/AddressesIndexListing.js +1 -1
- package/dist/features/account/components/BuyerAccountGuideView.js +7 -7
- package/dist/features/account/components/BuyerAuctionsGuideView.js +7 -7
- package/dist/features/account/components/BuyerOrdersGuideView.js +6 -6
- package/dist/features/account/components/BuyerShoppingGuideView.js +7 -7
- package/dist/features/account/components/MessagesView.js +1 -1
- package/dist/features/account/components/NotificationPreferencesPanel.js +12 -3
- package/dist/features/account/components/UserOffersPanel.js +2 -2
- package/dist/features/account/components/UserSidebar.js +3 -3
- package/dist/features/account/components/UserSupportView.js +5 -5
- package/dist/features/admin/components/AdminAdsView.js +1 -1
- package/dist/features/admin/components/AdminAllEventEntriesView.js +2 -2
- package/dist/features/admin/components/AdminAnalyticsGuideView.js +3 -3
- package/dist/features/admin/components/AdminBidsView.js +6 -2
- package/dist/features/admin/components/AdminBlogView.js +7 -2
- package/dist/features/admin/components/AdminBrandsView.js +7 -2
- package/dist/features/admin/components/AdminBundleEditorView.js +13 -9
- package/dist/features/admin/components/AdminBundlesView.js +4 -2
- package/dist/features/admin/components/AdminCarouselEditorView.js +7 -8
- package/dist/features/admin/components/AdminCarouselView.js +6 -4
- package/dist/features/admin/components/AdminCartsView.js +1 -1
- package/dist/features/admin/components/AdminCatalogGuideView.js +5 -5
- package/dist/features/admin/components/AdminCategoriesView.js +7 -2
- package/dist/features/admin/components/AdminContactEditorView.js +2 -2
- package/dist/features/admin/components/AdminContactView.js +4 -2
- package/dist/features/admin/components/AdminContentGuideView.js +6 -6
- package/dist/features/admin/components/AdminCouponsView.js +4 -2
- package/dist/features/admin/components/AdminEmployeeEditorView.js +1 -1
- package/dist/features/admin/components/AdminFaqsView.js +4 -2
- package/dist/features/admin/components/AdminFeatureFlagsView.js +1 -1
- package/dist/features/admin/components/AdminFeaturesView.js +5 -1
- package/dist/features/admin/components/AdminGuideHubView.js +1 -1
- package/dist/features/admin/components/AdminHistoryView.js +1 -1
- package/dist/features/admin/components/AdminListingScaffold.js +1 -1
- package/dist/features/admin/components/AdminMediaView.js +10 -5
- package/dist/features/admin/components/AdminNavigationView.js +1 -1
- package/dist/features/admin/components/AdminNewsletterView.js +4 -2
- package/dist/features/admin/components/AdminNotificationsView.js +7 -2
- package/dist/features/admin/components/AdminOrdersGuideView.js +5 -5
- package/dist/features/admin/components/AdminOrdersView.js +11 -2
- package/dist/features/admin/components/AdminPayoutsView.js +6 -2
- package/dist/features/admin/components/AdminPrizeDrawsView.js +4 -0
- package/dist/features/admin/components/AdminProductsView.js +14 -2
- package/dist/features/admin/components/AdminReturnRequestsView.js +1 -1
- package/dist/features/admin/components/AdminReviewsView.js +7 -2
- package/dist/features/admin/components/AdminScammerEditorView.js +3 -3
- package/dist/features/admin/components/AdminScammersView.js +5 -5
- package/dist/features/admin/components/AdminSectionsView.js +2 -2
- package/dist/features/admin/components/AdminSessionsView.js +6 -2
- package/dist/features/admin/components/AdminSidebar.js +3 -3
- package/dist/features/admin/components/AdminSiteSettingsView.js +1 -1
- package/dist/features/admin/components/AdminStoreAddressesView.js +1 -1
- package/dist/features/admin/components/AdminStoreEditorView.js +1 -1
- package/dist/features/admin/components/AdminStoresGuideView.js +6 -6
- package/dist/features/admin/components/AdminStoresView.js +7 -2
- package/dist/features/admin/components/AdminSublistingCategoriesView.js +3 -1
- package/dist/features/admin/components/AdminSupportTicketDetailView.js +4 -4
- package/dist/features/admin/components/AdminSupportTicketsView.js +8 -8
- package/dist/features/admin/components/AdminTeamGuideView.js +4 -4
- package/dist/features/admin/components/AdminTeamView.js +4 -2
- package/dist/features/admin/components/AdminTrustGuideView.js +5 -5
- package/dist/features/admin/components/AdminUserEditorView.js +2 -2
- package/dist/features/admin/components/AdminUsersGuideView.js +5 -5
- package/dist/features/admin/components/AdminUsersView.js +6 -2
- package/dist/features/admin/components/AdminViewCards.js +3 -3
- package/dist/features/admin/components/AdminWishlistsView.js +1 -1
- package/dist/features/admin/components/DataTable.js +1 -1
- package/dist/features/admin/constants/filter-tabs.d.ts +9 -0
- package/dist/features/admin/constants/filter-tabs.js +3 -0
- package/dist/features/auctions/components/AuctionBidsTable.js +1 -1
- package/dist/features/auctions/components/AuctionBottomActions.d.ts +7 -0
- package/dist/features/auctions/components/AuctionBottomActions.js +24 -0
- package/dist/features/auctions/components/AuctionDetailPageView.js +7 -7
- package/dist/features/auctions/components/AuctionsListView.js +1 -1
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +2 -2
- package/dist/features/auctions/components/MarketplaceAuctionGrid.js +1 -1
- package/dist/features/auctions/components/PlaceBidFormClient.js +1 -1
- package/dist/features/auth/components/LoginForm.js +1 -1
- package/dist/features/auth/components/VerifyEmailView.js +2 -2
- package/dist/features/before-after/components/BeforeAfterGallery.js +1 -1
- package/dist/features/blog/components/BlogFeaturedCard.js +1 -1
- package/dist/features/blog/components/BlogIndexListing.js +1 -1
- package/dist/features/blog/components/BlogListView.js +2 -2
- package/dist/features/blog/components/BlogPostView.js +8 -8
- package/dist/features/cart/components/CartDrawer.js +2 -2
- package/dist/features/cart/repository/cart.repository.js +11 -4
- package/dist/features/cart/schemas/firestore.d.ts +3 -0
- package/dist/features/categories/components/BrandDetailPageView.js +1 -1
- package/dist/features/categories/components/CategoriesIndexListing.js +1 -1
- package/dist/features/categories/components/CategoryDetailPageView.js +39 -3
- package/dist/features/categories/components/CategoryDetailTabs.d.ts +4 -1
- package/dist/features/categories/components/CategoryDetailTabs.js +7 -2
- package/dist/features/categories/components/CategoryGrid.js +1 -1
- package/dist/features/categories/components/CategoryProductsView.js +1 -1
- package/dist/features/categories/components/CategoryStoresListing.d.ts +5 -0
- package/dist/features/categories/components/CategoryStoresListing.js +11 -0
- package/dist/features/categories/components/CategoryTableColumns.js +2 -2
- package/dist/features/categories/components/CategoryTree.js +1 -1
- package/dist/features/categories/components/index.d.ts +2 -0
- package/dist/features/categories/components/index.js +1 -0
- package/dist/features/checkout/components/CheckoutStepper.js +2 -2
- package/dist/features/classified/components/ClassifiedIndexListing.js +2 -0
- package/dist/features/classified/components/ClassifiedListView.js +1 -1
- package/dist/features/collections/components/CollectionCard.js +1 -1
- package/dist/features/contact/components/ContactInfoSidebar.js +1 -1
- package/dist/features/copilot/components/AdminCopilotView.js +2 -2
- package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +2 -0
- package/dist/features/digital-codes/components/DigitalCodesListView.js +1 -1
- package/dist/features/events/components/AdminEventsView.js +5 -1
- package/dist/features/events/components/EventCard.js +1 -1
- package/dist/features/events/components/EventPollWidget.js +3 -3
- package/dist/features/events/components/EventStatusBadge.js +5 -5
- package/dist/features/events/components/EventsIndexListing.js +1 -1
- package/dist/features/events/components/EventsListView.js +2 -2
- package/dist/features/events/components/SpinWheelView.js +5 -3
- package/dist/features/faq/components/FAQAccordion.js +2 -2
- package/dist/features/filters/AsyncFacetSection.js +3 -3
- package/dist/features/filters/FilterFacetSection.js +5 -5
- package/dist/features/filters/RangeFilter.js +1 -1
- package/dist/features/forms/Input.js +5 -5
- package/dist/features/forms/Select.js +3 -3
- package/dist/features/forms/Slider.js +1 -1
- package/dist/features/forms/Textarea.js +3 -3
- package/dist/features/forms/utils.d.ts +2 -2
- package/dist/features/forms/utils.js +2 -2
- package/dist/features/history/hooks/useHistory.js +23 -10
- package/dist/features/homepage/components/AdvertisementBanner.js +2 -2
- package/dist/features/homepage/components/CharacterHotspotForm.js +2 -2
- package/dist/features/homepage/components/FeaturedResultsSection.js +1 -1
- package/dist/features/homepage/components/HeroSection.js +1 -1
- package/dist/features/homepage/components/NewsletterSection.js +1 -1
- package/dist/features/homepage/components/SectionCarousel.js +1 -1
- package/dist/features/layout/BottomActions.js +2 -2
- package/dist/features/layout/ListingLayout.js +3 -3
- package/dist/features/layout/TitleBarLayout.js +1 -1
- package/dist/features/live/components/LiveItemsIndexListing.js +2 -0
- package/dist/features/live/components/LiveItemsListView.js +1 -1
- package/dist/features/media/index.d.ts +2 -0
- package/dist/features/media/index.js +1 -0
- package/dist/features/media/modals/ImageCropModal.js +1 -1
- package/dist/features/media/modals/ImageEditor.d.ts +12 -0
- package/dist/features/media/modals/ImageEditor.js +73 -0
- package/dist/features/media/upload/ImageUpload.d.ts +5 -1
- package/dist/features/media/upload/ImageUpload.js +33 -8
- package/dist/features/media/upload/MediaUploadField.d.ts +5 -1
- package/dist/features/media/upload/MediaUploadField.js +26 -12
- package/dist/features/orders/components/OrdersList.js +12 -12
- package/dist/features/orders/components/RefundHistoryTable.js +2 -2
- package/dist/features/orders/components/RefundRequestView.js +3 -3
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +1 -1
- package/dist/features/pre-orders/components/PreOrderActionsClient.js +1 -1
- package/dist/features/pre-orders/components/PreOrderBadge.js +5 -5
- package/dist/features/pre-orders/components/PreOrderBottomActions.d.ts +5 -0
- package/dist/features/pre-orders/components/PreOrderBottomActions.js +22 -0
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +5 -5
- package/dist/features/pre-orders/components/PreOrdersIndexListing.js +47 -0
- package/dist/features/pre-orders/components/PreOrdersListView.js +1 -1
- package/dist/features/pre-orders/components/PreorderCard.js +3 -3
- package/dist/features/products/components/AuctionsIndexListing.js +23 -0
- package/dist/features/products/components/BidHistory.js +2 -2
- package/dist/features/products/components/CompareOverlay.js +1 -1
- package/dist/features/products/components/CustomFieldsEditor.js +1 -1
- package/dist/features/products/components/CustomSectionTabContent.js +1 -1
- package/dist/features/products/components/CustomSectionsEditor.js +1 -1
- package/dist/features/products/components/GroupSettingsPanel.js +2 -2
- package/dist/features/products/components/MakeOfferButton.js +2 -2
- package/dist/features/products/components/PrizeDrawBottomActions.d.ts +6 -0
- package/dist/features/products/components/PrizeDrawBottomActions.js +24 -0
- package/dist/features/products/components/PrizeDrawDetailPageView.js +5 -7
- package/dist/features/products/components/PrizeDrawEntryActions.js +5 -18
- package/dist/features/products/components/PrizeDrawItemsEditor.js +3 -3
- package/dist/features/products/components/PrizeRevealModal.js +7 -4
- package/dist/features/products/components/ProductDetailActions.d.ts +6 -1
- package/dist/features/products/components/ProductDetailActions.js +36 -6
- package/dist/features/products/components/ProductDetailPageView.js +19 -18
- package/dist/features/products/components/ProductFeaturesSelector.js +1 -1
- package/dist/features/products/components/ProductGalleryClient.js +1 -1
- package/dist/features/products/components/ProductGrid.js +8 -8
- package/dist/features/products/components/ProductTabs.js +1 -1
- package/dist/features/products/components/ProductTabsShell.js +1 -1
- package/dist/features/products/components/ProductsIndexListing.js +47 -0
- package/dist/features/products/components/RelatedProducts.js +1 -1
- package/dist/features/products/components/ShowGroupSection.js +1 -1
- package/dist/features/products/components/SublistingCarouselSection.js +1 -1
- package/dist/features/products/components/SublistingCategorySelect.js +1 -1
- package/dist/features/products/components/index.d.ts +0 -2
- package/dist/features/products/components/index.js +0 -1
- package/dist/features/products/constants/action-defs.d.ts +7 -0
- package/dist/features/products/constants/action-defs.js +14 -0
- package/dist/features/products/constants/listing-tabs.d.ts +6 -0
- package/dist/features/products/constants/listing-tabs.js +1 -0
- package/dist/features/promotions/components/CouponCard.js +3 -3
- package/dist/features/promotions/components/CouponsIndexListing.js +2 -2
- package/dist/features/promotions/components/PromotionsView.js +1 -1
- package/dist/features/reviews/components/ReviewDetailPageView.js +1 -1
- package/dist/features/reviews/components/ReviewDetailShell.js +4 -4
- package/dist/features/reviews/components/ReviewModal.js +2 -2
- package/dist/features/reviews/components/ReviewSummary.js +1 -1
- package/dist/features/reviews/components/ReviewsIndexListing.js +1 -1
- package/dist/features/reviews/components/ReviewsList.js +1 -1
- package/dist/features/seller/components/SellerAddressesView.js +4 -3
- package/dist/features/seller/components/SellerAnalyticsAlertsView.js +2 -2
- package/dist/features/seller/components/SellerAuctionsView.js +11 -4
- package/dist/features/seller/components/SellerBidsView.js +22 -7
- package/dist/features/seller/components/SellerBundlesView.js +11 -4
- package/dist/features/seller/components/SellerClassifiedView.js +12 -5
- package/dist/features/seller/components/SellerCouponEditorView.js +2 -2
- package/dist/features/seller/components/SellerCouponsView.js +13 -4
- package/dist/features/seller/components/SellerDigitalCodesView.js +11 -4
- package/dist/features/seller/components/SellerFeaturesView.js +1 -1
- package/dist/features/seller/components/SellerGoogleReviewsView.js +10 -5
- package/dist/features/seller/components/SellerGroupedListingsView.js +2 -0
- package/dist/features/seller/components/SellerLiveView.js +13 -6
- package/dist/features/seller/components/SellerOffersPanel.js +2 -2
- package/dist/features/seller/components/SellerOffersView.js +2 -2
- package/dist/features/seller/components/SellerOrdersView.js +41 -18
- package/dist/features/seller/components/SellerPayoutMethodsView.js +14 -5
- package/dist/features/seller/components/SellerPayoutsView.js +2 -2
- package/dist/features/seller/components/SellerPreOrdersView.js +7 -2
- package/dist/features/seller/components/SellerPrizeDrawsView.js +7 -2
- package/dist/features/seller/components/SellerProductShell.js +27 -9
- package/dist/features/seller/components/SellerProductsCards.js +2 -1
- package/dist/features/seller/components/SellerProductsView.js +22 -9
- package/dist/features/seller/components/SellerReviewsView.js +9 -1
- package/dist/features/seller/components/SellerShippingConfigsView.js +15 -6
- package/dist/features/seller/components/SellerSidebar.js +2 -2
- package/dist/features/seller/components/SellerStoreCategoriesView.js +11 -4
- package/dist/features/seller/components/SellerTemplatesView.js +20 -7
- package/dist/features/seller/components/analytics/SellerTopProducts.js +1 -1
- package/dist/features/shell/StepForm.js +9 -3
- package/dist/features/site-settings/components/ActionPermissionsManager.js +1 -1
- package/dist/features/site-settings/components/NavPermissionsManager.js +1 -1
- package/dist/features/stores/components/InteractiveStoreCard.js +1 -1
- package/dist/features/stores/components/StoreDetailLayoutView.js +1 -1
- package/dist/features/stores/components/StoreFinanceGuideView.js +2 -2
- package/dist/features/stores/components/StoreHeader.js +1 -1
- package/dist/features/stores/components/StoreListingsGuideView.js +3 -3
- package/dist/features/stores/components/StoreOrdersGuideView.js +4 -4
- package/dist/features/stores/components/StoreReviewsListing.js +1 -1
- package/dist/features/stores/components/StoreSettingsGuideView.js +2 -2
- package/dist/features/stores/components/StoresIndexListing.js +17 -1
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +4 -4
- package/dist/features/wishlist/components/WishlistPage.js +3 -3
- package/dist/features/wishlist/hooks/useWishlistToggle.js +6 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.js +9 -3
- package/dist/react/hooks/use-action-dispatch.d.ts +5 -0
- package/dist/react/hooks/use-action-dispatch.js +10 -0
- package/dist/seed/cart-seed-data.js +50 -3
- package/dist/seed/categories-seed-data.js +80 -16
- package/dist/seed/index.d.ts +3 -0
- package/dist/seed/index.js +3 -0
- package/dist/seed/manifest.js +15 -1
- package/dist/seed/products-classifieds-seed-data.d.ts +10 -0
- package/dist/seed/products-classifieds-seed-data.js +197 -0
- package/dist/seed/products-digital-codes-seed-data.d.ts +10 -0
- package/dist/seed/products-digital-codes-seed-data.js +204 -0
- package/dist/seed/products-live-items-seed-data.d.ts +13 -0
- package/dist/seed/products-live-items-seed-data.js +190 -0
- package/dist/styles.css +301 -3
- package/dist/tailwind-utilities.css +1 -1
- package/dist/tokens/index.d.ts +3 -3
- package/dist/tokens/index.js +3 -3
- package/dist/tokens/motion.d.ts +162 -0
- package/dist/tokens/motion.js +89 -0
- package/dist/ui/DataTable.js +6 -5
- package/dist/ui/components/Accordion.js +2 -1
- package/dist/ui/components/Button.style.css +15 -0
- package/dist/ui/components/Card.d.ts +5 -2
- package/dist/ui/components/Card.js +29 -11
- package/dist/ui/components/Div.d.ts +2 -16
- package/dist/ui/components/Div.js +2 -16
- package/dist/ui/components/Input.js +1 -1
- package/dist/ui/components/Layout.d.ts +9 -19
- package/dist/ui/components/Layout.js +9 -7
- package/dist/ui/components/ListingToolbar.js +1 -1
- package/dist/ui/components/Modal.js +7 -4
- package/dist/ui/components/Motion.d.ts +75 -0
- package/dist/ui/components/Motion.js +122 -0
- package/dist/ui/components/Select.js +1 -1
- package/dist/ui/components/Semantic.d.ts +81 -14
- package/dist/ui/components/Semantic.js +75 -10
- package/dist/ui/components/Semantic.style.css +261 -2
- package/dist/ui/components/SideDrawer.d.ts +1 -1
- package/dist/ui/components/SideDrawer.js +8 -6
- package/dist/ui/components/SideModal.d.ts +1 -1
- package/dist/ui/components/SideModal.js +11 -9
- package/dist/ui/components/StackedViewShell.js +6 -1
- package/dist/ui/components/StatsGrid.js +1 -1
- package/dist/ui/components/Toast.js +5 -2
- package/dist/ui/components/Typography.d.ts +44 -3
- package/dist/ui/components/Typography.js +15 -30
- package/dist/ui/components/Typography.style.css +24 -0
- package/dist/ui/components/VacationBanner.js +2 -1
- package/dist/ui/components/surface-tokens.d.ts +70 -0
- package/dist/ui/components/surface-tokens.js +68 -0
- package/dist/ui/forms/FormShell.d.ts +6 -1
- package/dist/ui/forms/FormShell.js +32 -4
- package/dist/ui/index.d.ts +9 -6
- package/dist/ui/index.js +4 -4
- package/dist/validation/schemas.d.ts +28 -28
- package/package.json +3 -1
- package/dist/_internal/client/features/seller/print-center/InventoryLabel.d.ts +0 -12
- package/dist/_internal/client/features/seller/print-center/InventoryLabel.js +0 -49
- package/dist/_internal/client/features/seller/print-center/LabelDesignPicker.d.ts +0 -7
- package/dist/_internal/client/features/seller/print-center/LabelDesignPicker.js +0 -32
- package/dist/_internal/client/features/seller/print-center/OrderPackingLabel.d.ts +0 -28
- package/dist/_internal/client/features/seller/print-center/OrderPackingLabel.js +0 -33
- package/dist/_internal/client/features/seller/print-center/PhysicalLocationModal.d.ts +0 -12
- package/dist/_internal/client/features/seller/print-center/PhysicalLocationModal.js +0 -30
- package/dist/_internal/client/features/seller/print-center/PrintCenterView.d.ts +0 -12
- package/dist/_internal/client/features/seller/print-center/PrintCenterView.js +0 -102
- package/dist/_internal/client/features/seller/print-center/PrintGrid.d.ts +0 -12
- package/dist/_internal/client/features/seller/print-center/PrintGrid.js +0 -13
- package/dist/_internal/client/features/seller/print-center/StoreCard.d.ts +0 -19
- package/dist/_internal/client/features/seller/print-center/StoreCard.js +0 -30
- package/dist/_internal/client/features/seller/print-center/WebsiteCard.d.ts +0 -11
- package/dist/_internal/client/features/seller/print-center/WebsiteCard.js +0 -25
- package/dist/_internal/client/features/seller/print-center/index.d.ts +0 -11
- package/dist/_internal/client/features/seller/print-center/index.js +0 -10
- package/dist/_internal/client/features/seller/print-center/types.d.ts +0 -20
- package/dist/_internal/client/features/seller/print-center/types.js +0 -20
- package/dist/_internal/client/features/seller/print-center/useInventoryPdf.d.ts +0 -18
- package/dist/_internal/client/features/seller/print-center/useInventoryPdf.js +0 -76
- package/dist/features/account/repository/address.repository.d.ts +0 -17
- package/dist/features/account/repository/address.repository.js +0 -184
- package/dist/features/auctions/components/AuctionCard.d.ts +0 -29
- package/dist/features/auctions/components/AuctionCard.js +0 -38
- package/dist/features/categories/components/BundleAddToCartCta.d.ts +0 -16
- package/dist/features/categories/components/BundleAddToCartCta.js +0 -54
- package/dist/features/categories/components/CategoriesListView.d.ts +0 -31
- package/dist/features/categories/components/CategoriesListView.js +0 -27
- package/dist/features/products/components/AuctionsView.d.ts +0 -6
- package/dist/features/products/components/AuctionsView.js +0 -5
- package/dist/features/products/components/BuyBar.d.ts +0 -21
- package/dist/features/products/components/BuyBar.js +0 -19
- package/dist/features/products/components/PreOrdersView.d.ts +0 -6
- package/dist/features/products/components/PreOrdersView.js +0 -5
- package/dist/features/reviews/components/ReviewsListView.d.ts +0 -31
- package/dist/features/reviews/components/ReviewsListView.js +0 -16
- package/dist/features/stores/components/StoresListView.d.ts +0 -19
- package/dist/features/stores/components/StoresListView.js +0 -25
- package/dist/features/stores/repository/store-address.repository.d.ts +0 -55
- package/dist/features/stores/repository/store-address.repository.js +0 -187
- package/dist/ui/components/BulkActionsBar.d.ts +0 -18
- package/dist/ui/components/BulkActionsBar.js +0 -25
- package/dist/ui/components/CollageLightbox.d.ts +0 -18
- package/dist/ui/components/CollageLightbox.js +0 -41
- package/dist/ui/components/StickyBottomBar.d.ts +0 -22
- package/dist/ui/components/StickyBottomBar.js +0 -20
|
@@ -5,7 +5,7 @@ import { X, Eye, Printer, MapPin, Truck } from "lucide-react";
|
|
|
5
5
|
import { useUrlTable } from "../../../react/hooks/useUrlTable";
|
|
6
6
|
import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
|
|
7
7
|
import { useActionDispatch } from "../../../react/hooks/use-action-dispatch";
|
|
8
|
-
import { BulkActionBar, Badge, Button, Div, FilterChipGroup, Heading, Input, ListingToolbar, Pagination, ListingViewShell, Select, SideDrawer, Stack, Text } from "../../../ui";
|
|
8
|
+
import { BulkActionBar, Badge, Button, Div, FilterChipGroup, Heading, Input, ListingToolbar, Pagination, ListingViewShell, Select, SideDrawer, Stack, Text, useToast } from "../../../ui";
|
|
9
9
|
import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
10
10
|
import { SELLER_ORDER_STATUS_TABS } from "../../admin/constants/filter-tabs";
|
|
11
11
|
import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
|
|
@@ -13,6 +13,7 @@ import { PhysicalLocationModal } from "./PhysicalLocationModal";
|
|
|
13
13
|
import { ROUTES } from "../../../constants";
|
|
14
14
|
import { toRecordArray, toRelativeDate, toRupees, toStringValue, useSellerListingData, } from "../hooks/useSellerListingData";
|
|
15
15
|
import { DataTable } from "../../admin/components/DataTable";
|
|
16
|
+
import { useBottomActions } from "../../layout";
|
|
16
17
|
// ---------------------------------------------------------------------------
|
|
17
18
|
// Config
|
|
18
19
|
// ---------------------------------------------------------------------------
|
|
@@ -109,7 +110,7 @@ function OrderDetailDrawer({ orderId, apiBase, onClose, }) {
|
|
|
109
110
|
};
|
|
110
111
|
const addr = order?.shippingAddress ?? {};
|
|
111
112
|
const addrLine = [addr.addressLine1, addr.city, addr.state, addr.pincode].filter(Boolean).join(", ");
|
|
112
|
-
return (_jsxs(SideDrawer, { isOpen: true, title: `Order ${order?.id ?? orderId}`, onClose: onClose, children: [loading && (_jsx(Div, { className: "flex items-center justify-center py-16", children: _jsx("div", { className: "h-6 w-6 animate-spin rounded-full border-2 border-[var(--appkit-color-primary)] border-t-transparent" }) })), fetchError && (_jsx(Div, { className: "mx-4 mt-4 rounded-lg border border-red-200 bg-
|
|
113
|
+
return (_jsxs(SideDrawer, { isOpen: true, title: `Order ${order?.id ?? orderId}`, onClose: onClose, children: [loading && (_jsx(Div, { className: "flex items-center justify-center py-16", children: _jsx("div", { className: "h-6 w-6 animate-spin rounded-full border-2 border-[var(--appkit-color-primary)] border-t-transparent" }) })), fetchError && (_jsx(Div, { className: "mx-4 mt-4 rounded-lg border border-red-200 bg-error-surface dark:border-red-900/60 px-4 py-3 text-sm text-error", children: fetchError })), order && !loading && (_jsxs(Stack, { gap: "none", className: "flex flex-col", children: [_jsxs("div", { className: "flex-1 overflow-y-auto px-4 py-4 space-y-5", children: [_jsxs(Div, { className: "flex items-center justify-between", children: [_jsx(Badge, { variant: STATUS_BADGE_VARIANT[order.status?.toUpperCase()] ?? "default", children: order.status ?? "Unknown" }), _jsx(Text, { size: "sm", className: "text-[var(--appkit-color-text-secondary)]", children: toRelativeDate(order.createdAt) })] }), (order.items ?? []).length > 0 && (_jsxs(Div, { children: [_jsx(Text, { size: "sm", className: "font-semibold text-[var(--appkit-color-text-primary)] mb-2", children: "Items" }), _jsx("div", { className: "divide-y divide-[var(--appkit-color-border)] dark:divide-slate-700 rounded-lg border border-[var(--appkit-color-border)] dark:border-slate-700", children: (order.items ?? []).map((item, i) => (_jsxs("div", { className: "flex items-center justify-between px-3 py-2.5 gap-3", children: [_jsxs("div", { className: "min-w-0", children: [_jsx(Text, { size: "sm", className: "font-medium truncate", children: item.title ?? item.productId ?? "Item" }), _jsxs(Text, { size: "xs", className: "text-[var(--appkit-color-text-secondary)]", children: ["Qty: ", item.quantity ?? 1] })] }), _jsx(Text, { size: "sm", className: "shrink-0 font-medium", children: toRupees(item.price ?? 0) })] }, i))) })] })), _jsxs(Div, { className: "flex items-center justify-between rounded-lg bg-zinc-50 dark:bg-slate-800/60 px-4 py-3", children: [_jsx(Text, { size: "sm", className: "font-semibold", children: "Total" }), _jsx(Text, { size: "sm", className: "font-bold text-[var(--appkit-color-primary)]", children: toRupees(order.totalAmount ?? 0) })] }), addrLine && (_jsxs(Div, { children: [_jsx(Text, { size: "sm", className: "font-semibold mb-1", children: "Shipping address" }), _jsx(Text, { size: "sm", className: "text-[var(--appkit-color-text-secondary)]", children: [String(addr.fullName ?? ""), addrLine].filter(Boolean).join(" · ") })] })), order.paymentMethod && (_jsxs(Div, { children: [_jsx(Text, { size: "sm", className: "font-semibold mb-1", children: "Payment" }), _jsx(Text, { size: "sm", className: "text-[var(--appkit-color-text-secondary)] capitalize", children: order.paymentMethod })] })), _jsxs("div", { className: "border-t border-[var(--appkit-color-border)] dark:border-slate-700 pt-4 space-y-3", children: [_jsx(Heading, { level: 4, className: "text-sm font-semibold", children: "Update order" }), _jsx(Select, { label: "New status", value: newStatus, options: UPDATE_STATUS_OPTIONS, onChange: (e) => setNewStatus(e.target.value) }), _jsx(Input, { label: "Tracking number", value: trackingNumber, onChange: (e) => setTrackingNumber(e.target.value), placeholder: "e.g. 12345678901234" }), _jsx(Input, { label: "Carrier", value: carrier, onChange: (e) => setCarrier(e.target.value), placeholder: "e.g. Delhivery, Bluedart" }), _jsx(Input, { label: "Tracking URL (optional)", value: trackingUrl, onChange: (e) => setTrackingUrl(e.target.value), placeholder: "https://...", type: "url" }), saveError && (_jsx(Div, { className: "rounded-lg border border-red-200 bg-error-surface dark:border-red-900/60 px-3 py-2 text-xs text-error", children: saveError }))] })] }), _jsxs("div", { className: "border-t border-[var(--appkit-color-border)] dark:border-slate-700 px-4 py-3.5 flex items-center justify-end gap-3", children: [_jsx(Button, { variant: "outline", onClick: onClose, disabled: saving, children: "Close" }), _jsx(Button, { onClick: handleSave, isLoading: saving, disabled: saving, children: "Save" })] })] }))] }));
|
|
113
114
|
}
|
|
114
115
|
// ---------------------------------------------------------------------------
|
|
115
116
|
// Main view
|
|
@@ -120,6 +121,7 @@ export function SellerOrdersView({ orderDetailApiBase = SELLER_ENDPOINTS.ORDERS,
|
|
|
120
121
|
const [selectedOrderId, setSelectedOrderId] = useState(null);
|
|
121
122
|
const [setLocationOpen, setSetLocationOpen] = useState(false);
|
|
122
123
|
const dispatch = useActionDispatch();
|
|
124
|
+
const { showToast } = useToast();
|
|
123
125
|
const table = useUrlTable({ defaults: { pageSize: String(PAGE_SIZE), sort: DEFAULT_SORT } });
|
|
124
126
|
const [searchInput, setSearchInput] = useState(table.get("q") || "");
|
|
125
127
|
const [filterOpen, setFilterOpen] = useState(false);
|
|
@@ -201,7 +203,7 @@ export function SellerOrdersView({ orderDetailApiBase = SELLER_ENDPOINTS.ORDERS,
|
|
|
201
203
|
key: "physicalLocation",
|
|
202
204
|
header: "Staging",
|
|
203
205
|
className: "w-28",
|
|
204
|
-
render: (row) => row.physicalLocation ? (_jsxs("span", { className: "text-xs font-mono text-zinc-500 dark:text-zinc-400", children: [row.physicalLocation.zone, "/", row.physicalLocation.shelf, "/", row.physicalLocation.bin] })) : (_jsx("span", { className: "text-xs text-zinc-400 dark:text-zinc-
|
|
206
|
+
render: (row) => row.physicalLocation ? (_jsxs("span", { className: "text-xs font-mono text-zinc-500 dark:text-zinc-400", children: [row.physicalLocation.zone, "/", row.physicalLocation.shelf, "/", row.physicalLocation.bin] })) : (_jsx("span", { className: "text-xs text-zinc-400 dark:text-zinc-400", children: "\u2014" })),
|
|
205
207
|
},
|
|
206
208
|
{
|
|
207
209
|
key: "shipping",
|
|
@@ -251,24 +253,44 @@ export function SellerOrdersView({ orderDetailApiBase = SELLER_ENDPOINTS.ORDERS,
|
|
|
251
253
|
});
|
|
252
254
|
}, [selection.selectedIds, dispatch]);
|
|
253
255
|
const handleSetLocation = useCallback(async (loc) => {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
256
|
+
try {
|
|
257
|
+
const res = await fetch(SELLER_ENDPOINTS.ORDERS_BULK_LOCATION, {
|
|
258
|
+
method: "PATCH",
|
|
259
|
+
headers: { "Content-Type": "application/json" },
|
|
260
|
+
body: JSON.stringify({ orderIds: selection.selectedIds, physicalLocation: loc }),
|
|
261
|
+
});
|
|
262
|
+
if (!res.ok) {
|
|
263
|
+
const body = await res.json().catch(() => null);
|
|
264
|
+
throw new Error(body?.error ?? "Failed to update location");
|
|
265
|
+
}
|
|
266
|
+
showToast("Location updated.", "success");
|
|
267
|
+
setSetLocationOpen(false);
|
|
268
|
+
}
|
|
269
|
+
catch (err) {
|
|
270
|
+
showToast(err instanceof Error ? err.message : "Failed to update location.", "error");
|
|
271
|
+
}
|
|
272
|
+
}, [selection.selectedIds, showToast]);
|
|
261
273
|
// S-STORE-5-A — bulk order selection → single payout request.
|
|
262
274
|
const requestPayoutForSelection = useCallback(async () => {
|
|
263
275
|
if (!selection.selectedIds.length)
|
|
264
276
|
return;
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
277
|
+
try {
|
|
278
|
+
const res = await fetch("/api/store/payouts/request", {
|
|
279
|
+
method: "POST",
|
|
280
|
+
headers: { "Content-Type": "application/json" },
|
|
281
|
+
body: JSON.stringify({ orderIds: selection.selectedIds }),
|
|
282
|
+
});
|
|
283
|
+
if (!res.ok) {
|
|
284
|
+
const body = await res.json().catch(() => null);
|
|
285
|
+
throw new Error(body?.error ?? "Failed to request payout");
|
|
286
|
+
}
|
|
287
|
+
showToast("Payout requested.", "success");
|
|
288
|
+
selection.clearSelection();
|
|
289
|
+
}
|
|
290
|
+
catch (err) {
|
|
291
|
+
showToast(err instanceof Error ? err.message : "Failed to request payout.", "error");
|
|
292
|
+
}
|
|
293
|
+
}, [selection, showToast]);
|
|
272
294
|
const bulkActions = [
|
|
273
295
|
{
|
|
274
296
|
id: ACTIONS.STORE["print-packing-slips"].id,
|
|
@@ -292,5 +314,6 @@ export function SellerOrdersView({ orderDetailApiBase = SELLER_ENDPOINTS.ORDERS,
|
|
|
292
314
|
if (hasChildren) {
|
|
293
315
|
return _jsx(ListingViewShell, { portal: "seller", ...props, children: children });
|
|
294
316
|
}
|
|
295
|
-
|
|
317
|
+
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: bulkActions } } : {});
|
|
318
|
+
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search by order ID or buyer name", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get("sort") || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set("sort", v); }, showTableView: true, view: view, onViewChange: (v) => setView(v), onResetAll: resetAll, hasActiveState: hasActiveState }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), selection.selectedIds.length > 0 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+88px)] z-20 px-3 sm:px-4 py-2 bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700", children: _jsx(BulkActionBar, { selectedCount: selection.selectedIds.length, onClearSelection: selection.clearSelection, actions: bulkActions }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx(Div, { className: "mb-4 rounded-xl border border-red-200 bg-error-surface dark:border-red-900/60 px-4 py-3 text-sm text-error", children: errorMessage })), _jsx(DataTable, { rows: rows, columns: columns, isLoading: isLoading, emptyLabel: "No orders yet", selectedIds: selection.selectedIdSet, onToggleSelect: selection.toggle, onToggleSelectAll: () => selection.toggleAll(), renderRowActions: renderRowActions })] }), filterOpen && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-40 bg-black/40", "aria-hidden": "true", onClick: () => setFilterOpen(false) }), _jsxs("div", { className: "fixed inset-y-0 left-0 z-50 flex w-80 flex-col bg-white dark:bg-slate-900 shadow-2xl", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: [_jsx("span", { className: "text-base font-semibold text-zinc-900 dark:text-zinc-100", children: "Filters" }), _jsxs("div", { className: "flex items-center gap-2", children: [activeFilterCount > 0 && (_jsx("button", { type: "button", onClick: clearFilters, className: "text-xs text-zinc-500 dark:text-zinc-400 hover:text-rose-500 transition-colors", children: "Clear all" })), _jsx("button", { type: "button", onClick: () => setFilterOpen(false), "aria-label": "Close", className: "rounded-lg p-1.5 text-zinc-500 dark:text-zinc-400 hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors", children: _jsx(X, { className: "h-5 w-5" }) })] })] }), _jsx("div", { className: "flex-1 overflow-y-auto px-4 py-4 space-y-5", children: _jsx(FilterChipGroup, { label: "Status", tabs: STATUS_OPTIONS, value: pendingFilters.status ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, status: id })) }) }), _jsx("div", { className: "border-t border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: _jsxs("button", { type: "button", onClick: applyFilters, className: "w-full rounded-lg bg-[var(--appkit-color-primary)] py-2.5 text-sm font-semibold text-white transition-colors active:scale-[0.98]", children: ["Apply", activeFilterCount > 0 ? ` (${activeFilterCount})` : ""] }) })] })] })), selectedOrderId && (_jsx(OrderDetailDrawer, { orderId: selectedOrderId, apiBase: orderDetailApiBase, onClose: () => setSelectedOrderId(null) })), setLocationOpen && (_jsx(PhysicalLocationModal, { count: selection.selectedIds.length, onSave: handleSetLocation, onClose: () => setSetLocationOpen(false) }))] }));
|
|
296
319
|
}
|
|
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { useState, useCallback } from "react";
|
|
4
4
|
import { Plus } from "lucide-react";
|
|
5
5
|
import { useUrlTable } from "../../../react/hooks/useUrlTable";
|
|
6
|
-
import { Button, ConfirmDeleteModal, Div, ListingToolbar, Text, } from "../../../ui";
|
|
6
|
+
import { Button, ConfirmDeleteModal, Div, ListingToolbar, Text, useToast, } from "../../../ui";
|
|
7
7
|
import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
8
8
|
import { ROUTES } from "../../..";
|
|
9
9
|
import { toRecordArray, toStringValue, useSellerListingData, } from "../hooks/useSellerListingData";
|
|
@@ -34,6 +34,7 @@ export function SellerPayoutMethodsView({ onCreateClick, onEditClick, onDelete,
|
|
|
34
34
|
const [deleteTargetId, setDeleteTargetId] = useState(null);
|
|
35
35
|
const [deletingId, setDeletingId] = useState(null);
|
|
36
36
|
const [settingDefaultId, setSettingDefaultId] = useState(null);
|
|
37
|
+
const { showToast } = useToast();
|
|
37
38
|
const commitSearch = useCallback(() => {
|
|
38
39
|
table.set(TABLE_KEYS.QUERY, searchInput.trim());
|
|
39
40
|
}, [searchInput, table]);
|
|
@@ -72,12 +73,16 @@ export function SellerPayoutMethodsView({ onCreateClick, onEditClick, onDelete,
|
|
|
72
73
|
});
|
|
73
74
|
}
|
|
74
75
|
refetch?.();
|
|
76
|
+
showToast("Payout method deleted.", "success");
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
showToast(err instanceof Error ? err.message : "Failed to delete payout method.", "error");
|
|
75
80
|
}
|
|
76
81
|
finally {
|
|
77
82
|
setDeletingId(null);
|
|
78
83
|
setDeleteTargetId(null);
|
|
79
84
|
}
|
|
80
|
-
}, [onDelete, refetch]);
|
|
85
|
+
}, [onDelete, refetch, showToast]);
|
|
81
86
|
const handleSetDefault = useCallback(async (id) => {
|
|
82
87
|
setSettingDefaultId(id);
|
|
83
88
|
try {
|
|
@@ -93,11 +98,15 @@ export function SellerPayoutMethodsView({ onCreateClick, onEditClick, onDelete,
|
|
|
93
98
|
});
|
|
94
99
|
}
|
|
95
100
|
refetch?.();
|
|
101
|
+
showToast("Default payout method updated.", "success");
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
showToast(err instanceof Error ? err.message : "Failed to update default.", "error");
|
|
96
105
|
}
|
|
97
106
|
finally {
|
|
98
107
|
setSettingDefaultId(null);
|
|
99
108
|
}
|
|
100
|
-
}, [onSetDefault, refetch]);
|
|
109
|
+
}, [onSetDefault, refetch, showToast]);
|
|
101
110
|
const handleCreate = useCallback(() => {
|
|
102
111
|
if (onCreateClick) {
|
|
103
112
|
onCreateClick();
|
|
@@ -114,7 +123,7 @@ export function SellerPayoutMethodsView({ onCreateClick, onEditClick, onDelete,
|
|
|
114
123
|
window.location.href = String(ROUTES.STORE.PAYOUT_METHODS_EDIT(id));
|
|
115
124
|
}
|
|
116
125
|
}, [onEditClick]);
|
|
117
|
-
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: 0, searchValue: searchInput, searchPlaceholder: "Search payout methods...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, onResetAll: resetAll, hasActiveState: hasActiveState, extra: _jsxs(Button, { size: "sm", onClick: handleCreate, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), _jsx("span", { children: "New Method" })] }) }), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx(Div, { className: "mb-4 rounded-xl border border-red-200 bg-
|
|
118
|
-
? "bg-
|
|
126
|
+
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: 0, searchValue: searchInput, searchPlaceholder: "Search payout methods...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, onResetAll: resetAll, hasActiveState: hasActiveState, extra: _jsxs(Button, { size: "sm", onClick: handleCreate, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), _jsx("span", { children: "New Method" })] }) }), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx(Div, { className: "mb-4 rounded-xl border border-red-200 bg-error-surface dark:border-red-900/60 px-4 py-3 text-sm text-error", children: errorMessage })), isLoading ? (_jsx(Div, { className: "space-y-3", children: Array.from({ length: 3 }).map((_, i) => (_jsx(Div, { className: "h-20 animate-pulse rounded-xl border border-zinc-100 dark:border-slate-700 bg-zinc-50 dark:bg-slate-800" }, i))) })) : rows.length === 0 ? (_jsxs(Div, { className: "py-16 text-center", children: [_jsx(Text, { className: "text-zinc-400 dark:text-zinc-400", children: "No payout methods yet \u2014 add a UPI VPA or bank account to receive payouts" }), _jsx("div", { className: "mt-4", children: _jsx(Button, { size: "sm", onClick: handleCreate, children: "Add payout method" }) })] })) : (_jsx("div", { className: "space-y-3", children: rows.map((row) => (_jsx("div", { className: "rounded-xl border border-zinc-200 dark:border-slate-700 bg-white dark:bg-slate-900 px-4 py-3", children: _jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsx("div", { className: "flex items-start gap-3 min-w-0", children: _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [_jsx(Text, { className: "text-sm font-medium", children: row.label }), _jsx(TypeBadge, { type: row.type }), row.isDefault && (_jsx("span", { className: "inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium bg-success-surface text-success", children: "Default" })), _jsx("span", { className: `inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${row.isActive
|
|
127
|
+
? "bg-success-surface text-success"
|
|
119
128
|
: "bg-zinc-100 text-zinc-600 dark:bg-slate-800 dark:text-slate-400"}`, children: row.isActive ? "Active" : "Inactive" })] }), _jsx(Text, { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400 font-mono", children: row.maskedIdentifier })] }) }), _jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [!row.isDefault && (_jsx(Button, { size: "sm", variant: "ghost", isLoading: settingDefaultId === row.id, onClick: () => handleSetDefault(row.id), children: "Set Default" })), _jsx(Button, { size: "sm", variant: "outline", onClick: () => handleEdit(row.id), children: "Edit" }), _jsx(Button, { size: "sm", variant: "danger", disabled: deletingId === row.id, onClick: () => setDeleteTargetId(row.id), children: "Delete" })] })] }) }, row.id))) }))] }), deleteTargetId && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete Payout Method", message: "Are you sure you want to delete this payout method? This cannot be undone.", onConfirm: () => handleDelete(deleteTargetId), onClose: () => setDeleteTargetId(null), isDeleting: deletingId === deleteTargetId }))] }));
|
|
120
129
|
}
|
|
@@ -80,8 +80,8 @@ export function SellerPayoutsView({ children, onViewClick, onExportClick, ...pro
|
|
|
80
80
|
if (hasChildren) {
|
|
81
81
|
return _jsx(ListingViewShell, { portal: "seller", ...props, children: children });
|
|
82
82
|
}
|
|
83
|
-
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search payouts by payout # or amount", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get("sort") || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set("sort", v); }, showTableView: true, view: view, onViewChange: (v) => setView(v), onResetAll: resetAll, hasActiveState: hasActiveState }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-
|
|
83
|
+
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search payouts by payout # or amount", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get("sort") || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set("sort", v); }, showTableView: true, view: view, onViewChange: (v) => setView(v), onResetAll: resetAll, hasActiveState: hasActiveState }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-error-surface px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })), view === "table" ? (_jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No payouts found", renderRowActions: (row) => (_jsx(RowActionMenu, { actions: [
|
|
84
84
|
...(onViewClick ? [{ label: ACTIONS.STORE["view-payout"].label, onClick: () => onViewClick(row.id) }] : []),
|
|
85
85
|
...(onExportClick ? [{ label: ACTIONS.STORE["export-payout"].label, onClick: () => onExportClick(row.id) }] : []),
|
|
86
|
-
] })) })) : (_jsx(AdminViewCards, { rows: rows, view: view, isLoading: isLoading, emptyLabel: "No payouts found", onRowClick: undefined, selectedIdSet: selection.selectedIdSet, onToggleSelect: selection.toggle }))] }), filterOpen && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-40 bg-black/40", "aria-hidden": "true", onClick: () => setFilterOpen(false) }), _jsxs("div", { className: "fixed inset-y-0 left-0 z-50 flex w-80 flex-col bg-white dark:bg-slate-900 shadow-2xl", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: [_jsx("span", { className: "text-base font-semibold text-zinc-900 dark:text-zinc-100", children: "Filters" }), _jsxs("div", { className: "flex items-center gap-2", children: [activeFilterCount > 0 && (_jsx("button", { type: "button", onClick: clearFilters, className: "text-xs text-zinc-500 hover:text-rose-500 dark:text-zinc-400 transition-colors", children: "Clear all" })), _jsx("button", { type: "button", onClick: () => setFilterOpen(false), "aria-label": "Close", className: "rounded-lg p-1.5 text-zinc-500 hover:bg-zinc-100 dark:hover:bg-
|
|
86
|
+
] })) })) : (_jsx(AdminViewCards, { rows: rows, view: view, isLoading: isLoading, emptyLabel: "No payouts found", onRowClick: undefined, selectedIdSet: selection.selectedIdSet, onToggleSelect: selection.toggle }))] }), filterOpen && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-40 bg-black/40", "aria-hidden": "true", onClick: () => setFilterOpen(false) }), _jsxs("div", { className: "fixed inset-y-0 left-0 z-50 flex w-80 flex-col bg-white dark:bg-slate-900 shadow-2xl", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: [_jsx("span", { className: "text-base font-semibold text-zinc-900 dark:text-zinc-100", children: "Filters" }), _jsxs("div", { className: "flex items-center gap-2", children: [activeFilterCount > 0 && (_jsx("button", { type: "button", onClick: clearFilters, className: "text-xs text-zinc-500 hover:text-rose-500 dark:text-zinc-400 transition-colors", children: "Clear all" })), _jsx("button", { type: "button", onClick: () => setFilterOpen(false), "aria-label": "Close", className: "rounded-lg p-1.5 text-zinc-500 dark:text-zinc-400 hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors", children: _jsx(X, { className: "h-5 w-5" }) })] })] }), _jsx("div", { className: "flex-1 overflow-y-auto px-4 py-4 space-y-5", children: _jsx(FilterChipGroup, { label: "Status", tabs: STATUS_OPTIONS, value: pendingFilters.status ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, status: id })) }) }), _jsx("div", { className: "border-t border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: _jsxs("button", { type: "button", onClick: applyFilters, className: "w-full rounded-lg bg-primary py-2.5 text-sm font-semibold text-white hover:bg-primary-600 transition-colors active:scale-[0.98]", children: ["Apply Filters", activeFilterCount > 0 ? ` (${activeFilterCount})` : ""] }) })] })] }))] }));
|
|
87
87
|
}
|
|
@@ -4,7 +4,7 @@ import React, { useState, useCallback } from "react";
|
|
|
4
4
|
import { X } from "lucide-react";
|
|
5
5
|
import { useUrlTable } from "../../../react/hooks/useUrlTable";
|
|
6
6
|
import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
|
|
7
|
-
import { Alert, Badge, Button, ConfirmDeleteModal, Div, FilterChipGroup, ListingToolbar, ListingViewShell, Pagination, Row, RowActionMenu, Text } from "../../../ui";
|
|
7
|
+
import { Alert, Badge, Button, ConfirmDeleteModal, Div, FilterChipGroup, ListingToolbar, ListingViewShell, Pagination, Row, RowActionMenu, Text, useToast } from "../../../ui";
|
|
8
8
|
import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
9
9
|
import { SELLER_PRE_ORDER_STATUS_TABS } from "../../admin/constants/filter-tabs";
|
|
10
10
|
import { ROUTES } from "../../../constants";
|
|
@@ -76,6 +76,7 @@ export function SellerPreOrdersView({ children, onDelete, ...props }) {
|
|
|
76
76
|
const dispatch = useActionDispatch();
|
|
77
77
|
const [deleteTargetId, setDeleteTargetId] = useState(null);
|
|
78
78
|
const [deletingId, setDeletingId] = useState(null);
|
|
79
|
+
const { showToast } = useToast();
|
|
79
80
|
const table = useUrlTable({ defaults: { pageSize: String(PAGE_SIZE), sort: DEFAULT_SORT } });
|
|
80
81
|
const [searchInput, setSearchInput] = useState(table.get("q") || "");
|
|
81
82
|
const [filterOpen, setFilterOpen] = useState(false);
|
|
@@ -144,12 +145,16 @@ export function SellerPreOrdersView({ children, onDelete, ...props }) {
|
|
|
144
145
|
await onDelete(id);
|
|
145
146
|
else
|
|
146
147
|
await fetch(`/api/store/products/${id}`, { method: "DELETE", credentials: "include" });
|
|
148
|
+
showToast("Pre-order deleted.", "success");
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
showToast(err instanceof Error ? err.message : "Failed to delete pre-order.", "error");
|
|
147
152
|
}
|
|
148
153
|
finally {
|
|
149
154
|
setDeletingId(null);
|
|
150
155
|
setDeleteTargetId(null);
|
|
151
156
|
}
|
|
152
|
-
}, [onDelete]);
|
|
157
|
+
}, [onDelete, showToast]);
|
|
153
158
|
if (hasChildren) {
|
|
154
159
|
return (_jsx(ListingViewShell, { portal: "seller", ...props, children: children }));
|
|
155
160
|
}
|
|
@@ -4,7 +4,7 @@ import React, { useState, useCallback } from "react";
|
|
|
4
4
|
import { X } from "lucide-react";
|
|
5
5
|
import { useUrlTable } from "../../../react/hooks/useUrlTable";
|
|
6
6
|
import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
|
|
7
|
-
import { Alert, Badge, Button, ConfirmDeleteModal, Div, FilterChipGroup, ListingToolbar, ListingViewShell, Pagination, Row, RowActionMenu, Text } from "../../../ui";
|
|
7
|
+
import { Alert, Badge, Button, ConfirmDeleteModal, Div, FilterChipGroup, ListingToolbar, ListingViewShell, Pagination, Row, RowActionMenu, Text, useToast } from "../../../ui";
|
|
8
8
|
import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
9
9
|
import { SELLER_PRIZE_DRAW_STATUS_TABS } from "../../admin/constants/filter-tabs";
|
|
10
10
|
import { ROUTES } from "../../../constants";
|
|
@@ -73,6 +73,7 @@ export function SellerPrizeDrawsView({ children, onDelete, ...props }) {
|
|
|
73
73
|
const dispatch = useActionDispatch();
|
|
74
74
|
const [deleteTargetId, setDeleteTargetId] = useState(null);
|
|
75
75
|
const [deletingId, setDeletingId] = useState(null);
|
|
76
|
+
const { showToast } = useToast();
|
|
76
77
|
const table = useUrlTable({ defaults: { pageSize: String(PAGE_SIZE), sort: DEFAULT_SORT } });
|
|
77
78
|
const [searchInput, setSearchInput] = useState(table.get("q") || "");
|
|
78
79
|
const [filterOpen, setFilterOpen] = useState(false);
|
|
@@ -141,12 +142,16 @@ export function SellerPrizeDrawsView({ children, onDelete, ...props }) {
|
|
|
141
142
|
await onDelete(id);
|
|
142
143
|
else
|
|
143
144
|
await fetch(`/api/store/products/${id}`, { method: "DELETE", credentials: "include" });
|
|
145
|
+
showToast("Prize draw deleted.", "success");
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
showToast(err instanceof Error ? err.message : "Failed to delete prize draw.", "error");
|
|
144
149
|
}
|
|
145
150
|
finally {
|
|
146
151
|
setDeletingId(null);
|
|
147
152
|
setDeleteTargetId(null);
|
|
148
153
|
}
|
|
149
|
-
}, [onDelete]);
|
|
154
|
+
}, [onDelete, showToast]);
|
|
150
155
|
if (hasChildren) {
|
|
151
156
|
return (_jsx(ListingViewShell, { portal: "seller", ...props, children: children }));
|
|
152
157
|
}
|
|
@@ -4,7 +4,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
|
4
4
|
import { useRouter } from "next/navigation";
|
|
5
5
|
import { FormShell, StepForm, StepFormActions, useFormShell } from "../../shell";
|
|
6
6
|
import { FormShellProvider } from "../../../ui/forms";
|
|
7
|
-
import { Alert, Button, Div, FormField, FormGroup, Heading, Section, Stack, Text, Toggle } from "../../../ui";
|
|
7
|
+
import { Alert, Button, Div, FormField, FormGroup, Heading, Section, Stack, Text, Toggle, useToast } from "../../../ui";
|
|
8
8
|
import { ImageUpload, MediaUploadField, MediaUploadList, useMediaUpload } from "../../media";
|
|
9
9
|
import { StoreAddressSelectorCreate } from "../../stores/components/StoreAddressSelectorCreate";
|
|
10
10
|
import { QuickProductForm } from "./QuickProductForm";
|
|
@@ -149,6 +149,7 @@ export function SellerProductShell({ mode, listingType = "standard", initialValu
|
|
|
149
149
|
const [stepError, setStepError] = useState(null);
|
|
150
150
|
const { isDirty, markDirty, markClean } = useFormShell();
|
|
151
151
|
const router = useRouter();
|
|
152
|
+
const { showToast } = useToast();
|
|
152
153
|
const { upload: shellUpload } = useMediaUpload();
|
|
153
154
|
// Auto-save in create mode — debounce 2s on any draft change
|
|
154
155
|
const autoSaveTimer = useRef(null);
|
|
@@ -202,13 +203,25 @@ export function SellerProductShell({ mode, listingType = "standard", initialValu
|
|
|
202
203
|
router.back();
|
|
203
204
|
}, [onDiscard, router]);
|
|
204
205
|
const handleSave = useCallback(async () => {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
206
|
+
try {
|
|
207
|
+
await onSave(draft);
|
|
208
|
+
markClean();
|
|
209
|
+
showToast("Saved.", "success");
|
|
210
|
+
}
|
|
211
|
+
catch (err) {
|
|
212
|
+
showToast(err instanceof Error ? err.message : "Failed to save.", "error");
|
|
213
|
+
}
|
|
214
|
+
}, [draft, onSave, markClean, showToast]);
|
|
208
215
|
const handlePublish = useCallback(async () => {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
216
|
+
try {
|
|
217
|
+
await onPublish({ ...draft, status: "published" });
|
|
218
|
+
markClean();
|
|
219
|
+
showToast("Published.", "success");
|
|
220
|
+
}
|
|
221
|
+
catch (err) {
|
|
222
|
+
showToast(err instanceof Error ? err.message : "Failed to publish.", "error");
|
|
223
|
+
}
|
|
224
|
+
}, [draft, onPublish, markClean, showToast]);
|
|
212
225
|
const listingTypeLabel = listingType === "auction"
|
|
213
226
|
? "Auction"
|
|
214
227
|
: listingType === "pre-order"
|
|
@@ -291,9 +304,14 @@ export function SellerProductShell({ mode, listingType = "standard", initialValu
|
|
|
291
304
|
setCurrentStep((c) => c + 1);
|
|
292
305
|
}
|
|
293
306
|
else {
|
|
294
|
-
|
|
307
|
+
try {
|
|
308
|
+
await handlePublish();
|
|
309
|
+
}
|
|
310
|
+
catch (err) {
|
|
311
|
+
showToast(err instanceof Error ? err.message : "Something went wrong.", "error");
|
|
312
|
+
}
|
|
295
313
|
}
|
|
296
|
-
}, [currentStep, steps, draft, handlePublish]);
|
|
314
|
+
}, [currentStep, steps, draft, handlePublish, showToast]);
|
|
297
315
|
// Step error badges — run each step's validate against current draft
|
|
298
316
|
const stepValidationErrors = useMemo(() => steps.map((s) => (s.validate ? Boolean(s.validate(draft)) : false)),
|
|
299
317
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Badge, Button, Div, Row, Text } from "../../../ui";
|
|
4
|
+
import { ROW_ACTION_META, ROW_ACTION_ID } from "../../../features/products/constants/action-defs";
|
|
4
5
|
import { CARD_BORDER, CARD_BORDER_ACTIVE, CARD_GRID_CLS, CARD_LIST_CLS, KIND_BADGE_VARIANT } from "./seller-products-styles";
|
|
5
6
|
function buildHref(row) {
|
|
6
7
|
if (row.listingKind === "auction")
|
|
@@ -14,6 +15,6 @@ export function SellerProductsCards({ view, rows, isLoading, listingKind, select
|
|
|
14
15
|
const isSelected = selectedIds.has(row.id);
|
|
15
16
|
const href = buildHref(row);
|
|
16
17
|
const borderCls = isSelected ? CARD_BORDER_ACTIVE : CARD_BORDER;
|
|
17
|
-
return view === "grid" ? (_jsxs(Div, { className: `group relative rounded-xl border bg-[var(--appkit-color-surface)] overflow-hidden hover:shadow-md transition-shadow ${borderCls}`, children: [_jsx(Div, { className: "absolute top-2 left-2 z-10", children: _jsx("input", { type: "checkbox", checked: isSelected, onChange: () => toggle(row.id), className: "h-4 w-4 rounded border-[var(--appkit-color-border)]", onClick: (e) => e.stopPropagation(), "aria-label": "Select" }) }), _jsxs("a", { href: href, className: "block", children: [row.imageUrl ? (_jsx("img", { src: row.imageUrl, alt: "", className: "w-full aspect-square object-cover" })) : (_jsx(Div, { className: "w-full aspect-square bg-[var(--appkit-color-surface-raised)] flex items-center justify-center text-[var(--appkit-color-text-faint)]", children: "\u2014" })), _jsxs(Div, { className: "p-3 space-y-1", children: [_jsx(Text, { className: "font-medium text-sm line-clamp-1", children: row.primary }), _jsxs(Row, { className: "gap-2
|
|
18
|
+
return view === "grid" ? (_jsxs(Div, { className: `group relative rounded-xl border bg-[var(--appkit-color-surface)] overflow-hidden hover:shadow-md transition-shadow ${borderCls}`, children: [_jsx(Div, { className: "absolute top-2 left-2 z-10", children: _jsx("input", { type: "checkbox", checked: isSelected, onChange: () => toggle(row.id), className: "h-4 w-4 rounded border-[var(--appkit-color-border)]", onClick: (e) => e.stopPropagation(), "aria-label": "Select" }) }), _jsxs("a", { href: href, className: "block", children: [row.imageUrl ? (_jsx("img", { src: row.imageUrl, alt: "", className: "w-full aspect-square object-cover" })) : (_jsx(Div, { className: "w-full aspect-square bg-[var(--appkit-color-surface-raised)] flex items-center justify-center text-[var(--appkit-color-text-faint)]", children: "\u2014" })), _jsxs(Div, { className: "p-3 space-y-1", children: [_jsx(Text, { className: "font-medium text-sm line-clamp-1", children: row.primary }), _jsxs(Row, { className: "gap-2", children: [_jsx(Badge, { variant: KIND_BADGE_VARIANT[row.listingKind] ?? "default", children: row.listingKind }), _jsx(Text, { className: "text-xs text-[var(--appkit-color-text-muted)] line-clamp-1", children: row.secondary })] })] })] }), _jsxs(Div, { className: "border-t border-[var(--appkit-color-border)] flex justify-end gap-1 p-2", children: [_jsx(Button, { variant: "ghost", size: "sm", onClick: (e) => { e.stopPropagation(); onEdit(row); }, "aria-label": "Edit", children: ROW_ACTION_META[ROW_ACTION_ID.EDIT].label }), _jsx(Button, { variant: "ghost", size: "sm", onClick: (e) => { e.stopPropagation(); onDuplicate(row); }, "aria-label": "Duplicate", children: ROW_ACTION_META[ROW_ACTION_ID.DUPLICATE].label }), onDelete && (_jsx(Button, { variant: "ghost", size: "sm", onClick: (e) => { e.stopPropagation(); onDelete(row); }, "aria-label": "Delete", children: ROW_ACTION_META[ROW_ACTION_ID.DELETE].label }))] })] }, row.id)) : (_jsxs(Div, { className: `flex items-center gap-3 rounded-lg border bg-[var(--appkit-color-surface)] px-3 py-2 hover:bg-[var(--appkit-color-surface-raised)] ${borderCls}`, children: [_jsx("input", { type: "checkbox", checked: isSelected, onChange: () => toggle(row.id), className: "h-4 w-4 rounded border-[var(--appkit-color-border)]", "aria-label": "Select" }), row.imageUrl ? (_jsx("img", { src: row.imageUrl, alt: "", className: "w-12 h-12 rounded object-cover" })) : (_jsx(Div, { className: "w-12 h-12 rounded bg-[var(--appkit-color-surface-raised)]" })), _jsxs("a", { href: href, className: "flex-1 min-w-0", children: [_jsx(Text, { className: "font-medium text-sm line-clamp-1", children: row.primary }), _jsxs(Row, { className: "gap-2", children: [_jsx(Badge, { variant: KIND_BADGE_VARIANT[row.listingKind] ?? "default", children: row.listingKind }), _jsx(Text, { className: "text-xs text-[var(--appkit-color-text-muted)] line-clamp-1", children: row.secondary })] })] }), _jsxs(Row, { className: "gap-1 flex-shrink-0", children: [_jsx(Button, { variant: "ghost", size: "sm", onClick: () => onEdit(row), "aria-label": "Edit", children: ROW_ACTION_META[ROW_ACTION_ID.EDIT].label }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => onDuplicate(row), "aria-label": "Duplicate", children: ROW_ACTION_META[ROW_ACTION_ID.DUPLICATE].label }), onDelete && (_jsx(Button, { variant: "ghost", size: "sm", onClick: () => onDelete(row), "aria-label": "Delete", children: ROW_ACTION_META[ROW_ACTION_ID.DELETE].label }))] })] }, row.id));
|
|
18
19
|
})] }));
|
|
19
20
|
}
|
|
@@ -6,7 +6,7 @@ import { Eye, EyeOff, Pencil, Trash2, Printer, MapPin } from "lucide-react";
|
|
|
6
6
|
import { PhysicalLocationModal } from "./PhysicalLocationModal";
|
|
7
7
|
import { useUrlTable } from "../../../react/hooks/useUrlTable";
|
|
8
8
|
import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
|
|
9
|
-
import { Alert, Badge, BulkActionBar, Button, Div, ListingToolbar, ListingViewShell, Pagination, Row, Span, Text } from "../../../ui";
|
|
9
|
+
import { Alert, Badge, BulkActionBar, Button, Div, ListingToolbar, ListingViewShell, Pagination, Row, Span, Text, useToast } from "../../../ui";
|
|
10
10
|
import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
11
11
|
import { SELLER_PRODUCT_STATUS_TABS } from "../../admin/constants/filter-tabs";
|
|
12
12
|
import { ROUTES } from "../../../constants";
|
|
@@ -17,6 +17,7 @@ import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
|
|
|
17
17
|
import { SellerProductsCards } from "./SellerProductsCards";
|
|
18
18
|
import { SellerProductsFilterDrawer } from "./SellerProductsFilterDrawer";
|
|
19
19
|
import { KIND_BADGE_VARIANT } from "./seller-products-styles";
|
|
20
|
+
import { useBottomActions } from "../../layout";
|
|
20
21
|
const PAGE_SIZE = 25;
|
|
21
22
|
const FILTER_KEYS = [
|
|
22
23
|
"status",
|
|
@@ -52,7 +53,7 @@ function TypeDropdown({ active, onChange, }) {
|
|
|
52
53
|
{ value: "digital-code", label: "Digital Code" },
|
|
53
54
|
{ value: "live", label: "Live" },
|
|
54
55
|
];
|
|
55
|
-
return (_jsxs(Row, { className: "gap-2 px-3 lg:px-4 py-2
|
|
56
|
+
return (_jsxs(Row, { className: "gap-2 px-3 lg:px-4 py-2 border-b border-[var(--appkit-color-border)]", children: [_jsx(Text, { className: "text-xs font-semibold uppercase tracking-wide text-[var(--appkit-color-text-muted)]", children: "Listing type" }), _jsx("select", { value: active, onChange: (e) => onChange(e.target.value), className: "rounded border border-[var(--appkit-color-border)] bg-transparent px-2 py-1 text-sm sm:max-w-xs", "aria-label": "Filter by listing type", children: options.map((o) => (_jsx("option", { value: o.value, children: o.label }, o.value))) })] }));
|
|
56
57
|
}
|
|
57
58
|
const PRODUCT_COLUMNS = [
|
|
58
59
|
{
|
|
@@ -104,6 +105,7 @@ export function SellerProductsView({ onDeleteProduct, onCreateClick, children, .
|
|
|
104
105
|
const hasChildren = React.Children.count(children) > 0;
|
|
105
106
|
const [view, setView] = useState("table");
|
|
106
107
|
const dispatch = useActionDispatch();
|
|
108
|
+
const { showToast } = useToast();
|
|
107
109
|
const table = useUrlTable({ defaults: { pageSize: String(PAGE_SIZE), sort: DEFAULT_SORT } });
|
|
108
110
|
const [searchInput, setSearchInput] = useState(table.get("q") || "");
|
|
109
111
|
const [filterOpen, setFilterOpen] = useState(false);
|
|
@@ -263,13 +265,23 @@ export function SellerProductsView({ onDeleteProduct, onCreateClick, children, .
|
|
|
263
265
|
});
|
|
264
266
|
}, [selection.selectedIds, dispatch]);
|
|
265
267
|
const handleSetLocation = useCallback(async (loc) => {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
268
|
+
try {
|
|
269
|
+
const res = await fetch(SELLER_ENDPOINTS.PRODUCTS_BULK_LOCATION, {
|
|
270
|
+
method: "PATCH",
|
|
271
|
+
headers: { "Content-Type": "application/json" },
|
|
272
|
+
body: JSON.stringify({ productIds: selection.selectedIds, physicalLocation: loc }),
|
|
273
|
+
});
|
|
274
|
+
if (!res.ok) {
|
|
275
|
+
const body = await res.json().catch(() => null);
|
|
276
|
+
throw new Error(body?.error ?? "Failed to update location");
|
|
277
|
+
}
|
|
278
|
+
showToast("Location updated.", "success");
|
|
279
|
+
setSetLocationOpen(false);
|
|
280
|
+
}
|
|
281
|
+
catch (err) {
|
|
282
|
+
showToast(err instanceof Error ? err.message : "Failed to update location.", "error");
|
|
283
|
+
}
|
|
284
|
+
}, [selection.selectedIds, showToast]);
|
|
273
285
|
const bulkActions = [
|
|
274
286
|
{
|
|
275
287
|
id: ACTIONS.STORE["print-labels"].id,
|
|
@@ -284,6 +296,7 @@ export function SellerProductsView({ onDeleteProduct, onCreateClick, children, .
|
|
|
284
296
|
onClick: () => setSetLocationOpen(true),
|
|
285
297
|
},
|
|
286
298
|
];
|
|
299
|
+
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: bulkActions } } : {});
|
|
287
300
|
return (_jsxs(_Fragment, { children: [_jsxs(Div, { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search products by name\u2026", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get("sort") || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set("sort", v); }, showTableView: true, view: view, onViewChange: (v) => setView(v), onResetAll: resetAll, hasActiveState: hasActiveState, toggles: [
|
|
288
301
|
{ label: "Show sold", active: showSold, onChange: (next) => table.set("showSold", next ? "true" : "") },
|
|
289
302
|
], extra: onCreateClick ? (_jsx(Button, { variant: "primary", size: "sm", onClick: onCreateClick, children: "+ New Listing" })) : null }), _jsx(TypeDropdown, { active: listingKind, onChange: handleKindChange }), totalPages > 1 && (_jsx(Div, { className: "sticky z-10 flex justify-center bg-[var(--appkit-color-surface)]/95 backdrop-blur-sm border-b border-[var(--appkit-color-border)] px-3 py-1.5", style: { top: "calc(var(--header-height, 0px) + 44px)" }, children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), selection.selectedIds.length > 0 && (_jsx(Div, { className: "sticky z-20 px-3 lg:px-4 py-2 bg-[var(--appkit-color-surface)]/95 backdrop-blur-sm border-b border-[var(--appkit-color-border)]", style: { top: "calc(var(--header-height, 0px) + 88px)" }, children: _jsx(BulkActionBar, { selectedCount: selection.selectedIds.length, onClearSelection: selection.clearSelection, actions: bulkActions }) })), _jsxs(Div, { className: "py-4 px-3 lg:px-4", children: [errorMessage && (_jsx(Alert, { variant: "error", className: "mb-4", children: errorMessage })), view !== "table" && (_jsx(SellerProductsCards, { view: view, rows: visibleRows, isLoading: isLoading, listingKind: listingKind, selectedIds: selection.selectedIdSet, toggle: selection.toggle, onEdit: handleEdit, onDuplicate: (row) => void handleDuplicate(row), onDelete: onDeleteProduct ? (row) => void handleDelete(row) : undefined })), view === "table" && (_jsx(DataTable, { columns: PRODUCT_COLUMNS, rows: visibleRows, isLoading: isLoading, emptyLabel: listingKind !== "all"
|
|
@@ -3,6 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
3
3
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
4
4
|
import { Alert, Badge, BulkActionBar, Button, Checkbox, Div, Modal, Row, Select, SideDrawer, Stack, Text, Textarea, } from "../../../ui";
|
|
5
5
|
import { StackedViewShell } from "../../../ui";
|
|
6
|
+
import { useBottomActions } from "../../layout";
|
|
6
7
|
import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
|
|
7
8
|
const STAR = "★";
|
|
8
9
|
const EMPTY_STAR = "☆";
|
|
@@ -141,6 +142,13 @@ export function SellerReviewsView({ reviewsApiBase = "/api/store/reviews", reply
|
|
|
141
142
|
setReplySaving(false);
|
|
142
143
|
}
|
|
143
144
|
};
|
|
145
|
+
useBottomActions(selectedIds.size > 0 ? { bulk: { selectedCount: selectedIds.size, onClearSelection: clearSelection, actions: [
|
|
146
|
+
{
|
|
147
|
+
id: "bulk-reply",
|
|
148
|
+
label: "Reply to selected",
|
|
149
|
+
onClick: () => setBulkReplyOpen(true),
|
|
150
|
+
},
|
|
151
|
+
] } } : {});
|
|
144
152
|
return (_jsxs(_Fragment, { children: [_jsx(StackedViewShell, { portal: "seller", title: "Reviews", sections: [
|
|
145
153
|
_jsxs(Stack, { gap: "lg", children: [_jsxs(Div, { className: "flex flex-wrap items-center gap-3", children: [_jsx(Select, { value: rating, onChange: (e) => { setRating(e.target.value); setPage(1); }, "aria-label": "Filter by rating", options: [
|
|
146
154
|
{ value: "", label: "All ratings" },
|
|
@@ -159,6 +167,6 @@ export function SellerReviewsView({ reviewsApiBase = "/api/store/reviews", reply
|
|
|
159
167
|
label: "Reply to selected",
|
|
160
168
|
onClick: () => setBulkReplyOpen(true),
|
|
161
169
|
},
|
|
162
|
-
] })), loading ? (_jsx(Div, { className: "py-8 text-center", children: _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", children: "Loading reviews\u2026" }) })) : reviews.length === 0 ? (_jsx(Div, { className: "py-12 text-center", children: _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", children: "No reviews found." }) })) : (_jsx(Stack, { gap: "md", children: reviews.map((review) => (_jsx(Div, { className: "p-4 rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)]", children: _jsxs(Div, { className: "flex items-start justify-between gap-3 flex-wrap", children: [_jsxs(Row, { className: "gap-3
|
|
170
|
+
] })), loading ? (_jsx(Div, { className: "py-8 text-center", children: _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", children: "Loading reviews\u2026" }) })) : reviews.length === 0 ? (_jsx(Div, { className: "py-12 text-center", children: _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", children: "No reviews found." }) })) : (_jsx(Stack, { gap: "md", children: reviews.map((review) => (_jsx(Div, { className: "p-4 rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)]", children: _jsxs(Div, { className: "flex items-start justify-between gap-3 flex-wrap", children: [_jsxs(Row, { align: "start", className: "gap-3 flex-1 min-w-0", children: [_jsx(Checkbox, { checked: selectedIds.has(review.id), onChange: () => toggleSelected(review.id), "aria-label": "Select review" }), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Text, { className: "font-medium truncate", children: review.productTitle }), _jsxs(Div, { className: "flex items-center gap-2 mt-1 flex-wrap", children: [_jsx(Stars, { rating: review.rating }), _jsxs(Text, { className: "text-sm text-[var(--appkit-color-text-muted)]", children: ["by ", review.userName] }), review.verified && _jsx(Badge, { variant: "success", children: "Verified" }), statusBadge(review.status), _jsx(Badge, { variant: review.sellerReply ? "success" : "warning", children: review.sellerReply ? "Store replied" : "Awaiting store reply" })] }), review.title && _jsx(Text, { className: "mt-2 font-medium", children: review.title }), _jsx(Text, { className: "mt-1 text-sm text-[var(--appkit-color-text-secondary)] line-clamp-3", children: review.comment }), review.sellerReply && (_jsxs(Div, { className: "mt-2 pl-3 border-l-2 border-[var(--appkit-color-primary)]", children: [_jsx(Text, { className: "text-xs text-[var(--appkit-color-text-muted)]", children: "Store reply:" }), _jsx(Text, { className: "text-sm", children: review.sellerReply })] }))] })] }), _jsxs(Row, { className: "gap-2 flex-shrink-0", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: () => openReply(review), children: review.sellerReply ? "Edit Reply" : ACTIONS.STORE["reply-review"].label }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => setContestTarget(review), children: ACTIONS.STORE["contest-review"].label }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => setFeedbackTarget(review), children: ACTIONS.STORE["buyer-feedback"].label })] })] }) }, review.id))) })), meta && meta.totalPages > 1 && (_jsxs(Div, { className: "flex items-center justify-center gap-2", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: () => setPage((p) => Math.max(1, p - 1)), disabled: page <= 1 || loading, children: "Previous" }), _jsxs(Text, { className: "text-sm", children: ["Page ", meta.page, " of ", meta.totalPages] }), _jsx(Button, { variant: "outline", size: "sm", onClick: () => setPage((p) => p + 1), disabled: !meta.hasMore || loading, children: "Next" })] }))] }, "reviews"),
|
|
163
171
|
] }), _jsx(SideDrawer, { isOpen: !!replyTarget, onClose: () => setReplyTarget(null), title: replyTarget?.sellerReply ? "Edit Reply" : "Reply to Review", mode: "create", children: _jsxs(Stack, { gap: "md", className: "p-4", children: [replyTarget && (_jsxs(Div, { className: "p-3 rounded bg-[var(--appkit-color-surface-muted)]", children: [_jsx(Stars, { rating: replyTarget.rating }), _jsx(Text, { className: "text-sm mt-1", children: replyTarget.comment })] })), replyError && _jsx(Alert, { variant: "error", children: replyError }), _jsxs(Div, { children: [_jsx(Text, { className: "text-sm font-medium mb-1.5", children: "Store reply" }), _jsx("textarea", { className: "w-full rounded-md border border-[var(--appkit-color-border)] bg-[var(--appkit-color-input-bg,var(--appkit-color-surface))] p-2.5 text-sm resize-none focus:outline-none focus:ring-2 focus:ring-[var(--appkit-color-primary)] dark:bg-[var(--appkit-color-surface-dark,#1e2330)] dark:border-[var(--appkit-color-border-dark)]", rows: 5, value: replyText, onChange: (e) => setReplyText(e.target.value), maxLength: 1000, placeholder: "Write your response to this review\u2026" }), _jsxs(Text, { className: "text-xs text-[var(--appkit-color-text-muted)] text-right mt-1", children: [replyText.length, "/1000"] })] }), _jsxs(Div, { className: "flex gap-2 justify-end", children: [_jsx(Button, { variant: "outline", onClick: () => setReplyTarget(null), disabled: replySaving, children: "Cancel" }), _jsx(Button, { variant: "primary", onClick: handleReplySave, disabled: replySaving || !replyText.trim(), isLoading: replySaving, children: replyTarget?.sellerReply ? "Update Reply" : "Post Reply" })] })] }) }), _jsx(Modal, { isOpen: bulkReplyOpen, onClose: () => setBulkReplyOpen(false), title: `Bulk reply to ${selectedIds.size} review${selectedIds.size === 1 ? "" : "s"}`, actions: _jsxs(Row, { className: "gap-2", children: [_jsx(Button, { variant: "ghost", onClick: () => setBulkReplyOpen(false), disabled: bulkSaving, children: "Cancel" }), _jsx(Button, { variant: "primary", onClick: () => void submitBulkReply(), disabled: !bulkReplyText.trim() || bulkSaving, isLoading: bulkSaving, children: "Send reply" })] }), children: _jsxs(Stack, { gap: "md", className: "p-1", children: [_jsx(Text, { className: "text-sm text-[var(--appkit-color-text-muted)]", children: "The same reply will be posted on all selected reviews." }), _jsx(Textarea, { value: bulkReplyText, onChange: (e) => setBulkReplyText(e.target.value), rows: 5, placeholder: "Thanks for your review\u2026", label: "Reply" })] }) }), _jsx(Modal, { isOpen: !!contestTarget, onClose: () => setContestTarget(null), title: "Contest this review", actions: _jsxs(Row, { className: "gap-2", children: [_jsx(Button, { variant: "ghost", onClick: () => setContestTarget(null), children: "Cancel" }), _jsx(Button, { variant: "primary", onClick: () => void submitContest(), disabled: !contestReason.trim(), children: "Submit" })] }), children: _jsxs(Stack, { gap: "md", className: "p-1", children: [_jsx(Text, { className: "text-sm text-[var(--appkit-color-text-muted)]", children: "Flag this review for admin investigation. Provide a clear reason \u2014 fake, abusive, off-topic, etc." }), _jsx(Textarea, { value: contestReason, onChange: (e) => setContestReason(e.target.value), rows: 4, label: "Reason" })] }) }), _jsx(Modal, { isOpen: !!feedbackTarget, onClose: () => setFeedbackTarget(null), title: "Send feedback to buyer", actions: _jsxs(Row, { className: "gap-2", children: [_jsx(Button, { variant: "ghost", onClick: () => setFeedbackTarget(null), children: "Cancel" }), _jsx(Button, { variant: "primary", onClick: () => void submitFeedback(), disabled: !feedbackText.trim(), children: "Send" })] }), children: _jsxs(Stack, { gap: "md", className: "p-1", children: [_jsx(Text, { className: "text-sm text-[var(--appkit-color-text-muted)]", children: "Private message sent to the buyer's notification inbox. Does not appear on the public review." }), _jsx(Textarea, { value: feedbackText, onChange: (e) => setFeedbackText(e.target.value), rows: 4, label: "Feedback" })] }) })] }));
|
|
164
172
|
}
|