From 5ff4538e8544c8ce49eb4d455cc6e72360ec3ec1 Mon Sep 17 00:00:00 2001 From: Kateryna Voronina <51786805+katamatata@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:35:57 +0200 Subject: [PATCH] feat(con): pagination for the 'Find a mentor' page (#968) * Fix padding for the nav bar * Add pagination for the 'Find A Mentor' page * Refactor pagination logic into a helper function * Refactor --- .../src/components/organisms/Navbar.scss | 2 +- .../pages/app/find-a-mentor/FindAMentor.tsx | 95 ++++++++++++------- .../src/pages/app/browse/BrowseCompany.tsx | 19 ++-- libs/shared-utils/src/index.ts | 1 + .../shared-utils/src/lib/pagination-helper.ts | 28 ++++++ 5 files changed, 98 insertions(+), 47 deletions(-) create mode 100644 libs/shared-utils/src/lib/pagination-helper.ts diff --git a/apps/redi-connect/src/components/organisms/Navbar.scss b/apps/redi-connect/src/components/organisms/Navbar.scss index db6989c11..a7535daa3 100644 --- a/apps/redi-connect/src/components/organisms/Navbar.scss +++ b/apps/redi-connect/src/components/organisms/Navbar.scss @@ -2,7 +2,7 @@ @import '_variables.scss'; .navbar { - padding: 1rem 1.25rem; + padding: 1rem 1.25rem !important; &__wrapper { display: flex; diff --git a/apps/redi-connect/src/pages/app/find-a-mentor/FindAMentor.tsx b/apps/redi-connect/src/pages/app/find-a-mentor/FindAMentor.tsx index b254bf94e..e9a98c5a8 100644 --- a/apps/redi-connect/src/pages/app/find-a-mentor/FindAMentor.tsx +++ b/apps/redi-connect/src/pages/app/find-a-mentor/FindAMentor.tsx @@ -14,6 +14,7 @@ import { FilterDropdown, Heading, Icon, + Pagination, SearchField, } from '@talent-connect/shared-atomic-design-components' import { @@ -34,6 +35,7 @@ import { withDefault, } from 'use-query-params' +import { paginateItems } from '@talent-connect/shared-utils' import { MentorProfileCard } from '../../../components/organisms/MentorProfileCard' import { LoggedIn } from '../../../components/templates' import { useLoading } from '../../../hooks/WithLoading' @@ -70,6 +72,9 @@ const FilterTag = ({ id, label, onClickHandler }: FilterTagProps) => ( ) +const MENTOR_CARDS_PER_PAGE = 12 +const PAGINATION_SCROLL_POSITION = 380 + const FindAMentor = () => { const queryClient = useQueryClient() const loopbackUserId = getAccessTokenFromLocalStorage().userId @@ -82,6 +87,7 @@ const FindAMentor = () => { const history = useHistory() const profile = myProfileQuery.data?.conProfile + const [currentPageNumber, setCurrentPageNumber] = useState(1) const [showFavorites, setShowFavorites] = useState(false) const [query, setQuery] = useQueryParams({ name: withDefault(StringParam, undefined), @@ -112,23 +118,31 @@ const FindAMentor = () => { setQuery(hasQuery ? query : { ...query, topics: profile?.categories ?? [] }) }, [myProfileQuery.data]) + const resetPaginationPageNumber = () => setCurrentPageNumber(1) + const toggleFilters = (filtersArr, filterName, item) => { const newFilters = toggleValueInArray(filtersArr, item) setQuery((latestQuery) => ({ ...latestQuery, [filterName]: newFilters })) + resetPaginationPageNumber() } const setName = (value) => { setQuery((latestQuery) => ({ ...latestQuery, name: value || undefined })) + resetPaginationPageNumber() } - const currentFavorites = - favouriteMentorsQuery.data?.conMenteeFavoritedMentors.map( - (item) => item.mentorId - ) ?? [] + const isMentorFavorite = (mentorId) => { + return favouriteMentorsQuery.data?.conMenteeFavoritedMentors + ?.map((p) => p.mentorId) + ?.includes(mentorId) + } const toggleFavorite = async (mentorId) => { - const isMentorCurrentlyFavorited = currentFavorites.includes(mentorId) - if (isMentorCurrentlyFavorited) { + const isMentorFavorite = + favouriteMentorsQuery.data?.conMenteeFavoritedMentors + ?.map((p) => p.mentorId) + ?.includes(mentorId) + if (isMentorFavorite) { await unfavoriteMentorMutation.mutateAsync({ input: { mentorId } }) queryClient.invalidateQueries(useListFavoriteMentorsQuery.getKey()) } else { @@ -143,6 +157,7 @@ const FindAMentor = () => { ...latestQuery, onlyFavorites: showFavorites ? undefined : true, })) + resetPaginationPageNumber() } const clearFilters = () => { @@ -152,6 +167,7 @@ const FindAMentor = () => { languages: [], locations: [], })) + resetPaginationPageNumber() } const isMalmoLocation = profile?.rediLocation === RediLocation.Malmo @@ -193,13 +209,22 @@ const FindAMentor = () => { history.replace(`/app/mentorships/${matchId}`) } - // This logic filters away mentors that have have opted out of being - // receiving application form mentees from other locations - const mentors = mentorsQuery.data?.conProfilesAvailableMentors.filter( - (mentor) => - !mentor.optOutOfMenteesFromOtherRediLocation || - mentor.rediLocation === profile?.rediLocation - ) + const mentors = mentorsQuery.data?.conProfilesAvailableMentors + // This logic filters away mentors that have have opted out of being + // receiving application form mentees from other locations + .filter( + (mentor) => + !mentor.optOutOfMenteesFromOtherRediLocation || + mentor.rediLocation === profile?.rediLocation + ) + // Filter mentors based on the onlyFavorites flag before pagination + .filter((mentor) => (onlyFavorites ? isMentorFavorite(mentor.id) : true)) + + const { currentItems, totalItems, totalPagesNumber } = paginateItems({ + items: mentors ?? [], + currentPageNumber, + itemsPerPage: MENTOR_CARDS_PER_PAGE, + }) return ( @@ -307,28 +332,30 @@ const FindAMentor = () => { - {mentors?.map((mentor) => { - const isFavorite = currentFavorites.includes(mentor.id) - - if (!isFavorite && showFavorites) return - - return ( - - toggleFavorite(mentor.id)} - isFavorite={isFavorite} - /> - - ) - })} + {currentItems.map((mentor) => ( + + toggleFavorite(mentor.id)} + isFavorite={isMentorFavorite(mentor.id)} + /> + + ))} + {totalItems > MENTOR_CARDS_PER_PAGE && ( + + )} {mentors?.length === 0 && !isLoading && ( diff --git a/apps/redi-talent-pool/src/pages/app/browse/BrowseCompany.tsx b/apps/redi-talent-pool/src/pages/app/browse/BrowseCompany.tsx index b0d3c145e..e99dd9d84 100644 --- a/apps/redi-talent-pool/src/pages/app/browse/BrowseCompany.tsx +++ b/apps/redi-talent-pool/src/pages/app/browse/BrowseCompany.tsx @@ -14,6 +14,7 @@ import { SearchField, } from '@talent-connect/shared-atomic-design-components' import { LANGUAGES } from '@talent-connect/shared-config' +import { paginateItems } from '@talent-connect/shared-utils' import { desiredPositions, desiredPositionsIdToLabelMap, @@ -119,17 +120,11 @@ export function BrowseCompany() { return isJobseekerFavorite(profile.id) }) - const lastItemIndex = currentPageNumber * JOBSEEKER_CARDS_PER_PAGE - const firstItemIndex = lastItemIndex - JOBSEEKER_CARDS_PER_PAGE - const currentItems = filteredJobseekerProfiles?.slice( - firstItemIndex, - lastItemIndex - ) - - const totalItems = filteredJobseekerProfiles?.length - const totalPagesNumber = totalItems - ? Math.ceil(totalItems / JOBSEEKER_CARDS_PER_PAGE) - : undefined + const { currentItems, totalItems, totalPagesNumber } = paginateItems({ + items: filteredJobseekerProfiles ?? [], + currentPageNumber, + itemsPerPage: JOBSEEKER_CARDS_PER_PAGE, + }) const handleFavoriteJobseeker = async (tpJobseekerProfileId: string) => { const isFavorite = @@ -405,7 +400,7 @@ export function BrowseCompany() { )} - {currentItems?.map((profile) => ( + {currentItems.map((profile) => ( { + items: Array + currentPageNumber: number + itemsPerPage: number +} + +interface PaginateItemsResult { + currentItems: Array + totalItems: number + totalPagesNumber: number +} + +export const paginateItems = ({ + items, + currentPageNumber, + itemsPerPage, +}: PaginateItemsParameters): PaginateItemsResult => { + const lastItemIndex = currentPageNumber * itemsPerPage + const firstItemIndex = lastItemIndex - itemsPerPage + const currentItems = items?.slice(firstItemIndex, lastItemIndex) + + const totalItems = items?.length + const totalPagesNumber = totalItems + ? Math.ceil(totalItems / itemsPerPage) + : undefined + + return { currentItems, totalItems, totalPagesNumber } +}