"use client"; import { api } from "@/trpc/react"; import React from "react"; import CategoryCard from "../category-card"; import { useInfiniteItemsObserver } from "@/lib/hooks/infinite-items-observer-hook"; import { Skeleton } from "@/components/ui/skeleton"; import { CATEGORY_GRID_CLASS } from "./category-grid"; import CategoryFilterBar, { CategoryFilter } from "../category-filter-bar"; export default function InfiniteCategoryGrid() { const [filter, setFilter] = React.useState({}); const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading } = api.category.getByCursor.useInfiniteQuery( { filter, }, { getNextPageParam: (lastPage) => lastPage.nextCursor, staleTime: 60 * 4 * 1000, // 4 minutes stale time refetchOnMount: false, // Prevents unnecessary refetching refetchOnWindowFocus: false, // Avoids refetch when switching tabs }, ); // 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((category, idx) => (
  • )) : null} {/* Loading indicator */} {(isLoading || isFetchingNextPage) && Array.from(new Array(isLoading ? 16 : 4).keys()).map((idx) => (
  • ))} {/* Bottom observer element */} {hasNextPage && (
  • )}
  • ); }