61 lines
2.2 KiB
TypeScript
61 lines
2.2 KiB
TypeScript
import { PollOption } from '../types/poll.types';
|
|
import { VoteButton } from './VoteButton';
|
|
|
|
interface OptionListProps {
|
|
options: PollOption[];
|
|
onVote: (optionId: string) => void;
|
|
hasVoted?: (option: PollOption) => boolean;
|
|
}
|
|
|
|
export function OptionList({ options, onVote, hasVoted }: OptionListProps) {
|
|
const totalVotes = options.reduce((sum, opt) => sum + opt.votes, 0);
|
|
|
|
const sortedOptions = [...options].sort((a, b) => b.votes - a.votes);
|
|
|
|
return (
|
|
<div className="space-y-3">
|
|
{sortedOptions.length === 0 ? (
|
|
<div className="text-center py-8 text-white/60">
|
|
No options yet. Add one to get started!
|
|
</div>
|
|
) : (
|
|
sortedOptions.map((option) => {
|
|
const percentage = totalVotes > 0 ? (option.votes / totalVotes) * 100 : 0;
|
|
const userHasVoted = hasVoted ? hasVoted(option) : false;
|
|
|
|
return (
|
|
<div
|
|
key={option.id}
|
|
className={`bg-white/10 backdrop-blur-sm rounded-lg p-4 border transition-all duration-200 ${
|
|
userHasVoted
|
|
? 'border-green-400/50 bg-green-400/10'
|
|
: 'border-white/20 hover:border-white/30'
|
|
}`}
|
|
>
|
|
<div className="flex items-center justify-between mb-2">
|
|
<span className="text-white font-medium text-lg">
|
|
{option.text}
|
|
{userHasVoted && <span className="ml-2 text-green-400 text-sm">✓ Voted</span>}
|
|
</span>
|
|
<VoteButton optionId={option.id} votes={option.votes} onVote={onVote} disabled={userHasVoted} />
|
|
</div>
|
|
|
|
<div className="w-full bg-white/10 rounded-full h-2 overflow-hidden">
|
|
<div
|
|
className="bg-gradient-to-r from-green-400 to-blue-500 h-full transition-all duration-500 ease-out"
|
|
style={{ width: `${percentage}%` }}
|
|
/>
|
|
</div>
|
|
|
|
<div className="mt-2 flex justify-between text-xs text-white/60">
|
|
<span>by {option.createdBy}</span>
|
|
<span>{percentage.toFixed(1)}%</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
})
|
|
)}
|
|
</div>
|
|
);
|
|
}
|