import { useState } from 'preact/hooks'; import shortenNumber from '../utils/shorten-number'; import EmojiText from './emoji-text'; import Icon from './icon'; import RelativeTime from './relative-time'; export default function Poll({ poll, lang, readOnly, refresh = () => {}, votePoll = () => {}, }) { const [uiState, setUIState] = useState('default'); const { expired, expiresAt, id, multiple, options, ownVotes, voted, votersCount, votesCount, emojis, } = poll; const expiresAtDate = !!expiresAt && new Date(expiresAt); // Update poll at point of expiry // NOTE: Disable this because setTimeout runs immediately if delay is too large // https://stackoverflow.com/a/56718027/20838 // useEffect(() => { // let timeout; // if (!expired && expiresAtDate) { // const ms = expiresAtDate.getTime() - Date.now() + 1; // +1 to give it a little buffer // if (ms > 0) { // timeout = setTimeout(() => { // setUIState('loading'); // (async () => { // // await refresh(); // setUIState('default'); // })(); // }, ms); // } // } // return () => { // clearTimeout(timeout); // }; // }, [expired, expiresAtDate]); const pollVotesCount = votersCount || votesCount; let roundPrecision = 0; if (pollVotesCount <= 1000) { roundPrecision = 0; } else if (pollVotesCount <= 10000) { roundPrecision = 1; } else if (pollVotesCount <= 100000) { roundPrecision = 2; } const [showResults, setShowResults] = useState(false); const optionsHaveVoteCounts = options.every((o) => o.votesCount !== null); return (
{(showResults && optionsHaveVoteCounts) || voted || expired ? ( <>
{options.map((option, i) => { const { title, votesCount: optionVotesCount } = option; const percentage = pollVotesCount ? ((optionVotesCount / pollVotesCount) * 100).toFixed( roundPrecision, ) : 0; // check if current poll choice is the leading one const isLeading = optionVotesCount > 0 && optionVotesCount === Math.max(...options.map((o) => o.votesCount)); return (
{voted && ownVotes.includes(i) && ( <> {' '} )}
{percentage}%
); })}
{!expired && !voted && ( )} ) : (
{ e.preventDefault(); const form = e.target; const formData = new FormData(form); const choices = []; formData.forEach((value, key) => { if (key === 'poll') { choices.push(value); } }); if (!choices.length) return; setUIState('loading'); await votePoll(choices); setUIState('default'); }} >
{options.map((option, i) => { const { title } = option; return (
); })}
{!readOnly && ( )}
)}

{!expired && !readOnly && ( )} {!voted && !expired && !readOnly && optionsHaveVoteCounts && ( )} {!expired && !readOnly && ' '} {shortenNumber(votesCount)} vote {votesCount === 1 ? '' : 's'} {!!votersCount && votersCount !== votesCount && ( <> {' '} • {shortenNumber(votersCount)} {' '} voter {votersCount === 1 ? '' : 's'} )}{' '} • {expired ? 'Ended' : 'Ending'}{' '} {!!expiresAtDate && }

{' '}
); }