fhir-react 0.3.5 → 0.3.8

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 (173) hide show
  1. package/.circleci/config.yml +1 -1
  2. package/.eslintrc +10 -1
  3. package/.stylelintrc +6 -2
  4. package/README.md +19 -1
  5. package/build/index.js +15 -11
  6. package/build/style.css +9 -8
  7. package/package.json +55 -54
  8. package/src/assets/containers/AdverseEvent/adverse-event.svg +6 -0
  9. package/src/assets/containers/Coverage/coverage.svg +4 -0
  10. package/src/assets/containers/{ResourceCategory/resource-placeholder.svg → Generic/generic.svg} +0 -0
  11. package/src/assets/containers/MedicationDispense/medication-dispense.svg +5 -0
  12. package/src/assets/containers/MedicationOrder/medication-order.svg +5 -0
  13. package/src/assets/containers/MedicationRequest/medication-request.svg +5 -0
  14. package/src/assets/containers/Organization/organization.svg +5 -0
  15. package/src/assets/containers/PractitionerRole/practitioner-role.svg +5 -0
  16. package/src/assets/containers/ReferralRequest/referral-request.svg +8 -0
  17. package/src/assets/containers/RelatedPerson/related-person.svg +6 -0
  18. package/src/assets/containers/ResourceCategory/resource-category.svg +3 -0
  19. package/src/components/containers/Accordion/Accordion.js +21 -13
  20. package/src/components/datatypes/Attachment/Attachment.css +5 -0
  21. package/src/components/datatypes/Attachment/Attachment.js +7 -2
  22. package/src/components/datatypes/CodeableConcept/CodeableConcept.js +6 -3
  23. package/src/components/datatypes/Coding/Coding.js +7 -3
  24. package/src/components/datatypes/Identifier/Identifier.js +7 -3
  25. package/src/components/datatypes/Reference/Reference.js +7 -1
  26. package/src/components/datatypes/Telecom/Telecom.js +2 -3
  27. package/src/components/resources/AdverseEvent/AdverseEvent.js +81 -42
  28. package/src/components/resources/AdverseEvent/AdverseEvent.stories.js +12 -2
  29. package/src/components/resources/AdverseEvent/AdverseEvent.test.js +109 -2
  30. package/src/components/resources/AllergyIntolerance/AllergyIntolerance.js +9 -5
  31. package/src/components/resources/AllergyIntolerance/AllergyIntolerance.stories.js +5 -4
  32. package/src/components/resources/AllergyIntolerance/AllergyIntolerance.test.js +107 -1
  33. package/src/components/resources/Appointment/Appointment.js +2 -1
  34. package/src/components/resources/Appointment/Appointment.test.js +36 -1
  35. package/src/components/resources/Binary/Binary.js +1 -2
  36. package/src/components/resources/Binary/Binary.stories.js +10 -4
  37. package/src/components/resources/Binary/Binary.test.js +67 -0
  38. package/src/components/resources/Bundle/Bundle.css +7 -0
  39. package/src/components/resources/Bundle/Bundle.js +15 -11
  40. package/src/components/resources/Bundle/Bundle.stories.js +12 -78
  41. package/src/components/resources/Bundle/Bundle.test.js +0 -3
  42. package/src/components/resources/CarePlan/CarePlan.js +2 -1
  43. package/src/components/resources/CarePlan/CarePlan.stories.js +31 -5
  44. package/src/components/resources/CarePlan/CarePlan.test.js +114 -6
  45. package/src/components/resources/CareTeam/CareTeam.js +72 -50
  46. package/src/components/resources/CareTeam/CareTeam.stories.js +20 -3
  47. package/src/components/resources/CareTeam/CareTeam.test.js +109 -1
  48. package/src/components/resources/CareTeam/CareTeamParticipants.js +1 -1
  49. package/src/components/resources/Claim/CareTeam.js +55 -0
  50. package/src/components/resources/Claim/Claim.css +2 -11
  51. package/src/components/resources/Claim/Claim.js +158 -309
  52. package/src/components/resources/Claim/Claim.stories.js +37 -5
  53. package/src/components/resources/Claim/Claim.test.js +104 -1
  54. package/src/components/resources/Claim/Diagnosis.js +61 -0
  55. package/src/components/resources/Claim/Insurance.js +58 -0
  56. package/src/components/resources/Claim/Item.js +79 -0
  57. package/src/components/resources/Claim/Items.js +29 -0
  58. package/src/components/resources/ClaimResponse/AddedItem.js +61 -11
  59. package/src/components/resources/ClaimResponse/AddedItems.js +5 -9
  60. package/src/components/resources/ClaimResponse/ClaimResponse.js +137 -83
  61. package/src/components/resources/ClaimResponse/ClaimResponse.stories.js +15 -2
  62. package/src/components/resources/ClaimResponse/ClaimResponse.test.js +112 -1
  63. package/src/components/resources/ClaimResponse/Item.js +44 -9
  64. package/src/components/resources/ClaimResponse/Items.js +5 -4
  65. package/src/components/resources/Condition/Condition.js +3 -3
  66. package/src/components/resources/Condition/Condition.test.js +37 -4
  67. package/src/components/resources/Coverage/Coverage.js +97 -69
  68. package/src/components/resources/Coverage/Coverage.stories.js +31 -5
  69. package/src/components/resources/Coverage/Coverage.test.js +111 -4
  70. package/src/components/resources/Device/Device.js +2 -1
  71. package/src/components/resources/Device/Device.stories.js +33 -5
  72. package/src/components/resources/Device/Device.test.js +108 -1
  73. package/src/components/resources/DiagnosticReport/DiagnosticReport.js +7 -2
  74. package/src/components/resources/DiagnosticReport/DiagnosticReport.stories.js +5 -4
  75. package/src/components/resources/DiagnosticReport/DiagnosticReport.test.js +107 -1
  76. package/src/components/resources/DocumentReference/DocumentReference.js +7 -2
  77. package/src/components/resources/DocumentReference/DocumentReference.stories.js +3 -2
  78. package/src/components/resources/DocumentReference/DocumentReference.test.js +113 -1
  79. package/src/components/resources/Encounter/Encounter.js +2 -1
  80. package/src/components/resources/Encounter/Encounter.test.js +36 -1
  81. package/src/components/resources/ExplanationOfBenefit/ExplanationOfBenefit.js +2 -0
  82. package/src/components/resources/ExplanationOfBenefit/ExplanationOfBenefit.test.js +38 -1
  83. package/src/components/resources/FamilyMemberHistory/FamilyMemberHistory.js +7 -2
  84. package/src/components/resources/FamilyMemberHistory/FamilyMemberHistory.stories.js +3 -2
  85. package/src/components/resources/FamilyMemberHistory/FamilyMemberHistory.test.js +108 -1
  86. package/src/components/resources/Generic/Generic.js +20 -7
  87. package/src/components/resources/Generic/Generic.stories.js +2 -1
  88. package/src/components/resources/Generic/Generic.test.js +26 -7
  89. package/src/components/resources/Goal/Goal.js +3 -5
  90. package/src/components/resources/Goal/Goal.stories.js +5 -4
  91. package/src/components/resources/Goal/Goal.test.js +101 -1
  92. package/src/components/resources/Immunization/Immunization.js +2 -2
  93. package/src/components/resources/Immunization/Immunization.test.js +36 -1
  94. package/src/components/resources/List/DrugTierDefinitionExtension.js +79 -35
  95. package/src/components/resources/List/Entries.js +3 -3
  96. package/src/components/resources/List/List.js +135 -88
  97. package/src/components/resources/List/List.stories.js +38 -5
  98. package/src/components/resources/List/List.test.js +105 -1
  99. package/src/components/resources/Location/Location.js +65 -47
  100. package/src/components/resources/Location/Location.stories.js +11 -4
  101. package/src/components/resources/Location/Location.test.js +106 -4
  102. package/src/components/resources/Medication/Medication.js +91 -51
  103. package/src/components/resources/Medication/Medication.stories.js +37 -7
  104. package/src/components/resources/Medication/Medication.test.js +113 -4
  105. package/src/components/resources/MedicationAdministration/MedicationAdministration.js +86 -62
  106. package/src/components/resources/MedicationAdministration/MedicationAdministration.stories.js +7 -0
  107. package/src/components/resources/MedicationAdministration/MedicationAdministration.test.js +117 -1
  108. package/src/components/resources/MedicationDispense/DosageInstruction.js +25 -0
  109. package/src/components/resources/MedicationDispense/MedicationDispense.js +68 -68
  110. package/src/components/resources/MedicationDispense/MedicationDispense.stories.js +7 -0
  111. package/src/components/resources/MedicationDispense/MedicationDispense.test.js +108 -1
  112. package/src/components/resources/MedicationKnowledge/MedicationKnowledge.js +115 -66
  113. package/src/components/resources/MedicationKnowledge/MedicationKnowledge.stories.js +6 -0
  114. package/src/components/resources/MedicationKnowledge/MedicationKnowledge.test.js +110 -1
  115. package/src/components/resources/MedicationOrder/MedicationOrder.js +3 -4
  116. package/src/components/resources/MedicationOrder/MedicationOrder.stories.js +1 -2
  117. package/src/components/resources/MedicationOrder/MedicationOrder.test.js +102 -4
  118. package/src/components/resources/MedicationRequest/MedicationRequest.js +3 -4
  119. package/src/components/resources/MedicationRequest/MedicationRequest.stories.js +11 -6
  120. package/src/components/resources/MedicationRequest/MedicationRequest.test.js +100 -4
  121. package/src/components/resources/MedicationStatement/MedicationDosage.js +2 -2
  122. package/src/components/resources/MedicationStatement/MedicationStatement.js +8 -2
  123. package/src/components/resources/MedicationStatement/MedicationStatement.stories.js +5 -4
  124. package/src/components/resources/MedicationStatement/MedicationStatement.test.js +108 -1
  125. package/src/components/resources/Observation/Observation.js +2 -1
  126. package/src/components/resources/Observation/Observation.test.js +30 -1
  127. package/src/components/resources/Organization/Organization.js +56 -37
  128. package/src/components/resources/Organization/Organization.stories.js +15 -2
  129. package/src/components/resources/Organization/Organization.test.js +109 -1
  130. package/src/components/resources/Patient/Patient.js +2 -0
  131. package/src/components/resources/Patient/Patient.test.js +31 -2
  132. package/src/components/resources/Practitioner/Practitioner.js +2 -1
  133. package/src/components/resources/Practitioner/Practitioner.test.js +36 -1
  134. package/src/components/resources/PractitionerRole/PractitionerRole.js +50 -29
  135. package/src/components/resources/PractitionerRole/PractitionerRole.stories.js +7 -0
  136. package/src/components/resources/PractitionerRole/PractitionerRole.test.js +108 -1
  137. package/src/components/resources/Procedure/Procedure.js +2 -2
  138. package/src/components/resources/Procedure/Procedure.test.js +30 -1
  139. package/src/components/resources/Questionnaire/Group.js +53 -0
  140. package/src/components/resources/Questionnaire/Items.js +45 -0
  141. package/src/components/resources/Questionnaire/Questionnaire.css +24 -5
  142. package/src/components/resources/Questionnaire/Questionnaire.js +31 -170
  143. package/src/components/resources/Questionnaire/Questionnaire.stories.js +8 -0
  144. package/src/components/resources/Questionnaire/Questionnaire.test.js +194 -15
  145. package/src/components/resources/Questionnaire/Questions.js +40 -0
  146. package/src/components/resources/Questionnaire/getQuestionText.js +20 -0
  147. package/src/components/resources/QuestionnaireResponse/Answers.js +59 -0
  148. package/src/components/resources/QuestionnaireResponse/Group.js +70 -0
  149. package/src/components/resources/QuestionnaireResponse/Items.js +45 -0
  150. package/src/components/resources/QuestionnaireResponse/QuestionnaireResponse.css +33 -8
  151. package/src/components/resources/QuestionnaireResponse/QuestionnaireResponse.js +52 -236
  152. package/src/components/resources/QuestionnaireResponse/QuestionnaireResponse.stories.js +8 -0
  153. package/src/components/resources/QuestionnaireResponse/QuestionnaireResponse.test.js +38 -3
  154. package/src/components/resources/QuestionnaireResponse/Questions.js +43 -0
  155. package/src/components/resources/QuestionnaireResponse/getQuestionText.js +22 -0
  156. package/src/components/resources/ReferralRequest/ReferralRequest.js +65 -40
  157. package/src/components/resources/ReferralRequest/ReferralRequest.test.js +111 -11
  158. package/src/components/resources/RelatedPerson/RelatedPerson.js +151 -0
  159. package/src/components/resources/RelatedPerson/RelatedPerson.stories.js +46 -0
  160. package/src/components/resources/RelatedPerson/RelatedPerson.test.js +156 -0
  161. package/src/components/resources/RelatedPerson/index.js +3 -0
  162. package/src/components/resources/ResearchStudy/ResearchStudy.js +160 -130
  163. package/src/components/resources/ResearchStudy/ResearchStudy.stories.js +2 -0
  164. package/src/components/resources/ResearchStudy/ResearchStudy.test.js +108 -1
  165. package/src/components/resources/ResourceCategory/ResourceCategory.js +7 -12
  166. package/src/components/resources/ResourceCategory/ResourceCategory.stories.js +13 -2
  167. package/src/components/resources/ResourceCategory/ResourceCategory.test.js +77 -18
  168. package/src/components/ui/index.js +32 -12
  169. package/src/fixtures/dstu2/resources/relatedPerson/example1.json +79 -0
  170. package/src/fixtures/example-icons.jsx +81 -11
  171. package/src/fixtures/r4/resources/relatedPerson/example1.json +64 -0
  172. package/src/fixtures/stu3/resources/relatedPerson/example1.json +43 -0
  173. package/src/style.scss +3 -1
@@ -0,0 +1,70 @@
1
+ import _get from 'lodash/get';
2
+ import { MissingValue } from '../../ui';
3
+ import PropTypes from 'prop-types';
4
+ import React from 'react';
5
+ import Answers from './Answers';
6
+ import Questions from './Questions';
7
+
8
+ const Group = ({ data, prepareItems, isChild = false }) => {
9
+ if (!Array.isArray(data) || data.length === 0) {
10
+ return null;
11
+ }
12
+
13
+ return data.map(prepareItems).map((item, i) => {
14
+ const title =
15
+ _get(item, 'title') ||
16
+ _get(item, 'text') ||
17
+ _get(item, '_linkId.fhir_comments.0');
18
+
19
+ return (
20
+ <ul
21
+ key={`questionnaire-response-item-${i}`}
22
+ className="fhir-resource__QuestionnaireResponse-list"
23
+ >
24
+ <li
25
+ className={
26
+ isChild
27
+ ? 'fhir-resource__QuestionnaireResponse-list-title-question'
28
+ : 'fhir-resource__QuestionnaireResponse-list-title'
29
+ }
30
+ data-testid={`linkId-${item.linkId}`}
31
+ >
32
+ {title || <MissingValue />}
33
+ </li>
34
+ {item.isGroup && (
35
+ <li>
36
+ <Group data={item.group} prepareItems={prepareItems} isChild />
37
+ </li>
38
+ )}
39
+ {!item.isGroup && (
40
+ <>
41
+ {item.question && (
42
+ <li>
43
+ <Questions
44
+ questions={item.question}
45
+ prepareItems={prepareItems}
46
+ />
47
+ </li>
48
+ )}
49
+ {item.answer && (
50
+ <li>
51
+ <Answers
52
+ data={item.answer}
53
+ prepareItems={prepareItems}
54
+ data-testid={`answer-${item.linkId}`}
55
+ />
56
+ </li>
57
+ )}
58
+ </>
59
+ )}
60
+ </ul>
61
+ );
62
+ });
63
+ };
64
+
65
+ Group.propTypes = {
66
+ data: PropTypes.array,
67
+ prepareItems: PropTypes.func.isRequired,
68
+ };
69
+
70
+ export default Group;
@@ -0,0 +1,45 @@
1
+ import fhirVersions from '../fhirResourceVersions';
2
+ import _get from 'lodash/get';
3
+ import PropTypes from 'prop-types';
4
+ import React from 'react';
5
+ import Group from './Group';
6
+
7
+ const Items = ({ fhirVersion, data }) => {
8
+ if (fhirVersion === fhirVersions.DSTU2) {
9
+ const prepareItems = item => {
10
+ return {
11
+ ...item,
12
+ isGroup: !!_get(item, 'group'),
13
+ };
14
+ };
15
+
16
+ if (data.isGroup) {
17
+ return <Group data={data.data} prepareItems={prepareItems} />;
18
+ }
19
+ return (
20
+ <Group data={[{ question: data.data }]} prepareItems={prepareItems} />
21
+ );
22
+ }
23
+
24
+ if (fhirVersion === fhirVersions.STU3 || fhirVersion === fhirVersions.R4) {
25
+ const prepareItems = item => ({
26
+ ...item,
27
+ group: !!_get(item, 'item') ? _get(item, 'item') : null,
28
+ isGroup: !!_get(item, 'item'),
29
+ });
30
+ return <Group data={[{ question: data }]} prepareItems={prepareItems} />;
31
+ }
32
+
33
+ return null;
34
+ };
35
+
36
+ Items.propTypes = {
37
+ data: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
38
+ fhirVersion: PropTypes.oneOf([
39
+ fhirVersions.DSTU2,
40
+ fhirVersions.STU3,
41
+ fhirVersions.R4,
42
+ ]).isRequired,
43
+ };
44
+
45
+ export default Items;
@@ -1,21 +1,45 @@
1
1
  .fhir-resource__QuestionnaireResponse-list {
2
2
  list-style: none;
3
- border: 1px solid #f0f0f0;
4
- padding: 2px;
5
- margin: 2px 2px 2px 20px;
3
+ padding: 0;
4
+ margin: 0;
5
+ }
6
+
7
+ .fhir-resource__QuestionnaireResponse-list:first-of-type {
8
+ padding-top: 20px;
6
9
  }
7
10
 
8
11
  .fhir-resource__QuestionnaireResponse-list-title {
9
- background-color: #f6f6f6;
10
- padding: 2px 2px 4px 2px;
12
+ padding: 2px 2px 8px 2px;
13
+ font-weight: bold;
14
+ }
15
+
16
+ .fhir-resource__QuestionnaireResponse-list-title-question {
17
+ background: #f8f9fa;
18
+ align-items: center;
19
+ margin-bottom: 56px;
20
+ padding-left: 16px;
21
+ border-radius: 4px;
22
+ color: #adb5bd;
11
23
  }
12
24
 
13
25
  .fhir-resource__QuestionnaireResponse-questions-list {
14
26
  list-style: none;
27
+ padding-left: 0;
28
+ display: block;
29
+ color: #adb5bd;
15
30
  }
16
31
 
17
32
  .fhir-resource__QuestionnaireResponse-questions-list li {
18
- border-bottom: 1px solid #f5f5f5;
33
+ display: block;
34
+ margin-bottom: 56px;
35
+ }
36
+
37
+ .fhir-resource__QuestionnaireResponse-questions-list-element {
38
+ background: #f8f9fa;
39
+ border-radius: 4px;
40
+ width: 100%;
41
+ padding-left: 16px;
42
+ margin-bottom: 56px;
19
43
  }
20
44
 
21
45
  .fhir-resource__QuestionnaireResponse-questions-list li:last-child {
@@ -23,11 +47,12 @@
23
47
  }
24
48
 
25
49
  .fhir-resource__QuestionnaireResponse-questions-list-item-details {
26
- margin-left: 20px;
50
+ margin: -30px 0;
27
51
  }
28
52
 
29
53
  .fhir-resource__QuestionnaireResponse-questions-list-item-details-el {
30
54
  display: inline-block;
55
+ color: black;
31
56
  margin-right: 15px;
32
- color: blue;
57
+ margin-left: 20px;
33
58
  }
@@ -2,221 +2,17 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import _get from 'lodash/get';
4
4
  import UnhandledResourceDataStructure from '../UnhandledResourceDataStructure';
5
- import {
6
- Root,
7
- Header,
8
- Title,
9
- Badge,
10
- BadgeSecondary,
11
- Body,
12
- Value,
13
- MissingValue,
14
- } from '../../ui';
5
+ import { Root, Header, Badge, Body, Value } from '../../ui';
15
6
  import Date from '../../datatypes/Date';
16
7
  import fhirVersions from '../fhirResourceVersions';
17
8
  import Coding from '../../datatypes/Coding';
18
9
  import Reference from '../../datatypes/Reference/Reference';
19
- import Attachment from '../../datatypes/Attachment';
20
- import Quantity from '../../datatypes/Quantity';
21
10
  import './QuestionnaireResponse.css';
11
+ import Accordion from '../../containers/Accordion';
12
+ import Items from './Items';
22
13
 
23
14
  const DEFAULT_TITLE = 'Questionnaire Response';
24
15
 
25
- const getQuestionText = item => {
26
- let text = _get(item, 'text');
27
- if (!text) {
28
- // DSTU2
29
- const groupConcept = _get(item, 'concept.0');
30
- if (groupConcept) {
31
- text = <Coding fhirData={groupConcept} />;
32
- }
33
- text = text ? text : <MissingValue />;
34
- // STU3
35
- const groupCode = _get(item, 'code.0');
36
- if (!text && groupCode) {
37
- text = <Coding fhirData={groupCode} />;
38
- }
39
- }
40
- return text;
41
- };
42
-
43
- const answerTypes = {
44
- valueString: value => value,
45
- valueDecimal: value => value,
46
- valueInteger: value => value,
47
- valueDate: value => <Date fhirData={value} />,
48
- valueDateTime: value => <Date fhirData={value} />,
49
- valueCoding: value => <Coding fhirData={value} />,
50
- valueAttachment: value => <Attachment fhirData={value} />,
51
- valueQuantity: value => <Quantity fhirData={value} />,
52
- valueBoolean: value => (value ? 'Yes' : 'No'),
53
- };
54
-
55
- const Answers = props => {
56
- const { data, prepareItems } = props;
57
- if (!Array.isArray(data)) {
58
- return null;
59
- }
60
- return (
61
- <div className="fhir-resource__QuestionnaireResponse-questions-list-item-details">
62
- {data.map(answer => {
63
- return Object.keys(answer).map((answerKey, i) => {
64
- const toRender = [];
65
- if (typeof answerTypes[answerKey] === 'function') {
66
- toRender.push(
67
- <div
68
- key={`item-${i}`}
69
- className="fhir-resource__QuestionnaireResponse-questions-list-item-details-el"
70
- data-testid={`${props['data-testid']}-${i}`}
71
- >
72
- {answerTypes[answerKey](answer[answerKey])}{' '}
73
- </div>,
74
- );
75
- }
76
- if (_get(answer, 'item')) {
77
- toRender.push(
78
- <Group
79
- key={`item-answer-${i}`}
80
- data={answer.item}
81
- prepareItems={prepareItems}
82
- />,
83
- );
84
- }
85
- return toRender;
86
- });
87
- })}
88
- </div>
89
- );
90
- };
91
-
92
- const Group = props => {
93
- const { data, prepareItems } = props;
94
- if (!Array.isArray(data) || data.length === 0) {
95
- return null;
96
- }
97
-
98
- return data.map(prepareItems).map((item, i) => {
99
- const title =
100
- _get(item, 'title') ||
101
- _get(item, 'text') ||
102
- _get(item, '_linkId.fhir_comments.0');
103
-
104
- return (
105
- <ul
106
- key={`item-${i}`}
107
- className="fhir-resource__QuestionnaireResponse-list"
108
- >
109
- <li
110
- className="fhir-resource__QuestionnaireResponse-list-title"
111
- data-testid={`linkId-${item.linkId}`}
112
- >
113
- {title || <MissingValue />}
114
- </li>
115
- {item.isGroup && (
116
- <li>
117
- <Group data={item.group} prepareItems={prepareItems} />
118
- </li>
119
- )}
120
- {!item.isGroup && (
121
- <>
122
- {item.question && (
123
- <li>
124
- <Questions
125
- questions={item.question}
126
- prepareItems={prepareItems}
127
- />
128
- </li>
129
- )}
130
- {item.answer && (
131
- <li>
132
- <Answers
133
- data={item.answer}
134
- prepareItems={prepareItems}
135
- data-testid={`answer-${item.linkId}`}
136
- />
137
- </li>
138
- )}
139
- </>
140
- )}
141
- </ul>
142
- );
143
- });
144
- };
145
-
146
- Group.propTypes = {
147
- data: PropTypes.array,
148
- prepareItems: PropTypes.func.isRequired,
149
- };
150
-
151
- const Questions = props => {
152
- const { questions, prepareItems } = props;
153
- if (!Array.isArray(questions) || questions.length === 0) {
154
- return null;
155
- }
156
- return (
157
- <ul className="fhir-resource__QuestionnaireResponse-questions-list">
158
- {questions.map(prepareItems).map((item, i) => {
159
- const text = getQuestionText(item);
160
- const hasGroup = item.isGroup;
161
- const answers = _get(item, 'answer', []);
162
- return (
163
- <li key={`item-${i}`} data-testid={`linkId-${item.linkId}`}>
164
- {text}
165
- {answers && <Answers data={item.answer} />}
166
- {hasGroup && (
167
- <Group data={item.group} prepareItems={prepareItems} />
168
- )}
169
- </li>
170
- );
171
- })}
172
- </ul>
173
- );
174
- };
175
-
176
- Questions.propTypes = {
177
- questions: PropTypes.array,
178
- prepareItems: PropTypes.func.isRequired,
179
- };
180
-
181
- const Items = props => {
182
- const { fhirVersion, data } = props;
183
- if (fhirVersion === fhirVersions.DSTU2) {
184
- const prepareItems = item => {
185
- return {
186
- ...item,
187
- isGroup: !!_get(item, 'group'),
188
- };
189
- };
190
-
191
- if (data.isGroup) {
192
- return <Group data={data.data} prepareItems={prepareItems} />;
193
- }
194
- return (
195
- <Group data={[{ question: data.data }]} prepareItems={prepareItems} />
196
- );
197
- }
198
-
199
- if (fhirVersion === fhirVersions.STU3 || fhirVersion === fhirVersions.R4) {
200
- const prepareItems = item => ({
201
- ...item,
202
- group: !!_get(item, 'item') ? _get(item, 'item') : null,
203
- isGroup: !!_get(item, 'item'),
204
- });
205
- return <Group data={[{ question: data }]} prepareItems={prepareItems} />;
206
- }
207
-
208
- return null;
209
- };
210
-
211
- Items.propTypes = {
212
- data: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
213
- fhirVersion: PropTypes.oneOf([
214
- fhirVersions.DSTU2,
215
- fhirVersions.STU3,
216
- fhirVersions.R4,
217
- ]).isRequired,
218
- };
219
-
220
16
  const commonDTO = fhirResource => {
221
17
  const status = _get(fhirResource, 'status');
222
18
  const dateTime = _get(fhirResource, 'authored');
@@ -275,8 +71,12 @@ const resourceDTO = (fhirVersion, fhirResource) => {
275
71
  }
276
72
  };
277
73
 
278
- const QuestionnaireResponse = props => {
279
- const { fhirResource, fhirVersion } = props;
74
+ const QuestionnaireResponse = ({
75
+ fhirResource,
76
+ fhirVersion,
77
+ fhirIcons,
78
+ onClick,
79
+ }) => {
280
80
  let fhirResourceData = {};
281
81
 
282
82
  try {
@@ -296,34 +96,50 @@ const QuestionnaireResponse = props => {
296
96
  rootItems,
297
97
  } = fhirResourceData;
298
98
 
99
+ const tableData = [
100
+ {
101
+ label: 'Subject',
102
+ testId: 'subject',
103
+ data: subject && <Reference fhirData={subject} />,
104
+ status: subject,
105
+ },
106
+ {
107
+ label: 'Author',
108
+ testId: 'author',
109
+ data: author && <Reference fhirData={author} />,
110
+ status: author,
111
+ },
112
+ ];
113
+
299
114
  return (
300
- <Root name="Questionnaire">
301
- <Header>
302
- <Title>{title || DEFAULT_TITLE}</Title>
303
- {status && <Badge data-testid="status">{status}</Badge>}
304
- {dateTime && (
305
- <BadgeSecondary data-testid="dateTime">
306
- <Date fhirData={dateTime} />
307
- </BadgeSecondary>
308
- )}
309
- </Header>
310
- <Body>
311
- {subject && (
312
- <Value label="Subject" data-testid="subject">
313
- <Reference fhirData={subject} />
314
- </Value>
315
- )}
316
- {author && (
317
- <Value label="Author" data-testid="author">
318
- <Reference fhirData={author} />
319
- </Value>
320
- )}
321
- {rootItems && (
322
- <div className="overflow-auto">
323
- <Items fhirVersion={fhirVersion} data={rootItems} />
324
- </div>
325
- )}
326
- </Body>
115
+ <Root name="QuestionnaireResponse">
116
+ <Accordion
117
+ headerContent={
118
+ <Header
119
+ resourceName="QuestionnaireResponse"
120
+ title={title || DEFAULT_TITLE}
121
+ badges={status && <Badge data-testid="status">{status}</Badge>}
122
+ additionalContent={
123
+ dateTime && (
124
+ <Value label="On" data-testid="dateTime">
125
+ <Date fhirData={dateTime} isBlack />
126
+ </Value>
127
+ )
128
+ }
129
+ icon={fhirIcons}
130
+ />
131
+ }
132
+ bodyContent={
133
+ <Body tableData={tableData}>
134
+ {rootItems && (
135
+ <div className="overflow-auto">
136
+ <Items fhirVersion={fhirVersion} data={rootItems} />
137
+ </div>
138
+ )}
139
+ </Body>
140
+ }
141
+ onClick={onClick}
142
+ />
327
143
  </Root>
328
144
  );
329
145
  };
@@ -14,6 +14,9 @@ import stu3Example2 from '../../../fixtures/stu3/resources/questionnaireResponse
14
14
  import r4Example1 from '../../../fixtures/r4/resources/questionnaireResponse/example1.json';
15
15
  import r4Example2 from '../../../fixtures/r4/resources/questionnaireResponse/example2.json';
16
16
 
17
+ import fhirIcons from '../../../fixtures/example-icons';
18
+ import QuestionnaireResponseIcon from '../../../assets/containers/QuestionnaireResponse/questionnaire-response.svg';
19
+
17
20
  export default { title: 'QuestionnaireResponse' };
18
21
 
19
22
  export const DefaultVisualizationDSTU2 = () => {
@@ -22,6 +25,7 @@ export const DefaultVisualizationDSTU2 = () => {
22
25
  <QuestionnaireResponse
23
26
  fhirVersion={fhirVersions.DSTU2}
24
27
  fhirResource={fhirResource}
28
+ fhirIcons={require('../../../assets/containers/QuestionnaireResponse/questionnaire-response.svg')}
25
29
  />
26
30
  );
27
31
  };
@@ -32,6 +36,7 @@ export const Example2OfDSTU2 = () => {
32
36
  <QuestionnaireResponse
33
37
  fhirVersion={fhirVersions.DSTU2}
34
38
  fhirResource={fhirResource}
39
+ fhirIcons={QuestionnaireResponseIcon}
35
40
  />
36
41
  );
37
42
  };
@@ -42,6 +47,7 @@ export const Example3OfDSTU2 = () => {
42
47
  <QuestionnaireResponse
43
48
  fhirVersion={fhirVersions.DSTU2}
44
49
  fhirResource={fhirResource}
50
+ fhirIcons={fhirIcons}
45
51
  />
46
52
  );
47
53
  };
@@ -52,6 +58,7 @@ export const Example1OfSTU3 = () => {
52
58
  <QuestionnaireResponse
53
59
  fhirVersion={fhirVersions.STU3}
54
60
  fhirResource={fhirResource}
61
+ fhirIcons={false}
55
62
  />
56
63
  );
57
64
  };
@@ -62,6 +69,7 @@ export const Example2OfSTU3 = () => {
62
69
  <QuestionnaireResponse
63
70
  fhirVersion={fhirVersions.STU3}
64
71
  fhirResource={fhirResource}
72
+ fhirIcons="random text"
65
73
  />
66
74
  );
67
75
  };
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { render } from '@testing-library/react';
2
+ import { fireEvent, render } from '@testing-library/react';
3
3
 
4
4
  import QuestionnaireResponse from './QuestionnaireResponse';
5
5
  import fhirVersions from '../fhirResourceVersions';
@@ -24,7 +24,7 @@ describe('QuestionnaireResponse should render component correctly', () => {
24
24
  );
25
25
  expect(getByTestId('status').textContent).toEqual('completed');
26
26
  expect(getByTestId('dateTime').textContent).toEqual('6/18/2013');
27
- expect(getByTestId('subject').textContent).toEqual('RoelPatient/f201');
27
+ expect(getByTestId('subject').textContent).toEqual('Roel');
28
28
  expect(getByTestId('author').textContent).toEqual('Practitioner/f201');
29
29
 
30
30
  expect(getByTestId('linkId-1.1').textContent).toEqual(
@@ -91,7 +91,7 @@ describe('QuestionnaireResponse should render component correctly', () => {
91
91
  );
92
92
  expect(getByTestId('status').textContent).toEqual('completed');
93
93
  expect(getByTestId('dateTime').textContent).toEqual('6/18/2013');
94
- expect(getByTestId('subject').textContent).toEqual('RoelPatient/f201');
94
+ expect(getByTestId('subject').textContent).toEqual('Roel');
95
95
  expect(getByTestId('author').textContent).toEqual('Practitioner/f201');
96
96
 
97
97
  expect(getByTestId('linkId-1.1').textContent).toEqual(
@@ -112,4 +112,39 @@ describe('QuestionnaireResponse should render component correctly', () => {
112
112
  'Do you drink alchohol?',
113
113
  );
114
114
  });
115
+
116
+ it('should fire custom onClick function', () => {
117
+ const defaultProps = {
118
+ fhirResource: r4Example1,
119
+ fhirVersion: fhirVersions.R4,
120
+ };
121
+
122
+ const onClick = jest.fn();
123
+ const { getByRole } = render(
124
+ <QuestionnaireResponse {...defaultProps} onClick={onClick} />,
125
+ );
126
+ const accordion = getByRole('button');
127
+ fireEvent.click(accordion);
128
+
129
+ const attribute = accordion.getAttribute('data-bs-toggle');
130
+ expect(attribute).not.toEqual('collapse');
131
+ expect(onClick).toHaveBeenCalled();
132
+ });
133
+
134
+ it('should not fire custom onClick function', () => {
135
+ const defaultProps = {
136
+ fhirResource: r4Example1,
137
+ fhirVersion: fhirVersions.R4,
138
+ };
139
+
140
+ const onClick = 'test';
141
+ const { getByRole } = render(
142
+ <QuestionnaireResponse {...defaultProps} onClick={onClick} />,
143
+ );
144
+ const accordion = getByRole('button');
145
+ fireEvent.click(accordion);
146
+
147
+ const attribute = accordion.getAttribute('data-bs-toggle');
148
+ expect(attribute).toEqual('collapse');
149
+ });
115
150
  });
@@ -0,0 +1,43 @@
1
+ import _get from 'lodash/get';
2
+ import PropTypes from 'prop-types';
3
+ import React from 'react';
4
+ import Group from './Group';
5
+ import Answers from './Answers';
6
+ import { getQuestionText } from './getQuestionText';
7
+
8
+ const Questions = ({ questions, prepareItems }) => {
9
+ if (!Array.isArray(questions) || questions.length === 0) {
10
+ return null;
11
+ }
12
+
13
+ return (
14
+ <ul className="fhir-resource__QuestionnaireResponse-questions-list">
15
+ {questions.map(prepareItems).map((item, i) => {
16
+ const text = getQuestionText(item);
17
+ const hasGroup = item.isGroup;
18
+ const answers = _get(item, 'answer', []);
19
+ return (
20
+ <li
21
+ key={`questionnaire-response-questions-item-${i}`}
22
+ data-testid={`linkId-${item.linkId}`}
23
+ >
24
+ <div className="fhir-resource__QuestionnaireResponse-questions-list-element">
25
+ {text}
26
+ </div>
27
+ {answers && <Answers data={item.answer} />}
28
+ {hasGroup && (
29
+ <Group data={item.group} prepareItems={prepareItems} isChild />
30
+ )}
31
+ </li>
32
+ );
33
+ })}
34
+ </ul>
35
+ );
36
+ };
37
+
38
+ Questions.propTypes = {
39
+ questions: PropTypes.array,
40
+ prepareItems: PropTypes.func.isRequired,
41
+ };
42
+
43
+ export default Questions;
@@ -0,0 +1,22 @@
1
+ import _get from 'lodash/get';
2
+ import Coding from '../../datatypes/Coding';
3
+ import { MissingValue } from '../../ui';
4
+ import React from 'react';
5
+
6
+ export const getQuestionText = item => {
7
+ let text = _get(item, 'text');
8
+ if (!text) {
9
+ // DSTU2
10
+ const groupConcept = _get(item, 'concept.0');
11
+ if (groupConcept) {
12
+ text = <Coding fhirData={groupConcept} />;
13
+ }
14
+ text = text ? text : <MissingValue />;
15
+ // STU3
16
+ const groupCode = _get(item, 'code.0');
17
+ if (!text && groupCode) {
18
+ text = <Coding fhirData={groupCode} />;
19
+ }
20
+ }
21
+ return text;
22
+ };