Skip to content

Commit

Permalink
fix: custom hook for quiz summary
Browse files Browse the repository at this point in the history
  • Loading branch information
KaustubhKumar05 committed Jan 16, 2024
1 parent f57d331 commit 41045a1
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 84 deletions.
Original file line number Diff line number Diff line change
@@ -1,66 +1,34 @@
import React, { useEffect, useState } from 'react';
import {
HMSQuizLeaderboardResponse,
HMSQuizLeaderboardSummary,
selectPollByID,
useHMSActions,
useHMSStore,
} from '@100mslive/react-sdk';
import React, { useState } from 'react';
import { selectPollByID, useHMSStore } from '@100mslive/react-sdk';
import { ChevronLeftIcon, ChevronRightIcon, CrossIcon } from '@100mslive/react-icons';
import { Box, Flex } from '../../../../Layout';
import { Loading } from '../../../../Loading';
import { Text } from '../../../../Text';
import { LeaderboardEntry } from './LeaderboardEntry';
import { StatisticBox } from './StatisticBox';
import { PeerParticipationSummary } from './PeerParticipationSummary';
// @ts-ignore
import { useSidepaneToggle } from '../../AppData/useSidepane';
// @ts-ignore
import { usePollViewState } from '../../AppData/useUISettings';
import { useQuizSummary } from './useQuizSummary';
// @ts-ignore
import { StatusIndicator } from '../common/StatusIndicator';
import { POLL_VIEWS } from '../../../common/constants';

export const LeaderboardSummary = ({ pollID }: { pollID: string }) => {
const hmsActions = useHMSActions();
const quiz = useHMSStore(selectPollByID(pollID));
const [quizLeaderboard, setQuizLeaderboard] = useState<HMSQuizLeaderboardResponse | undefined>();
const { quizLeaderboard, maxPossibleScore } = useQuizSummary(pollID);
const [viewAllEntries, setViewAllEntries] = useState(false);
const summary: HMSQuizLeaderboardSummary = quizLeaderboard?.summary || {
totalUsers: 0,
votedUsers: 0,
avgScore: 0,
avgTime: 0,
correctAnswers: 0,
};

const { setPollView } = usePollViewState();
const toggleSidepane = useSidepaneToggle();

useEffect(() => {
const fetchLeaderboardData = async () => {
if (!quizLeaderboard && quiz) {
const leaderboardData = await hmsActions.interactivityCenter.fetchLeaderboard(quiz.id, 0, 50);
setQuizLeaderboard(leaderboardData);
}
};
fetchLeaderboardData();
}, [quiz, hmsActions.interactivityCenter, quizLeaderboard]);

if (!quiz || !quizLeaderboard)
return (
<Flex align="center" justify="center" css={{ size: '100%' }}>
<Loading />
</Flex>
);

const defaultCalculations = { maxPossibleScore: 0, totalResponses: 0 };
const { maxPossibleScore, totalResponses } =
quiz.questions?.reduce((accumulator, question) => {
accumulator.maxPossibleScore += question.weight || 0;
accumulator.totalResponses += question?.responses?.length || 0;
return accumulator;
}, defaultCalculations) || defaultCalculations;

const questionCount = quiz.questions?.length || 0;

return (
Expand All @@ -86,27 +54,7 @@ export const LeaderboardSummary = ({ pollID }: { pollID: string }) => {
</Flex>
</Flex>

{!viewAllEntries ? (
<Box css={{ py: '$4' }}>
<Text variant="sm" css={{ fontWeight: '$semiBold' }}>
Participation Summary
</Text>

<Box css={{ my: '$4' }}>
<Flex css={{ w: '100%', gap: '$4' }}>
<StatisticBox
title="Voted"
value={`${summary?.totalUsers ? (100 * summary?.votedUsers) / summary?.totalUsers : 0}%`}
/>
<StatisticBox title="Correct Answers" value={`${summary?.correctAnswers}/${totalResponses}`} />
</Flex>
<Flex css={{ w: '100%', gap: '$4', mt: '$4' }}>
{summary?.avgTime > 0 ? <StatisticBox title="Avg. Time" value={summary?.avgTime} /> : null}
<StatisticBox title="Avg. Score" value={summary?.avgScore} />
</Flex>
</Box>
</Box>
) : null}
{!viewAllEntries ? <PeerParticipationSummary quiz={quiz} /> : null}

<Text variant="sm" css={{ fontWeight: '$semiBold' }}>
Leaderboard
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,38 @@
import React from 'react';
import { HMSPoll, selectLocalPeer, useHMSStore } from '@100mslive/react-sdk';
import { HMSPoll, selectLocalPeerID, useHMSStore } from '@100mslive/react-sdk';
import { Box } from '../../../../Layout';
import { Text } from '../../../../Text';
import { StatisticBox } from './StatisticBox';
// @ts-ignore
import { getPeerParticipationSummary } from '../../../common/utils';
import { useQuizSummary } from './useQuizSummary';

export const PeerParticipationSummary = ({ poll }: { poll: HMSPoll }) => {
const localPeer = useHMSStore(selectLocalPeer);
const { totalResponses, correctResponses, score } = getPeerParticipationSummary(
poll,
localPeer?.id,
localPeer?.customerUserId,
);
export const PeerParticipationSummary = ({ quiz }: { quiz: HMSPoll }) => {
const localPeerId = useHMSStore(selectLocalPeerID);
const { quizLeaderboard, summary } = useQuizSummary(quiz.id);
if (quiz.state !== 'stopped') {
return <></>;
}
const isLocalPeerQuizCreator = localPeerId === quiz.startedBy;
const peerEntry = quizLeaderboard?.entries.find(entry => entry.peer?.peerid === localPeerId);

const boxes = isLocalPeerQuizCreator
? [
{
title: 'Voted',
value: `${summary.totalUsers ? ((100 * summary.votedUsers) / summary.totalUsers).toFixed(2) : 0}% (${
summary.votedUsers
}/${summary.totalUsers})`,
},
{ title: 'Correct Answers', value: summary.correctAnswers },
{ title: 'Avg. Time Taken', value: summary.avgTime },
{ title: 'Avg. Score', value: summary.avgScore },
]
: [
{ title: 'Your rank', value: peerEntry?.position },
{ title: 'Points', value: peerEntry?.score },
{ title: 'Time Taken', value: peerEntry?.duration },
{ title: 'Correct Answers', value: `${peerEntry?.correctResponses}/${peerEntry?.totalResponses}` },
];

const boxes = [
{ title: 'Points', value: score },
{ title: 'Correct Answers', value: `${correctResponses}/${totalResponses}` },
];
return (
<Box>
<Text css={{ fontWeight: '$semiBold', my: '$8' }}>Participation Summary</Text>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const StandardView = ({ poll }: { poll: HMSPoll }) => {

return (
<>
{isQuiz && isStopped ? <PeerParticipationSummary poll={poll} /> : null}
{isQuiz && isStopped ? <PeerParticipationSummary quiz={poll} /> : null}
{poll.questions?.map((question, index) => (
<QuestionCard
pollID={poll.id}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@ import React from 'react';
import { Box } from '../../../../Layout';
import { Text } from '../../../../Text';

export const StatisticBox = ({ title, value = 0 }: { title: string; value: string | number }) => (
<Box css={{ p: '$8', background: '$surface_default', borderRadius: '$1', w: '100%' }}>
<Text
variant="tiny"
css={{ textTransform: 'uppercase', color: '$on_surface_medium', fontWeight: '$semiBold', my: '$4' }}
>
{title}
</Text>
<Text css={{ fontWeight: '$semiBold' }}>{value}</Text>
</Box>
);
export const StatisticBox = ({ title, value = 0 }: { title: string; value: string | number | undefined }) => {
if (!value) {
return <></>;
}
return (
<Box css={{ p: '$8', background: '$surface_default', borderRadius: '$1', w: '100%' }}>
<Text
variant="tiny"
css={{ textTransform: 'uppercase', color: '$on_surface_medium', fontWeight: '$semiBold', my: '$4' }}
>
{title}
</Text>
<Text css={{ fontWeight: '$semiBold' }}>{value}</Text>
</Box>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { useEffect, useState } from 'react';
import {
HMSNotificationTypes,
HMSQuizLeaderboardResponse,
HMSQuizLeaderboardSummary,
selectPollByID,
useHMSActions,
useHMSNotifications,
useHMSStore,
} from '@100mslive/react-sdk';

export const useQuizSummary = (quizID: string) => {
const hmsActions = useHMSActions();
const quiz = useHMSStore(selectPollByID(quizID));
const pollEndNotification = useHMSNotifications(HMSNotificationTypes.POLL_STOPPED);
const [quizLeaderboard, setQuizLeaderboard] = useState<HMSQuizLeaderboardResponse | undefined>();

const summary: HMSQuizLeaderboardSummary = quizLeaderboard?.summary || {
totalUsers: 0,
votedUsers: 0,
avgScore: 0,
avgTime: 0,
correctAnswers: 0,
};

const defaultCalculations = { maxPossibleScore: 0, totalResponses: 0 };

const { maxPossibleScore, totalResponses } =
quiz?.questions?.reduce((accumulator, question) => {
accumulator.maxPossibleScore += question.weight || 0;
accumulator.totalResponses += question?.responses?.length || 0;
return accumulator;
}, defaultCalculations) || defaultCalculations;

useEffect(() => {
const fetchLeaderboardData = async () => {
if (!quizLeaderboard && quiz && quiz?.anonymous && quiz.state === 'stopped') {
const leaderboardData = await hmsActions.interactivityCenter.fetchLeaderboard(quiz.id, 0, 50);
setQuizLeaderboard(leaderboardData);
}
};

if (pollEndNotification) {
fetchLeaderboardData();
}
}, [quiz, hmsActions.interactivityCenter, quizLeaderboard, pollEndNotification]);

return { quizLeaderboard, summary, maxPossibleScore, totalResponses };
};

0 comments on commit 41045a1

Please sign in to comment.