Admin dashboard & round management UX overhaul
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m43s
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m43s
- Extract round detail monolith (2900→600 lines) into 13 standalone components - Add shared round/status config (round-config.ts) replacing 4 local copies - Delete 12 legacy competition-scoped pages, merge project pool into projects page - Add round-type-specific dashboard stat panels (submission, mentoring, live final, deliberation, summary) - Add contextual header quick actions based on active round type - Improve pipeline visualization: progress bars, checkmarks, chevron connectors, overflow fix - Add config tab completion dots (green/amber/red) and inline validation warnings - Enhance juries page with round assignments, member avatars, and cap mode badges - Add context-aware project list (recent submissions vs active evaluations) - Move competition settings into Manage Editions page Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -109,6 +109,8 @@ export const dashboardRouter = router({
|
||||
categoryBreakdown,
|
||||
oceanIssueBreakdown,
|
||||
recentActivity,
|
||||
// Recently active
|
||||
recentlyActiveEvals,
|
||||
// Action signals
|
||||
pendingCOIs,
|
||||
] = await Promise.all([
|
||||
@@ -257,7 +259,43 @@ export const dashboardRouter = router({
|
||||
},
|
||||
}),
|
||||
|
||||
// 17. Pending COIs
|
||||
// 17. Recently active projects (with recent evaluations)
|
||||
ctx.prisma.evaluation.findMany({
|
||||
where: {
|
||||
status: 'SUBMITTED',
|
||||
assignment: {
|
||||
round: { competition: { programId: editionId } },
|
||||
},
|
||||
},
|
||||
orderBy: { submittedAt: 'desc' },
|
||||
take: 8,
|
||||
select: {
|
||||
id: true,
|
||||
globalScore: true,
|
||||
submittedAt: true,
|
||||
assignment: {
|
||||
select: {
|
||||
user: { select: { name: true } },
|
||||
project: {
|
||||
select: {
|
||||
id: true,
|
||||
title: true,
|
||||
teamName: true,
|
||||
country: true,
|
||||
competitionCategory: true,
|
||||
oceanIssue: true,
|
||||
logoKey: true,
|
||||
createdAt: true,
|
||||
submittedAt: true,
|
||||
status: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
||||
// 18. Pending COIs
|
||||
ctx.prisma.conflictOfInterest.count({
|
||||
where: {
|
||||
hasConflict: true,
|
||||
@@ -443,6 +481,22 @@ export const dashboardRouter = router({
|
||||
|
||||
// ── Return ──────────────────────────────────────────────────────
|
||||
|
||||
// Deduplicate recently active projects (same project may have multiple evals)
|
||||
const seenProjectIds = new Set<string>()
|
||||
const recentlyActiveProjects = recentlyActiveEvals
|
||||
.filter((e) => {
|
||||
const pid = e.assignment.project.id
|
||||
if (seenProjectIds.has(pid)) return false
|
||||
seenProjectIds.add(pid)
|
||||
return true
|
||||
})
|
||||
.map((e) => ({
|
||||
...e.assignment.project,
|
||||
latestEvaluator: e.assignment.user.name,
|
||||
latestScore: e.globalScore,
|
||||
evaluatedAt: e.submittedAt,
|
||||
}))
|
||||
|
||||
return {
|
||||
edition,
|
||||
// Pipeline
|
||||
@@ -460,6 +514,7 @@ export const dashboardRouter = router({
|
||||
pendingCOIs,
|
||||
// Lists
|
||||
latestProjects,
|
||||
recentlyActiveProjects,
|
||||
categoryBreakdown,
|
||||
oceanIssueBreakdown,
|
||||
recentActivity,
|
||||
|
||||
Reference in New Issue
Block a user