@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
|
@@ -6,6 +6,7 @@ import { useUrlTable } from "../../../react/hooks/useUrlTable";
|
|
|
6
6
|
import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
|
|
7
7
|
import { usePanelUrlSync } from "../../../react/hooks/use-panel-url-sync";
|
|
8
8
|
import { BulkActionBar, Button, Heading, ListingToolbar, ListingViewShell, Pagination, SideDrawer, Text } from "../../../ui";
|
|
9
|
+
import { useBottomActions } from "../../layout";
|
|
9
10
|
import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
10
11
|
import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
|
|
11
12
|
import { toRecordArray, toRelativeDate, toStringValue, useAdminListingData, } from "../hooks/useAdminListingData";
|
|
@@ -23,7 +24,7 @@ const SORT_OPTIONS = [
|
|
|
23
24
|
function FaqsFilterDrawer({ filterOpen, setFilterOpen, activeFilterCount, clearFilters, pendingFilters, setPendingFilters, applyFilters, }) {
|
|
24
25
|
if (!filterOpen)
|
|
25
26
|
return null;
|
|
26
|
-
return (_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-
|
|
27
|
+
return (_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: _jsxs("div", { className: "space-y-2", children: [_jsx(Text, { className: "text-xs font-semibold uppercase tracking-widest text-zinc-500 dark:text-zinc-400", children: "Status" }), _jsx("div", { className: "flex flex-wrap gap-2", children: [{ label: "All", value: "" }, { label: "Published", value: "true" }, { label: "Draft", value: "false" }].map((opt) => (_jsx("button", { type: "button", onClick: () => setPendingFilters((p) => ({ ...p, isActive: opt.value })), className: `rounded-full px-3 py-1 text-xs font-medium border transition-colors ${(pendingFilters.isActive || "") === opt.value ? "bg-primary text-white border-primary" : "border-zinc-300 dark:border-slate-600 text-zinc-700 dark:text-zinc-300 hover:bg-zinc-50 dark:hover:bg-slate-800"}`, children: opt.label }, opt.label))) })] }) }), _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})` : ""] }) })] })] }));
|
|
27
28
|
}
|
|
28
29
|
export function AdminFaqsView({ children, getRowHref, onBulkArchive, onBulkDelete, ...props }) {
|
|
29
30
|
const hasChildren = React.Children.count(children) > 0;
|
|
@@ -94,8 +95,9 @@ export function AdminFaqsView({ children, getRowHref, onBulkArchive, onBulkDelet
|
|
|
94
95
|
onClick: async () => { await onBulkDelete(selection.selectedIds); selection.clearSelection(); refetch?.(); },
|
|
95
96
|
}] : []),
|
|
96
97
|
];
|
|
98
|
+
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: bulkActions } } : {});
|
|
97
99
|
if (hasChildren) {
|
|
98
100
|
return _jsx(ListingViewShell, { portal: "admin", ...props, children: children });
|
|
99
101
|
}
|
|
100
|
-
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(Heading, { level: 1, className: "sr-only", children: "FAQs" }), _jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search questions, categories, or tokens", 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, extra: _jsxs(Button, { size: "sm", onClick: openCreatePanel, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), "Add FAQ"] }) }), 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.selectedCount > 0 && bulkActions.length > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx("div", { className: "mb-4 rounded-xl border border-red-200 bg-
|
|
102
|
+
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(Heading, { level: 1, className: "sr-only", children: "FAQs" }), _jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search questions, categories, or tokens", 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, extra: _jsxs(Button, { size: "sm", onClick: openCreatePanel, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), "Add FAQ"] }) }), 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.selectedCount > 0 && bulkActions.length > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), _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 FAQs found", onRowClick: (row) => openEditPanel(row.id) })) : (_jsx(AdminViewCards, { rows: rows, view: view, isLoading: isLoading, emptyLabel: "No FAQs found", onRowClick: undefined, selectedIdSet: selection.selectedIdSet, onToggleSelect: selection.toggle }))] }), _jsx(FaqsFilterDrawer, { filterOpen: filterOpen, setFilterOpen: setFilterOpen, activeFilterCount: activeFilterCount, clearFilters: clearFilters, pendingFilters: pendingFilters, setPendingFilters: setPendingFilters, applyFilters: applyFilters }), _jsx(SideDrawer, { isOpen: isCreateOpen || isEditOpen, onClose: closePanel, title: isCreateOpen ? "Add FAQ" : "Edit FAQ", mode: isCreateOpen ? "create" : "edit", children: (isCreateOpen || isEditOpen) && (_jsx(AdminFaqEditorView, { faqId: editId ?? undefined, onSaved: closePanel, onDeleted: closePanel, embedded: true })) })] }));
|
|
101
103
|
}
|
|
@@ -41,7 +41,7 @@ function AccordionSection({ title, defaultOpen = true, children }) {
|
|
|
41
41
|
return (_jsxs(Div, { className: "rounded-lg border border-zinc-200 dark:border-zinc-700 overflow-hidden", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "w-full flex items-center justify-between px-4 py-3 bg-zinc-50 dark:bg-zinc-800/60 text-left", "aria-expanded": open, children: [_jsx(Text, { className: "text-xs font-semibold uppercase tracking-widest text-zinc-500 dark:text-zinc-400", children: title }), _jsx("svg", { className: `h-4 w-4 text-zinc-400 transition-transform ${open ? "rotate-180" : ""}`, fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), open && (_jsx(Div, { className: "divide-y divide-zinc-100 dark:divide-zinc-800", children: children }))] }));
|
|
42
42
|
}
|
|
43
43
|
function FlagRow({ label, desc, checked, onChange, rollout, onRolloutChange, showRollout }) {
|
|
44
|
-
return (_jsxs(Div, { className: "flex items-center justify-between gap-4
|
|
44
|
+
return (_jsxs(Div, { surface: "default", padding: "inline", className: "flex items-center justify-between gap-4", children: [_jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Toggle, { checked: checked, onChange: onChange, label: label }), _jsx(Text, { className: "mt-0.5 ml-10 text-xs text-zinc-400 dark:text-zinc-400 truncate", children: desc })] }), showRollout && (_jsxs(Div, { className: "flex flex-col gap-1 w-28 shrink-0", children: [_jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "Rollout %" }), _jsx(Input, { type: "number", min: 0, max: 100, value: rollout ?? 100, onChange: (e) => onRolloutChange?.(Math.min(100, Math.max(0, Number(e.target.value)))), disabled: !checked, className: "w-full" })] }))] }));
|
|
45
45
|
}
|
|
46
46
|
export function AdminFeatureFlagsView({ labels = {}, renderFlags, ...rest }) {
|
|
47
47
|
const queryClient = useQueryClient();
|
|
@@ -12,6 +12,7 @@ import { toRecordArray, toRelativeDate, toStringValue, useAdminListingData, } fr
|
|
|
12
12
|
import { DataTable } from "./DataTable";
|
|
13
13
|
import { AdminFeatureEditorView } from "./AdminFeatureEditorView";
|
|
14
14
|
import { PRODUCT_FEATURE_SCOPE_TABS } from "../../products/constants/product-features.constants";
|
|
15
|
+
import { useBottomActions } from "../../layout";
|
|
15
16
|
const PAGE_SIZE = 50;
|
|
16
17
|
const DEFAULT_SORT = "displayOrder";
|
|
17
18
|
const DEFAULT_SCOPE = "platform";
|
|
@@ -26,7 +27,7 @@ const TAB_BASE_CLASS = "rounded-full px-3 py-1 text-xs font-medium border transi
|
|
|
26
27
|
const TAB_ACTIVE_CLASS = "bg-primary text-white border-primary";
|
|
27
28
|
const TAB_INACTIVE_CLASS = "border-zinc-300 dark:border-slate-600 text-zinc-700 dark:text-zinc-300 hover:bg-zinc-50 dark:hover:bg-slate-800";
|
|
28
29
|
const PAGINATION_BAR_CLASS = "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";
|
|
29
|
-
const ERROR_BANNER_CLASS = "mb-4 rounded-xl border border-red-200 bg-
|
|
30
|
+
const ERROR_BANNER_CLASS = "mb-4 rounded-xl border border-red-200 bg-error-surface px-4 py-3 text-sm text-error dark:border-red-900/60";
|
|
30
31
|
function mapFeatureRow(item, index) {
|
|
31
32
|
const productTypes = Array.isArray(item.productTypes)
|
|
32
33
|
? item.productTypes
|
|
@@ -88,6 +89,9 @@ export function AdminFeaturesView({ children, ...props }) {
|
|
|
88
89
|
return (_jsx(ListingViewShell, { portal: "admin", ...props, children: children }));
|
|
89
90
|
}
|
|
90
91
|
const tabClass = (value) => `${TAB_BASE_CLASS} ${scopeFilter === value ? TAB_ACTIVE_CLASS : TAB_INACTIVE_CLASS}`;
|
|
92
|
+
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
93
|
+
{ id: "delete", label: ACTIONS.ADMIN["delete-feature"].label, variant: "secondary", onClick: () => { selection.clearSelection(); } },
|
|
94
|
+
] } } : {});
|
|
91
95
|
return (_jsxs(Div, { className: "min-h-screen", children: [_jsx(ListingToolbar, { searchValue: searchInput, searchPlaceholder: "Search features by label", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get("sort") || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => {
|
|
92
96
|
table.set("sort", v);
|
|
93
97
|
}, showTableView: true, view: view, onViewChange: (v) => setView(v), onResetAll: resetAll, hasActiveState: hasActiveState, extra: _jsxs(Button, { size: "sm", onClick: openCreatePanel, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), "Add Feature"] }) }), _jsx(Row, { className: STICKY_TABS_CLASS, gap: "xs", children: PRODUCT_FEATURE_SCOPE_TABS.map((tab) => (_jsx("button", { type: "button", onClick: () => {
|
|
@@ -75,5 +75,5 @@ export function AdminGuideHubView({ permissions = [], isFullAdmin = false }) {
|
|
|
75
75
|
background: "linear-gradient(135deg,var(--appkit-color-primary-700,#4f46e5) 0%,var(--appkit-color-cobalt,#2563eb) 60%,var(--appkit-color-secondary-400,#7c3aed) 100%)",
|
|
76
76
|
}, children: [_jsxs(Div, { className: "flex items-center gap-3 mb-3", children: [_jsx(Div, { className: "flex-shrink-0 w-10 h-10 rounded-xl bg-white/20 flex items-center justify-center", children: _jsx(BookOpen, { className: "w-5 h-5 text-white" }) }), _jsx(Text, { className: "text-sm font-semibold text-white/80 uppercase tracking-widest", children: "Admin & Employee Guide" })] }), _jsx(Heading, { level: 1, className: "text-2xl md:text-3xl font-bold text-white mb-2", children: "LetItRip Internal Guide" }), _jsx(Text, { className: "text-white/80 text-base", children: "Everything you need to operate and manage LetItRip \u2014 India's largest collectibles marketplace." })] }) }), _jsx(Alert, { variant: "info", compact: true, children: "These guides describe expected platform behaviour. Real access to each section is enforced independently by the permission system \u2014 this page is reference only." }), !hasAny && (_jsx(Alert, { variant: "info", title: "Limited access", children: "Your permission set doesn't include read access to any admin sections yet. Contact your admin to request the permissions you need." })), hasAny && (_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "text-lg font-semibold text-[var(--appkit-color-text)] mb-4", children: "Guides" }), _jsx(Div, { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: visibleCards.map(({ Icon, title, description, href }) => (_jsxs("a", { href: href, className: "group flex flex-col gap-3 rounded-xl border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] p-5 hover:border-[var(--appkit-color-primary)] hover:shadow-md transition-all", children: [_jsxs(Div, { className: "flex items-center gap-3", children: [_jsx(Div, { className: "flex-shrink-0 w-9 h-9 rounded-lg flex items-center justify-center", style: {
|
|
77
77
|
background: "linear-gradient(135deg,var(--appkit-color-primary-700,#4f46e5) 0%,var(--appkit-color-cobalt,#2563eb) 100%)",
|
|
78
|
-
}, children: _jsx(Icon, { className: "w-4 h-4 text-white" }) }), _jsx(Text, { className: "font-semibold text-[var(--appkit-color-text)] group-hover:text-[var(--appkit-color-primary)] transition-colors", children: title })] }), _jsx(Text, { className: "text-sm text-[var(--appkit-color-text-muted)] leading-relaxed", children: description }), _jsx(Text, { className: "text-xs font-medium text-[var(--appkit-color-primary)] mt-auto", children: "Read guide \u2192" })] }, title))) })] })), _jsx(Section, { className: "rounded-2xl border border-amber-200 bg-
|
|
78
|
+
}, children: _jsx(Icon, { className: "w-4 h-4 text-white" }) }), _jsx(Text, { className: "font-semibold text-[var(--appkit-color-text)] group-hover:text-[var(--appkit-color-primary)] transition-colors", children: title })] }), _jsx(Text, { className: "text-sm text-[var(--appkit-color-text-muted)] leading-relaxed", children: description }), _jsx(Text, { className: "text-xs font-medium text-[var(--appkit-color-primary)] mt-auto", children: "Read guide \u2192" })] }, title))) })] })), _jsx(Section, { className: "rounded-2xl border border-amber-200 bg-warning-surface dark:border-amber-800 p-6", children: _jsxs(Div, { className: "flex items-start gap-3", children: [_jsx(AlertTriangle, { className: "w-5 h-5 text-warning flex-shrink-0 mt-0.5" }), _jsxs(Div, { children: [_jsx(Text, { className: "font-semibold text-amber-800 dark:text-amber-300 mb-1", children: "Remember: with great access comes responsibility" }), _jsx(Text, { className: "text-sm text-amber-700 dark:text-amber-400", children: "Admin actions are logged. Never access user PII (email, phone) without a legitimate support reason. Never grant capabilities or permissions without documented approval. When in doubt, escalate to a senior admin." })] })] }) })] }));
|
|
79
79
|
}
|
|
@@ -57,5 +57,5 @@ export function AdminHistoryView({ children, ...props }) {
|
|
|
57
57
|
if (hasChildren) {
|
|
58
58
|
return _jsx(ListingViewShell, { portal: "admin", ...props, children: children });
|
|
59
59
|
}
|
|
60
|
-
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: 0, searchValue: searchInput, searchPlaceholder: "Search by user ID", 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-
|
|
60
|
+
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: 0, searchValue: searchInput, searchPlaceholder: "Search by user ID", 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 user history records found" })) : (_jsx(AdminViewCards, { rows: rows, view: view, isLoading: isLoading, emptyLabel: "No user history records found", onRowClick: undefined, selectedIdSet: selection.selectedIdSet, onToggleSelect: selection.toggle }))] })] }));
|
|
61
61
|
}
|
|
@@ -64,5 +64,5 @@ export function AdminListingScaffold({ title, subtitle, actionLabel, actionHref,
|
|
|
64
64
|
} })), sortSlot: sortSlot ?? (_jsx(Button, { type: "button", variant: "outline", size: "sm", children: "Newest first" })), actionsSlot: actionsSlot ??
|
|
65
65
|
(actionLabel ? (actionHref ? (_jsx(Button, { type: "button", variant: "primary", size: "sm", onClick: () => {
|
|
66
66
|
window.location.href = actionHref;
|
|
67
|
-
}, children: actionLabel })) : (_jsx(Button, { type: "button", variant: "primary", size: "sm", children: actionLabel }))) : undefined), filterActiveCount: activeFilters?.length ?? 0, filterPendingCount: 0, errorSlot: errorMessage ? (_jsx(Div, { className: "rounded-xl border border-red-200 bg-
|
|
67
|
+
}, children: actionLabel })) : (_jsx(Button, { type: "button", variant: "primary", size: "sm", children: actionLabel }))) : undefined), filterActiveCount: activeFilters?.length ?? 0, filterPendingCount: 0, errorSlot: errorMessage ? (_jsx(Div, { className: "rounded-xl border border-red-200 bg-error-surface px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })) : undefined, children: hasChildren ? (children) : (_jsx(DataTable, { columns: columns ?? buildColumns(), rows: rows, isLoading: isLoading, emptyLabel: emptyLabel, getRowHref: getRowHref, renderRowActions: renderRowActions })) }));
|
|
68
68
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import React from "react";
|
|
4
|
-
import { Alert, Button, Div, Input, Select, StackedViewShell, Text, } from "../../../ui";
|
|
4
|
+
import { Alert, Button, Div, Input, Select, StackedViewShell, Text, useToast, } from "../../../ui";
|
|
5
5
|
import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
|
|
6
6
|
import { MediaUploadField, MediaUploadList, useMediaCleanup, useMediaUpload, } from "../../media";
|
|
7
7
|
const PREFIX_OPTIONS = [
|
|
@@ -79,6 +79,7 @@ export function AdminMediaView({ labels = {}, children, ...rest }) {
|
|
|
79
79
|
const stagedUrls = React.useMemo(() => Array.from(new Set([...heroStagedUrls, ...galleryStagedUrls])), [heroStagedUrls, galleryStagedUrls]);
|
|
80
80
|
const [operationMessage, setOperationMessage] = React.useState(null);
|
|
81
81
|
const [copiedUrl, setCopiedUrl] = React.useState(null);
|
|
82
|
+
const { showToast } = useToast();
|
|
82
83
|
const onUpload = React.useCallback(async (file) => {
|
|
83
84
|
setOperationMessage(null);
|
|
84
85
|
return upload(file, "admin/media", true);
|
|
@@ -98,21 +99,25 @@ export function AdminMediaView({ labels = {}, children, ...rest }) {
|
|
|
98
99
|
setHeroStagedUrls([]);
|
|
99
100
|
setGalleryStagedUrls([]);
|
|
100
101
|
setOperationMessage("Discarded staged media uploads.");
|
|
102
|
+
showToast("Staged uploads cleared.", "success");
|
|
101
103
|
}
|
|
102
|
-
catch {
|
|
104
|
+
catch (err) {
|
|
103
105
|
setOperationMessage("Failed to discard staged media uploads.");
|
|
106
|
+
showToast(err instanceof Error ? err.message : "Failed to clear uploads.", "error");
|
|
104
107
|
}
|
|
105
|
-
}, [cleanup, stagedUrls]);
|
|
108
|
+
}, [cleanup, stagedUrls, showToast]);
|
|
106
109
|
const copyToClipboard = React.useCallback(async (url) => {
|
|
107
110
|
try {
|
|
108
111
|
await navigator.clipboard.writeText(url);
|
|
109
112
|
setCopiedUrl(url);
|
|
110
113
|
setTimeout(() => setCopiedUrl(null), 2000);
|
|
114
|
+
showToast("Copied!", "success");
|
|
111
115
|
}
|
|
112
|
-
catch {
|
|
116
|
+
catch (err) {
|
|
113
117
|
setOperationMessage("Could not copy URL to clipboard.");
|
|
118
|
+
showToast(err instanceof Error ? err.message : "Failed to copy.", "error");
|
|
114
119
|
}
|
|
115
|
-
}, []);
|
|
120
|
+
}, [showToast]);
|
|
116
121
|
if (hasChildren) {
|
|
117
122
|
return (_jsx(StackedViewShell, { portal: "admin", ...rest, title: labels.title ?? "Media Library", sections: [children] }));
|
|
118
123
|
}
|
|
@@ -82,7 +82,7 @@ export function AdminNavigationView({ labels = {}, ...rest }) {
|
|
|
82
82
|
setEditing(null);
|
|
83
83
|
setDrawerOpen(true);
|
|
84
84
|
}, children: "+ New item" })] }, "header"),
|
|
85
|
-
sorted.length === 0 && !isLoading ? (_jsx(Text, { className: "text-sm text-zinc-400 dark:text-zinc-
|
|
85
|
+
sorted.length === 0 && !isLoading ? (_jsx(Text, { className: "text-sm text-zinc-400 dark:text-zinc-400 py-8 text-center", children: "No nav items yet. Click \"New item\" to add one." }, "empty")) : null,
|
|
86
86
|
_jsx("div", { className: "divide-y divide-zinc-200 dark:divide-zinc-700 rounded-lg border border-zinc-200 dark:border-zinc-700 overflow-hidden", children: sorted.map((item, idx) => (_jsx(NavItemRow, { item: item, idx: idx, total: sorted.length, reorderPending: reorderMutation.isPending, onMoveUp: handleMoveUp, onMoveDown: handleMoveDown, onVisibilityChange: (id, isVisible) => visibilityMutation.mutate({ id, isVisible }), onEdit: (i) => { setEditing(i); setDrawerOpen(true); }, onDelete: setDeleteTarget }, item.id))) }, "list"),
|
|
87
87
|
] }), _jsx(AdminNavEditorView, { open: drawerOpen, onClose: () => setDrawerOpen(false), onSaved: () => queryClient.invalidateQueries({ queryKey: ["admin", "navigation"] }), item: editing, parentOptions: parentOptions }), _jsx(ConfirmDeleteModal, { isOpen: Boolean(deleteTarget), onClose: () => setDeleteTarget(null), onConfirm: () => deleteMutation.mutate(deleteTarget.id), isDeleting: deleteMutation.isPending, title: "Delete nav item", message: `Remove "${deleteTarget?.label}" from navigation? This cannot be undone.` })] }));
|
|
88
88
|
}
|
|
@@ -6,6 +6,7 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
|
6
6
|
import { useUrlTable } from "../../../react/hooks/useUrlTable";
|
|
7
7
|
import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
|
|
8
8
|
import { BulkActionBar, Button, ConfirmDeleteModal, FilterChipGroup, ListingToolbar, ListingViewShell, Pagination, RowActionMenu, useToast, } from "../../../ui";
|
|
9
|
+
import { useBottomActions } from "../../layout";
|
|
9
10
|
import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
10
11
|
import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
|
|
11
12
|
import { ADMIN_NEWSLETTER_STATUS_TABS } from "../constants/filter-tabs";
|
|
@@ -23,7 +24,7 @@ const STATUS_OPTIONS = ADMIN_NEWSLETTER_STATUS_TABS;
|
|
|
23
24
|
function NewsletterFilterDrawer({ filterOpen, setFilterOpen, activeFilterCount, clearFilters, pendingFilters, setPendingFilters, applyFilters, }) {
|
|
24
25
|
if (!filterOpen)
|
|
25
26
|
return null;
|
|
26
|
-
return (_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-
|
|
27
|
+
return (_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})` : ""] }) })] })] }));
|
|
27
28
|
}
|
|
28
29
|
export function AdminNewsletterView({ children, onBulkUnsubscribe, ...props }) {
|
|
29
30
|
const hasChildren = React.Children.count(children) > 0;
|
|
@@ -132,10 +133,11 @@ export function AdminNewsletterView({ children, onBulkUnsubscribe, ...props }) {
|
|
|
132
133
|
onClick: async () => { await onBulkUnsubscribe(selection.selectedIds); selection.clearSelection(); },
|
|
133
134
|
}] : []),
|
|
134
135
|
];
|
|
136
|
+
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: bulkActions } } : {});
|
|
135
137
|
if (hasChildren) {
|
|
136
138
|
return _jsx(ListingViewShell, { portal: "admin", ...props, children: children });
|
|
137
139
|
}
|
|
138
|
-
return (_jsxs(_Fragment, { children: [selection.selectedCount > 0 && bulkActions.length > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), _jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search by email or source", 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, extra: _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: handleExportCsv, children: ACTIONS.ADMIN["export-csv"].label }) }), 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-
|
|
140
|
+
return (_jsxs(_Fragment, { children: [selection.selectedCount > 0 && bulkActions.length > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), _jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search by email or source", 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, extra: _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: handleExportCsv, children: ACTIONS.ADMIN["export-csv"].label }) }), 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 })), _jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No subscribers found", renderRowActions: (row) => {
|
|
139
141
|
const nr = row;
|
|
140
142
|
return (_jsx(RowActionMenu, { actions: [
|
|
141
143
|
{
|
|
@@ -12,6 +12,7 @@ import { ROW_ACTION_META, ROW_ACTION_ID } from "../../products/constants/action-
|
|
|
12
12
|
import { toRecordArray, toRelativeDate, toStringValue, useAdminListingData, } from "../hooks/useAdminListingData";
|
|
13
13
|
import { DataTable } from "./DataTable";
|
|
14
14
|
import { apiClient } from "../../../http";
|
|
15
|
+
import { useBottomActions } from "../../layout";
|
|
15
16
|
const PAGE_SIZE = 25;
|
|
16
17
|
const FILTER_KEYS = ["type"];
|
|
17
18
|
const DEFAULT_SORT = "-createdAt";
|
|
@@ -26,7 +27,7 @@ const NOTIF_TYPES = [
|
|
|
26
27
|
function NotificationsFilterDrawer({ filterOpen, setFilterOpen, activeFilterCount, clearFilters, pendingFilters, setPendingFilters, applyFilters, }) {
|
|
27
28
|
if (!filterOpen)
|
|
28
29
|
return null;
|
|
29
|
-
return (_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-
|
|
30
|
+
return (_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: _jsxs("div", { className: "space-y-2", children: [_jsx(Text, { className: "text-xs font-semibold uppercase tracking-widest text-zinc-500 dark:text-zinc-400", children: "Type" }), _jsx("div", { className: "flex flex-wrap gap-2", children: NOTIF_TYPES.map((opt) => (_jsx("button", { type: "button", onClick: () => setPendingFilters((p) => ({ ...p, type: opt === "All" ? "" : opt })), className: `rounded-full px-3 py-1 text-xs font-medium border transition-colors ${(pendingFilters.type || "All") === opt ? "bg-primary text-white border-primary" : "border-zinc-300 dark:border-slate-600 text-zinc-700 dark:text-zinc-300 hover:bg-zinc-50 dark:hover:bg-slate-800"}`, children: opt }, opt))) })] }) }), _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})` : ""] }) })] })] }));
|
|
30
31
|
}
|
|
31
32
|
export function AdminNotificationsView({ children, ...props }) {
|
|
32
33
|
const hasChildren = React.Children.count(children) > 0;
|
|
@@ -121,8 +122,12 @@ export function AdminNotificationsView({ children, ...props }) {
|
|
|
121
122
|
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search by title or user ID", 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 }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
122
123
|
{ id: ROW_ACTION_ID.MARK_READ, label: ACTIONS.ADMIN["mark-read"].label, variant: "primary", onClick: () => { selection.clearSelection(); } },
|
|
123
124
|
{ id: ROW_ACTION_ID.DELETE, label: ACTIONS.ADMIN["delete-notification"].label, variant: "secondary", onClick: () => { selection.clearSelection(); } },
|
|
124
|
-
] }), 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-
|
|
125
|
+
] }), 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 })), _jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No notifications found", renderRowActions: (row) => {
|
|
125
126
|
const nr = row;
|
|
127
|
+
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
128
|
+
{ id: ROW_ACTION_ID.MARK_READ, label: ACTIONS.ADMIN["mark-read"].label, variant: "primary", onClick: () => { selection.clearSelection(); } },
|
|
129
|
+
{ id: ROW_ACTION_ID.DELETE, label: ACTIONS.ADMIN["delete-notification"].label, variant: "secondary", onClick: () => { selection.clearSelection(); } },
|
|
130
|
+
] } } : {});
|
|
126
131
|
return (_jsx(RowActionMenu, { actions: [
|
|
127
132
|
{ label: ACTIONS.ADMIN["resend-notification"].label, onClick: () => resendMutation.mutate(nr.id) },
|
|
128
133
|
{ label: ROW_ACTION_META[ROW_ACTION_ID.DELETE].label, destructive: ROW_ACTION_META[ROW_ACTION_ID.DELETE].destructive, onClick: () => setDeleteTarget(nr) },
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { ShoppingBag, Hash, Scale, Wallet, RotateCcw, DollarSign, Gavel } from "lucide-react";
|
|
3
|
-
import { Div, Heading, Text, Section } from "../../../ui";
|
|
3
|
+
import { Div, Heading, Span, Text, Section } from "../../../ui";
|
|
4
4
|
import { GC } from "../../_guide-cls";
|
|
5
5
|
export function AdminOrdersGuideView() {
|
|
6
6
|
return (_jsxs(Div, { className: "space-y-8 pb-10 max-w-3xl mx-auto", children: [_jsxs(Section, { children: [_jsxs(Div, { className: "flex items-center gap-3 mb-2", children: [_jsx(Div, { className: "flex-shrink-0 w-10 h-10 rounded-xl flex items-center justify-center", style: { background: "linear-gradient(135deg,var(--appkit-color-primary-700,#4f46e5) 0%,var(--appkit-color-cobalt,#2563eb) 100%)" }, children: _jsx(ShoppingBag, { className: "w-5 h-5 text-white" }) }), _jsx(Text, { className: "text-sm font-semibold text-[var(--appkit-color-text-muted)] uppercase tracking-widest", children: "Admin Guide" })] }), _jsx(Heading, { level: 1, className: "text-2xl md:text-3xl font-bold text-[var(--appkit-color-text)] mb-2", children: "Orders & Finance" }), _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", children: "Order statuses, payouts, disputes, returns, and commission math on LetItRip." })] }), [
|
|
@@ -22,19 +22,19 @@ export function AdminOrdersGuideView() {
|
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
Icon: Scale, title: "Intervening in a Dispute",
|
|
25
|
-
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsx("li", { children: "Admin steps in when: seller is unresponsive for 3+ days on a return, or buyer escalates via support ticket." }), _jsxs("li", { children: ["Admin dispute tools: ", _jsx("
|
|
25
|
+
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsx("li", { children: "Admin steps in when: seller is unresponsive for 3+ days on a return, or buyer escalates via support ticket." }), _jsxs("li", { children: ["Admin dispute tools: ", _jsx(Span, { weight: "bold", children: "force-accept return" }), " (moves to REFUNDED and withholds seller payout), ", _jsx(Span, { weight: "bold", children: "platform credit" }), " (future feature)."] }), _jsx("li", { children: "Document your reasoning in the support ticket before taking any force action." })] })),
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
28
|
Icon: Wallet, title: "Payouts",
|
|
29
|
-
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx("
|
|
29
|
+
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Payout cycle" }), ": Weekly. All DELIVERED orders (minus platform commission) are batched into a single payout per store."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Status flow" }), ": PENDING \u2192 PROCESSING \u2192 PAID / FAILED."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "FAILED payout" }), ": Check the store's ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "payoutDetails" }), " \u2014 UPI VPA or bank details may be stale. Contact the seller via their store email before retrying."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "ordersIncluded" }), ": Array of order IDs bundled in this payout batch \u2014 use to audit which orders are covered."] })] })),
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
Icon: RotateCcw, title: "Return Requests",
|
|
33
|
-
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsx("li", { children: "Admin can view the return reason and attached photos on the order detail page." }), _jsxs("li", { children: [_jsx("
|
|
33
|
+
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsx("li", { children: "Admin can view the return reason and attached photos on the order detail page." }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "When to override a seller rejection" }), ": Only when photographic evidence clearly supports the buyer's claim of a significant not-as-described defect. Do not override for buyer's remorse."] }), _jsx("li", { children: "After admin override: refund is issued automatically via Razorpay (3\u20137 business days for card, 1\u20132 for UPI). Seller payout for that order is withheld." })] })),
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
Icon: DollarSign, title: "Commission & Settlement Math",
|
|
37
|
-
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx("
|
|
37
|
+
content: (_jsxs("ul", { className: GC.listMuted, children: [_jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "platformFee" }), ": Set in ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "siteSettings.fees.platformFee" }), " (percentage). Applied to the order's item subtotal."] }), _jsxs("li", { children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "customCommissionRate" }), ": Stored on ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "StoreDocument" }), " for stores with the ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "lower_commission_rate" }), " capability. Overrides the platform default for that store."] }), _jsx("li", { children: "Payout = order subtotal \u00D7 (1 \u2212 commission rate). Shipping fees are passed through to the seller at cost." })] })),
|
|
38
38
|
},
|
|
39
39
|
{
|
|
40
40
|
Icon: Gavel, title: "Auction Settlement",
|
|
@@ -14,6 +14,7 @@ import { ADMIN_ORDER_STATUS_TABS } from "../constants/filter-tabs";
|
|
|
14
14
|
import { toRecordArray, toRelativeDate, toRupees, toStringValue, useAdminListingData, } from "../hooks/useAdminListingData";
|
|
15
15
|
import { DataTable } from "./DataTable";
|
|
16
16
|
import { AdminOrderEditorView } from "./AdminOrderEditorView";
|
|
17
|
+
import { useBottomActions } from "../../layout";
|
|
17
18
|
const PAGE_SIZE = 25;
|
|
18
19
|
const FILTER_KEYS = ["status"];
|
|
19
20
|
const DEFAULT_SORT = "-createdAt";
|
|
@@ -25,7 +26,7 @@ const STATUS_OPTIONS = ADMIN_ORDER_STATUS_TABS;
|
|
|
25
26
|
function OrdersFilterDrawer({ filterOpen, setFilterOpen, activeFilterCount, clearFilters, pendingFilters, setPendingFilters, applyFilters, }) {
|
|
26
27
|
if (!filterOpen)
|
|
27
28
|
return null;
|
|
28
|
-
return (_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-
|
|
29
|
+
return (_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})` : ""] }) })] })] }));
|
|
29
30
|
}
|
|
30
31
|
export function AdminOrdersView({ children, ...props }) {
|
|
31
32
|
const hasChildren = React.Children.count(children) > 0;
|
|
@@ -102,6 +103,14 @@ export function AdminOrdersView({ children, ...props }) {
|
|
|
102
103
|
if (hasChildren) {
|
|
103
104
|
return _jsx(ListingViewShell, { portal: "admin", ...props, children: children });
|
|
104
105
|
}
|
|
106
|
+
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
107
|
+
{ id: "mark-shipped", label: ACTIONS.ADMIN["mark-shipped"].label, variant: "secondary", onClick: () => { for (const id of selection.selectedIds)
|
|
108
|
+
void handleQuickStatus(id, "SHIPPED"); selection.clearSelection(); } },
|
|
109
|
+
{ id: "mark-delivered", label: ACTIONS.ADMIN["mark-delivered"].label, variant: "primary", onClick: () => { for (const id of selection.selectedIds)
|
|
110
|
+
void handleQuickStatus(id, "DELIVERED"); selection.clearSelection(); } },
|
|
111
|
+
{ id: "mark-cancelled", label: ACTIONS.ADMIN["cancel-order"].label, variant: "danger", onClick: () => { for (const id of selection.selectedIds)
|
|
112
|
+
void handleQuickStatus(id, "CANCELLED"); selection.clearSelection(); } },
|
|
113
|
+
] } } : {});
|
|
105
114
|
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search orders, buyers, or tracking IDs", 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 }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
106
115
|
{ id: "mark-shipped", label: ACTIONS.ADMIN["mark-shipped"].label, variant: "secondary", onClick: () => { for (const id of selection.selectedIds)
|
|
107
116
|
void handleQuickStatus(id, "SHIPPED"); selection.clearSelection(); } },
|
|
@@ -109,7 +118,7 @@ export function AdminOrdersView({ children, ...props }) {
|
|
|
109
118
|
void handleQuickStatus(id, "DELIVERED"); selection.clearSelection(); } },
|
|
110
119
|
{ id: "mark-cancelled", label: ACTIONS.ADMIN["cancel-order"].label, variant: "danger", onClick: () => { for (const id of selection.selectedIds)
|
|
111
120
|
void handleQuickStatus(id, "CANCELLED"); selection.clearSelection(); } },
|
|
112
|
-
] }), 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-
|
|
121
|
+
] }), 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 orders found", selectedIds: selection.selectedIdSet, onToggleSelect: selection.toggle, onToggleSelectAll: (next) => next ? selection.setSelectedIds(rows.map(r => r.id)) : selection.clearSelection(), renderRowActions: (row) => (_jsx(QuickEditMenu, { actions: [
|
|
113
122
|
{
|
|
114
123
|
label: "View full details",
|
|
115
124
|
onClick: () => { setSelectedRow(row); setDrawerOpen(true); },
|
|
@@ -12,6 +12,7 @@ import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
|
|
|
12
12
|
import { toRecordArray, toRelativeDate, toRupees, toStringValue, useAdminListingData, } from "../hooks/useAdminListingData";
|
|
13
13
|
import { DataTable } from "./DataTable";
|
|
14
14
|
import { apiClient } from "../../../http";
|
|
15
|
+
import { useBottomActions } from "../../layout";
|
|
15
16
|
const PAGE_SIZE = 25;
|
|
16
17
|
const FILTER_KEYS = ["status"];
|
|
17
18
|
const DEFAULT_SORT = "-createdAt";
|
|
@@ -24,7 +25,7 @@ const STATUS_OPTIONS = ADMIN_PAYOUT_STATUS_TABS;
|
|
|
24
25
|
function PayoutsFilterDrawer({ filterOpen, setFilterOpen, activeFilterCount, clearFilters, pendingFilters, setPendingFilters, applyFilters, }) {
|
|
25
26
|
if (!filterOpen)
|
|
26
27
|
return null;
|
|
27
|
-
return (_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-
|
|
28
|
+
return (_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})` : ""] }) })] })] }));
|
|
28
29
|
}
|
|
29
30
|
export function AdminPayoutsView({ children, ...props }) {
|
|
30
31
|
const hasChildren = React.Children.count(children) > 0;
|
|
@@ -132,8 +133,11 @@ export function AdminPayoutsView({ children, ...props }) {
|
|
|
132
133
|
}
|
|
133
134
|
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search stores, payout IDs, or order groups", 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, extra: _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: handleExportCsv, children: ACTIONS.ADMIN["export-csv"].label }) }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
134
135
|
{ id: "mark-paid", label: ACTIONS.ADMIN["mark-paid"].label, variant: "primary", onClick: () => { selection.clearSelection(); } },
|
|
135
|
-
] }), 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-
|
|
136
|
+
] }), 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 })), _jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No payouts found", renderRowActions: (row) => {
|
|
136
137
|
const pr = row;
|
|
138
|
+
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
139
|
+
{ id: "mark-paid", label: ACTIONS.ADMIN["mark-paid"].label, variant: "primary", onClick: () => { selection.clearSelection(); } },
|
|
140
|
+
] } } : {});
|
|
137
141
|
return (_jsx(RowActionMenu, { actions: [
|
|
138
142
|
{
|
|
139
143
|
label: ACTIONS.ADMIN["grant-payout"].label,
|
|
@@ -11,6 +11,7 @@ import { ADMIN_PRODUCT_STATUS_TABS } from "../constants/filter-tabs";
|
|
|
11
11
|
import { ROUTES } from "../../../constants";
|
|
12
12
|
import { toRecordArray, toRelativeDate, toRupees, toStringValue, useAdminListingData, } from "../hooks/useAdminListingData";
|
|
13
13
|
import { DataTable } from "./DataTable";
|
|
14
|
+
import { useBottomActions } from "../../layout";
|
|
14
15
|
const PAGE_SIZE = 25;
|
|
15
16
|
const FILTER_KEYS = ["status"];
|
|
16
17
|
const DEFAULT_SORT = "-createdAt";
|
|
@@ -137,6 +138,9 @@ export function AdminPrizeDrawsView({ children, ...props }) {
|
|
|
137
138
|
if (hasChildren) {
|
|
138
139
|
return (_jsx(ListingViewShell, { portal: "admin", ...props, children: children }));
|
|
139
140
|
}
|
|
141
|
+
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
142
|
+
{ id: "delete", label: ACTIONS.ADMIN["delete-prize-draw"].label, variant: "secondary", onClick: () => { selection.clearSelection(); } },
|
|
143
|
+
] } } : {});
|
|
140
144
|
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search prize draws by name or store\u2026", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get("sort") || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => {
|
|
141
145
|
table.set("sort", v);
|
|
142
146
|
}, showTableView: true, view: view, onViewChange: (v) => setView(v), onResetAll: resetAll, hasActiveState: hasActiveState }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
@@ -5,6 +5,7 @@ import { Plus, X } from "lucide-react";
|
|
|
5
5
|
import { useUrlTable } from "../../../react/hooks/useUrlTable";
|
|
6
6
|
import { usePanelUrlSync } from "../../../react/hooks/use-panel-url-sync";
|
|
7
7
|
import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
|
|
8
|
+
import { useBottomActions } from "../../layout";
|
|
8
9
|
import { BulkActionBar, Button, FilterChipGroup, Heading, ListingToolbar, ListingViewShell, Pagination, SideDrawer, Text, Toggle, useToast } from "../../../ui";
|
|
9
10
|
import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
10
11
|
import { ADMIN_PRODUCT_STATUS_TABS, ADMIN_PRODUCT_LISTING_TYPE_TABS, } from "../constants/filter-tabs";
|
|
@@ -59,7 +60,7 @@ function buildBaseColumns() {
|
|
|
59
60
|
function ProductsFilterDrawer({ filterOpen, setFilterOpen, activeFilterCount, clearFilters, pendingFilters, setPendingFilters, applyFilters, }) {
|
|
60
61
|
if (!filterOpen)
|
|
61
62
|
return null;
|
|
62
|
-
return (_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-
|
|
63
|
+
return (_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" }) })] })] }), _jsxs("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(FilterChipGroup, { label: "Type", tabs: TYPE_OPTIONS, value: pendingFilters.type ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, type: 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})` : ""] }) })] })] }));
|
|
63
64
|
}
|
|
64
65
|
export function AdminProductsView({ children, actionHref, getRowHref, ...props }) {
|
|
65
66
|
const hasChildren = React.Children.count(children) > 0;
|
|
@@ -111,6 +112,9 @@ export function AdminProductsView({ children, actionHref, getRowHref, ...props }
|
|
|
111
112
|
"Pre-orders": "listingType==pre-order",
|
|
112
113
|
"Prize Draws": "listingType==prize-draw",
|
|
113
114
|
Products: "listingType==standard",
|
|
115
|
+
Classifieds: "listingType==classified",
|
|
116
|
+
"Digital Codes": "listingType==digital-code",
|
|
117
|
+
"Live Items": "listingType==live",
|
|
114
118
|
};
|
|
115
119
|
const typeFilter = TYPE_FILTER[typeRaw];
|
|
116
120
|
if (typeFilter)
|
|
@@ -179,6 +183,14 @@ export function AdminProductsView({ children, actionHref, getRowHref, ...props }
|
|
|
179
183
|
className: "w-56",
|
|
180
184
|
render: (row) => (_jsx("div", { className: "flex flex-wrap gap-x-3 gap-y-1", onClick: (e) => e.stopPropagation(), onKeyDown: (e) => e.stopPropagation(), role: "presentation", children: FLAG_DEFS.map(({ key, label }) => (_jsx(Toggle, { size: "sm", label: label, checked: !!row[key], onChange: (v) => { void handleToggle(row.id, key, v); } }, key))) })),
|
|
181
185
|
};
|
|
186
|
+
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
187
|
+
{ id: "feature", label: ACTIONS.ADMIN["toggle-featured"].label, variant: "secondary", onClick: () => { for (const id of selection.selectedIds)
|
|
188
|
+
void handleToggle(id, "featured", !rows.find(r => r.id === id)?.featured); selection.clearSelection(); } },
|
|
189
|
+
{ id: "promote", label: ACTIONS.ADMIN["toggle-promoted"].label, variant: "secondary", onClick: () => { for (const id of selection.selectedIds)
|
|
190
|
+
void handleToggle(id, "isPromoted", !rows.find(r => r.id === id)?.isPromoted); selection.clearSelection(); } },
|
|
191
|
+
{ id: "sale", label: ACTIONS.ADMIN["toggle-on-sale"].label, variant: "secondary", onClick: () => { for (const id of selection.selectedIds)
|
|
192
|
+
void handleToggle(id, "isOnSale", !rows.find(r => r.id === id)?.isOnSale); selection.clearSelection(); } },
|
|
193
|
+
] } } : {});
|
|
182
194
|
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(Heading, { level: 1, className: "sr-only", children: "Products" }), _jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search products, SKUs, or seller names", 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: [
|
|
183
195
|
{ label: "Show sold", active: showSold, onChange: (next) => table.set("showSold", next ? "true" : "") },
|
|
184
196
|
], extra: _jsxs(Button, { size: "sm", onClick: openCreatePanel, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), "Add Product"] }) }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
@@ -188,7 +200,7 @@ export function AdminProductsView({ children, actionHref, getRowHref, ...props }
|
|
|
188
200
|
void handleToggle(id, "isPromoted", !rows.find(r => r.id === id)?.isPromoted); selection.clearSelection(); } },
|
|
189
201
|
{ id: "sale", label: ACTIONS.ADMIN["toggle-on-sale"].label, variant: "secondary", onClick: () => { for (const id of selection.selectedIds)
|
|
190
202
|
void handleToggle(id, "isOnSale", !rows.find(r => r.id === id)?.isOnSale); selection.clearSelection(); } },
|
|
191
|
-
] }), 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-
|
|
203
|
+
] }), 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, columns: [...buildBaseColumns(), flagColumn], isLoading: isLoading, emptyLabel: "No products found", onRowClick: (row) => openEditPanel(row.id), selectedIds: selection.selectedIdSet, onToggleSelect: selection.toggle, onToggleSelectAll: (next) => next ? selection.setSelectedIds(rows.map(r => r.id)) : selection.clearSelection(), renderRowActions: (row) => (_jsx(QuickEditMenu, { actions: [
|
|
192
204
|
{
|
|
193
205
|
label: ACTIONS.ADMIN["approve-product"].label,
|
|
194
206
|
onClick: () => handleQuickEdit(row.id, { status: "published" }),
|
|
@@ -86,7 +86,7 @@ export function AdminReturnRequestsView({ children: _children }) {
|
|
|
86
86
|
const currentPage = table.getNumber("page", 1);
|
|
87
87
|
const totalPages = Math.ceil(total / PAGE_SIZE);
|
|
88
88
|
const selection = useBulkSelection({ items: rows ?? [], keyExtractor: (r) => r.id });
|
|
89
|
-
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: 0, searchValue: searchInput, searchPlaceholder: "Search by order ID or buyer", 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-
|
|
89
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: 0, searchValue: searchInput, searchPlaceholder: "Search by order ID or buyer", 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 })), _jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No return requests", renderRowActions: (row) => {
|
|
90
90
|
const rr = row;
|
|
91
91
|
return (_jsx(RowActionMenu, { actions: [
|
|
92
92
|
{
|