From c1c0506ec6bc04852e30149a40e7d00bc284abb1 Mon Sep 17 00:00:00 2001 From: Harsh Date: Sun, 11 Jan 2026 09:26:01 +0000 Subject: [PATCH 01/10] feat: improve ModuleCard layout with split mentor/mentee sections --- frontend/src/components/ModuleCard.tsx | 66 +++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/ModuleCard.tsx b/frontend/src/components/ModuleCard.tsx index 5c2b9faab1..d94c25825c 100644 --- a/frontend/src/components/ModuleCard.tsx +++ b/frontend/src/components/ModuleCard.tsx @@ -1,5 +1,5 @@ -import upperFirst from 'lodash/upperFirst' import Link from 'next/link' +import Image from 'next/image' import { usePathname } from 'next/navigation' import type React from 'react' import { useState } from 'react' @@ -36,7 +36,7 @@ const ModuleCard = ({ modules, accessLevel, admins }: ModuleCardProps) => { return (
-
+
{displayedModule.map((module) => { return })} @@ -67,21 +67,75 @@ const ModuleCard = ({ modules, accessLevel, admins }: ModuleCardProps) => { const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) => { const pathname = usePathname() + + const mentors = module.mentors || [] + const mentees = module.mentees || [] + return ( -
+
- + + +
+ {mentors.length > 0 && ( +
+ Mentors +
+ {mentors.slice(0, 4).map((contributor) => ( + contributor?.avatarUrl && ( + {contributor.name + ) + ))} + {mentors.length > 4 && ( + +{mentors.length - 4} + )} +
+
+ )} + {mentees.length > 0 && ( +
+ Mentees +
+ {mentees.slice(0, 4).map((contributor) => ( + contributor?.avatarUrl && ( + {contributor.name + ) + ))} + {mentees.length > 4 && ( + +{mentees.length - 4} + )} +
+
+ )} +
+ {isAdmin && module.labels && module.labels.length > 0 && (
@@ -105,7 +159,7 @@ export const getSimpleDuration = (start: string | number, end: string | number): const ms = endDate.getTime() - startDate.getTime() const days = Math.floor(ms / (1000 * 60 * 60 * 24)) - const weeks = Math.ceil(days / 7) - return `${weeks} week${weeks === 1 ? '' : 's'}` + const weeks = Math.ceil(days / 7) + return `${weeks} week${weeks !== 1 ? 's' : ''}` } From ba91a244747b47b173631895b2c4083ef9781630 Mon Sep 17 00:00:00 2001 From: Harsh Date: Sun, 11 Jan 2026 10:09:21 +0000 Subject: [PATCH 02/10] update: improve module card layout --- frontend/src/components/ModuleCard.tsx | 69 ++++++++++++++------------ 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/frontend/src/components/ModuleCard.tsx b/frontend/src/components/ModuleCard.tsx index d94c25825c..0a880e0d2e 100644 --- a/frontend/src/components/ModuleCard.tsx +++ b/frontend/src/components/ModuleCard.tsx @@ -71,10 +71,15 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) = const mentors = module.mentors || [] const mentees = module.mentees || [] + const mentorsWithAvatars = mentors.filter((m) => m?.avatarUrl) + const menteesWithAvatars = mentees.filter((m) => m?.avatarUrl) + + const hasContributors = mentorsWithAvatars.length > 0 || menteesWithAvatars.length > 0 + return (
@@ -87,13 +92,13 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) = value={getSimpleDuration(module.startedAt, module.endedAt)} /> -
- {mentors.length > 0 && ( -
- Mentors -
- {mentors.slice(0, 4).map((contributor) => ( - contributor?.avatarUrl && ( + {hasContributors && ( +
+ {mentorsWithAvatars.length > 0 && ( +
+ Mentors +
+ {mentorsWithAvatars.slice(0, 4).map((contributor) => ( {contributor.name - ) - ))} - {mentors.length > 4 && ( - +{mentors.length - 4} - )} + ))} + {mentorsWithAvatars.length > 4 && ( + + +{mentorsWithAvatars.length - 4} + + )} +
-
- )} - {mentees.length > 0 && ( -
- Mentees -
- {mentees.slice(0, 4).map((contributor) => ( - contributor?.avatarUrl && ( + )} + {menteesWithAvatars.length > 0 && ( +
0 ? 'border-l-1 border-gray-100 pl-4 dark:border-gray-700' : ''}`}> + Mentees +
+ {menteesWithAvatars.slice(0, 4).map((contributor) => ( {contributor.name - ) - ))} - {mentees.length > 4 && ( - +{mentees.length - 4} - )} + ))} + {menteesWithAvatars.length > 4 && ( + + +{menteesWithAvatars.length - 4} + + )} +
-
- )} -
+ )} +
+ )} {isAdmin && module.labels && module.labels.length > 0 && (
@@ -159,7 +166,7 @@ export const getSimpleDuration = (start: string | number, end: string | number): const ms = endDate.getTime() - startDate.getTime() const days = Math.floor(ms / (1000 * 60 * 60 * 24)) - const weeks = Math.ceil(days / 7) - return `${weeks} week${weeks !== 1 ? 's' : ''}` + + return `${weeks} week${weeks === 1 ? '' : 's'}` } From 8810feb4f4baa4716a3979687b073a90de6cdf26 Mon Sep 17 00:00:00 2001 From: Kate Date: Sun, 11 Jan 2026 18:18:55 -0800 Subject: [PATCH 03/10] Update code with make check. Capitalize level on the card --- frontend/src/components/ModuleCard.tsx | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/ModuleCard.tsx b/frontend/src/components/ModuleCard.tsx index 0a880e0d2e..6f8b89e283 100644 --- a/frontend/src/components/ModuleCard.tsx +++ b/frontend/src/components/ModuleCard.tsx @@ -1,5 +1,6 @@ -import Link from 'next/link' +import { capitalize } from 'lodash' import Image from 'next/image' +import Link from 'next/link' import { usePathname } from 'next/navigation' import type React from 'react' import { useState } from 'react' @@ -84,7 +85,7 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) = > - + {hasContributors && ( -
+
{mentorsWithAvatars.length > 0 && ( -
- Mentors +
+ + Mentors +
{mentorsWithAvatars.slice(0, 4).map((contributor) => ( ))} {mentorsWithAvatars.length > 4 && ( - + +{mentorsWithAvatars.length - 4} )} @@ -118,8 +121,12 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) =
)} {menteesWithAvatars.length > 0 && ( -
0 ? 'border-l-1 border-gray-100 pl-4 dark:border-gray-700' : ''}`}> - Mentees +
0 ? 'border-l-1 border-gray-100 pl-4 dark:border-gray-700' : ''}`} + > + + Mentees +
{menteesWithAvatars.slice(0, 4).map((contributor) => ( ))} {menteesWithAvatars.length > 4 && ( - + +{menteesWithAvatars.length - 4} )} From a62451defdc0b894d369bbdf113ff4dabf0d3793 Mon Sep 17 00:00:00 2001 From: Kate Date: Sun, 11 Jan 2026 18:26:14 -0800 Subject: [PATCH 04/10] Update avatar source for Mentors and Mentees --- frontend/src/components/ModuleCard.tsx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/ModuleCard.tsx b/frontend/src/components/ModuleCard.tsx index 6f8b89e283..61cef618ba 100644 --- a/frontend/src/components/ModuleCard.tsx +++ b/frontend/src/components/ModuleCard.tsx @@ -77,6 +77,17 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) = const hasContributors = mentorsWithAvatars.length > 0 || menteesWithAvatars.length > 0 + const getAvatarUrlWithSize = (avatarUrl: string): string => { + try { + const url = new URL(avatarUrl) + url.searchParams.set('s', '60') + return url.toString() + } catch { + const separator = avatarUrl.includes('?') ? '&' : '?' + return `${avatarUrl}${separator}s=60` + } + } + return (
@@ -134,7 +145,7 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) = alt={contributor.name || contributor.login} className="rounded-full border-1 border-gray-200 dark:border-gray-700" height={24} - src={`${contributor.avatarUrl}&s=60`} + src={getAvatarUrlWithSize(contributor.avatarUrl)} title={contributor.name || contributor.login} width={24} /> From db1deb7a17ced6ae21ab681720ed4a7920788208 Mon Sep 17 00:00:00 2001 From: Kate Date: Sun, 11 Jan 2026 18:42:48 -0800 Subject: [PATCH 05/10] Fix module key fallback --- frontend/src/components/ModuleCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/ModuleCard.tsx b/frontend/src/components/ModuleCard.tsx index 61cef618ba..89bf7a7c75 100644 --- a/frontend/src/components/ModuleCard.tsx +++ b/frontend/src/components/ModuleCard.tsx @@ -91,7 +91,7 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) = return (
From 87c96c468773d5288dc57e4ed6956e6e31b0977b Mon Sep 17 00:00:00 2001 From: Harsh Date: Tue, 13 Jan 2026 01:44:11 +0000 Subject: [PATCH 06/10] Add clickable links to mentor and mentee avatars in ModuleCard --- frontend/src/components/ModuleCard.tsx | 52 ++++++++++++++++++-------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/frontend/src/components/ModuleCard.tsx b/frontend/src/components/ModuleCard.tsx index 89bf7a7c75..f59898319d 100644 --- a/frontend/src/components/ModuleCard.tsx +++ b/frontend/src/components/ModuleCard.tsx @@ -76,6 +76,16 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) = const menteesWithAvatars = mentees.filter((m) => m?.avatarUrl) const hasContributors = mentorsWithAvatars.length > 0 || menteesWithAvatars.length > 0 + const isAdminView = pathname?.startsWith('/my/mentorship') + const programKey = pathname?.split('/programs/')[1]?.split('/')[0] || '' + const moduleKey = module.key || module.id + + const getMenteeUrl = (login: string) => { + if (isAdminView) { + return `/my/mentorship/programs/${programKey}/modules/${moduleKey}/mentees/${login}` + } + return `/members/${login}` + } const getAvatarUrlWithSize = (avatarUrl: string): string => { try { @@ -113,15 +123,20 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) =
{mentorsWithAvatars.slice(0, 4).map((contributor) => ( - {contributor.name + href={`/members/${contributor.login}`} + className="hover:opacity-80 transition-opacity" + > + {contributor.name + ))} {mentorsWithAvatars.length > 4 && ( @@ -140,15 +155,20 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) =
{menteesWithAvatars.slice(0, 4).map((contributor) => ( - {contributor.name + href={getMenteeUrl(contributor.login)} + className="hover:opacity-80 transition-opacity" + > + {contributor.name + ))} {menteesWithAvatars.length > 4 && ( From 845b5b4da861fe7a0905e75be7b40d015a27d3df Mon Sep 17 00:00:00 2001 From: Harsh Date: Tue, 13 Jan 2026 02:05:24 +0000 Subject: [PATCH 07/10] Add clickable links to mentor and mentee avatars in ModuleCard --- frontend/src/components/ModuleCard.tsx | 146 +++++++++++++------------ 1 file changed, 75 insertions(+), 71 deletions(-) diff --git a/frontend/src/components/ModuleCard.tsx b/frontend/src/components/ModuleCard.tsx index f59898319d..df82bfc914 100644 --- a/frontend/src/components/ModuleCard.tsx +++ b/frontend/src/components/ModuleCard.tsx @@ -114,79 +114,83 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) = value={getSimpleDuration(module.startedAt, module.endedAt)} /> - {hasContributors && ( -
- {mentorsWithAvatars.length > 0 && ( -
- - Mentors - -
- {mentorsWithAvatars.slice(0, 4).map((contributor) => ( - - {contributor.name - - ))} - {mentorsWithAvatars.length > 4 && ( - - +{mentorsWithAvatars.length - 4} - - )} + { + hasContributors && ( +
+ {mentorsWithAvatars.length > 0 && ( +
+ + Mentors + +
+ {mentorsWithAvatars.slice(0, 4).map((contributor) => ( + + {contributor.name + + ))} + {mentorsWithAvatars.length > 4 && ( + + +{mentorsWithAvatars.length - 4} + + )} +
-
- )} - {menteesWithAvatars.length > 0 && ( -
0 ? 'border-l-1 border-gray-100 pl-4 dark:border-gray-700' : ''}`} - > - - Mentees - -
- {menteesWithAvatars.slice(0, 4).map((contributor) => ( - - {contributor.name - - ))} - {menteesWithAvatars.length > 4 && ( - - +{menteesWithAvatars.length - 4} - - )} + )} + {menteesWithAvatars.length > 0 && ( +
0 ? 'border-l-1 border-gray-100 pl-4 dark:border-gray-700' : ''}`} + > + + Mentees + +
+ {menteesWithAvatars.slice(0, 4).map((contributor) => ( + + {contributor.name + + ))} + {menteesWithAvatars.length > 4 && ( + + +{menteesWithAvatars.length - 4} + + )} +
-
- )} -
- )} - - {isAdmin && module.labels && module.labels.length > 0 && ( -
- -
- )} -
+ )} +
+ ) + } + + { + isAdmin && module.labels && module.labels.length > 0 && ( +
+ +
+ ) + } +
) } From 3137ca5d356eacca6739a33aed17833087e54ee0 Mon Sep 17 00:00:00 2001 From: Harsh Date: Fri, 16 Jan 2026 05:43:04 +0000 Subject: [PATCH 08/10] fix: inline variables and add mentees to SingleModuleCard --- frontend/src/components/ModuleCard.tsx | 150 +++++++++---------- frontend/src/components/SingleModuleCard.tsx | 19 +++ 2 files changed, 91 insertions(+), 78 deletions(-) diff --git a/frontend/src/components/ModuleCard.tsx b/frontend/src/components/ModuleCard.tsx index df82bfc914..e765ba233a 100644 --- a/frontend/src/components/ModuleCard.tsx +++ b/frontend/src/components/ModuleCard.tsx @@ -75,13 +75,11 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) = const mentorsWithAvatars = mentors.filter((m) => m?.avatarUrl) const menteesWithAvatars = mentees.filter((m) => m?.avatarUrl) - const hasContributors = mentorsWithAvatars.length > 0 || menteesWithAvatars.length > 0 - const isAdminView = pathname?.startsWith('/my/mentorship') const programKey = pathname?.split('/programs/')[1]?.split('/')[0] || '' const moduleKey = module.key || module.id const getMenteeUrl = (login: string) => { - if (isAdminView) { + if (pathname?.startsWith('/my/mentorship')) { return `/my/mentorship/programs/${programKey}/modules/${moduleKey}/mentees/${login}` } return `/members/${login}` @@ -114,83 +112,79 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) = value={getSimpleDuration(module.startedAt, module.endedAt)} /> - { - hasContributors && ( -
- {mentorsWithAvatars.length > 0 && ( -
- - Mentors - -
- {mentorsWithAvatars.slice(0, 4).map((contributor) => ( - - {contributor.name - - ))} - {mentorsWithAvatars.length > 4 && ( - - +{mentorsWithAvatars.length - 4} - - )} -
+ {(mentorsWithAvatars.length > 0 || menteesWithAvatars.length > 0) && ( +
+ {mentorsWithAvatars.length > 0 && ( +
+ + Mentors + +
+ {mentorsWithAvatars.slice(0, 4).map((contributor) => ( + + {contributor.name + + ))} + {mentorsWithAvatars.length > 4 && ( + + +{mentorsWithAvatars.length - 4} + + )}
- )} - {menteesWithAvatars.length > 0 && ( -
0 ? 'border-l-1 border-gray-100 pl-4 dark:border-gray-700' : ''}`} - > - - Mentees - -
- {menteesWithAvatars.slice(0, 4).map((contributor) => ( - - {contributor.name - - ))} - {menteesWithAvatars.length > 4 && ( - - +{menteesWithAvatars.length - 4} - - )} -
+
+ )} + {menteesWithAvatars.length > 0 && ( +
0 ? 'border-l-1 border-gray-100 pl-4 dark:border-gray-700' : ''}`} + > + + Mentees + +
+ {menteesWithAvatars.slice(0, 4).map((contributor) => ( + + {contributor.name + + ))} + {menteesWithAvatars.length > 4 && ( + + +{menteesWithAvatars.length - 4} + + )}
- )} -
- ) - } - - { - isAdmin && module.labels && module.labels.length > 0 && ( -
- -
- ) - } -
+
+ )} +
+ )} + + {isAdmin && module.labels && module.labels.length > 0 && ( +
+ +
+ )} +
) } diff --git a/frontend/src/components/SingleModuleCard.tsx b/frontend/src/components/SingleModuleCard.tsx index 6a58f8b0ee..68c76f4358 100644 --- a/frontend/src/components/SingleModuleCard.tsx +++ b/frontend/src/components/SingleModuleCard.tsx @@ -11,6 +11,7 @@ import type { Module } from 'types/mentorship' import { formatDate } from 'utils/dateFormatter' 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' @@ -88,6 +89,24 @@ const SingleModuleCard: React.FC = ({ module, accessLevel label="Mentors" /> )} + {module.mentees?.length > 0 && + (pathname?.startsWith('/my/mentorship') ? ( + + ) : ( + + ))}
) } From b158ec3b4d6e67cd66fcb50ba1c252fd147cbc64 Mon Sep 17 00:00:00 2001 From: Kate Date: Sat, 17 Jan 2026 15:02:24 -0800 Subject: [PATCH 09/10] Update module card text color --- frontend/src/components/InfoItem.tsx | 2 +- frontend/src/components/ModuleCard.tsx | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/InfoItem.tsx b/frontend/src/components/InfoItem.tsx index aa268c2bd6..a38f8a2336 100644 --- a/frontend/src/components/InfoItem.tsx +++ b/frontend/src/components/InfoItem.tsx @@ -44,7 +44,7 @@ export const TextInfoItem = ({ value: string }) => { return ( -
+
{label}: {value}
diff --git a/frontend/src/components/ModuleCard.tsx b/frontend/src/components/ModuleCard.tsx index e765ba233a..9daebfc517 100644 --- a/frontend/src/components/ModuleCard.tsx +++ b/frontend/src/components/ModuleCard.tsx @@ -97,10 +97,10 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) = } return ( -
+
@@ -116,7 +116,7 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) =
{mentorsWithAvatars.length > 0 && (
- + Mentors
@@ -137,7 +137,7 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) = ))} {mentorsWithAvatars.length > 4 && ( - + +{mentorsWithAvatars.length - 4} )} @@ -148,7 +148,7 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) =
0 ? 'border-l-1 border-gray-100 pl-4 dark:border-gray-700' : ''}`} > - + Mentees
@@ -169,7 +169,7 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) = ))} {menteesWithAvatars.length > 4 && ( - + +{menteesWithAvatars.length - 4} )} From 9405c3b42d2fa736b5195e01a9db9f9e683ad56b Mon Sep 17 00:00:00 2001 From: Kate Date: Sat, 17 Jan 2026 15:14:31 -0800 Subject: [PATCH 10/10] Remove labels and update font-bold --- frontend/src/components/ModuleCard.tsx | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/frontend/src/components/ModuleCard.tsx b/frontend/src/components/ModuleCard.tsx index 9daebfc517..7a11201fba 100644 --- a/frontend/src/components/ModuleCard.tsx +++ b/frontend/src/components/ModuleCard.tsx @@ -8,7 +8,6 @@ import { FaChevronDown, FaChevronUp, FaTurnUp, FaCalendar, FaHourglassHalf } fro import type { Module } from 'types/mentorship' import { formatDate } from 'utils/dateFormatter' import { TextInfoItem } from 'components/InfoItem' -import { LabelList } from 'components/LabelList' import SingleModuleCard from 'components/SingleModuleCard' import { TruncatedText } from 'components/TruncatedText' @@ -26,7 +25,6 @@ const ModuleCard = ({ modules, accessLevel, admins }: ModuleCardProps) => { } const displayedModule = showAllModule ? modules : modules.slice(0, 4) - const isAdmin = accessLevel === 'admin' const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' || e.key === ' ') { @@ -39,7 +37,7 @@ const ModuleCard = ({ modules, accessLevel, admins }: ModuleCardProps) => {
{displayedModule.map((module) => { - return + return })}
{modules.length > 4 && ( @@ -66,7 +64,7 @@ const ModuleCard = ({ modules, accessLevel, admins }: ModuleCardProps) => { ) } -const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) => { +const ModuleItem = ({ module }: { module: Module }) => { const pathname = usePathname() const mentors = module.mentors || [] @@ -116,7 +114,7 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) =
{mentorsWithAvatars.length > 0 && (
- + Mentors
@@ -148,7 +146,7 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) =
0 ? 'border-l-1 border-gray-100 pl-4 dark:border-gray-700' : ''}`} > - + Mentees
@@ -178,12 +176,6 @@ const ModuleItem = ({ module, isAdmin }: { module: Module; isAdmin: boolean }) = )}
)} - - {isAdmin && module.labels && module.labels.length > 0 && ( -
- -
- )}
) }