feat: mentor detail side sheet + Teams column
The mentor list now ends with a Teams column showing chips of each mentor's active assignments (truncated at 2 + overflow badge). Clicking any row opens a right-side Sheet with the mentor's profile (expertise, country, joined date, max assignments) and a per-team activity feed — project, status (active / completed / dropped), assignment date, and counts of messages / files / milestones with their last timestamp. Stat cards on both the Mentor and Mentee panels were stale and not particularly informative, so they're gone — the table itself is now the focal element on each panel. getMentorPool gained an activeTeams[] field; new getMentorDetail query backs the side sheet. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1016,6 +1016,7 @@ export const mentorRouter = router({
|
||||
},
|
||||
select: {
|
||||
completionStatus: true,
|
||||
project: { select: { id: true, title: true } },
|
||||
messages: {
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: 1,
|
||||
@@ -1043,9 +1044,14 @@ export const mentorRouter = router({
|
||||
let current = 0
|
||||
let completed = 0
|
||||
const activityDates: Date[] = []
|
||||
const activeTeams: { id: string; title: string }[] = []
|
||||
for (const a of m.mentorAssignments) {
|
||||
if (a.completionStatus === 'completed') completed++
|
||||
else current++
|
||||
if (a.completionStatus === 'completed') {
|
||||
completed++
|
||||
} else {
|
||||
current++
|
||||
activeTeams.push(a.project)
|
||||
}
|
||||
if (a.messages[0]) activityDates.push(a.messages[0].createdAt)
|
||||
if (a.files[0]) activityDates.push(a.files[0].createdAt)
|
||||
if (a.milestoneCompletions[0])
|
||||
@@ -1069,6 +1075,7 @@ export const mentorRouter = router({
|
||||
maxAssignments: m.maxAssignments,
|
||||
capacityRemaining,
|
||||
lastActivityAt,
|
||||
activeTeams,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -2305,4 +2312,81 @@ export const mentorRouter = router({
|
||||
})
|
||||
return dropped
|
||||
}),
|
||||
|
||||
/**
|
||||
* Per-mentor activity detail used by the admin mentor side sheet. For each
|
||||
* (active or dropped) assignment, returns the project, key timestamps, and
|
||||
* counts of messages, files, and completed milestones so the admin can see
|
||||
* "what has this mentor been up to" at a glance.
|
||||
*/
|
||||
getMentorDetail: adminProcedure
|
||||
.input(z.object({ mentorId: z.string() }))
|
||||
.query(async ({ ctx, input }) => {
|
||||
const mentor = await ctx.prisma.user.findUniqueOrThrow({
|
||||
where: { id: input.mentorId },
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
country: true,
|
||||
expertiseTags: true,
|
||||
maxAssignments: true,
|
||||
createdAt: true,
|
||||
},
|
||||
})
|
||||
|
||||
const assignments = await ctx.prisma.mentorAssignment.findMany({
|
||||
where: { mentorId: input.mentorId },
|
||||
orderBy: { assignedAt: 'desc' },
|
||||
include: {
|
||||
project: {
|
||||
select: {
|
||||
id: true,
|
||||
title: true,
|
||||
competitionCategory: true,
|
||||
country: true,
|
||||
},
|
||||
},
|
||||
_count: {
|
||||
select: { messages: true, files: true, milestoneCompletions: true },
|
||||
},
|
||||
messages: {
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: 1,
|
||||
select: { createdAt: true },
|
||||
},
|
||||
files: {
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: 1,
|
||||
select: { createdAt: true },
|
||||
},
|
||||
milestoneCompletions: {
|
||||
orderBy: { completedAt: 'desc' },
|
||||
take: 1,
|
||||
select: { completedAt: true },
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
return {
|
||||
mentor,
|
||||
assignments: assignments.map((a) => ({
|
||||
id: a.id,
|
||||
assignedAt: a.assignedAt,
|
||||
method: a.method,
|
||||
completionStatus: a.completionStatus,
|
||||
droppedAt: a.droppedAt,
|
||||
droppedReason: a.droppedReason,
|
||||
droppedBy: a.droppedBy,
|
||||
workspaceEnabled: a.workspaceEnabled,
|
||||
project: a.project,
|
||||
messageCount: a._count.messages,
|
||||
fileCount: a._count.files,
|
||||
milestoneCompletionCount: a._count.milestoneCompletions,
|
||||
lastMessageAt: a.messages[0]?.createdAt ?? null,
|
||||
lastFileAt: a.files[0]?.createdAt ?? null,
|
||||
lastMilestoneAt: a.milestoneCompletions[0]?.completedAt ?? null,
|
||||
})),
|
||||
}
|
||||
}),
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user