@mohasinac/appkit 4.9.5 → 4.11.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/DashboardLayoutClient.d.ts +6 -1
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +4 -1
- package/dist/_internal/client/features/lottery/LotteryPullForm.d.ts +1 -1
- package/dist/_internal/client/features/lottery/LotteryPullForm.js +2 -2
- package/dist/_internal/server/features/admin/daily-digest-actions.d.ts +18 -0
- package/dist/_internal/server/features/admin/daily-digest-actions.js +37 -0
- package/dist/_internal/server/features/auctions/actions.js +3 -2
- package/dist/_internal/server/features/auctions/service.d.ts +4 -3
- package/dist/_internal/server/features/auctions/service.js +6 -6
- package/dist/_internal/server/features/audit-log/actions.d.ts +25 -0
- package/dist/_internal/server/features/audit-log/actions.js +38 -0
- package/dist/_internal/server/features/brands/actions.js +0 -2
- package/dist/_internal/server/features/brands/og.d.ts +4 -1
- package/dist/_internal/server/features/brands/og.js +1 -1
- package/dist/_internal/server/features/bundles/data.d.ts +9 -0
- package/dist/_internal/server/features/bundles/data.js +14 -0
- package/dist/_internal/server/features/bundles/index.d.ts +1 -1
- package/dist/_internal/server/features/bundles/index.js +1 -1
- package/dist/_internal/server/features/catalogue/og.d.ts +20 -0
- package/dist/_internal/server/features/catalogue/og.js +27 -0
- package/dist/_internal/server/features/grouped/data.d.ts +16 -0
- package/dist/_internal/server/features/grouped/data.js +50 -1
- package/dist/_internal/server/features/grouped/index.d.ts +1 -1
- package/dist/_internal/server/features/grouped/index.js +1 -1
- package/dist/_internal/server/features/orders/actions.js +9 -0
- package/dist/_internal/server/features/orders/adapters.js +25 -0
- package/dist/_internal/server/features/products/data.d.ts +23 -0
- package/dist/_internal/server/features/products/data.js +159 -0
- package/dist/_internal/server/features/products/index.d.ts +1 -1
- package/dist/_internal/server/features/products/index.js +1 -1
- package/dist/_internal/server/functions/scheduled.d.ts +3 -1
- package/dist/_internal/server/functions/scheduled.js +17 -1
- package/dist/_internal/server/jobs/core/dailyStatusDigest.d.ts +40 -0
- package/dist/_internal/server/jobs/core/dailyStatusDigest.js +164 -0
- package/dist/_internal/server/jobs/core/hardBanCascade.js +11 -0
- package/dist/_internal/server/jobs/core/testerSandboxCleanup.d.ts +1 -0
- package/dist/_internal/server/jobs/core/testerSandboxCleanup.js +4 -1
- package/dist/_internal/server/jobs/core/testerSandboxRefresh.d.ts +12 -0
- package/dist/_internal/server/jobs/core/testerSandboxRefresh.js +85 -0
- package/dist/_internal/server/jobs/core/whatsappNotify.js +16 -0
- package/dist/_internal/server/jobs/handlers/dailyStatusDigest.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/dailyStatusDigest.js +4 -0
- package/dist/_internal/server/jobs/handlers/index.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/index.js +3 -0
- package/dist/_internal/server/jobs/handlers/testerSandboxRefresh.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/testerSandboxRefresh.js +2 -0
- package/dist/_internal/server/notifications/channel-health.d.ts +27 -0
- package/dist/_internal/server/notifications/channel-health.js +101 -0
- package/dist/_internal/shared/features/auctions/config.d.ts +20 -0
- package/dist/_internal/shared/features/auctions/config.js +31 -1
- package/dist/_internal/shared/features/brands/schema.d.ts +0 -6
- package/dist/_internal/shared/features/brands/schema.js +0 -1
- package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +7 -0
- package/dist/_internal/shared/features/categories/bundle-schemas.js +3 -0
- package/dist/_internal/shared/features/orders/schema.d.ts +8 -8
- package/dist/_internal/shared/listing-types/art/config.d.ts +1 -1
- package/dist/_internal/shared/listing-types/art/config.js +1 -1
- package/dist/_internal/shared/listing-types/classified/config.d.ts +1 -1
- package/dist/_internal/shared/listing-types/classified/config.js +1 -1
- package/dist/_internal/shared/listing-types/digital-code/config.d.ts +1 -1
- package/dist/_internal/shared/listing-types/digital-code/config.js +1 -1
- package/dist/_internal/shared/listing-types/live/config.d.ts +1 -1
- package/dist/_internal/shared/listing-types/live/config.js +1 -1
- package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +1 -1
- package/dist/_internal/shared/listing-types/prize-draw/config.js +1 -1
- package/dist/_internal/shared/listing-types/stickers/config.d.ts +1 -1
- package/dist/_internal/shared/listing-types/stickers/config.js +1 -1
- package/dist/client.d.ts +21 -12
- package/dist/client.js +14 -7
- package/dist/constants/api-endpoints.d.ts +9 -9
- package/dist/constants/api-endpoints.js +3 -3
- package/dist/contracts/client-auth.d.ts +3 -7
- package/dist/contracts/email.d.ts +1 -0
- package/dist/features/account/components/AddressForm.js +24 -2
- package/dist/features/account/components/BecomeSellerView.d.ts +1 -2
- package/dist/features/account/components/BecomeSellerView.js +1 -1
- package/dist/features/account/components/NotificationBell.js +1 -1
- package/dist/features/account/components/UserBidsView.d.ts +1 -0
- package/dist/features/account/components/UserBidsView.js +47 -0
- package/dist/features/account/components/UserOrdersView.d.ts +4 -11
- package/dist/features/account/components/UserOrdersView.js +54 -4
- package/dist/features/account/components/UserReturnsView.d.ts +4 -9
- package/dist/features/account/components/UserReturnsView.js +37 -3
- package/dist/features/account/components/index.d.ts +3 -2
- package/dist/features/account/components/index.js +1 -0
- package/dist/features/admin/actions/admin-actions.js +22 -0
- package/dist/features/admin/actions/admin-coupon-actions.js +10 -0
- package/dist/features/admin/actions/notification-actions.js +4 -3
- package/dist/features/admin/components/AdminAdsView.d.ts +2 -3
- package/dist/features/admin/components/AdminAdsView.js +86 -89
- package/dist/features/admin/components/AdminAllEventEntriesView.js +18 -3
- package/dist/features/admin/components/AdminAuditLogView.d.ts +11 -0
- package/dist/features/admin/components/AdminAuditLogView.js +95 -0
- package/dist/features/admin/components/AdminBlogEditorView.js +37 -3
- package/dist/features/admin/components/AdminBrandEditorView.js +10 -6
- package/dist/features/admin/components/AdminBundleEditorView.js +18 -2
- package/dist/features/admin/components/AdminCarouselEditorView.js +2 -2
- package/dist/features/admin/components/AdminCarouselGroupEditorView.js +2 -2
- package/dist/features/admin/components/AdminCartsView.js +34 -4
- package/dist/features/admin/components/AdminCategoryEditorView.js +5 -4
- package/dist/features/admin/components/AdminCouponEditorView.js +2 -2
- package/dist/features/admin/components/AdminFaqEditorView.js +2 -2
- package/dist/features/admin/components/AdminHistoryView.js +11 -1
- package/dist/features/admin/components/AdminNotificationsView.js +27 -1
- package/dist/features/admin/components/AdminOrderEditorView.d.ts +10 -1
- package/dist/features/admin/components/AdminOrderEditorView.js +4 -3
- package/dist/features/admin/components/AdminOrdersView.js +92 -24
- package/dist/features/admin/components/AdminPayoutMarkPaidModal.d.ts +7 -0
- package/dist/features/admin/components/AdminPayoutMarkPaidModal.js +47 -0
- package/dist/features/admin/components/AdminPayoutsView.js +15 -31
- package/dist/features/admin/components/AdminProductEditorView.js +26 -3
- package/dist/features/admin/components/AdminSiteSettingsView.js +31 -4
- package/dist/features/admin/components/AdminStoreAddressesView.js +22 -2
- package/dist/features/admin/components/AdminStoresView.js +7 -0
- package/dist/features/admin/components/AdminSublistingCategoryEditorView.js +2 -2
- package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +2 -2
- package/dist/features/admin/components/AdminUserEditorView.d.ts +2 -2
- package/dist/features/admin/components/AdminUserEditorView.js +4 -2
- package/dist/features/admin/components/AdminUsersView.js +1 -1
- package/dist/features/admin/components/AdminWishlistsView.js +14 -1
- package/dist/features/admin/components/DataListingView.d.ts +2 -2
- package/dist/features/admin/components/ViewAuditLogEntryModal.d.ts +19 -0
- package/dist/features/admin/components/ViewAuditLogEntryModal.js +22 -0
- package/dist/features/admin/components/ViewNotificationModal.d.ts +21 -0
- package/dist/features/admin/components/ViewNotificationModal.js +15 -0
- package/dist/features/admin/components/analytics/AdminPageViewsReportView.d.ts +4 -7
- package/dist/features/admin/components/analytics/AdminPageViewsReportView.js +56 -36
- package/dist/features/admin/components/index.d.ts +8 -1
- package/dist/features/admin/components/index.js +4 -0
- package/dist/features/admin/constants/filter-tabs.d.ts +49 -0
- package/dist/features/admin/constants/filter-tabs.js +27 -0
- package/dist/features/admin/hooks/useAdminListing.d.ts +6 -0
- package/dist/features/admin/hooks/useAdminListing.js +3 -1
- package/dist/features/admin/hooks/useAdminListingData.d.ts +9 -1
- package/dist/features/admin/hooks/useAdminListingData.js +9 -2
- package/dist/features/admin/repository/site-settings.repository.d.ts +5 -0
- package/dist/features/admin/schemas/firestore.d.ts +21 -0
- package/dist/features/admin/schemas/firestore.js +6 -0
- package/dist/features/analytics/types.d.ts +1 -1
- package/dist/features/analytics/types.js +8 -0
- package/dist/features/auctions/actions/bid-actions.js +4 -1
- package/dist/features/auctions/components/AuctionBottomActions.d.ts +2 -1
- package/dist/features/auctions/components/AuctionBottomActions.js +14 -1
- package/dist/features/auctions/components/AuctionDetailPageView.js +21 -9
- package/dist/features/auctions/components/LiveMinIncrement.d.ts +18 -0
- package/dist/features/auctions/components/LiveMinIncrement.js +17 -0
- package/dist/features/auctions/components/PlaceBidFormClient.d.ts +5 -2
- package/dist/features/auctions/components/PlaceBidFormClient.js +7 -3
- package/dist/features/auctions/schemas/index.d.ts +5 -0
- package/dist/features/audit-log/repository/audit-log.repository.d.ts +45 -0
- package/dist/features/audit-log/repository/audit-log.repository.js +30 -0
- package/dist/features/audit-log/schemas/firestore.d.ts +59 -0
- package/dist/features/audit-log/schemas/firestore.js +35 -0
- package/dist/features/auth/actions/index.d.ts +0 -1
- package/dist/features/auth/actions/index.js +0 -1
- package/dist/features/auth/hooks/useAuth.d.ts +8 -35
- package/dist/features/auth/hooks/useAuth.js +21 -37
- package/dist/features/auth/permissions/constants.d.ts +1 -1
- package/dist/features/auth/permissions/constants.js +2 -0
- package/dist/features/blog/schemas/index.d.ts +32 -0
- package/dist/features/catalogue/components/AdminCatalogueApprovalsView.js +31 -3
- package/dist/features/catalogue/components/CatalogueItemEditorView.js +2 -1
- package/dist/features/catalogue/components/PublicCatalogueItemDetailView.d.ts +11 -0
- package/dist/features/catalogue/components/PublicCatalogueItemDetailView.js +33 -0
- package/dist/features/catalogue/components/PublicCatalogueView.js +2 -1
- package/dist/features/catalogue/index.d.ts +2 -0
- package/dist/features/catalogue/index.js +1 -0
- package/dist/features/categories/components/BrandDetailPageView.js +14 -12
- package/dist/features/categories/components/BundleDetailView.d.ts +3 -1
- package/dist/features/categories/components/BundleDetailView.js +3 -2
- package/dist/features/categories/components/CategoryDetailPageView.js +7 -3
- package/dist/features/categories/components/CategoryHighlightsAndFaqSection.d.ts +14 -0
- package/dist/features/categories/components/CategoryHighlightsAndFaqSection.js +22 -0
- package/dist/features/categories/components/CategoryProductsView.d.ts +1 -5
- package/dist/features/categories/components/CategoryProductsView.js +1 -1
- package/dist/features/categories/components/CategorySelectorCreate.js +16 -2
- package/dist/features/categories/schemas/firestore.d.ts +19 -2
- package/dist/features/categories/schemas/index.d.ts +24 -3
- package/dist/features/categories/schemas/index.js +3 -1
- package/dist/features/categories/types/index.d.ts +7 -0
- package/dist/features/checkout/actions/checkout-value-otp-actions.d.ts +17 -3
- package/dist/features/checkout/actions/checkout-value-otp-actions.js +101 -22
- package/dist/features/classified/components/ClassifiedContactSellerPanel.d.ts +12 -0
- package/dist/features/classified/components/ClassifiedContactSellerPanel.js +49 -0
- package/dist/features/classified/components/ClassifiedDetailPageView.d.ts +7 -0
- package/dist/features/classified/components/ClassifiedDetailPageView.js +69 -0
- package/dist/features/contact/components/ContactForm.js +17 -4
- package/dist/features/contact/components/ContactPageView.js +8 -2
- package/dist/features/contact/email.d.ts +1 -0
- package/dist/features/contact/email.js +3 -0
- package/dist/features/digital-codes/components/DigitalCodeDetailPageView.d.ts +19 -0
- package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +79 -0
- package/dist/features/events/components/AdminEventEditorView.js +54 -2
- package/dist/features/events/components/AdminEventEntriesView.d.ts +2 -16
- package/dist/features/events/components/AdminEventEntriesView.js +56 -89
- package/dist/features/events/components/EventFormDrawer.js +5 -1
- package/dist/features/events/components/EventRaffleEntryForm.d.ts +1 -3
- package/dist/features/events/components/EventRaffleEntryForm.js +1 -1
- package/dist/features/events/schemas/index.d.ts +22 -0
- package/dist/features/grouped/components/GroupedListingsCarousel.d.ts +13 -0
- package/dist/features/grouped/components/GroupedListingsCarousel.js +31 -0
- package/dist/features/grouped/repository/grouped-listings.repository.d.ts +12 -0
- package/dist/features/grouped/repository/grouped-listings.repository.js +34 -0
- package/dist/features/homepage/components/CharacterHotspotForm.js +202 -187
- package/dist/features/homepage/components/SectionCarousel.d.ts +1 -7
- package/dist/features/homepage/components/SectionCarousel.js +1 -1
- package/dist/features/layout/BottomActions.js +4 -3
- package/dist/features/layout/BottomActionsContext.d.ts +10 -0
- package/dist/features/layout/BottomActionsContext.js +5 -1
- package/dist/features/layout/TitleBarLayout.d.ts +1 -1
- package/dist/features/layout/TitleBarLayout.js +3 -3
- package/dist/features/layout/hooks/useBottomActions.d.ts +2 -0
- package/dist/features/layout/hooks/useBottomActions.js +4 -1
- package/dist/features/live/components/LiveItemDetailPageView.d.ts +9 -0
- package/dist/features/live/components/LiveItemDetailPageView.js +74 -0
- package/dist/features/media/MediaImage.js +39 -3
- package/dist/features/media/MediaVideo.js +17 -1
- package/dist/features/media/types/index.d.ts +10 -0
- package/dist/features/media/types/index.js +1 -0
- package/dist/features/media/upload/MediaUploadField.d.ts +7 -1
- package/dist/features/media/upload/MediaUploadField.js +11 -7
- package/dist/features/media/upload/video-poster.d.ts +2 -0
- package/dist/features/media/upload/video-poster.js +16 -1
- package/dist/features/media/upload/video-poster.test.js +1 -1
- package/dist/features/orders/components/OrderStatusTimeline.d.ts +12 -0
- package/dist/features/orders/components/OrderStatusTimeline.js +55 -0
- package/dist/features/orders/components/index.d.ts +2 -0
- package/dist/features/orders/components/index.js +1 -0
- package/dist/features/orders/constants/payment-window.d.ts +25 -0
- package/dist/features/orders/constants/payment-window.js +25 -0
- package/dist/features/orders/repository/orders.repository.d.ts +32 -0
- package/dist/features/orders/repository/orders.repository.js +56 -0
- package/dist/features/orders/schemas/index.d.ts +24 -24
- package/dist/features/orders/types/index.d.ts +33 -0
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +9 -1
- package/dist/features/pre-orders/schemas/index.d.ts +5 -0
- package/dist/features/products/components/BidHistory.js +9 -1
- package/dist/features/products/components/GroupSettingsPanel.js +25 -3
- package/dist/features/products/components/PrizeDrawDetailPageView.js +11 -1
- package/dist/features/products/components/PrizeDrawEntryActions.d.ts +1 -4
- package/dist/features/products/components/PrizeDrawEntryActions.js +1 -1
- package/dist/features/products/components/ProductDetailActions.d.ts +1 -2
- package/dist/features/products/components/ProductDetailActions.js +1 -1
- package/dist/features/products/components/ProductDetailPageView.js +11 -116
- package/dist/features/products/components/ProductGrid.js +15 -1
- package/dist/features/products/components/RelatedItemsSection.d.ts +16 -0
- package/dist/features/products/components/RelatedItemsSection.js +17 -0
- package/dist/features/products/constants/action-defs.d.ts +1 -0
- package/dist/features/products/constants/action-defs.js +1 -0
- package/dist/features/products/schemas/index.d.ts +5 -0
- package/dist/features/promotions/components/CouponsIndexListing.d.ts +1 -3
- package/dist/features/promotions/components/CouponsIndexListing.js +1 -1
- package/dist/features/search/components/SearchView.d.ts +1 -3
- package/dist/features/search/components/SearchView.js +1 -1
- package/dist/features/seller/components/QuickProductForm.js +2 -1
- package/dist/features/seller/components/SellerBidsView.js +66 -107
- package/dist/features/seller/components/SellerGoogleReviewsView.js +17 -1
- package/dist/features/seller/components/SellerOrdersView.d.ts +15 -3
- package/dist/features/seller/components/SellerOrdersView.js +134 -163
- package/dist/features/seller/components/SellerPayoutMethodsView.js +60 -48
- package/dist/features/seller/components/SellerPayoutSettingsView.js +69 -4
- package/dist/features/seller/components/SellerPayoutsView.d.ts +12 -0
- package/dist/features/seller/components/SellerPayoutsView.js +25 -5
- package/dist/features/seller/components/SellerProductShell.d.ts +10 -3
- package/dist/features/seller/components/SellerProductShell.js +90 -37
- package/dist/features/seller/components/SellerProductsFilterDrawer.d.ts +2 -7
- package/dist/features/seller/components/SellerProductsFilterDrawer.js +4 -4
- package/dist/features/seller/components/SellerProductsView.d.ts +2 -4
- package/dist/features/seller/components/SellerProductsView.js +131 -189
- package/dist/features/seller/components/SellerReviewsView.js +95 -133
- package/dist/features/seller/components/SellerShippingConfigsView.js +47 -67
- package/dist/features/seller/components/SellerShippingView.js +41 -4
- package/dist/features/seller/components/SellerStoreCategoriesView.js +51 -59
- package/dist/features/seller/components/SellerStorefrontView.d.ts +6 -1
- package/dist/features/seller/components/SellerStorefrontView.js +42 -5
- package/dist/features/seller/components/index.d.ts +2 -2
- package/dist/features/seller/components/index.js +2 -2
- package/dist/features/shell/FormShell.d.ts +24 -4
- package/dist/features/shell/FormShell.js +12 -6
- package/dist/features/shell/QuickFormDrawer.js +67 -12
- package/dist/features/shell/StepForm.d.ts +30 -1
- package/dist/features/shell/StepForm.js +47 -4
- package/dist/features/shell/index.d.ts +1 -1
- package/dist/features/shell/index.js +1 -1
- package/dist/features/shipments/components/AdminShipmentEditorView.js +2 -2
- package/dist/features/shipments/schemas/validation.d.ts +14 -4
- package/dist/features/tester/components/AdminTesterFeedbackListView.js +23 -2
- package/dist/features/tester/components/TesterChecklistStepRow.js +1 -1
- package/dist/features/tester/components/TesterHubView.js +3 -2
- package/dist/features/tester/seed-data/orders-tester-seed-data.js +9 -1
- package/dist/features/tester/seed-data/products-tester-seed-data.js +43 -32
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +487 -18
- package/dist/index.d.ts +17 -3
- package/dist/index.js +23 -5
- package/dist/next/routing/route-map.d.ts +13 -0
- package/dist/next/routing/route-map.js +12 -0
- package/dist/providers/email-resend/provider.js +1 -0
- package/dist/providers/firebase-client/auth.d.ts +1 -0
- package/dist/providers/firebase-client/auth.js +7 -1
- package/dist/repositories/index.d.ts +1 -0
- package/dist/repositories/index.js +1 -0
- package/dist/schemas/registry.d.ts +61 -25
- package/dist/security/pii-mask.js +1 -1
- package/dist/seed/bids-seed-data.js +48 -3
- package/dist/seed/categories-seed-data.js +69 -0
- package/dist/seed/grouped-listings-seed-data.js +167 -0
- package/dist/seed/payouts-seed-data.js +4 -4
- package/dist/seed/products-art-seed-data.js +188 -5
- package/dist/seed/products-auctions-seed-data.js +226 -6
- package/dist/seed/products-classifieds-seed-data.js +255 -8
- package/dist/seed/products-digital-codes-seed-data.js +258 -19
- package/dist/seed/products-live-items-seed-data.js +143 -10
- package/dist/seed/products-preorders-seed-data.js +213 -8
- package/dist/seed/products-prize-draws-seed-data.js +198 -0
- package/dist/seed/products-standard-seed-data.js +234 -4
- package/dist/seed/products-stickers-seed-data.js +178 -5
- package/dist/seed/site-settings-seed-data.js +23 -30
- package/dist/seed/store-extensions-seed-data.js +2 -2
- package/dist/server-entry.d.ts +6 -2
- package/dist/server-entry.js +24 -3
- package/dist/server.d.ts +10 -3
- package/dist/server.js +11 -4
- package/dist/styles.css +29 -1
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/Form.d.ts +11 -2
- package/dist/ui/components/Form.js +4 -3
- package/dist/ui/components/FormField.d.ts +3 -1
- package/dist/ui/components/FormField.js +22 -4
- package/dist/ui/components/ImageLightbox.js +37 -3
- package/dist/ui/components/ImageLightbox.style.css +28 -0
- package/dist/ui/components/ListingLayout.d.ts +1 -2
- package/dist/ui/components/ListingLayout.js +1 -1
- package/dist/ui/components/RecordDetailModal.d.ts +68 -0
- package/dist/ui/components/RecordDetailModal.js +8 -0
- package/dist/ui/components/SlottedListingView.js +9 -1
- package/dist/ui/forms/FormErrorSummary.d.ts +25 -0
- package/dist/ui/forms/FormErrorSummary.js +37 -0
- package/dist/ui/forms/FormShell.d.ts +37 -2
- package/dist/ui/forms/FormShell.js +37 -7
- package/dist/ui/forms/FormShell.style.css +17 -0
- package/dist/ui/forms/index.d.ts +2 -0
- package/dist/ui/forms/index.js +1 -0
- package/dist/ui/index.d.ts +4 -0
- package/dist/ui/index.js +5 -0
- package/dist/utils/media-url.d.ts +12 -1
- package/dist/utils/media-url.js +59 -1
- package/dist/validation/schemas.d.ts +4 -4
- package/package.json +1 -1
- package/dist/_internal/client/features/classified/ClassifiedDetailView.d.ts +0 -9
- package/dist/_internal/client/features/classified/ClassifiedDetailView.js +0 -55
- package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.d.ts +0 -18
- package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.js +0 -21
- package/dist/_internal/client/features/live/LiveItemDetailView.d.ts +0 -9
- package/dist/_internal/client/features/live/LiveItemDetailView.js +0 -25
- package/dist/_internal/server/jobs/core/prizeRevealClose.d.ts +0 -2
- package/dist/_internal/server/jobs/core/prizeRevealClose.js +0 -28
- package/dist/_internal/server/jobs/core/prizeRevealExpiry.d.ts +0 -2
- package/dist/_internal/server/jobs/core/prizeRevealExpiry.js +0 -61
- package/dist/_internal/server/jobs/core/prizeRevealOpen.d.ts +0 -2
- package/dist/_internal/server/jobs/core/prizeRevealOpen.js +0 -68
- package/dist/_internal/server/jobs/core/prizeRevealReminder.d.ts +0 -2
- package/dist/_internal/server/jobs/core/prizeRevealReminder.js +0 -49
- package/dist/_internal/server/jobs/handlers/prizeRevealClose.d.ts +0 -2
- package/dist/_internal/server/jobs/handlers/prizeRevealClose.js +0 -2
- package/dist/_internal/server/jobs/handlers/prizeRevealExpiry.d.ts +0 -2
- package/dist/_internal/server/jobs/handlers/prizeRevealExpiry.js +0 -2
- package/dist/_internal/server/jobs/handlers/prizeRevealOpen.d.ts +0 -2
- package/dist/_internal/server/jobs/handlers/prizeRevealOpen.js +0 -2
- package/dist/_internal/server/jobs/handlers/prizeRevealReminder.d.ts +0 -2
- package/dist/_internal/server/jobs/handlers/prizeRevealReminder.js +0 -2
- package/dist/features/auth/consent-otp.d.ts +0 -57
- package/dist/features/auth/consent-otp.js +0 -127
- package/dist/features/cart/components/CheckoutOtpModal.d.ts +0 -15
- package/dist/features/cart/components/CheckoutOtpModal.js +0 -12
- package/dist/features/checkout/actions/checkout-actions.d.ts +0 -31
- package/dist/features/checkout/actions/checkout-actions.js +0 -124
- package/dist/features/classified/components/ClassifiedIndexListing.d.ts +0 -5
- package/dist/features/classified/components/ClassifiedIndexListing.js +0 -123
- package/dist/features/classified/components/ClassifiedListView.d.ts +0 -6
- package/dist/features/classified/components/ClassifiedListView.js +0 -44
- package/dist/features/digital-codes/components/DigitalCodesIndexListing.d.ts +0 -5
- package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +0 -114
- package/dist/features/digital-codes/components/DigitalCodesListView.d.ts +0 -6
- package/dist/features/digital-codes/components/DigitalCodesListView.js +0 -38
- package/dist/features/live/components/LiveItemsIndexListing.d.ts +0 -5
- package/dist/features/live/components/LiveItemsIndexListing.js +0 -115
- package/dist/features/live/components/LiveItemsListView.d.ts +0 -6
- package/dist/features/live/components/LiveItemsListView.js +0 -44
- package/dist/features/seller/components/SellerTemplatesView.d.ts +0 -12
- package/dist/features/seller/components/SellerTemplatesView.js +0 -276
- package/dist/react/hooks/useVisibleItems.d.ts +0 -37
- package/dist/react/hooks/useVisibleItems.js +0 -59
- package/dist/ui/components/TabStrip.d.ts +0 -34
- package/dist/ui/components/TabStrip.js +0 -56
- package/dist/ui/components/TabStrip.style.css +0 -97
|
@@ -16,7 +16,9 @@ import { getDefaultCurrency } from "../../../core/baseline-resolver";
|
|
|
16
16
|
import { formatCurrency } from "../../../utils/number.formatter";
|
|
17
17
|
import { normalizeRichTextHtml } from "../../../utils/string.formatter";
|
|
18
18
|
import { safeDisplayName } from "../../../security";
|
|
19
|
-
import {
|
|
19
|
+
import { getSiteSettingsGlobal } from "../../admin/utils/getSiteSettingsGlobal";
|
|
20
|
+
import { resolveMinBidIncrement, } from "../../../_internal/shared/features/auctions/config";
|
|
21
|
+
import { Button, Container, CountdownDisplay, Div, Heading, Input, Main, Nav, RichText, Row, Section, Span, Stack, Text, Ul, Li, Dl, Dt, Dd, } from "../../../ui";
|
|
20
22
|
import { AuctionDetailView } from "../../products/components/AuctionDetailView";
|
|
21
23
|
import { ProductTabsShell } from "../../products/components/ProductTabsShell";
|
|
22
24
|
import { CustomSectionTabContent } from "../../products/components/CustomSectionTabContent";
|
|
@@ -32,6 +34,11 @@ import { listReviewsBySeller } from "../../reviews/actions/review-actions";
|
|
|
32
34
|
import { PlaceBidModalButton } from "./PlaceBidFormClient";
|
|
33
35
|
import { CollapsibleBidHistory } from "./CollapsibleBidHistory";
|
|
34
36
|
import { LiveBidPrice } from "./LiveBidPrice";
|
|
37
|
+
import { LiveMinIncrement } from "./LiveMinIncrement";
|
|
38
|
+
import { RelatedItemsSection } from "../../products/components/RelatedItemsSection";
|
|
39
|
+
import { computeRelatedItems } from "../../../_internal/server/features/products/data";
|
|
40
|
+
import { GroupedListingsCarousel } from "../../grouped/components/GroupedListingsCarousel";
|
|
41
|
+
import { getGroupsWithItemsForProduct } from "../../../_internal/server/features/grouped/data";
|
|
35
42
|
import { SublistingCarouselSection } from "../../products/components/SublistingCarouselSection";
|
|
36
43
|
function toDescriptionHtml(raw) {
|
|
37
44
|
if (!raw)
|
|
@@ -41,7 +48,7 @@ function toDescriptionHtml(raw) {
|
|
|
41
48
|
}
|
|
42
49
|
function renderAuctionInfoPanel(props) {
|
|
43
50
|
const { productId, title, currentBid, currency, bidCount, isEnded, endDate, buyNowPrice, featured, freeShipping, condition, category, categoryName, brand, brandSlug, productFeatures, features, descriptionHtml, safeSeller, storeHref } = props;
|
|
44
|
-
return (_jsxs(Stack, { gap: "md", children: [_jsxs(Div, { children: [_jsxs(Row, { gap: "xs", wrap: true, className: "mb-2", children: [_jsx(Span, { size: "xs", weight: "semibold", className: CLS_LIVE_BADGE, children: "\uD83C\uDFF7\uFE0F Live Auction" }), isEnded ? (_jsx(Span, { color: "error", surface: "danger-surface", size: "xs", weight: "medium", className: "inline-block", padding: "pill-sm", rounded: "full", children: "Ended" })) : (_jsx(Span, { color: "success", surface: "success-surface", size: "xs", weight: "medium", className: "inline-block", padding: "pill-sm", rounded: "full", children: "Active" }))] }), _jsx(Heading, { level: 1, className: "leading-snug", smSize: "2xl", color: "primary", size: "xl", weight: "bold", children: title })] }), _jsxs(Div, { children: [_jsx(Text, { className: "mb-0.5", color: "muted", size: "xs", children: "Current bid" }), _jsx(LiveBidPrice, { productId: productId, currentBid: currentBid, bidCount: bidCount, currency: currency, isEnded: isEnded, priceSize: "2xl", badgeSize: "sm" }), endDate && _jsxs(Text, { className: "mt-1.5", color: "muted", size: "sm", children: [
|
|
51
|
+
return (_jsxs(Stack, { gap: "md", children: [_jsxs(Div, { children: [_jsxs(Row, { gap: "xs", wrap: true, className: "mb-2", children: [_jsx(Span, { size: "xs", weight: "semibold", className: CLS_LIVE_BADGE, children: "\uD83C\uDFF7\uFE0F Live Auction" }), isEnded ? (_jsx(Span, { color: "error", surface: "danger-surface", size: "xs", weight: "medium", className: "inline-block", padding: "pill-sm", rounded: "full", children: "Ended" })) : (_jsx(Span, { color: "success", surface: "success-surface", size: "xs", weight: "medium", className: "inline-block", padding: "pill-sm", rounded: "full", children: "Active" }))] }), _jsx(Heading, { level: 1, className: "leading-snug", smSize: "2xl", color: "primary", size: "xl", weight: "bold", children: title })] }), _jsxs(Div, { children: [_jsx(Text, { className: "mb-0.5", color: "muted", size: "xs", children: "Current bid" }), _jsx(LiveBidPrice, { productId: productId, currentBid: currentBid, bidCount: bidCount, currency: currency, isEnded: isEnded, priceSize: "2xl", badgeSize: "sm" }), endDate && !isEnded && (_jsxs(Text, { className: "mt-1.5", color: "muted", size: "sm", children: ["Ends in ", _jsx(Span, { weight: "medium", color: "muted", children: _jsx(CountdownDisplay, { targetDate: endDate, format: "auto", expiredLabel: "Ended" }) })] })), endDate && _jsxs(Text, { className: "mt-0.5", color: "faint", size: "xs", children: [isEnded ? "Ended" : "Ends", " ", endDate.toLocaleString()] })] }), buyNowPrice !== null && !isEnded && (_jsxs(Row, { align: "center", gap: "sm", className: "border border-[var(--appkit-color-primary-200)] dark:border-[var(--appkit-color-primary-800)] bg-primary-50 dark:bg-primary-900/20", padding: "inlineSm", rounded: "lg", children: [_jsx(Span, { size: "xs", color: "muted", children: "Buy Now:" }), _jsx(Span, { size: "base", weight: "bold", className: "text-primary-700 dark:text-primary-300", children: formatCurrency(buyNowPrice, currency) })] })), _jsx(ProductFeatureBadges, { featured: featured, freeShipping: freeShipping, condition: condition ?? undefined, labels: { featured: "Featured", fasterDelivery: "Faster Delivery", ratedSeller: "Rated Seller", condition: "Condition", conditionNew: "New", conditionUsed: "Used", conditionBroken: "For Parts", conditionRefurbished: "Refurbished", returnable: "Returnable", freeShipping: "Free Shipping", codAvailable: "Cash on Delivery", emiAvailable: "EMI Available", wishlistCount: (n) => `${n} wishlisted`, categoryProductCount: (n, cat) => `${n} in ${cat}` } }), (categoryName || category || brand) && (_jsxs(Row, { gap: "sm", wrap: true, children: [category && _jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(category)), className: "inline-flex items-center rounded-full border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-[var(--appkit-space-2-5)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)] font-medium text-[var(--appkit-color-text-muted)] transition-colors hover:border-primary-300 hover:bg-primary-50 hover:text-primary-700 dark:hover:border-primary-700/60 dark:hover:bg-primary-900/20 dark:hover:text-primary-400", children: categoryName || category }), !category && categoryName && _jsx(Span, { layout: "inline-flex", size: "xs", weight: "medium", border: "subtle", rounded: "full", padding: "pill-sm-tall", surface: "muted", color: "muted", children: categoryName }), brand && brandSlug && _jsx(Link, { href: String(ROUTES.PUBLIC.BRAND_DETAIL(brandSlug)), className: "inline-flex items-center rounded-full border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-[var(--appkit-space-2-5)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)] font-medium text-[var(--appkit-color-text-muted)] transition-colors hover:border-primary-300 hover:bg-primary-50 hover:text-primary-700 dark:hover:border-primary-700/60 dark:hover:bg-primary-900/20 dark:hover:text-primary-400", children: brand }), brand && !brandSlug && _jsx(Span, { layout: "inline-flex", size: "xs", weight: "medium", border: "subtle", rounded: "full", padding: "pill-sm-tall", surface: "muted", color: "muted", children: brand })] })), productFeatures && features.length > 0 && _jsx(FeatureBadgeList, { productFeatureIds: features, features: productFeatures }), !productFeatures && features.length > 0 && (_jsxs(Div, { border: "subtle", surface: "muted", padding: "inline", rounded: "xl", children: [_jsx(Text, { className: "mb-2 tracking-wide", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: "About this item" }), _jsx(Ul, { spacing: "comfortable", size: "sm", color: "primary", children: features.map((f, i) => _jsxs(Li, { layout: "flex-start", gap: "2", children: [_jsx(Span, { className: "mt-0.5 flex-shrink-0 text-primary-500", children: "\u2022" }), f] }, i)) })] })), descriptionHtml && _jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "text-[length:var(--appkit-text-sm)] leading-relaxed text-[var(--appkit-color-text-muted)] line-clamp-4" }), safeSeller && (_jsx(Div, { className: `${__P.p3}`, border: "subtle", rounded: "xl", surface: "muted", children: _jsxs(Row, { justify: "between", align: "center", children: [_jsxs(Div, { children: [_jsx(Text, { className: "text-[10px] tracking-wide mb-0.5", color: "faint", transform: "uppercase", children: "Listed by" }), _jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: safeSeller })] }), storeHref && _jsx(Link, { href: storeHref, className: "shrink-0 rounded-lg bg-primary/10 dark:bg-primary/20 px-[var(--appkit-space-3)] py-[var(--appkit-space-1-5)] text-[length:var(--appkit-text-xs)] font-semibold text-primary-700 dark:text-primary-300 hover:bg-primary/20 dark:hover:bg-primary/30 transition-colors", children: "Visit Store \u2192" })] }) }))] }));
|
|
45
52
|
}
|
|
46
53
|
function renderAuctionStoreReviews(storeReviews) {
|
|
47
54
|
if (storeReviews.length === 0)
|
|
@@ -78,7 +85,7 @@ export async function AuctionDetailPageView({ id, initialAuction, onPlaceBid, on
|
|
|
78
85
|
: typeof p.price === "number"
|
|
79
86
|
? p.price
|
|
80
87
|
: 0;
|
|
81
|
-
const
|
|
88
|
+
const minBidIncrementOverride = typeof p.minBidIncrement === "number" ? p.minBidIncrement : undefined;
|
|
82
89
|
const images = Array.isArray(p.images)
|
|
83
90
|
? p.images
|
|
84
91
|
: typeof p.mainImage === "string"
|
|
@@ -117,6 +124,13 @@ export async function AuctionDetailPageView({ id, initialAuction, onPlaceBid, on
|
|
|
117
124
|
const relatedDocs = await productRepository
|
|
118
125
|
.findByCategory(String(p.category ?? ""))
|
|
119
126
|
.catch(() => []);
|
|
127
|
+
const [{ relatedItems, relatedByBrand, relatedByTags, relatedByStore }, groups, siteSettings] = await Promise.all([
|
|
128
|
+
computeRelatedItems(product),
|
|
129
|
+
getGroupsWithItemsForProduct(product.id),
|
|
130
|
+
getSiteSettingsGlobal(),
|
|
131
|
+
]);
|
|
132
|
+
const bidIncrementTiers = siteSettings.auctionConfig?.bidIncrementTiers ?? [];
|
|
133
|
+
const initialMinBidIncrement = resolveMinBidIncrement(currentBid, bidIncrementTiers, minBidIncrementOverride);
|
|
120
134
|
return (_jsxs(Main, { children: [_jsx(HistoryTracker, { productId: String(p.id ?? p.slug ?? ""), productType: "auction", snapshot: {
|
|
121
135
|
title: typeof p.title === "string" ? p.title : undefined,
|
|
122
136
|
thumb: typeof p.mainImage === "string"
|
|
@@ -127,9 +141,9 @@ export async function AuctionDetailPageView({ id, initialAuction, onPlaceBid, on
|
|
|
127
141
|
price: typeof p.price === "number" ? p.price : undefined,
|
|
128
142
|
storeId: typeof p.storeId === "string" ? p.storeId : undefined,
|
|
129
143
|
storeName: typeof p.storeName === "string" ? p.storeName : undefined,
|
|
130
|
-
} }), _jsxs(Container, { size: "xl", padding: "y-lg", children: [_jsxs(Row, { className: "mb-4", align: "center", justify: "between", gap: "sm", wrap: true, children: [_jsxs(Nav, { "aria-label": "Breadcrumb", layout: "flex-wrap", gap: "2xs", textSize: "xs", color: "muted", children: [_jsx(Link, { href: String(ROUTES.HOME), className: CLS_BREADCRUMB_LINK, children: "Home" }), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.AUCTIONS), className: CLS_BREADCRUMB_LINK, children: "Auctions" }), category && (_jsxs(_Fragment, { children: [_jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(category)), className: CLS_BREADCRUMB_LINK, children: categoryName || category })] })), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Span, { className: "truncate max-w-[200px]", color: "muted", children: title })] }), _jsx(ShareButton, { title: title })] }), _jsx(AuctionDetailView, { renderGallery: () => (_jsx(ProductGalleryClient, { images: images, video: productVideo, productName: title })), renderInfo: () => renderAuctionInfoPanel({ productId: String(product.id), title, currentBid, currency, bidCount, isEnded, endDate, buyNowPrice, featured, freeShipping, condition, category, categoryName, brand, brandSlug, productFeatures, features, descriptionHtml, safeSeller, storeHref }), renderBidForm: () => onPlaceBid ? (_jsx(Stack, { id: "auction-bid-form", gap: "3", children: _jsxs(Stack, { className: `${__P.p5}`, border: "subtle", gap: "3", rounded: "xl", surface: "muted", children: [_jsxs(Row, { justify: "between", align: "baseline", children: [_jsx(LiveBidPrice, { productId: String(product.id), currentBid: currentBid, bidCount: bidCount, currency: currency, isEnded: isEnded, priceSize: "xl", badgeSize: "xs" }), !isEnded && (_jsxs(
|
|
144
|
+
} }), _jsxs(Container, { size: "xl", padding: "y-lg", children: [_jsxs(Row, { className: "mb-4", align: "center", justify: "between", gap: "sm", wrap: true, children: [_jsxs(Nav, { "aria-label": "Breadcrumb", layout: "flex-wrap", gap: "2xs", textSize: "xs", color: "muted", children: [_jsx(Link, { href: String(ROUTES.HOME), className: CLS_BREADCRUMB_LINK, children: "Home" }), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.AUCTIONS), className: CLS_BREADCRUMB_LINK, children: "Auctions" }), category && (_jsxs(_Fragment, { children: [_jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(category)), className: CLS_BREADCRUMB_LINK, children: categoryName || category })] })), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Span, { className: "truncate max-w-[200px]", color: "muted", children: title })] }), _jsx(ShareButton, { title: title })] }), _jsx(AuctionDetailView, { renderGallery: () => (_jsx(ProductGalleryClient, { images: images, video: productVideo, productName: title })), renderInfo: () => renderAuctionInfoPanel({ productId: String(product.id), title, currentBid, currency, bidCount, isEnded, endDate, buyNowPrice, featured, freeShipping, condition, category, categoryName, brand, brandSlug, productFeatures, features, descriptionHtml, safeSeller, storeHref }), renderBidForm: () => onPlaceBid ? (_jsx(Stack, { id: "auction-bid-form", gap: "3", children: _jsxs(Stack, { className: `${__P.p5}`, border: "subtle", gap: "3", rounded: "xl", surface: "muted", children: [_jsxs(Row, { justify: "between", align: "baseline", children: [_jsx(LiveBidPrice, { productId: String(product.id), currentBid: currentBid, bidCount: bidCount, currency: currency, isEnded: isEnded, priceSize: "xl", badgeSize: "xs" }), !isEnded && (_jsx(LiveMinIncrement, { productId: String(product.id), currentBid: currentBid, bidCount: bidCount, currency: currency, isEnded: isEnded, tiers: bidIncrementTiers, minBidIncrementOverride: minBidIncrementOverride }))] }), !isEnded && endDate && (_jsxs(Text, { align: "center", size: "xs", color: "muted", children: ["Ends in ", _jsx(CountdownDisplay, { targetDate: endDate, format: "auto", expiredLabel: "Ended" })] })), _jsx(PlaceBidModalButton, { productId: String(product.id), currentBid: currentBid, startingBid: startingBid, tiers: bidIncrementTiers, minBidIncrementOverride: minBidIncrementOverride, currency: currency, isEnded: isEnded, auctionEndDate: endDate, buyNowPrice: buyNowPrice, bidsHaveStarted: bidsHaveStarted, bidCount: bidCount, tags: tags, onPlaceBid: onPlaceBid, onBuyNow: onBuyNow, triggerClassName: "w-full" })] }) })) : (
|
|
131
145
|
/* Read-only bid panel — shown when no bid action is wired (preview/demo) */
|
|
132
|
-
_jsxs(Stack, { className: `${__P.p5}`, border: "subtle", gap: "md", rounded: "xl", surface: "muted", children: [_jsx(Stack, { gap: "xs", children: _jsxs(Text, { size: "xs", color: "muted", children: ["Starting bid: ", formatCurrency(startingBid, currency), !isEnded && _jsxs(_Fragment, { children: [" \u00B7 min increment ", formatCurrency(
|
|
146
|
+
_jsxs(Stack, { className: `${__P.p5}`, border: "subtle", gap: "md", rounded: "xl", surface: "muted", children: [_jsx(Stack, { gap: "xs", children: _jsxs(Text, { size: "xs", color: "muted", children: ["Starting bid: ", formatCurrency(startingBid, currency), !isEnded && _jsxs(_Fragment, { children: [" \u00B7 min increment ", formatCurrency(initialMinBidIncrement, currency)] })] }) }), _jsxs(Stack, { gap: "sm", children: [_jsx(Input, { type: "number", placeholder: `At least ${formatCurrency(currentBid + initialMinBidIncrement, currency)}`, min: currentBid + initialMinBidIncrement, "aria-label": "Your bid amount", disabled: isEnded }), !isEnded && endDate && (_jsxs(Text, { align: "center", size: "xs", color: "muted", children: ["Ends in ", _jsx(CountdownDisplay, { targetDate: endDate, format: "auto", expiredLabel: "Ended" })] })), _jsx(Button, { variant: "primary", size: "md", className: "w-full", disabled: isEnded, children: isEnded ? "Auction Ended" : "Place Bid" }), buyNowPrice !== null && !isEnded && !bidsHaveStarted && (_jsxs(Button, { variant: "secondary", size: "md", className: "w-full", disabled: true, children: ["Buy Now \u2014 ", formatCurrency(buyNowPrice, currency)] }))] }), tags.length > 0 && (_jsx(Div, { border: "default", className: "border-t", padding: "t-md", children: _jsx(Row, { wrap: true, gap: "xs", children: tags.map((tag) => (_jsx(Span, { size: "xs", rounded: "full", padding: "pill-sm-tall", surface: "subtle", color: "muted", children: tag }, tag))) }) }))] })), renderMobileBidForm: () => !isEnded && onPlaceBid ? (_jsxs(Stack, { className: `lg:hidden ${__P.p4}`, border: "subtle", gap: "3", rounded: "xl", surface: "muted", children: [_jsx(LiveBidPrice, { productId: String(product.id), currentBid: currentBid, bidCount: bidCount, currency: currency, isEnded: isEnded, priceSize: "base", badgeSize: "xs" }), endDate && (_jsxs(Text, { align: "center", size: "xs", color: "muted", children: ["Ends in ", _jsx(CountdownDisplay, { targetDate: endDate, format: "auto", expiredLabel: "Ended" })] })), _jsx(PlaceBidModalButton, { productId: String(product.id), currentBid: currentBid, startingBid: startingBid, tiers: bidIncrementTiers, minBidIncrementOverride: minBidIncrementOverride, currency: currency, isEnded: isEnded, auctionEndDate: endDate, buyNowPrice: buyNowPrice, bidsHaveStarted: bidsHaveStarted, bidCount: bidCount, tags: tags, onPlaceBid: onPlaceBid, onBuyNow: onBuyNow, triggerClassName: "w-full" })] })) : !isEnded ? (_jsxs(Div, { className: `${__P.p4} lg:hidden`, border: "subtle", rounded: "xl", surface: "muted", children: [_jsxs(Row, { align: "center", gap: "sm", className: "mb-3", children: [_jsx(Span, { size: "base", weight: "bold", className: "text-primary-600 dark:text-primary-400", children: formatCurrency(currentBid, currency) }), _jsxs(Span, { size: "xs", color: "muted", children: [bidCount, " bids"] })] }), endDate && (_jsxs(Text, { align: "center", className: "mb-3", size: "xs", color: "muted", children: ["Ends in ", _jsx(CountdownDisplay, { targetDate: endDate, format: "auto", expiredLabel: "Ended" })] })), _jsx(Button, { variant: "primary", size: "md", className: "w-full", children: "Place Bid" })] })) : null, renderSublistingSection: sublistingCategoryId
|
|
133
147
|
? () => (_jsx(SublistingCarouselSection, { sublistingCategoryId: sublistingCategoryId, currentListingId: String(product.id) }))
|
|
134
148
|
: undefined, renderTabs: () => (_jsx(ProductTabsShell, { descriptionContent: descriptionHtml ? (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm sm:prose max-w-none dark:prose-invert", className: "text-[var(--appkit-color-text-muted)]" })) : undefined, specsContent: specs.length > 0 ? (_jsx(Dl, { divide: "subtle", rounded: "xl", border: "subtle", className: "overflow-hidden", children: specs.map((s, i) => (_jsxs(Row, { gap: "md", oddEven: "zebra", surface: "default", padding: "inline", children: [_jsx(Dt, { className: "w-36 flex-shrink-0", color: "primary", weight: "medium", children: s.name }), _jsxs(Dd, { className: "flex-1", color: "muted", children: [s.value, s.unit ? ` ${s.unit}` : ""] })] }, i))) })) : undefined, customTabs: customSections.map((s) => ({
|
|
135
149
|
id: s.id,
|
|
@@ -176,8 +190,6 @@ export async function AuctionDetailPageView({ id, initialAuction, onPlaceBid, on
|
|
|
176
190
|
bidCount: typeof r.bidCount === "number" ? r.bidCount : undefined,
|
|
177
191
|
slug: typeof r.slug === "string" ? r.slug : undefined,
|
|
178
192
|
}));
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
return (_jsx(RelatedProducts, { labels: { title: "Similar Auctions" }, renderGrid: () => (_jsx(MarketplaceAuctionGrid, { auctions: related, gridClassName: "grid grid-cols-2 gap-[var(--appkit-space-4)] sm:grid-cols-3 lg:grid-cols-4" })) }));
|
|
182
|
-
} }), renderAuctionStoreReviews(storeReviews), _jsx(AuctionBottomActions, { currentBid: currentBid, currency: currency, bidCount: bidCount, isEnded: isEnded })] })] }));
|
|
193
|
+
return (_jsxs(Stack, { gap: "xl", children: [related.length > 0 && (_jsx(RelatedProducts, { labels: { title: "Similar Auctions" }, renderGrid: () => (_jsx(MarketplaceAuctionGrid, { auctions: related, gridClassName: "grid grid-cols-2 gap-[var(--appkit-space-4)] sm:grid-cols-3 lg:grid-cols-4" })) })), _jsx(GroupedListingsCarousel, { groups: groups }), _jsx(RelatedItemsSection, { relatedItems: relatedItems, relatedByBrand: relatedByBrand, relatedByTags: relatedByTags, relatedByStore: relatedByStore, categoryLabel: categoryName || category || undefined, brandLabel: brand || undefined, storeLabel: storeName || undefined })] }));
|
|
194
|
+
} }), renderAuctionStoreReviews(storeReviews), _jsx(AuctionBottomActions, { currentBid: currentBid, currency: currency, bidCount: bidCount, isEnded: isEnded, auctionEndDate: endDate })] })] }));
|
|
183
195
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type BidIncrementTier } from "../../../_internal/shared/features/auctions/config";
|
|
2
|
+
export interface LiveMinIncrementProps {
|
|
3
|
+
productId: string;
|
|
4
|
+
currentBid: number;
|
|
5
|
+
bidCount: number;
|
|
6
|
+
currency: string;
|
|
7
|
+
isEnded: boolean;
|
|
8
|
+
tiers: BidIncrementTier[];
|
|
9
|
+
minBidIncrementOverride?: number;
|
|
10
|
+
size?: "xs" | "sm";
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* LiveMinIncrement — the "min increment ₹X" text, kept live via the same
|
|
14
|
+
* `/auction-bids/{id}` SSE channel `LiveBidPrice` uses. The effective
|
|
15
|
+
* increment depends on the current bid amount (tiered), so it must keep
|
|
16
|
+
* resolving against the live current bid, not just the SSR snapshot.
|
|
17
|
+
*/
|
|
18
|
+
export declare function LiveMinIncrement({ productId, currentBid, bidCount, currency, isEnded, tiers, minBidIncrementOverride, size, }: LiveMinIncrementProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Span } from "../../../ui";
|
|
4
|
+
import { formatCurrency } from "../../../utils/number.formatter";
|
|
5
|
+
import { useLiveAuctionBid } from "../hooks/useLiveAuctionBid";
|
|
6
|
+
import { resolveMinBidIncrement, } from "../../../_internal/shared/features/auctions/config";
|
|
7
|
+
/**
|
|
8
|
+
* LiveMinIncrement — the "min increment ₹X" text, kept live via the same
|
|
9
|
+
* `/auction-bids/{id}` SSE channel `LiveBidPrice` uses. The effective
|
|
10
|
+
* increment depends on the current bid amount (tiered), so it must keep
|
|
11
|
+
* resolving against the live current bid, not just the SSR snapshot.
|
|
12
|
+
*/
|
|
13
|
+
export function LiveMinIncrement({ productId, currentBid, bidCount, currency, isEnded, tiers, minBidIncrementOverride, size = "xs", }) {
|
|
14
|
+
const live = useLiveAuctionBid(productId, currentBid, bidCount, { enabled: !isEnded });
|
|
15
|
+
const increment = resolveMinBidIncrement(live.currentBid, tiers, minBidIncrementOverride);
|
|
16
|
+
return (_jsxs(Span, { size: size, color: "muted", children: ["min increment ", formatCurrency(increment, currency)] }));
|
|
17
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { type BidIncrementTier } from "../../../_internal/shared/features/auctions/config";
|
|
2
3
|
export interface PlaceBidInput {
|
|
3
4
|
productId: string;
|
|
4
5
|
bidAmount: number;
|
|
@@ -8,9 +9,11 @@ export interface PlaceBidFormClientProps {
|
|
|
8
9
|
productId: string;
|
|
9
10
|
currentBid: number;
|
|
10
11
|
startingBid: number;
|
|
11
|
-
|
|
12
|
+
tiers: BidIncrementTier[];
|
|
13
|
+
minBidIncrementOverride?: number;
|
|
12
14
|
currency: string;
|
|
13
15
|
isEnded: boolean;
|
|
16
|
+
auctionEndDate: Date | null;
|
|
14
17
|
buyNowPrice: number | null;
|
|
15
18
|
bidsHaveStarted?: boolean;
|
|
16
19
|
bidCount: number;
|
|
@@ -18,7 +21,7 @@ export interface PlaceBidFormClientProps {
|
|
|
18
21
|
onPlaceBid: (input: PlaceBidInput) => Promise<unknown>;
|
|
19
22
|
onBuyNow?: () => Promise<unknown>;
|
|
20
23
|
}
|
|
21
|
-
export declare function PlaceBidFormClient({ productId, currentBid: ssrCurrentBid, startingBid,
|
|
24
|
+
export declare function PlaceBidFormClient({ productId, currentBid: ssrCurrentBid, startingBid, tiers, minBidIncrementOverride, currency, isEnded, auctionEndDate, buyNowPrice, bidsHaveStarted, bidCount: ssrBidCount, tags, onPlaceBid, onBuyNow, }: PlaceBidFormClientProps): React.JSX.Element;
|
|
22
25
|
/**
|
|
23
26
|
* `PlaceBidModalButton` — opens a modal that hosts the same PlaceBidFormClient.
|
|
24
27
|
*
|
|
@@ -4,12 +4,13 @@ import { useState, useTransition } from "react";
|
|
|
4
4
|
import { useRouter } from "next/navigation";
|
|
5
5
|
import { formatCurrency } from "../../../utils/number.formatter";
|
|
6
6
|
import { isAuthError } from "../../../utils/auth-error";
|
|
7
|
-
import { Button, Div, LoginRequiredModal, Modal, Row, Span, Stack, Text } from "../../../ui";
|
|
7
|
+
import { Button, CountdownDisplay, Div, LoginRequiredModal, Modal, Row, Span, Stack, Text } from "../../../ui";
|
|
8
8
|
import { Form } from "../../../ui/components/Form";
|
|
9
9
|
import { FieldInput } from "../../../ui/forms/FieldInput";
|
|
10
10
|
import { applyZodIssues } from "../../../ui/forms/FormShell";
|
|
11
11
|
import { placeBidSchema } from "../schemas/bid-input";
|
|
12
12
|
import { useLiveAuctionBid } from "../hooks/useLiveAuctionBid";
|
|
13
|
+
import { resolveMinBidIncrement, } from "../../../_internal/shared/features/auctions/config";
|
|
13
14
|
import { normalizeError } from "../../../errors/normalize";
|
|
14
15
|
const __P = {
|
|
15
16
|
p5: "p-[var(--appkit-space-5)]",
|
|
@@ -21,13 +22,16 @@ const BID_ERROR_DISPLAY = {
|
|
|
21
22
|
BID_SELF_BID: "You cannot bid on your own listing.",
|
|
22
23
|
BID_USER_BANNED: "Your account is currently restricted from bidding. Contact support.",
|
|
23
24
|
};
|
|
24
|
-
export function PlaceBidFormClient({ productId, currentBid: ssrCurrentBid, startingBid,
|
|
25
|
+
export function PlaceBidFormClient({ productId, currentBid: ssrCurrentBid, startingBid, tiers, minBidIncrementOverride, currency, isEnded, auctionEndDate, buyNowPrice, bidsHaveStarted = false, bidCount: ssrBidCount, tags = [], onPlaceBid, onBuyNow, }) {
|
|
25
26
|
const router = useRouter();
|
|
26
27
|
// Live-updates while the bid card is open — reflects other bidders'
|
|
27
28
|
// activity on this auction, not just the bidder's own submission.
|
|
28
29
|
const live = useLiveAuctionBid(productId, ssrCurrentBid, ssrBidCount, { enabled: !isEnded });
|
|
29
30
|
const currentBid = live.currentBid;
|
|
30
31
|
const bidCount = live.bidCount;
|
|
32
|
+
// Tiered, floor-raising: resolves fresh whenever the live current bid
|
|
33
|
+
// crosses a tier boundary while this modal is open.
|
|
34
|
+
const minBidIncrement = resolveMinBidIncrement(currentBid, tiers, minBidIncrementOverride);
|
|
31
35
|
const minBid = currentBid + minBidIncrement;
|
|
32
36
|
const [bidAmount, setBidAmount] = useState(String(minBid));
|
|
33
37
|
const [stepMul, setStepMul] = useState(1);
|
|
@@ -110,7 +114,7 @@ export function PlaceBidFormClient({ productId, currentBid: ssrCurrentBid, start
|
|
|
110
114
|
}, children: ["+", formatCurrency(minBidIncrement * n, currency)] }, n))), _jsx(Button, { type: "button", variant: stepMul === "custom" ? "primary" : "ghost", size: "sm", role: "radio", "aria-checked": stepMul === "custom", disabled: isEnded || isPending, onClick: () => setStepMul("custom"), children: "Custom" })] }), _jsx(FieldInput, { name: "bidAmount", type: "number", value: bidAmount, readOnly: stepMul !== "custom", onChange: (value) => {
|
|
111
115
|
setBidAmount(value);
|
|
112
116
|
clearErrors();
|
|
113
|
-
}, placeholder: `At least ${formatCurrency(minBid, currency)}`, min: minBid, "aria-label": "Your bid amount", disabled: isEnded || isPending }), stepMul === "custom" && (_jsxs(Text, { size: "xs", color: "muted", "aria-live": "polite", children: ["Any amount \u2265 ", formatCurrency(minBid, currency), " is accepted."] })), success && (_jsx(Text, { className: "text-success", size: "xs", children: "\u2713 Bid placed successfully!" })), _jsx(Button, { variant: "primary", size: "md", className: "w-full", disabled: isEnded || isPending, isLoading: isPending, type: "button", onClick: () => {
|
|
117
|
+
}, placeholder: `At least ${formatCurrency(minBid, currency)}`, min: minBid, "aria-label": "Your bid amount", disabled: isEnded || isPending }), stepMul === "custom" && (_jsxs(Text, { size: "xs", color: "muted", "aria-live": "polite", children: ["Any amount \u2265 ", formatCurrency(minBid, currency), " is accepted."] })), success && (_jsx(Text, { className: "text-success", size: "xs", children: "\u2713 Bid placed successfully!" })), !isEnded && auctionEndDate && (_jsxs(Text, { align: "center", size: "xs", color: "muted", children: ["Ends in ", _jsx(CountdownDisplay, { targetDate: auctionEndDate, format: "auto", expiredLabel: "Ended" })] })), _jsx(Button, { variant: "primary", size: "md", className: "w-full", disabled: isEnded || isPending, isLoading: isPending, type: "button", onClick: () => {
|
|
114
118
|
clearErrors();
|
|
115
119
|
const parsed = schema.safeParse({ bidAmount });
|
|
116
120
|
if (!parsed.success)
|
|
@@ -28,6 +28,7 @@ export declare const auctionItemSchema: z.ZodObject<{
|
|
|
28
28
|
thumbnailUrl: z.ZodOptional<z.ZodString>;
|
|
29
29
|
source: z.ZodOptional<z.ZodEnum<["upload", "youtube", "external"]>>;
|
|
30
30
|
youtubeId: z.ZodOptional<z.ZodString>;
|
|
31
|
+
duration: z.ZodOptional<z.ZodNumber>;
|
|
31
32
|
}, "strip", z.ZodTypeAny, {
|
|
32
33
|
type: "video" | "image" | "file";
|
|
33
34
|
url: string;
|
|
@@ -35,6 +36,7 @@ export declare const auctionItemSchema: z.ZodObject<{
|
|
|
35
36
|
alt?: string | undefined;
|
|
36
37
|
thumbnailUrl?: string | undefined;
|
|
37
38
|
youtubeId?: string | undefined;
|
|
39
|
+
duration?: number | undefined;
|
|
38
40
|
}, {
|
|
39
41
|
type: "video" | "image" | "file";
|
|
40
42
|
url: string;
|
|
@@ -42,6 +44,7 @@ export declare const auctionItemSchema: z.ZodObject<{
|
|
|
42
44
|
alt?: string | undefined;
|
|
43
45
|
thumbnailUrl?: string | undefined;
|
|
44
46
|
youtubeId?: string | undefined;
|
|
47
|
+
duration?: number | undefined;
|
|
45
48
|
}>, "many">>;
|
|
46
49
|
currency: z.ZodString;
|
|
47
50
|
price: z.ZodNumber;
|
|
@@ -84,6 +87,7 @@ export declare const auctionItemSchema: z.ZodObject<{
|
|
|
84
87
|
alt?: string | undefined;
|
|
85
88
|
thumbnailUrl?: string | undefined;
|
|
86
89
|
youtubeId?: string | undefined;
|
|
90
|
+
duration?: number | undefined;
|
|
87
91
|
}[] | undefined;
|
|
88
92
|
storeSlug?: string | undefined;
|
|
89
93
|
}, {
|
|
@@ -113,6 +117,7 @@ export declare const auctionItemSchema: z.ZodObject<{
|
|
|
113
117
|
alt?: string | undefined;
|
|
114
118
|
thumbnailUrl?: string | undefined;
|
|
115
119
|
youtubeId?: string | undefined;
|
|
120
|
+
duration?: number | undefined;
|
|
116
121
|
}[] | undefined;
|
|
117
122
|
storeSlug?: string | undefined;
|
|
118
123
|
}>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AdminAuditLogRepository — thin wrapper over the `adminAuditLog` collection.
|
|
3
|
+
* See `appkit/src/features/audit-log/schemas/firestore.ts` for the doc shape.
|
|
4
|
+
*/
|
|
5
|
+
import { BaseRepository, parseSieveDateValue, type SieveModel, type FirebaseSieveResult } from "../../../providers/db-firebase";
|
|
6
|
+
import { type AdminAuditLogDocument } from "../schemas/firestore";
|
|
7
|
+
export declare class AdminAuditLogRepository extends BaseRepository<AdminAuditLogDocument> {
|
|
8
|
+
constructor();
|
|
9
|
+
static readonly SIEVE_FIELDS: {
|
|
10
|
+
id: {
|
|
11
|
+
canFilter: boolean;
|
|
12
|
+
canSort: boolean;
|
|
13
|
+
};
|
|
14
|
+
actorUid: {
|
|
15
|
+
canFilter: boolean;
|
|
16
|
+
canSort: boolean;
|
|
17
|
+
};
|
|
18
|
+
actorName: {
|
|
19
|
+
canFilter: boolean;
|
|
20
|
+
canSort: boolean;
|
|
21
|
+
};
|
|
22
|
+
action: {
|
|
23
|
+
canFilter: boolean;
|
|
24
|
+
canSort: boolean;
|
|
25
|
+
};
|
|
26
|
+
targetType: {
|
|
27
|
+
canFilter: boolean;
|
|
28
|
+
canSort: boolean;
|
|
29
|
+
};
|
|
30
|
+
targetId: {
|
|
31
|
+
canFilter: boolean;
|
|
32
|
+
canSort: boolean;
|
|
33
|
+
};
|
|
34
|
+
createdAt: {
|
|
35
|
+
canFilter: boolean;
|
|
36
|
+
canSort: boolean;
|
|
37
|
+
parseValue: typeof parseSieveDateValue;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Paginated, Firestore-native audit-log list (admin use).
|
|
42
|
+
*/
|
|
43
|
+
list(model: SieveModel): Promise<FirebaseSieveResult<AdminAuditLogDocument>>;
|
|
44
|
+
}
|
|
45
|
+
export declare const adminAuditLogRepository: AdminAuditLogRepository;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AdminAuditLogRepository — thin wrapper over the `adminAuditLog` collection.
|
|
3
|
+
* See `appkit/src/features/audit-log/schemas/firestore.ts` for the doc shape.
|
|
4
|
+
*/
|
|
5
|
+
import { BaseRepository, parseSieveDateValue, } from "../../../providers/db-firebase";
|
|
6
|
+
import { ADMIN_AUDIT_LOG_COLLECTION } from "../schemas/firestore";
|
|
7
|
+
export class AdminAuditLogRepository extends BaseRepository {
|
|
8
|
+
constructor() {
|
|
9
|
+
super(ADMIN_AUDIT_LOG_COLLECTION);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Paginated, Firestore-native audit-log list (admin use).
|
|
13
|
+
*/
|
|
14
|
+
async list(model) {
|
|
15
|
+
return this.sieveQuery(model, AdminAuditLogRepository.SIEVE_FIELDS, {
|
|
16
|
+
defaultPageSize: 50,
|
|
17
|
+
maxPageSize: 200,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
AdminAuditLogRepository.SIEVE_FIELDS = {
|
|
22
|
+
id: { canFilter: true, canSort: false },
|
|
23
|
+
actorUid: { canFilter: true, canSort: false },
|
|
24
|
+
actorName: { canFilter: true, canSort: false },
|
|
25
|
+
action: { canFilter: true, canSort: true },
|
|
26
|
+
targetType: { canFilter: true, canSort: false },
|
|
27
|
+
targetId: { canFilter: true, canSort: false },
|
|
28
|
+
createdAt: { canFilter: true, canSort: true, parseValue: parseSieveDateValue },
|
|
29
|
+
};
|
|
30
|
+
export const adminAuditLogRepository = new AdminAuditLogRepository();
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin Audit Log Firestore Document Types & Constants
|
|
3
|
+
*
|
|
4
|
+
* Collection: adminAuditLog
|
|
5
|
+
* Document ID: Firestore auto-ID (no slug prefix — see CLAUDE.md "True
|
|
6
|
+
* Firestore auto-IDs" list, same convention as `notifications`/`sessions`/`jobs`).
|
|
7
|
+
*
|
|
8
|
+
* A queryable record of high-value privileged admin actions — bans, checkout
|
|
9
|
+
* bypass, coupon edits, payout mark-paid, store status changes, role changes.
|
|
10
|
+
* This is deliberately an MVP scope (instrumenting existing high-value call
|
|
11
|
+
* sites), not an exhaustive every-write-path audit trail — see CLAUDE.md's
|
|
12
|
+
* "Admin Audit Log" section for the full instrumented-action list.
|
|
13
|
+
*/
|
|
14
|
+
import type { BaseDocument } from "../../../_internal/shared/types/base-document";
|
|
15
|
+
import type { JsonValue } from "../../../schemas/types";
|
|
16
|
+
export declare const ADMIN_AUDIT_LOG_COLLECTION = "adminAuditLog";
|
|
17
|
+
export declare const AdminAuditActionValues: {
|
|
18
|
+
readonly USER_HARD_BAN: "user_hard_ban";
|
|
19
|
+
readonly USER_SOFT_BAN: "user_soft_ban";
|
|
20
|
+
readonly USER_UNBAN: "user_unban";
|
|
21
|
+
readonly CHECKOUT_BYPASS: "checkout_bypass";
|
|
22
|
+
readonly COUPON_UPDATE: "coupon_update";
|
|
23
|
+
readonly PAYOUT_MARK_PAID: "payout_mark_paid";
|
|
24
|
+
readonly STORE_STATUS_CHANGE: "store_status_change";
|
|
25
|
+
readonly USER_ROLE_CHANGE: "user_role_change";
|
|
26
|
+
};
|
|
27
|
+
export type AdminAuditAction = (typeof AdminAuditActionValues)[keyof typeof AdminAuditActionValues];
|
|
28
|
+
export interface AdminAuditLogDocument extends BaseDocument {
|
|
29
|
+
actorUid: string;
|
|
30
|
+
actorName?: string;
|
|
31
|
+
action: AdminAuditAction;
|
|
32
|
+
/** e.g. "user" | "store" | "coupon" | "payout" — the kind of entity affected. */
|
|
33
|
+
targetType: string;
|
|
34
|
+
targetId: string;
|
|
35
|
+
/** Denormalized human-readable label (display name, coupon code, etc.) so the log list never needs a join. */
|
|
36
|
+
targetLabel?: string;
|
|
37
|
+
reason?: string;
|
|
38
|
+
metadata?: Record<string, JsonValue>;
|
|
39
|
+
}
|
|
40
|
+
export declare const ADMIN_AUDIT_LOG_FIELDS: {
|
|
41
|
+
readonly ACTOR_UID: "actorUid";
|
|
42
|
+
readonly ACTOR_NAME: "actorName";
|
|
43
|
+
readonly ACTION: "action";
|
|
44
|
+
readonly TARGET_TYPE: "targetType";
|
|
45
|
+
readonly TARGET_ID: "targetId";
|
|
46
|
+
readonly TARGET_LABEL: "targetLabel";
|
|
47
|
+
readonly REASON: "reason";
|
|
48
|
+
readonly CREATED_AT: "createdAt";
|
|
49
|
+
readonly ACTION_VALUES: {
|
|
50
|
+
readonly USER_HARD_BAN: "user_hard_ban";
|
|
51
|
+
readonly USER_SOFT_BAN: "user_soft_ban";
|
|
52
|
+
readonly USER_UNBAN: "user_unban";
|
|
53
|
+
readonly CHECKOUT_BYPASS: "checkout_bypass";
|
|
54
|
+
readonly COUPON_UPDATE: "coupon_update";
|
|
55
|
+
readonly PAYOUT_MARK_PAID: "payout_mark_paid";
|
|
56
|
+
readonly STORE_STATUS_CHANGE: "store_status_change";
|
|
57
|
+
readonly USER_ROLE_CHANGE: "user_role_change";
|
|
58
|
+
};
|
|
59
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin Audit Log Firestore Document Types & Constants
|
|
3
|
+
*
|
|
4
|
+
* Collection: adminAuditLog
|
|
5
|
+
* Document ID: Firestore auto-ID (no slug prefix — see CLAUDE.md "True
|
|
6
|
+
* Firestore auto-IDs" list, same convention as `notifications`/`sessions`/`jobs`).
|
|
7
|
+
*
|
|
8
|
+
* A queryable record of high-value privileged admin actions — bans, checkout
|
|
9
|
+
* bypass, coupon edits, payout mark-paid, store status changes, role changes.
|
|
10
|
+
* This is deliberately an MVP scope (instrumenting existing high-value call
|
|
11
|
+
* sites), not an exhaustive every-write-path audit trail — see CLAUDE.md's
|
|
12
|
+
* "Admin Audit Log" section for the full instrumented-action list.
|
|
13
|
+
*/
|
|
14
|
+
export const ADMIN_AUDIT_LOG_COLLECTION = "adminAuditLog";
|
|
15
|
+
export const AdminAuditActionValues = {
|
|
16
|
+
USER_HARD_BAN: "user_hard_ban",
|
|
17
|
+
USER_SOFT_BAN: "user_soft_ban",
|
|
18
|
+
USER_UNBAN: "user_unban",
|
|
19
|
+
CHECKOUT_BYPASS: "checkout_bypass",
|
|
20
|
+
COUPON_UPDATE: "coupon_update",
|
|
21
|
+
PAYOUT_MARK_PAID: "payout_mark_paid",
|
|
22
|
+
STORE_STATUS_CHANGE: "store_status_change",
|
|
23
|
+
USER_ROLE_CHANGE: "user_role_change",
|
|
24
|
+
};
|
|
25
|
+
export const ADMIN_AUDIT_LOG_FIELDS = {
|
|
26
|
+
ACTOR_UID: "actorUid",
|
|
27
|
+
ACTOR_NAME: "actorName",
|
|
28
|
+
ACTION: "action",
|
|
29
|
+
TARGET_TYPE: "targetType",
|
|
30
|
+
TARGET_ID: "targetId",
|
|
31
|
+
TARGET_LABEL: "targetLabel",
|
|
32
|
+
REASON: "reason",
|
|
33
|
+
CREATED_AT: "createdAt",
|
|
34
|
+
ACTION_VALUES: AdminAuditActionValues,
|
|
35
|
+
};
|
|
@@ -21,10 +21,6 @@ export interface RegisterData {
|
|
|
21
21
|
displayName?: string;
|
|
22
22
|
acceptTerms: boolean;
|
|
23
23
|
}
|
|
24
|
-
export interface ChangePasswordData {
|
|
25
|
-
currentPassword: string;
|
|
26
|
-
newPassword: string;
|
|
27
|
-
}
|
|
28
24
|
export interface ChangeEmailData {
|
|
29
25
|
currentPassword: string;
|
|
30
26
|
newEmail: string;
|
|
@@ -91,38 +87,15 @@ export declare function useResetPassword(options?: {
|
|
|
91
87
|
onError?: (error: Error) => void;
|
|
92
88
|
}): import("@tanstack/react-query").UseMutationResult<JsonValue, Error, ResetPasswordData, unknown>;
|
|
93
89
|
/**
|
|
94
|
-
* Password change is
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* session cookie
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
* 2. useVerifyPasswordChangeOtp — verifies the code server-side.
|
|
103
|
-
* 3. useChangePassword — only now actually applies newPassword; the API
|
|
104
|
-
* route rejects this call unless step 2 already succeeded.
|
|
90
|
+
* Password change is Firebase-only (no custom OTP code, no Resend) — the
|
|
91
|
+
* "Change Password" settings action sends the exact same reset-link email
|
|
92
|
+
* as "Forgot Password" (see useForgotPassword above), to the signed-in
|
|
93
|
+
* user's own address. Completing the link requires access to that inbox,
|
|
94
|
+
* which a stolen session cookie alone can't provide — closing the same gap
|
|
95
|
+
* the older OTP-code system existed for, through inbox possession instead
|
|
96
|
+
* of a typed code. There is no separate hook for this: consumers call
|
|
97
|
+
* useForgotPassword({ email: user.email }) directly from the settings page.
|
|
105
98
|
*/
|
|
106
|
-
export declare function useRequestPasswordChangeOtp(options?: {
|
|
107
|
-
onSuccess?: (data: {
|
|
108
|
-
maskedEmail: string;
|
|
109
|
-
}) => void;
|
|
110
|
-
onError?: (error: Error) => void;
|
|
111
|
-
}): import("@tanstack/react-query").UseMutationResult<{
|
|
112
|
-
maskedEmail: string;
|
|
113
|
-
}, Error, {
|
|
114
|
-
currentPassword: string;
|
|
115
|
-
}, unknown>;
|
|
116
|
-
export declare function useVerifyPasswordChangeOtp(options?: {
|
|
117
|
-
onSuccess?: (data: JsonValue) => void;
|
|
118
|
-
onError?: (error: Error) => void;
|
|
119
|
-
}): import("@tanstack/react-query").UseMutationResult<JsonValue, Error, {
|
|
120
|
-
code: string;
|
|
121
|
-
}, unknown>;
|
|
122
|
-
export declare function useChangePassword(options?: {
|
|
123
|
-
onSuccess?: (data: JsonValue) => void;
|
|
124
|
-
onError?: (error: Error) => void;
|
|
125
|
-
}): import("@tanstack/react-query").UseMutationResult<JsonValue, Error, ChangePasswordData, unknown>;
|
|
126
99
|
export declare function useChangeEmail(options?: {
|
|
127
100
|
onSuccess?: (data: JsonValue) => void;
|
|
128
101
|
onError?: (error: Error) => void;
|
|
@@ -7,7 +7,7 @@ import { getClientSessionAdapter } from "../../../contracts/client-session";
|
|
|
7
7
|
import { apiClient } from "../../../http";
|
|
8
8
|
import { useAuthEvent } from "./useAuthEvent";
|
|
9
9
|
import { RealtimeEventStatus } from "../../../react/hooks/useRealtimeEvent";
|
|
10
|
-
import { AUTH_ENDPOINTS,
|
|
10
|
+
import { AUTH_ENDPOINTS, } from "../../../constants/api-endpoints";
|
|
11
11
|
export function useCurrentUser(opts) {
|
|
12
12
|
const query = useQuery({
|
|
13
13
|
queryKey: ["auth", "me"],
|
|
@@ -307,7 +307,18 @@ export function useRegister(options) {
|
|
|
307
307
|
// `auth.currentUser` is populated for client-side Firebase usage
|
|
308
308
|
// (RTDB presence, etc) — do NOT call /api/auth/session again here,
|
|
309
309
|
// that would create a second, orphaned session document.
|
|
310
|
-
|
|
310
|
+
const authProvider = getClientAuthProvider();
|
|
311
|
+
await authProvider.signInWithEmailAndPassword(data.email.trim(), data.password);
|
|
312
|
+
// Verification email is Firebase-native only (no Resend) — see project
|
|
313
|
+
// policy on "profile related auth changes". Deliberately non-fatal:
|
|
314
|
+
// the account already exists at this point, so a send failure must not
|
|
315
|
+
// fail registration — the user can re-request verification later.
|
|
316
|
+
try {
|
|
317
|
+
await authProvider.sendEmailVerification();
|
|
318
|
+
}
|
|
319
|
+
catch (err) {
|
|
320
|
+
void normalizeError(err);
|
|
321
|
+
}
|
|
311
322
|
return { success: true, ...response };
|
|
312
323
|
},
|
|
313
324
|
onSuccess: options?.onSuccess,
|
|
@@ -354,42 +365,15 @@ export function useResetPassword(options) {
|
|
|
354
365
|
});
|
|
355
366
|
}
|
|
356
367
|
/**
|
|
357
|
-
* Password change is
|
|
358
|
-
*
|
|
359
|
-
*
|
|
360
|
-
*
|
|
361
|
-
* session cookie
|
|
362
|
-
*
|
|
363
|
-
*
|
|
364
|
-
*
|
|
365
|
-
* 2. useVerifyPasswordChangeOtp — verifies the code server-side.
|
|
366
|
-
* 3. useChangePassword — only now actually applies newPassword; the API
|
|
367
|
-
* route rejects this call unless step 2 already succeeded.
|
|
368
|
+
* Password change is Firebase-only (no custom OTP code, no Resend) — the
|
|
369
|
+
* "Change Password" settings action sends the exact same reset-link email
|
|
370
|
+
* as "Forgot Password" (see useForgotPassword above), to the signed-in
|
|
371
|
+
* user's own address. Completing the link requires access to that inbox,
|
|
372
|
+
* which a stolen session cookie alone can't provide — closing the same gap
|
|
373
|
+
* the older OTP-code system existed for, through inbox possession instead
|
|
374
|
+
* of a typed code. There is no separate hook for this: consumers call
|
|
375
|
+
* useForgotPassword({ email: user.email }) directly from the settings page.
|
|
368
376
|
*/
|
|
369
|
-
export function useRequestPasswordChangeOtp(options) {
|
|
370
|
-
return useMutation({
|
|
371
|
-
mutationFn: async ({ currentPassword }) => {
|
|
372
|
-
await getClientAuthProvider().reauthenticateOnly(currentPassword);
|
|
373
|
-
return apiClient.post(ACCOUNT_ENDPOINTS.CHANGE_PASSWORD_OTP_REQUEST, {});
|
|
374
|
-
},
|
|
375
|
-
onSuccess: options?.onSuccess,
|
|
376
|
-
onError: options?.onError,
|
|
377
|
-
});
|
|
378
|
-
}
|
|
379
|
-
export function useVerifyPasswordChangeOtp(options) {
|
|
380
|
-
return useMutation({
|
|
381
|
-
mutationFn: async ({ code }) => apiClient.post(ACCOUNT_ENDPOINTS.CHANGE_PASSWORD_OTP_VERIFY, { code }),
|
|
382
|
-
onSuccess: options?.onSuccess,
|
|
383
|
-
onError: options?.onError,
|
|
384
|
-
});
|
|
385
|
-
}
|
|
386
|
-
export function useChangePassword(options) {
|
|
387
|
-
return useMutation({
|
|
388
|
-
mutationFn: async (data) => apiClient.post(ACCOUNT_ENDPOINTS.CHANGE_PASSWORD, data),
|
|
389
|
-
onSuccess: options?.onSuccess,
|
|
390
|
-
onError: options?.onError,
|
|
391
|
-
});
|
|
392
|
-
}
|
|
393
377
|
export function useChangeEmail(options) {
|
|
394
378
|
return useMutation({
|
|
395
379
|
mutationFn: async (data) => {
|