'use client' import { useState } from 'react' import { Button } from '@/components/ui/button' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Label } from '@/components/ui/label' import { Input } from '@/components/ui/input' import { Slider } from '@/components/ui/slider' import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '@/components/ui/alert-dialog' import { CheckCircle2 } from 'lucide-react' interface LiveVotingCriterion { id: string label: string description?: string scale: number weight: number } interface LiveVotingFormProps { projectId: string votingMode?: 'simple' | 'criteria' criteria?: LiveVotingCriterion[] onVoteSubmit: (vote: { score: number; criterionScores?: Record }) => void disabled?: boolean existingVote?: { score: number criterionScoresJson?: Record } | null } export function LiveVotingForm({ projectId, votingMode = 'simple', criteria, onVoteSubmit, disabled = false, existingVote, }: LiveVotingFormProps) { const [score, setScore] = useState(existingVote?.score ?? 50) const [criterionScores, setCriterionScores] = useState>( existingVote?.criterionScoresJson ?? {} ) const [confirmDialogOpen, setConfirmDialogOpen] = useState(false) const [hasSubmitted, setHasSubmitted] = useState(!!existingVote) const handleSubmit = () => { setConfirmDialogOpen(true) } const handleConfirm = () => { if (votingMode === 'criteria' && criteria) { // Compute weighted score for display let weightedSum = 0 for (const c of criteria) { const normalizedScore = (criterionScores[c.id] / c.scale) * 10 weightedSum += normalizedScore * c.weight } const computedScore = Math.round(Math.min(10, Math.max(1, weightedSum))) * 10 // Scale to 100 for display onVoteSubmit({ score: computedScore, criterionScores, }) } else { onVoteSubmit({ score }) } setHasSubmitted(true) setConfirmDialogOpen(false) } if (hasSubmitted || disabled) { return (

Vote Submitted

{votingMode === 'simple' && (

Score: {score}/100

)} {votingMode === 'criteria' && criteria && (
{criteria.map((c) => (
{c.label}: {criterionScores[c.id] ?? 0}/{c.scale}
))}
)}
) } // Criteria-based voting if (votingMode === 'criteria' && criteria && criteria.length > 0) { const allScored = criteria.every((c) => criterionScores[c.id] !== undefined && criterionScores[c.id] > 0) return ( <> Criteria-Based Voting Score each criterion individually {criteria.map((criterion) => (
{criterion.description && (

{criterion.description}

)}

Weight: {(criterion.weight * 100).toFixed(0)}%

{ const val = parseInt(e.target.value, 10) if (!isNaN(val)) { setCriterionScores({ ...criterionScores, [criterion.id]: Math.min(criterion.scale, Math.max(1, val)), }) } }} className="w-20 text-center" placeholder="0" /> / {criterion.scale}
setCriterionScores({ ...criterionScores, [criterion.id]: values[0], }) } min={0} max={criterion.scale} step={1} className="w-full" />
))}
Confirm Your Vote

Your scores:

{criteria.map((c) => (
{c.label}: {criterionScores[c.id]}/{c.scale}
))}

This action cannot be undone. Are you sure?

Cancel Confirm Vote
) } // Simple voting (0-100 slider) return ( <> Live Voting Rate this project on a scale of 0-100
setScore(Math.min(100, Math.max(0, parseInt(e.target.value) || 0)))} className="w-20 text-center" /> {score}
setScore(values[0])} min={0} max={100} step={1} className="w-full" />
Poor (0) Average (50) Excellent (100)
{/* Confirmation Dialog */} Confirm Your Vote You are about to submit a score of {score}/100. This action cannot be undone. Are you sure? Cancel Confirm Vote ) }