@mohasinac/appkit 2.7.27 → 2.7.31
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/filters/filter-load-options.d.ts +29 -0
- package/dist/_internal/client/features/filters/filter-load-options.js +98 -0
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +1 -1
- package/dist/_internal/server/features/checkout/actions.js +42 -35
- package/dist/_internal/server/features/classified/adapters.d.ts +21 -0
- package/dist/_internal/server/features/classified/adapters.js +24 -0
- package/dist/_internal/server/features/classified/index.d.ts +3 -0
- package/dist/_internal/server/features/classified/index.js +3 -0
- package/dist/_internal/server/features/classified/metadata.d.ts +8 -0
- package/dist/_internal/server/features/classified/metadata.js +43 -0
- package/dist/_internal/server/features/classified/og.d.ts +30 -0
- package/dist/_internal/server/features/classified/og.js +76 -0
- package/dist/_internal/server/features/digital-code/adapters.d.ts +21 -0
- package/dist/_internal/server/features/digital-code/adapters.js +29 -0
- package/dist/_internal/server/features/digital-code/index.d.ts +3 -0
- package/dist/_internal/server/features/digital-code/index.js +3 -0
- package/dist/_internal/server/features/digital-code/metadata.d.ts +8 -0
- package/dist/_internal/server/features/digital-code/metadata.js +36 -0
- package/dist/_internal/server/features/digital-code/og.d.ts +27 -0
- package/dist/_internal/server/features/digital-code/og.js +77 -0
- package/dist/_internal/server/features/live/adapters.d.ts +21 -0
- package/dist/_internal/server/features/live/adapters.js +34 -0
- package/dist/_internal/server/features/live/index.d.ts +3 -0
- package/dist/_internal/server/features/live/index.js +3 -0
- package/dist/_internal/server/features/live/metadata.d.ts +8 -0
- package/dist/_internal/server/features/live/metadata.js +39 -0
- package/dist/_internal/server/features/live/og.d.ts +27 -0
- package/dist/_internal/server/features/live/og.js +72 -0
- package/dist/_internal/server/features/promotions/actions.js +4 -3
- package/dist/_internal/server/jobs/core/onOrderCreate.js +19 -16
- package/dist/_internal/server/jobs/core/onOrderStatusChange.js +25 -22
- package/dist/_internal/server/jobs/core/onProductWrite.js +48 -58
- package/dist/_internal/shared/actions/action-registry.js +504 -9
- package/dist/_internal/shared/features/blog/schema.d.ts +4 -4
- package/dist/_internal/shared/features/brands/schema.d.ts +5 -5
- package/dist/_internal/shared/features/cart/schema.d.ts +18 -18
- package/dist/_internal/shared/features/categories/bundle-copy.d.ts +1 -1
- package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +38 -38
- package/dist/_internal/shared/features/events/schema.d.ts +8 -8
- package/dist/_internal/shared/features/orders/schema.d.ts +8 -8
- package/dist/_internal/shared/features/products/schema.d.ts +42 -42
- package/dist/_internal/shared/features/promotions/schema.d.ts +4 -4
- package/dist/_internal/shared/features/reviews/schema.d.ts +1 -1
- package/dist/_internal/shared/media/limits.js +4 -3
- package/dist/client.d.ts +4 -0
- package/dist/client.js +2 -0
- package/dist/configs/next.js +4 -0
- package/dist/constants/api-endpoints.d.ts +6 -0
- package/dist/constants/api-endpoints.js +2 -0
- package/dist/constants/field-names.d.ts +1 -0
- package/dist/constants/field-names.js +1 -0
- package/dist/constants/table-keys.d.ts +6 -0
- package/dist/constants/table-keys.js +9 -0
- package/dist/core/hooks/useSyncManager.js +9 -8
- package/dist/features/about/components/FeesView.js +10 -7
- package/dist/features/about/components/HelpPageView.js +10 -1
- package/dist/features/about/components/HowAuctionsWorkView.js +10 -1
- package/dist/features/about/components/HowCheckoutWorksView.js +10 -1
- package/dist/features/about/components/HowOffersWorkView.js +10 -1
- package/dist/features/about/components/HowOrdersWorkView.js +10 -1
- package/dist/features/about/components/HowPayoutsWorkView.js +10 -1
- package/dist/features/about/components/HowPreOrdersWorkView.js +10 -1
- package/dist/features/about/components/HowReviewsWorkView.js +10 -1
- package/dist/features/about/components/PublicProfileView.js +46 -16
- package/dist/features/about/components/SecurityPrivacyView.js +7 -1
- package/dist/features/account/components/AddressesIndexListing.js +2 -2
- package/dist/features/account/components/NotificationBell.js +27 -16
- package/dist/features/account/components/NotificationPreferencesPanel.d.ts +9 -0
- package/dist/features/account/components/NotificationPreferencesPanel.js +91 -0
- package/dist/features/account/components/UserSidebar.js +4 -4
- package/dist/features/account/components/UserSupportView.js +16 -6
- package/dist/features/account/components/index.d.ts +2 -0
- package/dist/features/account/components/index.js +1 -0
- package/dist/features/account/schemas/index.d.ts +4 -4
- package/dist/features/account/types/index.d.ts +34 -0
- package/dist/features/admin/actions/admin-actions.js +4 -3
- package/dist/features/admin/actions/notification-actions.d.ts +24 -22
- package/dist/features/admin/actions/notification-actions.js +122 -22
- package/dist/features/admin/components/AdminAdEditorView.js +29 -15
- package/dist/features/admin/components/AdminAddressEditorView.d.ts +7 -0
- package/dist/features/admin/components/AdminAddressEditorView.js +117 -0
- package/dist/features/admin/components/AdminAdsView.js +22 -28
- package/dist/features/admin/components/AdminAllEventEntriesView.js +6 -1
- package/dist/features/admin/components/AdminBidsView.js +10 -3
- package/dist/features/admin/components/AdminBlogEditorView.js +2 -2
- package/dist/features/admin/components/AdminBlogView.js +8 -3
- package/dist/features/admin/components/AdminBrandsView.js +7 -2
- package/dist/features/admin/components/AdminBundleEditorView.js +5 -2
- package/dist/features/admin/components/AdminCarouselEditorView.js +6 -3
- package/dist/features/admin/components/AdminCarouselView.js +13 -7
- package/dist/features/admin/components/AdminCategoriesView.js +8 -3
- package/dist/features/admin/components/AdminCategoryEditorView.js +12 -9
- package/dist/features/admin/components/AdminContactView.js +6 -1
- package/dist/features/admin/components/AdminCouponEditorView.js +8 -2
- package/dist/features/admin/components/AdminCouponsView.js +6 -1
- package/dist/features/admin/components/AdminEmployeeEditorView.js +12 -9
- package/dist/features/admin/components/AdminFaqEditorView.js +2 -2
- package/dist/features/admin/components/AdminFaqsView.js +7 -2
- package/dist/features/admin/components/AdminFeatureFlagsView.js +58 -13
- package/dist/features/admin/components/AdminFeaturesView.js +4 -3
- package/dist/features/admin/components/AdminMediaView.js +9 -8
- package/dist/features/admin/components/AdminNavigationView.js +10 -17
- package/dist/features/admin/components/AdminNewsletterView.js +6 -1
- package/dist/features/admin/components/AdminNotificationsView.js +11 -3
- package/dist/features/admin/components/AdminOrdersView.js +6 -1
- package/dist/features/admin/components/AdminPayoutsView.js +10 -3
- package/dist/features/admin/components/AdminPrizeDrawsView.js +10 -3
- package/dist/features/admin/components/AdminProductEditorView.d.ts +3 -1
- package/dist/features/admin/components/AdminProductEditorView.js +12 -9
- package/dist/features/admin/components/AdminProductsView.js +18 -12
- package/dist/features/admin/components/AdminReturnRequestsView.js +5 -4
- package/dist/features/admin/components/AdminReviewsView.js +36 -26
- package/dist/features/admin/components/AdminScammerEditorView.js +3 -2
- package/dist/features/admin/components/AdminScammersView.js +28 -26
- package/dist/features/admin/components/AdminSectionsView.js +112 -99
- package/dist/features/admin/components/AdminSessionsView.js +10 -3
- package/dist/features/admin/components/AdminSidebar.js +4 -4
- package/dist/features/admin/components/AdminSiteSettingsView.js +45 -4
- package/dist/features/admin/components/AdminStoresView.js +6 -1
- package/dist/features/admin/components/AdminSublistingCategoriesView.js +0 -1
- package/dist/features/admin/components/AdminSupportTicketDetailView.js +1 -1
- package/dist/features/admin/components/AdminSupportTicketsView.js +32 -34
- package/dist/features/admin/components/AdminTeamView.js +6 -1
- package/dist/features/admin/components/AdminUserEditorView.js +8 -15
- package/dist/features/admin/components/AdminUsersView.js +6 -1
- package/dist/features/admin/components/AdminViewCards.js +4 -3
- package/dist/features/admin/components/DashboardStats.js +2 -2
- package/dist/features/admin/components/DataTable.js +2 -2
- package/dist/features/admin/components/index.d.ts +2 -0
- package/dist/features/admin/components/index.js +1 -0
- package/dist/features/admin/components/sections/adminSectionsTypes.js +4 -3
- package/dist/features/admin/repository/chat.repository.js +8 -8
- package/dist/features/admin/repository/site-settings.repository.d.ts +1 -0
- package/dist/features/admin/repository/site-settings.repository.js +11 -9
- package/dist/features/admin/schemas/firestore.d.ts +38 -0
- package/dist/features/admin/schemas/firestore.js +15 -0
- package/dist/features/auctions/components/AuctionBidsTable.d.ts +13 -0
- package/dist/features/auctions/components/AuctionBidsTable.js +62 -0
- package/dist/features/auctions/components/AuctionDetailPageView.js +15 -21
- package/dist/features/auctions/components/AuctionFilters.d.ts +7 -1
- package/dist/features/auctions/components/AuctionFilters.js +3 -2
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +18 -9
- package/dist/features/auctions/components/MarketplaceAuctionGrid.js +3 -2
- package/dist/features/auctions/components/index.d.ts +2 -1
- package/dist/features/auctions/components/index.js +1 -1
- package/dist/features/auctions/schemas/index.d.ts +14 -14
- package/dist/features/auth/actions/realtime-token-actions.js +19 -4
- package/dist/features/auth/components/RegisterForm.js +8 -4
- package/dist/features/auth/consent-otp.d.ts +2 -0
- package/dist/features/auth/consent-otp.js +8 -0
- package/dist/features/auth/schemas/firestore.d.ts +2 -0
- package/dist/features/auth/schemas/firestore.js +18 -25
- package/dist/features/auth/schemas/index.d.ts +2 -2
- package/dist/features/before-after/api/[id]/route.js +8 -6
- package/dist/features/before-after/schemas/index.d.ts +2 -2
- package/dist/features/blog/actions/blog-actions.d.ts +3 -3
- package/dist/features/blog/components/BlogIndexListing.js +21 -2
- package/dist/features/blog/components/BlogPostForm.js +11 -5
- package/dist/features/blog/components/BlogPostView.js +10 -2
- package/dist/features/blog/schemas/index.d.ts +18 -18
- package/dist/features/cart/components/CartDrawer.js +3 -2
- package/dist/features/cart/components/CartView.js +2 -1
- package/dist/features/cart/components/CheckoutView.js +2 -1
- package/dist/features/cart/repository/cart.repository.js +4 -3
- package/dist/features/cart/utils/pending-ops.d.ts +1 -1
- package/dist/features/categories/api/[id]/route.js +4 -3
- package/dist/features/categories/api/route.js +4 -3
- package/dist/features/categories/components/BrandDetailPageView.js +2 -2
- package/dist/features/categories/components/BrandDetailTabs.d.ts +5 -1
- package/dist/features/categories/components/BrandDetailTabs.js +30 -16
- package/dist/features/categories/components/BundleCollage.d.ts +8 -0
- package/dist/features/categories/components/BundleCollage.js +50 -0
- package/dist/features/categories/components/BundleDetailView.js +2 -10
- package/dist/features/categories/components/BundleItemsPicker.js +20 -13
- package/dist/features/categories/components/CategoriesIndexListing.js +28 -9
- package/dist/features/categories/components/CategoryDetailPageView.js +2 -2
- package/dist/features/categories/components/CategoryDetailTabs.d.ts +5 -1
- package/dist/features/categories/components/CategoryDetailTabs.js +31 -16
- package/dist/features/categories/components/CategoryProductsListing.js +52 -13
- package/dist/features/categories/components/index.d.ts +2 -0
- package/dist/features/categories/components/index.js +1 -0
- package/dist/features/categories/schemas/index.d.ts +6 -6
- package/dist/features/checkout/actions/checkout-actions.js +4 -3
- package/dist/features/checkout/hooks/usePaymentCheckout.js +31 -22
- package/dist/features/classified/components/ClassifiedFilters.d.ts +12 -0
- package/dist/features/classified/components/ClassifiedFilters.js +20 -0
- package/dist/features/classified/components/ClassifiedIndexListing.d.ts +4 -0
- package/dist/features/classified/components/ClassifiedIndexListing.js +110 -0
- package/dist/features/classified/components/ClassifiedListView.d.ts +6 -0
- package/dist/features/classified/components/ClassifiedListView.js +43 -0
- package/dist/features/classified/components/index.d.ts +6 -0
- package/dist/features/classified/components/index.js +3 -0
- package/dist/features/collections/api/[slug]/route.js +16 -12
- package/dist/features/collections/schemas/index.d.ts +5 -5
- package/dist/features/consultation/api/[id]/route.js +12 -9
- package/dist/features/consultation/components/ConsultationForm.js +3 -2
- package/dist/features/consultation/schemas/index.d.ts +6 -6
- package/dist/features/contact/email.js +77 -116
- package/dist/features/copilot/components/AdminCopilotView.js +12 -2
- package/dist/features/corporate/api/[id]/route.js +12 -9
- package/dist/features/corporate/components/CorporateInquiryForm.js +2 -1
- package/dist/features/digital-codes/components/DigitalCodeFilters.d.ts +12 -0
- package/dist/features/digital-codes/components/DigitalCodeFilters.js +17 -0
- package/dist/features/digital-codes/components/DigitalCodesIndexListing.d.ts +4 -0
- package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +107 -0
- package/dist/features/digital-codes/components/DigitalCodesListView.d.ts +6 -0
- package/dist/features/digital-codes/components/DigitalCodesListView.js +37 -0
- package/dist/features/digital-codes/components/index.d.ts +6 -0
- package/dist/features/digital-codes/components/index.js +3 -0
- package/dist/features/events/actions/event-actions.js +4 -3
- package/dist/features/events/components/AdminEventEditorView.js +3 -2
- package/dist/features/events/components/AdminEventsView.js +4 -2
- package/dist/features/events/components/EventPollWidget.js +5 -5
- package/dist/features/events/components/EventsIndexListing.js +2 -2
- package/dist/features/events/repository/event-entry.repository.d.ts +1 -0
- package/dist/features/events/repository/event-entry.repository.js +5 -0
- package/dist/features/events/schemas/index.d.ts +20 -20
- package/dist/features/faq/actions/faq-actions.d.ts +8 -8
- package/dist/features/faq/components/ContactCTA.js +3 -1
- package/dist/features/faq/components/FAQAccordion.js +1 -1
- package/dist/features/faq/schemas/index.d.ts +4 -4
- package/dist/features/filters/AsyncFacetSection.d.ts +18 -0
- package/dist/features/filters/AsyncFacetSection.js +65 -0
- package/dist/features/filters/index.d.ts +2 -0
- package/dist/features/filters/index.js +1 -0
- package/dist/features/forms/Checkbox.js +2 -2
- package/dist/features/forms/Input.js +2 -2
- package/dist/features/forms/Radio.js +5 -5
- package/dist/features/forms/Select.js +2 -2
- package/dist/features/forms/Slider.js +2 -2
- package/dist/features/forms/Textarea.js +2 -2
- package/dist/features/homepage/api/[id]/route.js +4 -3
- package/dist/features/homepage/api/sections/[id]/route.js +12 -9
- package/dist/features/homepage/components/AdSlot.js +2 -1
- package/dist/features/homepage/components/AdvertisementBanner.js +5 -3
- package/dist/features/homepage/components/BrandsSection.js +2 -2
- package/dist/features/homepage/components/CTABannerSection.js +2 -2
- package/dist/features/homepage/components/CharacterHotspot.d.ts +2 -2
- package/dist/features/homepage/components/CharacterHotspot.js +119 -157
- package/dist/features/homepage/components/CharacterHotspotForm.js +25 -20
- package/dist/features/homepage/components/CustomCardsSection.js +8 -6
- package/dist/features/homepage/components/FeaturedProductsSection.js +2 -2
- package/dist/features/homepage/components/GoogleReviewsSection.js +3 -3
- package/dist/features/homepage/components/HeroBanner.js +5 -4
- package/dist/features/homepage/components/HeroCarousel.js +13 -26
- package/dist/features/homepage/components/HowItWorksSection.js +4 -2
- package/dist/features/homepage/components/SocialFeedSection.js +2 -2
- package/dist/features/homepage/components/SocialPostCard.js +3 -2
- package/dist/features/homepage/lib/social-feed-fetcher.js +6 -3
- package/dist/features/layout/AppLayoutShell.d.ts +8 -2
- package/dist/features/layout/AppLayoutShell.js +54 -78
- package/dist/features/layout/BottomActions.js +43 -48
- package/dist/features/live/components/LiveItemFilters.d.ts +12 -0
- package/dist/features/live/components/LiveItemFilters.js +24 -0
- package/dist/features/live/components/LiveItemsIndexListing.d.ts +4 -0
- package/dist/features/live/components/LiveItemsIndexListing.js +108 -0
- package/dist/features/live/components/LiveItemsListView.d.ts +6 -0
- package/dist/features/live/components/LiveItemsListView.js +43 -0
- package/dist/features/live/components/index.d.ts +6 -0
- package/dist/features/live/components/index.js +3 -0
- package/dist/features/media/MediaLightbox.js +8 -14
- package/dist/features/media/types/index.d.ts +2 -2
- package/dist/features/media/upload/CameraCapture.js +2 -2
- package/dist/features/media/upload/ImageUpload.js +4 -2
- package/dist/features/media/upload/MediaUploadField.js +24 -8
- package/dist/features/media/upload/MediaUploadList.js +1 -1
- package/dist/features/orders/actions/order-actions.js +4 -3
- package/dist/features/orders/components/MarketplaceOrderCard.js +2 -1
- package/dist/features/orders/components/OrderFilters.js +12 -9
- package/dist/features/orders/schemas/index.d.ts +6 -6
- package/dist/features/pre-orders/api/[id]/route.js +12 -9
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +5 -4
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +29 -22
- package/dist/features/pre-orders/components/PreOrderFilters.d.ts +7 -1
- package/dist/features/pre-orders/components/PreOrderFilters.js +3 -2
- package/dist/features/pre-orders/components/PreOrdersIndexListing.js +17 -52
- package/dist/features/pre-orders/components/PreorderCard.d.ts +0 -9
- package/dist/features/pre-orders/components/PreorderCard.js +2 -13
- package/dist/features/pre-orders/components/index.d.ts +1 -1
- package/dist/features/pre-orders/components/index.js +1 -1
- package/dist/features/pre-orders/schemas/index.d.ts +10 -10
- package/dist/features/products/api/[id]/route.js +9 -7
- package/dist/features/products/api/route.js +1 -1
- package/dist/features/products/columns/productTableColumns.js +3 -3
- package/dist/features/products/components/AuctionsIndexListing.js +15 -51
- package/dist/features/products/components/BidHistory.js +2 -2
- package/dist/features/products/components/CompareOverlay.d.ts +2 -0
- package/dist/features/products/components/CompareOverlay.js +3 -2
- package/dist/features/products/components/MakeOfferButton.js +20 -14
- package/dist/features/products/components/MarketplacePrizeDrawCard.js +2 -1
- package/dist/features/products/components/PrizeDrawCollage.d.ts +1 -15
- package/dist/features/products/components/PrizeDrawCollage.js +54 -14
- package/dist/features/products/components/PrizeDrawDetailPageView.js +2 -1
- package/dist/features/products/components/PrizeDrawEntryActions.js +2 -1
- package/dist/features/products/components/PrizeDrawItemsEditor.js +9 -7
- package/dist/features/products/components/PrizeDrawsIndexListing.js +18 -51
- package/dist/features/products/components/PrizeRevealModal.js +24 -14
- package/dist/features/products/components/ProductDetailPageView.js +2 -1
- package/dist/features/products/components/ProductFilters.d.ts +7 -1
- package/dist/features/products/components/ProductFilters.js +11 -8
- package/dist/features/products/components/ProductForm.js +18 -16
- package/dist/features/products/components/ProductGalleryClient.js +2 -1
- package/dist/features/products/components/ProductGrid.js +12 -15
- package/dist/features/products/components/ProductsIndexListing.js +16 -52
- package/dist/features/products/components/ProductsIndexPageView.js +2 -2
- package/dist/features/products/repository/products.repository.d.ts +4 -0
- package/dist/features/products/repository/products.repository.js +22 -3
- package/dist/features/products/schemas/firestore.d.ts +7 -1
- package/dist/features/products/schemas/index.d.ts +56 -56
- package/dist/features/products/schemas/product-features.validators.d.ts +14 -14
- package/dist/features/products/types/index.d.ts +4 -0
- package/dist/features/promotions/components/CouponsIndexListing.js +1 -1
- package/dist/features/promotions/schemas/index.d.ts +6 -6
- package/dist/features/reviews/actions/review-actions.js +6 -5
- package/dist/features/reviews/api/[id]/route.js +4 -3
- package/dist/features/reviews/components/ReviewDetailPageView.js +2 -2
- package/dist/features/reviews/components/ReviewDetailShell.js +6 -3
- package/dist/features/reviews/components/ReviewsIndexListing.js +2 -2
- package/dist/features/reviews/schemas/index.d.ts +6 -6
- package/dist/features/scams/components/ScamProfileView.js +19 -10
- package/dist/features/scams/components/ScamRegistryView.js +2 -1
- package/dist/features/search/components/Search.d.ts +1 -1
- package/dist/features/search/components/Search.js +56 -49
- package/dist/features/search/schemas/index.d.ts +5 -5
- package/dist/features/seller/actions/offer-actions.js +11 -9
- package/dist/features/seller/components/SellerAddressesView.js +6 -4
- package/dist/features/seller/components/SellerBidsView.js +2 -2
- package/dist/features/seller/components/SellerCouponsView.js +1 -1
- package/dist/features/seller/components/SellerOffersPanel.js +6 -1
- package/dist/features/seller/components/SellerOrdersView.js +1 -1
- package/dist/features/seller/components/SellerPayoutSettingsView.js +3 -3
- package/dist/features/seller/components/SellerPreOrdersView.js +5 -4
- package/dist/features/seller/components/SellerPrizeDrawsView.js +5 -4
- package/dist/features/seller/components/SellerProductShell.d.ts +19 -1
- package/dist/features/seller/components/SellerProductShell.js +75 -9
- package/dist/features/seller/components/SellerProductsView.js +10 -11
- package/dist/features/seller/components/SellerShippingView.js +3 -3
- package/dist/features/seller/components/SellerSidebar.js +10 -7
- package/dist/features/seller/components/SellerStorefrontView.js +3 -3
- package/dist/features/seller/schemas/index.d.ts +4 -4
- package/dist/features/shell/FormShell.js +2 -1
- package/dist/features/shell/QuickFormDrawer.js +4 -3
- package/dist/features/shell/StepForm.js +4 -3
- package/dist/features/stores/actions/store-query-actions.js +4 -3
- package/dist/features/stores/components/StoreAboutView.js +2 -1
- package/dist/features/stores/components/StoreAuctionsListing.js +43 -64
- package/dist/features/stores/components/StoreDetailLayoutView.js +18 -4
- package/dist/features/stores/components/StorePreOrdersListing.js +33 -57
- package/dist/features/stores/components/StoreProductsListing.js +16 -49
- package/dist/features/stores/components/StoresIndexListing.js +2 -2
- package/dist/features/stores/schemas/index.d.ts +2 -2
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +8 -7
- package/dist/features/wishlist/hooks/useGuestWishlist.d.ts +5 -5
- package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +6 -6
- package/dist/features/wishlist/utils/guest-wishlist.d.ts +5 -5
- package/dist/index.d.ts +27 -3
- package/dist/index.js +1743 -1725
- package/dist/monitoring/server-logger.js +5 -9
- package/dist/next/api/apiHandler.js +56 -37
- package/dist/next/components/GlobalError.js +2 -1
- package/dist/next/routing/route-map.d.ts +41 -0
- package/dist/next/routing/route-map.js +17 -0
- package/dist/react/ErrorBoundary.js +2 -1
- package/dist/react/contexts/SessionContext.js +38 -28
- package/dist/react/hooks/useCamera.d.ts +1 -1
- package/dist/react/hooks/useCamera.js +8 -7
- package/dist/seed/products-auctions-seed-data.js +40 -40
- package/dist/seed/products-preorders-seed-data.js +16 -16
- package/dist/seed/products-prize-draws-seed-data.js +4 -4
- package/dist/seed/products-standard-seed-data.js +202 -202
- package/dist/seed/site-settings-seed-data.js +6 -0
- package/dist/server-entry.d.ts +3 -0
- package/dist/server-entry.js +3 -0
- package/dist/server.d.ts +12 -0
- package/dist/server.js +15 -0
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/DataTable.js +28 -7
- package/dist/ui/components/Button.d.ts +8 -1
- package/dist/ui/components/Button.js +47 -8
- package/dist/ui/components/CollageLightbox.d.ts +18 -0
- package/dist/ui/components/CollageLightbox.js +41 -0
- package/dist/ui/components/Dropdown.js +7 -6
- package/dist/ui/components/ImageLightbox.d.ts +7 -1
- package/dist/ui/components/ImageLightbox.js +15 -5
- package/dist/ui/components/PageLoader.js +4 -3
- package/dist/ui/components/PaginatedMultiSelect.d.ts +28 -0
- package/dist/ui/components/PaginatedMultiSelect.js +141 -0
- package/dist/ui/components/PaginatedMultiSelect.style.css +272 -0
- package/dist/ui/components/Semantic.js +1 -1
- package/dist/ui/components/SideDrawer.js +17 -15
- package/dist/ui/components/index.style.css +1 -0
- package/dist/ui/index.d.ts +2 -0
- package/dist/ui/index.js +1 -0
- package/dist/utils/number.formatter.js +5 -13
- package/dist/utils/string.formatter.js +21 -18
- package/dist/validation/schemas.d.ts +2 -2
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@ 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 CLS_BREADCRUMB_LINK = "hover:text-primary-600 transition-colors";
|
|
5
6
|
import { ROUTES } from "../../../next";
|
|
6
7
|
import { getDefaultCurrency } from "../../../core/baseline-resolver";
|
|
7
8
|
import { formatCurrency } from "../../../utils/number.formatter";
|
|
@@ -29,6 +30,16 @@ function toDescriptionHtml(raw) {
|
|
|
29
30
|
const s = typeof raw === "string" ? raw : JSON.stringify(raw);
|
|
30
31
|
return normalizeRichTextHtml(s);
|
|
31
32
|
}
|
|
33
|
+
function renderAuctionInfoPanel(props) {
|
|
34
|
+
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, { className: "inline-block rounded-full bg-amber-100 dark:bg-amber-900/30 px-2.5 py-0.5 text-xs font-semibold text-amber-700 dark:text-amber-300", children: "\uD83C\uDFF7\uFE0F Live Auction" }), isEnded ? (_jsx(Span, { className: "inline-block rounded-full bg-red-100 px-2.5 py-0.5 text-xs font-medium text-red-700 dark:bg-red-900/30 dark:text-red-400", children: "Ended" })) : (_jsx(Span, { className: "inline-block rounded-full bg-emerald-100 px-2.5 py-0.5 text-xs font-medium text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400", 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, { className: "text-2xl font-bold text-primary-600 dark:text-primary-400", children: formatCurrency(currentBid, currency) }), _jsxs(Span, { className: "rounded-full bg-zinc-100 dark:bg-zinc-800 px-3 py-1 text-sm font-medium 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, { className: "font-medium 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, { className: "text-xs text-zinc-600 dark:text-zinc-400", children: "Buy Now:" }), _jsx(Span, { className: "text-base font-bold 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, { 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-xs font-medium 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, { 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-xs font-medium 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-3", 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-500 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
|
+
}
|
|
37
|
+
function renderAuctionStoreReviews(storeReviews) {
|
|
38
|
+
if (storeReviews.length === 0)
|
|
39
|
+
return null;
|
|
40
|
+
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 font-bold 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) ? "text-amber-400" : "text-zinc-200 dark:text-zinc-700", 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, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-white dark:bg-zinc-900/60 p-4 space-y-1.5", children: [_jsx(Row, { justify: "between", align: "center", children: _jsxs(Row, { gap: "xs", align: "center", children: [_jsx(Span, { className: "text-sm font-medium text-zinc-800 dark:text-zinc-200", children: review.userName }), _jsx(Row, { gap: "xs", children: [1, 2, 3, 4, 5].map((star) => _jsx(Span, { className: `text-xs ${star <= review.rating ? "text-amber-400" : "text-zinc-200 dark:text-zinc-700"}`, 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-500", children: review.productTitle })] }, review.id))) })] }));
|
|
42
|
+
}
|
|
32
43
|
export async function AuctionDetailPageView({ id, initialAuction, onPlaceBid, productFeatures }) {
|
|
33
44
|
const product = initialAuction !== undefined
|
|
34
45
|
? (initialAuction ?? undefined)
|
|
@@ -78,8 +89,8 @@ export async function AuctionDetailPageView({ id, initialAuction, onPlaceBid, pr
|
|
|
78
89
|
const storeHref = storeSlug
|
|
79
90
|
? String(ROUTES.PUBLIC.STORE_DETAIL(storeSlug))
|
|
80
91
|
: null;
|
|
81
|
-
const category = typeof p.category === "string" ? p.category : null;
|
|
82
|
-
const categoryName = typeof p.categoryName === "string" ? p.categoryName : null;
|
|
92
|
+
const category = Array.isArray(p.categorySlugs) && p.categorySlugs.length > 0 ? p.categorySlugs[0] : (typeof p.category === "string" ? p.category : null);
|
|
93
|
+
const categoryName = Array.isArray(p.categoryNames) && p.categoryNames.length > 0 ? p.categoryNames[0] : (typeof p.categoryName === "string" ? p.categoryName : null);
|
|
83
94
|
const brand = typeof p.brand === "string" ? p.brand : null;
|
|
84
95
|
const brandSlug = typeof p.brandSlug === "string" ? p.brandSlug : null;
|
|
85
96
|
const tags = Array.isArray(p.tags) ? p.tags : [];
|
|
@@ -105,21 +116,7 @@ export async function AuctionDetailPageView({ id, initialAuction, onPlaceBid, pr
|
|
|
105
116
|
price: typeof p.price === "number" ? p.price : undefined,
|
|
106
117
|
storeId: typeof p.storeId === "string" ? p.storeId : undefined,
|
|
107
118
|
storeName: typeof p.storeName === "string" ? p.storeName : undefined,
|
|
108
|
-
} }), _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:
|
|
109
|
-
featured: "Featured",
|
|
110
|
-
fasterDelivery: "Faster Delivery",
|
|
111
|
-
ratedSeller: "Rated Seller",
|
|
112
|
-
condition: "Condition",
|
|
113
|
-
conditionNew: "New",
|
|
114
|
-
conditionUsed: "Used",
|
|
115
|
-
conditionBroken: "For Parts",
|
|
116
|
-
conditionRefurbished: "Refurbished",
|
|
117
|
-
returnable: "Returnable",
|
|
118
|
-
freeShipping: "Free Shipping",
|
|
119
|
-
codAvailable: "Cash on Delivery",
|
|
120
|
-
wishlistCount: (n) => `${n} wishlisted`,
|
|
121
|
-
categoryProductCount: (n, cat) => `${n} in ${cat}`,
|
|
122
|
-
} }), (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, { 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-xs font-medium 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, { 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-xs font-medium 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-3", 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-500 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" }))] }) }))] })), renderBidForm: () => onPlaceBid ? (_jsx(Div, { id: "auction-bid-form", children: _jsx(PlaceBidFormClient, { productId: String(product.id), currentBid: currentBid, startingBid: startingBid, minBidIncrement: minBidIncrement, currency: currency, isEnded: isEnded, buyNowPrice: buyNowPrice, bidCount: bidCount, tags: tags, onPlaceBid: onPlaceBid }) })) : (
|
|
119
|
+
} }), _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", children: _jsx(PlaceBidFormClient, { productId: String(product.id), currentBid: currentBid, startingBid: startingBid, minBidIncrement: minBidIncrement, currency: currency, isEnded: isEnded, buyNowPrice: buyNowPrice, bidCount: bidCount, tags: tags, onPlaceBid: onPlaceBid }) })) : (
|
|
123
120
|
/* Read-only bid panel — shown when no bid action is wired (preview/demo) */
|
|
124
121
|
_jsxs(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 p-5 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 && (_jsxs(Button, { variant: "secondary", size: "md", className: "w-full", 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, { 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))) }) }))] })), renderMobileBidForm: () => !isEnded && onPlaceBid ? (_jsx(Div, { className: "lg:hidden", children: _jsx(PlaceBidFormClient, { productId: String(product.id), currentBid: currentBid, startingBid: startingBid, minBidIncrement: minBidIncrement, currency: currency, isEnded: isEnded, buyNowPrice: buyNowPrice, bidCount: bidCount, tags: tags, onPlaceBid: onPlaceBid }) })) : !isEnded ? (_jsxs(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/60 p-4 lg:hidden", children: [_jsxs(Row, { align: "center", gap: "sm", className: "mb-3", children: [_jsx(Span, { className: "text-base font-bold text-primary-600 dark:text-primary-400", children: formatCurrency(currentBid, currency) }), _jsxs(Span, { className: "text-xs text-zinc-500", children: [bidCount, " bids"] })] }), _jsx(Button, { variant: "primary", size: "md", className: "w-full", children: "Place Bid" })] })) : null, renderSublistingSection: sublistingCategoryId
|
|
125
122
|
? () => (_jsx(SublistingCarouselSection, { sublistingCategoryId: sublistingCategoryId, currentListingId: String(product.id) }))
|
|
@@ -176,8 +173,5 @@ export async function AuctionDetailPageView({ id, initialAuction, onPlaceBid, pr
|
|
|
176
173
|
if (related.length === 0)
|
|
177
174
|
return null;
|
|
178
175
|
return (_jsx(RelatedProducts, { labels: { title: "Similar Auctions" }, renderGrid: () => (_jsx(MarketplaceAuctionGrid, { auctions: related, gridClassName: "grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4" })) }));
|
|
179
|
-
} }), storeReviews
|
|
180
|
-
const avg = storeReviews.reduce((s, r) => s + r.rating, 0) / storeReviews.length;
|
|
181
|
-
return (_jsxs(Div, { className: "mb-4 flex items-center gap-3", children: [_jsx(Span, { className: "text-3xl font-bold 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) ? "text-amber-400" : "text-zinc-200 dark:text-zinc-700", children: "\u2605" }, star))) }), _jsxs(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: [storeReviews.length, " review", storeReviews.length !== 1 ? "s" : ""] })] })] }));
|
|
182
|
-
})(), _jsx(Stack, { gap: "sm", children: storeReviews.slice(0, 10).map((review) => (_jsxs(Div, { className: "rounded-xl border border-zinc-100 dark:border-zinc-800 bg-white dark:bg-zinc-900/60 p-4 space-y-1.5", children: [_jsx(Row, { justify: "between", align: "center", children: _jsxs(Row, { gap: "xs", align: "center", children: [_jsx(Span, { className: "text-sm font-medium text-zinc-800 dark:text-zinc-200", children: review.userName }), _jsx(Row, { gap: "xs", children: [1, 2, 3, 4, 5].map((star) => (_jsx(Span, { className: `text-xs ${star <= review.rating ? "text-amber-400" : "text-zinc-200 dark:text-zinc-700"}`, 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-500", children: review.productTitle })] }, review.id))) })] })), !isEnded && (_jsxs(BuyBar, { children: [_jsx(Span, { className: "mr-auto text-sm font-bold text-zinc-900 dark:text-zinc-50", children: formatCurrency(currentBid, currency) }), _jsxs(Span, { className: "text-xs text-zinc-400 dark:text-zinc-500 mr-1", children: [bidCount, " bid", bidCount !== 1 ? "s" : ""] }), _jsx("a", { href: "#auction-bid-form", className: "appkit-button appkit-button--primary appkit-button--sm shrink-0", children: _jsx("span", { className: "appkit-button__content", children: "Place Bid" }) })] }))] })] }));
|
|
176
|
+
} }), renderAuctionStoreReviews(storeReviews), !isEnded && (_jsxs(BuyBar, { children: [_jsx(Span, { className: "mr-auto text-sm font-bold text-zinc-900 dark:text-zinc-50", children: formatCurrency(currentBid, currency) }), _jsxs(Span, { className: "text-xs text-zinc-400 dark:text-zinc-500 mr-1", children: [bidCount, " bid", bidCount !== 1 ? "s" : ""] }), _jsx("a", { href: "#auction-bid-form", className: "appkit-button appkit-button--primary appkit-button--sm shrink-0", children: _jsx("span", { className: "appkit-button__content", children: "Place Bid" }) })] }))] })] }));
|
|
183
177
|
}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import type { FacetOption } from "../../filters/FilterFacetSection";
|
|
2
2
|
import type { UrlTable } from "../../filters/FilterPanel";
|
|
3
|
+
import type { AsyncFacetSectionProps } from "../../filters/AsyncFacetSection";
|
|
4
|
+
type LoadOptionsFn = AsyncFacetSectionProps["loadOptions"];
|
|
3
5
|
export interface AuctionFiltersProps {
|
|
4
6
|
table: UrlTable;
|
|
5
7
|
categoryOptions?: FacetOption[];
|
|
6
8
|
brandOptions?: FacetOption[];
|
|
7
9
|
storeOptions?: FacetOption[];
|
|
10
|
+
loadCategoryOptions?: LoadOptionsFn;
|
|
11
|
+
loadBrandOptions?: LoadOptionsFn;
|
|
12
|
+
loadStoreOptions?: LoadOptionsFn;
|
|
8
13
|
currencyPrefix?: string;
|
|
9
14
|
}
|
|
10
|
-
export declare function AuctionFilters({ table, categoryOptions, brandOptions, storeOptions, currencyPrefix, }: AuctionFiltersProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export declare function AuctionFilters({ table, categoryOptions, brandOptions, storeOptions, loadCategoryOptions, loadBrandOptions, loadStoreOptions, currencyPrefix, }: AuctionFiltersProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export {};
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useTranslations } from "next-intl";
|
|
4
4
|
import { FilterFacetSection } from "../../filters/FilterFacetSection";
|
|
5
|
+
import { AsyncFacetSection } from "../../filters/AsyncFacetSection";
|
|
5
6
|
import { RangeFilter } from "../../filters/RangeFilter";
|
|
6
7
|
import { Div } from "../../../ui";
|
|
7
|
-
export function AuctionFilters({ table, categoryOptions = [], brandOptions = [], storeOptions = [], currencyPrefix = "", }) {
|
|
8
|
+
export function AuctionFilters({ table, categoryOptions = [], brandOptions = [], storeOptions = [], loadCategoryOptions, loadBrandOptions, loadStoreOptions, currencyPrefix = "", }) {
|
|
8
9
|
const t = useTranslations("filters");
|
|
9
10
|
const selectedCategories = table.get("category")
|
|
10
11
|
? table.get("category").split("|").filter(Boolean)
|
|
@@ -13,5 +14,5 @@ export function AuctionFilters({ table, categoryOptions = [], brandOptions = [],
|
|
|
13
14
|
const selectedStores = table.get("storeId")
|
|
14
15
|
? table.get("storeId").split("|").filter(Boolean)
|
|
15
16
|
: [];
|
|
16
|
-
return (_jsxs(Div, { children: [categoryOptions.length > 0
|
|
17
|
+
return (_jsxs(Div, { children: [loadCategoryOptions ? (_jsx(AsyncFacetSection, { title: t("category"), loadOptions: loadCategoryOptions, selected: selectedCategories, onChange: (vals) => table.set("category", vals.join("|")), defaultCollapsed: false })) : categoryOptions.length > 0 ? (_jsx(FilterFacetSection, { title: t("category"), options: categoryOptions, selected: selectedCategories, onChange: (vals) => table.set("category", vals.join("|")), searchable: true, defaultCollapsed: categoryOptions.length > 6 })) : null, loadBrandOptions ? (_jsx(AsyncFacetSection, { title: t("brand"), loadOptions: loadBrandOptions, selected: selectedBrands, onChange: (vals) => table.set("brand", vals[0] ?? ""), defaultCollapsed: false })) : brandOptions.length > 0 ? (_jsx(FilterFacetSection, { title: t("brand"), options: brandOptions, selected: selectedBrands, onChange: (vals) => table.set("brand", vals[0] ?? ""), searchable: brandOptions.length > 4, defaultCollapsed: brandOptions.length > 6 })) : null, _jsx(RangeFilter, { title: t("bidPriceRange"), minValue: table.get("minBid"), maxValue: table.get("maxBid"), onMinChange: (v) => table.set("minBid", v), onMaxChange: (v) => table.set("maxBid", v), prefix: currencyPrefix, showSlider: true, minBound: 0, maxBound: 500000, step: 500, minPlaceholder: t("minBidPrice"), maxPlaceholder: t("maxBidPrice"), defaultCollapsed: false }), loadStoreOptions ? (_jsx(AsyncFacetSection, { title: t("store"), loadOptions: loadStoreOptions, selected: selectedStores, onChange: (vals) => table.set("storeId", vals[0] ?? ""), defaultCollapsed: false })) : storeOptions.length > 0 ? (_jsx(FilterFacetSection, { title: t("store"), options: storeOptions, selected: selectedStores, onChange: (vals) => table.set("storeId", vals[0] ?? ""), searchable: storeOptions.length > 4, defaultCollapsed: storeOptions.length > 6 })) : null, _jsx(RangeFilter, { title: t("dateRange"), type: "date", minValue: table.get("dateFrom"), maxValue: table.get("dateTo"), onMinChange: (v) => table.set("dateFrom", v), onMaxChange: (v) => table.set("dateTo", v), minPlaceholder: t("minDate"), maxPlaceholder: t("maxDate"), defaultCollapsed: false })] }));
|
|
17
18
|
}
|
|
@@ -12,6 +12,18 @@ 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
|
+
function renderAuctionCardHero(props) {
|
|
16
|
+
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: "h-5 w-5 fill-amber-400 text-amber-400" }) })) : 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, { className: "rounded-full bg-rose-600/90 px-2 py-0.5 text-xs font-bold text-white", children: mergedLabels.liveBadge }) : null, isEndingSoon ? _jsx(Span, { className: "rounded-full bg-amber-500/90 px-2 py-0.5 text-xs font-bold text-white", children: mergedLabels.endingSoon }) : null, isEnded ? _jsx(Span, { className: "rounded-full bg-zinc-600/90 px-2 py-0.5 text-xs font-bold text-white", children: mergedLabels.ended }) : null, product.status === "sold" ? _jsx(Span, { className: "rounded-full bg-zinc-700/90 px-2 py-0.5 text-xs font-bold text-white", children: mergedLabels.sold }) : null] }), _jsx(Div, { className: "pointer-events-none absolute bottom-2 right-2 z-10", children: _jsxs(Span, { className: "inline-flex items-center gap-1 rounded-full bg-amber-600/90 px-2 py-0.5 text-xs font-semibold text-white", children: [_jsx(Gavel, { className: "h-3 w-3" }), mergedLabels.typeBadge] }) })] }));
|
|
18
|
+
}
|
|
19
|
+
function renderAuctionCardInfoList(props) {
|
|
20
|
+
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 ? "fill-rose-500 text-rose-500" : "text-zinc-400"}` }) })) : 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
|
+
}
|
|
23
|
+
function renderAuctionCardInfoGrid(props) {
|
|
24
|
+
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 ? "fill-rose-500 text-rose-500" : "text-zinc-400"}` }) })) : 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
|
+
}
|
|
15
27
|
const DEFAULT_LABELS = {
|
|
16
28
|
selectItem: "Select item",
|
|
17
29
|
deselectItem: "Deselect item",
|
|
@@ -137,13 +149,10 @@ export function MarketplaceAuctionCard({ product, buyoutPrice, className = "", v
|
|
|
137
149
|
: isEndingSoon
|
|
138
150
|
? COUNTDOWN_STATUS_CLASS.endingSoon
|
|
139
151
|
: COUNTDOWN_STATUS_CLASS.live;
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
: hasCurrentBid
|
|
147
|
-
? mergedLabels.currentBid
|
|
148
|
-
: 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] })) })] })) })] }));
|
|
152
|
+
const cardInfoProps = {
|
|
153
|
+
product, auctionHref, displayBid, bidCount, hasCurrentBid, isEnded, isEndingSoon,
|
|
154
|
+
remaining, resolvedBuyoutPrice, inWishlist, wishlistLoading, wishlistActions,
|
|
155
|
+
countdownClass, mergedLabels, handleWishlist, handleNavigate,
|
|
156
|
+
};
|
|
157
|
+
return (_jsxs(BaseListingCard, { isSelected: isSelected, isDisabled: isEnded, variant: baseVariant, className: className, onMouseDown: !isSelected ? longPress.onMouseDown : undefined, onMouseUp: !isSelected ? longPress.onMouseUp : undefined, onMouseLeave: !isSelected ? longPress.onMouseLeave : undefined, onTouchStart: !isSelected ? longPress.onTouchStart : undefined, onTouchEnd: !isSelected ? longPress.onTouchEnd : undefined, children: [renderAuctionCardHero({ product, auctionHref, currentSrc, hovered, images, imageIndex, hasVideo, isEnded, isEndingSoon, isSelected, selectable, mergedLabels, onSelect, setHovered, handleSelect }), _jsx(BaseListingCard.Info, { variant: baseVariant, children: baseVariant === "list" ? renderAuctionCardInfoList(cardInfoProps) : renderAuctionCardInfoGrid(cardInfoProps) })] }));
|
|
149
158
|
}
|
|
@@ -3,15 +3,16 @@ 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 CLS_SKELETON_BTN = "h-8 w-20 rounded bg-zinc-300";
|
|
6
7
|
const DEFAULT_GRID_LABELS = {
|
|
7
8
|
emptyTitle: "No auctions found",
|
|
8
9
|
emptyDescription: "Check back later for live listings.",
|
|
9
10
|
};
|
|
10
11
|
function AuctionCardSkeleton({ variant = "grid", }) {
|
|
11
12
|
if (variant === "list") {
|
|
12
|
-
return (_jsxs(Div, { className: "flex min-h-[220px] flex-row overflow-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-3", 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:
|
|
13
|
+
return (_jsxs(Div, { className: "flex min-h-[220px] flex-row overflow-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-3", 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 })] })] })] }));
|
|
13
14
|
}
|
|
14
|
-
return (_jsxs(Div, { className: "overflow-hidden rounded-xl bg-zinc-200 animate-pulse", children: [_jsx(Div, { className: "aspect-square bg-zinc-300" }), _jsxs(Div, { className: "space-y-2 p-3", 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:
|
|
15
|
+
return (_jsxs(Div, { className: "overflow-hidden rounded-xl bg-zinc-200 animate-pulse", children: [_jsx(Div, { className: "aspect-square bg-zinc-300" }), _jsxs(Div, { className: "space-y-2 p-3", 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 }) })] })] }));
|
|
15
16
|
}
|
|
16
17
|
export function MarketplaceAuctionGrid({ auctions, loading = false, skeletonCount = 12, variant = "grid", selectable = false, selectedIds = [], onSelectionChange, gridClassName, emptyIcon, labels, cardLabels, wishlistActions, }) {
|
|
17
18
|
const mergedLabels = { ...DEFAULT_GRID_LABELS, ...labels };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export { AuctionCard, AuctionCountdown } from "./AuctionCard";
|
|
2
1
|
export { MarketplaceAuctionCard, type MarketplaceAuctionCardData, type MarketplaceAuctionCardLabels, type MarketplaceAuctionCardProps, } from "./MarketplaceAuctionCard";
|
|
3
2
|
export { MarketplaceAuctionGrid, type MarketplaceAuctionGridLabels, type MarketplaceAuctionGridProps, } from "./MarketplaceAuctionGrid";
|
|
4
3
|
export { AuctionsListView } from "./AuctionsListView";
|
|
5
4
|
export { AuctionDetailPageView } from "./AuctionDetailPageView";
|
|
6
5
|
export type { AuctionDetailPageViewProps } from "./AuctionDetailPageView";
|
|
6
|
+
export { AuctionBidsTable } from "./AuctionBidsTable";
|
|
7
|
+
export type { AuctionBidsTableProps, AuctionWithBids } from "./AuctionBidsTable";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { AuctionCard, AuctionCountdown } from "./AuctionCard";
|
|
2
1
|
export { MarketplaceAuctionCard, } from "./MarketplaceAuctionCard";
|
|
3
2
|
export { MarketplaceAuctionGrid, } from "./MarketplaceAuctionGrid";
|
|
4
3
|
export { AuctionsListView } from "./AuctionsListView";
|
|
5
4
|
export { AuctionDetailPageView } from "./AuctionDetailPageView";
|
|
5
|
+
export { AuctionBidsTable } from "./AuctionBidsTable";
|
|
@@ -31,14 +31,14 @@ export declare const auctionItemSchema: z.ZodObject<{
|
|
|
31
31
|
}, "strip", z.ZodTypeAny, {
|
|
32
32
|
type: "video" | "image" | "file";
|
|
33
33
|
url: string;
|
|
34
|
-
source?: "
|
|
34
|
+
source?: "upload" | "youtube" | "external" | undefined;
|
|
35
35
|
alt?: string | undefined;
|
|
36
36
|
thumbnailUrl?: string | undefined;
|
|
37
37
|
youtubeId?: string | undefined;
|
|
38
38
|
}, {
|
|
39
39
|
type: "video" | "image" | "file";
|
|
40
40
|
url: string;
|
|
41
|
-
source?: "
|
|
41
|
+
source?: "upload" | "youtube" | "external" | undefined;
|
|
42
42
|
alt?: string | undefined;
|
|
43
43
|
thumbnailUrl?: string | undefined;
|
|
44
44
|
youtubeId?: string | undefined;
|
|
@@ -64,27 +64,27 @@ export declare const auctionItemSchema: z.ZodObject<{
|
|
|
64
64
|
updatedAt: string;
|
|
65
65
|
status: "draft" | "published" | "archived" | "sold";
|
|
66
66
|
title: string;
|
|
67
|
-
price: number;
|
|
68
67
|
featured: boolean;
|
|
69
68
|
listingType: "auction";
|
|
70
69
|
slug: string;
|
|
70
|
+
price: number;
|
|
71
71
|
auctionEndDate: string;
|
|
72
72
|
startingBid: number;
|
|
73
73
|
bidCount: number;
|
|
74
74
|
sellerId: string;
|
|
75
75
|
storeId?: string | undefined;
|
|
76
|
+
description?: string | undefined;
|
|
77
|
+
mainImage?: string | undefined;
|
|
78
|
+
images?: string[] | undefined;
|
|
79
|
+
currentBid?: number | undefined;
|
|
76
80
|
media?: {
|
|
77
81
|
type: "video" | "image" | "file";
|
|
78
82
|
url: string;
|
|
79
|
-
source?: "
|
|
83
|
+
source?: "upload" | "youtube" | "external" | undefined;
|
|
80
84
|
alt?: string | undefined;
|
|
81
85
|
thumbnailUrl?: string | undefined;
|
|
82
86
|
youtubeId?: string | undefined;
|
|
83
87
|
}[] | undefined;
|
|
84
|
-
images?: string[] | undefined;
|
|
85
|
-
description?: string | undefined;
|
|
86
|
-
mainImage?: string | undefined;
|
|
87
|
-
currentBid?: number | undefined;
|
|
88
88
|
storeSlug?: string | undefined;
|
|
89
89
|
}, {
|
|
90
90
|
currency: string;
|
|
@@ -93,27 +93,27 @@ export declare const auctionItemSchema: z.ZodObject<{
|
|
|
93
93
|
updatedAt: string;
|
|
94
94
|
status: "draft" | "published" | "archived" | "sold";
|
|
95
95
|
title: string;
|
|
96
|
-
price: number;
|
|
97
96
|
featured: boolean;
|
|
98
97
|
listingType: "auction";
|
|
99
98
|
slug: string;
|
|
99
|
+
price: number;
|
|
100
100
|
auctionEndDate: string;
|
|
101
101
|
startingBid: number;
|
|
102
102
|
bidCount: number;
|
|
103
103
|
sellerId: string;
|
|
104
104
|
storeId?: string | undefined;
|
|
105
|
+
description?: string | undefined;
|
|
106
|
+
mainImage?: string | undefined;
|
|
107
|
+
images?: string[] | undefined;
|
|
108
|
+
currentBid?: number | undefined;
|
|
105
109
|
media?: {
|
|
106
110
|
type: "video" | "image" | "file";
|
|
107
111
|
url: string;
|
|
108
|
-
source?: "
|
|
112
|
+
source?: "upload" | "youtube" | "external" | undefined;
|
|
109
113
|
alt?: string | undefined;
|
|
110
114
|
thumbnailUrl?: string | undefined;
|
|
111
115
|
youtubeId?: string | undefined;
|
|
112
116
|
}[] | undefined;
|
|
113
|
-
images?: string[] | undefined;
|
|
114
|
-
description?: string | undefined;
|
|
115
|
-
mainImage?: string | undefined;
|
|
116
|
-
currentBid?: number | undefined;
|
|
117
117
|
storeSlug?: string | undefined;
|
|
118
118
|
}>;
|
|
119
119
|
export declare const bidRecordSchema: z.ZodObject<{
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { getAdminAuth } from "../../../providers/db-firebase/index";
|
|
8
8
|
import { chatRepository } from "../../admin/repository/chat.repository";
|
|
9
|
+
import { conversationsRepository } from "../../messages/repository/conversations.repository";
|
|
10
|
+
import { storeRepository } from "../../stores/repository/store.repository";
|
|
9
11
|
import { serverLogger } from "../../../monitoring/index";
|
|
10
12
|
export async function issueRealtimeToken(userId, userRole) {
|
|
11
13
|
let chatIds = {};
|
|
@@ -14,14 +16,27 @@ export async function issueRealtimeToken(userId, userRole) {
|
|
|
14
16
|
chatIds = Object.fromEntries(userChatIds.map((id) => [id, true]));
|
|
15
17
|
}
|
|
16
18
|
catch (err) {
|
|
17
|
-
serverLogger.warn("Could not resolve chatIds for realtime token", {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
serverLogger.warn("Could not resolve chatIds for realtime token", { userId, err });
|
|
20
|
+
}
|
|
21
|
+
let conversationIds = {};
|
|
22
|
+
try {
|
|
23
|
+
const buyerConvs = await conversationsRepository.listByBuyer(userId);
|
|
24
|
+
buyerConvs.forEach((c) => { conversationIds[c.id] = true; });
|
|
25
|
+
if (userRole === "seller") {
|
|
26
|
+
const store = await storeRepository.findByOwnerId(userId);
|
|
27
|
+
if (store?.id) {
|
|
28
|
+
const sellerConvs = await conversationsRepository.listByStore(store.id);
|
|
29
|
+
sellerConvs.forEach((c) => { conversationIds[c.id] = true; });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
serverLogger.warn("Could not resolve conversationIds for realtime token", { userId, err });
|
|
21
35
|
}
|
|
22
36
|
const customToken = await getAdminAuth().createCustomToken(userId, {
|
|
23
37
|
role: userRole,
|
|
24
38
|
chatIds,
|
|
39
|
+
conversationIds,
|
|
25
40
|
});
|
|
26
41
|
serverLogger.info("issueRealtimeToken: token issued", {
|
|
27
42
|
userId,
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useCallback, useState } from "react";
|
|
4
4
|
import { Alert, Div, Heading, Label, Text } from "../../../ui";
|
|
5
|
+
function renderRegisterFormFields(props) {
|
|
6
|
+
const { values, setValues, labels, renderTermsLink, renderPasswordStrength } = props;
|
|
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";
|
|
8
|
+
const CLS_LABEL = "block text-sm font-medium mb-1";
|
|
9
|
+
return (_jsxs(_Fragment, { children: [_jsxs(Div, { children: [_jsx(Label, { htmlFor: "reg-name", className: CLS_LABEL, children: labels?.displayNameLabel ?? "Full name" }), _jsx("input", { id: "reg-name", name: "displayName", type: "text", autoComplete: "name", required: true, placeholder: labels?.displayNamePlaceholder ?? "Your name", value: values.displayName, onChange: (e) => setValues({ ...values, displayName: e.target.value }), className: "w-full rounded-lg border border-neutral-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary" })] }), _jsxs(Div, { children: [_jsx(Label, { htmlFor: "reg-email", className: CLS_LABEL, children: labels?.emailLabel ?? "Email address" }), _jsx("input", { id: "reg-email", name: "email", type: "email", autoComplete: "username", required: true, placeholder: labels?.emailPlaceholder ?? "you@example.com", value: values.email, onChange: (e) => setValues({ ...values, email: e.target.value }), className: CLS_INPUT })] }), _jsxs(Div, { children: [_jsx(Label, { htmlFor: "reg-password", className: CLS_LABEL, children: labels?.passwordLabel ?? "Password" }), _jsx("input", { id: "reg-password", name: "password", type: "password", autoComplete: "new-password", required: true, placeholder: labels?.passwordPlaceholder ?? "••••••••", value: values.password, onChange: (e) => setValues({ ...values, password: e.target.value }), className: CLS_INPUT }), renderPasswordStrength?.(values.password)] }), _jsxs(Div, { children: [_jsx(Label, { htmlFor: "reg-confirm", className: CLS_LABEL, children: labels?.confirmPasswordLabel ?? "Confirm password" }), _jsx("input", { id: "reg-confirm", name: "confirmPassword", type: "password", autoComplete: "new-password", required: true, placeholder: labels?.confirmPasswordPlaceholder ?? "••••••••", value: values.confirmPassword, onChange: (e) => setValues({ ...values, confirmPassword: e.target.value }), className: CLS_INPUT })] }), _jsxs(Div, { className: "flex items-start gap-2", children: [_jsx("input", { id: "reg-terms", type: "checkbox", required: true, checked: values.acceptTerms, onChange: (e) => setValues({ ...values, acceptTerms: e.target.checked }), className: "mt-0.5 h-4 w-4 rounded border-neutral-300 dark:border-slate-600 accent-primary" }), _jsxs(Label, { htmlFor: "reg-terms", className: "text-sm leading-snug", children: [labels?.acceptTermsLabel ?? "I accept the", " ", renderTermsLink?.()] })] })] }));
|
|
10
|
+
}
|
|
5
11
|
export function RegisterForm({ onSubmit, isLoading = false, error, success, labels = {}, renderSocialButtons, renderLoginLink, renderTermsLink, renderPasswordStrength, className = "", }) {
|
|
6
12
|
const [values, setValues] = useState({
|
|
7
13
|
email: "",
|
|
@@ -21,7 +27,5 @@ export function RegisterForm({ onSubmit, isLoading = false, error, success, labe
|
|
|
21
27
|
await onSubmit(values);
|
|
22
28
|
}, [onSubmit, values, labels.passwordMismatch]);
|
|
23
29
|
const displayError = error ?? validationError;
|
|
24
|
-
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: [
|
|
25
|
-
? (labels.submittingLabel ?? "Creating account…")
|
|
26
|
-
: (labels.submitLabel ?? "Create account") })] }), renderSocialButtons?.()] }) }));
|
|
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", disabled: isLoading, className: "w-full rounded-lg bg-zinc-900 px-4 py-2.5 text-sm font-semibold text-white disabled:opacity-60 hover:bg-zinc-800 dark:bg-zinc-100 dark:text-zinc-900 dark:hover:bg-zinc-200 transition-colors", children: isLoading ? (labels.submittingLabel ?? "Creating account…") : (labels.submitLabel ?? "Create account") })] }), renderSocialButtons?.()] }) }));
|
|
27
31
|
}
|
|
@@ -46,6 +46,8 @@ export declare function saveConsentOtp(uid: string, addressId: string, data: Rec
|
|
|
46
46
|
export declare function readConsentOtp(uid: string, addressId: string): Promise<ConsentOtpDoc | null>;
|
|
47
47
|
/** Partially update a consent OTP document. */
|
|
48
48
|
export declare function patchConsentOtp(uid: string, addressId: string, data: Record<string, unknown>): Promise<void>;
|
|
49
|
+
/** Build the consent OTP WhatsApp message body. */
|
|
50
|
+
export declare function buildConsentOtpWhatsApp(recipientName: string, code: string, siteName: string): string;
|
|
49
51
|
/** Build the consent OTP email subject and HTML body. */
|
|
50
52
|
export declare function buildConsentOtpEmail(recipientName: string, code: string, siteName: string): {
|
|
51
53
|
subject: string;
|
|
@@ -102,6 +102,14 @@ export async function patchConsentOtp(uid, addressId, data) {
|
|
|
102
102
|
const db = getAdminDb();
|
|
103
103
|
await consentOtpRef(db, uid, addressId).update(data);
|
|
104
104
|
}
|
|
105
|
+
/** Build the consent OTP WhatsApp message body. */
|
|
106
|
+
export function buildConsentOtpWhatsApp(recipientName, code, siteName) {
|
|
107
|
+
return (`*${siteName} — Consent OTP*\n\n` +
|
|
108
|
+
`You are shipping to *${recipientName}*.\n\n` +
|
|
109
|
+
`Your verification code is: *${code}*\n\n` +
|
|
110
|
+
`This code expires in ${CONSENT_OTP_EXPIRY_MINUTES} minutes. ` +
|
|
111
|
+
`If you did not request this, please ignore this message.`);
|
|
112
|
+
}
|
|
105
113
|
/** Build the consent OTP email subject and HTML body. */
|
|
106
114
|
export function buildConsentOtpEmail(recipientName, code, siteName) {
|
|
107
115
|
return {
|
|
@@ -98,6 +98,8 @@ export interface UserDocument {
|
|
|
98
98
|
hardBannedBy?: string;
|
|
99
99
|
/** Timestamp when user confirmed they read the scam awareness guide. Required before full platform access. */
|
|
100
100
|
scamAwarenessAcknowledgedAt?: Date;
|
|
101
|
+
/** User-controlled notification channel and type preferences. */
|
|
102
|
+
notificationPreferences?: import("../../account/types").NotificationPreferences;
|
|
101
103
|
}
|
|
102
104
|
export interface UserSoftBan {
|
|
103
105
|
action: BannedAction;
|
|
@@ -212,31 +212,24 @@ export const sessionQueryHelpers = {
|
|
|
212
212
|
};
|
|
213
213
|
export function parseUserAgent(userAgent) {
|
|
214
214
|
const ua = userAgent.toLowerCase();
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
else if (ua.includes("ios") || ua.includes("iphone") || ua.includes("ipad"))
|
|
234
|
-
os = "iOS";
|
|
235
|
-
let device = "Desktop";
|
|
236
|
-
if (ua.includes("mobile"))
|
|
237
|
-
device = "Mobile";
|
|
238
|
-
else if (ua.includes("tablet") || ua.includes("ipad"))
|
|
239
|
-
device = "Tablet";
|
|
215
|
+
const BROWSER_TOKENS = [
|
|
216
|
+
["chrome", "Chrome"],
|
|
217
|
+
["firefox", "Firefox"],
|
|
218
|
+
["safari", "Safari"],
|
|
219
|
+
["edge", "Edge"],
|
|
220
|
+
];
|
|
221
|
+
const browser = BROWSER_TOKENS.find(([tok]) => ua.includes(tok))?.[1] ?? "Unknown";
|
|
222
|
+
const OS_TOKENS = [
|
|
223
|
+
["windows", "Windows"],
|
|
224
|
+
["mac", "macOS"],
|
|
225
|
+
["linux", "Linux"],
|
|
226
|
+
["android", "Android"],
|
|
227
|
+
[["ios", "iphone", "ipad"], "iOS"],
|
|
228
|
+
];
|
|
229
|
+
const os = OS_TOKENS.find(([tok]) => Array.isArray(tok) ? tok.some((t) => ua.includes(t)) : ua.includes(tok))?.[1] ?? "Unknown";
|
|
230
|
+
const device = ua.includes("mobile") ? "Mobile"
|
|
231
|
+
: ua.includes("tablet") || ua.includes("ipad") ? "Tablet"
|
|
232
|
+
: "Desktop";
|
|
240
233
|
return { userAgent, browser, os, device };
|
|
241
234
|
}
|
|
242
235
|
export const SESSION_FIELDS = {
|
|
@@ -58,14 +58,14 @@ export declare const authUserSchema: z.ZodObject<{
|
|
|
58
58
|
}, "strip", z.ZodTypeAny, {
|
|
59
59
|
id: string;
|
|
60
60
|
displayName?: string | undefined;
|
|
61
|
-
role?: "
|
|
61
|
+
role?: "user" | "seller" | "moderator" | "employee" | "admin" | undefined;
|
|
62
62
|
email?: string | undefined;
|
|
63
63
|
photoURL?: string | undefined;
|
|
64
64
|
isEmailVerified?: boolean | undefined;
|
|
65
65
|
}, {
|
|
66
66
|
id: string;
|
|
67
67
|
displayName?: string | undefined;
|
|
68
|
-
role?: "
|
|
68
|
+
role?: "user" | "seller" | "moderator" | "employee" | "admin" | undefined;
|
|
69
69
|
email?: string | undefined;
|
|
70
70
|
photoURL?: string | undefined;
|
|
71
71
|
isEmailVerified?: boolean | undefined;
|