feat: revamp applicant jury feedback UI with score summaries and observer-style design
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
Dashboard sidebar card now shows per-round avg score with progress bars. Evaluations page redesigned with stats strip, score comparison bars, criteria progress bars, animated cards, and styled feedback blocks. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,7 @@ import { CompetitionTimelineSidebar } from '@/components/applicant/competition-t
|
||||
import { MentoringRequestCard } from '@/components/applicant/mentoring-request-card'
|
||||
import { AnimatedCard } from '@/components/shared/animated-container'
|
||||
import { ProjectLogoUpload } from '@/components/shared/project-logo-upload'
|
||||
import { Progress } from '@/components/ui/progress'
|
||||
import {
|
||||
FileText,
|
||||
Calendar,
|
||||
@@ -35,6 +36,8 @@ import {
|
||||
Check,
|
||||
X,
|
||||
UserCircle,
|
||||
Trophy,
|
||||
Vote,
|
||||
} from 'lucide-react'
|
||||
import { toast } from 'sonner'
|
||||
|
||||
@@ -390,7 +393,9 @@ export default function ApplicantDashboardPage() {
|
||||
<CardHeader>
|
||||
<div className="flex items-center justify-between">
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Star className="h-5 w-5" />
|
||||
<div className="rounded-lg bg-yellow-500/10 p-1.5">
|
||||
<Star className="h-4 w-4 text-yellow-500" />
|
||||
</div>
|
||||
Jury Feedback
|
||||
</CardTitle>
|
||||
<Button variant="ghost" size="sm" asChild>
|
||||
@@ -400,15 +405,47 @@ export default function ApplicantDashboardPage() {
|
||||
</Button>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2">
|
||||
{evaluations?.map((round) => (
|
||||
<div key={round.roundId} className="flex items-center justify-between text-sm rounded-lg border p-2.5">
|
||||
<span className="font-medium">{round.roundName}</span>
|
||||
<Badge variant="secondary" className="text-xs">
|
||||
{round.evaluationCount} review{round.evaluationCount !== 1 ? 's' : ''}
|
||||
</Badge>
|
||||
</div>
|
||||
))}
|
||||
<CardContent className="space-y-3">
|
||||
{evaluations?.map((round) => {
|
||||
const scores = round.evaluations
|
||||
.map((ev) => ev.globalScore)
|
||||
.filter((s): s is number => s !== null)
|
||||
const avgScore = scores.length > 0
|
||||
? scores.reduce((a, b) => a + b, 0) / scores.length
|
||||
: null
|
||||
const maxScore = round.roundType === 'LIVE_FINAL' ? 10 : 100
|
||||
const pct = avgScore !== null ? (avgScore / maxScore) * 100 : 0
|
||||
const roundIcon = round.roundType === 'LIVE_FINAL'
|
||||
? <Trophy className="h-3.5 w-3.5 text-amber-500" />
|
||||
: round.roundType === 'DELIBERATION'
|
||||
? <Vote className="h-3.5 w-3.5 text-violet-500" />
|
||||
: <Star className="h-3.5 w-3.5 text-yellow-500" />
|
||||
|
||||
return (
|
||||
<div key={round.roundId} className="rounded-lg border p-3 space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="flex items-center gap-1.5 text-sm font-medium">
|
||||
{roundIcon}
|
||||
{round.roundName}
|
||||
</span>
|
||||
<Badge variant="secondary" className="text-xs">
|
||||
{round.evaluationCount} review{round.evaluationCount !== 1 ? 's' : ''}
|
||||
</Badge>
|
||||
</div>
|
||||
{avgScore !== null && (
|
||||
<div className="space-y-1">
|
||||
<div className="flex items-center justify-between text-xs text-muted-foreground">
|
||||
<span>Avg Score</span>
|
||||
<span className="font-semibold text-foreground tabular-nums">
|
||||
{avgScore.toFixed(1)}<span className="text-muted-foreground font-normal"> / {maxScore}</span>
|
||||
</span>
|
||||
</div>
|
||||
<Progress value={pct} className="h-1.5" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</AnimatedCard>
|
||||
|
||||
Reference in New Issue
Block a user