diff --git a/src/pages/News/AuthorsPage.tsx b/src/pages/News/AuthorsPage.tsx index a49bc47e..b26517d8 100644 --- a/src/pages/News/AuthorsPage.tsx +++ b/src/pages/News/AuthorsPage.tsx @@ -1,7 +1,7 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; import { motion } from 'framer-motion'; -import { User, Building, BookOpen } from 'lucide-react'; +import { User, Building, BookOpen, Search } from 'lucide-react'; import Header from '@/sections/Header'; import Footer from '@/sections/Footer'; @@ -17,6 +17,16 @@ const AuthorsPage: React.FC = () => { const [authors, setAuthors] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); + const [searchTerm, setSearchTerm] = useState(''); + const [debouncedSearch, setDebouncedSearch] = useState(''); + + // Debounce search input + useEffect(() => { + const handler = setTimeout(() => { + setDebouncedSearch(searchTerm.trim().toLowerCase()); + }, 300); + return () => clearTimeout(handler); + }, [searchTerm]); useEffect(() => { const loadAllAuthors = async () => { @@ -61,6 +71,14 @@ const AuthorsPage: React.FC = () => { navigate(`/authors/${slug}`); }; + // Filter authors based on search + const filteredAuthors = useMemo(() => { + if (!debouncedSearch) return authors; + return authors.filter((author) => + author.name.toLowerCase().includes(debouncedSearch), + ); + }, [authors, debouncedSearch]); + const renderContent = () => { if (isLoading) { return ( @@ -95,88 +113,113 @@ const AuthorsPage: React.FC = () => { ); } + // Search bar return ( -
- {authors.map((author, index) => ( - handleAuthorClick(author.slug)} - className="bg-white dark:bg-gray-800 rounded-2xl shadow-xl dark:shadow-2xl dark:shadow-black/20 - transition-shadow duration-300 group-hover:shadow-blue-200 dark:group-hover:shadow-blue-500/30 - cursor-pointer group flex flex-col" - initial={{ opacity: 0, y: 20 }} - animate={{ opacity: 1, y: 0 }} - transition={{ - duration: 0.5, - delay: index * 0.1, - scale: { - type: 'spring', - stiffness: 300, - damping: 15, - }, - }} - whileHover={{ scale: 1.05 }} - > -
- {/* Avatar */} -
- {author.avatar ? ( - {author.name} - ) : ( -
- +
+
+
+ + setSearchTerm(e.target.value)} + /> +
+
+ + {filteredAuthors.length === 0 ? ( +
+ No authors found matching " + + {searchTerm} + + " +
+ ) : ( +
+ {filteredAuthors.map((author, index) => ( + handleAuthorClick(author.slug)} + className="bg-white dark:bg-gray-800 rounded-2xl shadow-xl dark:shadow-2xl dark:shadow-black/20 + transition-shadow duration-300 group-hover:shadow-blue-200 dark:group-hover:shadow-blue-500/30 + cursor-pointer group flex flex-col" + initial={{ opacity: 0, y: 20 }} + animate={{ opacity: 1, y: 0 }} + transition={{ + duration: 0.5, + delay: index * 0.1, + }} + whileHover={{ scale: 1.05 }} + > +
+ {/* Avatar */} +
+ {author.avatar ? ( + {author.name} + ) : ( +
+ +
+ )}
- )} -
- - {/* Author Info*/} -
-

- {author.name} -

- - {/* Title and Org */} -
- - {author.title} - - {author.organization && ( -
- - {author.organization} + + {/* Author Info*/} +
+

+ {author.name} +

+ + {/* Title and Org */} +
+ + {author.title} + + {author.organization && ( +
+ + + {author.organization} + +
+ )}
- )} -
- {/* Description */} -

- {author.description} -

- - {/* Quick Stats */} -
-
- - - {author.postCount}{' '} - {author.postCount === 1 ? 'Article' : 'Articles'} - -
- {author.organization && ( -
- - {author.organization} + {/* Description */} +

+ {author.description} +

+ + {/* Quick Stats */} +
+
+ + + {author.postCount}{' '} + {author.postCount === 1 ? 'Article' : 'Articles'} + +
+ {author.organization && ( +
+ + {author.organization} +
+ )}
- )} +
-
-
- - ))} + + ))} +
+ )}
); };