@mohasinac/appkit 4.30.19 → 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/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 +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/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
|
@@ -153,50 +153,6 @@ export const notificationQueryHelpers = {
|
|
|
153
153
|
],
|
|
154
154
|
byType: (type) => ["type", "==", type],
|
|
155
155
|
};
|
|
156
|
-
export const CHAT_ROOM_COLLECTION = "chatRooms";
|
|
157
|
-
export const CHAT_ROOM_INDEXED_FIELDS = [
|
|
158
|
-
"buyerId",
|
|
159
|
-
"ownerId",
|
|
160
|
-
"orderId",
|
|
161
|
-
"participantIds",
|
|
162
|
-
"adminDeleted",
|
|
163
|
-
"updatedAt",
|
|
164
|
-
];
|
|
165
|
-
export const CHAT_ROOM_FIELDS = {
|
|
166
|
-
ID: "id",
|
|
167
|
-
BUYER_ID: "buyerId",
|
|
168
|
-
OWNER_ID: "ownerId",
|
|
169
|
-
ORDER_ID: "orderId",
|
|
170
|
-
PRODUCT_ID: "productId",
|
|
171
|
-
PRODUCT_TITLE: "productTitle",
|
|
172
|
-
BUYER_NAME: "buyerName",
|
|
173
|
-
OWNER_NAME: "ownerName",
|
|
174
|
-
LAST_MESSAGE: "lastMessage",
|
|
175
|
-
LAST_MESSAGE_AT: "lastMessageAt",
|
|
176
|
-
CREATED_AT: "createdAt",
|
|
177
|
-
UPDATED_AT: "updatedAt",
|
|
178
|
-
DELETED_BY: "deletedBy",
|
|
179
|
-
IS_GROUP: "isGroup",
|
|
180
|
-
PARTICIPANT_IDS: "participantIds",
|
|
181
|
-
ADMIN_DELETED: "adminDeleted",
|
|
182
|
-
};
|
|
183
|
-
export const DEFAULT_CHAT_ROOM_DATA = {
|
|
184
|
-
buyerId: "",
|
|
185
|
-
ownerId: "",
|
|
186
|
-
orderId: "",
|
|
187
|
-
buyerName: "",
|
|
188
|
-
ownerName: "",
|
|
189
|
-
deletedBy: [],
|
|
190
|
-
isGroup: false,
|
|
191
|
-
participantIds: [],
|
|
192
|
-
adminDeleted: false,
|
|
193
|
-
};
|
|
194
|
-
export const chatRoomQueryHelpers = {
|
|
195
|
-
byBuyer: (buyerId) => ["buyerId", "==", buyerId],
|
|
196
|
-
byOwner: (ownerId) => ["ownerId", "==", ownerId],
|
|
197
|
-
byOrder: (orderId) => ["orderId", "==", orderId],
|
|
198
|
-
active: () => ["adminDeleted", "==", false],
|
|
199
|
-
};
|
|
200
156
|
export const DEFAULT_NOTIFICATION_CHANNELS = {
|
|
201
157
|
inApp: { enabled: true, readOnly: true },
|
|
202
158
|
email: { enabled: false, minPriority: "normal" },
|
|
@@ -212,6 +168,11 @@ const PRIORITY_ORDER = {
|
|
|
212
168
|
export function meetsMinPriority(priority, minPriority = "normal") {
|
|
213
169
|
return PRIORITY_ORDER[priority] >= PRIORITY_ORDER[minPriority];
|
|
214
170
|
}
|
|
171
|
+
// `FeatureFlagKey` / `FeatureFlagMeta` / `FEATURE_FLAG_META` were deleted with
|
|
172
|
+
// the `featureFlags` group on 2026-08-29. They described 14 toggles of which 11
|
|
173
|
+
// had no reader anywhere — an admin could switch "Wishlists" or "Reviews" off
|
|
174
|
+
// and watch nothing happen, which is worse than the feature not being
|
|
175
|
+
// configurable at all.
|
|
215
176
|
export const SITE_SETTINGS_COLLECTION = "siteSettings";
|
|
216
177
|
export const SITE_SETTINGS_INDEXED_FIELDS = [];
|
|
217
178
|
/**
|
|
@@ -235,6 +196,8 @@ export const DEFAULT_SITE_SETTINGS_DATA = {
|
|
|
235
196
|
upiManualEnabled: true,
|
|
236
197
|
codEnabled: true,
|
|
237
198
|
otpCheckoutThreshold: 5000,
|
|
199
|
+
smsVerification: false,
|
|
200
|
+
adminCheckoutBypass: false,
|
|
238
201
|
},
|
|
239
202
|
emi: {
|
|
240
203
|
enabled: false,
|
|
@@ -293,35 +256,22 @@ export const DEFAULT_SITE_SETTINGS_DATA = {
|
|
|
293
256
|
autoExtendWindowMinutes: 5,
|
|
294
257
|
settlementGracePeriodHours: 24,
|
|
295
258
|
},
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
smsVerification: false,
|
|
303
|
-
translations: true,
|
|
304
|
-
wishlists: true,
|
|
305
|
-
auctions: true,
|
|
306
|
-
reviews: true,
|
|
307
|
-
events: true,
|
|
308
|
-
blog: true,
|
|
309
|
-
coupons: true,
|
|
310
|
-
notifications: true,
|
|
311
|
-
sellerRegistration: true,
|
|
312
|
-
preOrders: true,
|
|
313
|
-
offers: true,
|
|
314
|
-
// W1-37 2026-05-23 — Phase 2 listing types enabled by default; all per-type
|
|
315
|
-
// surfaces (seller + admin via W1-29 + public) are now shipped.
|
|
259
|
+
// Every type on by default. `isListingTypeEnabled` treats a MISSING key as
|
|
260
|
+
// enabled, so this block is documentation of the full set rather than the
|
|
261
|
+
// mechanism — a type absent here still renders. `art` and `stickers` were
|
|
262
|
+
// missing from the old `featureFlags.listingTypes` literal for exactly that
|
|
263
|
+
// reason: nothing broke, so nobody noticed (Root Cause #58).
|
|
264
|
+
listings: {
|
|
316
265
|
listingTypes: {
|
|
317
266
|
standard: true,
|
|
318
267
|
auction: true,
|
|
319
268
|
"pre-order": true,
|
|
320
269
|
"prize-draw": true,
|
|
321
|
-
bundle: true,
|
|
322
270
|
classified: true,
|
|
323
271
|
"digital-code": true,
|
|
324
272
|
live: true,
|
|
273
|
+
art: true,
|
|
274
|
+
stickers: true,
|
|
325
275
|
},
|
|
326
276
|
categoryTypes: {
|
|
327
277
|
category: true,
|
|
@@ -371,89 +321,3 @@ export const DEFAULT_TRUST_BAR_ITEMS = [
|
|
|
371
321
|
// NOTE: labelKey/descKey hold plain display text (not i18n message keys) —
|
|
372
322
|
// this feature-flag list has no matching next-intl namespace, so the admin
|
|
373
323
|
// UI reads these two fields directly rather than through getTranslations().
|
|
374
|
-
export const FEATURE_FLAG_META = [
|
|
375
|
-
{
|
|
376
|
-
key: "chats",
|
|
377
|
-
labelKey: "In-app chats",
|
|
378
|
-
descKey: "Buyer/seller direct messaging.",
|
|
379
|
-
icon: "\u{1F4AC}",
|
|
380
|
-
category: "platform",
|
|
381
|
-
},
|
|
382
|
-
{
|
|
383
|
-
key: "smsVerification",
|
|
384
|
-
labelKey: "SMS verification",
|
|
385
|
-
descKey: "Phone-number OTP verification during signup/checkout.",
|
|
386
|
-
icon: "\u{1F4F1}",
|
|
387
|
-
category: "platform",
|
|
388
|
-
},
|
|
389
|
-
{
|
|
390
|
-
key: "translations",
|
|
391
|
-
labelKey: "Translations",
|
|
392
|
-
descKey: "Locale switcher and translated UI strings.",
|
|
393
|
-
icon: "\u{1F310}",
|
|
394
|
-
category: "platform",
|
|
395
|
-
},
|
|
396
|
-
{
|
|
397
|
-
key: "auctions",
|
|
398
|
-
labelKey: "Auctions",
|
|
399
|
-
descKey: "Auction listings and bidding.",
|
|
400
|
-
icon: "\u{1F528}",
|
|
401
|
-
category: "platform",
|
|
402
|
-
},
|
|
403
|
-
{
|
|
404
|
-
key: "reviews",
|
|
405
|
-
labelKey: "Reviews",
|
|
406
|
-
descKey: "Product and store reviews.",
|
|
407
|
-
icon: "⭐",
|
|
408
|
-
category: "platform",
|
|
409
|
-
},
|
|
410
|
-
{
|
|
411
|
-
key: "notifications",
|
|
412
|
-
labelKey: "Notifications",
|
|
413
|
-
descKey: "In-app notification bell and inbox.",
|
|
414
|
-
icon: "\u{1F514}",
|
|
415
|
-
category: "platform",
|
|
416
|
-
},
|
|
417
|
-
{
|
|
418
|
-
key: "sellerRegistration",
|
|
419
|
-
labelKey: "Seller registration",
|
|
420
|
-
descKey: "\"Become a seller\" signup flow.",
|
|
421
|
-
icon: "\u{1F3EA}",
|
|
422
|
-
category: "platform",
|
|
423
|
-
},
|
|
424
|
-
{
|
|
425
|
-
key: "preOrders",
|
|
426
|
-
labelKey: "Pre-orders",
|
|
427
|
-
descKey: "Pre-order listings and deposit checkout.",
|
|
428
|
-
icon: "\u{1F4E6}",
|
|
429
|
-
category: "platform",
|
|
430
|
-
},
|
|
431
|
-
{
|
|
432
|
-
key: "wishlists",
|
|
433
|
-
labelKey: "Wishlists",
|
|
434
|
-
descKey: "Save-for-later wishlist feature.",
|
|
435
|
-
icon: "❤️",
|
|
436
|
-
category: "platform",
|
|
437
|
-
},
|
|
438
|
-
{
|
|
439
|
-
key: "events",
|
|
440
|
-
labelKey: "Events",
|
|
441
|
-
descKey: "Sales, raffles, spin-wheel, and lottery events.",
|
|
442
|
-
icon: "\u{1F389}",
|
|
443
|
-
category: "platform",
|
|
444
|
-
},
|
|
445
|
-
{
|
|
446
|
-
key: "blog",
|
|
447
|
-
labelKey: "Blog",
|
|
448
|
-
descKey: "Blog posts section.",
|
|
449
|
-
icon: "\u{1F4DD}",
|
|
450
|
-
category: "platform",
|
|
451
|
-
},
|
|
452
|
-
{
|
|
453
|
-
key: "coupons",
|
|
454
|
-
labelKey: "Coupons",
|
|
455
|
-
descKey: "Coupon codes and discounts.",
|
|
456
|
-
icon: "\u{1F3AB}",
|
|
457
|
-
category: "platform",
|
|
458
|
-
},
|
|
459
|
-
];
|
|
@@ -53,9 +53,16 @@ export const navItemFormSchema = z.object({
|
|
|
53
53
|
section: "basics", sectionLabel: "Nav item", sectionRequired: true,
|
|
54
54
|
quick: true, order: 1, row: "pair",
|
|
55
55
|
}),
|
|
56
|
-
href: annotate(hrefSchema, {
|
|
56
|
+
href: annotate(hrefSchema, {
|
|
57
|
+
section: "basics", quick: true, order: 2, row: "pair",
|
|
58
|
+
label: "URL / href",
|
|
59
|
+
// On the schema rather than the control, so every surface that renders this
|
|
60
|
+
// field gets it — the editor used to carry it as a local `helperText`.
|
|
61
|
+
help: "Use relative paths (e.g. /products) or full URLs.",
|
|
62
|
+
}),
|
|
57
63
|
icon: annotate(z.string().max(60).optional(), {
|
|
58
|
-
section: "basics", order: 3, row: "pair",
|
|
64
|
+
section: "basics", order: 3, row: "pair", kind: "select",
|
|
65
|
+
label: "Icon (optional)",
|
|
59
66
|
}),
|
|
60
67
|
order: annotate(z.coerce.number().int("Order must be a whole number.").min(0, "Order cannot be negative.").optional(), { section: "placement", sectionLabel: "Placement", order: 1, row: "pair" }),
|
|
61
68
|
parentId: annotate(z.string().max(80).optional(), {
|
|
@@ -5,11 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export * from "./actions";
|
|
7
7
|
export { notificationRepository } from "./repository/notification.repository";
|
|
8
|
-
export { chatRepository } from "./repository/chat.repository";
|
|
9
8
|
export { contactSubmissionsRepository } from "../../core/contact-submissions.repository";
|
|
10
|
-
export type { ContactSubmissionDocument, ContactSubmissionCreateInput } from "../../core/contact-submissions.repository";
|
|
11
|
-
export { newsletterRepository } from "../../core/newsletter.repository";
|
|
12
|
-
export type { ChatRoomDocument, ChatRoomCreateInput, } from "./repository/chat.repository";
|
|
13
9
|
export { siteSettingsRepository } from "./repository/site-settings.repository";
|
|
14
10
|
export { GET as adminProductsGET } from "./api/products/route";
|
|
15
11
|
export { GET as adminCouponsGET } from "./api/coupons/route";
|
|
@@ -5,9 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export * from "./actions";
|
|
7
7
|
export { notificationRepository } from "./repository/notification.repository";
|
|
8
|
-
export { chatRepository } from "./repository/chat.repository";
|
|
9
8
|
export { contactSubmissionsRepository } from "../../core/contact-submissions.repository";
|
|
10
|
-
export { newsletterRepository } from "../../core/newsletter.repository";
|
|
11
9
|
export { siteSettingsRepository } from "./repository/site-settings.repository";
|
|
12
10
|
export { GET as adminProductsGET } from "./api/products/route";
|
|
13
11
|
export { GET as adminCouponsGET } from "./api/coupons/route";
|
|
@@ -27,13 +27,6 @@ export interface AdminListParams {
|
|
|
27
27
|
sort?: string;
|
|
28
28
|
filters?: string;
|
|
29
29
|
}
|
|
30
|
-
export interface AdminListResponse<T> {
|
|
31
|
-
items: T[];
|
|
32
|
-
total: number;
|
|
33
|
-
page: number;
|
|
34
|
-
perPage: number;
|
|
35
|
-
totalPages: number;
|
|
36
|
-
}
|
|
37
30
|
export interface AnalyticsMonthEntry {
|
|
38
31
|
month: string;
|
|
39
32
|
orders: number;
|
|
@@ -28,5 +28,19 @@ export declare class PageViewsRepository extends BaseRepository<PageViewDocument
|
|
|
28
28
|
/** All day-buckets in [startDate, endDate] (inclusive, YYYY-MM-DD), optionally
|
|
29
29
|
* scoped to one entityType. Used by the admin page-views report tab. */
|
|
30
30
|
listInRange(startDate: string, endDate: string, entityType?: PageViewEntityType): Promise<PageViewDocument[]>;
|
|
31
|
+
/**
|
|
32
|
+
* Day-buckets older than `days`, as refs for `batchDelete`.
|
|
33
|
+
*
|
|
34
|
+
* 🛑 This collection had NO prune and NO rollup until 2026-08-31. It writes
|
|
35
|
+
* one document per entity per day, forever, and 27 scheduled functions
|
|
36
|
+
* existed without one of them touching it — so its growth was bounded only by
|
|
37
|
+
* how many distinct pages the catalogue had times how long the site had been
|
|
38
|
+
* up. See `pageViewPrune`.
|
|
39
|
+
*
|
|
40
|
+
* Returns refs rather than documents, matching `getOldReadRefs` on
|
|
41
|
+
* notifications: a prune needs the id, and hydrating the body of every doc it
|
|
42
|
+
* is about to delete is read budget spent on nothing (Rule #6).
|
|
43
|
+
*/
|
|
44
|
+
getOlderThanRefs(days: number): Promise<FirebaseFirestore.DocumentReference[]>;
|
|
31
45
|
}
|
|
32
46
|
export declare const pageViewsRepository: PageViewsRepository;
|
|
@@ -39,5 +39,29 @@ export class PageViewsRepository extends BaseRepository {
|
|
|
39
39
|
const snap = await query.get();
|
|
40
40
|
return snap.docs.map((d) => this.mapDoc(d));
|
|
41
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Day-buckets older than `days`, as refs for `batchDelete`.
|
|
44
|
+
*
|
|
45
|
+
* 🛑 This collection had NO prune and NO rollup until 2026-08-31. It writes
|
|
46
|
+
* one document per entity per day, forever, and 27 scheduled functions
|
|
47
|
+
* existed without one of them touching it — so its growth was bounded only by
|
|
48
|
+
* how many distinct pages the catalogue had times how long the site had been
|
|
49
|
+
* up. See `pageViewPrune`.
|
|
50
|
+
*
|
|
51
|
+
* Returns refs rather than documents, matching `getOldReadRefs` on
|
|
52
|
+
* notifications: a prune needs the id, and hydrating the body of every doc it
|
|
53
|
+
* is about to delete is read budget spent on nothing (Rule #6).
|
|
54
|
+
*/
|
|
55
|
+
async getOlderThanRefs(days) {
|
|
56
|
+
const cutoff = new Date();
|
|
57
|
+
cutoff.setUTCDate(cutoff.getUTCDate() - days);
|
|
58
|
+
const cutoffKey = cutoff.toISOString().slice(0, 10);
|
|
59
|
+
// `<` and not `<=`: the cutoff day itself is still inside the window.
|
|
60
|
+
const snap = await this.getCollection()
|
|
61
|
+
.where(PAGE_VIEW_FIELDS.DATE, "<", cutoffKey)
|
|
62
|
+
.select()
|
|
63
|
+
.get();
|
|
64
|
+
return snap.docs.map((d) => d.ref);
|
|
65
|
+
}
|
|
42
66
|
}
|
|
43
67
|
export const pageViewsRepository = new PageViewsRepository();
|
|
@@ -5,21 +5,11 @@
|
|
|
5
5
|
* Called by letitrip thin wrapper which handles auth + rate limiting.
|
|
6
6
|
*/
|
|
7
7
|
import { getAdminAuth } from "../../../providers/db-firebase/index";
|
|
8
|
-
import { chatRepository } from "../../admin/repository/chat.repository";
|
|
9
8
|
import { conversationsRepository } from "../../messages/repository/conversations.repository";
|
|
10
9
|
import { storeRepository } from "../../stores/repository/store.repository";
|
|
11
10
|
import { serverLogger } from "../../../monitoring/index";
|
|
12
11
|
import { normalizeError } from "../../../errors/normalize";
|
|
13
12
|
export async function issueRealtimeToken(userId, userRole) {
|
|
14
|
-
let chatIds = {};
|
|
15
|
-
try {
|
|
16
|
-
const userChatIds = await chatRepository.getChatIdsForUser(userId);
|
|
17
|
-
chatIds = Object.fromEntries(userChatIds.map((id) => [id, true]));
|
|
18
|
-
}
|
|
19
|
-
catch (err) {
|
|
20
|
-
void normalizeError(err);
|
|
21
|
-
serverLogger.warn("Could not resolve chatIds for realtime token", { userId, err });
|
|
22
|
-
}
|
|
23
13
|
const conversationIds = {};
|
|
24
14
|
try {
|
|
25
15
|
const buyerConvs = await conversationsRepository.listByBuyer(userId);
|
|
@@ -38,12 +28,11 @@ export async function issueRealtimeToken(userId, userRole) {
|
|
|
38
28
|
}
|
|
39
29
|
const customToken = await getAdminAuth().createCustomToken(userId, {
|
|
40
30
|
role: userRole,
|
|
41
|
-
chatIds,
|
|
42
31
|
conversationIds,
|
|
43
32
|
});
|
|
44
33
|
serverLogger.info("issueRealtimeToken: token issued", {
|
|
45
34
|
userId,
|
|
46
|
-
|
|
35
|
+
conversationCount: Object.keys(conversationIds).length,
|
|
47
36
|
});
|
|
48
37
|
return { customToken, expiresAt: Date.now() + 3600000 };
|
|
49
38
|
}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { getTokenTimeRemaining, isTokenExpired } from "./token-helpers";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
admin: 3,
|
|
8
|
-
};
|
|
2
|
+
// Was a SECOND, disagreeing copy of the hierarchy (employee and moderator both
|
|
3
|
+
// ranked 2, where the canonical one puts moderator above employee), so
|
|
4
|
+
// `hasRole` gave a different answer depending on which module you imported.
|
|
5
|
+
// Deleted 2026-08-29 in favour of the one in security/authorization.
|
|
6
|
+
import { ROLE_HIERARCHY } from "../../security/authorization";
|
|
9
7
|
export function hasRole(userRole, requiredRole) {
|
|
10
8
|
return ROLE_HIERARCHY[userRole] >= ROLE_HIERARCHY[requiredRole];
|
|
11
9
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useMemo } from "react";
|
|
4
|
+
import { isAccountDisabled } from "../role-predicates";
|
|
4
5
|
import { Button, Div, Heading, Row, Text } from "../../../ui";
|
|
5
6
|
export function RoleGate({ children, user, allowedRoles, fallback = null, }) {
|
|
6
7
|
if (!user?.role) {
|
|
@@ -31,7 +32,7 @@ export function ProtectedRoute({ children, user, loading = false, requireAuth =
|
|
|
31
32
|
}
|
|
32
33
|
if (user) {
|
|
33
34
|
// Check account status
|
|
34
|
-
if (requireActiveAccount && user
|
|
35
|
+
if (requireActiveAccount && isAccountDisabled(user)) {
|
|
35
36
|
return { isAuthorized: false, redirectPath: unauthorizedPath };
|
|
36
37
|
}
|
|
37
38
|
// Check email verification
|
|
@@ -2,7 +2,6 @@ import React from "react";
|
|
|
2
2
|
export interface LoginFormValues {
|
|
3
3
|
email: string;
|
|
4
4
|
password: string;
|
|
5
|
-
rememberMe?: boolean;
|
|
6
5
|
}
|
|
7
6
|
export interface LoginFormProps {
|
|
8
7
|
onSubmit: (values: LoginFormValues) => Promise<void>;
|
|
@@ -17,7 +16,6 @@ export interface LoginFormProps {
|
|
|
17
16
|
emailPlaceholder?: string;
|
|
18
17
|
passwordLabel?: string;
|
|
19
18
|
passwordPlaceholder?: string;
|
|
20
|
-
rememberMe?: string;
|
|
21
19
|
forgotPasswordLabel?: string;
|
|
22
20
|
submitLabel?: string;
|
|
23
21
|
submittingLabel?: string;
|
|
@@ -5,7 +5,6 @@ import { useState } from "react";
|
|
|
5
5
|
import { Alert, Button, Div, Heading, Row, SiteMark, Stack, Text, useToast } from "../../../ui";
|
|
6
6
|
import { Form } from "../../../ui/components/Form";
|
|
7
7
|
import { FieldInput } from "../../../ui/forms/FieldInput";
|
|
8
|
-
import { FieldCheckbox } from "../../../ui/forms/FieldCheckbox";
|
|
9
8
|
import { applyZodIssues } from "../../../ui/forms/apply-zod-issues";
|
|
10
9
|
import { loginSchema } from "../schemas";
|
|
11
10
|
import { SocialAuthButtons } from "./SocialAuthButtons";
|
|
@@ -15,9 +14,8 @@ export function LoginForm({ onSubmit, onGoogleLogin, isLoading = false, error, l
|
|
|
15
14
|
const [values, setValues] = useState({
|
|
16
15
|
email: "",
|
|
17
16
|
password: "",
|
|
18
|
-
rememberMe: false,
|
|
19
17
|
});
|
|
20
|
-
return (_jsx(Row, { className: `min-h-[60vh] ${className}`, align: "center", justify: "center", padding: "x-md", children: _jsxs(Stack, { className: "max-w-md w-full", gap: "lg", children: [_jsxs(Div, { className: "text-center", children: [_jsx(Row, { justify: "center", className: "mb-3", children: _jsx(SiteMark, { size: "lg" }) }), _jsx(Heading, { level: 1, className: "font-extrabold", size: "3xl", children: labels.title ?? "Sign In" }), (labels.subtitle || renderCreateAccountLink) && (_jsxs(Text, { className: "mt-2", color: "muted", size: "sm", children: [labels.subtitle ?? "Or", " ", renderCreateAccountLink?.()] }))] }), error && (_jsx(Alert, { variant: "error", compact: true, children: error })), _jsx(Form, { schema: loginSchema, noValidate: true, onSubmit: (e) => e.preventDefault(), spacing: "md", children: ({ setFieldError, clearErrors }) => (_jsxs(_Fragment, { children: [_jsx(FormErrorSummary, {}), _jsx(FieldInput, { name: "email", label: labels.emailLabel ?? "Email address", type: "email", autoComplete: "username", required: true, placeholder: labels.emailPlaceholder ?? "you@example.com", value: values.email, onChange: (v) => setValues({ ...values, email: v }) }), _jsx(FieldInput, { name: "password", label: labels.passwordLabel ?? "Password", type: "password", autoComplete: "current-password", required: true, placeholder: labels.passwordPlaceholder ?? "••••••••", value: values.password, onChange: (v) => setValues({ ...values, password: v }) }),
|
|
18
|
+
return (_jsx(Row, { className: `min-h-[60vh] ${className}`, align: "center", justify: "center", padding: "x-md", children: _jsxs(Stack, { className: "max-w-md w-full", gap: "lg", children: [_jsxs(Div, { className: "text-center", children: [_jsx(Row, { justify: "center", className: "mb-3", children: _jsx(SiteMark, { size: "lg" }) }), _jsx(Heading, { level: 1, className: "font-extrabold", size: "3xl", children: labels.title ?? "Sign In" }), (labels.subtitle || renderCreateAccountLink) && (_jsxs(Text, { className: "mt-2", color: "muted", size: "sm", children: [labels.subtitle ?? "Or", " ", renderCreateAccountLink?.()] }))] }), error && (_jsx(Alert, { variant: "error", compact: true, children: error })), _jsx(Form, { schema: loginSchema, noValidate: true, onSubmit: (e) => e.preventDefault(), spacing: "md", children: ({ setFieldError, clearErrors }) => (_jsxs(_Fragment, { children: [_jsx(FormErrorSummary, {}), _jsx(FieldInput, { name: "email", label: labels.emailLabel ?? "Email address", type: "email", autoComplete: "username", required: true, placeholder: labels.emailPlaceholder ?? "you@example.com", value: values.email, onChange: (v) => setValues({ ...values, email: v }) }), _jsx(FieldInput, { name: "password", label: labels.passwordLabel ?? "Password", type: "password", autoComplete: "current-password", required: true, placeholder: labels.passwordPlaceholder ?? "••••••••", value: values.password, onChange: (v) => setValues({ ...values, password: v }) }), _jsx(Row, { justify: "end", children: renderForgotPasswordLink?.() }), _jsx(Button, { type: "submit", isLoading: isLoading, disabled: isLoading, className: "w-full", onClick: async () => {
|
|
21
19
|
clearErrors();
|
|
22
20
|
const parsed = loginSchema.safeParse(values);
|
|
23
21
|
if (!parsed.success)
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { normalizeError } from "../../../errors/normalize";
|
|
4
|
-
import { useState } from "react";
|
|
4
|
+
import React, { useState } from "react";
|
|
5
5
|
import { z } from "zod";
|
|
6
|
-
import { Alert,
|
|
7
|
-
import { Form } from "../../../ui/components/Form";
|
|
6
|
+
import { Alert, Div, Heading, Row, SiteMark, Stack, Text } from "../../../ui";
|
|
8
7
|
import { FieldInput } from "../../../ui/forms/FieldInput";
|
|
9
8
|
import { FieldCheckbox } from "../../../ui/forms/FieldCheckbox";
|
|
10
9
|
import { applyZodIssues } from "../../../ui/forms/apply-zod-issues";
|
|
10
|
+
import { FormShellContext, useFormShellState } from "../../../ui/forms/FormShell";
|
|
11
11
|
import { registerSchema, registerPasswordSchema } from "../schemas";
|
|
12
12
|
import { FormErrorSummary } from "../../../ui/forms/FormErrorSummary";
|
|
13
|
+
import { SectionForm, useSectionFormNav } from "../../shell/SectionForm";
|
|
13
14
|
const registerClientSchema = registerSchema.extend({
|
|
14
15
|
displayName: z.string().min(1, "Enter your name"),
|
|
15
16
|
confirmPassword: registerPasswordSchema,
|
|
@@ -20,8 +21,35 @@ const registerClientSchema = registerSchema.extend({
|
|
|
20
21
|
message: "Passwords do not match",
|
|
21
22
|
path: ["confirmPassword"],
|
|
22
23
|
});
|
|
24
|
+
/*
|
|
25
|
+
* Hand-authored rather than derived from the schema, which is the exception
|
|
26
|
+
* here and not the rule.
|
|
27
|
+
*
|
|
28
|
+
* Two reasons the generator is the wrong tool for this one form. `labels` is a
|
|
29
|
+
* PUBLIC prop of a published component — every string below is consumer
|
|
30
|
+
* overridable, and moving them into schema annotations would silently drop that
|
|
31
|
+
* override for anyone outside this repo. And `renderPasswordStrength` /
|
|
32
|
+
* `renderTermsLink` are POSITIONAL slots: a meter that must sit under the
|
|
33
|
+
* password box, a terms line that must sit under the checkbox. The generator
|
|
34
|
+
* places fields, not arbitrary nodes between them.
|
|
35
|
+
*
|
|
36
|
+
* One section, `required: true` — so it renders open, without a collapse
|
|
37
|
+
* control, i.e. exactly the flat list it has always been. A five-field signup
|
|
38
|
+
* form has nothing to group; what it gains here is the error→section
|
|
39
|
+
* attribution that makes `<FormErrorSummary>` able to jump to a field.
|
|
40
|
+
*/
|
|
41
|
+
function buildSections(labels, renderPasswordStrength, renderTermsLink) {
|
|
42
|
+
return [
|
|
43
|
+
{
|
|
44
|
+
id: "account",
|
|
45
|
+
label: labels.title ?? "Create Account",
|
|
46
|
+
required: true,
|
|
47
|
+
fields: ["displayName", "email", "password", "confirmPassword", "acceptTerms"],
|
|
48
|
+
render: ({ values, onChange }) => (_jsxs(_Fragment, { children: [_jsx(FieldInput, { name: "displayName", label: labels.displayNameLabel ?? "Full name", type: "text", autoComplete: "name", required: true, placeholder: labels.displayNamePlaceholder ?? "Your name", value: values.displayName, onChange: (v) => onChange({ displayName: v }) }), _jsx(FieldInput, { name: "email", label: labels.emailLabel ?? "Email address", type: "email", autoComplete: "username", required: true, placeholder: labels.emailPlaceholder ?? "you@example.com", value: values.email, onChange: (v) => onChange({ email: v }) }), _jsxs(Div, { children: [_jsx(FieldInput, { name: "password", label: labels.passwordLabel ?? "Password", type: "password", autoComplete: "new-password", required: true, placeholder: labels.passwordPlaceholder ?? "••••••••", value: values.password, onChange: (v) => onChange({ password: v }) }), renderPasswordStrength?.(values.password)] }), _jsx(FieldInput, { name: "confirmPassword", label: labels.confirmPasswordLabel ?? "Confirm password", type: "password", autoComplete: "new-password", required: true, placeholder: labels.confirmPasswordPlaceholder ?? "••••••••", value: values.confirmPassword, onChange: (v) => onChange({ confirmPassword: v }) }), _jsx(FieldCheckbox, { name: "acceptTerms", label: `${labels.acceptTermsLabel ?? "I accept the terms"}`, checked: values.acceptTerms, onChange: (c) => onChange({ acceptTerms: c }) }), renderTermsLink && (_jsx(Text, { size: "xs", variant: "secondary", children: renderTermsLink() }))] })),
|
|
49
|
+
},
|
|
50
|
+
];
|
|
51
|
+
}
|
|
23
52
|
export function RegisterForm({ onSubmit, isLoading = false, error, success, labels = {}, renderSocialButtons, renderLoginLink, renderTermsLink, renderPasswordStrength, className = "", }) {
|
|
24
|
-
const { showToast } = useToast();
|
|
25
53
|
const [values, setValues] = useState({
|
|
26
54
|
email: "",
|
|
27
55
|
password: "",
|
|
@@ -29,19 +57,34 @@ export function RegisterForm({ onSubmit, isLoading = false, error, success, labe
|
|
|
29
57
|
displayName: "",
|
|
30
58
|
acceptTerms: false,
|
|
31
59
|
});
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
60
|
+
const sections = React.useMemo(() => buildSections(labels, renderPasswordStrength, renderTermsLink), [labels, renderPasswordStrength, renderTermsLink]);
|
|
61
|
+
const nav = useSectionFormNav(sections, values, { scope: "auth:register" });
|
|
62
|
+
const { shellCtx, setFieldError, clearErrors } = useFormShellState(registerClientSchema, {
|
|
63
|
+
sections: nav.sectionMeta,
|
|
64
|
+
onGoToSection: nav.goToSection,
|
|
65
|
+
fieldToSectionIndex: nav.fieldToSectionIndex,
|
|
66
|
+
});
|
|
67
|
+
const handleSubmit = async () => {
|
|
68
|
+
clearErrors();
|
|
69
|
+
const parsed = registerClientSchema.safeParse(values);
|
|
70
|
+
if (!parsed.success) {
|
|
71
|
+
applyZodIssues(parsed.error.issues, setFieldError);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
await onSubmit(values);
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
/*
|
|
79
|
+
* On a field, not a toast. "Registration failed" told the user nothing
|
|
80
|
+
* and discarded whatever the caller actually objected to — a taken
|
|
81
|
+
* email, a rejected password — which is the one thing they can act on.
|
|
82
|
+
*/
|
|
83
|
+
const normalized = normalizeError(err);
|
|
84
|
+
setFieldError("email", normalized.message || "Registration failed");
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
return (_jsx(Row, { className: `min-h-[60vh] ${className}`, align: "center", justify: "center", padding: "x-md", children: _jsxs(Stack, { className: "max-w-md w-full", gap: "lg", children: [_jsxs(Div, { className: "text-center", children: [_jsx(Row, { justify: "center", className: "mb-3", children: _jsx(SiteMark, { size: "lg" }) }), _jsx(Heading, { level: 1, className: "font-extrabold", size: "3xl", children: labels.title ?? "Create Account" }), (labels.subtitle || renderLoginLink) && (_jsxs(Text, { className: "mt-2 text-[var(--appkit-color-text-muted)]", size: "sm", children: [labels.subtitle ?? "Already have an account?", " ", renderLoginLink?.()] }))] }), success && (_jsx(Alert, { variant: "success", compact: true, children: success })), error && (_jsx(Alert, { variant: "error", compact: true, children: error })), _jsxs(FormShellContext.Provider, { value: shellCtx, children: [_jsx(FormErrorSummary, {}), _jsx(SectionForm, { sections: sections, values: values, onChange: (partial) => setValues((prev) => Object.assign({}, prev, partial)), onSubmit: handleSubmit, schema: registerClientSchema, openIds: nav.openIds, onOpenChange: nav.setOpenIds, isLoading: isLoading, submitLabel: isLoading
|
|
88
|
+
? (labels.submittingLabel ?? "Creating account…")
|
|
89
|
+
: (labels.submitLabel ?? "Create account") })] }), renderSocialButtons?.()] }) }));
|
|
47
90
|
}
|
|
@@ -11,7 +11,33 @@
|
|
|
11
11
|
* Permission naming: admin:resource:action
|
|
12
12
|
* Ban action naming: plain verb phrase — write_reviews, place_bids, etc.
|
|
13
13
|
*/
|
|
14
|
-
export type Permission = "admin:dashboard:view" | "admin:users:read" | "admin:users:write" | "admin:users:delete" | "admin:user-bans:read" | "admin:user-bans:write" | "admin:products:read" | "admin:products:write" | "admin:products:delete" | "admin:orders:read" | "admin:orders:write" | "admin:returns:read" | "admin:returns:write" | "admin:stores:read" | "admin:stores:write" | "admin:store-addresses:read" | "admin:addresses:read" | "admin:addresses:write" | "admin:analytics:view" | "admin:payouts:read" | "admin:payouts:write" | "admin:audit-log:read" | "admin:categories:read" | "admin:categories:write" | "admin:categories:delete" | "admin:brands:read" | "admin:brands:write" | "admin:brands:delete" | "admin:coupons:read" | "admin:coupons:write" | "admin:coupons:delete" | "admin:deals:read" | "admin:deals:write" | "admin:featured:read" | "admin:featured:write" | "admin:reviews:read" | "admin:reviews:write" | "admin:reviews:delete" | "admin:blog:read" | "admin:blog:write" | "admin:blog:delete" | "admin:blog:publish" | "admin:bids:read" | "admin:bids:write" | "admin:offers:read" | "admin:offers:write" | "admin:media:read" | "admin:media:write" | "admin:media:delete" | "admin:site:read" | "admin:site:write" | "admin:settings:write" | "admin:navigation:read" | "admin:navigation:write" | "admin:sections:read" | "admin:sections:write" | "admin:carousel:read" | "admin:carousel:write" | "admin:carousel:delete" | "admin:ads:read" | "admin:ads:write" | "admin:ads:delete" | "admin:faqs:read" | "admin:faqs:write" | "admin:faqs:delete" | "admin:tester-checklist:read" | "admin:tester-checklist:write" | "admin:tester-checklist:delete" | "admin:tester-feedback:read" | "admin:tester-feedback:write" | "admin:newsletter:read" | "admin:newsletter:write" | "admin:contact:read"
|
|
14
|
+
export type Permission = "admin:dashboard:view" | "admin:users:read" | "admin:users:write" | "admin:users:delete" | "admin:user-bans:read" | "admin:user-bans:write" | "admin:products:read" | "admin:products:write" | "admin:products:delete" | "admin:orders:read" | "admin:orders:write" | "admin:returns:read" | "admin:returns:write" | "admin:stores:read" | "admin:stores:write" | "admin:store-addresses:read" | "admin:addresses:read" | "admin:addresses:write" | "admin:analytics:view" | "admin:payouts:read" | "admin:payouts:write" | "admin:audit-log:read" | "admin:categories:read" | "admin:categories:write" | "admin:categories:delete" | "admin:brands:read" | "admin:brands:write" | "admin:brands:delete" | "admin:coupons:read" | "admin:coupons:write" | "admin:coupons:delete" | "admin:deals:read" | "admin:deals:write" | "admin:featured:read" | "admin:featured:write" | "admin:reviews:read" | "admin:reviews:write" | "admin:reviews:delete" | "admin:blog:read" | "admin:blog:write" | "admin:blog:delete" | "admin:blog:publish" | "admin:bids:read" | "admin:bids:write" | "admin:offers:read" | "admin:offers:write" | "admin:media:read" | "admin:media:write" | "admin:media:delete" | "admin:site:read" | "admin:site:write" | "admin:settings:write" | "admin:navigation:read" | "admin:navigation:write" | "admin:sections:read" | "admin:sections:write" | "admin:carousel:read" | "admin:carousel:write" | "admin:carousel:delete" | "admin:ads:read" | "admin:ads:write" | "admin:ads:delete" | "admin:faqs:read" | "admin:faqs:write" | "admin:faqs:delete" | "admin:tester-checklist:read" | "admin:tester-checklist:write" | "admin:tester-checklist:delete" | "admin:tester-feedback:read" | "admin:tester-feedback:write" | "admin:newsletter:read" | "admin:newsletter:write" | "admin:contact:read"
|
|
15
|
+
/** Destructive/mutating contact-submission actions. Added 2026-08-29 —
|
|
16
|
+
* `DELETE /api/admin/contact-submissions/[id]` declared `admin:contact:delete`,
|
|
17
|
+
* which is not a member of this union and therefore could never be granted. */
|
|
18
|
+
| "admin:contact:write" | "admin:moderation:read" | "admin:roles:read"
|
|
19
|
+
/**
|
|
20
|
+
* Skip OTP + payment when placing an order. Replaces
|
|
21
|
+
* `siteSettings.featureFlags.adminCheckoutBypass`: a capability granted to a
|
|
22
|
+
* person belongs in the permission system, not in a site-wide toggle that is
|
|
23
|
+
* either on for every admin or off for all of them.
|
|
24
|
+
*
|
|
25
|
+
* Named `admin:checkout:bypass` rather than the bare `checkout:bypass` so it
|
|
26
|
+
* matches the `admin:resource:action` convention every other member follows
|
|
27
|
+
* and is picked up by PERMISSION_DOMAINS prefix matching.
|
|
28
|
+
*/
|
|
29
|
+
| "admin:checkout:bypass"
|
|
30
|
+
/**
|
|
31
|
+
* Lets a `tester` reach `/admin/**` with real read/write access.
|
|
32
|
+
*
|
|
33
|
+
* Replaces the `canTestAdmin` boolean. Not a second role: the hierarchy is
|
|
34
|
+
* linear, so there is no level meaning "seller-level, plus read admin" that
|
|
35
|
+
* would not also outrank moderator and employee. Granted through the same
|
|
36
|
+
* `permissions[]` array employees already use, so there is one grant
|
|
37
|
+
* mechanism — and revoking it is a permission change, which the admin audit
|
|
38
|
+
* log already records.
|
|
39
|
+
*/
|
|
40
|
+
| "tester:admin-surfaces" | "admin:events:read" | "admin:events:write" | "admin:events:delete" | "admin:event-entries:read" | "admin:event-entries:write" | "admin:support-tickets:read" | "admin:support-tickets:write" | "admin:shipments:read" | "admin:shipments:write" | "admin:catalogue:read" | "admin:catalogue:write" | "admin:grouped-listings:read" | "admin:grouped-listings:write" | "admin:support-tickets:assign" | "admin:support-tickets:close" | "admin:scammers:read" | "admin:scammers:write" | "admin:scammers:verify" | "admin:scammers:delete" | "admin:sessions:read" | "admin:sessions:delete" | "admin:notifications:read" | "admin:notifications:write" | "admin:carts:read" | "admin:wishlists:read" | "admin:feature-flags:read" | "admin:feature-flags:write" | "admin:copilot:view" | "admin:team:read" | "admin:team:write" | "admin:maintenance:view-server-errors" | "admin:maintenance:view-client-errors" | "admin:maintenance:view-function-errors" | "admin:maintenance:view-cloud-logs" | "admin:maintenance:view-payment-rollbacks" | "admin:maintenance:run-analysis" | "admin:maintenance:purge-errors";
|
|
15
41
|
/**
|
|
16
42
|
* Granular user actions that can be soft-banned individually.
|
|
17
43
|
* A user may have multiple simultaneous soft bans of different types.
|