From 0fc49b6bca4509c67547b54a7bfc3a11c57065db Mon Sep 17 00:00:00 2001 From: Emma Fredriksen Date: Thu, 15 Oct 2026 20:09:27 +0200 Subject: [PATCH 1/2] feat: implement paging draft --- backend/src/index.ts | 28 ++++++++++-- frontend/src/components/Pagination.tsx | 42 +++++++++++++++++ frontend/src/components/PlaceHolderComp.tsx | 0 frontend/src/hooks/useArtworks.ts | 50 +++++++++++++++------ frontend/src/pages/HomePage.tsx | 30 +++++++++++-- 5 files changed, 129 insertions(+), 21 deletions(-) create mode 100644 frontend/src/components/Pagination.tsx delete mode 100644 frontend/src/components/PlaceHolderComp.tsx diff --git a/backend/src/index.ts b/backend/src/index.ts index 7b743d1..781d8db 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -15,9 +15,14 @@ const typeDefs = `#graphql image_url: String } + type ArtworkPage { + artworks: [Artwork!]! + totalCount: Int! + } + type Query { hello: String! - artworks: [Artwork!]! + artworks(limit: Int!, offset: Int!): ArtworkPage! } `; @@ -26,8 +31,25 @@ const resolvers = { Query: { hello: () => "Hello from Artex backend!", - artworks: async () => { - return await db.collection("met_artworks").find({}).toArray(); + artworks: async ( + _: unknown, + { limit, offset }: { limit: number; offset: number }, + ) => { + if (limit < 1 || limit > 100 || offset < 0) { + throw new Error("Invalid pagination parameters"); + } + const collection = db.collection("met_artworks"); + + const [artworks, totalCount] = await Promise.all([ + collection.find({}).sort({ id: 1 }).skip(offset).limit(limit).toArray(), + + collection.countDocuments({}), + ]); + + return { + artworks, + totalCount, + }; }, }, }; diff --git a/frontend/src/components/Pagination.tsx b/frontend/src/components/Pagination.tsx new file mode 100644 index 0000000..00c4237 --- /dev/null +++ b/frontend/src/components/Pagination.tsx @@ -0,0 +1,42 @@ +type PaginationProps = { + page: number; + totalPages: number; + onPageChange: (page: number) => void; +}; + +export default function Pagination({ + page, + totalPages, + onPageChange, +}: PaginationProps) { + if (totalPages <= 1) return null; + + return ( + + ); +} diff --git a/frontend/src/components/PlaceHolderComp.tsx b/frontend/src/components/PlaceHolderComp.tsx deleted file mode 100644 index e69de29..0000000 diff --git a/frontend/src/hooks/useArtworks.ts b/frontend/src/hooks/useArtworks.ts index 1826db4..430c333 100644 --- a/frontend/src/hooks/useArtworks.ts +++ b/frontend/src/hooks/useArtworks.ts @@ -1,32 +1,47 @@ import { useEffect, useState } from "react"; import type { Artwork } from "../types/Artwork"; -export function useArtworks() { +export function useArtworks(page: number, pageSize = 12) { const [artworks, setArtworks] = useState([]); + const [totalCount, setTotalCount] = useState(0); const [error, setError] = useState(""); const [loading, setLoading] = useState(true); useEffect(() => { + const controller = new AbortController(); + async function fetchArtworks() { + setLoading(true); + setError(""); + try { const response = await fetch("/graphql", { method: "POST", headers: { "Content-Type": "application/json", }, + signal: controller.signal, body: JSON.stringify({ query: ` - query { - artworks { - id - title - artist_display - image_url - } - } - `, + query GetArtworks($limit: Int!, $offset: Int!) { + artworks(limit: $limit, offset: $offset) { + totalCount + artworks { + id + title + artist_display + image_url + } + } + } + `, + variables: { + limit: pageSize, + offset: (page - 1) * pageSize, + }, }), }); + if (!response.ok) { throw new Error(`HTTP ${response.status}`); } @@ -37,16 +52,23 @@ export function useArtworks() { throw new Error(result.errors[0].message); } - setArtworks(result.data.artworks.slice(0, 12)); + setArtworks(result.data.artworks.artworks); + setTotalCount(result.data.artworks.totalCount); } catch (err) { + if (controller.signal.aborted) return; + setError(err instanceof Error ? err.message : "Unknown error"); } finally { - setLoading(false); + if (!controller.signal.aborted) { + setLoading(false); + } } } fetchArtworks(); - }, []); - return { artworks, loading, error }; + return () => controller.abort(); + }, [page, pageSize]); + + return { artworks, totalCount, loading, error }; } diff --git a/frontend/src/pages/HomePage.tsx b/frontend/src/pages/HomePage.tsx index 698d708..acb6b66 100644 --- a/frontend/src/pages/HomePage.tsx +++ b/frontend/src/pages/HomePage.tsx @@ -1,17 +1,39 @@ +import { useState } from "react"; import ArtworkGrid from "../components/ArtworkGrid"; import Hero from "../components/Hero"; +import Pagination from "../components/Pagination"; import { useArtworks } from "../hooks/useArtworks"; +const PAGE_SIZE = 12; + export default function HomePage() { - const { artworks, loading, error } = useArtworks(); + const [page, setPage] = useState(1); + + const { artworks, totalCount, loading, error } = useArtworks(page, PAGE_SIZE); - if (loading) return

Loading artworks...

; - if (error) return

Error: {error}

; + const totalPages = Math.ceil(totalCount / PAGE_SIZE); return (
- + +
+ {error &&

Error: {error}

} + + {loading &&

Loading artworks...

} + +
+ +
+ + {!error && ( + + )} +
); } From 2a83d8bf1e487d3e3cbae5d251972e6b637a5eee Mon Sep 17 00:00:00 2001 From: Emma Fredriksen Date: Thu, 15 Oct 2026 20:26:34 +0200 Subject: [PATCH 2/2] docs: update favicon and remove vite icons --- frontend/index.html | 4 ++-- frontend/public/favicon.png | Bin 0 -> 20836 bytes frontend/public/favicon.svg | 1 - frontend/public/icons.svg | 24 ------------------------ frontend/src/assets/react.svg | 1 - frontend/src/assets/vite.svg | 1 - 6 files changed, 2 insertions(+), 29 deletions(-) create mode 100644 frontend/public/favicon.png delete mode 100644 frontend/public/favicon.svg delete mode 100644 frontend/public/icons.svg delete mode 100644 frontend/src/assets/react.svg delete mode 100644 frontend/src/assets/vite.svg diff --git a/frontend/index.html b/frontend/index.html index 0fca6f0..241c301 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -2,9 +2,9 @@ - + - frontend + Artex
diff --git a/frontend/public/favicon.png b/frontend/public/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..28a265fb29a161489a3fd2b91b04fbdf9eca5d37 GIT binary patch literal 20836 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 F_z$v*#&ZAw literal 0 HcmV?d00001 diff --git a/frontend/public/favicon.svg b/frontend/public/favicon.svg deleted file mode 100644 index 6893eb1..0000000 --- a/frontend/public/favicon.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/public/icons.svg b/frontend/public/icons.svg deleted file mode 100644 index e952219..0000000 --- a/frontend/public/icons.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/src/assets/react.svg b/frontend/src/assets/react.svg deleted file mode 100644 index 6c87de9..0000000 --- a/frontend/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/src/assets/vite.svg b/frontend/src/assets/vite.svg deleted file mode 100644 index 5101b67..0000000 --- a/frontend/src/assets/vite.svg +++ /dev/null @@ -1 +0,0 @@ -Vite