@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
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { sieveFilter, sieveAnd, SIEVE_OP } from "@mohasinac/appkit";
|
|
3
3
|
import { cache } from "react";
|
|
4
4
|
import { storeRepository, siteSettingsRepository, reviewRepository, couponsRepository } from "../../../repositories";
|
|
5
|
+
import { safeRead } from "../../../errors/safe-read";
|
|
5
6
|
import { ROUTES } from "../../../next";
|
|
6
7
|
import { Container, Main, Section, Text } from "../../../ui";
|
|
7
8
|
import { STORE_PAGE_TABS } from "../../products/constants/listing-tabs";
|
|
@@ -26,7 +27,10 @@ const STORE_LISTING_HREF = {
|
|
|
26
27
|
// a real non-zero count and landed on a page with none of those items.
|
|
27
28
|
art: (slug) => String(ROUTES.PUBLIC.STORE_ART(slug)),
|
|
28
29
|
};
|
|
29
|
-
|
|
30
|
+
// The store IS this layout's subject, and `findBySlug` already returns null for
|
|
31
|
+
// "no such slug" — swallowing a read failure into the same value would render
|
|
32
|
+
// the "Store not found." branch below for a live store during an outage.
|
|
33
|
+
export const getStoreBySlug = cache((slug) => storeRepository.findBySlug(slug));
|
|
30
34
|
function tabLabel(base, count) {
|
|
31
35
|
if (!count)
|
|
32
36
|
return base;
|
|
@@ -39,9 +43,14 @@ export async function StoreDetailLayoutView({ storeSlug, activeTab, children, sc
|
|
|
39
43
|
}
|
|
40
44
|
const storeId = store?.id;
|
|
41
45
|
const [settings, trust] = await Promise.all([
|
|
42
|
-
siteSettingsRepository.findById("global")
|
|
46
|
+
safeRead(() => siteSettingsRepository.findById("global"), {
|
|
47
|
+
route: "/stores/[slug]", key: "store.siteSettings", fallback: null,
|
|
48
|
+
}),
|
|
43
49
|
scamRegistryEnabled && storeId
|
|
44
|
-
|
|
50
|
+
// Fails open to "no trust verdict", which hides the badge entirely rather
|
|
51
|
+
// than asserting a seller is clear — but that has to be recorded, since a
|
|
52
|
+
// missing badge is exactly what a clean seller looks like.
|
|
53
|
+
? safeRead(() => getSellerTrustStatus(storeId), { route: "/stores/[slug]", key: "store.sellerTrust", fallback: undefined })
|
|
45
54
|
: Promise.resolve(undefined),
|
|
46
55
|
]);
|
|
47
56
|
// One derived batch instead of nine copy-pasted per-type queries. The tabs
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BaseRepository } from "../../../providers/db-firebase";
|
|
2
2
|
import type { FirebaseSieveFields, FirebaseSieveResult, SieveModel } from "../../../providers/db-firebase";
|
|
3
|
+
import type { JsonValue } from "../../../schemas/types";
|
|
3
4
|
import type { DocumentSnapshot } from "firebase-admin/firestore";
|
|
4
5
|
import { type SupportTicketDocument, type SupportTicketCreateInput, type SupportTicketUpdateInput, type TicketMessage, type TicketStatus } from "../schemas/firestore";
|
|
5
6
|
import { type HistoryActor } from "../../../_internal/shared/history/index";
|
|
@@ -22,10 +23,30 @@ export declare class SupportRepository extends BaseRepository<SupportTicketDocum
|
|
|
22
23
|
*/
|
|
23
24
|
protected piiFields: readonly ["userEmail", "userDisplayName", "assignedToName"];
|
|
24
25
|
constructor();
|
|
26
|
+
/**
|
|
27
|
+
* Derived on every write path via `applyWriteHooks`.
|
|
28
|
+
*
|
|
29
|
+
* 🛑 `subject` only. `description` and every message body are PII-encrypted
|
|
30
|
+
* at rest, and a plaintext prefix index over an encrypted field gives back
|
|
31
|
+
* precisely what the encryption withheld — the same reason an email is an
|
|
32
|
+
* exact-match blind index rather than a searchable corpus.
|
|
33
|
+
*/
|
|
34
|
+
protected buildSearchTxtFor(data: Record<string, JsonValue>): string[] | null;
|
|
25
35
|
/** Decrypt on read so callers see the shape they wrote. */
|
|
26
36
|
protected mapDoc<D = SupportTicketDocument>(snap: DocumentSnapshot): D;
|
|
27
37
|
createTicket(input: SupportTicketCreateInput): Promise<SupportTicketDocument>;
|
|
28
38
|
getUserTickets(userId: string, page?: number, pageSize?: number): Promise<FirebaseSieveResult<SupportTicketDocument>>;
|
|
39
|
+
/**
|
|
40
|
+
* Every ticket ABOUT one store.
|
|
41
|
+
*
|
|
42
|
+
* Keyed on the top-level `storeId`, not `relatedParties.storeId` — the
|
|
43
|
+
* nested one is unindexed and unqueryable, which is the whole reason a
|
|
44
|
+
* seller had no way to see the tickets raised against their own store.
|
|
45
|
+
*/
|
|
46
|
+
getStoreTickets(storeId: string, page?: number, pageSize?: number, opts?: {
|
|
47
|
+
search?: string;
|
|
48
|
+
status?: string;
|
|
49
|
+
}): Promise<FirebaseSieveResult<SupportTicketDocument>>;
|
|
29
50
|
getTicketById(ticketId: string): Promise<SupportTicketDocument | null>;
|
|
30
51
|
countActiveTickets(userId: string): Promise<number>;
|
|
31
52
|
getActiveOrderTicket(userId: string, orderId: string): Promise<SupportTicketDocument | null>;
|
|
@@ -3,6 +3,9 @@ import { BaseRepository, prepareForFirestore, parseSieveDateValue, } from "../..
|
|
|
3
3
|
import { normalizeError } from "../../../errors/normalize";
|
|
4
4
|
import { DatabaseError } from "../../../errors";
|
|
5
5
|
import { SUPPORT_TICKET_FIELDS } from "../../../constants/field-names";
|
|
6
|
+
import { buildSearchTxt } from "../../../utils/search-txt";
|
|
7
|
+
import { planSearchTxt, emptySearchResult } from "../../../utils/search-txt-query";
|
|
8
|
+
import { sieveAnd, sieveFilter, SIEVE_OP } from "../../../utils/sieve-builder";
|
|
6
9
|
import { decryptPiiFields } from "../../../security/pii-encrypt";
|
|
7
10
|
import { SUPPORT_TICKET_COLLECTION, SUPPORT_TICKET_PII_FIELDS, SUPPORT_TICKET_TRACKED_FIELDS, TicketStatusValues, ACTIVE_TICKET_STATUSES, } from "../schemas/firestore";
|
|
8
11
|
import { withHistory } from "../../../_internal/shared/history/index";
|
|
@@ -19,6 +22,18 @@ export class SupportRepository extends BaseRepository {
|
|
|
19
22
|
*/
|
|
20
23
|
this.piiFields = SUPPORT_TICKET_PII_FIELDS;
|
|
21
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Derived on every write path via `applyWriteHooks`.
|
|
27
|
+
*
|
|
28
|
+
* 🛑 `subject` only. `description` and every message body are PII-encrypted
|
|
29
|
+
* at rest, and a plaintext prefix index over an encrypted field gives back
|
|
30
|
+
* precisely what the encryption withheld — the same reason an email is an
|
|
31
|
+
* exact-match blind index rather than a searchable corpus.
|
|
32
|
+
*/
|
|
33
|
+
buildSearchTxtFor(data) {
|
|
34
|
+
const subject = typeof data.subject === "string" ? data.subject : "";
|
|
35
|
+
return subject ? buildSearchTxt([subject]) : null;
|
|
36
|
+
}
|
|
22
37
|
/** Decrypt on read so callers see the shape they wrote. */
|
|
23
38
|
mapDoc(snap) {
|
|
24
39
|
const raw = super.mapDoc(snap);
|
|
@@ -51,6 +66,49 @@ export class SupportRepository extends BaseRepository {
|
|
|
51
66
|
};
|
|
52
67
|
return this.sieveQuery(model, SupportRepository.SIEVE_FIELDS, { defaultPageSize: pageSize, maxPageSize: 50 });
|
|
53
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Every ticket ABOUT one store.
|
|
71
|
+
*
|
|
72
|
+
* Keyed on the top-level `storeId`, not `relatedParties.storeId` — the
|
|
73
|
+
* nested one is unindexed and unqueryable, which is the whole reason a
|
|
74
|
+
* seller had no way to see the tickets raised against their own store.
|
|
75
|
+
*/
|
|
76
|
+
async getStoreTickets(storeId, page = 1, pageSize = 20, opts) {
|
|
77
|
+
/*
|
|
78
|
+
* The term is tokenised the same way the index was built, and only the
|
|
79
|
+
* FIRST token is pushed down — Firestore allows one `array-contains` per
|
|
80
|
+
* query. The rest are applied in memory by `sieveQuery`'s own pass, which
|
|
81
|
+
* is what keeps a two-word search from silently matching on the first word
|
|
82
|
+
* alone (the partial-pushdown trap in Root Cause #62).
|
|
83
|
+
*/
|
|
84
|
+
const clauses = [
|
|
85
|
+
sieveFilter(SUPPORT_TICKET_FIELDS.STORE_ID, SIEVE_OP.EQ, storeId),
|
|
86
|
+
...(opts?.status
|
|
87
|
+
? [sieveFilter(SUPPORT_TICKET_FIELDS.STATUS, SIEVE_OP.EQ, opts.status)]
|
|
88
|
+
: []),
|
|
89
|
+
];
|
|
90
|
+
const plan = planSearchTxt(opts?.search);
|
|
91
|
+
/*
|
|
92
|
+
* A search that narrowed to no usable term returns NOTHING, not every
|
|
93
|
+
* ticket about the store. The alternative — falling through to the
|
|
94
|
+
* unfiltered list — is the shape where a user types a real subject,
|
|
95
|
+
* sees every row, and concludes the search is broken rather than that
|
|
96
|
+
* their term was stripped.
|
|
97
|
+
*/
|
|
98
|
+
if (plan.empty)
|
|
99
|
+
return emptySearchResult();
|
|
100
|
+
let baseQuery = this.getCollection().where(SUPPORT_TICKET_FIELDS.STORE_ID, "==", storeId);
|
|
101
|
+
if (plan.head) {
|
|
102
|
+
baseQuery = baseQuery.where(SUPPORT_TICKET_FIELDS.SEARCH_TXT, "array-contains", plan.head);
|
|
103
|
+
}
|
|
104
|
+
const model = {
|
|
105
|
+
filters: sieveAnd(...clauses.slice(1)),
|
|
106
|
+
sorts: "-createdAt",
|
|
107
|
+
page,
|
|
108
|
+
pageSize,
|
|
109
|
+
};
|
|
110
|
+
return this.sieveQuery(model, SupportRepository.SIEVE_FIELDS, { defaultPageSize: pageSize, maxPageSize: 50, baseQuery });
|
|
111
|
+
}
|
|
54
112
|
async getTicketById(ticketId) {
|
|
55
113
|
return this.findById(ticketId);
|
|
56
114
|
}
|
|
@@ -185,6 +243,11 @@ export class SupportRepository extends BaseRepository {
|
|
|
185
243
|
}
|
|
186
244
|
SupportRepository.SIEVE_FIELDS = {
|
|
187
245
|
userId: { canFilter: true, canSort: false },
|
|
246
|
+
// The store a ticket is ABOUT. Filterable so a seller can list their own —
|
|
247
|
+
// `relatedParties.storeId` is not in this map and never was, which is why
|
|
248
|
+
// no seller-scoped query was possible.
|
|
249
|
+
storeId: { canFilter: true, canSort: false },
|
|
250
|
+
searchTxt: { canFilter: true, canSort: false },
|
|
188
251
|
status: { canFilter: true, canSort: false },
|
|
189
252
|
category: { canFilter: true, canSort: false },
|
|
190
253
|
priority: { canFilter: true, canSort: false },
|
|
@@ -84,6 +84,21 @@ export interface SupportTicketDocument extends BaseDocument {
|
|
|
84
84
|
description: string;
|
|
85
85
|
/** Linked order ID — required when category === "order_issue". */
|
|
86
86
|
orderId?: string;
|
|
87
|
+
/**
|
|
88
|
+
* The store this ticket is ABOUT, when it is about one.
|
|
89
|
+
*
|
|
90
|
+
* 🛑 Top-level and indexed, unlike `relatedParties.storeId`. That field
|
|
91
|
+
* exists and cannot serve a query: it is not in
|
|
92
|
+
* `SUPPORT_TICKET_INDEXED_FIELDS`, not in the repository's `SIEVE_FIELDS`,
|
|
93
|
+
* and has no composite index — so "every ticket about my store" was
|
|
94
|
+
* unanswerable, which is why no seller support surface existed.
|
|
95
|
+
*
|
|
96
|
+
* `relatedParties.storeId` stays as what it always was: the admin's
|
|
97
|
+
* after-the-fact linkage, set through the ST-6 panel. This one is set at
|
|
98
|
+
* creation, by the seller-facing route, and is what the seller's own list
|
|
99
|
+
* queries on.
|
|
100
|
+
*/
|
|
101
|
+
storeId?: string;
|
|
87
102
|
/**
|
|
88
103
|
* ST-6 — subjects of the ticket. Admin/support assignable. `orderId` is
|
|
89
104
|
* mirrored here for consistency when set via the linked-parties panel.
|
|
@@ -102,6 +117,16 @@ export interface SupportTicketDocument extends BaseDocument {
|
|
|
102
117
|
internalNotes?: string;
|
|
103
118
|
/** Threaded conversation. Ordered by createdAt asc. */
|
|
104
119
|
messages: TicketMessage[];
|
|
120
|
+
/**
|
|
121
|
+
* Word-prefix search tokens. Derived on write by `buildSearchTxtFor`.
|
|
122
|
+
*
|
|
123
|
+
* 🛑 Built from `subject` ONLY — not `description`, and not the message
|
|
124
|
+
* bodies. Those are PII-encrypted at rest (`SUPPORT_TICKET_PII_FIELDS`), and
|
|
125
|
+
* a plaintext token index over an encrypted field hands back exactly what
|
|
126
|
+
* the encryption was there to withhold. The subject is what an admin scans a
|
|
127
|
+
* list by, and it is not encrypted.
|
|
128
|
+
*/
|
|
129
|
+
searchTxt?: string[];
|
|
105
130
|
/**
|
|
106
131
|
* Stamped by the repository the first time `status` becomes `resolved` /
|
|
107
132
|
* `closed`. Both were declared, given `SUPPORT_TICKET_FIELDS` constants and
|
|
@@ -141,11 +166,11 @@ export declare const SUPPORT_TICKET_TRACKED_FIELDS: readonly ["status", "priorit
|
|
|
141
166
|
* (`assignedTo`) and never the name.
|
|
142
167
|
*/
|
|
143
168
|
export declare const SUPPORT_TICKET_PII_FIELDS: readonly ["userEmail", "userDisplayName", "assignedToName"];
|
|
144
|
-
export type SupportTicketCreateInput = Pick<SupportTicketDocument, "userId" | "userEmail" | "userDisplayName" | "category" | "subject" | "description" | "orderId">;
|
|
169
|
+
export type SupportTicketCreateInput = Pick<SupportTicketDocument, "userId" | "userEmail" | "userDisplayName" | "category" | "subject" | "description" | "orderId" | "storeId">;
|
|
145
170
|
export type SupportTicketUpdateInput = Partial<Pick<SupportTicketDocument, "status" | "priority" | "assignedTo" | "assignedToName" | "internalNotes" | "relatedParties">>;
|
|
146
171
|
export declare const SUPPORT_TICKET_COLLECTION: "supportTickets";
|
|
147
172
|
export declare const SUPPORT_TICKET_ID_PREFIX: "ticket-";
|
|
148
|
-
export declare const SUPPORT_TICKET_INDEXED_FIELDS: readonly ["userId", "status", "category", "priority", "assignedTo", "orderId", "createdAt", "updatedAt"];
|
|
173
|
+
export declare const SUPPORT_TICKET_INDEXED_FIELDS: readonly ["userId", "storeId", "searchTxt", "status", "category", "priority", "assignedTo", "orderId", "createdAt", "updatedAt"];
|
|
149
174
|
export declare const DEFAULT_SUPPORT_TICKET_DATA: Partial<SupportTicketDocument>;
|
|
150
175
|
export declare const SUPPORT_TICKET_FIELDS: {
|
|
151
176
|
readonly ID: "id";
|
|
@@ -104,6 +104,8 @@ export const SUPPORT_TICKET_COLLECTION = "supportTickets";
|
|
|
104
104
|
export const SUPPORT_TICKET_ID_PREFIX = "ticket-";
|
|
105
105
|
export const SUPPORT_TICKET_INDEXED_FIELDS = [
|
|
106
106
|
"userId",
|
|
107
|
+
"storeId",
|
|
108
|
+
"searchTxt",
|
|
107
109
|
"status",
|
|
108
110
|
"category",
|
|
109
111
|
"priority",
|
|
@@ -64,6 +64,13 @@ export const supportTicketCreateSchema = z
|
|
|
64
64
|
order: 4,
|
|
65
65
|
row: "pair",
|
|
66
66
|
help: "Required when the category is an order issue.",
|
|
67
|
+
/*
|
|
68
|
+
* Only meaningful for an order complaint, and paired with `visibleValues`
|
|
69
|
+
* at the payload so an id typed before switching category is not sent
|
|
70
|
+
* with a ticket that has nothing to do with an order. The `superRefine`
|
|
71
|
+
* below makes it required in the one case where it shows.
|
|
72
|
+
*/
|
|
73
|
+
when: (v) => v.category === TicketCategoryValues.ORDER_ISSUE,
|
|
67
74
|
}),
|
|
68
75
|
})
|
|
69
76
|
.superRefine((v, ctx) => {
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* 🛑 `annotate()` must be the OUTERMOST call on each field — it keys a WeakMap
|
|
4
|
+
* by schema instance and every zod wrapper returns a new one.
|
|
5
|
+
*/
|
|
6
|
+
export declare const checklistItemFormSchema: z.ZodObject<{
|
|
7
|
+
label: z.ZodString;
|
|
8
|
+
description: z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>;
|
|
9
|
+
href: z.ZodUnion<[z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>, z.ZodLiteral<"">]>;
|
|
10
|
+
groupLabel: z.ZodString;
|
|
11
|
+
groupKey: z.ZodString;
|
|
12
|
+
pageLabel: z.ZodString;
|
|
13
|
+
pageKey: z.ZodString;
|
|
14
|
+
order: z.ZodNumber;
|
|
15
|
+
phase: z.ZodNumber;
|
|
16
|
+
isActive: z.ZodBoolean;
|
|
17
|
+
adminOnly: z.ZodBoolean;
|
|
18
|
+
}, "strip", z.ZodTypeAny, {
|
|
19
|
+
label: string;
|
|
20
|
+
isActive: boolean;
|
|
21
|
+
order: number;
|
|
22
|
+
groupKey: string;
|
|
23
|
+
pageKey: string;
|
|
24
|
+
phase: number;
|
|
25
|
+
groupLabel: string;
|
|
26
|
+
pageLabel: string;
|
|
27
|
+
adminOnly: boolean;
|
|
28
|
+
href?: string | undefined;
|
|
29
|
+
description?: string | undefined;
|
|
30
|
+
}, {
|
|
31
|
+
label: string;
|
|
32
|
+
isActive: boolean;
|
|
33
|
+
order: number;
|
|
34
|
+
groupKey: string;
|
|
35
|
+
pageKey: string;
|
|
36
|
+
phase: number;
|
|
37
|
+
groupLabel: string;
|
|
38
|
+
pageLabel: string;
|
|
39
|
+
adminOnly: boolean;
|
|
40
|
+
href?: string | undefined;
|
|
41
|
+
description?: string | undefined;
|
|
42
|
+
}>;
|
|
43
|
+
export type ChecklistItemFormValues = z.infer<typeof checklistItemFormSchema>;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* WHY: `AdminTesterChecklistItemEditorView` declared a five-field
|
|
3
|
+
* `.passthrough()` schema inside the component against eleven controls,
|
|
4
|
+
* passed it to `<Form schema>`, and validated with one `if` on `label`.
|
|
5
|
+
* Two of the five — `groupKey` and `pageKey` — were rendered as raw
|
|
6
|
+
* `<Input>` with no `name`, so even had the schema run, `applyZodIssues`
|
|
7
|
+
* would have had nowhere to put their errors. The six fields it did not
|
|
8
|
+
* declare included `href`, which the tester hub turns into a "Go test
|
|
9
|
+
* this →" link and which `audit-tester-checklist-hrefs` enforces on the
|
|
10
|
+
* SEED data while the admin editor accepted anything at all.
|
|
11
|
+
* WHAT: The checklist-item editor's schema — every rendered field, annotated
|
|
12
|
+
* for `buildSectionsFromSchema`.
|
|
13
|
+
*
|
|
14
|
+
* ## `href` is checked here as well as in the audit
|
|
15
|
+
*
|
|
16
|
+
* The audit only sees `tester-checklist-seed-data.ts`. An admin authoring a
|
|
17
|
+
* case through the UI bypasses it entirely, and a bad link is invisible until
|
|
18
|
+
* a tester clicks it and lands on a 404 — the same dead-deeplink shape as
|
|
19
|
+
* Root Cause #32. A leading-slash rule cannot prove the route exists, but it
|
|
20
|
+
* does reject the two things actually typed by hand: a bare page name, and a
|
|
21
|
+
* full URL to another origin.
|
|
22
|
+
*
|
|
23
|
+
* EXPORTS:
|
|
24
|
+
* checklistItemFormSchema, type ChecklistItemFormValues
|
|
25
|
+
*
|
|
26
|
+
* @tag domain:tester
|
|
27
|
+
* @tag layer:schema
|
|
28
|
+
* @tag pattern:none
|
|
29
|
+
* @tag access:isomorphic
|
|
30
|
+
* @tag consumers:AdminTesterChecklistItemEditorView
|
|
31
|
+
* @tag sideEffects:none
|
|
32
|
+
*/
|
|
33
|
+
import { z } from "zod";
|
|
34
|
+
import { annotate } from "../../shell/field-ui-meta";
|
|
35
|
+
/**
|
|
36
|
+
* 🛑 `annotate()` must be the OUTERMOST call on each field — it keys a WeakMap
|
|
37
|
+
* by schema instance and every zod wrapper returns a new one.
|
|
38
|
+
*/
|
|
39
|
+
export const checklistItemFormSchema = z.object({
|
|
40
|
+
label: annotate(z
|
|
41
|
+
.string()
|
|
42
|
+
.min(3, "The test case needs at least 3 characters.")
|
|
43
|
+
.max(500, "Keep the test case under 500 characters."), {
|
|
44
|
+
section: "basics", sectionLabel: "Test case", sectionRequired: true,
|
|
45
|
+
quick: true, order: 1, row: "full", label: "Test case (Yes/No question)",
|
|
46
|
+
help: "Write it as a before → after, not as \"check X works\" — most defects here return a plausible-looking 200.",
|
|
47
|
+
}),
|
|
48
|
+
description: annotate(z.string().max(1000).optional().or(z.literal("")), {
|
|
49
|
+
section: "basics", order: 2, row: "full", kind: "textarea",
|
|
50
|
+
label: "Description", help: "Extra context for the tester.",
|
|
51
|
+
}),
|
|
52
|
+
/*
|
|
53
|
+
* Optional, and validated when present. `.url()` would reject the relative
|
|
54
|
+
* path this field is FOR; a leading slash is what makes it a route on this
|
|
55
|
+
* origin rather than someone else's.
|
|
56
|
+
*/
|
|
57
|
+
href: annotate(z
|
|
58
|
+
.string()
|
|
59
|
+
.refine((v) => v === "" || v.startsWith("/"), {
|
|
60
|
+
message: "Start the link with / — it is a route on this site, not a full URL.",
|
|
61
|
+
})
|
|
62
|
+
.optional()
|
|
63
|
+
.or(z.literal("")), {
|
|
64
|
+
section: "basics", order: 3, row: "full", label: "Deep link",
|
|
65
|
+
help: "Jumps the tester straight to the feature being tested, e.g. /cart.",
|
|
66
|
+
}),
|
|
67
|
+
groupLabel: annotate(z.string().min(1, "A group is required.").max(200), {
|
|
68
|
+
section: "members", sectionLabel: "Where it appears", sectionRequired: true,
|
|
69
|
+
order: 1, row: "pair", label: "Group",
|
|
70
|
+
help: "Top-level accordion section on the Tester Hub.",
|
|
71
|
+
}),
|
|
72
|
+
groupKey: annotate(z
|
|
73
|
+
.string()
|
|
74
|
+
.min(1, "A group key is required.")
|
|
75
|
+
.max(100)
|
|
76
|
+
.regex(/^[a-z0-9-]+$/, "Lowercase letters, numbers and hyphens only."), {
|
|
77
|
+
section: "members", order: 2, row: "pair", label: "Group key",
|
|
78
|
+
help: "Auto-generated from the group name.",
|
|
79
|
+
}),
|
|
80
|
+
pageLabel: annotate(z.string().min(1, "A page is required.").max(200), {
|
|
81
|
+
section: "members", order: 3, row: "pair", label: "Page",
|
|
82
|
+
help: "Sub-accordion within the group.",
|
|
83
|
+
}),
|
|
84
|
+
pageKey: annotate(z
|
|
85
|
+
.string()
|
|
86
|
+
.min(1, "A page key is required.")
|
|
87
|
+
.max(100)
|
|
88
|
+
.regex(/^[a-z0-9-]+$/, "Lowercase letters, numbers and hyphens only."), {
|
|
89
|
+
section: "members", order: 4, row: "pair", label: "Page key",
|
|
90
|
+
help: "Auto-generated from the page name.",
|
|
91
|
+
}),
|
|
92
|
+
order: annotate(z.number().int().min(0, "Order cannot be negative."), {
|
|
93
|
+
section: "limits", sectionLabel: "Ordering", order: 1, row: "pair",
|
|
94
|
+
kind: "number", label: "Display order",
|
|
95
|
+
help: "Lower is shown first within the page.",
|
|
96
|
+
}),
|
|
97
|
+
phase: annotate(z.number().int().min(1, "Phases are numbered from 1."), {
|
|
98
|
+
section: "limits", order: 2, row: "pair", kind: "number", label: "Phase",
|
|
99
|
+
help: "Test batch this case belongs to — testers work through one phase at a time.",
|
|
100
|
+
}),
|
|
101
|
+
isActive: annotate(z.boolean(), {
|
|
102
|
+
section: "visibility", sectionLabel: "Visibility", order: 1, row: "full",
|
|
103
|
+
label: "Active (visible to testers)",
|
|
104
|
+
}),
|
|
105
|
+
adminOnly: annotate(z.boolean(), {
|
|
106
|
+
section: "visibility", order: 2, row: "full",
|
|
107
|
+
label: "Admin-only (requires canTestAdmin)",
|
|
108
|
+
}),
|
|
109
|
+
});
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* @tag consumers:seed/index.ts,seed-cli.mjs
|
|
14
14
|
* @tag sideEffects:none
|
|
15
15
|
*/
|
|
16
|
-
import {
|
|
16
|
+
import { seedPhoto } from "../../../seed/_helpers/media";
|
|
17
17
|
import { testDataExpiresAt } from "./tester-ttl";
|
|
18
18
|
export const blogTesterSeedData = [
|
|
19
19
|
{
|
|
@@ -22,7 +22,7 @@ export const blogTesterSeedData = [
|
|
|
22
22
|
slug: "tester-sandbox-post",
|
|
23
23
|
excerpt: "A disposable test blog post for the tester QA program — check that images, formatting, and reading flow work correctly.",
|
|
24
24
|
content: `<h2>This is a test post</h2><p>It exists only for the tester QA program and will be deleted automatically after 7 days.</p><p>Check: does this render correctly? Are images loading? Is the layout readable?</p>`,
|
|
25
|
-
coverImage: { type: "image", url:
|
|
25
|
+
coverImage: { type: "image", url: seedPhoto("blog-cover-tester-sandbox-post-20260101", 1200, 600), alt: "Test cover image" },
|
|
26
26
|
category: "guides",
|
|
27
27
|
tags: ["test"],
|
|
28
28
|
isFeatured: false,
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* @tag sideEffects:none
|
|
19
19
|
*/
|
|
20
20
|
import { CATEGORY_FIELDS } from "../../../constants/field-names";
|
|
21
|
-
import {
|
|
21
|
+
import { seedPhoto } from "../../../seed/_helpers/media";
|
|
22
22
|
import { testDataExpiresAt } from "./tester-ttl";
|
|
23
23
|
const emptyMetrics = {
|
|
24
24
|
productCount: 0,
|
|
@@ -50,7 +50,7 @@ export const categoriesTesterSeedData = [
|
|
|
50
50
|
isFeatured: false,
|
|
51
51
|
isBrand: false,
|
|
52
52
|
seo: { title: "Tester Sandbox", description: "Disposable test category.", keywords: ["test"] },
|
|
53
|
-
display: { icon: "🧪", coverImage:
|
|
53
|
+
display: { icon: "🧪", coverImage: seedPhoto("category-image-tester-sandbox-20260101", 1200, 600), color: "#64748b", showInMenu: false, showInFooter: false },
|
|
54
54
|
isActive: true,
|
|
55
55
|
isSearchable: true,
|
|
56
56
|
showOnHomepage: false,
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* @tag sideEffects:none
|
|
16
16
|
*/
|
|
17
17
|
import { EVENT_FIELDS } from "../../../constants/field-names";
|
|
18
|
-
import {
|
|
18
|
+
import { seedPhoto } from "../../../seed/_helpers/media";
|
|
19
19
|
import { testDataExpiresAt } from "./tester-ttl";
|
|
20
20
|
const TEST_EVENT_COVER_ALT = "Test event cover";
|
|
21
21
|
const TEST_RAFFLE_PRIZE = "Test prize — not a real reward";
|
|
@@ -29,7 +29,7 @@ export const eventsTesterSeedData = [
|
|
|
29
29
|
status: EVENT_FIELDS.STATUS_VALUES.ACTIVE,
|
|
30
30
|
startsAt: new Date(),
|
|
31
31
|
endsAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
|
|
32
|
-
coverImage: { type: "image", url:
|
|
32
|
+
coverImage: { type: "image", url: seedPhoto("event-cover-tester-sandbox-spin-20260101", 1200, 600), alt: TEST_EVENT_COVER_ALT },
|
|
33
33
|
tags: ["test"],
|
|
34
34
|
hasRaffle: true,
|
|
35
35
|
raffleType: "open_raffle",
|
|
@@ -58,7 +58,7 @@ export const eventsTesterSeedData = [
|
|
|
58
58
|
status: EVENT_FIELDS.STATUS_VALUES.ACTIVE,
|
|
59
59
|
startsAt: new Date(),
|
|
60
60
|
endsAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
|
|
61
|
-
coverImage: { type: "image", url:
|
|
61
|
+
coverImage: { type: "image", url: seedPhoto("event-cover-tester-sandbox-top-scorers-20260101", 1200, 600), alt: TEST_EVENT_COVER_ALT },
|
|
62
62
|
tags: ["test"],
|
|
63
63
|
hasRaffle: true,
|
|
64
64
|
raffleType: "top_n_scorers",
|
|
@@ -81,7 +81,7 @@ export const eventsTesterSeedData = [
|
|
|
81
81
|
status: EVENT_FIELDS.STATUS_VALUES.ACTIVE,
|
|
82
82
|
startsAt: new Date(),
|
|
83
83
|
endsAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
|
|
84
|
-
coverImage: { type: "image", url:
|
|
84
|
+
coverImage: { type: "image", url: seedPhoto("event-cover-tester-sandbox-top-participants-20260101", 1200, 600), alt: TEST_EVENT_COVER_ALT },
|
|
85
85
|
tags: ["test"],
|
|
86
86
|
hasRaffle: true,
|
|
87
87
|
raffleType: "top_n_participants",
|
|
@@ -104,7 +104,7 @@ export const eventsTesterSeedData = [
|
|
|
104
104
|
status: EVENT_FIELDS.STATUS_VALUES.ACTIVE,
|
|
105
105
|
startsAt: new Date(),
|
|
106
106
|
endsAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
|
|
107
|
-
coverImage: { type: "image", url:
|
|
107
|
+
coverImage: { type: "image", url: seedPhoto("event-cover-tester-sandbox-offer-20260101", 1200, 600), alt: TEST_EVENT_COVER_ALT },
|
|
108
108
|
tags: ["test"],
|
|
109
109
|
offerConfig: {
|
|
110
110
|
couponId: "coupon-rehan10",
|
|
@@ -27,14 +27,14 @@
|
|
|
27
27
|
* @tag consumers:seed/index.ts,seed-cli.mjs
|
|
28
28
|
* @tag sideEffects:none
|
|
29
29
|
*/
|
|
30
|
-
import {
|
|
30
|
+
import { seedPhoto } from "../../../seed/_helpers/media";
|
|
31
31
|
const NOW = new Date();
|
|
32
32
|
const daysAgo = (n) => new Date(NOW.getTime() - n * 86400000);
|
|
33
33
|
// Deterministic per-product thumbnail — see the identical helper's comment
|
|
34
34
|
// in appkit/src/seed/orders-seed-data.ts for why this doesn't need to match
|
|
35
35
|
// the real product's own seeded image.
|
|
36
36
|
function orderItemImage(productId) {
|
|
37
|
-
return
|
|
37
|
+
return seedPhoto(`order-item-${productId}`, 300, 300);
|
|
38
38
|
}
|
|
39
39
|
const BUYER_ID = "user-tester-qa";
|
|
40
40
|
const BUYER_NAME = "QA Tester";
|