"use client"; import { api } from "@/trpc/react"; import React from "react"; import { ARTICLE_GRID_CLASS } from "./article-grid"; import ArticleCard from "../article-card"; import { useInfiniteItemsObserver } from "@/lib/hooks/infinite-items-observer-hook"; import { Skeleton } from "@/components/ui/skeleton"; import ArticleFilterBar, { ArticleFilter } from "../article-filter-bar"; function InfiniteArticlesGrid() { const [filter, setFilter] = React.useState( undefined, ); const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading } = api.article.getByCursor.useInfiniteQuery( { filter, }, { getNextPageParam: (lastPage) => lastPage.nextCursor, }, ); // Calculate all visible items across all loaded pages const allItems = React.useMemo(() => { return data?.pages.flatMap((page) => page.items) || []; }, [data]); // Ref for bottom observation const bottomObserverRef = React.useRef(null); useInfiniteItemsObserver({ bottomObserverRef, fetchNextPage, hasNextPage, isFetchingNextPage, }); return (
{data?.pages?.length ? allItems.map((article, idx) => (
  • )) : null} {/* Loading indicator */} {(isLoading || isFetchingNextPage) && Array.from(new Array(isLoading ? 16 : 4).keys()).map((idx) => (
  • ))} {/* Bottom observer element */} {hasNextPage && (
  • )}
  • ); } export default InfiniteArticlesGrid;