diff --git a/src/Router.tsx b/src/Router.tsx
index bf4cef2..559b309 100644
--- a/src/Router.tsx
+++ b/src/Router.tsx
@@ -16,7 +16,10 @@ const router = createBrowserRouter([
{
path: "/treasures",
Component: ArtworksPage,
- children: [{ index: true }, { path: ":id" }],
+ },
+ {
+ path: "/treasures/:id",
+ Component: ArtworksPage,
},
],
ErrorBoundary: () => (
diff --git a/src/components/ui/LazyImage.tsx b/src/components/ui/LazyImage.tsx
index 23a5807..6a6e65f 100644
--- a/src/components/ui/LazyImage.tsx
+++ b/src/components/ui/LazyImage.tsx
@@ -4,32 +4,40 @@ import React, { useState } from "react";
type Props = React.ComponentProps<"img"> & {
lazySrc: string;
containerClassName?: string;
+ placeholderClassName?: string;
+ placeholder?: React.ReactNode;
};
const LazyImage = ({
lazySrc,
src,
containerClassName,
+ placeholderClassName,
className,
+ placeholder,
...props
}: Props) => {
const [isLoaded, setLoaded] = useState(false);
return (
-
+
+
+
+ {!isLoaded && placeholder ? placeholder : null}
+

setLoaded(true)}
+ onLoad={() => setTimeout(() => setLoaded(true), 50)}
className={cn(
- "transition-all",
+ "transition-all duration-500 relative z-[1]",
isLoaded ? "opacity-100" : "opacity-0",
className
)}
diff --git a/src/pages/artworks/ArtworkListing.tsx b/src/pages/artworks/ArtworkListing.tsx
new file mode 100644
index 0000000..2d65246
--- /dev/null
+++ b/src/pages/artworks/ArtworkListing.tsx
@@ -0,0 +1,83 @@
+import pb from "@/utility/api";
+import { useInfiniteQuery } from "react-query";
+import { Link } from "react-router-dom";
+import LazyImage from "@/components/ui/LazyImage";
+import React, { useMemo } from "react";
+import Button from "@/components/ui/Button";
+import { useBottomScrollListener } from "react-bottom-scroll-listener";
+import { Skeleton } from "@/components/ui/Skeleton";
+
+const ArtworkListing = () => {
+ const { data, isLoading, isFetchingNextPage, hasNextPage, fetchNextPage } =
+ useInfiniteQuery({
+ queryKey: ["artworks"],
+ queryFn: ({ pageParam = 1 }) => {
+ return pb
+ .collection("artworks")
+ .getList(pageParam, 12, { sort: "-created" });
+ },
+ getNextPageParam: (lastPage) =>
+ lastPage.page < lastPage.totalPages ? lastPage.page + 1 : undefined,
+ });
+
+ useBottomScrollListener
(
+ () => {
+ if (!isFetchingNextPage) {
+ fetchNextPage();
+ }
+ },
+ { offset: 100 }
+ );
+
+ const items = useMemo(
+ () => data?.pages.flatMap((i) => i.items) || [],
+ [data]
+ );
+
+ return (
+
+
+ {items.map((item) => (
+
+
+
+
+ ))}
+
+ {isLoading || isFetchingNextPage
+ ? [...Array(12)].map((_, idx) => (
+
+ ))
+ : null}
+
+
+ {hasNextPage && !isFetchingNextPage ? (
+
+
+
+ ) : null}
+
+ );
+};
+
+export default React.memo(ArtworkListing);
diff --git a/src/pages/artworks/page.tsx b/src/pages/artworks/page.tsx
index d2967e8..d66657d 100644
--- a/src/pages/artworks/page.tsx
+++ b/src/pages/artworks/page.tsx
@@ -1,16 +1,11 @@
-import pb from "@/utility/api";
import { Howl } from "howler";
-import { useInfiniteQuery } from "react-query";
-import { Link, useNavigate, useParams } from "react-router-dom";
+import { useLocation, useNavigate, useParams } 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";
import ViewSheet from "./viewSheet";
-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 { Skeleton } from "@/components/ui/Skeleton";
+import ArtworkListing from "./ArtworkListing";
+import { useCallback } from "react";
const openingChestSfx = new Howl({
src: openingSfx,
@@ -20,31 +15,15 @@ const openingChestSfx = new Howl({
const ArtworksPage = () => {
const { id: viewArtId } = useParams();
const navigate = useNavigate();
+ const location = useLocation();
- const { data, isLoading, isFetchingNextPage, hasNextPage, fetchNextPage } =
- useInfiniteQuery({
- queryKey: ["artworks"],
- queryFn: ({ pageParam = 1 }) => {
- return pb
- .collection("artworks")
- .getList(pageParam, 12, { sort: "-created" });
- },
- getNextPageParam: (lastPage) =>
- lastPage.page < lastPage.totalPages ? lastPage.page + 1 : undefined,
- });
- useBottomScrollListener(
- () => {
- if (!isFetchingNextPage) {
- fetchNextPage();
- }
- },
- { offset: 100 }
- );
-
- const items = useMemo(
- () => data?.pages.flatMap((i) => i.items) || [],
- [data]
- );
+ const goBack = useCallback(() => {
+ if (location.key !== "default") {
+ navigate(-1);
+ } else {
+ navigate("/treasures");
+ }
+ }, [location, navigate]);
return (
@@ -66,52 +45,9 @@ const ArtworksPage = () => {
-
- {items.map((item) => (
-
-
-
-
- ))}
+
- {isLoading || isFetchingNextPage
- ? [...Array(12)].map((_, idx) => (
-
- ))
- : null}
-
-
- {hasNextPage && !isFetchingNextPage ? (
-
-
-
- ) : null}
-
- navigate("/treasures")}
- />
+
);
};
diff --git a/src/pages/artworks/viewSheet.tsx b/src/pages/artworks/viewSheet.tsx
index 77cfef6..92e8945 100644
--- a/src/pages/artworks/viewSheet.tsx
+++ b/src/pages/artworks/viewSheet.tsx
@@ -5,6 +5,8 @@ import loadingIllust from "@/assets/images/l9fsdoa2j7vb1.gif";
import Badge from "@/components/ui/Badge";
import Button from "@/components/ui/Button";
import { ChevronLeft } from "lucide-react";
+import LazyImage from "@/components/ui/LazyImage";
+import { useEffect, useState } from "react";
type Props = {
id?: string | null;
@@ -12,13 +14,20 @@ type Props = {
onClose: () => void;
};
-const ViewSheet = ({ id, isOpen, onClose }: Props) => {
+const ViewSheet = ({ id: viewId, isOpen, onClose }: Props) => {
+ const [id, setId] = useState(viewId);
const { data, isLoading, isError } = useQuery({
queryKey: ["artwork", id],
queryFn: () => pb.collection("artworks").getOne(id || ""),
enabled: !!id,
});
+ useEffect(() => {
+ if (viewId) {
+ setId(viewId);
+ }
+ }, [viewId, setId]);
+
return (
{
-