feat: show applicant's current round instead of assignments in members table
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
For APPLICANT users in the admin members list, the Assignments column now shows the project's current round name and state badge (Active, Pending, Rejected, etc.) instead of "0 assigned". Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -426,7 +426,29 @@ export function MembersContent() {
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div>
|
||||
{user.role === 'MENTOR' ? (
|
||||
{user.role === 'APPLICANT' ? (
|
||||
(() => {
|
||||
const info = (user as unknown as { applicantRoundInfo?: { roundName: string; state: string } | null }).applicantRoundInfo
|
||||
if (!info) return <span className="text-sm text-muted-foreground">-</span>
|
||||
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 (
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<span className="text-sm">{info.roundName}</span>
|
||||
<Badge variant={stateColor} className="w-fit text-[10px] px-1.5 py-0">
|
||||
{stateLabel}
|
||||
</Badge>
|
||||
</div>
|
||||
)
|
||||
})()
|
||||
) : user.role === 'MENTOR' ? (
|
||||
<p>{(user as unknown as { _count: { mentorAssignments: number; assignments: number } })._count.mentorAssignments} mentored</p>
|
||||
) : (
|
||||
<p>{(user as unknown as { _count: { mentorAssignments: number; assignments: number } })._count.assignments} assigned</p>
|
||||
@@ -520,9 +542,33 @@ export function MembersContent() {
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-between text-sm">
|
||||
<span className="text-muted-foreground">Assignments</span>
|
||||
<span className="text-muted-foreground">
|
||||
{user.role === 'APPLICANT' ? 'Current Round' : 'Assignments'}
|
||||
</span>
|
||||
<span>
|
||||
{user.role === 'MENTOR'
|
||||
{user.role === 'APPLICANT' ? (
|
||||
(() => {
|
||||
const info = (user as unknown as { applicantRoundInfo?: { roundName: string; state: string } | null }).applicantRoundInfo
|
||||
if (!info) return <span className="text-muted-foreground">-</span>
|
||||
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 (
|
||||
<span className="flex items-center gap-1.5">
|
||||
<span>{info.roundName}</span>
|
||||
<Badge variant={stateColor} className="text-[10px] px-1.5 py-0">
|
||||
{stateLabel}
|
||||
</Badge>
|
||||
</span>
|
||||
)
|
||||
})()
|
||||
) : 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`}
|
||||
</span>
|
||||
|
||||
@@ -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<string, { roundName: string; state: string } | null>()
|
||||
|
||||
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,
|
||||
|
||||
Reference in New Issue
Block a user