Platform-wide visual overhaul, team invites, analytics improvements, and deployment hardening
UI overhaul applying jury dashboard design patterns across all pages: - Stat cards with border-l-4 accent + icon pills on admin, observer, mentor, applicant dashboards and reports - Card section headers with color-coded icon pills throughout - Hover lift effects (translate-y + shadow) on cards and list items - Gradient progress bars (brand-teal to brand-blue) platform-wide - AnimatedCard stagger animations on all dashboard sections - Auth pages with gradient accent strip and polished icon containers - EmptyState component upgraded with rounded icon pill containers - Replaced AI-looking icons (Brain/Sparkles/Bot/Wand2/Cpu) with descriptive alternatives across 12 files - Removed gradient overlay from jury dashboard header - Quick actions restyled as card links with group hover effects Backend improvements: - Team member invite emails with account setup flow and notification logging - Analytics routers accept edition-wide queries (programId) in addition to roundId - Round detail endpoint returns inline progress data (eliminates extra getProgress call) - Award voting endpoints parallelized with Promise.all - Bulk invite supports optional sendInvitation flag - AwardVote composite index migration for query performance Infrastructure: - Docker entrypoint with migration retry loop (configurable retries/delay) - docker-compose pull_policy: always for automatic image refresh - Simplified deploy/update scripts using docker compose up -d --pull always - Updated deployment documentation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -87,18 +87,44 @@ export const roundRouter = router({
|
||||
},
|
||||
})
|
||||
|
||||
// Get evaluation stats
|
||||
const evaluationStats = await ctx.prisma.evaluation.groupBy({
|
||||
by: ['status'],
|
||||
where: {
|
||||
assignment: { roundId: input.id },
|
||||
// Get evaluation stats + progress in parallel (avoids duplicate groupBy in getProgress)
|
||||
const [evaluationStats, totalAssignments, completedAssignments] =
|
||||
await Promise.all([
|
||||
ctx.prisma.evaluation.groupBy({
|
||||
by: ['status'],
|
||||
where: {
|
||||
assignment: { roundId: input.id },
|
||||
},
|
||||
_count: true,
|
||||
}),
|
||||
ctx.prisma.assignment.count({ where: { roundId: input.id } }),
|
||||
ctx.prisma.assignment.count({
|
||||
where: { roundId: input.id, isCompleted: true },
|
||||
}),
|
||||
])
|
||||
|
||||
const evaluationsByStatus = evaluationStats.reduce(
|
||||
(acc, curr) => {
|
||||
acc[curr.status] = curr._count
|
||||
return acc
|
||||
},
|
||||
_count: true,
|
||||
})
|
||||
{} as Record<string, number>
|
||||
)
|
||||
|
||||
return {
|
||||
...round,
|
||||
evaluationStats,
|
||||
// Inline progress data (eliminates need for separate getProgress call)
|
||||
progress: {
|
||||
totalProjects: round._count.projects,
|
||||
totalAssignments,
|
||||
completedAssignments,
|
||||
completionPercentage:
|
||||
totalAssignments > 0
|
||||
? Math.round((completedAssignments / totalAssignments) * 100)
|
||||
: 0,
|
||||
evaluationsByStatus,
|
||||
},
|
||||
}
|
||||
}),
|
||||
|
||||
|
||||
Reference in New Issue
Block a user