diff --git a/packages/roomkit-react/src/Prebuilt/components/Polls/Voting/QuestionCard.jsx b/packages/roomkit-react/src/Prebuilt/components/Polls/Voting/QuestionCard.jsx index fcedf91f95..0f43aa4f73 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Polls/Voting/QuestionCard.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Polls/Voting/QuestionCard.jsx @@ -1,9 +1,17 @@ // @ts-check import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { match } from 'ts-pattern'; -import { selectLocalPeer, selectLocalPeerRoleName, useHMSActions, useHMSStore } from '@100mslive/react-sdk'; +import { + HMSRoomState, + selectLocalPeer, + selectLocalPeerRoleName, + selectRoomState, + useHMSActions, + useHMSStore, +} from '@100mslive/react-sdk'; import { CheckCircleIcon, ChevronDownIcon, CrossCircleIcon } from '@100mslive/react-icons'; import { Box, Button, Flex, Text } from '../../../../'; +import { isNotNullish } from '../../../../Stats/Stats'; import { checkCorrectAnswer } from '../../../common/utils'; import { MultipleChoiceOptions } from '../common/MultipleChoiceOptions'; import { SingleChoiceOptions } from '../common/SingleChoiceOptions'; @@ -23,11 +31,12 @@ export const QuestionCard = ({ answer, localPeerResponse, updateSavedResponses, + updateUnsavedResponses, rolesThatCanViewResponses, }) => { const actions = useHMSActions(); const localPeer = useHMSStore(selectLocalPeer); - + const roomState = useHMSStore(selectRoomState); const isLocalPeerCreator = localPeer?.id === startedBy; const localPeerRoleName = useHMSStore(selectLocalPeerRoleName); const roleCanViewResponse = @@ -48,7 +57,6 @@ export const QuestionCard = ({ const canRespond = isLive && !localPeerChoice; const startTime = useRef(Date.now()); const isCorrectAnswer = checkCorrectAnswer(answer, localPeerChoice, type); - const [singleOptionAnswer, setSingleOptionAnswer] = useState(); const [multipleOptionAnswer, setMultipleOptionAnswer] = useState(new Set()); const [showOptions, setShowOptions] = useState(true); @@ -73,7 +81,15 @@ export const QuestionCard = ({ options: Array.from(multipleOptionAnswer), duration: Date.now() - startTime.current, }; - await actions.interactivityCenter.addResponsesToPoll(pollID, [submittedResponse]); + if (roomState === HMSRoomState.Connected) { + await actions.interactivityCenter.addResponsesToPoll(pollID, [submittedResponse]); + } else { + updateUnsavedResponses(prev => { + const prevCopy = { ...prev }; + prevCopy[index] = { pollID: pollID, ...submittedResponse }; + return prevCopy; + }); + } updateSavedResponses(prev => { const prevCopy = { ...prev }; prevCopy[index] = { option: singleOptionAnswer, options: Array.from(multipleOptionAnswer) }; @@ -85,9 +101,11 @@ export const QuestionCard = ({ index, singleOptionAnswer, multipleOptionAnswer, + roomState, + updateSavedResponses, actions.interactivityCenter, pollID, - updateSavedResponses, + updateUnsavedResponses, ]); return ( @@ -183,13 +201,21 @@ export const QuestionCard = ({ ) : null} {isLive && ( - + 0 + } + isValidVote={isValidVote} + onVote={handleVote} + response={localPeerChoice} + isQuiz={isQuiz} + /> )} ); }; -const QuestionActions = ({ isValidVote, response, isQuiz, onVote }) => { +const QuestionActions = ({ isValidVote, response, isQuiz, onVote, disableVote }) => { return ( {response ? ( @@ -199,7 +225,7 @@ const QuestionActions = ({ isValidVote, response, isQuiz, onVote }) => { {!isQuiz && !response.skipped ? 'Voted' : null} ) : ( - )} diff --git a/packages/roomkit-react/src/Prebuilt/components/Polls/Voting/StandardVoting.tsx b/packages/roomkit-react/src/Prebuilt/components/Polls/Voting/StandardVoting.tsx index 16a6ef2f46..676af59d2f 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Polls/Voting/StandardVoting.tsx +++ b/packages/roomkit-react/src/Prebuilt/components/Polls/Voting/StandardVoting.tsx @@ -8,10 +8,12 @@ export const StandardView = ({ poll, localPeerResponses, updateSavedResponses, + updateUnsavedResponses, }: { poll: HMSPoll; localPeerResponses: Record; updateSavedResponses: Dispatch>>; + updateUnsavedResponses: Dispatch>>; }) => { if (!poll?.questions) { return null; @@ -25,6 +27,7 @@ export const StandardView = ({ {isQuiz && isStopped ? : null} {poll.questions?.map((question, index) => ( ; updateSavedResponses: Dispatch>>; + updateUnsavedResponses: Dispatch>>; }) => { const [currentIndex, setCurrentIndex] = useState(getIndexToShow(localPeerResponses)); const activeQuestion = poll.questions?.find(question => question.index === currentIndex); @@ -32,6 +34,7 @@ export const TimedView = ({ {poll.questions.map(question => { return attemptedAll || activeQuestion?.index === question.index ? ( v const showSingleView = poll?.type === 'quiz' && poll.state === 'started'; const fetchedInitialResponses = useRef(false); const [savedResponses, setSavedResponses] = useState>({}); + const [unsavedResponses, setUnsavedResponses] = useState>({}); const localPeer = useHMSStore(selectLocalPeer); const localPeerId = localPeer?.id; const customerUserId = localPeer?.customerUserId; - + const roomState = useHMSStore(selectRoomState); // To reset whenever a different poll is opened useEffect(() => { fetchedInitialResponses.current = false; setSavedResponses({}); }, [id, setSavedResponses]); + // To send whenever room is connected back + useEffect(() => { + const handleDisconnectedVote = async () => { + if (unsavedResponses && Object.keys(unsavedResponses).length > 0 && roomState === HMSRoomState.Connected) { + for (const key in unsavedResponses) { + await actions.interactivityCenter.addResponsesToPoll(unsavedResponses[key].pollID, [unsavedResponses[key]]); + } + setUnsavedResponses({}); + } + }; + handleDisconnectedVote(); + }, [actions.interactivityCenter, roomState, setUnsavedResponses, unsavedResponses]); + useEffect(() => { const getResponses = async () => { if (poll && actions.interactivityCenter && !fetchedInitialResponses.current) { @@ -115,9 +131,19 @@ export const Voting = ({ id, toggleVoting }: { id: string; toggleVoting: () => v ) : null} {showSingleView ? ( - + ) : ( - + )}