diff --git a/src/app/page.tsx b/src/app/page.tsx index 145dd82..64f5a78 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -76,6 +76,7 @@ export default async function HomePage({ searchParams }: HomePageProps) { )} (listArticles) + const [currentPage, setCurrentPage] = useState(page) + const [hasMoreState, setHasMoreState] = useState(hasMore) + const [isLoading, setIsLoading] = useState(false) + + const loadMoreRef = useRef(null) + + const loadNextPage = useCallback(async () => { + if (isLoading || !hasMoreState) return + setIsLoading(true) + + try { + const nextPage = currentPage + 1 + const isBrowsingAll = activeCategory === 'all' && !activeTag + const res = await getArticles({ + category: activeCategory, + tag: activeTag, + page: nextPage, + pageSize: 10, + is_pinned: isBrowsingAll ? false : undefined, + }) + + if (res && res.articles) { + setArticles((prev) => { + // Prevent duplicates just in case + const existingIds = new Set(prev.map((a) => a.id)) + const uniqueNew = res.articles.filter((a) => !existingIds.has(a.id)) + return [...prev, ...uniqueNew] + }) + setCurrentPage(nextPage) + setHasMoreState(res.total > nextPage * 10) + } else { + setHasMoreState(false) + } + } catch (err) { + console.error('[Infinite Scroll] Failed to load next page:', err) + } finally { + setIsLoading(false) + } + }, [isLoading, hasMoreState, currentPage, activeCategory, activeTag]) + + useEffect(() => { + if (!hasMoreState) return + + const observer = new IntersectionObserver( + (entries) => { + if (entries[0].isIntersecting) { + loadNextPage() + } + }, + { threshold: 0.1, rootMargin: '100px' } + ) + + const currentRef = loadMoreRef.current + if (currentRef) { + observer.observe(currentRef) + } + + return () => { + observer.disconnect() + } + }, [hasMoreState, loadNextPage]) + const categoryResetHref = activeTag ? `/?tag=${activeTag}` : '/' const tagResetHref = activeCategory === 'all' ? '/' : `/?category=${activeCategory}` @@ -66,7 +133,7 @@ export function ArticleGrid({ )} - {listArticles.length === 0 && !featuredArticle ? ( + {articles.length === 0 && !featuredArticle ? (

) : (

- {listArticles.map((article, index) => ( + {articles.map((article, index) => (
{index > 0 &&
}
@@ -91,34 +158,31 @@ export function ArticleGrid({
)} - {hasMore && ( -
- - Charger la suite → - + {hasMoreState && ( +
+ {isLoading && Chargement...}
)}