feat: infinite scroll

This commit is contained in:
Khairul Hidayat 2024-01-10 17:48:16 +00:00
parent 93fd7d7526
commit 30f63454e3
3 changed files with 66 additions and 7 deletions

View File

@ -19,6 +19,7 @@
"pixi.js": "^7.3.3",
"pocketbase": "^0.20.1",
"react": "^18.2.0",
"react-bottom-scroll-listener": "^5.1.0",
"react-dom": "^18.2.0",
"react-helmet": "^6.1.0",
"react-query": "^3.39.3",

View File

@ -1,6 +1,6 @@
import pb from "@/utility/api";
import { Howl } from "howler";
import { useQuery } from "react-query";
import { useInfiniteQuery } from "react-query";
import { Link } from "react-router-dom";
import playIcon from "@/assets/icons/play-outline.svg";
import openingSfx from "@/assets/audio/VO_JA_Furina_Opening_Treasure_Chest_02.ogg";
@ -8,6 +8,10 @@ import ViewSheet from "./viewSheet";
import useModal from "@/hooks/useModal";
import LazyImage from "@/components/ui/LazyImage";
import PageMetadata from "@/components/containers/PageMetadata";
import { useMemo } from "react";
import Button from "@/components/ui/Button";
import { useBottomScrollListener } from "react-bottom-scroll-listener";
import loadingIllust from "@/assets/images/l9fsdoa2j7vb1.gif";
const openingChestSfx = new Howl({
src: openingSfx,
@ -15,13 +19,32 @@ const openingChestSfx = new Howl({
});
const ArtworksPage = () => {
const { data } = useQuery({
const { data, isFetchingNextPage, hasNextPage, fetchNextPage } =
useInfiniteQuery({
queryKey: ["artworks"],
queryFn: () =>
pb.collection("artworks").getList(1, 100, { sort: "-created" }),
queryFn: ({ pageParam = 1 }) => {
return pb
.collection("artworks")
.getList(pageParam, 12, { sort: "-created" });
},
getNextPageParam: (lastPage) =>
lastPage.page < lastPage.totalPages ? lastPage.page + 1 : undefined,
});
useBottomScrollListener<HTMLDivElement>(
() => {
if (!isFetchingNextPage) {
fetchNextPage();
}
},
{ offset: 100 }
);
const viewItemModal = useModal<string>();
const items = useMemo(
() => data?.pages.flatMap((i) => i.items) || [],
[data]
);
return (
<div className="container py-16">
<PageMetadata title="Treasures" />
@ -43,7 +66,7 @@ const ArtworksPage = () => {
</div>
<div className="grid grid-cols-2 md:grid-cols-3 xl:grid-cols-4 gap-4 mt-8">
{data?.items.map((item) => (
{items.map((item) => (
<Link
key={item.id}
// to={`/treasures/${item.id}`}
@ -66,6 +89,29 @@ const ArtworksPage = () => {
))}
</div>
{hasNextPage && !isFetchingNextPage ? (
<div className="flex justify-center mt-8">
<Button
onClick={() => {
if (!isFetchingNextPage) {
fetchNextPage();
}
}}
variant="solid"
className="min-w-[200px]"
>
Load More
</Button>
</div>
) : null}
{isFetchingNextPage ? (
<div className="flex flex-col justify-center items-center text-center mt-12 py-8">
<img src={loadingIllust} className="h-32 animate-bounce" />
<p className="mt-2">Loading next items..</p>
</div>
) : null}
<ViewSheet modal={viewItemModal} />
</div>
);

View File

@ -2048,6 +2048,11 @@ locate-path@^6.0.0:
dependencies:
p-locate "^5.0.0"
lodash.debounce@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
lodash.merge@^4.6.2:
version "4.6.2"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
@ -2418,6 +2423,13 @@ queue-microtask@^1.2.2:
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
react-bottom-scroll-listener@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/react-bottom-scroll-listener/-/react-bottom-scroll-listener-5.1.0.tgz#8544536ad794c47ee0728c117f988d69cb05e0ff"
integrity sha512-HI4qRKLbQ0Ox8xwIgYtLMk+1zETTaLtGBrhcTUFVRLL3OjVzfnyPPiXPGDnAPY6sGQh4KFH7Flp1dddnSmG33A==
dependencies:
lodash.debounce "^4.0.8"
react-dom@^18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"