// @flow import React, { useCallback, useMemo, useState } from 'react'; import type { AbstractComponent } from 'react'; import { useTranslation } from 'react-i18next'; import { useDispatch, useSelector } from 'react-redux'; import { sendAnalytics, createPollEvent } from '../../analytics'; import { setVoteChanging } from '../actions'; import { getPoll } from '../functions'; /** * The type of the React {@code Component} props of inheriting component. */ type InputProps = { /** * ID of the poll to display */ pollId: string, }; export type AnswerInfo = { name: string, percentage: number, voters?: Array<{ id: number, name: string }>, voterCount: number }; /** * The type of the React {@code Component} props of {@link AbstractPollResults}. */ export type AbstractProps = { answers: Array, changeVote: Function, showDetails: boolean, question: string, t: Function, toggleIsDetailed: Function, haveVoted: boolean, }; /** * Higher Order Component taking in a concrete PollResult component and * augmenting it with state/behavior common to both web and native implementations. * * @param {React.AbstractComponent} Component - The concrete component. * @returns {React.AbstractComponent} */ const AbstractPollResults = (Component: AbstractComponent) => (props: InputProps) => { const { pollId } = props; const pollDetails = useSelector(getPoll(pollId)); const [ showDetails, setShowDetails ] = useState(false); const toggleIsDetailed = useCallback(() => { sendAnalytics(createPollEvent('vote.detailsViewed')); setShowDetails(!showDetails); }); const answers: Array = useMemo(() => { const voterSet = new Set(); // Getting every voters ID that participates to the poll for (const answer of pollDetails.answers) { for (const [ voterId ] of answer.voters) { voterSet.add(voterId); } } const totalVoters = voterSet.size; return pollDetails.answers.map(answer => { const percentage = totalVoters === 0 ? 0 : Math.round(answer.voters.size / totalVoters * 100); let voters = null; if (showDetails) { voters = [ ...answer.voters ].map(([ id, name ]) => { return { id, name }; }); } return { name: answer.name, percentage, voters, voterCount: answer.voters.size }; }); }, [ pollDetails.answers, showDetails ]); const dispatch = useDispatch(); const changeVote = useCallback(() => { dispatch(setVoteChanging(pollId, true)); sendAnalytics(createPollEvent('vote.changed')); }, [ dispatch, pollId ]); const { t } = useTranslation(); return ( ); }; export default AbstractPollResults;