diff --git a/frontend/__tests__/a11y/components/TopContributorsList.a11y.test.tsx b/frontend/__tests__/a11y/components/ContributorsList.a11y.test.tsx
similarity index 82%
rename from frontend/__tests__/a11y/components/TopContributorsList.a11y.test.tsx
rename to frontend/__tests__/a11y/components/ContributorsList.a11y.test.tsx
index 093b44acfa..4cccdc05e6 100644
--- a/frontend/__tests__/a11y/components/TopContributorsList.a11y.test.tsx
+++ b/frontend/__tests__/a11y/components/ContributorsList.a11y.test.tsx
@@ -2,7 +2,8 @@ import { render } from '@testing-library/react'
import { axe, toHaveNoViolations } from 'jest-axe'
import { ReactNode } from 'react'
import { Contributor } from 'types/contributor'
-import TopContributorsList from 'components/TopContributorsList'
+import { getMemberUrl } from 'utils/urlFormatter'
+import ContributorsList from 'components/ContributorsList'
expect.extend(toHaveNoViolations)
@@ -53,9 +54,11 @@ const mockContributors: Contributor[] = [
},
]
-describe('TopContributorsList Accessibility', () => {
+describe('ContributorsList Accessibility', () => {
it('should not have any accessibility violations', async () => {
- const { container } = render()
+ const { container } = render(
+
+ )
const results = await axe(container)
diff --git a/frontend/__tests__/unit/components/CardDetailsPage.test.tsx b/frontend/__tests__/unit/components/CardDetailsPage.test.tsx
index 4f44c9ec05..b779fa3623 100644
--- a/frontend/__tests__/unit/components/CardDetailsPage.test.tsx
+++ b/frontend/__tests__/unit/components/CardDetailsPage.test.tsx
@@ -359,25 +359,27 @@ jest.mock('components/ToggleableList', () => ({
),
}))
-jest.mock('components/TopContributorsList', () => ({
+jest.mock('components/ContributorsList', () => ({
__esModule: true,
default: ({
contributors,
maxInitialDisplay,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
icon,
+ label = 'Contributors',
// eslint-disable-next-line @typescript-eslint/no-unused-vars
- label,
+ getUrl,
...props
}: {
contributors: unknown[]
icon?: unknown
label?: string
maxInitialDisplay: number
+ getUrl: (login: string) => string
[key: string]: unknown
}) => (
-
- Top Contributors ({contributors.length} items, max display: {maxInitialDisplay})
+
+ {label} ({contributors.length} items, max display: {maxInitialDisplay})
),
}))
@@ -964,7 +966,7 @@ describe('CardDetailsPage', () => {
it('passes correct props to child components', () => {
render(
)
- expect(screen.getByTestId('top-contributors-list')).toHaveTextContent(
+ expect(screen.getByTestId('contributors-list')).toHaveTextContent(
'Top Contributors (2 items, max display: 12)'
)
})
@@ -1054,9 +1056,7 @@ describe('CardDetailsPage', () => {
)
expect(screen.getByTestId('health-metrics')).toHaveTextContent('Health Metrics (1 items)')
- expect(screen.getByTestId('top-contributors-list')).toHaveTextContent(
- 'Top Contributors (2 items'
- )
+ expect(screen.getByTestId('contributors-list')).toHaveTextContent('Top Contributors (2 items')
expect(screen.getByTestId('repositories-card')).toHaveTextContent('Repositories (2 items)')
})
@@ -1165,7 +1165,7 @@ describe('CardDetailsPage', () => {
render(
)
- expect(screen.getByTestId('top-contributors-list')).toHaveTextContent(
+ expect(screen.getByTestId('contributors-list')).toHaveTextContent(
'Top Contributors (50 items, max display: 12)'
)
})
@@ -1225,7 +1225,7 @@ describe('CardDetailsPage', () => {
render(
)
- expect(screen.getByTestId('top-contributors-list')).toHaveTextContent(
+ expect(screen.getByTestId('contributors-list')).toHaveTextContent(
'Top Contributors (1000 items, max display: 12)'
)
})
@@ -1375,7 +1375,7 @@ describe('CardDetailsPage', () => {
expect(screen.getByText('Project summary text')).toBeInTheDocument()
expect(screen.getByText('User summary content')).toBeInTheDocument()
expect(screen.getByTestId('health-metrics')).toBeInTheDocument()
- expect(screen.getByTestId('top-contributors-list')).toBeInTheDocument()
+ expect(screen.getByTestId('contributors-list')).toBeInTheDocument()
expect(screen.getByTestId('repositories-card')).toBeInTheDocument()
expect(screen.getByTestId('sponsor-card')).toBeInTheDocument()
})
diff --git a/frontend/__tests__/unit/components/TopContributorsList.test.tsx b/frontend/__tests__/unit/components/ContributorsList.test.tsx
similarity index 82%
rename from frontend/__tests__/unit/components/TopContributorsList.test.tsx
rename to frontend/__tests__/unit/components/ContributorsList.test.tsx
index 1ac8d2ec00..5e8a3185dc 100644
--- a/frontend/__tests__/unit/components/TopContributorsList.test.tsx
+++ b/frontend/__tests__/unit/components/ContributorsList.test.tsx
@@ -3,7 +3,8 @@ import React from 'react'
import { FaUsers } from 'react-icons/fa6'
import { render } from 'wrappers/testUtil'
import type { Contributor } from 'types/contributor'
-import TopContributorsList from 'components/TopContributorsList'
+import { getMemberUrl } from 'utils/urlFormatter'
+import ContributorsList from 'components/ContributorsList'
jest.mock('next/link', () => ({
__esModule: true,
@@ -181,9 +182,10 @@ const mockContributors: Contributor[] = [
},
]
-describe('TopContributorsList Component', () => {
+describe('ContributorsList Component', () => {
const defaultProps = {
contributors: mockContributors,
+ getUrl: getMemberUrl,
}
afterEach(() => {
@@ -191,8 +193,8 @@ describe('TopContributorsList Component', () => {
})
describe('Renders successfully with minimal required props', () => {
- it('renders with minimal props (only contributors)', () => {
- render(
)
+ it('renders with minimal props (only contributors and getUrl)', () => {
+ render(
)
expect(screen.getByTestId('secondary-card')).toBeInTheDocument()
expect(screen.getByTestId('anchor-title')).toBeInTheDocument()
@@ -201,12 +203,12 @@ describe('TopContributorsList Component', () => {
})
it('renders component without crashing', () => {
- const { container } = render(
)
+ const { container } = render(
)
expect(container).toBeInTheDocument()
})
it('renders without crashing with empty contributors array', () => {
- render(
)
+ render(
)
// Component returns early for empty array, so no secondary card should be rendered
expect(screen.queryByTestId('secondary-card')).not.toBeInTheDocument()
})
@@ -214,7 +216,7 @@ describe('TopContributorsList Component', () => {
describe('Conditional rendering logic', () => {
it('does not render anything when contributors array is empty', () => {
- render(
)
+ render(
)
// Component returns early for empty array, so no secondary card should be rendered
expect(screen.queryByTestId('secondary-card')).not.toBeInTheDocument()
})
@@ -222,7 +224,11 @@ describe('TopContributorsList Component', () => {
it('renders show more/less button only when contributors exceed maxInitialDisplay', () => {
// Test with few contributors (should not show button)
const { rerender } = render(
-
+
)
expect(screen.queryByRole('button')).not.toBeInTheDocument()
@@ -235,7 +241,13 @@ describe('TopContributorsList Component', () => {
name: `User ${index}`,
}))
- rerender(
)
+ rerender(
+
+ )
expect(screen.getByRole('button')).toBeInTheDocument()
expect(screen.getByText('Show more')).toBeInTheDocument()
})
@@ -249,7 +261,13 @@ describe('TopContributorsList Component', () => {
name: `User ${index}`,
}))
- render(
)
+ render(
+
+ )
// Should only show 5 initially
expect(screen.getAllByTestId('contributor-avatar')).toHaveLength(5)
@@ -274,7 +292,7 @@ describe('TopContributorsList Component', () => {
},
]
- render(
)
+ render(
)
expect(screen.getByText('Alex Developer')).toBeInTheDocument()
expect(screen.getByText('Contributor2')).toBeInTheDocument() // capitalize utility should be applied
@@ -284,15 +302,15 @@ describe('TopContributorsList Component', () => {
describe('Prop-based behavior', () => {
it('uses custom label when provided', () => {
const customLabel = 'Featured Contributors'
- render(
)
+ render(
)
expect(screen.getByText(customLabel)).toBeInTheDocument()
})
it('uses default label when not provided', () => {
- render(
)
+ render(
)
- expect(screen.getByText('Top Contributors')).toBeInTheDocument()
+ expect(screen.getByText('Contributors')).toBeInTheDocument()
})
it('respects custom maxInitialDisplay prop', () => {
@@ -304,19 +322,25 @@ describe('TopContributorsList Component', () => {
name: `User ${index}`,
}))
- render(
)
+ render(
+
+ )
expect(screen.getAllByTestId('contributor-avatar')).toHaveLength(3)
expect(screen.getByRole('button')).toBeInTheDocument()
})
it('displays icon when provided', () => {
- render(
)
+ render(
)
expect(screen.getByTestId('card-icon')).toBeInTheDocument()
})
it('does not display icon when not provided', () => {
- render(
)
+ render(
)
expect(screen.queryByTestId('card-icon')).not.toBeInTheDocument()
})
})
@@ -331,7 +355,13 @@ describe('TopContributorsList Component', () => {
name: `User ${index}`,
}))
- render(
)
+ render(
+
+ )
// Initially shows 5 contributors
expect(screen.getAllByTestId('contributor-avatar')).toHaveLength(5)
@@ -364,7 +394,13 @@ describe('TopContributorsList Component', () => {
name: `User ${index}`,
}))
- render(
)
+ render(
+
+ )
const toggleButton = screen.getByRole('button')
@@ -390,7 +426,13 @@ describe('TopContributorsList Component', () => {
name: `User ${index}`,
}))
- render(
)
+ render(
+
+ )
// Initial state - collapsed
expect(screen.getAllByTestId('contributor-avatar')).toHaveLength(5)
@@ -413,7 +455,9 @@ describe('TopContributorsList Component', () => {
name: `User ${index}`,
}))
- render(
)
+ render(
+
+ )
// Should show first 3 contributors
expect(screen.getByText('User 0')).toBeInTheDocument()
@@ -433,7 +477,7 @@ describe('TopContributorsList Component', () => {
name: `User ${index}`,
}))
- render(
)
+ render(
)
// Should show 12 by default (based on component default)
expect(screen.getAllByTestId('contributor-avatar')).toHaveLength(12)
@@ -451,7 +495,7 @@ describe('TopContributorsList Component', () => {
},
]
- render(
)
+ render(
)
expect(screen.getByText('Testuser')).toBeInTheDocument()
})
@@ -467,16 +511,16 @@ describe('TopContributorsList Component', () => {
},
]
- render(
)
+ render(
)
const avatar = screen.getByTestId('contributor-avatar')
- expect(avatar).toHaveAttribute('src', '&s=60') // Should append size parameter even with empty URL
+ expect(avatar).toHaveAttribute('src', '?s=60') // Should append size parameter even with empty URL
})
})
describe('Text and content rendering', () => {
it('renders contributor names correctly', () => {
- render(
)
+ render(
)
expect(screen.getByText('Alex Developer')).toBeInTheDocument()
expect(screen.getByText('Jane Developer')).toBeInTheDocument()
@@ -492,7 +536,13 @@ describe('TopContributorsList Component', () => {
name: `User ${index}`,
}))
- render(
)
+ render(
+
+ )
expect(screen.getByText('Show more')).toBeInTheDocument()
@@ -501,7 +551,7 @@ describe('TopContributorsList Component', () => {
})
it('renders title with proper structure', () => {
- render(
)
+ render(
)
expect(screen.getByTestId('anchor-title')).toBeInTheDocument()
expect(screen.getByText('Custom Title')).toBeInTheDocument()
@@ -527,14 +577,20 @@ describe('TopContributorsList Component', () => {
},
]
- render(
)
+ render(
)
// Should still render without crashing
expect(screen.getByTestId('secondary-card')).toBeInTheDocument()
})
it('handles zero maxInitialDisplay value', () => {
- render(
)
+ render(
+
+ )
// Should still show button since contributors length > 0
expect(screen.getByRole('button')).toBeInTheDocument()
@@ -542,14 +598,26 @@ describe('TopContributorsList Component', () => {
})
it('handles negative maxInitialDisplay value', () => {
- render(
)
+ render(
+
+ )
// slice with negative number should still work
expect(screen.getByTestId('secondary-card')).toBeInTheDocument()
})
it('handles very large maxInitialDisplay value', () => {
- render(
)
+ render(
+
+ )
// Should show all contributors and no button
expect(screen.getAllByTestId('contributor-avatar')).toHaveLength(3)
@@ -559,7 +627,7 @@ describe('TopContributorsList Component', () => {
describe('Accessibility roles and labels', () => {
it('renders proper image alt text and titles', () => {
- render(
)
+ render(
)
const avatars = screen.getAllByTestId('contributor-avatar')
expect(avatars[0]).toHaveAttribute('alt', "Alex Developer's avatar")
@@ -571,7 +639,7 @@ describe('TopContributorsList Component', () => {
})
it('renders proper link titles and hrefs', () => {
- render(
)
+ render(
)
const links = screen.getAllByTestId('contributor-link')
expect(links[0]).toHaveAttribute('href', '/members/developer1')
@@ -591,7 +659,13 @@ describe('TopContributorsList Component', () => {
name: `User ${index}`,
}))
- render(
)
+ render(
+
+ )
const button = screen.getByRole('button')
expect(button).toBeInTheDocument()
@@ -601,7 +675,7 @@ describe('TopContributorsList Component', () => {
describe('DOM structure / classNames / styles', () => {
it('renders correct CSS classes on components', () => {
- render(
)
+ render(
)
const contributorItems = screen
.getAllByTestId('contributor-avatar')
@@ -619,7 +693,7 @@ describe('TopContributorsList Component', () => {
})
it('renders proper grid structure', () => {
- const { container } = render(
)
+ const { container } = render(
)
const gridContainer = container.querySelector('.grid')
expect(gridContainer).toHaveClass(
@@ -631,7 +705,7 @@ describe('TopContributorsList Component', () => {
})
it('renders avatar with correct dimensions and styling', () => {
- render(
)
+ render(
)
const avatars = screen.getAllByTestId('contributor-avatar')
for (const avatar of avatars) {
@@ -642,7 +716,7 @@ describe('TopContributorsList Component', () => {
})
it('renders contributor links with proper styling', () => {
- render(
)
+ render(
)
const links = screen.getAllByTestId('contributor-link')
diff --git a/frontend/__tests__/unit/components/SingleModuleCard.test.tsx b/frontend/__tests__/unit/components/SingleModuleCard.test.tsx
index 91e1adc393..9eaba76be3 100644
--- a/frontend/__tests__/unit/components/SingleModuleCard.test.tsx
+++ b/frontend/__tests__/unit/components/SingleModuleCard.test.tsx
@@ -67,10 +67,17 @@ jest.mock('components/ModuleCard', () => ({
}),
}))
-jest.mock('components/TopContributorsList', () => ({
+jest.mock('components/ContributorsList', () => ({
__esModule: true,
- default: ({ contributors, label }: { contributors: unknown[]; label: string }) => (
-
+ default: ({
+ contributors,
+ label,
+ }: {
+ contributors: unknown[]
+ label: string
+ getUrl: (login: string) => string
+ }) => (
+
{label}: {contributors.length} contributors
@@ -155,7 +162,7 @@ describe('SingleModuleCard', () => {
it('renders mentors list when mentors exist', () => {
render()
- expect(screen.getByTestId('top-contributors-list')).toBeInTheDocument()
+ expect(screen.getByTestId('contributors-list')).toBeInTheDocument()
expect(screen.getByText('Mentors: 2 contributors')).toBeInTheDocument()
})
@@ -163,7 +170,7 @@ describe('SingleModuleCard', () => {
const moduleWithoutMentors = { ...mockModule, mentors: [] }
render()
- expect(screen.queryByTestId('top-contributors-list')).not.toBeInTheDocument()
+ expect(screen.queryByTestId('contributors-list')).not.toBeInTheDocument()
})
it('renders module link with correct href', () => {
@@ -224,7 +231,7 @@ describe('SingleModuleCard', () => {
render()
expect(screen.getByText('Test Module')).toBeInTheDocument()
- expect(screen.queryByTestId('top-contributors-list')).not.toBeInTheDocument()
+ expect(screen.queryByTestId('contributors-list')).not.toBeInTheDocument()
})
it('handles undefined admins array gracefully', () => {
diff --git a/frontend/src/app/about/page.tsx b/frontend/src/app/about/page.tsx
index 122c96b8e6..f447e70caa 100644
--- a/frontend/src/app/about/page.tsx
+++ b/frontend/src/app/about/page.tsx
@@ -24,13 +24,14 @@ import {
projectTimeline,
projectStory,
} from 'utils/aboutData'
+import { getMemberUrl } from 'utils/urlFormatter'
import AnchorTitle from 'components/AnchorTitle'
+import ContributorsList from 'components/ContributorsList'
import Leaders from 'components/Leaders'
import Markdown from 'components/MarkdownWrapper'
import SecondaryCard from 'components/SecondaryCard'
import ShowMoreButton from 'components/ShowMoreButton'
import AboutSkeleton from 'components/skeletons/AboutSkeleton'
-import TopContributorsList from 'components/TopContributorsList'
const leaders = {
arkid15r: 'CCSP, CISSP, CSSLP',
@@ -150,11 +151,12 @@ const About = () => {
{topContributors && (
-
)}
diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx
index 5b92c37f9d..944c13f435 100644
--- a/frontend/src/app/page.tsx
+++ b/frontend/src/app/page.tsx
@@ -27,9 +27,11 @@ import type { Chapter } from 'types/chapter'
import type { Event } from 'types/event'
import { formatDate, formatDateRange } from 'utils/dateFormatter'
+import { getMemberUrl } from 'utils/urlFormatter'
import AnchorTitle from 'components/AnchorTitle'
import CalendarButton from 'components/CalendarButton'
import ChapterMapWrapper from 'components/ChapterMapWrapper'
+import ContributorsList from 'components/ContributorsList'
import LeadersList from 'components/LeadersList'
import LoadingSpinner from 'components/LoadingSpinner'
import MovingLogos from 'components/LogoCarousel'
@@ -40,7 +42,6 @@ import RecentIssues from 'components/RecentIssues'
import RecentPullRequests from 'components/RecentPullRequests'
import RecentReleases from 'components/RecentReleases'
import SecondaryCard from 'components/SecondaryCard'
-import TopContributorsList from 'components/TopContributorsList'
import { TruncatedText } from 'components/TruncatedText'
export default function Home() {
@@ -320,10 +321,12 @@ export default function Home() {
}}
/>
-
diff --git a/frontend/src/components/CardDetailsPage.tsx b/frontend/src/components/CardDetailsPage.tsx
index ad9178d15a..c3bdabdba5 100644
--- a/frontend/src/components/CardDetailsPage.tsx
+++ b/frontend/src/components/CardDetailsPage.tsx
@@ -13,18 +13,19 @@ import type { ExtendedSession } from 'types/auth'
import type { DetailsCardProps } from 'types/card'
import { IS_PROJECT_HEALTH_ENABLED } from 'utils/env.client'
import { scrollToAnchor } from 'utils/scrollToAnchor'
+import { getMemberUrl, getMenteeUrl } from 'utils/urlFormatter'
import { getSocialIcon } from 'utils/urlIconMappings'
import AnchorTitle from 'components/AnchorTitle'
import ChapterMapWrapper from 'components/ChapterMapWrapper'
import ContributionHeatmap from 'components/ContributionHeatmap'
import ContributionStats from 'components/ContributionStats'
+import ContributorsList from 'components/ContributorsList'
import EntityActions from 'components/EntityActions'
import HealthMetrics from 'components/HealthMetrics'
import InfoBlock from 'components/InfoBlock'
import Leaders from 'components/Leaders'
import LeadersList from 'components/LeadersList'
import Markdown from 'components/MarkdownWrapper'
-import MenteeContributorsList from 'components/MenteeContributorsList'
import MetricsScoreCircle from 'components/MetricsScoreCircle'
import Milestones from 'components/Milestones'
import ModuleCard from 'components/ModuleCard'
@@ -36,7 +37,6 @@ import SecondaryCard from 'components/SecondaryCard'
import SponsorCard from 'components/SponsorCard'
import StatusBadge from 'components/StatusBadge'
import ToggleableList from 'components/ToggleableList'
-import TopContributorsList from 'components/TopContributorsList'
export type CardType =
| 'chapter'
@@ -305,36 +305,39 @@ const DetailsCard = ({
)}
{topContributors && (
-
)}
{admins && admins.length > 0 && type === 'program' && (
-
)}
{mentors && mentors.length > 0 && (
-
)}
{mentees && mentees.length > 0 && (
-
getMenteeUrl(programKey || '', entityKey || '', login)}
/>
)}
{showIssuesAndMilestones(type) && (
diff --git a/frontend/src/components/TopContributorsList.tsx b/frontend/src/components/ContributorsList.tsx
similarity index 85%
rename from frontend/src/components/TopContributorsList.tsx
rename to frontend/src/components/ContributorsList.tsx
index d3bc34ca7f..ac2d9fa56e 100644
--- a/frontend/src/components/TopContributorsList.tsx
+++ b/frontend/src/components/ContributorsList.tsx
@@ -4,22 +4,25 @@ import Link from 'next/link'
import { useState } from 'react'
import type { IconType } from 'react-icons'
import type { Contributor } from 'types/contributor'
-import { getMemberUrl } from 'utils/urlFormatter'
import AnchorTitle from 'components/AnchorTitle'
import SecondaryCard from 'components/SecondaryCard'
import ShowMoreButton from 'components/ShowMoreButton'
-const TopContributorsList = ({
- contributors,
- label = 'Top Contributors',
- maxInitialDisplay = 12,
- icon,
-}: {
+interface ContributorsListProps {
contributors: Contributor[]
label?: string
maxInitialDisplay?: number
icon?: IconType
-}) => {
+ getUrl: (login: string) => string
+}
+
+const ContributorsList = ({
+ contributors,
+ label = 'Contributors',
+ maxInitialDisplay = 12,
+ icon,
+ getUrl,
+}: ContributorsListProps) => {
const [showAllContributors, setShowAllContributors] = useState(false)
const toggleContributors = () => setShowAllContributors(!showAllContributors)
@@ -29,7 +32,7 @@ const TopContributorsList = ({
: contributors.slice(0, maxInitialDisplay)
if (contributors.length === 0) {
- return
+ return null
}
return (
@@ -52,13 +55,13 @@ const TopContributorsList = ({
alt={item?.name ? `${item.name}'s avatar` : 'Contributor avatar'}
className="rounded-full"
height={24}
- src={`${item?.avatarUrl}&s=60`}
+ src={`${item?.avatarUrl}${item?.avatarUrl?.includes('?') ? '&' : '?'}s=60`}
title={item?.name || item?.login}
width={24}
/>
{upperFirst(item.name) || upperFirst(item.login)}
@@ -72,4 +75,4 @@ const TopContributorsList = ({
)
}
-export default TopContributorsList
+export default ContributorsList
diff --git a/frontend/src/components/MenteeContributorsList.tsx b/frontend/src/components/MenteeContributorsList.tsx
deleted file mode 100644
index f9cdf00cc8..0000000000
--- a/frontend/src/components/MenteeContributorsList.tsx
+++ /dev/null
@@ -1,82 +0,0 @@
-import upperFirst from 'lodash/upperFirst'
-import Image from 'next/image'
-import Link from 'next/link'
-import { useState } from 'react'
-import type { IconType } from 'react-icons'
-import type { Contributor } from 'types/contributor'
-import AnchorTitle from 'components/AnchorTitle'
-import SecondaryCard from 'components/SecondaryCard'
-import ShowMoreButton from 'components/ShowMoreButton'
-
-interface MenteeContributorsListProps {
- contributors: Contributor[]
- label?: string
- maxInitialDisplay?: number
- icon?: IconType
- programKey: string
- moduleKey: string
-}
-
-const MenteeContributorsList = ({
- contributors,
- label = 'Mentees',
- maxInitialDisplay = 12,
- icon,
- programKey,
- moduleKey,
-}: MenteeContributorsListProps) => {
- const [showAllContributors, setShowAllContributors] = useState(false)
-
- const toggleContributors = () => setShowAllContributors(!showAllContributors)
-
- const displayContributors = showAllContributors
- ? contributors
- : contributors.slice(0, maxInitialDisplay)
-
- if (contributors.length === 0) {
- return null
- }
- const getMenteeUrl = (login: string) =>
- `/my/mentorship/programs/${programKey}/modules/${moduleKey}/mentees/${login}`
-
- return (
-
-
-
- }
- >
-
- {displayContributors.map((item) => (
-
-
-
-
- {upperFirst(item.name) || upperFirst(item.login)}
-
-
-
- ))}
-
- {contributors.length > maxInitialDisplay &&
}
-
- )
-}
-
-export default MenteeContributorsList
diff --git a/frontend/src/components/SingleModuleCard.tsx b/frontend/src/components/SingleModuleCard.tsx
index 68c76f4358..68e5f7ee8c 100644
--- a/frontend/src/components/SingleModuleCard.tsx
+++ b/frontend/src/components/SingleModuleCard.tsx
@@ -9,11 +9,11 @@ import { HiUserGroup } from 'react-icons/hi'
import { ExtendedSession } from 'types/auth'
import type { Module } from 'types/mentorship'
import { formatDate } from 'utils/dateFormatter'
+import { getMemberUrl, getMenteeUrl } from 'utils/urlFormatter'
+import ContributorsList from 'components/ContributorsList'
import EntityActions from 'components/EntityActions'
import Markdown from 'components/MarkdownWrapper'
-import MenteeContributorsList from 'components/MenteeContributorsList'
import { getSimpleDuration } from 'components/ModuleCard'
-import TopContributorsList from 'components/TopContributorsList'
interface SingleModuleCardProps {
module: Module
@@ -82,29 +82,30 @@ const SingleModuleCard: React.FC
= ({ module, accessLevel
{/* Mentors */}
{module.mentors?.length > 0 && (
-
)}
{module.mentees?.length > 0 &&
(pathname?.startsWith('/my/mentorship') ? (
- getMenteeUrl(programKey, module.key, login)}
/>
) : (
-
))}
diff --git a/frontend/src/utils/urlFormatter.ts b/frontend/src/utils/urlFormatter.ts
index e801487ae2..19218eb479 100644
--- a/frontend/src/utils/urlFormatter.ts
+++ b/frontend/src/utils/urlFormatter.ts
@@ -1,2 +1,4 @@
export const getMemberUrl = (login: string): string => `/members/${login}`
export const getProjectUrl = (projectKey: string): string => `/projects/${projectKey}`
+export const getMenteeUrl = (programKey: string, moduleKey: string, login: string): string =>
+ `/my/mentorship/programs/${programKey}/modules/${moduleKey}/mentees/${login}`