|
1 | 1 | /* eslint-disable perfectionist/sort-objects */ |
2 | 2 |
|
3 | 3 | import { defineInstrument } from '/runtime/v1/@opendatacapture/runtime-core'; |
4 | | -import { sum } from '/runtime/v1/[email protected]'; |
| 4 | +import { omit, sum } from '/runtime/v1/[email protected]'; |
5 | 5 | import { z } from '/runtime/v1/[email protected]'; |
6 | 6 |
|
| 7 | +const $Response = z.number().int().min(0).max(3); |
| 8 | + |
7 | 9 | export default defineInstrument({ |
8 | 10 | kind: 'FORM', |
9 | 11 | language: ['en', 'fr'], |
10 | 12 | tags: { |
11 | | - en: ['Health'], |
12 | | - fr: ['Santé'] |
| 13 | + en: ['Health', 'Depression'], |
| 14 | + fr: ['Santé', 'Dépression'] |
13 | 15 | }, |
14 | 16 | internal: { |
15 | 17 | edition: 1, |
@@ -90,16 +92,16 @@ export default defineInstrument({ |
90 | 92 | }, |
91 | 93 | options: { |
92 | 94 | en: { |
93 | | - 0: 'Not at all', |
94 | | - 1: 'Several days', |
95 | | - 2: 'More than half of days', |
| 95 | + 0: 'Not at All', |
| 96 | + 1: 'Several Days', |
| 97 | + 2: 'More than half the days', |
96 | 98 | 3: 'Nearly every day' |
97 | 99 | }, |
98 | 100 | fr: { |
99 | | - 0: 'Not at all', |
100 | | - 1: 'Several days', |
101 | | - 2: 'More than half of days', |
102 | | - 3: 'Nearly every day' |
| 101 | + 0: 'Jamais', |
| 102 | + 1: 'Plusieurs jours', |
| 103 | + 2: 'Plus de la moitié des jours', |
| 104 | + 3: 'Presque tous les jours' |
103 | 105 | } |
104 | 106 | }, |
105 | 107 | variant: 'likert' |
@@ -216,21 +218,33 @@ export default defineInstrument({ |
216 | 218 | totalScore: { |
217 | 219 | kind: 'computed', |
218 | 220 | label: { en: 'Total Score', fr: 'Score total' }, |
219 | | - value: ({ questions }) => sum(Object.values(questions)) |
| 221 | + value: ({ questions }) => sum(Object.values(omit(questions, 'impactOnFunctioning'))) |
220 | 222 | } |
221 | 223 | }, |
222 | | - validationSchema: z.object({ |
223 | | - questions: z.object({ |
224 | | - interestPleasure: z.number().int().min(0).max(3), |
225 | | - feelingDown: z.number().int().min(0).max(3), |
226 | | - sleepIssues: z.number().int().min(0).max(3), |
227 | | - energyLevel: z.number().int().min(0).max(3), |
228 | | - appetiteChanges: z.number().int().min(0).max(3), |
229 | | - selfWorth: z.number().int().min(0).max(3), |
230 | | - concentrationIssues: z.number().int().min(0).max(3), |
231 | | - psychomotorChanges: z.number().int().min(0).max(3), |
232 | | - suicidalThoughts: z.number().int().min(0).max(3) |
233 | | - }), |
234 | | - impactOnFunctioning: z.number().int().min(0).max(3).optional() |
235 | | - }) |
| 224 | + validationSchema: z |
| 225 | + .object({ |
| 226 | + questions: z.object({ |
| 227 | + interestPleasure: $Response, |
| 228 | + feelingDown: $Response, |
| 229 | + sleepIssues: $Response, |
| 230 | + energyLevel: $Response, |
| 231 | + appetiteChanges: $Response, |
| 232 | + selfWorth: $Response, |
| 233 | + concentrationIssues: $Response, |
| 234 | + psychomotorChanges: $Response, |
| 235 | + suicidalThoughts: $Response |
| 236 | + }), |
| 237 | + impactOnFunctioning: $Response.optional() |
| 238 | + }) |
| 239 | + .superRefine(({ impactOnFunctioning, questions }, ctx) => { |
| 240 | + const isAnyNonZero = sum(Object.values(questions)) > 0; |
| 241 | + // If any response is not zero, then impactOnFunctioning is required |
| 242 | + if (isAnyNonZero && impactOnFunctioning === undefined) { |
| 243 | + ctx.addIssue({ |
| 244 | + code: 'custom', |
| 245 | + message: 'This question is required / Cette question est obligatoire', |
| 246 | + path: ['impactOnFunctioning'] |
| 247 | + }); |
| 248 | + } |
| 249 | + }) |
236 | 250 | }); |
0 commit comments