@pocketprep/ui-kit 3.4.89 → 3.5.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 (28) hide show
  1. package/dist/@pocketprep/ui-kit.js +14834 -16036
  2. package/dist/@pocketprep/ui-kit.js.map +1 -1
  3. package/dist/@pocketprep/ui-kit.umd.cjs +12 -12
  4. package/dist/@pocketprep/ui-kit.umd.cjs.map +1 -1
  5. package/dist/style.css +1 -1
  6. package/lib/components/Bundles/BundleSearch.vue +41 -11
  7. package/lib/components/Pagination/QuestionReviewPagination.vue +21 -19
  8. package/lib/components/Quiz/Question/ChoicesContainer.vue +95 -129
  9. package/lib/components/Quiz/Question/DropdownExplanation.vue +39 -53
  10. package/lib/components/Quiz/Question/Explanation.vue +47 -57
  11. package/lib/components/Quiz/Question/MatrixChoicesContainer.vue +211 -224
  12. package/lib/components/Quiz/Question/MatrixRadioGroup.vue +5 -4
  13. package/lib/components/Quiz/Question/MobileMatrixChoicesContainer.vue +321 -319
  14. package/lib/components/Quiz/Question/MobileMatrixRadioGroup.vue +7 -6
  15. package/lib/components/Quiz/Question/PassageAndImage.vue +32 -43
  16. package/lib/components/Quiz/Question/PassageAndImageDropdown.vue +32 -43
  17. package/lib/components/Quiz/Question/Paywall.vue +28 -39
  18. package/lib/components/Quiz/Question/QuestionContext.vue +23 -31
  19. package/lib/components/Quiz/Question/StatsSummary.vue +10 -20
  20. package/lib/components/Quiz/Question/Summary.vue +54 -64
  21. package/lib/components/Quiz/Question/composables.ts +71 -0
  22. package/lib/components/Quiz/Question/injectionSymbols.ts +69 -0
  23. package/lib/components/Quiz/Question.vue +788 -988
  24. package/lib/components/Quiz/QuizContainer.vue +36 -34
  25. package/lib/components/Quiz/question.d.ts +4 -4
  26. package/lib/directives.ts +27 -22
  27. package/lib/styles/_breakpoints.scss +6 -12
  28. package/package.json +4 -4
@@ -13,14 +13,14 @@
13
13
 
14
14
  }"
15
15
  v-dark="isDarkMode"
16
- v-breakpoint:questionEl="breakpoints"
16
+ v-breakpoint="breakpointsWithEl"
17
17
  >
18
18
  <div
19
19
  class="uikit-question-mobile-matrix-choices-container__row-container"
20
20
  v-for="(rowLabel, rowIndex) in matrixRowLabels"
21
21
  :key="rowIndex"
22
22
  v-dark="isDarkMode"
23
- v-breakpoint:questionEl="breakpoints"
23
+ v-breakpoint="breakpointsWithEl"
24
24
  >
25
25
  <div
26
26
  class="uikit-question-mobile-matrix-choices-container__row"
@@ -29,7 +29,7 @@
29
29
  expandedRowNumbers.includes(rowIndex),
30
30
  }"
31
31
  v-dark="isDarkMode"
32
- v-breakpoint:questionEl="breakpoints"
32
+ v-breakpoint="breakpointsWithEl"
33
33
  @click.stop="toggleChoiceDropdown(rowIndex)"
34
34
  >
35
35
  <Icon
@@ -71,20 +71,13 @@
71
71
  v-for="(colHeader, colHeaderIndex) in selectedColumnHeaders"
72
72
  :key="colHeaderIndex"
73
73
  >
74
- <template v-if="
75
- selectedColumnHeaders &&
76
- selectedColumnHeaders[rowIndex] &&
77
- selectedColumnHeaders[rowIndex][colHeaderIndex]">
74
+ <template v-if="doesSelectedColumnHeaderExist(rowIndex, colHeaderIndex)">
78
75
  <div
79
76
  class="uikit-question-mobile-matrix-choices-container__selected-choice-labels"
80
77
  v-dark="isDarkMode"
81
- v-breakpoint:questionEl="breakpoints"
78
+ v-breakpoint="breakpointsWithEl"
82
79
  >
83
- {{ selectedColumnHeaders[rowIndex][colHeaderIndex] ===
84
- selectedColumnHeaders[rowIndex][selectedColumnHeaders[rowIndex].length - 1] ?
85
- stripHtmlTags(selectedColumnHeaders[rowIndex][colHeaderIndex]) :
86
- `${stripHtmlTags(selectedColumnHeaders[rowIndex][colHeaderIndex])},`
87
- }}
80
+ {{ getSelectedChoiceLabels(rowIndex, colHeaderIndex) }}
88
81
  </div>
89
82
  </template>
90
83
  </div>
@@ -117,7 +110,7 @@
117
110
  />
118
111
  <Checkbox
119
112
  v-else
120
- :model-value="matrixCheckboxGrid[rowIndex][columnIndex]"
113
+ :model-value="matrixCheckboxGrid[rowIndex]?.[columnIndex]"
121
114
  :is-dark-mode="isDarkMode"
122
115
  :disabled="showMatrixAnswers || reviewMode"
123
116
  :checkbox-styles="checkboxContainerStyling(rowIndex, columnIndex)"
@@ -128,8 +121,8 @@
128
121
  :class="{
129
122
  'uikit-question-mobile-matrix-choices-container__checkbox-label--distractor':
130
123
  (showMatrixAnswers || reviewMode) &&
131
- matrixChoiceLayout[rowIndex] &&
132
- matrixChoiceLayout[rowIndex][columnIndex]?.startsWith('d'),
124
+ matrixChoiceLayout?.[rowIndex] &&
125
+ matrixChoiceLayout?.[rowIndex]?.[columnIndex]?.startsWith('d'),
133
126
  }"
134
127
  >
135
128
  {{ stripHtmlTags(column) }}
@@ -151,7 +144,6 @@
151
144
  :matrix-answer-keys="matrixAnswerKeys"
152
145
  :is-dark-mode="isDarkMode"
153
146
  :question-el="questionEl"
154
- :breakpoints="breakpoints"
155
147
  :disabled="false"
156
148
  @update:modelValue="updateRadioRowSelection(rowIndex, $event)"
157
149
  />
@@ -161,389 +153,399 @@
161
153
  </div>
162
154
  </template>
163
155
 
164
- <script lang="ts">
165
- import { Component, Vue, Prop, Emit, Watch } from 'vue-facing-decorator'
156
+ <script setup lang="ts">
166
157
  import Icon from '../../Icons/Icon.vue'
167
- import PocketButton from '../../Buttons/Button.vue'
168
158
  import Checkbox from '../../Forms/Checkbox.vue'
169
159
  import MobileMatrixRadioGroup from './MobileMatrixRadioGroup.vue'
170
- import { dark, breakpoint } from '../../../directives'
171
- import type { TBreakPointsObject, IRadioOptions, TMatrixChoiceKey } from './../question'
172
- import type { Study } from '@pocketprep/types'
160
+ import { dark as vDark, breakpoint as vBreakpoint } from '../../../directives'
161
+ import { useQuestionContext } from './composables'
162
+ import type { IRadioOptions, TMatrixChoiceKey } from './../question'
173
163
  import BrandColors from '../../../pocketprep-export.module.scss'
164
+ import { computed, onMounted, ref, watch } from 'vue'
165
+
166
+ const emit = defineEmits<{
167
+ 'emitSelectedMatrixChoice': [matrixChoiceKeys: TMatrixChoiceKey[]]
168
+ }>()
169
+
170
+ const {
171
+ // questionEl is used by the breakpoint directive
172
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
173
+ questionEl,
174
+ question,
175
+ isMatrixQuestionCorrect,
176
+ reviewMode,
177
+ isDarkMode,
178
+ breakpointsWithEl,
179
+ showMatrixAnswers,
180
+ matrixAnswerKeys,
181
+ selectedMatrixChoices,
182
+ } = useQuestionContext()
183
+
184
+ const matrixCheckboxGrid = ref<boolean[][] | undefined>(undefined)
185
+ const matrixRadioGrid = ref<IRadioOptions[] | undefined>(undefined)
186
+ const expandedRowNumbers = ref<number[]>([])
187
+ const selectedColumnHeaders = ref<string[][]>([])
188
+ const brandColors = BrandColors
189
+
190
+ const stripHtmlTags = (string?: string) => {
191
+ if (string) {
192
+ const div = document.createElement('div')
193
+ div.innerHTML = string
194
+ return div.textContent || ''
195
+ }
196
+ return ''
197
+ }
198
+
199
+ const matrixChoiceLayout = computed(() => {
200
+ return question.value.matrixChoiceLayout
201
+ })
174
202
 
175
- @Component({
176
- components: {
177
- Icon,
178
- Checkbox,
179
- PocketButton,
180
- MobileMatrixRadioGroup,
181
- },
182
- directives: {
183
- dark,
184
- breakpoint,
185
- },
203
+ const defaultCheckboxGrid = computed(() => {
204
+ return matrixChoiceLayout.value?.map(row => {
205
+ const choiceRow = row.map(() => false)
206
+ return choiceRow
207
+ })
186
208
  })
187
- export default class MobileMatrixChoicesContainer extends Vue {
188
- @Prop({ default: false }) reviewMode!: boolean
189
- @Prop({ default: false }) isDarkMode!: boolean
190
- @Prop({ default: null }) questionEl!: Element | null
191
- @Prop({ default: {
192
- 'mobile': 767,
193
- 'tablet-portrait': 1023,
194
- 'tablet-landscape': 1439,
195
- } }) breakpoints!: TBreakPointsObject
196
- @Prop() question!: Study.Class.QuestionJSON
197
- @Prop() matrixChoiceLayout!: string[][]
198
- @Prop({ default: false }) showMatrixAnswers!: boolean
199
- @Prop({ default: false }) isUnanswered!: boolean
200
- @Prop({ default: false }) isMatrixQuestionCorrect!: boolean
201
- @Prop() matrixAnswerKeys!: TMatrixChoiceKey[]
202
- @Prop() matrixDistractorKeys!: TMatrixChoiceKey[]
203
- @Prop() selectedMatrixChoices!: TMatrixChoiceKey[]
204
- @Prop() matrixChoices!: TMatrixChoiceKey[]
205
-
206
- matrixCheckboxGrid: boolean[][] | undefined = undefined
207
- matrixRadioGrid: IRadioOptions[] | undefined = undefined
208
- expandedRowNumbers: number[] = []
209
- selectedColumnHeaders: string[][] = []
210
- brandColors = BrandColors
211
-
212
- stripHtmlTags (string?: string) {
213
- if (string) {
214
- const div = document.createElement('div')
215
- div.innerHTML = string
216
- return div.textContent || ''
209
+
210
+ const defaultRadioButtonGrid = computed(() => {
211
+ return matrixChoiceLayout.value?.map(row => {
212
+ return {
213
+ choices: row as TMatrixChoiceKey[],
214
+ value: null as TMatrixChoiceKey | null,
217
215
  }
218
- return ''
219
- }
216
+ })
217
+ })
220
218
 
221
- get defaultCheckboxGrid () {
222
- return this.matrixChoiceLayout?.map(row => {
223
- const choiceRow = row.map(() => false)
224
- return choiceRow
225
- })
226
- }
219
+ const matrixRowLabels = computed(() => {
220
+ return question.value.matrixLabels?.rows
221
+ })
227
222
 
228
- get defaultRadioButtonGrid () {
229
- return this.matrixChoiceLayout?.map(row => {
230
- return {
231
- choices: row as TMatrixChoiceKey[],
232
- value: null as TMatrixChoiceKey | null,
233
- }
234
- })
235
- }
223
+ const matrixColumnLabels = computed(() => {
224
+ return question.value.matrixLabels?.columns
225
+ })
236
226
 
237
- get matrixRowLabels () {
238
- return this.question.matrixLabels?.rows
227
+ onMounted(() => {
228
+ if (question.value.type === 'Matrix Checkbox') {
229
+ matrixCheckboxGrid.value = convertSelectedMatrixChoiceToCheckboxGrid()
239
230
  }
240
231
 
241
- get matrixColumnLabels () {
242
- return this.question.matrixLabels?.columns
232
+ if (question.value.type === 'Matrix Radio Button') {
233
+ matrixRadioGrid.value = convertSelectedMatrixChoiceToRadioBtnGrid()
243
234
  }
244
235
 
245
- mounted () {
246
- if (this.question.type === 'Matrix Checkbox') {
247
- this.matrixCheckboxGrid = this.convertSelectedMatrixChoiceToCheckboxGrid()
248
- }
236
+ question.value.matrixChoiceLayout?.forEach(() => {
237
+ selectedColumnHeaders.value.push([])
238
+ })
239
+ })
249
240
 
250
- if (this.question.type === 'Matrix Radio Button') {
251
- this.matrixRadioGrid = this.convertSelectedMatrixChoiceToRadioBtnGrid()
252
- }
241
+ const toggleChoiceDropdown = (rowIndex: number) => {
242
+ const includedRowNumberIndex = expandedRowNumbers.value.findIndex(row => row === rowIndex)
243
+ if (includedRowNumberIndex === -1) {
244
+ expandedRowNumbers.value.push(rowIndex)
245
+ } else {
246
+ expandedRowNumbers.value.splice(includedRowNumberIndex, 1)
247
+ }
248
+ }
253
249
 
254
- this.question.matrixChoiceLayout?.forEach(() => {
255
- this.selectedColumnHeaders.push([])
250
+ const selectedChoiceKey = (rowIndex: number, columnIndex: number) => {
251
+ const row = rowIndex += 1
252
+ const column = columnIndex += 1
253
+ if (selectedMatrixChoices.value.length && matrixAnswerKeys.value.length) {
254
+ const matrixSelectedChoiceKey = selectedMatrixChoices.value.find((choice) => {
255
+ const substring = choice.substring(1)
256
+ return substring === `${row}_${column}`
256
257
  })
257
- }
258
258
 
259
- toggleChoiceDropdown (rowIndex: number) {
260
- const includedRowNumberIndex = this.expandedRowNumbers.findIndex(row => row === rowIndex)
261
- if (includedRowNumberIndex === -1) {
262
- this.expandedRowNumbers.push(rowIndex)
263
- } else {
264
- this.expandedRowNumbers.splice(includedRowNumberIndex, 1)
265
- }
259
+ return matrixSelectedChoiceKey
266
260
  }
261
+ return undefined
262
+ }
267
263
 
268
- selectedChoiceKey (rowIndex: number, columnIndex: number) {
269
- const row = rowIndex += 1
270
- const column = columnIndex += 1
271
- if (this.selectedMatrixChoices.length && this.matrixAnswerKeys.length) {
272
- const matrixSelectedChoiceKey = this.selectedMatrixChoices.find((choice) => {
273
- const substring = choice.substring(1)
274
- return substring === `${row}_${column}`
275
- })
276
-
277
- return matrixSelectedChoiceKey
278
- }
279
- return undefined
280
- }
264
+ const getRadioRowSelection = (rowIndex: number) => {
265
+ return matrixRadioGrid.value?.[rowIndex]?.value
266
+ }
281
267
 
282
- getRadioRowSelection (rowIndex: number) {
283
- return this.matrixRadioGrid?.[rowIndex]?.value
284
- }
268
+ const getRadioRowChoices = (rowIndex: number) => {
269
+ const choices = matrixRadioGrid.value?.[rowIndex]?.choices
270
+ return choices
271
+ }
285
272
 
286
- getRadioRowChoices (rowIndex: number) {
287
- const choices = this.matrixRadioGrid?.[rowIndex]?.choices
288
- return choices
289
- }
273
+ const updateRadioRowSelection = (rowIndex: number, choiceKey: TMatrixChoiceKey | null) => {
274
+ const row = matrixRadioGrid.value?.[rowIndex]
275
+ if (row) {
276
+ row.value = choiceKey
290
277
 
291
- updateRadioRowSelection (rowIndex: number, choiceKey: TMatrixChoiceKey) {
292
- const row = this.matrixRadioGrid?.[rowIndex]
293
- if (row) {
294
- row.value = choiceKey
295
-
296
- // update row header label
297
- const choiceKeyIndex = row.choices.findIndex(choice => choice === choiceKey)
298
- const rowHeader = this.question.matrixLabels?.columns[choiceKeyIndex]
299
- if (rowHeader) {
300
- this.selectedColumnHeaders[rowIndex]?.pop()
301
- this.selectedColumnHeaders[rowIndex]?.push(rowHeader)
302
- }
278
+ // update row header label
279
+ const choiceKeyIndex = row.choices.findIndex(choice => choice === choiceKey)
280
+ const rowHeader = question.value.matrixLabels?.columns[choiceKeyIndex]
281
+ if (rowHeader) {
282
+ selectedColumnHeaders.value[rowIndex]?.pop()
283
+ selectedColumnHeaders.value[rowIndex]?.push(rowHeader)
303
284
  }
304
285
  }
286
+ }
305
287
 
306
- correctlySelectedChoice (rowIndex: number, columnIndex: number) {
307
- if (this.selectedMatrixChoices && this.matrixAnswerKeys) {
308
- const selectedChoice = this.selectedChoiceKey(rowIndex, columnIndex)
309
- if (selectedChoice && selectedChoice.startsWith('a') && this.matrixAnswerKeys.includes(selectedChoice)) {
310
- return true
311
- }
288
+ const correctlySelectedChoice = (rowIndex: number, columnIndex: number) => {
289
+ if (selectedMatrixChoices.value && matrixAnswerKeys.value) {
290
+ const selectedChoice = selectedChoiceKey(rowIndex, columnIndex)
291
+ if (selectedChoice && selectedChoice.startsWith('a') && matrixAnswerKeys.value.includes(selectedChoice)) {
292
+ return true
312
293
  }
313
- return false
314
294
  }
295
+ return false
296
+ }
315
297
 
316
- incorrectlySelectedChoice (rowIndex: number, columnIndex: number) {
317
- if (this.selectedMatrixChoices && this.matrixAnswerKeys) {
318
- const selectedChoice = this.selectedChoiceKey(rowIndex, columnIndex)
319
- if (selectedChoice && selectedChoice.startsWith('d')) {
320
- return true
321
- }
298
+ const incorrectlySelectedChoice = (rowIndex: number, columnIndex: number) => {
299
+ if (selectedMatrixChoices.value && matrixAnswerKeys.value) {
300
+ const selectedChoice = selectedChoiceKey(rowIndex, columnIndex)
301
+ if (selectedChoice && selectedChoice.startsWith('d')) {
302
+ return true
322
303
  }
323
- return false
324
- }
325
-
326
- correctAnswerButNotSelected (rowIndex: number, columnIndex: number) {
327
- const selectedChoice = this.selectedChoiceKey(rowIndex, columnIndex)
328
- const answerKey = this.matrixAnswerKeys.find(choice => choice === `a${rowIndex + 1}_${columnIndex + 1}`)
329
- return answerKey && !selectedChoice
330
304
  }
305
+ return false
306
+ }
307
+
308
+ const correctAnswerButNotSelected = (rowIndex: number, columnIndex: number) => {
309
+ const selectedChoice = selectedChoiceKey(rowIndex, columnIndex)
310
+ const answerKey = matrixAnswerKeys.value.find(choice => choice === `a${rowIndex + 1}_${columnIndex + 1}`)
311
+ return answerKey && !selectedChoice
312
+ }
331
313
 
332
- checkboxContainerStyling (rowIndex: number, columnIndex: number) {
333
- const isReviewMode = this.showMatrixAnswers || this.reviewMode
334
- const incorrectlySelectedChoice = this.incorrectlySelectedChoice(rowIndex, columnIndex)
314
+ const checkboxContainerStyling = (rowIndex: number, columnIndex: number) => {
315
+ const isReviewMode = showMatrixAnswers.value || reviewMode
335
316
 
336
- // check box is correctlySelected
337
- if (isReviewMode && this.correctlySelectedChoice(rowIndex, columnIndex)) {
338
- const borderColor = this.isDarkMode ? this.brandColors.jungleGreen : this.brandColors.cadaverous
339
- return {
340
- borderColor: `${borderColor} !important`,
341
- background: `${borderColor} !important`,
342
- }
317
+ // check box is correctlySelected
318
+ if (isReviewMode && correctlySelectedChoice(rowIndex, columnIndex)) {
319
+ const borderColor = isDarkMode ? brandColors.jungleGreen : brandColors.cadaverous
320
+ return {
321
+ borderColor: `${borderColor} !important`,
322
+ background: `${borderColor} !important`,
343
323
  }
324
+ }
344
325
 
345
- if (isReviewMode && incorrectlySelectedChoice) {
346
- return {
347
- background: `${this.brandColors.steel} !important`,
348
- border: `1px solid ${this.brandColors.steel} !important`,
349
- }
326
+ if (isReviewMode && incorrectlySelectedChoice(rowIndex, columnIndex)) {
327
+ return {
328
+ background: `${brandColors.steel} !important`,
329
+ border: `1px solid ${brandColors.steel} !important`,
350
330
  }
331
+ }
351
332
 
352
- if (isReviewMode && this.correctAnswerButNotSelected(rowIndex, columnIndex)) {
353
- return {
354
- background: 'transparent !important',
355
- border: `1px solid ${this.brandColors.slate} !important`,
356
- }
333
+ if (isReviewMode && correctAnswerButNotSelected(rowIndex, columnIndex)) {
334
+ return {
335
+ background: 'transparent !important',
336
+ border: `1px solid ${brandColors.slate} !important`,
357
337
  }
358
338
  }
339
+ }
359
340
 
360
- checkboxCheckStyling (rowIndex: number, columnIndex: number) {
361
- const isReviewMode = this.showMatrixAnswers || this.reviewMode
362
- if (isReviewMode && this.correctAnswerButNotSelected(rowIndex, columnIndex)) {
363
- const color = this.isDarkMode ? this.brandColors.jungleGreen : this.brandColors.cadaverous
364
- return {
365
- color: `${color} !important`,
366
- }
341
+ const checkboxCheckStyling = (rowIndex: number, columnIndex: number) => {
342
+ const isReviewMode = showMatrixAnswers.value || reviewMode
343
+ if (isReviewMode && correctAnswerButNotSelected(rowIndex, columnIndex)) {
344
+ const color = isDarkMode ? brandColors.jungleGreen : brandColors.cadaverous
345
+ return {
346
+ color: `${color} !important`,
367
347
  }
368
348
  }
349
+ }
369
350
 
370
- correctRow (rowIndex: number) {
371
- if (this.question?.matrixChoiceLayout && this.question?.matrixChoiceLayout[rowIndex]) {
372
- if (
373
- this.question?.type === 'Matrix Checkbox' &&
374
- this.matrixCheckboxGrid &&
375
- this.matrixCheckboxGrid[rowIndex]
376
- ) {
377
- const correctAnswerKeys = this.question?.matrixChoiceLayout[rowIndex].filter(choice =>
378
- choice.startsWith('a')
379
- )
380
- const selectedAnswerKeys = this.matrixCheckboxGrid[rowIndex].map((choice, choiceIndex) => {
381
- return this.selectedChoiceKey(rowIndex, choiceIndex)
382
- })
383
- const correctSelectedKeys = this.matrixCheckboxGrid[rowIndex].filter((choice, choiceIndex) => {
384
- const selectedChoice = this.selectedChoiceKey(rowIndex, choiceIndex)
385
- return selectedChoice?.startsWith('a')
386
- })
387
- return !selectedAnswerKeys.some(choice => choice?.startsWith('d')) &&
388
- (correctAnswerKeys.length === correctSelectedKeys.length)
389
- }
390
-
391
- if (
392
- this.question?.type === 'Matrix Radio Button' &&
393
- this.matrixRadioGrid &&
394
- this.matrixRadioGrid[rowIndex]
395
- ) {
396
- const rowVal = this.matrixRadioGrid[rowIndex].value
397
- if (rowVal) {
398
- return rowVal.startsWith('a')
399
- }
400
- return false
351
+ const correctRow = (rowIndex: number) => {
352
+ if (matrixChoiceLayout.value && matrixChoiceLayout.value[rowIndex]) {
353
+ if (
354
+ question?.value.type === 'Matrix Checkbox' &&
355
+ matrixCheckboxGrid.value &&
356
+ matrixCheckboxGrid.value[rowIndex]
357
+ ) {
358
+ const correctAnswerKeys = matrixChoiceLayout.value[rowIndex]?.filter(choice =>
359
+ choice.startsWith('a')
360
+ )
361
+ const selectedAnswerKeys = matrixCheckboxGrid.value[rowIndex]?.map((choice, choiceIndex) => {
362
+ return selectedChoiceKey(rowIndex, choiceIndex)
363
+ })
364
+ const correctSelectedKeys = matrixCheckboxGrid.value[rowIndex]?.filter((choice, choiceIndex) => {
365
+ const selectedChoice = selectedChoiceKey(rowIndex, choiceIndex)
366
+ return selectedChoice?.startsWith('a')
367
+ })
368
+ return !selectedAnswerKeys?.some(choice => choice?.startsWith('d')) &&
369
+ (correctAnswerKeys?.length === correctSelectedKeys?.length)
370
+ }
371
+
372
+ if (
373
+ question?.value.type === 'Matrix Radio Button' &&
374
+ matrixRadioGrid.value &&
375
+ matrixRadioGrid.value[rowIndex]
376
+ ) {
377
+ const rowVal = matrixRadioGrid.value[rowIndex]?.value
378
+ if (rowVal) {
379
+ return rowVal.startsWith('a')
401
380
  }
381
+ return false
402
382
  }
403
- return false
404
383
  }
384
+ return false
385
+ }
405
386
 
406
- convertSelectedMatrixChoiceToCheckboxGrid () {
407
- const checkboxGrid = this.defaultCheckboxGrid
387
+ const convertSelectedMatrixChoiceToCheckboxGrid = () => {
388
+ const checkboxGrid = defaultCheckboxGrid.value
408
389
 
409
- // Reset this.selectedColumnHeaders string[][] in case in headers are still in the arrays
410
- // Let selectedMatrixChoices set those columns
411
- const columnMatrixLabels = this.question.matrixLabels?.rows
412
- const defaultSelectedColumnLabels: string[][] = []
413
- if (columnMatrixLabels) {
414
- columnMatrixLabels.forEach(() => {
415
- defaultSelectedColumnLabels.push([])
416
- })
390
+ // Reset selectedColumnHeaders string[][] in case in headers are still in the arrays
391
+ // Let selectedMatrixChoices set those columns
392
+ const columnMatrixLabels = question.value.matrixLabels?.rows
393
+ const defaultSelectedColumnLabels: string[][] = []
394
+ if (columnMatrixLabels) {
395
+ columnMatrixLabels.forEach(() => {
396
+ defaultSelectedColumnLabels.push([])
397
+ })
417
398
 
418
- this.selectedColumnHeaders = defaultSelectedColumnLabels
419
- }
399
+ selectedColumnHeaders.value = defaultSelectedColumnLabels
400
+ }
420
401
 
421
- this.selectedMatrixChoices.forEach(choice => {
422
- const rowIndex = Number(choice.substring(1, choice.indexOf('_'))) - 1
423
- const columnIndex = Number(choice.split('_').pop()) - 1
424
- if (checkboxGrid && checkboxGrid[rowIndex]) {
425
- checkboxGrid[rowIndex][columnIndex] = true
426
- if (this.selectedColumnHeaders[rowIndex] && this.question.matrixLabels?.columns[columnIndex]) {
427
- const columnHeader = this.question.matrixLabels?.columns[columnIndex]
428
- this.selectedColumnHeaders[rowIndex].push(columnHeader)
402
+ selectedMatrixChoices.value.forEach(choice => {
403
+ const rowIndex = Number(choice.substring(1, choice.indexOf('_'))) - 1
404
+ const columnIndex = Number(choice.split('_').pop()) - 1
405
+ const row = checkboxGrid && checkboxGrid[rowIndex]
406
+ if (row) {
407
+ row[columnIndex] = true
408
+ if (selectedColumnHeaders.value[rowIndex] && question.value.matrixLabels?.columns[columnIndex]) {
409
+ const columnHeader = question.value.matrixLabels?.columns[columnIndex]
410
+ if (columnHeader) {
411
+ selectedColumnHeaders.value[rowIndex]?.push(columnHeader)
429
412
  }
430
413
  }
431
- })
432
- return checkboxGrid
433
- }
434
-
435
- convertSelectedMatrixChoiceToRadioBtnGrid () {
436
- const radioBtnGrid = this.defaultRadioButtonGrid
437
-
438
- const columnMatrixLabels = this.question.matrixLabels?.rows
439
- const defaultSelectedColumnLabels: string[][] = []
440
- if (columnMatrixLabels) {
441
- columnMatrixLabels.forEach(() => {
442
- defaultSelectedColumnLabels.push([])
443
- })
444
-
445
- this.selectedColumnHeaders = defaultSelectedColumnLabels
446
414
  }
415
+ })
416
+ return checkboxGrid
417
+ }
447
418
 
448
- this.selectedMatrixChoices.forEach(choice => {
449
- const rowIndex = Number(choice.substring(1, choice.indexOf('_'))) - 1
450
- const columnIndex = Number(choice.split('_').pop()) - 1
451
- if (this.selectedColumnHeaders[rowIndex] && this.question.matrixLabels?.columns[columnIndex]) {
452
- const columnHeader = this.question.matrixLabels?.columns[columnIndex]
453
- // In case a column header is still in selectedColumnHeaders, remove it first and let
454
- // selectedMatrixChoices add selected column header based on selected choices
455
- this.selectedColumnHeaders[rowIndex].pop()
456
- this.selectedColumnHeaders[rowIndex].push(columnHeader)
457
- }
458
- if (radioBtnGrid && radioBtnGrid[rowIndex]) {
459
- radioBtnGrid[rowIndex].value = choice
460
- }
419
+ const convertSelectedMatrixChoiceToRadioBtnGrid = () => {
420
+ const radioBtnGrid = defaultRadioButtonGrid.value
421
+
422
+ const columnMatrixLabels = question.value.matrixLabels?.rows
423
+ const defaultSelectedColumnLabels: string[][] = []
424
+ if (columnMatrixLabels) {
425
+ columnMatrixLabels.forEach(() => {
426
+ defaultSelectedColumnLabels.push([])
461
427
  })
462
- return radioBtnGrid
428
+
429
+ selectedColumnHeaders.value = defaultSelectedColumnLabels
463
430
  }
464
431
 
465
- checkboxRowClicked (rowIndex: number, columnIndex: number) {
466
- if (this.matrixCheckboxGrid && this.matrixCheckboxGrid[rowIndex]) {
467
- this.matrixCheckboxGrid[rowIndex][columnIndex] = !this.matrixCheckboxGrid[rowIndex][columnIndex]
468
- const columnHeader = this.question.matrixLabels?.columns[columnIndex]
432
+ selectedMatrixChoices.value.forEach(choice => {
433
+ const rowIndex = Number(choice.substring(1, choice.indexOf('_'))) - 1
434
+ const columnIndex = Number(choice.split('_').pop()) - 1
435
+ if (selectedColumnHeaders.value[rowIndex] && question.value.matrixLabels?.columns[columnIndex]) {
436
+ const columnHeader = question.value.matrixLabels?.columns[columnIndex]
437
+ // In case a column header is still in selectedColumnHeaders, remove it first and let
438
+ // selectedMatrixChoices add selected column header based on selected choices
439
+ if (columnHeader) {
440
+ selectedColumnHeaders.value[rowIndex]?.pop()
441
+ selectedColumnHeaders.value[rowIndex]?.push(columnHeader)
442
+ }
443
+ }
444
+ const radioBtnGridRow = radioBtnGrid && radioBtnGrid[rowIndex]
445
+ if (radioBtnGridRow) {
446
+ radioBtnGridRow.value = choice
447
+ }
448
+ })
449
+ return radioBtnGrid
450
+ }
469
451
 
470
- if (this.selectedColumnHeaders && this.selectedColumnHeaders[rowIndex] && columnHeader) {
471
- if (this.selectedColumnHeaders[rowIndex].includes(columnHeader)) {
472
- const columnHeaderIndex = this.selectedColumnHeaders[rowIndex].indexOf(columnHeader)
473
- if (columnHeaderIndex !== -1) {
474
- this.selectedColumnHeaders[rowIndex].splice(columnHeaderIndex, 1)
475
- }
476
- } else {
477
- this.selectedColumnHeaders[rowIndex].push(columnHeader)
452
+ const checkboxRowClicked = (rowIndex: number, columnIndex: number) => {
453
+ const matrixCheckboxGridRow = matrixCheckboxGrid.value && matrixCheckboxGrid.value[rowIndex]
454
+ if (matrixCheckboxGridRow) {
455
+ matrixCheckboxGridRow[columnIndex] = !matrixCheckboxGridRow[columnIndex]
456
+ const columnHeader = question.value.matrixLabels?.columns[columnIndex]
457
+
458
+ if (selectedColumnHeaders.value && selectedColumnHeaders.value[rowIndex] && columnHeader) {
459
+ if (selectedColumnHeaders.value[rowIndex]?.includes(columnHeader)) {
460
+ const columnHeaderIndex = selectedColumnHeaders.value[rowIndex]?.indexOf(columnHeader)
461
+ if (columnHeaderIndex !== undefined && columnHeaderIndex !== -1) {
462
+ selectedColumnHeaders.value[rowIndex]?.splice(columnHeaderIndex, 1)
478
463
  }
464
+ } else {
465
+ selectedColumnHeaders.value[rowIndex]?.push(columnHeader)
479
466
  }
480
467
  }
481
468
  }
469
+ }
470
+
471
+ const doesSelectedColumnHeaderExist = (rowIndex: number, columnIndex: number) => {
472
+ return selectedColumnHeaders.value?.[rowIndex]?.[columnIndex] || false
473
+ }
482
474
 
483
- @Emit('emitSelectedMatrixChoice')
484
- emitSelectedMatrixChoice (matrixChoiceKeys: TMatrixChoiceKey[]) {
485
- return matrixChoiceKeys
475
+ const getSelectedChoiceLabels = (rowIndex: number, columnIndex: number) => {
476
+ const columnHeadersInRow = selectedColumnHeaders.value?.[rowIndex]
477
+ if (!columnHeadersInRow) {
478
+ return
479
+ }
480
+ const selectedColumnHeader = columnHeadersInRow[columnIndex]
481
+ const lastColumnHeader = columnHeadersInRow[columnHeadersInRow.length - 1]
482
+ if (!selectedColumnHeader) {
483
+ return ''
486
484
  }
487
485
 
486
+ return selectedColumnHeader === lastColumnHeader
487
+ ? stripHtmlTags(selectedColumnHeader)
488
+ : `${stripHtmlTags(selectedColumnHeader)},`
489
+ }
488
490
 
489
- @Watch('matrixCheckboxGrid', { deep: true })
490
- matrixCheckboxGridChange () {
491
- if (this.matrixChoiceLayout && this.matrixCheckboxGrid && (!this.reviewMode || !this.showMatrixAnswers)) {
492
- const selectedCheckboxChoices: TMatrixChoiceKey[] = []
491
+ const emitSelectedMatrixChoice = (matrixChoiceKeys: TMatrixChoiceKey[]) => {
492
+ emit('emitSelectedMatrixChoice', matrixChoiceKeys)
493
+ }
493
494
 
494
- this.matrixCheckboxGrid.forEach((row, rowIndex) => {
495
- row.forEach((choice, choiceIndex) => {
496
- if (
497
- choice &&
498
- this.matrixChoiceLayout[rowIndex] &&
499
- this.matrixChoiceLayout[rowIndex][choiceIndex]
500
- ) {
501
- const choiceKey = this.matrixChoiceLayout[rowIndex][choiceIndex] as TMatrixChoiceKey
495
+ watch(matrixCheckboxGrid, () => {
496
+ if (matrixChoiceLayout.value && matrixCheckboxGrid.value && (!reviewMode || !showMatrixAnswers.value)) {
497
+ const selectedCheckboxChoices: TMatrixChoiceKey[] = []
498
+
499
+ matrixCheckboxGrid.value.forEach((row, rowIndex) => {
500
+ row.forEach((choice, choiceIndex) => {
501
+ if (
502
+ choice &&
503
+ matrixChoiceLayout.value?.[rowIndex] &&
504
+ matrixChoiceLayout.value?.[rowIndex]?.[choiceIndex]
505
+ ) {
506
+ const choiceKey = matrixChoiceLayout.value?.[rowIndex]?.[choiceIndex] as TMatrixChoiceKey
507
+ if (choiceKey) {
502
508
  selectedCheckboxChoices.push(choiceKey)
503
509
  }
504
- })
510
+ }
505
511
  })
512
+ })
506
513
 
507
- this.emitSelectedMatrixChoice(selectedCheckboxChoices)
508
- }
514
+ emitSelectedMatrixChoice(selectedCheckboxChoices)
509
515
  }
516
+ }, { deep: true })
510
517
 
511
- @Watch('matrixRadioGrid', { deep: true })
512
- matrixRadioGridChange () {
513
- if (this.matrixChoiceLayout && this.matrixRadioGrid && (!this.reviewMode || !this.showMatrixAnswers)) {
514
- const selectedRadioButtonChoices: TMatrixChoiceKey[] = []
518
+ watch(matrixRadioGrid, () => {
519
+ if (matrixChoiceLayout.value && matrixRadioGrid.value && (!reviewMode || !showMatrixAnswers.value)) {
520
+ const selectedRadioButtonChoices: TMatrixChoiceKey[] = []
515
521
 
516
- this.matrixRadioGrid.forEach((row) => {
517
- if (row.value) {
518
- selectedRadioButtonChoices.push(row.value)
519
- }
520
- })
522
+ matrixRadioGrid.value.forEach((row) => {
523
+ if (row.value) {
524
+ selectedRadioButtonChoices.push(row.value)
525
+ }
526
+ })
521
527
 
522
- this.emitSelectedMatrixChoice(selectedRadioButtonChoices)
523
- }
528
+ emitSelectedMatrixChoice(selectedRadioButtonChoices)
524
529
  }
530
+ }, { deep: true })
525
531
 
526
- @Watch('showMatrixAnswers')
527
- closeRows () {
528
- if (this.showMatrixAnswers) {
529
- this.expandedRowNumbers = []
530
- }
532
+ watch(showMatrixAnswers, () => {
533
+ if (showMatrixAnswers) {
534
+ expandedRowNumbers.value = []
531
535
  }
536
+ })
532
537
 
533
- @Watch('selectedMatrixChoices')
534
- selectedMatrixChoicesChange () {
535
- if ((this.reviewMode || this.showMatrixAnswers) && this.question.type === 'Matrix Checkbox') {
536
- const selectedCheckboxGrid = this.convertSelectedMatrixChoiceToCheckboxGrid()
537
- this.matrixCheckboxGrid = selectedCheckboxGrid ? selectedCheckboxGrid : this.defaultCheckboxGrid
538
- }
539
-
540
- if ((this.reviewMode || this.showMatrixAnswers) && this.question.type === 'Matrix Radio Button') {
541
- const selectedRadioBtnGrid = this.convertSelectedMatrixChoiceToRadioBtnGrid()
542
- this.matrixRadioGrid = selectedRadioBtnGrid
543
- }
538
+ watch(selectedMatrixChoices, () => {
539
+ if ((reviewMode || showMatrixAnswers.value) && question.value.type === 'Matrix Checkbox') {
540
+ const selectedCheckboxGrid = convertSelectedMatrixChoiceToCheckboxGrid()
541
+ matrixCheckboxGrid.value = selectedCheckboxGrid ? selectedCheckboxGrid : defaultCheckboxGrid.value
544
542
  }
545
- }
546
543
 
544
+ if ((reviewMode || showMatrixAnswers.value) && question.value.type === 'Matrix Radio Button') {
545
+ const selectedRadioBtnGrid = convertSelectedMatrixChoiceToRadioBtnGrid()
546
+ matrixRadioGrid.value = selectedRadioBtnGrid
547
+ }
548
+ })
547
549
  </script>
548
550
 
549
551
  <style lang="scss">