import { BookOpen, ChevronLeft, ChevronRight, Filter, Grid, List, Search, X } from 'lucide-react'; import { useRef, useState, useEffect } from 'react'; import { BlogItem, useGetBlogsQuery } from '../redux/services/blogApi'; import { useGetFaqCategoriesQuery } from '../redux/services/faqApi'; import { ImageWithFallback } from './figma/ImageWithFallback'; import { PrimaryCTAButton } from './PrimaryCTAButton'; import { navigateTo } from './Router'; import { Badge } from './ui/badge'; import { Button } from './ui/button'; import { Card, CardContent } from './ui/card'; import { Input } from './ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select'; import { FullScreenLoader } from './FullScreenLoader'; import { getSlugWithId } from '../utils/urlHelpers'; // Define category type with ID and name interface CategoryOption { id: string; name: string; } type DateRange = | 'all_time' | 'last_7_days' | 'last_30_days' | 'last_3_months' | 'last_6_months'; type SortBy = | 'most_recent' | 'oldest_first' | 'title_az'; export function Articles() { const [searchTerm, setSearchTerm] = useState(''); const [selectedCategory, setSelectedCategory] = useState({ id: 'all', name: 'All Categories' }); const [selectedReadTime, setSelectedReadTime] = useState('All Read Times'); const [selectedDateRange, setSelectedDateRange] = useState('all_time'); const [selectedTopic, setSelectedTopic] = useState<{ id: string; name: string; }>({ id: 'all', name: 'All Topics' }); const [sortBy, setSortBy] = useState('most_recent'); const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid'); const [currentPage, setCurrentPage] = useState(1); const [debouncedSearch, setDebouncedSearch] = useState(''); const articlesPerPage = 6; const containerRef = useRef(null); const [allTags, setAllTags] = useState<{ id: string; name: string }[]>([]); // Fetch categories for filter dropdown const { data: categoriesData, isLoading: isLoadingCategories } = useGetFaqCategoriesQuery({ limit: 100, offset: 0 }); // Filter categories to only those for blog and create options with id and name const categories: CategoryOption[] = [ { id: 'all', name: 'All Categories' }, ...(categoriesData?.data?.items ?.filter((category: any) => category.for_blog) .map((category: any) => ({ id: category.id, name: category.category_name })) || []) ]; // Debounce search term useEffect(() => { const timer = setTimeout(() => { setDebouncedSearch(searchTerm); }, 500); return () => clearTimeout(timer); }, [searchTerm]); // Fetch blogs from API with all parameters const { data: blogsData, isLoading: isLoadingBlogs, isError: isBlogsError, refetch: refetchBlogs } = useGetBlogsQuery({ limit: articlesPerPage, offset: (currentPage - 1) * articlesPerPage, search: debouncedSearch || undefined, content_status: 'publish', content_type: 'BLOG', date_range: selectedDateRange !== 'all_time' ? selectedDateRange : undefined, sort_by: sortBy, content_category_id: selectedCategory.id !== 'all' ? selectedCategory.id : undefined, // Send UUID tag_id: selectedTopic.id !== 'all' ? selectedTopic.id : undefined, }); const sortOptions = [ { value: 'most_recent', label: 'Most Recent' }, { value: 'oldest_first', label: 'Oldest First' }, { value: 'title_az', label: 'Title A-Z' } ]; const readTimes = ['All Read Times', 'Under 5 min', '5-10 min', 'Over 10 min']; const dateRanges = [ { value: 'all_time', label: 'All Time' }, { value: 'last_7_days', label: 'Last 7 days' }, { value: 'last_30_days', label: 'Last 30 days' }, { value: 'last_3_months', label: 'Last 3 months' } ]; // Format date function const formatDate = (dateString: string) => { return new Date(dateString).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }); }; // Calculate read time based on content length (approx) const calculateReadTime = (content: string): string => { const wordsPerMinute = 200; const wordCount = content.split(/\s+/).length; const minutes = Math.ceil(wordCount / wordsPerMinute); return `${minutes} min read`; }; // Filter articles by read time (client-side only - API doesn't support this) const getReadTimeFilteredArticles = () => { if (selectedReadTime === 'All Read Times' || !blogsData?.data?.items) { return blogsData?.data?.items || []; } return (blogsData?.data?.items || []).filter((blog: BlogItem) => { const readTimeMinutes = parseInt(calculateReadTime(blog.content).replace(' min read', '')) || 0; return (selectedReadTime === 'Under 5 min' && readTimeMinutes < 5) || (selectedReadTime === '5-10 min' && readTimeMinutes >= 5 && readTimeMinutes <= 10) || (selectedReadTime === 'Over 10 min' && readTimeMinutes > 10); }); }; const finalFilteredArticles = getReadTimeFilteredArticles(); const totalPages = Math.ceil((blogsData?.data?.pagination?.total || 0) / articlesPerPage); const clearAllFilters = () => { setSearchTerm(''); setDebouncedSearch(''); setSelectedCategory({ id: 'all', name: 'All Categories' }); setSelectedReadTime('All Read Times'); setSelectedDateRange('all_time'); setSelectedTopic({ id: 'all', name: 'All Topics' }); setSortBy('most_recent'); setCurrentPage(1); }; const hasActiveFilters = Boolean( searchTerm || selectedCategory.id !== 'all' || selectedReadTime !== 'All Read Times' || selectedDateRange !== 'all_time' || selectedTopic.id !== 'all' ); useEffect(() => { if (!blogsData?.data?.items || allTags.length > 0) return; const tags = Array.from( new Map( blogsData.data.items .flatMap((blog: BlogItem) => blog.blog_tags || []) .map(tag => [tag.id, { id: tag.id, name: tag.tag_name }]) ).values() ); setAllTags(tags); }, [blogsData]); // Handle loading state if (isLoadingBlogs || isLoadingCategories) { return (
); } // Handle error state if (isBlogsError) { return (

Failed to load articles

Please try again later

); } return (
{/* Hero Section */}
INSIGHTS & KNOWLEDGE

Articles & Research

Discover cutting-edge insights, research findings, and expert perspectives on leadership development, management strategies, and organizational excellence.

{/* Statistics Strip */}
{blogsData?.data?.pagination?.total || 0}+
Expert Articles
{categories.length - 1}
Categories
{allTags.length}+
Topics
{/* Search and Controls Section */}
{/* Search Bar */}
setSearchTerm(e.target.value)} className="pl-10 pr-4 py-3 text-body rounded-lg border border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-200 transition-all duration-200 w-full bg-gray-50" style={{ fontSize: 'var(--font-body)', fontFamily: 'var(--font-family-base)', height: '48px' }} />
{/* View Toggle and Sort */}
{/* Main Content Section with Sidebar */}
{/* Left Sidebar - Sticky Filters */}
{/* Filter Header */}

Filters

{hasActiveFilters && ( )}
{/* Filter Content */}
{/* Category Filter */}
{/* Read Time Filter - Client-side only */}
{/* Date Range Filter */}
{/* Topics Filter */}
{/* Right Content Area - Scrollable Articles */}
Showing {finalFilteredArticles.length} of {blogsData?.data?.pagination?.total || 0} articles
{/* Articles Results */} {finalFilteredArticles.length === 0 ? (

No articles found matching your criteria.

{hasActiveFilters && ( )}
) : ( <> {/* Grid View */} {viewMode === 'grid' && (
{finalFilteredArticles.map((article: BlogItem) => ( { // Use slug_name to create the URL with full UUID const url = getSlugWithId(article.slug_name, article.id); navigateTo(`/learning/articles/${url}`); }} >
{article.content_category} {calculateReadTime(article.content)}

{article.title}

{article.short_description || article.content.substring(0, 150) + '...'}

{formatDate(article.updated_at)}
{/* Display tags if available */} {article.blog_tags && article.blog_tags.length > 0 && (
{article.blog_tags.slice(0, 3).map((tag, idx) => ( {tag.tag_name} ))} {article.blog_tags.length > 3 && ( +{article.blog_tags.length - 3} )}
)}
))}
)} {/* List View */} {viewMode === 'list' && (
{finalFilteredArticles.map((article: BlogItem) => ( { // Use slug_name to create the URL with full UUID const url = getSlugWithId(article.slug_name, article.id); navigateTo(`/learning/articles/${url}`); }} >
{article.content_category} {calculateReadTime(article.content)}

{article.title}

{article.short_description || article.content.substring(0, 200) + '...'}

{formatDate(article.updated_at)}
{/* Display tags if available */} {article.blog_tags && article.blog_tags.length > 0 && (
{article.blog_tags.slice(0, 2).map((tag, idx) => ( {tag.tag_name} ))} {article.blog_tags.length > 2 && ( +{article.blog_tags.length - 2} )}
)}
))}
)} {/* Pagination */} {totalPages > 1 && (
{Array.from({ length: totalPages }, (_, i) => { const page = i + 1; // Show limited pages for better UX if (totalPages > 7) { const showPage = page === 1 || page === totalPages || (page >= currentPage - 1 && page <= currentPage + 1); if (!showPage) { if (page === currentPage - 2 || page === currentPage + 2) { return ...; } return null; } } return ( ); })}
)} )}
{/* CTA Banner Section */}
NEXT STEPS

Ready to explore more insights? {" "}Discover{" "} our complete library of leadership resources.

navigateTo('/learning/articles')} ariaLabel="Browse all leadership articles and resources" className="cta-banner-yellow mb-6" />

Access cutting-edge research, expert insights, and practical guidance to accelerate your leadership journey and organizational success.

); }