@100mslive/roomkit-react 0.1.8 → 0.1.9-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/dist/{HLSView-DDGPZHA2.js → HLSView-U53QN3AC.js} +3 -3
  2. package/dist/Modal/Dialog.d.ts +402 -1706
  3. package/dist/Prebuilt/App.d.ts +5 -0
  4. package/dist/Prebuilt/AppContext.d.ts +1 -0
  5. package/dist/Prebuilt/AppStateContext.d.ts +16 -0
  6. package/dist/Prebuilt/components/ConferenceScreen.d.ts +2 -0
  7. package/dist/Prebuilt/components/Footer/PollsToggle.d.ts +2 -0
  8. package/dist/Prebuilt/components/LeaveScreen.d.ts +2 -0
  9. package/dist/Prebuilt/components/MwebLandscapePrompt.d.ts +2 -0
  10. package/dist/Prebuilt/components/Notifications/AutoplayBlockedModal.d.ts +2 -0
  11. package/dist/Prebuilt/components/Notifications/HLSFailureModal.d.ts +2 -0
  12. package/dist/Prebuilt/components/Notifications/InitErrorModal.d.ts +2 -0
  13. package/dist/Prebuilt/components/Notifications/Notifications.d.ts +2 -0
  14. package/dist/Prebuilt/components/Notifications/PeerNotifications.d.ts +1 -0
  15. package/dist/Prebuilt/components/Notifications/PermissionErrorModal.d.ts +2 -0
  16. package/dist/Prebuilt/components/Notifications/ReconnectNotifications.d.ts +2 -0
  17. package/dist/Prebuilt/components/Notifications/TrackBulkUnmuteModal.d.ts +2 -0
  18. package/dist/Prebuilt/components/Notifications/TrackNotifications.d.ts +1 -0
  19. package/dist/Prebuilt/components/Notifications/TrackUnmuteModal.d.ts +2 -0
  20. package/dist/Prebuilt/components/Polls/Polls.d.ts +2 -0
  21. package/dist/Prebuilt/components/Preview/PreviewJoin.d.ts +1 -2
  22. package/dist/Prebuilt/components/Preview/PreviewScreen.d.ts +2 -0
  23. package/dist/Prebuilt/components/hooks/useRedirectToLeave.d.ts +1 -1
  24. package/dist/{VirtualBackground-UVZJVOA2.js → VirtualBackground-PMLQPJB6.js} +3 -5
  25. package/dist/{VirtualBackground-UVZJVOA2.js.map → VirtualBackground-PMLQPJB6.js.map} +1 -1
  26. package/dist/chunk-ANQRGVIX.js +14441 -0
  27. package/dist/chunk-ANQRGVIX.js.map +7 -0
  28. package/dist/{chunk-6SQTFOK6.js → chunk-XQ2NRKIW.js} +66 -3
  29. package/dist/{chunk-6SQTFOK6.js.map → chunk-XQ2NRKIW.js.map} +4 -4
  30. package/dist/context/DialogContext.d.ts +6 -0
  31. package/dist/hooks/useDialogContainerSelector.d.ts +1 -0
  32. package/dist/index.cjs.js +10944 -9974
  33. package/dist/index.cjs.js.map +4 -4
  34. package/dist/index.d.ts +1 -0
  35. package/dist/index.js +6 -2
  36. package/dist/meta.cjs.json +3871 -3188
  37. package/dist/meta.esbuild.json +4303 -3728
  38. package/dist/utils/animations.d.ts +11 -0
  39. package/package.json +6 -7
  40. package/src/Modal/Dialog.tsx +31 -3
  41. package/src/Prebuilt/App.tsx +46 -99
  42. package/src/Prebuilt/AppContext.tsx +4 -0
  43. package/src/Prebuilt/AppStateContext.tsx +71 -0
  44. package/src/Prebuilt/common/constants.js +35 -0
  45. package/src/Prebuilt/common/utils.js +47 -0
  46. package/src/Prebuilt/components/AppData/AppData.jsx +5 -0
  47. package/src/Prebuilt/components/AppData/useSidepane.js +23 -1
  48. package/src/Prebuilt/components/AppData/useUISettings.js +48 -4
  49. package/src/Prebuilt/components/{conference.jsx → ConferenceScreen.tsx} +30 -43
  50. package/src/Prebuilt/components/Footer/Footer.tsx +5 -0
  51. package/src/Prebuilt/components/Footer/PaginatedParticipants.tsx +63 -32
  52. package/src/Prebuilt/components/Footer/ParticipantList.jsx +2 -1
  53. package/src/Prebuilt/components/Footer/PollsToggle.tsx +22 -0
  54. package/src/Prebuilt/components/Footer/RoleAccordion.tsx +2 -2
  55. package/src/Prebuilt/components/Header/StreamActions.tsx +5 -3
  56. package/src/Prebuilt/components/Leave/DesktopLeaveRoom.tsx +4 -5
  57. package/src/Prebuilt/components/Leave/LeaveRoom.tsx +0 -4
  58. package/src/Prebuilt/components/{PostLeave.jsx → LeaveScreen.tsx} +6 -13
  59. package/src/Prebuilt/components/MoreSettings/ChangeNameModal.jsx +2 -3
  60. package/src/Prebuilt/components/MoreSettings/EmbedUrl.jsx +2 -3
  61. package/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx +18 -1
  62. package/src/Prebuilt/components/{MwebLandscapePrompt.jsx → MwebLandscapePrompt.tsx} +10 -11
  63. package/src/Prebuilt/components/Notifications/{AutoplayBlockedModal.jsx → AutoplayBlockedModal.tsx} +2 -1
  64. package/src/Prebuilt/components/Notifications/{HLSFailureModal.jsx → HLSFailureModal.tsx} +10 -8
  65. package/src/Prebuilt/components/Notifications/{InitErrorModal.jsx → InitErrorModal.tsx} +5 -2
  66. package/src/Prebuilt/components/Notifications/{Notifications.jsx → Notifications.tsx} +41 -27
  67. package/src/Prebuilt/components/Notifications/{PeerNotifications.jsx → PeerNotifications.tsx} +3 -0
  68. package/src/Prebuilt/components/Notifications/{PermissionErrorModal.jsx → PermissionErrorModal.tsx} +6 -4
  69. package/src/Prebuilt/components/Notifications/{ReconnectNotifications.jsx → ReconnectNotifications.tsx} +11 -6
  70. package/src/Prebuilt/components/Notifications/{TrackBulkUnmuteModal.jsx → TrackBulkUnmuteModal.tsx} +9 -3
  71. package/src/Prebuilt/components/Notifications/{TrackUnmuteModal.jsx → TrackUnmuteModal.tsx} +9 -3
  72. package/src/Prebuilt/components/Notifications/index.tsx +1 -0
  73. package/src/Prebuilt/components/Polls/CreatePollQuiz/PollsQuizMenu.jsx +229 -0
  74. package/src/Prebuilt/components/Polls/CreatePollQuiz/Timer.jsx +71 -0
  75. package/src/Prebuilt/components/Polls/CreateQuestions/CreateQuestions.jsx +132 -0
  76. package/src/Prebuilt/components/Polls/CreateQuestions/DeleteQuestionModal.jsx +66 -0
  77. package/src/Prebuilt/components/Polls/CreateQuestions/QuestionForm.jsx +251 -0
  78. package/src/Prebuilt/components/Polls/CreateQuestions/SavedQuestion.jsx +57 -0
  79. package/src/Prebuilt/components/Polls/Polls.tsx +28 -0
  80. package/src/Prebuilt/components/Polls/Voting/PollResultSummary.jsx +125 -0
  81. package/src/Prebuilt/components/Polls/Voting/QuestionCard.jsx +249 -0
  82. package/src/Prebuilt/components/Polls/Voting/StandardVoting.jsx +40 -0
  83. package/src/Prebuilt/components/Polls/Voting/TimedVoting.jsx +36 -0
  84. package/src/Prebuilt/components/Polls/Voting/Voting.jsx +99 -0
  85. package/src/Prebuilt/components/Polls/common/MultipleChoiceOptions.jsx +101 -0
  86. package/src/Prebuilt/components/Polls/common/OptionInputWithDelete.jsx +25 -0
  87. package/src/Prebuilt/components/Polls/common/SingleChoiceOptions.jsx +125 -0
  88. package/src/Prebuilt/components/Polls/common/StatusIndicator.jsx +47 -0
  89. package/src/Prebuilt/components/Polls/common/VoteCount.jsx +28 -0
  90. package/src/Prebuilt/components/Polls/common/VoteProgress.jsx +17 -0
  91. package/src/Prebuilt/components/Polls/common/VoterList.jsx +22 -0
  92. package/src/Prebuilt/components/Polls/common/Votes.jsx +72 -0
  93. package/src/Prebuilt/components/Preview/PreviewForm.tsx +3 -2
  94. package/src/Prebuilt/components/Preview/PreviewJoin.tsx +32 -27
  95. package/src/Prebuilt/components/Preview/{PreviewContainer.tsx → PreviewScreen.tsx} +2 -19
  96. package/src/Prebuilt/components/RaiseHand.jsx +1 -1
  97. package/src/Prebuilt/components/RoleChangeModal.jsx +2 -3
  98. package/src/Prebuilt/components/RoleChangeRequest/RequestPrompt.tsx +2 -3
  99. package/src/Prebuilt/components/Settings/SettingsModal.jsx +2 -3
  100. package/src/Prebuilt/components/Settings/StartRecording.jsx +15 -4
  101. package/src/Prebuilt/components/SidePaneTabs.tsx +1 -1
  102. package/src/Prebuilt/components/StatsForNerds.jsx +2 -3
  103. package/src/Prebuilt/components/Streaming/Common.jsx +31 -21
  104. package/src/Prebuilt/components/VideoLayouts/ScreenshareLayout.tsx +8 -9
  105. package/src/Prebuilt/components/VideoTile.jsx +37 -33
  106. package/src/Prebuilt/components/hooks/useAutoStartStreaming.tsx +3 -3
  107. package/src/Prebuilt/components/hooks/useRedirectToLeave.tsx +9 -17
  108. package/src/Prebuilt/components/pdfAnnotator/pdfFileOptions.jsx +2 -3
  109. package/src/Prebuilt/components/pdfAnnotator/submitPdf.jsx +1 -1
  110. package/src/Prebuilt/components/pdfAnnotator/uploadedFile.jsx +2 -3
  111. package/src/Prebuilt/layouts/EmbedView.jsx +47 -60
  112. package/src/Prebuilt/layouts/PDFView.jsx +49 -99
  113. package/src/Prebuilt/layouts/SidePane.tsx +8 -4
  114. package/src/Prebuilt/layouts/VideoStreamingSection.tsx +2 -2
  115. package/src/Prebuilt/primitives/DialogContent.jsx +4 -5
  116. package/src/context/DialogContext.tsx +13 -0
  117. package/src/hooks/useDialogContainerSelector.tsx +7 -0
  118. package/src/index.ts +1 -0
  119. package/src/utils/animations.ts +6 -0
  120. package/dist/Prebuilt/components/Notifications/HeadlessEndRoomListener.d.ts +0 -2
  121. package/dist/Prebuilt/components/PrebuiltDialogPortal.d.ts +0 -4
  122. package/dist/Prebuilt/components/PrebuiltTileElements.d.ts +0 -2198
  123. package/dist/Prebuilt/components/Preview/PreviewContainer.d.ts +0 -3
  124. package/dist/chunk-HUMNPIYI.js +0 -70
  125. package/dist/chunk-HUMNPIYI.js.map +0 -7
  126. package/dist/chunk-PRM33R4R.js +0 -7160
  127. package/dist/chunk-PRM33R4R.js.map +0 -7
  128. package/dist/conference-N7S47TDK.js +0 -6602
  129. package/dist/conference-N7S47TDK.js.map +0 -7
  130. package/src/Prebuilt/components/GoLiveButton.jsx +0 -42
  131. package/src/Prebuilt/components/Notifications/HeadlessEndRoomListener.tsx +0 -23
  132. package/src/Prebuilt/components/PrebuiltDialogPortal.tsx +0 -6
  133. package/src/Prebuilt/components/PrebuiltTileElements.tsx +0 -5
  134. package/src/Prebuilt/components/Streaming/HLSStreaming.jsx +0 -220
  135. package/src/Prebuilt/components/Streaming/RTMPStreaming.jsx +0 -334
  136. package/src/Prebuilt/components/Streaming/StreamingLanding.jsx +0 -76
  137. /package/dist/{HLSView-DDGPZHA2.js.map → HLSView-U53QN3AC.js.map} +0 -0
  138. /package/{src/Prebuilt/components/Notifications/index.jsx → dist/Prebuilt/components/Notifications/index.d.ts} +0 -0
  139. /package/src/Prebuilt/components/Notifications/{TrackNotifications.jsx → TrackNotifications.tsx} +0 -0
@@ -0,0 +1,251 @@
1
+ // @ts-check
2
+ import React, { useCallback, useRef, useState } from 'react';
3
+ import { AddCircleIcon, TrashIcon } from '@100mslive/react-icons';
4
+ import { Box, Button, Dropdown, Flex, Input, Switch, Text, Tooltip } from '../../../../';
5
+ import { DialogDropdownTrigger } from '../../../primitives/DropdownTrigger';
6
+ import { DeleteQuestionModal } from './DeleteQuestionModal';
7
+ import { useDropdownSelection } from '../../hooks/useDropdownSelection';
8
+ import { isValidTextInput } from '../../../common/utils';
9
+ import { MultipleChoiceOptionInputs } from '../common/MultipleChoiceOptions';
10
+ import { SingleChoiceOptionInputs } from '../common/SingleChoiceOptions';
11
+ import { QUESTION_TYPE, QUESTION_TYPE_TITLE } from '../../../common/constants';
12
+
13
+ export const QuestionForm = ({ question, index, length, onSave, removeQuestion, isQuiz }) => {
14
+ const ref = useRef(null);
15
+ const selectionBg = useDropdownSelection();
16
+ const [openDelete, setOpenDelete] = useState(false);
17
+ const [open, setOpen] = useState(false);
18
+ const [type, setType] = useState(question.type || QUESTION_TYPE.SINGLE_CHOICE);
19
+ const [text, setText] = useState(question.text);
20
+ const [options, setOptions] = useState(
21
+ question?.options || [
22
+ { text: '', isCorrectAnswer: false },
23
+ { text: '', isCorrectAnswer: false },
24
+ ],
25
+ );
26
+ const [skippable, setSkippable] = useState(false);
27
+ const isValid = isValidQuestion({
28
+ text,
29
+ type,
30
+ options,
31
+ isQuiz,
32
+ });
33
+
34
+ const handleOptionTextChange = useCallback(
35
+ (index, text) => {
36
+ setOptions(options => [...options.slice(0, index), { ...options[index], text }, ...options.slice(index + 1)]);
37
+ },
38
+ [setOptions],
39
+ );
40
+
41
+ const removeOption = useCallback(
42
+ index =>
43
+ setOptions(options => {
44
+ const newOptions = [...options];
45
+ newOptions.splice(index, 1);
46
+ return newOptions;
47
+ }),
48
+ [setOptions],
49
+ );
50
+
51
+ const selectSingleChoiceAnswer = useCallback(
52
+ answerIndex => {
53
+ if (!isQuiz) {
54
+ return;
55
+ }
56
+ setOptions(options =>
57
+ options.map((option, index) => ({
58
+ ...option,
59
+ isCorrectAnswer: index === answerIndex,
60
+ })),
61
+ );
62
+ },
63
+ [setOptions, isQuiz],
64
+ );
65
+
66
+ const selectMultipleChoiceAnswer = useCallback(
67
+ (checked, index) => {
68
+ if (!isQuiz) {
69
+ return;
70
+ }
71
+ setOptions(options => [
72
+ ...options.slice(0, index),
73
+ { ...options[index], isCorrectAnswer: checked },
74
+ ...options.slice(index + 1),
75
+ ]);
76
+ },
77
+ [setOptions, isQuiz],
78
+ );
79
+
80
+ return (
81
+ <>
82
+ <Text variant="overline" css={{ c: '$on_surface_low', textTransform: 'uppercase' }}>
83
+ Question {index + 1} of {length}
84
+ </Text>
85
+ <Text variant="body2" css={{ mt: '$4', mb: '$md' }}>
86
+ Question Type
87
+ </Text>
88
+ <Dropdown.Root open={open} onOpenChange={setOpen}>
89
+ <DialogDropdownTrigger
90
+ ref={ref}
91
+ title={QUESTION_TYPE_TITLE[type]}
92
+ css={{
93
+ backgroundColor: '$surface_bright',
94
+ border: '1px solid $border_bright',
95
+ }}
96
+ open={open}
97
+ />
98
+ <Dropdown.Portal>
99
+ <Dropdown.Content align="start" sideOffset={8} css={{ w: ref.current?.clientWidth, zIndex: 1000 }}>
100
+ {Object.keys(QUESTION_TYPE_TITLE).map(value => {
101
+ return (
102
+ <Dropdown.Item
103
+ key={value}
104
+ onSelect={() => setType(value)}
105
+ css={{
106
+ px: '$9',
107
+ bg: type === value ? selectionBg : undefined,
108
+ }}
109
+ >
110
+ {QUESTION_TYPE_TITLE[value]}
111
+ </Dropdown.Item>
112
+ );
113
+ })}
114
+ </Dropdown.Content>
115
+ </Dropdown.Portal>
116
+ </Dropdown.Root>
117
+ <Input
118
+ placeholder="Ask a question"
119
+ css={{
120
+ mt: '$md',
121
+ backgroundColor: '$surface_bright',
122
+ border: '1px solid $border_bright',
123
+ }}
124
+ type="text"
125
+ value={text}
126
+ onChange={event => setText(event.target.value)}
127
+ />
128
+ {type === QUESTION_TYPE.SINGLE_CHOICE || type === QUESTION_TYPE.MULTIPLE_CHOICE ? (
129
+ <>
130
+ <Text variant="body2" css={{ my: '$6', c: '$on_surface_medium' }}>
131
+ Options
132
+ </Text>
133
+
134
+ {isQuiz && (
135
+ <Text variant="xs" css={{ c: '$on_surface_medium', mb: '$md' }}>
136
+ {type === QUESTION_TYPE.SINGLE_CHOICE
137
+ ? 'Use the radio buttons to indicate the correct answer'
138
+ : 'Use the checkboxes to indicate the correct answer(s)'}
139
+ </Text>
140
+ )}
141
+
142
+ {type === QUESTION_TYPE.SINGLE_CHOICE && (
143
+ <SingleChoiceOptionInputs
144
+ isQuiz={isQuiz}
145
+ options={options}
146
+ selectAnswer={selectSingleChoiceAnswer}
147
+ handleOptionTextChange={handleOptionTextChange}
148
+ removeOption={removeOption}
149
+ />
150
+ )}
151
+
152
+ {type === QUESTION_TYPE.MULTIPLE_CHOICE && (
153
+ <MultipleChoiceOptionInputs
154
+ isQuiz={isQuiz}
155
+ options={options}
156
+ selectAnswer={selectMultipleChoiceAnswer}
157
+ handleOptionTextChange={handleOptionTextChange}
158
+ removeOption={removeOption}
159
+ />
160
+ )}
161
+
162
+ {options?.length < 20 && (
163
+ <Flex
164
+ css={{
165
+ c: '$on_surface_medium',
166
+ cursor: 'pointer',
167
+ '&:hover': { c: '$on_surface_high' },
168
+ }}
169
+ onClick={() => setOptions([...options, { text: '', isCorrectAnswer: false }])}
170
+ >
171
+ <AddCircleIcon style={{ position: 'relative', left: '-2px' }} />
172
+
173
+ <Text
174
+ variant="body1"
175
+ css={{
176
+ ml: '$4',
177
+ c: 'inherit',
178
+ }}
179
+ >
180
+ Add an option
181
+ </Text>
182
+ </Flex>
183
+ )}
184
+ {isQuiz ? (
185
+ <Flex css={{ mt: '$md', gap: '$6' }}>
186
+ <Switch defaultChecked={skippable} onCheckedChange={checked => setSkippable(checked)} />
187
+ <Text variant="sm" css={{ color: '$on_surface_medium' }}>
188
+ Not required to answer
189
+ </Text>
190
+ </Flex>
191
+ ) : null}
192
+ </>
193
+ ) : null}
194
+
195
+ <Flex justify="between" align="center" css={{ mt: '$12' }}>
196
+ <Box
197
+ css={{
198
+ color: '$on_surface_medium',
199
+ cursor: 'pointer',
200
+ '&:hover': { color: '$on_surface_high' },
201
+ }}
202
+ >
203
+ <TrashIcon onClick={() => setOpenDelete(!open)} />
204
+ </Box>
205
+ <Tooltip
206
+ disabled={isValid}
207
+ title={`Please fill all the fields ${isQuiz ? 'and mark the correct answer(s)' : ''} to continue`}
208
+ boxCss={{ maxWidth: '$40' }}
209
+ >
210
+ <Button
211
+ variant="standard"
212
+ disabled={!isValid}
213
+ onClick={() => {
214
+ onSave({
215
+ saved: true,
216
+ text,
217
+ type,
218
+ options,
219
+ skippable,
220
+ draftID: question.draftID,
221
+ });
222
+ }}
223
+ >
224
+ Save
225
+ </Button>
226
+ </Tooltip>
227
+ </Flex>
228
+
229
+ <DeleteQuestionModal open={openDelete} setOpen={setOpenDelete} removeQuestion={removeQuestion} />
230
+ </>
231
+ );
232
+ };
233
+
234
+ export const isValidQuestion = ({ text, type, options, isQuiz = false }) => {
235
+ if (!isValidTextInput(text) || !type) {
236
+ return false;
237
+ }
238
+
239
+ if (![QUESTION_TYPE.SINGLE_CHOICE, QUESTION_TYPE.MULTIPLE_CHOICE].includes(type)) {
240
+ return true;
241
+ }
242
+
243
+ const everyOptionHasText = options.every(option => option && isValidTextInput(option.text, 1));
244
+ const hasCorrectAnswer = options.some(option => option.isCorrectAnswer);
245
+
246
+ if (!isQuiz) {
247
+ return everyOptionHasText;
248
+ }
249
+
250
+ return everyOptionHasText && hasCorrectAnswer;
251
+ };
@@ -0,0 +1,57 @@
1
+ // @ts-check
2
+ import React, { useState } from 'react';
3
+ import { CheckCircleIcon, TrashIcon } from '@100mslive/react-icons';
4
+ import { Box, Button, Flex, Text } from '../../../../';
5
+ import { DeleteQuestionModal } from './DeleteQuestionModal';
6
+ import { QUESTION_TYPE_TITLE } from '../../../common/constants';
7
+
8
+ export const SavedQuestion = ({ question, index, length, convertToDraft, removeQuestion }) => {
9
+ const [openDeleteModal, setOpenDeleteModal] = useState(false);
10
+ return (
11
+ <>
12
+ <Text variant="overline" css={{ c: '$on_surface_low', textTransform: 'uppercase' }}>
13
+ Question {index + 1} of {length}: {QUESTION_TYPE_TITLE[question.type]}
14
+ </Text>
15
+ <Text variant="body2" css={{ mt: '$4', mb: '$md' }}>
16
+ {question.text}
17
+ </Text>
18
+ {question.options.map(option => (
19
+ <Flex css={{ alignItems: 'center', my: '$xs' }}>
20
+ <Text variant="body2" css={{ c: '$on_surface_medium' }}>
21
+ {option.text}
22
+ </Text>
23
+ {option.isCorrectAnswer && (
24
+ <Flex css={{ color: '$alert_success', mx: '$xs' }}>
25
+ <CheckCircleIcon height={24} width={24} />
26
+ </Flex>
27
+ )}
28
+ </Flex>
29
+ ))}
30
+ {question.skippable ? (
31
+ <Text variant="sm" css={{ color: '$on_surface_low', my: '$md' }}>
32
+ Not required to answer
33
+ </Text>
34
+ ) : null}
35
+ <Flex justify="between" css={{ w: '100%', alignItems: 'center' }}>
36
+ <Box
37
+ onClick={() => setOpenDeleteModal(true)}
38
+ css={{ color: '$on_surface_low', '&:hover': { color: '$on_surface_medium', cursor: 'pointer' } }}
39
+ >
40
+ <TrashIcon />
41
+ </Box>
42
+ <Button
43
+ variant="standard"
44
+ css={{ fontWeight: '$semiBold', p: '$4 $8' }}
45
+ onClick={() => convertToDraft(question.draftID)}
46
+ >
47
+ Edit
48
+ </Button>
49
+ </Flex>
50
+ <DeleteQuestionModal
51
+ removeQuestion={() => removeQuestion(question.draftID)}
52
+ open={openDeleteModal}
53
+ setOpen={setOpenDeleteModal}
54
+ />
55
+ </>
56
+ );
57
+ };
@@ -0,0 +1,28 @@
1
+ import React from 'react';
2
+ // @ts-ignore: No implicit Any
3
+ import { PollsQuizMenu } from './CreatePollQuiz/PollsQuizMenu';
4
+ // @ts-ignore: No implicit Any
5
+ import { CreateQuestions } from './CreateQuestions/CreateQuestions';
6
+ // @ts-ignore: No implicit Any
7
+ import { Voting } from './Voting/Voting';
8
+ // @ts-ignore: No implicit Any
9
+ import { usePollViewToggle } from '../AppData/useSidepane';
10
+ // @ts-ignore: No implicit Any
11
+ import { usePollViewState } from '../AppData/useUISettings';
12
+ // @ts-ignore: No implicit Any
13
+ import { POLL_VIEWS } from '../../common/constants';
14
+
15
+ export const Polls = () => {
16
+ const togglePollView = usePollViewToggle();
17
+ const { pollInView: pollID, view } = usePollViewState();
18
+
19
+ if (view === POLL_VIEWS.CREATE_POLL_QUIZ) {
20
+ return <PollsQuizMenu />;
21
+ } else if (view === POLL_VIEWS.CREATE_QUESTIONS) {
22
+ return <CreateQuestions />;
23
+ } else if (view === POLL_VIEWS.VOTE) {
24
+ return <Voting toggleVoting={togglePollView} id={pollID} />;
25
+ } else {
26
+ return null;
27
+ }
28
+ };
@@ -0,0 +1,125 @@
1
+ // @ts-check
2
+ import React, { useMemo } from 'react';
3
+ import { selectLocalPeerID, useHMSStore } from '@100mslive/react-sdk';
4
+ import { Box, Text } from '../../../../';
5
+ import { checkCorrectAnswer } from '../../../common/utils';
6
+
7
+ /**
8
+ * @param {{ isQuiz: boolean;
9
+ * isAdmin: boolean;
10
+ * pollResult: import("@100mslive/react-sdk").HMSPoll['result'];
11
+ * questions: import("@100mslive/react-sdk").HMSPoll['questions'] }} param0
12
+ */
13
+ export const PollResultSummary = ({ isQuiz, isAdmin, pollResult, questions }) => {
14
+ const localPeerID = useHMSStore(selectLocalPeerID);
15
+ const noAnswers = pollResult?.maxUsers || 0 - (pollResult?.totalUsers || 0);
16
+ const participationPercentage =
17
+ pollResult?.maxUsers && pollResult?.maxUsers > 0 ? ((pollResult?.totalUsers || 0) * 100) / pollResult.maxUsers : 0;
18
+
19
+ const totalCorrectAnswers = useMemo(() => {
20
+ let correctAnswers = 0;
21
+ questions?.forEach(question => {
22
+ correctAnswers += question.result?.correctResponses || 0;
23
+ });
24
+ return correctAnswers;
25
+ }, [questions]);
26
+
27
+ const totalIncorrectAnswers = useMemo(() => {
28
+ let incorrectAnswers = 0;
29
+ questions?.forEach(question => {
30
+ incorrectAnswers +=
31
+ (question.result?.totalResponses || 0) -
32
+ (question.result?.correctResponses || 0) -
33
+ (question.result?.skippedCount || 0);
34
+ });
35
+ return incorrectAnswers;
36
+ }, [questions]);
37
+
38
+ const localCorrectAnswers = useMemo(() => {
39
+ let correctAnswers = 0;
40
+ questions?.forEach(question => {
41
+ const localResponse = question.responses?.find(response => response.peer?.peerid === localPeerID);
42
+ if (checkCorrectAnswer(question.answer, localResponse, question.type)) {
43
+ correctAnswers++;
44
+ }
45
+ });
46
+ return correctAnswers;
47
+ }, [localPeerID, questions]);
48
+
49
+ const localIncorrectAnswers = useMemo(() => {
50
+ let incorrectAnswers = 0;
51
+ questions?.forEach(question => {
52
+ const localResponse = question.responses?.find(response => response.peer?.peerid === localPeerID);
53
+ if (!checkCorrectAnswer(question.answer, localResponse, question.type) && localResponse) {
54
+ incorrectAnswers++;
55
+ }
56
+ });
57
+ return incorrectAnswers;
58
+ }, [localPeerID, questions]);
59
+
60
+ if (!pollResult) {
61
+ return null;
62
+ }
63
+
64
+ let StatsComponents;
65
+
66
+ if (isQuiz && isAdmin) {
67
+ StatsComponents = (
68
+ <>
69
+ <PollStat label="No. of correct answers" value={totalCorrectAnswers} />
70
+ <PollStat label="No. of wrong answerss" value={totalIncorrectAnswers} />
71
+ <PollStat label="Peers who didn't answer" value={noAnswers} />
72
+ <PollStat label="Participation Percentage" value={participationPercentage.toFixed(2) + '%'} />
73
+ </>
74
+ );
75
+ } else if (isQuiz && !isAdmin) {
76
+ StatsComponents = (
77
+ <>
78
+ <PollStat label="No. of correct answers" value={localCorrectAnswers} />
79
+ <PollStat label="No. of wrong answers" value={localIncorrectAnswers} />
80
+ </>
81
+ );
82
+ } else if (!isQuiz && isAdmin) {
83
+ StatsComponents = (
84
+ <>
85
+ <PollStat label="Peers who didn't answer" value={noAnswers} />
86
+ <PollStat label="Participation Percentage" value={participationPercentage.toFixed(2) + '%'} />
87
+ </>
88
+ );
89
+ } else {
90
+ return null;
91
+ }
92
+
93
+ return (
94
+ <Box
95
+ css={{
96
+ display: 'grid',
97
+ 'grid-template-columns': 'repeat(2, 2fr)',
98
+ gap: '$4',
99
+ mt: '$3',
100
+ }}
101
+ >
102
+ {StatsComponents}
103
+ </Box>
104
+ );
105
+ };
106
+
107
+ const PollStat = ({ label, value }) => {
108
+ return (
109
+ <Box css={{ bg: '$surface_bright', p: '$8', r: '$1' }}>
110
+ <Text
111
+ variant="overline"
112
+ css={{
113
+ fontWeight: '$semiBold',
114
+ color: '$on_surface_medium',
115
+ textTransform: 'uppercase',
116
+ }}
117
+ >
118
+ {label}
119
+ </Text>
120
+ <Text variant="sub1" css={{ fontWeight: '$semiBold', color: '$on_surface_medium' }}>
121
+ {value}
122
+ </Text>
123
+ </Box>
124
+ );
125
+ };