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.
- package/.github/workflows/publish_npmjs.yml +18 -0
- package/.storybook/config.js +9 -3
- package/.storybook/presets.js +1 -0
- package/.storybook/preview-head.html +4 -0
- package/README.md +47 -3
- package/package.json +13 -4
- package/src/assets/common/chevron-right.svg +3 -0
- package/src/assets/containers/AllergyIntolerance/allergy-intolerance.svg +9 -0
- package/src/assets/containers/Appointment/appointment.svg +14 -0
- package/src/assets/containers/CarePlan/care-plan.svg +10 -0
- package/src/assets/containers/CareTeam/care-team.svg +10 -0
- package/src/assets/containers/Claim/claim.svg +6 -0
- package/src/assets/containers/ClaimResponse/claim-response.svg +7 -0
- package/src/assets/containers/Condition/condition.svg +11 -0
- package/src/assets/containers/Device/device.svg +8 -0
- package/src/assets/containers/DiagnosticReport/diagnostic-report.svg +14 -0
- package/src/assets/containers/DocumentReference/document-reference.svg +10 -0
- package/src/assets/containers/Encounter/encounter.svg +10 -0
- package/src/assets/containers/ExplanationOfBenefit/explanation-of-benefit.svg +3 -0
- package/src/assets/containers/FamilyMemberHistory/family-member-history.svg +7 -0
- package/src/assets/containers/Goal/goal.svg +11 -0
- package/src/assets/containers/Immunization/immunization.svg +7 -0
- package/src/assets/containers/List/list.svg +3 -0
- package/src/assets/containers/Location/location.svg +4 -0
- package/src/assets/containers/Medication/medication.svg +5 -0
- package/src/assets/containers/MedicationAdministration/medication-administration.svg +6 -0
- package/src/assets/containers/MedicationKnowledge/medication-knowledge.svg +11 -0
- package/src/assets/containers/MedicationStatement/medication-statement.svg +5 -0
- package/src/assets/containers/Observation/observation.svg +12 -0
- package/src/assets/containers/Practitioner/practitioner.svg +5 -0
- package/src/assets/containers/Procedure/procedure.svg +9 -0
- package/src/assets/containers/Questionnaire/questionnaire.svg +6 -0
- package/src/assets/containers/QuestionnaireResponse/questionnaire-response.svg +6 -0
- package/src/assets/containers/QustionnaireResponse/questionnaire-response.svg +6 -0
- package/src/assets/containers/ResearchStudy/research-study.svg +9 -0
- package/src/assets/containers/ResourceCategory/resource-placeholder.svg +3 -0
- package/src/components/containers/Accordion/Accordion.js +80 -0
- package/src/components/containers/Accordion/Accordion.stories.js +76 -0
- package/src/components/containers/Accordion/index.js +3 -0
- package/src/components/containers/ResourceContainer/ResourceContainer.css +0 -1
- package/src/components/containers/ResourceContainer/ResourceContainer.js +1 -1
- package/src/components/datatypes/AccountBalance/AccountBalance.js +33 -0
- package/src/components/datatypes/AccountBalance/index.js +3 -0
- package/src/components/datatypes/Annotation/Annotation.js +1 -1
- package/src/components/datatypes/Date/Date.js +14 -4
- package/src/components/datatypes/DatePeriod/DatePeriod.js +38 -0
- package/src/components/datatypes/DatePeriod/index.js +3 -0
- package/src/components/datatypes/HeaderIcon/HeaderIcon.js +31 -0
- package/src/components/datatypes/HeaderIcon/index.js +3 -0
- package/src/components/datatypes/HumanName/HumanName.js +6 -21
- package/src/components/datatypes/Reference/Reference.js +3 -6
- package/src/components/resources/AdverseEvent/AdverseEvent.test.js +2 -2
- package/src/components/resources/AllergyIntolerance/AllergyIntolerance.test.js +4 -4
- package/src/components/resources/Appointment/Appointment.js +91 -65
- package/src/components/resources/Appointment/Appointment.test.js +3 -3
- package/src/components/resources/Bundle/Bundle.js +2 -2
- package/src/components/resources/Bundle/Bundle.stories.js +78 -12
- package/src/components/resources/Bundle/Bundle.test.js +3 -0
- package/src/components/resources/CarePlan/CarePlan.test.js +4 -4
- package/src/components/resources/CareTeam/CareTeam.js +13 -14
- package/src/components/resources/CareTeam/CareTeam.test.js +4 -4
- package/src/components/resources/Claim/Claim.test.js +6 -6
- package/src/components/resources/ClaimResponse/ClaimResponse.test.js +6 -6
- package/src/components/resources/Condition/Condition.js +63 -47
- package/src/components/resources/Condition/Condition.stories.js +41 -8
- package/src/components/resources/Condition/Condition.test.js +20 -14
- package/src/components/resources/DiagnosticReport/DiagnosticReport.test.js +5 -7
- package/src/components/resources/DocumentReference/DocumentReference.js +1 -1
- package/src/components/resources/DocumentReference/DocumentReference.test.js +3 -3
- package/src/components/resources/Encounter/Encounter.js +66 -36
- package/src/components/resources/Encounter/EncounterParticipants.js +2 -2
- package/src/components/resources/ExplanationOfBenefit/CareTeam.js +2 -2
- package/src/components/resources/ExplanationOfBenefit/Diagnosis.js +15 -5
- package/src/components/resources/ExplanationOfBenefit/ExplanationOfBenefit.js +272 -201
- package/src/components/resources/ExplanationOfBenefit/ExplanationOfBenefit.test.js +79 -62
- package/src/components/resources/ExplanationOfBenefit/Items.js +2 -2
- package/src/components/resources/ExplanationOfBenefit/PriceLabel.js +20 -0
- package/src/components/resources/ExplanationOfBenefit/Related.js +3 -3
- package/src/components/resources/ExplanationOfBenefit/SupportingInfo.js +14 -3
- package/src/components/resources/ExplanationOfBenefit/TotalGraph.js +68 -0
- package/src/components/resources/ExplanationOfBenefitGraph/ExplanationOfBenefitGraph.js +89 -0
- package/src/components/resources/ExplanationOfBenefitGraph/ExplanationOfBenefitGraph.stories.js +78 -0
- package/src/components/resources/ExplanationOfBenefitGraph/ExplanationOfBenefitGraph.test.js +51 -0
- package/src/components/resources/ExplanationOfBenefitGraph/index.js +3 -0
- package/src/components/resources/Goal/Goal.test.js +1 -1
- package/src/components/resources/Immunization/Immunization.js +125 -94
- package/src/components/resources/Immunization/Immunization.stories.js +23 -4
- package/src/components/resources/Immunization/Immunization.test.js +17 -12
- package/src/components/resources/List/List.test.js +3 -3
- package/src/components/resources/MedicationAdministration/MedicationAdministration.test.js +7 -7
- package/src/components/resources/MedicationDispense/MedicationDispense.test.js +2 -2
- package/src/components/resources/MedicationRequest/MedicationRequest.test.js +4 -4
- package/src/components/resources/Observation/Observation.js +72 -54
- package/src/components/resources/Observation/Observation.test.js +6 -18
- package/src/components/resources/Observation/ObservationGraph.js +159 -55
- package/src/components/resources/Observation/ObservationGraph.test.js +47 -26
- package/src/components/resources/Patient/Patient.js +77 -87
- package/src/components/resources/Patient/Patient.test.js +1 -1
- package/src/components/resources/Practitioner/Practitioner.js +80 -60
- package/src/components/resources/Practitioner/Practitioner.test.js +4 -4
- package/src/components/resources/Procedure/Procedure.js +99 -87
- package/src/components/resources/Procedure/Procedure.stories.js +8 -6
- package/src/components/resources/Procedure/Procedure.test.js +11 -8
- package/src/components/resources/Questionnaire/Questionnaire.test.js +3 -3
- package/src/components/resources/QuestionnaireResponse/QuestionnaireResponse.test.js +5 -5
- package/src/components/resources/ReferralRequest/ReferralRequest.test.js +2 -2
- package/src/components/resources/ResearchStudy/ResearchStudy.test.js +1 -1
- package/src/components/resources/ResourceCategory/ResourceCategory.js +56 -0
- package/src/components/resources/ResourceCategory/ResourceCategory.stories.js +29 -0
- package/src/components/resources/ResourceCategory/ResourceCategory.test.js +101 -0
- package/src/components/resources/ResourceCategory/index.js +3 -0
- package/src/components/ui/_header.scss +3 -0
- package/src/components/ui/bootstrap-reboot.min.css +2 -22
- package/src/components/ui/index.js +191 -29
- package/src/constants/badge-status.jsx +98 -0
- package/src/fixtures/dstu2/resources/condition/condition.svg +35 -0
- package/src/fixtures/dstu2/resources/immunization/immunization.svg +10 -0
- package/src/fixtures/example-icons.jsx +169 -0
- package/src/index.js +6 -1
- package/src/style.scss +176 -0
- package/src/utils/formatDate.js +21 -0
- package/src/utils/formatDate.test.js +22 -0
- package/src/utils/getBadgeColor.js +6 -0
- package/src/utils/getBadgeColor.test.js +14 -0
- package/src/utils/isUrl.js +9 -0
- package/src/utils/isUrl.test.js +12 -0
- package/src/utils.js +7 -0
- package/build/bootstrap-reboot.min.css +0 -414
- package/build/index.js +0 -15
- package/build/style.css +0 -459
- package/src/components/datatypes/HumanName/HumanName.css +0 -15
- package/src/components/datatypes/Reference/Reference.css +0 -8
- package/src/components/resources/Observation/ObservationGraph.css +0 -51
- package/src/components/resources/Patient/Patient.css +0 -19
- package/src/components/ui/index.css +0 -123
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M15.9726 5.24759C15.9726 5.09345 15.9419 5.09345 15.8803 5.09345H9.23274C9.17119 5.09345 9.14041 5.06262 9.14041 5.00096V0.592486C9.14041 0.530829 9.10964 0.5 9.04809 0.5H6.95533C6.89378 0.5 6.863 0.530829 6.863 0.592486V11.8141C6.863 11.8757 6.89378 11.9066 6.95533 11.9066H9.04809C9.10964 11.9066 9.14041 11.8757 9.14041 11.8141V7.46724C9.14041 7.40559 9.17119 7.37476 9.23274 7.37476H13.6029C13.6645 7.37476 13.6952 7.40559 13.6952 7.46724V9.56358C13.6952 9.62524 13.6645 9.65607 13.6029 9.65607H11.5102C11.4486 9.65607 11.4178 9.6869 11.4178 9.74855V14.1262C11.4178 14.1879 11.387 14.2187 11.3255 14.2187H4.67792C4.61637 14.2187 4.5856 14.1879 4.5856 14.1262V5.18593C4.5856 5.12428 4.55482 5.09345 4.49327 5.09345L0 5.06262V7.34393H2.18508C2.24663 7.34393 2.27741 7.37476 2.27741 7.43642V16.4075C2.27741 16.4692 2.30819 16.5 2.36974 16.5H13.6029C13.6645 16.5 13.6952 16.4692 13.6952 16.4075V16.4383V12.0607C13.6952 11.9682 13.726 11.9374 13.7876 11.9374H15.8495C15.8495 11.9374 15.9111 11.9374 15.9726 11.8757C16.0342 11.8449 15.9726 5.24759 15.9726 5.24759Z" fill="#3D8BFD"/>
|
|
3
|
+
</svg>
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { Chevron } from '../../ui';
|
|
3
|
+
|
|
4
|
+
const CHEVRON_DOWN_COLOR = '#6f83a9';
|
|
5
|
+
const CHEVRON_UP_COLOR = '#2a6fd7';
|
|
6
|
+
|
|
7
|
+
const Accordion = props => {
|
|
8
|
+
const { headerContent, bodyContent } = props;
|
|
9
|
+
const [rotate, setRotate] = useState(false);
|
|
10
|
+
const handleAccordionClick = () => setRotate(!rotate);
|
|
11
|
+
|
|
12
|
+
const isAccordionOpenable = () => {
|
|
13
|
+
let childrenCondition = false;
|
|
14
|
+
let tableDataCondition = false;
|
|
15
|
+
if (bodyContent.props.children)
|
|
16
|
+
childrenCondition = bodyContent.props.children.length > 0;
|
|
17
|
+
if (bodyContent.props.tableData)
|
|
18
|
+
tableDataCondition =
|
|
19
|
+
bodyContent.props.tableData.filter(x => 'data' in x && x.data).length >
|
|
20
|
+
0;
|
|
21
|
+
|
|
22
|
+
return childrenCondition || tableDataCondition;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const getChevron = () =>
|
|
26
|
+
isAccordionOpenable() && (
|
|
27
|
+
<div
|
|
28
|
+
className={`fhir-ui__${
|
|
29
|
+
props.resourceName
|
|
30
|
+
}-Header__chevron chevron position-absolute ${
|
|
31
|
+
rotate ? ' header-rotate' : ''
|
|
32
|
+
}`}
|
|
33
|
+
style={{ top: '24px', right: '24px' }}
|
|
34
|
+
>
|
|
35
|
+
<Chevron strokeColor={rotate ? CHEVRON_UP_COLOR : CHEVRON_DOWN_COLOR} />
|
|
36
|
+
</div>
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<div className="fhir-container__Accordion accordion">
|
|
41
|
+
<div className="fhir-container__Accordion__body accordion-body">
|
|
42
|
+
<div className="fhir-container__Accordion__body-data accordion-item border-1 shadow-sm">
|
|
43
|
+
<div
|
|
44
|
+
className="fhir-container__Accordion__header accordion-header"
|
|
45
|
+
id="flush-headingOne"
|
|
46
|
+
>
|
|
47
|
+
<button
|
|
48
|
+
className={`fhir-container__Accordion__header-button w-100 p-0 border-0 rounded-1 collapsed text-dark bg-white shadow-none point ${
|
|
49
|
+
isAccordionOpenable() ? '' : 'pe-none'
|
|
50
|
+
}`}
|
|
51
|
+
type="button"
|
|
52
|
+
data-bs-target="#collapseTarget"
|
|
53
|
+
data-bs-toggle={isAccordionOpenable() ? 'collapse' : null}
|
|
54
|
+
aria-controls="collapseTarget"
|
|
55
|
+
aria-expanded="false"
|
|
56
|
+
onClick={handleAccordionClick}
|
|
57
|
+
>
|
|
58
|
+
<div className="fhir-container__Accordion__header-text d-flex w-100 justify-content-start position-relative">
|
|
59
|
+
{React.cloneElement(headerContent, {
|
|
60
|
+
isAccordionOpenable: isAccordionOpenable(),
|
|
61
|
+
})}
|
|
62
|
+
{getChevron()}
|
|
63
|
+
</div>
|
|
64
|
+
</button>
|
|
65
|
+
</div>
|
|
66
|
+
<div
|
|
67
|
+
className="fhir-container__Accordion__data accordion-collapse collapse"
|
|
68
|
+
id="collapseTarget"
|
|
69
|
+
>
|
|
70
|
+
<div className="fhir-container__Accordion__data-text accordion-body ps-4 pt-3 pe-4 border-top">
|
|
71
|
+
{bodyContent}
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export default Accordion;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { BadgeSecondary, Body, MissingValue, Title, Value } from '../../ui';
|
|
2
|
+
|
|
3
|
+
import Accordion from './Accordion';
|
|
4
|
+
import Annotation from '../../datatypes/Annotation';
|
|
5
|
+
import Date from '../../datatypes/Date';
|
|
6
|
+
import Procedure from '../../resources/Procedure/Procedure';
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import Reference from '../../datatypes/Reference';
|
|
9
|
+
import _get from 'lodash/get';
|
|
10
|
+
import example1 from '../../../fixtures/dstu2/resources/procedure/example1.json';
|
|
11
|
+
import fhirIcons from '../../../fixtures/example-icons';
|
|
12
|
+
import { object } from '@storybook/addon-knobs';
|
|
13
|
+
import stu3Example1 from '../../../fixtures/stu3/resources/procedure/example1.json';
|
|
14
|
+
|
|
15
|
+
export default {
|
|
16
|
+
title: 'Accordion',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const DefaultVisualization = () => {
|
|
20
|
+
const fhirResource = object('Resource', stu3Example1);
|
|
21
|
+
const title =
|
|
22
|
+
_get(fhirResource, 'code.coding[0].display') ||
|
|
23
|
+
_get(fhirResource, 'code.text');
|
|
24
|
+
const performedDateTime = _get(fhirResource, 'performedDateTime');
|
|
25
|
+
const performer = _get(fhirResource, 'performer', []);
|
|
26
|
+
const locationReference = _get(fhirResource, 'location[0]');
|
|
27
|
+
const reasonCode = _get(fhirResource, 'reasonCode', []);
|
|
28
|
+
const note = _get(fhirResource, 'note', []);
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<Accordion
|
|
32
|
+
headerContent={
|
|
33
|
+
<div className="">
|
|
34
|
+
<Title>{title}</Title>
|
|
35
|
+
<div className="pb-3" />
|
|
36
|
+
<BadgeSecondary data-testid="performedDateTime">
|
|
37
|
+
<Date fhirData={performedDateTime} />
|
|
38
|
+
</BadgeSecondary>
|
|
39
|
+
</div>
|
|
40
|
+
}
|
|
41
|
+
bodyContent={
|
|
42
|
+
<Body>
|
|
43
|
+
<Value label="Performed by">
|
|
44
|
+
{performer.map((item, i) => (
|
|
45
|
+
<div key={`item-${i}`}>
|
|
46
|
+
{_get(item, 'actor.display', <MissingValue />)}
|
|
47
|
+
</div>
|
|
48
|
+
))}
|
|
49
|
+
</Value>
|
|
50
|
+
<Value label="Location" data-testid="location">
|
|
51
|
+
<Reference fhirData={locationReference} />
|
|
52
|
+
</Value>
|
|
53
|
+
<Value label="Reason" data-testid="hasReasonCode">
|
|
54
|
+
<Annotation fhirData={reasonCode} />
|
|
55
|
+
</Value>
|
|
56
|
+
<Value label="Notes" data-testid="hasNote">
|
|
57
|
+
<Annotation fhirData={note} />
|
|
58
|
+
</Value>
|
|
59
|
+
</Body>
|
|
60
|
+
}
|
|
61
|
+
/>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export const ProcedureVisualization = () => {
|
|
66
|
+
const fhirResource = object('Resource', example1);
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<Accordion
|
|
70
|
+
headerContent={<div className=""></div>}
|
|
71
|
+
bodyContent={
|
|
72
|
+
<Procedure fhirResource={fhirResource} fhirIcons={fhirIcons} />
|
|
73
|
+
}
|
|
74
|
+
/>
|
|
75
|
+
);
|
|
76
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Value } from '../../ui';
|
|
3
|
+
import { parseValueIntoMonetaryValueOfGivenCurrency } from '../../../utils';
|
|
4
|
+
|
|
5
|
+
const AccountBalance = props => {
|
|
6
|
+
const { totalBenefit, totalCost } = props;
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<div className="fhir-datatype__AccountBalance container-fluid p-0 m-0 ">
|
|
10
|
+
<Value label="Total cost" data-testid="totalCost" secondary>
|
|
11
|
+
{parseValueIntoMonetaryValueOfGivenCurrency(
|
|
12
|
+
totalCost.value,
|
|
13
|
+
totalCost.code,
|
|
14
|
+
)}
|
|
15
|
+
</Value>
|
|
16
|
+
<Value label="Coverd by benefit" data-testid="totalBenefit" secondary>
|
|
17
|
+
{parseValueIntoMonetaryValueOfGivenCurrency(
|
|
18
|
+
totalBenefit.value * -1,
|
|
19
|
+
totalBenefit.code,
|
|
20
|
+
)}
|
|
21
|
+
</Value>
|
|
22
|
+
<div className="border-top my-1 row border-secondary" />
|
|
23
|
+
<Value label="Patient Owed" secondary>
|
|
24
|
+
{parseValueIntoMonetaryValueOfGivenCurrency(
|
|
25
|
+
totalCost.value - totalBenefit.value,
|
|
26
|
+
totalBenefit.code,
|
|
27
|
+
)}
|
|
28
|
+
</Value>
|
|
29
|
+
</div>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export default AccountBalance;
|
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { formatDate } from '../../../utils/formatDate';
|
|
2
3
|
|
|
3
|
-
const Date =
|
|
4
|
-
const { fhirData } = props;
|
|
4
|
+
const Date = ({ fhirData, isBlack, testId, className = '' }) => {
|
|
5
5
|
if (!fhirData) {
|
|
6
6
|
return null;
|
|
7
7
|
}
|
|
8
|
-
const
|
|
9
|
-
|
|
8
|
+
const locale = 'en-US';
|
|
9
|
+
const dateValue = formatDate(String(fhirData).slice(0, 10), locale);
|
|
10
|
+
return (
|
|
11
|
+
<span
|
|
12
|
+
data-testid={testId || 'providedDate'}
|
|
13
|
+
className={`${[className, 'fhir-datatype__Date', 'font-source'].join(
|
|
14
|
+
' ',
|
|
15
|
+
)}${isBlack ? '' : ' text-secondary'}`}
|
|
16
|
+
>
|
|
17
|
+
{dateValue}
|
|
18
|
+
</span>
|
|
19
|
+
);
|
|
10
20
|
};
|
|
11
21
|
|
|
12
22
|
export default Date;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import Date from '../Date';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
const DatePeriod = props => {
|
|
5
|
+
const {
|
|
6
|
+
periodBeginLabel,
|
|
7
|
+
periodBeginDate,
|
|
8
|
+
periodBeginTestId,
|
|
9
|
+
periodEndLabel,
|
|
10
|
+
periodEndDate,
|
|
11
|
+
periodEndTestId,
|
|
12
|
+
} = props;
|
|
13
|
+
|
|
14
|
+
const SingleDateSpan = props => (
|
|
15
|
+
<span className="fhir-datetype__DatePeriod__begin-date text-black-50 me-2 font-source fw-normal lh-lg">
|
|
16
|
+
{props.label}
|
|
17
|
+
</span>
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<div className="d-flex flex-column flex-sm-row align-items-start align-items-sm-start">
|
|
22
|
+
{periodBeginDate && (
|
|
23
|
+
<div className="d-flex flex-wrap">
|
|
24
|
+
<SingleDateSpan label={periodBeginLabel} />
|
|
25
|
+
<Date testId={periodBeginTestId} isBlack fhirData={periodBeginDate} />
|
|
26
|
+
</div>
|
|
27
|
+
)}
|
|
28
|
+
{periodEndDate && (
|
|
29
|
+
<div className="ms-sm-4 d-flex flex-wrap">
|
|
30
|
+
<SingleDateSpan label={periodEndLabel} />
|
|
31
|
+
<Date testId={periodEndTestId} isBlack fhirData={periodEndDate} />
|
|
32
|
+
</div>
|
|
33
|
+
)}
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default DatePeriod;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { isUrl } from '../../../utils/isUrl';
|
|
3
|
+
|
|
4
|
+
const HeaderIcon = ({ headerIcon }) => {
|
|
5
|
+
const PlaceholderImage = () => {
|
|
6
|
+
return <div className="header-icon__placeholder rounded-1" />;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const Image = () => {
|
|
10
|
+
if (
|
|
11
|
+
React.isValidElement(headerIcon) &&
|
|
12
|
+
typeof headerIcon.type === 'string'
|
|
13
|
+
) {
|
|
14
|
+
return headerIcon;
|
|
15
|
+
}
|
|
16
|
+
if (isUrl(headerIcon)) {
|
|
17
|
+
return (
|
|
18
|
+
<img
|
|
19
|
+
className="header-icon__image"
|
|
20
|
+
src={headerIcon}
|
|
21
|
+
alt="header icon"
|
|
22
|
+
/>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
return <PlaceholderImage />;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
return <Image />;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default HeaderIcon;
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import _get from 'lodash/get';
|
|
3
2
|
import _flatten from 'lodash/flatten';
|
|
4
|
-
|
|
5
|
-
import './HumanName.css';
|
|
3
|
+
import _get from 'lodash/get';
|
|
6
4
|
|
|
7
5
|
function HumanName(props) {
|
|
8
|
-
const { fhirData,
|
|
6
|
+
const { fhirData, isTitle } = props;
|
|
9
7
|
const givenName = _get(fhirData, 'given', []).join(', ');
|
|
10
8
|
const familyName = _flatten(Array(_get(fhirData, 'family', ''))).join(', ');
|
|
11
9
|
const suffix = _get(fhirData, 'suffix', []).join(' ');
|
|
@@ -15,24 +13,11 @@ function HumanName(props) {
|
|
|
15
13
|
? textName
|
|
16
14
|
: `${givenName} ${familyName} ${suffix}`.trim();
|
|
17
15
|
|
|
18
|
-
const headerElement = primary ? (
|
|
19
|
-
<span className="fhir-datatype__HumanName__Header--primary">{header}</span>
|
|
20
|
-
) : (
|
|
21
|
-
<span className="fhir-datatype__HumanName__Header--default">{header}</span>
|
|
22
|
-
);
|
|
23
|
-
const rootClassName = primary
|
|
24
|
-
? ''
|
|
25
|
-
: 'fhir-datatype__HumanName__not-primary-block';
|
|
26
|
-
|
|
27
16
|
return (
|
|
28
|
-
|
|
29
|
-
{
|
|
30
|
-
{use && (
|
|
31
|
-
|
|
32
|
-
{` (${use})`}
|
|
33
|
-
</small>
|
|
34
|
-
)}
|
|
35
|
-
</div>
|
|
17
|
+
<>
|
|
18
|
+
{header}
|
|
19
|
+
{!isTitle && use && <span>{` (${use})`}</span>}
|
|
20
|
+
</>
|
|
36
21
|
);
|
|
37
22
|
}
|
|
38
23
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import _get from 'lodash/get';
|
|
3
|
-
import './Reference.css';
|
|
4
3
|
|
|
5
4
|
const Reference = props => {
|
|
6
5
|
const { fhirData } = props;
|
|
@@ -8,13 +7,11 @@ const Reference = props => {
|
|
|
8
7
|
const reference = _get(fhirData, 'reference', '');
|
|
9
8
|
return (
|
|
10
9
|
<div
|
|
11
|
-
className="fhir-datatype__Reference"
|
|
10
|
+
className="fhir-datatype__Reference d-inline-block"
|
|
12
11
|
data-testid={props['data-testid']}
|
|
13
12
|
>
|
|
14
|
-
{display &&
|
|
15
|
-
|
|
16
|
-
)}
|
|
17
|
-
<span className="fhir-datatype__Reference__details">{reference}</span>
|
|
13
|
+
{display && <span className="mr-2 pe-1">{display}</span>}
|
|
14
|
+
<span>{reference}</span>
|
|
18
15
|
</div>
|
|
19
16
|
);
|
|
20
17
|
};
|
|
@@ -16,7 +16,7 @@ describe('should render component correctly', () => {
|
|
|
16
16
|
|
|
17
17
|
expect(getByTestId('title').textContent).toContain('Patient');
|
|
18
18
|
|
|
19
|
-
expect(getByTestId('date').textContent).toEqual('2017
|
|
19
|
+
expect(getByTestId('date').textContent).toEqual('1/29/2017');
|
|
20
20
|
|
|
21
21
|
expect(getByTestId('type').textContent).toContain('304386008');
|
|
22
22
|
|
|
@@ -36,7 +36,7 @@ describe('should render component correctly', () => {
|
|
|
36
36
|
|
|
37
37
|
expect(getByTestId('title').textContent).toContain('Patient');
|
|
38
38
|
|
|
39
|
-
expect(getByTestId('date').textContent).toEqual('2017
|
|
39
|
+
expect(getByTestId('date').textContent).toEqual('1/29/2017');
|
|
40
40
|
|
|
41
41
|
expect(getByTestId('hasSeriousness').textContent).toContain('Non-serious');
|
|
42
42
|
|
|
@@ -22,7 +22,7 @@ describe('should render component correctly', () => {
|
|
|
22
22
|
|
|
23
23
|
expect(getByTestId('status').textContent).toContain('unconfirmed');
|
|
24
24
|
|
|
25
|
-
expect(getByTestId('recordedDate').textContent).toContain('2010
|
|
25
|
+
expect(getByTestId('recordedDate').textContent).toContain('3/1/2010');
|
|
26
26
|
|
|
27
27
|
expect(getByTestId('substance').textContent).toContain('PENICILLIN');
|
|
28
28
|
|
|
@@ -46,7 +46,7 @@ describe('should render component correctly', () => {
|
|
|
46
46
|
|
|
47
47
|
expect(getByTestId('status').textContent).toContain('confirmed');
|
|
48
48
|
|
|
49
|
-
expect(getByTestId('recordedDate').textContent).toContain('2014
|
|
49
|
+
expect(getByTestId('recordedDate').textContent).toContain('10/9/2014');
|
|
50
50
|
|
|
51
51
|
expect(getByTestId('substance').textContent).toContain(
|
|
52
52
|
'allergenic extract',
|
|
@@ -78,7 +78,7 @@ describe('should render component correctly', () => {
|
|
|
78
78
|
|
|
79
79
|
expect(getByTestId('status').textContent).toContain('Confirmed');
|
|
80
80
|
|
|
81
|
-
expect(getByTestId('recordedDate').textContent).toContain('2014
|
|
81
|
+
expect(getByTestId('recordedDate').textContent).toContain('10/9/2014');
|
|
82
82
|
|
|
83
83
|
expect(getByTestId('substance').textContent).toContain(
|
|
84
84
|
'allergenic extract',
|
|
@@ -114,7 +114,7 @@ describe('should render component correctly', () => {
|
|
|
114
114
|
|
|
115
115
|
expect(getByTestId('status').textContent).toContain('Confirmed');
|
|
116
116
|
|
|
117
|
-
expect(getByTestId('recordedDate').textContent).toContain('2015
|
|
117
|
+
expect(getByTestId('recordedDate').textContent).toContain('8/6/2015');
|
|
118
118
|
|
|
119
119
|
expect(getByTestId('patient').textContent).toEqual('Patient/mom');
|
|
120
120
|
|
|
@@ -6,9 +6,7 @@ import fhirVersions from '../fhirResourceVersions';
|
|
|
6
6
|
import {
|
|
7
7
|
Root,
|
|
8
8
|
Header,
|
|
9
|
-
Title,
|
|
10
9
|
Badge,
|
|
11
|
-
BadgeSecondary,
|
|
12
10
|
Body,
|
|
13
11
|
Value,
|
|
14
12
|
ValueSection,
|
|
@@ -23,6 +21,7 @@ import Coding from '../../datatypes/Coding';
|
|
|
23
21
|
import Reference from '../../datatypes/Reference';
|
|
24
22
|
import CodeableConcept from '../../datatypes/CodeableConcept';
|
|
25
23
|
import { isNotEmptyArray } from '../../../utils';
|
|
24
|
+
import Accordion from '../../containers/Accordion';
|
|
26
25
|
|
|
27
26
|
const prepareParticipantData = data => {
|
|
28
27
|
let participantPatient = [];
|
|
@@ -163,71 +162,98 @@ const Appointment = props => {
|
|
|
163
162
|
serviceCategory,
|
|
164
163
|
} = resourceDTO(fhirVersion, fhirResource);
|
|
165
164
|
|
|
165
|
+
const tableData = [
|
|
166
|
+
{
|
|
167
|
+
label: 'Type',
|
|
168
|
+
testId: 'type',
|
|
169
|
+
data:
|
|
170
|
+
isNotEmptyArray(typeCoding) &&
|
|
171
|
+
typeCoding.map((item, i) => (
|
|
172
|
+
<Coding key={`item-${i}`} fhirData={item} />
|
|
173
|
+
)),
|
|
174
|
+
status: isNotEmptyArray(typeCoding),
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
label: 'Duration [min]',
|
|
178
|
+
testId: 'minutesDuration',
|
|
179
|
+
data: minutesDuration,
|
|
180
|
+
status: minutesDuration,
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
label: 'Reason',
|
|
184
|
+
testId: 'reason',
|
|
185
|
+
data: isNotEmptyArray(reason) && <CodeableConcept fhirData={reason} />,
|
|
186
|
+
status: isNotEmptyArray(reason),
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
label: 'Cancelation Reason',
|
|
190
|
+
testId: 'cancelationReason',
|
|
191
|
+
data: isNotEmptyArray(cancelationReason) && (
|
|
192
|
+
<CodeableConcept fhirData={cancelationReason} />
|
|
193
|
+
),
|
|
194
|
+
status: isNotEmptyArray(cancelationReason),
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
label: 'Service Category',
|
|
198
|
+
testId: 'serviceCategory',
|
|
199
|
+
data: isNotEmptyArray(serviceCategory) && (
|
|
200
|
+
<CodeableConcept fhirData={serviceCategory} />
|
|
201
|
+
),
|
|
202
|
+
status: isNotEmptyArray(serviceCategory),
|
|
203
|
+
},
|
|
204
|
+
];
|
|
205
|
+
|
|
166
206
|
return (
|
|
167
207
|
<Root name="Appointment">
|
|
168
|
-
<
|
|
169
|
-
{
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
{
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
<TableCell>{participantPatient}</TableCell>
|
|
218
|
-
<TableCell>{participantPractitioner}</TableCell>
|
|
219
|
-
<TableCell>{participantLocation}</TableCell>
|
|
220
|
-
</TableRow>
|
|
221
|
-
</tbody>
|
|
222
|
-
</Table>
|
|
223
|
-
</ValueSection>
|
|
224
|
-
)}
|
|
225
|
-
{comment && (
|
|
226
|
-
<Value label="Comment" data-testid="comment">
|
|
227
|
-
{comment}
|
|
228
|
-
</Value>
|
|
229
|
-
)}
|
|
230
|
-
</Body>
|
|
208
|
+
<Accordion
|
|
209
|
+
headerContent={
|
|
210
|
+
<Header
|
|
211
|
+
resourceName={fhirResource.resourceName}
|
|
212
|
+
additionalContent={
|
|
213
|
+
start && (
|
|
214
|
+
<Value label="Start date" data-testid="headerStartDate">
|
|
215
|
+
<Date fhirData={start} isBlack />
|
|
216
|
+
</Value>
|
|
217
|
+
)
|
|
218
|
+
}
|
|
219
|
+
badges={status && <Badge data-testid="status">{status}</Badge>}
|
|
220
|
+
title={description}
|
|
221
|
+
/>
|
|
222
|
+
}
|
|
223
|
+
bodyContent={
|
|
224
|
+
<Body tableData={tableData}>
|
|
225
|
+
{isNotEmptyArray(participant) && (
|
|
226
|
+
<ValueSection
|
|
227
|
+
label="Participant"
|
|
228
|
+
data-testid="participant"
|
|
229
|
+
marginTop
|
|
230
|
+
>
|
|
231
|
+
<Table>
|
|
232
|
+
<thead>
|
|
233
|
+
<TableRow>
|
|
234
|
+
<TableHeader>Patient</TableHeader>
|
|
235
|
+
<TableHeader>Practitioner</TableHeader>
|
|
236
|
+
<TableHeader>Other</TableHeader>
|
|
237
|
+
</TableRow>
|
|
238
|
+
</thead>
|
|
239
|
+
<tbody className="border-top-0">
|
|
240
|
+
<TableRow>
|
|
241
|
+
<TableCell>{participantPatient}</TableCell>
|
|
242
|
+
<TableCell>{participantPractitioner}</TableCell>
|
|
243
|
+
<TableCell>{participantLocation}</TableCell>
|
|
244
|
+
</TableRow>
|
|
245
|
+
</tbody>
|
|
246
|
+
</Table>
|
|
247
|
+
</ValueSection>
|
|
248
|
+
)}
|
|
249
|
+
{comment && (
|
|
250
|
+
<ValueSection label="Comment" data-testid="comment" marginTop>
|
|
251
|
+
<span className="text-secondary">{comment}</span>
|
|
252
|
+
</ValueSection>
|
|
253
|
+
)}
|
|
254
|
+
</Body>
|
|
255
|
+
}
|
|
256
|
+
/>
|
|
231
257
|
</Root>
|
|
232
258
|
);
|
|
233
259
|
};
|