@mohasinac/appkit 2.7.26 → 2.7.30
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 +2 -2
- package/dist/_internal/client/features/digital-code/CodeRevealPanel.js +2 -2
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +1 -1
- package/dist/_internal/server/features/checkout/actions.js +42 -35
- package/dist/_internal/server/features/classified/adapters.d.ts +21 -0
- package/dist/_internal/server/features/classified/adapters.js +24 -0
- package/dist/_internal/server/features/classified/index.d.ts +3 -0
- package/dist/_internal/server/features/classified/index.js +3 -0
- package/dist/_internal/server/features/classified/metadata.d.ts +8 -0
- package/dist/_internal/server/features/classified/metadata.js +43 -0
- package/dist/_internal/server/features/classified/og.d.ts +30 -0
- package/dist/_internal/server/features/classified/og.js +76 -0
- package/dist/_internal/server/features/digital-code/adapters.d.ts +21 -0
- package/dist/_internal/server/features/digital-code/adapters.js +29 -0
- package/dist/_internal/server/features/digital-code/index.d.ts +3 -0
- package/dist/_internal/server/features/digital-code/index.js +3 -0
- package/dist/_internal/server/features/digital-code/metadata.d.ts +8 -0
- package/dist/_internal/server/features/digital-code/metadata.js +36 -0
- package/dist/_internal/server/features/digital-code/og.d.ts +27 -0
- package/dist/_internal/server/features/digital-code/og.js +77 -0
- package/dist/_internal/server/features/live/adapters.d.ts +21 -0
- package/dist/_internal/server/features/live/adapters.js +34 -0
- package/dist/_internal/server/features/live/index.d.ts +3 -0
- package/dist/_internal/server/features/live/index.js +3 -0
- package/dist/_internal/server/features/live/metadata.d.ts +8 -0
- package/dist/_internal/server/features/live/metadata.js +39 -0
- package/dist/_internal/server/features/live/og.d.ts +27 -0
- package/dist/_internal/server/features/live/og.js +72 -0
- package/dist/_internal/server/features/promotions/actions.js +4 -3
- package/dist/_internal/server/jobs/core/onOrderCreate.js +19 -16
- package/dist/_internal/server/jobs/core/onOrderStatusChange.js +25 -22
- package/dist/_internal/server/jobs/core/onProductWrite.js +48 -58
- package/dist/_internal/shared/actions/action-registry.js +310 -8
- package/dist/_internal/shared/features/blog/schema.d.ts +4 -4
- package/dist/_internal/shared/features/brands/schema.d.ts +5 -5
- package/dist/_internal/shared/features/cart/schema.d.ts +18 -18
- package/dist/_internal/shared/features/categories/bundle-copy.d.ts +1 -1
- package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +38 -38
- package/dist/_internal/shared/features/events/schema.d.ts +8 -8
- package/dist/_internal/shared/features/orders/schema.d.ts +8 -8
- package/dist/_internal/shared/features/products/schema.d.ts +42 -42
- package/dist/_internal/shared/features/promotions/schema.d.ts +4 -4
- package/dist/_internal/shared/features/reviews/schema.d.ts +1 -1
- package/dist/_internal/shared/media/limits.js +4 -3
- package/dist/client.d.ts +2 -0
- package/dist/client.js +1 -0
- package/dist/configs/next.js +4 -0
- package/dist/constants/table-keys.d.ts +6 -0
- package/dist/constants/table-keys.js +9 -0
- package/dist/core/hooks/useSyncManager.js +9 -8
- package/dist/features/about/components/FeesView.js +10 -7
- package/dist/features/about/components/HelpPageView.js +10 -1
- package/dist/features/about/components/HowAuctionsWorkView.js +10 -1
- package/dist/features/about/components/HowCheckoutWorksView.js +10 -1
- package/dist/features/about/components/HowOffersWorkView.js +10 -1
- package/dist/features/about/components/HowOrdersWorkView.js +10 -1
- package/dist/features/about/components/HowPayoutsWorkView.js +10 -1
- package/dist/features/about/components/HowPreOrdersWorkView.js +10 -1
- package/dist/features/about/components/HowReviewsWorkView.js +10 -1
- package/dist/features/about/components/PublicProfileView.js +44 -14
- package/dist/features/about/components/SecurityPrivacyView.js +7 -1
- package/dist/features/account/components/AddressesIndexListing.js +2 -2
- package/dist/features/account/components/NotificationBell.js +27 -16
- package/dist/features/account/components/NotificationPreferencesPanel.d.ts +9 -0
- package/dist/features/account/components/NotificationPreferencesPanel.js +91 -0
- package/dist/features/account/components/UserSidebar.js +4 -4
- package/dist/features/account/components/UserSupportView.js +16 -6
- package/dist/features/account/components/index.d.ts +2 -0
- package/dist/features/account/components/index.js +1 -0
- package/dist/features/account/schemas/index.d.ts +4 -4
- package/dist/features/account/types/index.d.ts +34 -0
- package/dist/features/admin/actions/admin-actions.js +4 -3
- package/dist/features/admin/actions/notification-actions.d.ts +24 -22
- package/dist/features/admin/actions/notification-actions.js +122 -22
- package/dist/features/admin/components/AdminAdEditorView.js +29 -15
- package/dist/features/admin/components/AdminAdsView.js +22 -28
- package/dist/features/admin/components/AdminAllEventEntriesView.js +6 -1
- package/dist/features/admin/components/AdminBidsView.js +10 -3
- package/dist/features/admin/components/AdminBlogEditorView.js +2 -2
- package/dist/features/admin/components/AdminBlogView.js +8 -3
- package/dist/features/admin/components/AdminBrandsView.js +7 -2
- package/dist/features/admin/components/AdminBundleEditorView.js +5 -2
- package/dist/features/admin/components/AdminCarouselEditorView.js +6 -3
- package/dist/features/admin/components/AdminCarouselView.js +13 -7
- package/dist/features/admin/components/AdminCategoriesView.js +8 -3
- package/dist/features/admin/components/AdminCategoryEditorView.js +2 -2
- package/dist/features/admin/components/AdminContactView.js +6 -1
- package/dist/features/admin/components/AdminCouponEditorView.js +8 -2
- package/dist/features/admin/components/AdminCouponsView.js +6 -1
- package/dist/features/admin/components/AdminEmployeeEditorView.js +12 -9
- package/dist/features/admin/components/AdminFaqEditorView.js +2 -2
- package/dist/features/admin/components/AdminFaqsView.js +7 -2
- package/dist/features/admin/components/AdminFeaturesView.js +4 -3
- package/dist/features/admin/components/AdminMediaView.js +9 -8
- package/dist/features/admin/components/AdminNavigationView.js +10 -17
- package/dist/features/admin/components/AdminNewsletterView.js +6 -1
- package/dist/features/admin/components/AdminNotificationsView.js +11 -3
- package/dist/features/admin/components/AdminOrdersView.js +6 -1
- package/dist/features/admin/components/AdminPayoutsView.js +10 -3
- package/dist/features/admin/components/AdminPrizeDrawsView.js +10 -3
- package/dist/features/admin/components/AdminProductsView.js +18 -12
- package/dist/features/admin/components/AdminReviewsView.js +33 -24
- package/dist/features/admin/components/AdminScammerEditorView.js +3 -2
- package/dist/features/admin/components/AdminScammersView.js +28 -26
- package/dist/features/admin/components/AdminSectionsView.js +112 -99
- package/dist/features/admin/components/AdminSessionsView.js +10 -3
- package/dist/features/admin/components/AdminSidebar.js +4 -4
- package/dist/features/admin/components/AdminSiteSettingsView.js +45 -4
- package/dist/features/admin/components/AdminStoresView.js +6 -1
- package/dist/features/admin/components/AdminSublistingCategoriesView.js +0 -1
- package/dist/features/admin/components/AdminSupportTicketDetailView.js +1 -1
- package/dist/features/admin/components/AdminSupportTicketsView.js +32 -34
- package/dist/features/admin/components/AdminTeamView.js +6 -1
- package/dist/features/admin/components/AdminUserEditorView.js +8 -15
- package/dist/features/admin/components/AdminUsersView.js +6 -1
- package/dist/features/admin/components/AdminViewCards.js +4 -3
- package/dist/features/admin/components/DashboardStats.js +2 -2
- package/dist/features/admin/components/DataTable.js +2 -2
- package/dist/features/admin/components/sections/adminSectionsTypes.js +4 -3
- package/dist/features/admin/repository/chat.repository.js +8 -8
- package/dist/features/admin/repository/site-settings.repository.d.ts +1 -0
- package/dist/features/admin/repository/site-settings.repository.js +11 -9
- package/dist/features/admin/schemas/firestore.d.ts +38 -0
- package/dist/features/admin/schemas/firestore.js +15 -0
- package/dist/features/auctions/components/AuctionDetailPageView.js +13 -19
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +18 -9
- package/dist/features/auctions/components/MarketplaceAuctionGrid.js +3 -2
- package/dist/features/auctions/components/index.d.ts +0 -1
- package/dist/features/auctions/components/index.js +0 -1
- package/dist/features/auctions/schemas/index.d.ts +14 -14
- package/dist/features/auth/actions/realtime-token-actions.js +19 -4
- package/dist/features/auth/components/RegisterForm.js +8 -4
- package/dist/features/auth/consent-otp.d.ts +2 -0
- package/dist/features/auth/consent-otp.js +8 -0
- package/dist/features/auth/schemas/firestore.d.ts +2 -0
- package/dist/features/auth/schemas/firestore.js +18 -25
- package/dist/features/auth/schemas/index.d.ts +2 -2
- package/dist/features/before-after/api/[id]/route.js +8 -6
- package/dist/features/before-after/schemas/index.d.ts +2 -2
- package/dist/features/blog/actions/blog-actions.d.ts +3 -3
- package/dist/features/blog/components/BlogIndexListing.js +21 -2
- package/dist/features/blog/components/BlogPostForm.js +11 -5
- package/dist/features/blog/components/BlogPostView.js +10 -2
- package/dist/features/blog/schemas/index.d.ts +18 -18
- package/dist/features/cart/components/CartDrawer.js +3 -2
- package/dist/features/cart/repository/cart.repository.js +4 -3
- package/dist/features/cart/utils/pending-ops.d.ts +1 -1
- package/dist/features/categories/api/[id]/route.js +4 -3
- package/dist/features/categories/api/route.js +4 -3
- package/dist/features/categories/components/BrandDetailPageView.js +2 -2
- package/dist/features/categories/components/BrandDetailTabs.js +2 -2
- package/dist/features/categories/components/BundleCollage.d.ts +8 -0
- package/dist/features/categories/components/BundleCollage.js +50 -0
- package/dist/features/categories/components/BundleDetailView.js +2 -10
- package/dist/features/categories/components/BundleItemsPicker.js +20 -13
- package/dist/features/categories/components/CategoriesIndexListing.js +28 -9
- package/dist/features/categories/components/CategoryDetailPageView.js +2 -2
- package/dist/features/categories/components/CategoryDetailTabs.js +2 -2
- package/dist/features/categories/components/CategoryProductsListing.js +52 -13
- package/dist/features/categories/components/index.d.ts +2 -0
- package/dist/features/categories/components/index.js +1 -0
- package/dist/features/categories/schemas/index.d.ts +6 -6
- package/dist/features/checkout/actions/checkout-actions.js +4 -3
- package/dist/features/checkout/hooks/usePaymentCheckout.js +31 -22
- package/dist/features/classified/components/ClassifiedFilters.d.ts +8 -0
- package/dist/features/classified/components/ClassifiedFilters.js +19 -0
- package/dist/features/classified/components/ClassifiedIndexListing.d.ts +4 -0
- package/dist/features/classified/components/ClassifiedIndexListing.js +110 -0
- package/dist/features/classified/components/ClassifiedListView.d.ts +6 -0
- package/dist/features/classified/components/ClassifiedListView.js +43 -0
- package/dist/features/classified/components/index.d.ts +6 -0
- package/dist/features/classified/components/index.js +3 -0
- package/dist/features/collections/api/[slug]/route.js +16 -12
- package/dist/features/collections/schemas/index.d.ts +5 -5
- package/dist/features/consultation/api/[id]/route.js +12 -9
- package/dist/features/consultation/components/ConsultationForm.js +3 -2
- package/dist/features/consultation/schemas/index.d.ts +6 -6
- package/dist/features/contact/email.js +77 -116
- package/dist/features/copilot/components/AdminCopilotView.js +12 -2
- package/dist/features/corporate/api/[id]/route.js +12 -9
- package/dist/features/corporate/components/CorporateInquiryForm.js +2 -1
- package/dist/features/digital-codes/components/DigitalCodeFilters.d.ts +8 -0
- package/dist/features/digital-codes/components/DigitalCodeFilters.js +16 -0
- package/dist/features/digital-codes/components/DigitalCodesIndexListing.d.ts +4 -0
- package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +107 -0
- package/dist/features/digital-codes/components/DigitalCodesListView.d.ts +6 -0
- package/dist/features/digital-codes/components/DigitalCodesListView.js +37 -0
- package/dist/features/digital-codes/components/index.d.ts +6 -0
- package/dist/features/digital-codes/components/index.js +3 -0
- package/dist/features/events/actions/event-actions.js +4 -3
- package/dist/features/events/components/AdminEventEditorView.js +3 -2
- package/dist/features/events/components/AdminEventsView.js +4 -2
- package/dist/features/events/components/EventPollWidget.js +5 -5
- package/dist/features/events/components/EventsIndexListing.js +2 -2
- package/dist/features/events/schemas/index.d.ts +20 -20
- package/dist/features/faq/actions/faq-actions.d.ts +8 -8
- package/dist/features/faq/components/ContactCTA.js +3 -1
- package/dist/features/faq/components/FAQAccordion.js +1 -1
- package/dist/features/faq/schemas/index.d.ts +4 -4
- package/dist/features/filters/AsyncFacetSection.d.ts +18 -0
- package/dist/features/filters/AsyncFacetSection.js +65 -0
- package/dist/features/forms/Checkbox.js +2 -2
- package/dist/features/forms/Input.js +2 -2
- package/dist/features/forms/Radio.js +5 -5
- package/dist/features/forms/Select.js +2 -2
- package/dist/features/forms/Slider.js +2 -2
- package/dist/features/forms/Textarea.js +2 -2
- package/dist/features/homepage/api/[id]/route.js +4 -3
- package/dist/features/homepage/api/sections/[id]/route.js +12 -9
- package/dist/features/homepage/components/AdSlot.js +2 -1
- package/dist/features/homepage/components/AdvertisementBanner.js +5 -3
- package/dist/features/homepage/components/BrandsSection.js +2 -2
- package/dist/features/homepage/components/CTABannerSection.js +2 -2
- package/dist/features/homepage/components/CharacterHotspot.d.ts +2 -2
- package/dist/features/homepage/components/CharacterHotspot.js +119 -157
- package/dist/features/homepage/components/CharacterHotspotForm.js +25 -20
- package/dist/features/homepage/components/CustomCardsSection.js +8 -6
- package/dist/features/homepage/components/FeaturedProductsSection.js +2 -2
- package/dist/features/homepage/components/GoogleReviewsSection.js +3 -3
- package/dist/features/homepage/components/HeroBanner.js +5 -4
- package/dist/features/homepage/components/HeroCarousel.js +13 -26
- package/dist/features/homepage/components/HowItWorksSection.js +4 -2
- package/dist/features/homepage/components/SocialFeedSection.js +2 -2
- package/dist/features/homepage/components/SocialPostCard.js +3 -2
- package/dist/features/homepage/lib/social-feed-fetcher.js +6 -3
- package/dist/features/layout/AppLayoutShell.d.ts +8 -2
- package/dist/features/layout/AppLayoutShell.js +55 -84
- package/dist/features/layout/BottomActions.js +43 -48
- package/dist/features/layout/NavbarWithSettings.d.ts +6 -0
- package/dist/features/layout/NavbarWithSettings.js +11 -0
- package/dist/features/live/components/LiveItemFilters.d.ts +8 -0
- package/dist/features/live/components/LiveItemFilters.js +23 -0
- package/dist/features/live/components/LiveItemsIndexListing.d.ts +4 -0
- package/dist/features/live/components/LiveItemsIndexListing.js +108 -0
- package/dist/features/live/components/LiveItemsListView.d.ts +6 -0
- package/dist/features/live/components/LiveItemsListView.js +43 -0
- package/dist/features/live/components/index.d.ts +6 -0
- package/dist/features/live/components/index.js +3 -0
- package/dist/features/media/MediaLightbox.js +8 -14
- package/dist/features/media/types/index.d.ts +2 -2
- package/dist/features/media/upload/CameraCapture.js +2 -2
- package/dist/features/media/upload/ImageUpload.js +4 -2
- package/dist/features/media/upload/MediaUploadField.js +24 -8
- package/dist/features/media/upload/MediaUploadList.js +1 -1
- package/dist/features/orders/actions/order-actions.js +4 -3
- package/dist/features/orders/components/MarketplaceOrderCard.js +2 -1
- package/dist/features/orders/components/OrderFilters.js +12 -9
- package/dist/features/orders/schemas/index.d.ts +6 -6
- package/dist/features/pre-orders/api/[id]/route.js +12 -9
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +5 -4
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +27 -20
- package/dist/features/pre-orders/components/PreOrdersIndexListing.js +17 -52
- package/dist/features/pre-orders/components/PreorderCard.d.ts +0 -9
- package/dist/features/pre-orders/components/PreorderCard.js +2 -13
- package/dist/features/pre-orders/components/index.d.ts +1 -1
- package/dist/features/pre-orders/components/index.js +1 -1
- package/dist/features/pre-orders/schemas/index.d.ts +10 -10
- package/dist/features/products/api/[id]/route.js +9 -7
- package/dist/features/products/api/route.js +1 -1
- package/dist/features/products/columns/productTableColumns.js +2 -2
- package/dist/features/products/components/AuctionsIndexListing.js +15 -51
- package/dist/features/products/components/BidHistory.js +2 -2
- package/dist/features/products/components/CompareOverlay.js +3 -2
- package/dist/features/products/components/MakeOfferButton.js +20 -14
- package/dist/features/products/components/MarketplacePrizeDrawCard.js +2 -1
- package/dist/features/products/components/PrizeDrawCollage.d.ts +1 -15
- package/dist/features/products/components/PrizeDrawCollage.js +54 -14
- package/dist/features/products/components/PrizeDrawDetailPageView.js +2 -1
- package/dist/features/products/components/PrizeDrawEntryActions.js +2 -1
- package/dist/features/products/components/PrizeDrawItemsEditor.js +9 -7
- package/dist/features/products/components/PrizeDrawsIndexListing.js +18 -51
- package/dist/features/products/components/PrizeRevealModal.js +24 -14
- package/dist/features/products/components/ProductDetailPageView.js +2 -1
- package/dist/features/products/components/ProductFilters.js +8 -6
- package/dist/features/products/components/ProductForm.js +12 -10
- package/dist/features/products/components/ProductGalleryClient.js +2 -1
- package/dist/features/products/components/ProductGrid.js +11 -14
- package/dist/features/products/components/ProductsIndexListing.js +16 -52
- package/dist/features/products/components/ProductsIndexPageView.js +2 -2
- package/dist/features/products/schemas/index.d.ts +56 -56
- package/dist/features/products/schemas/product-features.validators.d.ts +14 -14
- package/dist/features/promotions/components/CouponsIndexListing.js +1 -1
- package/dist/features/promotions/schemas/index.d.ts +6 -6
- package/dist/features/reviews/actions/review-actions.js +6 -5
- package/dist/features/reviews/api/[id]/route.js +4 -3
- package/dist/features/reviews/components/ReviewDetailPageView.js +2 -2
- package/dist/features/reviews/components/ReviewDetailShell.js +6 -3
- package/dist/features/reviews/components/ReviewsIndexListing.js +2 -2
- package/dist/features/reviews/schemas/index.d.ts +6 -6
- package/dist/features/scams/components/ScamProfileView.js +19 -10
- package/dist/features/scams/components/ScamRegistryView.js +2 -1
- package/dist/features/search/components/Search.d.ts +1 -1
- package/dist/features/search/components/Search.js +56 -49
- package/dist/features/search/schemas/index.d.ts +5 -5
- package/dist/features/seller/actions/offer-actions.js +11 -9
- package/dist/features/seller/components/SellerAddressesView.js +6 -4
- package/dist/features/seller/components/SellerBidsView.js +2 -2
- package/dist/features/seller/components/SellerCouponsView.js +1 -1
- package/dist/features/seller/components/SellerOffersPanel.js +6 -1
- package/dist/features/seller/components/SellerOrdersView.js +1 -1
- package/dist/features/seller/components/SellerPayoutSettingsView.js +3 -3
- package/dist/features/seller/components/SellerPreOrdersView.js +5 -4
- package/dist/features/seller/components/SellerPrizeDrawsView.js +5 -4
- package/dist/features/seller/components/SellerProductShell.d.ts +19 -1
- package/dist/features/seller/components/SellerProductShell.js +75 -9
- package/dist/features/seller/components/SellerProductsView.js +10 -11
- package/dist/features/seller/components/SellerShippingView.js +3 -3
- package/dist/features/seller/components/SellerSidebar.js +10 -7
- package/dist/features/seller/components/SellerStorefrontView.js +3 -3
- package/dist/features/seller/schemas/index.d.ts +4 -4
- package/dist/features/shell/FormShell.js +2 -1
- package/dist/features/shell/QuickFormDrawer.js +4 -3
- package/dist/features/shell/StepForm.js +4 -3
- package/dist/features/stores/actions/store-query-actions.js +4 -3
- package/dist/features/stores/components/StoreAboutView.js +2 -1
- package/dist/features/stores/components/StoreAuctionsListing.js +43 -64
- package/dist/features/stores/components/StoreDetailLayoutView.js +2 -2
- package/dist/features/stores/components/StorePreOrdersListing.js +33 -57
- package/dist/features/stores/components/StoreProductsListing.js +16 -49
- package/dist/features/stores/components/StoresIndexListing.js +2 -2
- package/dist/features/stores/schemas/index.d.ts +2 -2
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +8 -7
- package/dist/features/wishlist/hooks/useGuestWishlist.d.ts +5 -5
- package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +6 -6
- package/dist/features/wishlist/utils/guest-wishlist.d.ts +5 -5
- package/dist/index.d.ts +21 -3
- package/dist/index.js +1737 -1725
- package/dist/monitoring/server-logger.js +5 -9
- package/dist/next/api/apiHandler.js +56 -37
- package/dist/next/components/GlobalError.js +2 -1
- package/dist/next/routing/route-map.d.ts +27 -0
- package/dist/next/routing/route-map.js +10 -0
- package/dist/react/ErrorBoundary.js +2 -1
- package/dist/react/contexts/SessionContext.js +38 -28
- package/dist/react/hooks/useCamera.d.ts +1 -1
- package/dist/react/hooks/useCamera.js +8 -7
- package/dist/seed/site-settings-seed-data.js +6 -0
- package/dist/server-entry.d.ts +3 -0
- package/dist/server-entry.js +3 -0
- package/dist/server.d.ts +12 -0
- package/dist/server.js +15 -0
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/DataTable.js +28 -7
- package/dist/ui/components/Button.d.ts +8 -1
- package/dist/ui/components/Button.js +47 -8
- package/dist/ui/components/CollageLightbox.d.ts +18 -0
- package/dist/ui/components/CollageLightbox.js +41 -0
- package/dist/ui/components/Dropdown.js +7 -6
- package/dist/ui/components/ImageLightbox.d.ts +7 -1
- package/dist/ui/components/ImageLightbox.js +15 -5
- package/dist/ui/components/PageLoader.js +4 -3
- package/dist/ui/components/PaginatedMultiSelect.d.ts +28 -0
- package/dist/ui/components/PaginatedMultiSelect.js +141 -0
- package/dist/ui/components/PaginatedMultiSelect.style.css +272 -0
- package/dist/ui/components/Semantic.js +1 -1
- package/dist/ui/components/SideDrawer.js +17 -15
- package/dist/ui/components/index.style.css +1 -0
- package/dist/ui/index.d.ts +2 -0
- package/dist/ui/index.js +1 -0
- package/dist/utils/number.formatter.js +5 -13
- package/dist/utils/string.formatter.js +21 -18
- package/dist/validation/schemas.d.ts +2 -2
- package/package.json +2 -2
|
@@ -10,22 +10,26 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { NextResponse } from "next/server.js";
|
|
12
12
|
import { getProviders } from "../../../../contracts";
|
|
13
|
+
const ERR_COLLECTION_SLUG_REQUIRED = "Collection slug is required";
|
|
14
|
+
const ERR_DB_NOT_CONFIGURED = "Database provider not configured";
|
|
15
|
+
const ERR_COLLECTION_NOT_FOUND = "Collection not found";
|
|
16
|
+
const ERR_INTERNAL_SERVER_ERROR = "Internal server error";
|
|
13
17
|
export async function GET(request, { params }) {
|
|
14
18
|
try {
|
|
15
19
|
const { slug } = await params;
|
|
16
20
|
if (!slug) {
|
|
17
|
-
return NextResponse.json({ success: false, error:
|
|
21
|
+
return NextResponse.json({ success: false, error: ERR_COLLECTION_SLUG_REQUIRED }, { status: 400 });
|
|
18
22
|
}
|
|
19
23
|
const { db } = getProviders();
|
|
20
24
|
if (!db)
|
|
21
|
-
return NextResponse.json({ success: false, error:
|
|
25
|
+
return NextResponse.json({ success: false, error: ERR_DB_NOT_CONFIGURED }, { status: 503 });
|
|
22
26
|
const repo = db.getRepository("collections");
|
|
23
27
|
const result = await repo.findAll({
|
|
24
28
|
filters: `slug==${slug}`,
|
|
25
29
|
perPage: 1,
|
|
26
30
|
});
|
|
27
31
|
if (!result.data[0]) {
|
|
28
|
-
return NextResponse.json({ success: false, error:
|
|
32
|
+
return NextResponse.json({ success: false, error: ERR_COLLECTION_NOT_FOUND }, { status: 404 });
|
|
29
33
|
}
|
|
30
34
|
return NextResponse.json({
|
|
31
35
|
success: true,
|
|
@@ -35,7 +39,7 @@ export async function GET(request, { params }) {
|
|
|
35
39
|
catch (error) {
|
|
36
40
|
return NextResponse.json({
|
|
37
41
|
success: false,
|
|
38
|
-
error: error instanceof Error ? error.message :
|
|
42
|
+
error: error instanceof Error ? error.message : ERR_INTERNAL_SERVER_ERROR,
|
|
39
43
|
}, { status: 500 });
|
|
40
44
|
}
|
|
41
45
|
}
|
|
@@ -43,19 +47,19 @@ export async function PATCH(request, { params }) {
|
|
|
43
47
|
try {
|
|
44
48
|
const { slug } = await params;
|
|
45
49
|
if (!slug) {
|
|
46
|
-
return NextResponse.json({ success: false, error:
|
|
50
|
+
return NextResponse.json({ success: false, error: ERR_COLLECTION_SLUG_REQUIRED }, { status: 400 });
|
|
47
51
|
}
|
|
48
52
|
const body = await request.json();
|
|
49
53
|
const { db } = getProviders();
|
|
50
54
|
if (!db)
|
|
51
|
-
return NextResponse.json({ success: false, error:
|
|
55
|
+
return NextResponse.json({ success: false, error: ERR_DB_NOT_CONFIGURED }, { status: 503 });
|
|
52
56
|
const repo = db.getRepository("collections");
|
|
53
57
|
const result = await repo.findAll({
|
|
54
58
|
filters: `slug==${slug}`,
|
|
55
59
|
perPage: 1,
|
|
56
60
|
});
|
|
57
61
|
if (!result.data[0]) {
|
|
58
|
-
return NextResponse.json({ success: false, error:
|
|
62
|
+
return NextResponse.json({ success: false, error: ERR_COLLECTION_NOT_FOUND }, { status: 404 });
|
|
59
63
|
}
|
|
60
64
|
const updated = await repo.update(result.data[0].id, body);
|
|
61
65
|
return NextResponse.json({
|
|
@@ -66,7 +70,7 @@ export async function PATCH(request, { params }) {
|
|
|
66
70
|
catch (error) {
|
|
67
71
|
return NextResponse.json({
|
|
68
72
|
success: false,
|
|
69
|
-
error: error instanceof Error ? error.message :
|
|
73
|
+
error: error instanceof Error ? error.message : ERR_INTERNAL_SERVER_ERROR,
|
|
70
74
|
}, { status: 500 });
|
|
71
75
|
}
|
|
72
76
|
}
|
|
@@ -74,18 +78,18 @@ export async function DELETE(request, { params }) {
|
|
|
74
78
|
try {
|
|
75
79
|
const { slug } = await params;
|
|
76
80
|
if (!slug) {
|
|
77
|
-
return NextResponse.json({ success: false, error:
|
|
81
|
+
return NextResponse.json({ success: false, error: ERR_COLLECTION_SLUG_REQUIRED }, { status: 400 });
|
|
78
82
|
}
|
|
79
83
|
const { db } = getProviders();
|
|
80
84
|
if (!db)
|
|
81
|
-
return NextResponse.json({ success: false, error:
|
|
85
|
+
return NextResponse.json({ success: false, error: ERR_DB_NOT_CONFIGURED }, { status: 503 });
|
|
82
86
|
const repo = db.getRepository("collections");
|
|
83
87
|
const result = await repo.findAll({
|
|
84
88
|
filters: `slug==${slug}`,
|
|
85
89
|
perPage: 1,
|
|
86
90
|
});
|
|
87
91
|
if (!result.data[0]) {
|
|
88
|
-
return NextResponse.json({ success: false, error:
|
|
92
|
+
return NextResponse.json({ success: false, error: ERR_COLLECTION_NOT_FOUND }, { status: 404 });
|
|
89
93
|
}
|
|
90
94
|
await repo.delete(result.data[0].id);
|
|
91
95
|
return NextResponse.json({
|
|
@@ -96,7 +100,7 @@ export async function DELETE(request, { params }) {
|
|
|
96
100
|
catch (error) {
|
|
97
101
|
return NextResponse.json({
|
|
98
102
|
success: false,
|
|
99
|
-
error: error instanceof Error ? error.message :
|
|
103
|
+
error: error instanceof Error ? error.message : ERR_INTERNAL_SERVER_ERROR,
|
|
100
104
|
}, { status: 500 });
|
|
101
105
|
}
|
|
102
106
|
}
|
|
@@ -26,13 +26,13 @@ export declare const collectionItemSchema: z.ZodObject<{
|
|
|
26
26
|
}, "strip", z.ZodTypeAny, {
|
|
27
27
|
sortOrder: number;
|
|
28
28
|
title: string;
|
|
29
|
-
active: boolean;
|
|
30
29
|
slug: string;
|
|
30
|
+
active: boolean;
|
|
31
31
|
createdAt?: string | undefined;
|
|
32
32
|
image?: string | undefined;
|
|
33
|
-
subtitle?: string | undefined;
|
|
34
33
|
description?: string | undefined;
|
|
35
34
|
brandSlug?: string | undefined;
|
|
35
|
+
subtitle?: string | undefined;
|
|
36
36
|
productCount?: number | undefined;
|
|
37
37
|
bannerImage?: string | undefined;
|
|
38
38
|
franchiseSlug?: string | undefined;
|
|
@@ -43,10 +43,10 @@ export declare const collectionItemSchema: z.ZodObject<{
|
|
|
43
43
|
createdAt?: string | undefined;
|
|
44
44
|
sortOrder?: number | undefined;
|
|
45
45
|
image?: string | undefined;
|
|
46
|
-
active?: boolean | undefined;
|
|
47
|
-
subtitle?: string | undefined;
|
|
48
46
|
description?: string | undefined;
|
|
49
47
|
brandSlug?: string | undefined;
|
|
48
|
+
active?: boolean | undefined;
|
|
49
|
+
subtitle?: string | undefined;
|
|
50
50
|
productCount?: number | undefined;
|
|
51
51
|
bannerImage?: string | undefined;
|
|
52
52
|
franchiseSlug?: string | undefined;
|
|
@@ -61,8 +61,8 @@ export declare const collectionListItemSchema: z.ZodObject<{
|
|
|
61
61
|
active: z.ZodDefault<z.ZodBoolean>;
|
|
62
62
|
}, "strip", z.ZodTypeAny, {
|
|
63
63
|
title: string;
|
|
64
|
-
active: boolean;
|
|
65
64
|
slug: string;
|
|
65
|
+
active: boolean;
|
|
66
66
|
image?: string | undefined;
|
|
67
67
|
subtitle?: string | undefined;
|
|
68
68
|
productCount?: number | undefined;
|
|
@@ -10,15 +10,18 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { NextResponse } from "next/server.js";
|
|
12
12
|
import { getProviders } from "../../../../contracts";
|
|
13
|
+
const ERR_CONSULTATION_ID_REQUIRED = "Consultation ID is required";
|
|
14
|
+
const ERR_DB_NOT_CONFIGURED = "Database provider not configured";
|
|
15
|
+
const ERR_INTERNAL_SERVER_ERROR = "Internal server error";
|
|
13
16
|
export async function GET(request, { params }) {
|
|
14
17
|
try {
|
|
15
18
|
const { id } = await params;
|
|
16
19
|
if (!id) {
|
|
17
|
-
return NextResponse.json({ success: false, error:
|
|
20
|
+
return NextResponse.json({ success: false, error: ERR_CONSULTATION_ID_REQUIRED }, { status: 400 });
|
|
18
21
|
}
|
|
19
22
|
const { db } = getProviders();
|
|
20
23
|
if (!db)
|
|
21
|
-
return NextResponse.json({ success: false, error:
|
|
24
|
+
return NextResponse.json({ success: false, error: ERR_DB_NOT_CONFIGURED }, { status: 503 });
|
|
22
25
|
const repo = db.getRepository("consultations");
|
|
23
26
|
const consultation = await repo.findById(id);
|
|
24
27
|
if (!consultation) {
|
|
@@ -32,7 +35,7 @@ export async function GET(request, { params }) {
|
|
|
32
35
|
catch (error) {
|
|
33
36
|
return NextResponse.json({
|
|
34
37
|
success: false,
|
|
35
|
-
error: error instanceof Error ? error.message :
|
|
38
|
+
error: error instanceof Error ? error.message : ERR_INTERNAL_SERVER_ERROR,
|
|
36
39
|
}, { status: 500 });
|
|
37
40
|
}
|
|
38
41
|
}
|
|
@@ -40,12 +43,12 @@ export async function PATCH(request, { params }) {
|
|
|
40
43
|
try {
|
|
41
44
|
const { id } = await params;
|
|
42
45
|
if (!id) {
|
|
43
|
-
return NextResponse.json({ success: false, error:
|
|
46
|
+
return NextResponse.json({ success: false, error: ERR_CONSULTATION_ID_REQUIRED }, { status: 400 });
|
|
44
47
|
}
|
|
45
48
|
const body = await request.json();
|
|
46
49
|
const { db } = getProviders();
|
|
47
50
|
if (!db)
|
|
48
|
-
return NextResponse.json({ success: false, error:
|
|
51
|
+
return NextResponse.json({ success: false, error: ERR_DB_NOT_CONFIGURED }, { status: 503 });
|
|
49
52
|
const repo = db.getRepository("consultations");
|
|
50
53
|
const updated = await repo.update(id, body);
|
|
51
54
|
if (!updated) {
|
|
@@ -59,7 +62,7 @@ export async function PATCH(request, { params }) {
|
|
|
59
62
|
catch (error) {
|
|
60
63
|
return NextResponse.json({
|
|
61
64
|
success: false,
|
|
62
|
-
error: error instanceof Error ? error.message :
|
|
65
|
+
error: error instanceof Error ? error.message : ERR_INTERNAL_SERVER_ERROR,
|
|
63
66
|
}, { status: 500 });
|
|
64
67
|
}
|
|
65
68
|
}
|
|
@@ -67,11 +70,11 @@ export async function DELETE(request, { params }) {
|
|
|
67
70
|
try {
|
|
68
71
|
const { id } = await params;
|
|
69
72
|
if (!id) {
|
|
70
|
-
return NextResponse.json({ success: false, error:
|
|
73
|
+
return NextResponse.json({ success: false, error: ERR_CONSULTATION_ID_REQUIRED }, { status: 400 });
|
|
71
74
|
}
|
|
72
75
|
const { db } = getProviders();
|
|
73
76
|
if (!db)
|
|
74
|
-
return NextResponse.json({ success: false, error:
|
|
77
|
+
return NextResponse.json({ success: false, error: ERR_DB_NOT_CONFIGURED }, { status: 503 });
|
|
75
78
|
const repo = db.getRepository("consultations");
|
|
76
79
|
await repo.delete(id);
|
|
77
80
|
return NextResponse.json({
|
|
@@ -82,7 +85,7 @@ export async function DELETE(request, { params }) {
|
|
|
82
85
|
catch (error) {
|
|
83
86
|
return NextResponse.json({
|
|
84
87
|
success: false,
|
|
85
|
-
error: error instanceof Error ? error.message :
|
|
88
|
+
error: error instanceof Error ? error.message : ERR_INTERNAL_SERVER_ERROR,
|
|
86
89
|
}, { status: 500 });
|
|
87
90
|
}
|
|
88
91
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import React from "react";
|
|
4
4
|
import { Button, Div, Input, Row, Select, Textarea } from "../../../ui";
|
|
5
|
+
const CLS_INPUT = "w-full rounded-md border border-neutral-300 px-3 py-2 text-sm";
|
|
5
6
|
const TIME_SLOTS = [
|
|
6
7
|
"9:00 AM",
|
|
7
8
|
"10:00 AM",
|
|
@@ -42,10 +43,10 @@ export function ConsultationForm({ onSubmit, isPending, concerns = [], }) {
|
|
|
42
43
|
e.preventDefault();
|
|
43
44
|
await onSubmit(form);
|
|
44
45
|
}
|
|
45
|
-
return (_jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [_jsx(Input, { name: "name", type: "text", placeholder: "Full name", value: form.name, onChange: handleChange, required: true, className:
|
|
46
|
+
return (_jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [_jsx(Input, { name: "name", type: "text", placeholder: "Full name", value: form.name, onChange: handleChange, required: true, className: CLS_INPUT }), _jsx(Input, { name: "email", type: "email", placeholder: "Email address", value: form.email, onChange: handleChange, required: true, className: CLS_INPUT }), _jsx(Input, { name: "phone", type: "tel", placeholder: "Phone number", value: form.phone, onChange: handleChange, required: true, className: CLS_INPUT }), concerns.length > 0 && (_jsx(Row, { wrap: true, gap: "sm", children: concerns.map((c) => (_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => toggleConcern(c), className: `rounded-full border px-3 py-1 text-xs transition ${form.concern.includes(c)
|
|
46
47
|
? "border-primary bg-primary text-white"
|
|
47
48
|
: "border-neutral-300 text-neutral-700 hover:border-primary"}`, children: c }, c))) })), _jsxs(Div, { className: "flex gap-3", children: [_jsx(Input, { name: "preferredDate", type: "date", value: form.preferredDate, onChange: handleChange, required: true, className: "flex-1 rounded-md border border-neutral-300 px-3 py-2 text-sm" }), _jsx(Select, { value: form.preferredTime, onValueChange: (value) => handleValueChange("preferredTime", value), options: TIME_SLOTS.map((t) => ({ value: t, label: t })), className: "flex-1 rounded-md border border-neutral-300 px-3 py-2 text-sm" })] }), _jsx(Select, { value: form.mode, onValueChange: (value) => handleValueChange("mode", value), options: [
|
|
48
49
|
{ value: "remote", label: "Remote (Video Call)" },
|
|
49
50
|
{ value: "in-person", label: "In-Person" },
|
|
50
|
-
], className:
|
|
51
|
+
], className: CLS_INPUT }), _jsx(Textarea, { name: "message", placeholder: "Any additional notes (optional)", value: form.message, onChange: handleChange, rows: 3, className: CLS_INPUT }), _jsx(Button, { type: "submit", disabled: isPending, variant: "primary", className: "w-full rounded-md bg-primary px-4 py-2 text-sm font-medium text-white transition hover:bg-primary/90 disabled:opacity-60", children: isPending ? "Booking..." : "Book Consultation" })] }));
|
|
51
52
|
}
|
|
@@ -33,9 +33,9 @@ export declare const consultationBookingSchema: z.ZodObject<{
|
|
|
33
33
|
createdAt?: string | undefined;
|
|
34
34
|
adminNote?: string | undefined;
|
|
35
35
|
message?: string | undefined;
|
|
36
|
-
mode?: "online" | "phone" | "in_person" | undefined;
|
|
37
|
-
userId?: string | undefined;
|
|
38
36
|
phone?: string | undefined;
|
|
37
|
+
mode?: "phone" | "online" | "in_person" | undefined;
|
|
38
|
+
userId?: string | undefined;
|
|
39
39
|
concern?: string[] | undefined;
|
|
40
40
|
preferredDate?: string | undefined;
|
|
41
41
|
preferredTime?: string | undefined;
|
|
@@ -47,9 +47,9 @@ export declare const consultationBookingSchema: z.ZodObject<{
|
|
|
47
47
|
status?: "pending" | "completed" | "confirmed" | "cancelled" | "no_show" | undefined;
|
|
48
48
|
adminNote?: string | undefined;
|
|
49
49
|
message?: string | undefined;
|
|
50
|
-
mode?: "online" | "phone" | "in_person" | undefined;
|
|
51
|
-
userId?: string | undefined;
|
|
52
50
|
phone?: string | undefined;
|
|
51
|
+
mode?: "phone" | "online" | "in_person" | undefined;
|
|
52
|
+
userId?: string | undefined;
|
|
53
53
|
concern?: string[] | undefined;
|
|
54
54
|
preferredDate?: string | undefined;
|
|
55
55
|
preferredTime?: string | undefined;
|
|
@@ -71,8 +71,8 @@ export declare const bookConsultationSchema: z.ZodObject<{
|
|
|
71
71
|
name: string;
|
|
72
72
|
concern: string[];
|
|
73
73
|
message?: string | undefined;
|
|
74
|
-
mode?: "online" | "phone" | "in_person" | undefined;
|
|
75
74
|
phone?: string | undefined;
|
|
75
|
+
mode?: "phone" | "online" | "in_person" | undefined;
|
|
76
76
|
preferredDate?: string | undefined;
|
|
77
77
|
preferredTime?: string | undefined;
|
|
78
78
|
}, {
|
|
@@ -80,8 +80,8 @@ export declare const bookConsultationSchema: z.ZodObject<{
|
|
|
80
80
|
name: string;
|
|
81
81
|
concern: string[];
|
|
82
82
|
message?: string | undefined;
|
|
83
|
-
mode?: "online" | "phone" | "in_person" | undefined;
|
|
84
83
|
phone?: string | undefined;
|
|
84
|
+
mode?: "phone" | "online" | "in_person" | undefined;
|
|
85
85
|
preferredDate?: string | undefined;
|
|
86
86
|
preferredTime?: string | undefined;
|
|
87
87
|
}>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { getProviders } from "../../contracts";
|
|
2
2
|
import { serverLogger } from "../../monitoring";
|
|
3
3
|
import { currentYear, formatCurrency, formatDateTime, nowMs, } from "../../utils";
|
|
4
|
+
const EMAIL_STYLE_MUTED = "color: #666; font-size: 14px;";
|
|
5
|
+
const EMAIL_STYLE_BODY = "color: #333; font-size: 14px;";
|
|
4
6
|
function getSiteName() {
|
|
5
7
|
return process.env.NEXT_PUBLIC_SITE_NAME?.trim() || "App";
|
|
6
8
|
}
|
|
@@ -74,134 +76,93 @@ export async function sendPasswordResetEmailWithLink(email, resetLink) {
|
|
|
74
76
|
throw error;
|
|
75
77
|
}
|
|
76
78
|
}
|
|
79
|
+
function buildOrderItemsHtml(items, productTitle, quantity, currency) {
|
|
80
|
+
if (items && items.length > 1) {
|
|
81
|
+
return `
|
|
82
|
+
<table width="100%" cellpadding="8" cellspacing="0" border="0" style="border-collapse: collapse; margin-bottom: 8px;">
|
|
83
|
+
<thead>
|
|
84
|
+
<tr style="background-color: #e9ecef;">
|
|
85
|
+
<th style="text-align: left; font-size: 12px; font-weight: 600; color: #666; text-transform: uppercase; letter-spacing: 0.05em; padding: 8px 12px;">Product</th>
|
|
86
|
+
<th style="text-align: center; font-size: 12px; font-weight: 600; color: #666; text-transform: uppercase; letter-spacing: 0.05em; padding: 8px 12px;">Qty</th>
|
|
87
|
+
<th style="text-align: right; font-size: 12px; font-weight: 600; color: #666; text-transform: uppercase; letter-spacing: 0.05em; padding: 8px 12px;">Amount</th>
|
|
88
|
+
</tr>
|
|
89
|
+
</thead>
|
|
90
|
+
<tbody>
|
|
91
|
+
${items.map((item, index) => `
|
|
92
|
+
<tr style="background-color: ${index % 2 === 0 ? "#ffffff" : "#f8f9fa"}; border-top: 1px solid #e9ecef;">
|
|
93
|
+
<td style="font-size: 14px; color: #333; padding: 8px 12px;">${item.productTitle}</td>
|
|
94
|
+
<td style="font-size: 14px; color: #333; text-align: center; padding: 8px 12px;">${item.quantity}</td>
|
|
95
|
+
<td style="font-size: 14px; color: #333; text-align: right; padding: 8px 12px;">${formatCurrency(item.totalPrice, currency)}</td>
|
|
96
|
+
</tr>`).join("")}
|
|
97
|
+
</tbody>
|
|
98
|
+
</table>`;
|
|
99
|
+
}
|
|
100
|
+
return `
|
|
101
|
+
<tr>
|
|
102
|
+
<td style="${EMAIL_STYLE_MUTED}">Product</td>
|
|
103
|
+
<td style="${EMAIL_STYLE_BODY}">${productTitle}</td>
|
|
104
|
+
</tr>
|
|
105
|
+
<tr>
|
|
106
|
+
<td style="${EMAIL_STYLE_MUTED}">Quantity</td>
|
|
107
|
+
<td style="${EMAIL_STYLE_BODY}">${quantity}</td>
|
|
108
|
+
</tr>`;
|
|
109
|
+
}
|
|
110
|
+
function buildOrderConfirmationHtml(params) {
|
|
111
|
+
const { userName, orderId, formattedTotal, shippingAddress, paymentMethod, orderUrl, itemsHtml, siteName, items } = params;
|
|
112
|
+
return `
|
|
113
|
+
<!DOCTYPE html><html>
|
|
114
|
+
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Order Confirmation</title></head>
|
|
115
|
+
<body style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; background-color: #f5f5f5;">
|
|
116
|
+
<table width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color: #f5f5f5; padding: 40px 0;">
|
|
117
|
+
<tr><td align="center">
|
|
118
|
+
<table width="600" cellpadding="0" cellspacing="0" border="0" style="background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
|
|
119
|
+
<tr><td style="background: linear-gradient(135deg, #10b981 0%, #059669 100%); padding: 40px; text-align: center;">
|
|
120
|
+
<p style="font-size: 48px; margin: 0 0 12px;">✅</p>
|
|
121
|
+
<h1 style="color: #ffffff; margin: 0; font-size: 28px; font-weight: 600;">Order Confirmed!</h1>
|
|
122
|
+
</td></tr>
|
|
123
|
+
<tr><td style="padding: 40px;">
|
|
124
|
+
<p style="color: #333; font-size: 16px; line-height: 1.6; margin: 0 0 20px;">Hi ${userName},</p>
|
|
125
|
+
<p style="color: #333; font-size: 16px; line-height: 1.6; margin: 0 0 24px;">Thank you for your order! We've received it and will process it shortly.</p>
|
|
126
|
+
<table width="100%" cellpadding="12" cellspacing="0" border="0" style="background-color: #f8f9fa; border-radius: 8px; margin-bottom: 24px;">
|
|
127
|
+
<tr><td style="color: #666; font-size: 13px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; border-bottom: 1px solid #e9ecef;" colspan="2">Order Details</td></tr>
|
|
128
|
+
<tr><td style="color: #666; font-size: 14px; width: 40%;">Order ID</td><td style="color: #333; font-size: 14px; font-weight: 600;">${orderId}</td></tr>
|
|
129
|
+
${items && items.length > 1
|
|
130
|
+
? `<tr><td style="color: #666; font-size: 14px; vertical-align: top;" colspan="2"><div style="font-weight: 600; margin-bottom: 8px;">Items (${items.length})</div>${itemsHtml}</td></tr>`
|
|
131
|
+
: itemsHtml}
|
|
132
|
+
<tr><td style="${EMAIL_STYLE_MUTED}">Total</td><td style="color: #333; font-size: 14px; font-weight: 700;">${formattedTotal}</td></tr>
|
|
133
|
+
<tr><td style="${EMAIL_STYLE_MUTED}">Payment</td><td style="${EMAIL_STYLE_BODY}">${paymentMethod === "cod" ? "Cash on Delivery" : "Online Payment"}</td></tr>
|
|
134
|
+
<tr><td style="color: #666; font-size: 14px; vertical-align: top;">Ship to</td><td style="${EMAIL_STYLE_BODY}">${shippingAddress}</td></tr>
|
|
135
|
+
</table>
|
|
136
|
+
<table width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 30px 0;">
|
|
137
|
+
<tr><td align="center">
|
|
138
|
+
<a href="${orderUrl}" style="display: inline-block; padding: 14px 40px; background: linear-gradient(135deg, #10b981 0%, #059669 100%); color: #ffffff; text-decoration: none; border-radius: 6px; font-size: 16px; font-weight: 600;">View Order</a>
|
|
139
|
+
</td></tr>
|
|
140
|
+
</table>
|
|
141
|
+
<p style="color: #999; font-size: 13px; line-height: 1.6; margin: 0;">We'll send you another email when your order is shipped.</p>
|
|
142
|
+
</td></tr>
|
|
143
|
+
<tr><td style="background-color: #f8f9fa; padding: 24px; text-align: center; border-top: 1px solid #eee;">
|
|
144
|
+
<p style="color: #999; font-size: 12px; margin: 0;">© ${currentYear()} ${siteName}. All rights reserved.</p>
|
|
145
|
+
</td></tr>
|
|
146
|
+
</table>
|
|
147
|
+
</td></tr>
|
|
148
|
+
</table>
|
|
149
|
+
</body></html>`;
|
|
150
|
+
}
|
|
77
151
|
export async function sendOrderConfirmationEmail(params) {
|
|
78
152
|
const siteName = getSiteName();
|
|
79
153
|
const siteUrl = getSiteUrl();
|
|
80
154
|
const { to, userName, orderId, productTitle, quantity, totalPrice, currency, shippingAddress, paymentMethod, items, } = params;
|
|
81
155
|
const orderUrl = `${siteUrl}/user/orders/view/${orderId}`;
|
|
82
156
|
const formattedTotal = formatCurrency(totalPrice, currency);
|
|
83
|
-
const itemsHtml = items
|
|
84
|
-
? `
|
|
85
|
-
<table width="100%" cellpadding="8" cellspacing="0" border="0" style="border-collapse: collapse; margin-bottom: 8px;">
|
|
86
|
-
<thead>
|
|
87
|
-
<tr style="background-color: #e9ecef;">
|
|
88
|
-
<th style="text-align: left; font-size: 12px; font-weight: 600; color: #666; text-transform: uppercase; letter-spacing: 0.05em; padding: 8px 12px;">Product</th>
|
|
89
|
-
<th style="text-align: center; font-size: 12px; font-weight: 600; color: #666; text-transform: uppercase; letter-spacing: 0.05em; padding: 8px 12px;">Qty</th>
|
|
90
|
-
<th style="text-align: right; font-size: 12px; font-weight: 600; color: #666; text-transform: uppercase; letter-spacing: 0.05em; padding: 8px 12px;">Amount</th>
|
|
91
|
-
</tr>
|
|
92
|
-
</thead>
|
|
93
|
-
<tbody>
|
|
94
|
-
${items
|
|
95
|
-
.map((item, index) => `
|
|
96
|
-
<tr style="background-color: ${index % 2 === 0 ? "#ffffff" : "#f8f9fa"}; border-top: 1px solid #e9ecef;">
|
|
97
|
-
<td style="font-size: 14px; color: #333; padding: 8px 12px;">${item.productTitle}</td>
|
|
98
|
-
<td style="font-size: 14px; color: #333; text-align: center; padding: 8px 12px;">${item.quantity}</td>
|
|
99
|
-
<td style="font-size: 14px; color: #333; text-align: right; padding: 8px 12px;">${formatCurrency(item.totalPrice, currency)}</td>
|
|
100
|
-
</tr>`)
|
|
101
|
-
.join("")}
|
|
102
|
-
</tbody>
|
|
103
|
-
</table>`
|
|
104
|
-
: `
|
|
105
|
-
<tr>
|
|
106
|
-
<td style="color: #666; font-size: 14px;">Product</td>
|
|
107
|
-
<td style="color: #333; font-size: 14px;">${productTitle}</td>
|
|
108
|
-
</tr>
|
|
109
|
-
<tr>
|
|
110
|
-
<td style="color: #666; font-size: 14px;">Quantity</td>
|
|
111
|
-
<td style="color: #333; font-size: 14px;">${quantity}</td>
|
|
112
|
-
</tr>`;
|
|
157
|
+
const itemsHtml = buildOrderItemsHtml(items, productTitle, quantity, currency);
|
|
113
158
|
const itemsText = items && items.length > 1
|
|
114
|
-
? items
|
|
115
|
-
.map((item) => ` • ${item.productTitle} × ${item.quantity} — ${formatCurrency(item.totalPrice, currency)}`)
|
|
116
|
-
.join("\n")
|
|
159
|
+
? items.map((item) => ` • ${item.productTitle} × ${item.quantity} — ${formatCurrency(item.totalPrice, currency)}`).join("\n")
|
|
117
160
|
: ` Product: ${productTitle}\n Quantity: ${quantity}`;
|
|
118
161
|
try {
|
|
119
162
|
const { data, error } = await sendConfiguredEmail({
|
|
120
163
|
to,
|
|
121
164
|
subject: `Order Confirmed — ${orderId}`,
|
|
122
|
-
html:
|
|
123
|
-
<!DOCTYPE html>
|
|
124
|
-
<html>
|
|
125
|
-
<head>
|
|
126
|
-
<meta charset="utf-8">
|
|
127
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
128
|
-
<title>Order Confirmation</title>
|
|
129
|
-
</head>
|
|
130
|
-
<body style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; background-color: #f5f5f5;">
|
|
131
|
-
<table width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color: #f5f5f5; padding: 40px 0;">
|
|
132
|
-
<tr>
|
|
133
|
-
<td align="center">
|
|
134
|
-
<table width="600" cellpadding="0" cellspacing="0" border="0" style="background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
|
|
135
|
-
<tr>
|
|
136
|
-
<td style="background: linear-gradient(135deg, #10b981 0%, #059669 100%); padding: 40px; text-align: center;">
|
|
137
|
-
<p style="font-size: 48px; margin: 0 0 12px;">✅</p>
|
|
138
|
-
<h1 style="color: #ffffff; margin: 0; font-size: 28px; font-weight: 600;">Order Confirmed!</h1>
|
|
139
|
-
</td>
|
|
140
|
-
</tr>
|
|
141
|
-
<tr>
|
|
142
|
-
<td style="padding: 40px;">
|
|
143
|
-
<p style="color: #333; font-size: 16px; line-height: 1.6; margin: 0 0 20px;">Hi ${userName},</p>
|
|
144
|
-
<p style="color: #333; font-size: 16px; line-height: 1.6; margin: 0 0 24px;">
|
|
145
|
-
Thank you for your order! We've received it and will process it shortly.
|
|
146
|
-
</p>
|
|
147
|
-
<table width="100%" cellpadding="12" cellspacing="0" border="0" style="background-color: #f8f9fa; border-radius: 8px; margin-bottom: 24px;">
|
|
148
|
-
<tr>
|
|
149
|
-
<td style="color: #666; font-size: 13px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; border-bottom: 1px solid #e9ecef;" colspan="2">Order Details</td>
|
|
150
|
-
</tr>
|
|
151
|
-
<tr>
|
|
152
|
-
<td style="color: #666; font-size: 14px; width: 40%;">Order ID</td>
|
|
153
|
-
<td style="color: #333; font-size: 14px; font-weight: 600;">${orderId}</td>
|
|
154
|
-
</tr>
|
|
155
|
-
${items && items.length > 1
|
|
156
|
-
? `
|
|
157
|
-
<tr>
|
|
158
|
-
<td style="color: #666; font-size: 14px; vertical-align: top;" colspan="2">
|
|
159
|
-
<div style="font-weight: 600; margin-bottom: 8px;">Items (${items.length})</div>
|
|
160
|
-
${itemsHtml}
|
|
161
|
-
</td>
|
|
162
|
-
</tr>`
|
|
163
|
-
: itemsHtml}
|
|
164
|
-
<tr>
|
|
165
|
-
<td style="color: #666; font-size: 14px;">Total</td>
|
|
166
|
-
<td style="color: #333; font-size: 14px; font-weight: 700;">${formattedTotal}</td>
|
|
167
|
-
</tr>
|
|
168
|
-
<tr>
|
|
169
|
-
<td style="color: #666; font-size: 14px;">Payment</td>
|
|
170
|
-
<td style="color: #333; font-size: 14px;">${paymentMethod === "cod" ? "Cash on Delivery" : "Online Payment"}</td>
|
|
171
|
-
</tr>
|
|
172
|
-
<tr>
|
|
173
|
-
<td style="color: #666; font-size: 14px; vertical-align: top;">Ship to</td>
|
|
174
|
-
<td style="color: #333; font-size: 14px;">${shippingAddress}</td>
|
|
175
|
-
</tr>
|
|
176
|
-
</table>
|
|
177
|
-
<table width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 30px 0;">
|
|
178
|
-
<tr>
|
|
179
|
-
<td align="center">
|
|
180
|
-
<a href="${orderUrl}" style="display: inline-block; padding: 14px 40px; background: linear-gradient(135deg, #10b981 0%, #059669 100%); color: #ffffff; text-decoration: none; border-radius: 6px; font-size: 16px; font-weight: 600;">
|
|
181
|
-
View Order
|
|
182
|
-
</a>
|
|
183
|
-
</td>
|
|
184
|
-
</tr>
|
|
185
|
-
</table>
|
|
186
|
-
<p style="color: #999; font-size: 13px; line-height: 1.6; margin: 0;">
|
|
187
|
-
We'll send you another email when your order is shipped.
|
|
188
|
-
</p>
|
|
189
|
-
</td>
|
|
190
|
-
</tr>
|
|
191
|
-
<tr>
|
|
192
|
-
<td style="background-color: #f8f9fa; padding: 24px; text-align: center; border-top: 1px solid #eee;">
|
|
193
|
-
<p style="color: #999; font-size: 12px; margin: 0;">
|
|
194
|
-
© ${currentYear()} ${siteName}. All rights reserved.
|
|
195
|
-
</p>
|
|
196
|
-
</td>
|
|
197
|
-
</tr>
|
|
198
|
-
</table>
|
|
199
|
-
</td>
|
|
200
|
-
</tr>
|
|
201
|
-
</table>
|
|
202
|
-
</body>
|
|
203
|
-
</html>
|
|
204
|
-
`,
|
|
165
|
+
html: buildOrderConfirmationHtml({ userName, orderId, formattedTotal, shippingAddress, paymentMethod, orderUrl, itemsHtml, siteName, items }),
|
|
205
166
|
text: `Hi ${userName},\n\nYour order ${orderId} has been confirmed!\n\n${itemsText}\nTotal: ${formattedTotal}\nPayment: ${paymentMethod === "cod" ? "Cash on Delivery" : "Online Payment"}\nShip to: ${shippingAddress}\n\nView your order: ${orderUrl}\n\n© ${currentYear()} ${siteName}`,
|
|
206
167
|
});
|
|
207
168
|
if (error) {
|
|
@@ -6,12 +6,22 @@ import { Alert, Button, Div, Heading, Input, Span, StackedViewShell, Text, } fro
|
|
|
6
6
|
import { apiClient } from "../../../http";
|
|
7
7
|
import { useCopilotChat } from "../hooks/useCopilotChat";
|
|
8
8
|
import { THEME_CONSTANTS } from "../../../tokens";
|
|
9
|
+
const LBL_CONVERSATION_ID = "Conversation ID";
|
|
9
10
|
function MessageBubble({ msg }) {
|
|
10
11
|
const isUser = msg.role === "user";
|
|
11
12
|
return (_jsx(Div, { className: `flex ${isUser ? "justify-end" : "justify-start"}`, children: _jsxs(Div, { className: `max-w-[80%] rounded-2xl px-4 py-2.5 text-sm ${isUser
|
|
12
13
|
? "bg-primary text-white rounded-tr-sm"
|
|
13
14
|
: "bg-neutral-100 dark:bg-slate-700 text-neutral-900 dark:text-neutral-100 rounded-tl-sm"}`, children: [_jsx(Text, { className: "whitespace-pre-wrap text-sm leading-relaxed", children: msg.content }), msg.durationMs ? (_jsxs(Span, { className: "mt-1 block text-xs opacity-60", children: [(msg.durationMs / 1000).toFixed(1), "s"] })) : null] }) }));
|
|
14
15
|
}
|
|
16
|
+
function renderCopilotChatPanel(props) {
|
|
17
|
+
const { messages, conversationId, isLoading, error, input, setInput, labels, messagesEndRef, handleSubmit } = props;
|
|
18
|
+
return (_jsxs(Div, { className: "flex flex-col rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 h-[calc(100vh-300px)]", children: [_jsx(Div, { className: "border-b border-neutral-200 dark:border-slate-700 p-3", children: _jsxs(Text, { className: "text-xs font-medium text-neutral-500 dark:text-zinc-400", children: [labels?.conversationId ?? LBL_CONVERSATION_ID, ": ", conversationId] }) }), _jsxs(Div, { className: "flex-1 overflow-y-auto p-4 space-y-4", children: [messages.length === 0 ? (_jsxs(Div, { className: "flex flex-col items-center justify-center h-full text-center", children: [_jsx(Text, { className: "font-medium", children: labels?.noMessages ?? "No messages yet" }), _jsx(Text, { variant: "secondary", className: "text-sm mt-1", children: labels?.noMessagesDesc ?? "Ask anything to get started" })] })) : null, messages.map((msg) => _jsx(MessageBubble, { msg: msg }, msg.id)), isLoading ? (_jsx(Div, { className: "flex justify-start", children: _jsx(Div, { className: "rounded-2xl rounded-tl-sm bg-neutral-100 dark:bg-slate-700 px-4 py-2.5", children: _jsx(Span, { className: "text-sm opacity-60 animate-pulse", children: "Thinking..." }) }) })) : null, error ? _jsx(Text, { className: "text-center text-sm text-red-500", children: labels?.errorLabel ?? "An error occurred. Please try again." }) : null, _jsx("div", { ref: messagesEndRef })] }), _jsx(Div, { className: "border-t border-neutral-200 dark:border-slate-700 p-3", children: _jsxs("form", { onSubmit: handleSubmit, className: "flex gap-2", children: [_jsx("input", { type: "text", value: input, onChange: (e) => setInput(e.target.value), placeholder: labels?.inputPlaceholder ?? "Ask anything...", disabled: isLoading, className: "flex-1 h-10 rounded-lg border border-neutral-200 dark:border-slate-600 bg-white dark:bg-slate-800 px-3 text-sm outline-none focus:ring-2 ring-primary/20 transition disabled:opacity-60" }), _jsx(Button, { type: "submit", variant: "primary", disabled: isLoading || !input.trim(), className: "shrink-0", children: isLoading ? labels?.sendingButton ?? "Sending..." : labels?.sendButton ?? "Send" })] }) })] }));
|
|
19
|
+
}
|
|
20
|
+
function renderCopilotHistoryPanel(props) {
|
|
21
|
+
const { historyQuery, conversationInput, setConversationInput, loadConversation, labels } = props;
|
|
22
|
+
return (_jsxs(Div, { className: "rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-900 p-4 space-y-3", children: [_jsx(Heading, { level: 3, className: "text-sm font-semibold", children: labels?.historyTitle ?? "Conversation History" }), _jsxs("form", { className: "space-y-2", onSubmit: (e) => { e.preventDefault(); if (!conversationInput.trim())
|
|
23
|
+
return; loadConversation(conversationInput.trim()); }, children: [_jsx(Input, { label: labels?.conversationId ?? LBL_CONVERSATION_ID, value: conversationInput, onChange: (e) => setConversationInput(e.target.value), placeholder: "conv_..." }), _jsx(Button, { type: "submit", variant: "secondary", size: "sm", className: "w-full", children: labels?.loadConversation ?? "Load conversation" })] }), historyQuery.error ? (_jsx(Alert, { variant: "warning", title: "History unavailable", children: historyQuery.error instanceof Error ? historyQuery.error.message : "Could not load history" })) : null, _jsxs(Div, { className: "max-h-72 overflow-y-auto space-y-2", children: [(historyQuery.data?.messages ?? []).map((log, index) => (_jsxs(Div, { className: "rounded-lg border border-neutral-200 dark:border-slate-700 p-2", children: [_jsx(Text, { className: "text-xs font-medium text-neutral-500 dark:text-zinc-400", children: new Date(log.createdAt).toLocaleString() }), _jsxs(Text, { className: `text-sm mt-1 ${THEME_CONSTANTS.utilities.textClamp3}`, children: ["Q: ", log.prompt] }), _jsxs(Text, { className: `text-sm mt-1 ${THEME_CONSTANTS.utilities.textClamp3} text-neutral-600 dark:text-zinc-300`, children: ["A: ", log.response] })] }, `${log.createdAt}-${index}`))), !historyQuery.isLoading && (historyQuery.data?.messages?.length ?? 0) === 0 ? (_jsx(Text, { variant: "secondary", className: "text-sm", children: "No server history found for this conversation yet." })) : null] })] }));
|
|
24
|
+
}
|
|
15
25
|
export function AdminCopilotView({ endpoint, historyEndpoint = "/api/copilot/history", renderHeader, labels = {}, className = "", }) {
|
|
16
26
|
const [input, setInput] = useState("");
|
|
17
27
|
const [conversationInput, setConversationInput] = useState("");
|
|
@@ -34,11 +44,11 @@ export function AdminCopilotView({ endpoint, historyEndpoint = "/api/copilot/his
|
|
|
34
44
|
};
|
|
35
45
|
return (_jsx(StackedViewShell, { portal: "admin", title: labels.title ?? "AI Copilot", className: className, sections: [
|
|
36
46
|
renderHeader ? (renderHeader(startNewConversation)) : (_jsxs(Div, { className: "flex items-center justify-between gap-3", children: [_jsx(Heading, { level: 2, children: labels.title ?? "AI Copilot" }), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: startNewConversation, children: labels.newConversation ?? "New Conversation" })] })),
|
|
37
|
-
_jsxs(Div, { className: "grid grid-cols-1 lg:grid-cols-[2fr,1fr] gap-4", children: [_jsxs(Div, { className: "flex flex-col rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 h-[calc(100vh-300px)]", children: [_jsx(Div, { className: "border-b border-neutral-200 dark:border-slate-700 p-3", children: _jsxs(Text, { className: "text-xs font-medium text-neutral-500 dark:text-zinc-400", children: [labels.conversationId ??
|
|
47
|
+
_jsxs(Div, { className: "grid grid-cols-1 lg:grid-cols-[2fr,1fr] gap-4", children: [_jsxs(Div, { className: "flex flex-col rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 h-[calc(100vh-300px)]", children: [_jsx(Div, { className: "border-b border-neutral-200 dark:border-slate-700 p-3", children: _jsxs(Text, { className: "text-xs font-medium text-neutral-500 dark:text-zinc-400", children: [labels.conversationId ?? LBL_CONVERSATION_ID, ": ", conversationId] }) }), _jsxs(Div, { className: "flex-1 overflow-y-auto p-4 space-y-4", children: [messages.length === 0 ? (_jsxs(Div, { className: "flex flex-col items-center justify-center h-full text-center", children: [_jsx(Text, { className: "font-medium", children: labels.noMessages ?? "No messages yet" }), _jsx(Text, { variant: "secondary", className: "text-sm mt-1", children: labels.noMessagesDesc ?? "Ask anything to get started" })] })) : null, messages.map((msg) => (_jsx(MessageBubble, { msg: msg }, msg.id))), isLoading ? (_jsx(Div, { className: "flex justify-start", children: _jsx(Div, { className: "rounded-2xl rounded-tl-sm bg-neutral-100 dark:bg-slate-700 px-4 py-2.5", children: _jsx(Span, { className: "text-sm opacity-60 animate-pulse", children: "Thinking..." }) }) })) : null, error ? (_jsx(Text, { className: "text-center text-sm text-red-500", children: labels.errorLabel ?? "An error occurred. Please try again." })) : null, _jsx("div", { ref: messagesEndRef })] }), _jsx(Div, { className: "border-t border-neutral-200 dark:border-slate-700 p-3", children: _jsxs("form", { onSubmit: handleSubmit, className: "flex gap-2", children: [_jsx("input", { type: "text", value: input, onChange: (event) => setInput(event.target.value), placeholder: labels.inputPlaceholder ?? "Ask anything...", disabled: isLoading, className: "flex-1 h-10 rounded-lg border border-neutral-200 dark:border-slate-600 bg-white dark:bg-slate-800 px-3 text-sm outline-none focus:ring-2 ring-primary/20 transition disabled:opacity-60" }), _jsx(Button, { type: "submit", variant: "primary", disabled: isLoading || !input.trim(), className: "shrink-0", children: isLoading ? labels.sendingButton ?? "Sending..." : labels.sendButton ?? "Send" })] }) })] }), _jsxs(Div, { className: "rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-900 p-4 space-y-3", children: [_jsx(Heading, { level: 3, className: "text-sm font-semibold", children: labels.historyTitle ?? "Conversation History" }), _jsxs("form", { className: "space-y-2", onSubmit: (event) => {
|
|
38
48
|
event.preventDefault();
|
|
39
49
|
if (!conversationInput.trim())
|
|
40
50
|
return;
|
|
41
51
|
loadConversation(conversationInput.trim());
|
|
42
|
-
}, children: [_jsx(Input, { label: labels.conversationId ??
|
|
52
|
+
}, children: [_jsx(Input, { label: labels.conversationId ?? LBL_CONVERSATION_ID, value: conversationInput, onChange: (event) => setConversationInput(event.target.value), placeholder: "conv_..." }), _jsx(Button, { type: "submit", variant: "secondary", size: "sm", className: "w-full", children: labels.loadConversation ?? "Load conversation" })] }), historyQuery.error ? (_jsx(Alert, { variant: "warning", title: "History unavailable", children: historyQuery.error instanceof Error ? historyQuery.error.message : "Could not load history" })) : null, _jsxs(Div, { className: "max-h-72 overflow-y-auto space-y-2", children: [(historyQuery.data?.messages ?? []).map((log, index) => (_jsxs(Div, { className: "rounded-lg border border-neutral-200 dark:border-slate-700 p-2", children: [_jsx(Text, { className: "text-xs font-medium text-neutral-500 dark:text-zinc-400", children: new Date(log.createdAt).toLocaleString() }), _jsxs(Text, { className: `text-sm mt-1 ${THEME_CONSTANTS.utilities.textClamp3}`, children: ["Q: ", log.prompt] }), _jsxs(Text, { className: `text-sm mt-1 ${THEME_CONSTANTS.utilities.textClamp3} text-neutral-600 dark:text-zinc-300`, children: ["A: ", log.response] })] }, `${log.createdAt}-${index}`))), !historyQuery.isLoading && (historyQuery.data?.messages?.length ?? 0) === 0 ? (_jsx(Text, { variant: "secondary", className: "text-sm", children: "No server history found for this conversation yet." })) : null] })] })] }),
|
|
43
53
|
] }));
|
|
44
54
|
}
|