fhir-react 0.2.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/.github/workflows/publish_npmjs.yml +18 -0
  2. package/.storybook/config.js +9 -3
  3. package/.storybook/presets.js +1 -0
  4. package/.storybook/preview-head.html +4 -0
  5. package/README.md +47 -3
  6. package/package.json +13 -4
  7. package/src/assets/common/chevron-right.svg +3 -0
  8. package/src/assets/containers/AllergyIntolerance/allergy-intolerance.svg +9 -0
  9. package/src/assets/containers/Appointment/appointment.svg +14 -0
  10. package/src/assets/containers/CarePlan/care-plan.svg +10 -0
  11. package/src/assets/containers/CareTeam/care-team.svg +10 -0
  12. package/src/assets/containers/Claim/claim.svg +6 -0
  13. package/src/assets/containers/ClaimResponse/claim-response.svg +7 -0
  14. package/src/assets/containers/Condition/condition.svg +11 -0
  15. package/src/assets/containers/Device/device.svg +8 -0
  16. package/src/assets/containers/DiagnosticReport/diagnostic-report.svg +14 -0
  17. package/src/assets/containers/DocumentReference/document-reference.svg +10 -0
  18. package/src/assets/containers/Encounter/encounter.svg +10 -0
  19. package/src/assets/containers/ExplanationOfBenefit/explanation-of-benefit.svg +3 -0
  20. package/src/assets/containers/FamilyMemberHistory/family-member-history.svg +7 -0
  21. package/src/assets/containers/Goal/goal.svg +11 -0
  22. package/src/assets/containers/Immunization/immunization.svg +7 -0
  23. package/src/assets/containers/List/list.svg +3 -0
  24. package/src/assets/containers/Location/location.svg +4 -0
  25. package/src/assets/containers/Medication/medication.svg +5 -0
  26. package/src/assets/containers/MedicationAdministration/medication-administration.svg +6 -0
  27. package/src/assets/containers/MedicationKnowledge/medication-knowledge.svg +11 -0
  28. package/src/assets/containers/MedicationStatement/medication-statement.svg +5 -0
  29. package/src/assets/containers/Observation/observation.svg +12 -0
  30. package/src/assets/containers/Practitioner/practitioner.svg +5 -0
  31. package/src/assets/containers/Procedure/procedure.svg +9 -0
  32. package/src/assets/containers/Questionnaire/questionnaire.svg +6 -0
  33. package/src/assets/containers/QuestionnaireResponse/questionnaire-response.svg +6 -0
  34. package/src/assets/containers/QustionnaireResponse/questionnaire-response.svg +6 -0
  35. package/src/assets/containers/ResearchStudy/research-study.svg +9 -0
  36. package/src/assets/containers/ResourceCategory/resource-placeholder.svg +3 -0
  37. package/src/components/containers/Accordion/Accordion.js +80 -0
  38. package/src/components/containers/Accordion/Accordion.stories.js +76 -0
  39. package/src/components/containers/Accordion/index.js +3 -0
  40. package/src/components/containers/ResourceContainer/ResourceContainer.css +0 -1
  41. package/src/components/containers/ResourceContainer/ResourceContainer.js +1 -1
  42. package/src/components/datatypes/AccountBalance/AccountBalance.js +33 -0
  43. package/src/components/datatypes/AccountBalance/index.js +3 -0
  44. package/src/components/datatypes/Annotation/Annotation.js +1 -1
  45. package/src/components/datatypes/Date/Date.js +14 -4
  46. package/src/components/datatypes/DatePeriod/DatePeriod.js +38 -0
  47. package/src/components/datatypes/DatePeriod/index.js +3 -0
  48. package/src/components/datatypes/HeaderIcon/HeaderIcon.js +31 -0
  49. package/src/components/datatypes/HeaderIcon/index.js +3 -0
  50. package/src/components/datatypes/HumanName/HumanName.js +6 -21
  51. package/src/components/datatypes/Reference/Reference.js +3 -6
  52. package/src/components/resources/AdverseEvent/AdverseEvent.test.js +2 -2
  53. package/src/components/resources/AllergyIntolerance/AllergyIntolerance.test.js +4 -4
  54. package/src/components/resources/Appointment/Appointment.js +91 -65
  55. package/src/components/resources/Appointment/Appointment.test.js +3 -3
  56. package/src/components/resources/Bundle/Bundle.js +2 -2
  57. package/src/components/resources/Bundle/Bundle.stories.js +78 -12
  58. package/src/components/resources/Bundle/Bundle.test.js +3 -0
  59. package/src/components/resources/CarePlan/CarePlan.test.js +4 -4
  60. package/src/components/resources/CareTeam/CareTeam.js +13 -14
  61. package/src/components/resources/CareTeam/CareTeam.test.js +4 -4
  62. package/src/components/resources/Claim/Claim.test.js +6 -6
  63. package/src/components/resources/ClaimResponse/ClaimResponse.test.js +6 -6
  64. package/src/components/resources/Condition/Condition.js +63 -47
  65. package/src/components/resources/Condition/Condition.stories.js +41 -8
  66. package/src/components/resources/Condition/Condition.test.js +20 -14
  67. package/src/components/resources/DiagnosticReport/DiagnosticReport.test.js +5 -7
  68. package/src/components/resources/DocumentReference/DocumentReference.js +1 -1
  69. package/src/components/resources/DocumentReference/DocumentReference.test.js +3 -3
  70. package/src/components/resources/Encounter/Encounter.js +66 -36
  71. package/src/components/resources/Encounter/EncounterParticipants.js +2 -2
  72. package/src/components/resources/ExplanationOfBenefit/CareTeam.js +2 -2
  73. package/src/components/resources/ExplanationOfBenefit/Diagnosis.js +15 -5
  74. package/src/components/resources/ExplanationOfBenefit/ExplanationOfBenefit.js +272 -201
  75. package/src/components/resources/ExplanationOfBenefit/ExplanationOfBenefit.test.js +79 -62
  76. package/src/components/resources/ExplanationOfBenefit/Items.js +2 -2
  77. package/src/components/resources/ExplanationOfBenefit/PriceLabel.js +20 -0
  78. package/src/components/resources/ExplanationOfBenefit/Related.js +3 -3
  79. package/src/components/resources/ExplanationOfBenefit/SupportingInfo.js +14 -3
  80. package/src/components/resources/ExplanationOfBenefit/TotalGraph.js +68 -0
  81. package/src/components/resources/ExplanationOfBenefitGraph/ExplanationOfBenefitGraph.js +89 -0
  82. package/src/components/resources/ExplanationOfBenefitGraph/ExplanationOfBenefitGraph.stories.js +78 -0
  83. package/src/components/resources/ExplanationOfBenefitGraph/ExplanationOfBenefitGraph.test.js +51 -0
  84. package/src/components/resources/ExplanationOfBenefitGraph/index.js +3 -0
  85. package/src/components/resources/Goal/Goal.test.js +1 -1
  86. package/src/components/resources/Immunization/Immunization.js +125 -94
  87. package/src/components/resources/Immunization/Immunization.stories.js +23 -4
  88. package/src/components/resources/Immunization/Immunization.test.js +17 -12
  89. package/src/components/resources/List/List.test.js +3 -3
  90. package/src/components/resources/MedicationAdministration/MedicationAdministration.test.js +7 -7
  91. package/src/components/resources/MedicationDispense/MedicationDispense.test.js +2 -2
  92. package/src/components/resources/MedicationRequest/MedicationRequest.test.js +4 -4
  93. package/src/components/resources/Observation/Observation.js +72 -54
  94. package/src/components/resources/Observation/Observation.test.js +6 -18
  95. package/src/components/resources/Observation/ObservationGraph.js +159 -55
  96. package/src/components/resources/Observation/ObservationGraph.test.js +47 -26
  97. package/src/components/resources/Patient/Patient.js +77 -87
  98. package/src/components/resources/Patient/Patient.test.js +1 -1
  99. package/src/components/resources/Practitioner/Practitioner.js +80 -60
  100. package/src/components/resources/Practitioner/Practitioner.test.js +4 -4
  101. package/src/components/resources/Procedure/Procedure.js +99 -87
  102. package/src/components/resources/Procedure/Procedure.stories.js +8 -6
  103. package/src/components/resources/Procedure/Procedure.test.js +11 -8
  104. package/src/components/resources/Questionnaire/Questionnaire.test.js +3 -3
  105. package/src/components/resources/QuestionnaireResponse/QuestionnaireResponse.test.js +5 -5
  106. package/src/components/resources/ReferralRequest/ReferralRequest.test.js +2 -2
  107. package/src/components/resources/ResearchStudy/ResearchStudy.test.js +1 -1
  108. package/src/components/resources/ResourceCategory/ResourceCategory.js +56 -0
  109. package/src/components/resources/ResourceCategory/ResourceCategory.stories.js +29 -0
  110. package/src/components/resources/ResourceCategory/ResourceCategory.test.js +101 -0
  111. package/src/components/resources/ResourceCategory/index.js +3 -0
  112. package/src/components/ui/_header.scss +3 -0
  113. package/src/components/ui/bootstrap-reboot.min.css +2 -22
  114. package/src/components/ui/index.js +191 -29
  115. package/src/constants/badge-status.jsx +98 -0
  116. package/src/fixtures/dstu2/resources/condition/condition.svg +35 -0
  117. package/src/fixtures/dstu2/resources/immunization/immunization.svg +10 -0
  118. package/src/fixtures/example-icons.jsx +169 -0
  119. package/src/index.js +6 -1
  120. package/src/style.scss +176 -0
  121. package/src/utils/formatDate.js +21 -0
  122. package/src/utils/formatDate.test.js +22 -0
  123. package/src/utils/getBadgeColor.js +6 -0
  124. package/src/utils/getBadgeColor.test.js +14 -0
  125. package/src/utils/isUrl.js +9 -0
  126. package/src/utils/isUrl.test.js +12 -0
  127. package/src/utils.js +7 -0
  128. package/build/bootstrap-reboot.min.css +0 -414
  129. package/build/index.js +0 -15
  130. package/build/style.css +0 -459
  131. package/src/components/datatypes/HumanName/HumanName.css +0 -15
  132. package/src/components/datatypes/Reference/Reference.css +0 -8
  133. package/src/components/resources/Observation/ObservationGraph.css +0 -51
  134. package/src/components/resources/Patient/Patient.css +0 -19
  135. package/src/components/ui/index.css +0 -123
@@ -1,17 +1,18 @@
1
- import React from 'react';
2
- import { render } from '@testing-library/react';
3
1
  import Procedure from './Procedure';
4
-
2
+ import React from 'react';
5
3
  import dstu2Example1 from '../../../fixtures/dstu2/resources/procedure/example1.json';
6
- import stu3Example1 from '../../../fixtures/stu3/resources/procedure/example1.json';
7
-
8
4
  import r4Example2 from '../../../fixtures/r4/resources/procedure/example2.json';
9
5
  import r4Example3 from '../../../fixtures/r4/resources/procedure/example3.json';
6
+ import { render } from '@testing-library/react';
7
+ import stu3Example1 from '../../../fixtures/stu3/resources/procedure/example1.json';
8
+
9
+ import fhirIcons from '../../../fixtures/example-icons';
10
10
 
11
11
  describe('Procedure should render component correctly', () => {
12
12
  it('should render component correctly with DSTU2 source data', () => {
13
13
  const defaultProps = {
14
14
  fhirResource: dstu2Example1,
15
+ fhirIcons: fhirIcons,
15
16
  };
16
17
  const { getByTestId } = render(<Procedure {...defaultProps} />);
17
18
 
@@ -22,6 +23,7 @@ describe('Procedure should render component correctly', () => {
22
23
  it('should render component correctly with STU3 source data', () => {
23
24
  const defaultProps = {
24
25
  fhirResource: stu3Example1,
26
+ fhirIcons: fhirIcons,
25
27
  };
26
28
  const { getByTestId } = render(<Procedure {...defaultProps} />);
27
29
 
@@ -34,6 +36,7 @@ describe('Procedure should render component correctly', () => {
34
36
  it('should render component that contain extra fields based of STU3 source data', () => {
35
37
  const defaultProps = {
36
38
  fhirResource: stu3Example1,
39
+ fhirIcons: fhirIcons,
37
40
  };
38
41
  const { getByTestId } = render(<Procedure {...defaultProps} />);
39
42
 
@@ -48,6 +51,7 @@ describe('Procedure should render component correctly', () => {
48
51
  it('should render component correctly with R4 source data - example 1', () => {
49
52
  const defaultProps = {
50
53
  fhirResource: r4Example2,
54
+ fhirIcons: fhirIcons,
51
55
  };
52
56
  const { getByTestId, queryByTestId } = render(
53
57
  <Procedure {...defaultProps} />,
@@ -57,9 +61,7 @@ describe('Procedure should render component correctly', () => {
57
61
  'Insertion of intracardiac pacemaker (procedure)',
58
62
  );
59
63
  expect(getByTestId('status').textContent).toEqual('completed');
60
- expect(getByTestId('performedDateTime').textContent).toEqual(
61
- 'on 2015-04-05',
62
- );
64
+ expect(getByTestId('providedDate').textContent).toEqual('4/5/2015');
63
65
  expect(getByTestId('hasCoding').textContent).toContain(
64
66
  'Insertion of intracardiac',
65
67
  );
@@ -77,6 +79,7 @@ describe('Procedure should render component correctly', () => {
77
79
  it('should render component correctly with STU3 source data - example 2', () => {
78
80
  const defaultProps = {
79
81
  fhirResource: r4Example3,
82
+ fhirIcons: fhirIcons,
80
83
  };
81
84
  const { getByTestId, queryByTestId } = render(
82
85
  <Procedure {...defaultProps} />,
@@ -58,7 +58,7 @@ describe('Questionnaire should render component correctly', () => {
58
58
  'Cancer Quality Forum Questionnaire',
59
59
  );
60
60
  expect(getByTestId('status').textContent).toEqual('draft');
61
- expect(getByTestId('dateTime').textContent).toEqual('2012-01');
61
+ expect(getByTestId('dateTime').textContent).toEqual('January 2012');
62
62
 
63
63
  // contain id and test of questions of subgroup
64
64
  expect(String(getByTestId('linkId-1.1').textContent).trim()).toContain(
@@ -119,7 +119,7 @@ describe('Questionnaire should render component correctly', () => {
119
119
  'Cancer Quality Forum Questionnaire',
120
120
  );
121
121
  expect(getByTestId('status').textContent).toEqual('draft');
122
- expect(getByTestId('dateTime').textContent).toEqual('2012-01');
122
+ expect(getByTestId('dateTime').textContent).toEqual('January 2012');
123
123
 
124
124
  // contain id and test of questions of subgroup
125
125
  expect(String(getByTestId('linkId-1.1').textContent).trim()).toContain(
@@ -180,7 +180,7 @@ describe('Questionnaire should render component correctly', () => {
180
180
  'Cancer Quality Forum Questionnaire',
181
181
  );
182
182
  expect(getByTestId('status').textContent).toEqual('draft');
183
- expect(getByTestId('dateTime').textContent).toEqual('2012-01');
183
+ expect(getByTestId('dateTime').textContent).toEqual('January 2012');
184
184
 
185
185
  // contain id and test of questions of subgroup
186
186
  expect(String(getByTestId('linkId-1.1').textContent).trim()).toContain(
@@ -23,7 +23,7 @@ describe('QuestionnaireResponse should render component correctly', () => {
23
23
  'Questionnaire Response',
24
24
  );
25
25
  expect(getByTestId('status').textContent).toEqual('completed');
26
- expect(getByTestId('dateTime').textContent).toEqual('2013-06-18');
26
+ expect(getByTestId('dateTime').textContent).toEqual('6/18/2013');
27
27
  expect(getByTestId('subject').textContent).toEqual('RoelPatient/f201');
28
28
  expect(getByTestId('author').textContent).toEqual('Practitioner/f201');
29
29
 
@@ -34,7 +34,7 @@ describe('QuestionnaireResponse should render component correctly', () => {
34
34
  'What is your gender?Male ',
35
35
  );
36
36
  expect(getByTestId('linkId-2.2').textContent).toEqual(
37
- 'What is your date of birth?1960-03-13 ',
37
+ 'What is your date of birth?3/13/1960 ',
38
38
  );
39
39
  expect(getByTestId('linkId-2.3').textContent).toEqual(
40
40
  'What is your country of birth?The Netherlands ',
@@ -56,7 +56,7 @@ describe('QuestionnaireResponse should render component correctly', () => {
56
56
  'Glasgow Coma Score',
57
57
  );
58
58
  expect(getByTestId('status').textContent).toEqual('completed');
59
- expect(getByTestId('dateTime').textContent).toEqual('2014-12-11');
59
+ expect(getByTestId('dateTime').textContent).toEqual('12/11/2014');
60
60
 
61
61
  expect(getByTestId('linkId-1.1').textContent).toContain('(LA6560-2) ');
62
62
  });
@@ -72,7 +72,7 @@ describe('QuestionnaireResponse should render component correctly', () => {
72
72
  'Questionnaire Response',
73
73
  );
74
74
  expect(getByTestId('status').textContent).toEqual('completed');
75
- expect(getByTestId('dateTime').textContent).toEqual('2013-02-19');
75
+ expect(getByTestId('dateTime').textContent).toEqual('2/19/2013');
76
76
 
77
77
  expect(getByTestId('answer-nameOfChild-0').textContent).toContain(
78
78
  'Cathy Jones',
@@ -90,7 +90,7 @@ describe('QuestionnaireResponse should render component correctly', () => {
90
90
  'Questionnaire Response',
91
91
  );
92
92
  expect(getByTestId('status').textContent).toEqual('completed');
93
- expect(getByTestId('dateTime').textContent).toEqual('2013-06-18');
93
+ expect(getByTestId('dateTime').textContent).toEqual('6/18/2013');
94
94
  expect(getByTestId('subject').textContent).toEqual('RoelPatient/f201');
95
95
  expect(getByTestId('author').textContent).toEqual('Practitioner/f201');
96
96
 
@@ -21,7 +21,7 @@ describe('should render ReferralRequest component properly', () => {
21
21
  expect(getByTestId('typeCoding').textContent).toContain(
22
22
  'Referral for service',
23
23
  );
24
- expect(getByTestId('dateSent').textContent).toContain('2014-02-14');
24
+ expect(getByTestId('dateSent').textContent).toContain('2/14/2014');
25
25
  expect(getByTestId('reason').textContent).toContain(
26
26
  'For consideration of Grommets',
27
27
  );
@@ -46,7 +46,7 @@ describe('should render ReferralRequest component properly', () => {
46
46
  expect(getByTestId('typeCoding').textContent).toContain(
47
47
  'Patient referral to specialist',
48
48
  );
49
- expect(getByTestId('dateSent').textContent).toContain('2014-02-14');
49
+ expect(getByTestId('dateSent').textContent).toContain('2/14/2014');
50
50
  expect(getByTestId('reason').textContent).toContain(
51
51
  'For consideration of Grommets',
52
52
  );
@@ -48,7 +48,7 @@ describe('should render ResearchStudy component properly', () => {
48
48
 
49
49
  expect(title).toEqual('Example study');
50
50
  expect(status).toEqual('completed');
51
- expect(period).toEqual('2015-02-01 - 2015-02-21');
51
+ expect(period).toEqual('2/1/2015 - 2/21/2015');
52
52
  expect(category).toEqual('Gene expression (GENE)');
53
53
  expect(focus).toEqual('Prostate cancer (PRC)');
54
54
  expect(protocol).toEqual('PlanDefinition/pdf1');
@@ -0,0 +1,56 @@
1
+ import { Root, Title } from '../../ui';
2
+ import ChevronRight from '../../../assets/common/chevron-right.svg';
3
+ import HeaderIcon from '../../datatypes/HeaderIcon';
4
+ import React from 'react';
5
+ import PropTypes from 'prop-types';
6
+
7
+ const ResourceCategory = props => {
8
+ const { title, itemsCount, fhirIcons } = props;
9
+
10
+ const parseNumber = value =>
11
+ /^[1-9]+\d*$/.test(value) ? Number.parseInt(value) : null;
12
+
13
+ const getItemsCountLabel = () =>
14
+ `${parsedItemsCount} ${parsedItemsCount === 1 ? 'item' : 'items'}`;
15
+
16
+ const headerIcon = fhirIcons['ResourceCategoryPlaceholder'];
17
+ const parsedItemsCount = parseNumber(itemsCount);
18
+
19
+ return (
20
+ <Root name="ResourceCategory">
21
+ <button
22
+ type="button"
23
+ className="btn d-flex align-items-center justify-content-between w-100 py-4 px-4 bg-white"
24
+ >
25
+ <div className="d-flex gap-2">
26
+ <HeaderIcon headerIcon={headerIcon} />
27
+ <Title data-testid="title">{title}</Title>
28
+ </div>
29
+ <div className="d-flex gap-2 align-items-center">
30
+ {parsedItemsCount > 0 && (
31
+ <div
32
+ className="d-flex rounded-pill py-1 px-2 bg-gray-200"
33
+ data-testid="itemsCount"
34
+ >
35
+ <small className="fw-bold text-nowrap ">
36
+ {getItemsCountLabel()}
37
+ </small>
38
+ </div>
39
+ )}
40
+ <img
41
+ src={ChevronRight}
42
+ alt="chevron"
43
+ style={{ height: 28, width: 28 }}
44
+ />
45
+ </div>
46
+ </button>
47
+ </Root>
48
+ );
49
+ };
50
+
51
+ ResourceCategory.propTypes = {
52
+ title: PropTypes.string.isRequired,
53
+ itemsCount: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
54
+ };
55
+
56
+ export default ResourceCategory;
@@ -0,0 +1,29 @@
1
+ import React from 'react';
2
+ import ResourceCategory from './ResourceCategory';
3
+ import fhirIcons from '../../../fixtures/example-icons';
4
+
5
+ export default { title: 'ResourceCategory' };
6
+
7
+ export const ExampleWithAllProperties = () => {
8
+ return (
9
+ <ResourceCategory
10
+ itemsCount={41}
11
+ title="Resource name"
12
+ fhirIcons={fhirIcons}
13
+ />
14
+ );
15
+ };
16
+
17
+ export const ExampleWith1Item = () => {
18
+ return (
19
+ <ResourceCategory
20
+ itemsCount={'1'}
21
+ title="Resource name"
22
+ fhirIcons={fhirIcons}
23
+ />
24
+ );
25
+ };
26
+
27
+ export const ExampleWithoutItemsCount = () => {
28
+ return <ResourceCategory title="Resource name" fhirIcons={fhirIcons} />;
29
+ };
@@ -0,0 +1,101 @@
1
+ import React from 'react';
2
+ import { render } from '@testing-library/react';
3
+
4
+ import fhirIcons from '../../../fixtures/example-icons';
5
+ import ResourceCategory from './ResourceCategory';
6
+
7
+ describe('should render ResourceCategory component properly', () => {
8
+ const placeholderResource = fhirIcons['ResourceCategoryPlaceholder'].props;
9
+
10
+ it('should render ResourceCategory component with icon and itemsCount > 1 correctly', () => {
11
+ const defaultProps = {
12
+ fhirIcons: fhirIcons,
13
+ itemsCount: '41',
14
+ title: 'Resource name',
15
+ };
16
+
17
+ const { container, getByTestId, getByAltText } = render(
18
+ <ResourceCategory {...defaultProps} />,
19
+ );
20
+ expect(container).not.toBeNull();
21
+
22
+ expect(getByTestId('itemsCount').textContent).toContain('41 items');
23
+ expect(getByTestId('title').textContent).toContain('Resource name');
24
+ const image = getByAltText(placeholderResource.alt);
25
+ expect(image.src).toContain(placeholderResource.src);
26
+ });
27
+
28
+ it('should render ResourceCategory component with icon and itemsCount === 1 correctly', () => {
29
+ const defaultProps = {
30
+ fhirIcons: fhirIcons,
31
+ itemsCount: 1,
32
+ title: 'Resource name',
33
+ };
34
+
35
+ const { container, getByTestId, getByAltText } = render(
36
+ <ResourceCategory {...defaultProps} />,
37
+ );
38
+ expect(container).not.toBeNull();
39
+
40
+ expect(getByTestId('itemsCount').textContent).toContain('1 item');
41
+ expect(getByTestId('title').textContent).toContain('Resource name');
42
+ const image = getByAltText(placeholderResource.alt);
43
+ expect(image.src).toContain(placeholderResource.src);
44
+ });
45
+
46
+ it('should render ResourceCategory correctly with negative number passed as itemsCount', () => {
47
+ const defaultProps = {
48
+ fhirIcons: fhirIcons,
49
+ itemsCount: -1,
50
+ title: 'Resource name',
51
+ };
52
+
53
+ const { container, getByTestId, getByAltText, queryByTestId } = render(
54
+ <ResourceCategory {...defaultProps} />,
55
+ );
56
+ expect(container).not.toBeNull();
57
+
58
+ const item = queryByTestId('itemsCount');
59
+ expect(item).toBeNull();
60
+ expect(getByTestId('title').textContent).toContain('Resource name');
61
+ const image = getByAltText(placeholderResource.alt);
62
+ expect(image.src).toContain(placeholderResource.src);
63
+ });
64
+
65
+ it('should render ResourceCategory correctly with invalid string passed as itemsCount', () => {
66
+ const defaultProps = {
67
+ fhirIcons: fhirIcons,
68
+ itemsCount: 'asdf1',
69
+ title: 'Resource name',
70
+ };
71
+
72
+ const { container, getByTestId, getByAltText, queryByTestId } = render(
73
+ <ResourceCategory {...defaultProps} />,
74
+ );
75
+ expect(container).not.toBeNull();
76
+ const item = queryByTestId('itemsCount');
77
+ expect(item).toBeNull();
78
+ expect(getByTestId('title').textContent).toContain('Resource name');
79
+ const image = getByAltText(placeholderResource.alt);
80
+ expect(image.src).toContain(placeholderResource.src);
81
+ });
82
+
83
+ it('should render ResourceCategory correctly with floating point number passed as text in itemsCount', () => {
84
+ const defaultProps = {
85
+ fhirIcons: fhirIcons,
86
+ itemsCount: '0.5',
87
+ title: 'Resource name',
88
+ };
89
+
90
+ const { container, getByTestId, getByAltText, queryByTestId } = render(
91
+ <ResourceCategory {...defaultProps} />,
92
+ );
93
+ expect(container).not.toBeNull();
94
+
95
+ const item = queryByTestId('itemsCount');
96
+ expect(item).toBeNull();
97
+ expect(getByTestId('title').textContent).toContain('Resource name');
98
+ const image = getByAltText(placeholderResource.alt);
99
+ expect(image.src).toContain(placeholderResource.src);
100
+ });
101
+ });
@@ -0,0 +1,3 @@
1
+ import ResourceCategory from './ResourceCategory';
2
+
3
+ export default ResourceCategory;
@@ -0,0 +1,3 @@
1
+ .header-rotate {
2
+ transform: rotate(-180deg);
3
+ }
@@ -14,23 +14,9 @@
14
14
  }
15
15
 
16
16
  .fhir-resource {
17
- font-family:
18
- -apple-system,
19
- BlinkMacSystemFont,
20
- 'Segoe UI',
21
- Roboto,
22
- 'Helvetica Neue',
23
- Arial,
24
- 'Noto Sans',
25
- sans-serif,
26
- 'Apple Color Emoji',
27
- 'Segoe UI Emoji',
28
- 'Segoe UI Symbol',
29
- 'Noto Color Emoji';
30
17
  font-size: 1rem;
31
18
  font-weight: 400;
32
19
  line-height: 1.5;
33
- color: #212529;
34
20
  background-color: #fff;
35
21
  -webkit-text-size-adjust: 100%;
36
22
  -webkit-tap-highlight-color: transparent;
@@ -187,14 +173,8 @@ sup {
187
173
  .fhir-resource kbd,
188
174
  .fhir-resource pre,
189
175
  .fhir-resource samp {
190
- font-family:
191
- SFMono-Regular,
192
- Menlo,
193
- Monaco,
194
- Consolas,
195
- 'Liberation Mono',
196
- 'Courier New',
197
- monospace;
176
+ font-family: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono',
177
+ 'Courier New', monospace;
198
178
  font-size: 1em;
199
179
  }
200
180
 
@@ -1,69 +1,214 @@
1
1
  import React from 'react';
2
2
 
3
- import './index.css';
3
+ import { getBadgeColor } from '../../utils/getBadgeColor';
4
+ import HeaderIcon from '../datatypes/HeaderIcon';
4
5
 
5
- export const Header = props => (
6
- <div className="fhir-ui__Header">{props.children}</div>
7
- );
6
+ export const Header = props => {
7
+ const rightItemsClass = 'align-items-center flex-fill d-flex';
8
+
9
+ return (
10
+ <>
11
+ {// This condition was left due to fact, that to much changes in Header will generate many errors in tests. This condition will be removed after all changes have been made.
12
+ props.children || (
13
+ <div
14
+ className={`fhir-ui__${props.resourceName}-Header w-100 p-4 position-relative`}
15
+ >
16
+ <div
17
+ className={`fhir-ui__${props.resourceName}-Header__title-data ${
18
+ props.isAccordionOpenable ? 'header__title-row' : ''
19
+ } d-flex w-100 flex-column flex-sm-row`}
20
+ >
21
+ <div className="d-flex">
22
+ <div
23
+ className={`fhir-ui__${props.resourceName}-Header__icon flex-shrink-1 m-half me-2`}
24
+ >
25
+ <HeaderIcon headerIcon={props.icon} />
26
+ </div>
27
+ <div
28
+ className={`fhir-ui__${props.resourceName}-Header__title flex-fill text-start`}
29
+ >
30
+ <Title data-testid={props.titleTestID || 'title'}>
31
+ {props.title || ''}
32
+ </Title>
33
+ </div>
34
+ </div>
35
+
36
+ <div
37
+ className={`fhir-ui__${props.resourceName}-Header__badges ps-1 ps-sm-2 mt-3 mt-sm-0 badges-max-width-sm flex-wrap flex-sm-nowrap justify-content-between justify-content-sm-end ${rightItemsClass}`}
38
+ >
39
+ {props.prefixBadge && (
40
+ <div className="me-3">{props.prefixBadge}</div>
41
+ )}
42
+ <div className="d-flex">
43
+ {props.badges}
44
+ {props.additionalBadge && (
45
+ <div className="ms-3">{props.additionalBadge}</div>
46
+ )}
47
+ </div>
48
+ </div>
49
+ </div>
50
+ <div
51
+ className={`fhir-ui__${
52
+ props.resourceName
53
+ }-Header__additional-content w-100 justify-content-start d-flex ${
54
+ props.additionalContent ? ' pt-2' : ''
55
+ }`}
56
+ >
57
+ {props.additionalContent}
58
+ <div
59
+ className={`fhir-ui__${props.resourceName}-Header__rightAdditionalContent justify-content-end ${rightItemsClass}`}
60
+ >
61
+ {props.rightAdditionalContent}
62
+ </div>
63
+ </div>
64
+ </div>
65
+ )}
66
+ </>
67
+ );
68
+ };
8
69
 
9
70
  export const Title = props => (
10
- <h4 className="fhir-ui__Title" data-testid="title">
71
+ <h4
72
+ className="fhir-ui__Title fw-bold fs-4 lh-base mb-0 w-90 title-width-sm"
73
+ data-testid={props['data-testid'] || 'title'}
74
+ >
11
75
  {props.children}
12
76
  </h4>
13
77
  );
14
78
 
15
- export const Badge = props => (
16
- <span className="fhir-ui__Badge" data-testid={props['data-testid']}>
17
- {props.children}
18
- </span>
19
- );
79
+ export const Badge = props => {
80
+ return (
81
+ <small
82
+ className={`fhir-ui__Badge text-capitalize d-flex align-items-center px-2 py-1 rounded-1 fw-bold ${getBadgeColor(
83
+ props,
84
+ )}`}
85
+ data-testid={props['data-testid']}
86
+ >
87
+ {props.children}
88
+ </small>
89
+ );
90
+ };
20
91
 
21
92
  export const BadgeSecondary = props => (
22
- <span className="fhir-ui__BadgeSecondary" data-testid={props['data-testid']}>
93
+ <small
94
+ className={`fhir-ui__BadgeSecondary px-2 py-1 rounded-1 fw-bold ${getBadgeColor(
95
+ props,
96
+ )}`}
97
+ data-testid={props['data-testid']}
98
+ >
23
99
  {props.children}
24
- </span>
100
+ </small>
101
+ );
102
+
103
+ export const ValueUnit = props => (
104
+ <div className="fhir-ui__ValueUnitRoot">
105
+ <span
106
+ data-testid="valueQuantity"
107
+ className="fhir-ui__ValueUnitQty fw-bold me-1"
108
+ >
109
+ {props.valueQty}
110
+ </span>
111
+ <span
112
+ data-testid="valueQuantityUnit"
113
+ className="fhir-ui__ValueUnit fw-bold text-gray-500"
114
+ >
115
+ {props.valueUnit}
116
+ </span>
117
+ </div>
25
118
  );
26
119
 
27
- export const Body = props => <div>{props.children}</div>;
120
+ export const Body = ({ tableData = [], reverseContent, children }) => (
121
+ <div className="fhir-ui__Body">
122
+ {reverseContent ? children : null}
123
+ <div className="row">
124
+ {tableData.map(
125
+ (value, index) =>
126
+ value.status && (
127
+ <div
128
+ className="d-flex flex-column flex-sm-row"
129
+ key={`table-data-item-${index}`}
130
+ >
131
+ <div className="dataTable__value-label ps-0">
132
+ <Label>{value.label}</Label>
133
+ </div>
134
+ <Data data-testid={value.testId}>{value.data}</Data>
135
+ </div>
136
+ ),
137
+ )}
138
+ </div>
139
+ {!reverseContent ? children : null}
140
+ </div>
141
+ );
28
142
 
29
143
  export const Value = props => (
30
- <div className="fhir-ui__Value">
31
- <label className="fhir-ui__Value-label">{props.label}</label>
32
- <div data-testid={props['data-testid']}>{props.children}</div>
144
+ <div
145
+ className={`fhir-ui__Value d-flex align-items-center flex-wrap flex-sm-nowrap pt-3 pb-2 pt-sm-0 pb-sm-0 ${
146
+ props.dirColumn ? 'flex-column align-items-baseline' : ''
147
+ }`}
148
+ >
149
+ <Label>{props.label}</Label>
150
+ <Data data-testid={props['data-testid']}>{props.children}</Data>
33
151
  </div>
34
152
  );
35
153
 
36
- export const Root = props => (
37
- <div className={`fhir-resource fhir-resource__${props.name}`}>
154
+ export const Label = props => (
155
+ <div className="fhir-ui__Label font-source text-secondary lh-lg me-2">
156
+ {props.children}
157
+ </div>
158
+ );
159
+
160
+ export const Data = props => (
161
+ <div
162
+ className="fhir-ui__Data font-source fw-normal lh-lg text-break"
163
+ data-testid={props['data-testid']}
164
+ >
38
165
  {props.children}
39
166
  </div>
40
167
  );
41
168
 
169
+ export const Root = props => (
170
+ <div className={`fhir-resource__${props.name}`}>{props.children}</div>
171
+ );
172
+
42
173
  export const Table = props => (
43
- <table className="fhir-ui__Table">{props.children}</table>
174
+ <div className="table-responsive">
175
+ <table className={`table table-striped mb-0 ${props.className || ''}`}>
176
+ {props.children}
177
+ </table>
178
+ </div>
44
179
  );
45
180
 
46
181
  export const TableHeader = props => {
47
182
  const { expand, noWordWrap } = props;
48
- let className = 'fhir-ui__TableHeader';
49
- if (expand) className += ' fhir-ui__TableHeader--expand';
50
- if (noWordWrap) className += ' fhir-ui__TableHeader--no-word-wrap';
51
- return <th className={className}>{props.children}</th>;
183
+ return (
184
+ <th
185
+ className={`${expand ? 'w-100' : ''} ${
186
+ noWordWrap ? 'text-nowrap' : ''
187
+ } text-gray-500`}
188
+ >
189
+ {props.children}
190
+ </th>
191
+ );
52
192
  };
53
193
 
54
- export const TableRow = props => (
55
- <tr className="fhir-ui__TableRow">{props.children}</tr>
56
- );
194
+ export const TableRow = props => <tr>{props.children}</tr>;
57
195
 
58
196
  export const TableCell = props => (
59
- <td className="fhir-ui__TableCell" data-testid={props['data-testid']}>
197
+ <td className="align-text-top border-0" data-testid={props['data-testid']}>
60
198
  {props.children}
61
199
  </td>
62
200
  );
63
201
 
64
202
  export const ValueSection = props => (
65
- <div className="fhir-ui__ValueSection" data-testid={props['data-testid']}>
66
- <label className="fhir-ui__ValueSection-label">{props.label}</label>
203
+ <div
204
+ className={`fhir-ui__ValueSection ${props.marginTop ? 'mt-40' : ''} ${
205
+ props.marginBottom ? 'mb-40' : ''
206
+ } ${props.className || ''}`}
207
+ data-testid={props['data-testid']}
208
+ >
209
+ <label className="fhir-ui__ValueSection-label fw-bold mb-2">
210
+ {props.label}
211
+ </label>
67
212
  <div className="fhir-ui__ValueSection-body">{props.children}</div>
68
213
  </div>
69
214
  );
@@ -77,3 +222,20 @@ export const NotEnoughData = props => (
77
222
  No additional data
78
223
  </div>
79
224
  );
225
+
226
+ export const Chevron = props => (
227
+ <svg
228
+ width="24"
229
+ height="24"
230
+ viewBox="0 0 24 24"
231
+ fill="none"
232
+ xmlns="http://www.w3.org/2000/svg"
233
+ >
234
+ <path
235
+ d="M20 8L12.3769 15.8393C12.277 15.9422 12.1414 16 12 16C11.8586 16 11.723 15.9422 11.6231 15.8393L4 8"
236
+ stroke={props.strokeColor}
237
+ strokeLinecap="round"
238
+ strokeLinejoin="round"
239
+ />
240
+ </svg>
241
+ );