diff --git a/src/components/admin/members-content.tsx b/src/components/admin/members-content.tsx index 71f5e20..fd15957 100644 --- a/src/components/admin/members-content.tsx +++ b/src/components/admin/members-content.tsx @@ -426,7 +426,29 @@ export function MembersContent() {
- {user.role === 'MENTOR' ? ( + {user.role === 'APPLICANT' ? ( + (() => { + const info = (user as unknown as { applicantRoundInfo?: { roundName: string; state: string } | null }).applicantRoundInfo + if (!info) return - + const stateColor = info.state === 'REJECTED' ? 'destructive' as const + : info.state === 'WITHDRAWN' ? 'secondary' as const + : info.state === 'PASSED' ? 'success' as const + : 'default' as const + const stateLabel = info.state === 'IN_PROGRESS' ? 'Active' + : info.state === 'PENDING' ? 'Pending' + : info.state === 'COMPLETED' ? 'Completed' + : info.state === 'PASSED' ? 'Passed' + : info.state + return ( +
+ {info.roundName} + + {stateLabel} + +
+ ) + })() + ) : user.role === 'MENTOR' ? (

{(user as unknown as { _count: { mentorAssignments: number; assignments: number } })._count.mentorAssignments} mentored

) : (

{(user as unknown as { _count: { mentorAssignments: number; assignments: number } })._count.assignments} assigned

@@ -520,9 +542,33 @@ export function MembersContent() {
- Assignments + + {user.role === 'APPLICANT' ? 'Current Round' : 'Assignments'} + - {user.role === 'MENTOR' + {user.role === 'APPLICANT' ? ( + (() => { + const info = (user as unknown as { applicantRoundInfo?: { roundName: string; state: string } | null }).applicantRoundInfo + if (!info) return - + const stateColor = info.state === 'REJECTED' ? 'destructive' as const + : info.state === 'WITHDRAWN' ? 'secondary' as const + : info.state === 'PASSED' ? 'success' as const + : 'default' as const + const stateLabel = info.state === 'IN_PROGRESS' ? 'Active' + : info.state === 'PENDING' ? 'Pending' + : info.state === 'COMPLETED' ? 'Completed' + : info.state === 'PASSED' ? 'Passed' + : info.state + return ( + + {info.roundName} + + {stateLabel} + + + ) + })() + ) : user.role === 'MENTOR' ? `${(user as unknown as { _count: { mentorAssignments: number; assignments: number } })._count.mentorAssignments} mentored` : `${(user as unknown as { _count: { mentorAssignments: number; assignments: number } })._count.assignments} assigned`} diff --git a/src/server/routers/user.ts b/src/server/routers/user.ts index 5812a79..5f7b0a0 100644 --- a/src/server/routers/user.ts +++ b/src/server/routers/user.ts @@ -297,8 +297,73 @@ export const userRouter = router({ const usersWithAvatars = await attachAvatarUrls(users) + // For APPLICANT users, attach their project's current round info + const applicantIds = users.filter((u) => u.role === 'APPLICANT').map((u) => u.id) + const applicantRoundMap = new Map() + + if (applicantIds.length > 0) { + // Find each applicant's project, then the latest round state + const projects = await ctx.prisma.project.findMany({ + where: { + OR: [ + { submittedByUserId: { in: applicantIds } }, + { teamMembers: { some: { userId: { in: applicantIds } } } }, + ], + }, + include: { + teamMembers: { select: { userId: true } }, + projectRoundStates: { + select: { + state: true, + round: { select: { name: true, sortOrder: true } }, + }, + orderBy: { round: { sortOrder: 'desc' } }, + }, + }, + }) + + // Build a map of userId -> project's current round info + for (const proj of projects) { + const userIds = [ + proj.submittedByUserId, + ...proj.teamMembers.map((tm) => tm.userId), + ].filter((id): id is string => id !== null) + + // Find the latest active round state (non-terminal first, fallback to terminal) + const latestActive = proj.projectRoundStates.find((rs) => + rs.state === 'IN_PROGRESS' || rs.state === 'PENDING' + ) + const latestTerminal = proj.projectRoundStates.find((rs) => + rs.state === 'REJECTED' || rs.state === 'WITHDRAWN' + ) + const latest = latestActive ?? proj.projectRoundStates[0] + + for (const uid of userIds) { + if (!applicantIds.includes(uid)) continue + if (latestTerminal && !latestActive) { + applicantRoundMap.set(uid, { + roundName: latestTerminal.round.name, + state: latestTerminal.state, + }) + } else if (latest) { + applicantRoundMap.set(uid, { + roundName: latest.round.name, + state: latest.state, + }) + } else { + applicantRoundMap.set(uid, null) + } + } + } + } + + const enrichedUsers = usersWithAvatars.map((u) => ({ + ...u, + applicantRoundInfo: applicantRoundMap.get(u.id) ?? null, + })) + return { - users: usersWithAvatars, + users: enrichedUsers, total, page, perPage,