@mohasinac/appkit 4.30.19 → 4.31.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_internal/client/features/layout/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 -87
- package/dist/_internal/client/features/lottery/LotteryPullForm.d.ts +16 -5
- package/dist/_internal/client/features/lottery/LotteryPullForm.js +65 -40
- 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/categories/data.js +15 -4
- 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/live/index.d.ts +0 -1
- package/dist/_internal/server/features/live/index.js +0 -1
- package/dist/_internal/server/features/products/data.js +15 -5
- 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/site-settings/adapters.d.ts +2 -2
- package/dist/_internal/server/features/site-settings/adapters.js +8 -5
- 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/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/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/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.d.ts +37 -20
- package/dist/client.js +36 -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/extend.d.ts +0 -9
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/realtime-session.js +7 -0
- 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/messages.d.ts +0 -8
- package/dist/errors/messages.js +0 -9
- 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/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/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/auth/actions/index.d.ts +0 -1
- package/dist/features/auth/actions/index.js +0 -1
- 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/Guards.js +2 -1
- package/dist/features/auth/components/LoginForm.d.ts +0 -2
- package/dist/features/auth/components/LoginForm.js +1 -3
- package/dist/features/auth/components/RegisterForm.js +62 -19
- 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/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/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/schemas/bundle-form.d.ts +142 -0
- package/dist/features/categories/schemas/bundle-form.js +149 -0
- package/dist/features/classified/components/ClassifiedDetailPageView.d.ts +5 -4
- package/dist/features/classified/components/ClassifiedDetailPageView.js +37 -16
- 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/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/homepage/components/MarketplaceHomepageView.js +24 -5
- package/dist/features/homepage/hooks/useBlogArticles.js +1 -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/lottery/schemas/config-write.d.ts +9 -5
- package/dist/features/lottery/schemas/config-write.js +69 -9
- 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/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/ProductDetailActions.js +0 -1
- package/dist/features/products/components/ProductDetailPageView.d.ts +7 -3
- package/dist/features/products/components/ProductDetailPageView.js +8 -5
- 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/products.repository.d.ts +5 -1
- package/dist/features/products/repository/products.repository.js +23 -1
- 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 +8 -7
- 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 -24
- 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/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/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/SellerDigitalCodesView.d.ts +14 -7
- package/dist/features/seller/components/SellerDigitalCodesView.js +4 -126
- 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/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/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/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 +275 -29
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +48 -12
- package/dist/http/api-handler.js +2 -1
- package/dist/index.d.ts +24 -103
- package/dist/index.js +33 -141
- 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 +6 -3
- package/dist/next/index.d.ts +7 -2
- package/dist/next/index.js +36 -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/db-firebase/admin.js +15 -1
- package/dist/providers/db-firebase/sieve.d.ts +22 -0
- 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/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/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
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* SellerSupportView — the tickets raised about this seller's store.
|
|
5
|
+
*
|
|
6
|
+
* ## Why there was nothing here before
|
|
7
|
+
*
|
|
8
|
+
* Support has always had a buyer surface and an admin surface and no seller
|
|
9
|
+
* one — no page, no API route, not even a `ROUTES.STORE.SUPPORT` constant.
|
|
10
|
+
* The reason was structural rather than an oversight: `SupportTicketDocument`
|
|
11
|
+
* had no queryable `storeId`, so "the tickets about my store" was not a
|
|
12
|
+
* question the data could answer.
|
|
13
|
+
*
|
|
14
|
+
* There is a category called `store_change_request` — sellers asking an admin
|
|
15
|
+
* to change a store field they cannot edit themselves — which a seller could
|
|
16
|
+
* only ever file through the BUYER surface, and then never see again from the
|
|
17
|
+
* store dashboard.
|
|
18
|
+
*
|
|
19
|
+
* ## Read-only, deliberately
|
|
20
|
+
*
|
|
21
|
+
* A seller can see and follow a ticket about their store; replying goes
|
|
22
|
+
* through the ticket thread the buyer and admin already share, and status is
|
|
23
|
+
* an admin decision. Giving a seller a status control here would let them
|
|
24
|
+
* close a complaint made against them.
|
|
25
|
+
*/
|
|
26
|
+
import React from "react";
|
|
27
|
+
import { Badge, Span, Stack, Text } from "../../../ui";
|
|
28
|
+
import { DataListingView } from "../../admin/components/DataListingView";
|
|
29
|
+
import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
30
|
+
import { SUPPORT_TICKET_FIELDS } from "../../../constants/field-names";
|
|
31
|
+
import { sieveFilter, SIEVE_OP } from "../../../utils/sieve-builder";
|
|
32
|
+
import { toRelativeDate, toStringValue } from "../../admin/hooks/useAdminListingData";
|
|
33
|
+
/** Status → badge tone. Mirrors `TicketStatusValues`. */
|
|
34
|
+
const STATUS_VARIANT = {
|
|
35
|
+
open: "info",
|
|
36
|
+
in_progress: "warning",
|
|
37
|
+
waiting_on_user: "warning",
|
|
38
|
+
resolved: "success",
|
|
39
|
+
closed: "default",
|
|
40
|
+
};
|
|
41
|
+
export function SellerSupportView({ labels = {} }) {
|
|
42
|
+
const mapRows = React.useCallback((response) => {
|
|
43
|
+
const items = Array.isArray(response?.items) ? response.items : [];
|
|
44
|
+
return items.map((raw) => {
|
|
45
|
+
const t = (raw ?? {});
|
|
46
|
+
return {
|
|
47
|
+
id: toStringValue(t.id),
|
|
48
|
+
primary: toStringValue(t.subject),
|
|
49
|
+
secondary: toStringValue(t.description).slice(0, 140),
|
|
50
|
+
status: toStringValue(t.status),
|
|
51
|
+
category: toStringValue(t.category).replace(/_/g, " "),
|
|
52
|
+
updated: toRelativeDate(t.updatedAt ?? t.createdAt),
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
}, []);
|
|
56
|
+
return (_jsxs(Stack, { gap: "md", children: [_jsx(DataListingView, { config: {
|
|
57
|
+
portal: "seller",
|
|
58
|
+
title: labels.title ?? "Support",
|
|
59
|
+
subtitle: "Tickets buyers and staff have raised about your store.",
|
|
60
|
+
/*
|
|
61
|
+
* The box is declared only because the endpoint now serves it —
|
|
62
|
+
* `supportTickets` gained a `searchTxt` corpus in this same commit.
|
|
63
|
+
* `fields` names what is actually matched, and it is SUBJECT ONLY:
|
|
64
|
+
* the description and every message body are PII-encrypted at rest,
|
|
65
|
+
* so they are not in the index and a placeholder promising them
|
|
66
|
+
* would be a promise the backend cannot keep.
|
|
67
|
+
*/
|
|
68
|
+
search: {
|
|
69
|
+
placeholder: "Search by subject…",
|
|
70
|
+
mode: "partial",
|
|
71
|
+
fields: ["subject"],
|
|
72
|
+
commit: "debounce",
|
|
73
|
+
},
|
|
74
|
+
emptyLabel: "No tickets have been raised about your store.",
|
|
75
|
+
queryKey: ["store", "support-tickets"],
|
|
76
|
+
endpoint: SELLER_ENDPOINTS.SUPPORT,
|
|
77
|
+
filterKeys: ["status"],
|
|
78
|
+
defaultSort: "",
|
|
79
|
+
sortOptions: [],
|
|
80
|
+
mapRows,
|
|
81
|
+
getTotal: (response, rows) => response?.total ?? rows.length,
|
|
82
|
+
buildFilters: (filterState) => filterState.status
|
|
83
|
+
? sieveFilter(SUPPORT_TICKET_FIELDS.STATUS, SIEVE_OP.EQ, filterState.status)
|
|
84
|
+
: undefined,
|
|
85
|
+
columns: [
|
|
86
|
+
{ key: "primary", header: "Subject" },
|
|
87
|
+
{
|
|
88
|
+
key: "status",
|
|
89
|
+
header: "Status",
|
|
90
|
+
render: (row) => (_jsx(Badge, { variant: STATUS_VARIANT[row.status] ?? "default", children: row.status.replace(/_/g, " ") })),
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
key: "category",
|
|
94
|
+
header: "About",
|
|
95
|
+
render: (row) => (_jsx(Span, { size: "xs", color: "muted", children: row.category })),
|
|
96
|
+
},
|
|
97
|
+
{ key: "updated", header: "Updated" },
|
|
98
|
+
],
|
|
99
|
+
} }), _jsx(Text, { size: "xs", color: "muted", children: "Replies and status changes happen in the ticket thread with our support team \u2014 a ticket raised about your store is not one you can close." })] }));
|
|
100
|
+
}
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
export { SellerDashboardView } from "./SellerDashboardView";
|
|
2
2
|
export type { SellerDashboardViewProps } from "./SellerDashboardView";
|
|
3
3
|
export { SellerProductsView } from "./SellerProductsView";
|
|
4
|
+
export { SellerListingTypeView, SELLER_LISTING_TYPE_SPECS } from "./SellerListingTypeView";
|
|
5
|
+
export type { SellerListingTypeViewProps, SellerListingTypeSpec, SellerListingTypeKey, SellerListingRow } from "./SellerListingTypeView";
|
|
4
6
|
export type { SellerProductsViewProps } from "./SellerProductsView";
|
|
5
|
-
export { SellerAuctionsView } from "./SellerAuctionsView";
|
|
6
|
-
export type { SellerAuctionsViewProps } from "./SellerAuctionsView";
|
|
7
|
-
export { SellerPreOrdersView } from "./SellerPreOrdersView";
|
|
8
|
-
export type { SellerPreOrdersViewProps } from "./SellerPreOrdersView";
|
|
9
|
-
export { SellerPrizeDrawsView } from "./SellerPrizeDrawsView";
|
|
10
|
-
export type { SellerPrizeDrawsViewProps } from "./SellerPrizeDrawsView";
|
|
11
7
|
export { PrintCenterView } from "./PrintCenterView";
|
|
12
8
|
export { SellerOrdersView, SellerOrderDetailPanel } from "./SellerOrdersView";
|
|
13
9
|
export type { SellerOrdersViewProps } from "./SellerOrdersView";
|
|
@@ -62,8 +58,6 @@ export { SellerDashboardView as StoreDashboardView } from "./SellerDashboardView
|
|
|
62
58
|
export type { SellerDashboardViewProps as StoreDashboardViewProps } from "./SellerDashboardView";
|
|
63
59
|
export { SellerProductsView as StoreProductListingsView } from "./SellerProductsView";
|
|
64
60
|
export type { SellerProductsViewProps as StoreProductListingsViewProps } from "./SellerProductsView";
|
|
65
|
-
export { SellerAuctionsView as StoreAuctionsView } from "./SellerAuctionsView";
|
|
66
|
-
export type { SellerAuctionsViewProps as StoreAuctionsViewProps } from "./SellerAuctionsView";
|
|
67
61
|
export { SellerOrdersView as StoreOrdersView } from "./SellerOrdersView";
|
|
68
62
|
export type { SellerOrdersViewProps as StoreOrdersViewProps } from "./SellerOrdersView";
|
|
69
63
|
export { SellerOffersView as StoreOffersView } from "./SellerOffersView";
|
|
@@ -132,3 +126,5 @@ export { BarcodeField } from "./BarcodeField";
|
|
|
132
126
|
export type { BarcodeFieldProps } from "./BarcodeField";
|
|
133
127
|
export { FulfillmentView } from "./FulfillmentView";
|
|
134
128
|
export type { FulfillmentViewProps } from "./FulfillmentView";
|
|
129
|
+
export { SellerSupportView } from "./SellerSupportView";
|
|
130
|
+
export type { SellerSupportViewProps } from "./SellerSupportView";
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
export { SellerDashboardView } from "./SellerDashboardView";
|
|
2
2
|
export { SellerProductsView } from "./SellerProductsView";
|
|
3
|
-
export {
|
|
4
|
-
export { SellerPreOrdersView } from "./SellerPreOrdersView";
|
|
5
|
-
export { SellerPrizeDrawsView } from "./SellerPrizeDrawsView";
|
|
3
|
+
export { SellerListingTypeView, SELLER_LISTING_TYPE_SPECS } from "./SellerListingTypeView";
|
|
6
4
|
export { PrintCenterView } from "./PrintCenterView";
|
|
7
5
|
export { SellerOrdersView, SellerOrderDetailPanel } from "./SellerOrdersView";
|
|
8
6
|
export { SellerOffersView } from "./SellerOffersView";
|
|
@@ -34,7 +32,6 @@ export { StoreSidebar } from "./SellerSidebar";
|
|
|
34
32
|
export { SellerDashboardView as StoreDashboardView } from "./SellerDashboardView";
|
|
35
33
|
// SellerProductsView aliased as StoreProductListingsView (StoreProductsView is the public customer-facing store listing)
|
|
36
34
|
export { SellerProductsView as StoreProductListingsView } from "./SellerProductsView";
|
|
37
|
-
export { SellerAuctionsView as StoreAuctionsView } from "./SellerAuctionsView";
|
|
38
35
|
export { SellerOrdersView as StoreOrdersView } from "./SellerOrdersView";
|
|
39
36
|
export { SellerOffersView as StoreOffersView } from "./SellerOffersView";
|
|
40
37
|
export { SellerCouponsView as StoreCouponsView } from "./SellerCouponsView";
|
|
@@ -69,3 +66,4 @@ export { SellerDigitalCodesView } from "./SellerDigitalCodesView";
|
|
|
69
66
|
export { SellerLiveView } from "./SellerLiveView";
|
|
70
67
|
export { BarcodeField } from "./BarcodeField";
|
|
71
68
|
export { FulfillmentView } from "./FulfillmentView";
|
|
69
|
+
export { SellerSupportView } from "./SellerSupportView";
|
|
@@ -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;
|