Unify portfolio and animal studies galleries
This commit is contained in:
76
src/components/animalStudies/AnimalStudiesGallery.tsx
Normal file
76
src/components/animalStudies/AnimalStudiesGallery.tsx
Normal file
@ -0,0 +1,76 @@
|
||||
"use client";
|
||||
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
|
||||
import type { AnimalStudiesCursor } from "@/actions/animalStudies/getAnimalStudiesPage";
|
||||
import { getAnimalStudiesPage } from "@/actions/animalStudies/getAnimalStudiesPage";
|
||||
import JustifiedGallery, { type JustifiedGalleryItem } from "@/components/gallery/JustifiedGallery";
|
||||
|
||||
export default function AnimalStudiesGallery({
|
||||
tagSlugs,
|
||||
}: {
|
||||
tagSlugs: string[];
|
||||
}) {
|
||||
const [items, setItems] = useState<JustifiedGalleryItem[]>([]);
|
||||
const [cursor, setCursor] = useState<AnimalStudiesCursor>(null);
|
||||
const [done, setDone] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const inFlight = useRef(false);
|
||||
|
||||
// Reset when tag filter changes (component key may already remount, but keep it safe)
|
||||
useEffect(() => {
|
||||
setItems([]);
|
||||
setCursor(null);
|
||||
setDone(false);
|
||||
setLoading(false);
|
||||
inFlight.current = false;
|
||||
}, []);
|
||||
|
||||
const loadMore = useCallback(async () => {
|
||||
if (inFlight.current || done) return;
|
||||
inFlight.current = true;
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
const res = await getAnimalStudiesPage({
|
||||
take: 60,
|
||||
cursor,
|
||||
tagSlugs,
|
||||
});
|
||||
|
||||
setItems((prev) => {
|
||||
const seen = new Set(prev.map((x) => x.id));
|
||||
const next = res.items.filter((x) => !seen.has(x.id));
|
||||
return prev.concat(next);
|
||||
});
|
||||
|
||||
setCursor(res.nextCursor);
|
||||
if (!res.nextCursor) setDone(true);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
inFlight.current = false;
|
||||
}
|
||||
}, [cursor, done, tagSlugs]);
|
||||
|
||||
useEffect(() => {
|
||||
void loadMore();
|
||||
}, [loadMore]);
|
||||
|
||||
return (
|
||||
<JustifiedGallery
|
||||
items={items}
|
||||
hrefFrom="animal-studies"
|
||||
showCaption
|
||||
targetRowHeight={160}
|
||||
targetRowHeightMobile={160}
|
||||
maxRowHeight={300}
|
||||
maxRowItems={5}
|
||||
maxRowItemsMobile={1}
|
||||
gap={12}
|
||||
onLoadMore={done ? undefined : () => void loadMore()}
|
||||
hasMore={!done}
|
||||
isLoadingMore={loading}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user