@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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { normalizeError } from "../../../../errors/normalize";
|
|
4
|
+
import { toUserMessage } from "../../../../errors/error-display-map";
|
|
4
5
|
import { useState } from "react";
|
|
5
6
|
import { Button, Div, Row, Span, Stack, Text } from "../../../../ui";
|
|
6
7
|
const __P = {
|
|
@@ -19,8 +20,10 @@ export function CodeRevealPanel({ orderId, redemptionInstructions, fetchCode, })
|
|
|
19
20
|
setRevealed(data);
|
|
20
21
|
}
|
|
21
22
|
catch (e) {
|
|
22
|
-
|
|
23
|
-
setError(
|
|
23
|
+
const normalized = normalizeError(e);
|
|
24
|
+
setError(toUserMessage(normalized.code, undefined, {
|
|
25
|
+
fallback: "Could not retrieve your code. Please try again.",
|
|
26
|
+
}));
|
|
24
27
|
}
|
|
25
28
|
finally {
|
|
26
29
|
setPending(false);
|
|
@@ -69,7 +69,7 @@ function useResponsiveDrawer(storageKey) {
|
|
|
69
69
|
localStorage.setItem(storageKey, "true");
|
|
70
70
|
}
|
|
71
71
|
catch (_err) {
|
|
72
|
-
void normalizeError(_err);
|
|
72
|
+
void normalizeError(_err); /* localStorage unavailable (private-browse / quota) — the sidebar still opens, only the preference is not remembered */
|
|
73
73
|
}
|
|
74
74
|
setDesktopOpen(true);
|
|
75
75
|
}
|
|
@@ -84,7 +84,7 @@ function useResponsiveDrawer(storageKey) {
|
|
|
84
84
|
localStorage.setItem(storageKey, "false");
|
|
85
85
|
}
|
|
86
86
|
catch (_err) {
|
|
87
|
-
void normalizeError(_err);
|
|
87
|
+
void normalizeError(_err); /* localStorage unavailable (private-browse / quota) — the sidebar still closes, only the preference is not remembered */
|
|
88
88
|
}
|
|
89
89
|
setDesktopOpen(false);
|
|
90
90
|
}
|
|
@@ -105,7 +105,7 @@ function useResponsiveDrawer(storageKey) {
|
|
|
105
105
|
localStorage.setItem(storageKey, String(next));
|
|
106
106
|
}
|
|
107
107
|
catch (_err) {
|
|
108
|
-
void normalizeError(_err);
|
|
108
|
+
void normalizeError(_err); /* localStorage unavailable (private-browse / quota) — the toggle still applies, only the preference is not remembered */
|
|
109
109
|
}
|
|
110
110
|
return next;
|
|
111
111
|
});
|
|
@@ -1,13 +1,29 @@
|
|
|
1
|
+
import { type NavSearchable } from "../../../shared/features/layout/matchesNavQuery";
|
|
1
2
|
/**
|
|
2
|
-
* Shared inline-filter logic for the Admin/Store/User sidebars
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Shared inline-filter logic for the Admin/Store/User sidebars. Each sidebar
|
|
4
|
+
* keeps its own accordion/markup; only this filtering is shared so it is not
|
|
5
|
+
* rewritten three times.
|
|
6
|
+
*
|
|
7
|
+
* ## It searches what a screen is FOR, not just what it is called
|
|
8
|
+
*
|
|
9
|
+
* This was `item.label.toLowerCase().includes(q)`, which could only find a
|
|
10
|
+
* screen by the name already on the button. "refund" found nothing, because
|
|
11
|
+
* the screen is called Payouts. "postcode" found nothing, because the field is
|
|
12
|
+
* called PIN code. "maintenance" found nothing, because that toggle lives
|
|
13
|
+
* inside Site Settings. W6 gave every nav item a `description` and `keywords`;
|
|
14
|
+
* `matchesNavQuery` reads all three.
|
|
15
|
+
*
|
|
16
|
+
* ## Results are RANKED, and within a group only
|
|
17
|
+
*
|
|
18
|
+
* A label hit beats a keyword hit beats a description hit, so typing "orders"
|
|
19
|
+
* puts **Orders** above the guide that merely mentions orders. Groups keep
|
|
20
|
+
* their declared order — reordering them by best score would move the sidebar
|
|
21
|
+
* around under the reader's cursor while they type.
|
|
6
22
|
*/
|
|
7
23
|
export declare function useSidebarSearch<Item extends {
|
|
8
24
|
href: string;
|
|
9
25
|
label: string;
|
|
10
|
-
}
|
|
26
|
+
} & Partial<NavSearchable>, Group extends {
|
|
11
27
|
title: string;
|
|
12
28
|
items: Item[];
|
|
13
29
|
defaultOpen?: boolean;
|
|
@@ -1,10 +1,26 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useMemo, useState } from "react";
|
|
3
|
+
import { matchesNavQuery } from "../../../shared/features/layout/matchesNavQuery";
|
|
3
4
|
/**
|
|
4
|
-
* Shared inline-filter logic for the Admin/Store/User sidebars
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* Shared inline-filter logic for the Admin/Store/User sidebars. Each sidebar
|
|
6
|
+
* keeps its own accordion/markup; only this filtering is shared so it is not
|
|
7
|
+
* rewritten three times.
|
|
8
|
+
*
|
|
9
|
+
* ## It searches what a screen is FOR, not just what it is called
|
|
10
|
+
*
|
|
11
|
+
* This was `item.label.toLowerCase().includes(q)`, which could only find a
|
|
12
|
+
* screen by the name already on the button. "refund" found nothing, because
|
|
13
|
+
* the screen is called Payouts. "postcode" found nothing, because the field is
|
|
14
|
+
* called PIN code. "maintenance" found nothing, because that toggle lives
|
|
15
|
+
* inside Site Settings. W6 gave every nav item a `description` and `keywords`;
|
|
16
|
+
* `matchesNavQuery` reads all three.
|
|
17
|
+
*
|
|
18
|
+
* ## Results are RANKED, and within a group only
|
|
19
|
+
*
|
|
20
|
+
* A label hit beats a keyword hit beats a description hit, so typing "orders"
|
|
21
|
+
* puts **Orders** above the guide that merely mentions orders. Groups keep
|
|
22
|
+
* their declared order — reordering them by best score would move the sidebar
|
|
23
|
+
* around under the reader's cursor while they type.
|
|
8
24
|
*/
|
|
9
25
|
export function useSidebarSearch(groups) {
|
|
10
26
|
const [query, setQuery] = useState("");
|
|
@@ -12,9 +28,14 @@ export function useSidebarSearch(groups) {
|
|
|
12
28
|
const filteredGroups = useMemo(() => {
|
|
13
29
|
if (!isSearching)
|
|
14
30
|
return groups;
|
|
15
|
-
const q = query.trim().toLowerCase();
|
|
16
31
|
return groups
|
|
17
|
-
.map((group) =>
|
|
32
|
+
.map((group) => {
|
|
33
|
+
const scored = group.items
|
|
34
|
+
.map((item) => ({ item, score: matchesNavQuery(item, query) }))
|
|
35
|
+
.filter((entry) => entry.score > 0)
|
|
36
|
+
.sort((a, b) => b.score - a.score);
|
|
37
|
+
return { ...group, items: scored.map((entry) => entry.item) };
|
|
38
|
+
})
|
|
18
39
|
.filter((group) => group.items.length > 0);
|
|
19
40
|
}, [groups, query, isSearching]);
|
|
20
41
|
return { query, setQuery, isSearching, filteredGroups };
|
|
@@ -1,5 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LotteryAdminEditView — the slot configuration for one lottery. Sectionised
|
|
3
|
+
* 2026-08-30.
|
|
4
|
+
*
|
|
5
|
+
* ## Two schemas became one
|
|
6
|
+
*
|
|
7
|
+
* It declared `lotteryConfigFormSchema` on `<Form>` and parsed
|
|
8
|
+
* `lotteryConfigWriteSchema` in the submit handler, so the form schema's
|
|
9
|
+
* duplicate-slot and free-lottery rules had never executed. The form schema is
|
|
10
|
+
* deleted; `lotteryConfigWriteSchema` carries the annotations now and is both
|
|
11
|
+
* what this form renders from and what the route parses.
|
|
12
|
+
*
|
|
13
|
+
* ## Title and description are gone, not moved
|
|
14
|
+
*
|
|
15
|
+
* They were editable here and reached nothing: `LotteryConfigClient` posts
|
|
16
|
+
* `data.lotteryConfig` to `PUT .../lottery-config` and ignores the rest, and
|
|
17
|
+
* that route accepts only the config. An event's title, dates, status and
|
|
18
|
+
* media are edited in the ordinary event editor — this page is the slots. Two
|
|
19
|
+
* inputs that saved silently into nowhere are worse than their absence, which
|
|
20
|
+
* is the same call made on `rememberMe`. The title still appears, as the
|
|
21
|
+
* heading, so it is obvious which lottery is open.
|
|
22
|
+
*/
|
|
1
23
|
import React from "react";
|
|
2
24
|
import type { LotteryConfigWriteInput } from "../../../../features/lottery/schemas/config-write";
|
|
25
|
+
/** One editable row of the slot table. */
|
|
3
26
|
interface LotterySlotRow {
|
|
4
27
|
slotNumber: number;
|
|
5
28
|
name: string;
|
|
@@ -22,9 +45,6 @@ interface LotterySlotRow {
|
|
|
22
45
|
* fullness check reads.
|
|
23
46
|
*/
|
|
24
47
|
interface LotteryEventFormData {
|
|
25
|
-
title: string;
|
|
26
|
-
description?: string;
|
|
27
|
-
type: "lottery";
|
|
28
48
|
lotteryConfig: LotteryConfigWriteInput;
|
|
29
49
|
}
|
|
30
50
|
interface LotteryAdminEditViewProps {
|
|
@@ -1,97 +1,121 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
/**
|
|
4
|
+
* LotteryAdminEditView — the slot configuration for one lottery. Sectionised
|
|
5
|
+
* 2026-08-30.
|
|
6
|
+
*
|
|
7
|
+
* ## Two schemas became one
|
|
8
|
+
*
|
|
9
|
+
* It declared `lotteryConfigFormSchema` on `<Form>` and parsed
|
|
10
|
+
* `lotteryConfigWriteSchema` in the submit handler, so the form schema's
|
|
11
|
+
* duplicate-slot and free-lottery rules had never executed. The form schema is
|
|
12
|
+
* deleted; `lotteryConfigWriteSchema` carries the annotations now and is both
|
|
13
|
+
* what this form renders from and what the route parses.
|
|
14
|
+
*
|
|
15
|
+
* ## Title and description are gone, not moved
|
|
16
|
+
*
|
|
17
|
+
* They were editable here and reached nothing: `LotteryConfigClient` posts
|
|
18
|
+
* `data.lotteryConfig` to `PUT .../lottery-config` and ignores the rest, and
|
|
19
|
+
* that route accepts only the config. An event's title, dates, status and
|
|
20
|
+
* media are edited in the ordinary event editor — this page is the slots. Two
|
|
21
|
+
* inputs that saved silently into nowhere are worse than their absence, which
|
|
22
|
+
* is the same call made on `rememberMe`. The title still appears, as the
|
|
23
|
+
* heading, so it is obvious which lottery is open.
|
|
24
|
+
*/
|
|
25
|
+
import React from "react";
|
|
26
|
+
import { Button, DataTable, Input, Row, Stack, Text, } from "../../../../ui";
|
|
9
27
|
import { FormErrorSummary } from "../../../../ui/forms/FormErrorSummary";
|
|
28
|
+
import { FormShellContext, useFormShellState } from "../../../../ui/forms/FormShell";
|
|
29
|
+
import { applyZodIssues } from "../../../../ui/forms/apply-zod-issues";
|
|
30
|
+
import { StackedViewShell } from "../../../../ui";
|
|
31
|
+
import { buildSectionsFromSchema, visibleValues } from "../../../../features/shell/build-sections";
|
|
32
|
+
import { SectionForm, useSectionFormNav } from "../../../../features/shell/SectionForm";
|
|
33
|
+
import { lotteryConfigWriteSchema } from "../../../../features/lottery/schemas/config-write";
|
|
34
|
+
const MAX_SLOTS = 200;
|
|
10
35
|
export function LotteryAdminEditView({ eventId, initialData, onSubmit, }) {
|
|
11
|
-
const [isPending, startTransition] = useTransition();
|
|
12
|
-
const [
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
};
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
? { ...s, [field]: field === "price" ? Math.round(parseFloat(value) * 100) / 100 || 0 : value }
|
|
33
|
-
: s));
|
|
34
|
-
};
|
|
36
|
+
const [isPending, startTransition] = React.useTransition();
|
|
37
|
+
const [form, setForm] = React.useState({
|
|
38
|
+
pricingMode: initialData?.pricingMode ?? "uniform",
|
|
39
|
+
uniformPrice: initialData?.uniformPrice ?? 0,
|
|
40
|
+
drawWindowDurationMinutes: initialData?.drawWindowDurationMinutes ?? 5,
|
|
41
|
+
maxPullsPerTransaction: initialData?.maxPullsPerTransaction ?? 1,
|
|
42
|
+
maxPullsPerUser: initialData?.maxPullsPerUser ?? 1,
|
|
43
|
+
slots: initialData?.slots ?? [{ slotNumber: 1, name: "", price: 0 }],
|
|
44
|
+
});
|
|
45
|
+
const patch = (partial) => setForm((prev) => Object.assign({}, prev, partial));
|
|
46
|
+
const sections = React.useMemo(() => buildSectionsFromSchema(lotteryConfigWriteSchema, {
|
|
47
|
+
renderers: {
|
|
48
|
+
slots: ({ values, onChange }) => (_jsx(SlotTable, { slots: values.slots, showPrice: values.pricingMode === "variable", onSlotsChange: (next) => onChange({ slots: next }) })),
|
|
49
|
+
},
|
|
50
|
+
}), []);
|
|
51
|
+
const nav = useSectionFormNav(sections, form, { scope: "admin:lottery-config" });
|
|
52
|
+
const { shellCtx, setFieldError, clearErrors } = useFormShellState(lotteryConfigWriteSchema, {
|
|
53
|
+
sections: nav.sectionMeta,
|
|
54
|
+
onGoToSection: nav.goToSection,
|
|
55
|
+
fieldToSectionIndex: nav.fieldToSectionIndex,
|
|
56
|
+
});
|
|
35
57
|
const handleSubmit = () => {
|
|
36
|
-
|
|
58
|
+
clearErrors();
|
|
59
|
+
/*
|
|
60
|
+
* Per-slot prices are dropped under uniform pricing, where the price of a
|
|
61
|
+
* slot IS `uniformPrice`. They used to be sent in both modes, so a figure
|
|
62
|
+
* loaded from `initialData` survived a switch to uniform — unreachable on
|
|
63
|
+
* screen, still written on save. `visibleValues` cannot reach inside an
|
|
64
|
+
* array, so this one masking stays explicit.
|
|
65
|
+
*/
|
|
66
|
+
const draft = visibleValues(lotteryConfigWriteSchema, form);
|
|
67
|
+
const candidate = {
|
|
68
|
+
...draft,
|
|
69
|
+
slots: form.slots.map((s) => ({
|
|
70
|
+
slotNumber: s.slotNumber,
|
|
71
|
+
name: s.name,
|
|
72
|
+
image: s.image?.trim() || undefined,
|
|
73
|
+
price: form.pricingMode === "variable" ? s.price : 0,
|
|
74
|
+
})),
|
|
75
|
+
};
|
|
76
|
+
const parsed = lotteryConfigWriteSchema.safeParse(candidate);
|
|
77
|
+
if (!parsed.success) {
|
|
78
|
+
applyZodIssues(parsed.error.issues, setFieldError);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
37
81
|
startTransition(async () => {
|
|
38
|
-
|
|
39
|
-
/*
|
|
40
|
-
* 🛑 This used to send `isBooked: false` and `weight: 0` on every slot,
|
|
41
|
-
* and drop `bookedByUserId` / `bookedByDisplayName` /
|
|
42
|
-
* `bookedByUserLotteryNumber` entirely — against a `.passthrough()`
|
|
43
|
-
* PATCH, which made the first save of a live lottery erase every
|
|
44
|
-
* purchased slot, silently, with a 200.
|
|
45
|
-
*
|
|
46
|
-
* The write shape now has NO booking fields at all and is `.strict()`,
|
|
47
|
-
* so a slot's buyer is not something this form can express, let alone
|
|
48
|
-
* overwrite. `PUT /lottery-config` merges by `slotNumber` against the
|
|
49
|
-
* stored config and is the only writer.
|
|
50
|
-
*/
|
|
51
|
-
const candidate = {
|
|
52
|
-
slots: slots.map((s) => ({
|
|
53
|
-
slotNumber: s.slotNumber,
|
|
54
|
-
name: s.name,
|
|
55
|
-
image: s.image?.trim() || undefined,
|
|
56
|
-
price: s.price,
|
|
57
|
-
})),
|
|
58
|
-
pricingMode,
|
|
59
|
-
uniformPrice: pricingMode === "uniform"
|
|
60
|
-
? Math.round(parseFloat(uniformPrice) * 100) / 100 || 0
|
|
61
|
-
: undefined,
|
|
62
|
-
drawWindowDurationMinutes: parseInt(drawWindowMinutes, 10) || 5,
|
|
63
|
-
maxPullsPerTransaction: parseInt(maxPullsPerTx, 10) || 1,
|
|
64
|
-
maxPullsPerUser: parseInt(maxPullsPerUser, 10) || 1,
|
|
65
|
-
};
|
|
66
|
-
/*
|
|
67
|
-
* The schema was passed to `<Form>` and never actually run — so the
|
|
68
|
-
* `parseFloat(x) || 0` coercions above, which it exists to catch, were
|
|
69
|
-
* still live. Parsed here so a bad slot is refused on the client
|
|
70
|
-
* rather than discovered as a 400.
|
|
71
|
-
*/
|
|
72
|
-
const parsed = lotteryConfigWriteSchema.safeParse(candidate);
|
|
73
|
-
if (!parsed.success) {
|
|
74
|
-
setError(parsed.error.issues[0]?.message ?? "Check the lottery settings.");
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
await onSubmit({ title, description, type: "lottery", lotteryConfig: parsed.data });
|
|
78
|
-
}
|
|
79
|
-
catch (err) {
|
|
80
|
-
void normalizeError(err);
|
|
81
|
-
setError(err instanceof Error ? err.message : "Failed to save lottery");
|
|
82
|
-
}
|
|
82
|
+
await onSubmit({ lotteryConfig: parsed.data });
|
|
83
83
|
});
|
|
84
84
|
};
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
return (_jsx(StackedViewShell, { portal: "admin", title: eventId
|
|
86
|
+
? `Edit lottery${initialData?.title ? ` — ${initialData.title}` : ""}`
|
|
87
|
+
: "Create lottery", sections: [
|
|
88
|
+
_jsxs(FormShellContext.Provider, { value: shellCtx, children: [_jsx(FormErrorSummary, {}), _jsx(SectionForm, { sections: sections, values: form, onChange: patch, onSubmit: handleSubmit, schema: lotteryConfigWriteSchema, openIds: nav.openIds, onOpenChange: nav.setOpenIds, isLoading: isPending, submitLabel: eventId ? "Update lottery" : "Create lottery" })] }, "lottery-config-form"),
|
|
89
|
+
] }));
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* The repeatable slot rows.
|
|
93
|
+
*
|
|
94
|
+
* A module-level component rather than an inline renderer: its handlers would
|
|
95
|
+
* otherwise sit six braces deep inside `useMemo`, which is what
|
|
96
|
+
* `audit-code-quality`'s DEEP_NESTING rule exists to stop.
|
|
97
|
+
*/
|
|
98
|
+
function SlotTable({ slots, showPrice, onSlotsChange, }) {
|
|
99
|
+
const addSlot = () => onSlotsChange([...slots, { slotNumber: slots.length + 1, name: "", price: 0 }]);
|
|
100
|
+
const removeSlot = (idx) => onSlotsChange(slots.filter((_, i) => i !== idx).map((s, i) => ({ ...s, slotNumber: i + 1 })));
|
|
101
|
+
const updateSlot = (idx, field, value) => onSlotsChange(slots.map((s, i) => i === idx
|
|
102
|
+
? {
|
|
103
|
+
...s,
|
|
104
|
+
[field]: field === "price"
|
|
105
|
+
? Math.round(parseFloat(value) * 100) / 100 || 0
|
|
106
|
+
: value,
|
|
107
|
+
}
|
|
108
|
+
: s));
|
|
109
|
+
const rows = slots.map((s, i) => ({ ...s, _idx: i }));
|
|
110
|
+
const columns = [
|
|
87
111
|
{
|
|
88
112
|
key: "slotNumber",
|
|
89
113
|
header: "#",
|
|
90
|
-
render: (s) => _jsx(Text, { size: "xs", color: "muted", family: "mono", children: s.slotNumber }),
|
|
114
|
+
render: (s) => (_jsx(Text, { size: "xs", color: "muted", family: "mono", children: s.slotNumber })),
|
|
91
115
|
},
|
|
92
116
|
{
|
|
93
117
|
key: "name",
|
|
94
|
-
header: "Prize
|
|
118
|
+
header: "Prize name",
|
|
95
119
|
render: (s) => (_jsx(Input, { type: "text", className: "w-full", placeholder: `Prize for slot ${s.slotNumber}`, value: s.name, onChange: (e) => updateSlot(s._idx, "name", e.target.value), "aria-label": `Slot ${s.slotNumber} prize name` })),
|
|
96
120
|
},
|
|
97
121
|
{
|
|
@@ -99,7 +123,7 @@ export function LotteryAdminEditView({ eventId, initialData, onSubmit, }) {
|
|
|
99
123
|
header: "Image",
|
|
100
124
|
render: (s) => (_jsx(Input, { type: "text", className: "w-full", placeholder: "/media/\u2026 or https://\u2026", value: s.image ?? "", onChange: (e) => updateSlot(s._idx, "image", e.target.value), "aria-label": `Slot ${s.slotNumber} prize image URL` })),
|
|
101
125
|
},
|
|
102
|
-
...(
|
|
126
|
+
...(showPrice
|
|
103
127
|
? [
|
|
104
128
|
{
|
|
105
129
|
key: "price",
|
|
@@ -109,9 +133,5 @@ export function LotteryAdminEditView({ eventId, initialData, onSubmit, }) {
|
|
|
109
133
|
]
|
|
110
134
|
: []),
|
|
111
135
|
];
|
|
112
|
-
|
|
113
|
-
return (_jsx(Container, { children: _jsx(Section, { children: _jsx(Form, { schema: lotteryConfigFormSchema, onSubmit: (e) => e.preventDefault(), className: "space-y-6", children: ({ clearErrors }) => (_jsxs(Stack, { gap: "xl", children: [_jsx(FormErrorSummary, {}), _jsx(Heading, { level: 1, size: "2xl", weight: "bold", children: eventId ? "Edit Lottery" : "Create Lottery" }), _jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 2, size: "lg", weight: "semibold", children: "Basic Info" }), _jsx(FieldInput, { name: "title", label: "Title", required: true, value: title, onChange: (v) => { setTitle(v); clearErrors(); } }), _jsx(FieldInput, { name: "description", label: "Description", value: description, onChange: (v) => { setDescription(v); clearErrors(); } })] }), _jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 2, size: "lg", weight: "semibold", children: "Configuration" }), _jsx(FieldSelect, { name: "pricingMode", label: "Pricing Mode", value: pricingMode, options: [
|
|
114
|
-
{ label: "Uniform (all slots same price)", value: "uniform" },
|
|
115
|
-
{ label: "Variable (per-slot pricing)", value: "variable" },
|
|
116
|
-
], onChange: (v) => setPricingMode(v) }), pricingMode === "uniform" && (_jsx(FieldInput, { name: "uniformPrice", label: "Price per Slot (\u20B9)", type: "number", value: uniformPrice, onChange: (v) => setUniformPrice(v) })), _jsx(FieldInput, { name: "drawWindowMinutes", label: "Draw Window (minutes)", type: "number", value: drawWindowMinutes, onChange: (v) => setDrawWindowMinutes(v) }), _jsx(FieldInput, { name: "maxPullsPerTx", label: "Max Pulls per Transaction", type: "number", value: maxPullsPerTx, onChange: (v) => setMaxPullsPerTx(v) }), _jsx(FieldInput, { name: "maxPullsPerUser", label: "Max Pulls per User", type: "number", value: maxPullsPerUser, onChange: (v) => setMaxPullsPerUser(v) })] }), _jsxs(Stack, { gap: "md", children: [_jsxs(Row, { align: "center", justify: "between", children: [_jsxs(Heading, { level: 2, size: "lg", weight: "semibold", children: ["Slots (", slots.length, ")"] }), _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: addSlot, disabled: slots.length >= 200, children: "+ Add Slot" })] }), _jsx(DataTable, { data: slotsWithIdx, columns: slotColumns, keyExtractor: (s) => String(s.slotNumber), emptyMessage: "No slots yet.", actions: (s) => slots.length > 1 ? (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => removeSlot(s._idx), "aria-label": `Remove slot ${s.slotNumber}`, children: "\u00D7" })) : null })] }), error && _jsx(Text, { className: "text-error", size: "sm", role: "alert", children: error }), _jsx(Button, { type: "submit", variant: "primary", isLoading: isPending, onClick: handleSubmit, className: "w-full sm:w-auto", children: isPending ? "Saving…" : eventId ? "Update Lottery" : "Create Lottery" })] })) }) }) }));
|
|
136
|
+
return (_jsxs(Stack, { gap: "md", children: [_jsxs(Row, { align: "center", justify: "between", children: [_jsxs(Text, { size: "sm", color: "muted", children: [slots.length, " slot", slots.length === 1 ? "" : "s"] }), _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: addSlot, disabled: slots.length >= MAX_SLOTS, children: "+ Add slot" })] }), _jsx(DataTable, { data: rows, columns: columns, keyExtractor: (s) => String(s.slotNumber), emptyMessage: "No slots yet.", actions: (s) => slots.length > 1 ? (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => removeSlot(s._idx), "aria-label": `Remove slot ${s.slotNumber}`, children: "\u00D7" })) : null })] }));
|
|
117
137
|
}
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User-facing lottery pull form — claim a slot with a UPI reference.
|
|
3
|
+
*
|
|
4
|
+
* Fields come from `lotteryPullSchema`. Two need a `renderers` entry because
|
|
5
|
+
* their labels depend on `totalSlots`, which a static annotation cannot know,
|
|
6
|
+
* and one needs `datetime-local` rather than a plain date.
|
|
7
|
+
*
|
|
8
|
+
* ## The upper bound stays a runtime check, on purpose
|
|
9
|
+
*
|
|
10
|
+
* `purchasedItemNumber` is `.min(1)` in the schema and has no `.max()`: the
|
|
11
|
+
* ceiling is `totalSlots`, a prop that varies per lottery. A schema shared with
|
|
12
|
+
* the route cannot carry it, so it is checked after the parse rather than
|
|
13
|
+
* pretended into the annotation. Everything else the hand-written validation
|
|
14
|
+
* used to duplicate — the reference length, the phone shape, the date — now
|
|
15
|
+
* comes from the schema, which is where those rules already lived.
|
|
16
|
+
*/
|
|
1
17
|
import React from "react";
|
|
2
18
|
interface LotteryPullFormProps {
|
|
3
19
|
sourceType: "event" | "product";
|
|
@@ -11,10 +27,5 @@ interface LotteryPullFormProps {
|
|
|
11
27
|
slotName: string;
|
|
12
28
|
}) => void;
|
|
13
29
|
}
|
|
14
|
-
/**
|
|
15
|
-
* User-facing lottery pull form.
|
|
16
|
-
* Submits TX ID + phone + payment time + item number.
|
|
17
|
-
* On success, shows the user their lottery number and assigned prize slot.
|
|
18
|
-
*/
|
|
19
30
|
export declare function LotteryPullForm({ sourceType, eventId, productId, totalSlots, maxPullsPerUser, onSuccess, }: LotteryPullFormProps): React.JSX.Element;
|
|
20
31
|
export {};
|
|
@@ -1,34 +1,67 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
/**
|
|
4
|
+
* User-facing lottery pull form — claim a slot with a UPI reference.
|
|
5
|
+
*
|
|
6
|
+
* Fields come from `lotteryPullSchema`. Two need a `renderers` entry because
|
|
7
|
+
* their labels depend on `totalSlots`, which a static annotation cannot know,
|
|
8
|
+
* and one needs `datetime-local` rather than a plain date.
|
|
9
|
+
*
|
|
10
|
+
* ## The upper bound stays a runtime check, on purpose
|
|
11
|
+
*
|
|
12
|
+
* `purchasedItemNumber` is `.min(1)` in the schema and has no `.max()`: the
|
|
13
|
+
* ceiling is `totalSlots`, a prop that varies per lottery. A schema shared with
|
|
14
|
+
* the route cannot carry it, so it is checked after the parse rather than
|
|
15
|
+
* pretended into the annotation. Everything else the hand-written validation
|
|
16
|
+
* used to duplicate — the reference length, the phone shape, the date — now
|
|
17
|
+
* comes from the schema, which is where those rules already lived.
|
|
18
|
+
*/
|
|
19
|
+
import { useMemo, useState } from "react";
|
|
6
20
|
import { useApiMutation } from "../../../../client/api/useApiMutation";
|
|
7
|
-
import { apiClient } from "../../../../http";
|
|
8
21
|
import { lotteryPullSchema } from "../../../../features/admin/schemas/admin-user-form";
|
|
22
|
+
import { buildSectionsFromSchema } from "../../../../features/shell/build-sections";
|
|
23
|
+
import { SectionForm, useSectionFormNav } from "../../../../features/shell/SectionForm";
|
|
24
|
+
import { apiClient } from "../../../../http";
|
|
25
|
+
import { FieldInput, Heading, Row, Span, Stack, Text } from "../../../../ui";
|
|
26
|
+
import { applyZodIssues } from "../../../../ui/forms/apply-zod-issues";
|
|
9
27
|
import { FormErrorSummary } from "../../../../ui/forms/FormErrorSummary";
|
|
10
|
-
|
|
11
|
-
* User-facing lottery pull form.
|
|
12
|
-
* Submits TX ID + phone + payment time + item number.
|
|
13
|
-
* On success, shows the user their lottery number and assigned prize slot.
|
|
14
|
-
*/
|
|
28
|
+
import { FormShellContext, useFormShellState } from "../../../../ui/forms/FormShell";
|
|
15
29
|
export function LotteryPullForm({ sourceType, eventId, productId, totalSlots, maxPullsPerUser, onSuccess, }) {
|
|
16
30
|
const [result, setResult] = useState(null);
|
|
17
|
-
const [
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
31
|
+
const [form, setForm] = useState({
|
|
32
|
+
sourceType,
|
|
33
|
+
transactionId: "",
|
|
34
|
+
paymentTime: "",
|
|
35
|
+
purchasedItemNumber: "",
|
|
36
|
+
userPhone: "",
|
|
37
|
+
});
|
|
21
38
|
const apiRoute = sourceType === "event"
|
|
22
39
|
? `/api/events/${eventId ?? ""}/lottery-pull`
|
|
23
40
|
: `/api/products/${productId ?? ""}/lottery-pull`;
|
|
41
|
+
const sections = useMemo(() => buildSectionsFromSchema(lotteryPullSchema, {
|
|
42
|
+
renderers: {
|
|
43
|
+
paymentTime: ({ values, onChange, errors }) => (_jsx(FieldInput, { name: "paymentTime", label: "Payment Date & Time",
|
|
44
|
+
// `datetime-local`, not `date` — the pull is matched against a
|
|
45
|
+
// bank timestamp, so the time of day is part of the evidence.
|
|
46
|
+
type: "datetime-local", required: true, value: values.paymentTime, error: errors.paymentTime, onChange: (v) => onChange({ paymentTime: v }) })),
|
|
47
|
+
purchasedItemNumber: ({ values, onChange, errors }) => (_jsx(FieldInput, { name: "purchasedItemNumber", label: `Slot Number (1 – ${totalSlots})`, type: "number", placeholder: `Enter a number between 1 and ${totalSlots}`, required: true, value: values.purchasedItemNumber, error: errors.purchasedItemNumber, onChange: (v) => onChange({ purchasedItemNumber: v }) })),
|
|
48
|
+
},
|
|
49
|
+
}), [totalSlots]);
|
|
50
|
+
const nav = useSectionFormNav(sections, form, { scope: "lottery:pull" });
|
|
51
|
+
const { shellCtx, setFieldError, clearErrors } = useFormShellState(lotteryPullSchema, {
|
|
52
|
+
sections: nav.sectionMeta,
|
|
53
|
+
onGoToSection: nav.goToSection,
|
|
54
|
+
fieldToSectionIndex: nav.fieldToSectionIndex,
|
|
55
|
+
});
|
|
24
56
|
const mutation = useApiMutation({
|
|
57
|
+
errorMessage: "Could not submit your entry.",
|
|
25
58
|
mutationFn: () => apiClient.post(apiRoute, {
|
|
26
59
|
sourceType,
|
|
27
60
|
...(sourceType === "event" ? { eventId } : { productId }),
|
|
28
|
-
transactionId,
|
|
29
|
-
paymentTime: new Date(paymentTime).toISOString(),
|
|
30
|
-
purchasedItemNumber: parseInt(
|
|
31
|
-
userPhone,
|
|
61
|
+
transactionId: form.transactionId,
|
|
62
|
+
paymentTime: new Date(form.paymentTime).toISOString(),
|
|
63
|
+
purchasedItemNumber: parseInt(form.purchasedItemNumber, 10),
|
|
64
|
+
userPhone: form.userPhone,
|
|
32
65
|
}),
|
|
33
66
|
successMessage: "Your lottery entry has been submitted!",
|
|
34
67
|
onSuccess: (data) => {
|
|
@@ -38,30 +71,22 @@ export function LotteryPullForm({ sourceType, eventId, productId, totalSlots, ma
|
|
|
38
71
|
}
|
|
39
72
|
},
|
|
40
73
|
});
|
|
74
|
+
const onSubmit = () => {
|
|
75
|
+
clearErrors();
|
|
76
|
+
const parsed = lotteryPullSchema.safeParse(form);
|
|
77
|
+
if (!parsed.success) {
|
|
78
|
+
applyZodIssues(parsed.error.issues, setFieldError);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
// Data-dependent ceiling — see the header.
|
|
82
|
+
if (parsed.data.purchasedItemNumber > totalSlots) {
|
|
83
|
+
setFieldError("purchasedItemNumber", `This lottery has ${totalSlots} slots.`);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
mutation.mutate();
|
|
87
|
+
};
|
|
41
88
|
if (result) {
|
|
42
89
|
return (_jsxs(Stack, { gap: "sm", padding: "md", rounded: "2xl", surface: "success-surface", className: "border border-success/20", children: [_jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Span, { layout: "inline-flex", color: "inverse", weight: "semibold", className: "bg-success text-[11px] tracking-wide", padding: "pill-sm", rounded: "full", transform: "uppercase", children: "Entry Confirmed" }), _jsxs(Heading, { level: 2, className: "text-success", size: "lg", weight: "bold", children: ["You're #", result.userLotteryNumber, "!"] })] }), _jsxs(Text, { className: "text-success", size: "sm", children: ["You've been assigned", " ", _jsxs(Span, { weight: "bold", children: ["Slot #", result.assignedPrizeSlotNumber] }), result.slotName ? ` — ${result.slotName}` : "", ". Good luck!"] })] }));
|
|
43
90
|
}
|
|
44
|
-
return (
|
|
45
|
-
clearErrors();
|
|
46
|
-
const num = parseInt(itemNumber, 10);
|
|
47
|
-
let valid = true;
|
|
48
|
-
if (!transactionId || transactionId.length < 4) {
|
|
49
|
-
setFieldError("transactionId", "Transaction ID must be at least 4 characters");
|
|
50
|
-
valid = false;
|
|
51
|
-
}
|
|
52
|
-
if (!paymentTime) {
|
|
53
|
-
setFieldError("paymentTime", "Payment date & time is required");
|
|
54
|
-
valid = false;
|
|
55
|
-
}
|
|
56
|
-
if (isNaN(num) || num < 1 || num > totalSlots) {
|
|
57
|
-
setFieldError("itemNumber", `Slot number must be between 1 and ${totalSlots}`);
|
|
58
|
-
valid = false;
|
|
59
|
-
}
|
|
60
|
-
if (!userPhone || userPhone.replace(/\D/g, "").length < 10) {
|
|
61
|
-
setFieldError("userPhone", "Enter a valid phone number (minimum 10 digits)");
|
|
62
|
-
valid = false;
|
|
63
|
-
}
|
|
64
|
-
if (valid)
|
|
65
|
-
mutation.mutate();
|
|
66
|
-
}, className: "w-full", children: mutation.isPending ? "Submitting…" : "Submit Entry" })] })) }));
|
|
91
|
+
return (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, size: "lg", weight: "semibold", children: "Submit Your Entry" }), _jsxs(Text, { size: "sm", color: "muted", children: ["Enter your UPI Transaction ID and payment details to claim your slot. You may enter up to", " ", maxPullsPerUser, " time", maxPullsPerUser === 1 ? "" : "s", "."] }), _jsxs(FormShellContext.Provider, { value: shellCtx, children: [_jsx(FormErrorSummary, {}), _jsx(SectionForm, { sections: sections, values: form, onChange: (partial) => setForm((prev) => Object.assign({}, prev, partial)), onSubmit: onSubmit, schema: lotteryPullSchema, openIds: nav.openIds, onOpenChange: nav.setOpenIds, isLoading: mutation.isPending, submitLabel: "Submit Entry" })] })] }));
|
|
67
92
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { normalizeError } from "../../../../../errors/normalize";
|
|
4
|
+
import { toUserMessage } from "../../../../../errors/error-display-map";
|
|
4
5
|
import * as React from "react";
|
|
5
6
|
import { Button, Div, Heading, Input, Li, Section, Span, Table, Tbody, Td, Text, Th, Thead, Tr, Ul } from "@mohasinac/appkit/client";
|
|
6
7
|
import { Select } from "@mohasinac/appkit/ui";
|
|
@@ -29,8 +30,10 @@ export function AnalysisRunnerView() {
|
|
|
29
30
|
setReport(body.data);
|
|
30
31
|
}
|
|
31
32
|
catch (err) {
|
|
32
|
-
|
|
33
|
-
setError(
|
|
33
|
+
const e = normalizeError(err);
|
|
34
|
+
setError(toUserMessage(e.code, undefined, {
|
|
35
|
+
fallback: "Could not run the analysis. Check the server logs for detail.",
|
|
36
|
+
}));
|
|
34
37
|
}
|
|
35
38
|
finally {
|
|
36
39
|
setRunning(false);
|
|
@@ -4,6 +4,7 @@ import * as React from "react";
|
|
|
4
4
|
import { Button, Div, Heading, Span, Table, Tbody, Td, Text, Th, Thead, Tr } from "@mohasinac/appkit/client";
|
|
5
5
|
import { ADMIN_ENDPOINTS } from "../../../../../constants/api-endpoints";
|
|
6
6
|
import { normalizeError } from "../../../../../errors/normalize";
|
|
7
|
+
import { toUserMessage } from "../../../../../errors/error-display-map";
|
|
7
8
|
const BORDER_STYLE = "1px solid var(--appkit-color-border)";
|
|
8
9
|
const COLUMNS = [
|
|
9
10
|
{ key: "timestampFmt", label: "When", width: "180px" },
|
|
@@ -38,8 +39,10 @@ export function CloudLogsListView({ title, subtitle, initialEntries, initialNext
|
|
|
38
39
|
setNextPageToken(body.data.nextPageToken);
|
|
39
40
|
}
|
|
40
41
|
catch (err) {
|
|
41
|
-
|
|
42
|
-
setError(
|
|
42
|
+
const e = normalizeError(err);
|
|
43
|
+
setError(toUserMessage(e.code, undefined, {
|
|
44
|
+
fallback: "Could not load more log entries. Please try again.",
|
|
45
|
+
}));
|
|
43
46
|
}
|
|
44
47
|
finally {
|
|
45
48
|
setLoadingMore(false);
|
|
@@ -51,5 +54,10 @@ export function CloudLogsListView({ title, subtitle, initialEntries, initialNext
|
|
|
51
54
|
borderBottom: BORDER_STYLE,
|
|
52
55
|
width: c.width,
|
|
53
56
|
whiteSpace: "nowrap",
|
|
54
|
-
}, children: c.label }, c.key))) }) }), _jsx(Tbody, { children: entries.length === 0 ? (_jsx(Tr, { children: _jsx(Td, { colSpan: COLUMNS.length, style: { padding: "2rem", textAlign: "center", color: "var(--appkit-color-text-muted)" }, children: "No log entries in the selected window." }) })) : (
|
|
57
|
+
}, children: c.label }, c.key))) }) }), _jsx(Tbody, { children: entries.length === 0 ? (_jsx(Tr, { children: _jsx(Td, { colSpan: COLUMNS.length, style: { padding: "2rem", textAlign: "center", color: "var(--appkit-color-text-muted)" }, children: "No log entries in the selected window." }) })) : (
|
|
58
|
+
// Named `entry`, not `e`: this is a Cloud Logging record, not a
|
|
59
|
+
// caught error, and rendering its `.message` is the entire point
|
|
60
|
+
// of this admin viewer. The short name read as the defect
|
|
61
|
+
// audit-raw-error-text exists to catch.
|
|
62
|
+
entries.map((entry) => (_jsxs(Tr, { style: { borderBottom: "1px solid var(--appkit-color-border-subtle)" }, children: [_jsx(Td, { style: { padding: "0.5rem 0.75rem", verticalAlign: "top", whiteSpace: "nowrap" }, children: fmt(entry.timestamp) }), _jsx(Td, { style: { padding: "0.5rem 0.75rem", verticalAlign: "top" }, children: entry.severity }), _jsx(Td, { style: { padding: "0.5rem 0.75rem", verticalAlign: "top" }, children: entry.resourceType }), _jsx(Td, { style: { padding: "0.5rem 0.75rem", verticalAlign: "top", fontFamily: "monospace" }, children: entry.message })] }, entry.id)))) })] }) }), _jsx(Div, { style: { marginTop: "1rem", textAlign: "center" }, children: nextPageToken ? (_jsx(Button, { type: "button", onClick: loadMore, isLoading: loadingMore, children: "Load more" })) : entries.length > 0 ? (_jsx(Text, { style: { color: "var(--appkit-color-text-muted)", fontSize: "0.85rem" }, children: "No more entries." })) : null })] }));
|
|
55
63
|
}
|