"use client"; import { useState, useEffect, useRef, useMemo } from 'react'; import { useKnowledgeBaseCategories, useFeaturedArticles, useKnowledgeBaseArticles } from '@/lib/hooks/useSupport'; import KnowledgeBaseArticleModal from './KnowledgeBaseArticleModal'; const KnowledgeBase = () => { const { categories, loading: categoriesLoading } = useKnowledgeBaseCategories(); const [searchTerm, setSearchTerm] = useState(''); const [selectedCategory, setSelectedCategory] = useState(null); const [selectedArticleSlug, setSelectedArticleSlug] = useState(null); // Refs for scrolling to results const articlesRef = useRef(null); const emptyStateRef = useRef(null); const articlesListRef = useRef(null); // Fetch all articles (for browsing and category filtering) const { articles: allArticles, loading: allArticlesLoading } = useKnowledgeBaseArticles(); // Fetch featured articles (for default view) const { articles: featuredArticles, loading: featuredLoading } = useFeaturedArticles(); // Determine which articles to display using useMemo for reactivity const { displayArticles, isLoading, headerText } = useMemo(() => { if (searchTerm) { // If searching, filter all articles by search term const filtered = allArticles.filter(article => article.title.toLowerCase().includes(searchTerm.toLowerCase()) || article.summary.toLowerCase().includes(searchTerm.toLowerCase()) || (article.content && article.content.toLowerCase().includes(searchTerm.toLowerCase())) ); return { displayArticles: filtered, isLoading: allArticlesLoading, headerText: 'Search Results' }; } else if (selectedCategory) { // If a category is selected, filter articles by that category const filtered = allArticles.filter(article => article.category_slug === selectedCategory); const categoryName = categories.find(cat => cat.slug === selectedCategory)?.name || 'Category'; return { displayArticles: filtered, isLoading: allArticlesLoading, headerText: `${categoryName} Articles` }; } else { return { displayArticles: featuredArticles, isLoading: featuredLoading, headerText: 'Featured Articles' }; } }, [searchTerm, selectedCategory, allArticles, featuredArticles, allArticlesLoading, featuredLoading, categories]); // Helper function to find the scrollable parent container const findScrollableParent = (element: HTMLElement | null): HTMLElement | null => { if (!element) return null; let parent = element.parentElement; while (parent) { const style = window.getComputedStyle(parent); const overflowY = style.overflowY || style.overflow; const maxHeight = style.maxHeight; // Check if this element is scrollable (has overflow and max-height) if ((overflowY === 'auto' || overflowY === 'scroll') && maxHeight && maxHeight !== 'none') { return parent; } parent = parent.parentElement; } return null; }; // Scroll to results when category is selected or search changes useEffect(() => { // Only scroll if we have a search term or selected category and articles are loaded if ((searchTerm || selectedCategory) && !isLoading) { // Wait for React to render the articles - use longer delay for category clicks const scrollTimeout = setTimeout(() => { requestAnimationFrame(() => { requestAnimationFrame(() => { if (articlesRef.current) { // Try to find the articles list first (most specific), then empty state, then first article item, then section const articlesList = articlesRef.current.querySelector('.articles-list'); const firstArticle = articlesRef.current.querySelector('.article-item'); const emptyState = articlesRef.current.querySelector('.empty-state'); const targetElement = articlesList || firstArticle || emptyState || articlesRef.current; if (targetElement) { // Find the scrollable parent container (the modal) const scrollableContainer = findScrollableParent(targetElement as HTMLElement); if (scrollableContainer) { // Calculate position relative to the scrollable container const containerRect = scrollableContainer.getBoundingClientRect(); const targetRect = targetElement.getBoundingClientRect(); // Calculate the scroll position within the container const scrollTop = scrollableContainer.scrollTop; const relativeTop = targetRect.top - containerRect.top; const offset = 20; // Small offset from top of container scrollableContainer.scrollTo({ top: scrollTop + relativeTop - offset, behavior: 'smooth' }); } else { // Fallback to window scroll if no scrollable container found const elementTop = targetElement.getBoundingClientRect().top + window.pageYOffset; const offsetPosition = elementTop - 100; window.scrollTo({ top: offsetPosition, behavior: 'smooth' }); } } } }); }); }, 600); // Longer delay to ensure React has fully rendered the articles return () => clearTimeout(scrollTimeout); } }, [searchTerm, selectedCategory, isLoading, displayArticles.length]); const handleSearch = (e: React.FormEvent) => { e.preventDefault(); // The search is already being performed by the hook }; const handleCategoryClick = (categorySlug: string) => { setSelectedCategory(categorySlug); // Clear search when category is selected if (searchTerm) { setSearchTerm(''); } // Scroll will be handled by useEffect after articles render }; const filteredCategories = selectedCategory ? categories.filter(cat => cat.slug === selectedCategory) : categories; return (

Knowledge Base

Find answers to frequently asked questions and explore our documentation.

{/* Search Bar */}
setSearchTerm(e.target.value)} placeholder="Search articles, topics, or keywords..." className="form-control" /> {searchTerm && ( )}
{/* Categories */} {!searchTerm && (

Browse by Category

{categoriesLoading ? (
Loading...
) : (
{Array.isArray(categories) && categories.map(category => (
handleCategoryClick(category.slug)} style={{ borderLeftColor: category.color }} >

{category.name}

{category.description}

{category.article_count} {category.article_count === 1 ? 'article' : 'articles'}
))}
)}
)} {/* Featured/Search Results Articles */}

{headerText}

{selectedCategory && !searchTerm && ( )}
{searchTerm && (

Found {displayArticles.length} {displayArticles.length === 1 ? 'article' : 'articles'} for "{searchTerm}"

)}
{isLoading ? (
Loading...
) : displayArticles.length === 0 ? (

No articles found

{searchTerm ? `We couldn't find any articles matching "${searchTerm}". Try different keywords.` : 'No articles available at the moment.'}

) : (
{Array.isArray(displayArticles) && displayArticles.map(article => (
setSelectedArticleSlug(article.slug)} >

{article.title}

{article.is_featured && ( Featured )}

{article.summary}

{article.category_name} {article.view_count} views {article.helpful_count} helpful
))}
)}
{/* Article Modal */} {selectedArticleSlug && ( setSelectedArticleSlug(null)} /> )}
); }; export default KnowledgeBase;