@mohasinac/appkit 2.8.2 → 2.8.4
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/classified/ClassifiedDetailView.js +7 -1
- package/dist/_internal/client/features/digital-code/CodeRevealPanel.js +4 -1
- package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.js +7 -1
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +3 -2
- package/dist/_internal/client/features/live/LiveItemDetailView.js +11 -2
- package/dist/_internal/client/scaffolds/AppShell.js +2 -1
- package/dist/_internal/client/scaffolds/DashboardScaffold.js +2 -1
- package/dist/_internal/server/features/checkout/actions.js +40 -39
- package/dist/_internal/shared/actions/action-registry.js +6 -0
- package/dist/_internal/shared/config/index.d.ts +1 -1
- package/dist/_internal/shared/config/schema.d.ts +0 -8
- package/dist/client-entry.d.ts +1 -1
- package/dist/client.d.ts +3 -1
- package/dist/client.js +3 -1
- package/dist/configs/next.js +12 -22
- package/dist/constants/api-endpoints.d.ts +6 -0
- package/dist/constants/api-endpoints.js +2 -0
- package/dist/features/about/components/AboutView.js +5 -2
- package/dist/features/about/components/FAQPageView.js +3 -3
- package/dist/features/about/components/FeesView.js +13 -5
- package/dist/features/about/components/HelpPageView.js +9 -5
- package/dist/features/about/components/HowAuctionsWorkView.js +9 -5
- package/dist/features/about/components/HowCheckoutWorksView.js +9 -5
- package/dist/features/about/components/HowOffersWorkView.js +10 -5
- package/dist/features/about/components/HowOrdersWorkView.js +10 -5
- package/dist/features/about/components/HowPayoutsWorkView.js +9 -5
- package/dist/features/about/components/HowPreOrdersWorkView.js +9 -5
- package/dist/features/about/components/HowReviewsWorkView.js +9 -5
- package/dist/features/about/components/PolicyPageView.js +3 -3
- package/dist/features/about/components/PublicProfileView.js +11 -4
- package/dist/features/about/components/SecurityPrivacyView.js +8 -4
- package/dist/features/about/components/ShippingPolicyView.js +3 -2
- package/dist/features/about/components/TrackOrderView.js +2 -2
- package/dist/features/about/components/UnauthorizedView.js +3 -3
- package/dist/features/account/components/AddressBook.js +1 -1
- package/dist/features/account/components/AddressForm.js +2 -2
- package/dist/features/account/components/AddressInlineSelect.d.ts +24 -0
- package/dist/features/account/components/AddressInlineSelect.js +78 -0
- package/dist/features/account/components/AddressSelectorCreate.d.ts +2 -1
- package/dist/features/account/components/AddressSelectorCreate.js +5 -32
- package/dist/features/account/components/AddressesIndexListing.js +3 -3
- package/dist/features/account/components/ChatWindow.js +2 -1
- package/dist/features/account/components/NotificationBell.js +13 -7
- package/dist/features/account/components/NotificationPreferencesPanel.js +4 -1
- package/dist/features/account/components/UserOffersPanel.js +2 -1
- package/dist/features/account/components/UserSidebar.js +11 -7
- package/dist/features/account/components/UserSupportView.js +13 -4
- package/dist/features/account/components/index.d.ts +2 -0
- package/dist/features/account/components/index.js +1 -0
- package/dist/features/addresses/repository/addresses.repository.d.ts +1 -0
- package/dist/features/addresses/repository/addresses.repository.js +13 -0
- package/dist/features/admin/components/AdminAdEditorView.js +8 -5
- package/dist/features/admin/components/AdminAddressEditorView.js +5 -5
- package/dist/features/admin/components/AdminAdsView.js +10 -7
- package/dist/features/admin/components/AdminAllEventEntriesView.js +5 -3
- package/dist/features/admin/components/AdminBidsView.js +6 -4
- package/dist/features/admin/components/AdminBlogEditorView.js +15 -9
- package/dist/features/admin/components/AdminBlogView.js +6 -4
- package/dist/features/admin/components/AdminBrandEditorView.js +10 -4
- package/dist/features/admin/components/AdminBrandsView.js +12 -10
- package/dist/features/admin/components/AdminBundleEditorView.js +4 -5
- package/dist/features/admin/components/AdminBundlesView.js +13 -11
- package/dist/features/admin/components/AdminCarouselEditorView.js +6 -3
- package/dist/features/admin/components/AdminCarouselView.js +6 -6
- package/dist/features/admin/components/AdminCartsView.js +6 -4
- package/dist/features/admin/components/AdminCatalogGuideView.js +2 -1
- package/dist/features/admin/components/AdminCategoriesView.js +12 -10
- package/dist/features/admin/components/AdminCategoryEditorView.js +11 -5
- package/dist/features/admin/components/AdminClassifiedView.js +4 -3
- package/dist/features/admin/components/AdminContactEditorView.js +8 -1
- package/dist/features/admin/components/AdminContactView.js +6 -4
- package/dist/features/admin/components/AdminCouponEditorView.js +23 -5
- package/dist/features/admin/components/AdminCouponsView.js +6 -4
- package/dist/features/admin/components/AdminDigitalCodesView.js +4 -3
- package/dist/features/admin/components/AdminEmployeeEditorView.js +7 -4
- package/dist/features/admin/components/AdminFaqEditorView.js +9 -3
- package/dist/features/admin/components/AdminFaqsView.js +9 -7
- package/dist/features/admin/components/AdminFeatureEditorView.js +7 -1
- package/dist/features/admin/components/AdminFeatureFlagsView.js +4 -1
- package/dist/features/admin/components/AdminFeaturesView.js +5 -4
- package/dist/features/admin/components/AdminFilterBar.js +4 -4
- package/dist/features/admin/components/AdminGroupedListingsView.js +66 -30
- package/dist/features/admin/components/AdminGuideHubView.js +4 -1
- package/dist/features/admin/components/AdminHistoryView.js +4 -3
- package/dist/features/admin/components/AdminLiveView.js +4 -3
- package/dist/features/admin/components/AdminMediaView.js +4 -1
- package/dist/features/admin/components/AdminNavigationView.js +7 -4
- package/dist/features/admin/components/AdminNewsletterView.js +5 -3
- package/dist/features/admin/components/AdminNotificationsView.js +8 -6
- package/dist/features/admin/components/AdminOrderEditorView.js +2 -2
- package/dist/features/admin/components/AdminOrdersView.js +6 -4
- package/dist/features/admin/components/AdminPageHeader.js +5 -2
- package/dist/features/admin/components/AdminPayoutsView.js +7 -5
- package/dist/features/admin/components/AdminPrizeDrawsView.js +11 -9
- package/dist/features/admin/components/AdminProductEditorView.js +12 -5
- package/dist/features/admin/components/AdminProductsView.js +11 -9
- package/dist/features/admin/components/AdminReturnRequestsView.js +4 -3
- package/dist/features/admin/components/AdminReviewsView.js +10 -8
- package/dist/features/admin/components/AdminScammerEditorView.js +6 -2
- package/dist/features/admin/components/AdminScammersView.js +11 -9
- package/dist/features/admin/components/AdminSectionsView.js +20 -22
- package/dist/features/admin/components/AdminSessionsManager.js +2 -1
- package/dist/features/admin/components/AdminSessionsView.js +8 -6
- package/dist/features/admin/components/AdminSidebar.js +11 -7
- package/dist/features/admin/components/AdminSiteConfigGuideView.js +2 -1
- package/dist/features/admin/components/AdminSiteSettingsView.js +5 -1
- package/dist/features/admin/components/AdminStoreAddressesView.js +4 -3
- package/dist/features/admin/components/AdminStoreEditorView.js +5 -5
- package/dist/features/admin/components/AdminStoresView.js +6 -4
- package/dist/features/admin/components/AdminSublistingCategoriesView.js +6 -5
- package/dist/features/admin/components/AdminSublistingCategoryEditorView.js +3 -3
- package/dist/features/admin/components/AdminSupportTicketDetailView.js +10 -3
- package/dist/features/admin/components/AdminSupportTicketsView.js +11 -9
- package/dist/features/admin/components/AdminTeamView.js +6 -4
- package/dist/features/admin/components/AdminTrustGuideView.js +3 -3
- package/dist/features/admin/components/AdminUsersGuideView.js +3 -3
- package/dist/features/admin/components/AdminUsersView.js +6 -4
- package/dist/features/admin/components/AdminViewCards.js +12 -6
- package/dist/features/admin/components/AdminWishlistsView.js +4 -3
- package/dist/features/admin/components/BrandQuickCreateForm.js +2 -2
- package/dist/features/admin/components/CategoryQuickCreateForm.js +2 -2
- package/dist/features/admin/components/DashboardStats.js +9 -3
- package/dist/features/admin/components/DataListingView.js +3 -3
- package/dist/features/admin/components/DataTable.js +11 -7
- package/dist/features/admin/components/DrawerFormFooter.js +2 -2
- package/dist/features/admin/components/QuickEditMenu.js +2 -1
- package/dist/features/admin/components/analytics/AdminAnalyticsCharts.js +5 -1
- package/dist/features/admin/constants/filter-tabs.d.ts +1 -1
- package/dist/features/admin/constants/filter-tabs.js +0 -11
- package/dist/features/admin/types/index.d.ts +1 -1
- package/dist/features/auctions/actions/bid-actions.js +4 -2
- package/dist/features/auctions/components/AuctionBidsTable.js +4 -1
- package/dist/features/auctions/components/AuctionDetailPageView.js +14 -6
- package/dist/features/auctions/components/AuctionsListView.js +7 -6
- package/dist/features/auctions/components/CollapsibleBidHistory.js +5 -1
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +9 -3
- package/dist/features/auctions/components/MarketplaceAuctionGrid.js +8 -2
- package/dist/features/auctions/components/PlaceBidFormClient.js +4 -1
- package/dist/features/auth/components/RegisterForm.js +2 -2
- package/dist/features/auth/components/VerifyEmailView.js +5 -2
- package/dist/features/before-after/components/BeforeAfterSlider.js +1 -1
- package/dist/features/blog/actions/blog-actions.js +3 -2
- package/dist/features/blog/components/BlogFeaturedCard.js +8 -1
- package/dist/features/blog/components/BlogIndexListing.js +11 -5
- package/dist/features/blog/components/BlogListView.js +11 -3
- package/dist/features/blog/components/BlogPostView.js +10 -3
- package/dist/features/cart/components/CartDrawer.js +11 -3
- package/dist/features/cart/components/CartSummary.js +2 -2
- package/dist/features/cart/components/CheckoutOtpModal.js +2 -1
- package/dist/features/categories/components/BrandDetailPageView.js +15 -10
- package/dist/features/categories/components/BrandDetailTabs.js +5 -1
- package/dist/features/categories/components/BundleDetailView.js +6 -3
- package/dist/features/categories/components/BundleDynamicRuleEditor.js +3 -1
- package/dist/features/categories/components/BundleItemsPicker.js +10 -3
- package/dist/features/categories/components/CategoriesIndexListing.js +13 -7
- package/dist/features/categories/components/CategoriesIndexPageView.js +5 -4
- package/dist/features/categories/components/CategoryBundlesListing.js +10 -6
- package/dist/features/categories/components/CategoryDetailPageView.js +18 -12
- package/dist/features/categories/components/CategoryDetailTabs.js +5 -1
- package/dist/features/categories/components/CategoryFilters.d.ts +12 -12
- package/dist/features/categories/components/CategoryFilters.js +13 -12
- package/dist/features/categories/components/CategoryForm.js +6 -3
- package/dist/features/categories/components/CategoryGrid.js +9 -2
- package/dist/features/categories/components/CategoryProductsListing.js +10 -4
- package/dist/features/categories/components/CategorySelectorCreate.js +3 -3
- package/dist/features/categories/components/CategorySortSelect.js +1 -1
- package/dist/features/categories/components/CategoryStoresListing.js +3 -3
- package/dist/features/categories/components/CategoryTableColumns.js +10 -6
- package/dist/features/categories/components/CategoryTree.d.ts +1 -1
- package/dist/features/categories/components/CategoryTree.js +2 -2
- package/dist/features/categories/schemas/firestore.d.ts +2 -2
- package/dist/features/checkout/actions/checkout-actions.d.ts +1 -1
- package/dist/features/checkout/actions/checkout-actions.js +1 -1
- package/dist/features/classified/components/ClassifiedFilters.js +2 -2
- package/dist/features/classified/components/ClassifiedIndexListing.js +9 -3
- package/dist/features/classified/components/ClassifiedListView.js +6 -5
- package/dist/features/collections/components/CollectionCard.js +2 -1
- package/dist/features/contact/components/ContactForm.js +4 -2
- package/dist/features/contact/components/ContactInfoSidebar.js +4 -1
- package/dist/features/copilot/components/AdminCopilotView.js +13 -5
- package/dist/features/cron/jobs/auction-expiry.job.d.ts +2 -2
- package/dist/features/cron/jobs/auction-expiry.job.js +2 -1
- package/dist/features/cron/jobs/preorder-reminder.job.d.ts +1 -1
- package/dist/features/cron/jobs/preorder-reminder.job.js +2 -1
- package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +9 -3
- package/dist/features/digital-codes/components/DigitalCodesListView.js +4 -3
- package/dist/features/events/actions/event-actions.js +6 -4
- package/dist/features/events/components/AdminEventEditorView.js +63 -41
- package/dist/features/events/components/AdminEventEntriesView.js +9 -6
- package/dist/features/events/components/AdminEventsView.js +7 -5
- package/dist/features/events/components/EventCard.js +7 -1
- package/dist/features/events/components/EventFilters.d.ts +4 -4
- package/dist/features/events/components/EventFilters.js +2 -2
- package/dist/features/events/components/EventFormDrawer.js +2 -1
- package/dist/features/events/components/EventLeaderboard.js +4 -4
- package/dist/features/events/components/EventOfferCard.js +4 -1
- package/dist/features/events/components/EventParticipateView.js +3 -2
- package/dist/features/events/components/EventPollWidget.js +6 -5
- package/dist/features/events/components/EventRaffleEntryForm.js +5 -2
- package/dist/features/events/components/EventRaffleWinnerView.js +7 -1
- package/dist/features/events/components/EventRafflesSection.js +6 -4
- package/dist/features/events/components/EventSaleBanner.js +5 -2
- package/dist/features/events/components/EventsIndexListing.js +8 -2
- package/dist/features/events/components/EventsListView.js +4 -1
- package/dist/features/events/components/SpinWheelView.js +7 -2
- package/dist/features/events/schemas/firestore.d.ts +1 -0
- package/dist/features/events/types/index.d.ts +1 -0
- package/dist/features/faq/actions/faq-actions.js +4 -2
- package/dist/features/faq/components/ContactCTA.js +4 -1
- package/dist/features/faq/components/FAQCategorySidebar.js +2 -2
- package/dist/features/faq/components/FAQHelpfulButtons.js +8 -5
- package/dist/features/faq/components/FAQPageContent.js +7 -6
- package/dist/features/faq/components/FAQSortDropdown.js +2 -2
- package/dist/features/filters/AsyncFacetSection.js +4 -2
- package/dist/features/filters/FilterFacetSection.js +14 -6
- package/dist/features/filters/RangeFilter.js +4 -2
- package/dist/features/filters/SwitchFilter.js +2 -1
- package/dist/features/forms/Checkbox.js +1 -1
- package/dist/features/forms/Radio.js +1 -1
- package/dist/features/forms/Slider.js +1 -1
- package/dist/features/homepage/components/AdSlot.js +4 -4
- package/dist/features/homepage/components/AdvertisementBanner.js +13 -4
- package/dist/features/homepage/components/AnnouncementBar.js +2 -1
- package/dist/features/homepage/components/BeforeAfterCard.js +8 -2
- package/dist/features/homepage/components/BrandsSection.js +6 -3
- package/dist/features/homepage/components/CTABannerSection.js +2 -2
- package/dist/features/homepage/components/CharacterHotspot.js +5 -2
- package/dist/features/homepage/components/CharacterHotspotForm.js +8 -4
- package/dist/features/homepage/components/CustomCardsSection.js +13 -7
- package/dist/features/homepage/components/CustomerReviewsSection.js +9 -3
- package/dist/features/homepage/components/FAQSection.js +7 -4
- package/dist/features/homepage/components/FeaturedBundlesSection.js +8 -2
- package/dist/features/homepage/components/FeaturedResultsSection.js +1 -1
- package/dist/features/homepage/components/GoogleReviewsSection.js +14 -8
- package/dist/features/homepage/components/HeroCarousel.js +1 -1
- package/dist/features/homepage/components/HomepageSkeleton.js +7 -1
- package/dist/features/homepage/components/HowItWorksInfoView.js +2 -2
- package/dist/features/homepage/components/HowItWorksSection.js +2 -2
- package/dist/features/homepage/components/MarketplaceHomepageView.js +4 -2
- package/dist/features/homepage/components/NewsletterBanner.js +3 -2
- package/dist/features/homepage/components/NewsletterSection.js +5 -2
- package/dist/features/homepage/components/PromoGrid.js +4 -1
- package/dist/features/homepage/components/SectionCarousel.js +7 -4
- package/dist/features/homepage/components/SecurityHighlightsSection.js +3 -3
- package/dist/features/homepage/components/ShopByCategorySection.js +10 -4
- package/dist/features/homepage/components/SiteFeaturesSection.js +5 -2
- package/dist/features/homepage/components/SocialFeedSection.js +4 -4
- package/dist/features/homepage/components/SocialPostCard.js +6 -3
- package/dist/features/homepage/components/TrustFeaturesSection.js +5 -5
- package/dist/features/homepage/components/TrustIndicatorsSection.js +5 -2
- package/dist/features/homepage/components/WelcomeSection.js +1 -1
- package/dist/features/homepage/components/WhatsAppCommunitySection.js +3 -3
- package/dist/features/layout/AppLayoutShell.js +2 -1
- package/dist/features/layout/BackToTop.js +1 -1
- package/dist/features/layout/BottomActions.js +4 -30
- package/dist/features/layout/BottomActionsContext.d.ts +0 -36
- package/dist/features/layout/BottomActionsContext.js +0 -36
- package/dist/features/layout/BottomNavItem.js +1 -1
- package/dist/features/layout/BottomSheet.js +4 -1
- package/dist/features/layout/FooterLayout.js +1 -1
- package/dist/features/layout/NavbarLayout.js +4 -1
- package/dist/features/layout/SidebarLayout.js +5 -2
- package/dist/features/live/components/LiveItemFilters.js +2 -2
- package/dist/features/live/components/LiveItemsIndexListing.js +9 -3
- package/dist/features/live/components/LiveItemsListView.js +6 -5
- package/dist/features/loyalty/components/CoinsDisplay.js +4 -2
- package/dist/features/media/AvatarUpload.js +2 -2
- package/dist/features/media/MediaLightbox.js +3 -2
- package/dist/features/media/modals/VideoThumbnailSelector.js +4 -1
- package/dist/features/media/modals/VideoTrimModal.js +1 -1
- package/dist/features/media/upload/CameraCapture.js +1 -1
- package/dist/features/media/upload/ImageUpload.js +4 -1
- package/dist/features/media/upload/MediaUploadField.js +11 -2
- package/dist/features/media/upload/MediaUploadList.js +5 -1
- package/dist/features/orders/components/MarketplaceOrderCard.js +2 -2
- package/dist/features/orders/components/OrdersList.js +2 -1
- package/dist/features/orders/components/RefundHistoryTable.js +4 -1
- package/dist/features/orders/components/RefundRequestView.js +2 -1
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +5 -1
- package/dist/features/pre-orders/components/PreOrderActionsClient.js +3 -3
- package/dist/features/pre-orders/components/PreOrderBadge.js +2 -1
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +16 -7
- package/dist/features/pre-orders/components/PreOrdersIndexListing.js +32 -24
- package/dist/features/pre-orders/components/PreOrdersListView.js +5 -4
- package/dist/features/products/actions/product-actions.js +17 -15
- package/dist/features/products/columns/index.d.ts +1 -1
- package/dist/features/products/columns/index.js +1 -1
- package/dist/features/products/columns/productTableColumns.js +9 -4
- package/dist/features/products/components/AuctionsIndexListing.js +9 -3
- package/dist/features/products/components/BidHistory.js +4 -4
- package/dist/features/products/components/CompareOverlay.js +10 -2
- package/dist/features/products/components/CustomFieldsEditor.js +2 -1
- package/dist/features/products/components/CustomSectionTabContent.js +2 -2
- package/dist/features/products/components/CustomSectionsEditor.js +3 -2
- package/dist/features/products/components/GroupSettingsPanel.js +34 -26
- package/dist/features/products/components/MakeOfferButton.js +6 -2
- package/dist/features/products/components/MakeOfferForm.js +2 -1
- package/dist/features/products/components/MarketplaceBundleCard.js +6 -3
- package/dist/features/products/components/MarketplacePrizeDrawCard.js +3 -2
- package/dist/features/products/components/PlaceBidForm.js +2 -1
- package/dist/features/products/components/PrizeDrawCollage.js +6 -16
- package/dist/features/products/components/PrizeDrawDetailPageView.js +6 -1
- package/dist/features/products/components/PrizeDrawItemsEditor.js +4 -2
- package/dist/features/products/components/PrizeDrawsIndexListing.js +6 -3
- package/dist/features/products/components/PrizeDrawsListingView.js +5 -4
- package/dist/features/products/components/PrizeDrawsSection.js +6 -4
- package/dist/features/products/components/PrizeRevealModal.js +5 -1
- package/dist/features/products/components/ProductDetailPageView.js +32 -16
- package/dist/features/products/components/ProductFeatureBadges.js +9 -9
- package/dist/features/products/components/ProductForm.d.ts +11 -1
- package/dist/features/products/components/ProductForm.js +10 -5
- package/dist/features/products/components/ProductGalleryClient.js +8 -4
- package/dist/features/products/components/ProductGradingTab.js +4 -1
- package/dist/features/products/components/ProductGrid.js +35 -14
- package/dist/features/products/components/ProductInfo.js +2 -1
- package/dist/features/products/components/ProductTabs.js +2 -1
- package/dist/features/products/components/ProductTabsShell.js +5 -1
- package/dist/features/products/components/ProductsIndexListing.js +32 -24
- package/dist/features/products/components/ProductsIndexPageView.js +2 -2
- package/dist/features/products/components/RelatedProducts.js +3 -3
- package/dist/features/products/components/ShowGroupSection.js +10 -6
- package/dist/features/products/components/SublistingCarouselSection.js +7 -3
- package/dist/features/products/components/SublistingCategorySelect.d.ts +3 -1
- package/dist/features/products/components/SublistingCategorySelect.js +4 -37
- package/dist/features/products/constants/action-defs.js +3 -3
- package/dist/features/products/constants/sieve.d.ts +2 -2
- package/dist/features/products/constants/sieve.js +2 -2
- package/dist/features/products/hooks/useRelatedProducts.js +5 -4
- package/dist/features/promotions/components/CouponCard.js +5 -3
- package/dist/features/promotions/components/CouponsIndexListing.js +7 -3
- package/dist/features/promotions/repository/coupons.repository.d.ts +8 -0
- package/dist/features/promotions/repository/coupons.repository.js +2 -0
- package/dist/features/reviews/actions/review-actions.js +2 -1
- package/dist/features/reviews/components/ReviewDetailPageView.js +3 -3
- package/dist/features/reviews/components/ReviewDetailShell.js +15 -3
- package/dist/features/reviews/components/ReviewSummary.js +4 -2
- package/dist/features/reviews/components/ReviewsIndexListing.js +8 -2
- package/dist/features/reviews/components/ReviewsIndexPageView.js +7 -6
- package/dist/features/reviews/components/ReviewsList.js +1 -1
- package/dist/features/scams/actions/scam-actions.js +3 -2
- package/dist/features/scams/components/ScamAwarenessModal.js +2 -2
- package/dist/features/scams/components/ScamProfileView.js +3 -3
- package/dist/features/scams/components/ScamRegistryView.js +11 -8
- package/dist/features/search/actions/search-actions.js +7 -6
- package/dist/features/search/components/Search.js +9 -6
- package/dist/features/search/components/SearchFiltersRow.js +1 -1
- package/dist/features/search/components/SearchResultsSection.js +1 -1
- package/dist/features/seller/components/CouponInlineSelect.d.ts +22 -0
- package/dist/features/seller/components/CouponInlineSelect.js +104 -0
- package/dist/features/seller/components/GroupInlineSelect.d.ts +23 -0
- package/dist/features/seller/components/GroupInlineSelect.js +80 -0
- package/dist/features/seller/components/PhysicalLocationModal.js +2 -1
- package/dist/features/seller/components/PrintCenterView.js +2 -1
- package/dist/features/seller/components/ProductInlineSelect.d.ts +24 -0
- package/dist/features/seller/components/ProductInlineSelect.js +42 -0
- package/dist/features/seller/components/QuickProductForm.js +4 -1
- package/dist/features/seller/components/SellerAddressesView.js +8 -3
- package/dist/features/seller/components/SellerAnalyticsAlertsView.js +6 -3
- package/dist/features/seller/components/SellerAnalyticsView.js +2 -2
- package/dist/features/seller/components/SellerAuctionsView.js +7 -5
- package/dist/features/seller/components/SellerBidsView.js +12 -10
- package/dist/features/seller/components/SellerBundlesView.js +9 -7
- package/dist/features/seller/components/SellerClassifiedView.js +6 -5
- package/dist/features/seller/components/SellerCouponEditorView.d.ts +2 -0
- package/dist/features/seller/components/SellerCouponEditorView.js +15 -3
- package/dist/features/seller/components/SellerCouponsView.js +7 -5
- package/dist/features/seller/components/SellerDashboardView.js +2 -2
- package/dist/features/seller/components/SellerDigitalCodesView.js +7 -6
- package/dist/features/seller/components/SellerGoogleReviewsView.js +2 -2
- package/dist/features/seller/components/SellerGroupedListingsView.js +10 -9
- package/dist/features/seller/components/SellerLiveView.js +6 -5
- package/dist/features/seller/components/SellerOffersView.js +6 -4
- package/dist/features/seller/components/SellerOrdersView.js +18 -13
- package/dist/features/seller/components/SellerPayoutMethodsView.js +8 -6
- package/dist/features/seller/components/SellerPayoutRequestView.js +5 -1
- package/dist/features/seller/components/SellerPayoutSettingsView.js +5 -2
- package/dist/features/seller/components/SellerPayoutsView.js +6 -4
- package/dist/features/seller/components/SellerPreOrdersView.js +12 -10
- package/dist/features/seller/components/SellerPrizeDrawsView.js +12 -10
- package/dist/features/seller/components/SellerProductShell.js +1 -1
- package/dist/features/seller/components/SellerProductsCards.js +4 -1
- package/dist/features/seller/components/SellerProductsView.js +14 -12
- package/dist/features/seller/components/SellerReviewsView.js +7 -3
- package/dist/features/seller/components/SellerShippingConfigsView.js +7 -6
- package/dist/features/seller/components/SellerShippingView.js +1 -1
- package/dist/features/seller/components/SellerSidebar.js +15 -8
- package/dist/features/seller/components/SellerStoreCategoriesView.js +5 -4
- package/dist/features/seller/components/SellerStorefrontView.js +2 -2
- package/dist/features/seller/components/SellerTemplatesView.js +11 -7
- package/dist/features/seller/components/SublistingInlineSelect.d.ts +19 -0
- package/dist/features/seller/components/SublistingInlineSelect.js +84 -0
- package/dist/features/seller/components/analytics/SellerTopProducts.js +1 -1
- package/dist/features/seller/components/index.d.ts +8 -0
- package/dist/features/seller/components/index.js +4 -0
- package/dist/features/shell/FormShell.js +10 -2
- package/dist/features/shell/QuickFormDrawer.js +5 -5
- package/dist/features/shell/StepForm.js +6 -6
- package/dist/features/site-settings/components/ActionPermissionsManager.js +8 -4
- package/dist/features/site-settings/components/NavPermissionsManager.js +7 -4
- package/dist/features/stores/actions/store-query-actions.js +3 -2
- package/dist/features/stores/components/InteractiveStoreCard.js +5 -1
- package/dist/features/stores/components/StoreAboutView.js +4 -1
- package/dist/features/stores/components/StoreAddressSelectorCreate.d.ts +2 -1
- package/dist/features/stores/components/StoreAddressSelectorCreate.js +5 -31
- package/dist/features/stores/components/StoreAuctionsListing.js +6 -3
- package/dist/features/stores/components/StoreAuctionsPageView.js +4 -2
- package/dist/features/stores/components/StoreDetailLayoutView.d.ts +1 -1
- package/dist/features/stores/components/StoreDetailLayoutView.js +7 -6
- package/dist/features/stores/components/StoreGuideHubView.js +5 -2
- package/dist/features/stores/components/StoreHeader.js +8 -1
- package/dist/features/stores/components/StorePreOrdersListing.js +6 -3
- package/dist/features/stores/components/StorePreOrdersPageView.js +4 -2
- package/dist/features/stores/components/StorePrizeDrawsPageView.js +4 -2
- package/dist/features/stores/components/StoreProductsListing.js +6 -3
- package/dist/features/stores/components/StoreProductsPageView.js +2 -1
- package/dist/features/stores/components/StoreProductsView.js +5 -4
- package/dist/features/stores/components/StoreReviewsListing.js +8 -2
- package/dist/features/stores/components/StoresIndexListing.js +16 -9
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +7 -1
- package/dist/features/whatsapp-bot/components/WhatsAppChatButton.js +2 -1
- package/dist/features/wishlist/components/WishlistPage.js +2 -1
- package/dist/features/wishlist/components/WishlistView.js +4 -3
- package/dist/index.d.ts +10 -0
- package/dist/index.js +13 -1
- package/dist/next/components/GlobalError.js +2 -2
- package/dist/next/routing/route-map.d.ts +2 -0
- package/dist/next/routing/route-map.js +1 -0
- package/dist/react/ErrorBoundary.js +2 -2
- package/dist/styles.css +2 -1
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/DataTable.js +17 -16
- package/dist/ui/components/DateInput.js +2 -2
- package/dist/ui/components/DetailPageGallery.js +4 -1
- package/dist/ui/components/DetailPageTabs.js +6 -2
- package/dist/ui/components/ImageLightbox.js +5 -3
- package/dist/ui/components/Input.js +6 -3
- package/dist/ui/components/Layout.d.ts +4 -0
- package/dist/ui/components/Layout.js +1 -1
- package/dist/ui/components/Layout.style.css +1 -0
- package/dist/ui/components/ListingFilterDrawer.js +4 -1
- package/dist/ui/components/ListingLayout.js +9 -8
- package/dist/ui/components/ListingToolbar.js +5 -1
- package/dist/ui/components/PaginatedSelect.d.ts +1 -2
- package/dist/ui/components/PaginatedSelect.js +1 -2
- package/dist/ui/components/Radio.js +1 -1
- package/dist/ui/components/Select.js +2 -1
- package/dist/ui/components/Slider.js +1 -1
- package/dist/ui/components/VacationBanner.js +2 -1
- package/dist/ui/components/surface-tokens.d.ts +1 -0
- package/dist/ui/components/surface-tokens.js +1 -0
- package/package.json +11 -2
|
@@ -6,6 +6,20 @@ import { Alert, Button, Div, Grid, Heading, Input, Label, RichTextEditor, Row, S
|
|
|
6
6
|
import { apiClient } from "../../../http";
|
|
7
7
|
import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
8
8
|
import { StepForm } from "../../shell";
|
|
9
|
+
import { ProductInlineSelect } from "../../seller/components/ProductInlineSelect";
|
|
10
|
+
import { CouponInlineSelect } from "../../seller/components/CouponInlineSelect";
|
|
11
|
+
const __P = {
|
|
12
|
+
p4: "p-4",
|
|
13
|
+
};
|
|
14
|
+
const __O = {
|
|
15
|
+
yAuto: "overflow-y-auto",
|
|
16
|
+
};
|
|
17
|
+
const CLS_REMOVE_BTN = "text-zinc-400 hover:text-red-500 transition-colors text-lg leading-none px-1 p-0 min-h-0 h-auto rounded-none";
|
|
18
|
+
const CLS_REMOVE_BTN_PX2 = "text-zinc-400 hover:text-red-500 transition-colors px-2 py-1 text-lg leading-none p-0 min-h-0 h-auto rounded-none";
|
|
19
|
+
const CLS_REMOVE_BTN_LG = "text-zinc-400 hover:text-red-500 text-lg leading-none px-2 p-0 min-h-0 h-auto rounded-none";
|
|
20
|
+
const CLS_RAFFLE_PANEL = "border border-amber-200 bg-amber-50 dark:border-amber-700 dark:bg-amber-900/20";
|
|
21
|
+
const CLS_RAFFLE_HEADING = "text-amber-900 dark:text-amber-100";
|
|
22
|
+
const CLS_RAFFLE_BODY = "text-amber-800 dark:text-amber-200";
|
|
9
23
|
const EVENT_TYPE_OPTIONS = [
|
|
10
24
|
{ label: "Sale", value: "sale" },
|
|
11
25
|
{ label: "Offer / Coupon", value: "offer" },
|
|
@@ -38,7 +52,7 @@ const FORM_FIELD_TYPE_OPTIONS = [
|
|
|
38
52
|
{ label: "Checkbox", value: "checkbox" },
|
|
39
53
|
{ label: "Radio", value: "radio" },
|
|
40
54
|
{ label: "Date", value: "date" },
|
|
41
|
-
{ label: "Rating (1–5)", value: "rating" },
|
|
55
|
+
{ label: "Rating (1–5)", value: "rating" }, // audit-sieve-views-ok — form field type, not sort key
|
|
42
56
|
{ label: "File upload", value: "file" },
|
|
43
57
|
];
|
|
44
58
|
const FIELD_TYPES_WITH_OPTIONS = ["select", "multiselect", "radio", "checkbox"];
|
|
@@ -50,7 +64,7 @@ function FormFieldBuilder({ fields, setFields }) {
|
|
|
50
64
|
const hasOptions = FIELD_TYPES_WITH_OPTIONS.includes(field.type);
|
|
51
65
|
const isNumeric = field.type === "number" || field.type === "rating";
|
|
52
66
|
const isText = field.type === "text" || field.type === "textarea" || field.type === "email";
|
|
53
|
-
return (_jsxs(Stack, { gap: "xs", surface: "default", rounded: "lg", border: "default", padding: "sm", children: [_jsxs(Row, { justify: "between", gap: "xs", children: [_jsxs(Text, { size: "xs", weight: "medium", color: "muted", children: ["Field ", idx + 1] }), _jsx("
|
|
67
|
+
return (_jsxs(Stack, { gap: "xs", surface: "default", rounded: "lg", border: "default", padding: "sm", children: [_jsxs(Row, { justify: "between", gap: "xs", children: [_jsxs(Text, { size: "xs", weight: "medium", color: "muted", children: ["Field ", idx + 1] }), _jsx(Button, { variant: "ghost", type: "button", onClick: () => removeField(field.id), className: CLS_REMOVE_BTN, "aria-label": "Remove field", children: "\u00D7" })] }), _jsxs(Grid, { cols: 2, gap: "xs", children: [_jsx(Select, { label: "Type", value: field.type, options: FORM_FIELD_TYPE_OPTIONS, onChange: (e) => updateField(field.id, { type: e.target.value, options: undefined }) }), _jsx(Input, { label: "Label", value: field.label, onChange: (e) => updateField(field.id, { label: e.target.value }), placeholder: "e.g. Describe your entry", required: true })] }), !hasOptions && field.type !== "date" && field.type !== "file" && field.type !== "rating" && (_jsx(Input, { label: "Placeholder (optional)", value: field.placeholder ?? "", onChange: (e) => updateField(field.id, { placeholder: e.target.value || undefined }), placeholder: "Hint shown inside the field" })), hasOptions && (_jsx(Textarea, { label: "Options \u2014 one per line", value: (field.options ?? []).join("\n"), onChange: (e) => updateField(field.id, { options: e.target.value.split("\n").map((s) => s.trim()).filter(Boolean) }), placeholder: "Option A\nOption B\nOption C", rows: 3 })), (isText || isNumeric) && (_jsxs(Stack, { gap: "xs", surface: "muted", rounded: "md", padding: "xs", children: [_jsx(Text, { size: "xs", color: "muted", children: "Validation (optional)" }), _jsxs(Grid, { gap: "xs", className: "grid-cols-2", children: [isText && (_jsxs(_Fragment, { children: [_jsx(Input, { label: "Min length", type: "number", value: String(field.validation?.minLength ?? ""), onChange: (e) => updateField(field.id, { validation: { ...field.validation, minLength: e.target.value ? Number(e.target.value) : undefined } }), placeholder: "0" }), _jsx(Input, { label: "Max length", type: "number", value: String(field.validation?.maxLength ?? ""), onChange: (e) => updateField(field.id, { validation: { ...field.validation, maxLength: e.target.value ? Number(e.target.value) : undefined } }), placeholder: "500" })] })), isNumeric && (_jsxs(_Fragment, { children: [_jsx(Input, { label: "Min value", type: "number", value: String(field.validation?.min ?? ""), onChange: (e) => updateField(field.id, { validation: { ...field.validation, min: e.target.value ? Number(e.target.value) : undefined } }), placeholder: "0" }), _jsx(Input, { label: "Max value", type: "number", value: String(field.validation?.max ?? ""), onChange: (e) => updateField(field.id, { validation: { ...field.validation, max: e.target.value ? Number(e.target.value) : undefined } }), placeholder: "100" })] }))] }), field.type === "text" && (_jsx(Input, { label: "Pattern (regex, optional)", value: field.validation?.pattern ?? "", onChange: (e) => updateField(field.id, { validation: { ...field.validation, pattern: e.target.value || undefined } }), placeholder: "^[A-Z].*" }))] })), _jsx(Toggle, { checked: field.required, onChange: (v) => updateField(field.id, { required: v }), label: "Required" })] }, field.id));
|
|
54
68
|
}), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: addField, children: "+ Add field" })] }));
|
|
55
69
|
}
|
|
56
70
|
const POLL_VISIBILITY_OPTIONS = [
|
|
@@ -120,11 +134,52 @@ const DEFAULT_DRAFT = {
|
|
|
120
134
|
raffleTopN: "10",
|
|
121
135
|
rafflePrize: "",
|
|
122
136
|
rafflePrizeCouponId: "",
|
|
137
|
+
rafflePrizeProductIds: [],
|
|
123
138
|
spinPrizes: [],
|
|
124
139
|
spinMaxPerUser: "1",
|
|
125
140
|
spinWindowStart: "",
|
|
126
141
|
spinWindowEnd: "",
|
|
127
142
|
};
|
|
143
|
+
// --- Pure build helpers (module-level, no component closure) -----------------
|
|
144
|
+
function buildEventTypeConfig(draft) {
|
|
145
|
+
if (draft.type === "sale")
|
|
146
|
+
return { saleConfig: { discountPercent: Number(draft.discountPercent) || 10, bannerText: draft.saleBannerText || undefined } };
|
|
147
|
+
if (draft.type === "offer")
|
|
148
|
+
return { offerConfig: { couponId: draft.couponId, displayCode: draft.displayCode, bannerText: draft.offerBannerText || undefined } };
|
|
149
|
+
if (draft.type === "poll")
|
|
150
|
+
return { pollConfig: { options: draft.pollOptions.filter((o) => o.label.trim()), allowMultiSelect: draft.allowMultiSelect, allowComment: draft.allowComment, resultsVisibility: draft.resultsVisibility } };
|
|
151
|
+
if (draft.type === "survey")
|
|
152
|
+
return { surveyConfig: { requireLogin: draft.requireLogin, maxEntriesPerUser: Number(draft.maxEntriesPerUser) || 1, hasLeaderboard: draft.hasLeaderboard, hasPointSystem: draft.hasPointSystem, pointsLabel: draft.hasPointSystem ? (draft.pointsLabel.trim() || "Points") : undefined, entryReviewRequired: draft.entryReviewRequired, formFields: draft.surveyFields.map((f, i) => ({ ...f, order: i })) } };
|
|
153
|
+
if (draft.type === "feedback")
|
|
154
|
+
return { feedbackConfig: { anonymous: draft.anonymous, formFields: draft.feedbackFields.map((f, i) => ({ ...f, order: i })) } };
|
|
155
|
+
return {};
|
|
156
|
+
}
|
|
157
|
+
function buildEventRaffleFields(draft) {
|
|
158
|
+
const isRaffleType = draft.type === "raffle" || draft.type === "spin_wheel";
|
|
159
|
+
const fields = {};
|
|
160
|
+
if (!draft.hasRaffle && !isRaffleType)
|
|
161
|
+
return fields;
|
|
162
|
+
fields.hasRaffle = true;
|
|
163
|
+
fields.raffleType = isRaffleType && draft.type === "spin_wheel" ? "spin_wheel" : draft.raffleType;
|
|
164
|
+
if (Number(draft.raffleTopN) > 0)
|
|
165
|
+
fields.raffleTopN = Number(draft.raffleTopN);
|
|
166
|
+
if (draft.rafflePrize)
|
|
167
|
+
fields.rafflePrize = draft.rafflePrize;
|
|
168
|
+
if (draft.rafflePrizeCouponId)
|
|
169
|
+
fields.rafflePrizeCouponId = draft.rafflePrizeCouponId;
|
|
170
|
+
if (draft.rafflePrizeProductIds.length > 0)
|
|
171
|
+
fields.rafflePrizeProductIds = draft.rafflePrizeProductIds;
|
|
172
|
+
if (draft.raffleType === "spin_wheel" || draft.type === "spin_wheel") {
|
|
173
|
+
fields.spinPrizes = draft.spinPrizes;
|
|
174
|
+
if (Number(draft.spinMaxPerUser) > 0)
|
|
175
|
+
fields.spinMaxPerUser = Number(draft.spinMaxPerUser);
|
|
176
|
+
if (draft.spinWindowStart)
|
|
177
|
+
fields.spinWindowStart = toISOString(draft.spinWindowStart);
|
|
178
|
+
if (draft.spinWindowEnd)
|
|
179
|
+
fields.spinWindowEnd = toISOString(draft.spinWindowEnd);
|
|
180
|
+
}
|
|
181
|
+
return fields;
|
|
182
|
+
}
|
|
128
183
|
// --- Component ---------------------------------------------------------------
|
|
129
184
|
export function AdminEventEditorView({ eventId, onSaved, embedded, ...rest }) {
|
|
130
185
|
const isEdit = Boolean(eventId);
|
|
@@ -187,6 +242,7 @@ export function AdminEventEditorView({ eventId, onSaved, embedded, ...rest }) {
|
|
|
187
242
|
raffleTopN: String(event.raffleTopN ?? 10),
|
|
188
243
|
rafflePrize: event.rafflePrize || "",
|
|
189
244
|
rafflePrizeCouponId: event.rafflePrizeCouponId || "",
|
|
245
|
+
rafflePrizeProductIds: Array.isArray(event.rafflePrizeProductIds) ? event.rafflePrizeProductIds : [],
|
|
190
246
|
spinPrizes: Array.isArray(event.spinPrizes) ? event.spinPrizes : [],
|
|
191
247
|
spinMaxPerUser: String(event.spinMaxPerUser ?? 1),
|
|
192
248
|
spinWindowStart: toLocalDatetime(event.spinWindowStart),
|
|
@@ -200,40 +256,6 @@ export function AdminEventEditorView({ eventId, onSaved, embedded, ...rest }) {
|
|
|
200
256
|
// --- save ---
|
|
201
257
|
const saveMutation = useMutation({
|
|
202
258
|
mutationFn: async () => {
|
|
203
|
-
const buildTypeConfig = () => {
|
|
204
|
-
if (draft.type === "sale")
|
|
205
|
-
return { saleConfig: { discountPercent: Number(draft.discountPercent) || 10, bannerText: draft.saleBannerText || undefined } };
|
|
206
|
-
if (draft.type === "offer")
|
|
207
|
-
return { offerConfig: { couponId: draft.couponId, displayCode: draft.displayCode, bannerText: draft.offerBannerText || undefined } };
|
|
208
|
-
if (draft.type === "poll")
|
|
209
|
-
return { pollConfig: { options: draft.pollOptions.filter((o) => o.label.trim()), allowMultiSelect: draft.allowMultiSelect, allowComment: draft.allowComment, resultsVisibility: draft.resultsVisibility } };
|
|
210
|
-
if (draft.type === "survey")
|
|
211
|
-
return { surveyConfig: { requireLogin: draft.requireLogin, maxEntriesPerUser: Number(draft.maxEntriesPerUser) || 1, hasLeaderboard: draft.hasLeaderboard, hasPointSystem: draft.hasPointSystem, pointsLabel: draft.hasPointSystem ? (draft.pointsLabel.trim() || "Points") : undefined, entryReviewRequired: draft.entryReviewRequired, formFields: draft.surveyFields.map((f, i) => ({ ...f, order: i })) } };
|
|
212
|
-
if (draft.type === "feedback")
|
|
213
|
-
return { feedbackConfig: { anonymous: draft.anonymous, formFields: draft.feedbackFields.map((f, i) => ({ ...f, order: i })) } };
|
|
214
|
-
return {};
|
|
215
|
-
};
|
|
216
|
-
const isRaffleType = draft.type === "raffle" || draft.type === "spin_wheel";
|
|
217
|
-
const raffleFields = {};
|
|
218
|
-
if (draft.hasRaffle || isRaffleType) {
|
|
219
|
-
raffleFields.hasRaffle = true;
|
|
220
|
-
raffleFields.raffleType = isRaffleType && draft.type === "spin_wheel" ? "spin_wheel" : draft.raffleType;
|
|
221
|
-
if (Number(draft.raffleTopN) > 0)
|
|
222
|
-
raffleFields.raffleTopN = Number(draft.raffleTopN);
|
|
223
|
-
if (draft.rafflePrize)
|
|
224
|
-
raffleFields.rafflePrize = draft.rafflePrize;
|
|
225
|
-
if (draft.rafflePrizeCouponId)
|
|
226
|
-
raffleFields.rafflePrizeCouponId = draft.rafflePrizeCouponId;
|
|
227
|
-
if (draft.raffleType === "spin_wheel" || draft.type === "spin_wheel") {
|
|
228
|
-
raffleFields.spinPrizes = draft.spinPrizes;
|
|
229
|
-
if (Number(draft.spinMaxPerUser) > 0)
|
|
230
|
-
raffleFields.spinMaxPerUser = Number(draft.spinMaxPerUser);
|
|
231
|
-
if (draft.spinWindowStart)
|
|
232
|
-
raffleFields.spinWindowStart = toISOString(draft.spinWindowStart);
|
|
233
|
-
if (draft.spinWindowEnd)
|
|
234
|
-
raffleFields.spinWindowEnd = toISOString(draft.spinWindowEnd);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
259
|
const payload = {
|
|
238
260
|
type: draft.type,
|
|
239
261
|
title: draft.title,
|
|
@@ -243,8 +265,8 @@ export function AdminEventEditorView({ eventId, onSaved, embedded, ...rest }) {
|
|
|
243
265
|
startsAt: toISOString(draft.startsAt),
|
|
244
266
|
endsAt: toISOString(draft.endsAt),
|
|
245
267
|
coverImageUrl: draft.coverImageUrl || undefined,
|
|
246
|
-
...
|
|
247
|
-
...
|
|
268
|
+
...buildEventTypeConfig(draft),
|
|
269
|
+
...buildEventRaffleFields(draft),
|
|
248
270
|
};
|
|
249
271
|
if (eventId) {
|
|
250
272
|
payload.status = draft.status;
|
|
@@ -316,7 +338,7 @@ export function AdminEventEditorView({ eventId, onSaved, embedded, ...rest }) {
|
|
|
316
338
|
return "Poll events require at least 2 options";
|
|
317
339
|
return null;
|
|
318
340
|
},
|
|
319
|
-
render: ({ values, onChange }) => (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Event Settings" }), isEdit && (_jsx(Select, { label: "Status", value: values.status, options: EVENT_STATUS_OPTIONS, onChange: (e) => onChange({ status: e.target.value }) })), values.createdBy && (_jsxs(Stack, { gap: "none", children: [_jsx(Text, { size: "sm", weight: "medium", className: "mb-1", children: "Created by" }), _jsx(Text, { size: "sm", color: "muted", children: values.createdBy })] })), values.type === "sale" && (_jsxs(Stack, { gap: "xs", surface: "muted", rounded: "lg", border: "default", padding: "sm", children: [_jsx(Text, { size: "sm", weight: "semibold", color: "muted", children: "Sale configuration" }), _jsxs(Grid, { cols: 2, gap: "sm", children: [_jsx(Input, { label: "Discount %", type: "number", value: values.discountPercent, onChange: (e) => onChange({ discountPercent: e.target.value }), placeholder: "10" }), _jsx(Input, { label: "Banner text (optional)", value: values.saleBannerText, onChange: (e) => onChange({ saleBannerText: e.target.value }), placeholder: "Limited time \u2014 ends Sunday!" })] })] })), values.type === "offer" && (_jsxs(Stack, { gap: "xs", surface: "muted", rounded: "lg", border: "default", padding: "sm", children: [_jsx(Text, { size: "sm", weight: "semibold", color: "muted", children: "Offer configuration" }), _jsxs(Grid, { cols: 2, gap: "sm", children: [_jsx(
|
|
341
|
+
render: ({ values, onChange }) => (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Event Settings" }), isEdit && (_jsx(Select, { label: "Status", value: values.status, options: EVENT_STATUS_OPTIONS, onChange: (e) => onChange({ status: e.target.value }) })), values.createdBy && (_jsxs(Stack, { gap: "none", children: [_jsx(Text, { size: "sm", weight: "medium", className: "mb-1", children: "Created by" }), _jsx(Text, { size: "sm", color: "muted", children: values.createdBy })] })), values.type === "sale" && (_jsxs(Stack, { gap: "xs", surface: "muted", rounded: "lg", border: "default", padding: "sm", children: [_jsx(Text, { size: "sm", weight: "semibold", color: "muted", children: "Sale configuration" }), _jsxs(Grid, { cols: 2, gap: "sm", children: [_jsx(Input, { label: "Discount %", type: "number", value: values.discountPercent, onChange: (e) => onChange({ discountPercent: e.target.value }), placeholder: "10" }), _jsx(Input, { label: "Banner text (optional)", value: values.saleBannerText, onChange: (e) => onChange({ saleBannerText: e.target.value }), placeholder: "Limited time \u2014 ends Sunday!" })] })] })), values.type === "offer" && (_jsxs(Stack, { gap: "xs", surface: "muted", rounded: "lg", border: "default", padding: "sm", children: [_jsx(Text, { size: "sm", weight: "semibold", color: "muted", children: "Offer configuration" }), _jsxs(Grid, { cols: 2, gap: "sm", children: [_jsxs(Div, { children: [_jsx(Text, { size: "sm", weight: "medium", className: "mb-1", children: "Coupon" }), _jsx(CouponInlineSelect, { scope: "admin", value: values.couponId, onChange: (id) => onChange({ couponId: id ?? "" }), placeholder: "Search coupons\u2026", allowCreate: false })] }), _jsx(Input, { label: "Display code", value: values.displayCode, onChange: (e) => onChange({ displayCode: e.target.value }), placeholder: "CHARIZARD25", required: true })] }), _jsx(Input, { label: "Banner text (optional)", value: values.offerBannerText, onChange: (e) => onChange({ offerBannerText: e.target.value }), placeholder: "Use CHARIZARD25 at checkout" })] })), values.type === "poll" && (_jsxs(Stack, { gap: "md", rounded: "xl", border: "default", padding: "md", children: [_jsx(Text, { size: "sm", weight: "semibold", color: "muted", children: "Poll configuration" }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "xs", color: "muted", children: "Options (minimum 2)" }), values.pollOptions.map((opt, idx) => (_jsxs(Row, { gap: "xs", children: [_jsx(Div, { className: "flex-1", children: _jsx(Input, { value: opt.label, onChange: (e) => onChange({ pollOptions: values.pollOptions.map((o) => o.id === opt.id ? { ...o, label: e.target.value } : o) }), placeholder: `Option ${idx + 1}` }) }), values.pollOptions.length > 2 && (_jsx(Button, { variant: "ghost", type: "button", onClick: () => onChange({ pollOptions: values.pollOptions.filter((o) => o.id !== opt.id) }), className: CLS_REMOVE_BTN_PX2, "aria-label": "Remove option", children: "\u00D7" }))] }, opt.id))), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => onChange({ pollOptions: [...values.pollOptions, { id: `opt${Date.now()}`, label: "" }] }), children: "+ Add option" })] }), _jsx(Select, { label: "Results visibility", value: values.resultsVisibility, options: POLL_VISIBILITY_OPTIONS, onChange: (e) => onChange({ resultsVisibility: e.target.value }) }), _jsxs(Stack, { gap: "sm", children: [_jsx(Toggle, { checked: values.allowMultiSelect, onChange: (v) => onChange({ allowMultiSelect: v }), label: "Allow multi-select" }), _jsx(Toggle, { checked: values.allowComment, onChange: (v) => onChange({ allowComment: v }), label: "Allow comment with vote" })] })] })), values.type === "survey" && (_jsxs(Stack, { gap: "md", rounded: "xl", border: "default", padding: "md", children: [_jsx(Text, { size: "sm", weight: "semibold", color: "muted", children: "Survey configuration" }), _jsxs(Grid, { cols: 2, gap: "sm", children: [_jsx(Input, { label: "Max entries per user", type: "number", value: values.maxEntriesPerUser, onChange: (e) => onChange({ maxEntriesPerUser: e.target.value }), placeholder: "1" }), values.hasPointSystem && (_jsx(Input, { label: "Points label", value: values.pointsLabel, onChange: (e) => onChange({ pointsLabel: e.target.value }), placeholder: "Points" }))] }), _jsxs(Stack, { gap: "xs", children: [_jsx(Toggle, { checked: values.requireLogin, onChange: (v) => onChange({ requireLogin: v }), label: "Require login to participate" }), _jsx(Toggle, { checked: values.hasLeaderboard, onChange: (v) => onChange({ hasLeaderboard: v }), label: "Show leaderboard" }), _jsx(Toggle, { checked: values.hasPointSystem, onChange: (v) => onChange({ hasPointSystem: v }), label: "Enable point system" }), _jsx(Toggle, { checked: values.entryReviewRequired, onChange: (v) => onChange({ entryReviewRequired: v }), label: "Require employee review before entry is approved" })] }), _jsx(FormFieldBuilder, { fields: values.surveyFields, setFields: (f) => onChange({ surveyFields: f }) })] })), values.type === "feedback" && (_jsxs(Stack, { gap: "md", rounded: "xl", border: "default", padding: "md", children: [_jsx(Text, { size: "sm", weight: "semibold", color: "muted", children: "Feedback configuration" }), _jsx(Toggle, { checked: values.anonymous, onChange: (v) => onChange({ anonymous: v }), label: "Allow anonymous submissions" }), _jsx(FormFieldBuilder, { fields: values.feedbackFields, setFields: (f) => onChange({ feedbackFields: f }) })] }))] })),
|
|
320
342
|
},
|
|
321
343
|
{
|
|
322
344
|
label: "Raffle / Spin",
|
|
@@ -324,14 +346,14 @@ export function AdminEventEditorView({ eventId, onSaved, embedded, ...rest }) {
|
|
|
324
346
|
const isRaffleType = values.type === "raffle" || values.type === "spin_wheel";
|
|
325
347
|
const showRaffleConfig = isRaffleType || values.hasRaffle;
|
|
326
348
|
const isSpinMode = values.type === "spin_wheel" || values.raffleType === "spin_wheel";
|
|
327
|
-
return (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Raffle & Spin Wheel" }), !isRaffleType && (_jsx(Toggle, { checked: values.hasRaffle, onChange: (v) => onChange({ hasRaffle: v }), label: "Attach a raffle to this event" })), !isRaffleType && !values.hasRaffle && (_jsx(Text, { size: "sm", color: "muted", children: "Enable the toggle above to attach a raffle draw to this event. Not applicable for this event type by default." })), showRaffleConfig && (_jsxs(Stack, { gap: "md", rounded: "xl", border: "default", padding: "md", children: [_jsxs(Grid, { cols: 2, gap: "sm", children: [_jsx(Select, { label: "Raffle type", value: values.type === "spin_wheel" ? "spin_wheel" : values.raffleType, options: RAFFLE_TYPE_OPTIONS, onChange: (e) => onChange({ raffleType: e.target.value }), disabled: values.type === "spin_wheel" }), _jsx(Input, { label: "Top N (for top-N raffle types)", type: "number", value: values.raffleTopN, onChange: (e) => onChange({ raffleTopN: e.target.value }), placeholder: "10" })] }), _jsx(Input, { label: "Prize description", value: values.rafflePrize, onChange: (e) => onChange({ rafflePrize: e.target.value }), placeholder: "\u20B92,000 store credit + exclusive Pikachu sticker" }), _jsx(
|
|
349
|
+
return (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Raffle & Spin Wheel" }), !isRaffleType && (_jsx(Toggle, { checked: values.hasRaffle, onChange: (v) => onChange({ hasRaffle: v }), label: "Attach a raffle to this event" })), !isRaffleType && !values.hasRaffle && (_jsx(Text, { size: "sm", color: "muted", children: "Enable the toggle above to attach a raffle draw to this event. Not applicable for this event type by default." })), showRaffleConfig && (_jsxs(Stack, { gap: "md", rounded: "xl", border: "default", padding: "md", children: [_jsxs(Grid, { cols: 2, gap: "sm", children: [_jsx(Select, { label: "Raffle type", value: values.type === "spin_wheel" ? "spin_wheel" : values.raffleType, options: RAFFLE_TYPE_OPTIONS, onChange: (e) => onChange({ raffleType: e.target.value }), disabled: values.type === "spin_wheel" }), _jsx(Input, { label: "Top N (for top-N raffle types)", type: "number", value: values.raffleTopN, onChange: (e) => onChange({ raffleTopN: e.target.value }), placeholder: "10" })] }), _jsx(Input, { label: "Prize description", value: values.rafflePrize, onChange: (e) => onChange({ rafflePrize: e.target.value }), placeholder: "\u20B92,000 store credit + exclusive Pikachu sticker" }), _jsxs(Div, { children: [_jsx(Text, { size: "sm", weight: "medium", className: "mb-1", children: "Coupon for winner (optional)" }), _jsx(CouponInlineSelect, { scope: "admin", value: values.rafflePrizeCouponId, onChange: (id) => onChange({ rafflePrizeCouponId: id ?? "" }), placeholder: "Search coupons\u2026", allowCreate: false })] }), _jsxs(Div, { children: [_jsx(Text, { size: "sm", weight: "medium", className: "mb-1", children: "Prize products (optional)" }), _jsx(ProductInlineSelect, { scope: "admin", multiple: true, value: values.rafflePrizeProductIds, onChange: (ids) => onChange({ rafflePrizeProductIds: ids }), placeholder: "Search products to feature as prizes\u2026" }), _jsx(Text, { size: "xs", color: "muted", className: "mt-1", children: "Products shown to winners or displayed as the prize showcase." })] }), isSpinMode && (_jsxs(Stack, { gap: "sm", rounded: "lg", border: "default", padding: "sm", children: [_jsx(Text, { size: "xs", weight: "medium", color: "muted", children: "Spin prizes (weighted random)" }), values.spinPrizes.length === 0 && (_jsx(Text, { size: "xs", color: "muted", children: "No spin prizes yet. Add at least one to enable spinning." })), values.spinPrizes.map((p) => (_jsxs(Grid, { gap: "xs", className: "grid-cols-12 items-end", children: [_jsx(Div, { className: "col-span-5", children: _jsx(Input, { label: "Label", value: p.label, onChange: (e) => onChange({ spinPrizes: values.spinPrizes.map((sp) => sp.id === p.id ? { ...sp, label: e.target.value } : sp) }), placeholder: "\u20B9100 off" }) }), _jsxs(Div, { className: "col-span-3", children: [_jsx(Text, { size: "xs", weight: "medium", className: "mb-1", children: "Coupon" }), _jsx(CouponInlineSelect, { scope: "admin", value: p.couponId ?? "", onChange: (id) => onChange({ spinPrizes: values.spinPrizes.map((sp) => sp.id === p.id ? { ...sp, couponId: id || undefined } : sp) }), placeholder: "Search\u2026", allowCreate: false })] }), _jsx(Div, { className: "col-span-2", children: _jsx(Input, { label: "Weight", type: "number", value: String(p.weight), onChange: (e) => onChange({ spinPrizes: values.spinPrizes.map((sp) => sp.id === p.id ? { ...sp, weight: Number(e.target.value) || 0 } : sp) }) }) }), _jsx(Row, { centered: true, className: "col-span-1 pb-2", children: _jsx(Toggle, { checked: p.isActive, onChange: (v) => onChange({ spinPrizes: values.spinPrizes.map((sp) => sp.id === p.id ? { ...sp, isActive: v } : sp) }), label: "" }) }), _jsx(Row, { centered: true, className: "col-span-1 pb-2", children: _jsx(Button, { variant: "ghost", type: "button", onClick: () => onChange({ spinPrizes: values.spinPrizes.filter((sp) => sp.id !== p.id) }), className: CLS_REMOVE_BTN_LG, "aria-label": "Remove prize", children: "\u00D7" }) })] }, p.id))), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => onChange({ spinPrizes: [...values.spinPrizes, { id: `prize-${Date.now()}`, label: "", couponId: undefined, weight: 1, isActive: true }] }), children: "+ Add spin prize" }), _jsx(Input, { label: "Max spins per user", type: "number", value: values.spinMaxPerUser, onChange: (e) => onChange({ spinMaxPerUser: e.target.value }), placeholder: "1" }), _jsxs(Grid, { cols: 2, gap: "sm", children: [_jsx(Input, { label: "Spin window start", type: "datetime-local", value: values.spinWindowStart, onChange: (e) => onChange({ spinWindowStart: e.target.value }) }), _jsx(Input, { label: "Spin window end", type: "datetime-local", value: values.spinWindowEnd, onChange: (e) => onChange({ spinWindowEnd: e.target.value }) })] })] })), isEdit && (_jsxs(Stack, { gap: "xs", rounded: "lg", padding: "sm", className: CLS_RAFFLE_PANEL, children: [_jsxs(Row, { justify: "between", gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", className: CLS_RAFFLE_HEADING, children: raffleWinnerName ? `Winner: ${raffleWinnerName}` : "Raffle not yet triggered" }), _jsx(Button, { type: "button", variant: "primary", size: "sm", onClick: () => triggerRaffleMutation.mutate(), disabled: triggerRaffleMutation.isPending || Boolean(raffleWinnerName), children: triggerRaffleMutation.isPending ? "Triggering…" : raffleWinnerName ? "Already triggered" : "Trigger Raffle Now" })] }), raffleEntryCount !== null && _jsxs(Text, { size: "xs", className: CLS_RAFFLE_BODY, children: ["Pool size: ", raffleEntryCount] }), raffleGithubUrl && _jsxs(Text, { size: "xs", className: `break-all ${CLS_RAFFLE_BODY}`, children: ["Fairness proof: ", raffleGithubUrl] }), triggerMessage && _jsx(Text, { size: "xs", className: CLS_RAFFLE_HEADING, children: triggerMessage })] }))] }))] }));
|
|
328
350
|
},
|
|
329
351
|
},
|
|
330
352
|
];
|
|
331
353
|
const alertSection = eventQuery.error ? (_jsx(Alert, { variant: "error", title: "Could not load event", children: eventQuery.error instanceof Error ? eventQuery.error.message : "Unknown error" })) : null;
|
|
332
354
|
const formContent = (_jsxs(Stack, { gap: "sm", children: [alertSection, _jsx(StepForm, { steps: steps, values: draft, onChange: update, onComplete: () => { saveMutation.mutate(); }, formId: "admin-event", currentStep: currentStep, onStepChange: setCurrentStep, completeLabel: isEdit ? "Save Changes" : "Create Event", isLoading: isLoading }), saveMessage && (_jsx(Alert, { variant: saveMessage.toLowerCase().includes("fail") || saveMessage.toLowerCase().includes("error") ? "error" : "success", title: "Save status", children: saveMessage }))] }));
|
|
333
355
|
if (embedded) {
|
|
334
|
-
return _jsx(Div, { className:
|
|
356
|
+
return _jsx(Div, { className: `${__O.yAuto} ${__P.p4}`, children: formContent });
|
|
335
357
|
}
|
|
336
358
|
return (_jsx(StackedViewShell, { portal: "admin", ...rest, title: isEdit ? "Edit Event" : "Create Event", sections: [formContent] }));
|
|
337
359
|
}
|
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import React from "react";
|
|
4
4
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
5
|
-
import { Alert, Button, Input, Select, StackedViewShell, Text, } from "../../../ui";
|
|
5
|
+
import { Alert, Button, Div, Input, Select, StackedViewShell, Text, } from "../../../ui";
|
|
6
6
|
import { apiClient } from "../../../http";
|
|
7
7
|
import { DataTable } from "../../admin/components/DataTable";
|
|
8
8
|
import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
9
|
+
const __P = {
|
|
10
|
+
p4: "p-4",
|
|
11
|
+
};
|
|
9
12
|
const REVIEW_STATUS_OPTIONS = [
|
|
10
13
|
{ label: "All", value: "all" },
|
|
11
14
|
{ label: "Pending", value: "pending" },
|
|
@@ -107,7 +110,7 @@ export function AdminEventEntriesView({ eventId, entriesEndpoint, entryReviewEnd
|
|
|
107
110
|
{
|
|
108
111
|
key: "points",
|
|
109
112
|
header: "Points",
|
|
110
|
-
render: (row) => (_jsxs(
|
|
113
|
+
render: (row) => (_jsxs(Div, { className: "flex items-center gap-1.5", children: [_jsx("input", { type: "number", min: 0, className: "w-20 rounded border border-zinc-200 dark:border-zinc-600 bg-white dark:bg-zinc-800 text-sm px-2 py-1 text-zinc-800 dark:text-zinc-200 focus:outline-none focus:ring-2 focus:ring-primary/50", placeholder: "0", value: pointsInputs[row.id] ?? (row.points !== undefined ? String(row.points) : ""), onChange: (e) => setPointsInputs((prev) => ({ ...prev, [row.id]: e.target.value })) }), _jsx(Button, { size: "sm", variant: "outline", disabled: pointsMutation.isPending || !(row.id in pointsInputs), onClick: () => {
|
|
111
114
|
const val = Number(pointsInputs[row.id]);
|
|
112
115
|
if (!isNaN(val)) {
|
|
113
116
|
pointsMutation.mutate({ entryId: row.id, points: val, currentStatus: row.reviewStatus });
|
|
@@ -118,11 +121,11 @@ export function AdminEventEntriesView({ eventId, entriesEndpoint, entryReviewEnd
|
|
|
118
121
|
{
|
|
119
122
|
key: "actions",
|
|
120
123
|
header: "Actions",
|
|
121
|
-
render: (row) => (_jsxs(
|
|
124
|
+
render: (row) => (_jsxs(Div, { className: "flex items-center gap-2 flex-wrap", children: [_jsx(Button, { size: "sm", variant: "secondary", disabled: reviewMutation.isPending || row.reviewStatus === "approved", onClick: () => reviewMutation.mutate({ entryId: row.id, status: "approved" }), children: "Approve" }), _jsx(Button, { size: "sm", variant: "outline", disabled: reviewMutation.isPending || row.reviewStatus === "flagged", onClick: () => reviewMutation.mutate({ entryId: row.id, status: "flagged" }), children: "Flag" }), row.formResponses && Object.keys(row.formResponses).length > 0 && (_jsx(Button, { size: "sm", variant: "outline", onClick: () => setExpandedEntryId((prev) => (prev === row.id ? null : row.id)), children: expandedEntryId === row.id ? "Hide" : "Responses" }))] })),
|
|
122
125
|
},
|
|
123
126
|
], [reviewMutation, pointsMutation, pointsInputs, expandedEntryId]);
|
|
124
|
-
const statsSection = (_jsxs(
|
|
125
|
-
const filtersSection = (_jsxs(
|
|
127
|
+
const statsSection = (_jsxs(Div, { className: "grid grid-cols-1 sm:grid-cols-3 gap-3", children: [_jsx(Alert, { variant: "info", title: "Total entries", children: String(statsQuery.data?.stats?.totalEntries ?? 0) }), _jsx(Alert, { variant: "success", title: "Approved", children: String(statsQuery.data?.stats?.approvedEntries ?? 0) }), _jsx(Alert, { variant: "warning", title: "Flagged", children: String(statsQuery.data?.stats?.flaggedEntries ?? 0) })] }));
|
|
128
|
+
const filtersSection = (_jsxs(Div, { className: "grid grid-cols-1 md:grid-cols-3 gap-3", children: [_jsx(Input, { label: "Search entries", value: searchQuery, onChange: (event) => {
|
|
126
129
|
setPage(1);
|
|
127
130
|
setSearchQuery(event.target.value);
|
|
128
131
|
}, placeholder: "Search by user, email, or id" }), _jsx(Select, { label: "Review status", value: statusFilter, options: REVIEW_STATUS_OPTIONS, onChange: (event) => {
|
|
@@ -130,7 +133,7 @@ export function AdminEventEntriesView({ eventId, entriesEndpoint, entryReviewEnd
|
|
|
130
133
|
setStatusFilter(event.target.value);
|
|
131
134
|
} })] }));
|
|
132
135
|
const expandedEntry = expandedEntryId ? rows.find((r) => r.id === expandedEntryId) : null;
|
|
133
|
-
const responsesPanelSection = expandedEntry?.formResponses && Object.keys(expandedEntry.formResponses).length > 0 ? (_jsxs(
|
|
136
|
+
const responsesPanelSection = expandedEntry?.formResponses && Object.keys(expandedEntry.formResponses).length > 0 ? (_jsxs(Div, { className: `rounded-xl border border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-800 ${__P.p4} space-y-3`, children: [_jsxs(Text, { className: "text-sm font-semibold text-zinc-800 dark:text-zinc-200", children: ["Responses \u2014 ", expandedEntry.userDisplayName || expandedEntry.userId || "Anonymous"] }), _jsx(Div, { className: "space-y-2", children: Object.entries(expandedEntry.formResponses).map(([key, value]) => (_jsxs(Div, { className: "space-y-0.5", children: [_jsx(Text, { className: "text-xs font-medium text-zinc-500 dark:text-zinc-400", children: key }), _jsx(Text, { className: "text-sm text-zinc-800 dark:text-zinc-200 whitespace-pre-wrap break-words", children: Array.isArray(value) ? value.join(", ") : String(value ?? "—") })] }, key))) })] })) : null;
|
|
134
137
|
const tableSection = (_jsx(DataTable, { columns: columns, rows: rows, isLoading: entriesQuery.isLoading, currentPage: entriesQuery.data?.page ?? page, totalPages: entriesQuery.data?.totalPages ?? 1, onPageChange: setPage, emptyLabel: "No entries found" }));
|
|
135
138
|
const eventTitle = statsQuery.data?.event?.title;
|
|
136
139
|
return (_jsx(StackedViewShell, { portal: "admin", ...rest, title: eventTitle ? `${eventTitle} Entries` : "Event Entries", renderHeader: renderHeader, sections: [
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { sieveFilter, SIEVE_OP } from "@mohasinac/appkit";
|
|
4
|
+
import { sortBy } from "@mohasinac/appkit";
|
|
3
5
|
import React from "react";
|
|
4
6
|
import { FilterChipGroup, ListingLayout } from "../../../ui";
|
|
5
7
|
import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
@@ -29,13 +31,13 @@ export function AdminEventsView({ children, ...props }) {
|
|
|
29
31
|
searchPlaceholder: "Search events by title or type",
|
|
30
32
|
emptyLabel: "No events found",
|
|
31
33
|
filterKeys: ["status", "type"],
|
|
32
|
-
defaultSort: "
|
|
34
|
+
defaultSort: sortBy("startsAt", "DESC"),
|
|
33
35
|
queryKey: ["admin", "events", "listing"],
|
|
34
36
|
endpoint: ADMIN_ENDPOINTS.EVENTS,
|
|
35
37
|
sortOptions: [
|
|
36
|
-
{ value: "
|
|
38
|
+
{ value: sortBy("startsAt", "DESC"), label: "Starting soonest" },
|
|
37
39
|
{ value: "startsAt", label: "Starting latest" },
|
|
38
|
-
{ value: "
|
|
40
|
+
{ value: sortBy("createdAt", "DESC"), label: "Newest" },
|
|
39
41
|
{ value: "title", label: "Title A–Z" },
|
|
40
42
|
],
|
|
41
43
|
mapRows: (response) => toRecordArray(response.items).map((item, index) => ({
|
|
@@ -51,9 +53,9 @@ export function AdminEventsView({ children, ...props }) {
|
|
|
51
53
|
buildFilters: (state) => {
|
|
52
54
|
const parts = [];
|
|
53
55
|
if (state.status && state.status !== "All")
|
|
54
|
-
parts.push(
|
|
56
|
+
parts.push(sieveFilter("status", SIEVE_OP.EQ, state.status));
|
|
55
57
|
if (state.type && state.type !== "All")
|
|
56
|
-
parts.push(
|
|
58
|
+
parts.push(sieveFilter("type", SIEVE_OP.EQ, state.type));
|
|
57
59
|
return parts.join(",") || undefined;
|
|
58
60
|
},
|
|
59
61
|
primaryAction: {
|
|
@@ -8,6 +8,12 @@ import { EVENT_FIELDS } from "../schemas";
|
|
|
8
8
|
import { EventStatusBadge } from "./EventStatusBadge";
|
|
9
9
|
import { ROUTES } from "../../../next";
|
|
10
10
|
import { useLongPress } from "../../../react/hooks/useLongPress";
|
|
11
|
+
const __P = {
|
|
12
|
+
p4: "p-4",
|
|
13
|
+
};
|
|
14
|
+
const __O = {
|
|
15
|
+
hidden: "overflow-hidden",
|
|
16
|
+
};
|
|
11
17
|
const TYPE_ICONS = {
|
|
12
18
|
sale: "🏷️",
|
|
13
19
|
offer: "🎁",
|
|
@@ -25,6 +31,6 @@ export function EventCard({ event, labels = {}, onParticipate, className = "", s
|
|
|
25
31
|
const msLeft = endsAt.getTime() - now.getTime();
|
|
26
32
|
const daysLeft = Math.max(0, Math.ceil(msLeft / (1000 * 60 * 60 * 24)));
|
|
27
33
|
const detailHref = String(ROUTES.PUBLIC.EVENT_DETAIL(event.slug ?? event.id));
|
|
28
|
-
return (_jsxs(Article, { className: `group relative flex h-full ${LAYOUT.cardHeight.event} flex-col overflow-hidden rounded-xl border bg-white shadow-sm transition-shadow hover:shadow-md dark:bg-slate-900 ${isSelected ? "border-primary outline outline-2 outline-primary" : "border-zinc-200 dark:border-slate-700"} ${className}`, onMouseDown: onSelect && !isSelected ? longPress.onMouseDown : undefined, onMouseUp: onSelect && !isSelected ? longPress.onMouseUp : undefined, onMouseLeave: onSelect && !isSelected ? longPress.onMouseLeave : undefined, onTouchStart: onSelect && !isSelected ? longPress.onTouchStart : undefined, onTouchEnd: onSelect && !isSelected ? longPress.onTouchEnd : undefined, children: [onSelect && (_jsx(BaseListingCard.Checkbox, { selected: isSelected, onSelect: (e) => { e.preventDefault(); onSelect(event.id, !isSelected); }, label: isSelected ? "Deselect event" : "Select event", position: "top-2 left-2", className: selectable || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), _jsx(Link, { href: detailHref, className: "block flex-shrink-0", children: event.coverImageUrl ? (_jsx(Div, { className:
|
|
34
|
+
return (_jsxs(Article, { className: `group relative flex h-full ${LAYOUT.cardHeight.event} flex-col overflow-hidden rounded-xl border bg-white shadow-sm transition-shadow hover:shadow-md dark:bg-slate-900 ${isSelected ? "border-primary outline outline-2 outline-primary" : "border-zinc-200 dark:border-slate-700"} ${className}`, onMouseDown: onSelect && !isSelected ? longPress.onMouseDown : undefined, onMouseUp: onSelect && !isSelected ? longPress.onMouseUp : undefined, onMouseLeave: onSelect && !isSelected ? longPress.onMouseLeave : undefined, onTouchStart: onSelect && !isSelected ? longPress.onTouchStart : undefined, onTouchEnd: onSelect && !isSelected ? longPress.onTouchEnd : undefined, children: [onSelect && (_jsx(BaseListingCard.Checkbox, { selected: isSelected, onSelect: (e) => { e.preventDefault(); onSelect(event.id, !isSelected); }, label: isSelected ? "Deselect event" : "Select event", position: "top-2 left-2", className: selectable || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), _jsx(Link, { href: detailHref, className: "block flex-shrink-0", children: event.coverImageUrl ? (_jsx(Div, { className: `aspect-video ${__O.hidden}`, children: _jsx(Div, { role: "img", "aria-label": safeTitle, className: "h-full w-full bg-cover bg-center transition-transform duration-300 group-hover:scale-105", style: { backgroundImage: `url(${event.coverImageUrl})` } }) })) : (_jsx(Div, { className: "aspect-video bg-gradient-to-br from-zinc-100 to-zinc-200 dark:from-slate-800 dark:to-slate-700 flex items-center justify-center", children: _jsx(Span, { className: "text-5xl opacity-40", "aria-hidden": "true", children: TYPE_ICONS[event.type] }) })) }), _jsxs(Div, { className: `flex flex-1 flex-col ${__P.p4}`, children: [_jsxs(Div, { className: "flex items-start justify-between gap-2 mb-2", children: [_jsx(Span, { size: "lg", "aria-hidden": "true", children: TYPE_ICONS[event.type] }), _jsx(EventStatusBadge, { status: event.status })] }), _jsx(Link, { href: detailHref, className: "block", children: _jsx(Heading, { level: 3, className: "font-semibold text-gray-900 dark:text-zinc-100 text-base leading-snug mb-1 group-hover:text-primary transition-colors", children: safeTitle }) }), _jsx(RichText, { html: normalizeRichTextHtml(event.description ?? ""), proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: `mb-3 ${THEME_CONSTANTS.utilities.textClamp3} text-sm text-zinc-600 dark:text-zinc-400` }), _jsxs(Div, { className: "mb-3 mt-auto flex items-center justify-between text-xs text-zinc-500 dark:text-zinc-400", children: [event.status === EVENT_FIELDS.STATUS_VALUES.ACTIVE &&
|
|
29
35
|
daysLeft > 0 && _jsxs(Span, { children: ["\u23F1 ", daysLeft, "d remaining"] }), _jsxs(Span, { children: ["\uD83D\uDC65 ", event.stats.totalEntries, " ", labels.entries ?? "entries"] })] }), event.status === EVENT_FIELDS.STATUS_VALUES.ACTIVE && onParticipate ? (_jsx(Button, { type: "button", onClick: () => onParticipate(event), className: "w-full rounded-lg bg-primary py-2 text-sm font-medium text-white transition-colors hover:bg-primary-600", children: labels.participate ?? "Participate" })) : (_jsxs(TextLink, { href: detailHref, className: "inline-flex w-full items-center justify-center gap-1.5 rounded-lg border border-zinc-300 px-3 py-2 text-sm font-medium text-zinc-700 transition-colors hover:bg-zinc-100 dark:border-slate-600 dark:text-zinc-200 dark:hover:bg-slate-800", children: [labels.viewDetails ?? "View details", " \u2192"] }))] })] }));
|
|
30
36
|
}
|
|
@@ -24,7 +24,7 @@ export declare const EVENT_ADMIN_SORT_OPTIONS: readonly [{
|
|
|
24
24
|
readonly value: string;
|
|
25
25
|
readonly label: "Ends Soonest";
|
|
26
26
|
}, {
|
|
27
|
-
readonly value:
|
|
27
|
+
readonly value: string;
|
|
28
28
|
readonly label: "Most Entries";
|
|
29
29
|
}, {
|
|
30
30
|
readonly value: string;
|
|
@@ -49,7 +49,7 @@ export declare const EVENT_SELLER_SORT_OPTIONS: readonly [{
|
|
|
49
49
|
readonly value: string;
|
|
50
50
|
readonly label: "Ends Soonest";
|
|
51
51
|
}, {
|
|
52
|
-
readonly value:
|
|
52
|
+
readonly value: string;
|
|
53
53
|
readonly label: "Most Entries";
|
|
54
54
|
}, {
|
|
55
55
|
readonly value: string;
|
|
@@ -68,7 +68,7 @@ export declare const EVENT_PUBLIC_SORT_OPTIONS: readonly [{
|
|
|
68
68
|
readonly value: string;
|
|
69
69
|
readonly label: "Title Z–A";
|
|
70
70
|
}, {
|
|
71
|
-
readonly value:
|
|
71
|
+
readonly value: string;
|
|
72
72
|
readonly label: "Most Entries";
|
|
73
73
|
}];
|
|
74
74
|
export declare const EVENT_SORT_OPTIONS: readonly [{
|
|
@@ -90,7 +90,7 @@ export declare const EVENT_SORT_OPTIONS: readonly [{
|
|
|
90
90
|
readonly value: string;
|
|
91
91
|
readonly label: "Ends Soonest";
|
|
92
92
|
}, {
|
|
93
|
-
readonly value:
|
|
93
|
+
readonly value: string;
|
|
94
94
|
readonly label: "Most Entries";
|
|
95
95
|
}, {
|
|
96
96
|
readonly value: string;
|
|
@@ -20,7 +20,7 @@ export const EVENT_ADMIN_SORT_OPTIONS = [
|
|
|
20
20
|
{ value: sortBy(EVENT_FIELDS.STARTS_AT, "ASC"), label: "Starts Soonest" },
|
|
21
21
|
{ value: sortBy(EVENT_FIELDS.ENDS_AT), label: "Ends Latest" },
|
|
22
22
|
{ value: sortBy(EVENT_FIELDS.ENDS_AT, "ASC"), label: "Ends Soonest" },
|
|
23
|
-
{ value: "
|
|
23
|
+
{ value: sortBy("stats.totalEntries", "DESC"), label: "Most Entries" },
|
|
24
24
|
{ value: sortBy(EVENT_FIELDS.CREATED_AT), label: "Newest First" },
|
|
25
25
|
];
|
|
26
26
|
export const EVENT_SELLER_SORT_OPTIONS = EVENT_ADMIN_SORT_OPTIONS;
|
|
@@ -29,7 +29,7 @@ export const EVENT_PUBLIC_SORT_OPTIONS = [
|
|
|
29
29
|
{ value: sortBy(EVENT_FIELDS.STARTS_AT), label: "Starts Latest" },
|
|
30
30
|
{ value: sortBy(EVENT_FIELDS.TITLE, "ASC"), label: "Title A–Z" },
|
|
31
31
|
{ value: sortBy(EVENT_FIELDS.TITLE), label: "Title Z–A" },
|
|
32
|
-
{ value: "
|
|
32
|
+
{ value: sortBy("stats.totalEntries", "DESC"), label: "Most Entries" },
|
|
33
33
|
];
|
|
34
34
|
// Backward-compatible alias.
|
|
35
35
|
export const EVENT_SORT_OPTIONS = EVENT_ADMIN_SORT_OPTIONS;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Div } from "../../../ui";
|
|
2
3
|
export function EventFormDrawer({ isOpen, onClose, renderHeader, renderBaseFields, renderMediaFields, renderTypeConfig, renderTypeSelector, renderFooter, className = "", }) {
|
|
3
4
|
if (!isOpen)
|
|
4
5
|
return null;
|
|
5
|
-
return (_jsxs(
|
|
6
|
+
return (_jsxs(Div, { className: `space-y-6 ${className}`, children: [renderHeader?.(), renderTypeSelector?.(), renderBaseFields?.(), renderMediaFields?.(), renderTypeConfig?.(), renderFooter?.()] }));
|
|
6
7
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import React from "react";
|
|
3
|
-
import { Span, Text } from "../../../ui";
|
|
3
|
+
import { Div, Span, Text } from "../../../ui";
|
|
4
4
|
export function EventLeaderboard({ isLoading = false, isEmpty = false, renderList, renderEntry, entries = [], renderEmpty, renderSkeleton, labels = {}, className = "", }) {
|
|
5
5
|
if (isLoading) {
|
|
6
6
|
if (renderSkeleton)
|
|
7
7
|
return _jsx(_Fragment, { children: renderSkeleton() });
|
|
8
|
-
return _jsx(
|
|
8
|
+
return _jsx(Div, { className: "flex justify-center py-8", children: "Loading\u2026" });
|
|
9
9
|
}
|
|
10
10
|
if (isEmpty) {
|
|
11
11
|
if (renderEmpty)
|
|
@@ -13,6 +13,6 @@ export function EventLeaderboard({ isLoading = false, isEmpty = false, renderLis
|
|
|
13
13
|
return (_jsx(Text, { variant: "secondary", size: "sm", className: "text-center py-4", children: labels.noEntries ?? "No entries yet." }));
|
|
14
14
|
}
|
|
15
15
|
if (renderList)
|
|
16
|
-
return _jsx(
|
|
17
|
-
return (_jsx(
|
|
16
|
+
return _jsx(Div, { className: className, children: renderList() });
|
|
17
|
+
return (_jsx(Div, { className: `space-y-2 ${className}`, children: entries.map((entry, i) => renderEntry ? (_jsx(React.Fragment, { children: renderEntry(entry, i) }, entry.userId)) : (_jsxs("div", { className: "flex items-center justify-between p-3 rounded-xl border", "data-section": "eventleaderboard-div-282", children: [_jsxs(Span, { weight: "medium", children: ["#", entry.rank, " ", entry.userDisplayName] }), _jsxs(Span, { children: [entry.totalPoints, " ", labels.points ?? "pts"] })] }, entry.userId))) }));
|
|
18
18
|
}
|
|
@@ -5,6 +5,9 @@ import Link from "next/link";
|
|
|
5
5
|
import { Div, Heading, Stack, Text } from "../../../ui";
|
|
6
6
|
import { Button } from "../../../ui/components/Button";
|
|
7
7
|
import { ROUTES } from "../../../next/routing/route-map";
|
|
8
|
+
const __P = {
|
|
9
|
+
p6: "p-6",
|
|
10
|
+
};
|
|
8
11
|
/**
|
|
9
12
|
* `EventOfferCard` — W1-18 — offer event UI noted as missing in the plan.
|
|
10
13
|
* Renders a coupon code with copy-to-clipboard + a CTA to the filtered
|
|
@@ -25,5 +28,5 @@ export function EventOfferCard({ couponCode, offerDescription, title = "Exclusiv
|
|
|
25
28
|
/* clipboard unavailable — leave button as-is */
|
|
26
29
|
}
|
|
27
30
|
};
|
|
28
|
-
return (_jsx(Div, { className:
|
|
31
|
+
return (_jsx(Div, { className: `rounded-2xl border border-zinc-200 dark:border-zinc-700 ${__P.p6}`, children: _jsxs(Stack, { gap: "md", children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 2, className: "text-2xl font-semibold", children: title }), offerDescription ? (_jsx(Text, { className: "text-sm text-zinc-600 dark:text-zinc-400", children: offerDescription })) : null] }), _jsxs(Div, { className: "flex items-center gap-3 rounded-lg bg-zinc-50 dark:bg-zinc-900 px-4 py-3", children: [_jsx("code", { className: "flex-1 font-mono text-lg font-bold text-zinc-900 dark:text-zinc-100", children: couponCode }), _jsx(Button, { type: "button", variant: "outline", onClick: copyCode, children: copied ? "Copied!" : "Copy code" })] }), _jsx(Div, { children: _jsx(Link, { href: href, children: _jsx(Button, { variant: "primary", children: "Apply at checkout" }) }) })] }) }));
|
|
29
32
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Div } from "../../../ui";
|
|
2
3
|
export function EventParticipateView({ isLoading = false, isSubmitted = false, renderEventInfo, renderForm, renderAction, renderSuccess, renderSkeleton, renderAuthGate, className = "", }) {
|
|
3
4
|
if (isLoading) {
|
|
4
5
|
if (renderSkeleton)
|
|
5
6
|
return _jsx(_Fragment, { children: renderSkeleton() });
|
|
6
|
-
return _jsx(
|
|
7
|
+
return _jsx(Div, { className: "flex justify-center py-20", children: "Loading\u2026" });
|
|
7
8
|
}
|
|
8
9
|
if (renderAuthGate)
|
|
9
10
|
return _jsx(_Fragment, { children: renderAuthGate() });
|
|
10
11
|
if (isSubmitted && renderSuccess)
|
|
11
12
|
return _jsx(_Fragment, { children: renderSuccess() });
|
|
12
|
-
return (_jsxs(
|
|
13
|
+
return (_jsxs(Div, { className: `max-w-xl mx-auto space-y-6 ${className}`, children: [renderEventInfo?.(), renderForm?.(), renderAction?.()] }));
|
|
13
14
|
}
|
|
@@ -3,7 +3,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { useState } from "react";
|
|
4
4
|
import { useAuth } from "../../../react/contexts/SessionContext";
|
|
5
5
|
import { ROUTES } from "../../../next";
|
|
6
|
-
import { LoginRequiredModal, Text } from "../../../ui";
|
|
6
|
+
import { Div, LoginRequiredModal, Span, Text } from "../../../ui";
|
|
7
|
+
const CLS_THANKS_BOX = "rounded-xl border border-green-200 dark:border-green-800 bg-success-surface px-6 py-8 text-center space-y-2";
|
|
7
8
|
export function EventPollWidget({ eventId, pollConfig, eventStatus, totalEntries, entriesEndpoint, className = "", }) {
|
|
8
9
|
const { user } = useAuth();
|
|
9
10
|
const endpoint = entriesEndpoint ?? `/api/events/${eventId}/entries`;
|
|
@@ -56,13 +57,13 @@ export function EventPollWidget({ eventId, pollConfig, eventStatus, totalEntries
|
|
|
56
57
|
}
|
|
57
58
|
};
|
|
58
59
|
if (isEnded) {
|
|
59
|
-
return (_jsxs(
|
|
60
|
+
return (_jsxs(Div, { className: `rounded-xl border border-zinc-200 dark:border-zinc-700 px-5 py-4 space-y-3 ${className}`, children: [_jsx(Text, { className: "text-sm font-medium text-zinc-500 dark:text-zinc-400", children: "This poll has closed." }), totalEntries !== undefined && (_jsxs(Text, { className: "text-sm text-zinc-400 dark:text-zinc-400", children: [totalEntries.toLocaleString(), " vote", totalEntries !== 1 ? "s" : "", " cast"] })), _jsx(Div, { className: "space-y-2", children: pollConfig.options.map((opt) => (_jsx(Div, { className: "rounded-lg border border-zinc-100 dark:border-zinc-800 px-4 py-2.5 text-sm text-zinc-600 dark:text-zinc-400", children: opt.label }, opt.id))) })] }));
|
|
60
61
|
}
|
|
61
62
|
if (pollConfig.requireLogin && !user) {
|
|
62
|
-
return (_jsxs(
|
|
63
|
+
return (_jsxs(Div, { className: `rounded-xl border border-zinc-200 dark:border-zinc-700 px-6 py-8 text-center space-y-3 ${className}`, children: [_jsx(Text, { className: "font-semibold text-zinc-900 dark:text-zinc-100", children: "Login to vote" }), _jsx(Text, { className: "text-sm text-zinc-500 dark:text-zinc-400", children: "You need an account to participate in this poll." }), _jsx("a", { href: String(ROUTES.AUTH.LOGIN), className: "inline-block rounded-xl bg-primary px-6 py-2.5 text-sm font-semibold text-white hover:bg-primary-600", children: "Log In" })] }));
|
|
63
64
|
}
|
|
64
65
|
if (isSubmitted) {
|
|
65
|
-
return (_jsxs(
|
|
66
|
+
return (_jsxs(Div, { className: `${CLS_THANKS_BOX} ${className}`, children: [_jsx(Text, { className: "font-semibold text-success", children: "Vote recorded!" }), _jsx(Text, { className: "text-sm text-zinc-500 dark:text-zinc-400", children: "Thanks for participating." })] }));
|
|
66
67
|
}
|
|
67
|
-
return (_jsxs(
|
|
68
|
+
return (_jsxs(Div, { className: `space-y-4 ${className}`, children: [_jsx(LoginRequiredModal, { isOpen: showLoginModal, onClose: () => setShowLoginModal(false), message: "You need to be signed in to vote in this poll. Please log in or create an account to continue." }), _jsx(Text, { className: "text-sm font-medium text-zinc-700 dark:text-zinc-200", children: isMulti ? "Select all that apply:" : "Choose one:" }), _jsx(Div, { className: "space-y-2", children: pollConfig.options.map((opt) => (_jsxs("label", { className: "flex items-center gap-3 cursor-pointer rounded-lg border border-zinc-200 dark:border-zinc-700 px-4 py-3 hover:bg-zinc-50 dark:hover:bg-zinc-800 transition-colors", children: [_jsx("input", { type: isMulti ? "checkbox" : "radio", name: `poll-${eventId}`, value: opt.id, checked: selectedVotes.includes(opt.id), onChange: () => toggleVote(opt.id), className: "accent-primary" }), _jsx(Span, { size: "sm", className: "text-zinc-700 dark:text-zinc-300", children: opt.label })] }, opt.id))) }), pollConfig.allowComment && (_jsx("textarea", { value: comment, onChange: (e) => setComment(e.target.value), placeholder: "Add a comment (optional)", rows: 3, className: "w-full rounded-lg border border-zinc-200 dark:border-zinc-700 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-800 dark:text-zinc-200 placeholder:text-zinc-400 focus:outline-none focus:ring-2 focus:ring-primary" })), error && _jsx(Text, { className: "text-sm text-error", children: error }), _jsx("button", { type: "button", onClick: handleSubmit, disabled: isLoading || selectedVotes.length === 0, className: "w-full rounded-xl bg-primary px-6 py-3 text-sm font-semibold text-white hover:bg-primary-600 disabled:opacity-60", children: isLoading ? "Submitting…" : "Submit Vote" })] }));
|
|
68
69
|
}
|
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useState } from "react";
|
|
4
4
|
import { Button } from "../../../ui/components/Button";
|
|
5
|
-
import { Div, Heading, Stack, Text } from "../../../ui";
|
|
5
|
+
import { Div, Heading, Label, Span, Stack, Text } from "../../../ui";
|
|
6
6
|
import { Badge } from "../../../ui/components/Badge";
|
|
7
|
+
const __P = {
|
|
8
|
+
p6: "p-6",
|
|
9
|
+
};
|
|
7
10
|
/**
|
|
8
11
|
* `EventRaffleEntryForm` — W1-18 — fills the gap noted in the plan ("Raffle
|
|
9
12
|
* entry form (71 LOC stub) — no entry form"). Renders the prize hero,
|
|
@@ -33,5 +36,5 @@ export function EventRaffleEntryForm({ eventId: _eventId, prizeLabel, raffleType
|
|
|
33
36
|
: raffleType === "top_n_participants"
|
|
34
37
|
? `Earliest ${topN ?? "N"} entries qualify.`
|
|
35
38
|
: "Spin the wheel to claim your prize.";
|
|
36
|
-
return (_jsxs(Div, { className:
|
|
39
|
+
return (_jsxs(Div, { className: `rounded-2xl border border-zinc-200 dark:border-zinc-700 ${__P.p6} space-y-4`, children: [prizeLabel ? (_jsxs(Stack, { gap: "xs", children: [_jsx(Badge, { variant: "warning", children: "Prize" }), _jsx(Heading, { level: 2, className: "text-2xl font-bold", children: prizeLabel })] })) : null, _jsx(Text, { className: "text-sm text-zinc-600 dark:text-zinc-400", children: eligibilityCopy }), submitted ? (_jsx(Div, { className: "rounded-lg bg-success-surface px-4 py-3 text-sm text-success", children: "You're in. Check the leaderboard for results." })) : overLimit ? (_jsxs(Div, { className: "rounded-lg bg-warning-surface px-4 py-3 text-sm text-warning", children: ["You've used all ", maxEntriesPerUser, " entry slot", maxEntriesPerUser === 1 ? "" : "s", " for this raffle."] })) : (_jsxs("form", { onSubmit: handleSubmit, className: "space-y-3", children: [_jsxs(Label, { htmlFor: "raffle-message", className: "block text-sm font-medium", children: ["Message ", _jsx(Span, { className: "text-zinc-400", children: "(optional)" })] }), _jsx("textarea", { id: "raffle-message", value: message, onChange: (e) => setMessage(e.target.value), rows: 3, maxLength: 500, className: "w-full rounded-lg border border-zinc-300 dark:border-zinc-700 px-3 py-2 text-sm bg-white dark:bg-zinc-900 focus:outline-none focus:ring-2 focus:ring-[var(--appkit-color-primary)]", placeholder: "Share why you'd like to win", disabled: busy }), _jsx(Button, { type: "submit", variant: "primary", disabled: busy, children: busy ? "Submitting…" : "Enter raffle" })] }))] }));
|
|
37
40
|
}
|