import React, { useCallback, useMemo } from 'react'; import { useInteractedWidgetOption, useWidgetResultState, useWidgetInteractionActions, useWidgetOptions, useIsWidgetOptionDisabled, } from '../../hooks'; import { WidgetResultState } from '../../types'; import { LLWidgetOption, LLWidgetOptionProps } from './LLWidgetOption'; export type LLWidgetVoteOptionProps = { widgetId: string; optionIndex: number; selectedOptionIndex: number; correctable?: boolean; onOptionChange: (optionIndex: number) => void; OptionComponent?: typeof LLWidgetOption; OptionComponentStyles?: LLWidgetOptionProps['styles']; }; export function LLWidgetVoteOption({ widgetId, optionIndex, selectedOptionIndex: selectedOptionIndexProp, onOptionChange, correctable, OptionComponent = LLWidgetOption, OptionComponentStyles, }: LLWidgetVoteOptionProps) { const { updateWidgetInteractionAction, createWidgetInteractionAction } = useWidgetInteractionActions({ widgetId }); const widgetResultState = useWidgetResultState({ widgetId }); const widgetOptions = useWidgetOptions({ widgetId }); const interactedOption = useInteractedWidgetOption({ widgetId }); const optionDisabled = useIsWidgetOptionDisabled({ widgetId, optionIndex }); const interactedOptionId = interactedOption?.id; const widgetOption = widgetOptions?.[optionIndex]; const widgetOptionId = widgetOption?.id; const selectedOptionIndex = useMemo(() => { // show interactedOption as selected when user has not interacted with any of the option // useful for inital mount of widget where selectedIndex is -1 but user has already interacted // with the widget before. if ( interactedOptionId && widgetOptionId && interactedOptionId === widgetOptionId && selectedOptionIndexProp < 0 ) { return optionIndex; } return selectedOptionIndexProp; }, [ selectedOptionIndexProp, widgetOptionId, interactedOptionId, optionIndex, ]); const votePercentage = useMemo(() => { if (!widgetOptions?.length) { return 0; } const totalVotes = widgetOptions.reduce( (total, option) => option.vote_count + total, 0 ); if (!totalVotes) { return 0; } const percentage = Math.round( (widgetOptions[optionIndex].vote_count / totalVotes) * 100 ); return percentage < 100 ? percentage : 100; }, [widgetOptions, optionIndex]); const onOptionPressHandler = useCallback(() => { onOptionChange(optionIndex); if (interactedOption) { updateWidgetInteractionAction({ interactionItem: widgetOption, }); } else { createWidgetInteractionAction({ interactionItem: widgetOption, }); } }, [ interactedOption, widgetId, widgetOption, optionIndex, selectedOptionIndex, updateWidgetInteractionAction, createWidgetInteractionAction, ]); const showWidgetResult = widgetResultState === WidgetResultState.SHOWN; if (!widgetOptions || !widgetOption) { return undefined; } return ( ); }