@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
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* WHY: `POST /api/store/grouped-listings` spread the raw request body into
|
|
3
|
+
* `.create()` and its PATCH built `{...body}` — no Zod on either. The two
|
|
4
|
+
* pages behind them validated one field between them (`new` checked
|
|
5
|
+
* `title` was non-empty and toasted; `[id]/edit` checked nothing at all).
|
|
6
|
+
* WHAT: One schema for the pages AND the store routes.
|
|
7
|
+
*
|
|
8
|
+
* ## `activeMemberCount` is NOT in this schema
|
|
9
|
+
*
|
|
10
|
+
* It is derived — both routes already recompute it from `productIds.length`,
|
|
11
|
+
* which is correct and was verified rather than assumed. Accepting it from the
|
|
12
|
+
* body would let a caller set a count that disagrees with the array, and the
|
|
13
|
+
* count is what the public visibility check reads.
|
|
14
|
+
*
|
|
15
|
+
* `slug`, `visibilityStatus` and `createdBy` are absent for the same reason:
|
|
16
|
+
* derived or session-owned, never typed.
|
|
17
|
+
*
|
|
18
|
+
* EXPORTS:
|
|
19
|
+
* groupedListingFormSchema, groupedListingCreateSchema,
|
|
20
|
+
* groupedListingUpdateSchema, type GroupedListingFormValues
|
|
21
|
+
*
|
|
22
|
+
* @tag domain:grouped
|
|
23
|
+
* @tag layer:schema
|
|
24
|
+
* @tag pattern:none
|
|
25
|
+
* @tag access:isomorphic
|
|
26
|
+
* @tag consumers:store/grouped-listings pages,/api/store/grouped-listings
|
|
27
|
+
* @tag sideEffects:none
|
|
28
|
+
*/
|
|
29
|
+
import { z } from "zod";
|
|
30
|
+
import { annotate } from "../../shell/field-ui-meta";
|
|
31
|
+
/** Mirrors `GroupTheme` in ./firestore. */
|
|
32
|
+
const groupThemeSchema = z.enum(["related", "character", "lineage", "set", "generic"]);
|
|
33
|
+
/**
|
|
34
|
+
* 🛑 `annotate()` must be the OUTERMOST call on each field — it keys a WeakMap
|
|
35
|
+
* by schema instance and every zod wrapper returns a new one.
|
|
36
|
+
*/
|
|
37
|
+
export const groupedListingFormSchema = z.object({
|
|
38
|
+
title: annotate(z.string().min(1, "Title is required").max(120, "Keep the title under 120 characters."), {
|
|
39
|
+
section: "basics", sectionLabel: "Group", sectionRequired: true,
|
|
40
|
+
quick: true, order: 1, row: "full",
|
|
41
|
+
}),
|
|
42
|
+
description: annotate(z.string().max(500, "Keep the description under 500 characters.").optional(), {
|
|
43
|
+
section: "basics", order: 2, row: "full",
|
|
44
|
+
}),
|
|
45
|
+
groupTheme: annotate(groupThemeSchema, {
|
|
46
|
+
section: "basics", quick: true, order: 3, row: "pair",
|
|
47
|
+
}),
|
|
48
|
+
productIds: annotate(z.array(z.string()), {
|
|
49
|
+
section: "members", sectionLabel: "Members", order: 1, row: "full", kind: "list",
|
|
50
|
+
}),
|
|
51
|
+
minActiveMembers: annotate(z.coerce.number().int("Must be a whole number.").min(1, "A group needs at least one member to show."), {
|
|
52
|
+
section: "members", order: 2, row: "pair",
|
|
53
|
+
help: "Below this many in-stock members, the group hides itself.",
|
|
54
|
+
}),
|
|
55
|
+
coverImage: annotate(z.string().optional(), {
|
|
56
|
+
section: "media", sectionLabel: "Media", order: 1, row: "full", kind: "media",
|
|
57
|
+
}),
|
|
58
|
+
isActive: annotate(z.boolean(), {
|
|
59
|
+
section: "visibility", sectionLabel: "Visibility", order: 1, row: "quarter",
|
|
60
|
+
}),
|
|
61
|
+
isFeatured: annotate(z.boolean(), {
|
|
62
|
+
section: "visibility", order: 2, row: "quarter",
|
|
63
|
+
}),
|
|
64
|
+
});
|
|
65
|
+
/**
|
|
66
|
+
* Create contract. `storeId` is absent — the store route sets it from the
|
|
67
|
+
* session, so a seller cannot file a group under another store.
|
|
68
|
+
*/
|
|
69
|
+
export const groupedListingCreateSchema = groupedListingFormSchema.partial({
|
|
70
|
+
description: true,
|
|
71
|
+
coverImage: true,
|
|
72
|
+
isFeatured: true,
|
|
73
|
+
minActiveMembers: true,
|
|
74
|
+
});
|
|
75
|
+
/** Update contract — partial, `.strict()` so an unknown key is a 400. */
|
|
76
|
+
export const groupedListingUpdateSchema = z
|
|
77
|
+
.object({
|
|
78
|
+
title: z.string().min(1).max(120).optional(),
|
|
79
|
+
description: z.string().max(500).optional(),
|
|
80
|
+
groupTheme: groupThemeSchema.optional(),
|
|
81
|
+
productIds: z.array(z.string()).optional(),
|
|
82
|
+
minActiveMembers: z.coerce.number().int().min(1).optional(),
|
|
83
|
+
coverImage: z.string().optional(),
|
|
84
|
+
isActive: z.boolean().optional(),
|
|
85
|
+
isFeatured: z.boolean().optional(),
|
|
86
|
+
brandSlug: z.string().optional(),
|
|
87
|
+
categorySlug: z.string().optional(),
|
|
88
|
+
})
|
|
89
|
+
.strict();
|
|
@@ -43,9 +43,9 @@ export declare const groupedListingFirestoreSchema: z.ZodObject<{
|
|
|
43
43
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
44
44
|
}, z.ZodTypeAny, "passthrough">;
|
|
45
45
|
slug: string;
|
|
46
|
-
isFeatured: boolean;
|
|
47
46
|
isActive: boolean;
|
|
48
47
|
createdBy: string;
|
|
48
|
+
isFeatured: boolean;
|
|
49
49
|
productIds: string[];
|
|
50
50
|
groupTheme: "set" | "related" | "character" | "lineage" | "generic";
|
|
51
51
|
visibilityStatus: "hidden" | "visible";
|
|
@@ -53,8 +53,8 @@ export declare const groupedListingFirestoreSchema: z.ZodObject<{
|
|
|
53
53
|
activeMemberCount: number;
|
|
54
54
|
storeId?: string | undefined;
|
|
55
55
|
description?: string | undefined;
|
|
56
|
-
brandSlug?: string | undefined;
|
|
57
56
|
categorySlug?: string | undefined;
|
|
57
|
+
brandSlug?: string | undefined;
|
|
58
58
|
coverImage?: string | undefined;
|
|
59
59
|
}, {
|
|
60
60
|
id: string;
|
|
@@ -66,9 +66,9 @@ export declare const groupedListingFirestoreSchema: z.ZodObject<{
|
|
|
66
66
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
67
67
|
}, z.ZodTypeAny, "passthrough">;
|
|
68
68
|
slug: string;
|
|
69
|
-
isFeatured: boolean;
|
|
70
69
|
isActive: boolean;
|
|
71
70
|
createdBy: string;
|
|
71
|
+
isFeatured: boolean;
|
|
72
72
|
productIds: string[];
|
|
73
73
|
groupTheme: "set" | "related" | "character" | "lineage" | "generic";
|
|
74
74
|
visibilityStatus: "hidden" | "visible";
|
|
@@ -76,8 +76,8 @@ export declare const groupedListingFirestoreSchema: z.ZodObject<{
|
|
|
76
76
|
activeMemberCount: number;
|
|
77
77
|
storeId?: string | undefined;
|
|
78
78
|
description?: string | undefined;
|
|
79
|
-
brandSlug?: string | undefined;
|
|
80
79
|
categorySlug?: string | undefined;
|
|
80
|
+
brandSlug?: string | undefined;
|
|
81
81
|
coverImage?: string | undefined;
|
|
82
82
|
}>;
|
|
83
83
|
export type GroupedListingFromSchema = z.infer<typeof groupedListingFirestoreSchema>;
|
|
@@ -2,21 +2,29 @@ import { z } from "zod";
|
|
|
2
2
|
import type { HomepageSectionDocument } from "../schemas";
|
|
3
3
|
import type { FirebaseSieveResult } from "../../../providers/db-firebase";
|
|
4
4
|
export declare const createSectionSchema: z.ZodObject<{
|
|
5
|
-
type: z.
|
|
5
|
+
type: z.ZodEnum<["welcome", "carousel", "stats", "trust-indicators", "categories", "brands", "products", "pre-orders", "auctions", "banner", "features", "reviews", "whatsapp-community", "faq", "blog-articles", "newsletter", "stores", "events", "social-feed", "custom-cards", "google-reviews", "featured-bundles", "prize-draws", "event-raffles", "collection-cards"]>;
|
|
6
6
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
7
7
|
order: z.ZodDefault<z.ZodNumber>;
|
|
8
8
|
config: z.ZodOptional<z.ZodObject<{}, "passthrough", z.ZodTypeAny, z.objectOutputType<{}, z.ZodTypeAny, "passthrough">, z.objectInputType<{}, z.ZodTypeAny, "passthrough">>>;
|
|
9
9
|
}, "strip", z.ZodTypeAny, {
|
|
10
|
-
type:
|
|
10
|
+
type: "banner" | "stores" | "products" | "pre-orders" | "prize-draws" | "auctions" | "reviews" | "events" | "categories" | "brands" | "carousel" | "newsletter" | "features" | "stats" | "welcome" | "trust-indicators" | "whatsapp-community" | "faq" | "blog-articles" | "social-feed" | "custom-cards" | "google-reviews" | "featured-bundles" | "event-raffles" | "collection-cards";
|
|
11
11
|
enabled: boolean;
|
|
12
12
|
order: number;
|
|
13
13
|
config?: z.objectOutputType<{}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
14
14
|
}, {
|
|
15
|
-
type:
|
|
15
|
+
type: "banner" | "stores" | "products" | "pre-orders" | "prize-draws" | "auctions" | "reviews" | "events" | "categories" | "brands" | "carousel" | "newsletter" | "features" | "stats" | "welcome" | "trust-indicators" | "whatsapp-community" | "faq" | "blog-articles" | "social-feed" | "custom-cards" | "google-reviews" | "featured-bundles" | "event-raffles" | "collection-cards";
|
|
16
16
|
enabled?: boolean | undefined;
|
|
17
17
|
order?: number | undefined;
|
|
18
18
|
config?: z.objectInputType<{}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
19
19
|
}>;
|
|
20
|
+
/**
|
|
21
|
+
* The next free `order` value.
|
|
22
|
+
*
|
|
23
|
+
* `HomepageSectionCreateInput.order` is REQUIRED, and both API create routes
|
|
24
|
+
* need the same answer for "the caller did not choose one". Two copies of this
|
|
25
|
+
* query is how they would come to disagree about where a new section lands.
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveNextSectionOrder(): Promise<number>;
|
|
20
28
|
export declare const updateSectionSchema: z.ZodObject<{
|
|
21
29
|
order: z.ZodOptional<z.ZodNumber>;
|
|
22
30
|
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -1,13 +1,45 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { serverLogger } from "../../../monitoring";
|
|
3
|
+
import { sortBy } from "../../../constants/sort";
|
|
4
|
+
import { HOMEPAGE_SECTION_FIELDS } from "../../../constants/field-names";
|
|
3
5
|
import { homepageSectionsRepository } from "../repository/homepage-sections.repository";
|
|
6
|
+
import { homepageSectionTypeSchema } from "../schemas";
|
|
4
7
|
// --- Schemas --------------------------------------------------------------
|
|
8
|
+
/*
|
|
9
|
+
* 🛑 `type` was `z.string().min(1)` — ANY non-empty string.
|
|
10
|
+
*
|
|
11
|
+
* This is the third of three create paths for `homepageSections`
|
|
12
|
+
* (`POST /api/admin/sections`, `POST /api/homepage-sections`, and this server
|
|
13
|
+
* action via `createHomepageSectionAction`), and it was the loosest: a caller
|
|
14
|
+
* could store a section whose `type` matches no renderer, which the homepage
|
|
15
|
+
* then skips in silence — a row that exists, occupies an order slot, and draws
|
|
16
|
+
* nothing.
|
|
17
|
+
*
|
|
18
|
+
* All three now agree on `homepageSectionTypeSchema`, which is derived from
|
|
19
|
+
* the `SectionType` union.
|
|
20
|
+
*/
|
|
5
21
|
export const createSectionSchema = z.object({
|
|
6
|
-
type:
|
|
22
|
+
type: homepageSectionTypeSchema,
|
|
7
23
|
enabled: z.boolean().default(true),
|
|
8
24
|
order: z.number().int().default(0),
|
|
9
25
|
config: z.object({}).passthrough().optional(),
|
|
10
26
|
});
|
|
27
|
+
/**
|
|
28
|
+
* The next free `order` value.
|
|
29
|
+
*
|
|
30
|
+
* `HomepageSectionCreateInput.order` is REQUIRED, and both API create routes
|
|
31
|
+
* need the same answer for "the caller did not choose one". Two copies of this
|
|
32
|
+
* query is how they would come to disagree about where a new section lands.
|
|
33
|
+
*/
|
|
34
|
+
export async function resolveNextSectionOrder() {
|
|
35
|
+
const latest = await homepageSectionsRepository.list({
|
|
36
|
+
sorts: sortBy(HOMEPAGE_SECTION_FIELDS.ORDER),
|
|
37
|
+
page: "1",
|
|
38
|
+
pageSize: "1",
|
|
39
|
+
});
|
|
40
|
+
const top = latest.items[0]?.order;
|
|
41
|
+
return typeof top === "number" ? top + 1 : 1;
|
|
42
|
+
}
|
|
11
43
|
export const updateSectionSchema = z.object({
|
|
12
44
|
order: z.number().int().optional(),
|
|
13
45
|
enabled: z.boolean().optional(),
|
|
@@ -2,6 +2,12 @@ import React from "react";
|
|
|
2
2
|
export declare function hashBannerMessage(msg: string): string;
|
|
3
3
|
export interface AnnouncementBarProps {
|
|
4
4
|
message: string;
|
|
5
|
+
/**
|
|
6
|
+
* Optional destination for the message. The admin editor has collected this
|
|
7
|
+
* (and `backgroundColor`) since it was built, but neither was ever rendered —
|
|
8
|
+
* so both were silently discarded on save. Wired 2026-08-24.
|
|
9
|
+
*/
|
|
10
|
+
link?: string;
|
|
5
11
|
className?: string;
|
|
6
12
|
/** Called when the user dismisses — consumer wires this to a server action to persist. */
|
|
7
13
|
onDismiss?: (hash: string) => void;
|
|
@@ -14,4 +20,4 @@ export interface AnnouncementBarProps {
|
|
|
14
20
|
*/
|
|
15
21
|
overlay?: boolean;
|
|
16
22
|
}
|
|
17
|
-
export declare function AnnouncementBar({ message, className, onDismiss, overlay }: AnnouncementBarProps): React.JSX.Element | null;
|
|
23
|
+
export declare function AnnouncementBar({ message, link, className, onDismiss, overlay }: AnnouncementBarProps): React.JSX.Element | null;
|
|
@@ -5,7 +5,7 @@ import { useState, useEffect } from "react";
|
|
|
5
5
|
import { X } from "lucide-react";
|
|
6
6
|
import { useAuth } from "../../../react/contexts/SessionContext";
|
|
7
7
|
import { Div } from "../../../ui/components/Div";
|
|
8
|
-
import { IconButton, Row, Span } from "@mohasinac/appkit/client";
|
|
8
|
+
import { IconButton, Row, Span, TextLink } from "@mohasinac/appkit/client";
|
|
9
9
|
const STORAGE_KEY = "letitrip:announcement-dismissed";
|
|
10
10
|
const ONE_WEEK_MS = 7 * 24 * 60 * 60 * 1000;
|
|
11
11
|
export function hashBannerMessage(msg) {
|
|
@@ -38,7 +38,7 @@ function saveLocalDismissal(message) {
|
|
|
38
38
|
void normalizeError(_err); /* quota exceeded — ignore */
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
|
-
export function AnnouncementBar({ message, className = "", onDismiss, overlay = false }) {
|
|
41
|
+
export function AnnouncementBar({ message, link, className = "", onDismiss, overlay = false }) {
|
|
42
42
|
const { user } = useAuth();
|
|
43
43
|
const bannerHash = hashBannerMessage(message);
|
|
44
44
|
const userAlreadyDismissed = !!user?.dismissedBannerHash && user.dismissedBannerHash === bannerHash;
|
|
@@ -58,7 +58,7 @@ export function AnnouncementBar({ message, className = "", onDismiss, overlay =
|
|
|
58
58
|
const positionCls = overlay
|
|
59
59
|
? "absolute inset-x-0 top-0 z-20 bg-primary-700/85 backdrop-blur-sm"
|
|
60
60
|
: "relative left-1/2 right-1/2 w-screen -translate-x-1/2 bg-primary-700";
|
|
61
|
-
return (_jsx(Div, { className: `${positionCls} transition-opacity duration-200 ${mounted ? "opacity-100" : "opacity-0"} ${className}`, role: "banner", children: _jsx(Div, { paddingX: "x-page", className: "container mx-auto max-w-[1920px]", children: _jsxs(Row, { textWeight: "medium", textSize: "sm", className: "relative text-left text-white", padding: "y-xs", align: "center", justify: "start", children: [_jsx(Span, { children: message }), _jsx(IconButton, { type: "button", onClick: () => {
|
|
61
|
+
return (_jsx(Div, { className: `${positionCls} transition-opacity duration-200 ${mounted ? "opacity-100" : "opacity-0"} ${className}`, role: "banner", children: _jsx(Div, { paddingX: "x-page", className: "container mx-auto max-w-[1920px]", children: _jsxs(Row, { textWeight: "medium", textSize: "sm", className: "relative text-left text-white", padding: "y-xs", align: "center", justify: "start", children: [link ? (_jsx(TextLink, { href: link, className: "text-white underline", children: message })) : (_jsx(Span, { children: message })), _jsx(IconButton, { type: "button", onClick: () => {
|
|
62
62
|
saveLocalDismissal(message);
|
|
63
63
|
onDismiss?.(bannerHash);
|
|
64
64
|
setDismissed(true);
|
|
@@ -6,10 +6,12 @@ import { carouselRepository, faqsRepository, siteSettingsRepository } from "../.
|
|
|
6
6
|
import { fetchLiveStats } from "../lib/live-stats";
|
|
7
7
|
import { renderSection, AnnouncementBar } from "../lib/section-renderer";
|
|
8
8
|
import { homepageSectionsRepository } from "../repository/homepage-sections.repository";
|
|
9
|
+
import { filterSectionsByFeatureFlags } from "../../../_internal/shared/features/homepage/section-gate";
|
|
9
10
|
import { getFeaturedProducts, getFeaturedAuctions, getFeaturedPreOrders } from "../../products/actions/product-actions";
|
|
10
11
|
import { listTopLevelCategories, listBrandCategories } from "../../categories/actions/category-actions";
|
|
11
12
|
import { listFeaturedBundles } from "../../../_internal/server/features/bundles/data";
|
|
12
13
|
import { listStores } from "../../stores/actions/store-query-actions";
|
|
14
|
+
import { toStoreListItem } from "../../../_internal/server/features/stores/adapters";
|
|
13
15
|
import { getFeaturedBlogPosts } from "../../blog/actions/blog-actions";
|
|
14
16
|
import { listPublicEvents } from "../../events/actions/event-actions";
|
|
15
17
|
/**
|
|
@@ -31,10 +33,14 @@ export async function MarketplaceHomepageView({ adSlots, newsletterFormSlot, onB
|
|
|
31
33
|
const announcementMessage = siteSettings?.announcementBar?.message?.trim() ||
|
|
32
34
|
"🎉 Up to 15% Off on Pokémon TCG this week — Use code SAVE15";
|
|
33
35
|
const showAnnouncement = siteSettings?.announcementBar?.enabled ?? true;
|
|
34
|
-
const [
|
|
36
|
+
const [allSections, rawFaqItems] = await Promise.all([
|
|
35
37
|
homepageSectionsRepository.getEnabledSections().catch(() => []),
|
|
36
38
|
faqsRepository.getHomepageFAQs().catch(() => []),
|
|
37
39
|
]);
|
|
40
|
+
// Respect the feature flags. This gate existed but lived inside a function
|
|
41
|
+
// with no call sites, so until 2026-08-24 turning off `auctions` hid auctions
|
|
42
|
+
// everywhere EXCEPT the homepage, which went on advertising them.
|
|
43
|
+
const enabledSections = filterSectionsByFeatureFlags(allSections, siteSettings?.featureFlags);
|
|
38
44
|
// Collect live metric requests from all enabled stats sections
|
|
39
45
|
const liveStatRequests = [];
|
|
40
46
|
for (const section of enabledSections) {
|
|
@@ -74,9 +80,13 @@ export async function MarketplaceHomepageView({ adSlots, newsletterFormSlot, onB
|
|
|
74
80
|
// Determine which data-driven section types are active so we only fetch what's needed
|
|
75
81
|
const activeTypes = new Set(orderedSections.map((s) => s.type));
|
|
76
82
|
const [productsResult, auctionsResult, preOrdersResult, categoriesResult, brandsResult, bundlesResult, storesResult, blogResult, eventsResult,] = await Promise.all([
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
83
|
+
// No `.catch(() => null)` on these three: they go through
|
|
84
|
+
// `listPublicProducts`, which already logs a failed query loudly and
|
|
85
|
+
// returns an empty result. Swallowing here would make a broken query
|
|
86
|
+
// indistinguishable from an empty catalogue (Root Cause #59).
|
|
87
|
+
activeTypes.has("products") ? getFeaturedProducts(12) : null,
|
|
88
|
+
activeTypes.has("auctions") ? getFeaturedAuctions(12) : null,
|
|
89
|
+
activeTypes.has("pre-orders") ? getFeaturedPreOrders(12) : null,
|
|
80
90
|
activeTypes.has("categories") ? listTopLevelCategories(12).catch(() => null) : null,
|
|
81
91
|
activeTypes.has("brands") ? listBrandCategories(12).catch(() => null) : null,
|
|
82
92
|
activeTypes.has("featured-bundles") ? listFeaturedBundles(8).catch(() => null) : null,
|
|
@@ -104,8 +114,12 @@ export async function MarketplaceHomepageView({ adSlots, newsletterFormSlot, onB
|
|
|
104
114
|
? brandsResult
|
|
105
115
|
: undefined,
|
|
106
116
|
bundles: bundlesResult?.length ? bundlesResult : undefined,
|
|
117
|
+
// Projected, NOT cast. FeaturedStoresSection is a Client Component and this
|
|
118
|
+
// value becomes its `initialItems`, so a raw StoreDocument here would be
|
|
119
|
+
// serialised into the homepage's public HTML — secrets included. Every
|
|
120
|
+
// other cast in this object maps a document that carries no secrets.
|
|
107
121
|
stores: storesResult?.items?.length
|
|
108
|
-
? storesResult.items
|
|
122
|
+
? storesResult.items.map((s) => toStoreListItem(s))
|
|
109
123
|
: undefined,
|
|
110
124
|
blog: blogResult?.length
|
|
111
125
|
? blogResult
|
|
@@ -115,5 +129,5 @@ export async function MarketplaceHomepageView({ adSlots, newsletterFormSlot, onB
|
|
|
115
129
|
: undefined,
|
|
116
130
|
};
|
|
117
131
|
const carouselSlides = toCarouselSlides(slides);
|
|
118
|
-
return (_jsx(Main, { children: _jsxs(Div, { className: "relative", children: [showAnnouncement ? (_jsx(AnnouncementBar, { overlay: true, message: announcementMessage, onDismiss: onBannerDismiss })) : null, orderedSections.map((section) => renderSection(section, adSlots, newsletterFormSlot ?? null, faqItems, carouselSlides, liveStats, sectionData))] }) }));
|
|
132
|
+
return (_jsx(Main, { children: _jsxs(Div, { className: "relative", children: [showAnnouncement ? (_jsx(AnnouncementBar, { overlay: true, message: announcementMessage, link: siteSettings?.announcementBar?.link, onDismiss: onBannerDismiss })) : null, orderedSections.map((section) => renderSection(section, adSlots, newsletterFormSlot ?? null, faqItems, carouselSlides, liveStats, sectionData))] }) }));
|
|
119
133
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** How many cards a homepage carousel wants before it stops back-filling. */
|
|
2
|
+
export declare const MIN_HOMEPAGE_COUNT = 12;
|
|
3
|
+
export interface HomepageListingQuery {
|
|
4
|
+
listingType?: string;
|
|
5
|
+
brand?: string;
|
|
6
|
+
featured?: boolean;
|
|
7
|
+
isPromoted?: boolean;
|
|
8
|
+
sorts?: string;
|
|
9
|
+
pageSize: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Always sends `availability=available`. The API treats an ABSENT value as
|
|
13
|
+
* "all" so that non-browse callers are unaffected — which means omitting it
|
|
14
|
+
* here is precisely how a homepage strip starts showing dead listings again.
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildHomepageListingQuery(input: HomepageListingQuery): string;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* WHY: The three homepage listing hooks each hand-wrote a pre-URL-encoded
|
|
3
|
+
* `filters=` Sieve string — `listingType%3D%3Dauction%2Cstatus%3D%3D…`.
|
|
4
|
+
* Unreadable, unreviewable, and each one silently omitted any liveness
|
|
5
|
+
* bound, so all three showed sold-out / ended / closed rows. Worse, they
|
|
6
|
+
* run AFTER the SSR paint and replace it, so a fix to the server half
|
|
7
|
+
* alone would have been undone 30 seconds later (Root Cause #30).
|
|
8
|
+
*
|
|
9
|
+
* WHAT: Build the query string from the same TYPED params
|
|
10
|
+
* `parsePublicProductParams` reads on the other side, so a homepage
|
|
11
|
+
* strip asks precisely what its SSR counterpart asked.
|
|
12
|
+
*
|
|
13
|
+
* EXPORTS: buildHomepageListingQuery, HomepageListingQuery, MIN_HOMEPAGE_COUNT
|
|
14
|
+
*
|
|
15
|
+
* @tag domain:homepage
|
|
16
|
+
* @tag layer:hook
|
|
17
|
+
* @tag pattern:none
|
|
18
|
+
* @tag access:client
|
|
19
|
+
* @tag consumers:useFeaturedAuctions,useFeaturedPreOrders,useFeaturedProducts
|
|
20
|
+
* @tag sideEffects:none
|
|
21
|
+
*/
|
|
22
|
+
import { AVAILABILITY_VALUES } from "../../../constants/field-names";
|
|
23
|
+
/** How many cards a homepage carousel wants before it stops back-filling. */
|
|
24
|
+
export const MIN_HOMEPAGE_COUNT = 12;
|
|
25
|
+
/**
|
|
26
|
+
* Always sends `availability=available`. The API treats an ABSENT value as
|
|
27
|
+
* "all" so that non-browse callers are unaffected — which means omitting it
|
|
28
|
+
* here is precisely how a homepage strip starts showing dead listings again.
|
|
29
|
+
*/
|
|
30
|
+
export function buildHomepageListingQuery(input) {
|
|
31
|
+
const sp = new URLSearchParams();
|
|
32
|
+
sp.set("availability", AVAILABILITY_VALUES.AVAILABLE);
|
|
33
|
+
if (input.listingType)
|
|
34
|
+
sp.set("listingType", input.listingType);
|
|
35
|
+
if (input.brand)
|
|
36
|
+
sp.set("brand", input.brand);
|
|
37
|
+
if (input.featured)
|
|
38
|
+
sp.set("featured", "true");
|
|
39
|
+
if (input.isPromoted)
|
|
40
|
+
sp.set("isPromoted", "true");
|
|
41
|
+
if (input.sorts)
|
|
42
|
+
sp.set("sorts", input.sorts);
|
|
43
|
+
sp.set("pageSize", String(input.pageSize));
|
|
44
|
+
return sp.toString();
|
|
45
|
+
}
|
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import type { ProductItem } from "../../products/types";
|
|
2
|
+
/**
|
|
3
|
+
* The soonest-ending LIVE auctions, for the homepage strip.
|
|
4
|
+
*
|
|
5
|
+
* This runs 30s after the SSR paint and REPLACES it, so it has to ask the
|
|
6
|
+
* server exactly what `getFeaturedAuctions` asked. It did not: both queries
|
|
7
|
+
* here were `listingType==auction,status==published` with no end-date bound,
|
|
8
|
+
* hand-written as a raw pre-encoded `filters=` string. So even once the SSR
|
|
9
|
+
* half was fixed, the strip would have reverted to showing expired auctions
|
|
10
|
+
* half a minute later (Root Cause #30).
|
|
11
|
+
*/
|
|
2
12
|
export declare function useFeaturedAuctions(options?: {
|
|
3
13
|
filterByBrand?: string;
|
|
4
14
|
initialData?: ProductItem[];
|
|
@@ -1,21 +1,41 @@
|
|
|
1
1
|
import { useQuery } from "@tanstack/react-query";
|
|
2
2
|
import { apiClient } from "../../../http";
|
|
3
3
|
import { PRODUCT_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
4
|
-
|
|
4
|
+
import { buildHomepageListingQuery, MIN_HOMEPAGE_COUNT } from "./homepage-query";
|
|
5
|
+
import { sortBy } from "../../../constants/sort";
|
|
6
|
+
import { PRODUCT_FIELDS } from "../../../constants/field-names";
|
|
7
|
+
/**
|
|
8
|
+
* The soonest-ending LIVE auctions, for the homepage strip.
|
|
9
|
+
*
|
|
10
|
+
* This runs 30s after the SSR paint and REPLACES it, so it has to ask the
|
|
11
|
+
* server exactly what `getFeaturedAuctions` asked. It did not: both queries
|
|
12
|
+
* here were `listingType==auction,status==published` with no end-date bound,
|
|
13
|
+
* hand-written as a raw pre-encoded `filters=` string. So even once the SSR
|
|
14
|
+
* half was fixed, the strip would have reverted to showing expired auctions
|
|
15
|
+
* half a minute later (Root Cause #30).
|
|
16
|
+
*/
|
|
5
17
|
export function useFeaturedAuctions(options) {
|
|
6
|
-
const brandFilter = options?.filterByBrand
|
|
7
|
-
? `%2Cbrand%3D%3D${encodeURIComponent(options.filterByBrand)}`
|
|
8
|
-
: "";
|
|
9
18
|
return useQuery({
|
|
10
19
|
queryKey: ["auctions", "featured", options?.filterByBrand ?? "all"],
|
|
11
20
|
initialData: options?.initialData,
|
|
12
21
|
queryFn: async () => {
|
|
13
|
-
const promotedRes = await apiClient.get(`${PRODUCT_ENDPOINTS.LIST}
|
|
22
|
+
const promotedRes = await apiClient.get(`${PRODUCT_ENDPOINTS.LIST}?${buildHomepageListingQuery({
|
|
23
|
+
listingType: "auction",
|
|
24
|
+
brand: options?.filterByBrand,
|
|
25
|
+
isPromoted: true,
|
|
26
|
+
sorts: sortBy(PRODUCT_FIELDS.AUCTION_END_DATE, "ASC"),
|
|
27
|
+
pageSize: 18,
|
|
28
|
+
})}`);
|
|
14
29
|
const promoted = promotedRes?.items ?? [];
|
|
15
|
-
if (promoted.length >=
|
|
30
|
+
if (promoted.length >= MIN_HOMEPAGE_COUNT)
|
|
16
31
|
return promoted;
|
|
17
|
-
const remaining =
|
|
18
|
-
const latestRes = await apiClient.get(`${PRODUCT_ENDPOINTS.LIST}
|
|
32
|
+
const remaining = MIN_HOMEPAGE_COUNT - promoted.length;
|
|
33
|
+
const latestRes = await apiClient.get(`${PRODUCT_ENDPOINTS.LIST}?${buildHomepageListingQuery({
|
|
34
|
+
listingType: "auction",
|
|
35
|
+
brand: options?.filterByBrand,
|
|
36
|
+
sorts: sortBy(PRODUCT_FIELDS.AUCTION_END_DATE, "ASC"),
|
|
37
|
+
pageSize: remaining + promoted.length,
|
|
38
|
+
})}`);
|
|
19
39
|
const latest = latestRes?.items ?? [];
|
|
20
40
|
const existingIds = new Set(promoted.map((a) => a.id));
|
|
21
41
|
const filler = latest
|
|
@@ -1,21 +1,30 @@
|
|
|
1
1
|
import { useQuery } from "@tanstack/react-query";
|
|
2
2
|
import { apiClient } from "../../../http";
|
|
3
3
|
import { PRODUCT_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
4
|
-
|
|
4
|
+
import { buildHomepageListingQuery, MIN_HOMEPAGE_COUNT } from "./homepage-query";
|
|
5
|
+
import { sortBy } from "../../../constants/sort";
|
|
6
|
+
import { PRODUCT_FIELDS } from "../../../constants/field-names";
|
|
5
7
|
export function useFeaturedPreOrders(options) {
|
|
6
|
-
const brandFilter = options?.filterByBrand
|
|
7
|
-
? `%2Cbrand%3D%3D${encodeURIComponent(options.filterByBrand)}`
|
|
8
|
-
: "";
|
|
9
8
|
return useQuery({
|
|
10
9
|
queryKey: ["pre-orders", "featured", options?.filterByBrand ?? "all"],
|
|
11
10
|
initialData: options?.initialData,
|
|
12
11
|
queryFn: async () => {
|
|
13
|
-
const featuredRes = await apiClient.get(`${PRODUCT_ENDPOINTS.LIST}
|
|
12
|
+
const featuredRes = await apiClient.get(`${PRODUCT_ENDPOINTS.LIST}?${buildHomepageListingQuery({
|
|
13
|
+
listingType: "pre-order",
|
|
14
|
+
brand: options?.filterByBrand,
|
|
15
|
+
sorts: sortBy(PRODUCT_FIELDS.PRE_ORDER_DELIVERY_DATE, "ASC"),
|
|
16
|
+
pageSize: 6,
|
|
17
|
+
})}`);
|
|
14
18
|
const featured = featuredRes?.items ?? [];
|
|
15
|
-
if (featured.length >=
|
|
19
|
+
if (featured.length >= MIN_HOMEPAGE_COUNT)
|
|
16
20
|
return featured;
|
|
17
|
-
const remaining =
|
|
18
|
-
const latestRes = await apiClient.get(`${PRODUCT_ENDPOINTS.LIST}
|
|
21
|
+
const remaining = MIN_HOMEPAGE_COUNT - featured.length;
|
|
22
|
+
const latestRes = await apiClient.get(`${PRODUCT_ENDPOINTS.LIST}?${buildHomepageListingQuery({
|
|
23
|
+
listingType: "pre-order",
|
|
24
|
+
brand: options?.filterByBrand,
|
|
25
|
+
sorts: sortBy(PRODUCT_FIELDS.CREATED_AT, "DESC"),
|
|
26
|
+
pageSize: remaining + featured.length,
|
|
27
|
+
})}`);
|
|
19
28
|
const latest = latestRes?.items ?? [];
|
|
20
29
|
const existingIds = new Set(featured.map((p) => p.id));
|
|
21
30
|
const filler = latest
|
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
import { useQuery } from "@tanstack/react-query";
|
|
2
2
|
import { apiClient } from "../../../http";
|
|
3
3
|
import { PRODUCT_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
4
|
-
|
|
4
|
+
import { buildHomepageListingQuery, MIN_HOMEPAGE_COUNT } from "./homepage-query";
|
|
5
|
+
import { sortBy } from "../../../constants/sort";
|
|
6
|
+
import { PRODUCT_FIELDS } from "../../../constants/field-names";
|
|
5
7
|
export function useFeaturedProducts(options) {
|
|
6
|
-
const brandFilter = options?.filterByBrand
|
|
7
|
-
? `%2Cbrand%3D%3D${encodeURIComponent(options.filterByBrand)}`
|
|
8
|
-
: "";
|
|
9
8
|
return useQuery({
|
|
10
9
|
queryKey: ["products", "featured", options?.filterByBrand ?? "all"],
|
|
11
10
|
queryFn: async () => {
|
|
12
|
-
const promotedRes = await apiClient.get(`${PRODUCT_ENDPOINTS.LIST}
|
|
11
|
+
const promotedRes = await apiClient.get(`${PRODUCT_ENDPOINTS.LIST}?${buildHomepageListingQuery({
|
|
12
|
+
brand: options?.filterByBrand,
|
|
13
|
+
isPromoted: true,
|
|
14
|
+
pageSize: 18,
|
|
15
|
+
})}`);
|
|
13
16
|
const promoted = promotedRes?.items ?? [];
|
|
14
|
-
if (promoted.length >=
|
|
17
|
+
if (promoted.length >= MIN_HOMEPAGE_COUNT)
|
|
15
18
|
return promotedRes;
|
|
16
|
-
const remaining =
|
|
17
|
-
const latestRes = await apiClient.get(`${PRODUCT_ENDPOINTS.LIST}
|
|
19
|
+
const remaining = MIN_HOMEPAGE_COUNT - promoted.length;
|
|
20
|
+
const latestRes = await apiClient.get(`${PRODUCT_ENDPOINTS.LIST}?${buildHomepageListingQuery({
|
|
21
|
+
brand: options?.filterByBrand,
|
|
22
|
+
sorts: sortBy(PRODUCT_FIELDS.CREATED_AT, "DESC"),
|
|
23
|
+
pageSize: remaining + promoted.length,
|
|
24
|
+
})}`);
|
|
18
25
|
const latest = latestRes?.items ?? [];
|
|
19
26
|
const existingIds = new Set(promoted.map((p) => p.id));
|
|
20
27
|
const filler = latest
|
|
@@ -47,6 +47,37 @@ export declare const homepageSectionFirestoreSchema: z.ZodObject<{
|
|
|
47
47
|
order: number;
|
|
48
48
|
config: Record<string, JsonValue>;
|
|
49
49
|
}>;
|
|
50
|
+
/**
|
|
51
|
+
* The create contract for a homepage section, shared by BOTH routes that can
|
|
52
|
+
* create one — `POST /api/admin/sections` (what the editor calls) and
|
|
53
|
+
* `POST /api/homepage-sections` (reachable by URL only).
|
|
54
|
+
*
|
|
55
|
+
* It exists because those two had drifted into being one validated path and
|
|
56
|
+
* one raw `{...body}` spread, and because the validated one's hand-written
|
|
57
|
+
* type list had fallen four values behind `SectionType` — so an admin could
|
|
58
|
+
* configure a Featured Bundles / Prize Draws / Event Raffles / Collection
|
|
59
|
+
* Cards section in full and get a 400 on save.
|
|
60
|
+
*
|
|
61
|
+
* `type` comes from `homepageSectionTypeSchema`, which is derived from the
|
|
62
|
+
* union, so that gap cannot reopen.
|
|
63
|
+
*/
|
|
64
|
+
export declare const homepageSectionCreateSchema: z.ZodObject<{
|
|
65
|
+
type: z.ZodEnum<["welcome", "carousel", "stats", "trust-indicators", "categories", "brands", "products", "pre-orders", "auctions", "banner", "features", "reviews", "whatsapp-community", "faq", "blog-articles", "newsletter", "stores", "events", "social-feed", "custom-cards", "google-reviews", "featured-bundles", "prize-draws", "event-raffles", "collection-cards"]>;
|
|
66
|
+
enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
67
|
+
order: z.ZodOptional<z.ZodNumber>;
|
|
68
|
+
config: z.ZodRecord<z.ZodString, z.ZodType<JsonValue, z.ZodTypeDef, JsonValue>>;
|
|
69
|
+
}, "strip", z.ZodTypeAny, {
|
|
70
|
+
type: "banner" | "stores" | "products" | "pre-orders" | "prize-draws" | "auctions" | "reviews" | "events" | "categories" | "brands" | "carousel" | "newsletter" | "features" | "stats" | "welcome" | "trust-indicators" | "whatsapp-community" | "faq" | "blog-articles" | "social-feed" | "custom-cards" | "google-reviews" | "featured-bundles" | "event-raffles" | "collection-cards";
|
|
71
|
+
enabled: boolean;
|
|
72
|
+
config: Record<string, JsonValue>;
|
|
73
|
+
order?: number | undefined;
|
|
74
|
+
}, {
|
|
75
|
+
type: "banner" | "stores" | "products" | "pre-orders" | "prize-draws" | "auctions" | "reviews" | "events" | "categories" | "brands" | "carousel" | "newsletter" | "features" | "stats" | "welcome" | "trust-indicators" | "whatsapp-community" | "faq" | "blog-articles" | "social-feed" | "custom-cards" | "google-reviews" | "featured-bundles" | "event-raffles" | "collection-cards";
|
|
76
|
+
config: Record<string, JsonValue>;
|
|
77
|
+
enabled?: boolean | undefined;
|
|
78
|
+
order?: number | undefined;
|
|
79
|
+
}>;
|
|
80
|
+
export type HomepageSectionCreateValues = z.infer<typeof homepageSectionCreateSchema>;
|
|
50
81
|
export declare const carouselBackgroundSchema: z.ZodObject<{
|
|
51
82
|
type: z.ZodEnum<["image", "video", "color", "gradient"]>;
|
|
52
83
|
url: z.ZodOptional<z.ZodString>;
|
|
@@ -720,6 +751,7 @@ export declare const carouselSlideFirestoreSchema: z.ZodObject<{
|
|
|
720
751
|
}, z.ZodTypeAny, "passthrough">;
|
|
721
752
|
active: boolean;
|
|
722
753
|
order: number;
|
|
754
|
+
createdBy: string;
|
|
723
755
|
cards: {
|
|
724
756
|
id: string;
|
|
725
757
|
background: {
|
|
@@ -762,7 +794,6 @@ export declare const carouselSlideFirestoreSchema: z.ZodObject<{
|
|
|
762
794
|
isButtonOnly?: boolean | undefined;
|
|
763
795
|
gridCol?: 3 | 1 | 2 | undefined;
|
|
764
796
|
}[];
|
|
765
|
-
createdBy: string;
|
|
766
797
|
link?: {
|
|
767
798
|
url: string;
|
|
768
799
|
openInNewTab: boolean;
|
|
@@ -829,6 +860,7 @@ export declare const carouselSlideFirestoreSchema: z.ZodObject<{
|
|
|
829
860
|
}, z.ZodTypeAny, "passthrough">;
|
|
830
861
|
active: boolean;
|
|
831
862
|
order: number;
|
|
863
|
+
createdBy: string;
|
|
832
864
|
cards: {
|
|
833
865
|
id: string;
|
|
834
866
|
background: {
|
|
@@ -871,7 +903,6 @@ export declare const carouselSlideFirestoreSchema: z.ZodObject<{
|
|
|
871
903
|
isButtonOnly?: boolean | undefined;
|
|
872
904
|
gridCol?: 3 | 1 | 2 | undefined;
|
|
873
905
|
}[];
|
|
874
|
-
createdBy: string;
|
|
875
906
|
link?: {
|
|
876
907
|
url: string;
|
|
877
908
|
openInNewTab: boolean;
|
|
@@ -56,6 +56,30 @@ export const homepageSectionFirestoreSchema = z.object({
|
|
|
56
56
|
config: z.record(z.string(), jsonValueSchema),
|
|
57
57
|
...auditTimestampsShape,
|
|
58
58
|
});
|
|
59
|
+
/**
|
|
60
|
+
* The create contract for a homepage section, shared by BOTH routes that can
|
|
61
|
+
* create one — `POST /api/admin/sections` (what the editor calls) and
|
|
62
|
+
* `POST /api/homepage-sections` (reachable by URL only).
|
|
63
|
+
*
|
|
64
|
+
* It exists because those two had drifted into being one validated path and
|
|
65
|
+
* one raw `{...body}` spread, and because the validated one's hand-written
|
|
66
|
+
* type list had fallen four values behind `SectionType` — so an admin could
|
|
67
|
+
* configure a Featured Bundles / Prize Draws / Event Raffles / Collection
|
|
68
|
+
* Cards section in full and get a 400 on save.
|
|
69
|
+
*
|
|
70
|
+
* `type` comes from `homepageSectionTypeSchema`, which is derived from the
|
|
71
|
+
* union, so that gap cannot reopen.
|
|
72
|
+
*/
|
|
73
|
+
export const homepageSectionCreateSchema = z.object({
|
|
74
|
+
type: homepageSectionTypeSchema,
|
|
75
|
+
enabled: z.boolean().optional().default(true),
|
|
76
|
+
order: z.number().int().optional(),
|
|
77
|
+
// Deliberately open. Every section type carries a different config shape,
|
|
78
|
+
// and a closed schema here would silently STRIP the builder's output for any
|
|
79
|
+
// type it did not enumerate — the `productBaseSchema` failure, one domain
|
|
80
|
+
// over.
|
|
81
|
+
config: z.record(z.string(), jsonValueSchema),
|
|
82
|
+
});
|
|
59
83
|
export const carouselBackgroundSchema = z.object({
|
|
60
84
|
type: z.enum(["image", "video", "color", "gradient"]),
|
|
61
85
|
url: z.string().optional(),
|