@aehrc/smart-forms-renderer 0.27.2 → 0.27.4
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/.storybook/main.ts +2 -1
- package/.storybook/preview.ts +6 -1
- package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionFields.d.ts +3 -2
- package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionFields.js +9 -17
- package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionFields.js.map +1 -1
- package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionItem.js +12 -9
- package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionItem.js.map +1 -1
- package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetFields.d.ts +2 -2
- package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetFields.js +7 -9
- package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetFields.js.map +1 -1
- package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetItem.js +12 -8
- package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetItem.js.map +1 -1
- package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.d.ts +2 -1
- package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.js +3 -3
- package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.js.map +1 -1
- package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionItem.js +6 -4
- package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionItem.js.map +1 -1
- package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionView.d.ts +2 -1
- package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionView.js +3 -3
- package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionView.js.map +1 -1
- package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.d.ts +2 -2
- package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.js +5 -7
- package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.js.map +1 -1
- package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetItem.js +4 -4
- package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetItem.js.map +1 -1
- package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.d.ts +2 -1
- package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.js +2 -3
- package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.js.map +1 -1
- package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionItem.js +5 -3
- package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionItem.js.map +1 -1
- package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionView.d.ts +2 -1
- package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionView.js +3 -3
- package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionView.js.map +1 -1
- package/lib/components/FormComponents/DecimalItem/DecimalItem.js +1 -1
- package/lib/components/FormComponents/GroupItem/TabButtonsWrapper.js +20 -20
- package/lib/components/FormComponents/GroupItem/TabButtonsWrapper.js.map +1 -1
- package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionFields.d.ts +3 -2
- package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionFields.js +7 -19
- package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionFields.js.map +1 -1
- package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionItem.js +40 -40
- package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionItem.js.map +1 -1
- package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceItemSwitcher.js +15 -3
- package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceItemSwitcher.js.map +1 -1
- package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionFields.d.ts +2 -1
- package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionFields.js +3 -3
- package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionFields.js.map +1 -1
- package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionItem.js +27 -26
- package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionItem.js.map +1 -1
- package/lib/components/FormComponents/StringItem/StringField.js +1 -1
- package/lib/components/FormComponents/StringItem/StringField.js.map +1 -1
- package/lib/hooks/useInitialiseRenderer.js +1 -1
- package/lib/hooks/useInitialiseRenderer.js.map +1 -1
- package/lib/hooks/useNextAndPreviousVisibleTabs.d.ts +7 -0
- package/lib/hooks/useNextAndPreviousVisibleTabs.js +63 -0
- package/lib/hooks/useNextAndPreviousVisibleTabs.js.map +1 -0
- package/lib/hooks/useNextPreviousVisibleTabs.d.ts +6 -0
- package/lib/hooks/useNextPreviousVisibleTabs.js +63 -0
- package/lib/hooks/useNextPreviousVisibleTabs.js.map +1 -0
- package/lib/index.d.ts +0 -7
- package/lib/index.js +0 -24
- package/lib/index.js.map +1 -1
- package/lib/utils/choice.d.ts +1 -7
- package/lib/utils/choice.js +10 -20
- package/lib/utils/choice.js.map +1 -1
- package/lib/utils/enableWhen.js +5 -7
- package/lib/utils/enableWhen.js.map +1 -1
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.js +1 -0
- package/lib/utils/index.js.map +1 -1
- package/lib/utils/openChoice.d.ts +9 -4
- package/lib/utils/openChoice.js +47 -78
- package/lib/utils/openChoice.js.map +1 -1
- package/lib/utils/tabs.d.ts +0 -21
- package/lib/utils/tabs.js +0 -51
- package/lib/utils/tabs.js.map +1 -1
- package/package.json +4 -4
- package/src/components/FormComponents/ChoiceItems/CheckboxOptionList.tsx +82 -0
- package/src/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionFields.tsx +23 -52
- package/src/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionItem.tsx +15 -9
- package/src/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetFields.tsx +17 -19
- package/src/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetItem.tsx +13 -8
- package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.tsx +5 -4
- package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionItem.tsx +6 -2
- package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionView.tsx +5 -1
- package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.tsx +9 -16
- package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetItem.tsx +4 -4
- package/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.tsx +4 -3
- package/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionItem.tsx +5 -2
- package/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionView.tsx +5 -1
- package/src/components/FormComponents/DecimalItem/DecimalItem.tsx +1 -1
- package/src/components/FormComponents/GroupItem/TabButtonsWrapper.tsx +28 -25
- package/src/components/FormComponents/ItemParts/{RadioAnswerOptionButtons.tsx → RadioOptionList.tsx} +7 -7
- package/src/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionFields.tsx +18 -50
- package/src/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionItem.tsx +70 -68
- package/src/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerValueSetFields.tsx +110 -0
- package/src/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerValueSetItem.tsx +188 -0
- package/src/components/FormComponents/OpenChoiceItems/OpenChoiceItemSwitcher.tsx +46 -19
- package/src/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionFields.tsx +5 -3
- package/src/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionItem.tsx +37 -29
- package/src/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerValueSetFields.tsx +104 -0
- package/src/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerValueSetItem.tsx +156 -0
- package/src/components/FormComponents/StringItem/StringField.tsx +1 -1
- package/src/hooks/useInitialiseRenderer.ts +1 -1
- package/src/hooks/useNextAndPreviousVisibleTabs.ts +86 -0
- package/src/hooks/useOpenLabel.ts +43 -0
- package/src/index.ts +0 -21
- package/src/stories/BuildFormWrapper.tsx +57 -0
- package/src/stories/assets/questionnaires/QAdvancedAdditionalDisplayContent.ts +83 -0
- package/src/stories/assets/questionnaires/QAdvancedControlAppearance.ts +294 -0
- package/src/stories/assets/questionnaires/QAdvancedOther.ts +495 -0
- package/src/stories/assets/questionnaires/QAdvancedTextApperance.ts +188 -0
- package/src/stories/assets/questionnaires/QAttachment.ts +38 -0
- package/src/stories/assets/questionnaires/QBehaviorCalculations.ts +645 -0
- package/src/stories/assets/questionnaires/QBehaviorChoiceRestriction.ts +281 -0
- package/src/stories/assets/questionnaires/QBehaviorOther.ts +1149 -0
- package/src/stories/assets/questionnaires/QBehaviorValueConstraints.ts +508 -0
- package/src/stories/assets/questionnaires/QBoolean.ts +130 -0
- package/src/stories/assets/questionnaires/QChoice.ts +137 -0
- package/src/stories/assets/questionnaires/QDate.ts +56 -0
- package/src/stories/assets/questionnaires/QDateTime.ts +56 -0
- package/src/stories/assets/questionnaires/QDecimal.ts +56 -0
- package/src/stories/assets/questionnaires/QDisplay.ts +38 -0
- package/src/stories/assets/questionnaires/QGroup.ts +52 -0
- package/src/stories/assets/questionnaires/QInteger.ts +119 -0
- package/src/stories/assets/questionnaires/QItemControlDisplay.ts +114 -0
- package/src/stories/assets/questionnaires/QItemControlGroup.ts +419 -0
- package/src/stories/assets/questionnaires/QItemControlQuestion.ts +1271 -0
- package/src/stories/assets/questionnaires/QOpenChoice.ts +151 -0
- package/src/stories/assets/questionnaires/QQuantity.ts +38 -0
- package/src/stories/assets/questionnaires/QReference.ts +38 -0
- package/src/stories/assets/questionnaires/QSingleItems.ts +251 -0
- package/src/stories/assets/questionnaires/QString.ts +131 -0
- package/src/stories/assets/questionnaires/QText.ts +169 -0
- package/src/stories/assets/questionnaires/QTime.ts +38 -0
- package/src/stories/assets/questionnaires/QUrl.ts +38 -0
- package/src/stories/assets/questionnaires/index.ts +44 -0
- package/src/stories/itemTypes/Attachment.stories.tsx +39 -0
- package/src/stories/itemTypes/Boolean.stories.tsx +72 -0
- package/src/stories/{MedicalHistoryTable.stories.tsx → itemTypes/Choice.stories.tsx} +32 -26
- package/src/stories/itemTypes/Date.stories.tsx +46 -0
- package/src/stories/itemTypes/DateTime.stories.tsx +45 -0
- package/src/stories/itemTypes/Decimal.stories.tsx +56 -0
- package/src/stories/itemTypes/Display.stories.tsx +39 -0
- package/src/stories/itemTypes/Group.stories.tsx +39 -0
- package/src/stories/itemTypes/Integer.stories.tsx +55 -0
- package/src/stories/itemTypes/OpenChoice.stories.tsx +64 -0
- package/src/stories/itemTypes/Quantity.stories.tsx +39 -0
- package/src/stories/itemTypes/Reference.stories.tsx +39 -0
- package/src/stories/itemTypes/String.stories.tsx +51 -0
- package/src/stories/itemTypes/Text.stories.tsx +51 -0
- package/src/stories/itemTypes/Time.stories.tsx +39 -0
- package/src/stories/itemTypes/Url.stories.tsx +39 -0
- package/src/stories/sdc/AdvancedAdditionalDisplayContent.stories.tsx +45 -0
- package/src/stories/sdc/AdvancedControlAppearance.stories.tsx +51 -0
- package/src/stories/sdc/AdvancedOther.stories.tsx +76 -0
- package/src/stories/sdc/AdvancedTextAppearance.stories.tsx +69 -0
- package/src/stories/sdc/BehaviorCalculations.stories.tsx +69 -0
- package/src/stories/sdc/BehaviorChoiceRestriction.stories.tsx +76 -0
- package/src/stories/sdc/BehaviorOther.stories.tsx +90 -0
- package/src/stories/sdc/BehaviorValueConstraints.stories.tsx +88 -0
- package/src/stories/sdc/ItemControlDisplay.stories.tsx +39 -0
- package/src/stories/sdc/ItemControlGroup.stories.tsx +55 -0
- package/src/stories/sdc/ItemControlQuestion.stories.tsx +118 -0
- package/src/utils/buildForm.ts +23 -0
- package/src/utils/choice.ts +16 -23
- package/src/utils/enableWhen.ts +5 -7
- package/src/utils/index.ts +1 -0
- package/src/utils/openChoice.ts +83 -98
- package/src/utils/tabs.ts +0 -75
- package/vite.config.ts +23 -0
- package/doctor-storybook.log +0 -18
- package/src/stories/SmartFormsRenderer.stories.ts +0 -139
- package/src/stories/assets/QItems-and-QRItems/QR_GTableMedicalHistory.json +0 -80
- package/src/stories/assets/QItems-and-QRItems/Q_GTableMedicalHistory.json +0 -109
- package/src/stories/assets/Qs-and-QRs/Q715.json +0 -15086
- package/src/stories/assets/Qs-and-QRs/QDev715.json +0 -16081
- package/src/stories/assets/Qs-and-QRs/QTestGrid.json +0 -411
- package/src/stories/assets/Qs-and-QRs/R715.json +0 -311
- package/src/stories/assets/Qs-and-QRs/RTestGrid.json +0 -34
|
@@ -45,20 +45,21 @@ function OpenChoiceRadioAnswerOptionItem(props: OpenChoiceRadioAnswerOptionItemP
|
|
|
45
45
|
|
|
46
46
|
const onFocusLinkId = useQuestionnaireStore.use.onFocusLinkId();
|
|
47
47
|
|
|
48
|
-
const readOnly = useReadOnly(qItem, parentIsReadOnly);
|
|
49
|
-
const openLabelText = getOpenLabelText(qItem);
|
|
50
|
-
|
|
51
48
|
// Init answers
|
|
52
49
|
const qrOpenChoiceRadio = qrItem ?? createEmptyQrItem(qItem);
|
|
53
50
|
let valueRadio: string | null = getQrChoiceValue(qrOpenChoiceRadio, true);
|
|
54
51
|
const answers = qrOpenChoiceRadio.answer ?? [];
|
|
55
52
|
|
|
53
|
+
const readOnly = useReadOnly(qItem, parentIsReadOnly);
|
|
54
|
+
const openLabelText = getOpenLabelText(qItem);
|
|
55
|
+
|
|
56
|
+
const options = qItem.answerOption ?? [];
|
|
57
|
+
|
|
56
58
|
// Init empty open label
|
|
57
|
-
const answerOptions = qItem.answerOption;
|
|
58
59
|
let initialOpenLabelValue = '';
|
|
59
60
|
let initialOpenLabelSelected = false;
|
|
60
|
-
if (
|
|
61
|
-
const oldLabelAnswer = getOldOpenLabelAnswer(answers,
|
|
61
|
+
if (options) {
|
|
62
|
+
const oldLabelAnswer = getOldOpenLabelAnswer(answers, options);
|
|
62
63
|
if (oldLabelAnswer && oldLabelAnswer.valueString) {
|
|
63
64
|
initialOpenLabelValue = oldLabelAnswer.valueString;
|
|
64
65
|
initialOpenLabelSelected = true;
|
|
@@ -79,40 +80,46 @@ function OpenChoiceRadioAnswerOptionItem(props: OpenChoiceRadioAnswerOptionItemP
|
|
|
79
80
|
changedOptionValue: string | null,
|
|
80
81
|
changedOpenLabelValue: string | null
|
|
81
82
|
) {
|
|
82
|
-
if (
|
|
83
|
+
if (options.length === 0) {
|
|
84
|
+
onQrItemChange(createEmptyQrItem(qItem));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
83
87
|
|
|
84
88
|
if (changedOptionValue !== null) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
} else {
|
|
93
|
-
// Otherwise, it is an open-label selection
|
|
94
|
-
onQrItemChange({
|
|
95
|
-
...createEmptyQrItem(qItem),
|
|
96
|
-
answer: [{ valueString: changedOptionValue }]
|
|
97
|
-
});
|
|
98
|
-
setOpenLabelValue(changedOptionValue);
|
|
99
|
-
setOpenLabelSelected(true);
|
|
100
|
-
}
|
|
89
|
+
const qrAnswer = findInAnswerOptions(options, changedOptionValue);
|
|
90
|
+
|
|
91
|
+
// If selected answer can be found in options, it is a non-open label selection
|
|
92
|
+
if (qrAnswer) {
|
|
93
|
+
onQrItemChange({ ...createEmptyQrItem(qItem), answer: [qrAnswer] });
|
|
94
|
+
setOpenLabelSelected(false);
|
|
95
|
+
return;
|
|
101
96
|
}
|
|
97
|
+
|
|
98
|
+
// Otherwise, it is an open-label selection
|
|
99
|
+
onQrItemChange({
|
|
100
|
+
...createEmptyQrItem(qItem),
|
|
101
|
+
answer: [{ valueString: changedOptionValue }]
|
|
102
|
+
});
|
|
103
|
+
setOpenLabelValue(changedOptionValue);
|
|
104
|
+
setOpenLabelSelected(true);
|
|
105
|
+
return;
|
|
102
106
|
}
|
|
103
107
|
|
|
104
108
|
if (changedOpenLabelValue !== null) {
|
|
105
109
|
setOpenLabelValue(changedOpenLabelValue);
|
|
106
110
|
|
|
111
|
+
// If open label is unchecked, remove it from answers
|
|
107
112
|
if (changedOpenLabelValue === '') {
|
|
108
113
|
onQrItemChange(createEmptyQrItem(qItem));
|
|
109
|
-
|
|
110
|
-
setOpenLabelValue(changedOpenLabelValue);
|
|
111
|
-
onQrItemChange({
|
|
112
|
-
...createEmptyQrItem(qItem),
|
|
113
|
-
answer: [{ valueString: changedOpenLabelValue }]
|
|
114
|
-
});
|
|
114
|
+
return;
|
|
115
115
|
}
|
|
116
|
+
|
|
117
|
+
// Otherwise, add open label to answers
|
|
118
|
+
setOpenLabelValue(changedOpenLabelValue);
|
|
119
|
+
onQrItemChange({
|
|
120
|
+
...createEmptyQrItem(qItem),
|
|
121
|
+
answer: [{ valueString: changedOpenLabelValue }]
|
|
122
|
+
});
|
|
116
123
|
}
|
|
117
124
|
}
|
|
118
125
|
|
|
@@ -124,6 +131,7 @@ function OpenChoiceRadioAnswerOptionItem(props: OpenChoiceRadioAnswerOptionItemP
|
|
|
124
131
|
<ItemFieldGrid qItem={qItem} readOnly={readOnly}>
|
|
125
132
|
<OpenChoiceRadioAnswerOptionFields
|
|
126
133
|
qItem={qItem}
|
|
134
|
+
options={options}
|
|
127
135
|
valueRadio={valueRadio}
|
|
128
136
|
openLabelText={openLabelText}
|
|
129
137
|
openLabelValue={openLabelValue}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2024 Commonwealth Scientific and Industrial Research
|
|
3
|
+
* Organisation (CSIRO) ABN 41 687 119 230.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { ChangeEvent } from 'react';
|
|
19
|
+
import React from 'react';
|
|
20
|
+
import { ChoiceItemOrientation } from '../../../interfaces/choice.enum';
|
|
21
|
+
import type { QuestionnaireItem, QuestionnaireItemAnswerOption } from 'fhir/r4';
|
|
22
|
+
import { StyledRadioGroup } from '../Item.styles';
|
|
23
|
+
import RadioButtonWithOpenLabel from '../ItemParts/RadioButtonWithOpenLabel';
|
|
24
|
+
import RadioOptionList from '../ItemParts/RadioOptionList';
|
|
25
|
+
import { getChoiceOrientation } from '../../../utils/choice';
|
|
26
|
+
import type { TerminologyError } from '../../../hooks/useValueSetCodings';
|
|
27
|
+
import { StyledAlert } from '../../Alert.styles';
|
|
28
|
+
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
|
|
29
|
+
import Typography from '@mui/material/Typography';
|
|
30
|
+
|
|
31
|
+
interface OpenChoiceRadioAnswerValueSetFieldsProps {
|
|
32
|
+
qItem: QuestionnaireItem;
|
|
33
|
+
options: QuestionnaireItemAnswerOption[];
|
|
34
|
+
valueRadio: string | null;
|
|
35
|
+
openLabelText: string | null;
|
|
36
|
+
openLabelValue: string | null;
|
|
37
|
+
openLabelSelected: boolean;
|
|
38
|
+
readOnly: boolean;
|
|
39
|
+
terminologyError: TerminologyError;
|
|
40
|
+
onValueChange: (changedOptionValue: string | null, changedOpenLabelValue: string | null) => void;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function OpenChoiceRadioAnswerValueSetFields(props: OpenChoiceRadioAnswerValueSetFieldsProps) {
|
|
44
|
+
const {
|
|
45
|
+
qItem,
|
|
46
|
+
options,
|
|
47
|
+
valueRadio,
|
|
48
|
+
openLabelText,
|
|
49
|
+
openLabelValue,
|
|
50
|
+
openLabelSelected,
|
|
51
|
+
readOnly,
|
|
52
|
+
terminologyError,
|
|
53
|
+
onValueChange
|
|
54
|
+
} = props;
|
|
55
|
+
|
|
56
|
+
const orientation = getChoiceOrientation(qItem) ?? ChoiceItemOrientation.Vertical;
|
|
57
|
+
|
|
58
|
+
if (options.length > 0) {
|
|
59
|
+
return (
|
|
60
|
+
<StyledRadioGroup
|
|
61
|
+
row={orientation === ChoiceItemOrientation.Horizontal}
|
|
62
|
+
name={qItem.text}
|
|
63
|
+
id={qItem.id}
|
|
64
|
+
onChange={(e: ChangeEvent<HTMLInputElement>) => onValueChange(e.target.value, null)}
|
|
65
|
+
value={valueRadio}
|
|
66
|
+
data-test="q-item-radio-group">
|
|
67
|
+
<RadioOptionList options={options} readOnly={readOnly} />
|
|
68
|
+
|
|
69
|
+
{openLabelText ? (
|
|
70
|
+
<RadioButtonWithOpenLabel
|
|
71
|
+
value={openLabelValue}
|
|
72
|
+
label={openLabelText}
|
|
73
|
+
readOnly={readOnly}
|
|
74
|
+
isSelected={openLabelSelected}
|
|
75
|
+
onInputChange={(input) => onValueChange(null, input)}
|
|
76
|
+
/>
|
|
77
|
+
) : null}
|
|
78
|
+
</StyledRadioGroup>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (terminologyError.error) {
|
|
83
|
+
return (
|
|
84
|
+
<StyledAlert color="error">
|
|
85
|
+
<ErrorOutlineIcon color="error" sx={{ pr: 0.75 }} />
|
|
86
|
+
<Typography variant="subtitle2">
|
|
87
|
+
There was an error fetching options from the terminology server for{' '}
|
|
88
|
+
{terminologyError.answerValueSet}
|
|
89
|
+
</Typography>
|
|
90
|
+
</StyledAlert>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<StyledAlert color="error">
|
|
96
|
+
<ErrorOutlineIcon color="error" sx={{ pr: 0.75 }} />
|
|
97
|
+
<Typography variant="subtitle2">
|
|
98
|
+
Unable to fetch options from the questionnaire or launch context
|
|
99
|
+
</Typography>
|
|
100
|
+
</StyledAlert>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export default OpenChoiceRadioAnswerValueSetFields;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2024 Commonwealth Scientific and Industrial Research
|
|
3
|
+
* Organisation (CSIRO) ABN 41 687 119 230.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import React, { useMemo, useState } from 'react';
|
|
19
|
+
import type { QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/r4';
|
|
20
|
+
import { createEmptyQrItem } from '../../../utils/qrItem';
|
|
21
|
+
import { getOpenLabelText } from '../../../utils/itemControl';
|
|
22
|
+
import { getOldOpenLabelAnswer } from '../../../utils/openChoice';
|
|
23
|
+
import { FullWidthFormComponentBox } from '../../Box.styles';
|
|
24
|
+
import {
|
|
25
|
+
convertCodingsToAnswerOptions,
|
|
26
|
+
findInAnswerOptions,
|
|
27
|
+
getQrChoiceValue
|
|
28
|
+
} from '../../../utils/choice';
|
|
29
|
+
import type {
|
|
30
|
+
PropsWithIsRepeatedAttribute,
|
|
31
|
+
PropsWithParentIsReadOnlyAttribute,
|
|
32
|
+
PropsWithQrItemChangeHandler
|
|
33
|
+
} from '../../../interfaces/renderProps.interface';
|
|
34
|
+
import OpenChoiceRadioAnswerValueSetFields from './OpenChoiceRadioAnswerValueSetFields';
|
|
35
|
+
import useReadOnly from '../../../hooks/useReadOnly';
|
|
36
|
+
import ItemFieldGrid from '../ItemParts/ItemFieldGrid';
|
|
37
|
+
import { useQuestionnaireStore } from '../../../stores';
|
|
38
|
+
import useValueSetCodings from '../../../hooks/useValueSetCodings';
|
|
39
|
+
|
|
40
|
+
interface OpenChoiceRadioAnswerValueSetItemProps
|
|
41
|
+
extends PropsWithQrItemChangeHandler,
|
|
42
|
+
PropsWithIsRepeatedAttribute,
|
|
43
|
+
PropsWithParentIsReadOnlyAttribute {
|
|
44
|
+
qItem: QuestionnaireItem;
|
|
45
|
+
qrItem: QuestionnaireResponseItem | null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function OpenChoiceRadioAnswerValueSetItem(props: OpenChoiceRadioAnswerValueSetItemProps) {
|
|
49
|
+
const { qItem, qrItem, parentIsReadOnly, onQrItemChange } = props;
|
|
50
|
+
|
|
51
|
+
const onFocusLinkId = useQuestionnaireStore.use.onFocusLinkId();
|
|
52
|
+
|
|
53
|
+
// Init answers
|
|
54
|
+
const qrOpenChoiceRadio = qrItem ?? createEmptyQrItem(qItem);
|
|
55
|
+
let valueRadio: string | null = getQrChoiceValue(qrOpenChoiceRadio, true);
|
|
56
|
+
const answers = qrOpenChoiceRadio.answer ?? [];
|
|
57
|
+
|
|
58
|
+
const readOnly = useReadOnly(qItem, parentIsReadOnly);
|
|
59
|
+
const openLabelText = getOpenLabelText(qItem);
|
|
60
|
+
|
|
61
|
+
// Get codings/options from valueSet
|
|
62
|
+
const { codings, terminologyError } = useValueSetCodings(qItem);
|
|
63
|
+
|
|
64
|
+
const options = useMemo(() => convertCodingsToAnswerOptions(codings), [codings]);
|
|
65
|
+
|
|
66
|
+
// Init empty open label
|
|
67
|
+
let initialOpenLabelValue = '';
|
|
68
|
+
let initialOpenLabelSelected = false;
|
|
69
|
+
if (options) {
|
|
70
|
+
const oldLabelAnswer = getOldOpenLabelAnswer(answers, options);
|
|
71
|
+
if (oldLabelAnswer && oldLabelAnswer.valueString) {
|
|
72
|
+
initialOpenLabelValue = oldLabelAnswer.valueString;
|
|
73
|
+
initialOpenLabelSelected = true;
|
|
74
|
+
valueRadio = initialOpenLabelValue;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const [openLabelValue, setOpenLabelValue] = useState<string | null>(initialOpenLabelValue);
|
|
79
|
+
const [openLabelSelected, setOpenLabelSelected] = useState(initialOpenLabelSelected);
|
|
80
|
+
|
|
81
|
+
// Allow open label to remain selected even if its input was cleared
|
|
82
|
+
if (openLabelSelected && valueRadio === null) {
|
|
83
|
+
valueRadio = '';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Event handlers
|
|
87
|
+
function handleValueChange(
|
|
88
|
+
changedOptionValue: string | null,
|
|
89
|
+
changedOpenLabelValue: string | null
|
|
90
|
+
) {
|
|
91
|
+
if (options.length === 0) {
|
|
92
|
+
onQrItemChange(createEmptyQrItem(qItem));
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (changedOptionValue !== null) {
|
|
97
|
+
const qrAnswer = findInAnswerOptions(options, changedOptionValue);
|
|
98
|
+
|
|
99
|
+
// If selected answer can be found in options, it is a non-open label selection
|
|
100
|
+
if (qrAnswer) {
|
|
101
|
+
onQrItemChange({ ...createEmptyQrItem(qItem), answer: [qrAnswer] });
|
|
102
|
+
setOpenLabelSelected(false);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Otherwise, it is an open-label selection
|
|
107
|
+
onQrItemChange({
|
|
108
|
+
...createEmptyQrItem(qItem),
|
|
109
|
+
answer: [{ valueString: changedOptionValue }]
|
|
110
|
+
});
|
|
111
|
+
setOpenLabelValue(changedOptionValue);
|
|
112
|
+
setOpenLabelSelected(true);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (changedOpenLabelValue !== null) {
|
|
117
|
+
setOpenLabelValue(changedOpenLabelValue);
|
|
118
|
+
|
|
119
|
+
// If open label is unchecked, remove it from answers
|
|
120
|
+
if (changedOpenLabelValue === '') {
|
|
121
|
+
onQrItemChange(createEmptyQrItem(qItem));
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Otherwise, add open label to answers
|
|
126
|
+
setOpenLabelValue(changedOpenLabelValue);
|
|
127
|
+
onQrItemChange({
|
|
128
|
+
...createEmptyQrItem(qItem),
|
|
129
|
+
answer: [{ valueString: changedOpenLabelValue }]
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return (
|
|
135
|
+
<FullWidthFormComponentBox
|
|
136
|
+
data-test="q-item-open-choice-radio-answer-option-box"
|
|
137
|
+
data-linkid={qItem.linkId}
|
|
138
|
+
onClick={() => onFocusLinkId(qItem.linkId)}>
|
|
139
|
+
<ItemFieldGrid qItem={qItem} readOnly={readOnly}>
|
|
140
|
+
<OpenChoiceRadioAnswerValueSetFields
|
|
141
|
+
qItem={qItem}
|
|
142
|
+
options={options}
|
|
143
|
+
valueRadio={valueRadio}
|
|
144
|
+
openLabelText={openLabelText}
|
|
145
|
+
openLabelValue={openLabelValue}
|
|
146
|
+
openLabelSelected={openLabelSelected}
|
|
147
|
+
readOnly={readOnly}
|
|
148
|
+
terminologyError={terminologyError}
|
|
149
|
+
onValueChange={handleValueChange}
|
|
150
|
+
/>
|
|
151
|
+
</ItemFieldGrid>
|
|
152
|
+
</FullWidthFormComponentBox>
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export default OpenChoiceRadioAnswerValueSetItem;
|
|
@@ -61,7 +61,7 @@ function StringField(props: StringFieldProps) {
|
|
|
61
61
|
size="small"
|
|
62
62
|
InputProps={{
|
|
63
63
|
endAdornment: (
|
|
64
|
-
<InputAdornment position=
|
|
64
|
+
<InputAdornment position="end">
|
|
65
65
|
<FadingCheckIcon fadeIn={calcExpUpdated} disabled={readOnly} />
|
|
66
66
|
{displayUnit}
|
|
67
67
|
</InputAdornment>
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4';
|
|
19
19
|
import { useLayoutEffect, useState } from 'react';
|
|
20
|
-
import { initialiseQuestionnaireResponse } from '../utils
|
|
20
|
+
import { initialiseQuestionnaireResponse } from '../utils';
|
|
21
21
|
import type Client from 'fhirclient/lib/Client';
|
|
22
22
|
import { readEncounter, readPatient, readUser } from '../api/smartClient';
|
|
23
23
|
import {
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2024 Commonwealth Scientific and Industrial Research
|
|
3
|
+
* Organisation (CSIRO) ABN 41 687 119 230.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { useQuestionnaireStore } from '../stores';
|
|
19
|
+
import type { Tabs } from '../interfaces/tab.interface';
|
|
20
|
+
import { constructTabsWithVisibility } from '../utils/tabs';
|
|
21
|
+
|
|
22
|
+
function useNextAndPreviousVisibleTabs(
|
|
23
|
+
currentTabIndex?: number,
|
|
24
|
+
tabs?: Tabs
|
|
25
|
+
): { previousTabIndex: number | null; nextTabIndex: number | null; numOfVisibleTabs: number } {
|
|
26
|
+
const enableWhenIsActivated = useQuestionnaireStore.use.enableWhenIsActivated();
|
|
27
|
+
const enableWhenItems = useQuestionnaireStore.use.enableWhenItems();
|
|
28
|
+
const enableWhenExpressions = useQuestionnaireStore.use.enableWhenExpressions();
|
|
29
|
+
|
|
30
|
+
const tabsNotDefined = currentTabIndex === undefined || tabs === undefined;
|
|
31
|
+
|
|
32
|
+
if (tabsNotDefined) {
|
|
33
|
+
return { previousTabIndex: null, nextTabIndex: null, numOfVisibleTabs: 0 };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const tabsWithVisibility = constructTabsWithVisibility({
|
|
37
|
+
tabs,
|
|
38
|
+
enableWhenIsActivated,
|
|
39
|
+
enableWhenItems,
|
|
40
|
+
enableWhenExpressions
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
previousTabIndex: getPreviousTabIndex(currentTabIndex, tabsWithVisibility),
|
|
45
|
+
nextTabIndex: getNextTabIndex(currentTabIndex, tabsWithVisibility),
|
|
46
|
+
numOfVisibleTabs: tabsWithVisibility.filter((tab) => tab.isVisible).length
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function getPreviousTabIndex(
|
|
51
|
+
currentTabIndex: number,
|
|
52
|
+
tabsWithVisibility: { linkId: string; isVisible: boolean }[]
|
|
53
|
+
): number | null {
|
|
54
|
+
const previousTabs = tabsWithVisibility.slice(0, currentTabIndex);
|
|
55
|
+
const foundIndex = previousTabs.reverse().findIndex((tab) => tab.isVisible);
|
|
56
|
+
|
|
57
|
+
// Previous visible tab not found
|
|
58
|
+
if (foundIndex === -1) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Previous visible tab less than 0
|
|
63
|
+
const previousTabIndex = currentTabIndex - foundIndex - 1;
|
|
64
|
+
if (previousTabIndex < 0) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return previousTabIndex;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function getNextTabIndex(
|
|
72
|
+
currentTabIndex: number,
|
|
73
|
+
tabsWithVisibility: { linkId: string; isVisible: boolean }[]
|
|
74
|
+
): number | null {
|
|
75
|
+
const subsequentTabs = tabsWithVisibility.slice(currentTabIndex + 1);
|
|
76
|
+
const foundIndex = subsequentTabs.findIndex((tab) => tab.isVisible);
|
|
77
|
+
|
|
78
|
+
// Next visible tab not found, something is wrong
|
|
79
|
+
if (foundIndex === -1) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return currentTabIndex + foundIndex + 1;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export default useNextAndPreviousVisibleTabs;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2024 Commonwealth Scientific and Industrial Research
|
|
3
|
+
* Organisation (CSIRO) ABN 41 687 119 230.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { getOldOpenLabelAnswer } from '../utils/openChoice';
|
|
19
|
+
import { useState } from 'react';
|
|
20
|
+
import type { QuestionnaireItemAnswerOption, QuestionnaireResponseItemAnswer } from 'fhir/r4';
|
|
21
|
+
|
|
22
|
+
function useOpenLabel(
|
|
23
|
+
options: QuestionnaireItemAnswerOption[],
|
|
24
|
+
answers: QuestionnaireResponseItemAnswer[]
|
|
25
|
+
) {
|
|
26
|
+
let initialOpenLabelValue = '';
|
|
27
|
+
let initialOpenLabelChecked = false;
|
|
28
|
+
|
|
29
|
+
if (options.length > 0) {
|
|
30
|
+
const oldLabelAnswer = getOldOpenLabelAnswer(answers, options);
|
|
31
|
+
if (oldLabelAnswer && oldLabelAnswer.valueString) {
|
|
32
|
+
initialOpenLabelValue = oldLabelAnswer.valueString;
|
|
33
|
+
initialOpenLabelChecked = true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const [openLabelValue, setOpenLabelValue] = useState(initialOpenLabelValue);
|
|
38
|
+
const [openLabelChecked, setOpenLabelChecked] = useState(initialOpenLabelChecked);
|
|
39
|
+
|
|
40
|
+
return { openLabelValue, setOpenLabelValue, openLabelChecked, setOpenLabelChecked };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export default useOpenLabel;
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { questionnaireResponseStore, questionnaireStore } from './stores';
|
|
2
2
|
import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4';
|
|
3
|
-
import { initialiseQuestionnaireResponse } from './utils/initialise';
|
|
4
3
|
import { removeEmptyAnswers } from './utils/removeEmptyAnswers';
|
|
5
4
|
import type { ItemToRepopulate } from './utils/repopulateItems';
|
|
6
5
|
import { getItemsToRepopulate } from './utils/repopulateItems';
|
|
@@ -13,26 +12,6 @@ export * from './utils';
|
|
|
13
12
|
export * from './interfaces';
|
|
14
13
|
export type { ItemToRepopulate };
|
|
15
14
|
|
|
16
|
-
/**
|
|
17
|
-
* Build the form with an initial Questionnaire and an optional filled QuestionnaireResponse.
|
|
18
|
-
* If a QuestionnaireResponse is not provided, an empty QuestionnaireResponse is set as the initial QuestionnaireResponse.
|
|
19
|
-
*
|
|
20
|
-
* @author Sean Fong
|
|
21
|
-
*/
|
|
22
|
-
export async function buildForm(
|
|
23
|
-
questionnaire: Questionnaire,
|
|
24
|
-
questionnaireResponse?: QuestionnaireResponse
|
|
25
|
-
): Promise<void> {
|
|
26
|
-
await questionnaireStore.getState().buildSourceQuestionnaire(questionnaire);
|
|
27
|
-
|
|
28
|
-
const initialisedQuestionnaireResponse = initialiseQuestionnaireResponse(
|
|
29
|
-
questionnaire,
|
|
30
|
-
questionnaireResponse
|
|
31
|
-
);
|
|
32
|
-
questionnaireResponseStore.getState().buildSourceResponse(initialisedQuestionnaireResponse);
|
|
33
|
-
questionnaireStore.getState().updatePopulatedProperties(initialisedQuestionnaireResponse);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
15
|
/**
|
|
37
16
|
* Destroy the form to clean up the questionnaire and questionnaireResponse stores.
|
|
38
17
|
*
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2024 Commonwealth Scientific and Industrial Research
|
|
3
|
+
* Organisation (CSIRO) ABN 41 687 119 230.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import React, { useLayoutEffect, useState } from 'react';
|
|
19
|
+
import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4';
|
|
20
|
+
import { BaseRenderer } from '../components';
|
|
21
|
+
import { QueryClientProvider } from '@tanstack/react-query';
|
|
22
|
+
import ThemeProvider from '../theme/Theme';
|
|
23
|
+
import useQueryClient from '../hooks/useQueryClient';
|
|
24
|
+
import { buildForm } from '../utils';
|
|
25
|
+
|
|
26
|
+
interface BuildFormWrapperProps {
|
|
27
|
+
questionnaire: Questionnaire;
|
|
28
|
+
questionnaireResponse?: QuestionnaireResponse;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function BuildFormWrapper(props: BuildFormWrapperProps) {
|
|
32
|
+
const { questionnaire, questionnaireResponse } = props;
|
|
33
|
+
|
|
34
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
35
|
+
|
|
36
|
+
useLayoutEffect(() => {
|
|
37
|
+
buildForm(questionnaire, questionnaireResponse).then(() => {
|
|
38
|
+
setIsLoading(false);
|
|
39
|
+
});
|
|
40
|
+
}, [questionnaire, questionnaireResponse]);
|
|
41
|
+
|
|
42
|
+
const queryClient = useQueryClient();
|
|
43
|
+
|
|
44
|
+
if (isLoading) {
|
|
45
|
+
return <div>Loading...</div>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<ThemeProvider>
|
|
50
|
+
<QueryClientProvider client={queryClient}>
|
|
51
|
+
<BaseRenderer />
|
|
52
|
+
</QueryClientProvider>
|
|
53
|
+
</ThemeProvider>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export default BuildFormWrapper;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { Questionnaire } from 'fhir/r4';
|
|
2
|
+
|
|
3
|
+
export const qEntryFormat: Questionnaire = {
|
|
4
|
+
resourceType: 'Questionnaire',
|
|
5
|
+
id: 'EntryFormat',
|
|
6
|
+
name: 'EntryFormat',
|
|
7
|
+
title: 'Entry Format',
|
|
8
|
+
version: '0.1.0',
|
|
9
|
+
status: 'draft',
|
|
10
|
+
publisher: 'AEHRC CSIRO',
|
|
11
|
+
date: '2024-05-01',
|
|
12
|
+
url: 'https://smartforms.csiro.au/docs/advanced/additional-display/entry-format',
|
|
13
|
+
item: [
|
|
14
|
+
{
|
|
15
|
+
extension: [
|
|
16
|
+
{
|
|
17
|
+
url: 'http://hl7.org/fhir/StructureDefinition/entryFormat',
|
|
18
|
+
valueString: '####'
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
linkId: 'postcode',
|
|
22
|
+
definition: 'http://hl7.org.au/fhir/StructureDefinition/au-address#Address.postalCode',
|
|
23
|
+
text: 'Postcode',
|
|
24
|
+
type: 'string',
|
|
25
|
+
repeats: false
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const qShortText: Questionnaire = {
|
|
31
|
+
resourceType: 'Questionnaire',
|
|
32
|
+
id: 'ShortText',
|
|
33
|
+
name: 'ShortText',
|
|
34
|
+
title: 'Short Text',
|
|
35
|
+
version: '0.1.0',
|
|
36
|
+
status: 'draft',
|
|
37
|
+
publisher: 'AEHRC CSIRO',
|
|
38
|
+
date: '2024-05-01',
|
|
39
|
+
url: 'https://smartforms.csiro.au/docs/advanced/additional-display/short-text',
|
|
40
|
+
item: [
|
|
41
|
+
{
|
|
42
|
+
extension: [
|
|
43
|
+
{
|
|
44
|
+
url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl',
|
|
45
|
+
valueCodeableConcept: {
|
|
46
|
+
coding: [
|
|
47
|
+
{
|
|
48
|
+
system: 'http://hl7.org/fhir/questionnaire-item-control',
|
|
49
|
+
version: '1.0.0',
|
|
50
|
+
code: 'tab-container'
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
],
|
|
56
|
+
linkId: 'tab-container',
|
|
57
|
+
type: 'group',
|
|
58
|
+
repeats: false,
|
|
59
|
+
item: [
|
|
60
|
+
{
|
|
61
|
+
extension: [
|
|
62
|
+
{
|
|
63
|
+
url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-shortText',
|
|
64
|
+
valueString: 'Regular medications'
|
|
65
|
+
}
|
|
66
|
+
],
|
|
67
|
+
linkId: 'tab-regular-medications',
|
|
68
|
+
text: 'Regular medications: check if still required, appropriate dose, understanding of medication and adherence',
|
|
69
|
+
type: 'group',
|
|
70
|
+
repeats: false,
|
|
71
|
+
item: [
|
|
72
|
+
{
|
|
73
|
+
linkId: 'highlight-short-text',
|
|
74
|
+
text: 'Notice the short text is used in the tab. The group title still displays the full text.',
|
|
75
|
+
type: 'display',
|
|
76
|
+
repeats: false
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
};
|