fcad-core-dragon 2.4.1-test.1 → 2.5.0-test.1

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # [2.5.0-test.1](https://git.crosemont.qc.ca/fcad/core/fcad-core-2/compare/v2.4.1-test.1...v2.5.0-test.1) (2026-06-08)
2
+
3
+
4
+ ### Features
5
+
6
+ * **components:** Ajout nouveau composant categorieCheckBoxNx ([f8c64ce](https://git.crosemont.qc.ca/fcad/core/fcad-core-2/commit/f8c64ce9e001dd3e93d450b12715978db3dc04dc))
7
+
1
8
  ## [2.4.1-test.1](https://git.crosemont.qc.ca/fcad/core/fcad-core-2/compare/v2.4.0...v2.4.1-test.1) (2026-06-08)
2
9
 
3
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fcad-core-dragon",
3
- "version": "2.4.1-test.1",
3
+ "version": "2.5.0-test.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./src/main.js",
@@ -224,6 +224,8 @@ export default {
224
224
  // this.updateTracker('appBase', 'loading')
225
225
  this.initializeApp(this.appConfig)
226
226
  }
227
+ // set the language of the app
228
+ this.setLocale(this.getAppConfigs.lang)
227
229
  this.setDocumentTitle()
228
230
  window.versionFCAD = this.$helper.getFcadVersionString()
229
231
  //check if this is running in a mobile environment and register state in the store
@@ -264,8 +266,6 @@ export default {
264
266
  },
265
267
 
266
268
  mounted() {
267
- // set the language of the app
268
- this.setLocale(this.getAppConfigs.lang)
269
269
  window.addEventListener('keydown', this.handleF5KeyPressed)
270
270
  window.addEventListener('beforeunload', this.handleBeforeUnload)
271
271
  },
@@ -0,0 +1,330 @@
1
+ <!-- About this Component--
2
+ * Renders a checkboxe input type for the Quiz component
3
+ * Related Quiz to question: REPONSE_MULTIPLE
4
+ * Receives the a data object defined by user
5
+ * Used by AppCompQuiz
6
+ -->
7
+ <template>
8
+ <div v-if="inputData.length > 0" :id="id" class="input-box">
9
+ <v-row
10
+ v-for="(categorie,i) in inputData"
11
+ :key="`cat_${categorie.id}`"
12
+ class="box-categorie"
13
+ >
14
+ <v-col>
15
+ <div v-html="categorie.categorie"></div>
16
+ </v-col>
17
+ <v-col>
18
+ <fieldset :aria-label="fieldsetLabel">
19
+ <div class="box-checkbox">
20
+ <label
21
+ v-for="(choixReponse, index) in categorie.values"
22
+ :key="`lbl_chx_${id}-${choixReponse.id}`"
23
+ :for="`boxchx_cat_${i}_${index}`"
24
+ class="checkbox-label"
25
+ :class="[
26
+ {
27
+ answerSlct: isSelected(i,choixReponse)
28
+ },
29
+ `${retro?.[i]?.[index] ?? ''}`
30
+ ]"
31
+ >
32
+ <input
33
+ :id="`boxchx_cat_${i}_${index}`"
34
+ :key="`boxchx_cat_${i}_${choixReponse}`"
35
+ :checked="isSelected(i,choixReponse)"
36
+ type="checkbox"
37
+ :name="`btn-checkbox-cat-${i}-${index}`"
38
+ :aria-labelledby="`span_${index}`"
39
+ :aria-describedby="`${index}-msg-erreur`"
40
+ @change="onSelectUpdate($event,i,choixReponse)"
41
+ />
42
+ <span
43
+ :id="`span_${index}`"
44
+ class="checkbox-contenu"
45
+ v-html="choixReponse"
46
+ ></span>
47
+ <span
48
+ :id="`${index}-msg-erreur`"
49
+ :key="`msg_chx_${index}`"
50
+ class="sr-only"
51
+ >
52
+ {{ messageAccessibility[index] }}
53
+ </span>
54
+ </label>
55
+ </div>
56
+ </fieldset>
57
+ </v-col>
58
+
59
+ </v-row>
60
+ </div>
61
+ </template>
62
+ <script>
63
+ import { useQuiz } from '../composables/useQuiz'
64
+ import { validateObjType } from '../shared/validators'
65
+ import { useI18n } from 'vue-i18n'
66
+
67
+ export default {
68
+ name: 'AppCompInputCheckBoxNx',
69
+ /* PROPS USED FOR PARENT TO COMMUNICATE DATA TO CHILD */
70
+ props: {
71
+ inputData: {
72
+ type: Array,
73
+ default: () => []
74
+ },
75
+ modelValue: {
76
+ type: Array,
77
+ default: () => []
78
+ },
79
+ solution: {
80
+ type: Array,
81
+ default: () => []
82
+ },
83
+ id: {
84
+ type: String,
85
+ default: ''
86
+ }
87
+ },
88
+ emits: ['update:modelValue', 'enable-submit'],
89
+ setup() {
90
+ const { t } = useI18n()
91
+ const { retroType, addRetroStyle, resetRetroStyle } = useQuiz()
92
+ return { retroType, addRetroStyle, resetRetroStyle, t }
93
+ },
94
+ data() {
95
+ return {
96
+ result: null,
97
+ retro: [],
98
+ messageAccessibility: []
99
+ }
100
+ },
101
+ computed: {
102
+ fieldsetLabel() {
103
+ return `${this.$t('quizState.checkboxFieldset')} ${this.$t('quizState.options')}`
104
+ }
105
+ },
106
+ watch: {
107
+ modelValue: {
108
+ handler(newVal) {
109
+ this.$emit('enable-submit', newVal.length && newVal.every((e) => e.length))
110
+ },
111
+ deep: true,
112
+ immediate: true
113
+ }
114
+ },
115
+ created() {
116
+ if (import.meta.env.DEV) {
117
+ let errors = this.validateInputData()
118
+
119
+ if (errors && errors.errorList.length)
120
+ return this.$bus.$emit('input-error', { e: this.id, errors })
121
+ }
122
+ },
123
+ mounted() {
124
+ },
125
+
126
+ methods: {
127
+ /**
128
+ * @description validate the raw data received by the component to render is view
129
+ * @returns {Object} errors - errorList: to display in view and errorConsole, to be displayed in console
130
+ */
131
+ validateInputData() {
132
+ let errors = null //array for errors dectected
133
+ let stringType = ['id','categorie']
134
+ let arrayType = ['values']
135
+ if (!this.inputData.length) return errors
136
+ for (let i = 0; i < this.inputData.length; i++) {
137
+ errors = validateObjType(
138
+ this.inputData[i],
139
+ { stringType, arrayType },
140
+ null,
141
+ `choix_reponse #${i + 1}`
142
+ )
143
+ const { errorList, errorInConsole } = errors
144
+
145
+ if (!errorList || !errorInConsole) return null
146
+ return errors
147
+ }
148
+
149
+ return errors
150
+ },
151
+
152
+ /**
153
+ * @description inicate wether the element is checked or not.
154
+ * Element is selected if in the modelValue
155
+ * @param value value of tje element to be checked
156
+ */
157
+ isSelected(parent,value) {
158
+
159
+ let existing
160
+ if(this.modelValue.length) existing = this.modelValue[parent].includes(value)
161
+ else existing = false
162
+
163
+ return existing
164
+ },
165
+ /**
166
+ * @description Method to force update of this.inputsValue.
167
+ * this force the old value and new value of the input to be tracked by VUE.
168
+ * @param newValue, the new value of the input
169
+ * @param index index of the selected element
170
+ */
171
+ onSelectUpdate(event, parent, value) {
172
+ const isChecked = event.target.checked
173
+ this.resetRetroStyle([this.retro, this.messageAccessibility])
174
+
175
+ let ValueModel
176
+
177
+ if(!this.modelValue.length) ValueModel = Array.from({length:this.inputData.length},()=>[])
178
+ else ValueModel = this.modelValue
179
+
180
+ let UpdatedValue = [...ValueModel]
181
+
182
+ if (isChecked) {
183
+ const existing = UpdatedValue[parent].includes(value)
184
+ if (!existing) UpdatedValue[parent].push(value)
185
+ } else UpdatedValue[parent] = UpdatedValue[parent].filter((v) => v !== value)
186
+
187
+
188
+ this.$emit('update:modelValue', UpdatedValue)
189
+
190
+ },
191
+ /**
192
+ * @description Component validation method to validate the user input against the solution
193
+ * can handle logic of Css style to apply (correct/wrong Answer) and return the result
194
+ * @return {Object} result
195
+ */
196
+ validateAnswer() {
197
+ // Validate the user answer
198
+ //Created a custom validated object for inputData
199
+ let mappedResults = Array.from({length:this.inputData.length},()=>[])
200
+ if (this.solution != null) {
201
+ this.inputData.forEach((e,index)=>{
202
+ mappedResults[index] = e.values.map(
203
+ (a) =>
204
+ (a = {
205
+ ...a,
206
+ correct: this.solution[index].includes(a)
207
+ })
208
+ )
209
+ })
210
+ } else {
211
+ this.inputData.forEach((e,index)=>{
212
+ mappedResults[index] = e.values.map(
213
+ (a) =>
214
+ (a = {
215
+ ...a,
216
+ correct: this.solution[index].includes(a)
217
+ })
218
+ )
219
+ })
220
+ }
221
+
222
+ let classRetro = Array.from({length:this.inputData.length},()=>[])
223
+ let mesA11y = Array.from({length:this.inputData.length},()=>[])
224
+
225
+ this.inputData.forEach((e,index)=>{
226
+ const { classRetro: cr, mesA11y: ma } =
227
+ this.addRetroStyle(
228
+ this.solution[index],
229
+ mappedResults[index],
230
+ this.inputData[index].values.length
231
+ )
232
+ classRetro[index] = cr
233
+ mesA11y[index] = ma
234
+ })
235
+
236
+ this.retro = classRetro
237
+ this.messageAccessibility = mesA11y
238
+
239
+ //filer mapped to return a customized object of the user selection
240
+ this.result =
241
+ this.modelValue.map((el,i) => {
242
+ return el.map((e,index)=>{
243
+ return{
244
+ id:index,
245
+ selected: e,
246
+ correct: this.solution[i].includes(e)
247
+ }
248
+ })
249
+ })
250
+ let retroResult = Array.from({length:this.inputData.length},()=>[])
251
+
252
+ this.inputData.forEach((e,index)=>{
253
+ retroResult[index] = this.retroType(this.solution[index], this.result[index])
254
+ })
255
+
256
+ const retro = retroResult.every(e => e === 'retro_positive') ? 'retro_positive' : 'retro_negative'
257
+
258
+ let cAns
259
+ if (this.solution != null) cAns = this.computeResult(this.result)
260
+ else cAns = false
261
+
262
+ //Object to return validation to parent
263
+ return {
264
+ userAnswer: this.result,
265
+ correctAnswer: cAns,
266
+ retroType: retro
267
+ }
268
+ },
269
+ /**
270
+ * @description - compute the correct elements in user response
271
+ * compare with the solution and return wether user succeeded or failed
272
+ * @param {Object} result - user responses
273
+ * @retuns boolean
274
+ */
275
+ computeResult(result) {
276
+ let res = result.map((e) => { return e.filter((a) => (a.correct)) }).flat()
277
+
278
+ return (
279
+ res.length == this.solution.flat() &&
280
+ this.solution.flat().length == result.flat().length
281
+ )
282
+ }
283
+ }
284
+ }
285
+ </script>
286
+ <style lang="scss">
287
+ fieldset {
288
+ border: inherit;
289
+ }
290
+
291
+ .custom-control-input:focus ~ .custom-control-label::before {
292
+ border: inherit;
293
+ }
294
+
295
+ .custom-control-input:focus ~ .custom-control-label::before {
296
+ box-shadow: inherit;
297
+ -webkit-box-shadow: inherit;
298
+ }
299
+
300
+ fieldset {
301
+ border: inherit;
302
+ }
303
+
304
+ .custom-checkbox {
305
+ width: 100%;
306
+ height: 100%;
307
+ padding-left: 0;
308
+
309
+ input {
310
+ width: 100%;
311
+ height: 100%;
312
+ }
313
+
314
+ label {
315
+ width: 100%;
316
+ height: 100%;
317
+
318
+ &:after,
319
+ &:before {
320
+ border: inherit;
321
+ top: 0px;
322
+ left: 0px;
323
+ height: 0;
324
+ width: 0;
325
+ background-color: inherit;
326
+ border: inherit;
327
+ }
328
+ }
329
+ }
330
+ </style>