@mohasinac/appkit 4.30.18 → 4.31.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/digital-code/CodeRevealPanel.js +5 -2
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +3 -3
- package/dist/_internal/client/features/layout/useSidebarSearch.d.ts +21 -5
- package/dist/_internal/client/features/layout/useSidebarSearch.js +27 -6
- package/dist/_internal/client/features/lottery/LotteryAdminEditView.d.ts +23 -3
- package/dist/_internal/client/features/lottery/LotteryAdminEditView.js +106 -86
- package/dist/_internal/client/features/lottery/LotteryPullForm.d.ts +16 -5
- package/dist/_internal/client/features/lottery/LotteryPullForm.js +65 -40
- package/dist/_internal/client/features/maintenance/views/AnalysisRunnerView.js +5 -2
- package/dist/_internal/client/features/maintenance/views/CloudLogsListView.js +11 -3
- package/dist/_internal/client/hand-mode/HandModeProvider.js +2 -0
- package/dist/_internal/server/features/auctions/actions.js +14 -3
- package/dist/_internal/server/features/auctions/service.js +1 -1
- package/dist/_internal/server/features/auth/permissions.d.ts +2 -0
- package/dist/_internal/server/features/auth/permissions.js +3 -2
- package/dist/_internal/server/features/blog/data.js +2 -2
- package/dist/_internal/server/features/blog/service.js +3 -3
- package/dist/_internal/server/features/brands/data.js +1 -1
- package/dist/_internal/server/features/brands/service.js +3 -3
- package/dist/_internal/server/features/bundles/actions.js +6 -1
- package/dist/_internal/server/features/bundles/data.js +21 -4
- package/dist/_internal/server/features/cart/data.js +3 -1
- package/dist/_internal/server/features/cart/service.js +13 -2
- package/dist/_internal/server/features/categories/data.js +26 -6
- package/dist/_internal/server/features/classified/index.d.ts +0 -1
- package/dist/_internal/server/features/classified/index.js +0 -1
- package/dist/_internal/server/features/digital-code/index.d.ts +0 -1
- package/dist/_internal/server/features/digital-code/index.js +0 -1
- package/dist/_internal/server/features/events/actions.js +17 -4
- package/dist/_internal/server/features/events/data.js +1 -1
- package/dist/_internal/server/features/events/service.js +1 -1
- package/dist/_internal/server/features/grouped/data.js +7 -2
- package/dist/_internal/server/features/item-requests/data.js +1 -1
- package/dist/_internal/server/features/live/index.d.ts +0 -1
- package/dist/_internal/server/features/live/index.js +0 -1
- package/dist/_internal/server/features/lottery/actions.js +2 -2
- package/dist/_internal/server/features/lottery/data.js +1 -1
- package/dist/_internal/server/features/orders/actions.js +7 -7
- package/dist/_internal/server/features/orders/data.d.ts +1 -1
- package/dist/_internal/server/features/orders/data.js +14 -2
- package/dist/_internal/server/features/orders/service.js +1 -1
- package/dist/_internal/server/features/pre-orders/service.js +1 -1
- package/dist/_internal/server/features/prize-draws/actions.js +1 -1
- package/dist/_internal/server/features/products/data.js +21 -6
- package/dist/_internal/server/features/products/list-public.d.ts +9 -0
- package/dist/_internal/server/features/products/list-public.js +95 -7
- package/dist/_internal/server/features/products/service.js +1 -1
- package/dist/_internal/server/features/promotions/actions.js +1 -1
- package/dist/_internal/server/features/promotions/data.js +1 -1
- package/dist/_internal/server/features/promotions/service.js +1 -1
- package/dist/_internal/server/features/reviews/data.d.ts +1 -1
- package/dist/_internal/server/features/reviews/data.js +6 -1
- package/dist/_internal/server/features/reviews/og-data.js +1 -1
- package/dist/_internal/server/features/shared/listing-data-factory.js +7 -2
- package/dist/_internal/server/features/site-settings/adapters.d.ts +2 -2
- package/dist/_internal/server/features/site-settings/adapters.js +8 -5
- package/dist/_internal/server/features/stores/data.js +1 -1
- package/dist/_internal/server/features/sublisting-categories/data.js +1 -1
- package/dist/_internal/server/features/tester/visibility.d.ts +2 -1
- package/dist/_internal/server/features/tester/visibility.js +2 -2
- package/dist/_internal/server/functions/scheduled.d.ts +3 -1
- package/dist/_internal/server/functions/scheduled.js +27 -1
- package/dist/_internal/server/jobs/core/auctionSettlement.js +6 -1
- package/dist/_internal/server/jobs/core/hardBanCascade.js +4 -0
- package/dist/_internal/server/jobs/core/index.d.ts +2 -0
- package/dist/_internal/server/jobs/core/index.js +2 -0
- package/dist/_internal/server/jobs/core/onOrderStatusChange.js +7 -15
- package/dist/_internal/server/jobs/core/pageViewPrune.d.ts +10 -0
- package/dist/_internal/server/jobs/core/pageViewPrune.js +44 -0
- package/dist/_internal/server/jobs/core/pageViewRollup.d.ts +2 -0
- package/dist/_internal/server/jobs/core/pageViewRollup.js +87 -0
- package/dist/_internal/server/jobs/core/revenueRollup.js +7 -1
- package/dist/_internal/server/jobs/handlers/index.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/index.js +2 -0
- package/dist/_internal/server/jobs/handlers/pageViewPrune.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/pageViewPrune.js +2 -0
- package/dist/_internal/server/jobs/handlers/pageViewRollup.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/pageViewRollup.js +2 -0
- package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
- package/dist/_internal/shared/actions/action-registry.js +69 -22
- package/dist/_internal/shared/checkout/rules/classified.rule.d.ts +9 -4
- package/dist/_internal/shared/checkout/rules/classified.rule.js +7 -2
- package/dist/_internal/shared/features/layout/matchesNavQuery.d.ts +14 -0
- package/dist/_internal/shared/features/layout/matchesNavQuery.js +72 -0
- package/dist/_internal/shared/features/layout/types.d.ts +37 -1
- package/dist/_internal/shared/features/layout/types.js +19 -1
- package/dist/_internal/shared/features/notifications/action-url.d.ts +9 -1
- package/dist/_internal/shared/features/notifications/action-url.js +47 -0
- package/dist/_internal/shared/features/offers/config.d.ts +65 -0
- package/dist/_internal/shared/features/offers/config.js +73 -2
- package/dist/_internal/shared/features/orders/schema.d.ts +19 -1
- package/dist/_internal/shared/features/orders/schema.js +22 -2
- package/dist/_internal/shared/features/site-settings/types.d.ts +12 -3
- package/dist/_internal/shared/listing-types/capabilities.d.ts +8 -2
- package/dist/_internal/shared/listing-types/capabilities.js +6 -1
- package/dist/_internal/shared/listing-types/classified/ctas.js +6 -1
- package/dist/_internal/shared/listing-types/feature-flags.d.ts +10 -5
- package/dist/_internal/shared/listing-types/feature-flags.js +11 -6
- package/dist/client/api/useApiQuery.js +17 -6
- package/dist/client.d.ts +38 -20
- package/dist/client.js +39 -14
- package/dist/configs/next.js +10 -2
- package/dist/constants/api-endpoints.d.ts +18 -54
- package/dist/constants/api-endpoints.js +6 -26
- package/dist/constants/field-names.d.ts +6 -24
- package/dist/constants/field-names.js +10 -27
- package/dist/constants/geo/countries.d.ts +50 -0
- package/dist/constants/geo/countries.js +129 -0
- package/dist/constants/geo/subdivisions.d.ts +13 -0
- package/dist/constants/geo/subdivisions.js +104 -0
- package/dist/constants/index.d.ts +2 -2
- package/dist/constants/index.js +2 -2
- package/dist/constants/table-keys.d.ts +24 -0
- package/dist/constants/table-keys.js +28 -0
- package/dist/contracts/client-realtime.d.ts +6 -0
- package/dist/contracts/extend.d.ts +0 -9
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/realtime-session.d.ts +12 -12
- package/dist/contracts/realtime-session.js +79 -77
- package/dist/core/browser.d.ts +1 -1
- package/dist/core/browser.js +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/site-config.d.ts +0 -3
- package/dist/core/site-config.js +0 -3
- package/dist/errors/index.d.ts +1 -1
- package/dist/errors/index.js +1 -1
- package/dist/errors/messages.d.ts +0 -8
- package/dist/errors/messages.js +0 -9
- package/dist/features/about/components/DeveloperView.js +7 -2
- package/dist/features/about/components/PolicyPageView.js +9 -1
- package/dist/features/about/components/PublicProfileView.js +23 -5
- package/dist/features/about/schemas/index.d.ts +8 -8
- package/dist/features/account/components/AddressFilters.js +32 -11
- package/dist/features/account/components/AddressForm.d.ts +26 -25
- package/dist/features/account/components/AddressForm.js +81 -103
- package/dist/features/account/components/AddressesIndexListing.js +8 -4
- package/dist/features/account/components/NotificationBell.js +4 -3
- package/dist/features/account/components/NotificationPreferencesPanel.js +1 -1
- package/dist/features/account/components/UserOffersPanel.js +1 -1
- package/dist/features/account/components/UserSidebar.d.ts +3 -4
- package/dist/features/account/components/UserSupportView.js +89 -58
- package/dist/features/account/components/index.d.ts +1 -7
- package/dist/features/account/components/index.js +0 -3
- package/dist/features/account/hooks/useAddresses.d.ts +4 -3
- package/dist/features/account/hooks/useAddresses.js +4 -6
- package/dist/features/account/hooks/useCollapsedSections.d.ts +51 -10
- package/dist/features/account/hooks/useCollapsedSections.js +211 -38
- package/dist/features/account/hooks/useProfile.d.ts +8 -0
- package/dist/features/account/index.d.ts +0 -3
- package/dist/features/account/index.js +0 -3
- package/dist/features/account/schemas/index.d.ts +0 -92
- package/dist/features/account/schemas/index.js +42 -20
- package/dist/features/addresses/components/AddressLocationFields.d.ts +13 -0
- package/dist/features/addresses/components/AddressLocationFields.js +41 -0
- package/dist/features/addresses/hooks/usePostalLookup.d.ts +17 -0
- package/dist/features/addresses/hooks/usePostalLookup.js +133 -0
- package/dist/features/addresses/schemas/address-form.d.ts +423 -0
- package/dist/features/addresses/schemas/address-form.js +212 -0
- package/dist/features/addresses/schemas/index.d.ts +1 -0
- package/dist/features/addresses/schemas/index.js +8 -0
- package/dist/features/admin/actions/admin-read-actions.d.ts +1 -1
- package/dist/features/admin/actions/index.d.ts +0 -1
- package/dist/features/admin/actions/index.js +0 -1
- package/dist/features/admin/actions/notification-actions.js +1 -41
- package/dist/features/admin/components/AdminActionIndexView.d.ts +32 -0
- package/dist/features/admin/components/AdminActionIndexView.js +128 -0
- package/dist/features/admin/components/AdminAdEditorView.js +159 -163
- package/dist/features/admin/components/AdminAddressEditorView.js +97 -55
- package/dist/features/admin/components/AdminBrandEditorView.d.ts +15 -0
- package/dist/features/admin/components/AdminBrandEditorView.js +113 -77
- package/dist/features/admin/components/AdminBundleEditorView.d.ts +19 -9
- package/dist/features/admin/components/AdminBundleEditorView.js +136 -168
- package/dist/features/admin/components/AdminCategoryEditorView.js +120 -43
- package/dist/features/admin/components/AdminCouponEditorView.js +145 -109
- package/dist/features/admin/components/AdminEmployeeEditorView.js +125 -56
- package/dist/features/admin/components/AdminFaqEditorView.js +112 -58
- package/dist/features/admin/components/AdminFeatureEditorView.js +108 -68
- package/dist/features/admin/components/AdminFulfillmentView.js +5 -2
- package/dist/features/admin/components/AdminMediaView.js +3 -3
- package/dist/features/admin/components/AdminNavEditorView.js +69 -44
- package/dist/features/admin/components/AdminOrderEditorView.js +47 -10
- package/dist/features/admin/components/AdminPrizeDrawsView.js +16 -2
- package/dist/features/admin/components/AdminSidebar.d.ts +11 -7
- package/dist/features/admin/components/AdminSiteSettingsView.js +37 -37
- package/dist/features/admin/components/AdminStoreEditorView.js +75 -52
- package/dist/features/admin/components/AdminSublistingCategoryEditorView.js +71 -30
- package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +95 -65
- package/dist/features/admin/components/BrandQuickCreateForm.d.ts +10 -0
- package/dist/features/admin/components/BrandQuickCreateForm.js +49 -26
- package/dist/features/admin/components/CategoryQuickCreateForm.d.ts +11 -0
- package/dist/features/admin/components/CategoryQuickCreateForm.js +48 -26
- package/dist/features/admin/components/index.d.ts +2 -2
- package/dist/features/admin/components/index.js +1 -1
- package/dist/features/admin/constants/site-settings-tabs.d.ts +120 -0
- package/dist/features/admin/constants/site-settings-tabs.js +152 -0
- package/dist/features/admin/index.d.ts +0 -3
- package/dist/features/admin/index.js +0 -2
- package/dist/features/admin/repository/analytics-rollup.repository.d.ts +35 -0
- package/dist/features/admin/repository/analytics-rollup.repository.js +30 -0
- package/dist/features/admin/schemas/admin-editor-forms.d.ts +56 -57
- package/dist/features/admin/schemas/admin-editor-forms.js +97 -54
- package/dist/features/admin/schemas/admin-ops-forms.d.ts +57 -5
- package/dist/features/admin/schemas/admin-ops-forms.js +104 -20
- package/dist/features/admin/schemas/admin-user-form.js +7 -0
- package/dist/features/admin/schemas/firestore.d.ts +48 -95
- package/dist/features/admin/schemas/firestore.js +15 -151
- package/dist/features/admin/schemas/nav-item-form.js +9 -2
- package/dist/features/admin/server.d.ts +0 -4
- package/dist/features/admin/server.js +0 -2
- package/dist/features/admin/types/index.d.ts +0 -7
- package/dist/features/analytics/repository/page-views.repository.d.ts +14 -0
- package/dist/features/analytics/repository/page-views.repository.js +24 -0
- package/dist/features/analytics/types.d.ts +1 -1
- package/dist/features/analytics/types.js +13 -0
- package/dist/features/auctions/components/AuctionDetailPageView.js +6 -2
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +3 -1
- package/dist/features/auth/actions/index.d.ts +0 -1
- package/dist/features/auth/actions/index.js +0 -1
- package/dist/features/auth/actions/profile-actions.js +4 -3
- package/dist/features/auth/actions/realtime-token-actions.js +1 -12
- package/dist/features/auth/auth-helpers.js +5 -7
- package/dist/features/auth/components/ForgotPasswordView.js +1 -1
- package/dist/features/auth/components/Guards.js +2 -1
- package/dist/features/auth/components/LoginForm.d.ts +0 -2
- package/dist/features/auth/components/LoginForm.js +2 -4
- package/dist/features/auth/components/RegisterForm.js +62 -19
- package/dist/features/auth/components/ResetPasswordView.js +1 -1
- package/dist/features/auth/hooks/useAuth.js +3 -0
- package/dist/features/auth/permissions/constants.d.ts +27 -1
- package/dist/features/auth/role-predicates.d.ts +75 -7
- package/dist/features/auth/role-predicates.js +28 -2
- package/dist/features/auth/schemas/firestore.d.ts +22 -0
- package/dist/features/auth/schemas/index.d.ts +1 -1
- package/dist/features/auth/schemas/index.js +44 -8
- package/dist/features/auth/types/index.d.ts +14 -1
- package/dist/features/blog/api/route.js +10 -2
- package/dist/features/blog/components/BlogIndexListing.js +1 -1
- package/dist/features/blog/hooks/useBlog.js +2 -2
- package/dist/features/blog/repository/blog.repository.js +3 -1
- package/dist/features/blog/schemas/index.d.ts +4 -0
- package/dist/features/blog/schemas/index.js +2 -0
- package/dist/features/blog/types/index.d.ts +1 -1
- package/dist/features/cart/actions/cart-actions.js +13 -4
- package/dist/features/cart/utils/pending-ops.js +1 -1
- package/dist/features/catalogue/components/CatalogueItemEditorView.d.ts +22 -0
- package/dist/features/catalogue/components/CatalogueItemEditorView.js +112 -52
- package/dist/features/catalogue/schemas/validation.d.ts +4 -4
- package/dist/features/catalogue/schemas/validation.js +47 -10
- package/dist/features/categories/components/BrandDetailPageView.js +28 -12
- package/dist/features/categories/components/CategoryDetailPageView.js +37 -20
- package/dist/features/categories/repository/categories.repository.js +3 -1
- package/dist/features/categories/schemas/bundle-form.d.ts +142 -0
- package/dist/features/categories/schemas/bundle-form.js +149 -0
- package/dist/features/checkout/actions/checkout-value-otp-actions.js +10 -1
- package/dist/features/classified/components/ClassifiedContactSellerPanel.js +1 -1
- package/dist/features/classified/components/ClassifiedDetailPageView.d.ts +5 -4
- package/dist/features/classified/components/ClassifiedDetailPageView.js +47 -18
- package/dist/features/consultation/components/ConsultationForm.js +1 -1
- package/dist/features/consultation/schemas/index.js +34 -10
- package/dist/features/corporate/schemas/index.js +36 -15
- package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +4 -1
- package/dist/features/events/components/EventBanner.js +5 -2
- package/dist/features/events/components/EventOfferCard.js +3 -1
- package/dist/features/events/components/EventPollWidget.js +1 -1
- package/dist/features/events/components/SpinWheelView.js +3 -2
- package/dist/features/filters/FilterPanel.js +3 -3
- package/dist/features/filters/RangeFilter.d.ts +10 -0
- package/dist/features/filters/RangeFilter.js +41 -4
- package/dist/features/grouped/components/GroupedListingEditorView.js +2 -1
- package/dist/features/history/hooks/useHistory.js +29 -27
- package/dist/features/homepage/components/AdSlot.js +3 -1
- package/dist/features/homepage/components/GoogleReviewsSection.js +8 -2
- package/dist/features/homepage/components/MarketplaceHomepageView.js +58 -15
- package/dist/features/homepage/components/SocialFeedSection.js +4 -1
- package/dist/features/homepage/hooks/useBlogArticles.js +1 -1
- package/dist/features/homepage/lib/live-stats.js +8 -1
- package/dist/features/homepage/repository/carousel.repository.js +2 -1
- package/dist/features/layout/BottomActions.js +84 -11
- package/dist/features/layout/BottomActionsContext.d.ts +1 -6
- package/dist/features/layout/BottomActionsContext.js +1 -1
- package/dist/features/layout/hooks/useBottomActions.js +2 -2
- package/dist/features/layout/hooks/useFormBottomActions.d.ts +12 -1
- package/dist/features/layout/hooks/useFormBottomActions.js +12 -6
- package/dist/features/live/components/LiveItemDetailPageView.js +4 -1
- package/dist/features/lottery/schemas/config-write.d.ts +9 -5
- package/dist/features/lottery/schemas/config-write.js +69 -9
- package/dist/features/media/finalize.js +3 -1
- package/dist/features/media/modals/ImageEditor.js +1 -1
- package/dist/features/media/modals/VideoThumbnailSelector.js +5 -2
- package/dist/features/media/modals/VideoTrimModal.js +5 -2
- package/dist/features/media/upload/MediaUploadField.js +2 -2
- package/dist/features/messages/hooks/useConversation.js +18 -4
- package/dist/features/messages/hooks/useConversations.js +25 -8
- package/dist/features/orders/components/RefundRequestView.js +5 -2
- package/dist/features/orders/schemas/buyer-forms.d.ts +6 -3
- package/dist/features/orders/schemas/buyer-forms.js +31 -3
- package/dist/features/orders/schemas/index.d.ts +2 -2
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +3 -1
- package/dist/features/pre-orders/components/PreOrderActionsClient.js +1 -1
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +4 -1
- package/dist/features/products/components/GroupSettingsPanel.js +3 -1
- package/dist/features/products/components/MakeOfferButton.d.ts +13 -2
- package/dist/features/products/components/MakeOfferButton.js +33 -11
- package/dist/features/products/components/PrizeDrawDetailPageView.js +4 -1
- package/dist/features/products/components/ProductDetailActions.js +0 -1
- package/dist/features/products/components/ProductDetailPageView.d.ts +7 -3
- package/dist/features/products/components/ProductDetailPageView.js +16 -7
- package/dist/features/products/components/ShareButton.js +3 -1
- package/dist/features/products/constants/action-defs.d.ts +1 -2
- package/dist/features/products/constants/action-defs.js +40 -43
- package/dist/features/products/repository/loadProductFeatures.js +10 -2
- package/dist/features/products/repository/products.repository.d.ts +5 -1
- package/dist/features/products/repository/products.repository.js +25 -2
- package/dist/features/products/schemas/firestore.d.ts +7 -3
- package/dist/features/products/schemas/product-features.validators.js +3 -0
- package/dist/features/promotions/components/CouponCard.js +11 -8
- package/dist/features/reviews/actions/review-actions.js +8 -1
- package/dist/features/reviews/components/ReviewDetailPageView.js +13 -3
- package/dist/features/reviews/components/ReviewDetailShell.js +3 -1
- package/dist/features/scams/actions/scam-actions.d.ts +9 -1
- package/dist/features/scams/actions/scam-actions.js +52 -12
- package/dist/features/scams/components/SellerTrustBadge.d.ts +1 -1
- package/dist/features/scams/components/SellerTrustBadge.js +13 -0
- package/dist/features/scams/repository/scammer.repository.js +2 -1
- package/dist/features/scams/schemas/firestore.d.ts +15 -1
- package/dist/features/scams/schemas/report-form.d.ts +5 -5
- package/dist/features/scams/schemas/report-form.js +18 -3
- package/dist/features/search/action-index/derive.d.ts +49 -0
- package/dist/features/search/action-index/derive.js +121 -0
- package/dist/features/search/action-index/repository.d.ts +42 -0
- package/dist/features/search/action-index/repository.js +100 -0
- package/dist/features/search/action-index/settings-entries.d.ts +41 -0
- package/dist/features/search/action-index/settings-entries.js +268 -0
- package/dist/features/search/action-index/types.d.ts +81 -0
- package/dist/features/search/action-index/types.js +102 -0
- package/dist/features/search/action-index/validate-entry.d.ts +34 -0
- package/dist/features/search/action-index/validate-entry.js +114 -0
- package/dist/features/search/hooks/useNavSuggestions.d.ts +5 -1
- package/dist/features/search/hooks/useNavSuggestions.js +23 -3
- package/dist/features/search/repository/search.repository.js +3 -1
- package/dist/features/seller/actions/offer-actions.js +43 -19
- package/dist/features/seller/actions/seller-actions.js +29 -5
- package/dist/features/seller/components/CategoryChipPicker.d.ts +9 -0
- package/dist/features/seller/components/CategoryChipPicker.js +12 -0
- package/dist/features/seller/components/FulfillmentView.js +5 -2
- package/dist/features/seller/components/PhysicalLocationModal.js +1 -1
- package/dist/features/seller/components/PrintCenterView.js +3 -1
- package/dist/features/seller/components/SellerAddressesView.js +5 -1
- package/dist/features/seller/components/SellerAnalyticsAlertsView.js +83 -43
- package/dist/features/seller/components/SellerArtView.d.ts +14 -7
- package/dist/features/seller/components/SellerArtView.js +4 -119
- package/dist/features/seller/components/SellerBidsView.js +1 -1
- package/dist/features/seller/components/SellerClassifiedView.d.ts +14 -7
- package/dist/features/seller/components/SellerClassifiedView.js +4 -124
- package/dist/features/seller/components/SellerCouponEditorView.d.ts +22 -1
- package/dist/features/seller/components/SellerCouponEditorView.js +91 -45
- package/dist/features/seller/components/SellerCouponsView.js +1 -1
- package/dist/features/seller/components/SellerDigitalCodesView.d.ts +14 -7
- package/dist/features/seller/components/SellerDigitalCodesView.js +4 -126
- package/dist/features/seller/components/SellerGoogleReviewsView.js +2 -2
- package/dist/features/seller/components/SellerListingTypeView.d.ts +66 -0
- package/dist/features/seller/components/SellerListingTypeView.js +277 -0
- package/dist/features/seller/components/SellerLiveView.d.ts +14 -7
- package/dist/features/seller/components/SellerLiveView.js +4 -126
- package/dist/features/seller/components/SellerOrdersView.js +3 -3
- package/dist/features/seller/components/SellerPayoutMethodsView.js +2 -2
- package/dist/features/seller/components/SellerProductShell.d.ts +5 -0
- package/dist/features/seller/components/SellerProductShell.js +15 -5
- package/dist/features/seller/components/SellerProductsView.js +24 -10
- package/dist/features/seller/components/SellerReviewsView.js +47 -16
- package/dist/features/seller/components/SellerShippingConfigsView.js +5 -4
- package/dist/features/seller/components/SellerSidebar.d.ts +3 -6
- package/dist/features/seller/components/SellerStickersView.d.ts +14 -7
- package/dist/features/seller/components/SellerStickersView.js +4 -119
- package/dist/features/seller/components/SellerStoreCategoriesView.js +3 -2
- package/dist/features/seller/components/SellerSupportView.d.ts +31 -0
- package/dist/features/seller/components/SellerSupportView.js +100 -0
- package/dist/features/seller/components/index.d.ts +4 -8
- package/dist/features/seller/components/index.js +2 -4
- package/dist/features/seller/index.d.ts +0 -1
- package/dist/features/seller/index.js +0 -1
- package/dist/features/seller/schemas/coupon-form.d.ts +214 -0
- package/dist/features/seller/schemas/coupon-form.js +155 -23
- package/dist/features/seller/schemas/offer-forms.d.ts +16 -7
- package/dist/features/seller/schemas/offer-forms.js +28 -12
- package/dist/features/shell/FormShell.js +2 -2
- package/dist/features/shell/QuickFormDrawer.js +2 -2
- package/dist/features/shell/SectionForm.d.ts +19 -1
- package/dist/features/shell/SectionForm.js +104 -17
- package/dist/features/shell/build-sections.d.ts +23 -0
- package/dist/features/shell/build-sections.js +106 -8
- package/dist/features/shell/field-ui-meta.d.ts +44 -0
- package/dist/features/shell/field-ui-meta.js +14 -7
- package/dist/features/shell/form-sections.d.ts +46 -0
- package/dist/features/shell/form-sections.js +114 -0
- package/dist/features/shipments/components/AdminShipmentEditorView.js +87 -64
- package/dist/features/shipments/schemas/validation.d.ts +2 -2
- package/dist/features/shipments/schemas/validation.js +44 -13
- package/dist/features/store-extensions/schemas/custom-role-form.js +6 -2
- package/dist/features/store-extensions/schemas/listing-template-form.d.ts +7 -7
- package/dist/features/store-extensions/schemas/payout-method-form.js +14 -0
- package/dist/features/stores/actions/store-query-actions.js +3 -2
- package/dist/features/stores/api/[storeSlug]/auctions/route.js +3 -1
- package/dist/features/stores/api/[storeSlug]/products/route.js +3 -1
- package/dist/features/stores/components/StoreDetailLayoutView.d.ts +1 -1
- package/dist/features/stores/components/StoreDetailLayoutView.js +12 -3
- package/dist/features/support/repository/support.repository.d.ts +21 -0
- package/dist/features/support/repository/support.repository.js +63 -0
- package/dist/features/support/schemas/firestore.d.ts +27 -2
- package/dist/features/support/schemas/firestore.js +2 -0
- package/dist/features/support/schemas/ticket-create-form.js +7 -0
- package/dist/features/tester/schemas/checklist-item-form.d.ts +43 -0
- package/dist/features/tester/schemas/checklist-item-form.js +109 -0
- package/dist/features/tester/seed-data/blog-tester-seed-data.js +2 -2
- package/dist/features/tester/seed-data/categories-tester-seed-data.js +2 -2
- package/dist/features/tester/seed-data/events-tester-seed-data.js +5 -5
- package/dist/features/tester/seed-data/orders-tester-seed-data.js +2 -2
- package/dist/features/tester/seed-data/products-tester-seed-data.js +48 -49
- package/dist/features/tester/seed-data/stores-tester-seed-data.js +3 -3
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +291 -30
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +51 -14
- package/dist/features/wishlist/hooks/useWishlistToggle.js +8 -1
- package/dist/http/api-handler.js +2 -1
- package/dist/index.d.ts +25 -104
- package/dist/index.js +38 -143
- package/dist/jobs.d.ts +1 -1
- package/dist/jobs.js +1 -1
- package/dist/monitoring/browser.d.ts +0 -2
- package/dist/monitoring/browser.js +12 -1
- package/dist/monitoring/index.d.ts +0 -2
- package/dist/monitoring/index.js +0 -1
- package/dist/next/api/routeHandler.js +9 -4
- package/dist/next/index.d.ts +1 -2
- package/dist/next/index.js +0 -1
- package/dist/next/middleware/index.d.ts +0 -2
- package/dist/next/middleware/index.js +0 -1
- package/dist/next/routing/route-map.d.ts +8 -7
- package/dist/next/routing/route-map.js +10 -3
- package/dist/providers/auth-firebase/session.js +3 -1
- package/dist/providers/db-firebase/admin-app-lite.js +8 -8
- package/dist/providers/db-firebase/admin.js +27 -13
- package/dist/providers/db-firebase/browser-stub.d.ts +1 -11
- package/dist/providers/db-firebase/browser-stub.js +6 -11
- package/dist/providers/db-firebase/index.d.ts +0 -1
- package/dist/providers/db-firebase/index.js +0 -1
- package/dist/providers/db-firebase/rtdb-paths.d.ts +15 -6
- package/dist/providers/db-firebase/rtdb-paths.js +15 -6
- package/dist/providers/db-firebase/rtdb-url.d.ts +27 -0
- package/dist/providers/db-firebase/rtdb-url.js +50 -0
- package/dist/providers/db-firebase/sieve.d.ts +22 -0
- package/dist/providers/firebase-client/realtime.d.ts +20 -0
- package/dist/providers/firebase-client/realtime.js +34 -1
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +1 -1
- package/dist/react/hooks/use-action-dispatch.js +8 -2
- package/dist/react/hooks/useFormStatePreservation.js +3 -1
- package/dist/react/hooks/useListingTypeFlags.d.ts +1 -1
- package/dist/react/hooks/useListingTypeFlags.js +1 -1
- package/dist/react/hooks/usePendingFilters.js +5 -3
- package/dist/react/hooks/usePendingTable.js +15 -3
- package/dist/react/hooks/useRealtimeEvent.js +20 -9
- package/dist/repositories/index.d.ts +0 -1
- package/dist/repositories/index.js +0 -1
- package/dist/schemas/registry.d.ts +197 -232
- package/dist/schemas/registry.js +5 -6
- package/dist/schemas/webhooks/razorpay.d.ts +50 -50
- package/dist/security/authorization.d.ts +9 -0
- package/dist/security/authorization.js +16 -2
- package/dist/security/browser.d.ts +1 -3
- package/dist/security/browser.js +5 -2
- package/dist/security/index.d.ts +1 -3
- package/dist/security/index.js +19 -2
- package/dist/security/pii-encrypt.js +16 -0
- package/dist/security/pii-schemas.d.ts +0 -14
- package/dist/security/pii-schemas.js +7 -15
- package/dist/seed/_helpers/category-forest.js +2 -2
- package/dist/seed/_helpers/media.d.ts +19 -0
- package/dist/seed/_helpers/media.js +75 -0
- package/dist/seed/blog-posts-seed-data.js +17 -17
- package/dist/seed/carousel-slides-seed-data.js +7 -7
- package/dist/seed/cart-seed-data.js +13 -13
- package/dist/seed/categories-seed-data.js +10 -10
- package/dist/seed/events-seed-data.js +24 -24
- package/dist/seed/factories/product.factory.js +4 -4
- package/dist/seed/factories/store.factory.js +3 -3
- package/dist/seed/factories/user.factory.js +2 -2
- package/dist/seed/grouped-listings-seed-data.js +11 -11
- package/dist/seed/homepage-sections-seed-data.js +2 -2
- package/dist/seed/index.d.ts +0 -1
- package/dist/seed/index.js +0 -1
- package/dist/seed/manifest.d.ts +1 -1
- package/dist/seed/manifest.js +0 -5
- package/dist/seed/notifications-seed-data.js +20 -1
- package/dist/seed/orders-seed-data.js +2 -2
- package/dist/seed/products-art-seed-data.js +16 -16
- package/dist/seed/products-auctions-seed-data.js +34 -34
- package/dist/seed/products-classifieds-seed-data.js +35 -37
- package/dist/seed/products-digital-codes-seed-data.js +20 -20
- package/dist/seed/products-live-items-seed-data.js +11 -11
- package/dist/seed/products-preorders-seed-data.js +13 -13
- package/dist/seed/products-prize-draws-seed-data.js +43 -43
- package/dist/seed/products-standard-seed-data.js +54 -54
- package/dist/seed/products-stickers-seed-data.js +15 -15
- package/dist/seed/reviews-seed-data.js +4 -4
- package/dist/seed/scammers-seed-data.js +3 -3
- package/dist/seed/site-settings-seed-data.js +11 -24
- package/dist/seed/store-extensions-seed-data.js +10 -10
- package/dist/seed/stores-seed-data.js +11 -11
- package/dist/seed/support-tickets-seed-data.d.ts +14 -0
- package/dist/seed/support-tickets-seed-data.js +20 -1
- package/dist/seed/users-seed-data.js +20 -20
- package/dist/server-entry.d.ts +0 -1
- package/dist/server-entry.js +0 -1
- package/dist/server.d.ts +9 -6
- package/dist/server.js +7 -13
- package/dist/styles.css +248 -68
- package/dist/tailwind-utilities.css +1 -1
- package/dist/tokens/themes/default-dark.js +2 -2
- package/dist/tokens/themes/default-light.js +2 -2
- package/dist/tokens/tokens.css +24 -4
- package/dist/ui/components/ActionRow.d.ts +50 -0
- package/dist/ui/components/ActionRow.js +53 -0
- package/dist/ui/components/ActionRow.style.css +145 -0
- package/dist/ui/components/Drawer.d.ts +10 -0
- package/dist/ui/components/Drawer.js +2 -1
- package/dist/ui/components/FilterDrawer.js +4 -1
- package/dist/ui/components/FilterDrawer.style.css +6 -12
- package/dist/ui/components/FormActionBar.js +14 -1
- package/dist/ui/components/FormActionBar.style.css +12 -11
- package/dist/ui/components/ListingLayout.js +8 -1
- package/dist/ui/components/ListingLayout.style.css +6 -13
- package/dist/ui/components/Modal.d.ts +15 -1
- package/dist/ui/components/Modal.js +17 -3
- package/dist/ui/components/QuickCreateModal.js +2 -2
- package/dist/ui/components/QuickCreateModal.style.css +78 -84
- package/dist/ui/components/RecordDetailModal.js +2 -2
- package/dist/ui/components/SideDrawer.d.ts +8 -0
- package/dist/ui/components/SideDrawer.js +2 -1
- package/dist/ui/components/SideDrawer.style.css +6 -3
- package/dist/ui/components/SideModal.d.ts +11 -1
- package/dist/ui/components/SideModal.js +3 -2
- package/dist/ui/components/SideModal.style.css +14 -0
- package/dist/ui/components/Typography.style.css +33 -24
- package/dist/ui/components/index.style.css +1 -0
- package/dist/ui/components/toolbar-collapse.js +1 -2
- package/dist/ui/forms/FormShell.style.css +260 -311
- package/dist/ui/index.d.ts +2 -0
- package/dist/ui/index.js +1 -0
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.js +0 -1
- package/dist/validation/index.d.ts +1 -1
- package/dist/validation/index.js +1 -1
- package/dist/validation/schemas.d.ts +0 -19
- package/dist/validation/schemas.js +8 -19
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +3 -6
|
@@ -72,10 +72,10 @@ function write(key, items) {
|
|
|
72
72
|
return;
|
|
73
73
|
try {
|
|
74
74
|
localStorage.setItem(key, JSON.stringify(items));
|
|
75
|
+
// Quota exceeded or storage blocked. Losing pending ops costs a retry, never data: the cart is canonical in Firestore.
|
|
75
76
|
}
|
|
76
77
|
catch (_err) {
|
|
77
78
|
void normalizeError(_err);
|
|
78
|
-
// storage quota exceeded — best effort
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
function writeCartOps(items) {
|
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Add or edit an item in a user's personal catalogue.
|
|
3
|
+
*
|
|
4
|
+
* Fields come from `createCatalogueItemSchema`'s annotations. Three need a
|
|
5
|
+
* `renderers` entry: the photo list (a real uploader, not the generator's
|
|
6
|
+
* disabled placeholder), and the two taxonomy selects, which are searchable
|
|
7
|
+
* because 47 categories is well past the 5-option threshold.
|
|
8
|
+
*
|
|
9
|
+
* ## `categorySlugs` and `brandSlug` were declared, read, and never collected
|
|
10
|
+
*
|
|
11
|
+
* Both are inherited from `ProductDraftFields` and both are read by
|
|
12
|
+
* `product-from-item.ts`, which builds the marketplace listing when an item is
|
|
13
|
+
* promoted. The hand-rolled form had no control for either, so every promoted
|
|
14
|
+
* listing carried `categorySlugs: []` — and per the Category Tree rules a
|
|
15
|
+
* product with an empty chain is invisible on every category and brand page it
|
|
16
|
+
* should appear under. A schema field with a reader and no control is the
|
|
17
|
+
* inverse of a dead control, and just as silent.
|
|
18
|
+
*
|
|
19
|
+
* `mainImage` is `t1-derive` — the first photo, not a field anyone types. It
|
|
20
|
+
* renders as a read-only preview rather than a text box that could be desynced
|
|
21
|
+
* from the gallery it is supposed to mirror.
|
|
22
|
+
*/
|
|
1
23
|
import React from "react";
|
|
2
24
|
import type { CatalogueItemDocument } from "../schemas/firestore";
|
|
3
25
|
export interface CatalogueItemEditorViewProps {
|
|
@@ -1,60 +1,120 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Add or edit an item in a user's personal catalogue.
|
|
5
|
+
*
|
|
6
|
+
* Fields come from `createCatalogueItemSchema`'s annotations. Three need a
|
|
7
|
+
* `renderers` entry: the photo list (a real uploader, not the generator's
|
|
8
|
+
* disabled placeholder), and the two taxonomy selects, which are searchable
|
|
9
|
+
* because 47 categories is well past the 5-option threshold.
|
|
10
|
+
*
|
|
11
|
+
* ## `categorySlugs` and `brandSlug` were declared, read, and never collected
|
|
12
|
+
*
|
|
13
|
+
* Both are inherited from `ProductDraftFields` and both are read by
|
|
14
|
+
* `product-from-item.ts`, which builds the marketplace listing when an item is
|
|
15
|
+
* promoted. The hand-rolled form had no control for either, so every promoted
|
|
16
|
+
* listing carried `categorySlugs: []` — and per the Category Tree rules a
|
|
17
|
+
* product with an empty chain is invisible on every category and brand page it
|
|
18
|
+
* should appear under. A schema field with a reader and no control is the
|
|
19
|
+
* inverse of a dead control, and just as silent.
|
|
20
|
+
*
|
|
21
|
+
* `mainImage` is `t1-derive` — the first photo, not a field anyone types. It
|
|
22
|
+
* renders as a read-only preview rather than a text box that could be desynced
|
|
23
|
+
* from the gallery it is supposed to mirror.
|
|
24
|
+
*/
|
|
3
25
|
import React from "react";
|
|
4
26
|
import { useQueryClient } from "@tanstack/react-query";
|
|
5
27
|
import { useApiMutation } from "@mohasinac/appkit/client";
|
|
6
|
-
import {
|
|
7
|
-
import { FormErrorSummary } from "../../../ui/forms";
|
|
8
|
-
import { MediaUploadList } from "../../media/upload/MediaUploadList";
|
|
9
|
-
import { useMediaUpload } from "../../media";
|
|
28
|
+
import { ACCOUNT_ENDPOINTS, BRAND_ENDPOINTS, CATEGORY_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
10
29
|
import { apiClient } from "../../../http";
|
|
11
|
-
import {
|
|
30
|
+
import { Alert, PaginatedSelect, Stack } from "../../../ui";
|
|
31
|
+
import { applyZodIssues } from "../../../ui/forms/apply-zod-issues";
|
|
32
|
+
import { FormErrorSummary } from "../../../ui/forms/FormErrorSummary";
|
|
33
|
+
import { FormShellContext, useFormShellState } from "../../../ui/forms/FormShell";
|
|
34
|
+
import { buildSectionsFromSchema } from "../../shell/build-sections";
|
|
35
|
+
import { SectionForm, useSectionFormNav } from "../../shell/SectionForm";
|
|
36
|
+
import { useMediaUpload } from "../../media";
|
|
37
|
+
import { MediaUploadList } from "../../media/upload/MediaUploadList";
|
|
12
38
|
import { createCatalogueItemSchema } from "../schemas/validation";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
{
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
{
|
|
21
|
-
]
|
|
39
|
+
/** PUBLIC endpoints — this is a buyer surface; the admin ones would 403. */
|
|
40
|
+
async function loadOptionsFrom(endpoint, query, page) {
|
|
41
|
+
const params = new URLSearchParams({ page: String(page), pageSize: "25" });
|
|
42
|
+
if (query)
|
|
43
|
+
params.set("q", query);
|
|
44
|
+
const res = await apiClient.get(`${endpoint}?${params.toString()}`);
|
|
45
|
+
const data = res ?? {};
|
|
46
|
+
return {
|
|
47
|
+
items: (data.items ?? []).map((c) => ({ value: c.id, label: c.name })),
|
|
48
|
+
hasMore: data.hasMore ?? false,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const loadCategoryOptions = (q, p) => loadOptionsFrom(CATEGORY_ENDPOINTS.LIST, q, p);
|
|
52
|
+
const loadBrandOptions = (q, p) => loadOptionsFrom(BRAND_ENDPOINTS.LIST, q, p);
|
|
22
53
|
export function CatalogueItemEditorView({ item, onSaved }) {
|
|
23
54
|
const isCreate = !item;
|
|
24
55
|
const queryClient = useQueryClient();
|
|
25
56
|
const { upload } = useMediaUpload();
|
|
26
57
|
const uploadIndexRef = React.useRef(0);
|
|
27
|
-
const [
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
58
|
+
const [form, setForm] = React.useState({
|
|
59
|
+
title: item?.title ?? "",
|
|
60
|
+
description: item?.description ?? "",
|
|
61
|
+
condition: item?.condition ?? "",
|
|
62
|
+
quantity: item?.quantity ?? 1,
|
|
63
|
+
price: item?.price ?? 0,
|
|
64
|
+
images: item?.images ?? [],
|
|
65
|
+
mainImage: item?.mainImage ?? item?.images?.[0] ?? "",
|
|
66
|
+
categorySlugs: item?.categorySlugs ?? [],
|
|
67
|
+
brandSlug: item?.brandSlug ?? "",
|
|
68
|
+
visibility: item?.visibility ?? "public",
|
|
69
|
+
});
|
|
70
|
+
const handleUpload = React.useCallback(async (file) => {
|
|
36
71
|
uploadIndexRef.current += 1;
|
|
37
72
|
return upload(file, "catalogue", true, {
|
|
38
73
|
type: "catalogue-image",
|
|
39
|
-
item: title || "item",
|
|
74
|
+
item: form.title || "item",
|
|
40
75
|
index: uploadIndexRef.current,
|
|
41
76
|
});
|
|
42
|
-
};
|
|
77
|
+
}, [upload, form.title]);
|
|
78
|
+
const sections = React.useMemo(() => buildSectionsFromSchema(createCatalogueItemSchema, {
|
|
79
|
+
renderers: {
|
|
80
|
+
images: ({ values, onChange }) => (_jsx(MediaUploadList, { label: "Photos", value: values.images.map((url) => ({ url, type: "image" })), onChange: (fields) => {
|
|
81
|
+
const urls = fields.map((f) => f.url);
|
|
82
|
+
// `mainImage` is derived, so it moves with the gallery rather
|
|
83
|
+
// than pointing at a photo the user has since removed.
|
|
84
|
+
onChange({ images: urls, mainImage: urls[0] ?? "" });
|
|
85
|
+
}, onUpload: handleUpload, accept: "image/*", maxItems: 8, helperText: "Photos older than 30 days must be refreshed before this item can be listed." })),
|
|
86
|
+
categorySlugs: ({ values, onChange }) => (
|
|
87
|
+
// Explicit `<string>`: with `multiple`, `value` is `V[]`, so an
|
|
88
|
+
// inferred V reads the array itself as the option type.
|
|
89
|
+
_jsx(PaginatedSelect, { multiple: true, value: values.categorySlugs, onChange: (v) => onChange({ categorySlugs: v ?? [] }), loadOptions: loadCategoryOptions, placeholder: "Search categories\u2026", searchPlaceholder: "Type a category name\u2026", noResultsText: "No categories found", ariaLabel: "Categories" })),
|
|
90
|
+
brandSlug: ({ values, onChange }) => (_jsx(PaginatedSelect, { value: values.brandSlug || null, onChange: (v) => onChange({ brandSlug: v ?? "" }), loadOptions: loadBrandOptions, placeholder: "Search brands\u2026", searchPlaceholder: "Type a brand name\u2026", noResultsText: "No brands found", ariaLabel: "Brand" })),
|
|
91
|
+
},
|
|
92
|
+
}), [handleUpload]);
|
|
93
|
+
const nav = useSectionFormNav(sections, form, { scope: "user:catalogue-item" });
|
|
94
|
+
const { shellCtx, setFieldError, clearErrors } = useFormShellState(createCatalogueItemSchema, {
|
|
95
|
+
sections: nav.sectionMeta,
|
|
96
|
+
onGoToSection: nav.goToSection,
|
|
97
|
+
fieldToSectionIndex: nav.fieldToSectionIndex,
|
|
98
|
+
});
|
|
43
99
|
const saveMutation = useApiMutation({
|
|
44
100
|
successMessage: isCreate ? "Added to your catalogue" : "Catalogue item updated",
|
|
101
|
+
errorMessage: isCreate ? "Could not add this item." : "Could not save your changes.",
|
|
45
102
|
mutationFn: async () => {
|
|
46
103
|
const payload = {
|
|
47
|
-
title,
|
|
48
|
-
description: description || undefined,
|
|
49
|
-
condition: condition || undefined,
|
|
50
|
-
price: Math.round(Number(price) * 100) / 100,
|
|
51
|
-
quantity: Number(quantity),
|
|
52
|
-
visibility,
|
|
53
|
-
images,
|
|
54
|
-
mainImage: images[0],
|
|
104
|
+
title: form.title,
|
|
105
|
+
description: form.description || undefined,
|
|
106
|
+
condition: form.condition || undefined,
|
|
107
|
+
price: Math.round(Number(form.price) * 100) / 100,
|
|
108
|
+
quantity: Number(form.quantity),
|
|
109
|
+
visibility: form.visibility,
|
|
110
|
+
images: form.images,
|
|
111
|
+
mainImage: form.images[0],
|
|
112
|
+
categorySlugs: form.categorySlugs,
|
|
113
|
+
brandSlug: form.brandSlug || undefined,
|
|
55
114
|
};
|
|
56
|
-
if (isCreate)
|
|
115
|
+
if (isCreate) {
|
|
57
116
|
return apiClient.post(ACCOUNT_ENDPOINTS.CATALOGUE, payload);
|
|
117
|
+
}
|
|
58
118
|
return apiClient.patch(ACCOUNT_ENDPOINTS.CATALOGUE_BY_ID(item.id), payload);
|
|
59
119
|
},
|
|
60
120
|
onSuccess: (saved) => {
|
|
@@ -62,21 +122,21 @@ export function CatalogueItemEditorView({ item, onSaved }) {
|
|
|
62
122
|
onSaved?.(saved.id);
|
|
63
123
|
},
|
|
64
124
|
});
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
125
|
+
const onSubmit = () => {
|
|
126
|
+
clearErrors();
|
|
127
|
+
const parsed = createCatalogueItemSchema.safeParse({
|
|
128
|
+
...form,
|
|
129
|
+
price: Math.round(Number(form.price) * 100) / 100,
|
|
130
|
+
quantity: Number(form.quantity),
|
|
131
|
+
brandSlug: form.brandSlug || undefined,
|
|
132
|
+
});
|
|
133
|
+
if (!parsed.success) {
|
|
134
|
+
applyZodIssues(parsed.error.issues, setFieldError);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
saveMutation.mutate();
|
|
138
|
+
};
|
|
139
|
+
return (_jsxs(Stack, { gap: "md", children: [item?.listingStatus && item.listingStatus !== "not_listed" && (_jsxs(Alert, { variant: "info", children: ["This item is ", item.listingStatus.replace(/_/g, " "), item.listingStatus === "rejected" && item.rejectionReason
|
|
140
|
+
? `: ${item.rejectionReason}`
|
|
141
|
+
: "."] })), _jsxs(FormShellContext.Provider, { value: shellCtx, children: [_jsx(FormErrorSummary, {}), _jsx(SectionForm, { sections: sections, values: form, onChange: (partial) => setForm((prev) => Object.assign({}, prev, partial)), onSubmit: onSubmit, schema: createCatalogueItemSchema, openIds: nav.openIds, onOpenChange: nav.setOpenIds, isLoading: saveMutation.isPending, submitLabel: isCreate ? "Add to Catalogue" : "Save Changes" })] })] }));
|
|
82
142
|
}
|
|
@@ -2,13 +2,13 @@ import { z } from "zod";
|
|
|
2
2
|
export declare const createCatalogueItemSchema: z.ZodObject<{
|
|
3
3
|
title: z.ZodString;
|
|
4
4
|
description: z.ZodOptional<z.ZodString>;
|
|
5
|
+
condition: z.ZodOptional<z.ZodEnum<["new", "like_new", "good", "fair", "poor", "used", "refurbished", "broken", "graded"]>>;
|
|
6
|
+
quantity: z.ZodDefault<z.ZodNumber>;
|
|
5
7
|
images: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
6
8
|
mainImage: z.ZodOptional<z.ZodString>;
|
|
7
|
-
condition: z.ZodOptional<z.ZodEnum<["new", "like_new", "good", "fair", "poor", "used", "refurbished", "broken", "graded"]>>;
|
|
8
9
|
categorySlugs: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
9
10
|
brandSlug: z.ZodOptional<z.ZodString>;
|
|
10
11
|
price: z.ZodOptional<z.ZodNumber>;
|
|
11
|
-
quantity: z.ZodDefault<z.ZodNumber>;
|
|
12
12
|
visibility: z.ZodDefault<z.ZodEnum<["public", "private"]>>;
|
|
13
13
|
}, "strip", z.ZodTypeAny, {
|
|
14
14
|
title: string;
|
|
@@ -36,13 +36,13 @@ export declare const createCatalogueItemSchema: z.ZodObject<{
|
|
|
36
36
|
export declare const updateCatalogueItemSchema: z.ZodObject<{
|
|
37
37
|
title: z.ZodOptional<z.ZodString>;
|
|
38
38
|
description: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
39
|
+
condition: z.ZodOptional<z.ZodOptional<z.ZodEnum<["new", "like_new", "good", "fair", "poor", "used", "refurbished", "broken", "graded"]>>>;
|
|
40
|
+
quantity: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
|
|
39
41
|
images: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodString, "many">>>;
|
|
40
42
|
mainImage: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
41
|
-
condition: z.ZodOptional<z.ZodOptional<z.ZodEnum<["new", "like_new", "good", "fair", "poor", "used", "refurbished", "broken", "graded"]>>>;
|
|
42
43
|
categorySlugs: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
|
|
43
44
|
brandSlug: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
44
45
|
price: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
|
|
45
|
-
quantity: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
|
|
46
46
|
visibility: z.ZodOptional<z.ZodDefault<z.ZodEnum<["public", "private"]>>>;
|
|
47
47
|
}, "strip", z.ZodTypeAny, {
|
|
48
48
|
title?: string | undefined;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { annotate } from "../../shell/field-ui-meta";
|
|
2
3
|
const productConditionSchema = z.enum([
|
|
3
4
|
"new",
|
|
4
5
|
"like_new",
|
|
@@ -11,15 +12,51 @@ const productConditionSchema = z.enum([
|
|
|
11
12
|
"graded",
|
|
12
13
|
]);
|
|
13
14
|
export const createCatalogueItemSchema = z.object({
|
|
14
|
-
title: z.string().min(1, "Title is required"),
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
title: annotate(z.string().min(1, "Title is required"), {
|
|
16
|
+
section: "basics", sectionLabel: "Item", sectionRequired: true,
|
|
17
|
+
order: 1, row: "full", label: "Title",
|
|
18
|
+
}),
|
|
19
|
+
description: annotate(z.string().optional(), {
|
|
20
|
+
section: "basics", order: 2, row: "full", kind: "textarea", label: "Description",
|
|
21
|
+
}),
|
|
22
|
+
condition: annotate(productConditionSchema.optional(), {
|
|
23
|
+
section: "basics", order: 3, row: "pair", kind: "select", label: "Condition",
|
|
24
|
+
}),
|
|
25
|
+
quantity: annotate(z.number().int().min(1).default(1), {
|
|
26
|
+
section: "basics", order: 4, row: "pair", kind: "number", label: "Quantity",
|
|
27
|
+
}),
|
|
28
|
+
/*
|
|
29
|
+
* `kind: "media"` is inferred from the field NAME (field-ui-meta.ts:336),
|
|
30
|
+
* which also sets `sectionKeepMounted` — mandatory here, because a collapsed
|
|
31
|
+
* section unmounts and would discard an in-flight upload. Declared anyway so
|
|
32
|
+
* the section id and order are not left to inference.
|
|
33
|
+
*/
|
|
34
|
+
images: annotate(z.array(z.string()).default([]), {
|
|
35
|
+
section: "media", sectionLabel: "Photos", order: 1, row: "full", kind: "media",
|
|
36
|
+
sectionKeepMounted: true, label: "Photos",
|
|
37
|
+
}),
|
|
38
|
+
/*
|
|
39
|
+
* Derived from `images[0]`, never typed. Rendering it as an editable box
|
|
40
|
+
* lets a user point it at a photo they have since removed from the gallery —
|
|
41
|
+
* the field would then name an image that does not exist on the item.
|
|
42
|
+
*/
|
|
43
|
+
mainImage: annotate(z.string().optional(), {
|
|
44
|
+
section: "media", order: 2, row: "full", kind: "media", label: "Main photo",
|
|
45
|
+
derived: true, tier: "t1-derive", help: "The first photo in the gallery.",
|
|
46
|
+
}),
|
|
47
|
+
categorySlugs: annotate(z.array(z.string()).optional(), {
|
|
48
|
+
section: "classification", sectionLabel: "Filing", order: 1, row: "pair",
|
|
49
|
+
label: "Categories",
|
|
50
|
+
}),
|
|
51
|
+
brandSlug: annotate(z.string().optional(), {
|
|
52
|
+
section: "classification", order: 2, row: "pair", kind: "select", label: "Brand",
|
|
53
|
+
}),
|
|
54
|
+
price: annotate(z.number().min(0).optional(), {
|
|
55
|
+
section: "pricing", sectionLabel: "Value", order: 1, row: "pair", kind: "number",
|
|
56
|
+
label: "Estimated value (₹)",
|
|
57
|
+
}),
|
|
58
|
+
visibility: annotate(z.enum(["public", "private"]).default("public"), {
|
|
59
|
+
section: "visibility", order: 1, row: "pair", kind: "select", label: "Visibility",
|
|
60
|
+
}),
|
|
24
61
|
});
|
|
25
62
|
export const updateCatalogueItemSchema = createCatalogueItemSchema.partial();
|
|
@@ -16,24 +16,25 @@ import { listingTabCounts, } from "../../../_internal/server/features/products/l
|
|
|
16
16
|
import { CATEGORY_PAGE_TABS } from "../../products/constants/listing-tabs";
|
|
17
17
|
import { enabledCategoryTypes, enabledListingTypes } from "../../../_internal/shared/listing-types/feature-flags";
|
|
18
18
|
import { siteSettingsRepository } from "../../../repositories";
|
|
19
|
+
import { safeRead } from "../../../errors/safe-read";
|
|
19
20
|
const __O = {
|
|
20
21
|
hidden: "overflow-hidden",
|
|
21
22
|
};
|
|
22
23
|
export async function BrandDetailPageView({ slug, initialBrand }) {
|
|
24
|
+
// The brand IS this page's subject — a read failure must surface rather than
|
|
25
|
+
// render an anonymous, empty brand page. `undefined` still means "no such
|
|
26
|
+
// brand slug".
|
|
23
27
|
const brand = (initialBrand ?? (await categoriesRepository
|
|
24
|
-
.getCategoryBySlug(slug)
|
|
25
|
-
.catch(() => undefined)));
|
|
28
|
+
.getCategoryBySlug(slug)) ?? undefined);
|
|
26
29
|
const brandName = brand?.name;
|
|
27
30
|
const [productsResult, tabCounts, allBundles, activeBrands, groupedListings, settings] = await Promise.all([
|
|
28
31
|
brandName
|
|
29
|
-
? productRepository
|
|
30
|
-
.list({
|
|
32
|
+
? safeRead(() => productRepository.list({
|
|
31
33
|
filters: sieveAnd(sieveFilter("status", SIEVE_OP.EQ, "published"), sieveFilter("brand", SIEVE_OP.EQ, brandName), sieveFilter("listingType", SIEVE_OP.EQ, "standard")),
|
|
32
34
|
sorts: sortBy("createdAt", "DESC"),
|
|
33
35
|
page: 1,
|
|
34
36
|
pageSize: 24,
|
|
35
|
-
})
|
|
36
|
-
.catch(() => null)
|
|
37
|
+
}), { route: "/brands/[slug]", key: "brand.products", fallback: null })
|
|
37
38
|
: Promise.resolve(null),
|
|
38
39
|
// One count per tab, derived from CATEGORY_PAGE_TABS. Four of the nine tabs
|
|
39
40
|
// (classifieds, digital codes, live, art) had no count at all and could
|
|
@@ -47,16 +48,31 @@ export async function BrandDetailPageView({ slug, initialBrand }) {
|
|
|
47
48
|
// We pull all bundle categories and filter client-side by brandSlug —
|
|
48
49
|
// no dedicated repository query needed at this catalog's bundle volume.
|
|
49
50
|
brand?.slug
|
|
50
|
-
? categoriesRepository
|
|
51
|
-
.listByType("bundle", { activeOnly: true, limit: 50 })
|
|
52
|
-
.catch(() => [])
|
|
51
|
+
? safeRead(() => categoriesRepository.listByType("bundle", { activeOnly: true, limit: 50 }), { route: "/brands/[slug]", key: "brand.bundles", fallback: [] })
|
|
53
52
|
: Promise.resolve([]),
|
|
54
53
|
// Related brands — every other active brand row, excluding this one.
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
// `as unknown` is load-bearing only because CategoryDocument.createdAt is a
|
|
55
|
+
// Date while CategoryItem.createdAt is a string — a pre-existing mismatch
|
|
56
|
+
// the old `.catch(() => [])` union happened to paper over.
|
|
57
|
+
safeRead(() => categoriesRepository.findActiveBrands(), {
|
|
58
|
+
route: "/brands/[slug]",
|
|
59
|
+
key: "brand.relatedBrands",
|
|
60
|
+
fallback: [],
|
|
61
|
+
}),
|
|
62
|
+
brand?.slug
|
|
63
|
+
? safeRead(() => getGroupsForBrand(brand.slug), {
|
|
64
|
+
route: "/brands/[slug]",
|
|
65
|
+
key: "brand.groupedListings",
|
|
66
|
+
fallback: [],
|
|
67
|
+
})
|
|
68
|
+
: Promise.resolve([]),
|
|
57
69
|
// Feature flags — accepted by BrandDetailTabs all along but never passed,
|
|
58
70
|
// so a disabled listing type still showed its tab here.
|
|
59
|
-
siteSettingsRepository.findById("global")
|
|
71
|
+
safeRead(() => siteSettingsRepository.findById("global"), {
|
|
72
|
+
route: "/brands/[slug]",
|
|
73
|
+
key: "brand.siteSettings",
|
|
74
|
+
fallback: null,
|
|
75
|
+
}),
|
|
60
76
|
]);
|
|
61
77
|
const brandBundles = brand?.slug
|
|
62
78
|
? allBundles.filter((b) => b.brandSlug === brand.slug)
|
|
@@ -15,14 +15,17 @@ import { listingTabCounts, } from "../../../_internal/server/features/products/l
|
|
|
15
15
|
import { CATEGORY_PAGE_TABS } from "../../products/constants/listing-tabs";
|
|
16
16
|
import { enabledCategoryTypes, enabledListingTypes } from "../../../_internal/shared/listing-types/feature-flags";
|
|
17
17
|
import { siteSettingsRepository } from "../../../repositories";
|
|
18
|
+
import { safeRead } from "../../../errors/safe-read";
|
|
18
19
|
const __O = {
|
|
19
20
|
hidden: "overflow-hidden",
|
|
20
21
|
xAuto: "overflow-x-auto",
|
|
21
22
|
};
|
|
22
23
|
export async function CategoryDetailPageView({ slug }) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
// The category IS this page's subject — a read failure must surface rather
|
|
25
|
+
// than render an anonymous, empty category page. `undefined` still means
|
|
26
|
+
// "no such category slug".
|
|
27
|
+
const category = ((await categoriesRepository
|
|
28
|
+
.getCategoryBySlug(slug)) ?? undefined);
|
|
26
29
|
// Products carry their FULL ancestor chain in `categorySlugs`, so matching on
|
|
27
30
|
// this category's own id already returns the whole subtree — no descendant
|
|
28
31
|
// expansion needed. Expanding it was also a latent outage: `categoriesIn` is
|
|
@@ -33,14 +36,12 @@ export async function CategoryDetailPageView({ slug }) {
|
|
|
33
36
|
const categoriesIn = category?.id ? [category.id] : null;
|
|
34
37
|
const [productsResult, tabCounts, bundlesResult, childCategories, rootSiblingCategories, groupedListings, settings] = await Promise.all([
|
|
35
38
|
categoriesIn
|
|
36
|
-
? productRepository
|
|
37
|
-
.list({
|
|
39
|
+
? safeRead(() => productRepository.list({
|
|
38
40
|
filters: sieveAnd(sieveFilter("status", SIEVE_OP.EQ, "published"), sieveFilter("listingType", SIEVE_OP.EQ, "standard")),
|
|
39
41
|
sorts: sortBy("createdAt", "DESC"),
|
|
40
42
|
page: 1,
|
|
41
43
|
pageSize: 24,
|
|
42
|
-
}, { categoriesIn })
|
|
43
|
-
.catch(() => null)
|
|
44
|
+
}, { categoriesIn }), { route: "/categories/[slug]", key: "category.products", fallback: null })
|
|
44
45
|
: Promise.resolve(null),
|
|
45
46
|
// One count per tab, derived from CATEGORY_PAGE_TABS itself — so every
|
|
46
47
|
// listing type is counted and a type with nothing in this category hides.
|
|
@@ -51,24 +52,40 @@ export async function CategoryDetailPageView({ slug }) {
|
|
|
51
52
|
// SB-UNI-D — bundles fetched from the categories collection. We pull
|
|
52
53
|
// all active bundle rows; the carousel filters by category affinity.
|
|
53
54
|
categoriesIn
|
|
54
|
-
? categoriesRepository
|
|
55
|
-
.listByType("bundle", { activeOnly: true, limit: 50 })
|
|
56
|
-
.catch(() => [])
|
|
55
|
+
? safeRead(() => categoriesRepository.listByType("bundle", { activeOnly: true, limit: 50 }), { route: "/categories/[slug]", key: "category.bundles", fallback: [] })
|
|
57
56
|
: Promise.resolve([]),
|
|
58
57
|
category?.id
|
|
59
|
-
? categoriesRepository.getChildren(category.id)
|
|
58
|
+
? safeRead(() => categoriesRepository.getChildren(category.id), {
|
|
59
|
+
route: "/categories/[slug]",
|
|
60
|
+
key: "category.children",
|
|
61
|
+
fallback: [],
|
|
62
|
+
})
|
|
60
63
|
: Promise.resolve([]),
|
|
61
64
|
// Related categories — every other category sharing this category's root
|
|
62
65
|
// (siblings + cousins across the tree, up to the tier-0/1/2 depth the
|
|
63
66
|
// catalog actually uses), not just direct children.
|
|
64
67
|
category?.rootId
|
|
65
|
-
? categoriesRepository.getCategoriesByRootId(category.rootId)
|
|
68
|
+
? safeRead(() => categoriesRepository.getCategoriesByRootId(category.rootId), {
|
|
69
|
+
route: "/categories/[slug]",
|
|
70
|
+
key: "category.rootSiblings",
|
|
71
|
+
fallback: [],
|
|
72
|
+
})
|
|
73
|
+
: Promise.resolve([]),
|
|
74
|
+
category?.slug
|
|
75
|
+
? safeRead(() => getGroupsForCategory(category.slug), {
|
|
76
|
+
route: "/categories/[slug]",
|
|
77
|
+
key: "category.groupedListings",
|
|
78
|
+
fallback: [],
|
|
79
|
+
})
|
|
66
80
|
: Promise.resolve([]),
|
|
67
|
-
category?.slug ? getGroupsForCategory(category.slug).catch(() => []) : Promise.resolve([]),
|
|
68
81
|
// Listing/category-type feature flags. This page accepted the props all
|
|
69
82
|
// along but never passed them, so an admin disabling a listing type still
|
|
70
83
|
// saw its tab here while the store page correctly hid it.
|
|
71
|
-
siteSettingsRepository.findById("global")
|
|
84
|
+
safeRead(() => siteSettingsRepository.findById("global"), {
|
|
85
|
+
route: "/categories/[slug]",
|
|
86
|
+
key: "category.siteSettings",
|
|
87
|
+
fallback: null,
|
|
88
|
+
}),
|
|
72
89
|
]);
|
|
73
90
|
const relatedCategories = rootSiblingCategories.filter((c) => c.id !== category?.id && (!c.categoryType || c.categoryType === "category"));
|
|
74
91
|
// Stores tab — stores whose storeCategory is this category or ANY descendant.
|
|
@@ -82,18 +99,18 @@ export async function CategoryDetailPageView({ slug }) {
|
|
|
82
99
|
// which caps at 30 values, hence the chunking.
|
|
83
100
|
const storeCategorySlugs = [
|
|
84
101
|
slug,
|
|
85
|
-
...(await categoriesRepository
|
|
86
|
-
|
|
87
|
-
.
|
|
102
|
+
...(await safeRead(() => categoriesRepository.getDescendantIds(category?.id ?? ""), {
|
|
103
|
+
route: "/categories/[slug]",
|
|
104
|
+
key: "category.descendantIds",
|
|
105
|
+
fallback: [],
|
|
106
|
+
})),
|
|
88
107
|
].filter(Boolean);
|
|
89
108
|
const SLUG_CHUNK = 30;
|
|
90
109
|
const slugChunks = [];
|
|
91
110
|
for (let i = 0; i < storeCategorySlugs.length; i += SLUG_CHUNK) {
|
|
92
111
|
slugChunks.push(storeCategorySlugs.slice(i, i + SLUG_CHUNK));
|
|
93
112
|
}
|
|
94
|
-
const storeResults = await Promise.all(slugChunks.map((chunk) => storeRepository
|
|
95
|
-
.listStores({ filters: sieveFilter("storeCategory", SIEVE_OP.EQ, chunk.join("|")), page: 1, pageSize: 50 }, true)
|
|
96
|
-
.catch(() => null)));
|
|
113
|
+
const storeResults = await Promise.all(slugChunks.map((chunk) => safeRead(() => storeRepository.listStores({ filters: sieveFilter("storeCategory", SIEVE_OP.EQ, chunk.join("|")), page: 1, pageSize: 50 }, true), { route: "/categories/[slug]", key: "category.stores", fallback: null })));
|
|
97
114
|
const seen = new Set();
|
|
98
115
|
const categoryStores = storeResults
|
|
99
116
|
.flatMap((r) => r?.items ?? [])
|
|
@@ -480,10 +480,12 @@ export class CategoriesRepository extends BaseRepository {
|
|
|
480
480
|
.collection(this.collection)
|
|
481
481
|
.doc(categoryId)
|
|
482
482
|
.update({ [CATEGORY_FIELDS.VIEW_COUNT]: increment(1) });
|
|
483
|
+
// Fire-and-forget analytics: a lost view increment changes nothing that
|
|
484
|
+
// renders, so it must never break the category read path it rides along
|
|
485
|
+
// with — the count is approximate by design.
|
|
483
486
|
}
|
|
484
487
|
catch (_err) {
|
|
485
488
|
void normalizeError(_err);
|
|
486
|
-
// View analytics must not break category read path.
|
|
487
489
|
}
|
|
488
490
|
}
|
|
489
491
|
generateSublistingId(name) {
|