@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.
Files changed (179) hide show
  1. package/.storybook/main.ts +2 -1
  2. package/.storybook/preview.ts +6 -1
  3. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionFields.d.ts +3 -2
  4. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionFields.js +9 -17
  5. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionFields.js.map +1 -1
  6. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionItem.js +12 -9
  7. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionItem.js.map +1 -1
  8. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetFields.d.ts +2 -2
  9. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetFields.js +7 -9
  10. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetFields.js.map +1 -1
  11. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetItem.js +12 -8
  12. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetItem.js.map +1 -1
  13. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.d.ts +2 -1
  14. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.js +3 -3
  15. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.js.map +1 -1
  16. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionItem.js +6 -4
  17. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionItem.js.map +1 -1
  18. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionView.d.ts +2 -1
  19. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionView.js +3 -3
  20. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionView.js.map +1 -1
  21. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.d.ts +2 -2
  22. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.js +5 -7
  23. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.js.map +1 -1
  24. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetItem.js +4 -4
  25. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetItem.js.map +1 -1
  26. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.d.ts +2 -1
  27. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.js +2 -3
  28. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.js.map +1 -1
  29. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionItem.js +5 -3
  30. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionItem.js.map +1 -1
  31. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionView.d.ts +2 -1
  32. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionView.js +3 -3
  33. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionView.js.map +1 -1
  34. package/lib/components/FormComponents/DecimalItem/DecimalItem.js +1 -1
  35. package/lib/components/FormComponents/GroupItem/TabButtonsWrapper.js +20 -20
  36. package/lib/components/FormComponents/GroupItem/TabButtonsWrapper.js.map +1 -1
  37. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionFields.d.ts +3 -2
  38. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionFields.js +7 -19
  39. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionFields.js.map +1 -1
  40. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionItem.js +40 -40
  41. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionItem.js.map +1 -1
  42. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceItemSwitcher.js +15 -3
  43. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceItemSwitcher.js.map +1 -1
  44. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionFields.d.ts +2 -1
  45. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionFields.js +3 -3
  46. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionFields.js.map +1 -1
  47. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionItem.js +27 -26
  48. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionItem.js.map +1 -1
  49. package/lib/components/FormComponents/StringItem/StringField.js +1 -1
  50. package/lib/components/FormComponents/StringItem/StringField.js.map +1 -1
  51. package/lib/hooks/useInitialiseRenderer.js +1 -1
  52. package/lib/hooks/useInitialiseRenderer.js.map +1 -1
  53. package/lib/hooks/useNextAndPreviousVisibleTabs.d.ts +7 -0
  54. package/lib/hooks/useNextAndPreviousVisibleTabs.js +63 -0
  55. package/lib/hooks/useNextAndPreviousVisibleTabs.js.map +1 -0
  56. package/lib/hooks/useNextPreviousVisibleTabs.d.ts +6 -0
  57. package/lib/hooks/useNextPreviousVisibleTabs.js +63 -0
  58. package/lib/hooks/useNextPreviousVisibleTabs.js.map +1 -0
  59. package/lib/index.d.ts +0 -7
  60. package/lib/index.js +0 -24
  61. package/lib/index.js.map +1 -1
  62. package/lib/utils/choice.d.ts +1 -7
  63. package/lib/utils/choice.js +10 -20
  64. package/lib/utils/choice.js.map +1 -1
  65. package/lib/utils/enableWhen.js +5 -7
  66. package/lib/utils/enableWhen.js.map +1 -1
  67. package/lib/utils/index.d.ts +1 -0
  68. package/lib/utils/index.js +1 -0
  69. package/lib/utils/index.js.map +1 -1
  70. package/lib/utils/openChoice.d.ts +9 -4
  71. package/lib/utils/openChoice.js +47 -78
  72. package/lib/utils/openChoice.js.map +1 -1
  73. package/lib/utils/tabs.d.ts +0 -21
  74. package/lib/utils/tabs.js +0 -51
  75. package/lib/utils/tabs.js.map +1 -1
  76. package/package.json +4 -4
  77. package/src/components/FormComponents/ChoiceItems/CheckboxOptionList.tsx +82 -0
  78. package/src/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionFields.tsx +23 -52
  79. package/src/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionItem.tsx +15 -9
  80. package/src/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetFields.tsx +17 -19
  81. package/src/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetItem.tsx +13 -8
  82. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.tsx +5 -4
  83. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionItem.tsx +6 -2
  84. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionView.tsx +5 -1
  85. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.tsx +9 -16
  86. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetItem.tsx +4 -4
  87. package/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.tsx +4 -3
  88. package/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionItem.tsx +5 -2
  89. package/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionView.tsx +5 -1
  90. package/src/components/FormComponents/DecimalItem/DecimalItem.tsx +1 -1
  91. package/src/components/FormComponents/GroupItem/TabButtonsWrapper.tsx +28 -25
  92. package/src/components/FormComponents/ItemParts/{RadioAnswerOptionButtons.tsx → RadioOptionList.tsx} +7 -7
  93. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionFields.tsx +18 -50
  94. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionItem.tsx +70 -68
  95. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerValueSetFields.tsx +110 -0
  96. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerValueSetItem.tsx +188 -0
  97. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceItemSwitcher.tsx +46 -19
  98. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionFields.tsx +5 -3
  99. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionItem.tsx +37 -29
  100. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerValueSetFields.tsx +104 -0
  101. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerValueSetItem.tsx +156 -0
  102. package/src/components/FormComponents/StringItem/StringField.tsx +1 -1
  103. package/src/hooks/useInitialiseRenderer.ts +1 -1
  104. package/src/hooks/useNextAndPreviousVisibleTabs.ts +86 -0
  105. package/src/hooks/useOpenLabel.ts +43 -0
  106. package/src/index.ts +0 -21
  107. package/src/stories/BuildFormWrapper.tsx +57 -0
  108. package/src/stories/assets/questionnaires/QAdvancedAdditionalDisplayContent.ts +83 -0
  109. package/src/stories/assets/questionnaires/QAdvancedControlAppearance.ts +294 -0
  110. package/src/stories/assets/questionnaires/QAdvancedOther.ts +495 -0
  111. package/src/stories/assets/questionnaires/QAdvancedTextApperance.ts +188 -0
  112. package/src/stories/assets/questionnaires/QAttachment.ts +38 -0
  113. package/src/stories/assets/questionnaires/QBehaviorCalculations.ts +645 -0
  114. package/src/stories/assets/questionnaires/QBehaviorChoiceRestriction.ts +281 -0
  115. package/src/stories/assets/questionnaires/QBehaviorOther.ts +1149 -0
  116. package/src/stories/assets/questionnaires/QBehaviorValueConstraints.ts +508 -0
  117. package/src/stories/assets/questionnaires/QBoolean.ts +130 -0
  118. package/src/stories/assets/questionnaires/QChoice.ts +137 -0
  119. package/src/stories/assets/questionnaires/QDate.ts +56 -0
  120. package/src/stories/assets/questionnaires/QDateTime.ts +56 -0
  121. package/src/stories/assets/questionnaires/QDecimal.ts +56 -0
  122. package/src/stories/assets/questionnaires/QDisplay.ts +38 -0
  123. package/src/stories/assets/questionnaires/QGroup.ts +52 -0
  124. package/src/stories/assets/questionnaires/QInteger.ts +119 -0
  125. package/src/stories/assets/questionnaires/QItemControlDisplay.ts +114 -0
  126. package/src/stories/assets/questionnaires/QItemControlGroup.ts +419 -0
  127. package/src/stories/assets/questionnaires/QItemControlQuestion.ts +1271 -0
  128. package/src/stories/assets/questionnaires/QOpenChoice.ts +151 -0
  129. package/src/stories/assets/questionnaires/QQuantity.ts +38 -0
  130. package/src/stories/assets/questionnaires/QReference.ts +38 -0
  131. package/src/stories/assets/questionnaires/QSingleItems.ts +251 -0
  132. package/src/stories/assets/questionnaires/QString.ts +131 -0
  133. package/src/stories/assets/questionnaires/QText.ts +169 -0
  134. package/src/stories/assets/questionnaires/QTime.ts +38 -0
  135. package/src/stories/assets/questionnaires/QUrl.ts +38 -0
  136. package/src/stories/assets/questionnaires/index.ts +44 -0
  137. package/src/stories/itemTypes/Attachment.stories.tsx +39 -0
  138. package/src/stories/itemTypes/Boolean.stories.tsx +72 -0
  139. package/src/stories/{MedicalHistoryTable.stories.tsx → itemTypes/Choice.stories.tsx} +32 -26
  140. package/src/stories/itemTypes/Date.stories.tsx +46 -0
  141. package/src/stories/itemTypes/DateTime.stories.tsx +45 -0
  142. package/src/stories/itemTypes/Decimal.stories.tsx +56 -0
  143. package/src/stories/itemTypes/Display.stories.tsx +39 -0
  144. package/src/stories/itemTypes/Group.stories.tsx +39 -0
  145. package/src/stories/itemTypes/Integer.stories.tsx +55 -0
  146. package/src/stories/itemTypes/OpenChoice.stories.tsx +64 -0
  147. package/src/stories/itemTypes/Quantity.stories.tsx +39 -0
  148. package/src/stories/itemTypes/Reference.stories.tsx +39 -0
  149. package/src/stories/itemTypes/String.stories.tsx +51 -0
  150. package/src/stories/itemTypes/Text.stories.tsx +51 -0
  151. package/src/stories/itemTypes/Time.stories.tsx +39 -0
  152. package/src/stories/itemTypes/Url.stories.tsx +39 -0
  153. package/src/stories/sdc/AdvancedAdditionalDisplayContent.stories.tsx +45 -0
  154. package/src/stories/sdc/AdvancedControlAppearance.stories.tsx +51 -0
  155. package/src/stories/sdc/AdvancedOther.stories.tsx +76 -0
  156. package/src/stories/sdc/AdvancedTextAppearance.stories.tsx +69 -0
  157. package/src/stories/sdc/BehaviorCalculations.stories.tsx +69 -0
  158. package/src/stories/sdc/BehaviorChoiceRestriction.stories.tsx +76 -0
  159. package/src/stories/sdc/BehaviorOther.stories.tsx +90 -0
  160. package/src/stories/sdc/BehaviorValueConstraints.stories.tsx +88 -0
  161. package/src/stories/sdc/ItemControlDisplay.stories.tsx +39 -0
  162. package/src/stories/sdc/ItemControlGroup.stories.tsx +55 -0
  163. package/src/stories/sdc/ItemControlQuestion.stories.tsx +118 -0
  164. package/src/utils/buildForm.ts +23 -0
  165. package/src/utils/choice.ts +16 -23
  166. package/src/utils/enableWhen.ts +5 -7
  167. package/src/utils/index.ts +1 -0
  168. package/src/utils/openChoice.ts +83 -98
  169. package/src/utils/tabs.ts +0 -75
  170. package/vite.config.ts +23 -0
  171. package/doctor-storybook.log +0 -18
  172. package/src/stories/SmartFormsRenderer.stories.ts +0 -139
  173. package/src/stories/assets/QItems-and-QRItems/QR_GTableMedicalHistory.json +0 -80
  174. package/src/stories/assets/QItems-and-QRItems/Q_GTableMedicalHistory.json +0 -109
  175. package/src/stories/assets/Qs-and-QRs/Q715.json +0 -15086
  176. package/src/stories/assets/Qs-and-QRs/QDev715.json +0 -16081
  177. package/src/stories/assets/Qs-and-QRs/QTestGrid.json +0 -411
  178. package/src/stories/assets/Qs-and-QRs/R715.json +0 -311
  179. package/src/stories/assets/Qs-and-QRs/RTestGrid.json +0 -34
@@ -23,12 +23,13 @@ import type {
23
23
  PropsWithIsRepeatedAttribute,
24
24
  PropsWithIsTabledAttribute
25
25
  } from '../../../interfaces/renderProps.interface';
26
- import type { QuestionnaireItem } from 'fhir/r4';
26
+ import type { QuestionnaireItem, QuestionnaireItemAnswerOption } from 'fhir/r4';
27
27
 
28
28
  interface ChoiceRadioAnswerOptionViewProps
29
29
  extends PropsWithIsRepeatedAttribute,
30
30
  PropsWithIsTabledAttribute {
31
31
  qItem: QuestionnaireItem;
32
+ options: QuestionnaireItemAnswerOption[];
32
33
  valueChoice: string | null;
33
34
  readOnly: boolean;
34
35
  calcExpUpdated: boolean;
@@ -39,6 +40,7 @@ interface ChoiceRadioAnswerOptionViewProps
39
40
  function ChoiceRadioAnswerOptionView(props: ChoiceRadioAnswerOptionViewProps) {
40
41
  const {
41
42
  qItem,
43
+ options,
42
44
  valueChoice,
43
45
  isRepeated,
44
46
  isTabled,
@@ -52,6 +54,7 @@ function ChoiceRadioAnswerOptionView(props: ChoiceRadioAnswerOptionViewProps) {
52
54
  return (
53
55
  <ChoiceRadioAnswerOptionFields
54
56
  qItem={qItem}
57
+ options={options}
55
58
  valueRadio={valueChoice}
56
59
  isTabled={isTabled}
57
60
  readOnly={readOnly}
@@ -69,6 +72,7 @@ function ChoiceRadioAnswerOptionView(props: ChoiceRadioAnswerOptionViewProps) {
69
72
  <ItemFieldGrid qItem={qItem} readOnly={readOnly}>
70
73
  <ChoiceRadioAnswerOptionFields
71
74
  qItem={qItem}
75
+ options={options}
72
76
  valueRadio={valueChoice}
73
77
  readOnly={readOnly}
74
78
  isTabled={isTabled}
@@ -18,8 +18,7 @@
18
18
  import React from 'react';
19
19
  import Typography from '@mui/material/Typography';
20
20
  import { ChoiceItemOrientation } from '../../../interfaces/choice.enum';
21
- import type { Coding, QuestionnaireItem } from 'fhir/r4';
22
- import ChoiceRadioSingle from './ChoiceRadioSingle';
21
+ import type { QuestionnaireItem, QuestionnaireItemAnswerOption } from 'fhir/r4';
23
22
  import { StyledRadioGroup } from '../Item.styles';
24
23
  import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
25
24
  import { StyledAlert } from '../../Alert.styles';
@@ -28,10 +27,11 @@ import { getChoiceOrientation } from '../../../utils/choice';
28
27
  import FadingCheckIcon from '../ItemParts/FadingCheckIcon';
29
28
  import type { PropsWithIsTabledAttribute } from '../../../interfaces/renderProps.interface';
30
29
  import Box from '@mui/material/Box';
30
+ import RadioOptionList from '../ItemParts/RadioOptionList';
31
31
 
32
32
  interface ChoiceRadioAnswerValueSetFieldsProps extends PropsWithIsTabledAttribute {
33
33
  qItem: QuestionnaireItem;
34
- codings: Coding[];
34
+ options: QuestionnaireItemAnswerOption[];
35
35
  valueRadio: string | null;
36
36
  readOnly: boolean;
37
37
  calcExpUpdated: boolean;
@@ -42,7 +42,7 @@ interface ChoiceRadioAnswerValueSetFieldsProps extends PropsWithIsTabledAttribut
42
42
  function ChoiceRadioAnswerValueSetFields(props: ChoiceRadioAnswerValueSetFieldsProps) {
43
43
  const {
44
44
  qItem,
45
- codings,
45
+ options,
46
46
  valueRadio,
47
47
  readOnly,
48
48
  calcExpUpdated,
@@ -53,7 +53,7 @@ function ChoiceRadioAnswerValueSetFields(props: ChoiceRadioAnswerValueSetFieldsP
53
53
 
54
54
  const orientation = getChoiceOrientation(qItem) ?? ChoiceItemOrientation.Vertical;
55
55
 
56
- if (codings.length > 0) {
56
+ if (options.length > 0) {
57
57
  return (
58
58
  <Box display="flex" alignItems="center">
59
59
  <StyledRadioGroup
@@ -61,18 +61,11 @@ function ChoiceRadioAnswerValueSetFields(props: ChoiceRadioAnswerValueSetFieldsP
61
61
  name={qItem.text}
62
62
  id={qItem.id}
63
63
  onChange={(e) => onCheckedChange(e.target.value)}
64
- value={valueRadio ?? null}>
65
- {codings.map((coding: Coding) => {
66
- return (
67
- <ChoiceRadioSingle
68
- key={coding.code ?? ''}
69
- value={coding.code ?? ''}
70
- label={coding.display ?? `${coding.code}`}
71
- readOnly={readOnly}
72
- />
73
- );
74
- })}
64
+ value={valueRadio}
65
+ data-test="q-item-radio-group">
66
+ <RadioOptionList options={options} readOnly={readOnly} />
75
67
  </StyledRadioGroup>
68
+
76
69
  <Box flexGrow={1} />
77
70
 
78
71
  <FadingCheckIcon fadeIn={calcExpUpdated} disabled={readOnly} />
@@ -60,7 +60,7 @@ function ChoiceRadioAnswerValueSetItem(props: ChoiceRadioAnswerValueSetItemProps
60
60
  // Get codings/options from valueSet
61
61
  const { codings, terminologyError } = useValueSetCodings(qItem);
62
62
 
63
- const answerOptions = useMemo(() => convertCodingsToAnswerOptions(codings), [codings]);
63
+ const options = useMemo(() => convertCodingsToAnswerOptions(codings), [codings]);
64
64
 
65
65
  const { calcExpUpdated } = useCodingCalculatedExpression({
66
66
  qItem: qItem,
@@ -75,7 +75,7 @@ function ChoiceRadioAnswerValueSetItem(props: ChoiceRadioAnswerValueSetItemProps
75
75
 
76
76
  function handleChange(newValue: string) {
77
77
  if (codings.length > 0) {
78
- const qrAnswer = findInAnswerOptions(answerOptions, newValue);
78
+ const qrAnswer = findInAnswerOptions(options, newValue);
79
79
  onQrItemChange(
80
80
  qrAnswer ? { ...createEmptyQrItem(qItem), answer: [qrAnswer] } : createEmptyQrItem(qItem)
81
81
  );
@@ -86,7 +86,7 @@ function ChoiceRadioAnswerValueSetItem(props: ChoiceRadioAnswerValueSetItemProps
86
86
  return (
87
87
  <ChoiceRadioAnswerValueSetFields
88
88
  qItem={qItem}
89
- codings={codings}
89
+ options={options}
90
90
  valueRadio={valueRadio}
91
91
  readOnly={readOnly}
92
92
  calcExpUpdated={calcExpUpdated}
@@ -105,7 +105,7 @@ function ChoiceRadioAnswerValueSetItem(props: ChoiceRadioAnswerValueSetItemProps
105
105
  <ItemFieldGrid qItem={qItem} readOnly={readOnly}>
106
106
  <ChoiceRadioAnswerValueSetFields
107
107
  qItem={qItem}
108
- codings={codings}
108
+ options={options}
109
109
  valueRadio={valueRadio}
110
110
  readOnly={readOnly}
111
111
  calcExpUpdated={calcExpUpdated}
@@ -19,13 +19,14 @@ import React, { Fragment } from 'react';
19
19
  import InputAdornment from '@mui/material/InputAdornment';
20
20
  import MenuItem from '@mui/material/MenuItem';
21
21
  import Select from '@mui/material/Select';
22
- import type { QuestionnaireItem } from 'fhir/r4';
22
+ import type { QuestionnaireItem, QuestionnaireItemAnswerOption } from 'fhir/r4';
23
23
  import useRenderingExtensions from '../../../hooks/useRenderingExtensions';
24
24
  import type { PropsWithIsTabledAttribute } from '../../../interfaces/renderProps.interface';
25
25
  import { TEXT_FIELD_WIDTH } from '../Textfield.styles';
26
26
 
27
27
  interface ChoiceSelectAnswerOptionFieldsProps extends PropsWithIsTabledAttribute {
28
28
  qItem: QuestionnaireItem;
29
+ options: QuestionnaireItemAnswerOption[];
29
30
  valueSelect: string;
30
31
  readOnly: boolean;
31
32
  calcExpUpdated: boolean;
@@ -33,7 +34,7 @@ interface ChoiceSelectAnswerOptionFieldsProps extends PropsWithIsTabledAttribute
33
34
  }
34
35
 
35
36
  function ChoiceSelectAnswerOptionFields(props: ChoiceSelectAnswerOptionFieldsProps) {
36
- const { qItem, valueSelect, readOnly, calcExpUpdated, isTabled, onSelectChange } = props;
37
+ const { qItem, options, valueSelect, readOnly, calcExpUpdated, isTabled, onSelectChange } = props;
37
38
 
38
39
  const { displayUnit, displayPrompt, entryFormat } = useRenderingExtensions(qItem);
39
40
 
@@ -52,7 +53,7 @@ function ChoiceSelectAnswerOptionFields(props: ChoiceSelectAnswerOptionFieldsPro
52
53
  sx={{ maxWidth: !isTabled ? TEXT_FIELD_WIDTH : 3000, minWidth: 160 }}
53
54
  size="small"
54
55
  onChange={(e) => onSelectChange(e.target.value)}>
55
- {qItem.answerOption?.map((option, index) => {
56
+ {options.map((option, index) => {
56
57
  if (option['valueCoding']) {
57
58
  return (
58
59
  <MenuItem key={option.valueCoding.code} value={option.valueCoding.code}>
@@ -52,6 +52,8 @@ function ChoiceSelectAnswerOptionItem(props: ChoiceSelectAnswerOptionItemProps)
52
52
  const qrChoice = qrItem ?? createEmptyQrItem(qItem);
53
53
  const valueChoice = getQrChoiceValue(qrChoice);
54
54
 
55
+ const options = qItem.answerOption ?? [];
56
+
55
57
  // Process calculated expressions
56
58
  const { calcExpUpdated } = useCodingCalculatedExpression({
57
59
  qItem: qItem,
@@ -66,12 +68,12 @@ function ChoiceSelectAnswerOptionItem(props: ChoiceSelectAnswerOptionItemProps)
66
68
 
67
69
  // Event handlers
68
70
  function handleChange(newValue: string) {
69
- if (!qItem.answerOption) {
71
+ if (options.length === 0) {
70
72
  onQrItemChange(createEmptyQrItem(qItem));
71
73
  return;
72
74
  }
73
75
 
74
- const qrAnswer = findInAnswerOptions(qItem.answerOption, newValue);
76
+ const qrAnswer = findInAnswerOptions(options, newValue);
75
77
  onQrItemChange(
76
78
  qrAnswer ? { ...createEmptyQrItem(qItem), answer: [qrAnswer] } : createEmptyQrItem(qItem)
77
79
  );
@@ -80,6 +82,7 @@ function ChoiceSelectAnswerOptionItem(props: ChoiceSelectAnswerOptionItemProps)
80
82
  return (
81
83
  <ChoiceSelectAnswerOptionView
82
84
  qItem={qItem}
85
+ options={options}
83
86
  valueChoice={valueChoice}
84
87
  readOnly={readOnly}
85
88
  calcExpUpdated={calcExpUpdated}
@@ -22,13 +22,14 @@ import type {
22
22
  PropsWithIsRepeatedAttribute,
23
23
  PropsWithIsTabledAttribute
24
24
  } from '../../../interfaces/renderProps.interface';
25
- import type { QuestionnaireItem } from 'fhir/r4';
25
+ import type { QuestionnaireItem, QuestionnaireItemAnswerOption } from 'fhir/r4';
26
26
  import ChoiceSelectAnswerOptionFields from './ChoiceSelectAnswerOptionFields';
27
27
 
28
28
  interface ChoiceSelectAnswerOptionViewProps
29
29
  extends PropsWithIsRepeatedAttribute,
30
30
  PropsWithIsTabledAttribute {
31
31
  qItem: QuestionnaireItem;
32
+ options: QuestionnaireItemAnswerOption[];
32
33
  valueChoice: string | null;
33
34
  readOnly: boolean;
34
35
  calcExpUpdated: boolean;
@@ -39,6 +40,7 @@ interface ChoiceSelectAnswerOptionViewProps
39
40
  function ChoiceSelectAnswerOptionView(props: ChoiceSelectAnswerOptionViewProps) {
40
41
  const {
41
42
  qItem,
43
+ options,
42
44
  valueChoice,
43
45
  isRepeated,
44
46
  isTabled,
@@ -52,6 +54,7 @@ function ChoiceSelectAnswerOptionView(props: ChoiceSelectAnswerOptionViewProps)
52
54
  return (
53
55
  <ChoiceSelectAnswerOptionFields
54
56
  qItem={qItem}
57
+ options={options}
55
58
  valueSelect={valueChoice ?? ''}
56
59
  readOnly={readOnly}
57
60
  calcExpUpdated={calcExpUpdated}
@@ -69,6 +72,7 @@ function ChoiceSelectAnswerOptionView(props: ChoiceSelectAnswerOptionViewProps)
69
72
  <ItemFieldGrid qItem={qItem} readOnly={readOnly}>
70
73
  <ChoiceSelectAnswerOptionFields
71
74
  qItem={qItem}
75
+ options={options}
72
76
  valueSelect={valueChoice ?? ''}
73
77
  readOnly={readOnly}
74
78
  calcExpUpdated={calcExpUpdated}
@@ -91,7 +91,7 @@ function DecimalItem(props: DecimalItemProps) {
91
91
  );
92
92
  onQrItemChange({
93
93
  ...createEmptyQrItem(qItem),
94
- answer: [{ valueInteger: newValueDecimal }]
94
+ answer: [{ valueDecimal: newValueDecimal }]
95
95
  });
96
96
  },
97
97
  onChangeByCalcExpressionNull: () => {
@@ -17,11 +17,11 @@
17
17
 
18
18
  import React, { memo } from 'react';
19
19
  import Box from '@mui/material/Box';
20
- import { findNumOfVisibleTabs, getVisibleTabIndex } from '../../../utils/tabs';
21
20
  import type { Tabs } from '../../../interfaces/tab.interface';
22
21
  import { useQuestionnaireStore } from '../../../stores';
23
22
  import NextTabButton from './NextTabButton';
24
23
  import PreviousTabButton from './PreviousTabButton';
24
+ import useNextAndPreviousVisibleTabs from '../../../hooks/useNextAndPreviousVisibleTabs';
25
25
 
26
26
  interface TabButtonsWrapperProps {
27
27
  currentTabIndex?: number;
@@ -31,27 +31,33 @@ interface TabButtonsWrapperProps {
31
31
  const TabButtonsWrapper = memo(function TabButtonsWrapper(props: TabButtonsWrapperProps) {
32
32
  const { currentTabIndex, tabs } = props;
33
33
 
34
- const enableWhenIsActivated = useQuestionnaireStore.use.enableWhenIsActivated();
35
- const enableWhenItems = useQuestionnaireStore.use.enableWhenItems();
36
- const enableWhenExpressions = useQuestionnaireStore.use.enableWhenExpressions();
37
34
  const switchTab = useQuestionnaireStore.use.switchTab();
38
35
 
36
+ const { previousTabIndex, nextTabIndex, numOfVisibleTabs } = useNextAndPreviousVisibleTabs(
37
+ currentTabIndex,
38
+ tabs
39
+ );
40
+
39
41
  const tabsNotDefined = currentTabIndex === undefined || tabs === undefined;
40
42
 
41
- function handleButtonClick(direction: 'next' | 'previous') {
42
- if (tabsNotDefined) {
43
+ // Event handlers
44
+ function handlePreviousTabButtonClick() {
45
+ if (previousTabIndex === null) {
43
46
  return;
44
47
  }
45
48
 
46
- const visibleTabIndex = getVisibleTabIndex({
47
- direction,
48
- tabs,
49
- currentTabIndex,
50
- enableWhenIsActivated,
51
- enableWhenItems,
52
- enableWhenExpressions
53
- });
54
- switchTab(visibleTabIndex);
49
+ switchTab(previousTabIndex);
50
+
51
+ // Scroll to top of page
52
+ window.scrollTo(0, 0);
53
+ }
54
+
55
+ function handleNextTabButtonClick() {
56
+ if (nextTabIndex === null) {
57
+ return;
58
+ }
59
+
60
+ switchTab(nextTabIndex);
55
61
 
56
62
  // Scroll to top of page
57
63
  window.scrollTo(0, 0);
@@ -61,26 +67,23 @@ const TabButtonsWrapper = memo(function TabButtonsWrapper(props: TabButtonsWrapp
61
67
  return null;
62
68
  }
63
69
 
64
- const previousTabButtonHidden = currentTabIndex === 0;
65
- const nextTabButtonHidden = currentTabIndex === Object.keys(tabs).length - 1;
70
+ const previousTabButtonHidden = previousTabIndex === null;
71
+ const nextTabButtonHidden = nextTabIndex === null;
66
72
 
67
- const buttonIsDisabled =
68
- findNumOfVisibleTabs(tabs, enableWhenIsActivated, enableWhenItems, enableWhenExpressions) <= 1;
73
+ // This is more of a fallback check to prevent the user from navigating to an invisble tab if buttons are visble for some reason
74
+ const tabButtonsDisabled = numOfVisibleTabs <= 1;
69
75
 
70
76
  return (
71
77
  <Box display="flex" mt={3}>
72
78
  {previousTabButtonHidden ? null : (
73
79
  <PreviousTabButton
74
- isDisabled={buttonIsDisabled}
75
- onPreviousTabClick={() => handleButtonClick('previous')}
80
+ isDisabled={tabButtonsDisabled}
81
+ onPreviousTabClick={handlePreviousTabButtonClick}
76
82
  />
77
83
  )}
78
84
  <Box flexGrow={1} />
79
85
  {nextTabButtonHidden ? null : (
80
- <NextTabButton
81
- isDisabled={buttonIsDisabled}
82
- onNextTabClick={() => handleButtonClick('next')}
83
- />
86
+ <NextTabButton isDisabled={tabButtonsDisabled} onNextTabClick={handleNextTabButtonClick} />
84
87
  )}
85
88
  </Box>
86
89
  );
@@ -17,19 +17,19 @@
17
17
 
18
18
  import React from 'react';
19
19
  import ChoiceRadioSingle from '../ChoiceItems/ChoiceRadioSingle';
20
- import type { QuestionnaireItem } from 'fhir/r4';
20
+ import type { QuestionnaireItemAnswerOption } from 'fhir/r4';
21
21
 
22
- interface RadioAnswerOptionButtonsProps {
23
- qItem: QuestionnaireItem;
22
+ interface RadioOptionListProps {
23
+ options: QuestionnaireItemAnswerOption[];
24
24
  readOnly: boolean;
25
25
  }
26
26
 
27
- function RadioAnswerOptionButtons(props: RadioAnswerOptionButtonsProps) {
28
- const { qItem, readOnly } = props;
27
+ function RadioOptionList(props: RadioOptionListProps) {
28
+ const { options, readOnly } = props;
29
29
 
30
30
  return (
31
31
  <>
32
- {qItem.answerOption?.map((option) => {
32
+ {options.map((option) => {
33
33
  if (option['valueCoding']) {
34
34
  return (
35
35
  <ChoiceRadioSingle
@@ -69,4 +69,4 @@ function RadioAnswerOptionButtons(props: RadioAnswerOptionButtonsProps) {
69
69
  );
70
70
  }
71
71
 
72
- export default RadioAnswerOptionButtons;
72
+ export default RadioOptionList;
@@ -16,21 +16,26 @@
16
16
  */
17
17
 
18
18
  import React from 'react';
19
- import { StyledFormGroup } from '../Item.styles';
20
19
  import { ChoiceItemOrientation } from '../../../interfaces/choice.enum';
21
- import CheckboxSingle from '../ItemParts/CheckboxSingle';
22
20
  import CheckboxSingleWithOpenLabel from '../ItemParts/CheckboxSingleWithOpenLabel';
23
- import type { QuestionnaireItem, QuestionnaireResponseItemAnswer } from 'fhir/r4';
21
+ import type {
22
+ QuestionnaireItem,
23
+ QuestionnaireItemAnswerOption,
24
+ QuestionnaireResponseItemAnswer
25
+ } from 'fhir/r4';
24
26
  import { getChoiceOrientation } from '../../../utils/choice';
27
+ import { StyledFormGroup } from '../Item.styles';
28
+ import CheckboxOptionList from '../ChoiceItems/CheckboxOptionList';
25
29
 
26
30
  interface OpenChoiceCheckboxAnswerOptionFieldsProps {
27
31
  qItem: QuestionnaireItem;
32
+ options: QuestionnaireItemAnswerOption[];
28
33
  answers: QuestionnaireResponseItemAnswer[];
29
34
  openLabelText: string | null;
30
35
  openLabelValue: string;
31
36
  openLabelChecked: boolean;
32
37
  readOnly: boolean;
33
- onValueChange: (changedOptionValue: string | null, changedOpenLabelValue: string | null) => void;
38
+ onOptionChange: (changedOptionValue: string) => void;
34
39
  onOpenLabelCheckedChange: (checked: boolean) => void;
35
40
  onOpenLabelInputChange: (input: string) => void;
36
41
  }
@@ -38,12 +43,13 @@ interface OpenChoiceCheckboxAnswerOptionFieldsProps {
38
43
  function OpenChoiceCheckboxAnswerOptionFields(props: OpenChoiceCheckboxAnswerOptionFieldsProps) {
39
44
  const {
40
45
  qItem,
46
+ options,
41
47
  answers,
42
48
  openLabelText,
43
49
  openLabelValue,
44
50
  openLabelChecked,
45
51
  readOnly,
46
- onValueChange,
52
+ onOptionChange,
47
53
  onOpenLabelCheckedChange,
48
54
  onOpenLabelInputChange
49
55
  } = props;
@@ -52,52 +58,14 @@ function OpenChoiceCheckboxAnswerOptionFields(props: OpenChoiceCheckboxAnswerOpt
52
58
 
53
59
  return (
54
60
  <StyledFormGroup row={orientation === ChoiceItemOrientation.Horizontal}>
55
- {qItem.answerOption?.map((option) => {
56
- if (option['valueCoding']) {
57
- return (
58
- <CheckboxSingle
59
- key={option.valueCoding.code ?? ''}
60
- value={option.valueCoding.code ?? ''}
61
- label={option.valueCoding.display ?? `${option.valueCoding.code}`}
62
- readOnly={readOnly}
63
- isChecked={answers.some(
64
- (answer) => JSON.stringify(answer) === JSON.stringify(option)
65
- )}
66
- onCheckedChange={(changedValue) => onValueChange(changedValue, null)}
67
- />
68
- );
69
- }
70
-
71
- if (option['valueString']) {
72
- return (
73
- <CheckboxSingle
74
- key={option.valueString}
75
- value={option.valueString}
76
- label={option.valueString}
77
- readOnly={readOnly}
78
- isChecked={answers.some((answer) => answer.valueString === option.valueString)}
79
- onCheckedChange={(changedValue) => onValueChange(changedValue, null)}
80
- />
81
- );
82
- }
83
-
84
- if (option['valueInteger']) {
85
- return (
86
- <CheckboxSingle
87
- key={option.valueInteger}
88
- value={option.valueInteger.toString()}
89
- label={option.valueInteger.toString()}
90
- readOnly={readOnly}
91
- isChecked={answers.some((answer) => answer.valueInteger === option.valueInteger)}
92
- onCheckedChange={(changedValue) => onValueChange(changedValue, null)}
93
- />
94
- );
95
- }
96
-
97
- return null;
98
- })}
61
+ <CheckboxOptionList
62
+ options={options}
63
+ answers={answers}
64
+ readOnly={readOnly}
65
+ onCheckedChange={onOptionChange}
66
+ />
99
67
 
100
- {openLabelText ? (
68
+ {openLabelText !== null ? (
101
69
  <CheckboxSingleWithOpenLabel
102
70
  value={openLabelValue}
103
71
  label={openLabelText}