'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 }) 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('') // 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)) } }, [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, }) 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.
When jurors can start voting (leave empty to set when opening voting)
Deadline for juror votes