@mohasinac/appkit 4.13.1 → 4.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +14 -5
- package/dist/_internal/client/features/lottery/LotteryAdminEditView.d.ts +3 -0
- package/dist/_internal/client/features/lottery/LotteryAdminEditView.js +6 -0
- package/dist/_internal/client/features/lottery/LotteryDetailView.d.ts +8 -0
- package/dist/_internal/client/features/lottery/LotteryDetailView.js +4 -1
- package/dist/_internal/client/features/lottery/LotteryListView.d.ts +7 -0
- package/dist/_internal/client/features/lottery/LotteryListView.js +1 -1
- package/dist/_internal/client/features/lottery/PrizeDrawLotteryDetailView.js +4 -1
- package/dist/_internal/client/features/lottery/slot-collage-items.d.ts +15 -0
- package/dist/_internal/client/features/lottery/slot-collage-items.js +13 -0
- package/dist/_internal/server/features/auctions/actions.js +8 -2
- package/dist/_internal/server/features/bundles/data.d.ts +16 -0
- package/dist/_internal/server/features/bundles/data.js +26 -0
- package/dist/_internal/server/features/bundles/index.d.ts +1 -1
- package/dist/_internal/server/features/bundles/index.js +1 -1
- package/dist/_internal/server/features/cart/service.d.ts +3 -3
- package/dist/_internal/server/features/checkout/actions.js +25 -0
- package/dist/_internal/server/features/checkout/locked-lines.d.ts +38 -0
- package/dist/_internal/server/features/checkout/locked-lines.js +171 -0
- package/dist/_internal/server/features/checkout/source-context.d.ts +5 -0
- package/dist/_internal/server/features/checkout/source-context.js +157 -0
- package/dist/_internal/server/features/homepage/index.d.ts +0 -1
- package/dist/_internal/server/features/homepage/index.js +7 -1
- package/dist/_internal/server/features/lottery/adapters.js +4 -0
- package/dist/_internal/server/features/offers/adapters.d.ts +103 -0
- package/dist/_internal/server/features/offers/adapters.js +88 -0
- package/dist/_internal/server/features/offers/index.d.ts +2 -0
- package/dist/_internal/server/features/offers/index.js +1 -0
- package/dist/_internal/server/features/orders/adapters.js +24 -0
- package/dist/_internal/server/features/products/data.js +15 -37
- package/dist/_internal/server/features/products/index.d.ts +1 -1
- package/dist/_internal/server/features/products/index.js +1 -1
- package/dist/_internal/server/features/products/list-public.d.ts +46 -20
- package/dist/_internal/server/features/products/list-public.js +266 -90
- package/dist/_internal/server/features/products/listing-tab-counts.d.ts +44 -0
- package/dist/_internal/server/features/products/listing-tab-counts.js +97 -0
- package/dist/_internal/server/features/site-settings/adapters.d.ts +51 -0
- package/dist/_internal/server/features/site-settings/adapters.js +75 -0
- package/dist/_internal/server/features/site-settings/index.d.ts +1 -0
- package/dist/_internal/server/features/site-settings/index.js +1 -0
- package/dist/_internal/server/features/stores/adapters.d.ts +56 -0
- package/dist/_internal/server/features/stores/adapters.js +91 -0
- package/dist/_internal/server/features/stores/index.d.ts +1 -0
- package/dist/_internal/server/features/stores/index.js +1 -0
- package/dist/_internal/server/jobs/core/auctionSettlement.js +56 -2
- package/dist/_internal/server/jobs/core/offerExpiry.js +55 -19
- package/dist/_internal/server/jobs/core/paymentReviewAutoApprove.d.ts +5 -0
- package/dist/_internal/server/jobs/core/paymentReviewAutoApprove.js +33 -1
- package/dist/_internal/server/jobs/handlers/messages.d.ts +7 -0
- package/dist/_internal/server/jobs/handlers/messages.js +10 -0
- package/dist/_internal/shared/actions/action-registry.js +17 -1
- package/dist/_internal/shared/checkout/lanes.d.ts +25 -0
- package/dist/_internal/shared/checkout/lanes.js +26 -0
- package/dist/_internal/shared/features/auctions/config.d.ts +27 -0
- package/dist/_internal/shared/features/auctions/config.js +27 -0
- package/dist/_internal/shared/features/auctions/schema.d.ts +14 -2
- package/dist/_internal/shared/features/auctions/schema.js +13 -1
- package/dist/_internal/shared/features/blog/schema.d.ts +2 -2
- package/dist/_internal/shared/features/cart/schema.d.ts +20 -15
- package/dist/_internal/shared/features/cart/schema.js +15 -0
- package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +32 -32
- package/dist/_internal/shared/features/emi/schedule.d.ts +24 -3
- package/dist/_internal/shared/features/emi/schedule.js +20 -5
- package/dist/_internal/shared/features/events/schema.d.ts +2 -2
- package/dist/_internal/shared/features/homepage/section-gate.d.ts +14 -0
- package/dist/_internal/shared/features/homepage/section-gate.js +51 -0
- package/dist/_internal/shared/features/offers/config.d.ts +30 -0
- package/dist/_internal/shared/features/offers/config.js +59 -0
- package/dist/_internal/shared/features/orders/schema.d.ts +8 -8
- package/dist/_internal/shared/features/products/schema.d.ts +30 -30
- package/dist/_internal/shared/features/products/to-product-item.js +6 -0
- package/dist/_internal/shared/features/reviews/schema.d.ts +2 -2
- package/dist/_internal/shared/features/site-settings/fees.d.ts +60 -0
- package/dist/_internal/shared/features/site-settings/fees.js +39 -0
- package/dist/_internal/shared/features/site-settings/types.d.ts +40 -0
- package/dist/_internal/shared/features/site-settings/types.js +1 -0
- package/dist/_internal/shared/history/history.d.ts +88 -0
- package/dist/_internal/shared/history/history.js +198 -0
- package/dist/_internal/shared/history/index.d.ts +4 -0
- package/dist/_internal/shared/history/index.js +2 -0
- package/dist/_internal/shared/history/types.d.ts +61 -0
- package/dist/_internal/shared/history/types.js +6 -0
- package/dist/_internal/shared/listing-types/_registry.d.ts +54 -1
- package/dist/_internal/shared/listing-types/_registry.js +67 -0
- package/dist/_internal/shared/listing-types/art/config.d.ts +3 -0
- package/dist/_internal/shared/listing-types/art/config.js +5 -0
- package/dist/_internal/shared/listing-types/auction/config.d.ts +13 -0
- package/dist/_internal/shared/listing-types/auction/config.js +21 -0
- package/dist/_internal/shared/listing-types/availability.d.ts +79 -0
- package/dist/_internal/shared/listing-types/availability.js +104 -0
- package/dist/_internal/shared/listing-types/capabilities.d.ts +15 -0
- package/dist/_internal/shared/listing-types/capabilities.js +12 -0
- package/dist/_internal/shared/listing-types/classified/config.d.ts +3 -0
- package/dist/_internal/shared/listing-types/classified/config.js +5 -0
- package/dist/_internal/shared/listing-types/digital-code/config.d.ts +11 -0
- package/dist/_internal/shared/listing-types/digital-code/config.js +22 -2
- package/dist/_internal/shared/listing-types/live/config.d.ts +3 -0
- package/dist/_internal/shared/listing-types/live/config.js +5 -0
- package/dist/_internal/shared/listing-types/pre-order/config.d.ts +3 -0
- package/dist/_internal/shared/listing-types/pre-order/config.js +19 -0
- package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +11 -0
- package/dist/_internal/shared/listing-types/prize-draw/config.js +15 -0
- package/dist/_internal/shared/listing-types/standard/config.d.ts +3 -0
- package/dist/_internal/shared/listing-types/standard/config.js +5 -0
- package/dist/_internal/shared/listing-types/stickers/config.d.ts +3 -0
- package/dist/_internal/shared/listing-types/stickers/config.js +5 -0
- package/dist/client.d.ts +20 -7
- package/dist/client.js +22 -4
- package/dist/constants/api-endpoints.d.ts +6 -0
- package/dist/constants/api-endpoints.js +2 -0
- package/dist/constants/field-names.d.ts +57 -8
- package/dist/constants/field-names.js +101 -8
- package/dist/constants/table-keys.d.ts +17 -0
- package/dist/constants/table-keys.js +17 -0
- package/dist/errors/error-codes.d.ts +13 -1
- package/dist/errors/error-codes.js +13 -1
- package/dist/errors/error-display-map.js +12 -3
- package/dist/errors/messages.d.ts +10 -2
- package/dist/errors/messages.js +10 -2
- package/dist/features/about/components/AboutView.d.ts +3 -0
- package/dist/features/about/components/AboutView.js +3 -2
- package/dist/features/about/components/PolicyPageView.d.ts +2 -1
- package/dist/features/about/components/PolicyPageView.js +61 -23
- package/dist/features/about/components/PublicProfileView.js +5 -0
- package/dist/features/about/schemas/firestore.d.ts +3 -0
- package/dist/features/account/components/UserBidsView.js +12 -4
- package/dist/features/account/components/UserOrdersView.js +7 -0
- package/dist/features/account/components/UserReturnsView.d.ts +3 -0
- package/dist/features/account/components/UserReturnsView.js +17 -1
- package/dist/features/account/components/index.d.ts +0 -2
- package/dist/features/account/components/index.js +0 -1
- package/dist/features/account/schemas/index.d.ts +2 -2
- package/dist/features/account/types/index.d.ts +21 -2
- package/dist/features/addresses/schemas/index.d.ts +4 -4
- package/dist/features/admin/components/AdminArtView.js +8 -3
- package/dist/features/admin/components/AdminAuditLogView.js +1 -0
- package/dist/features/admin/components/AdminBidsView.js +15 -2
- package/dist/features/admin/components/AdminBlogEditorView.js +65 -33
- package/dist/features/admin/components/AdminClassifiedView.js +8 -3
- package/dist/features/admin/components/AdminDigitalCodesView.js +8 -3
- package/dist/features/admin/components/AdminFeatureEditorView.js +35 -6
- package/dist/features/admin/components/AdminFeatureFlagsView.js +1 -0
- package/dist/features/admin/components/AdminLiveView.js +8 -3
- package/dist/features/admin/components/AdminNavEditorView.js +15 -5
- package/dist/features/admin/components/AdminNewsletterView.js +18 -2
- package/dist/features/admin/components/AdminOffersView.d.ts +4 -0
- package/dist/features/admin/components/AdminOffersView.js +230 -0
- package/dist/features/admin/components/AdminOrdersView.js +10 -1
- package/dist/features/admin/components/AdminPaymentMethodsView.js +24 -4
- package/dist/features/admin/components/AdminPrizeDrawsView.js +5 -0
- package/dist/features/admin/components/AdminProductsView.js +16 -29
- package/dist/features/admin/components/AdminScammerEditorView.d.ts +2 -1
- package/dist/features/admin/components/AdminScammerEditorView.js +3 -13
- package/dist/features/admin/components/AdminScammersView.js +3 -8
- package/dist/features/admin/components/AdminSectionsView.js +32 -23
- package/dist/features/admin/components/AdminSessionsView.js +17 -2
- package/dist/features/admin/components/AdminSiteSettingsView.js +31 -13
- package/dist/features/admin/components/AdminSiteView.js +6 -2
- package/dist/features/admin/components/AdminStickersView.js +8 -3
- package/dist/features/admin/components/ViewAuditLogEntryModal.js +1 -0
- 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.d.ts +4 -2
- package/dist/features/admin/components/sections/adminSectionsTypes.js +45 -27
- package/dist/features/admin/constants/filter-tabs.d.ts +89 -0
- package/dist/features/admin/constants/filter-tabs.js +56 -0
- package/dist/features/admin/schemas/firestore.d.ts +122 -3
- package/dist/features/admin/schemas/firestore.js +1 -0
- package/dist/features/admin/schemas/homepage-section-form.d.ts +22 -0
- package/dist/features/admin/schemas/homepage-section-form.js +68 -0
- package/dist/features/admin/schemas/nav-item-form.d.ts +74 -0
- package/dist/features/admin/schemas/nav-item-form.js +72 -0
- package/dist/features/auctions/actions/bid-actions.d.ts +20 -5
- package/dist/features/auctions/actions/bid-actions.js +93 -20
- package/dist/features/auctions/components/AuctionBidsTable.d.ts +10 -1
- package/dist/features/auctions/components/AuctionBidsTable.js +22 -4
- package/dist/features/auctions/components/AuctionDetailPageView.js +11 -6
- package/dist/features/auctions/components/AuctionsListView.js +5 -6
- package/dist/features/auctions/components/MarketplaceAuctionCard.d.ts +7 -0
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +19 -2
- package/dist/features/auctions/components/PlaceBidFormClient.d.ts +1 -2
- package/dist/features/auctions/components/PlaceBidFormClient.js +8 -4
- package/dist/features/auctions/components/bid-detail-fields.d.ts +29 -0
- package/dist/features/auctions/components/bid-detail-fields.js +103 -0
- package/dist/features/auctions/repository/bid.repository.d.ts +13 -0
- package/dist/features/auctions/repository/bid.repository.js +23 -0
- package/dist/features/auctions/schemas/firestore.d.ts +17 -0
- package/dist/features/auctions/schemas/index.d.ts +12 -12
- package/dist/features/audit-log/schemas/firestore.d.ts +14 -0
- package/dist/features/audit-log/schemas/firestore.js +7 -0
- package/dist/features/auth/permissions/constants.d.ts +1 -1
- package/dist/features/auth/permissions/constants.js +10 -1
- package/dist/features/blog/actions/blog-actions.d.ts +7 -7
- package/dist/features/blog/schemas/blog-form.d.ts +80 -0
- package/dist/features/blog/schemas/blog-form.js +100 -0
- package/dist/features/blog/schemas/index.d.ts +6 -6
- package/dist/features/cart/repository/cart.repository.js +1 -0
- package/dist/features/cart/schemas/firestore.d.ts +15 -0
- package/dist/features/catalogue/schemas/validation.d.ts +4 -4
- package/dist/features/categories/components/BrandDetailPageView.js +23 -40
- package/dist/features/categories/components/BrandDetailTabs.d.ts +7 -7
- package/dist/features/categories/components/BrandDetailTabs.js +8 -12
- package/dist/features/categories/components/BundleCollage.js +1 -1
- package/dist/features/categories/components/CategoryDetailPageView.js +53 -57
- package/dist/features/categories/components/CategoryDetailTabs.d.ts +10 -8
- package/dist/features/categories/components/CategoryDetailTabs.js +11 -16
- package/dist/features/categories/components/CategoryProductsListing.js +11 -1
- package/dist/features/categories/components/ConcernCard.js +7 -1
- package/dist/features/categories/schemas/firestore.d.ts +13 -0
- package/dist/features/categories/schemas/index.d.ts +26 -26
- package/dist/features/classified/components/ClassifiedDetailPageView.d.ts +16 -1
- package/dist/features/classified/components/ClassifiedDetailPageView.js +23 -3
- package/dist/features/events/components/AdminEventEditorView.js +32 -54
- package/dist/features/events/components/AdminEventEntriesView.js +22 -3
- package/dist/features/events/components/AdminEventsView.js +15 -11
- package/dist/features/events/components/EventFilters.d.ts +9 -1
- package/dist/features/events/components/EventFilters.js +45 -21
- package/dist/features/events/components/EventsIndexListing.d.ts +6 -1
- package/dist/features/events/components/EventsIndexListing.js +2 -2
- package/dist/features/events/components/EventsListPageView.js +13 -4
- package/dist/features/events/repository/events.repository.d.ts +17 -0
- package/dist/features/events/repository/events.repository.js +27 -0
- package/dist/features/events/schemas/event-form.d.ts +113 -0
- package/dist/features/events/schemas/event-form.js +82 -0
- package/dist/features/events/schemas/firestore.d.ts +12 -0
- package/dist/features/events/schemas/firestore.js +12 -0
- package/dist/features/events/schemas/index.d.ts +50 -50
- package/dist/features/events/types/index.d.ts +11 -0
- package/dist/features/events/types/index.js +57 -1
- package/dist/features/faq/actions/faq-actions.d.ts +12 -12
- package/dist/features/faq/schemas/index.d.ts +8 -8
- package/dist/features/filters/FilterFacetSection.d.ts +7 -1
- package/dist/features/filters/FilterFacetSection.js +11 -3
- package/dist/features/grouped/schemas/grouped-listing-form.d.ts +101 -0
- package/dist/features/grouped/schemas/grouped-listing-form.js +89 -0
- package/dist/features/grouped/schemas/index.d.ts +4 -4
- package/dist/features/homepage/actions/homepage-section-actions.d.ts +11 -3
- package/dist/features/homepage/actions/homepage-section-actions.js +33 -1
- package/dist/features/homepage/components/AnnouncementBar.d.ts +7 -1
- package/dist/features/homepage/components/AnnouncementBar.js +3 -3
- package/dist/features/homepage/components/MarketplaceHomepageView.js +20 -6
- package/dist/features/homepage/hooks/homepage-query.d.ts +16 -0
- package/dist/features/homepage/hooks/homepage-query.js +45 -0
- package/dist/features/homepage/hooks/useFeaturedAuctions.d.ts +10 -0
- package/dist/features/homepage/hooks/useFeaturedAuctions.js +28 -8
- package/dist/features/homepage/hooks/useFeaturedPreOrders.js +17 -8
- package/dist/features/homepage/hooks/useFeaturedProducts.js +15 -8
- package/dist/features/homepage/schemas/index.d.ts +33 -2
- package/dist/features/homepage/schemas/index.js +24 -0
- package/dist/features/layout/AppLayoutShell.d.ts +11 -1
- package/dist/features/layout/AppLayoutShell.js +15 -14
- package/dist/features/layout/BackToTop.d.ts +9 -0
- package/dist/features/layout/BackToTop.js +10 -1
- package/dist/features/layout/BottomActions.js +28 -25
- package/dist/features/layout/BottomChrome.d.ts +34 -0
- package/dist/features/layout/BottomChrome.js +55 -0
- package/dist/features/layout/BottomNavLayout.d.ts +6 -0
- package/dist/features/layout/BottomNavLayout.js +7 -1
- package/dist/features/layout/BottomNavbar.js +15 -2
- package/dist/features/layout/FooterLayout.js +11 -1
- package/dist/features/layout/NavbarLayout.js +1 -1
- package/dist/features/layout/TitleBarLayout.d.ts +7 -0
- package/dist/features/layout/TitleBarLayout.js +28 -5
- package/dist/features/layout/index.d.ts +2 -0
- package/dist/features/layout/index.js +1 -0
- package/dist/features/lottery/types/index.d.ts +3 -0
- package/dist/features/media/MediaPickerModal.js +5 -1
- package/dist/features/messages/schemas/index.d.ts +2 -2
- package/dist/features/orders/components/OrderScopeTabs.d.ts +20 -0
- package/dist/features/orders/components/OrderScopeTabs.js +31 -0
- package/dist/features/orders/components/OrderStatusTimeline.d.ts +5 -1
- package/dist/features/orders/components/OrderStatusTimeline.js +39 -20
- package/dist/features/orders/constants/order-scope.d.ts +48 -0
- package/dist/features/orders/constants/order-scope.js +111 -0
- package/dist/features/orders/repository/orders.repository.d.ts +54 -7
- package/dist/features/orders/repository/orders.repository.js +121 -22
- package/dist/features/orders/schemas/firestore.d.ts +152 -0
- package/dist/features/orders/schemas/firestore.js +30 -0
- package/dist/features/orders/schemas/index.d.ts +18 -18
- package/dist/features/orders/types/index.d.ts +35 -7
- package/dist/features/pre-orders/components/PreOrdersIndexListing.js +14 -9
- package/dist/features/pre-orders/components/PreOrdersListView.js +6 -5
- package/dist/features/pre-orders/schemas/index.d.ts +1 -1
- package/dist/features/products/actions/product-actions.d.ts +14 -0
- package/dist/features/products/actions/product-actions.js +49 -11
- package/dist/features/products/api/route.d.ts +12 -0
- package/dist/features/products/api/route.js +42 -100
- package/dist/features/products/components/ArtStickersListView.js +2 -2
- package/dist/features/products/components/AuctionsIndexListing.js +13 -11
- package/dist/features/products/components/AvailabilityTabs.d.ts +11 -0
- package/dist/features/products/components/AvailabilityTabs.js +47 -0
- package/dist/features/products/components/GroupSettingsPanel.js +5 -1
- package/dist/features/products/components/MakeOfferButton.js +48 -49
- package/dist/features/products/components/PrizeDrawCollage.d.ts +20 -4
- package/dist/features/products/components/PrizeDrawCollage.js +9 -1
- package/dist/features/products/components/PrizeDrawsIndexListing.js +14 -12
- package/dist/features/products/components/PrizeDrawsListingView.js +2 -2
- package/dist/features/products/components/PrizeDrawsSection.d.ts +7 -1
- package/dist/features/products/components/PrizeDrawsSection.js +23 -18
- package/dist/features/products/components/ProductDetailPageView.d.ts +4 -1
- package/dist/features/products/components/ProductDetailPageView.js +18 -4
- package/dist/features/products/components/ProductForm.js +5 -2
- package/dist/features/products/components/ProductGrid.js +6 -1
- package/dist/features/products/components/ProductsIndexListing.js +22 -32
- package/dist/features/products/components/ProductsIndexPageView.js +6 -9
- package/dist/features/products/components/index.d.ts +2 -2
- package/dist/features/products/components/index.js +1 -1
- package/dist/features/products/config/listing-type-listing-config.d.ts +20 -0
- package/dist/features/products/config/listing-type-listing-config.js +22 -10
- package/dist/features/products/constants/action-defs.d.ts +2 -0
- package/dist/features/products/constants/action-defs.js +6 -0
- package/dist/features/products/hooks/useAvailabilityScope.d.ts +13 -0
- package/dist/features/products/hooks/useAvailabilityScope.js +19 -0
- package/dist/features/products/hooks/useProducts.d.ts +5 -0
- package/dist/features/products/hooks/useProducts.js +13 -2
- package/dist/features/products/repository/products.repository.d.ts +31 -2
- package/dist/features/products/repository/products.repository.js +53 -21
- package/dist/features/products/schemas/firestore.d.ts +17 -3
- package/dist/features/products/schemas/firestore.js +7 -2
- package/dist/features/products/schemas/index.d.ts +64 -64
- package/dist/features/products/schemas/product-features.validators.d.ts +79 -6
- package/dist/features/products/schemas/product-features.validators.js +63 -0
- package/dist/features/products/types/index.d.ts +16 -1
- package/dist/features/promotions/schemas/index.d.ts +2 -2
- package/dist/features/reviews/schemas/index.d.ts +16 -16
- package/dist/features/scams/constants/scammer-status-display.d.ts +28 -0
- package/dist/features/scams/constants/scammer-status-display.js +79 -0
- package/dist/features/search/schemas/index.d.ts +4 -4
- package/dist/features/seller/actions/offer-actions.js +57 -4
- package/dist/features/seller/components/OfferPhaseTimeline.d.ts +59 -0
- package/dist/features/seller/components/OfferPhaseTimeline.js +107 -0
- package/dist/features/seller/components/SellerArtView.js +5 -0
- package/dist/features/seller/components/SellerAuctionsView.js +13 -15
- package/dist/features/seller/components/SellerBidsView.js +11 -4
- package/dist/features/seller/components/SellerClassifiedView.js +5 -0
- package/dist/features/seller/components/SellerCouponEditorView.js +17 -17
- package/dist/features/seller/components/SellerDigitalCodesView.js +5 -0
- package/dist/features/seller/components/SellerLiveView.js +5 -0
- package/dist/features/seller/components/SellerOffersView.js +2 -1
- package/dist/features/seller/components/SellerOrdersView.js +31 -9
- package/dist/features/seller/components/SellerPayoutSettingsView.js +56 -31
- package/dist/features/seller/components/SellerPreOrdersView.js +5 -0
- package/dist/features/seller/components/SellerPrizeDrawsView.js +14 -16
- package/dist/features/seller/components/SellerProductShell.js +7 -1
- package/dist/features/seller/components/SellerProductsView.js +11 -8
- package/dist/features/seller/components/SellerStickersView.js +5 -0
- package/dist/features/seller/components/index.d.ts +0 -2
- package/dist/features/seller/components/index.js +0 -1
- package/dist/features/seller/repository/offer.repository.d.ts +142 -24
- package/dist/features/seller/repository/offer.repository.js +165 -26
- package/dist/features/seller/schemas/coupon-form.d.ts +72 -0
- package/dist/features/seller/schemas/coupon-form.js +116 -0
- package/dist/features/seller/schemas/firestore.d.ts +56 -2
- package/dist/features/seller/schemas/firestore.js +27 -0
- package/dist/features/seller/schemas/index.d.ts +2 -2
- package/dist/features/seller/schemas/offer-forms.d.ts +46 -0
- package/dist/features/seller/schemas/offer-forms.js +42 -0
- package/dist/features/seller/server.d.ts +0 -1
- package/dist/features/seller/server.js +0 -1
- package/dist/features/shell/SectionForm.d.ts +99 -0
- package/dist/features/shell/SectionForm.js +128 -0
- package/dist/features/shell/build-sections.d.ts +63 -0
- package/dist/features/shell/build-sections.js +207 -0
- package/dist/features/shell/entity-form.d.ts +109 -0
- package/dist/features/shell/entity-form.js +96 -0
- package/dist/features/shell/field-ui-meta.d.ts +115 -0
- package/dist/features/shell/field-ui-meta.js +324 -0
- package/dist/features/shell/index.d.ts +8 -0
- package/dist/features/shell/index.js +4 -0
- package/dist/features/status-history/components/StatusTimeline.d.ts +74 -0
- package/dist/features/status-history/components/StatusTimeline.js +46 -0
- package/dist/features/status-history/index.d.ts +11 -0
- package/dist/features/status-history/index.js +10 -0
- package/dist/features/store-extensions/components/ReviewDecisionModal.d.ts +27 -0
- package/dist/features/store-extensions/components/ReviewDecisionModal.js +82 -0
- package/dist/features/store-extensions/index.d.ts +12 -0
- package/dist/features/store-extensions/index.js +12 -0
- package/dist/features/store-extensions/schemas/admin-notification-form.d.ts +36 -0
- package/dist/features/store-extensions/schemas/admin-notification-form.js +114 -0
- package/dist/features/store-extensions/schemas/analytics-forms.d.ts +57 -0
- package/dist/features/store-extensions/schemas/analytics-forms.js +158 -0
- package/dist/features/store-extensions/schemas/custom-role-form.d.ts +85 -0
- package/dist/features/store-extensions/schemas/custom-role-form.js +118 -0
- package/dist/features/store-extensions/schemas/firestore.d.ts +21 -1
- package/dist/features/store-extensions/schemas/firestore.js +60 -0
- package/dist/features/store-extensions/schemas/google-config-form.d.ts +53 -0
- package/dist/features/store-extensions/schemas/google-config-form.js +105 -0
- package/dist/features/store-extensions/schemas/item-request-create-form.d.ts +28 -0
- package/dist/features/store-extensions/schemas/item-request-create-form.js +80 -0
- package/dist/features/store-extensions/schemas/listing-template-form.d.ts +78 -0
- package/dist/features/store-extensions/schemas/listing-template-form.js +87 -0
- package/dist/features/store-extensions/schemas/moderation-review-form.d.ts +49 -0
- package/dist/features/store-extensions/schemas/moderation-review-form.js +101 -0
- package/dist/features/store-extensions/schemas/payout-method-form.d.ts +153 -0
- package/dist/features/store-extensions/schemas/payout-method-form.js +155 -0
- package/dist/features/store-extensions/schemas/report-create-form.d.ts +25 -0
- package/dist/features/store-extensions/schemas/report-create-form.js +79 -0
- package/dist/features/store-extensions/schemas/report-review-form.d.ts +47 -0
- package/dist/features/store-extensions/schemas/report-review-form.js +111 -0
- package/dist/features/store-extensions/schemas/shipping-config-form.d.ts +148 -0
- package/dist/features/store-extensions/schemas/shipping-config-form.js +104 -0
- package/dist/features/store-extensions/schemas/store-category-form.d.ts +54 -0
- package/dist/features/store-extensions/schemas/store-category-form.js +73 -0
- package/dist/features/stores/api/[storeSlug]/route.js +2 -25
- package/dist/features/stores/components/StoreAuctionsListing.js +15 -1
- package/dist/features/stores/components/StoreClassifiedsListing.js +12 -2
- package/dist/features/stores/components/StoreDetailLayoutView.js +24 -71
- package/dist/features/stores/components/StoreDigitalCodesListing.js +12 -2
- package/dist/features/stores/components/StoreLiveItemsListing.js +12 -2
- package/dist/features/stores/components/StorePreOrdersListing.js +12 -1
- package/dist/features/stores/components/StoreProductsListing.js +11 -1
- package/dist/features/stores/repository/store.repository.js +6 -0
- package/dist/features/stores/schemas/index.d.ts +6 -6
- package/dist/features/support/schemas/index.d.ts +4 -4
- package/dist/features/tester/actions/checklist-item-actions.d.ts +4 -4
- package/dist/features/tester/seed-data/offers-tester-seed-data.js +119 -3
- package/dist/features/tester/seed-data/products-tester-seed-data.js +131 -1
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +431 -1
- package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
- package/dist/index.d.ts +25 -12
- package/dist/index.js +26 -11
- package/dist/next/routing/route-map.d.ts +23 -3
- package/dist/next/routing/route-map.js +14 -2
- package/dist/providers/db-firebase/base.repository.d.ts +30 -0
- package/dist/providers/db-firebase/base.repository.js +50 -1
- package/dist/providers/db-firebase/index.d.ts +1 -1
- package/dist/providers/db-firebase/index.js +1 -1
- package/dist/providers/db-firebase/sieve.d.ts +25 -0
- package/dist/providers/db-firebase/sieve.js +52 -18
- package/dist/react/hooks/useUrlTable.js +10 -1
- package/dist/schemas/firestore-value.d.ts +8 -0
- package/dist/schemas/firestore-value.js +44 -0
- package/dist/schemas/index.d.ts +1 -1
- package/dist/schemas/index.js +1 -1
- package/dist/schemas/registry.d.ts +702 -69
- package/dist/schemas/registry.js +64 -1
- package/dist/seed/_helpers/category-forest.d.ts +2 -0
- package/dist/seed/_helpers/category-forest.js +309 -0
- package/dist/seed/_helpers/category-tree.d.ts +27 -0
- package/dist/seed/_helpers/category-tree.js +103 -0
- package/dist/seed/bids-seed-data.js +30 -0
- package/dist/seed/catalogue-seed-data.js +12 -12
- package/dist/seed/categories-seed-data.js +177 -162
- package/dist/seed/events-seed-data.js +61 -10
- package/dist/seed/homepage-sections-seed-data.js +5 -1
- package/dist/seed/offers-seed-data.js +244 -34
- package/dist/seed/orders-seed-data.js +336 -1
- package/dist/seed/products-art-seed-data.js +50 -12
- package/dist/seed/products-auctions-seed-data.js +138 -18
- package/dist/seed/products-classifieds-seed-data.js +80 -16
- package/dist/seed/products-digital-codes-seed-data.js +66 -18
- package/dist/seed/products-live-items-seed-data.js +64 -13
- package/dist/seed/products-preorders-seed-data.d.ts +0 -1
- package/dist/seed/products-preorders-seed-data.js +52 -13
- package/dist/seed/products-prize-draws-seed-data.js +63 -14
- package/dist/seed/products-standard-seed-data.js +99 -26
- package/dist/seed/products-stickers-seed-data.js +47 -12
- package/dist/seed/reviews-seed-data.js +6 -1
- package/dist/seed/site-settings-seed-data.d.ts +1 -38
- package/dist/seed/site-settings-seed-data.js +38 -76
- package/dist/seed/stores-seed-data.js +71 -1
- package/dist/seed/users-seed-data.js +15 -5
- package/dist/server-entry.d.ts +1 -2
- package/dist/server-entry.js +4 -3
- package/dist/server.d.ts +6 -3
- package/dist/server.js +13 -4
- package/dist/styles.css +78 -12
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/Button.style.css +19 -4
- package/dist/ui/components/CollapsibleSection.d.ts +17 -1
- package/dist/ui/components/CollapsibleSection.js +6 -2
- package/dist/ui/components/FilterChipGroup.d.ts +25 -1
- package/dist/ui/components/FilterChipGroup.js +21 -4
- package/dist/ui/components/HandMode.style.css +47 -0
- package/dist/ui/components/Layout.d.ts +9 -2
- package/dist/ui/components/Layout.js +1 -1
- package/dist/ui/components/ListingLayout.js +8 -8
- package/dist/ui/components/ListingLayout.style.css +8 -7
- package/dist/ui/components/RecordDetailModal.d.ts +10 -1
- package/dist/ui/components/RecordDetailModal.js +2 -2
- package/dist/ui/components/StickyToolbar.d.ts +3 -1
- package/dist/ui/components/StickyToolbar.js +62 -20
- package/dist/ui/components/bottom-chrome-slot.d.ts +21 -0
- package/dist/ui/components/bottom-chrome-slot.js +29 -0
- package/dist/ui/components/index.style.css +3 -0
- package/dist/ui/forms/FormShell.d.ts +43 -13
- package/dist/ui/forms/FormShell.js +22 -11
- package/dist/ui/forms/index.d.ts +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/package.json +2 -1
- package/scripts/node-esm-loader.mjs +65 -0
- package/scripts/seed-cli-loader.mjs +6 -49
- package/scripts/seed-cli.mjs +1 -1
|
@@ -21,6 +21,9 @@ import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
|
|
|
21
21
|
import { TABLE_KEYS, VIEW_MODE } from "../../../constants/table-keys";
|
|
22
22
|
import { PREORDER_SORT_OPTIONS } from "../../products/constants/sieve";
|
|
23
23
|
import { useBottomActions } from "../../layout";
|
|
24
|
+
import { AVAILABILITY_VALUES } from "../../../constants/field-names";
|
|
25
|
+
import { AvailabilityTabs } from "../../products/components/AvailabilityTabs";
|
|
26
|
+
const PRE_ORDER_LISTING_TYPES = ["pre-order"];
|
|
24
27
|
const __P = {
|
|
25
28
|
p3: "p-[var(--appkit-space-3)]",
|
|
26
29
|
};
|
|
@@ -36,7 +39,8 @@ export function PreOrdersIndexListing({ initialData, categorySlug, brandName })
|
|
|
36
39
|
const [searchInput, setSearchInput] = useState(table.get(TABLE_KEYS.QUERY) || "");
|
|
37
40
|
const [filterOpen, setFilterOpen] = useState(false);
|
|
38
41
|
const [compareIds, setCompareIds] = useState([]);
|
|
39
|
-
const
|
|
42
|
+
const availability = table.get(TABLE_KEYS.AVAILABILITY) ||
|
|
43
|
+
AVAILABILITY_VALUES.AVAILABLE;
|
|
40
44
|
const [view, setView] = useState(table.get(TABLE_KEYS.VIEW) || VIEW_MODE.GRID);
|
|
41
45
|
const localCart = useGuestCart();
|
|
42
46
|
const localWishlist = useGuestWishlist();
|
|
@@ -54,11 +58,11 @@ export function PreOrdersIndexListing({ initialData, categorySlug, brandName })
|
|
|
54
58
|
setFilterOpen(false);
|
|
55
59
|
}, [onFilterApply]);
|
|
56
60
|
const resetAll = useCallback(() => {
|
|
57
|
-
onResetAll({ [TABLE_KEYS.QUERY]: "", [TABLE_KEYS.SORT]: "", [TABLE_KEYS.
|
|
61
|
+
onResetAll({ [TABLE_KEYS.QUERY]: "", [TABLE_KEYS.SORT]: "", [TABLE_KEYS.AVAILABILITY]: "" });
|
|
58
62
|
setSearchInput("");
|
|
59
63
|
}, [onResetAll]);
|
|
60
64
|
const hasActiveState = !!table.get(TABLE_KEYS.QUERY) ||
|
|
61
|
-
|
|
65
|
+
availability !== AVAILABILITY_VALUES.AVAILABLE ||
|
|
62
66
|
table.get(TABLE_KEYS.SORT) !== DEFAULT_SORT ||
|
|
63
67
|
filterActiveCount > 0;
|
|
64
68
|
const params = {
|
|
@@ -76,9 +80,12 @@ export function PreOrdersIndexListing({ initialData, categorySlug, brandName })
|
|
|
76
80
|
page: table.getNumber(TABLE_KEYS.PAGE, 1),
|
|
77
81
|
perPage: table.getNumber(TABLE_KEYS.PAGE_SIZE, 24),
|
|
78
82
|
listingType: "pre-order",
|
|
79
|
-
//
|
|
80
|
-
//
|
|
81
|
-
|
|
83
|
+
// "Closed" for a pre-order means its allocation filled, which the shared
|
|
84
|
+
// per-type predicate resolves from preOrderCurrentCount vs
|
|
85
|
+
// preOrderMaxQuantity. This used to be a bare stockQuantity>0, which is
|
|
86
|
+
// a DIFFERENT question and disagreed with what /products asked of the
|
|
87
|
+
// same rows.
|
|
88
|
+
availability,
|
|
82
89
|
};
|
|
83
90
|
const { products: preOrders, totalPages, page, isLoading } = useProducts(params, { initialData });
|
|
84
91
|
const commitSearch = useCallback(() => {
|
|
@@ -175,9 +182,7 @@ export function PreOrdersIndexListing({ initialData, categorySlug, brandName })
|
|
|
175
182
|
},
|
|
176
183
|
},
|
|
177
184
|
] } } : {});
|
|
178
|
-
return (_jsxs(Div, { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: filterActiveCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search pre-orders...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, onSearchKeyDown: handleSearchKeyDown, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: PREORDER_SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, view: view, onViewChange: handleViewToggle, onResetAll: resetAll, hasActiveState: hasActiveState, bulkMode: selection.isSelecting, bulkSelectedCount: selection.selectedCount, bulkTotalCount: preOrders.length, onBulkSelectAll: selection.toggleAll, onBulkClear: selection.clearSelection,
|
|
179
|
-
{ label: "Show closed", active: showClosed, onChange: (next) => table.set(TABLE_KEYS.SHOW_CLOSED, next ? "true" : "") },
|
|
180
|
-
] }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
185
|
+
return (_jsxs(Div, { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: filterActiveCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search pre-orders...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, onSearchKeyDown: handleSearchKeyDown, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: PREORDER_SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, view: view, onViewChange: handleViewToggle, onResetAll: resetAll, hasActiveState: hasActiveState, bulkMode: selection.isSelecting, bulkSelectedCount: selection.selectedCount, bulkTotalCount: preOrders.length, onBulkSelectAll: selection.toggleAll, onBulkClear: selection.clearSelection }), _jsx(Div, { padding: "y-sm", children: _jsx(AvailabilityTabs, { types: PRE_ORDER_LISTING_TYPES }) }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
181
186
|
{
|
|
182
187
|
id: ACTION_ID.ADD_TO_CART,
|
|
183
188
|
label: ACTION_META[ACTION_ID.ADD_TO_CART].label,
|
|
@@ -2,19 +2,20 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Container, Main, Heading, Section } from "../../../ui";
|
|
3
3
|
import { AdSlot } from "../../homepage/components/AdSlot";
|
|
4
4
|
import { PreOrdersIndexListing } from "./PreOrdersIndexListing";
|
|
5
|
-
import { listPublicProducts, parsePublicProductParams, } from "../../../_internal/server/features/products/list-public";
|
|
5
|
+
import { listPublicProducts, parsePublicProductParams, defaultAvailabilityForListingTypes, } from "../../../_internal/server/features/products/list-public";
|
|
6
6
|
const PRE_ORDER_LISTING_TYPES = ["pre-order"];
|
|
7
7
|
const DEFAULT_PAGE_SIZE = 24;
|
|
8
8
|
const DEFAULT_SORT = "-createdAt";
|
|
9
9
|
export async function PreOrdersListView({ searchParams = {} }) {
|
|
10
|
-
// Shared with /api/products
|
|
11
|
-
//
|
|
12
|
-
//
|
|
10
|
+
// Shared with /api/products, and derived rather than hardcoded. This view
|
|
11
|
+
// carried a literal `hideSoldByDefault: true` until 2026-08-24 even though
|
|
12
|
+
// pre-order's registered hide-default is "closed" — so /pre-orders and
|
|
13
|
+
// /products disagreed about what "closed" meant for the same rows.
|
|
13
14
|
const result = await listPublicProducts(parsePublicProductParams(searchParams, {
|
|
14
15
|
listingTypes: PRE_ORDER_LISTING_TYPES,
|
|
15
16
|
pageSize: DEFAULT_PAGE_SIZE,
|
|
16
17
|
sorts: DEFAULT_SORT,
|
|
17
|
-
|
|
18
|
+
...defaultAvailabilityForListingTypes(PRE_ORDER_LISTING_TYPES),
|
|
18
19
|
}));
|
|
19
20
|
return (_jsx(Main, { children: _jsx(Section, { padding: "y-2xl", children: _jsxs(Container, { size: "xl", children: [_jsx(Heading, { level: 1, className: "mb-8", color: "primary", size: "3xl", weight: "semibold", children: "Pre-Orders" }), _jsx(AdSlot, { id: "listing-sidebar-top", className: "mb-6" }), _jsx(PreOrdersIndexListing, { initialData: result ?? undefined }), _jsx(AdSlot, { id: "listing-sidebar-bottom", className: "mt-8" })] }) }) }));
|
|
20
21
|
}
|
|
@@ -79,6 +79,7 @@ export declare const preorderItemSchema: z.ZodObject<{
|
|
|
79
79
|
createdAt?: string | undefined;
|
|
80
80
|
active?: boolean | undefined;
|
|
81
81
|
images?: string[] | undefined;
|
|
82
|
+
isFeatured?: boolean | undefined;
|
|
82
83
|
media?: {
|
|
83
84
|
type: "video" | "image" | "file";
|
|
84
85
|
url: string;
|
|
@@ -88,7 +89,6 @@ export declare const preorderItemSchema: z.ZodObject<{
|
|
|
88
89
|
youtubeId?: string | undefined;
|
|
89
90
|
duration?: number | undefined;
|
|
90
91
|
}[] | undefined;
|
|
91
|
-
isFeatured?: boolean | undefined;
|
|
92
92
|
franchise?: string | undefined;
|
|
93
93
|
preorderShipDate?: string | undefined;
|
|
94
94
|
}>;
|
|
@@ -16,10 +16,24 @@ export type ProductListResult = FirebaseSieveResult<ProductDocument>;
|
|
|
16
16
|
export declare function listProducts(params?: ProductListActionParams): Promise<ProductListResult>;
|
|
17
17
|
export declare function getProductById(id: string): Promise<ProductDocument | null>;
|
|
18
18
|
export declare function getFeaturedProducts(pageSize?: number): Promise<ProductListResult>;
|
|
19
|
+
/**
|
|
20
|
+
* The soonest-ending LIVE auctions.
|
|
21
|
+
*
|
|
22
|
+
* This used to be `listingType==auction,status==published` sorted
|
|
23
|
+
* `auctionEndDate ASC` with no lower bound — and ascending order front-loads
|
|
24
|
+
* the OLDEST end dates, so the homepage's "Live Auctions" strip led with the
|
|
25
|
+
* most-expired lots in the catalogue. Nothing about it was flagged as wrong
|
|
26
|
+
* because an ended auction still renders as a perfectly normal card.
|
|
27
|
+
*
|
|
28
|
+
* One listing type, sorted by the same field the scope filters on, means
|
|
29
|
+
* `listPublicProducts` pushes `auctionEndDate >= now` into Firestore rather
|
|
30
|
+
* than filtering a bounded window in memory.
|
|
31
|
+
*/
|
|
19
32
|
export declare function getFeaturedAuctions(pageSize?: number): Promise<ProductListResult>;
|
|
20
33
|
export declare function getLatestProducts(pageSize?: number): Promise<ProductListResult>;
|
|
21
34
|
export declare function getLatestAuctions(pageSize?: number): Promise<ProductListResult>;
|
|
22
35
|
export declare function listAuctions(params?: ProductListActionParams): Promise<ProductListResult>;
|
|
36
|
+
/** Pre-orders still accepting orders, soonest delivery first. */
|
|
23
37
|
export declare function getFeaturedPreOrders(pageSize?: number): Promise<ProductListResult>;
|
|
24
38
|
export declare function getLatestPreOrders(pageSize?: number): Promise<ProductListResult>;
|
|
25
39
|
export declare function listPreOrders(params?: ProductListActionParams): Promise<ProductListResult>;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { sieveAnd, sieveFilter, SIEVE_OP } from "@mohasinac/appkit";
|
|
2
2
|
import { sortBy } from "@mohasinac/appkit";
|
|
3
|
+
import { listPublicProducts } from "../../../_internal/server/features/products/list-public";
|
|
4
|
+
import { AVAILABILITY_VALUES, PRODUCT_FIELDS } from "../../../constants/field-names";
|
|
3
5
|
import { productRepository } from "../repository/products.repository";
|
|
4
6
|
import { ProductStatusValues } from "../schemas";
|
|
5
7
|
/**
|
|
@@ -34,21 +36,55 @@ export async function listProducts(params = {}) {
|
|
|
34
36
|
export async function getProductById(id) {
|
|
35
37
|
return productRepository.findById(id);
|
|
36
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* `PublicProductListResult` → the `FirebaseSieveResult<ProductDocument>` shape
|
|
41
|
+
* these helpers have always returned, so their ~15 call sites (including the
|
|
42
|
+
* six server-action wrappers in `src/actions/product.actions.ts` and their
|
|
43
|
+
* tests) are unchanged by the switch to the shared query.
|
|
44
|
+
*/
|
|
45
|
+
function toListResult(result, pageSize) {
|
|
46
|
+
if (!result) {
|
|
47
|
+
return { items: [], total: 0, page: 1, pageSize, totalPages: 0, hasMore: false };
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
items: result.items,
|
|
51
|
+
total: result.total,
|
|
52
|
+
page: result.page,
|
|
53
|
+
pageSize: result.pageSize,
|
|
54
|
+
totalPages: result.totalPages,
|
|
55
|
+
hasMore: result.hasMore,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
37
58
|
export async function getFeaturedProducts(pageSize = 8) {
|
|
38
|
-
return
|
|
39
|
-
|
|
59
|
+
return toListResult(await listPublicProducts({
|
|
60
|
+
featured: true,
|
|
61
|
+
availability: AVAILABILITY_VALUES.AVAILABLE,
|
|
40
62
|
sorts: sortBy("createdAt", "DESC"),
|
|
41
63
|
page: 1,
|
|
42
64
|
pageSize,
|
|
43
|
-
});
|
|
65
|
+
}), pageSize);
|
|
44
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* The soonest-ending LIVE auctions.
|
|
69
|
+
*
|
|
70
|
+
* This used to be `listingType==auction,status==published` sorted
|
|
71
|
+
* `auctionEndDate ASC` with no lower bound — and ascending order front-loads
|
|
72
|
+
* the OLDEST end dates, so the homepage's "Live Auctions" strip led with the
|
|
73
|
+
* most-expired lots in the catalogue. Nothing about it was flagged as wrong
|
|
74
|
+
* because an ended auction still renders as a perfectly normal card.
|
|
75
|
+
*
|
|
76
|
+
* One listing type, sorted by the same field the scope filters on, means
|
|
77
|
+
* `listPublicProducts` pushes `auctionEndDate >= now` into Firestore rather
|
|
78
|
+
* than filtering a bounded window in memory.
|
|
79
|
+
*/
|
|
45
80
|
export async function getFeaturedAuctions(pageSize = 6) {
|
|
46
|
-
return
|
|
47
|
-
|
|
48
|
-
|
|
81
|
+
return toListResult(await listPublicProducts({
|
|
82
|
+
listingTypes: [PRODUCT_FIELDS.LISTING_TYPE_VALUES.AUCTION],
|
|
83
|
+
availability: AVAILABILITY_VALUES.AVAILABLE,
|
|
84
|
+
sorts: sortBy(PRODUCT_FIELDS.AUCTION_END_DATE, "ASC"),
|
|
49
85
|
page: 1,
|
|
50
86
|
pageSize,
|
|
51
|
-
});
|
|
87
|
+
}), pageSize);
|
|
52
88
|
}
|
|
53
89
|
export async function getLatestProducts(pageSize = 12) {
|
|
54
90
|
return productRepository.list({
|
|
@@ -75,13 +111,15 @@ export async function listAuctions(params = {}) {
|
|
|
75
111
|
pageSize,
|
|
76
112
|
});
|
|
77
113
|
}
|
|
114
|
+
/** Pre-orders still accepting orders, soonest delivery first. */
|
|
78
115
|
export async function getFeaturedPreOrders(pageSize = 6) {
|
|
79
|
-
return
|
|
80
|
-
|
|
81
|
-
|
|
116
|
+
return toListResult(await listPublicProducts({
|
|
117
|
+
listingTypes: [PRODUCT_FIELDS.LISTING_TYPE_VALUES.PRE_ORDER],
|
|
118
|
+
availability: AVAILABILITY_VALUES.AVAILABLE,
|
|
119
|
+
sorts: sortBy(PRODUCT_FIELDS.PRE_ORDER_DELIVERY_DATE, "ASC"),
|
|
82
120
|
page: 1,
|
|
83
121
|
pageSize,
|
|
84
|
-
});
|
|
122
|
+
}), pageSize);
|
|
85
123
|
}
|
|
86
124
|
export async function getLatestPreOrders(pageSize = 12) {
|
|
87
125
|
return productRepository.list({
|
|
@@ -13,6 +13,18 @@
|
|
|
13
13
|
* resolved from `getProviders().db.getRepository("products")`.
|
|
14
14
|
*/
|
|
15
15
|
import { NextResponse } from "next/server.js";
|
|
16
|
+
/**
|
|
17
|
+
* Delegates to `listPublicProducts` — the single implementation shared with
|
|
18
|
+
* every SSR listing view and with the reference consumer's own route.
|
|
19
|
+
*
|
|
20
|
+
* It used to be an independent copy: its own `buildFilters`, its own
|
|
21
|
+
* `validateSieveFilters`, and its own filter allowlist that omitted
|
|
22
|
+
* `auctionEndDate` / `preOrderDeliveryDate` / `prizeRevealStatus` — so on this
|
|
23
|
+
* path an ended auction could not be filtered out even by a caller that asked
|
|
24
|
+
* for it, and an `inStock=true` became a raw `stockQuantity>0` pushed straight
|
|
25
|
+
* into Firestore, the FAILED_PRECONDITION shape Root Cause #59 documents.
|
|
26
|
+
* Two implementations of one query is the drift itself; there is now one.
|
|
27
|
+
*/
|
|
16
28
|
export declare function GET(request: Request): Promise<NextResponse>;
|
|
17
29
|
export declare const POST: (request: Request, context?: {
|
|
18
30
|
params: Promise<Record<string, string>>;
|
|
@@ -19,6 +19,7 @@ import { createRouteHandler } from "../../../next";
|
|
|
19
19
|
import { mediaFieldSchema } from "../../media/types/index";
|
|
20
20
|
import { printMetaSchema } from "../schemas/index";
|
|
21
21
|
import { sanitizeProductsForPublic } from "../utils/sanitize";
|
|
22
|
+
import { listPublicProducts, parsePublicProductParams, } from "../../../_internal/server/features/products/list-public";
|
|
22
23
|
import { normalizeError } from "../../../errors/normalize";
|
|
23
24
|
// --- Mutation schemas ---------------------------------------------------------
|
|
24
25
|
// Minimal schemas for secured mutations — consumer apps can extend as needed.
|
|
@@ -49,8 +50,11 @@ const productMutateSchema = z
|
|
|
49
50
|
sellerName: z.string().optional(),
|
|
50
51
|
sellerEmail: z.string().email().optional(),
|
|
51
52
|
slug: z.string().optional(),
|
|
53
|
+
// `bundle` is deliberately absent: SB-UNI-D moved bundles onto
|
|
54
|
+
// `categories` as a categoryType, so a product written with that value
|
|
55
|
+
// would match no listing-type query anywhere.
|
|
52
56
|
listingType: z
|
|
53
|
-
.enum(["standard", "auction", "pre-order", "prize-draw", "
|
|
57
|
+
.enum(["standard", "auction", "pre-order", "prize-draw", "classified", "digital-code", "live", "art", "stickers"])
|
|
54
58
|
.optional(),
|
|
55
59
|
media: z.array(mediaFieldSchema).optional(),
|
|
56
60
|
})
|
|
@@ -59,114 +63,52 @@ const productMutateSchema = z
|
|
|
59
63
|
function param(url, key) {
|
|
60
64
|
return url.searchParams.get(key);
|
|
61
65
|
}
|
|
62
|
-
|
|
63
|
-
const v = url.searchParams.get(key);
|
|
64
|
-
const n = v !== null ? Number(v) : NaN;
|
|
65
|
-
return Number.isFinite(n) ? n : fallback;
|
|
66
|
-
}
|
|
67
|
-
/** Public fields callers may filter on via the ?filters= param. */
|
|
68
|
-
const SAFE_PRODUCT_FILTER_FIELDS = new Set([
|
|
69
|
-
"status",
|
|
70
|
-
"category",
|
|
71
|
-
"brand",
|
|
72
|
-
"condition",
|
|
73
|
-
"storeId",
|
|
74
|
-
"title",
|
|
75
|
-
"price",
|
|
76
|
-
"listingType",
|
|
77
|
-
"featured",
|
|
78
|
-
"isPromoted",
|
|
79
|
-
"stockQuantity",
|
|
80
|
-
"availableQuantity",
|
|
81
|
-
"tags",
|
|
82
|
-
]);
|
|
66
|
+
// --- GET /api/products --------------------------------------------------------
|
|
83
67
|
/**
|
|
84
|
-
*
|
|
85
|
-
*
|
|
68
|
+
* Delegates to `listPublicProducts` — the single implementation shared with
|
|
69
|
+
* every SSR listing view and with the reference consumer's own route.
|
|
70
|
+
*
|
|
71
|
+
* It used to be an independent copy: its own `buildFilters`, its own
|
|
72
|
+
* `validateSieveFilters`, and its own filter allowlist that omitted
|
|
73
|
+
* `auctionEndDate` / `preOrderDeliveryDate` / `prizeRevealStatus` — so on this
|
|
74
|
+
* path an ended auction could not be filtered out even by a caller that asked
|
|
75
|
+
* for it, and an `inStock=true` became a raw `stockQuantity>0` pushed straight
|
|
76
|
+
* into Firestore, the FAILED_PRECONDITION shape Root Cause #59 documents.
|
|
77
|
+
* Two implementations of one query is the drift itself; there is now one.
|
|
86
78
|
*/
|
|
87
|
-
function validateSieveFilters(raw, allowedFields) {
|
|
88
|
-
return raw
|
|
89
|
-
.split(",")
|
|
90
|
-
.map((c) => c.trim())
|
|
91
|
-
.filter((c) => {
|
|
92
|
-
const m = c.match(/^([^<>=!@]+)\s*(?:==|!=|<=|>=|<|>|@=\*?)/);
|
|
93
|
-
return m ? allowedFields.has(m[1].trim()) : false;
|
|
94
|
-
})
|
|
95
|
-
.join(",");
|
|
96
|
-
}
|
|
97
|
-
function buildFilters(url) {
|
|
98
|
-
const parts = [];
|
|
99
|
-
const status = param(url, "status");
|
|
100
|
-
if (status)
|
|
101
|
-
parts.push(`status==${status}`);
|
|
102
|
-
const category = param(url, "category");
|
|
103
|
-
if (category)
|
|
104
|
-
parts.push(`category==${category}`);
|
|
105
|
-
const brand = param(url, "brand");
|
|
106
|
-
if (brand)
|
|
107
|
-
parts.push(`brand==${brand}`);
|
|
108
|
-
const condition = param(url, "condition");
|
|
109
|
-
if (condition)
|
|
110
|
-
parts.push(`condition==${condition}`);
|
|
111
|
-
const storeId = param(url, "storeId");
|
|
112
|
-
if (storeId)
|
|
113
|
-
parts.push(`storeId==${storeId}`);
|
|
114
|
-
const q = param(url, "q");
|
|
115
|
-
if (q)
|
|
116
|
-
parts.push(`title@=*${q}`);
|
|
117
|
-
const minPrice = param(url, "minPrice");
|
|
118
|
-
if (minPrice !== null && !Number.isNaN(Number(minPrice)))
|
|
119
|
-
parts.push(`price>=${minPrice}`);
|
|
120
|
-
const maxPrice = param(url, "maxPrice");
|
|
121
|
-
if (maxPrice !== null && !Number.isNaN(Number(maxPrice)))
|
|
122
|
-
parts.push(`price<=${maxPrice}`);
|
|
123
|
-
const inStock = param(url, "inStock");
|
|
124
|
-
if (inStock === "true")
|
|
125
|
-
parts.push("stockQuantity>0");
|
|
126
|
-
// SB1-G — canonical discriminator. Public URL accepts only ?listingType=X.
|
|
127
|
-
const listingTypeParam = param(url, "listingType");
|
|
128
|
-
if (listingTypeParam) {
|
|
129
|
-
parts.push(`listingType==${listingTypeParam}`);
|
|
130
|
-
}
|
|
131
|
-
const featured = param(url, "featured");
|
|
132
|
-
if (featured === "true")
|
|
133
|
-
parts.push("featured==true");
|
|
134
|
-
// Merge validated Sieve filters — only safe public fields allowed
|
|
135
|
-
const raw = param(url, "filters");
|
|
136
|
-
if (raw) {
|
|
137
|
-
const safe = validateSieveFilters(raw, SAFE_PRODUCT_FILTER_FIELDS);
|
|
138
|
-
if (safe)
|
|
139
|
-
parts.push(safe);
|
|
140
|
-
}
|
|
141
|
-
return parts.join(",");
|
|
142
|
-
}
|
|
143
|
-
// --- GET /api/products --------------------------------------------------------
|
|
144
79
|
export async function GET(request) {
|
|
145
80
|
try {
|
|
146
81
|
const url = new URL(request.url);
|
|
147
|
-
const
|
|
148
|
-
const
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if (!
|
|
153
|
-
|
|
82
|
+
const listingTypeParam = param(url, "listingType");
|
|
83
|
+
const requestedTypes = (listingTypeParam ?? "").split("|").filter(Boolean);
|
|
84
|
+
const result = await listPublicProducts(parsePublicProductParams(url.searchParams, {
|
|
85
|
+
listingTypes: requestedTypes.length > 0 ? requestedTypes : undefined,
|
|
86
|
+
}));
|
|
87
|
+
if (!result) {
|
|
88
|
+
// Already logged loudly by listPublicProducts. Surfaced as an explicit
|
|
89
|
+
// warning rather than a bare empty page, so a broken query stays
|
|
90
|
+
// distinguishable from an empty catalogue.
|
|
91
|
+
return NextResponse.json({
|
|
92
|
+
success: true,
|
|
93
|
+
data: {
|
|
94
|
+
items: [],
|
|
95
|
+
total: 0,
|
|
96
|
+
page: 1,
|
|
97
|
+
pageSize: 0,
|
|
98
|
+
totalPages: 0,
|
|
99
|
+
hasMore: false,
|
|
100
|
+
warning: "Product search is temporarily unavailable.",
|
|
101
|
+
},
|
|
102
|
+
});
|
|
154
103
|
}
|
|
155
|
-
const repo = db.getRepository("products");
|
|
156
|
-
const result = await repo.findAll({
|
|
157
|
-
filters,
|
|
158
|
-
sort,
|
|
159
|
-
page,
|
|
160
|
-
perPage: pageSize,
|
|
161
|
-
});
|
|
162
|
-
const totalPages = Math.max(1, Math.ceil(result.total / pageSize));
|
|
163
104
|
const body = {
|
|
164
|
-
items: sanitizeProductsForPublic(result.
|
|
105
|
+
items: sanitizeProductsForPublic(result.items),
|
|
165
106
|
total: result.total,
|
|
166
107
|
page: result.page,
|
|
167
|
-
pageSize,
|
|
168
|
-
totalPages,
|
|
169
|
-
hasMore: result.
|
|
108
|
+
pageSize: result.pageSize,
|
|
109
|
+
totalPages: result.totalPages,
|
|
110
|
+
hasMore: result.hasMore,
|
|
111
|
+
truncated: result.truncated,
|
|
170
112
|
};
|
|
171
113
|
const response = NextResponse.json({ success: true, data: body });
|
|
172
114
|
response.headers.set("Cache-Control", "public, max-age=60, s-maxage=120, stale-while-revalidate=60");
|
|
@@ -5,7 +5,7 @@ import { ProductsIndexListing } from "./ProductsIndexListing";
|
|
|
5
5
|
import { PRODUCT_FIELDS } from "../../../constants/field-names";
|
|
6
6
|
import { sortBy } from "../../../constants/sort";
|
|
7
7
|
import { ART_STICKERS_TYPE_FILTER_TABS, ART_STICKERS_LISTING_TYPES, } from "../constants/listing-tabs";
|
|
8
|
-
import { listPublicProducts, parsePublicProductParams,
|
|
8
|
+
import { listPublicProducts, parsePublicProductParams, defaultAvailabilityForListingTypes, } from "../../../_internal/server/features/products/list-public";
|
|
9
9
|
const DEFAULT_PAGE_SIZE = 24;
|
|
10
10
|
const DEFAULT_SORT = sortBy(PRODUCT_FIELDS.CREATED_AT);
|
|
11
11
|
export async function ArtStickersListView({ searchParams = {} }) {
|
|
@@ -18,7 +18,7 @@ export async function ArtStickersListView({ searchParams = {} }) {
|
|
|
18
18
|
sorts: DEFAULT_SORT,
|
|
19
19
|
// Derived, so this page and ProductsIndexListing can never disagree
|
|
20
20
|
// about the default view (Root Cause #30).
|
|
21
|
-
...
|
|
21
|
+
...defaultAvailabilityForListingTypes(ART_STICKERS_LISTING_TYPES),
|
|
22
22
|
}));
|
|
23
23
|
return (_jsxs(Main, { children: [_jsx(Section, { border: "bottom-subtle", paddingY: "b-md", padding: "t-xl", children: _jsxs(Container, { size: "xl", children: [_jsx(Heading, { level: 1, size: "3xl", weight: "bold", color: "primary", children: "Art & Stickers" }), _jsx(Text, { className: "mt-1", color: "muted", size: "sm", children: "Original art prints and sticker packs from independent sellers" })] }) }), _jsxs(Container, { size: "xl", padding: "x-md", children: [_jsx(AdSlot, { id: "listing-sidebar-top", className: "mb-4 mt-4" }), _jsx(ProductsIndexListing, { initialData: result ?? null, listingTypes: ART_STICKERS_LISTING_TYPES, typeTabs: ART_STICKERS_TYPE_FILTER_TABS, searchPlaceholder: "Search art & stickers..." }), _jsx(AdSlot, { id: "listing-sidebar-bottom", className: "mt-8" })] })] }));
|
|
24
24
|
}
|
|
@@ -17,6 +17,8 @@ import { useAuthGate } from "../../../react/hooks/useAuthGate";
|
|
|
17
17
|
import { ACTION_ID } from "../constants/action-defs";
|
|
18
18
|
import { AUCTION_PUBLIC_SORT_OPTIONS } from "../constants/sieve";
|
|
19
19
|
import { useBottomActions } from "../../layout";
|
|
20
|
+
import { AVAILABILITY_VALUES } from "../../../constants/field-names";
|
|
21
|
+
import { AvailabilityTabs } from "./AvailabilityTabs";
|
|
20
22
|
const __P = {
|
|
21
23
|
p3: "p-[var(--appkit-space-3)]",
|
|
22
24
|
};
|
|
@@ -24,6 +26,7 @@ const __O = {
|
|
|
24
26
|
hidden: "overflow-hidden",
|
|
25
27
|
};
|
|
26
28
|
const DEFAULT_SORT = AUCTION_PUBLIC_SORT_OPTIONS[0].value;
|
|
29
|
+
const AUCTION_LISTING_TYPES = ["auction"];
|
|
27
30
|
const FILTER_KEYS = [TABLE_KEYS.CATEGORY, TABLE_KEYS.BRAND, TABLE_KEYS.MIN_BID, TABLE_KEYS.MAX_BID, TABLE_KEYS.STORE_ID, TABLE_KEYS.DATE_FROM, TABLE_KEYS.DATE_TO];
|
|
28
31
|
export function AuctionsIndexListing({ initialData, categorySlug, brandName }) {
|
|
29
32
|
const table = useUrlTable({ defaults: { pageSize: "24", sort: DEFAULT_SORT } });
|
|
@@ -31,7 +34,8 @@ export function AuctionsIndexListing({ initialData, categorySlug, brandName }) {
|
|
|
31
34
|
const { requireAuth, modalOpen, modalMessage, closeModal } = useAuthGate();
|
|
32
35
|
const [searchInput, setSearchInput] = useState(table.get(TABLE_KEYS.QUERY) || "");
|
|
33
36
|
const [filterOpen, setFilterOpen] = useState(false);
|
|
34
|
-
const
|
|
37
|
+
const availability = table.get(TABLE_KEYS.AVAILABILITY) ||
|
|
38
|
+
AVAILABILITY_VALUES.AVAILABLE;
|
|
35
39
|
const [view, setView] = useState(table.get(TABLE_KEYS.VIEW) || VIEW_MODE.GRID);
|
|
36
40
|
const localWishlist = useGuestWishlist();
|
|
37
41
|
const wishlistedIds = new Set(localWishlist.items.filter((i) => i.type === "auction").map((i) => i.itemId));
|
|
@@ -48,11 +52,11 @@ export function AuctionsIndexListing({ initialData, categorySlug, brandName }) {
|
|
|
48
52
|
setFilterOpen(false);
|
|
49
53
|
}, [onFilterApply]);
|
|
50
54
|
const resetAll = useCallback(() => {
|
|
51
|
-
onResetAll({ [TABLE_KEYS.QUERY]: "", [TABLE_KEYS.SORT]: "", [TABLE_KEYS.
|
|
55
|
+
onResetAll({ [TABLE_KEYS.QUERY]: "", [TABLE_KEYS.SORT]: "", [TABLE_KEYS.AVAILABILITY]: "" });
|
|
52
56
|
setSearchInput("");
|
|
53
57
|
}, [onResetAll]);
|
|
54
58
|
const hasActiveState = !!table.get(TABLE_KEYS.QUERY) ||
|
|
55
|
-
|
|
59
|
+
availability !== AVAILABILITY_VALUES.AVAILABLE ||
|
|
56
60
|
table.get(TABLE_KEYS.SORT) !== DEFAULT_SORT ||
|
|
57
61
|
filterActiveCount > 0;
|
|
58
62
|
const params = {
|
|
@@ -63,16 +67,16 @@ export function AuctionsIndexListing({ initialData, categorySlug, brandName }) {
|
|
|
63
67
|
minBid: table.get(TABLE_KEYS.MIN_BID) ? Number(table.get(TABLE_KEYS.MIN_BID)) : undefined,
|
|
64
68
|
maxBid: table.get(TABLE_KEYS.MAX_BID) ? Number(table.get(TABLE_KEYS.MAX_BID)) : undefined,
|
|
65
69
|
storeId: table.get(TABLE_KEYS.STORE_ID) || undefined,
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
: new Date().toISOString(),
|
|
70
|
+
// Now purely the drawer's own end-date window. It used to double as the
|
|
71
|
+
// hide-ended mechanism, which meant the drawer facet and the toggle fought
|
|
72
|
+
// over one param; the scope tab owns that decision instead.
|
|
73
|
+
dateFrom: table.get(TABLE_KEYS.DATE_FROM) || undefined,
|
|
71
74
|
dateTo: table.get(TABLE_KEYS.DATE_TO) || undefined,
|
|
72
75
|
sort: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT,
|
|
73
76
|
page: table.getNumber(TABLE_KEYS.PAGE, 1),
|
|
74
77
|
perPage: table.getNumber(TABLE_KEYS.PAGE_SIZE, 24),
|
|
75
78
|
listingType: "auction",
|
|
79
|
+
availability,
|
|
76
80
|
};
|
|
77
81
|
const { products: auctions, totalPages, page, isLoading } = useProducts(params, { initialData });
|
|
78
82
|
const selection = useBulkSelection({ items: auctions, keyExtractor: (a) => a.id });
|
|
@@ -131,9 +135,7 @@ export function AuctionsIndexListing({ initialData, categorySlug, brandName }) {
|
|
|
131
135
|
},
|
|
132
136
|
},
|
|
133
137
|
] } } : {});
|
|
134
|
-
return (_jsxs(Div, { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: filterActiveCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search auctions...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, onSearchKeyDown: handleSearchKeyDown, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: AUCTION_PUBLIC_SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, view: view, onViewChange: handleViewToggle, onResetAll: resetAll, hasActiveState: hasActiveState, bulkMode: selection.isSelecting, bulkSelectedCount: selection.selectedCount, bulkTotalCount: auctions.length, onBulkSelectAll: selection.toggleAll, onBulkClear: selection.clearSelection,
|
|
135
|
-
{ label: "Show ended", active: showEnded, onChange: (next) => table.set(TABLE_KEYS.SHOW_ENDED, next ? "true" : "") },
|
|
136
|
-
] }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
138
|
+
return (_jsxs(Div, { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: filterActiveCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search auctions...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, onSearchKeyDown: handleSearchKeyDown, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: AUCTION_PUBLIC_SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, view: view, onViewChange: handleViewToggle, onResetAll: resetAll, hasActiveState: hasActiveState, bulkMode: selection.isSelecting, bulkSelectedCount: selection.selectedCount, bulkTotalCount: auctions.length, onBulkSelectAll: selection.toggleAll, onBulkClear: selection.clearSelection }), _jsx(Div, { padding: "y-sm", children: _jsx(AvailabilityTabs, { types: AUCTION_LISTING_TYPES }) }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
137
139
|
{
|
|
138
140
|
id: ACTION_ID.WATCH_AUCTION,
|
|
139
141
|
label: "Add to Watchlist",
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { ListingType } from "../types";
|
|
3
|
+
export interface AvailabilityTabsProps {
|
|
4
|
+
/**
|
|
5
|
+
* The listing types the surface spans. Drives the middle tab's wording only
|
|
6
|
+
* — the scope itself means the same thing for every type.
|
|
7
|
+
*/
|
|
8
|
+
types: readonly ListingType[];
|
|
9
|
+
className?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function AvailabilityTabs({ types, className }: AvailabilityTabsProps): React.JSX.Element;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
/*
|
|
4
|
+
* WHY: Every listing surface used to carry a "Show sold" / "Show ended" /
|
|
5
|
+
* "Show closed" pill that WIDENED the list — flipping it mixed dead rows
|
|
6
|
+
* into the live ones, so there was no way to browse the archive on its
|
|
7
|
+
* own, and no way to be sure the default view was clean. Three URL
|
|
8
|
+
* spellings of one intent had also accumulated, and each listing page
|
|
9
|
+
* hand-built its own toggle array, so the label and the SSR default
|
|
10
|
+
* drifted apart per page.
|
|
11
|
+
*
|
|
12
|
+
* WHAT: One three-tab scope bar — Available / <Sold & Ended> / All — shared by
|
|
13
|
+
* the public browse pages, the store tabs, the category and brand
|
|
14
|
+
* panels, and the admin/seller dashboards. The middle label is DERIVED
|
|
15
|
+
* from each listing type's `hideDefault`, so /auctions reads "Ended",
|
|
16
|
+
* /art reads "Sold", and /products reads "Sold & Ended".
|
|
17
|
+
*
|
|
18
|
+
* EXPORTS: AvailabilityTabs, AvailabilityTabsProps
|
|
19
|
+
*
|
|
20
|
+
* @tag domain:products
|
|
21
|
+
* @tag layer:ui
|
|
22
|
+
* @tag pattern:none
|
|
23
|
+
* @tag access:client
|
|
24
|
+
* @tag consumers:ProductsIndexListing,AuctionsIndexListing,PreOrdersIndexListing,PrizeDrawsIndexListing,Store*Listing,CategoryProductsListing,Seller*View,Admin*View
|
|
25
|
+
* @tag sideEffects:url-mutation
|
|
26
|
+
*/
|
|
27
|
+
import { useMemo } from "react";
|
|
28
|
+
import { Tabs, TabsList, TabsTrigger } from "../../../ui";
|
|
29
|
+
import { useUrlTable } from "../../../react/hooks/useUrlTable";
|
|
30
|
+
import { TABLE_KEYS } from "../../../constants/table-keys";
|
|
31
|
+
import { AVAILABILITY_VALUES } from "../../../constants/field-names";
|
|
32
|
+
import { availabilityTabsFor } from "../../../_internal/shared/listing-types/_registry";
|
|
33
|
+
export function AvailabilityTabs({ types, className }) {
|
|
34
|
+
const table = useUrlTable();
|
|
35
|
+
const tabs = useMemo(() => availabilityTabsFor(types), [types]);
|
|
36
|
+
// An absent param is the Available scope — the same default every SSR
|
|
37
|
+
// filter-builder resolves through `defaultAvailabilityForListingTypes`.
|
|
38
|
+
// Reading a different default here is precisely how SSR and the first
|
|
39
|
+
// refetch end up permanently disagreeing (Root Cause #30).
|
|
40
|
+
const active = table.get(TABLE_KEYS.AVAILABILITY) || AVAILABILITY_VALUES.AVAILABLE;
|
|
41
|
+
return (_jsx(Tabs, { value: active,
|
|
42
|
+
// A single `set`, never followed by `setPage`. `useUrlTable.set` already
|
|
43
|
+
// resets the page for any key outside NON_RESETTING_KEYS, and a
|
|
44
|
+
// follow-up call would read stale searchParams and overwrite this one
|
|
45
|
+
// (Root Cause #13).
|
|
46
|
+
onChange: (next) => table.set(TABLE_KEYS.AVAILABILITY, next), className: className, children: _jsx(TabsList, { children: tabs.map((tab) => (_jsx(TabsTrigger, { value: tab.id, children: tab.label }, tab.id))) }) }));
|
|
47
|
+
}
|
|
@@ -235,7 +235,11 @@ export function GroupSettingsPanel({ productId, productSlug, groupId, isGroupPar
|
|
|
235
235
|
setOpen(next);
|
|
236
236
|
if (next && isGroupParent && children === null)
|
|
237
237
|
loadChildren();
|
|
238
|
-
}, paddingX: "none", paddingY: "xs", justify: "between", className: "w-full text-left group", "aria-expanded": open, children: [_jsx(Heading, { level: 3, size: "sm", weight: "semibold", color: "muted", children: "Group Settings" }), _jsx(Span, { size: "xs", className: "group-hover:text-[var(--appkit-color-text-muted)] dark:group-hover:text-[var(--appkit-color-text-faint)] transition-colors", color: "faint", children: open ? "▲" : "▼" })] }), open && (_jsxs(Stack, { gap: "sm", className: `mt-3 ${__P.p4}`, surface: "muted", rounded: "lg", border: "default", children: [!groupId && !groupParentSlug && (_jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "xs", color: "muted", children: "Group related listings together \u2014 e.g. a set, bundle, or multi-part item. Parts can be sold individually but shown together." }), _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: startGroup, isLoading: loading, children: "Start a group" })] })), isGroupParent && groupId && (_jsxs(Stack, { gap: "md", children: [_jsxs(FormShellContext.Provider, { value: titleShellCtx, children: [_jsxs(Row, { align: "start", gap: "sm", wrap: true, children: [_jsx(Div, { className: "flex-1 min-w-[200px]", children: _jsx(FormField, { name: "groupTitle", label: "Group title", type: "text", value: editTitle, onChange: setEditTitle, placeholder: "e.g. Human Toy Complete Set" }) }), _jsx(Div, { padding: "t-lg", children: _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: saveTitle, isLoading: loading, children: "Save title" }) })] }), _jsx(FormErrorSummary, {})] }), _jsxs(Div, { children: [_jsxs(Text, { className: "mb-2", color: "muted", size: "xs", weight: "semibold", children: ["Members (", childSlugsCount + 1, " \u2014 including this listing)"] }), loading && !children ? (_jsx(Text, { size: "xs", color: "faint", children: "Loading\u2026" })) : (_jsxs(Div, { className: "divide-y divide-zinc-100 divide-[var(--appkit-color-border-subtle)]", children: [_jsxs(Row, { align: "center", gap: "sm", padding: "y-xs", children: [_jsx(Span, { padding: "pill-2xs", weight: "semibold", className: "bg-[var(--appkit-color-primary)]/10 text-[var(--appkit-color-primary)] text-[10px]", rounded: "default", children: "Parent" }), _jsx(Text, { className: "flex-1", color: "primary", size: "sm", children: productSlug })] }), (children ?? []).filter((c) => c.id !== productId).map((child) => (_jsxs(Row, { align: "center", gap: "sm", padding: "y-xs", children: [child.images?.[0] ? (_jsx(Div, { className: "relative w-8 h-8 flex-shrink-0 border border-[var(--appkit-color-border)]", rounded: "full", overflow: "hidden", children: _jsx(MediaImage, { src: child.images[0], alt: child.title, size: "thumbnail" }) })) : (_jsx(Div, { className: "w-8 h-8", surface: "subtle", rounded: "full" })), _jsx(Text, { className: "flex-1 truncate", color: "primary", size: "sm", children: child.title }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => requestUnlinkChild(child.id), isLoading: loading, className: `${CLS_DELETE_LINK} text-[length:var(--appkit-text-xs)]`, children: "Unlink" })] }, child.id)))] }))] }), _jsxs(Row, { gap: "sm", wrap: true, children: [_jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: () => setShowAddModal(true), children: "Add child listing" }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: requestDissolveGroup, isLoading: loading, className: CLS_DELETE_LINK, children: "Dissolve group" })] })] })), !isGroupParent && groupParentSlug && (_jsxs(Stack, { gap: "xs", children: [_jsxs(Text, { size: "sm", color: "muted", children: ["Part of:", " ", _jsx(Span, { weight: "medium", color: "primary", children: groupTitle ?? groupParentSlug })] }), _jsxs(Text, { size: "xs", color: "muted", children: ["Parent listing: ", _jsx(Code, { className: "font-mono", children: groupParentSlug })] }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: requestLeaveGroup, isLoading: loading, className: `${CLS_DELETE_LINK} w-fit`, children: "Leave group" })] }))] })), (
|
|
238
|
+
}, paddingX: "none", paddingY: "xs", justify: "between", className: "w-full text-left group", "aria-expanded": open, children: [_jsx(Heading, { level: 3, size: "sm", weight: "semibold", color: "muted", children: "Group Settings" }), _jsx(Span, { size: "xs", className: "group-hover:text-[var(--appkit-color-text-muted)] dark:group-hover:text-[var(--appkit-color-text-faint)] transition-colors", color: "faint", children: open ? "▲" : "▼" })] }), open && (_jsxs(Stack, { gap: "sm", className: `mt-3 ${__P.p4}`, surface: "muted", rounded: "lg", border: "default", children: [!groupId && !groupParentSlug && (_jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "xs", color: "muted", children: "Group related listings together \u2014 e.g. a set, bundle, or multi-part item. Parts can be sold individually but shown together." }), _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: startGroup, isLoading: loading, children: "Start a group" })] })), isGroupParent && groupId && (_jsxs(Stack, { gap: "md", children: [_jsxs(FormShellContext.Provider, { value: titleShellCtx, children: [_jsxs(Row, { align: "start", gap: "sm", wrap: true, children: [_jsx(Div, { className: "flex-1 min-w-[200px]", children: _jsx(FormField, { name: "groupTitle", label: "Group title", type: "text", value: editTitle, onChange: setEditTitle, placeholder: "e.g. Human Toy Complete Set" }) }), _jsx(Div, { padding: "t-lg", children: _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: saveTitle, isLoading: loading, children: "Save title" }) })] }), _jsx(FormErrorSummary, {})] }), _jsxs(Div, { children: [_jsxs(Text, { className: "mb-2", color: "muted", size: "xs", weight: "semibold", children: ["Members (", childSlugsCount + 1, " \u2014 including this listing)"] }), loading && !children ? (_jsx(Text, { size: "xs", color: "faint", children: "Loading\u2026" })) : (_jsxs(Div, { className: "divide-y divide-zinc-100 divide-[var(--appkit-color-border-subtle)]", children: [_jsxs(Row, { align: "center", gap: "sm", padding: "y-xs", children: [_jsx(Span, { padding: "pill-2xs", weight: "semibold", className: "bg-[var(--appkit-color-primary)]/10 text-[var(--appkit-color-primary)] text-[10px]", rounded: "default", children: "Parent" }), _jsx(Text, { className: "flex-1", color: "primary", size: "sm", children: productSlug })] }), (children ?? []).filter((c) => c.id !== productId).map((child) => (_jsxs(Row, { align: "center", gap: "sm", padding: "y-xs", children: [child.images?.[0] ? (_jsx(Div, { className: "relative w-8 h-8 flex-shrink-0 border border-[var(--appkit-color-border)]", rounded: "full", overflow: "hidden", children: _jsx(MediaImage, { src: child.images[0], alt: child.title, size: "thumbnail" }) })) : (_jsx(Div, { className: "w-8 h-8", surface: "subtle", rounded: "full" })), _jsx(Text, { className: "flex-1 truncate", color: "primary", size: "sm", children: child.title }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => requestUnlinkChild(child.id), isLoading: loading, className: `${CLS_DELETE_LINK} text-[length:var(--appkit-text-xs)]`, children: "Unlink" })] }, child.id)))] }))] }), _jsxs(Row, { gap: "sm", wrap: true, children: [_jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: () => setShowAddModal(true), children: "Add child listing" }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: requestDissolveGroup, isLoading: loading, className: CLS_DELETE_LINK, children: "Dissolve group" })] })] })), !isGroupParent && groupParentSlug && (_jsxs(Stack, { gap: "xs", children: [_jsxs(Text, { size: "sm", color: "muted", children: ["Part of:", " ", _jsx(Span, { weight: "medium", color: "primary", children: groupTitle ?? groupParentSlug })] }), _jsxs(Text, { size: "xs", color: "muted", children: ["Parent listing: ", _jsx(Code, { className: "font-mono", children: groupParentSlug })] }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: requestLeaveGroup, isLoading: loading, className: `${CLS_DELETE_LINK} w-fit`, children: "Leave group" })] }))] })), (() => {
|
|
239
|
+
const content = (_jsx(AddChildContent, { addTab: addTab, setAddTab: setAddTab, createForm: createForm, setCreateForm: setCreateForm, productSlug: productSlug, storeProductsEndpoint: storeProductsEndpoint, linkTargets: linkTargets, setLinkTargets: setLinkTargets, onAddCreate: addCreateChild, onAddLink: addLinkChild, loading: loading }));
|
|
240
|
+
const close = () => setShowAddModal(false);
|
|
241
|
+
return (groupChildSlugs?.length ?? 0) >= 4 ? (_jsx(SideDrawer, { isOpen: showAddModal, onClose: close, title: "Add child listing", children: content })) : (_jsx(Modal, { open: showAddModal, onClose: close, title: "Add child listing", size: "lg", children: content }));
|
|
242
|
+
})(), confirmAction && (_jsx(ConfirmDeleteModal, { isOpen: true, title: confirmAction.title, message: confirmAction.message, onConfirm: confirmAction.onConfirm, onClose: () => setConfirmAction(null), isDeleting: loading }))] }));
|
|
239
243
|
}
|
|
240
244
|
function AddChildContent({ addTab, setAddTab, createForm, setCreateForm, productSlug, storeProductsEndpoint, linkTargets, setLinkTargets, onAddCreate, onAddLink, loading, }) {
|
|
241
245
|
const { shellCtx, validate } = useFormShellState(createChildSchema);
|