@mohasinac/appkit 4.13.0 → 4.14.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 +6 -0
- 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/checkout/actions.js +6 -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/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/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 +45 -9
- 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 +15 -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/blog/schema.d.ts +2 -2
- package/dist/_internal/shared/features/cart/schema.d.ts +12 -12
- 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 +32 -32
- 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 +66 -0
- package/dist/_internal/shared/history/history.js +158 -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 +7 -5
- package/dist/client.js +2 -2
- package/dist/constants/api-endpoints.d.ts +6 -0
- package/dist/constants/api-endpoints.js +2 -0
- package/dist/constants/field-names.d.ts +49 -2
- package/dist/constants/field-names.js +53 -2
- 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/UserOrdersView.js +7 -0
- 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/AdminClassifiedView.js +8 -3
- package/dist/features/admin/components/AdminDigitalCodesView.js +8 -3
- package/dist/features/admin/components/AdminFeatureFlagsView.js +1 -0
- package/dist/features/admin/components/AdminLiveView.js +8 -3
- package/dist/features/admin/components/AdminOffersView.d.ts +4 -0
- package/dist/features/admin/components/AdminOffersView.js +186 -0
- package/dist/features/admin/components/AdminOrdersView.js +10 -1
- package/dist/features/admin/components/AdminPrizeDrawsView.js +5 -0
- package/dist/features/admin/components/AdminProductsView.js +16 -29
- 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/index.d.ts +2 -0
- package/dist/features/admin/components/index.js +1 -0
- package/dist/features/admin/constants/filter-tabs.d.ts +86 -0
- package/dist/features/admin/constants/filter-tabs.js +55 -0
- package/dist/features/admin/schemas/firestore.d.ts +122 -3
- package/dist/features/admin/schemas/firestore.js +1 -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/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/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/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/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/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/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/index.d.ts +4 -4
- 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 +2 -2
- 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/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 +116 -22
- package/dist/features/orders/schemas/firestore.d.ts +117 -0
- package/dist/features/orders/schemas/firestore.js +30 -0
- package/dist/features/orders/schemas/index.d.ts +18 -18
- 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/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 +66 -66
- package/dist/features/products/schemas/product-features.validators.d.ts +6 -6
- 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/search/schemas/index.d.ts +4 -4
- package/dist/features/seller/actions/offer-actions.js +25 -2
- package/dist/features/seller/components/SellerArtView.js +5 -0
- package/dist/features/seller/components/SellerAuctionsView.js +13 -15
- package/dist/features/seller/components/SellerClassifiedView.js +5 -0
- package/dist/features/seller/components/SellerDigitalCodesView.js +5 -0
- package/dist/features/seller/components/SellerLiveView.js +5 -0
- package/dist/features/seller/components/SellerOrdersView.js +31 -9
- package/dist/features/seller/components/SellerPayoutSettingsView.js +19 -18
- 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 +73 -16
- package/dist/features/seller/repository/offer.repository.js +38 -3
- package/dist/features/seller/schemas/index.d.ts +2 -2
- package/dist/features/seller/schemas/offer-forms.d.ts +25 -0
- package/dist/features/seller/schemas/offer-forms.js +21 -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/entity-form.d.ts +109 -0
- package/dist/features/shell/entity-form.js +96 -0
- package/dist/features/shell/index.d.ts +4 -0
- package/dist/features/shell/index.js +2 -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 +105 -1
- package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
- package/dist/index.d.ts +13 -10
- package/dist/index.js +14 -9
- package/dist/next/routing/route-map.d.ts +7 -1
- package/dist/next/routing/route-map.js +5 -0
- 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/registry.d.ts +68 -68
- 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/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 +32 -27
- package/dist/seed/products-art-seed-data.js +50 -12
- package/dist/seed/products-auctions-seed-data.js +97 -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 +4 -3
- package/dist/server.js +8 -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/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 -2
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* WHY: The category tree the seed shipped was two levels deep with a single
|
|
3
|
+
* root — so `categoryType:"sublisting"` (documented as "tier-4 leaf groups
|
|
4
|
+
* under a parent category") was structurally unreachable, no page ever
|
|
5
|
+
* exercised a mid-tier rollup, and the three live-item products had no
|
|
6
|
+
* category at all because nothing in a Beyblade-only tree fit them.
|
|
7
|
+
* WHAT: The authoring literal for a 4-level, TWO-root forest. Structural fields
|
|
8
|
+
* (parentIds/ancestors/tier/path/position/subtreeSize/…) are derived by
|
|
9
|
+
* `buildCategoryTree`, never written here.
|
|
10
|
+
*
|
|
11
|
+
* EXPORTS:
|
|
12
|
+
* CATEGORY_FOREST — nested CategoryTreeNode[] consumed by categories-seed-data
|
|
13
|
+
*
|
|
14
|
+
* @tag domain:categories
|
|
15
|
+
* @tag layer:seed
|
|
16
|
+
* @tag pattern:derived
|
|
17
|
+
* @tag access:server-only
|
|
18
|
+
* @tag consumers:seed/categories-seed-data.ts
|
|
19
|
+
* @tag sideEffects:none
|
|
20
|
+
*/
|
|
21
|
+
import { seedExtMedia } from "./media";
|
|
22
|
+
const cover = (slug) => seedExtMedia(`https://picsum.photos/seed/category-image-${slug}-20260101/1200/600`);
|
|
23
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
24
|
+
// Root 1 — Spinning Tops. The Beyblade catalogue, four generations deep:
|
|
25
|
+
// generation -> part-family -> specific line
|
|
26
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
27
|
+
const SPINNING_TOPS = {
|
|
28
|
+
id: "category-spinning-tops",
|
|
29
|
+
name: "Spinning Tops",
|
|
30
|
+
description: "Collectible spinning tops and battle systems — Beyblade Original, Metal Fight, Burst, X, and the gear that goes with them.",
|
|
31
|
+
extra: {
|
|
32
|
+
isFeatured: true,
|
|
33
|
+
featuredPriority: 1,
|
|
34
|
+
showOnHomepage: true,
|
|
35
|
+
display: { icon: "🌀", coverImage: cover("spinning-tops"), color: "#0891b2", showInMenu: true, showInFooter: true },
|
|
36
|
+
highlights: [
|
|
37
|
+
"Every era of Beyblade in one place — Original, Metal Fight, Burst, and X",
|
|
38
|
+
"Verified sellers with condition-graded listings",
|
|
39
|
+
"Auctions, pre-orders, and prize draws alongside straightforward buy-now listings",
|
|
40
|
+
],
|
|
41
|
+
faqs: [
|
|
42
|
+
{ question: "What's the difference between the four Beyblade generations?", answer: "Original (1999-2003) started the franchise with ripcord launchers; Metal Fight (2008-2013) added metal-weighted tops; Burst (2015-present) introduced tops that burst apart on hard hits; X (2023-present) uses the new Xtreme Gear system with clip-on parts." },
|
|
43
|
+
{ question: "Are used tops sold here safe to battle with?", answer: "Every listing shows a condition rating (New/Like New/Good/Used) and sellers are expected to disclose any chips or cracks — check the condition badge and item photos before buying." },
|
|
44
|
+
],
|
|
45
|
+
seo: { title: "Spinning Tops | LetItRip", description: "Buy Beyblade and spinning tops — Original, Metal Fight, Burst, X, and accessories.", keywords: ["beyblade", "spinning tops", "beyblade x", "beyblade burst"] },
|
|
46
|
+
},
|
|
47
|
+
children: [
|
|
48
|
+
{
|
|
49
|
+
id: "category-beyblade-original",
|
|
50
|
+
name: "Beyblade Original",
|
|
51
|
+
description: "The original Beyblade series (1999–2003) by Takara — Plastic Generation tops, Engine Gear, HMS, and the launchers that started the franchise.",
|
|
52
|
+
extra: {
|
|
53
|
+
display: { icon: "🪀", coverImage: cover("beyblade-original"), color: "#b45309", showInMenu: true, showInFooter: false },
|
|
54
|
+
highlights: [
|
|
55
|
+
"The tops that started it all in 1999",
|
|
56
|
+
"Ripcord launcher compatible with the full original-series lineup",
|
|
57
|
+
"A favourite among vintage collectors — sealed pieces command a premium",
|
|
58
|
+
],
|
|
59
|
+
faqs: [
|
|
60
|
+
{ question: "Will an original-series top work with a Burst or X launcher?", answer: "No — each generation uses its own launcher and ripcord system. Original-series tops need an original-series launcher." },
|
|
61
|
+
{ question: "How do I tell a genuine Takara release from a reprint?", answer: "Check the sticker finish and base stamp under good lighting — sellers with vintage-collectible tagged listings usually note authentication details in the description." },
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
children: [
|
|
65
|
+
{
|
|
66
|
+
id: "category-original-tops",
|
|
67
|
+
name: "Original Tops",
|
|
68
|
+
description: "Complete original-series Beyblades, from the first Plastic Generation releases through HMS.",
|
|
69
|
+
children: [
|
|
70
|
+
{ id: "category-original-plastic-gen", name: "Plastic Generation", description: "The 1999–2002 plastic-series tops — the first four seasons of the franchise." },
|
|
71
|
+
{ id: "category-original-hms", name: "Heavy Metal System", description: "The 2003 HMS line, the last and heaviest of the original generation." },
|
|
72
|
+
],
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
id: "category-original-launchers",
|
|
76
|
+
name: "Original Launchers",
|
|
77
|
+
description: "Ripcord launchers, grips and winders for original-series tops.",
|
|
78
|
+
children: [
|
|
79
|
+
{ id: "category-original-ripcord-launchers", name: "Ripcord Launchers", description: "The classic pull-cord launchers used across the original series." },
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
id: "category-beyblade-metal",
|
|
86
|
+
name: "Beyblade Metal Fight",
|
|
87
|
+
description: "The Metal Fight era — Metal Fusion, Metal Masters, Metal Fury and Zero-G. Metal-weighted tops and their swappable part system.",
|
|
88
|
+
extra: {
|
|
89
|
+
display: { icon: "⚙️", coverImage: cover("beyblade-metal"), color: "#64748b", showInMenu: true, showInFooter: false },
|
|
90
|
+
highlights: [
|
|
91
|
+
"Metal-weighted tops for serious attack and defense power",
|
|
92
|
+
"Covers all four Metal Fight sub-generations: Fusion, Masters, Fury, Zero-G",
|
|
93
|
+
"Popular with tournament players for their heavier base weight",
|
|
94
|
+
],
|
|
95
|
+
faqs: [
|
|
96
|
+
{ question: "What does the code after a top's name mean (e.g. \"105RF\")?", answer: "It's the track height and bottom type — 105RF means a 105-height track with a Rubber Flat bottom. Swapping tracks and bottoms lets you tune stamina vs. attack." },
|
|
97
|
+
{ question: "Can Metal Fight tops battle Burst tops in the same stadium?", answer: "Physically yes if the stadium size matches, but they don't burst apart on impact the way Burst tops do — most local groups keep the generations separate for fair play." },
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
children: [
|
|
101
|
+
{
|
|
102
|
+
id: "category-metal-tops",
|
|
103
|
+
name: "Metal Fight Tops",
|
|
104
|
+
description: "Complete Metal Fight Beyblades across all four sub-generations.",
|
|
105
|
+
children: [
|
|
106
|
+
{ id: "category-metal-fusion", name: "Metal Fusion", description: "The 2008 debut wave that introduced the metal-wheel system." },
|
|
107
|
+
{ id: "category-metal-masters", name: "Metal Masters", description: "The 4D-precursor wave, with heavier fusion wheels and tighter tolerances." },
|
|
108
|
+
{ id: "category-metal-fury", name: "Metal Fury", description: "The 4D System wave — multi-mode wheels and switchable bottoms." },
|
|
109
|
+
],
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
id: "category-metal-parts",
|
|
113
|
+
name: "Metal Fight Parts",
|
|
114
|
+
description: "Individual face bolts, energy rings, tracks and tips for building custom Metal Fight combos.",
|
|
115
|
+
children: [
|
|
116
|
+
{ id: "category-metal-energy-rings", name: "Energy Rings", description: "The clear upper ring that sets a Metal Fight top's spin balance." },
|
|
117
|
+
{ id: "category-metal-tracks-tips", name: "Tracks & Tips", description: "Spin tracks and performance tips — the height and floor contact of a build." },
|
|
118
|
+
],
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
id: "category-beyblade-burst",
|
|
124
|
+
name: "Beyblade Burst",
|
|
125
|
+
description: "Beyblade Burst by Takara-Tomy and Hasbro — tops that burst apart on impact, with swappable Layer / Disc / Driver parts.",
|
|
126
|
+
extra: {
|
|
127
|
+
isFeatured: true,
|
|
128
|
+
display: { icon: "💥", coverImage: cover("beyblade-burst"), color: "#059669", showInMenu: true, showInFooter: false },
|
|
129
|
+
highlights: [
|
|
130
|
+
"Tops that burst apart on a hard enough hit — a whole new battle mechanic",
|
|
131
|
+
"Swappable Layer / Disc / Driver parts for build customization",
|
|
132
|
+
"The most actively traded generation on the platform",
|
|
133
|
+
],
|
|
134
|
+
faqs: [
|
|
135
|
+
{ question: "What's the difference between a Layer, Disc and Driver?", answer: "Layer is the top piece (attack profile), Disc sits underneath it (weight/stamina), Driver is the tip that touches the stadium floor (spin behaviour). Mixing and matching lets you build custom combos." },
|
|
136
|
+
{ question: "Is a burst during battle bad for the top?", answer: "No — Burst tops are designed to separate on hard impacts as the game's core mechanic, then click back together for the next battle." },
|
|
137
|
+
],
|
|
138
|
+
},
|
|
139
|
+
children: [
|
|
140
|
+
{
|
|
141
|
+
id: "category-burst-tops",
|
|
142
|
+
name: "Burst Tops",
|
|
143
|
+
description: "Complete Burst-system Beyblades across every Burst wave.",
|
|
144
|
+
children: [
|
|
145
|
+
{ id: "category-burst-classic", name: "Burst Classic", description: "The original 2015–2017 Burst waves, before the Cho-Z metal upgrade." },
|
|
146
|
+
{ id: "category-burst-cho-z", name: "Cho-Z", description: "The metal-layer Cho-Z wave — heavier layers and much higher burst resistance." },
|
|
147
|
+
{ id: "category-burst-superking", name: "Superking", description: "The Sparking / Superking wave with its five-sided ratchet and chip system." },
|
|
148
|
+
],
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
id: "category-burst-parts",
|
|
152
|
+
name: "Burst Parts",
|
|
153
|
+
description: "Individual Layers, Discs and Drivers for building custom Burst combos.",
|
|
154
|
+
children: [
|
|
155
|
+
{ id: "category-burst-layers", name: "Layers", description: "The top piece — sets a Burst combo's attack profile and burst resistance." },
|
|
156
|
+
{ id: "category-burst-discs", name: "Discs", description: "The middle weight component, tuning stamina and balance." },
|
|
157
|
+
{ id: "category-burst-drivers", name: "Drivers", description: "The floor-contact tip that decides how a Burst combo moves." },
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
id: "category-beyblade-x",
|
|
164
|
+
name: "Beyblade X",
|
|
165
|
+
description: "Beyblade X by Takara-Tomy — the current generation, built around the Xtreme Gear system and its Blade / Ratchet / Bit parts.",
|
|
166
|
+
extra: {
|
|
167
|
+
isFeatured: true,
|
|
168
|
+
display: { icon: "💫", coverImage: cover("beyblade-x"), color: "#0d9488", showInMenu: true, showInFooter: false },
|
|
169
|
+
highlights: [
|
|
170
|
+
"The newest generation — Xtreme Gear system launched in 2023",
|
|
171
|
+
"Faster clip-on part swaps than any previous generation",
|
|
172
|
+
"Actively growing tournament scene with new waves releasing regularly",
|
|
173
|
+
],
|
|
174
|
+
faqs: [
|
|
175
|
+
{ question: "Do I need new stadiums for Beyblade X?", answer: "X-format tops battle best in the wider X-format stadiums, though many X tops still spin in older round stadiums — check a listing's description for stadium compatibility notes." },
|
|
176
|
+
{ question: "What does the Blade / Ratchet / Bit naming mean?", answer: "Beyblade X renamed the part system — Blade (top piece), Ratchet (middle, sets height), Bit (bottom tip) — functionally similar to Burst's Layer/Disc/Driver but not physically interchangeable with them." },
|
|
177
|
+
],
|
|
178
|
+
},
|
|
179
|
+
children: [
|
|
180
|
+
{
|
|
181
|
+
id: "category-x-tops",
|
|
182
|
+
name: "Beyblade X Tops",
|
|
183
|
+
description: "Complete Beyblade X tops — starters and boosters.",
|
|
184
|
+
children: [
|
|
185
|
+
{ id: "category-x-starters", name: "Starter Sets", description: "Top plus launcher — the entry point into the X format." },
|
|
186
|
+
{ id: "category-x-boosters", name: "Boosters", description: "Top-only releases for players who already own a launcher." },
|
|
187
|
+
],
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
id: "category-x-parts",
|
|
191
|
+
name: "Beyblade X Parts",
|
|
192
|
+
description: "Individual Blades, Ratchets and Bits for custom X builds.",
|
|
193
|
+
children: [
|
|
194
|
+
{ id: "category-x-blades", name: "Blades", description: "The upper piece that defines an X combo's attack shape." },
|
|
195
|
+
{ id: "category-x-ratchets", name: "Ratchets", description: "The middle component that sets height and weight distribution." },
|
|
196
|
+
{ id: "category-x-bits", name: "Bits", description: "The floor-contact tip — the X-format equivalent of a Driver." },
|
|
197
|
+
],
|
|
198
|
+
},
|
|
199
|
+
],
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
id: "category-battle-gear",
|
|
203
|
+
name: "Battle Gear",
|
|
204
|
+
description: "Everything that isn't a top — stadiums, storage and the accessories that make a battle setup work.",
|
|
205
|
+
extra: {
|
|
206
|
+
display: { icon: "🏟️", coverImage: cover("battle-gear"), color: "#7c3aed", showInMenu: true, showInFooter: false },
|
|
207
|
+
highlights: [
|
|
208
|
+
"Tournament-legal stadiums for every generation",
|
|
209
|
+
"Storage and transport built for part collections, not just complete tops",
|
|
210
|
+
],
|
|
211
|
+
faqs: [
|
|
212
|
+
{ question: "Is one stadium enough for all four generations?", answer: "Mostly — older round stadiums handle Original through Burst fine. Beyblade X's Xtreme Line stadiums add a rail feature X tops are designed around, so serious X play wants an X-format stadium." },
|
|
213
|
+
],
|
|
214
|
+
},
|
|
215
|
+
children: [
|
|
216
|
+
{
|
|
217
|
+
id: "category-gear-stadiums",
|
|
218
|
+
name: "Stadiums",
|
|
219
|
+
description: "Battle stadiums, from pocket-sized to tournament-grade.",
|
|
220
|
+
children: [
|
|
221
|
+
{ id: "category-stadiums-standard", name: "Standard Stadiums", description: "Round stadiums suiting Original, Metal Fight and Burst play." },
|
|
222
|
+
{ id: "category-stadiums-xtreme", name: "Xtreme Stadiums", description: "X-format stadiums with the Xtreme Line rail feature." },
|
|
223
|
+
],
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
id: "category-gear-storage",
|
|
227
|
+
name: "Storage & Care",
|
|
228
|
+
description: "Cases, trays and maintenance gear for a growing collection.",
|
|
229
|
+
children: [
|
|
230
|
+
{ id: "category-storage-cases", name: "Cases & Trays", description: "Hard cases and compartment trays for tops and loose parts." },
|
|
231
|
+
],
|
|
232
|
+
},
|
|
233
|
+
],
|
|
234
|
+
},
|
|
235
|
+
],
|
|
236
|
+
};
|
|
237
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
238
|
+
// Root 2 — Living Collectibles.
|
|
239
|
+
//
|
|
240
|
+
// Deliberately off the Beyblade theme, for two reasons. First, the `live`
|
|
241
|
+
// listing type's fields (species, sex, CITES/jurisdiction) only make sense for
|
|
242
|
+
// actual animals and plants, and its three seed fixtures are explicitly
|
|
243
|
+
// off-catalogue demo content. They previously carried `categorySlugs: []` and
|
|
244
|
+
// no brand, which made them unreachable from every category and brand page —
|
|
245
|
+
// and, once empty tabs hide, would have meant the Live Items tab never appeared
|
|
246
|
+
// anywhere at all. Second, the seed had only ever had ONE root, so no page had
|
|
247
|
+
// ever exercised a multi-root tree.
|
|
248
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
249
|
+
const LIVING_COLLECTIBLES = {
|
|
250
|
+
id: "category-living-collectibles",
|
|
251
|
+
name: "Living Collectibles",
|
|
252
|
+
description: "Live animals and plants from vetted sellers — every listing carries jurisdiction and welfare information, and ships only where it is legal to do so.",
|
|
253
|
+
extra: {
|
|
254
|
+
display: { icon: "🌱", coverImage: cover("living-collectibles"), color: "#16a34a", showInMenu: true, showInFooter: false },
|
|
255
|
+
highlights: [
|
|
256
|
+
"Sellers must be verified before a live listing goes public",
|
|
257
|
+
"Jurisdiction checks run at checkout — a listing that can't legally ship to you won't let you buy it",
|
|
258
|
+
"Species, age and provenance disclosed on every listing",
|
|
259
|
+
],
|
|
260
|
+
faqs: [
|
|
261
|
+
{ question: "How are live animals shipped?", answer: "They generally aren't — most live listings are local-collection only, and the listing states the collection area. Where courier transport is legal and appropriate, the seller arranges a specialist live-animal service." },
|
|
262
|
+
{ question: "What happens if a species isn't allowed in my state?", answer: "Checkout blocks it. Each live listing records where it may lawfully go, and the jurisdiction check runs before payment rather than after." },
|
|
263
|
+
],
|
|
264
|
+
},
|
|
265
|
+
children: [
|
|
266
|
+
{
|
|
267
|
+
id: "category-companion-animals",
|
|
268
|
+
name: "Companion Animals",
|
|
269
|
+
description: "Dogs, reptiles and other companion animals from verified sellers.",
|
|
270
|
+
children: [
|
|
271
|
+
{
|
|
272
|
+
id: "category-animals-dogs",
|
|
273
|
+
name: "Dogs",
|
|
274
|
+
description: "Puppies and adult dogs from health-screened, vetted breeders.",
|
|
275
|
+
children: [
|
|
276
|
+
{ id: "category-dogs-retrievers", name: "Retrievers", description: "Golden and Labrador retrievers." },
|
|
277
|
+
],
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
id: "category-animals-reptiles",
|
|
281
|
+
name: "Reptiles",
|
|
282
|
+
description: "Captive-bred reptiles with documented provenance.",
|
|
283
|
+
children: [
|
|
284
|
+
{ id: "category-reptiles-lizards", name: "Lizards", description: "Bearded dragons, geckos and other commonly kept lizards." },
|
|
285
|
+
],
|
|
286
|
+
},
|
|
287
|
+
],
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
id: "category-live-plants",
|
|
291
|
+
name: "Live Plants",
|
|
292
|
+
description: "Cultivated plants, specimen trees and the tools to keep them.",
|
|
293
|
+
children: [
|
|
294
|
+
{
|
|
295
|
+
id: "category-plants-bonsai",
|
|
296
|
+
name: "Bonsai",
|
|
297
|
+
description: "Trained bonsai specimens, sold with their age and training history.",
|
|
298
|
+
children: [
|
|
299
|
+
{ id: "category-bonsai-juniper", name: "Juniper Bonsai", description: "Juniper specimens — the most widely grown bonsai species." },
|
|
300
|
+
],
|
|
301
|
+
},
|
|
302
|
+
],
|
|
303
|
+
},
|
|
304
|
+
],
|
|
305
|
+
};
|
|
306
|
+
export const CATEGORY_FOREST = [
|
|
307
|
+
SPINNING_TOPS,
|
|
308
|
+
LIVING_COLLECTIBLES,
|
|
309
|
+
];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { CategoryDocument } from "../../features/categories/schemas";
|
|
2
|
+
/** The authoring shape — only the fields a human should have to write. */
|
|
3
|
+
export interface CategoryTreeNode {
|
|
4
|
+
/** Doc id AND slug; they are always equal for categories (`id === slug`). */
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
/** Per-row extras: display, seo, highlights, faqs, isFeatured, … */
|
|
9
|
+
extra?: Partial<CategoryDocument>;
|
|
10
|
+
children?: CategoryTreeNode[];
|
|
11
|
+
}
|
|
12
|
+
export interface BuildCategoryTreeOptions {
|
|
13
|
+
createdBy: string;
|
|
14
|
+
createdAt: Date;
|
|
15
|
+
updatedAt: Date;
|
|
16
|
+
/** Applied to every row unless the node's own `extra` overrides it. */
|
|
17
|
+
defaults?: Partial<CategoryDocument>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Flatten a forest of nested nodes into seed rows with every structural field
|
|
21
|
+
* computed.
|
|
22
|
+
*
|
|
23
|
+
* Traversal is DFS pre-order, and `position` is a single counter running across
|
|
24
|
+
* ALL roots — the numbering is global to the collection, not per-tree, which is
|
|
25
|
+
* what `onCategoryWrite`'s range shifting assumes.
|
|
26
|
+
*/
|
|
27
|
+
export declare function buildCategoryTree(roots: CategoryTreeNode[], opts: BuildCategoryTreeOptions): Partial<CategoryDocument>[];
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* WHY: `CategoryDocument` requires nine interlocking structural fields on every
|
|
3
|
+
* row — rootId, parentIds (the FULL ancestor chain), childrenIds, tier,
|
|
4
|
+
* path, isLeaf, ancestors, position and subtreeSize. Hand-writing those
|
|
5
|
+
* across a real tree guarantees mistakes, and the seed already had them:
|
|
6
|
+
* the old root claimed `subtreeSize: 4` at `position: 0` while all four of
|
|
7
|
+
* its children ALSO sat at positions 0-3, which is not a valid DFS
|
|
8
|
+
* pre-order numbering.
|
|
9
|
+
* WHAT: Declare the tree once as a nested literal; derive every structural
|
|
10
|
+
* field from it. Purely deterministic — no Math.random, no Date.now — so
|
|
11
|
+
* reseeding is idempotent (Root Cause #25).
|
|
12
|
+
*
|
|
13
|
+
* EXPORTS:
|
|
14
|
+
* CategoryTreeNode — the authoring shape (id/name/... plus `children`)
|
|
15
|
+
* buildCategoryTree — nested literal -> flat Partial<CategoryDocument>[]
|
|
16
|
+
*
|
|
17
|
+
* `position`/`subtreeSize` are DFS pre-order coordinates: a node's subtree
|
|
18
|
+
* occupies exactly `[position, position + subtreeSize - 1]`, which is what lets
|
|
19
|
+
* `onCategoryWrite` shift ranges on insert/delete. Seeding them correctly means
|
|
20
|
+
* that Function has nothing to repair on first write.
|
|
21
|
+
*
|
|
22
|
+
* @tag domain:categories
|
|
23
|
+
* @tag layer:seed
|
|
24
|
+
* @tag pattern:derived
|
|
25
|
+
* @tag access:server-only
|
|
26
|
+
* @tag consumers:seed/categories-seed-data.ts
|
|
27
|
+
* @tag sideEffects:none
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Flatten a forest of nested nodes into seed rows with every structural field
|
|
31
|
+
* computed.
|
|
32
|
+
*
|
|
33
|
+
* Traversal is DFS pre-order, and `position` is a single counter running across
|
|
34
|
+
* ALL roots — the numbering is global to the collection, not per-tree, which is
|
|
35
|
+
* what `onCategoryWrite`'s range shifting assumes.
|
|
36
|
+
*/
|
|
37
|
+
export function buildCategoryTree(roots, opts) {
|
|
38
|
+
const rows = [];
|
|
39
|
+
let position = 0;
|
|
40
|
+
function visit(node, rootId,
|
|
41
|
+
/** Ancestors nearest-last, matching how `parentIds` is read elsewhere. */
|
|
42
|
+
ancestors, tier, parentPath, order) {
|
|
43
|
+
const myPosition = position++;
|
|
44
|
+
// The slug segment is the id minus its `category-` prefix, so
|
|
45
|
+
// `spinning-tops/beyblade-burst/burst-parts` reads as a real path.
|
|
46
|
+
const segment = node.id.replace(/^category-/, "");
|
|
47
|
+
const path = parentPath ? `${parentPath}/${segment}` : segment;
|
|
48
|
+
const children = node.children ?? [];
|
|
49
|
+
// `seo` and `display` are REQUIRED on CategoryDocument, so synthesise
|
|
50
|
+
// sensible ones rather than make every row hand-write a block. A node that
|
|
51
|
+
// wants a real icon/cover/keywords overrides via `extra`, which is spread
|
|
52
|
+
// last.
|
|
53
|
+
const seo = {
|
|
54
|
+
title: `${node.name} | LetItRip`,
|
|
55
|
+
description: node.description,
|
|
56
|
+
keywords: node.name.toLowerCase().split(/\s+/).filter(Boolean),
|
|
57
|
+
};
|
|
58
|
+
const display = {
|
|
59
|
+
// Deeper rows are navigational, not menu-worthy: showing all four tiers
|
|
60
|
+
// in the header menu would drown it.
|
|
61
|
+
showInMenu: tier <= 1,
|
|
62
|
+
showInFooter: false,
|
|
63
|
+
};
|
|
64
|
+
const row = {
|
|
65
|
+
...opts.defaults,
|
|
66
|
+
seo,
|
|
67
|
+
display,
|
|
68
|
+
id: node.id,
|
|
69
|
+
slug: node.id,
|
|
70
|
+
name: node.name,
|
|
71
|
+
description: node.description,
|
|
72
|
+
rootId,
|
|
73
|
+
parentIds: ancestors.map((a) => a.id),
|
|
74
|
+
childrenIds: children.map((c) => c.id),
|
|
75
|
+
ancestors: ancestors.map((a) => ({ ...a })),
|
|
76
|
+
tier,
|
|
77
|
+
path,
|
|
78
|
+
order,
|
|
79
|
+
isLeaf: children.length === 0,
|
|
80
|
+
position: myPosition,
|
|
81
|
+
createdBy: opts.createdBy,
|
|
82
|
+
createdAt: opts.createdAt,
|
|
83
|
+
updatedAt: opts.updatedAt,
|
|
84
|
+
...node.extra,
|
|
85
|
+
};
|
|
86
|
+
rows.push(row);
|
|
87
|
+
const nextAncestors = [
|
|
88
|
+
...ancestors,
|
|
89
|
+
{ id: node.id, name: node.name, tier },
|
|
90
|
+
];
|
|
91
|
+
let descendants = 0;
|
|
92
|
+
children.forEach((child, index) => {
|
|
93
|
+
descendants += visit(child, rootId, nextAncestors, tier + 1, path, index + 1);
|
|
94
|
+
});
|
|
95
|
+
// A node's subtree spans itself plus everything beneath it.
|
|
96
|
+
row.subtreeSize = descendants + 1;
|
|
97
|
+
return row.subtreeSize;
|
|
98
|
+
}
|
|
99
|
+
for (const [index, root] of roots.entries()) {
|
|
100
|
+
visit(root, root.id, [], 0, "", index + 1);
|
|
101
|
+
}
|
|
102
|
+
return rows;
|
|
103
|
+
}
|
|
@@ -13,8 +13,8 @@ const NOW = new Date();
|
|
|
13
13
|
const daysAgo = (n) => new Date(NOW.getTime() - n * 86400000);
|
|
14
14
|
export const catalogueSeedData = [
|
|
15
15
|
{
|
|
16
|
-
id: "mycatalog-user-
|
|
17
|
-
ownerId: "user-
|
|
16
|
+
id: "mycatalog-user-rohit-collector-vintage-hotwheels-20260801-a1b2c3",
|
|
17
|
+
ownerId: "user-rohit-collector",
|
|
18
18
|
ownerRole: "user",
|
|
19
19
|
title: "Vintage Hot Wheels Redline (1969)",
|
|
20
20
|
description: "Original paint, minor wheel wear. Family collection.",
|
|
@@ -30,8 +30,8 @@ export const catalogueSeedData = [
|
|
|
30
30
|
updatedAt: daysAgo(5),
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
|
-
id: "mycatalog-user-
|
|
34
|
-
ownerId: "user-
|
|
33
|
+
id: "mycatalog-user-rohit-collector-charizard-holo-20260805-b2c3d4",
|
|
34
|
+
ownerId: "user-rohit-collector",
|
|
35
35
|
ownerRole: "user",
|
|
36
36
|
title: "Charizard Holo 1st Edition (played)",
|
|
37
37
|
images: [],
|
|
@@ -46,8 +46,8 @@ export const catalogueSeedData = [
|
|
|
46
46
|
updatedAt: daysAgo(2),
|
|
47
47
|
},
|
|
48
48
|
{
|
|
49
|
-
id: "mycatalog-user-priya-
|
|
50
|
-
ownerId: "user-priya-
|
|
49
|
+
id: "mycatalog-user-priya-cards-gundam-rx78-20260710-c3d4e5",
|
|
50
|
+
ownerId: "user-priya-cards",
|
|
51
51
|
ownerRole: "user",
|
|
52
52
|
title: "Gundam RX-78-2 Model Kit (built)",
|
|
53
53
|
images: [],
|
|
@@ -63,8 +63,8 @@ export const catalogueSeedData = [
|
|
|
63
63
|
updatedAt: daysAgo(20),
|
|
64
64
|
},
|
|
65
65
|
{
|
|
66
|
-
id: "mycatalog-user-priya-
|
|
67
|
-
ownerId: "user-priya-
|
|
66
|
+
id: "mycatalog-user-priya-cards-broken-beyblade-20260715-d4e5f6",
|
|
67
|
+
ownerId: "user-priya-cards",
|
|
68
68
|
ownerRole: "user",
|
|
69
69
|
title: "Beyblade Burst (missing launcher)",
|
|
70
70
|
images: [],
|
|
@@ -80,8 +80,8 @@ export const catalogueSeedData = [
|
|
|
80
80
|
updatedAt: daysAgo(14),
|
|
81
81
|
},
|
|
82
82
|
{
|
|
83
|
-
id: "mycatalog-
|
|
84
|
-
ownerId: "user-
|
|
83
|
+
id: "mycatalog-user-tyson-blader-pokemon-binder-20260601-e5f6a7",
|
|
84
|
+
ownerId: "user-tyson-blader",
|
|
85
85
|
ownerRole: "seller",
|
|
86
86
|
title: "Pokémon Binder — 180 cards, mixed sets",
|
|
87
87
|
images: [],
|
|
@@ -95,8 +95,8 @@ export const catalogueSeedData = [
|
|
|
95
95
|
updatedAt: daysAgo(45),
|
|
96
96
|
},
|
|
97
97
|
{
|
|
98
|
-
id: "mycatalog-user-arjun-
|
|
99
|
-
ownerId: "user-arjun-
|
|
98
|
+
id: "mycatalog-user-arjun-gunpla-funko-batman-20260620-f6a7b8",
|
|
99
|
+
ownerId: "user-arjun-gunpla",
|
|
100
100
|
ownerRole: "user",
|
|
101
101
|
title: "Funko Pop Batman (box wear only)",
|
|
102
102
|
images: [],
|