@mohasinac/appkit 2.8.2 → 2.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_internal/client/features/classified/ClassifiedDetailView.js +7 -1
- package/dist/_internal/client/features/digital-code/CodeRevealPanel.js +4 -1
- package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.js +7 -1
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +3 -2
- package/dist/_internal/client/features/live/LiveItemDetailView.js +11 -2
- package/dist/_internal/client/scaffolds/AppShell.js +2 -1
- package/dist/_internal/client/scaffolds/DashboardScaffold.js +2 -1
- package/dist/_internal/server/features/checkout/actions.js +40 -39
- package/dist/_internal/shared/actions/action-registry.js +6 -0
- package/dist/_internal/shared/config/index.d.ts +1 -1
- package/dist/_internal/shared/config/schema.d.ts +0 -8
- package/dist/client-entry.d.ts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/configs/next.js +12 -22
- package/dist/constants/api-endpoints.d.ts +6 -0
- package/dist/constants/api-endpoints.js +2 -0
- package/dist/core/hooks/useSiteSettings.d.ts +1 -1
- package/dist/features/about/components/AboutView.js +5 -2
- package/dist/features/about/components/FAQPageView.js +3 -3
- package/dist/features/about/components/FeesView.js +13 -5
- package/dist/features/about/components/HelpPageView.js +9 -5
- package/dist/features/about/components/HowAuctionsWorkView.js +9 -5
- package/dist/features/about/components/HowCheckoutWorksView.js +9 -5
- package/dist/features/about/components/HowOffersWorkView.js +10 -5
- package/dist/features/about/components/HowOrdersWorkView.js +10 -5
- package/dist/features/about/components/HowPayoutsWorkView.js +9 -5
- package/dist/features/about/components/HowPreOrdersWorkView.js +9 -5
- package/dist/features/about/components/HowReviewsWorkView.js +9 -5
- package/dist/features/about/components/PolicyPageView.js +3 -3
- package/dist/features/about/components/PublicProfileView.js +11 -4
- package/dist/features/about/components/SecurityPrivacyView.js +8 -4
- package/dist/features/about/components/ShippingPolicyView.js +3 -2
- package/dist/features/about/components/TrackOrderView.js +2 -2
- package/dist/features/about/components/UnauthorizedView.js +3 -3
- package/dist/features/account/components/AddressBook.js +1 -1
- package/dist/features/account/components/AddressForm.js +2 -2
- package/dist/features/account/components/AddressInlineSelect.d.ts +24 -0
- package/dist/features/account/components/AddressInlineSelect.js +78 -0
- package/dist/features/account/components/AddressSelectorCreate.d.ts +2 -1
- package/dist/features/account/components/AddressSelectorCreate.js +5 -32
- package/dist/features/account/components/AddressesIndexListing.js +3 -3
- package/dist/features/account/components/ChatWindow.js +2 -1
- package/dist/features/account/components/NotificationBell.js +13 -7
- package/dist/features/account/components/NotificationPreferencesPanel.js +4 -1
- package/dist/features/account/components/UserOffersPanel.js +2 -1
- package/dist/features/account/components/UserSidebar.js +11 -7
- package/dist/features/account/components/UserSupportView.js +13 -4
- package/dist/features/account/components/index.d.ts +2 -0
- package/dist/features/account/components/index.js +1 -0
- package/dist/features/account/hooks/useAccount.d.ts +2 -2
- package/dist/features/account/hooks/useAddressSelector.d.ts +1 -1
- package/dist/features/account/hooks/useAddresses.d.ts +2 -2
- package/dist/features/account/hooks/useNotifications.d.ts +1 -1
- package/dist/features/account/hooks/useProfile.d.ts +1 -1
- package/dist/features/account/hooks/usePublicProfile.d.ts +2 -2
- package/dist/features/addresses/repository/addresses.repository.d.ts +1 -0
- package/dist/features/addresses/repository/addresses.repository.js +13 -0
- package/dist/features/admin/components/AdminAdEditorView.js +8 -5
- package/dist/features/admin/components/AdminAddressEditorView.js +5 -5
- package/dist/features/admin/components/AdminAdsView.js +10 -7
- package/dist/features/admin/components/AdminBlogEditorView.js +15 -9
- package/dist/features/admin/components/AdminBrandEditorView.js +10 -4
- package/dist/features/admin/components/AdminBrandsView.js +4 -4
- package/dist/features/admin/components/AdminBundleEditorView.js +4 -5
- package/dist/features/admin/components/AdminBundlesView.js +3 -3
- package/dist/features/admin/components/AdminCarouselEditorView.js +6 -3
- package/dist/features/admin/components/AdminCarouselView.js +6 -6
- package/dist/features/admin/components/AdminCatalogGuideView.js +2 -1
- package/dist/features/admin/components/AdminCategoriesView.js +5 -5
- package/dist/features/admin/components/AdminCategoryEditorView.js +11 -5
- package/dist/features/admin/components/AdminContactEditorView.js +8 -1
- package/dist/features/admin/components/AdminCouponEditorView.js +23 -5
- package/dist/features/admin/components/AdminEmployeeEditorView.js +7 -4
- package/dist/features/admin/components/AdminFaqEditorView.js +9 -3
- package/dist/features/admin/components/AdminFaqsView.js +4 -4
- package/dist/features/admin/components/AdminFeatureEditorView.js +7 -1
- package/dist/features/admin/components/AdminFeatureFlagsView.js +4 -1
- package/dist/features/admin/components/AdminFilterBar.js +4 -4
- package/dist/features/admin/components/AdminGroupedListingsView.js +65 -30
- package/dist/features/admin/components/AdminGuideHubView.js +4 -1
- package/dist/features/admin/components/AdminMediaView.js +4 -1
- package/dist/features/admin/components/AdminNavigationView.js +7 -4
- package/dist/features/admin/components/AdminNotificationsView.js +2 -2
- package/dist/features/admin/components/AdminOrderEditorView.js +2 -2
- package/dist/features/admin/components/AdminPageHeader.js +5 -2
- package/dist/features/admin/components/AdminPrizeDrawsView.js +5 -5
- package/dist/features/admin/components/AdminProductEditorView.js +12 -5
- package/dist/features/admin/components/AdminProductsView.js +4 -4
- package/dist/features/admin/components/AdminReviewsView.js +2 -2
- package/dist/features/admin/components/AdminScammerEditorView.js +6 -2
- package/dist/features/admin/components/AdminScammersView.js +3 -3
- package/dist/features/admin/components/AdminSectionsView.js +20 -22
- package/dist/features/admin/components/AdminSessionsManager.js +2 -1
- package/dist/features/admin/components/AdminSessionsView.js +2 -2
- package/dist/features/admin/components/AdminSidebar.js +11 -7
- package/dist/features/admin/components/AdminSiteConfigGuideView.js +2 -1
- package/dist/features/admin/components/AdminSiteSettingsView.js +5 -1
- package/dist/features/admin/components/AdminStoreAddressesView.js +2 -2
- package/dist/features/admin/components/AdminStoreEditorView.js +5 -5
- package/dist/features/admin/components/AdminSublistingCategoryEditorView.js +3 -3
- package/dist/features/admin/components/AdminSupportTicketDetailView.js +10 -3
- package/dist/features/admin/components/AdminSupportTicketsView.js +3 -3
- package/dist/features/admin/components/AdminTrustGuideView.js +3 -3
- package/dist/features/admin/components/AdminUsersGuideView.js +3 -3
- package/dist/features/admin/components/AdminViewCards.js +12 -6
- package/dist/features/admin/components/BrandQuickCreateForm.js +2 -2
- package/dist/features/admin/components/CategoryQuickCreateForm.js +2 -2
- package/dist/features/admin/components/DashboardStats.js +9 -3
- package/dist/features/admin/components/DataListingView.js +3 -3
- package/dist/features/admin/components/DataTable.js +11 -7
- package/dist/features/admin/components/DrawerFormFooter.js +2 -2
- package/dist/features/admin/components/QuickEditMenu.js +2 -1
- package/dist/features/admin/components/analytics/AdminAnalyticsCharts.js +5 -1
- package/dist/features/admin/hooks/useAdmin.d.ts +1 -1
- package/dist/features/admin/hooks/useAdminSectionsListing.d.ts +1 -1
- package/dist/features/admin/hooks/useChat.d.ts +1 -1
- package/dist/features/auctions/components/AuctionBidsTable.js +4 -1
- package/dist/features/auctions/components/AuctionDetailPageView.js +14 -6
- package/dist/features/auctions/components/CollapsibleBidHistory.js +5 -1
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +9 -3
- package/dist/features/auctions/components/MarketplaceAuctionGrid.js +8 -2
- package/dist/features/auctions/components/PlaceBidFormClient.js +4 -1
- package/dist/features/auctions/hooks/useAuctions.d.ts +8 -8
- package/dist/features/auth/components/RegisterForm.js +2 -2
- package/dist/features/auth/components/VerifyEmailView.js +5 -2
- package/dist/features/auth/hooks/useAuth.d.ts +2 -2
- package/dist/features/before-after/components/BeforeAfterSlider.js +1 -1
- package/dist/features/blog/components/BlogFeaturedCard.js +8 -1
- package/dist/features/blog/components/BlogIndexListing.js +11 -5
- package/dist/features/blog/components/BlogListView.js +11 -3
- package/dist/features/blog/components/BlogPostView.js +10 -3
- package/dist/features/cart/components/CartDrawer.js +11 -3
- package/dist/features/cart/components/CartSummary.js +2 -2
- package/dist/features/cart/components/CheckoutOtpModal.js +2 -1
- package/dist/features/cart/hooks/useCart.d.ts +1 -1
- package/dist/features/cart/hooks/useCartQuery.d.ts +1 -1
- package/dist/features/cart/hooks/useCheckoutReadQueries.d.ts +2 -2
- package/dist/features/cart/hooks/useOrder.d.ts +2 -2
- package/dist/features/categories/components/BrandDetailPageView.js +5 -2
- package/dist/features/categories/components/BrandDetailTabs.js +5 -1
- package/dist/features/categories/components/BundleDetailView.js +6 -3
- package/dist/features/categories/components/BundleDynamicRuleEditor.js +3 -1
- package/dist/features/categories/components/BundleItemsPicker.js +10 -3
- package/dist/features/categories/components/CategoriesIndexListing.js +12 -6
- package/dist/features/categories/components/CategoryBundlesListing.js +5 -2
- package/dist/features/categories/components/CategoryDetailPageView.js +6 -2
- package/dist/features/categories/components/CategoryDetailTabs.js +5 -1
- package/dist/features/categories/components/CategoryForm.js +6 -3
- package/dist/features/categories/components/CategoryGrid.js +9 -2
- package/dist/features/categories/components/CategoryProductsListing.js +10 -4
- package/dist/features/categories/components/CategorySelectorCreate.js +3 -3
- package/dist/features/categories/components/CategorySortSelect.js +1 -1
- package/dist/features/categories/components/CategoryStoresListing.js +3 -3
- package/dist/features/categories/components/CategoryTableColumns.js +10 -6
- package/dist/features/categories/components/CategoryTree.js +1 -1
- package/dist/features/categories/hooks/useCategories.d.ts +3 -3
- package/dist/features/categories/hooks/useCategorySelector.d.ts +3 -3
- package/dist/features/categories/hooks/useCategoryTree.d.ts +1 -1
- package/dist/features/checkout/hooks/useCheckoutApi.d.ts +2 -2
- package/dist/features/classified/components/ClassifiedFilters.js +2 -2
- package/dist/features/classified/components/ClassifiedIndexListing.js +9 -3
- package/dist/features/collections/components/CollectionCard.js +2 -1
- package/dist/features/collections/hooks/useCollections.d.ts +2 -2
- package/dist/features/contact/components/ContactForm.js +4 -2
- package/dist/features/contact/components/ContactInfoSidebar.js +4 -1
- package/dist/features/copilot/components/AdminCopilotView.js +13 -5
- package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +9 -3
- package/dist/features/events/components/AdminEventEditorView.js +62 -40
- package/dist/features/events/components/AdminEventEntriesView.js +9 -6
- package/dist/features/events/components/EventCard.js +7 -1
- package/dist/features/events/components/EventFormDrawer.js +2 -1
- package/dist/features/events/components/EventLeaderboard.js +4 -4
- package/dist/features/events/components/EventOfferCard.js +4 -1
- package/dist/features/events/components/EventParticipateView.js +3 -2
- package/dist/features/events/components/EventPollWidget.js +6 -5
- package/dist/features/events/components/EventRaffleEntryForm.js +5 -2
- package/dist/features/events/components/EventRaffleWinnerView.js +7 -1
- package/dist/features/events/components/EventRafflesSection.js +2 -2
- package/dist/features/events/components/EventSaleBanner.js +5 -2
- package/dist/features/events/components/EventsIndexListing.js +8 -2
- package/dist/features/events/components/EventsListView.js +4 -1
- package/dist/features/events/components/SpinWheelView.js +7 -2
- package/dist/features/events/hooks/useEvent.d.ts +3 -3
- package/dist/features/events/hooks/useEvents.d.ts +1 -1
- package/dist/features/events/schemas/firestore.d.ts +1 -0
- package/dist/features/events/types/index.d.ts +1 -0
- package/dist/features/faq/components/ContactCTA.js +4 -1
- package/dist/features/faq/components/FAQCategorySidebar.js +2 -2
- package/dist/features/faq/components/FAQHelpfulButtons.js +8 -5
- package/dist/features/faq/components/FAQPageContent.js +5 -5
- package/dist/features/faq/components/FAQSortDropdown.js +2 -2
- package/dist/features/faq/hooks/useFAQs.d.ts +1 -1
- package/dist/features/faq/hooks/useFaqList.d.ts +15 -15
- package/dist/features/filters/AsyncFacetSection.js +4 -2
- package/dist/features/filters/FilterFacetSection.js +14 -6
- package/dist/features/filters/RangeFilter.js +4 -2
- package/dist/features/filters/SwitchFilter.js +2 -1
- package/dist/features/forms/Checkbox.js +1 -1
- package/dist/features/forms/Radio.js +1 -1
- package/dist/features/forms/Slider.js +1 -1
- package/dist/features/homepage/components/AdSlot.js +4 -4
- package/dist/features/homepage/components/AdvertisementBanner.js +13 -4
- package/dist/features/homepage/components/AnnouncementBar.js +2 -1
- package/dist/features/homepage/components/BeforeAfterCard.js +8 -2
- package/dist/features/homepage/components/BrandsSection.js +6 -3
- package/dist/features/homepage/components/CTABannerSection.js +2 -2
- package/dist/features/homepage/components/CharacterHotspot.js +5 -2
- package/dist/features/homepage/components/CharacterHotspotForm.js +8 -4
- package/dist/features/homepage/components/CustomCardsSection.js +13 -7
- package/dist/features/homepage/components/CustomerReviewsSection.js +9 -3
- package/dist/features/homepage/components/FAQSection.js +7 -4
- package/dist/features/homepage/components/FeaturedBundlesSection.js +8 -2
- package/dist/features/homepage/components/FeaturedResultsSection.js +1 -1
- package/dist/features/homepage/components/GoogleReviewsSection.js +14 -8
- package/dist/features/homepage/components/HeroCarousel.js +1 -1
- package/dist/features/homepage/components/HomepageSkeleton.js +7 -1
- package/dist/features/homepage/components/HowItWorksInfoView.js +2 -2
- package/dist/features/homepage/components/HowItWorksSection.js +2 -2
- package/dist/features/homepage/components/NewsletterBanner.js +3 -2
- package/dist/features/homepage/components/NewsletterSection.js +5 -2
- package/dist/features/homepage/components/PromoGrid.js +4 -1
- package/dist/features/homepage/components/SectionCarousel.js +7 -4
- package/dist/features/homepage/components/SecurityHighlightsSection.js +3 -3
- package/dist/features/homepage/components/ShopByCategorySection.js +10 -4
- package/dist/features/homepage/components/SiteFeaturesSection.js +5 -2
- package/dist/features/homepage/components/SocialFeedSection.js +4 -4
- package/dist/features/homepage/components/SocialPostCard.js +6 -3
- package/dist/features/homepage/components/TrustFeaturesSection.js +5 -5
- package/dist/features/homepage/components/TrustIndicatorsSection.js +5 -2
- package/dist/features/homepage/components/WelcomeSection.js +1 -1
- package/dist/features/homepage/components/WhatsAppCommunitySection.js +3 -3
- package/dist/features/homepage/hooks/useBlogArticles.d.ts +1 -1
- package/dist/features/homepage/hooks/useFeaturedAuctions.d.ts +1 -1
- package/dist/features/homepage/hooks/useFeaturedPreOrders.d.ts +1 -1
- package/dist/features/homepage/hooks/useFeaturedProducts.d.ts +1 -1
- package/dist/features/homepage/hooks/useFeaturedStores.d.ts +1 -1
- package/dist/features/homepage/hooks/useHeroCarousel.d.ts +1 -1
- package/dist/features/homepage/hooks/useHomepageEvents.d.ts +1 -1
- package/dist/features/homepage/hooks/useHomepageReviews.d.ts +1 -1
- package/dist/features/homepage/hooks/useHomepageSections.d.ts +1 -1
- package/dist/features/homepage/hooks/useTopBrands.d.ts +1 -1
- package/dist/features/homepage/hooks/useTopCategories.d.ts +1 -1
- package/dist/features/layout/AppLayoutShell.js +2 -1
- package/dist/features/layout/BackToTop.js +1 -1
- package/dist/features/layout/BottomActions.js +4 -3
- package/dist/features/layout/BottomNavItem.js +1 -1
- package/dist/features/layout/BottomSheet.js +4 -1
- package/dist/features/layout/FooterLayout.js +1 -1
- package/dist/features/layout/NavbarLayout.js +4 -1
- package/dist/features/layout/SidebarLayout.js +5 -2
- package/dist/features/live/components/LiveItemFilters.js +2 -2
- package/dist/features/live/components/LiveItemsIndexListing.js +9 -3
- package/dist/features/loyalty/components/CoinsDisplay.js +4 -2
- package/dist/features/loyalty/hooks/useLoyaltyBalance.d.ts +1 -1
- package/dist/features/media/AvatarUpload.js +2 -2
- package/dist/features/media/MediaLightbox.js +3 -2
- package/dist/features/media/modals/VideoThumbnailSelector.js +4 -1
- package/dist/features/media/modals/VideoTrimModal.js +1 -1
- package/dist/features/media/upload/CameraCapture.js +1 -1
- package/dist/features/media/upload/ImageUpload.js +4 -1
- package/dist/features/media/upload/MediaUploadField.js +11 -2
- package/dist/features/media/upload/MediaUploadList.js +5 -1
- package/dist/features/orders/components/MarketplaceOrderCard.js +2 -2
- package/dist/features/orders/components/OrdersList.js +2 -1
- package/dist/features/orders/components/RefundHistoryTable.js +4 -1
- package/dist/features/orders/components/RefundRequestView.js +2 -1
- package/dist/features/orders/hooks/useOrders.d.ts +2 -2
- package/dist/features/payments/hooks/usePayments.d.ts +1 -1
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +5 -1
- package/dist/features/pre-orders/components/PreOrderActionsClient.js +3 -3
- package/dist/features/pre-orders/components/PreOrderBadge.js +2 -1
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +16 -7
- package/dist/features/pre-orders/components/PreOrdersIndexListing.js +32 -24
- package/dist/features/pre-orders/hooks/usePreOrders.d.ts +2 -2
- package/dist/features/products/columns/productTableColumns.js +9 -4
- package/dist/features/products/components/AuctionsIndexListing.js +9 -3
- package/dist/features/products/components/BidHistory.js +4 -4
- package/dist/features/products/components/CompareOverlay.js +10 -2
- package/dist/features/products/components/CustomFieldsEditor.js +2 -1
- package/dist/features/products/components/CustomSectionTabContent.js +2 -2
- package/dist/features/products/components/CustomSectionsEditor.js +3 -2
- package/dist/features/products/components/GroupSettingsPanel.js +34 -26
- package/dist/features/products/components/MakeOfferButton.js +6 -2
- package/dist/features/products/components/MakeOfferForm.js +2 -1
- package/dist/features/products/components/MarketplaceBundleCard.js +6 -3
- package/dist/features/products/components/MarketplacePrizeDrawCard.js +3 -2
- package/dist/features/products/components/PlaceBidForm.js +2 -1
- package/dist/features/products/components/PrizeDrawCollage.js +6 -2
- package/dist/features/products/components/PrizeDrawDetailPageView.js +6 -1
- package/dist/features/products/components/PrizeDrawItemsEditor.js +4 -2
- package/dist/features/products/components/PrizeDrawsIndexListing.js +6 -3
- package/dist/features/products/components/PrizeDrawsSection.js +2 -2
- package/dist/features/products/components/PrizeRevealModal.js +5 -1
- package/dist/features/products/components/ProductDetailPageView.js +32 -16
- package/dist/features/products/components/ProductFeatureBadges.js +9 -9
- package/dist/features/products/components/ProductForm.d.ts +11 -1
- package/dist/features/products/components/ProductForm.js +10 -5
- package/dist/features/products/components/ProductGalleryClient.js +8 -4
- package/dist/features/products/components/ProductGradingTab.js +4 -1
- package/dist/features/products/components/ProductGrid.js +35 -14
- package/dist/features/products/components/ProductInfo.js +2 -1
- package/dist/features/products/components/ProductTabs.js +2 -1
- package/dist/features/products/components/ProductTabsShell.js +5 -1
- package/dist/features/products/components/ProductsIndexListing.js +32 -24
- package/dist/features/products/components/ProductsIndexPageView.js +2 -2
- package/dist/features/products/components/RelatedProducts.js +3 -3
- package/dist/features/products/components/ShowGroupSection.js +10 -6
- package/dist/features/products/components/SublistingCarouselSection.js +7 -3
- package/dist/features/products/components/SublistingCategorySelect.d.ts +3 -1
- package/dist/features/products/components/SublistingCategorySelect.js +4 -37
- package/dist/features/products/constants/action-defs.js +3 -3
- package/dist/features/products/hooks/useProductDetail.d.ts +1 -1
- package/dist/features/products/hooks/useRelatedProducts.d.ts +1 -1
- package/dist/features/promotions/components/CouponCard.js +5 -3
- package/dist/features/promotions/components/CouponsIndexListing.js +7 -3
- package/dist/features/promotions/hooks/usePromotions.d.ts +2 -2
- package/dist/features/promotions/repository/coupons.repository.d.ts +8 -0
- package/dist/features/promotions/repository/coupons.repository.js +2 -0
- package/dist/features/reviews/components/ReviewDetailPageView.js +3 -3
- package/dist/features/reviews/components/ReviewDetailShell.js +15 -3
- package/dist/features/reviews/components/ReviewSummary.js +4 -2
- package/dist/features/reviews/components/ReviewsIndexListing.js +8 -2
- package/dist/features/reviews/components/ReviewsList.js +1 -1
- package/dist/features/reviews/hooks/useReviews.d.ts +2 -2
- package/dist/features/scams/components/ScamAwarenessModal.js +2 -2
- package/dist/features/scams/components/ScamProfileView.js +3 -3
- package/dist/features/scams/components/ScamRegistryView.js +6 -4
- package/dist/features/search/components/Search.js +9 -6
- package/dist/features/search/components/SearchFiltersRow.js +1 -1
- package/dist/features/search/components/SearchResultsSection.js +1 -1
- package/dist/features/search/hooks/useSearch.d.ts +2 -2
- package/dist/features/seller/components/CouponInlineSelect.d.ts +22 -0
- package/dist/features/seller/components/CouponInlineSelect.js +103 -0
- package/dist/features/seller/components/GroupInlineSelect.d.ts +23 -0
- package/dist/features/seller/components/GroupInlineSelect.js +80 -0
- package/dist/features/seller/components/PhysicalLocationModal.js +2 -1
- package/dist/features/seller/components/PrintCenterView.js +2 -1
- package/dist/features/seller/components/ProductInlineSelect.d.ts +24 -0
- package/dist/features/seller/components/ProductInlineSelect.js +42 -0
- package/dist/features/seller/components/QuickProductForm.js +4 -1
- package/dist/features/seller/components/SellerAddressesView.js +8 -3
- package/dist/features/seller/components/SellerAnalyticsAlertsView.js +6 -3
- package/dist/features/seller/components/SellerAnalyticsView.js +2 -2
- package/dist/features/seller/components/SellerBidsView.js +7 -7
- package/dist/features/seller/components/SellerBundlesView.js +2 -1
- package/dist/features/seller/components/SellerCouponEditorView.d.ts +2 -0
- package/dist/features/seller/components/SellerCouponEditorView.js +15 -3
- package/dist/features/seller/components/SellerCouponsView.js +1 -1
- package/dist/features/seller/components/SellerDashboardView.js +2 -2
- package/dist/features/seller/components/SellerDigitalCodesView.js +2 -2
- package/dist/features/seller/components/SellerGoogleReviewsView.js +2 -2
- package/dist/features/seller/components/SellerGroupedListingsView.js +5 -5
- package/dist/features/seller/components/SellerOrdersView.js +13 -10
- package/dist/features/seller/components/SellerPayoutMethodsView.js +5 -4
- package/dist/features/seller/components/SellerPayoutRequestView.js +5 -1
- package/dist/features/seller/components/SellerPayoutSettingsView.js +5 -2
- package/dist/features/seller/components/SellerPreOrdersView.js +6 -6
- package/dist/features/seller/components/SellerPrizeDrawsView.js +6 -6
- package/dist/features/seller/components/SellerProductShell.js +1 -1
- package/dist/features/seller/components/SellerProductsCards.js +4 -1
- package/dist/features/seller/components/SellerProductsView.js +5 -5
- package/dist/features/seller/components/SellerReviewsView.js +7 -3
- package/dist/features/seller/components/SellerShippingConfigsView.js +4 -4
- package/dist/features/seller/components/SellerShippingView.js +1 -1
- package/dist/features/seller/components/SellerSidebar.js +15 -8
- package/dist/features/seller/components/SellerStoreCategoriesView.js +1 -1
- package/dist/features/seller/components/SellerStorefrontView.js +2 -2
- package/dist/features/seller/components/SellerTemplatesView.js +7 -4
- package/dist/features/seller/components/SublistingInlineSelect.d.ts +19 -0
- package/dist/features/seller/components/SublistingInlineSelect.js +83 -0
- package/dist/features/seller/components/analytics/SellerTopProducts.js +1 -1
- package/dist/features/seller/components/index.d.ts +8 -0
- package/dist/features/seller/components/index.js +4 -0
- package/dist/features/seller/hooks/useSellerPayouts.d.ts +3 -3
- package/dist/features/seller/hooks/useSellerStore.d.ts +6 -6
- package/dist/features/seller/hooks/useSellerStorefront.d.ts +2 -2
- package/dist/features/shell/FormShell.js +10 -2
- package/dist/features/shell/QuickFormDrawer.js +5 -5
- package/dist/features/shell/StepForm.js +6 -6
- package/dist/features/site-settings/components/ActionPermissionsManager.js +8 -4
- package/dist/features/site-settings/components/NavPermissionsManager.js +7 -4
- package/dist/features/stores/components/InteractiveStoreCard.js +5 -1
- package/dist/features/stores/components/StoreAboutView.js +4 -1
- package/dist/features/stores/components/StoreAddressSelectorCreate.d.ts +2 -1
- package/dist/features/stores/components/StoreAddressSelectorCreate.js +5 -31
- package/dist/features/stores/components/StoreAuctionsListing.js +6 -3
- package/dist/features/stores/components/StoreGuideHubView.js +5 -2
- package/dist/features/stores/components/StoreHeader.js +8 -1
- package/dist/features/stores/components/StorePreOrdersListing.js +6 -3
- package/dist/features/stores/components/StoreProductsListing.js +6 -3
- package/dist/features/stores/components/StoreReviewsListing.js +8 -2
- package/dist/features/stores/components/StoresIndexListing.js +12 -6
- package/dist/features/stores/hooks/useStoreAddressSelector.d.ts +1 -1
- package/dist/features/stores/hooks/useStores.d.ts +6 -6
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +7 -1
- package/dist/features/whatsapp-bot/components/WhatsAppChatButton.js +2 -1
- package/dist/features/wishlist/components/WishlistPage.js +2 -1
- package/dist/features/wishlist/hooks/useUserWishlist.d.ts +15 -15
- package/dist/features/wishlist/hooks/useWishlist.d.ts +1 -1
- package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.js +13 -1
- package/dist/next/components/GlobalError.js +2 -2
- package/dist/next/routing/route-map.d.ts +2 -0
- package/dist/next/routing/route-map.js +1 -0
- package/dist/react/ErrorBoundary.js +2 -2
- package/dist/styles.css +2 -1
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/DataTable.js +17 -16
- package/dist/ui/components/DateInput.js +2 -2
- package/dist/ui/components/DetailPageGallery.js +4 -1
- package/dist/ui/components/DetailPageTabs.js +6 -2
- package/dist/ui/components/ImageLightbox.js +5 -3
- package/dist/ui/components/Input.js +6 -3
- package/dist/ui/components/Layout.d.ts +4 -0
- package/dist/ui/components/Layout.js +1 -1
- package/dist/ui/components/Layout.style.css +1 -0
- package/dist/ui/components/ListingFilterDrawer.js +4 -1
- package/dist/ui/components/ListingLayout.js +9 -8
- package/dist/ui/components/ListingToolbar.js +5 -1
- package/dist/ui/components/PaginatedSelect.d.ts +1 -2
- package/dist/ui/components/PaginatedSelect.js +1 -2
- package/dist/ui/components/Radio.js +1 -1
- package/dist/ui/components/Select.js +2 -1
- package/dist/ui/components/Slider.js +1 -1
- package/dist/ui/components/VacationBanner.js +2 -1
- package/dist/ui/components/surface-tokens.d.ts +1 -0
- package/dist/ui/components/surface-tokens.js +1 -0
- package/package.json +11 -2
|
@@ -2,13 +2,21 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import Link from "next/link";
|
|
3
3
|
import { productRepository } from "../../../repositories";
|
|
4
4
|
import { listBidsByProduct } from "../../auctions/actions/bid-actions";
|
|
5
|
+
const __P = {
|
|
6
|
+
p3: "p-3",
|
|
7
|
+
p4: "p-4",
|
|
8
|
+
p5: "p-5",
|
|
9
|
+
};
|
|
5
10
|
const CLS_BREADCRUMB_LINK = "hover:text-primary-600 transition-colors";
|
|
11
|
+
const CLS_LIVE_BADGE = "inline-block rounded-full bg-amber-100 dark:bg-amber-900/30 px-2.5 py-0.5 text-amber-700 dark:text-amber-300";
|
|
12
|
+
const CLS_STAR_ON = "text-amber-400";
|
|
13
|
+
const CLS_STAR_OFF = "text-zinc-200 dark:text-zinc-700";
|
|
6
14
|
import { ROUTES } from "../../../next";
|
|
7
15
|
import { getDefaultCurrency } from "../../../core/baseline-resolver";
|
|
8
16
|
import { formatCurrency } from "../../../utils/number.formatter";
|
|
9
17
|
import { normalizeRichTextHtml } from "../../../utils/string.formatter";
|
|
10
18
|
import { safeDisplayName } from "../../../security";
|
|
11
|
-
import { Button, Container, Div, Heading, Input, Main, RichText, Row, Section, Span, Stack, Text, } from "../../../ui";
|
|
19
|
+
import { Button, Container, Div, Heading, Input, Main, Nav, RichText, Row, Section, Span, Stack, Text, Ul, Li, Dl, Dt, Dd, } from "../../../ui";
|
|
12
20
|
import { AuctionDetailView } from "../../products/components/AuctionDetailView";
|
|
13
21
|
import { ProductTabsShell } from "../../products/components/ProductTabsShell";
|
|
14
22
|
import { CustomSectionTabContent } from "../../products/components/CustomSectionTabContent";
|
|
@@ -32,13 +40,13 @@ function toDescriptionHtml(raw) {
|
|
|
32
40
|
}
|
|
33
41
|
function renderAuctionInfoPanel(props) {
|
|
34
42
|
const { title, currentBid, currency, bidCount, isEnded, endDate, buyNowPrice, featured, freeShipping, condition, category, categoryName, brand, brandSlug, productFeatures, features, descriptionHtml, safeSeller, storeHref } = props;
|
|
35
|
-
return (_jsxs(Stack, { gap: "md", children: [_jsxs(Div, { children: [_jsxs(Row, { gap: "xs", className: "mb-2 flex-wrap", children: [_jsx(Span, {
|
|
43
|
+
return (_jsxs(Stack, { gap: "md", children: [_jsxs(Div, { children: [_jsxs(Row, { gap: "xs", className: "mb-2 flex-wrap", children: [_jsx(Span, { size: "xs", weight: "semibold", className: CLS_LIVE_BADGE, children: "\uD83C\uDFF7\uFE0F Live Auction" }), isEnded ? (_jsx(Span, { size: "xs", weight: "medium", className: "inline-block rounded-full bg-error-surface px-2.5 py-0.5 text-error", children: "Ended" })) : (_jsx(Span, { size: "xs", weight: "medium", className: "inline-block rounded-full bg-success-surface px-2.5 py-0.5 text-success", children: "Active" }))] }), _jsx(Heading, { level: 1, className: "text-xl font-bold leading-snug text-zinc-900 dark:text-zinc-50 sm:text-2xl", children: title })] }), _jsxs(Div, { children: [_jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 mb-0.5", children: "Current bid" }), _jsxs(Row, { align: "center", gap: "sm", wrap: true, children: [_jsx(Span, { weight: "bold", className: "text-2xl text-primary-600 dark:text-primary-400", children: formatCurrency(currentBid, currency) }), _jsxs(Span, { size: "sm", weight: "medium", className: "rounded-full bg-zinc-100 dark:bg-zinc-800 px-3 py-1 text-zinc-600 dark:text-zinc-300", children: [bidCount, " ", bidCount === 1 ? "bid" : "bids"] })] }), endDate && _jsxs(Text, { className: "mt-1.5 text-sm text-zinc-500 dark:text-zinc-400", children: [isEnded ? "Ended" : "Ends", " ", _jsx(Span, { weight: "medium", className: "text-zinc-700 dark:text-zinc-300", children: endDate.toLocaleString() })] })] }), buyNowPrice !== null && !isEnded && (_jsxs(Row, { align: "center", gap: "sm", className: "rounded-lg border border-primary-200 dark:border-primary-800 bg-primary-50 dark:bg-primary-900/20 px-3 py-2", children: [_jsx(Span, { size: "xs", className: "text-zinc-600 dark:text-zinc-400", children: "Buy Now:" }), _jsx(Span, { size: "base", weight: "bold", className: "text-primary-700 dark:text-primary-300", children: formatCurrency(buyNowPrice, currency) })] })), _jsx(ProductFeatureBadges, { featured: featured, freeShipping: freeShipping, condition: condition ?? undefined, labels: { featured: "Featured", fasterDelivery: "Faster Delivery", ratedSeller: "Rated Seller", condition: "Condition", conditionNew: "New", conditionUsed: "Used", conditionBroken: "For Parts", conditionRefurbished: "Refurbished", returnable: "Returnable", freeShipping: "Free Shipping", codAvailable: "Cash on Delivery", wishlistCount: (n) => `${n} wishlisted`, categoryProductCount: (n, cat) => `${n} in ${cat}` } }), (categoryName || category || brand) && (_jsxs(Row, { gap: "sm", wrap: true, children: [category && _jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(category)), className: "inline-flex items-center rounded-full border border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-800/50 px-2.5 py-1 text-xs font-medium text-zinc-600 dark:text-zinc-300 transition-colors hover:border-primary-300 hover:bg-primary-50 hover:text-primary-700 dark:hover:border-primary-700/60 dark:hover:bg-primary-900/20 dark:hover:text-primary-400", children: categoryName || category }), !category && categoryName && _jsx(Span, { size: "xs", weight: "medium", className: "inline-flex items-center rounded-full border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-800/50 px-2.5 py-1 text-zinc-500 dark:text-zinc-400", children: categoryName }), brand && brandSlug && _jsx(Link, { href: String(ROUTES.PUBLIC.BRAND_DETAIL(brandSlug)), className: "inline-flex items-center rounded-full border border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-800/50 px-2.5 py-1 text-xs font-medium text-zinc-600 dark:text-zinc-300 transition-colors hover:border-primary-300 hover:bg-primary-50 hover:text-primary-700 dark:hover:border-primary-700/60 dark:hover:bg-primary-900/20 dark:hover:text-primary-400", children: brand }), brand && !brandSlug && _jsx(Span, { size: "xs", weight: "medium", className: "inline-flex items-center rounded-full border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-800/50 px-2.5 py-1 text-zinc-500 dark:text-zinc-400", children: brand })] })), productFeatures && features.length > 0 && _jsx(FeatureBadgeList, { productFeatureIds: features, features: productFeatures }), !productFeatures && features.length > 0 && (_jsxs(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 px-4 py-3", children: [_jsx(Text, { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-zinc-500 dark:text-zinc-400", children: "About this item" }), _jsx(Ul, { className: "space-y-1.5", children: features.map((f, i) => _jsxs(Li, { className: "flex items-start gap-2 text-sm text-zinc-700 dark:text-zinc-300", children: [_jsx(Span, { className: "mt-0.5 flex-shrink-0 text-primary-500", children: "\u2022" }), f] }, i)) })] })), descriptionHtml && _jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "text-sm leading-relaxed text-zinc-600 dark:text-zinc-400 line-clamp-4" }), safeSeller && (_jsx(Div, { className: `rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 ${__P.p3}`, children: _jsxs(Row, { justify: "between", align: "center", children: [_jsxs(Div, { children: [_jsx(Text, { className: "text-[10px] uppercase tracking-wide text-zinc-400 dark:text-zinc-400 mb-0.5", children: "Listed by" }), _jsx(Text, { className: "text-sm font-semibold text-zinc-800 dark:text-zinc-200", children: safeSeller })] }), storeHref && _jsx(Link, { href: storeHref, className: "shrink-0 rounded-lg bg-primary/10 dark:bg-primary/20 px-3 py-1.5 text-xs font-semibold text-primary-700 dark:text-primary-300 hover:bg-primary/20 dark:hover:bg-primary/30 transition-colors", children: "Visit Store \u2192" })] }) }))] }));
|
|
36
44
|
}
|
|
37
45
|
function renderAuctionStoreReviews(storeReviews) {
|
|
38
46
|
if (storeReviews.length === 0)
|
|
39
47
|
return null;
|
|
40
48
|
const avg = storeReviews.reduce((s, r) => s + r.rating, 0) / storeReviews.length;
|
|
41
|
-
return (_jsxs(Section, { className: "mt-10", children: [_jsx(Heading, { level: 2, className: "mb-2 text-xl font-semibold text-zinc-900 dark:text-zinc-50", children: "Store Reviews" }), _jsxs(Div, { className: "mb-4 flex items-center gap-3", children: [_jsx(Span, { className: "text-3xl
|
|
49
|
+
return (_jsxs(Section, { className: "mt-10", children: [_jsx(Heading, { level: 2, className: "mb-2 text-xl font-semibold text-zinc-900 dark:text-zinc-50", children: "Store Reviews" }), _jsxs(Div, { className: "mb-4 flex items-center gap-3", children: [_jsx(Span, { weight: "bold", className: "text-3xl text-zinc-900 dark:text-zinc-50", children: avg.toFixed(1) }), _jsxs(Div, { children: [_jsx(Row, { gap: "xs", children: [1, 2, 3, 4, 5].map((star) => _jsx(Span, { className: star <= Math.round(avg) ? CLS_STAR_ON : CLS_STAR_OFF, children: "\u2605" }, star)) }), _jsxs(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: [storeReviews.length, " review", storeReviews.length !== 1 ? "s" : ""] })] })] }), _jsx(Stack, { gap: "sm", children: storeReviews.slice(0, 10).map((review) => (_jsxs(Div, { surface: "card", padding: "sm", className: "space-y-1.5", children: [_jsx(Row, { justify: "between", align: "center", children: _jsxs(Row, { gap: "xs", align: "center", children: [_jsx(Span, { size: "sm", weight: "medium", className: "text-zinc-800 dark:text-zinc-200", children: review.userName }), _jsx(Row, { gap: "xs", children: [1, 2, 3, 4, 5].map((star) => _jsx(Span, { size: "xs", className: star <= review.rating ? CLS_STAR_ON : CLS_STAR_OFF, children: "\u2605" }, star)) })] }) }), review.title && _jsx(Text, { className: "text-sm font-semibold text-zinc-800 dark:text-zinc-100", children: review.title }), _jsx(Text, { className: "text-sm text-zinc-600 dark:text-zinc-400 leading-relaxed", children: review.comment }), _jsx(Text, { className: "text-xs text-zinc-400 dark:text-zinc-400", children: review.productTitle })] }, review.id))) })] }));
|
|
42
50
|
}
|
|
43
51
|
export async function AuctionDetailPageView({ id, initialAuction, onPlaceBid, onBuyNow, productFeatures }) {
|
|
44
52
|
const product = initialAuction !== undefined
|
|
@@ -117,11 +125,11 @@ export async function AuctionDetailPageView({ id, initialAuction, onPlaceBid, on
|
|
|
117
125
|
price: typeof p.price === "number" ? p.price : undefined,
|
|
118
126
|
storeId: typeof p.storeId === "string" ? p.storeId : undefined,
|
|
119
127
|
storeName: typeof p.storeName === "string" ? p.storeName : undefined,
|
|
120
|
-
} }), _jsxs(Container, { size: "xl", className: "px-4 py-6", children: [_jsxs(
|
|
128
|
+
} }), _jsxs(Container, { size: "xl", className: "px-4 py-6", children: [_jsxs(Div, { className: "mb-4 flex items-center justify-between flex-wrap gap-2", children: [_jsxs(Nav, { "aria-label": "Breadcrumb", className: "flex items-center gap-1.5 text-xs text-zinc-500 dark:text-zinc-400 flex-wrap", children: [_jsx(Link, { href: String(ROUTES.HOME), className: CLS_BREADCRUMB_LINK, children: "Home" }), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.AUCTIONS), className: CLS_BREADCRUMB_LINK, children: "Auctions" }), category && (_jsxs(_Fragment, { children: [_jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(category)), className: CLS_BREADCRUMB_LINK, children: categoryName || category })] })), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Span, { className: "text-zinc-700 dark:text-zinc-300 truncate max-w-[200px]", children: title })] }), _jsx(ShareButton, { title: title })] }), _jsx(AuctionDetailView, { renderGallery: () => (_jsx(ProductGalleryClient, { images: images, productName: title })), renderInfo: () => renderAuctionInfoPanel({ title, currentBid, currency, bidCount, isEnded, endDate, buyNowPrice, featured, freeShipping, condition, category, categoryName, brand, brandSlug, productFeatures, features, descriptionHtml, safeSeller, storeHref }), renderBidForm: () => onPlaceBid ? (_jsx(Div, { id: "auction-bid-form", className: "space-y-3", children: _jsxs(Div, { className: `rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 ${__P.p5} space-y-3`, children: [_jsxs(Row, { justify: "between", align: "baseline", children: [_jsx(Span, { size: "xl", weight: "bold", className: "text-primary-600 dark:text-primary-400", children: formatCurrency(currentBid, currency) }), _jsxs(Span, { size: "xs", className: "text-zinc-500 dark:text-zinc-400", children: [bidCount, " ", bidCount === 1 ? "bid" : "bids", " \u00B7 min increment ", formatCurrency(minBidIncrement, currency)] })] }), _jsx(PlaceBidModalButton, { productId: String(product.id), currentBid: currentBid, startingBid: startingBid, minBidIncrement: minBidIncrement, currency: currency, isEnded: isEnded, buyNowPrice: buyNowPrice, bidsHaveStarted: bidsHaveStarted, bidCount: bidCount, tags: tags, onPlaceBid: onPlaceBid, onBuyNow: onBuyNow, triggerClassName: "w-full" })] }) })) : (
|
|
121
129
|
/* Read-only bid panel — shown when no bid action is wired (preview/demo) */
|
|
122
|
-
_jsxs(Div, { className:
|
|
130
|
+
_jsxs(Div, { className: `rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 ${__P.p5} space-y-4`, children: [_jsx(Div, { className: "space-y-1", children: _jsxs(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: ["Starting bid: ", formatCurrency(startingBid, currency), " \u00B7 min increment ", formatCurrency(minBidIncrement, currency)] }) }), _jsxs(Stack, { gap: "sm", children: [_jsx(Input, { type: "number", placeholder: `At least ${formatCurrency(currentBid + minBidIncrement, currency)}`, min: currentBid + minBidIncrement, "aria-label": "Your bid amount", disabled: isEnded }), _jsx(Button, { variant: "primary", size: "md", className: "w-full", disabled: isEnded, children: isEnded ? "Auction Ended" : "Place Bid" }), buyNowPrice !== null && !isEnded && !bidsHaveStarted && (_jsxs(Button, { variant: "secondary", size: "md", className: "w-full", disabled: true, children: ["Buy Now \u2014 ", formatCurrency(buyNowPrice, currency)] }))] }), tags.length > 0 && (_jsx(Div, { className: "border-t border-zinc-200 dark:border-zinc-700 pt-4", children: _jsx(Row, { wrap: true, gap: "xs", children: tags.map((tag) => (_jsx(Span, { size: "xs", className: "rounded-full bg-zinc-100 dark:bg-zinc-800 px-2.5 py-1 text-zinc-600 dark:text-zinc-300", children: tag }, tag))) }) }))] })), renderMobileBidForm: () => !isEnded && onPlaceBid ? (_jsxs(Div, { className: `lg:hidden rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 ${__P.p4} space-y-3`, children: [_jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Span, { size: "base", weight: "bold", className: "text-primary-600 dark:text-primary-400", children: formatCurrency(currentBid, currency) }), _jsxs(Span, { size: "xs", className: "text-zinc-500 dark:text-zinc-400", children: [bidCount, " bids"] })] }), _jsx(PlaceBidModalButton, { productId: String(product.id), currentBid: currentBid, startingBid: startingBid, minBidIncrement: minBidIncrement, currency: currency, isEnded: isEnded, buyNowPrice: buyNowPrice, bidsHaveStarted: bidsHaveStarted, bidCount: bidCount, tags: tags, onPlaceBid: onPlaceBid, onBuyNow: onBuyNow, triggerClassName: "w-full" })] })) : !isEnded ? (_jsxs(Div, { className: `rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 ${__P.p4} lg:hidden`, children: [_jsxs(Row, { align: "center", gap: "sm", className: "mb-3", children: [_jsx(Span, { size: "base", weight: "bold", className: "text-primary-600 dark:text-primary-400", children: formatCurrency(currentBid, currency) }), _jsxs(Span, { size: "xs", className: "text-zinc-500 dark:text-zinc-400", children: [bidCount, " bids"] })] }), _jsx(Button, { variant: "primary", size: "md", className: "w-full", children: "Place Bid" })] })) : null, renderSublistingSection: sublistingCategoryId
|
|
123
131
|
? () => (_jsx(SublistingCarouselSection, { sublistingCategoryId: sublistingCategoryId, currentListingId: String(product.id) }))
|
|
124
|
-
: undefined, renderTabs: () => (_jsx(ProductTabsShell, { descriptionContent: descriptionHtml ? (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm sm:prose max-w-none dark:prose-invert", className: "text-zinc-700 dark:text-zinc-300" })) : undefined, specsContent: specs.length > 0 ? (_jsx(
|
|
132
|
+
: undefined, renderTabs: () => (_jsx(ProductTabsShell, { descriptionContent: descriptionHtml ? (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm sm:prose max-w-none dark:prose-invert", className: "text-zinc-700 dark:text-zinc-300" })) : undefined, specsContent: specs.length > 0 ? (_jsx(Dl, { className: "divide-y divide-zinc-100 dark:divide-zinc-800 rounded-xl border border-zinc-100 dark:border-zinc-800 overflow-hidden text-sm", children: specs.map((s, i) => (_jsxs(Div, { className: "flex gap-4 px-4 py-3 bg-white dark:bg-zinc-900 even:bg-zinc-50 dark:even:bg-zinc-800/50", children: [_jsx(Dt, { className: "w-36 flex-shrink-0 font-medium text-zinc-700 dark:text-zinc-300", children: s.name }), _jsxs(Dd, { className: "flex-1 text-zinc-600 dark:text-zinc-400", children: [s.value, s.unit ? ` ${s.unit}` : ""] })] }, i))) })) : undefined, customTabs: customSections.map((s) => ({
|
|
125
133
|
id: s.id,
|
|
126
134
|
label: s.title,
|
|
127
135
|
content: _jsx(CustomSectionTabContent, { section: s }),
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useState } from "react";
|
|
4
|
+
import { Div, Span } from "../../../ui";
|
|
4
5
|
import { BidHistory } from "../../products/components/BidHistory";
|
|
6
|
+
const __O = {
|
|
7
|
+
hidden: "overflow-hidden",
|
|
8
|
+
};
|
|
5
9
|
export function CollapsibleBidHistory({ bids, currency }) {
|
|
6
10
|
const [open, setOpen] = useState(false);
|
|
7
|
-
return (_jsxs(
|
|
11
|
+
return (_jsxs(Div, { className: `mt-6 rounded-xl border border-zinc-100 dark:border-zinc-800 ${__O.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-900/60 hover:bg-zinc-100 dark:hover:bg-zinc-800/60 transition-colors", "aria-expanded": open, children: [_jsxs(Span, { size: "sm", weight: "semibold", className: "uppercase tracking-wide text-zinc-500 dark:text-zinc-400", children: ["Bid History", bids.length > 0 && (_jsx(Span, { size: "xs", weight: "medium", className: "ml-2 rounded-full bg-zinc-200 dark:bg-zinc-700 px-2 py-0.5 text-zinc-600 dark:text-zinc-300 normal-case tracking-normal", children: bids.length }))] }), _jsx("svg", { className: `h-4 w-4 text-zinc-400 transition-transform duration-200 ${open ? "rotate-180" : ""}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), open && (_jsx(Div, { surface: "default", className: "px-4 py-4", children: _jsx(BidHistory, { bids: bids, isEmpty: bids.length === 0, currency: currency }) }))] }));
|
|
8
12
|
}
|
|
@@ -12,17 +12,23 @@ import { formatCurrency } from "../../../utils";
|
|
|
12
12
|
import { getDefaultCurrency } from "../../../core/baseline-resolver";
|
|
13
13
|
import { BaseListingCard, Button, Caption, Div, Row, Span, Text, TextLink, } from "../../../ui";
|
|
14
14
|
import { THEME_CONSTANTS } from "../../../tokens";
|
|
15
|
+
const CLS_STAR_ICON = "h-5 w-5 fill-amber-400 text-amber-400";
|
|
16
|
+
const CLS_LIVE_BADGE = "rounded-full bg-rose-600/90 px-2 py-0.5 text-white";
|
|
17
|
+
const CLS_ENDING_BADGE = "rounded-full bg-amber-500/90 px-2 py-0.5 text-white";
|
|
18
|
+
const CLS_RESERVE_BADGE = "inline-flex items-center gap-1 rounded-full bg-amber-600/90 px-2 py-0.5 text-white";
|
|
19
|
+
const CLS_HEART_ON = "fill-rose-500 text-rose-500";
|
|
20
|
+
const CLS_HEART_OFF = "text-zinc-400";
|
|
15
21
|
function renderAuctionCardHero(props) {
|
|
16
22
|
const { product, auctionHref, currentSrc, hovered, images, imageIndex, hasVideo, isEnded, isEndingSoon, isSelected, selectable, mergedLabels, onSelect, setHovered, handleSelect } = props;
|
|
17
|
-
return (_jsxs(BaseListingCard.Hero, { aspect: "square", variant: "grid", onMouseEnter: () => setHovered(true), onMouseLeave: () => setHovered(false), children: [_jsx(TextLink, { href: auctionHref ?? "#", className: "absolute inset-0 block", children: _jsx(MediaImage, { src: currentSrc, alt: product.title, size: "card", fallback: "Auction image", className: `transition-transform duration-500 ${hovered && images.length > 1 ? "scale-105" : "scale-100"}` }) }), hasVideo && imageIndex === 0 ? (_jsx(Div, { className: "absolute right-2 top-2", children: _jsx(Span, { className: "flex h-8 w-8 items-center justify-center rounded-full bg-black/50 text-white", children: _jsx(Play, { className: "h-4 w-4", "aria-label": mergedLabels.videoLabel }) }) })) : null, images.length > 1 ? (_jsx(Div, { className: "pointer-events-none absolute bottom-2 left-1/2 flex -translate-x-1/2 gap-1", children: images.map((_, index) => (_jsx(Span, { className: `rounded-full transition-all duration-200 ${index === imageIndex ? "h-1.5 w-3 bg-white" : "h-1.5 w-1.5 bg-white/60"}` }, `${product.id}-image-${index}`))) })) : null, product.featured ? (_jsx(Div, { className: "pointer-events-none absolute left-2 top-2 z-10", children: _jsx(Star, { className:
|
|
23
|
+
return (_jsxs(BaseListingCard.Hero, { aspect: "square", variant: "grid", onMouseEnter: () => setHovered(true), onMouseLeave: () => setHovered(false), children: [_jsx(TextLink, { href: auctionHref ?? "#", className: "absolute inset-0 block", children: _jsx(MediaImage, { src: currentSrc, alt: product.title, size: "card", fallback: "Auction image", className: `transition-transform duration-500 ${hovered && images.length > 1 ? "scale-105" : "scale-100"}` }) }), hasVideo && imageIndex === 0 ? (_jsx(Div, { className: "absolute right-2 top-2", children: _jsx(Span, { className: "flex h-8 w-8 items-center justify-center rounded-full bg-black/50 text-white", children: _jsx(Play, { className: "h-4 w-4", "aria-label": mergedLabels.videoLabel }) }) })) : null, images.length > 1 ? (_jsx(Div, { className: "pointer-events-none absolute bottom-2 left-1/2 flex -translate-x-1/2 gap-1", children: images.map((_, index) => (_jsx(Span, { className: `rounded-full transition-all duration-200 ${index === imageIndex ? "h-1.5 w-3 bg-white" : "h-1.5 w-1.5 bg-white/60"}` }, `${product.id}-image-${index}`))) })) : null, product.featured ? (_jsx(Div, { className: "pointer-events-none absolute left-2 top-2 z-10", children: _jsx(Star, { className: CLS_STAR_ICON }) })) : null, onSelect && (_jsx(BaseListingCard.Checkbox, { selected: isSelected, onSelect: handleSelect, label: isSelected ? mergedLabels.deselectItem : mergedLabels.selectItem, className: selectable || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), _jsxs(Div, { className: `absolute left-2 z-10 flex flex-col gap-1 ${product.featured ? "top-8" : "top-2"}`, children: [!isEnded ? _jsx(Span, { size: "xs", weight: "bold", className: CLS_LIVE_BADGE, children: mergedLabels.liveBadge }) : null, isEndingSoon ? _jsx(Span, { size: "xs", weight: "bold", className: CLS_ENDING_BADGE, children: mergedLabels.endingSoon }) : null, isEnded ? _jsx(Span, { size: "xs", weight: "bold", className: "rounded-full bg-zinc-600/90 px-2 py-0.5 text-white", children: mergedLabels.ended }) : null, product.status === "sold" ? _jsx(Span, { size: "xs", weight: "bold", className: "rounded-full bg-zinc-700/90 px-2 py-0.5 text-white", children: mergedLabels.sold }) : null] }), _jsx(Div, { className: "pointer-events-none absolute bottom-2 right-2 z-10", children: _jsxs(Span, { size: "xs", weight: "semibold", className: CLS_RESERVE_BADGE, children: [_jsx(Gavel, { className: "h-3 w-3" }), mergedLabels.typeBadge] }) })] }));
|
|
18
24
|
}
|
|
19
25
|
function renderAuctionCardInfoList(props) {
|
|
20
26
|
const { product, auctionHref, displayBid, bidCount, isEnded, remaining, inWishlist, wishlistLoading, wishlistActions, countdownClass, mergedLabels, handleWishlist, handleNavigate } = props;
|
|
21
|
-
return (_jsxs(_Fragment, { children: [_jsxs(Div, { className: "flex items-start justify-between gap-2 min-w-0", children: [_jsx(TextLink, { href: auctionHref ?? "#", className: `${THEME_CONSTANTS.utilities.textClamp2} flex-1 text-sm font-medium leading-snug text-zinc-900 dark:text-zinc-100 transition-colors hover:text-primary`, children: product.title }), wishlistActions ? (_jsx(Button, { type: "button", variant: "ghost", onClick: handleWishlist, disabled: wishlistLoading, "aria-label": inWishlist ? mergedLabels.removeFromWishlist : mergedLabels.addToWishlist, className: "shrink-0 rounded-full p-1", children: _jsx(Heart, { className: `h-3.5 w-3.5 ${inWishlist ?
|
|
27
|
+
return (_jsxs(_Fragment, { children: [_jsxs(Div, { className: "flex items-start justify-between gap-2 min-w-0", children: [_jsx(TextLink, { href: auctionHref ?? "#", className: `${THEME_CONSTANTS.utilities.textClamp2} flex-1 text-sm font-medium leading-snug text-zinc-900 dark:text-zinc-100 transition-colors hover:text-primary`, children: product.title }), wishlistActions ? (_jsx(Button, { type: "button", variant: "ghost", onClick: handleWishlist, disabled: wishlistLoading, "aria-label": inWishlist ? mergedLabels.removeFromWishlist : mergedLabels.addToWishlist, className: "shrink-0 rounded-full p-1", children: _jsx(Heart, { className: `h-3.5 w-3.5 ${inWishlist ? CLS_HEART_ON : CLS_HEART_OFF}` }) })) : null] }), _jsxs(Div, { className: "flex items-center gap-2 flex-wrap", children: [_jsx(Text, { className: "text-sm font-bold text-primary", children: formatCurrency(displayBid, getDefaultCurrency()) }), _jsxs(Div, { className: `inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] font-semibold ${countdownClass}`, children: [_jsx(Clock, { className: "h-2.5 w-2.5" }), _jsx(Span, { children: formatCountdownLabel(remaining, mergedLabels.ended) })] }), bidCount > 0 && _jsx(Caption, { className: "text-[11px]", children: mergedLabels.totalBids(bidCount) })] }), !isEnded && (_jsxs(Button, { type: "button", variant: "warning", size: "sm", className: "self-start gap-1 px-2.5 text-xs mt-0.5", onClick: handleNavigate, children: [_jsx(Gavel, { className: "h-3 w-3" }), _jsx(Span, { children: mergedLabels.placeBid })] }))] }));
|
|
22
28
|
}
|
|
23
29
|
function renderAuctionCardInfoGrid(props) {
|
|
24
30
|
const { product, auctionHref, displayBid, bidCount, hasCurrentBid, isEnded, remaining, resolvedBuyoutPrice, inWishlist, wishlistLoading, wishlistActions, countdownClass, mergedLabels, handleWishlist, handleNavigate } = props;
|
|
25
|
-
return (_jsxs(_Fragment, { children: [_jsxs(Div, { className: "flex items-start gap-2", children: [_jsx(TextLink, { href: auctionHref ?? "#", className: "min-w-0 flex-1 text-sm font-medium leading-snug text-zinc-900 dark:text-zinc-100 transition-colors hover:text-primary", children: product.title }), wishlistActions ? (_jsx(Button, { type: "button", variant: "ghost", onClick: handleWishlist, disabled: wishlistLoading, "aria-label": inWishlist ? mergedLabels.removeFromWishlist : mergedLabels.addToWishlist, className: "-mt-0.5 rounded-full p-1", children: _jsx(Heart, { className: `h-4 w-4 ${inWishlist ?
|
|
31
|
+
return (_jsxs(_Fragment, { children: [_jsxs(Div, { className: "flex items-start gap-2", children: [_jsx(TextLink, { href: auctionHref ?? "#", className: "min-w-0 flex-1 text-sm font-medium leading-snug text-zinc-900 dark:text-zinc-100 transition-colors hover:text-primary", children: product.title }), wishlistActions ? (_jsx(Button, { type: "button", variant: "ghost", onClick: handleWishlist, disabled: wishlistLoading, "aria-label": inWishlist ? mergedLabels.removeFromWishlist : mergedLabels.addToWishlist, className: "-mt-0.5 rounded-full p-1", children: _jsx(Heart, { className: `h-4 w-4 ${inWishlist ? CLS_HEART_ON : CLS_HEART_OFF}` }) })) : null] }), _jsxs(Div, { children: [_jsx(Caption, { children: isEnded && hasCurrentBid ? mergedLabels.winningBid : hasCurrentBid ? mergedLabels.currentBid : mergedLabels.startingBid }), _jsx(Text, { className: "text-base font-bold leading-none text-primary", children: formatCurrency(displayBid, getDefaultCurrency()) }), isEnded && product.winnerDisplayName && (_jsxs(Caption, { className: "mt-0.5 text-zinc-500 dark:text-zinc-400", children: [mergedLabels.wonBy, ": ", maskDisplayName(product.winnerDisplayName)] }))] }), _jsxs(Row, { wrap: true, justify: "between", gap: "sm", className: "gap-x-2 gap-y-1", children: [_jsxs(Div, { className: `inline-flex items-center gap-1 rounded-full px-2.5 py-1 text-xs font-semibold ${countdownClass}`, children: [_jsx(Clock, { className: "h-3 w-3" }), _jsx(Span, { children: formatCountdownLabel(remaining, mergedLabels.ended) })] }), _jsx(Caption, { children: mergedLabels.totalBids(bidCount) })] }), _jsx(Row, { wrap: true, gap: "xs", className: "mt-auto", children: isEnded ? (_jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "flex-1 cursor-not-allowed gap-1 px-2 text-xs opacity-60", disabled: true, children: _jsx(Span, { children: mergedLabels.ended }) })) : (_jsxs(_Fragment, { children: [_jsxs(Button, { type: "button", variant: "warning", size: "sm", className: "flex-1 gap-1 px-2 text-xs", onClick: handleNavigate, children: [_jsx(Gavel, { className: "h-3 w-3" }), _jsx(Span, { children: mergedLabels.placeBid })] }), resolvedBuyoutPrice ? (_jsxs(Button, { type: "button", variant: "danger", size: "sm", className: "flex-1 gap-1 px-2 text-xs", onClick: handleNavigate, children: [_jsx(ShoppingBag, { className: "h-3 w-3" }), _jsx(Span, { children: mergedLabels.buyout })] })) : null] })) })] }));
|
|
26
32
|
}
|
|
27
33
|
const DEFAULT_LABELS = {
|
|
28
34
|
selectItem: "Select item",
|
|
@@ -3,6 +3,12 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { Gavel } from "lucide-react";
|
|
4
4
|
import { Div, Row, Stack, Text } from "../../../ui";
|
|
5
5
|
import { MarketplaceAuctionCard, } from "./MarketplaceAuctionCard";
|
|
6
|
+
const __P = {
|
|
7
|
+
p3: "p-3",
|
|
8
|
+
};
|
|
9
|
+
const __O = {
|
|
10
|
+
hidden: "overflow-hidden",
|
|
11
|
+
};
|
|
6
12
|
const CLS_SKELETON_BTN = "h-8 w-20 rounded bg-zinc-300";
|
|
7
13
|
const DEFAULT_GRID_LABELS = {
|
|
8
14
|
emptyTitle: "No auctions found",
|
|
@@ -10,9 +16,9 @@ const DEFAULT_GRID_LABELS = {
|
|
|
10
16
|
};
|
|
11
17
|
function AuctionCardSkeleton({ variant = "grid", }) {
|
|
12
18
|
if (variant === "list") {
|
|
13
|
-
return (_jsxs(Div, { className:
|
|
19
|
+
return (_jsxs(Div, { className: `flex min-h-[220px] flex-row ${__O.hidden} rounded-xl bg-zinc-200 animate-pulse`, children: [_jsx(Div, { className: "aspect-square w-40 flex-shrink-0 bg-zinc-300" }), _jsxs(Div, { className: `flex-1 space-y-2 ${__P.p3}`, children: [_jsx(Div, { className: "h-4 w-2/3 rounded bg-zinc-300" }), _jsx(Div, { className: "h-3 w-full rounded bg-zinc-300" }), _jsx(Div, { className: "h-3 w-3/4 rounded bg-zinc-300" }), _jsx(Div, { className: "h-5 w-1/2 rounded bg-zinc-300" }), _jsxs(Row, { gap: "sm", children: [_jsx(Div, { className: CLS_SKELETON_BTN }), _jsx(Div, { className: CLS_SKELETON_BTN })] })] })] }));
|
|
14
20
|
}
|
|
15
|
-
return (_jsxs(Div, { className:
|
|
21
|
+
return (_jsxs(Div, { className: `${__O.hidden} rounded-xl bg-zinc-200 animate-pulse`, children: [_jsx(Div, { className: "aspect-square bg-zinc-300" }), _jsxs(Div, { className: `space-y-2 ${__P.p3}`, children: [_jsx(Div, { className: "h-4 w-3/4 rounded bg-zinc-300" }), _jsx(Div, { className: "h-3 w-1/3 rounded bg-zinc-300" }), _jsx(Div, { className: "h-5 w-1/2 rounded bg-zinc-300" }), _jsxs(Row, { justify: "between", children: [_jsx(Div, { className: "h-3 w-1/4 rounded bg-zinc-300" }), _jsx(Div, { className: "h-3 w-1/3 rounded bg-zinc-300" })] }), _jsx(Row, { gap: "sm", children: _jsx(Div, { className: CLS_SKELETON_BTN }) })] })] }));
|
|
16
22
|
}
|
|
17
23
|
export function MarketplaceAuctionGrid({ auctions, loading = false, skeletonCount = 12, variant = "grid", selectable = false, selectedIds = [], onSelectionChange, gridClassName, emptyIcon, labels, cardLabels, wishlistActions, }) {
|
|
18
24
|
const mergedLabels = { ...DEFAULT_GRID_LABELS, ...labels };
|
|
@@ -4,6 +4,9 @@ import { useState, useTransition } from "react";
|
|
|
4
4
|
import { formatCurrency } from "../../../utils/number.formatter";
|
|
5
5
|
import { isAuthError } from "../../../utils/auth-error";
|
|
6
6
|
import { Button, Div, Input, LoginRequiredModal, Modal, Row, Span, Stack, Text } from "../../../ui";
|
|
7
|
+
const __P = {
|
|
8
|
+
p5: "p-5",
|
|
9
|
+
};
|
|
7
10
|
const BID_ERROR_DISPLAY = {
|
|
8
11
|
BID_AUCTION_ENDED: "This auction has closed. No more bids are accepted.",
|
|
9
12
|
BID_AMOUNT_TOO_LOW: "Your bid must exceed the current winning bid.",
|
|
@@ -82,7 +85,7 @@ export function PlaceBidFormClient({ productId, currentBid, startingBid, minBidI
|
|
|
82
85
|
}
|
|
83
86
|
});
|
|
84
87
|
}
|
|
85
|
-
return (_jsxs(Div, { className:
|
|
88
|
+
return (_jsxs(Div, { className: `rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 ${__P.p5} space-y-4`, children: [_jsxs(Div, { className: "space-y-1", children: [_jsxs(Row, { justify: "between", align: "center", children: [_jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "Current bid" }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "Starting bid" })] }), _jsxs(Row, { justify: "between", align: "baseline", children: [_jsx(Span, { size: "xl", weight: "bold", className: "text-primary-600 dark:text-primary-400", children: formatCurrency(currentBid, currency) }), _jsx(Span, { size: "sm", className: "text-zinc-500 dark:text-zinc-400", children: formatCurrency(startingBid, currency) })] }), _jsxs(Text, { className: "text-xs text-zinc-400 dark:text-zinc-400", children: [bidCount, " ", bidCount === 1 ? "bid" : "bids", " \u00B7 min increment", " ", formatCurrency(minBidIncrement, currency)] })] }), _jsx(LoginRequiredModal, { isOpen: showLoginModal, onClose: () => setShowLoginModal(false), message: "You need to be signed in to place a bid. Please log in or create an account to continue." }), _jsx("form", { onSubmit: handleSubmit, children: _jsxs(Stack, { gap: "sm", children: [_jsx(Input, { type: "number", value: bidAmount, onChange: (e) => setBidAmount(e.target.value), placeholder: `At least ${formatCurrency(minBid, currency)}`, min: minBid, step: minBidIncrement, "aria-label": "Your bid amount", disabled: isEnded || isPending }), error && (_jsx(Text, { className: "text-xs text-error", children: error })), success && (_jsx(Text, { className: "text-xs text-success", children: "\u2713 Bid placed successfully!" })), _jsx(Button, { variant: "primary", size: "md", className: "w-full", disabled: isEnded || isPending, type: "submit", children: isPending ? "Placing Bid…" : isEnded ? "Auction Ended" : "Place Bid" }), buyNowAvailable && (_jsx(Button, { variant: "secondary", size: "md", className: "w-full", type: "button", disabled: isBuyNowPending || isPending, onClick: handleBuyNow, children: isBuyNowPending ? "Processing…" : `Buy Now — ${formatCurrency(buyNowPrice, currency)}` }))] }) }), tags.length > 0 && (_jsx(Div, { className: "border-t border-zinc-200 dark:border-zinc-700 pt-4", children: _jsx(Row, { wrap: true, gap: "xs", children: tags.map((tag) => (_jsx(Span, { className: "rounded-full bg-zinc-100 dark:bg-zinc-800 px-2.5 py-1 text-xs text-zinc-600 dark:text-zinc-300", children: tag }, tag))) }) }))] }));
|
|
86
89
|
}
|
|
87
90
|
/**
|
|
88
91
|
* `PlaceBidModalButton` — opens a modal that hosts the same PlaceBidFormClient.
|
|
@@ -17,22 +17,22 @@ interface UseAuctionDetailOptions {
|
|
|
17
17
|
bidsQueryKeyPrefix?: string;
|
|
18
18
|
}
|
|
19
19
|
export declare function useAuctions(params?: AuctionListQuery, opts?: UseAuctionsOptions): {
|
|
20
|
-
data: AuctionListResponse | undefined;
|
|
20
|
+
data: NoInfer<AuctionListResponse> | undefined;
|
|
21
21
|
auctions: AuctionItem[];
|
|
22
22
|
total: number;
|
|
23
23
|
totalPages: number;
|
|
24
24
|
hasMore: boolean;
|
|
25
25
|
isLoading: boolean;
|
|
26
26
|
error: string | null;
|
|
27
|
-
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<AuctionListResponse
|
|
27
|
+
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<NoInfer<AuctionListResponse>, Error>>;
|
|
28
28
|
};
|
|
29
29
|
export declare function useAuction(slug: string, opts?: {
|
|
30
30
|
enabled?: boolean;
|
|
31
31
|
}): {
|
|
32
|
-
auction: AuctionItem | null;
|
|
32
|
+
auction: NonNullable<NoInfer<AuctionItem | null>> | null;
|
|
33
33
|
isLoading: boolean;
|
|
34
34
|
error: string | null;
|
|
35
|
-
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<AuctionItem | null
|
|
35
|
+
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<NoInfer<AuctionItem | null>, Error>>;
|
|
36
36
|
};
|
|
37
37
|
export declare function useAuctionBids(auctionSlug: string, limit?: number, opts?: {
|
|
38
38
|
enabled?: boolean;
|
|
@@ -43,9 +43,9 @@ export declare function useAuctionBids(auctionSlug: string, limit?: number, opts
|
|
|
43
43
|
error: string | null;
|
|
44
44
|
};
|
|
45
45
|
export declare function useAuctionDetail(id: string, opts?: UseAuctionDetailOptions): {
|
|
46
|
-
productQuery: import("@tanstack/react-query").UseQueryResult<ProductItem | null
|
|
47
|
-
product: ProductItem | null;
|
|
48
|
-
bidsQuery: import("@tanstack/react-query").UseQueryResult<PublicBid[]
|
|
49
|
-
bids: PublicBid[]
|
|
46
|
+
productQuery: import("@tanstack/react-query").UseQueryResult<NoInfer<ProductItem | null>, Error>;
|
|
47
|
+
product: NonNullable<NoInfer<ProductItem | null>> | null;
|
|
48
|
+
bidsQuery: import("@tanstack/react-query").UseQueryResult<NoInfer<PublicBid[]>, Error>;
|
|
49
|
+
bids: NoInfer<PublicBid[]>;
|
|
50
50
|
};
|
|
51
51
|
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useCallback, useState } from "react";
|
|
4
|
-
import { Alert, Div, Heading, Label, Text } from "../../../ui";
|
|
4
|
+
import { Alert, Button, Div, Heading, Label, Text } from "../../../ui";
|
|
5
5
|
function renderRegisterFormFields(props) {
|
|
6
6
|
const { values, setValues, labels, renderTermsLink, renderPasswordStrength } = props;
|
|
7
7
|
const CLS_INPUT = "w-full rounded-lg border border-neutral-300 dark:border-slate-600 bg-white dark:bg-slate-800 text-zinc-900 dark:text-zinc-100 placeholder:text-neutral-400 dark:placeholder:text-slate-500 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary";
|
|
@@ -27,5 +27,5 @@ export function RegisterForm({ onSubmit, isLoading = false, error, success, labe
|
|
|
27
27
|
await onSubmit(values);
|
|
28
28
|
}, [onSubmit, values, labels.passwordMismatch]);
|
|
29
29
|
const displayError = error ?? validationError;
|
|
30
|
-
return (_jsx(Div, { className: `flex items-center justify-center min-h-[60vh] px-4 ${className}`, children: _jsxs(Div, { className: "max-w-md w-full space-y-6", children: [_jsxs(Div, { className: "text-center", children: [_jsx(Heading, { level: 1, className: "text-3xl font-extrabold", children: labels.title ?? "Create Account" }), (labels.subtitle || renderLoginLink) && (_jsxs(Text, { className: "mt-2 text-sm text-neutral-600 dark:text-zinc-400", children: [labels.subtitle ?? "Already have an account?", " ", renderLoginLink?.()] }))] }), success && (_jsx(Alert, { variant: "success", compact: true, children: success })), displayError && (_jsx(Alert, { variant: "error", compact: true, children: displayError })), _jsxs("form", { className: "space-y-4", onSubmit: handleSubmit, noValidate: true, children: [renderRegisterFormFields({ values, setValues, labels, renderTermsLink, renderPasswordStrength }), _jsx(
|
|
30
|
+
return (_jsx(Div, { className: `flex items-center justify-center min-h-[60vh] px-4 ${className}`, children: _jsxs(Div, { className: "max-w-md w-full space-y-6", children: [_jsxs(Div, { className: "text-center", children: [_jsx(Heading, { level: 1, className: "text-3xl font-extrabold", children: labels.title ?? "Create Account" }), (labels.subtitle || renderLoginLink) && (_jsxs(Text, { className: "mt-2 text-sm text-neutral-600 dark:text-zinc-400", children: [labels.subtitle ?? "Already have an account?", " ", renderLoginLink?.()] }))] }), success && (_jsx(Alert, { variant: "success", compact: true, children: success })), displayError && (_jsx(Alert, { variant: "error", compact: true, children: displayError })), _jsxs("form", { className: "space-y-4", onSubmit: handleSubmit, noValidate: true, children: [renderRegisterFormFields({ values, setValues, labels, renderTermsLink, renderPasswordStrength }), _jsx(Button, { type: "submit", isLoading: isLoading, disabled: isLoading, className: "w-full", children: isLoading ? (labels.submittingLabel ?? "Creating account…") : (labels.submitLabel ?? "Create account") })] }), renderSocialButtons?.()] }) }));
|
|
31
31
|
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Div, Heading, Text, Button } from "../../../ui";
|
|
3
3
|
import { THEME_CONSTANTS } from "../../../tokens";
|
|
4
|
+
const CLS_SUCCESS_CIRCLE = "w-12 h-12 rounded-full bg-green-100 flex items-center justify-center mx-auto mb-6";
|
|
5
|
+
const CLS_ERROR_CIRCLE = "w-12 h-12 rounded-full bg-red-100 flex items-center justify-center mx-auto mb-6";
|
|
6
|
+
const CLS_ERROR_ICON = "w-6 h-6 text-red-600";
|
|
4
7
|
export function VerifyEmailView({ status, error, labels = {}, onRetry, renderContinueButton, className = "", }) {
|
|
5
|
-
return (_jsx(Div, { className: `flex items-center justify-center min-h-[60vh] px-4 ${className}`, children: _jsxs(Div, { surface: "elevated", padding: "xl", className: "max-w-md w-full text-center", children: [status === "loading" && (_jsxs(_Fragment, { children: [_jsx(Div, { className: "w-12 h-12 rounded-full border-4 border-primary border-t-transparent animate-spin mx-auto mb-6" }), _jsx(Heading, { level: 2, className: "text-xl font-semibold mb-2", children: labels.loadingTitle ?? "Verifying your email…" }), _jsx(Text, { className: "text-zinc-500 dark:text-zinc-400", children: labels.loadingDescription ?? "Please wait a moment." })] })), status === "success" && (_jsxs(_Fragment, { children: [_jsx(Div, { className:
|
|
6
|
-
"Your email has been verified successfully." }), renderContinueButton?.()] })), status === "error" && (_jsxs(_Fragment, { children: [_jsx(Div, { className:
|
|
8
|
+
return (_jsx(Div, { className: `flex items-center justify-center min-h-[60vh] px-4 ${className}`, children: _jsxs(Div, { surface: "elevated", padding: "xl", className: "max-w-md w-full text-center", children: [status === "loading" && (_jsxs(_Fragment, { children: [_jsx(Div, { className: "w-12 h-12 rounded-full border-4 border-primary border-t-transparent animate-spin mx-auto mb-6" }), _jsx(Heading, { level: 2, className: "text-xl font-semibold mb-2", children: labels.loadingTitle ?? "Verifying your email…" }), _jsx(Text, { className: "text-zinc-500 dark:text-zinc-400", children: labels.loadingDescription ?? "Please wait a moment." })] })), status === "success" && (_jsxs(_Fragment, { children: [_jsx(Div, { className: CLS_SUCCESS_CIRCLE, children: _jsx("svg", { className: `w-6 h-6 ${THEME_CONSTANTS.themed.textSuccess}`, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }) }), _jsx(Heading, { level: 2, className: "text-xl font-semibold mb-2", children: labels.successTitle ?? "Email verified!" }), _jsx(Text, { className: "text-zinc-500 dark:text-zinc-400 mb-6", children: labels.successDescription ??
|
|
9
|
+
"Your email has been verified successfully." }), renderContinueButton?.()] })), status === "error" && (_jsxs(_Fragment, { children: [_jsx(Div, { className: CLS_ERROR_CIRCLE, children: _jsx("svg", { className: CLS_ERROR_ICON, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) }), _jsx(Heading, { level: 2, className: "text-xl font-semibold mb-2", children: labels.errorTitle ?? "Verification failed" }), _jsx(Text, { className: "text-zinc-500 dark:text-zinc-400 mb-2", children: error ??
|
|
7
10
|
labels.errorDescription ??
|
|
8
11
|
"The verification link may have expired." }), onRetry && (_jsx(Button, { onClick: onRetry, className: "mt-4 rounded-lg bg-primary px-4 py-2 text-sm font-semibold text-white hover:bg-primary/90 transition-colors", children: labels.retryLabel ?? "Try again" }))] }))] }) }));
|
|
9
12
|
}
|
|
@@ -4,11 +4,11 @@ interface UseCurrentUserOptions {
|
|
|
4
4
|
enabled?: boolean;
|
|
5
5
|
}
|
|
6
6
|
export declare function useCurrentUser(opts?: UseCurrentUserOptions): {
|
|
7
|
-
user: AuthUser | null;
|
|
7
|
+
user: NonNullable<NoInfer<AuthUser | null>> | null;
|
|
8
8
|
isLoading: boolean;
|
|
9
9
|
isAuthenticated: boolean;
|
|
10
10
|
error: Error | null;
|
|
11
|
-
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<AuthUser | null
|
|
11
|
+
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<NoInfer<AuthUser | null>, Error>>;
|
|
12
12
|
};
|
|
13
13
|
export interface LoginCredentials {
|
|
14
14
|
email: string;
|
|
@@ -23,5 +23,5 @@ export function BeforeAfterSlider({ item, className = "", }) {
|
|
|
23
23
|
return (_jsxs(Div, { ref: containerRef, className: `relative aspect-square select-none overflow-hidden rounded-xl ${className}`, onPointerMove: handlePointerMove, onTouchMove: handleTouchMove, children: [_jsx(Div, { role: "img", "aria-label": "After", className: "absolute inset-0 h-full w-full bg-center bg-cover", style: { backgroundImage: `url(${item.afterImageUrl})` } }), _jsx(Div, { className: "absolute inset-0 overflow-hidden", style: { width: `${position}%` }, children: _jsx(Div, { role: "img", "aria-label": "Before", className: "h-full w-full bg-center bg-cover", style: {
|
|
24
24
|
width: containerRef.current?.offsetWidth ?? "100%",
|
|
25
25
|
backgroundImage: `url(${item.beforeImageUrl})`,
|
|
26
|
-
} }) }), _jsxs(Div, { className: "absolute inset-y-0 flex w-1 -translate-x-1/2 cursor-ew-resize flex-col items-center justify-center", style: { left: `${position}%` }, children: [_jsx(Div, { className: "h-full w-0.5 bg-white/80 shadow" }), _jsx(Div, { className: "absolute h-8 w-8 rounded-full border-2 border-white bg-white/80 shadow-md" })] }), _jsx(Span, { className: "absolute left-2 top-2 rounded bg-black/40 px-2 py-0.5 text-
|
|
26
|
+
} }) }), _jsxs(Div, { className: "absolute inset-y-0 flex w-1 -translate-x-1/2 cursor-ew-resize flex-col items-center justify-center", style: { left: `${position}%` }, children: [_jsx(Div, { className: "h-full w-0.5 bg-white/80 shadow" }), _jsx(Div, { className: "absolute h-8 w-8 rounded-full border-2 border-white bg-white/80 shadow-md" })] }), _jsx(Span, { size: "xs", weight: "medium", className: "absolute left-2 top-2 rounded bg-black/40 px-2 py-0.5 text-white", children: "Before" }), _jsx(Span, { size: "xs", weight: "medium", className: "absolute right-2 top-2 rounded bg-black/40 px-2 py-0.5 text-white", children: "After" }), item.durationWeeks && (_jsxs(Span, { size: "xs", weight: "medium", className: "absolute bottom-2 left-1/2 -translate-x-1/2 rounded bg-black/50 px-3 py-1 text-white", children: [item.durationWeeks, " weeks"] }))] }));
|
|
27
27
|
}
|
|
@@ -6,6 +6,12 @@ import { getMediaUrl } from "../../media/types/index";
|
|
|
6
6
|
import { getDefaultLocale } from "../../../core/baseline-resolver";
|
|
7
7
|
import { safeDisplayName } from "../../../security";
|
|
8
8
|
import { useLongPress } from "../../../react/hooks/useLongPress";
|
|
9
|
+
const __P = {
|
|
10
|
+
p4: "p-4",
|
|
11
|
+
};
|
|
12
|
+
const __O = {
|
|
13
|
+
hidden: "overflow-hidden",
|
|
14
|
+
};
|
|
9
15
|
const CATEGORY_BADGE = {
|
|
10
16
|
news: "bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300",
|
|
11
17
|
tips: "bg-emerald-100 text-emerald-800 dark:bg-emerald-900/40 dark:text-emerald-300",
|
|
@@ -13,6 +19,7 @@ const CATEGORY_BADGE = {
|
|
|
13
19
|
updates: "bg-purple-100 text-purple-800 dark:bg-purple-900/40 dark:text-purple-300",
|
|
14
20
|
community: "bg-orange-100 text-orange-800 dark:bg-orange-900/40 dark:text-orange-300",
|
|
15
21
|
};
|
|
22
|
+
const CLS_FEATURED_BADGE = "bg-yellow-100 text-yellow-800 dark:bg-yellow-900/40 dark:text-yellow-300 px-2 py-0.5 rounded-full";
|
|
16
23
|
export function BlogFeaturedCard({ post, href, labels = {}, className = "", selectable = false, isSelected = false, onSelect, }) {
|
|
17
24
|
const longPress = useLongPress(() => onSelect?.(post.id, !isSelected));
|
|
18
25
|
const safeTitle = post.title?.trim() || "Untitled post";
|
|
@@ -24,5 +31,5 @@ export function BlogFeaturedCard({ post, href, labels = {}, className = "", sele
|
|
|
24
31
|
day: "numeric",
|
|
25
32
|
})
|
|
26
33
|
: "";
|
|
27
|
-
return (_jsxs(Article, { className: `group relative flex h-full flex-col overflow-hidden rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-sm hover:shadow-md transition-shadow duration-200 ${isSelected ? "ring-2 ring-primary outline outline-2 outline-primary" : ""} ${className}`, onMouseDown: onSelect && !isSelected ? longPress.onMouseDown : undefined, onMouseUp: onSelect && !isSelected ? longPress.onMouseUp : undefined, onMouseLeave: onSelect && !isSelected ? longPress.onMouseLeave : undefined, onTouchStart: onSelect && !isSelected ? longPress.onTouchStart : undefined, onTouchEnd: onSelect && !isSelected ? longPress.onTouchEnd : undefined, children: [onSelect && (_jsx(BaseListingCard.Checkbox, { selected: isSelected, onSelect: (e) => { e.preventDefault(); onSelect(post.id, !isSelected); }, label: isSelected ? "Deselect post" : "Select post", position: "top-2 left-2", className: selectable || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), _jsxs(TextLink, { href: href, className: "flex h-full flex-col", children: [_jsx(Div, { className:
|
|
34
|
+
return (_jsxs(Article, { className: `group relative flex h-full flex-col overflow-hidden rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-sm hover:shadow-md transition-shadow duration-200 ${isSelected ? "ring-2 ring-primary outline outline-2 outline-primary" : ""} ${className}`, onMouseDown: onSelect && !isSelected ? longPress.onMouseDown : undefined, onMouseUp: onSelect && !isSelected ? longPress.onMouseUp : undefined, onMouseLeave: onSelect && !isSelected ? longPress.onMouseLeave : undefined, onTouchStart: onSelect && !isSelected ? longPress.onTouchStart : undefined, onTouchEnd: onSelect && !isSelected ? longPress.onTouchEnd : undefined, children: [onSelect && (_jsx(BaseListingCard.Checkbox, { selected: isSelected, onSelect: (e) => { e.preventDefault(); onSelect(post.id, !isSelected); }, label: isSelected ? "Deselect post" : "Select post", position: "top-2 left-2", className: selectable || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), _jsxs(TextLink, { href: href, className: "flex h-full flex-col", children: [_jsx(Div, { className: `aspect-video ${__O.hidden} flex-shrink-0`, children: coverImageUrl ? (_jsx(Div, { role: "img", "aria-label": safeTitle, className: "h-full w-full bg-cover bg-center transition-transform duration-300 group-hover:scale-105", style: { backgroundImage: `url(${coverImageUrl})` } })) : (_jsx(Div, { role: "img", "aria-label": safeTitle, className: "h-full w-full bg-gradient-to-br from-zinc-200 via-zinc-100 to-zinc-300 dark:from-slate-800 dark:via-slate-700 dark:to-slate-900" })) }), _jsxs(Div, { className: `flex flex-1 flex-col ${__P.p4}`, children: [_jsxs(Row, { className: "gap-1.5 mb-2 flex-wrap", children: [_jsx(Span, { size: "xs", weight: "medium", className: `inline-block px-2 py-0.5 rounded-full capitalize ${CATEGORY_BADGE[post.category] ?? "bg-zinc-100 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-300"}`, children: post.category }), post.isFeatured && (_jsx(Span, { size: "xs", weight: "medium", className: CLS_FEATURED_BADGE, children: labels.featuredBadge ?? "Featured" }))] }), _jsx(Heading, { level: 3, className: `font-semibold text-neutral-900 dark:text-zinc-100 text-base leading-snug mb-1 ${THEME_CONSTANTS.utilities.textClamp2}`, children: safeTitle }), post.excerpt && (_jsx(Text, { className: `text-neutral-500 dark:text-zinc-400 text-sm ${THEME_CONSTANTS.utilities.textClamp2} mb-3`, children: post.excerpt })), _jsxs(Row, { className: "mt-auto gap-3 text-xs text-zinc-400 dark:text-zinc-400 flex-wrap", children: [post.authorName && (_jsx(Span, { children: safeDisplayName(post.authorName, "Author") })), post.readTimeMinutes != null && (_jsxs(Span, { children: [post.readTimeMinutes, " ", labels.readTime ?? "min read"] })), date && _jsx(Span, { children: date })] })] })] })] }));
|
|
28
35
|
}
|
|
@@ -3,25 +3,31 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { useState, useCallback, useMemo } from "react";
|
|
4
4
|
import { useUrlTable } from "../../../react/hooks/useUrlTable";
|
|
5
5
|
import { useBlogPosts } from "../hooks/useBlog";
|
|
6
|
-
import { ListingFilterDrawer, ListingToolbar, Pagination, Text } from "../../../ui";
|
|
6
|
+
import { Div, ListingFilterDrawer, ListingToolbar, Pagination, Text } from "../../../ui";
|
|
7
7
|
import { ROUTES } from "../../../next";
|
|
8
8
|
import { BlogCard } from "./BlogListView";
|
|
9
9
|
import { BlogFilters, BLOG_PUBLIC_SORT_OPTIONS } from "./BlogFilters";
|
|
10
10
|
import { TABLE_KEYS, VIEW_MODE } from "../../../constants/table-keys";
|
|
11
11
|
import { sortBy } from "../../../constants/sort";
|
|
12
12
|
import { BLOG_FIELDS } from "../../../constants/field-names";
|
|
13
|
+
const __P = {
|
|
14
|
+
p5: "p-5",
|
|
15
|
+
};
|
|
16
|
+
const __O = {
|
|
17
|
+
hidden: "overflow-hidden",
|
|
18
|
+
};
|
|
13
19
|
function renderBlogGrid(props) {
|
|
14
20
|
const { isLoading, posts, view } = props;
|
|
15
21
|
if (isLoading) {
|
|
16
|
-
return (_jsx(
|
|
22
|
+
return (_jsx(Div, { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6", children: Array.from({ length: 6 }).map((_, i) => (_jsxs(Div, { className: `rounded-xl border border-zinc-100 dark:border-slate-700 ${__O.hidden} animate-pulse`, children: [_jsx(Div, { className: "aspect-video bg-zinc-200 dark:bg-slate-700" }), _jsxs(Div, { className: `${__P.p5} space-y-2`, children: [_jsx(Div, { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-1/4" }), _jsx(Div, { className: "h-4 bg-zinc-200 dark:bg-slate-700 rounded w-3/4" }), _jsx(Div, { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-full" }), _jsx(Div, { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-2/3" })] })] }, i))) }));
|
|
17
23
|
}
|
|
18
24
|
if (posts.length === 0) {
|
|
19
25
|
return _jsx(Text, { className: "py-12 text-center text-sm text-zinc-500 dark:text-zinc-400", children: "No posts found." });
|
|
20
26
|
}
|
|
21
27
|
if (view === "list") {
|
|
22
|
-
return (_jsx(
|
|
28
|
+
return (_jsx(Div, { className: "flex flex-col divide-y divide-zinc-100 dark:divide-zinc-800 rounded-xl border border-zinc-100 dark:border-zinc-800", children: posts.map((post) => _jsx(BlogCard, { post: post, href: String(ROUTES.BLOG.ARTICLE(post.slug)) }, post.id)) }));
|
|
23
29
|
}
|
|
24
|
-
return (_jsx(
|
|
30
|
+
return (_jsx(Div, { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6", children: posts.map((post) => _jsx(BlogCard, { post: post, href: String(ROUTES.BLOG.ARTICLE(post.slug)) }, post.id)) }));
|
|
25
31
|
}
|
|
26
32
|
function renderBlogFilterDrawer(props) {
|
|
27
33
|
const { filterOpen, setFilterOpen, activeFilterCount, clearFilters, applyFilters, pendingTable } = props;
|
|
@@ -107,5 +113,5 @@ export function BlogIndexListing({ initialData }) {
|
|
|
107
113
|
const commitSearch = useCallback(() => {
|
|
108
114
|
table.set(TABLE_KEYS.QUERY, searchInput.trim());
|
|
109
115
|
}, [searchInput, table]);
|
|
110
|
-
return (_jsxs(
|
|
116
|
+
return (_jsxs(Div, { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search posts...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: BLOG_PUBLIC_SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, view: view, onViewChange: handleViewToggle, 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) }) })), _jsx(Div, { className: "py-6", children: renderBlogGrid({ isLoading, posts, view }) }), renderBlogFilterDrawer({ filterOpen, setFilterOpen, activeFilterCount, clearFilters, applyFilters, pendingTable })] }));
|
|
111
117
|
}
|
|
@@ -6,6 +6,14 @@ import { THEME_CONSTANTS } from "../../../tokens";
|
|
|
6
6
|
import { getDefaultLocale } from "../../../core/baseline-resolver";
|
|
7
7
|
import { getMediaUrl } from "../../media/types/index";
|
|
8
8
|
import { safeDisplayName } from "../../../security";
|
|
9
|
+
const __P = {
|
|
10
|
+
p5: "p-5",
|
|
11
|
+
};
|
|
12
|
+
const __O = {
|
|
13
|
+
hidden: "overflow-hidden",
|
|
14
|
+
xAuto: "overflow-x-auto",
|
|
15
|
+
};
|
|
16
|
+
const CLS_FEATURED_BADGE = "rounded-full bg-yellow-100 px-2 py-0.5 text-yellow-700 dark:bg-yellow-900/40 dark:text-yellow-300";
|
|
9
17
|
export function BlogCard({ post, href, onClick, className = "" }) {
|
|
10
18
|
const coverImageUrl = getMediaUrl(post.coverImage);
|
|
11
19
|
const date = post.publishedAt
|
|
@@ -18,18 +26,18 @@ export function BlogCard({ post, href, onClick, className = "" }) {
|
|
|
18
26
|
const isInteractive = !!(href || onClick);
|
|
19
27
|
const card = (_jsxs(Article, { role: onClick && !href ? "button" : undefined, tabIndex: onClick && !href ? 0 : undefined, onKeyDown: onClick && !href
|
|
20
28
|
? (e) => (e.key === "Enter" || e.key === " ") && onClick(post)
|
|
21
|
-
: undefined, onClick: onClick && !href ? () => onClick(post) : undefined, className: `group flex flex-col h-full overflow-hidden rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-sm transition hover:shadow-md ${isInteractive ? "cursor-pointer" : ""} ${className}`, children: [_jsx(Div, { className:
|
|
29
|
+
: undefined, onClick: onClick && !href ? () => onClick(post) : undefined, className: `group flex flex-col h-full overflow-hidden rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-sm transition hover:shadow-md ${isInteractive ? "cursor-pointer" : ""} ${className}`, children: [_jsx(Div, { className: `aspect-video w-full ${__O.hidden} bg-neutral-100 dark:bg-slate-800 flex-shrink-0`, children: coverImageUrl ? (_jsx(Div, { role: "img", "aria-label": post.title, className: "h-full w-full bg-center bg-cover transition-transform duration-300 group-hover:scale-105", style: { backgroundImage: `url(${coverImageUrl})` } })) : (_jsx(Div, { className: "h-full w-full bg-gradient-to-br from-zinc-200 via-zinc-100 to-zinc-300 dark:from-slate-800 dark:via-slate-700 dark:to-slate-900 flex items-center justify-center", children: _jsx(Span, { className: "text-4xl opacity-30", "aria-hidden": "true", children: "\u270D\uFE0F" }) })) }), _jsxs(Div, { className: `flex flex-1 flex-col ${__P.p5}`, children: [_jsxs(Row, { className: "mb-2 gap-2 flex-wrap", children: [_jsx(Span, { size: "xs", weight: "medium", className: "rounded-full bg-primary/10 px-2 py-0.5 capitalize text-primary", children: post.category }), post.isFeatured && (_jsx(Span, { size: "xs", weight: "medium", className: CLS_FEATURED_BADGE, children: "Featured" })), post.readTimeMinutes && (_jsxs(Span, { size: "xs", className: "text-zinc-400 dark:text-zinc-400", children: [post.readTimeMinutes, " min read"] }))] }), _jsx(Heading, { level: 3, className: `${THEME_CONSTANTS.utilities.textClamp2} text-base font-semibold text-neutral-900 dark:text-zinc-100 group-hover:text-primary`, children: post.title }), post.excerpt && (_jsx(Text, { className: `mt-2 ${THEME_CONSTANTS.utilities.textClamp3} flex-1 text-sm text-neutral-500 dark:text-zinc-400`, children: post.excerpt })), _jsxs(Row, { className: "mt-auto pt-3 gap-3", children: [post.authorAvatar ? (_jsx(Div, { role: "img", "aria-label": post.authorName ?? "author", className: "h-7 w-7 flex-shrink-0 rounded-full bg-center bg-cover", style: { backgroundImage: `url(${post.authorAvatar})` } })) : post.authorName ? (_jsx(Div, { className: "flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-full bg-primary/10 text-xs font-bold text-primary", children: post.authorName.charAt(0).toUpperCase() })) : null, _jsxs(Text, { className: "text-xs text-neutral-500 dark:text-zinc-400 min-w-0", children: [post.authorName && (_jsx(Span, { weight: "medium", className: "text-neutral-700 dark:text-zinc-300", children: safeDisplayName(post.authorName, "Author") })), date && _jsxs(Span, { className: "ml-1 text-neutral-400", children: ["\u00B7 ", date] })] })] })] })] }));
|
|
22
30
|
if (href) {
|
|
23
31
|
return (_jsx(Link, { href: href, className: "block h-full", children: card }));
|
|
24
32
|
}
|
|
25
33
|
return card;
|
|
26
34
|
}
|
|
27
35
|
export function BlogCategoryTabs({ categories, active, onSelect, labels = {}, }) {
|
|
28
|
-
return (_jsxs(Div, { className:
|
|
36
|
+
return (_jsxs(Div, { className: `scrollbar-none flex gap-2 ${__O.xAuto} pb-1`, children: [_jsx(Button, { onClick: () => onSelect(null), variant: !active ? "primary" : "ghost", size: "sm", className: `whitespace-nowrap rounded-full px-4 py-1.5 text-sm font-medium transition ${!active ? "bg-neutral-900 text-white" : "bg-neutral-100 dark:bg-slate-800 text-neutral-600 dark:text-zinc-300 hover:bg-neutral-200 dark:hover:bg-slate-700"}`, children: labels.all ?? "All" }), categories.map((cat) => (_jsx(Button, { onClick: () => onSelect(cat), variant: active === cat ? "primary" : "ghost", size: "sm", className: `whitespace-nowrap rounded-full px-4 py-1.5 text-sm font-medium capitalize transition ${active === cat ? "bg-neutral-900 text-white" : "bg-neutral-100 dark:bg-slate-800 text-neutral-600 dark:text-zinc-300 hover:bg-neutral-200 dark:hover:bg-slate-700"}`, children: labels[cat] ?? cat }, cat)))] }));
|
|
29
37
|
}
|
|
30
38
|
export function BlogListView({ posts, isLoading, totalPages = 1, currentPage = 1, total = 0, onPageChange, onPostClick, emptyLabel = "No posts found", slots, }) {
|
|
31
39
|
if (isLoading) {
|
|
32
|
-
return (_jsx(Div, { className: "grid gap-6 sm:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsxs(Div, { className: "animate-pulse overflow-hidden rounded-xl border border-neutral-200 dark:border-slate-700 bg-neutral-100 dark:bg-slate-800", children: [_jsx(Div, { className: "aspect-video bg-neutral-200 dark:bg-slate-700" }), _jsxs(Div, { className:
|
|
40
|
+
return (_jsx(Div, { className: "grid gap-6 sm:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsxs(Div, { className: "animate-pulse overflow-hidden rounded-xl border border-neutral-200 dark:border-slate-700 bg-neutral-100 dark:bg-slate-800", children: [_jsx(Div, { className: "aspect-video bg-neutral-200 dark:bg-slate-700" }), _jsxs(Div, { className: `space-y-2 ${__P.p5}`, children: [_jsx(Div, { className: "h-4 w-16 rounded bg-neutral-200 dark:bg-slate-700" }), _jsx(Div, { className: "h-5 w-full rounded bg-neutral-200 dark:bg-slate-700" }), _jsx(Div, { className: "h-4 w-3/4 rounded bg-neutral-200 dark:bg-slate-700" })] })] }, i))) }));
|
|
33
41
|
}
|
|
34
42
|
if (posts.length === 0) {
|
|
35
43
|
if (slots?.renderEmptyState) {
|
|
@@ -9,6 +9,12 @@ import { getMediaUrl } from "../../media/types/index";
|
|
|
9
9
|
import { getDefaultLocale } from "../../../core/baseline-resolver";
|
|
10
10
|
import { normalizeRichTextHtml } from "../../../utils/string.formatter";
|
|
11
11
|
import { ROUTES } from "../../../next/routing/route-map";
|
|
12
|
+
const __P = {
|
|
13
|
+
p8: "p-8",
|
|
14
|
+
};
|
|
15
|
+
const __O = {
|
|
16
|
+
hidden: "overflow-hidden",
|
|
17
|
+
};
|
|
12
18
|
const CATEGORY_BADGE = {
|
|
13
19
|
news: "bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300",
|
|
14
20
|
tips: "bg-emerald-100 text-emerald-800 dark:bg-emerald-900/40 dark:text-emerald-300",
|
|
@@ -16,8 +22,9 @@ const CATEGORY_BADGE = {
|
|
|
16
22
|
updates: "bg-purple-100 text-purple-800 dark:bg-purple-900/40 dark:text-purple-300",
|
|
17
23
|
community: "bg-orange-100 text-orange-800 dark:bg-orange-900/40 dark:text-orange-300",
|
|
18
24
|
};
|
|
25
|
+
const CLS_FEATURED_BADGE = "bg-yellow-100 text-yellow-800 dark:bg-yellow-900/40 dark:text-yellow-300 px-2 py-0.5 rounded-full";
|
|
19
26
|
function renderBlogPostHeader(post, date, labels) {
|
|
20
|
-
return (_jsxs(Div, { className: "mb-8", children: [_jsxs(Row, { className: "gap-2 mb-4", children: [_jsx(Span, { className: `inline-block px-2 py-0.5 rounded-full
|
|
27
|
+
return (_jsxs(Div, { className: "mb-8", children: [_jsxs(Row, { className: "gap-2 mb-4", children: [_jsx(Span, { size: "xs", weight: "medium", className: `inline-block px-2 py-0.5 rounded-full capitalize ${CATEGORY_BADGE[post.category] ?? ""}`, children: post.category }), post.isFeatured && _jsx(Span, { size: "xs", weight: "medium", className: CLS_FEATURED_BADGE, children: labels?.featured ?? "Featured" })] }), _jsx(Heading, { level: 1, className: "text-3xl font-bold mb-4", children: post.title }), post.excerpt && _jsx(Text, { className: "text-lg text-zinc-500 dark:text-zinc-400 mb-6", children: post.excerpt }), _jsxs(Row, { wrap: true, gap: "md", className: "text-sm text-zinc-400 dark:text-zinc-400", children: [post.authorName && _jsxs(Span, { children: [labels?.author ?? "By", " ", _jsx(Span, { weight: "medium", className: "text-zinc-700 dark:text-zinc-300", children: post.authorName })] }), post.readTimeMinutes != null && _jsxs(Span, { children: [post.readTimeMinutes, " ", labels?.readTime ?? "min read"] }), date && _jsxs(Span, { children: [labels?.publishedOn ?? "Published", " ", date] }), post.views != null && _jsxs(Span, { children: [post.views, " ", labels?.viewsLabel ?? "views"] })] })] }));
|
|
21
28
|
}
|
|
22
29
|
function renderBlogPostRelated(related, labels, renderRelatedCard) {
|
|
23
30
|
if (related.length === 0)
|
|
@@ -36,7 +43,7 @@ export function BlogPostView({ slug, initialData, labels = {}, renderImage, rend
|
|
|
36
43
|
if (error || !post) {
|
|
37
44
|
if (renderError)
|
|
38
45
|
return _jsx(_Fragment, { children: renderError(error ?? null) });
|
|
39
|
-
return (_jsxs(Div, { className:
|
|
46
|
+
return (_jsxs(Div, { className: `flex flex-col items-center justify-center min-h-screen gap-4 ${__P.p8}`, children: [_jsx(Heading, { level: 1, className: "text-xl font-semibold", children: labels.notFound ?? "Post not found" }), _jsx(Text, { className: "text-zinc-500 dark:text-zinc-400", children: labels.notFoundDescription ?? "This post is not available." }), renderBackButton?.()] }));
|
|
40
47
|
}
|
|
41
48
|
const date = post.publishedAt
|
|
42
49
|
? new Date(post.publishedAt).toLocaleDateString(getDefaultLocale(), {
|
|
@@ -46,5 +53,5 @@ export function BlogPostView({ slug, initialData, labels = {}, renderImage, rend
|
|
|
46
53
|
})
|
|
47
54
|
: "";
|
|
48
55
|
const coverImageUrl = getMediaUrl(post.coverImage);
|
|
49
|
-
return (_jsxs(Div, { className: `min-h-screen ${className}`, children: [coverImageUrl && (_jsxs(Div, { className:
|
|
56
|
+
return (_jsxs(Div, { className: `min-h-screen ${className}`, children: [coverImageUrl && (_jsxs(Div, { className: `relative h-72 md:h-96 ${__O.hidden}`, children: [renderImage ? (renderImage(post)) : (_jsx(Div, { role: "img", "aria-label": post.title, className: "h-full w-full bg-cover bg-center", style: { backgroundImage: `url(${coverImageUrl})` } })), _jsx(Div, { className: "absolute inset-0 bg-gradient-to-t from-black/50 to-transparent" })] })), _jsxs(Div, { className: "max-w-3xl mx-auto px-4 py-12", children: [renderBlogPostHeader(post, date, labels), post.tags && post.tags.length > 0 && (_jsx(Row, { wrap: true, gap: "sm", className: "mb-8", children: post.tags.map((tag) => (_jsxs(Link, { href: `${String(ROUTES.PUBLIC.BLOG)}?tags=${encodeURIComponent(tag)}`, className: "inline-block px-3 py-1 rounded-full bg-neutral-100 dark:bg-zinc-800 hover:bg-primary/10 text-zinc-600 dark:text-zinc-400 hover:text-primary text-xs font-medium transition-colors", children: ["#", tag] }, tag))) })), renderAuthorBio && _jsx(Div, { className: "mb-6", children: renderAuthorBio(post) }), _jsx(Div, { surface: "card", padding: "xl", className: "mb-12", children: renderContent ? renderContent(post) : (_jsx(RichText, { html: normalizeRichTextHtml(post.content ?? ""), proseClass: "prose max-w-none dark:prose-invert" })) }), renderBlogPostRelated(related, labels, renderRelatedCard), renderBackButton && _jsx(Div, { className: "mt-10 pt-8 border-t border-zinc-200 dark:border-zinc-700", children: renderBackButton() })] })] }));
|
|
50
57
|
}
|