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:
@@ -178,7 +178,7 @@ async function AssignmentsContent({
|
||||
</div>
|
||||
</div>
|
||||
<div className="ml-auto">
|
||||
<Progress value={overallProgress} className="h-2 w-32" />
|
||||
<Progress value={overallProgress} className="h-2 w-32" gradient />
|
||||
<p className="text-xs text-muted-foreground mt-1">{overallProgress}% complete</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -210,7 +210,7 @@ async function AssignmentsContent({
|
||||
new Date(assignment.round.votingEndAt) >= now
|
||||
|
||||
return (
|
||||
<TableRow key={assignment.id}>
|
||||
<TableRow key={assignment.id} className="transition-all duration-200 hover:-translate-y-0.5 hover:shadow-sm">
|
||||
<TableCell>
|
||||
<Link
|
||||
href={`/jury/projects/${assignment.project.id}`}
|
||||
@@ -328,7 +328,7 @@ async function AssignmentsContent({
|
||||
new Date(assignment.round.votingEndAt) >= now
|
||||
|
||||
return (
|
||||
<Card key={assignment.id}>
|
||||
<Card key={assignment.id} className="transition-all duration-200 hover:-translate-y-0.5 hover:shadow-md">
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-start justify-between">
|
||||
<Link
|
||||
|
||||
@@ -743,16 +743,13 @@ export default async function JuryDashboardPage() {
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
{/* Header */}
|
||||
<div className="relative">
|
||||
<div className="absolute -top-6 -left-6 -right-6 h-32 bg-gradient-to-b from-brand-blue/[0.03] to-transparent dark:from-brand-blue/[0.06] pointer-events-none rounded-xl" />
|
||||
<div className="relative">
|
||||
<h1 className="text-2xl font-bold tracking-tight text-brand-blue dark:text-foreground">
|
||||
{getGreeting()}, {session?.user?.name || 'Juror'}
|
||||
</h1>
|
||||
<p className="text-muted-foreground mt-0.5">
|
||||
Here's an overview of your evaluation progress
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold tracking-tight text-brand-blue dark:text-foreground">
|
||||
{getGreeting()}, {session?.user?.name || 'Juror'}
|
||||
</h1>
|
||||
<p className="text-muted-foreground mt-0.5">
|
||||
Here's an overview of your evaluation progress
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
Star,
|
||||
AlertCircle,
|
||||
} from 'lucide-react'
|
||||
import { CollapsibleFilesSection } from '@/components/jury/collapsible-files-section'
|
||||
import { format } from 'date-fns'
|
||||
|
||||
interface PageProps {
|
||||
@@ -83,6 +84,7 @@ async function EvaluationContent({ projectId }: { projectId: string }) {
|
||||
id: true,
|
||||
title: true,
|
||||
teamName: true,
|
||||
_count: { select: { files: true } },
|
||||
},
|
||||
})
|
||||
|
||||
@@ -223,6 +225,13 @@ async function EvaluationContent({ projectId }: { projectId: string }) {
|
||||
|
||||
<Separator />
|
||||
|
||||
{/* Project Documents */}
|
||||
<CollapsibleFilesSection
|
||||
projectId={project.id}
|
||||
roundId={round.id}
|
||||
fileCount={project._count?.files ?? 0}
|
||||
/>
|
||||
|
||||
{/* Criteria scores */}
|
||||
{criteria.length > 0 && (
|
||||
<Card>
|
||||
|
||||
@@ -240,7 +240,12 @@ async function ProjectContent({ projectId }: { projectId: string }) {
|
||||
{/* Description */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg">Project Description</CardTitle>
|
||||
<CardTitle className="flex items-center gap-2.5 text-lg">
|
||||
<div className="rounded-lg bg-emerald-500/10 p-1.5">
|
||||
<FileText className="h-4 w-4 text-emerald-500" />
|
||||
</div>
|
||||
Project Description
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{project.description ? (
|
||||
@@ -266,7 +271,12 @@ async function ProjectContent({ projectId }: { projectId: string }) {
|
||||
{/* Round Info */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg">Round Details</CardTitle>
|
||||
<CardTitle className="flex items-center gap-2.5 text-lg">
|
||||
<div className="rounded-lg bg-blue-500/10 p-1.5">
|
||||
<Calendar className="h-4 w-4 text-blue-500" />
|
||||
</div>
|
||||
Round Details
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
@@ -310,7 +320,12 @@ async function ProjectContent({ projectId }: { projectId: string }) {
|
||||
{evaluation && (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg">Your Evaluation</CardTitle>
|
||||
<CardTitle className="flex items-center gap-2.5 text-lg">
|
||||
<div className="rounded-lg bg-brand-teal/10 p-1.5">
|
||||
<CheckCircle2 className="h-4 w-4 text-brand-teal" />
|
||||
</div>
|
||||
Your Evaluation
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
|
||||
Reference in New Issue
Block a user