'use client' import { use, useState, useEffect } from 'react' import Link from 'next/link' import { useRouter } from 'next/navigation' import { trpc } from '@/lib/trpc/client' import { Button } from '@/components/ui/button' import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from '@/components/ui/card' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Textarea } from '@/components/ui/textarea' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select' import { Switch } from '@/components/ui/switch' import { Skeleton } from '@/components/ui/skeleton' import { toast } from 'sonner' import { ArrowLeft, Save, Loader2 } from 'lucide-react' export default function EditAwardPage({ params, }: { params: Promise<{ id: string }> }) { const { id: awardId } = use(params) const router = useRouter() const utils = trpc.useUtils() const { data: award, isLoading } = trpc.specialAward.get.useQuery({ id: awardId }) // Fetch competition rounds for source round selector const competitionId = award?.competitionId const { data: competition } = trpc.competition.getById.useQuery( { id: competitionId! }, { enabled: !!competitionId } ) const updateAward = trpc.specialAward.update.useMutation({ onSuccess: () => { utils.specialAward.get.invalidate({ id: awardId }) utils.specialAward.list.invalidate() }, }) const [name, setName] = useState('') const [description, setDescription] = useState('') const [criteriaText, setCriteriaText] = useState('') const [scoringMode, setScoringMode] = useState<'PICK_WINNER' | 'RANKED' | 'SCORED'>('PICK_WINNER') const [useAiEligibility, setUseAiEligibility] = useState(true) const [maxRankedPicks, setMaxRankedPicks] = useState('3') const [votingStartAt, setVotingStartAt] = useState('') const [votingEndAt, setVotingEndAt] = useState('') const [evaluationRoundId, setEvaluationRoundId] = useState('') const [eligibilityMode, setEligibilityMode] = useState<'STAY_IN_MAIN' | 'SEPARATE_POOL'>('STAY_IN_MAIN') // Helper to format date for datetime-local input const formatDateForInput = (date: Date | string | null | undefined): string => { if (!date) return '' const d = new Date(date) // Format: YYYY-MM-DDTHH:mm return d.toISOString().slice(0, 16) } // Load existing values when award data arrives useEffect(() => { if (award) { setName(award.name) setDescription(award.description || '') setCriteriaText(award.criteriaText || '') setScoringMode(award.scoringMode as 'PICK_WINNER' | 'RANKED' | 'SCORED') setUseAiEligibility(award.useAiEligibility) setMaxRankedPicks(String(award.maxRankedPicks || 3)) setVotingStartAt(formatDateForInput(award.votingStartAt)) setVotingEndAt(formatDateForInput(award.votingEndAt)) setEvaluationRoundId(award.evaluationRoundId || '') setEligibilityMode(award.eligibilityMode as 'STAY_IN_MAIN' | 'SEPARATE_POOL') } }, [award]) const handleSubmit = async () => { if (!name.trim()) return try { await updateAward.mutateAsync({ id: awardId, name: name.trim(), description: description.trim() || undefined, criteriaText: criteriaText.trim() || undefined, useAiEligibility, scoringMode, maxRankedPicks: scoringMode === 'RANKED' ? parseInt(maxRankedPicks) : undefined, votingStartAt: votingStartAt ? new Date(votingStartAt) : undefined, votingEndAt: votingEndAt ? new Date(votingEndAt) : undefined, evaluationRoundId: evaluationRoundId || undefined, eligibilityMode, }) toast.success('Award updated') router.push(`/admin/awards/${awardId}`) } catch (error) { toast.error( error instanceof Error ? error.message : 'Failed to update award' ) } } if (isLoading) { return (
Update award settings and eligibility criteria
Use AI to automatically evaluate project eligibility based on the criteria above. Turn off for awards decided by feeling or manual selection.
Projects from this round will be considered for award eligibility
Whether award-eligible projects continue in the main competition or move to a separate track
When jurors can start voting (leave empty to set when opening voting)
Deadline for juror votes