Skip to content

Commit

Permalink
feat(con): pagination for the 'Find a mentor' page (#968)
Browse files Browse the repository at this point in the history
* Fix padding for the nav bar

* Add pagination for the 'Find A Mentor' page

* Refactor pagination logic into a helper function

* Refactor
  • Loading branch information
katamatata authored Sep 16, 2024
1 parent 6cc7930 commit 5ff4538
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 47 deletions.
2 changes: 1 addition & 1 deletion apps/redi-connect/src/components/organisms/Navbar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
@import '_variables.scss';

.navbar {
padding: 1rem 1.25rem;
padding: 1rem 1.25rem !important;

&__wrapper {
display: flex;
Expand Down
95 changes: 61 additions & 34 deletions apps/redi-connect/src/pages/app/find-a-mentor/FindAMentor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
FilterDropdown,
Heading,
Icon,
Pagination,
SearchField,
} from '@talent-connect/shared-atomic-design-components'
import {
Expand All @@ -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'
Expand Down Expand Up @@ -70,6 +72,9 @@ const FilterTag = ({ id, label, onClickHandler }: FilterTagProps) => (
</Tag>
)

const MENTOR_CARDS_PER_PAGE = 12
const PAGINATION_SCROLL_POSITION = 380

const FindAMentor = () => {
const queryClient = useQueryClient()
const loopbackUserId = getAccessTokenFromLocalStorage().userId
Expand All @@ -82,6 +87,7 @@ const FindAMentor = () => {
const history = useHistory()
const profile = myProfileQuery.data?.conProfile

const [currentPageNumber, setCurrentPageNumber] = useState(1)
const [showFavorites, setShowFavorites] = useState<boolean>(false)
const [query, setQuery] = useQueryParams({
name: withDefault(StringParam, undefined),
Expand Down Expand Up @@ -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 {
Expand All @@ -143,6 +157,7 @@ const FindAMentor = () => {
...latestQuery,
onlyFavorites: showFavorites ? undefined : true,
}))
resetPaginationPageNumber()
}

const clearFilters = () => {
Expand All @@ -152,6 +167,7 @@ const FindAMentor = () => {
languages: [],
locations: [],
}))
resetPaginationPageNumber()
}

const isMalmoLocation = profile?.rediLocation === RediLocation.Malmo
Expand Down Expand Up @@ -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 (
<LoggedIn>
Expand Down Expand Up @@ -307,28 +332,30 @@ const FindAMentor = () => {
</div>

<Columns>
{mentors?.map((mentor) => {
const isFavorite = currentFavorites.includes(mentor.id)

if (!isFavorite && showFavorites) return

return (
<Columns.Column
mobile={{ size: 12 }}
tablet={{ size: 6 }}
desktop={{ size: 4 }}
key={mentor.id}
>
<MentorProfileCard
mentorProfile={mentor}
linkTo={`/app/find-a-mentor/profile/${mentor.id}`}
toggleFavorite={() => toggleFavorite(mentor.id)}
isFavorite={isFavorite}
/>
</Columns.Column>
)
})}
{currentItems.map((mentor) => (
<Columns.Column
mobile={{ size: 12 }}
tablet={{ size: 6 }}
desktop={{ size: 4 }}
key={mentor.id}
>
<MentorProfileCard
mentorProfile={mentor}
linkTo={`/app/find-a-mentor/profile/${mentor.id}`}
toggleFavorite={() => toggleFavorite(mentor.id)}
isFavorite={isMentorFavorite(mentor.id)}
/>
</Columns.Column>
))}
</Columns>
{totalItems > MENTOR_CARDS_PER_PAGE && (
<Pagination
totalPagesNumber={totalPagesNumber}
currentPageNumber={currentPageNumber}
setCurrentPageNumber={setCurrentPageNumber}
scrollPosition={PAGINATION_SCROLL_POSITION}
/>
)}

{mentors?.length === 0 && !isLoading && (
<Content>
Expand Down
19 changes: 7 additions & 12 deletions apps/redi-talent-pool/src/pages/app/browse/BrowseCompany.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 =
Expand Down Expand Up @@ -405,7 +400,7 @@ export function BrowseCompany() {
)}
</div>
<Columns>
{currentItems?.map((profile) => (
{currentItems.map((profile) => (
<Columns.Column
key={profile.id}
mobile={{ size: 12 }}
Expand Down
1 change: 1 addition & 0 deletions libs/shared-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ export * from './lib/crop-image'
export * from './lib/decode-jwt'
export * from './lib/delete-undefined-properties'
export * from './lib/init-sentry'
export * from './lib/pagination-helper'
export * from './lib/tailwind-classnames-util'
export * from './lib/to-pascal-case'
28 changes: 28 additions & 0 deletions libs/shared-utils/src/lib/pagination-helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
interface PaginateItemsParameters<T> {
items: Array<T>
currentPageNumber: number
itemsPerPage: number
}

interface PaginateItemsResult<T> {
currentItems: Array<T>
totalItems: number
totalPagesNumber: number
}

export const paginateItems = <T>({
items,
currentPageNumber,
itemsPerPage,
}: PaginateItemsParameters<T>): PaginateItemsResult<T> => {
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 }
}

0 comments on commit 5ff4538

Please sign in to comment.