@kenyaemr/esm-care-panel-app 5.4.1-pre.1915 → 5.4.1-pre.1922
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/.turbo/turbo-build.log +25 -18
- package/dist/207.js +1 -0
- package/dist/207.js.map +1 -0
- package/dist/83.js +2 -0
- package/dist/83.js.map +1 -0
- package/dist/856.js +1 -0
- package/dist/856.js.map +1 -0
- package/dist/kenyaemr-esm-care-panel-app.js +1 -1
- package/dist/kenyaemr-esm-care-panel-app.js.buildmanifest.json +65 -65
- package/dist/kenyaemr-esm-care-panel-app.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/config-schema.ts +14 -0
- package/src/dispensing-patient-details/conditions.component.tsx +55 -0
- package/src/dispensing-patient-details/conditions.resource.ts +97 -0
- package/src/dispensing-patient-details/diagnoses.component.tsx +55 -0
- package/src/dispensing-patient-details/diagnoses.resource.ts +30 -0
- package/src/dispensing-patient-details/dispensing-patient-details.scss +47 -0
- package/src/dispensing-patient-details/dispensing-patient-vitals.resources.ts +132 -0
- package/src/dispensing-patient-details/patient-vitals.component.tsx +27 -0
- package/src/index.ts +8 -0
- package/src/routes.json +20 -2
- package/dist/165.js +0 -2
- package/dist/165.js.map +0 -1
- package/dist/196.js +0 -1
- package/dist/196.js.map +0 -1
- package/dist/933.js +0 -1
- package/dist/933.js.map +0 -1
- /package/dist/{165.js.LICENSE.txt → 83.js.LICENSE.txt} +0 -0
package/dist/routes.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"kenyaemr":"^19.0.0"},"pages":[],"extensions":[{"name":"care-panel-patient-summary","component":"carePanelPatientSummary","slot":"patient-chart-care-panel-dashboard-slot","order":10,"meta":{"columnSpan":4}},{"name":"care-panel-summary-dashboard-link","component":"carePanelSummaryDashboardLink","slot":"patient-chart-dashboard-slot","order":3,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-care-panel-dashboard-slot","layoutMode":"anchored","path":"Care panel"}},{"name":"delete-regimen-confirmation-dialog","component":"deleteRegimenConfirmationDialog"},{"name":"hiv-patient-visit-summary-dashboard-link","component":"hivPatientSummaryDashboardLink","slot":"hiv-care-and-treatment-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-hiv-patient-summary-slot","path":"HIV Patient Summary","layoutMode":"anchored"}},{"name":"hiv-patient-visit-summary","slot":"patient-chart-hiv-patient-summary-slot","component":"hivPatientSummary","order":3,"online":true,"offline":false}],"workspaces":[{"name":"patient-regimen-workspace","title":"Patient Regimen","component":"regimenFormWorkspace","type":"form","canMaximize":true,"canHide":true,"width":"wider"}],"version":"5.4.1-pre.
|
|
1
|
+
{"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"kenyaemr":"^19.0.0"},"pages":[],"extensions":[{"name":"care-panel-patient-summary","component":"carePanelPatientSummary","slot":"patient-chart-care-panel-dashboard-slot","order":10,"meta":{"columnSpan":4}},{"name":"care-panel-summary-dashboard-link","component":"carePanelSummaryDashboardLink","slot":"patient-chart-dashboard-slot","order":3,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-care-panel-dashboard-slot","layoutMode":"anchored","path":"Care panel"}},{"name":"delete-regimen-confirmation-dialog","component":"deleteRegimenConfirmationDialog"},{"name":"hiv-patient-visit-summary-dashboard-link","component":"hivPatientSummaryDashboardLink","slot":"hiv-care-and-treatment-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-hiv-patient-summary-slot","path":"HIV Patient Summary","layoutMode":"anchored"}},{"name":"hiv-patient-visit-summary","slot":"patient-chart-hiv-patient-summary-slot","component":"hivPatientSummary","order":3,"online":true,"offline":false},{"name":"patient-diagnoses","component":"patientDiagnoses","online":true,"offline":true},{"name":"patient-conditions","component":"patientConditions","online":true,"offline":true},{"name":"dispensing-patient-vitals","component":"dispensingPaentientVitals","online":true,"offline":true}],"workspaces":[{"name":"patient-regimen-workspace","title":"Patient Regimen","component":"regimenFormWorkspace","type":"form","canMaximize":true,"canHide":true,"width":"wider"}],"version":"5.4.1-pre.1922"}
|
package/package.json
CHANGED
package/src/config-schema.ts
CHANGED
|
@@ -5,6 +5,10 @@ export interface CarePanelConfig {
|
|
|
5
5
|
encounterProviderRoleUuid: string;
|
|
6
6
|
};
|
|
7
7
|
hivProgramUuid: string;
|
|
8
|
+
dispensingVitalsConcepts: Array<{
|
|
9
|
+
uuid: string;
|
|
10
|
+
display: string;
|
|
11
|
+
}>;
|
|
8
12
|
}
|
|
9
13
|
|
|
10
14
|
export const configSchema = {
|
|
@@ -20,4 +24,14 @@ export const configSchema = {
|
|
|
20
24
|
_description: 'HIV Program UUID',
|
|
21
25
|
_default: 'dfdc6d40-2f2f-463d-ba90-cc97350441a8',
|
|
22
26
|
},
|
|
27
|
+
dispensingVitalsConcepts: {
|
|
28
|
+
_type: Type.Array,
|
|
29
|
+
_description: 'Uuids of patient vitals concept required for dispensing',
|
|
30
|
+
_default: [
|
|
31
|
+
{
|
|
32
|
+
display: 'Weight (Kg)',
|
|
33
|
+
uuid: '5089AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
},
|
|
23
37
|
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { InlineLoading, InlineNotification, Tile } from '@carbon/react';
|
|
2
|
+
import { WarningFilled } from '@carbon/react/icons';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
|
+
import { usePatientConditions } from './conditions.resource';
|
|
6
|
+
import styles from './dispensing-patient-details.scss';
|
|
7
|
+
|
|
8
|
+
type PatientConditionsProps = {
|
|
9
|
+
patientUuid: string;
|
|
10
|
+
encounterUuid: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const PatientConditions: React.FC<PatientConditionsProps> = ({ encounterUuid, patientUuid }) => {
|
|
14
|
+
const { t } = useTranslation();
|
|
15
|
+
const { conditions, error, isLoading, mutate } = usePatientConditions(patientUuid);
|
|
16
|
+
|
|
17
|
+
if (isLoading) {
|
|
18
|
+
return (
|
|
19
|
+
<InlineLoading
|
|
20
|
+
iconDescription="Loading"
|
|
21
|
+
description={t('loadingConditions', 'Loading active Conditions ...')}
|
|
22
|
+
status="active"
|
|
23
|
+
/>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (error) {
|
|
28
|
+
return <InlineNotification kind="error" subtitle={t('conditionsError', 'Error loading conditions')} lowContrast />;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<Tile className={styles.container}>
|
|
33
|
+
<div className={styles.content}>
|
|
34
|
+
<div>
|
|
35
|
+
<WarningFilled size={24} className={styles.icon} />
|
|
36
|
+
<p>
|
|
37
|
+
{conditions.length > 0 && (
|
|
38
|
+
<span>
|
|
39
|
+
<span style={{ fontWeight: 'bold' }}>
|
|
40
|
+
{t('activeConditionsCount', '{{ count }} conditions', {
|
|
41
|
+
count: conditions.length,
|
|
42
|
+
})}
|
|
43
|
+
</span>{' '}
|
|
44
|
+
{conditions?.map(({ display }) => display).join(' | ')}
|
|
45
|
+
</span>
|
|
46
|
+
)}
|
|
47
|
+
{conditions.length === 0 && t('noActiveConditions', 'No active Conditions')}
|
|
48
|
+
</p>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</Tile>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default PatientConditions;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { fhirBaseUrl, useFhirFetchAll } from '@openmrs/esm-framework';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
|
|
4
|
+
export interface Resource {
|
|
5
|
+
resourceType: string;
|
|
6
|
+
id: string;
|
|
7
|
+
meta: ResourceMeta;
|
|
8
|
+
clinicalStatus: ClinicalStatus;
|
|
9
|
+
code: Code;
|
|
10
|
+
subject: Subject;
|
|
11
|
+
onsetDateTime: string;
|
|
12
|
+
recordedDate: string;
|
|
13
|
+
recorder: Recorder;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ResourceMeta {
|
|
17
|
+
versionId: string;
|
|
18
|
+
lastUpdated: string;
|
|
19
|
+
tag: Array<ResourceMetaTag>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface ResourceMetaTag {
|
|
23
|
+
system: string;
|
|
24
|
+
code: string;
|
|
25
|
+
display: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface ClinicalStatus {
|
|
29
|
+
coding: Array<Coding>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface Coding {
|
|
33
|
+
system: string;
|
|
34
|
+
code: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface Code {
|
|
38
|
+
coding: Array<ConditionCoding>;
|
|
39
|
+
text: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface ConditionCoding {
|
|
43
|
+
code: string;
|
|
44
|
+
display?: string;
|
|
45
|
+
system?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface Subject {
|
|
49
|
+
reference: string;
|
|
50
|
+
type: string;
|
|
51
|
+
display: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface Recorder {
|
|
55
|
+
reference: string;
|
|
56
|
+
type: string;
|
|
57
|
+
display: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface Condition {
|
|
61
|
+
id: string;
|
|
62
|
+
status?: 'active' | 'inactive';
|
|
63
|
+
display: string;
|
|
64
|
+
patient: string;
|
|
65
|
+
onsetDateTime: string;
|
|
66
|
+
recordedDate: string;
|
|
67
|
+
recorder: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export const usePatientConditions = (patientUuid: string) => {
|
|
71
|
+
const url = `${fhirBaseUrl}/Condition?patient=${patientUuid}&_summary=data`;
|
|
72
|
+
const { data, isLoading, mutate, error } = useFhirFetchAll<Resource>(url);
|
|
73
|
+
|
|
74
|
+
const conditions = useMemo(() => {
|
|
75
|
+
return data?.reduce<Array<Condition>>((prev, entry) => {
|
|
76
|
+
if (entry?.resourceType === 'Condition') {
|
|
77
|
+
const condition: Condition = {
|
|
78
|
+
id: entry.id,
|
|
79
|
+
display: entry?.code?.text,
|
|
80
|
+
onsetDateTime: entry?.onsetDateTime,
|
|
81
|
+
patient: entry?.subject?.display,
|
|
82
|
+
recordedDate: entry?.recordedDate,
|
|
83
|
+
recorder: entry?.recorder?.display,
|
|
84
|
+
status: entry?.clinicalStatus?.coding[0]?.code as any,
|
|
85
|
+
};
|
|
86
|
+
return [...prev, condition];
|
|
87
|
+
}
|
|
88
|
+
return prev;
|
|
89
|
+
}, []);
|
|
90
|
+
}, [data]);
|
|
91
|
+
return {
|
|
92
|
+
conditions: (conditions ?? []).filter((condition) => condition.status === 'active'),
|
|
93
|
+
isLoading,
|
|
94
|
+
error,
|
|
95
|
+
mutate,
|
|
96
|
+
};
|
|
97
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { InlineLoading, InlineNotification, Tile } from '@carbon/react';
|
|
2
|
+
import { WarningFilled } from '@carbon/react/icons';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
|
+
import { usePatientDiagnosis } from './diagnoses.resource';
|
|
6
|
+
import styles from './dispensing-patient-details.scss';
|
|
7
|
+
|
|
8
|
+
type PatientDiagnosesProps = {
|
|
9
|
+
patientUuid: string;
|
|
10
|
+
encounterUuid: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const PatientDiagnoses: React.FC<PatientDiagnosesProps> = ({ encounterUuid, patientUuid }) => {
|
|
14
|
+
const { diagnoses, isLoading, error } = usePatientDiagnosis(encounterUuid);
|
|
15
|
+
const { t } = useTranslation();
|
|
16
|
+
|
|
17
|
+
if (isLoading) {
|
|
18
|
+
return (
|
|
19
|
+
<InlineLoading
|
|
20
|
+
iconDescription="Loading"
|
|
21
|
+
description={t('loadingDiagnoses', 'Loading Diagnoses ...')}
|
|
22
|
+
status="active"
|
|
23
|
+
/>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (error) {
|
|
28
|
+
return <InlineNotification kind="error" subtitle={t('diagnosesError', 'Error loading diagnoses')} lowContrast />;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<Tile className={styles.container}>
|
|
33
|
+
<div className={styles.content}>
|
|
34
|
+
<div>
|
|
35
|
+
<WarningFilled size={24} className={styles.icon} />
|
|
36
|
+
<p>
|
|
37
|
+
{diagnoses.length > 0 && (
|
|
38
|
+
<span>
|
|
39
|
+
<span style={{ fontWeight: 'bold' }}>
|
|
40
|
+
{t('diagnosesCount', '{{ count }} diagnoses', {
|
|
41
|
+
count: diagnoses.length,
|
|
42
|
+
})}
|
|
43
|
+
</span>{' '}
|
|
44
|
+
{diagnoses?.map(({ text }) => text).join(' | ')}
|
|
45
|
+
</span>
|
|
46
|
+
)}
|
|
47
|
+
{diagnoses.length === 0 && t('noFinalDiagnoses', 'No patient final diagnosis for this visit')}
|
|
48
|
+
</p>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</Tile>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default PatientDiagnoses;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type FetchResponse, openmrsFetch, restBaseUrl, type Visit } from '@openmrs/esm-framework';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import useSWR from 'swr';
|
|
4
|
+
|
|
5
|
+
export const usePatientDiagnosis = (encounterUuid: string) => {
|
|
6
|
+
const customRepresentation =
|
|
7
|
+
'custom:(uuid,display,visit:(uuid,patient,encounters:(uuid,diagnoses:(uuid,display,certainty,diagnosis:(coded:(uuid,display))),encounterDatetime,encounterType:(uuid,display),encounterProviders:(uuid,display,provider:(uuid,person:(uuid,display)))),location:(uuid,name,display),visitType:(uuid,name,display),startDatetime,stopDatetime))';
|
|
8
|
+
const url = `${restBaseUrl}/encounter/${encounterUuid}?v=${customRepresentation}`;
|
|
9
|
+
|
|
10
|
+
const { data, error, isLoading } = useSWR<FetchResponse<{ visit: Visit }>>(url, openmrsFetch);
|
|
11
|
+
|
|
12
|
+
const diagnoses = useMemo(() => {
|
|
13
|
+
return (
|
|
14
|
+
data?.data?.visit?.encounters?.flatMap(
|
|
15
|
+
(encounter) =>
|
|
16
|
+
encounter.diagnoses.map((diagnosis) => ({
|
|
17
|
+
id: diagnosis.diagnosis.coded.uuid,
|
|
18
|
+
text: diagnosis.display,
|
|
19
|
+
certainty: diagnosis.certainty,
|
|
20
|
+
})) || [],
|
|
21
|
+
) || []
|
|
22
|
+
);
|
|
23
|
+
}, [data]);
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
error,
|
|
27
|
+
isLoading,
|
|
28
|
+
diagnoses: (diagnoses ?? []) as Array<{ id: string; text: string; certainty: string }>,
|
|
29
|
+
};
|
|
30
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
@use '@carbon/layout';
|
|
2
|
+
@use '@carbon/colors';
|
|
3
|
+
@use '@carbon/type';
|
|
4
|
+
@import '~@openmrs/esm-styleguide/src/vars';
|
|
5
|
+
|
|
6
|
+
.container {
|
|
7
|
+
height: layout.$spacing-06;
|
|
8
|
+
padding: 0 layout.$spacing-03 0 0;
|
|
9
|
+
border-left: layout.$spacing-02 solid #f1c21b;
|
|
10
|
+
background-color: rgba(253, 209, 58, 0.3);
|
|
11
|
+
margin: layout.$spacing-03 0 layout.$spacing-03 0;
|
|
12
|
+
width: 100%;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.content {
|
|
16
|
+
margin: auto;
|
|
17
|
+
min-width: 100%;
|
|
18
|
+
height: 100%;
|
|
19
|
+
display: flex;
|
|
20
|
+
align-items: center;
|
|
21
|
+
|
|
22
|
+
div {
|
|
23
|
+
align-items: center;
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: row;
|
|
26
|
+
width: 100%;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
p {
|
|
30
|
+
margin-left: layout.$spacing-03;
|
|
31
|
+
font-size: 0.9rem;
|
|
32
|
+
width: 80%;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
a {
|
|
36
|
+
margin: auto;
|
|
37
|
+
color: #0f62fe;
|
|
38
|
+
text-decoration: none;
|
|
39
|
+
text-align: right;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
svg.icon {
|
|
44
|
+
fill: #f1c21b;
|
|
45
|
+
vertical-align: middle;
|
|
46
|
+
margin-left: layout.$spacing-03;
|
|
47
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { FetchResponse, fhirBaseUrl, openmrsFetch, parseDate, useConfig } from '@openmrs/esm-framework';
|
|
2
|
+
import useSWR from 'swr';
|
|
3
|
+
import { CarePanelConfig } from '../config-schema';
|
|
4
|
+
import { useMemo } from 'react';
|
|
5
|
+
|
|
6
|
+
export interface Entry {
|
|
7
|
+
fullUrl: string;
|
|
8
|
+
resource: Resource;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface Resource {
|
|
12
|
+
resourceType: string;
|
|
13
|
+
id: string;
|
|
14
|
+
meta: Meta;
|
|
15
|
+
status: string;
|
|
16
|
+
category: Category[];
|
|
17
|
+
code: Code;
|
|
18
|
+
subject: Subject;
|
|
19
|
+
encounter: Encounter;
|
|
20
|
+
effectiveDateTime: string;
|
|
21
|
+
issued: string;
|
|
22
|
+
valueQuantity: ValueQuantity;
|
|
23
|
+
referenceRange: ReferenceRange[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface Meta {
|
|
27
|
+
versionId: string;
|
|
28
|
+
lastUpdated: string;
|
|
29
|
+
tag: Tag[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface Tag {
|
|
33
|
+
system: string;
|
|
34
|
+
code: string;
|
|
35
|
+
display: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface Category {
|
|
39
|
+
coding: Coding[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface Coding {
|
|
43
|
+
system: string;
|
|
44
|
+
code: string;
|
|
45
|
+
display: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface Code {
|
|
49
|
+
coding: CategoryCoding[];
|
|
50
|
+
text: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface CategoryCoding {
|
|
54
|
+
code: string;
|
|
55
|
+
display?: string;
|
|
56
|
+
system?: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface Subject {
|
|
60
|
+
reference: string;
|
|
61
|
+
type: string;
|
|
62
|
+
display: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface Encounter {
|
|
66
|
+
reference: string;
|
|
67
|
+
type: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface ValueQuantity {
|
|
71
|
+
value: number;
|
|
72
|
+
unit: string;
|
|
73
|
+
system: string;
|
|
74
|
+
code: string;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface ReferenceRange {
|
|
78
|
+
low: Low;
|
|
79
|
+
high: High;
|
|
80
|
+
type: Type;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface Low {
|
|
84
|
+
value: number;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface High {
|
|
88
|
+
value: number;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface Type {
|
|
92
|
+
coding: Coding3[];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface Coding3 {
|
|
96
|
+
system: string;
|
|
97
|
+
code: string;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
type DispensingVitals = {
|
|
101
|
+
display: string;
|
|
102
|
+
uuid: string;
|
|
103
|
+
value: number | string;
|
|
104
|
+
dateRecoded?: Date;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export const usePatientVitals = (patientUuid: string, encounterUuid: string) => {
|
|
108
|
+
const { dispensingVitalsConcepts } = useConfig<CarePanelConfig>();
|
|
109
|
+
const urlParams = new URLSearchParams({
|
|
110
|
+
patient: patientUuid,
|
|
111
|
+
code: dispensingVitalsConcepts.map(({ uuid }) => uuid).join(','),
|
|
112
|
+
encounter: encounterUuid,
|
|
113
|
+
});
|
|
114
|
+
const url = `${fhirBaseUrl}/Observation?${urlParams.toString()}`;
|
|
115
|
+
const { data, error, isLoading, mutate } = useSWR<FetchResponse<{ entry: Array<Entry> }>>(url, openmrsFetch);
|
|
116
|
+
const vitals = useMemo<Array<DispensingVitals>>(
|
|
117
|
+
() =>
|
|
118
|
+
(data?.data?.entry ?? []).map((entry) => ({
|
|
119
|
+
display: entry?.resource?.code?.text,
|
|
120
|
+
uuid: entry?.resource?.id,
|
|
121
|
+
value: entry?.resource?.valueQuantity?.value,
|
|
122
|
+
dateRecoded: entry?.resource?.issued ? parseDate(entry?.resource?.issued) : undefined,
|
|
123
|
+
})),
|
|
124
|
+
[data],
|
|
125
|
+
);
|
|
126
|
+
return {
|
|
127
|
+
vitals,
|
|
128
|
+
isLoading,
|
|
129
|
+
mutate,
|
|
130
|
+
error,
|
|
131
|
+
};
|
|
132
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Layer } from '@carbon/react';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { usePatientVitals } from './dispensing-patient-vitals.resources';
|
|
4
|
+
|
|
5
|
+
type PatientVitalsProps = {
|
|
6
|
+
patientUuid: string;
|
|
7
|
+
encounterUuid: string;
|
|
8
|
+
};
|
|
9
|
+
const DispensingPatientVitals: React.FC<PatientVitalsProps> = ({ encounterUuid, patientUuid }) => {
|
|
10
|
+
const { vitals, error, isLoading } = usePatientVitals(patientUuid, encounterUuid);
|
|
11
|
+
|
|
12
|
+
if (isLoading || error) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
return (
|
|
16
|
+
<Layer>
|
|
17
|
+
{vitals.map((vital) => (
|
|
18
|
+
<div>
|
|
19
|
+
<strong>{vital?.display}: </strong>
|
|
20
|
+
<span>{vital?.value}</span>
|
|
21
|
+
</div>
|
|
22
|
+
))}
|
|
23
|
+
</Layer>
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default DispensingPatientVitals;
|
package/src/index.ts
CHANGED
|
@@ -8,6 +8,9 @@ import deleteRegimenConfirmationDialogComponent from './regimen-editor/delete-re
|
|
|
8
8
|
import regimenFormComponent from './regimen-editor/regimen-form.component';
|
|
9
9
|
import CarePanelDashboard from './care-panel-dashboard/care-panel-dashboard.component';
|
|
10
10
|
import PatientSummary from './patient-summary/patient-summary.component';
|
|
11
|
+
import PatientDiagnoses from './dispensing-patient-details/diagnoses.component';
|
|
12
|
+
import PatientConditions from './dispensing-patient-details/conditions.component';
|
|
13
|
+
import DispensingPatientVitals from './dispensing-patient-details/patient-vitals.component';
|
|
11
14
|
|
|
12
15
|
const moduleName = '@kenyaemr/esm-care-panel-app';
|
|
13
16
|
|
|
@@ -45,3 +48,8 @@ export const hivPatientSummaryDashboardLink = getSyncLifecycle(
|
|
|
45
48
|
);
|
|
46
49
|
export const hivPatientSummary = getSyncLifecycle(PatientSummary, options);
|
|
47
50
|
export const regimenFormWorkspace = getSyncLifecycle(regimenFormComponent, options);
|
|
51
|
+
|
|
52
|
+
// TODO Clean when community version gets merged
|
|
53
|
+
export const patientDiagnoses = getSyncLifecycle(PatientDiagnoses, options);
|
|
54
|
+
export const patientConditions = getSyncLifecycle(PatientConditions, options);
|
|
55
|
+
export const dispensingPaentientVitals = getSyncLifecycle(DispensingPatientVitals, options);
|
package/src/routes.json
CHANGED
|
@@ -50,14 +50,32 @@
|
|
|
50
50
|
"order": 3,
|
|
51
51
|
"online": true,
|
|
52
52
|
"offline": false
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"name": "patient-diagnoses",
|
|
56
|
+
"component": "patientDiagnoses",
|
|
57
|
+
"online": true,
|
|
58
|
+
"offline": true
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"name": "patient-conditions",
|
|
62
|
+
"component": "patientConditions",
|
|
63
|
+
"online": true,
|
|
64
|
+
"offline": true
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"name": "dispensing-patient-vitals",
|
|
68
|
+
"component": "dispensingPaentientVitals",
|
|
69
|
+
"online": true,
|
|
70
|
+
"offline": true
|
|
53
71
|
}
|
|
54
72
|
],
|
|
55
73
|
"workspaces": [
|
|
56
74
|
{
|
|
57
75
|
"name": "patient-regimen-workspace",
|
|
58
76
|
"title": "Patient Regimen",
|
|
59
|
-
"component":"regimenFormWorkspace",
|
|
60
|
-
"type":"form",
|
|
77
|
+
"component": "regimenFormWorkspace",
|
|
78
|
+
"type": "form",
|
|
61
79
|
"canMaximize": true,
|
|
62
80
|
"canHide": true,
|
|
63
81
|
"width": "wider"
|