From cf29b09eff8b351c02853aa7530879f4c17fa85c Mon Sep 17 00:00:00 2001 From: MohamedHamdanA Date: Sun, 23 Feb 2025 11:37:14 +0530 Subject: [PATCH] feat: add server-side pagination for environments (fixes #707) --- .../[project]/@environment/page.tsx | 92 ++++++++++++------- 1 file changed, 60 insertions(+), 32 deletions(-) diff --git a/apps/platform/src/app/(main)/(project)/[workspace]/[project]/@environment/page.tsx b/apps/platform/src/app/(main)/(project)/[workspace]/[project]/@environment/page.tsx index a4c139bdd..08dc888e3 100644 --- a/apps/platform/src/app/(main)/(project)/[workspace]/[project]/@environment/page.tsx +++ b/apps/platform/src/app/(main)/(project)/[workspace]/[project]/@environment/page.tsx @@ -1,6 +1,5 @@ 'use client' - -import { useEffect } from 'react' +import { useEffect, useState } from 'react' import { useAtom, useAtomValue, useSetAtom } from 'jotai' import { EnvironmentSVG } from '@public/svg/dashboard' import { @@ -22,33 +21,61 @@ function EnvironmentPage(): React.JSX.Element { const setIsCreateEnvironmentOpen = useSetAtom(createEnvironmentOpenAtom) const isDeleteEnvironmentOpen = useAtomValue(deleteEnvironmentOpenAtom) const isEditEnvironmentOpen = useAtomValue(editEnvironmentOpenAtom) - const [environments, setEnvironments] = useAtom(environmentsOfProjectAtom) const selectedProject = useAtomValue(selectedProjectAtom) const selectedEnvironment = useAtomValue(selectedEnvironmentAtom) + const [environments, setEnvironments] = useAtom(environmentsOfProjectAtom) - const getAllEnvironmentsOfProject = useHttp(() => - ControllerInstance.getInstance().environmentController.getAllEnvironmentsOfProject( - { - projectSlug: selectedProject!.slug - } - ) + // Pagination state: page number, loading, and whether more data is available + const [page, setPage] = useState(0) + const [hasMore, setHasMore] = useState(true) + const [loading, setLoading] = useState(false) + const limit = 10 // default number of items per request + + // Prepare the API call using the useHttp hook with pagination parameters + const getEnvironments = useHttp(() => + ControllerInstance.getInstance().environmentController.getEnvironmentsOfProject({ + projectSlug: selectedProject!.slug, + page, + limit, + sort: 'name', + order: 'asc', + search: '' + }) ) + // Fetch environments when the component mounts or when the page changes useEffect(() => { - selectedProject && - getAllEnvironmentsOfProject().then(({ data, success }) => { - if (success && data) { - setEnvironments(data.items) - } - }) - }, [getAllEnvironmentsOfProject, selectedProject, setEnvironments]) + if (selectedProject) { + setLoading(true) + getEnvironments() + .then(({ data, success }) => { + if (success && data) { + // On first page, replace; on subsequent pages, append new items + setEnvironments(prev => + page === 0 ? data.items : [...prev, ...data.items] + ) + // If the returned items are fewer than the limit, there's no more data + if (data.items.length < limit) { + setHasMore(false) + } + } + }) + .finally(() => { + setLoading(false) + }) + } + }, [selectedProject, page, getEnvironments, setEnvironments]) + + const handleLoadMore = () => { + if (hasMore && !loading) { + setPage(prevPage => prevPage + 1) + } + } return ( -
- {/* Showing this when there are no environments present */} - {environments.length === 0 ? ( +
+ {environments.length === 0 && !loading ? ( + // Display when no environments are present
@@ -69,23 +96,24 @@ function EnvironmentPage(): React.JSX.Element {
) : ( - // Showing this when environments are present + // Display environment cards along with the "Load More" button if more data exists
- {environments.map((environment) => ( + {environments.map(environment => ( ))} - {/* Delete environment alert dialog */} - {isDeleteEnvironmentOpen && selectedEnvironment ? ( - - ) : null} + {hasMore ?
+ +
: null} - {/* Edit environment dialog */} - {isEditEnvironmentOpen && selectedEnvironment ? ( - - ) : null} + {isDeleteEnvironmentOpen && selectedEnvironment ? : null} + {isEditEnvironmentOpen && selectedEnvironment ? : null}
)}