@welshare/questionnaire 0.1.1 → 0.2.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.
- package/README.md +151 -0
- package/dist/esm/components/bmi-form.d.ts +68 -0
- package/dist/esm/components/bmi-form.d.ts.map +1 -0
- package/dist/esm/components/bmi-form.js +138 -0
- package/dist/esm/components/question-renderer.d.ts +6 -1
- package/dist/esm/components/question-renderer.d.ts.map +1 -1
- package/dist/esm/components/question-renderer.js +49 -14
- package/dist/esm/components/questions/decimal-question.d.ts +8 -1
- package/dist/esm/components/questions/decimal-question.d.ts.map +1 -1
- package/dist/esm/components/questions/decimal-question.js +19 -1
- package/dist/esm/components/questions/multiple-choice-question.d.ts.map +1 -1
- package/dist/esm/components/questions/multiple-choice-question.js +2 -2
- package/dist/esm/contexts/questionnaire-context.d.ts.map +1 -1
- package/dist/esm/contexts/questionnaire-context.js +3 -2
- package/dist/esm/index.d.ts +6 -2
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +5 -1
- package/dist/esm/lib/bmi-helpers.d.ts +50 -0
- package/dist/esm/lib/bmi-helpers.d.ts.map +1 -0
- package/dist/esm/lib/bmi-helpers.js +69 -0
- package/dist/esm/lib/constants.d.ts +94 -0
- package/dist/esm/lib/constants.d.ts.map +1 -0
- package/dist/esm/lib/constants.js +93 -0
- package/dist/esm/lib/questionnaire-utils.d.ts +21 -1
- package/dist/esm/lib/questionnaire-utils.d.ts.map +1 -1
- package/dist/esm/lib/questionnaire-utils.js +85 -4
- package/dist/esm/types/fhir.d.ts +1 -0
- package/dist/esm/types/fhir.d.ts.map +1 -1
- package/dist/esm/types/index.d.ts +25 -0
- package/dist/esm/types/index.d.ts.map +1 -1
- package/dist/styles.css +108 -0
- package/package.json +17 -6
- package/dist/node_modules/@welshare/questionnaire/.tshy/build.json +0 -8
- package/dist/node_modules/@welshare/questionnaire/.tshy/esm.json +0 -16
- package/dist/node_modules/@welshare/questionnaire/LICENSE +0 -7
- package/dist/node_modules/@welshare/questionnaire/README.md +0 -173
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/debug-section.d.ts +0 -44
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/debug-section.d.ts.map +0 -1
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/debug-section.js +0 -28
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/question-renderer.d.ts +0 -80
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/question-renderer.d.ts.map +0 -1
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/question-renderer.js +0 -159
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/boolean-question.d.ts +0 -15
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/boolean-question.d.ts.map +0 -1
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/boolean-question.js +0 -19
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/choice-question.d.ts +0 -19
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/choice-question.d.ts.map +0 -1
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/choice-question.js +0 -23
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/decimal-question.d.ts +0 -12
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/decimal-question.d.ts.map +0 -1
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/decimal-question.js +0 -7
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/integer-question.d.ts +0 -18
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/integer-question.d.ts.map +0 -1
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/integer-question.js +0 -24
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/multiple-choice-question.d.ts +0 -20
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/multiple-choice-question.d.ts.map +0 -1
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/multiple-choice-question.js +0 -39
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/string-question.d.ts +0 -12
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/string-question.d.ts.map +0 -1
- package/dist/node_modules/@welshare/questionnaire/dist/esm/components/questions/string-question.js +0 -7
- package/dist/node_modules/@welshare/questionnaire/dist/esm/contexts/questionnaire-context.d.ts +0 -41
- package/dist/node_modules/@welshare/questionnaire/dist/esm/contexts/questionnaire-context.d.ts.map +0 -1
- package/dist/node_modules/@welshare/questionnaire/dist/esm/contexts/questionnaire-context.js +0 -350
- package/dist/node_modules/@welshare/questionnaire/dist/esm/index.d.ts +0 -7
- package/dist/node_modules/@welshare/questionnaire/dist/esm/index.d.ts.map +0 -1
- package/dist/node_modules/@welshare/questionnaire/dist/esm/index.js +0 -6
- package/dist/node_modules/@welshare/questionnaire/dist/esm/lib/questionnaire-utils.d.ts +0 -33
- package/dist/node_modules/@welshare/questionnaire/dist/esm/lib/questionnaire-utils.d.ts.map +0 -1
- package/dist/node_modules/@welshare/questionnaire/dist/esm/lib/questionnaire-utils.js +0 -99
- package/dist/node_modules/@welshare/questionnaire/dist/esm/package.json +0 -3
- package/dist/node_modules/@welshare/questionnaire/dist/esm/types/fhir.d.ts +0 -117
- package/dist/node_modules/@welshare/questionnaire/dist/esm/types/fhir.d.ts.map +0 -1
- package/dist/node_modules/@welshare/questionnaire/dist/esm/types/fhir.js +0 -3
- package/dist/node_modules/@welshare/questionnaire/dist/esm/types/index.d.ts +0 -51
- package/dist/node_modules/@welshare/questionnaire/dist/esm/types/index.d.ts.map +0 -1
- package/dist/node_modules/@welshare/questionnaire/dist/esm/types/index.js +0 -1
- package/dist/node_modules/@welshare/questionnaire/dist/styles.css +0 -467
- package/dist/node_modules/@welshare/questionnaire/dist/tokens.css +0 -130
- package/dist/node_modules/@welshare/questionnaire/package.json +0 -85
- package/dist/node_modules/@welshare/questionnaire/src/components/debug-section.tsx +0 -116
- package/dist/node_modules/@welshare/questionnaire/src/components/question-renderer.tsx +0 -368
- package/dist/node_modules/@welshare/questionnaire/src/components/questionnaire-styles.css +0 -467
- package/dist/node_modules/@welshare/questionnaire/src/components/questionnaire-tokens.css +0 -130
- package/dist/node_modules/@welshare/questionnaire/src/components/questions/boolean-question.tsx +0 -72
- package/dist/node_modules/@welshare/questionnaire/src/components/questions/choice-question.tsx +0 -68
- package/dist/node_modules/@welshare/questionnaire/src/components/questions/decimal-question.tsx +0 -32
- package/dist/node_modules/@welshare/questionnaire/src/components/questions/integer-question.tsx +0 -87
- package/dist/node_modules/@welshare/questionnaire/src/components/questions/multiple-choice-question.tsx +0 -119
- package/dist/node_modules/@welshare/questionnaire/src/components/questions/string-question.tsx +0 -31
- package/dist/node_modules/@welshare/questionnaire/src/contexts/questionnaire-context.tsx +0 -499
- package/dist/node_modules/@welshare/questionnaire/src/index.ts +0 -41
- package/dist/node_modules/@welshare/questionnaire/src/lib/__tests__/questionnaire-utils.test.ts +0 -578
- package/dist/node_modules/@welshare/questionnaire/src/lib/questionnaire-utils.ts +0 -122
- package/dist/node_modules/@welshare/questionnaire/src/types/fhir.ts +0 -126
- package/dist/node_modules/@welshare/questionnaire/src/types/index.ts +0 -44
- package/dist/node_modules/@welshare/questionnaire/tsconfig.json +0 -16
package/dist/node_modules/@welshare/questionnaire/src/lib/__tests__/questionnaire-utils.test.ts
DELETED
|
@@ -1,578 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import type { Questionnaire, QuestionnaireItem } from "../../types/fhir.js";
|
|
3
|
-
import { getVisiblePages, getAllQuestionsFromPage } from "../questionnaire-utils.js";
|
|
4
|
-
|
|
5
|
-
describe("questionnaire-utils", () => {
|
|
6
|
-
describe("getVisiblePages", () => {
|
|
7
|
-
it("should return empty array for questionnaire without items", () => {
|
|
8
|
-
const questionnaire: Questionnaire = {
|
|
9
|
-
resourceType: "Questionnaire",
|
|
10
|
-
id: "test-1",
|
|
11
|
-
status: "active",
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
const result = getVisiblePages(questionnaire);
|
|
15
|
-
expect(result).toEqual([]);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it("should return empty array for questionnaire with null items", () => {
|
|
19
|
-
const questionnaire: Questionnaire = {
|
|
20
|
-
resourceType: "Questionnaire",
|
|
21
|
-
id: "test-2",
|
|
22
|
-
status: "active",
|
|
23
|
-
item: undefined,
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const result = getVisiblePages(questionnaire);
|
|
27
|
-
expect(result).toEqual([]);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it("should return visible group items only", () => {
|
|
31
|
-
const questionnaire: Questionnaire = {
|
|
32
|
-
resourceType: "Questionnaire",
|
|
33
|
-
id: "test-3",
|
|
34
|
-
status: "active",
|
|
35
|
-
item: [
|
|
36
|
-
{
|
|
37
|
-
linkId: "page1",
|
|
38
|
-
type: "group",
|
|
39
|
-
text: "Page 1",
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
linkId: "page2",
|
|
43
|
-
type: "group",
|
|
44
|
-
text: "Page 2",
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
linkId: "q1",
|
|
48
|
-
type: "string",
|
|
49
|
-
text: "Question 1",
|
|
50
|
-
},
|
|
51
|
-
],
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const result = getVisiblePages(questionnaire);
|
|
55
|
-
expect(result).toHaveLength(2);
|
|
56
|
-
expect(result[0].linkId).toBe("page1");
|
|
57
|
-
expect(result[1].linkId).toBe("page2");
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it("should exclude hidden group items", () => {
|
|
61
|
-
const questionnaire: Questionnaire = {
|
|
62
|
-
resourceType: "Questionnaire",
|
|
63
|
-
id: "test-4",
|
|
64
|
-
status: "active",
|
|
65
|
-
item: [
|
|
66
|
-
{
|
|
67
|
-
linkId: "page1",
|
|
68
|
-
type: "group",
|
|
69
|
-
text: "Page 1",
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
linkId: "page2",
|
|
73
|
-
type: "group",
|
|
74
|
-
text: "Page 2",
|
|
75
|
-
extension: [
|
|
76
|
-
{
|
|
77
|
-
url: "http://hl7.org/fhir/StructureDefinition/questionnaire-hidden",
|
|
78
|
-
valueBoolean: true,
|
|
79
|
-
},
|
|
80
|
-
],
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
linkId: "page3",
|
|
84
|
-
type: "group",
|
|
85
|
-
text: "Page 3",
|
|
86
|
-
},
|
|
87
|
-
],
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
const result = getVisiblePages(questionnaire);
|
|
91
|
-
expect(result).toHaveLength(2);
|
|
92
|
-
expect(result[0].linkId).toBe("page1");
|
|
93
|
-
expect(result[1].linkId).toBe("page3");
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it("should exclude non-group items", () => {
|
|
97
|
-
const questionnaire: Questionnaire = {
|
|
98
|
-
resourceType: "Questionnaire",
|
|
99
|
-
id: "test-5",
|
|
100
|
-
status: "active",
|
|
101
|
-
item: [
|
|
102
|
-
{
|
|
103
|
-
linkId: "page1",
|
|
104
|
-
type: "group",
|
|
105
|
-
text: "Page 1",
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
linkId: "q1",
|
|
109
|
-
type: "string",
|
|
110
|
-
text: "Question 1",
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
linkId: "q2",
|
|
114
|
-
type: "boolean",
|
|
115
|
-
text: "Question 2",
|
|
116
|
-
},
|
|
117
|
-
],
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
const result = getVisiblePages(questionnaire);
|
|
121
|
-
expect(result).toHaveLength(1);
|
|
122
|
-
expect(result[0].linkId).toBe("page1");
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it("should handle group with hidden extension set to false", () => {
|
|
126
|
-
const questionnaire: Questionnaire = {
|
|
127
|
-
resourceType: "Questionnaire",
|
|
128
|
-
id: "test-6",
|
|
129
|
-
status: "active",
|
|
130
|
-
item: [
|
|
131
|
-
{
|
|
132
|
-
linkId: "page1",
|
|
133
|
-
type: "group",
|
|
134
|
-
text: "Page 1",
|
|
135
|
-
extension: [
|
|
136
|
-
{
|
|
137
|
-
url: "http://hl7.org/fhir/StructureDefinition/questionnaire-hidden",
|
|
138
|
-
valueBoolean: false,
|
|
139
|
-
},
|
|
140
|
-
],
|
|
141
|
-
},
|
|
142
|
-
],
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
const result = getVisiblePages(questionnaire);
|
|
146
|
-
expect(result).toHaveLength(1);
|
|
147
|
-
expect(result[0].linkId).toBe("page1");
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it("should handle nested group structures", () => {
|
|
151
|
-
const questionnaire: Questionnaire = {
|
|
152
|
-
resourceType: "Questionnaire",
|
|
153
|
-
id: "test-7",
|
|
154
|
-
status: "active",
|
|
155
|
-
item: [
|
|
156
|
-
{
|
|
157
|
-
linkId: "page1",
|
|
158
|
-
type: "group",
|
|
159
|
-
text: "Page 1",
|
|
160
|
-
item: [
|
|
161
|
-
{
|
|
162
|
-
linkId: "nested-group",
|
|
163
|
-
type: "group",
|
|
164
|
-
text: "Nested Group",
|
|
165
|
-
},
|
|
166
|
-
],
|
|
167
|
-
},
|
|
168
|
-
{
|
|
169
|
-
linkId: "page2",
|
|
170
|
-
type: "group",
|
|
171
|
-
text: "Page 2",
|
|
172
|
-
},
|
|
173
|
-
],
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
const result = getVisiblePages(questionnaire);
|
|
177
|
-
expect(result).toHaveLength(2);
|
|
178
|
-
expect(result[0].linkId).toBe("page1");
|
|
179
|
-
expect(result[1].linkId).toBe("page2");
|
|
180
|
-
});
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
describe("getAllQuestionsFromPage", () => {
|
|
184
|
-
it("should return empty array for page without items", () => {
|
|
185
|
-
const pageItem: QuestionnaireItem = {
|
|
186
|
-
linkId: "page1",
|
|
187
|
-
type: "group",
|
|
188
|
-
text: "Page 1",
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
const result = getAllQuestionsFromPage(pageItem);
|
|
192
|
-
expect(result).toEqual([]);
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
it("should return empty array for page with null items", () => {
|
|
196
|
-
const pageItem: QuestionnaireItem = {
|
|
197
|
-
linkId: "page1",
|
|
198
|
-
type: "group",
|
|
199
|
-
text: "Page 1",
|
|
200
|
-
item: undefined,
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
const result = getAllQuestionsFromPage(pageItem);
|
|
204
|
-
expect(result).toEqual([]);
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
it("should return all questions from a flat page", () => {
|
|
208
|
-
const pageItem: QuestionnaireItem = {
|
|
209
|
-
linkId: "page1",
|
|
210
|
-
type: "group",
|
|
211
|
-
text: "Page 1",
|
|
212
|
-
item: [
|
|
213
|
-
{
|
|
214
|
-
linkId: "q1",
|
|
215
|
-
type: "string",
|
|
216
|
-
text: "Question 1",
|
|
217
|
-
},
|
|
218
|
-
{
|
|
219
|
-
linkId: "q2",
|
|
220
|
-
type: "boolean",
|
|
221
|
-
text: "Question 2",
|
|
222
|
-
},
|
|
223
|
-
{
|
|
224
|
-
linkId: "q3",
|
|
225
|
-
type: "integer",
|
|
226
|
-
text: "Question 3",
|
|
227
|
-
},
|
|
228
|
-
],
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
const result = getAllQuestionsFromPage(pageItem);
|
|
232
|
-
expect(result).toHaveLength(3);
|
|
233
|
-
expect(result[0].linkId).toBe("q1");
|
|
234
|
-
expect(result[1].linkId).toBe("q2");
|
|
235
|
-
expect(result[2].linkId).toBe("q3");
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
it("should exclude display items", () => {
|
|
239
|
-
const pageItem: QuestionnaireItem = {
|
|
240
|
-
linkId: "page1",
|
|
241
|
-
type: "group",
|
|
242
|
-
text: "Page 1",
|
|
243
|
-
item: [
|
|
244
|
-
{
|
|
245
|
-
linkId: "display1",
|
|
246
|
-
type: "display",
|
|
247
|
-
text: "This is a display item",
|
|
248
|
-
},
|
|
249
|
-
{
|
|
250
|
-
linkId: "q1",
|
|
251
|
-
type: "string",
|
|
252
|
-
text: "Question 1",
|
|
253
|
-
},
|
|
254
|
-
{
|
|
255
|
-
linkId: "display2",
|
|
256
|
-
type: "display",
|
|
257
|
-
text: "Another display item",
|
|
258
|
-
},
|
|
259
|
-
{
|
|
260
|
-
linkId: "q2",
|
|
261
|
-
type: "boolean",
|
|
262
|
-
text: "Question 2",
|
|
263
|
-
},
|
|
264
|
-
],
|
|
265
|
-
};
|
|
266
|
-
|
|
267
|
-
const result = getAllQuestionsFromPage(pageItem);
|
|
268
|
-
expect(result).toHaveLength(2);
|
|
269
|
-
expect(result[0].linkId).toBe("q1");
|
|
270
|
-
expect(result[1].linkId).toBe("q2");
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
it("should flatten questions from nested groups", () => {
|
|
274
|
-
const pageItem: QuestionnaireItem = {
|
|
275
|
-
linkId: "page1",
|
|
276
|
-
type: "group",
|
|
277
|
-
text: "Page 1",
|
|
278
|
-
item: [
|
|
279
|
-
{
|
|
280
|
-
linkId: "q1",
|
|
281
|
-
type: "string",
|
|
282
|
-
text: "Question 1",
|
|
283
|
-
},
|
|
284
|
-
{
|
|
285
|
-
linkId: "nested-group",
|
|
286
|
-
type: "group",
|
|
287
|
-
text: "Nested Group",
|
|
288
|
-
item: [
|
|
289
|
-
{
|
|
290
|
-
linkId: "q2",
|
|
291
|
-
type: "boolean",
|
|
292
|
-
text: "Question 2",
|
|
293
|
-
},
|
|
294
|
-
{
|
|
295
|
-
linkId: "q3",
|
|
296
|
-
type: "integer",
|
|
297
|
-
text: "Question 3",
|
|
298
|
-
},
|
|
299
|
-
],
|
|
300
|
-
},
|
|
301
|
-
{
|
|
302
|
-
linkId: "q4",
|
|
303
|
-
type: "decimal",
|
|
304
|
-
text: "Question 4",
|
|
305
|
-
},
|
|
306
|
-
],
|
|
307
|
-
};
|
|
308
|
-
|
|
309
|
-
const result = getAllQuestionsFromPage(pageItem);
|
|
310
|
-
expect(result).toHaveLength(4);
|
|
311
|
-
expect(result[0].linkId).toBe("q1");
|
|
312
|
-
expect(result[1].linkId).toBe("q2");
|
|
313
|
-
expect(result[2].linkId).toBe("q3");
|
|
314
|
-
expect(result[3].linkId).toBe("q4");
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
it("should handle deeply nested groups", () => {
|
|
318
|
-
const pageItem: QuestionnaireItem = {
|
|
319
|
-
linkId: "page1",
|
|
320
|
-
type: "group",
|
|
321
|
-
text: "Page 1",
|
|
322
|
-
item: [
|
|
323
|
-
{
|
|
324
|
-
linkId: "q1",
|
|
325
|
-
type: "string",
|
|
326
|
-
text: "Question 1",
|
|
327
|
-
},
|
|
328
|
-
{
|
|
329
|
-
linkId: "level1-group",
|
|
330
|
-
type: "group",
|
|
331
|
-
text: "Level 1 Group",
|
|
332
|
-
item: [
|
|
333
|
-
{
|
|
334
|
-
linkId: "q2",
|
|
335
|
-
type: "boolean",
|
|
336
|
-
text: "Question 2",
|
|
337
|
-
},
|
|
338
|
-
{
|
|
339
|
-
linkId: "level2-group",
|
|
340
|
-
type: "group",
|
|
341
|
-
text: "Level 2 Group",
|
|
342
|
-
item: [
|
|
343
|
-
{
|
|
344
|
-
linkId: "q3",
|
|
345
|
-
type: "integer",
|
|
346
|
-
text: "Question 3",
|
|
347
|
-
},
|
|
348
|
-
{
|
|
349
|
-
linkId: "level3-group",
|
|
350
|
-
type: "group",
|
|
351
|
-
text: "Level 3 Group",
|
|
352
|
-
item: [
|
|
353
|
-
{
|
|
354
|
-
linkId: "q4",
|
|
355
|
-
type: "decimal",
|
|
356
|
-
text: "Question 4",
|
|
357
|
-
},
|
|
358
|
-
],
|
|
359
|
-
},
|
|
360
|
-
],
|
|
361
|
-
},
|
|
362
|
-
],
|
|
363
|
-
},
|
|
364
|
-
{
|
|
365
|
-
linkId: "q5",
|
|
366
|
-
type: "date",
|
|
367
|
-
text: "Question 5",
|
|
368
|
-
},
|
|
369
|
-
],
|
|
370
|
-
};
|
|
371
|
-
|
|
372
|
-
const result = getAllQuestionsFromPage(pageItem);
|
|
373
|
-
expect(result).toHaveLength(5);
|
|
374
|
-
expect(result[0].linkId).toBe("q1");
|
|
375
|
-
expect(result[1].linkId).toBe("q2");
|
|
376
|
-
expect(result[2].linkId).toBe("q3");
|
|
377
|
-
expect(result[3].linkId).toBe("q4");
|
|
378
|
-
expect(result[4].linkId).toBe("q5");
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
it("should exclude display items from nested groups", () => {
|
|
382
|
-
const pageItem: QuestionnaireItem = {
|
|
383
|
-
linkId: "page1",
|
|
384
|
-
type: "group",
|
|
385
|
-
text: "Page 1",
|
|
386
|
-
item: [
|
|
387
|
-
{
|
|
388
|
-
linkId: "q1",
|
|
389
|
-
type: "string",
|
|
390
|
-
text: "Question 1",
|
|
391
|
-
},
|
|
392
|
-
{
|
|
393
|
-
linkId: "nested-group",
|
|
394
|
-
type: "group",
|
|
395
|
-
text: "Nested Group",
|
|
396
|
-
item: [
|
|
397
|
-
{
|
|
398
|
-
linkId: "display1",
|
|
399
|
-
type: "display",
|
|
400
|
-
text: "Display in nested group",
|
|
401
|
-
},
|
|
402
|
-
{
|
|
403
|
-
linkId: "q2",
|
|
404
|
-
type: "boolean",
|
|
405
|
-
text: "Question 2",
|
|
406
|
-
},
|
|
407
|
-
],
|
|
408
|
-
},
|
|
409
|
-
],
|
|
410
|
-
};
|
|
411
|
-
|
|
412
|
-
const result = getAllQuestionsFromPage(pageItem);
|
|
413
|
-
expect(result).toHaveLength(2);
|
|
414
|
-
expect(result[0].linkId).toBe("q1");
|
|
415
|
-
expect(result[1].linkId).toBe("q2");
|
|
416
|
-
});
|
|
417
|
-
|
|
418
|
-
it("should handle mixed nested groups and questions", () => {
|
|
419
|
-
const pageItem: QuestionnaireItem = {
|
|
420
|
-
linkId: "page1",
|
|
421
|
-
type: "group",
|
|
422
|
-
text: "Page 1",
|
|
423
|
-
item: [
|
|
424
|
-
{
|
|
425
|
-
linkId: "section1",
|
|
426
|
-
type: "group",
|
|
427
|
-
text: "Section 1",
|
|
428
|
-
item: [
|
|
429
|
-
{
|
|
430
|
-
linkId: "q1",
|
|
431
|
-
type: "string",
|
|
432
|
-
text: "Question 1",
|
|
433
|
-
},
|
|
434
|
-
{
|
|
435
|
-
linkId: "q2",
|
|
436
|
-
type: "boolean",
|
|
437
|
-
text: "Question 2",
|
|
438
|
-
},
|
|
439
|
-
],
|
|
440
|
-
},
|
|
441
|
-
{
|
|
442
|
-
linkId: "q3",
|
|
443
|
-
type: "integer",
|
|
444
|
-
text: "Question 3",
|
|
445
|
-
},
|
|
446
|
-
{
|
|
447
|
-
linkId: "section2",
|
|
448
|
-
type: "group",
|
|
449
|
-
text: "Section 2",
|
|
450
|
-
item: [
|
|
451
|
-
{
|
|
452
|
-
linkId: "subsection",
|
|
453
|
-
type: "group",
|
|
454
|
-
text: "Subsection",
|
|
455
|
-
item: [
|
|
456
|
-
{
|
|
457
|
-
linkId: "q4",
|
|
458
|
-
type: "decimal",
|
|
459
|
-
text: "Question 4",
|
|
460
|
-
},
|
|
461
|
-
],
|
|
462
|
-
},
|
|
463
|
-
{
|
|
464
|
-
linkId: "q5",
|
|
465
|
-
type: "date",
|
|
466
|
-
text: "Question 5",
|
|
467
|
-
},
|
|
468
|
-
],
|
|
469
|
-
},
|
|
470
|
-
],
|
|
471
|
-
};
|
|
472
|
-
|
|
473
|
-
const result = getAllQuestionsFromPage(pageItem);
|
|
474
|
-
expect(result).toHaveLength(5);
|
|
475
|
-
expect(result.map((q) => q.linkId)).toEqual(["q1", "q2", "q3", "q4", "q5"]);
|
|
476
|
-
});
|
|
477
|
-
|
|
478
|
-
it("should handle all question types", () => {
|
|
479
|
-
const pageItem: QuestionnaireItem = {
|
|
480
|
-
linkId: "page1",
|
|
481
|
-
type: "group",
|
|
482
|
-
text: "Page 1",
|
|
483
|
-
item: [
|
|
484
|
-
{
|
|
485
|
-
linkId: "q1",
|
|
486
|
-
type: "boolean",
|
|
487
|
-
text: "Boolean question",
|
|
488
|
-
},
|
|
489
|
-
{
|
|
490
|
-
linkId: "q2",
|
|
491
|
-
type: "decimal",
|
|
492
|
-
text: "Decimal question",
|
|
493
|
-
},
|
|
494
|
-
{
|
|
495
|
-
linkId: "q3",
|
|
496
|
-
type: "integer",
|
|
497
|
-
text: "Integer question",
|
|
498
|
-
},
|
|
499
|
-
{
|
|
500
|
-
linkId: "q4",
|
|
501
|
-
type: "date",
|
|
502
|
-
text: "Date question",
|
|
503
|
-
},
|
|
504
|
-
{
|
|
505
|
-
linkId: "q5",
|
|
506
|
-
type: "dateTime",
|
|
507
|
-
text: "DateTime question",
|
|
508
|
-
},
|
|
509
|
-
{
|
|
510
|
-
linkId: "q6",
|
|
511
|
-
type: "time",
|
|
512
|
-
text: "Time question",
|
|
513
|
-
},
|
|
514
|
-
{
|
|
515
|
-
linkId: "q7",
|
|
516
|
-
type: "string",
|
|
517
|
-
text: "String question",
|
|
518
|
-
},
|
|
519
|
-
{
|
|
520
|
-
linkId: "q8",
|
|
521
|
-
type: "text",
|
|
522
|
-
text: "Text question",
|
|
523
|
-
},
|
|
524
|
-
{
|
|
525
|
-
linkId: "q9",
|
|
526
|
-
type: "url",
|
|
527
|
-
text: "URL question",
|
|
528
|
-
},
|
|
529
|
-
{
|
|
530
|
-
linkId: "q10",
|
|
531
|
-
type: "choice",
|
|
532
|
-
text: "Choice question",
|
|
533
|
-
},
|
|
534
|
-
{
|
|
535
|
-
linkId: "q11",
|
|
536
|
-
type: "open-choice",
|
|
537
|
-
text: "Open choice question",
|
|
538
|
-
},
|
|
539
|
-
{
|
|
540
|
-
linkId: "q12",
|
|
541
|
-
type: "attachment",
|
|
542
|
-
text: "Attachment question",
|
|
543
|
-
},
|
|
544
|
-
{
|
|
545
|
-
linkId: "q13",
|
|
546
|
-
type: "reference",
|
|
547
|
-
text: "Reference question",
|
|
548
|
-
},
|
|
549
|
-
{
|
|
550
|
-
linkId: "q14",
|
|
551
|
-
type: "quantity",
|
|
552
|
-
text: "Quantity question",
|
|
553
|
-
},
|
|
554
|
-
],
|
|
555
|
-
};
|
|
556
|
-
|
|
557
|
-
const result = getAllQuestionsFromPage(pageItem);
|
|
558
|
-
expect(result).toHaveLength(14);
|
|
559
|
-
expect(result.map((q) => q.type)).toEqual([
|
|
560
|
-
"boolean",
|
|
561
|
-
"decimal",
|
|
562
|
-
"integer",
|
|
563
|
-
"date",
|
|
564
|
-
"dateTime",
|
|
565
|
-
"time",
|
|
566
|
-
"string",
|
|
567
|
-
"text",
|
|
568
|
-
"url",
|
|
569
|
-
"choice",
|
|
570
|
-
"open-choice",
|
|
571
|
-
"attachment",
|
|
572
|
-
"reference",
|
|
573
|
-
"quantity",
|
|
574
|
-
]);
|
|
575
|
-
});
|
|
576
|
-
});
|
|
577
|
-
});
|
|
578
|
-
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import type { Questionnaire, QuestionnaireItem } from "../types/fhir.js";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Get visible pages from a questionnaire (excludes hidden groups)
|
|
5
|
-
*/
|
|
6
|
-
export const getVisiblePages = (questionnaire: Questionnaire): QuestionnaireItem[] => {
|
|
7
|
-
if (!questionnaire.item) return [];
|
|
8
|
-
|
|
9
|
-
return questionnaire.item.filter((item) => {
|
|
10
|
-
// Check if hidden
|
|
11
|
-
const isHidden = item.extension?.some(
|
|
12
|
-
(ext) =>
|
|
13
|
-
ext.url === "http://hl7.org/fhir/StructureDefinition/questionnaire-hidden" &&
|
|
14
|
-
ext.valueBoolean === true
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
// Only include visible group items
|
|
18
|
-
return item.type === "group" && !isHidden;
|
|
19
|
-
});
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Calculate progress percentage
|
|
24
|
-
* @param currentPageIndex 0-based page index
|
|
25
|
-
* @param totalPages Total number of pages
|
|
26
|
-
* @returns Progress percentage (0-100)
|
|
27
|
-
*/
|
|
28
|
-
export const calculateProgress = (currentPageIndex: number, totalPages: number): number => {
|
|
29
|
-
if (totalPages === 0) return 0;
|
|
30
|
-
return ((currentPageIndex + 1) / totalPages) * 100;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Get all questions from a page (flattens nested groups)
|
|
35
|
-
*/
|
|
36
|
-
export const getAllQuestionsFromPage = (pageItem: QuestionnaireItem): QuestionnaireItem[] => {
|
|
37
|
-
const questions: QuestionnaireItem[] = [];
|
|
38
|
-
|
|
39
|
-
const collectQuestions = (items?: QuestionnaireItem[]) => {
|
|
40
|
-
if (!items) return;
|
|
41
|
-
|
|
42
|
-
for (const item of items) {
|
|
43
|
-
if (item.type === "group" && item.item) {
|
|
44
|
-
// Recursively collect from nested groups
|
|
45
|
-
collectQuestions(item.item);
|
|
46
|
-
} else if (item.type !== "display") {
|
|
47
|
-
// Add non-display items (actual questions)
|
|
48
|
-
questions.push(item);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
if (pageItem.item) {
|
|
54
|
-
collectQuestions(pageItem.item);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return questions;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Recursively searches for a questionnaire item by linkId
|
|
62
|
-
*/
|
|
63
|
-
export function findQuestionnaireItem(
|
|
64
|
-
items: QuestionnaireItem[] | undefined,
|
|
65
|
-
linkId: string
|
|
66
|
-
): QuestionnaireItem | null {
|
|
67
|
-
if (!items) return null;
|
|
68
|
-
|
|
69
|
-
for (const item of items) {
|
|
70
|
-
if (item.linkId === linkId) {
|
|
71
|
-
return item;
|
|
72
|
-
}
|
|
73
|
-
// Recursively search nested items
|
|
74
|
-
if (item.item && item.item.length > 0) {
|
|
75
|
-
const found = findQuestionnaireItem(item.item, linkId);
|
|
76
|
-
if (found) return found;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return null;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Check if a question has any answer value
|
|
85
|
-
*/
|
|
86
|
-
export const hasAnswerValue = (answer: any): boolean => {
|
|
87
|
-
if (!answer) return false;
|
|
88
|
-
|
|
89
|
-
return (
|
|
90
|
-
answer.valueBoolean !== undefined ||
|
|
91
|
-
answer.valueInteger !== undefined ||
|
|
92
|
-
answer.valueDecimal !== undefined ||
|
|
93
|
-
answer.valueString !== undefined ||
|
|
94
|
-
answer.valueCoding !== undefined ||
|
|
95
|
-
answer.valueDate !== undefined ||
|
|
96
|
-
answer.valueDateTime !== undefined ||
|
|
97
|
-
answer.valueTime !== undefined ||
|
|
98
|
-
answer.valueUri !== undefined ||
|
|
99
|
-
answer.valueQuantity !== undefined
|
|
100
|
-
);
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Check if a question item should be hidden based on extensions
|
|
105
|
-
*/
|
|
106
|
-
export const isQuestionHidden = (item: QuestionnaireItem): boolean => {
|
|
107
|
-
return item.extension?.some(
|
|
108
|
-
(ext) =>
|
|
109
|
-
ext.url === "http://hl7.org/fhir/StructureDefinition/questionnaire-hidden" &&
|
|
110
|
-
ext.valueBoolean === true
|
|
111
|
-
) ?? false;
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Get the exclusive option code from a question item (if any)
|
|
116
|
-
*/
|
|
117
|
-
export const getExclusiveOptionCode = (item: QuestionnaireItem): string | undefined => {
|
|
118
|
-
const exclusiveExt = item.extension?.find(
|
|
119
|
-
(ext) => ext.url === "http://codes.welshare.app/StructureDefinition/questionnaire-exclusive-option"
|
|
120
|
-
);
|
|
121
|
-
return exclusiveExt?.valueString;
|
|
122
|
-
};
|