@openmrs/esm-ward-app 9.2.1-pre.7387 → 9.2.1-pre.7405
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 +3 -3
- package/dist/1326.js +1 -1
- package/dist/1326.js.map +1 -1
- package/dist/380.js +1 -1
- package/dist/380.js.map +1 -1
- package/dist/4098.js +1 -0
- package/dist/4098.js.map +1 -0
- package/dist/4300.js +1 -1
- package/dist/5885.js +1 -1
- package/dist/5885.js.map +1 -1
- package/dist/7512.js +1 -1
- package/dist/7524.js +1 -1
- package/dist/7524.js.map +1 -1
- package/dist/9775.js +1 -1
- package/dist/9775.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/openmrs-esm-ward-app.js.buildmanifest.json +45 -45
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/types/index.ts +11 -0
- package/src/utils.ts +15 -0
- package/src/ward-view/default-ward/default-ward-view.component.tsx +3 -1
- package/src/ward-view/materal-ward/maternal-ward-view.component.tsx +15 -2
- package/src/ward-view/ward-view.resource.test.ts +140 -0
- package/src/ward-view/ward-view.resource.ts +21 -22
- package/src/ward-view-header/ward-metrics.component.tsx +59 -38
- package/src/ward-view-header/ward-metrics.test.tsx +17 -17
- package/src/ward-view-header/ward-view-header.component.tsx +3 -3
- package/translations/en.json +2 -4
- package/dist/8610.js +0 -1
- package/dist/8610.js.map +0 -1
- /package/src/{ward-view-header → ward-view}/ward-metrics.scss +0 -0
|
@@ -21,6 +21,7 @@ import type {
|
|
|
21
21
|
WardPatientGroupDetails,
|
|
22
22
|
} from '../types';
|
|
23
23
|
import { useTranslation } from 'react-i18next';
|
|
24
|
+
import { filterFemale, filterNewborns, filterReproductiveAge } from '../utils';
|
|
24
25
|
|
|
25
26
|
// the server side has 2 slightly incompatible types for Bed
|
|
26
27
|
export function bedLayoutToBed(bedLayout: BedLayout): Bed {
|
|
@@ -46,14 +47,25 @@ export function filterBeds(admissionLocation: AdmissionLocationFetchResponse): B
|
|
|
46
47
|
return bedLayouts;
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
export function getWardMetrics(
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
|
|
50
|
+
export function getWardMetrics(wardPatientGroup: WardPatientGroupDetails): WardMetrics {
|
|
51
|
+
// pull all the patients out of the three constructs they are stored in: unadmitted but in a bed, admitted and in a bed, and admitted but not in a bed
|
|
52
|
+
const allPatients = [
|
|
53
|
+
...wardPatientGroup.wardUnadmittedPatientsWithBed?.values(),
|
|
54
|
+
...[...wardPatientGroup.wardAdmittedPatientsWithBed?.values()].map((admission) => admission.patient),
|
|
55
|
+
...wardPatientGroup.wardUnassignedPatientsList?.map((admission) => admission.patient),
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
const patientCount = allPatients?.length ?? 0;
|
|
59
|
+
const newborns = filterNewborns(allPatients)?.length ?? 0;
|
|
60
|
+
const femalesOfReproductiveAge = filterReproductiveAge(filterFemale(allPatients))?.length ?? 0;
|
|
61
|
+
const totalBeds = wardPatientGroup.bedLayouts?.length ?? 0;
|
|
62
|
+
const occupiedBeds = wardPatientGroup.bedLayouts?.filter((bed) => bed.patients?.length > 0).length ?? 0;
|
|
53
63
|
return {
|
|
54
|
-
patients:
|
|
64
|
+
patients: patientCount.toString(),
|
|
55
65
|
freeBeds: (totalBeds - occupiedBeds).toString(),
|
|
56
66
|
totalBeds: totalBeds.toString(),
|
|
67
|
+
newborns: newborns.toString(), // used by maternal ward only
|
|
68
|
+
femalesOfReproductiveAge: femalesOfReproductiveAge.toString(), // used by maternal ward only
|
|
57
69
|
};
|
|
58
70
|
}
|
|
59
71
|
|
|
@@ -110,9 +122,6 @@ export function createAndGetWardPatientGrouping(
|
|
|
110
122
|
);
|
|
111
123
|
}) ?? [];
|
|
112
124
|
|
|
113
|
-
//excluding inpatientRequests
|
|
114
|
-
const totalPatientsCount = allWardPatientUuids.size;
|
|
115
|
-
|
|
116
125
|
for (const inpatientRequest of inpatientRequests ?? []) {
|
|
117
126
|
// TODO: inpatientRequest is undefined sometimes, why?
|
|
118
127
|
if (inpatientRequest) {
|
|
@@ -127,7 +136,6 @@ export function createAndGetWardPatientGrouping(
|
|
|
127
136
|
bedLayouts,
|
|
128
137
|
wardUnassignedPatientsList,
|
|
129
138
|
allWardPatientUuids,
|
|
130
|
-
totalPatientsCount,
|
|
131
139
|
inpatientAdmissionsByPatientUuid,
|
|
132
140
|
};
|
|
133
141
|
}
|
|
@@ -142,19 +150,10 @@ export function getWardMetricNameTranslation(name: string, t: TFunction) {
|
|
|
142
150
|
return t('totalBeds', 'Total beds');
|
|
143
151
|
case 'pendingOut':
|
|
144
152
|
return t('pendingOut', 'Pending out');
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
switch (name) {
|
|
150
|
-
case 'patients':
|
|
151
|
-
return t('patientsMetricValue', '{{ metricValue }}', { metricValue: value });
|
|
152
|
-
case 'freeBeds':
|
|
153
|
-
return t('freeBedsMetricValue', '{{ metricValue }}', { metricValue: value });
|
|
154
|
-
case 'totalBeds':
|
|
155
|
-
return t('totalBedsMetricValue', '{{ metricValue }}', { metricValue: value });
|
|
156
|
-
case 'pendingOut':
|
|
157
|
-
return t('pendingOutMetricValue', '{{ metricValue }}', { metricValue: value });
|
|
153
|
+
case 'femalesOfReproductiveAge':
|
|
154
|
+
return t('mothers', 'Mothers');
|
|
155
|
+
case 'newborns':
|
|
156
|
+
return t('infants', 'Infants');
|
|
158
157
|
}
|
|
159
158
|
}
|
|
160
159
|
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { showNotification, useAppContext, useFeatureFlag } from '@openmrs/esm-framework';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
|
-
import type
|
|
5
|
-
import {
|
|
6
|
-
getWardMetricNameTranslation,
|
|
7
|
-
getWardMetrics,
|
|
8
|
-
getWardMetricValueTranslation,
|
|
9
|
-
} from '../ward-view/ward-view.resource';
|
|
4
|
+
import { WardMetricType, type WardViewContext } from '../types';
|
|
5
|
+
import { getWardMetricNameTranslation, getWardMetrics } from '../ward-view/ward-view.resource';
|
|
10
6
|
import WardMetric from './ward-metric.component';
|
|
11
|
-
import styles from '
|
|
7
|
+
import styles from '../ward-view/ward-metrics.scss';
|
|
12
8
|
|
|
13
|
-
|
|
9
|
+
interface WardMetricsProps {
|
|
10
|
+
metrics?: WardMetricType[];
|
|
11
|
+
}
|
|
14
12
|
|
|
15
|
-
const WardMetrics = (
|
|
13
|
+
const WardMetrics: React.FC<WardMetricsProps> = ({
|
|
14
|
+
metrics = [WardMetricType.PATIENTS, WardMetricType.FREE_BEDS, WardMetricType.TOTAL_BEDS, WardMetricType.PENDING_OUT],
|
|
15
|
+
}) => {
|
|
16
16
|
const { t } = useTranslation();
|
|
17
17
|
const isBedManagementModuleInstalled = useFeatureFlag('bedmanagement-module');
|
|
18
18
|
const { wardPatientGroupDetails } = useAppContext<WardViewContext>('ward-view-context') ?? {};
|
|
19
|
-
const { admissionLocationResponse, inpatientAdmissionResponse, inpatientRequestResponse
|
|
19
|
+
const { admissionLocationResponse, inpatientAdmissionResponse, inpatientRequestResponse } =
|
|
20
20
|
wardPatientGroupDetails || {};
|
|
21
21
|
const { isLoading, error } = admissionLocationResponse ?? {};
|
|
22
22
|
const isDataLoading =
|
|
@@ -33,43 +33,64 @@ const WardMetrics = () => {
|
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
const wardMetricValues = getWardMetrics(
|
|
36
|
+
const wardMetricValues = getWardMetrics(wardPatientGroupDetails);
|
|
37
37
|
return (
|
|
38
38
|
<div className={styles.metricsContainer}>
|
|
39
|
-
{
|
|
40
|
-
wardMetrics.map((wardMetric) => {
|
|
41
|
-
return (
|
|
42
|
-
<WardMetric
|
|
43
|
-
metricName={getWardMetricNameTranslation(wardMetric.name, t)}
|
|
44
|
-
metricValue={getWardMetricValueTranslation(wardMetric.name, t, wardMetricValues[wardMetric.name])}
|
|
45
|
-
isLoading={!!isLoading || !!isDataLoading}
|
|
46
|
-
key={wardMetric.name}
|
|
47
|
-
/>
|
|
48
|
-
);
|
|
49
|
-
})
|
|
50
|
-
) : (
|
|
39
|
+
{metrics.includes(WardMetricType.PATIENTS) && (
|
|
51
40
|
<WardMetric
|
|
52
41
|
metricName={getWardMetricNameTranslation('patients', t)}
|
|
53
|
-
metricValue={'
|
|
42
|
+
metricValue={wardMetricValues['patients']}
|
|
54
43
|
isLoading={false}
|
|
55
44
|
key={'patients'}
|
|
56
45
|
/>
|
|
57
46
|
)}
|
|
47
|
+
{metrics.includes(WardMetricType.FEMALE_OF_REPRODUCTIVE_AGE) &&
|
|
48
|
+
wardMetricValues['femalesOfReproductiveAge'] &&
|
|
49
|
+
wardMetricValues['femalesOfReproductiveAge'] !== '0' && (
|
|
50
|
+
<WardMetric
|
|
51
|
+
metricName={getWardMetricNameTranslation('femalesOfReproductiveAge', t)}
|
|
52
|
+
metricValue={wardMetricValues['femalesOfReproductiveAge']}
|
|
53
|
+
isLoading={!!isLoading || !!isDataLoading}
|
|
54
|
+
key={'femalesOfReproductiveAge'}
|
|
55
|
+
/>
|
|
56
|
+
)}
|
|
57
|
+
{metrics.includes(WardMetricType.NEWBORNS) &&
|
|
58
|
+
wardMetricValues['newborns'] &&
|
|
59
|
+
wardMetricValues['newborns'] !== '0' && (
|
|
60
|
+
<WardMetric
|
|
61
|
+
metricName={getWardMetricNameTranslation('newborns', t)}
|
|
62
|
+
metricValue={wardMetricValues['newborns']}
|
|
63
|
+
isLoading={!!isLoading || !!isDataLoading}
|
|
64
|
+
key={'newborns'}
|
|
65
|
+
/>
|
|
66
|
+
)}
|
|
58
67
|
{isBedManagementModuleInstalled && (
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
<>
|
|
69
|
+
{metrics.includes(WardMetricType.FREE_BEDS) && (
|
|
70
|
+
<WardMetric
|
|
71
|
+
metricName={getWardMetricNameTranslation('freeBeds', t)}
|
|
72
|
+
metricValue={wardMetricValues['freeBeds']}
|
|
73
|
+
isLoading={!!isLoading || !!isDataLoading}
|
|
74
|
+
key={'freeBeds'}
|
|
75
|
+
/>
|
|
76
|
+
)}
|
|
77
|
+
{metrics.includes(WardMetricType.TOTAL_BEDS) && (
|
|
78
|
+
<WardMetric
|
|
79
|
+
metricName={getWardMetricNameTranslation('totalBeds', t)}
|
|
80
|
+
metricValue={wardMetricValues['totalBeds']}
|
|
81
|
+
isLoading={!!isLoading || !!isDataLoading}
|
|
82
|
+
key={'totalBeds'}
|
|
83
|
+
/>
|
|
84
|
+
)}
|
|
85
|
+
{metrics.includes(WardMetricType.PENDING_OUT) && (
|
|
86
|
+
<WardMetric
|
|
87
|
+
metricName={getWardMetricNameTranslation('pendingOut', t)}
|
|
88
|
+
metricValue={wardPatientGroupDetails?.wardPatientPendingCount?.toString()}
|
|
89
|
+
isLoading={!!isDataLoading}
|
|
90
|
+
key="pending"
|
|
91
|
+
/>
|
|
92
|
+
)}
|
|
93
|
+
</>
|
|
73
94
|
)}
|
|
74
95
|
</div>
|
|
75
96
|
);
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
import { useAppContext } from '@openmrs/esm-framework';
|
|
2
2
|
import { screen } from '@testing-library/react';
|
|
3
3
|
import React from 'react';
|
|
4
|
-
import { renderWithSwr } from '
|
|
4
|
+
import { renderWithSwr } from 'tools';
|
|
5
5
|
import { mockWardViewContext } from '../../mock';
|
|
6
|
-
import { type WardViewContext } from '../types';
|
|
7
|
-
import { getWardMetrics } from '../ward-view/ward-view.resource';
|
|
6
|
+
import { WardMetricType, type WardViewContext } from '../types';
|
|
8
7
|
import WardMetrics from './ward-metrics.component';
|
|
9
8
|
|
|
10
|
-
const wardMetrics = [
|
|
11
|
-
{ name: 'patients', key: 'patients', defaultTranslation: 'Patients' },
|
|
12
|
-
{ name: 'freeBeds', key: 'freeBeds', defaultTranslation: 'Free beds' },
|
|
13
|
-
{ name: 'totalBeds', key: 'totalBeds', defaultTranslation: 'Total beds' },
|
|
14
|
-
];
|
|
15
|
-
|
|
16
9
|
jest.mocked(useAppContext<WardViewContext>).mockReturnValue(mockWardViewContext);
|
|
17
10
|
|
|
18
11
|
describe('Ward Metrics', () => {
|
|
19
|
-
it('Should display metrics
|
|
20
|
-
const mockWardPatientGroupDetails = mockWardViewContext.wardPatientGroupDetails;
|
|
21
|
-
const { bedLayouts } = mockWardPatientGroupDetails;
|
|
22
|
-
const bedMetrics = getWardMetrics(bedLayouts, mockWardPatientGroupDetails);
|
|
12
|
+
it('Should display standard metrics by default', () => {
|
|
23
13
|
renderWithSwr(<WardMetrics />);
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
14
|
+
expect(screen.getByText('Patients')).toBeInTheDocument();
|
|
15
|
+
expect(screen.getByText('Free beds')).toBeInTheDocument();
|
|
16
|
+
expect(screen.getByText('Total beds')).toBeInTheDocument();
|
|
17
|
+
expect(screen.getByText('Pending out')).toBeInTheDocument();
|
|
18
|
+
expect(screen.queryByText('Mothers')).not.toBeInTheDocument();
|
|
19
|
+
expect(screen.queryByText('Infants')).not.toBeInTheDocument();
|
|
20
|
+
});
|
|
21
|
+
it('Should display extra metrics when configured', () => {
|
|
22
|
+
renderWithSwr(<WardMetrics metrics={[WardMetricType.FEMALE_OF_REPRODUCTIVE_AGE]} />);
|
|
23
|
+
expect(screen.getByText('Mothers')).toBeInTheDocument();
|
|
24
|
+
expect(screen.queryByText('Patients')).not.toBeInTheDocument();
|
|
25
|
+
expect(screen.queryByText('Free beds')).not.toBeInTheDocument();
|
|
26
|
+
expect(screen.queryByText('Total beds')).not.toBeInTheDocument();
|
|
27
|
+
expect(screen.queryByText('Pending out')).not.toBeInTheDocument();
|
|
28
28
|
});
|
|
29
29
|
});
|
|
@@ -2,19 +2,19 @@ import React, { type ReactNode } from 'react';
|
|
|
2
2
|
import styles from './ward-view-header.scss';
|
|
3
3
|
import AdmissionRequestsBar from './admission-requests-bar.component';
|
|
4
4
|
import useWardLocation from '../hooks/useWardLocation';
|
|
5
|
-
import WardMetrics from './ward-metrics.component';
|
|
6
5
|
|
|
7
6
|
interface WardViewHeaderProps {
|
|
8
7
|
wardPendingPatients: ReactNode;
|
|
8
|
+
wardMetrics: ReactNode;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
const WardViewHeader: React.FC<WardViewHeaderProps> = ({ wardPendingPatients }) => {
|
|
11
|
+
const WardViewHeader: React.FC<WardViewHeaderProps> = ({ wardPendingPatients, wardMetrics }) => {
|
|
12
12
|
const { location } = useWardLocation();
|
|
13
13
|
|
|
14
14
|
return (
|
|
15
15
|
<div className={styles.wardViewHeader}>
|
|
16
16
|
<h4>{location?.display}</h4>
|
|
17
|
-
|
|
17
|
+
{wardMetrics}
|
|
18
18
|
<AdmissionRequestsBar {...{ wardPendingPatients }} />
|
|
19
19
|
</div>
|
|
20
20
|
);
|
package/translations/en.json
CHANGED
|
@@ -48,9 +48,9 @@
|
|
|
48
48
|
"fetchingEmrConfigurationFailed": "Fetching EMR configuration failed. Try refreshing the page or contact your system administrator.",
|
|
49
49
|
"fetchingPatientNotesFailed": "Fetching patient notes failed. Try refreshing the page or contact your system administrator.",
|
|
50
50
|
"freeBeds": "Free beds",
|
|
51
|
-
"freeBedsMetricValue": "{{ metricValue }}",
|
|
52
51
|
"hours_one": "{{count}} hour",
|
|
53
52
|
"hours_other": "{{count}} hours",
|
|
53
|
+
"infants": "Infants",
|
|
54
54
|
"inpatientNotesWorkspaceTitle": "In-patient notes",
|
|
55
55
|
"invalidLocationSpecified": "Invalid location specified",
|
|
56
56
|
"invalidWardLocation": "Invalid ward location: {{location}}",
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
"minutes_one": "{{count}} minutes",
|
|
61
61
|
"minutes_other": "{{count}} minutes",
|
|
62
62
|
"motherChildBedShare": "Mother / Child",
|
|
63
|
+
"mothers": "Mothers",
|
|
63
64
|
"nextPage": "Next page",
|
|
64
65
|
"noActiveVisit": "No active visit",
|
|
65
66
|
"noAdmission": "No admission found",
|
|
@@ -91,7 +92,6 @@
|
|
|
91
92
|
"patientNoteSaveError": "Error saving patient note",
|
|
92
93
|
"patientNotesDidntLoad": "Patient notes didn't load",
|
|
93
94
|
"patients": "Patients",
|
|
94
|
-
"patientsMetricValue": "{{ metricValue }}",
|
|
95
95
|
"patientTransferRequestCreated": "Patient transfer request created",
|
|
96
96
|
"patientUnassignedFromBed": "Patient unassigned from bed",
|
|
97
97
|
"patientUnassignedFromBedDetail": "{{patientName}} is now unassigned from bed",
|
|
@@ -99,7 +99,6 @@
|
|
|
99
99
|
"pendingAdmissions": "Pending admissions",
|
|
100
100
|
"pendingDischarge": "Pending Discharge",
|
|
101
101
|
"pendingOut": "Pending out",
|
|
102
|
-
"pendingOutMetricValue": "{{ metricValue }}",
|
|
103
102
|
"pendingTransfer": "Pending Transfer",
|
|
104
103
|
"pleaseSelectBed": "Please select a bed",
|
|
105
104
|
"pleaseSelectTransferLocation": "Please select transfer location",
|
|
@@ -119,7 +118,6 @@
|
|
|
119
118
|
"timeOnWard": "Time on this ward: {{timeOnWard}}",
|
|
120
119
|
"timeSinceAdmission": "Admitted: {{timeSinceAdmission}}",
|
|
121
120
|
"totalBeds": "Total beds",
|
|
122
|
-
"totalBedsMetricValue": "{{ metricValue }}",
|
|
123
121
|
"transfer": "Transfer",
|
|
124
122
|
"transferElsewhere": "Transfer elsewhere",
|
|
125
123
|
"transferPatient": "Transfer patient",
|