@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
|
@@ -3,6 +3,68 @@ import { z } from "zod";
|
|
|
3
3
|
* 🛑 `annotate()` must be the OUTERMOST call on each field — it keys a WeakMap
|
|
4
4
|
* by schema instance and every zod wrapper returns a new one.
|
|
5
5
|
*/
|
|
6
|
+
/**
|
|
7
|
+
* The fields both coupon editors share, before either adds its own rules.
|
|
8
|
+
*
|
|
9
|
+
* Split out of `sellerCouponFormSchema` so the ADMIN editor can extend it.
|
|
10
|
+
* It could not before: that schema ends in `.superRefine`, which returns a
|
|
11
|
+
* ZodEffects with no `.extend()` — which is a large part of why the admin
|
|
12
|
+
* editor ended up declaring its own five-field `.passthrough()` stub locally
|
|
13
|
+
* and validating nothing at all.
|
|
14
|
+
*/
|
|
15
|
+
export declare const couponFormBase: z.ZodObject<{
|
|
16
|
+
code: z.ZodString;
|
|
17
|
+
type: z.ZodEnum<["percentage", "fixed", "free_shipping"]>;
|
|
18
|
+
value: z.ZodEffects<z.ZodString, string, string>;
|
|
19
|
+
minPurchase: z.ZodEffects<z.ZodString, string, string>;
|
|
20
|
+
maxDiscount: z.ZodEffects<z.ZodString, string, string>;
|
|
21
|
+
totalLimit: z.ZodEffects<z.ZodString, string, string>;
|
|
22
|
+
perUserLimit: z.ZodEffects<z.ZodString, string, string>;
|
|
23
|
+
startDate: z.ZodString;
|
|
24
|
+
endDate: z.ZodString;
|
|
25
|
+
isActive: z.ZodBoolean;
|
|
26
|
+
applicableProducts: z.ZodArray<z.ZodString, "many">;
|
|
27
|
+
applicableCategories: z.ZodArray<z.ZodString, "many">;
|
|
28
|
+
}, "strip", z.ZodTypeAny, {
|
|
29
|
+
value: string;
|
|
30
|
+
code: string;
|
|
31
|
+
type: "fixed" | "percentage" | "free_shipping";
|
|
32
|
+
isActive: boolean;
|
|
33
|
+
endDate: string;
|
|
34
|
+
maxDiscount: string;
|
|
35
|
+
minPurchase: string;
|
|
36
|
+
applicableProducts: string[];
|
|
37
|
+
applicableCategories: string[];
|
|
38
|
+
totalLimit: string;
|
|
39
|
+
perUserLimit: string;
|
|
40
|
+
startDate: string;
|
|
41
|
+
}, {
|
|
42
|
+
value: string;
|
|
43
|
+
code: string;
|
|
44
|
+
type: "fixed" | "percentage" | "free_shipping";
|
|
45
|
+
isActive: boolean;
|
|
46
|
+
endDate: string;
|
|
47
|
+
maxDiscount: string;
|
|
48
|
+
minPurchase: string;
|
|
49
|
+
applicableProducts: string[];
|
|
50
|
+
applicableCategories: string[];
|
|
51
|
+
totalLimit: string;
|
|
52
|
+
perUserLimit: string;
|
|
53
|
+
startDate: string;
|
|
54
|
+
}>;
|
|
55
|
+
/**
|
|
56
|
+
* The cross-field rules both editors need. Shared for the same reason the
|
|
57
|
+
* fields are: a percentage over 100 is the store paying the customer whichever
|
|
58
|
+
* portal typed it.
|
|
59
|
+
*/
|
|
60
|
+
export declare function refineCouponCommon(v: {
|
|
61
|
+
type: string;
|
|
62
|
+
value: string;
|
|
63
|
+
startDate: string;
|
|
64
|
+
endDate: string;
|
|
65
|
+
totalLimit: string;
|
|
66
|
+
perUserLimit: string;
|
|
67
|
+
}, ctx: z.RefinementCtx): void;
|
|
6
68
|
export declare const sellerCouponFormSchema: z.ZodEffects<z.ZodObject<{
|
|
7
69
|
code: z.ZodString;
|
|
8
70
|
type: z.ZodEnum<["percentage", "fixed", "free_shipping"]>;
|
|
@@ -70,3 +132,155 @@ export declare const sellerCouponFormSchema: z.ZodEffects<z.ZodObject<{
|
|
|
70
132
|
startDate: string;
|
|
71
133
|
}>;
|
|
72
134
|
export type SellerCouponFormValues = z.infer<typeof sellerCouponFormSchema>;
|
|
135
|
+
/**
|
|
136
|
+
* What `POST /api/store/coupons` accepts.
|
|
137
|
+
*
|
|
138
|
+
* The index signature is what lets it pass as a JSON body without a cast at the
|
|
139
|
+
* callsite — the named fields still constrain what may be set.
|
|
140
|
+
*/
|
|
141
|
+
export interface SellerCouponPayload {
|
|
142
|
+
[key: string]: string | number | boolean | string[] | undefined;
|
|
143
|
+
code: string;
|
|
144
|
+
type: SellerCouponFormValues["type"];
|
|
145
|
+
value: number;
|
|
146
|
+
minPurchase?: number;
|
|
147
|
+
maxDiscount?: number;
|
|
148
|
+
totalLimit: number;
|
|
149
|
+
perUserLimit: number;
|
|
150
|
+
startDate: string;
|
|
151
|
+
endDate: string;
|
|
152
|
+
isActive: boolean;
|
|
153
|
+
applicableProducts?: string[];
|
|
154
|
+
applicableCategories?: string[];
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* The draft, as the route wants it.
|
|
158
|
+
*
|
|
159
|
+
* 🛑 One implementation because the conditions have to match the form's, and a
|
|
160
|
+
* per-callsite conversion is how they stopped matching: the create client
|
|
161
|
+
* correctly zeroed `value` for a free-shipping coupon and then sent
|
|
162
|
+
* `maxDiscount` for EVERY type — so a cap typed while the type was
|
|
163
|
+
* "percentage" survived a switch to fixed or free-shipping, invisibly, because
|
|
164
|
+
* the input that would have shown it was no longer rendered.
|
|
165
|
+
*
|
|
166
|
+
* The rule is now stated once, here, next to the `when` predicates it mirrors:
|
|
167
|
+
* a field the form hides is a field the payload omits.
|
|
168
|
+
*/
|
|
169
|
+
export declare function couponDraftToPayload(draft: SellerCouponFormValues): SellerCouponPayload;
|
|
170
|
+
/**
|
|
171
|
+
* A coupon as an ADMIN edits it — the seller's fields plus the ones only the
|
|
172
|
+
* platform can set.
|
|
173
|
+
*
|
|
174
|
+
* `AdminCouponEditorView` declared its own schema locally: five fields, two of
|
|
175
|
+
* them `.passthrough()`, against nineteen rendered controls. It was passed to
|
|
176
|
+
* `<Form schema>` and never parsed, so none of the seventeen unlisted controls
|
|
177
|
+
* was checked by anything — `value` could be 500%, `endDate` could precede
|
|
178
|
+
* `startDate`, and `buyQuantity` could be zero.
|
|
179
|
+
*
|
|
180
|
+
* Extending the shared base rather than restating it is what keeps the two
|
|
181
|
+
* portals' rules from drifting; that they had already drifted is Root Cause
|
|
182
|
+
* #59's shape on the validation axis.
|
|
183
|
+
*/
|
|
184
|
+
export declare const adminCouponFormSchema: z.ZodEffects<z.ZodObject<{
|
|
185
|
+
code: z.ZodString;
|
|
186
|
+
value: z.ZodEffects<z.ZodString, string, string>;
|
|
187
|
+
minPurchase: z.ZodEffects<z.ZodString, string, string>;
|
|
188
|
+
maxDiscount: z.ZodEffects<z.ZodString, string, string>;
|
|
189
|
+
totalLimit: z.ZodEffects<z.ZodString, string, string>;
|
|
190
|
+
perUserLimit: z.ZodEffects<z.ZodString, string, string>;
|
|
191
|
+
startDate: z.ZodString;
|
|
192
|
+
endDate: z.ZodString;
|
|
193
|
+
isActive: z.ZodBoolean;
|
|
194
|
+
applicableProducts: z.ZodArray<z.ZodString, "many">;
|
|
195
|
+
applicableCategories: z.ZodArray<z.ZodString, "many">;
|
|
196
|
+
} & {
|
|
197
|
+
type: z.ZodEnum<["percentage", "fixed", "free_shipping", "buy_x_get_y"]>;
|
|
198
|
+
name: z.ZodString;
|
|
199
|
+
description: z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>;
|
|
200
|
+
buyQuantity: z.ZodEffects<z.ZodString, string, string>;
|
|
201
|
+
getQuantity: z.ZodEffects<z.ZodString, string, string>;
|
|
202
|
+
currentUsage: z.ZodOptional<z.ZodNumber>;
|
|
203
|
+
firstTimeUserOnly: z.ZodBoolean;
|
|
204
|
+
appliesToAuctions: z.ZodBoolean;
|
|
205
|
+
}, "strip", z.ZodTypeAny, {
|
|
206
|
+
value: string;
|
|
207
|
+
code: string;
|
|
208
|
+
type: "fixed" | "percentage" | "free_shipping" | "buy_x_get_y";
|
|
209
|
+
name: string;
|
|
210
|
+
isActive: boolean;
|
|
211
|
+
endDate: string;
|
|
212
|
+
firstTimeUserOnly: boolean;
|
|
213
|
+
maxDiscount: string;
|
|
214
|
+
minPurchase: string;
|
|
215
|
+
buyQuantity: string;
|
|
216
|
+
getQuantity: string;
|
|
217
|
+
applicableProducts: string[];
|
|
218
|
+
applicableCategories: string[];
|
|
219
|
+
totalLimit: string;
|
|
220
|
+
perUserLimit: string;
|
|
221
|
+
startDate: string;
|
|
222
|
+
appliesToAuctions: boolean;
|
|
223
|
+
description?: string | undefined;
|
|
224
|
+
currentUsage?: number | undefined;
|
|
225
|
+
}, {
|
|
226
|
+
value: string;
|
|
227
|
+
code: string;
|
|
228
|
+
type: "fixed" | "percentage" | "free_shipping" | "buy_x_get_y";
|
|
229
|
+
name: string;
|
|
230
|
+
isActive: boolean;
|
|
231
|
+
endDate: string;
|
|
232
|
+
firstTimeUserOnly: boolean;
|
|
233
|
+
maxDiscount: string;
|
|
234
|
+
minPurchase: string;
|
|
235
|
+
buyQuantity: string;
|
|
236
|
+
getQuantity: string;
|
|
237
|
+
applicableProducts: string[];
|
|
238
|
+
applicableCategories: string[];
|
|
239
|
+
totalLimit: string;
|
|
240
|
+
perUserLimit: string;
|
|
241
|
+
startDate: string;
|
|
242
|
+
appliesToAuctions: boolean;
|
|
243
|
+
description?: string | undefined;
|
|
244
|
+
currentUsage?: number | undefined;
|
|
245
|
+
}>, {
|
|
246
|
+
value: string;
|
|
247
|
+
code: string;
|
|
248
|
+
type: "fixed" | "percentage" | "free_shipping" | "buy_x_get_y";
|
|
249
|
+
name: string;
|
|
250
|
+
isActive: boolean;
|
|
251
|
+
endDate: string;
|
|
252
|
+
firstTimeUserOnly: boolean;
|
|
253
|
+
maxDiscount: string;
|
|
254
|
+
minPurchase: string;
|
|
255
|
+
buyQuantity: string;
|
|
256
|
+
getQuantity: string;
|
|
257
|
+
applicableProducts: string[];
|
|
258
|
+
applicableCategories: string[];
|
|
259
|
+
totalLimit: string;
|
|
260
|
+
perUserLimit: string;
|
|
261
|
+
startDate: string;
|
|
262
|
+
appliesToAuctions: boolean;
|
|
263
|
+
description?: string | undefined;
|
|
264
|
+
currentUsage?: number | undefined;
|
|
265
|
+
}, {
|
|
266
|
+
value: string;
|
|
267
|
+
code: string;
|
|
268
|
+
type: "fixed" | "percentage" | "free_shipping" | "buy_x_get_y";
|
|
269
|
+
name: string;
|
|
270
|
+
isActive: boolean;
|
|
271
|
+
endDate: string;
|
|
272
|
+
firstTimeUserOnly: boolean;
|
|
273
|
+
maxDiscount: string;
|
|
274
|
+
minPurchase: string;
|
|
275
|
+
buyQuantity: string;
|
|
276
|
+
getQuantity: string;
|
|
277
|
+
applicableProducts: string[];
|
|
278
|
+
applicableCategories: string[];
|
|
279
|
+
totalLimit: string;
|
|
280
|
+
perUserLimit: string;
|
|
281
|
+
startDate: string;
|
|
282
|
+
appliesToAuctions: boolean;
|
|
283
|
+
description?: string | undefined;
|
|
284
|
+
currentUsage?: number | undefined;
|
|
285
|
+
}>;
|
|
286
|
+
export type AdminCouponFormValues = z.infer<typeof adminCouponFormSchema>;
|
|
@@ -44,7 +44,16 @@ const numericString = (label) => z
|
|
|
44
44
|
* 🛑 `annotate()` must be the OUTERMOST call on each field — it keys a WeakMap
|
|
45
45
|
* by schema instance and every zod wrapper returns a new one.
|
|
46
46
|
*/
|
|
47
|
-
|
|
47
|
+
/**
|
|
48
|
+
* The fields both coupon editors share, before either adds its own rules.
|
|
49
|
+
*
|
|
50
|
+
* Split out of `sellerCouponFormSchema` so the ADMIN editor can extend it.
|
|
51
|
+
* It could not before: that schema ends in `.superRefine`, which returns a
|
|
52
|
+
* ZodEffects with no `.extend()` — which is a large part of why the admin
|
|
53
|
+
* editor ended up declaring its own five-field `.passthrough()` stub locally
|
|
54
|
+
* and validating nothing at all.
|
|
55
|
+
*/
|
|
56
|
+
export const couponFormBase = z
|
|
48
57
|
.object({
|
|
49
58
|
code: annotate(z
|
|
50
59
|
.string()
|
|
@@ -57,14 +66,26 @@ export const sellerCouponFormSchema = z
|
|
|
57
66
|
type: annotate(z.enum(["percentage", "fixed", "free_shipping"]), {
|
|
58
67
|
section: "basics", quick: true, order: 2, row: "pair",
|
|
59
68
|
}),
|
|
69
|
+
/*
|
|
70
|
+
* `when` carries what the editor held as JSX conditionals, so a field the
|
|
71
|
+
* form hides is one the payload cannot carry — see `couponDraftToPayload`.
|
|
72
|
+
*/
|
|
60
73
|
value: annotate(numericString("The discount value"), {
|
|
61
74
|
section: "basics", quick: true, order: 3, row: "pair",
|
|
75
|
+
when: (v) => v.type !== "free_shipping",
|
|
62
76
|
}),
|
|
63
77
|
minPurchase: annotate(numericString("Minimum purchase"), {
|
|
64
78
|
section: "limits", sectionLabel: "Limits", order: 1, row: "pair",
|
|
65
79
|
}),
|
|
80
|
+
/*
|
|
81
|
+
* A percentage cap is meaningless on a fixed or free-shipping coupon. The
|
|
82
|
+
* input was already hidden for those, and the value was SENT anyway — so a
|
|
83
|
+
* cap typed while the type was "percentage" persisted after switching to
|
|
84
|
+
* free shipping, invisibly.
|
|
85
|
+
*/
|
|
66
86
|
maxDiscount: annotate(numericString("Maximum discount"), {
|
|
67
87
|
section: "limits", order: 2, row: "pair",
|
|
88
|
+
when: (v) => v.type === "percentage",
|
|
68
89
|
}),
|
|
69
90
|
totalLimit: annotate(numericString("Total uses"), {
|
|
70
91
|
section: "limits", order: 3, row: "pair",
|
|
@@ -87,30 +108,141 @@ export const sellerCouponFormSchema = z
|
|
|
87
108
|
applicableCategories: annotate(z.array(z.string()), {
|
|
88
109
|
section: "scope", order: 2, row: "full", kind: "list",
|
|
89
110
|
}),
|
|
111
|
+
});
|
|
112
|
+
/**
|
|
113
|
+
* The cross-field rules both editors need. Shared for the same reason the
|
|
114
|
+
* fields are: a percentage over 100 is the store paying the customer whichever
|
|
115
|
+
* portal typed it.
|
|
116
|
+
*/
|
|
117
|
+
export function refineCouponCommon(v, ctx) {
|
|
118
|
+
{
|
|
119
|
+
const issue = (path, message) => ctx.addIssue({ code: z.ZodIssueCode.custom, path: [path], message });
|
|
120
|
+
// A discount value is required for everything except free shipping, and
|
|
121
|
+
// a percentage above 100 is not a discount — it is the store paying the
|
|
122
|
+
// customer. Nothing bounded this before.
|
|
123
|
+
if (v.type !== "free_shipping") {
|
|
124
|
+
const amount = Number(v.value);
|
|
125
|
+
if (v.value.trim() === "")
|
|
126
|
+
issue("value", "A discount value is required.");
|
|
127
|
+
else if (amount <= 0)
|
|
128
|
+
issue("value", "The discount must be greater than zero.");
|
|
129
|
+
else if (v.type === "percentage" && amount > 100) {
|
|
130
|
+
issue("value", "A percentage discount cannot exceed 100%.");
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (v.startDate && v.endDate && v.startDate > v.endDate) {
|
|
134
|
+
issue("endDate", "The end date must be after the start date.");
|
|
135
|
+
}
|
|
136
|
+
// A per-customer limit above the total makes the total unreachable — the
|
|
137
|
+
// coupon reads as more generous than it can ever be.
|
|
138
|
+
const total = Number(v.totalLimit);
|
|
139
|
+
const perUser = Number(v.perUserLimit);
|
|
140
|
+
if (v.totalLimit.trim() && v.perUserLimit.trim() && perUser > total) {
|
|
141
|
+
issue("perUserLimit", "Uses per customer cannot exceed the total uses.");
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
export const sellerCouponFormSchema = couponFormBase.superRefine(refineCouponCommon);
|
|
146
|
+
/**
|
|
147
|
+
* The draft, as the route wants it.
|
|
148
|
+
*
|
|
149
|
+
* 🛑 One implementation because the conditions have to match the form's, and a
|
|
150
|
+
* per-callsite conversion is how they stopped matching: the create client
|
|
151
|
+
* correctly zeroed `value` for a free-shipping coupon and then sent
|
|
152
|
+
* `maxDiscount` for EVERY type — so a cap typed while the type was
|
|
153
|
+
* "percentage" survived a switch to fixed or free-shipping, invisibly, because
|
|
154
|
+
* the input that would have shown it was no longer rendered.
|
|
155
|
+
*
|
|
156
|
+
* The rule is now stated once, here, next to the `when` predicates it mirrors:
|
|
157
|
+
* a field the form hides is a field the payload omits.
|
|
158
|
+
*/
|
|
159
|
+
export function couponDraftToPayload(draft) {
|
|
160
|
+
const isPercentage = draft.type === "percentage";
|
|
161
|
+
const hasValue = draft.type !== "free_shipping";
|
|
162
|
+
return {
|
|
163
|
+
code: draft.code,
|
|
164
|
+
type: draft.type,
|
|
165
|
+
value: hasValue ? Number(draft.value) || 0 : 0,
|
|
166
|
+
minPurchase: draft.minPurchase ? Number(draft.minPurchase) : undefined,
|
|
167
|
+
maxDiscount: isPercentage && draft.maxDiscount ? Number(draft.maxDiscount) : undefined,
|
|
168
|
+
totalLimit: Number(draft.totalLimit) || 0,
|
|
169
|
+
perUserLimit: Number(draft.perUserLimit) || 0,
|
|
170
|
+
startDate: draft.startDate,
|
|
171
|
+
endDate: draft.endDate,
|
|
172
|
+
isActive: draft.isActive,
|
|
173
|
+
...(draft.applicableProducts?.length ? { applicableProducts: draft.applicableProducts } : {}),
|
|
174
|
+
...(draft.applicableCategories?.length
|
|
175
|
+
? { applicableCategories: draft.applicableCategories }
|
|
176
|
+
: {}),
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* A coupon as an ADMIN edits it — the seller's fields plus the ones only the
|
|
181
|
+
* platform can set.
|
|
182
|
+
*
|
|
183
|
+
* `AdminCouponEditorView` declared its own schema locally: five fields, two of
|
|
184
|
+
* them `.passthrough()`, against nineteen rendered controls. It was passed to
|
|
185
|
+
* `<Form schema>` and never parsed, so none of the seventeen unlisted controls
|
|
186
|
+
* was checked by anything — `value` could be 500%, `endDate` could precede
|
|
187
|
+
* `startDate`, and `buyQuantity` could be zero.
|
|
188
|
+
*
|
|
189
|
+
* Extending the shared base rather than restating it is what keeps the two
|
|
190
|
+
* portals' rules from drifting; that they had already drifted is Root Cause
|
|
191
|
+
* #59's shape on the validation axis.
|
|
192
|
+
*/
|
|
193
|
+
export const adminCouponFormSchema = couponFormBase
|
|
194
|
+
.extend({
|
|
195
|
+
/*
|
|
196
|
+
* Widened past the seller's three. Only the platform runs buy-x-get-y —
|
|
197
|
+
* a seller offering one would be spending another seller's stock.
|
|
198
|
+
*/
|
|
199
|
+
type: annotate(z.enum(["percentage", "fixed", "free_shipping", "buy_x_get_y"]), {
|
|
200
|
+
section: "basics", quick: true, order: 2, row: "pair", label: "Coupon type",
|
|
201
|
+
}),
|
|
202
|
+
name: annotate(z.string().min(1, "Give the campaign a name.").max(120), {
|
|
203
|
+
section: "basics", quick: true, order: 4, row: "pair", label: "Campaign name",
|
|
204
|
+
}),
|
|
205
|
+
description: annotate(z.string().max(500).optional().or(z.literal("")), {
|
|
206
|
+
section: "basics", order: 5, row: "full", kind: "textarea",
|
|
207
|
+
}),
|
|
208
|
+
buyQuantity: annotate(numericString("Buy quantity"), {
|
|
209
|
+
section: "basics", order: 6, row: "pair", kind: "number",
|
|
210
|
+
when: (v) => v.type === "buy_x_get_y",
|
|
211
|
+
}),
|
|
212
|
+
getQuantity: annotate(numericString("Get quantity"), {
|
|
213
|
+
section: "basics", order: 7, row: "pair", kind: "number",
|
|
214
|
+
when: (v) => v.type === "buy_x_get_y",
|
|
215
|
+
}),
|
|
216
|
+
/*
|
|
217
|
+
* Written by orders, never by this form. `t3-mirror` renders it read-only
|
|
218
|
+
* instead of as a box an admin could set to whatever they liked — which is
|
|
219
|
+
* what "Current usage" was, `disabled` by an attribute a programmatic
|
|
220
|
+
* submit ignores.
|
|
221
|
+
*/
|
|
222
|
+
currentUsage: annotate(z.number().int().min(0).optional(), {
|
|
223
|
+
section: "limits", order: 5, row: "pair", derived: true, tier: "t3-mirror",
|
|
224
|
+
label: "Current usage", help: "Updated by orders.",
|
|
225
|
+
}),
|
|
226
|
+
firstTimeUserOnly: annotate(z.boolean(), {
|
|
227
|
+
section: "scope", order: 3, row: "quarter", label: "First-time users only",
|
|
228
|
+
}),
|
|
229
|
+
appliesToAuctions: annotate(z.boolean(), {
|
|
230
|
+
section: "scope", order: 4, row: "quarter", label: "Applies to auctions",
|
|
231
|
+
}),
|
|
90
232
|
})
|
|
91
233
|
.superRefine((v, ctx) => {
|
|
92
|
-
|
|
93
|
-
// A
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
234
|
+
refineCouponCommon(v, ctx);
|
|
235
|
+
// A buy-x-get-y with a zero on either side is not an offer.
|
|
236
|
+
if (v.type === "buy_x_get_y") {
|
|
237
|
+
for (const key of ["buyQuantity", "getQuantity"]) {
|
|
238
|
+
const n = Number(v[key]);
|
|
239
|
+
if (v[key].trim() === "" || !Number.isFinite(n) || n < 1) {
|
|
240
|
+
ctx.addIssue({
|
|
241
|
+
code: z.ZodIssueCode.custom,
|
|
242
|
+
path: [key],
|
|
243
|
+
message: "Enter a whole number of one or more.",
|
|
244
|
+
});
|
|
245
|
+
}
|
|
104
246
|
}
|
|
105
247
|
}
|
|
106
|
-
if (v.startDate && v.endDate && v.startDate > v.endDate) {
|
|
107
|
-
issue("endDate", "The end date must be after the start date.");
|
|
108
|
-
}
|
|
109
|
-
// A per-customer limit above the total makes the total unreachable — the
|
|
110
|
-
// coupon reads as more generous than it can ever be.
|
|
111
|
-
const total = Number(v.totalLimit);
|
|
112
|
-
const perUser = Number(v.perUserLimit);
|
|
113
|
-
if (v.totalLimit.trim() && v.perUserLimit.trim() && perUser > total) {
|
|
114
|
-
issue("perUserLimit", "Uses per customer cannot exceed the total uses.");
|
|
115
|
-
}
|
|
116
248
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import type { OfferBounds } from "../../../_internal/shared/features/offers/config";
|
|
2
3
|
export declare const counterOfferFormSchema: z.ZodObject<{
|
|
3
4
|
counterAmount: z.ZodNumber;
|
|
4
5
|
sellerNote: z.ZodOptional<z.ZodString>;
|
|
@@ -13,16 +14,24 @@ export type CounterOfferFormValues = z.infer<typeof counterOfferFormSchema>;
|
|
|
13
14
|
/**
|
|
14
15
|
* Buyer-side Make-an-Offer form.
|
|
15
16
|
*
|
|
16
|
-
* A factory rather than a constant because both bounds depend on the listing
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
17
|
+
* A factory rather than a constant because both bounds depend on the listing.
|
|
18
|
+
* It takes the already-resolved `OfferBounds` rather than recomputing them:
|
|
19
|
+
* `resolveOfferBounds()` is what `makeOffer` enforces, so anything this schema
|
|
20
|
+
* accepts, the server accepts. Deriving a second floor here is exactly how the
|
|
21
|
+
* forms came to advertise a 50% minimum the server rejected at 70 (see the
|
|
22
|
+
* offers config header).
|
|
23
|
+
*
|
|
24
|
+
* Three shapes, all from the same bounds object:
|
|
25
|
+
*
|
|
26
|
+
* - **Buy request** (`isBuyRequest`) — no cart on this type and no haggling
|
|
27
|
+
* opted in, so `min === max` and the only legal amount is the asking price.
|
|
28
|
+
* - **Offer, no cart** — floor to asking price *inclusive*: with no Add to Cart
|
|
29
|
+
* button, refusing a full-price offer would leave the buyer nowhere to go.
|
|
30
|
+
* - **Offer, cartable** — the original rule, ceiling exclusive of the price.
|
|
22
31
|
*/
|
|
23
32
|
export declare function makeOfferFormSchema(opts: {
|
|
24
33
|
listedPrice: number;
|
|
25
|
-
|
|
34
|
+
bounds: OfferBounds;
|
|
26
35
|
formatAmount: (n: number) => string;
|
|
27
36
|
}): z.ZodObject<{
|
|
28
37
|
offerAmount: z.ZodNumber;
|
|
@@ -31,21 +31,37 @@ export const counterOfferFormSchema = z.object({
|
|
|
31
31
|
/**
|
|
32
32
|
* Buyer-side Make-an-Offer form.
|
|
33
33
|
*
|
|
34
|
-
* A factory rather than a constant because both bounds depend on the listing
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
34
|
+
* A factory rather than a constant because both bounds depend on the listing.
|
|
35
|
+
* It takes the already-resolved `OfferBounds` rather than recomputing them:
|
|
36
|
+
* `resolveOfferBounds()` is what `makeOffer` enforces, so anything this schema
|
|
37
|
+
* accepts, the server accepts. Deriving a second floor here is exactly how the
|
|
38
|
+
* forms came to advertise a 50% minimum the server rejected at 70 (see the
|
|
39
|
+
* offers config header).
|
|
40
|
+
*
|
|
41
|
+
* Three shapes, all from the same bounds object:
|
|
42
|
+
*
|
|
43
|
+
* - **Buy request** (`isBuyRequest`) — no cart on this type and no haggling
|
|
44
|
+
* opted in, so `min === max` and the only legal amount is the asking price.
|
|
45
|
+
* - **Offer, no cart** — floor to asking price *inclusive*: with no Add to Cart
|
|
46
|
+
* button, refusing a full-price offer would leave the buyer nowhere to go.
|
|
47
|
+
* - **Offer, cartable** — the original rule, ceiling exclusive of the price.
|
|
40
48
|
*/
|
|
41
49
|
export function makeOfferFormSchema(opts) {
|
|
42
|
-
const { listedPrice,
|
|
50
|
+
const { listedPrice, bounds, formatAmount } = opts;
|
|
51
|
+
const amount = z.coerce
|
|
52
|
+
.number({ invalid_type_error: "Enter an offer amount." })
|
|
53
|
+
.positive("Offer amount must be greater than zero.");
|
|
54
|
+
const bounded = bounds.isBuyRequest
|
|
55
|
+
? amount
|
|
56
|
+
.min(bounds.min, `This seller is not taking lower offers — the price is ${formatAmount(bounds.min)}.`)
|
|
57
|
+
.max(bounds.max, `This seller is not taking lower offers — the price is ${formatAmount(bounds.max)}.`)
|
|
58
|
+
: amount
|
|
59
|
+
.min(bounds.min, `Minimum offer is ${formatAmount(bounds.min)}.`)
|
|
60
|
+
.max(bounds.max, bounds.max >= listedPrice
|
|
61
|
+
? `Your offer cannot exceed the asking price of ${formatAmount(listedPrice)}.`
|
|
62
|
+
: `Offer must be below the listed price of ${formatAmount(listedPrice)} — use Add to Cart to buy at that price.`);
|
|
43
63
|
return z.object({
|
|
44
|
-
offerAmount:
|
|
45
|
-
.number({ invalid_type_error: "Enter an offer amount." })
|
|
46
|
-
.positive("Offer amount must be greater than zero.")
|
|
47
|
-
.min(minOffer, `Minimum offer is ${formatAmount(minOffer)}.`)
|
|
48
|
-
.max(listedPrice - 0.01, `Offer must be below the listed price of ${formatAmount(listedPrice)} — use Add to Cart to buy at that price.`),
|
|
64
|
+
offerAmount: bounded,
|
|
49
65
|
buyerNote: z.string().max(300, "Keep your note under 300 characters.").optional(),
|
|
50
66
|
});
|
|
51
67
|
}
|
|
@@ -6,7 +6,7 @@ import { Button } from "../../ui/components/Button";
|
|
|
6
6
|
import { IconButton } from "../../ui/components/IconButton";
|
|
7
7
|
import { classNames } from "../../ui/style.helper";
|
|
8
8
|
import { FORM_ACTION_META, FORM_ACTION_ID } from "../products/constants/action-defs";
|
|
9
|
-
import { Div, Row, Span, Stack, Text } from "../../ui";
|
|
9
|
+
import { ActionRow, Div, Row, Span, Stack, Text } from "../../ui";
|
|
10
10
|
/**
|
|
11
11
|
* Carries the `schema` prop passed to `<FormShell>` down to any nested
|
|
12
12
|
* `<SectionForm>` that doesn't declare its own `schema`/`SectionDef.schema` —
|
|
@@ -125,5 +125,5 @@ export function FormShell({ isOpen, onClose, title, breadcrumb, schema, isDirty
|
|
|
125
125
|
return (_jsxs(FormSchemaContext.Provider, { value: schema, children: [_jsx(Div, { surface: "overlay-sm", className: "fixed inset-0 backdrop-blur-[2px]", style: { zIndex: "calc(var(--appkit-z-modal) - 1)" }, "aria-hidden": "true", onClick: attemptClose }), _jsxs(Div, { layout: "flex", ref: panelRef, role: "dialog", "aria-modal": "true", "aria-label": title, className: "fixed top-0 bottom-0 left-0 right-0 lg:left-[10%] lg:right-[10%] [flex-direction:column] bg-[var(--appkit-color-surface)]", shadow: "2xl", style: { zIndex: "var(--appkit-z-modal)" }, children: [_jsxs(Row, { gap: "sm", paddingX: "x-5", className: "flex-shrink-0 sticky top-0 z-10 border-b border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)]", padding: "y-sm", children: [previewMode ? (_jsxs(Button, { variant: "ghost", type: "button", onClick: () => setPreviewMode(false), "aria-label": "Back to edit", gap: "xs", rounded: "lg", textSize: "sm", textColor: "muted", className: "flex-shrink-0", children: [_jsx(ArrowLeft, { className: "w-4 h-4" }), _jsx(Span, { className: "hidden sm:inline", children: "Back to Edit" })] })) : (_jsx(IconButton, { type: "button", onClick: attemptClose, "aria-label": "Close", variant: "ghost", rounded: "lg", className: "text-[var(--appkit-color-text-muted)] flex-shrink-0", children: _jsx(X, { className: "w-5 h-5" }) })), _jsxs(Div, { className: "flex-1 min-w-0", children: [breadcrumb && (_jsx(Text, { className: "text-[var(--appkit-color-text-muted)] truncate mb-0.5", size: "xs", children: breadcrumb })), _jsx(Text, { className: "text-[var(--appkit-color-text)] truncate", size: "sm", weight: "semibold", children: previewMode ? `Preview — ${title}` : title })] }), _jsx(Row, { gap: "xs", className: "flex-shrink-0", children: previewMode ? null : (_jsxs(_Fragment, { children: [previewSlot && (_jsxs(Button, { variant: "outline", type: "button", onClick: () => setPreviewMode(true), gap: "xs", rounded: "lg", paddingX: "sm", textSize: "sm", textColor: "muted", children: [_jsx(Eye, { className: "w-4 h-4" }), _jsx(Span, { className: "hidden sm:inline", children: "Preview" })] })), onSaveDraft && (_jsx(Button, { variant: "outline", size: "sm", onClick: handleSaveDraft, disabled: isLoading || savingDraft || publishing, isLoading: savingDraft, children: saveLabel })), onPublish && (_jsx(Button, { variant: "primary", size: "sm", onClick: handlePublish, disabled: isLoading || savingDraft || publishing, isLoading: publishing, children: publishLabel }))] })) })] }), _jsxs(Div, { layout: "flex", className: `flex-1 ${__O.hidden}`, children: [sections && sections.length > 0 && !previewMode && (_jsx("nav", { "aria-label": "Form sections", className: "hidden lg:flex flex-col flex-shrink-0 w-48 border-r border-[var(--appkit-color-border)] py-[var(--appkit-space-4)] px-[var(--appkit-space-3)] gap-[var(--appkit-space-1)] overflow-y-auto", children: sections.map((sec) => (_jsx(Button, { variant: "ghost", type: "button", onClick: () => scrollToSection(sec.id), rounded: "lg", paddingX: "sm", paddingY: "xs", textSize: "sm", textColor: "muted", justify: "start", className: "text-left", children: sec.label }, sec.id))) })), sections && sections.length > 0 && !previewMode && (_jsx(Row, { gap: "px", className: `lg:hidden fixed top-[var(--form-shell-topbar-h,57px)] left-0 right-0 z-10 ${__O.xAuto} px-[1.25rem] bg-[var(--appkit-color-surface)] border-b border-[var(--appkit-color-border)]`, padding: "y-xs", children: sections.map((sec) => (_jsx(Button, { variant: "outline", type: "button", onClick: () => scrollToSection(sec.id), rounded: "full", paddingX: "sm", paddingY: "xs", textSize: "xs", textColor: "muted", className: "flex-shrink-0 hover:border-primary hover:text-primary whitespace-nowrap", children: sec.label }, sec.id))) })), _jsx(Div, { ref: bodyRef, className: classNames("flex-1 overflow-y-auto", sections && sections.length > 0 && !previewMode ? "pt-[var(--appkit-space-0)] lg:pt-[var(--appkit-space-0)]" : ""), children: previewMode && previewSlot ? (_jsxs(_Fragment, { children: [_jsxs(Row, { textSize: "sm", gap: "xs", className: "sticky top-0 z-10 bg-[var(--appkit-color-warning-surface)] border-b border-[var(--appkit-color-warning)] text-[var(--appkit-color-warning-text,var(--appkit-color-warning))]", paddingY: "y-xs", paddingX: "x-md", children: [_jsx(Eye, { className: "w-4 h-4 flex-shrink-0" }), _jsx(Span, { children: "Preview \u2014 not visible to buyers until published" })] }), _jsx(Div, { padding: "y-md", children: previewSlot() })] })) : splitPreview && previewSlot ? (
|
|
126
126
|
// S-STORE-3-D — desktop 60/40 split: form left, preview right.
|
|
127
127
|
// Below `lg`, falls back to single-column form (preview-as-modal via existing toggle).
|
|
128
|
-
_jsxs(Div, { className: "lg:grid lg:grid-cols-[3fr_2fr] lg:gap-[1.5rem] lg:px-[1.5rem] lg:py-[1.5rem] lg:max-w-[1400px] lg:mx-auto", children: [_jsx(Div, { className: "max-w-3xl mx-auto px-[1.25rem] sm:px-[1.5rem] lg:max-w-none lg:px-[0] lg:py-[0]", padding: "y-lg", children: children }), _jsxs(Div, { className: `hidden lg:block sticky lg:top-4 lg:self-start lg:max-h-[calc(100vh-6rem)] ${__O.yAuto} border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-raised)] ${__P.p4}`, rounded: "lg", children: [_jsxs(Row, { textWeight: "semibold", textSize: "xs", gap: "xs", className: "mb-3 uppercase tracking-wide text-[var(--appkit-color-text-muted)]", children: [_jsx(Eye, { className: "w-3.5 h-3.5" }), _jsx(Span, { children: "Live preview" })] }), previewSlot()] })] })) : (_jsx(Div, { className: "max-w-3xl mx-auto px-[1.25rem] sm:px-[1.5rem]", padding: "y-lg", children: children })) })] }), !previewMode && renderBottomBar ? (renderBottomBar()) : !previewMode && (onSaveDraft || onPublish) ? (_jsxs(Stack, { gap: "none", className: "flex-shrink-0 sticky bottom-0 z-10 border-t border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)]", children: [footerTopSlot && (_jsx(Div, { paddingX: "x-5", padding: "t-sm", children: footerTopSlot })), _jsxs(
|
|
128
|
+
_jsxs(Div, { className: "lg:grid lg:grid-cols-[3fr_2fr] lg:gap-[1.5rem] lg:px-[1.5rem] lg:py-[1.5rem] lg:max-w-[1400px] lg:mx-auto", children: [_jsx(Div, { className: "max-w-3xl mx-auto px-[1.25rem] sm:px-[1.5rem] lg:max-w-none lg:px-[0] lg:py-[0]", padding: "y-lg", children: children }), _jsxs(Div, { className: `hidden lg:block sticky lg:top-4 lg:self-start lg:max-h-[calc(100vh-6rem)] ${__O.yAuto} border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-raised)] ${__P.p4}`, rounded: "lg", children: [_jsxs(Row, { textWeight: "semibold", textSize: "xs", gap: "xs", className: "mb-3 uppercase tracking-wide text-[var(--appkit-color-text-muted)]", children: [_jsx(Eye, { className: "w-3.5 h-3.5" }), _jsx(Span, { children: "Live preview" })] }), previewSlot()] })] })) : (_jsx(Div, { className: "max-w-3xl mx-auto px-[1.25rem] sm:px-[1.5rem]", padding: "y-lg", children: children })) })] }), !previewMode && renderBottomBar ? (renderBottomBar()) : !previewMode && (onSaveDraft || onPublish) ? (_jsxs(Stack, { gap: "none", className: "flex-shrink-0 sticky bottom-0 z-10 border-t border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)]", children: [footerTopSlot && (_jsx(Div, { paddingX: "x-5", padding: "t-sm", children: footerTopSlot })), _jsxs(ActionRow, { align: "end", paddingX: "x-5", padding: "y-sm", style: { paddingBottom: "calc(var(--appkit-space-3) + var(--keyboard-inset-height, 0px))" }, anchor: _jsx(Button, { variant: "ghost", size: "sm", onClick: attemptClose, disabled: isLoading, children: FORM_ACTION_META[FORM_ACTION_ID.DISCARD].label }), children: [onSaveDraft && (_jsx(Button, { variant: "outline", size: "sm", onClick: handleSaveDraft, disabled: isLoading || savingDraft || publishing, isLoading: savingDraft, children: saveLabel })), onPublish && (_jsxs(Button, { variant: "primary", size: "sm", onClick: handlePublish, disabled: isLoading || savingDraft || publishing, isLoading: publishing, children: [publishLabel, " \u2192"] }))] })] })) : null] }), showUnsaved && (_jsxs(_Fragment, { children: [_jsx(Div, { surface: "overlay-lg", className: "fixed inset-0", style: { zIndex: "var(--appkit-z-confirm)" }, onClick: () => setShowUnsaved(false) }), _jsxs(Div, { className: "fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[90vw] max-w-sm bg-[var(--appkit-color-surface)]", shadow: "2xl", rounded: "xl", padding: "lg", style: { zIndex: "var(--appkit-z-confirm)" }, children: [_jsxs(Row, { gap: "sm", align: "start", className: "mb-4", children: [_jsx(Span, { layout: "flex-center", className: "flex-shrink-0 w-10 h-10 bg-[var(--appkit-color-warning-surface)]", rounded: "full", children: _jsx(AlertTriangle, { className: "w-5 h-5 text-[var(--appkit-color-warning)]" }) }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { className: "text-[var(--appkit-color-text)]", weight: "semibold", children: "Unsaved changes" }), _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: "You have unsaved changes. Leave without saving?" })] })] }), _jsxs(Row, { gap: "xs", justify: "end", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: () => setShowUnsaved(false), children: "Stay" }), _jsx(Button, { variant: "danger", size: "sm", onClick: () => { setShowUnsaved(false); onClose(); }, children: "Leave" })] })] })] }))] }));
|
|
129
129
|
}
|
|
@@ -6,7 +6,7 @@ import { Button } from "../../ui/components/Button";
|
|
|
6
6
|
import { IconButton } from "../../ui/components/IconButton";
|
|
7
7
|
import { FormField } from "../../ui/components/FormField";
|
|
8
8
|
import { Toggle } from "../../ui/components/Toggle";
|
|
9
|
-
import { Div, Form, Row, Stack, Text } from "../../ui";
|
|
9
|
+
import { ActionRow, Div, Form, Row, Stack, Text } from "../../ui";
|
|
10
10
|
import { FormShellContext, FormErrorSummary } from "../../ui/forms";
|
|
11
11
|
import { useHandMode } from "../../_internal/client/hand-mode";
|
|
12
12
|
function initValues(fields, defaults = {}) {
|
|
@@ -203,5 +203,5 @@ export function QuickFormDrawer({ isOpen, onClose, title, fields, defaultValues,
|
|
|
203
203
|
: field.type === "select"
|
|
204
204
|
? "select"
|
|
205
205
|
: "text", value: String(value ?? ""), onChange: (v) => set(field.name, field.type === "number" ? Number(v) : v), options: field.options, placeholder: field.placeholder, disabled: busy, error: errors[field.name] }), field.helperText && !errors[field.name] && (_jsx(Text, { className: "mt-1 text-[var(--appkit-color-text-muted)]", size: "xs", children: field.helperText }))] }, field.name));
|
|
206
|
-
}), renderExtra?.(values, set)] }), _jsxs(Div, { className: "flex-shrink-0 border-t border-[var(--appkit-color-border)] bg-[var(--appkit-color-bg)]", children: [_jsx(Div, { paddingX: "x-md", padding: "t-sm", children: _jsx(FormErrorSummary, {}) }), _jsxs(
|
|
206
|
+
}), renderExtra?.(values, set)] }), _jsxs(Div, { className: "flex-shrink-0 border-t border-[var(--appkit-color-border)] bg-[var(--appkit-color-bg)]", children: [_jsx(Div, { paddingX: "x-md", padding: "t-sm", children: _jsx(FormErrorSummary, {}) }), _jsxs(ActionRow, { padding: "md", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: handleClose, disabled: busy, children: cancelLabel }), _jsxs(Button, { variant: "primary", size: "sm", onClick: () => void handleSubmit(), disabled: busy, isLoading: busy, children: [submitLabel, " \u2192"] })] })] })] })] }) }));
|
|
207
207
|
}
|
|
@@ -110,6 +110,14 @@ export interface SectionFormProps<T extends object = Record<string, JsonValue>>
|
|
|
110
110
|
export declare function orderSections<T extends object>(sections: SectionDef<T>[]): SectionDef<T>[];
|
|
111
111
|
/** `fieldName -> index into the ORDERED section list`. */
|
|
112
112
|
export declare function buildFieldToSectionIndex<T extends object>(ordered: SectionDef<T>[]): Record<string, number>;
|
|
113
|
+
export interface UseSectionFormNavOptions {
|
|
114
|
+
/**
|
|
115
|
+
* `"{portal}:{surface}"` — persists this form's open set to the user's
|
|
116
|
+
* profile. Omit for in-memory-only, which is the default and what every
|
|
117
|
+
* pre-existing call site gets.
|
|
118
|
+
*/
|
|
119
|
+
scope?: string;
|
|
120
|
+
}
|
|
113
121
|
export interface UseSectionFormNavResult<T extends object> {
|
|
114
122
|
/** Sections in render order — required first. */
|
|
115
123
|
ordered: SectionDef<T>[];
|
|
@@ -126,8 +134,18 @@ export interface UseSectionFormNavResult<T extends object> {
|
|
|
126
134
|
* `fieldToSectionIndex` into `useFormShellState(schema, nav)` and `openIds`
|
|
127
135
|
* back into `<SectionForm>`.
|
|
128
136
|
*/
|
|
129
|
-
export declare function useSectionFormNav<T extends object = Record<string, JsonValue>>(sections: SectionDef<T>[], values?: T): UseSectionFormNavResult<T>;
|
|
137
|
+
export declare function useSectionFormNav<T extends object = Record<string, JsonValue>>(sections: SectionDef<T>[], values?: T, opts?: UseSectionFormNavOptions): UseSectionFormNavResult<T>;
|
|
130
138
|
/** DOM id for a section panel — kept in one place so nav and render agree. */
|
|
131
139
|
export declare function sectionAnchorId(id: string): string;
|
|
140
|
+
/**
|
|
141
|
+
* Scroll a section into view and focus the first invalid control inside it.
|
|
142
|
+
*
|
|
143
|
+
* Deliberately module-level and shared by `goToSection` and `SectionForm`'s own
|
|
144
|
+
* submit handler: the deferred frame is the load-bearing part and is easy to
|
|
145
|
+
* drop when copying. The panel must MOUNT before it can be scrolled to —
|
|
146
|
+
* expanding is a state update, so without the deferral the scroll lands on a
|
|
147
|
+
* zero-height collapsed header and the offending field stays off-screen.
|
|
148
|
+
*/
|
|
149
|
+
export declare function scrollToSection(id: string): void;
|
|
132
150
|
export declare function SectionForm<T extends object = Record<string, JsonValue>>({ sections, values, onChange, onSubmit, submitLabel, isLoading, schema, openIds: controlledOpenIds, onOpenChange, expandMode, hideActions, destructiveAction, onValidationChange, onCancel, cancelLabel, bottomBar, }: SectionFormProps<T>): import("react").JSX.Element;
|
|
133
151
|
export default SectionForm;
|