added category infinite grid and fixed missing items at useInfiniteQuery
This commit is contained in:
+8
-7
@@ -1,13 +1,14 @@
|
||||
import CategoryCard from "@/components/category/category-card";
|
||||
import { Category } from "@/server/db/schema";
|
||||
import React from "react";
|
||||
import { Skeleton } from "../ui/skeleton";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
|
||||
const GRID_CLASS = "grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3";
|
||||
export const CATEGORY_GRID_CLASS =
|
||||
"grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3";
|
||||
|
||||
function CategoriesGrid({ categories }: { categories: Category[] }) {
|
||||
function CategoryGrid({ categories }: { categories: Category[] }) {
|
||||
return (
|
||||
<menu className={GRID_CLASS}>
|
||||
<menu className={CATEGORY_GRID_CLASS}>
|
||||
{categories.map((category) => (
|
||||
<li key={category.id}>
|
||||
<CategoryCard {...category} />
|
||||
@@ -17,12 +18,12 @@ function CategoriesGrid({ categories }: { categories: Category[] }) {
|
||||
);
|
||||
}
|
||||
|
||||
export default CategoriesGrid;
|
||||
export default CategoryGrid;
|
||||
|
||||
export function CategoriesGridSkeleton() {
|
||||
export function CategoryGridSkeleton() {
|
||||
const range = Array.from(new Array(6).keys());
|
||||
return (
|
||||
<ul className={GRID_CLASS}>
|
||||
<ul className={CATEGORY_GRID_CLASS}>
|
||||
{range.map((i) => (
|
||||
<li key={i}>
|
||||
<Skeleton className="h-12 w-full" />
|
||||
@@ -0,0 +1,67 @@
|
||||
"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 ArticleFilterBar, { ArticleFilter } from "../article-filter-bar";
|
||||
|
||||
export default function InfiniteCategoryGrid() {
|
||||
// const [filter, setFilter] = React.useState<ArticleFilter | undefined>(
|
||||
// undefined,
|
||||
// );
|
||||
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading } =
|
||||
api.category.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 (
|
||||
<div className="relative space-y-4">
|
||||
{/* <ArticleFilterBar onFilterUpdate={setFilter} /> */}
|
||||
<menu className={`${CATEGORY_GRID_CLASS} overflow-auto`}>
|
||||
{data?.pages?.length
|
||||
? allItems.map((category, idx) => (
|
||||
<li key={`category-${idx}`}>
|
||||
<CategoryCard {...category} />
|
||||
</li>
|
||||
))
|
||||
: null}
|
||||
|
||||
{/* Loading indicator */}
|
||||
{(isLoading || isFetchingNextPage) &&
|
||||
Array.from(new Array(isLoading ? 16 : 4).keys()).map((idx) => (
|
||||
<li key={idx}>
|
||||
<Skeleton className="size-full min-h-20" />
|
||||
</li>
|
||||
))}
|
||||
|
||||
{/* Bottom observer element */}
|
||||
{hasNextPage && (
|
||||
<li ref={bottomObserverRef} className="col-span-full h-12" />
|
||||
)}
|
||||
</menu>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user