All checks were successful
Build and Push Docker Image / build (push) Successful in 7m23s
- Phase 1: 7 round config sub-components covering all ~65 Zod schema fields across INTAKE, FILTERING, EVALUATION, SUBMISSION, MENTORING, LIVE_FINAL, DELIBERATION - Phase 2: Replace Competitions nav with Rounds + add Juries; new /admin/rounds and /admin/rounds/[roundId] pages with tabbed detail (Config, Projects, Windows, Documents, Awards) - Phase 3: Top-level /admin/juries with list + detail pages (members table, settings panel, self-service review) - Phase 4: File requirements editor in round config; project detail per-requirement upload slots replacing generic drop zone - Phase 5: Awards edit page with source round dropdown, eligibility mode, auto-tag rules builder; round detail Awards tab; specialAward router enhanced with evaluationRoundId/eligibilityMode fields - Phase 6: Evaluation page rewrite supporting all 3 scoring modes (criteria/global/binary) with config-driven behavior; live voting UI polish - Phase 7: UI design polish across admin pages — consistent headers, cards, hover transitions, empty states, brand colors - Bulk upload page for admin project imports - File router enhanced with admin upload and submission window procedures Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
109 lines
3.9 KiB
TypeScript
109 lines
3.9 KiB
TypeScript
'use client'
|
|
|
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
|
import { Label } from '@/components/ui/label'
|
|
import { Switch } from '@/components/ui/switch'
|
|
import { Badge } from '@/components/ui/badge'
|
|
|
|
type SubmissionConfigProps = {
|
|
config: Record<string, unknown>
|
|
onChange: (config: Record<string, unknown>) => void
|
|
}
|
|
|
|
const STATUSES = [
|
|
{ value: 'PENDING', label: 'Pending', color: 'bg-gray-100 text-gray-700' },
|
|
{ value: 'IN_PROGRESS', label: 'In Progress', color: 'bg-blue-100 text-blue-700' },
|
|
{ value: 'PASSED', label: 'Passed', color: 'bg-emerald-100 text-emerald-700' },
|
|
{ value: 'REJECTED', label: 'Rejected', color: 'bg-red-100 text-red-700' },
|
|
{ value: 'COMPLETED', label: 'Completed', color: 'bg-purple-100 text-purple-700' },
|
|
{ value: 'WITHDRAWN', label: 'Withdrawn', color: 'bg-amber-100 text-amber-700' },
|
|
]
|
|
|
|
export function SubmissionConfig({ config, onChange }: SubmissionConfigProps) {
|
|
const update = (key: string, value: unknown) => {
|
|
onChange({ ...config, [key]: value })
|
|
}
|
|
|
|
const eligible = (config.eligibleStatuses as string[]) ?? ['PASSED']
|
|
|
|
const toggleStatus = (status: string) => {
|
|
const current = [...eligible]
|
|
const idx = current.indexOf(status)
|
|
if (idx >= 0) {
|
|
current.splice(idx, 1)
|
|
} else {
|
|
current.push(status)
|
|
}
|
|
update('eligibleStatuses', current)
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="text-base">Submission Eligibility</CardTitle>
|
|
<CardDescription>
|
|
Which project states from the previous round are eligible to submit documents in this round
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="space-y-4">
|
|
<div className="space-y-2">
|
|
<Label>Eligible Project Statuses</Label>
|
|
<p className="text-xs text-muted-foreground">
|
|
Projects with these statuses from the previous round can submit
|
|
</p>
|
|
<div className="flex flex-wrap gap-2">
|
|
{STATUSES.map((s) => (
|
|
<Badge
|
|
key={s.value}
|
|
variant={eligible.includes(s.value) ? 'default' : 'outline'}
|
|
className="cursor-pointer select-none"
|
|
onClick={() => toggleStatus(s.value)}
|
|
>
|
|
{s.label}
|
|
</Badge>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="text-base">Notifications & Locking</CardTitle>
|
|
<CardDescription>Behavior when the submission round activates</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="space-y-4">
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<Label htmlFor="notifyEligibleTeams">Notify Eligible Teams</Label>
|
|
<p className="text-xs text-muted-foreground">
|
|
Send email notification to teams when submission window opens
|
|
</p>
|
|
</div>
|
|
<Switch
|
|
id="notifyEligibleTeams"
|
|
checked={(config.notifyEligibleTeams as boolean) ?? true}
|
|
onCheckedChange={(v) => update('notifyEligibleTeams', v)}
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<Label htmlFor="lockPreviousWindows">Lock Previous Windows</Label>
|
|
<p className="text-xs text-muted-foreground">
|
|
Prevent uploads to earlier submission windows when this round activates
|
|
</p>
|
|
</div>
|
|
<Switch
|
|
id="lockPreviousWindows"
|
|
checked={(config.lockPreviousWindows as boolean) ?? true}
|
|
onCheckedChange={(v) => update('lockPreviousWindows', v)}
|
|
/>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
)
|
|
}
|