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:
@@ -46,43 +46,28 @@ import {
|
||||
ArrowRight,
|
||||
} from 'lucide-react'
|
||||
import { useEdition } from '@/contexts/edition-context'
|
||||
import {
|
||||
roundTypeConfig,
|
||||
roundStatusConfig,
|
||||
awardStatusConfig,
|
||||
ROUND_TYPE_OPTIONS,
|
||||
} from '@/lib/round-config'
|
||||
|
||||
// ─── Constants ───────────────────────────────────────────────────────────────
|
||||
// ─── Constants (derived from shared config) ──────────────────────────────────
|
||||
|
||||
const ROUND_TYPES = [
|
||||
{ value: 'INTAKE', label: 'Intake' },
|
||||
{ value: 'FILTERING', label: 'Filtering' },
|
||||
{ value: 'EVALUATION', label: 'Evaluation' },
|
||||
{ value: 'SUBMISSION', label: 'Submission' },
|
||||
{ value: 'MENTORING', label: 'Mentoring' },
|
||||
{ value: 'LIVE_FINAL', label: 'Live Final' },
|
||||
{ value: 'DELIBERATION', label: 'Deliberation' },
|
||||
] as const
|
||||
const ROUND_TYPES = ROUND_TYPE_OPTIONS
|
||||
|
||||
const ROUND_TYPE_COLORS: Record<string, { dot: string; bg: string; text: string; border: string }> = {
|
||||
INTAKE: { dot: '#9ca3af', bg: 'bg-gray-50', text: 'text-gray-600', border: 'border-gray-300' },
|
||||
FILTERING: { dot: '#f59e0b', bg: 'bg-amber-50', text: 'text-amber-700', border: 'border-amber-300' },
|
||||
EVALUATION: { dot: '#3b82f6', bg: 'bg-blue-50', text: 'text-blue-700', border: 'border-blue-300' },
|
||||
SUBMISSION: { dot: '#8b5cf6', bg: 'bg-purple-50', text: 'text-purple-700', border: 'border-purple-300' },
|
||||
MENTORING: { dot: '#557f8c', bg: 'bg-teal-50', text: 'text-teal-700', border: 'border-teal-300' },
|
||||
LIVE_FINAL: { dot: '#de0f1e', bg: 'bg-red-50', text: 'text-red-700', border: 'border-red-300' },
|
||||
DELIBERATION: { dot: '#6366f1', bg: 'bg-indigo-50', text: 'text-indigo-700', border: 'border-indigo-300' },
|
||||
}
|
||||
const ROUND_TYPE_COLORS: Record<string, { dot: string; bg: string; text: string; border: string }> = Object.fromEntries(
|
||||
Object.entries(roundTypeConfig).map(([k, v]) => [k, { dot: v.dotColor, bg: v.cardBg, text: v.cardText, border: v.cardBorder }])
|
||||
)
|
||||
|
||||
const ROUND_STATUS_STYLES: Record<string, { color: string; label: string; pulse?: boolean }> = {
|
||||
ROUND_DRAFT: { color: '#9ca3af', label: 'Draft' },
|
||||
ROUND_ACTIVE: { color: '#10b981', label: 'Active', pulse: true },
|
||||
ROUND_CLOSED: { color: '#3b82f6', label: 'Closed' },
|
||||
ROUND_ARCHIVED: { color: '#6b7280', label: 'Archived' },
|
||||
}
|
||||
const ROUND_STATUS_STYLES: Record<string, { color: string; label: string; pulse?: boolean }> = Object.fromEntries(
|
||||
Object.entries(roundStatusConfig).map(([k, v]) => [k, { color: v.dotColor, label: v.label, pulse: v.pulse }])
|
||||
)
|
||||
|
||||
const AWARD_STATUS_COLORS: Record<string, string> = {
|
||||
DRAFT: 'text-gray-500',
|
||||
NOMINATIONS_OPEN: 'text-amber-600',
|
||||
VOTING_OPEN: 'text-emerald-600',
|
||||
CLOSED: 'text-blue-600',
|
||||
ARCHIVED: 'text-gray-400',
|
||||
}
|
||||
const AWARD_STATUS_COLORS: Record<string, string> = Object.fromEntries(
|
||||
Object.entries(awardStatusConfig).map(([k, v]) => [k, v.color])
|
||||
)
|
||||
|
||||
// ─── Types ───────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -268,12 +253,12 @@ export default function RoundsPage() {
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-[#053d57] mb-1">No Competition Configured</h3>
|
||||
<p className="text-sm text-muted-foreground max-w-sm mb-5">
|
||||
Create a competition to start building the evaluation pipeline.
|
||||
Create a program edition to start building the evaluation pipeline.
|
||||
</p>
|
||||
<Link href={`/admin/competitions/new?programId=${programId}` as Route}>
|
||||
<Link href={'/admin/programs' as Route}>
|
||||
<Button className="bg-[#de0f1e] hover:bg-[#de0f1e]/90">
|
||||
<Plus className="h-4 w-4 mr-2" />
|
||||
Create Competition
|
||||
Manage Editions
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user