diff --git a/dashboard/src/api/client/query.tsx b/dashboard/src/api/client/query.tsx index 5e700a1..2821965 100644 --- a/dashboard/src/api/client/query.tsx +++ b/dashboard/src/api/client/query.tsx @@ -55,7 +55,6 @@ const queryClient = new QueryClient({ }), }); -// TODO: definitely not the way to o it(children) but will figure out later const ReactQueryClientProvider: FC<{ children: ReactNode }> = ({ children, }) => { diff --git a/dashboard/src/api/mocks/useGetProjects.mock.ts b/dashboard/src/api/mocks/useGetProjects.mock.ts index 5fa8a68..595cf01 100644 --- a/dashboard/src/api/mocks/useGetProjects.mock.ts +++ b/dashboard/src/api/mocks/useGetProjects.mock.ts @@ -153,6 +153,252 @@ export const mockedProjectsResponse: GetProjectsResponse = { numberOfVersions: 3, createdAt: "2021-09-25T00:00:00.000Z", }, + { + id: 26, + name: "Project 26", + numberOfVersions: 1, + createdAt: "2021-09-26T00:00:00.000Z", + }, + { + id: 27, + name: "Project 27", + numberOfVersions: 2, + createdAt: "2021-09-27T00:00:00.000Z", + }, + { + id: 28, + name: "Project 28", + numberOfVersions: 2, + createdAt: "2021-09-28T00:00:00.000Z", + }, + { + id: 29, + name: "Project 29", + numberOfVersions: 3, + createdAt: "2021-09-29T00:00:00.000Z", + }, + { + id: 30, + name: "Project 30", + numberOfVersions: 1, + createdAt: "2021-09-30T00:00:00.000Z", + }, + { + id: 31, + name: "Project 31", + numberOfVersions: 2, + createdAt: "2021-10-01T00:00:00.000Z", + }, + { + id: 32, + name: "Project 32", + numberOfVersions: 2, + createdAt: "2021-10-02T00:00:00.000Z", + }, + { + id: 33, + name: "Project 33", + numberOfVersions: 3, + createdAt: "2021-10-03T00:00:00.000Z", + }, + { + id: 34, + name: "Project 34", + numberOfVersions: 1, + createdAt: "2021-10-04T00:00:00.000Z", + }, + { + id: 35, + name: "Project 35", + numberOfVersions: 2, + createdAt: "2021-10-05T00:00:00.000Z", + }, + { + id: 36, + name: "Project 36", + numberOfVersions: 2, + createdAt: "2021-10-06T00:00:00.000Z", + }, + { + id: 37, + name: "Project 37", + numberOfVersions: 3, + createdAt: "2021-10-07T00:00:00.000Z", + }, + { + id: 38, + name: "Project 38", + numberOfVersions: 1, + createdAt: "2021-10-08T00:00:00.000Z", + }, + { + id: 39, + name: "Project 39", + numberOfVersions: 2, + createdAt: "2021-10-09T00:00:00.000Z", + }, + { + id: 40, + name: "Project 40", + numberOfVersions: 2, + createdAt: "2021-10-10T00:00:00.000Z", + }, + { + id: 41, + name: "Project 41", + numberOfVersions: 3, + createdAt: "2021-10-11T00:00:00.000Z", + }, + { + id: 42, + name: "Project 42", + numberOfVersions: 1, + createdAt: "2021-10-12T00:00:00.000Z", + }, + { + id: 43, + name: "Project 43", + numberOfVersions: 2, + createdAt: "2021-10-13T00:00:00.000Z", + }, + { + id: 44, + name: "Project 44", + numberOfVersions: 2, + createdAt: "2021-10-14T00:00:00.000Z", + }, + { + id: 45, + name: "Project 45", + numberOfVersions: 3, + createdAt: "2021-10-15T00:00:00.000Z", + }, + { + id: 46, + name: "Project 46", + numberOfVersions: 1, + createdAt: "2021-10-16T00:00:00.000Z", + }, + { + id: 47, + name: "Project 47", + numberOfVersions: 2, + createdAt: "2021-10-17T00:00:00.000Z", + }, + { + id: 48, + name: "Project 48", + numberOfVersions: 2, + createdAt: "2021-10-18T00:00:00.000Z", + }, + { + id: 49, + name: "Project 49", + numberOfVersions: 3, + createdAt: "2021-10-19T00:00:00.000Z", + }, + { + id: 50, + name: "Project 50", + numberOfVersions: 1, + createdAt: "2021-10-20T00:00:00.000Z", + }, + { + id: 51, + name: "Project 51", + numberOfVersions: 2, + createdAt: "2021-10-21T00:00:00.000Z", + }, + { + id: 52, + name: "Project 52", + numberOfVersions: 2, + createdAt: "2021-10-22T00:00:00.000Z", + }, + { + id: 53, + name: "Project 53", + numberOfVersions: 3, + createdAt: "2021-10-23T00:00:00.000Z", + }, + { + id: 54, + name: "Project 54", + numberOfVersions: 1, + createdAt: "2021-10-24T00:00:00.000Z", + }, + { + id: 55, + name: "Project 55", + numberOfVersions: 2, + createdAt: "2021-10-25T00:00:00.000Z", + }, + { + id: 56, + name: "Project 56", + numberOfVersions: 2, + createdAt: "2021-10-26T00:00:00.000Z", + }, + { + id: 57, + name: "Project 57", + numberOfVersions: 3, + createdAt: "2021-10-27T00:00:00.000Z", + }, + { + id: 58, + name: "Project 58", + numberOfVersions: 1, + createdAt: "2021-10-28T00:00:00.000Z", + }, + { + id: 59, + name: "Project 59", + numberOfVersions: 2, + createdAt: "2021-10-29T00:00:00.000Z", + }, + { + id: 60, + name: "Project 60", + numberOfVersions: 2, + createdAt: "2021-10-30T00:00:00.000Z", + }, + { + id: 61, + name: "Project 61", + numberOfVersions: 3, + createdAt: "2021-10-31T00:00:00.000Z", + }, + { + id: 62, + name: "Project 62", + numberOfVersions: 1, + createdAt: "2021-11-01T00:00:00.000Z", + }, + { + id: 63, + name: "Project 63", + numberOfVersions: 2, + createdAt: "2021-11-02T00:00:00.000Z", + }, + { + id: 64, + name: "Project 64", + numberOfVersions: 2, + createdAt: "2021-11-03T00:00:00.000Z", + }, + { + id: 65, + name: "Project 65", + numberOfVersions: 3, + createdAt: "2021-11-04T00:00:00.000Z", + }, + { + id: 66, + name: "Project 66", + numberOfVersions: 1, + createdAt: "2021-11-05T00:00:00.000Z", + }, ], }; diff --git a/dashboard/src/components/TablePaginationSection.tsx b/dashboard/src/components/TablePaginationSection.tsx index c3ee890..22724f2 100644 --- a/dashboard/src/components/TablePaginationSection.tsx +++ b/dashboard/src/components/TablePaginationSection.tsx @@ -1,9 +1,43 @@ import KeyboardArrowLeftIcon from "@mui/icons-material/KeyboardArrowLeft"; import KeyboardArrowRightIcon from "@mui/icons-material/KeyboardArrowRight"; import { Box, Button, IconButton, iconButtonClasses } from "@mui/joy"; +import { FC } from "react"; + +interface TablePaginationSectionProps { + currentPage: number; + pageCount: number; + onPageChange: (page: number) => void; +} + +export const TablePaginationSection: FC = ({ + currentPage, + pageCount, + onPageChange, +}) => { + const generatePageNumbers = () => { + const pageNumbers = []; + if (pageCount <= 7) { + for (let i = 1; i <= pageCount; i++) { + pageNumbers.push(i); + } + } else { + if (currentPage <= 4) { + for (let i = 1; i <= 5; i++) { + pageNumbers.push(i); + } + pageNumbers.push("...", pageCount); + } else if (currentPage >= pageCount - 3) { + pageNumbers.push(1, "..."); + for (let i = pageCount - 4; i <= pageCount; i++) { + pageNumbers.push(i); + } + } else { + pageNumbers.push(1, "...", currentPage - 1, currentPage, currentPage + 1, "...", pageCount); + } + } + return pageNumbers; + }; -export const PaginationSection = () => { - //TODO: Implement pagination logic. Try to use cached data from query hook using query key return ( { variant="outlined" color="neutral" startDecorator={} + onClick={() => onPageChange(Math.max(1, currentPage - 1))} + disabled={currentPage === 1} > Previous - {["1", "2", "3", "…", "8", "9", "10"].map((page) => ( + {generatePageNumbers().map((page, index) => ( typeof page === 'number' && onPageChange(page)} + disabled={page === currentPage || typeof page !== 'number'} > {page} @@ -43,6 +81,8 @@ export const PaginationSection = () => { variant="outlined" color="neutral" endDecorator={} + onClick={() => onPageChange(Math.min(pageCount, currentPage + 1))} + disabled={currentPage === pageCount} > Next diff --git a/dashboard/src/views/Projects/Versions/index.tsx b/dashboard/src/views/Projects/Versions/index.tsx index a63bde5..e7c3beb 100644 --- a/dashboard/src/views/Projects/Versions/index.tsx +++ b/dashboard/src/views/Projects/Versions/index.tsx @@ -13,10 +13,11 @@ import { useEffect, useState } from "react"; import { useParams } from "react-router"; import { useGetProject } from "../../../api/hooks/useGetProject"; import { useGetVersions } from "../../../api/hooks/useGetVersions"; -import { PaginationSection } from "../../../components/TablePaginationSection"; -import { GetVersionsResponse } from "../../../interfaces/versions"; +import { TablePaginationSection } from "../../../components/TablePaginationSection"; +import { GetVersionsResponse, Version } from "../../../interfaces/versions"; import { VersionTableRow } from "./components"; +const ITEMS_PER_PAGE = 20; export const VersionsOverview = () => { const [searchBar, setSearchBar] = useState(""); @@ -24,6 +25,9 @@ export const VersionsOverview = () => { const { data: project } = useGetProject(projectId); const { data: versionsData } = useGetVersions(projectId); const [versionsList, setVersionsList] = useState(); + const [currentPage, setCurrentPage] = useState(1); + const [pageCount, setPageCount] = useState(1); + const [paginatedVersions, setPaginatedVersions] = useState(); useEffect(() => { if (!versionsData) return; @@ -40,6 +44,23 @@ export const VersionsOverview = () => { setVersionsList({ versions: filteredVersions }); }; + useEffect(() => { + if (!versionsList || !versionsList.versions + ) return; + + const pageCount = Math.ceil(versionsList.versions.length / ITEMS_PER_PAGE); + const paginatedVersions = versionsList.versions.slice( + (currentPage - 1) * ITEMS_PER_PAGE, + currentPage * ITEMS_PER_PAGE + ); + setPageCount(pageCount); + setPaginatedVersions(paginatedVersions); + }, [versionsList, currentPage]); + + const handlePageChange = (newPage: number) => { + setCurrentPage(newPage); + }; + return ( <> { - {versionsList && ( + {paginatedVersions && ( - {versionsList.versions.map((version) => ( + {paginatedVersions.map((version) => ( { - + ); }; diff --git a/dashboard/src/views/Projects/index.tsx b/dashboard/src/views/Projects/index.tsx index a575932..25ed7ce 100644 --- a/dashboard/src/views/Projects/index.tsx +++ b/dashboard/src/views/Projects/index.tsx @@ -10,14 +10,19 @@ import { } from "@mui/joy"; import { useEffect, useState } from "react"; import { useGetProjects } from "../../api/hooks/useGetProjects"; -import { PaginationSection } from "../../components/TablePaginationSection"; +import { TablePaginationSection } from "../../components/TablePaginationSection"; import { GetProjectsResponse, Project } from "../../interfaces/projects"; import { ProjectTableRow } from "./components"; +const ITEMS_PER_PAGE = 20; + export const ProjectsOverview = () => { const [searchBar, setSearchBar] = useState(""); const { data: projects } = useGetProjects(); const [projectsList, setProjectsList] = useState(); + const [currentPage, setCurrentPage] = useState(1); + const [pageCount, setPageCount] = useState(1); + const [paginatedVersions, setPaginatedVersions] = useState(); useEffect(() => { setProjectsList(projects); @@ -32,6 +37,22 @@ export const ProjectsOverview = () => { setProjectsList({ projects: filteredProjects }); }; + useEffect(() => { + if (!projectsList || !projectsList.projects) return; + + const pageCount = Math.ceil(projectsList.projects.length / ITEMS_PER_PAGE); + const paginatedVersions = projectsList.projects.slice( + (currentPage - 1) * ITEMS_PER_PAGE, + currentPage * ITEMS_PER_PAGE + ); + setPageCount(pageCount); + setPaginatedVersions(paginatedVersions); + }, [projectsList, currentPage]); + + const handlePageChange = (newPage: number) => { + setCurrentPage(newPage); + }; + return ( <> { - {projectsList && ( + {paginatedVersions && ( - {projectsList.projects.map((project) => ( + {paginatedVersions.map((project) => ( { - + ); };