From d5c7a44d782263d794977bb676f393e4397e9dc4 Mon Sep 17 00:00:00 2001 From: Lim Zi Yang Date: Sat, 17 Feb 2024 14:34:03 +0800 Subject: [PATCH 1/3] feat: implement basic pagination --- .../service-catalog/_hooks/use-pagination.ts | 56 ++++++++++++++++ .../service-catalog/_views/services-view.tsx | 66 +++++++++++++++---- 2 files changed, 110 insertions(+), 12 deletions(-) create mode 100644 frontend/src/app/(authenticated)/service-catalog/_hooks/use-pagination.ts diff --git a/frontend/src/app/(authenticated)/service-catalog/_hooks/use-pagination.ts b/frontend/src/app/(authenticated)/service-catalog/_hooks/use-pagination.ts new file mode 100644 index 00000000..177aed52 --- /dev/null +++ b/frontend/src/app/(authenticated)/service-catalog/_hooks/use-pagination.ts @@ -0,0 +1,56 @@ +import { Pipeline } from "@/types/pipeline" +import { useState } from "react" + +interface UsePaginationOptions { + itemsPerPage?: number + services?: Pipeline[] | void +} + +const usePagination = ({ + itemsPerPage = 12, + services, +}: UsePaginationOptions) => { + const [page, setPage] = useState(1) + const [servicesAtPage, setServicesAtPage] = useState( + services ? services.slice(0, itemsPerPage) : [] + ) + const noOfPages = services ? Math.ceil(services.length / itemsPerPage) : 0 + + const handleSetServicesAtPage = (pageNo: number) => { + const startIndex = (pageNo - 1) * itemsPerPage + const endIndex = pageNo * itemsPerPage + setServicesAtPage(services ? services.slice(startIndex, endIndex) : []) + } + + const handleClickNextPage = () => { + if (page < noOfPages) { + handleSetServicesAtPage(page + 1) + setPage(page + 1) + } + } + + const handleClickPrevPage = () => { + if (page > 1) { + handleSetServicesAtPage(page - 1) + setPage(page - 1) + } + } + + const handleClickPageNo = (pageNo: number) => { + handleSetServicesAtPage(pageNo) + setPage(pageNo) + } + + return { + page, + noOfPages, + handleClickNextPage, + isNextDisabled: page === noOfPages, + handleClickPrevPage, + isPrevDisabled: page === 1, + handleClickPageNo, + servicesAtPage, + } +} + +export default usePagination diff --git a/frontend/src/app/(authenticated)/service-catalog/_views/services-view.tsx b/frontend/src/app/(authenticated)/service-catalog/_views/services-view.tsx index e150596a..75a72020 100644 --- a/frontend/src/app/(authenticated)/service-catalog/_views/services-view.tsx +++ b/frontend/src/app/(authenticated)/service-catalog/_views/services-view.tsx @@ -10,12 +10,48 @@ import { PaginationPrevious, } from "@/components/ui/pagination" import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime" +import usePagination from "../_hooks/use-pagination" interface ServicesViewProps { services: Pipeline[] | void router: AppRouterInstance } +const createPaginationItems = ( + currentPage: number, + noOfPages: number, + handleClickPageNo: (pageNo: number) => void +) => { + const paginationItems = [] + for (let i = 1; i <= noOfPages; i++) { + paginationItems.push( + + + + ) + } + return paginationItems +} + export default function ServicesView({ services, router }: ServicesViewProps) { + const { + page, + noOfPages, + handleClickNextPage, + isNextDisabled, + handleClickPrevPage, + isPrevDisabled, + handleClickPageNo, + servicesAtPage, + } = usePagination({ itemsPerPage: 4, services }) + return services && services.length === 0 ? (

No services available

@@ -23,7 +59,7 @@ export default function ServicesView({ services, router }: ServicesViewProps) { ) : ( <>
- {services?.map((service) => ( + {servicesAtPage?.map((service) => (
@@ -48,19 +84,25 @@ export default function ServicesView({ services, router }: ServicesViewProps) { - - - - 1 - - - 2 - - - 3 + + {createPaginationItems(page, noOfPages, handleClickPageNo)} - + From d6fb114ba82ca71854101392803beef8e9501bfa Mon Sep 17 00:00:00 2001 From: Lim Zi Yang Date: Sat, 17 Feb 2024 15:26:45 +0800 Subject: [PATCH 2/3] feat: add items per page option --- .../service-catalog/_hooks/use-pagination.ts | 48 +++++++++++++++---- .../service-catalog/_views/services-view.tsx | 25 ++++++++++ 2 files changed, 63 insertions(+), 10 deletions(-) diff --git a/frontend/src/app/(authenticated)/service-catalog/_hooks/use-pagination.ts b/frontend/src/app/(authenticated)/service-catalog/_hooks/use-pagination.ts index 177aed52..a703a9ff 100644 --- a/frontend/src/app/(authenticated)/service-catalog/_hooks/use-pagination.ts +++ b/frontend/src/app/(authenticated)/service-catalog/_hooks/use-pagination.ts @@ -1,26 +1,49 @@ import { Pipeline } from "@/types/pipeline" -import { useState } from "react" +import { useCallback, useEffect, useState } from "react" interface UsePaginationOptions { itemsPerPage?: number services?: Pipeline[] | void } -const usePagination = ({ - itemsPerPage = 12, - services, -}: UsePaginationOptions) => { +type ItemsPerRowType = "5" | "10" | "15" | "20" | "25" + +const ITEMS_PER_PAGE = { + "5": 5, + "10": 10, + "15": 15, + "20": 20, + "25": 25, +} + +const usePagination = ({ services }: UsePaginationOptions) => { const [page, setPage] = useState(1) + const [itemsPerPage, setItemsPerPage] = useState(ITEMS_PER_PAGE["10"]) const [servicesAtPage, setServicesAtPage] = useState( services ? services.slice(0, itemsPerPage) : [] ) const noOfPages = services ? Math.ceil(services.length / itemsPerPage) : 0 - const handleSetServicesAtPage = (pageNo: number) => { - const startIndex = (pageNo - 1) * itemsPerPage - const endIndex = pageNo * itemsPerPage - setServicesAtPage(services ? services.slice(startIndex, endIndex) : []) - } + const handleSetServicesAtPage = useCallback( + (pageNo: number, items: number = itemsPerPage) => { + const startIndex = (pageNo - 1) * items + const endIndex = pageNo * items + setServicesAtPage(services ? services.slice(startIndex, endIndex) : []) + }, + [services, itemsPerPage] + ) + + useEffect(() => { + const noOfPages = services ? Math.ceil(services.length / itemsPerPage) : 0 + if (page > noOfPages) { + // Set page to last page + const newPageNo = noOfPages + setPage(newPageNo) + handleSetServicesAtPage(newPageNo) + } else { + handleSetServicesAtPage(page) + } + }, [itemsPerPage, page, services, handleSetServicesAtPage]) const handleClickNextPage = () => { if (page < noOfPages) { @@ -41,6 +64,10 @@ const usePagination = ({ setPage(pageNo) } + const handleSetItemsPerPage = (itemsPerPageValue: ItemsPerRowType) => { + const itemsPerPage = ITEMS_PER_PAGE[itemsPerPageValue] + setItemsPerPage(itemsPerPage) + } return { page, noOfPages, @@ -49,6 +76,7 @@ const usePagination = ({ handleClickPrevPage, isPrevDisabled: page === 1, handleClickPageNo, + handleSetItemsPerPage, servicesAtPage, } } diff --git a/frontend/src/app/(authenticated)/service-catalog/_views/services-view.tsx b/frontend/src/app/(authenticated)/service-catalog/_views/services-view.tsx index 75a72020..31c81760 100644 --- a/frontend/src/app/(authenticated)/service-catalog/_views/services-view.tsx +++ b/frontend/src/app/(authenticated)/service-catalog/_views/services-view.tsx @@ -11,6 +11,15 @@ import { } from "@/components/ui/pagination" import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime" import usePagination from "../_hooks/use-pagination" +import { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectLabel, + SelectTrigger, + SelectValue, +} from "@/components/ui/select" interface ServicesViewProps { services: Pipeline[] | void router: AppRouterInstance @@ -49,6 +58,7 @@ export default function ServicesView({ services, router }: ServicesViewProps) { handleClickPrevPage, isPrevDisabled, handleClickPageNo, + handleSetItemsPerPage, servicesAtPage, } = usePagination({ itemsPerPage: 4, services }) @@ -104,6 +114,21 @@ export default function ServicesView({ services, router }: ServicesViewProps) { +
From 5c3f92c6ae1e2b4cc3cfbf4f8b9713b95360a8a4 Mon Sep 17 00:00:00 2001 From: Lim Zi Yang Date: Sat, 17 Feb 2024 15:30:25 +0800 Subject: [PATCH 3/3] refactor: remove noOfPages constant from useEffect --- .../(authenticated)/service-catalog/_hooks/use-pagination.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/src/app/(authenticated)/service-catalog/_hooks/use-pagination.ts b/frontend/src/app/(authenticated)/service-catalog/_hooks/use-pagination.ts index a703a9ff..6c33964f 100644 --- a/frontend/src/app/(authenticated)/service-catalog/_hooks/use-pagination.ts +++ b/frontend/src/app/(authenticated)/service-catalog/_hooks/use-pagination.ts @@ -34,7 +34,6 @@ const usePagination = ({ services }: UsePaginationOptions) => { ) useEffect(() => { - const noOfPages = services ? Math.ceil(services.length / itemsPerPage) : 0 if (page > noOfPages) { // Set page to last page const newPageNo = noOfPages @@ -43,7 +42,7 @@ const usePagination = ({ services }: UsePaginationOptions) => { } else { handleSetServicesAtPage(page) } - }, [itemsPerPage, page, services, handleSetServicesAtPage]) + }, [itemsPerPage, page, services, handleSetServicesAtPage, noOfPages]) const handleClickNextPage = () => { if (page < noOfPages) {