@kenyaemr/esm-ward-app 8.1.1-pre.118 → 8.1.1-pre.121
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 +16 -20
- package/dist/124.js +1 -0
- package/dist/124.js.map +1 -0
- package/dist/125.js +1 -1
- package/dist/125.js.map +1 -1
- package/dist/130.js +1 -1
- package/dist/130.js.map +1 -1
- package/dist/153.js +1 -0
- package/dist/153.js.map +1 -0
- package/dist/372.js +1 -1
- package/dist/372.js.map +1 -1
- package/dist/471.js +1 -0
- package/dist/471.js.map +1 -0
- package/dist/481.js +1 -0
- package/dist/481.js.map +1 -0
- package/dist/53.js +1 -1
- package/dist/53.js.map +1 -1
- package/dist/559.js +1 -1
- package/dist/559.js.map +1 -1
- package/dist/574.js +1 -1
- package/dist/{500.js → 576.js} +1 -1
- package/dist/576.js.map +1 -0
- package/dist/577.js +1 -1
- package/dist/577.js.map +1 -1
- package/dist/649.js +2 -0
- package/dist/{161.js.LICENSE.txt → 649.js.LICENSE.txt} +0 -6
- package/dist/649.js.map +1 -0
- package/dist/{659.js → 662.js} +1 -1
- package/dist/662.js.map +1 -0
- package/dist/67.js +2 -0
- package/dist/67.js.LICENSE.txt +5 -0
- package/dist/67.js.map +1 -0
- package/dist/920.js +1 -0
- package/dist/920.js.map +1 -0
- package/dist/921.js +1 -0
- package/dist/921.js.map +1 -0
- package/dist/922.js +1 -1
- package/dist/922.js.map +1 -1
- package/dist/kenyaemr-esm-ward-app.js +1 -1
- package/dist/kenyaemr-esm-ward-app.js.buildmanifest.json +148 -165
- package/dist/kenyaemr-esm-ward-app.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.LICENSE.txt +0 -10
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/mock.tsx +8 -0
- package/package.json +1 -1
- package/src/beds/empty-bed-skeleton.tsx +3 -3
- package/src/beds/empty-bed.component.tsx +3 -3
- package/src/beds/ward-bed.component.tsx +41 -0
- package/src/beds/ward-bed.scss +45 -0
- package/src/beds/{occupied-bed.test.tsx → ward-bed.test.tsx} +27 -16
- package/src/config-schema.ts +196 -75
- package/src/hooks/useAssignedBedByPatient.ts +9 -0
- package/src/hooks/useInpatientAdmission.ts +1 -1
- package/src/hooks/useMotherAndChildren.ts +2 -2
- package/src/hooks/useObs.ts +2 -2
- package/src/hooks/useWardPatientGrouping.ts +2 -0
- package/src/index.ts +10 -29
- package/src/root.component.tsx +3 -0
- package/src/routes.json +6 -11
- package/src/types/index.ts +29 -14
- package/src/ward-patient-card/card-rows/admission-request-note-row.component.tsx +38 -0
- package/src/ward-patient-card/card-rows/coded-obs-tags-row.component.tsx +108 -0
- package/src/ward-patient-card/card-rows/mother-child-row.component.tsx +84 -0
- package/src/ward-patient-card/card-rows/{pending-items-car-row.extension.tsx → pending-items-row.component.tsx} +12 -8
- package/src/ward-patient-card/row-elements/ward-patient-coded-obs-tags.tsx +12 -7
- package/src/ward-patient-card/row-elements/ward-patient-header-address.tsx +5 -5
- package/src/ward-patient-card/row-elements/ward-patient-identifier.tsx +18 -40
- package/src/ward-patient-card/row-elements/ward-patient-obs.resource.ts +2 -2
- package/src/ward-patient-card/row-elements/ward-patient-obs.tsx +15 -8
- package/src/ward-patient-card/ward-patient-card.component.tsx +16 -54
- package/src/ward-patient-card/ward-patient-card.scss +7 -1
- package/src/ward-view/default-ward/default-ward-beds.component.tsx +42 -0
- package/src/ward-view/default-ward/default-ward-patient-card-header.component.tsx +32 -0
- package/src/ward-view/default-ward/default-ward-patient-card.component.tsx +31 -0
- package/src/ward-view/default-ward/default-ward-pending-patients.component.tsx +52 -0
- package/src/ward-view/default-ward/default-ward-unassigned-patients.component.tsx +32 -0
- package/src/ward-view/default-ward/default-ward-view.component.tsx +31 -0
- package/src/ward-view/materal-ward/maternal-ward-beds.component.tsx +65 -0
- package/src/ward-view/materal-ward/maternal-ward-patient-card-header.component.tsx +30 -0
- package/src/ward-view/materal-ward/maternal-ward-patient-card.component.tsx +93 -0
- package/src/{beds/occupied-bed.scss → ward-view/materal-ward/maternal-ward-patient-card.scss} +4 -10
- package/src/ward-view/materal-ward/maternal-ward-patient-card.test.tsx +47 -0
- package/src/ward-view/materal-ward/maternal-ward-pending-patients.component.tsx +48 -0
- package/src/ward-view/materal-ward/maternal-ward-unassigned-patients.component.tsx +33 -0
- package/src/ward-view/materal-ward/maternal-ward-view.component.tsx +38 -0
- package/src/ward-view/materal-ward/maternal-ward-view.resource.ts +89 -0
- package/src/ward-view/ward-view.component.tsx +11 -151
- package/src/ward-view/ward-view.resource.ts +78 -6
- package/src/ward-view/ward-view.scss +1 -0
- package/src/ward-view/ward-view.test.tsx +10 -8
- package/src/ward-view/ward.component.tsx +106 -0
- package/src/ward-view-header/admission-requests-bar.component.tsx +10 -6
- package/src/ward-view-header/admission-requests-bar.test.tsx +5 -4
- package/src/ward-view-header/ward-metrics.component.tsx +12 -11
- package/src/ward-view-header/ward-metrics.test.tsx +4 -58
- package/src/ward-view-header/ward-view-header.component.tsx +6 -4
- package/src/ward-workspace/admission-request-card/admission-request-card-actions.component.tsx +7 -4
- package/src/ward-workspace/admission-request-card/admission-request-card-header.component.tsx +9 -21
- package/src/ward-workspace/admission-request-card/admission-request-card.component.tsx +9 -3
- package/src/ward-workspace/admission-request-card/admission-request-card.scss +6 -1
- package/src/ward-workspace/admission-request-workspace/admission-requests-workspace.test.tsx +11 -38
- package/src/ward-workspace/admission-request-workspace/admission-requests.workspace.tsx +8 -38
- package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.test.tsx +80 -89
- package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.workspace.tsx +21 -13
- package/src/ward-workspace/patient-banner/patient-banner.component.tsx +5 -12
- package/src/ward-workspace/patient-details/ward-patient-action-button.extension.tsx +2 -2
- package/src/ward-workspace/patient-details/ward-patient.workspace.tsx +13 -6
- package/src/ward-workspace/patient-discharge/patient-discharge.workspace.tsx +6 -6
- package/src/ward-workspace/patient-transfer-bed-swap/patient-bed-swap-form.component.tsx +7 -7
- package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-request-form.component.tsx +6 -6
- package/translations/en.json +7 -1
- package/dist/126.js +0 -1
- package/dist/126.js.map +0 -1
- package/dist/161.js +0 -2
- package/dist/161.js.map +0 -1
- package/dist/2.js +0 -1
- package/dist/2.js.map +0 -1
- package/dist/269.js +0 -1
- package/dist/269.js.map +0 -1
- package/dist/466.js +0 -1
- package/dist/466.js.map +0 -1
- package/dist/500.js.map +0 -1
- package/dist/557.js +0 -1
- package/dist/557.js.map +0 -1
- package/dist/659.js.map +0 -1
- package/dist/701.js +0 -1
- package/dist/701.js.map +0 -1
- package/dist/749.js +0 -1
- package/dist/749.js.map +0 -1
- package/dist/908.js +0 -1
- package/dist/908.js.map +0 -1
- package/src/beds/empty-bed.scss +0 -24
- package/src/beds/occupied-bed.component.tsx +0 -35
- package/src/beds/unassigned-patient.component.tsx +0 -20
- package/src/beds/unassigned-patient.scss +0 -6
- package/src/config-schema-admission-request-note.ts +0 -9
- package/src/config-schema-extension-colored-obs-tags.ts +0 -91
- package/src/config-schema-mother-child-row.ts +0 -26
- package/src/config-schema-pending-items-extension.ts +0 -29
- package/src/hooks/useCurrentWardCardConfig.ts +0 -32
- package/src/ward-patient-card/card-rows/admission-request-note.extension.tsx +0 -32
- package/src/ward-patient-card/card-rows/colored-obs-tags-card-row.extension.tsx +0 -13
- package/src/ward-patient-card/card-rows/mother-child-row.extension.tsx +0 -110
- package/src/ward-patient-card/ward-patient-card-element.component.tsx +0 -69
- package/src/ward-patient-card/ward-patient-resource.ts +0 -15
- package/src/ward-view/ward-bed.component.tsx +0 -14
- /package/src/ward-patient-card/row-elements/{ward-pateint-skeleton-text.tsx → ward-patient-skeleton-text.tsx} +0 -0
|
@@ -21,5 +21,7 @@ export function useWardPatientGrouping() {
|
|
|
21
21
|
admissionLocationResponse,
|
|
22
22
|
inpatientAdmissionResponse,
|
|
23
23
|
inpatientRequestResponse,
|
|
24
|
+
isLoading:
|
|
25
|
+
admissionLocationResponse.isLoading || inpatientAdmissionResponse.isLoading || inpatientRequestResponse.isLoading,
|
|
24
26
|
};
|
|
25
27
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
defineConfigSchema,
|
|
3
|
-
defineExtensionConfigSchema,
|
|
4
3
|
getAsyncLifecycle,
|
|
5
4
|
getSyncLifecycle,
|
|
6
5
|
registerBreadcrumbs,
|
|
7
6
|
registerFeatureFlag,
|
|
8
7
|
} from '@openmrs/esm-framework';
|
|
9
8
|
import { configSchema } from './config-schema';
|
|
10
|
-
import { admissionRequestNoteRowConfigSchema } from './config-schema-admission-request-note';
|
|
11
|
-
import { coloredObsTagsCardRowConfigSchema } from './config-schema-extension-colored-obs-tags';
|
|
12
9
|
import { moduleName } from './constant';
|
|
13
10
|
import { createDashboardLink } from './createDashboardLink.component';
|
|
14
11
|
import rootComponent from './root.component';
|
|
15
|
-
import { motherChildRowConfigSchema } from './config-schema-mother-child-row';
|
|
16
|
-
import { pendingItemsExtensionConfigSchema } from './config-schema-pending-items-extension';
|
|
17
12
|
|
|
18
13
|
export const importTranslation = require.context('../translations', false, /.json$/, 'lazy');
|
|
19
14
|
|
|
@@ -60,26 +55,6 @@ export const wardPatientNotesActionButtonExtension = getAsyncLifecycle(
|
|
|
60
55
|
options,
|
|
61
56
|
);
|
|
62
57
|
|
|
63
|
-
export const coloredObsTagCardRowExtension = getAsyncLifecycle(
|
|
64
|
-
() => import('./ward-patient-card/card-rows/colored-obs-tags-card-row.extension'),
|
|
65
|
-
options,
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
export const admissionRequestNoteRowExtension = getAsyncLifecycle(
|
|
69
|
-
() => import('./ward-patient-card/card-rows/admission-request-note.extension'),
|
|
70
|
-
options,
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
export const motherChildRowExtension = getAsyncLifecycle(
|
|
74
|
-
() => import('./ward-patient-card/card-rows/mother-child-row.extension'),
|
|
75
|
-
options,
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
export const pendingItemsCardRowExtension = getAsyncLifecycle(
|
|
79
|
-
() => import('./ward-patient-card/card-rows/pending-items-car-row.extension'),
|
|
80
|
-
options,
|
|
81
|
-
);
|
|
82
|
-
|
|
83
58
|
// t('transfers', 'Transfers')
|
|
84
59
|
export const patientTransferAndSwapWorkspace = getAsyncLifecycle(
|
|
85
60
|
() => import('./ward-workspace/patient-transfer-bed-swap/patient-transfer-swap.workspace'),
|
|
@@ -118,13 +93,19 @@ export const clinicalFormWorkspaceSideRailIcon = getAsyncLifecycle(
|
|
|
118
93
|
options,
|
|
119
94
|
);
|
|
120
95
|
|
|
96
|
+
export const defaultWardView = getAsyncLifecycle(
|
|
97
|
+
() => import('./ward-view/default-ward/default-ward-view.component'),
|
|
98
|
+
options,
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
export const maternalWardView = getAsyncLifecycle(
|
|
102
|
+
() => import('./ward-view/materal-ward/maternal-ward-view.component'),
|
|
103
|
+
options,
|
|
104
|
+
);
|
|
105
|
+
|
|
121
106
|
export function startupApp() {
|
|
122
107
|
registerBreadcrumbs([]);
|
|
123
108
|
defineConfigSchema(moduleName, configSchema);
|
|
124
|
-
defineExtensionConfigSchema('colored-obs-tags-card-row', coloredObsTagsCardRowConfigSchema);
|
|
125
|
-
defineExtensionConfigSchema('admission-request-note-card-row', admissionRequestNoteRowConfigSchema);
|
|
126
|
-
defineExtensionConfigSchema('mother-child-card-row', motherChildRowConfigSchema);
|
|
127
|
-
defineExtensionConfigSchema('ward-patient-pending-items-card-row', pendingItemsExtensionConfigSchema);
|
|
128
109
|
|
|
129
110
|
registerFeatureFlag(
|
|
130
111
|
'bedmanagement-module',
|
package/src/root.component.tsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { WorkspaceContainer } from '@openmrs/esm-framework';
|
|
1
2
|
import React from 'react';
|
|
2
3
|
import { BrowserRouter, Route, Routes } from 'react-router-dom';
|
|
3
4
|
import WardView from './ward-view/ward-view.component';
|
|
@@ -14,6 +15,8 @@ const Root: React.FC = () => {
|
|
|
14
15
|
<Route path="/:locationUuid" element={<WardView />} />
|
|
15
16
|
</Routes>
|
|
16
17
|
</BrowserRouter>
|
|
18
|
+
|
|
19
|
+
<WorkspaceContainer overlay contextKey="ward" />
|
|
17
20
|
</main>
|
|
18
21
|
);
|
|
19
22
|
};
|
package/src/routes.json
CHANGED
|
@@ -61,19 +61,14 @@
|
|
|
61
61
|
"slot": "action-menu-ward-patient-items-slot"
|
|
62
62
|
},
|
|
63
63
|
{
|
|
64
|
-
"component": "
|
|
65
|
-
"name": "
|
|
66
|
-
"slot": "ward
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
"component": "motherChildRowExtension",
|
|
70
|
-
"name": "mother-child-card-row",
|
|
71
|
-
"slot": "ward-patient-card-slot"
|
|
64
|
+
"component": "defaultWardView",
|
|
65
|
+
"name": "default-ward",
|
|
66
|
+
"slot": "default-ward"
|
|
72
67
|
},
|
|
73
68
|
{
|
|
74
|
-
"component": "
|
|
75
|
-
"name": "ward
|
|
76
|
-
"slot": "ward
|
|
69
|
+
"component": "maternalWardView",
|
|
70
|
+
"name": "maternal-ward",
|
|
71
|
+
"slot": "maternal-ward"
|
|
77
72
|
}
|
|
78
73
|
],
|
|
79
74
|
"workspaces": [
|
package/src/types/index.ts
CHANGED
|
@@ -11,7 +11,7 @@ import type {
|
|
|
11
11
|
import type React from 'react';
|
|
12
12
|
import type { useWardPatientGrouping } from '../hooks/useWardPatientGrouping';
|
|
13
13
|
|
|
14
|
-
export type
|
|
14
|
+
export type WardPatientCardType = React.FC<WardPatient>;
|
|
15
15
|
|
|
16
16
|
// WardPatient is a patient admitted to a ward, and/or in a bed on a ward
|
|
17
17
|
export type WardPatient = {
|
|
@@ -44,10 +44,7 @@ export type WardPatient = {
|
|
|
44
44
|
|
|
45
45
|
export interface WardPatientWorkspaceProps extends DefaultWorkspaceProps {
|
|
46
46
|
wardPatient: WardPatient;
|
|
47
|
-
|
|
48
|
-
export interface MotherAndChildrenRelationships {
|
|
49
|
-
motherByChildUuid: Map<string, Patient>;
|
|
50
|
-
childrenByMotherUuid: Map<string, Array<Patient>>;
|
|
47
|
+
WardPatientHeader: React.FC<WardPatient>;
|
|
51
48
|
}
|
|
52
49
|
|
|
53
50
|
// server-side types defined in openmrs-module-bedmanagement:
|
|
@@ -70,6 +67,14 @@ export interface Bed {
|
|
|
70
67
|
status: BedStatus;
|
|
71
68
|
}
|
|
72
69
|
|
|
70
|
+
export interface BedDetail {
|
|
71
|
+
bedId: number;
|
|
72
|
+
bedNumber: number;
|
|
73
|
+
bedType: BedType;
|
|
74
|
+
physicalLocation: Location;
|
|
75
|
+
patients: Array<Patient>;
|
|
76
|
+
}
|
|
77
|
+
|
|
73
78
|
export interface BedLayout {
|
|
74
79
|
rowNumber: number;
|
|
75
80
|
columnNumber: number;
|
|
@@ -144,9 +149,6 @@ export interface InpatientAdmission {
|
|
|
144
149
|
// the current in patient request
|
|
145
150
|
currentInpatientRequest: InpatientRequest;
|
|
146
151
|
}
|
|
147
|
-
export interface WardAppContext {
|
|
148
|
-
allPatientsByPatientUuid: Map<string, Patient>;
|
|
149
|
-
}
|
|
150
152
|
|
|
151
153
|
export interface MotherAndChild {
|
|
152
154
|
mother: Patient;
|
|
@@ -228,11 +230,24 @@ export interface ObsPayload {
|
|
|
228
230
|
groupMembers?: Array<ObsPayload>;
|
|
229
231
|
}
|
|
230
232
|
|
|
231
|
-
export
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
mother: Patient;
|
|
233
|
+
export type WardPatientGroupDetails = ReturnType<typeof useWardPatientGrouping>;
|
|
234
|
+
export interface WardViewContext {
|
|
235
|
+
wardPatientGroupDetails: WardPatientGroupDetails;
|
|
236
|
+
WardPatientHeader: React.FC<WardPatient>;
|
|
236
237
|
}
|
|
237
238
|
|
|
238
|
-
export
|
|
239
|
+
export interface PatientAndAdmission {
|
|
240
|
+
patient: Patient;
|
|
241
|
+
currentAdmission: InpatientAdmission;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export interface MotherChildRelationships {
|
|
245
|
+
motherByChildUuid: Map<string, PatientAndAdmission>;
|
|
246
|
+
childrenByMotherUuid: Map<string, PatientAndAdmission[]>;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export interface MaternalWardViewContext {
|
|
250
|
+
motherChildRelationships: MotherChildRelationships;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export type PatientWorkspaceAdditionalProps = Omit<WardPatientWorkspaceProps, keyof DefaultWorkspaceProps>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type ObsElementConfig } from '../../config-schema';
|
|
3
|
+
import { type WardPatient } from '../../types';
|
|
4
|
+
import { useElementConfig } from '../../ward-view/ward-view.resource';
|
|
5
|
+
import WardPatientObs from '../row-elements/ward-patient-obs';
|
|
6
|
+
import styles from '../ward-patient-card.scss';
|
|
7
|
+
|
|
8
|
+
interface AdmissionRequestNoteRowProps {
|
|
9
|
+
wardPatient: WardPatient;
|
|
10
|
+
id: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const AdmissionRequestNoteRow: React.FC<AdmissionRequestNoteRowProps> = ({ id, wardPatient }) => {
|
|
14
|
+
const { patient, visit, inpatientAdmission } = wardPatient;
|
|
15
|
+
const { conceptUuid } = useElementConfig('admissionRequestNote', id) ?? {};
|
|
16
|
+
const config: ObsElementConfig = {
|
|
17
|
+
conceptUuid,
|
|
18
|
+
limit: 0,
|
|
19
|
+
id: 'admission-note',
|
|
20
|
+
onlyWithinCurrentVisit: true,
|
|
21
|
+
orderBy: 'ascending',
|
|
22
|
+
label: 'Admission Note',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// only show if the patient has not been admitted yet
|
|
26
|
+
const admitted = inpatientAdmission != null;
|
|
27
|
+
if (admitted) {
|
|
28
|
+
return null;
|
|
29
|
+
} else {
|
|
30
|
+
return (
|
|
31
|
+
<div className={styles.wardPatientCardRow}>
|
|
32
|
+
<WardPatientObs id={id} configOverride={config} patient={patient} visit={visit} />
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default AdmissionRequestNoteRow;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { Tag } from '@carbon/react';
|
|
2
|
+
import { type OpenmrsResource, type Patient, type Visit } from '@openmrs/esm-framework';
|
|
3
|
+
import React, { type ReactNode } from 'react';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
|
+
import { useObs } from '../../hooks/useObs';
|
|
6
|
+
import { useElementConfig } from '../../ward-view/ward-view.resource';
|
|
7
|
+
import styles from '../ward-patient-card.scss';
|
|
8
|
+
import WardPatientSkeletonText from '../row-elements/ward-patient-skeleton-text';
|
|
9
|
+
import {
|
|
10
|
+
getObsEncounterString,
|
|
11
|
+
obsCustomRepresentation,
|
|
12
|
+
useConceptToTagColorMap,
|
|
13
|
+
} from '../row-elements/ward-patient-obs.resource';
|
|
14
|
+
import WardPatientResponsiveTooltip from '../row-elements/ward-patient-responsive-tooltip';
|
|
15
|
+
|
|
16
|
+
interface WardPatientCodedObsTagsRowProps {
|
|
17
|
+
id: string;
|
|
18
|
+
patient: Patient;
|
|
19
|
+
visit: Visit;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The WardPatientCodedObsTags displays observations of coded values of a particular concept in the active visit as tags.
|
|
24
|
+
* Typically, these are taken from checkbox fields from a form. Each answer value can either be configured
|
|
25
|
+
* to show as its own tag, or collapsed into a summary tag show the number of these values present.
|
|
26
|
+
*
|
|
27
|
+
* This is a rather specialized element;
|
|
28
|
+
* for a more general display of obs value, use WardPatientObs instead.
|
|
29
|
+
* @param config
|
|
30
|
+
* @returns
|
|
31
|
+
*/
|
|
32
|
+
const CodedObsTagsRow: React.FC<WardPatientCodedObsTagsRowProps> = ({ id, patient, visit }) => {
|
|
33
|
+
const config = useElementConfig('coloredObsTags', id);
|
|
34
|
+
const { conceptUuid, summaryLabel, summaryLabelColor } = config ?? {};
|
|
35
|
+
const { data, isLoading } = useObs(
|
|
36
|
+
{ patient: patient.uuid, concept: conceptUuid },
|
|
37
|
+
conceptUuid != null,
|
|
38
|
+
obsCustomRepresentation,
|
|
39
|
+
);
|
|
40
|
+
const { t } = useTranslation();
|
|
41
|
+
const conceptToTagColorMap = useConceptToTagColorMap(config?.tags ?? []);
|
|
42
|
+
|
|
43
|
+
if (isLoading) {
|
|
44
|
+
return (
|
|
45
|
+
<div className={styles.wardPatientCardRow}>
|
|
46
|
+
<WardPatientSkeletonText />
|
|
47
|
+
</div>
|
|
48
|
+
);
|
|
49
|
+
} else {
|
|
50
|
+
const obsToDisplay = data?.filter((o) => {
|
|
51
|
+
const matchVisit = o.encounter.visit?.uuid == visit?.uuid;
|
|
52
|
+
return matchVisit;
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const summaryLabelToDisplay = summaryLabel != null ? t(summaryLabel) : obsToDisplay?.[0]?.concept?.display;
|
|
56
|
+
|
|
57
|
+
// for each obs configured to be displayed with a color, we create a tag for it
|
|
58
|
+
// for other obs not configured, we create a single summary tag for all of them.
|
|
59
|
+
const summaryTagTooltipText: ReactNode[] = [];
|
|
60
|
+
const coloredOpsTags = obsToDisplay
|
|
61
|
+
?.map((o) => {
|
|
62
|
+
const { display, uuid } = o.value as OpenmrsResource;
|
|
63
|
+
|
|
64
|
+
const color = conceptToTagColorMap?.get(uuid);
|
|
65
|
+
if (color) {
|
|
66
|
+
return (
|
|
67
|
+
<WardPatientResponsiveTooltip tooltipContent={getObsEncounterString(o, t)}>
|
|
68
|
+
<Tag type={color} key={`ward-coded-obs-tag-${o.uuid}`}>
|
|
69
|
+
{display}
|
|
70
|
+
</Tag>
|
|
71
|
+
</WardPatientResponsiveTooltip>
|
|
72
|
+
);
|
|
73
|
+
} else {
|
|
74
|
+
summaryTagTooltipText.push(
|
|
75
|
+
<div key={uuid}>
|
|
76
|
+
{display} ({getObsEncounterString(o, t)})
|
|
77
|
+
</div>,
|
|
78
|
+
);
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
.filter((o) => o != null);
|
|
83
|
+
|
|
84
|
+
if (coloredOpsTags?.length > 0 || summaryTagTooltipText.length > 0) {
|
|
85
|
+
return (
|
|
86
|
+
<div className={styles.wardPatientCardRow}>
|
|
87
|
+
<span className={styles.wardPatientObsLabel}>
|
|
88
|
+
{coloredOpsTags}
|
|
89
|
+
{summaryTagTooltipText.length > 0 ? (
|
|
90
|
+
<WardPatientResponsiveTooltip tooltipContent={summaryTagTooltipText}>
|
|
91
|
+
<Tag type={summaryLabelColor}>
|
|
92
|
+
{t('countItems', '{{count}} {{item}}', {
|
|
93
|
+
count: summaryTagTooltipText.length,
|
|
94
|
+
item: summaryLabelToDisplay,
|
|
95
|
+
})}
|
|
96
|
+
</Tag>
|
|
97
|
+
</WardPatientResponsiveTooltip>
|
|
98
|
+
) : null}
|
|
99
|
+
</span>
|
|
100
|
+
</div>
|
|
101
|
+
);
|
|
102
|
+
} else {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export default CodedObsTagsRow;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { BabyIcon, MotherIcon, type Patient, useAppContext } from '@openmrs/esm-framework';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { type InpatientAdmission, type MaternalWardViewContext } from '../../types';
|
|
5
|
+
import { type MaternalWardPatientCardProps } from '../../ward-view/materal-ward/maternal-ward-patient-card.component';
|
|
6
|
+
import WardPatientAge from '../row-elements/ward-patient-age';
|
|
7
|
+
import WardPatientIdentifier from '../row-elements/ward-patient-identifier';
|
|
8
|
+
import WardPatientLocation from '../row-elements/ward-patient-location';
|
|
9
|
+
import WardPatientName from '../row-elements/ward-patient-name';
|
|
10
|
+
import wardPatientCardStyles from '../ward-patient-card.scss';
|
|
11
|
+
import styles from './mother-child-row.scss';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* This component displays the mother or children of the patient in the patient card. The patient's child is
|
|
15
|
+
* not displayed if it is in the same bed as the patient
|
|
16
|
+
*
|
|
17
|
+
* @param param0
|
|
18
|
+
* @returns
|
|
19
|
+
*/
|
|
20
|
+
const MotherChildRow: React.FC<MaternalWardPatientCardProps> = ({ wardPatient, childrenOfWardPatientInSameBed }) => {
|
|
21
|
+
const { patient } = wardPatient;
|
|
22
|
+
|
|
23
|
+
const { motherChildRelationships } = useAppContext<MaternalWardViewContext>('maternal-ward-view-context') ?? {};
|
|
24
|
+
|
|
25
|
+
const { childrenByMotherUuid, motherByChildUuid } = motherChildRelationships ?? {};
|
|
26
|
+
|
|
27
|
+
const motherOfPatient = motherByChildUuid?.get(patient.uuid);
|
|
28
|
+
const childrenOfPatient = childrenByMotherUuid?.get(patient.uuid);
|
|
29
|
+
const childrenOfPatientNotInSameBed = childrenOfPatient?.filter((child) => {
|
|
30
|
+
return !childrenOfWardPatientInSameBed?.some((childInSameBed) => childInSameBed.patient.uuid == child.patient.uuid);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<>
|
|
35
|
+
{motherOfPatient && (
|
|
36
|
+
<MotherOrChild
|
|
37
|
+
otherPatient={motherOfPatient.patient}
|
|
38
|
+
otherPatientAdmission={motherOfPatient.currentAdmission}
|
|
39
|
+
isOtherPatientTheMother={true}
|
|
40
|
+
/>
|
|
41
|
+
)}
|
|
42
|
+
{childrenOfPatientNotInSameBed?.map((childOfPatient) => (
|
|
43
|
+
<MotherOrChild
|
|
44
|
+
key={childOfPatient.patient.uuid}
|
|
45
|
+
otherPatient={childOfPatient.patient}
|
|
46
|
+
otherPatientAdmission={childOfPatient.currentAdmission}
|
|
47
|
+
isOtherPatientTheMother={false}
|
|
48
|
+
/>
|
|
49
|
+
))}
|
|
50
|
+
</>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
interface MotherOrChildProp {
|
|
55
|
+
otherPatient: Patient;
|
|
56
|
+
otherPatientAdmission: InpatientAdmission;
|
|
57
|
+
isOtherPatientTheMother: boolean;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const MotherOrChild: React.FC<MotherOrChildProp> = ({
|
|
61
|
+
otherPatient,
|
|
62
|
+
otherPatientAdmission,
|
|
63
|
+
isOtherPatientTheMother,
|
|
64
|
+
}) => {
|
|
65
|
+
const Icon = isOtherPatientTheMother ? MotherIcon : BabyIcon;
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<div
|
|
69
|
+
key={otherPatient.uuid}
|
|
70
|
+
className={classNames(styles.motherOrBabyRow, wardPatientCardStyles.wardPatientCardRow)}>
|
|
71
|
+
<div className={styles.motherOrBabyIconDiv}>
|
|
72
|
+
<Icon className={styles.motherOrBabyIcon} size={24} />
|
|
73
|
+
</div>
|
|
74
|
+
<div className={classNames(styles.motherOrBabyRowElementsDiv, wardPatientCardStyles.dotSeparatedChildren)}>
|
|
75
|
+
<WardPatientName patient={otherPatient} />
|
|
76
|
+
<WardPatientIdentifier id="patient-identifier" patient={otherPatient} />
|
|
77
|
+
<WardPatientAge patient={otherPatient} />
|
|
78
|
+
<WardPatientLocation inpatientAdmission={otherPatientAdmission} />
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export default MotherChildRow;
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
import React, { useCallback, useEffect } from 'react';
|
|
2
|
-
import { type WardPatientCard } from '../../types';
|
|
3
1
|
import { Hourglass } from '@carbon/react/icons';
|
|
2
|
+
import React, { useCallback, useEffect } from 'react';
|
|
3
|
+
import { type WardPatient } from '../../types';
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import type { PendingItemsDefinition } from '../../config-schema';
|
|
5
|
+
import { useElementConfig } from '../../ward-view/ward-view.resource';
|
|
7
6
|
import { WardPatientPendingOrder } from '../row-elements/ward-patient-pending-order.component';
|
|
8
|
-
import styles from '../ward-patient-card.scss';
|
|
9
7
|
import WardPatientPendingTransfer from '../row-elements/ward-patient-pending-transfer';
|
|
8
|
+
import styles from '../ward-patient-card.scss';
|
|
9
|
+
|
|
10
|
+
export interface PendingItemsRowProps {
|
|
11
|
+
id: string;
|
|
12
|
+
wardPatient: WardPatient;
|
|
13
|
+
}
|
|
10
14
|
|
|
11
|
-
const
|
|
12
|
-
const { orders, showPendingItems } =
|
|
15
|
+
const PendingItemsRow: React.FC<PendingItemsRowProps> = ({ id, wardPatient }) => {
|
|
16
|
+
const { orders, showPendingItems } = useElementConfig('pendingItems', id);
|
|
13
17
|
const [hasPendingOrders, setHasPendingOrders] = React.useState(false);
|
|
14
18
|
|
|
15
19
|
const hasPendingItems = !!wardPatient?.inpatientRequest || hasPendingOrders;
|
|
@@ -47,4 +51,4 @@ const PendingItemsCarRowExtension: WardPatientCard = (wardPatient) => {
|
|
|
47
51
|
);
|
|
48
52
|
};
|
|
49
53
|
|
|
50
|
-
export default
|
|
54
|
+
export default PendingItemsRow;
|
|
@@ -2,15 +2,15 @@ import { Tag } from '@carbon/react';
|
|
|
2
2
|
import { type OpenmrsResource, type Patient, type Visit } from '@openmrs/esm-framework';
|
|
3
3
|
import React, { type ReactNode } from 'react';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
|
-
import { type ColoredObsTagsCardRowConfigObject } from '../../config-schema-extension-colored-obs-tags';
|
|
6
5
|
import { useObs } from '../../hooks/useObs';
|
|
6
|
+
import { useElementConfig } from '../../ward-view/ward-view.resource';
|
|
7
7
|
import styles from '../ward-patient-card.scss';
|
|
8
|
-
import WardPatientSkeletonText from './ward-
|
|
8
|
+
import WardPatientSkeletonText from './ward-patient-skeleton-text';
|
|
9
9
|
import { getObsEncounterString, obsCustomRepresentation, useConceptToTagColorMap } from './ward-patient-obs.resource';
|
|
10
10
|
import WardPatientResponsiveTooltip from './ward-patient-responsive-tooltip';
|
|
11
11
|
|
|
12
12
|
interface WardPatientCodedObsTagsProps {
|
|
13
|
-
|
|
13
|
+
id: string;
|
|
14
14
|
patient: Patient;
|
|
15
15
|
visit: Visit;
|
|
16
16
|
}
|
|
@@ -25,11 +25,16 @@ interface WardPatientCodedObsTagsProps {
|
|
|
25
25
|
* @param config
|
|
26
26
|
* @returns
|
|
27
27
|
*/
|
|
28
|
-
const WardPatientCodedObsTags: React.FC<WardPatientCodedObsTagsProps> = ({
|
|
29
|
-
const
|
|
30
|
-
const {
|
|
28
|
+
const WardPatientCodedObsTags: React.FC<WardPatientCodedObsTagsProps> = ({ id, patient, visit }) => {
|
|
29
|
+
const config = useElementConfig('coloredObsTags', id);
|
|
30
|
+
const { conceptUuid, summaryLabel, summaryLabelColor } = config ?? {};
|
|
31
|
+
const { data, isLoading } = useObs(
|
|
32
|
+
{ patient: patient.uuid, concept: conceptUuid },
|
|
33
|
+
conceptUuid != null,
|
|
34
|
+
obsCustomRepresentation,
|
|
35
|
+
);
|
|
31
36
|
const { t } = useTranslation();
|
|
32
|
-
const conceptToTagColorMap = useConceptToTagColorMap(config
|
|
37
|
+
const conceptToTagColorMap = useConceptToTagColorMap(config?.tags ?? []);
|
|
33
38
|
|
|
34
39
|
if (isLoading) {
|
|
35
40
|
return (
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import styles from '../ward-patient-card.scss';
|
|
3
1
|
import { type Patient } from '@openmrs/esm-framework';
|
|
4
|
-
import
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { useElementConfig } from '../../ward-view/ward-view.resource';
|
|
5
4
|
|
|
6
5
|
export interface WardPatientAddressProps {
|
|
7
6
|
patient: Patient;
|
|
8
|
-
|
|
7
|
+
id: string;
|
|
9
8
|
}
|
|
10
9
|
|
|
11
|
-
const WardPatientAddress: React.FC<WardPatientAddressProps> = ({ patient,
|
|
10
|
+
const WardPatientAddress: React.FC<WardPatientAddressProps> = ({ patient, id }) => {
|
|
12
11
|
const preferredAddress = patient?.person?.preferredAddress;
|
|
12
|
+
const config = useElementConfig("patientAddress", id);
|
|
13
13
|
|
|
14
14
|
return (
|
|
15
15
|
<>
|
|
@@ -1,51 +1,29 @@
|
|
|
1
|
+
import { type Patient, type PatientIdentifier, PatientBannerPatientIdentifier } from '@openmrs/esm-framework';
|
|
1
2
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { Tag } from '@carbon/react';
|
|
4
|
-
import { type Patient, translateFrom, type PatientIdentifier } from '@openmrs/esm-framework';
|
|
5
|
-
import { moduleName } from '../../constant';
|
|
6
|
-
import { useTranslation } from 'react-i18next';
|
|
7
|
-
|
|
8
|
-
/** Sort the identifiers by preferred first. The identifier with value of true
|
|
9
|
-
* takes precedence over false. If both identifiers have same preferred value,
|
|
10
|
-
* sort them by most recently created or changed. */
|
|
11
|
-
const identifierCompareFunction = (pi1: PatientIdentifier, pi2: PatientIdentifier) => {
|
|
12
|
-
let comp = (pi2.preferred ? 1 : 0) - (pi1.preferred ? 1 : 0);
|
|
13
|
-
|
|
14
|
-
if (comp == 0) {
|
|
15
|
-
const date1 = pi1.auditInfo.dateChanged ?? pi1.auditInfo.dateCreated;
|
|
16
|
-
const date2 = pi2.auditInfo.dateChanged ?? pi2.auditInfo.dateCreated;
|
|
17
|
-
comp = date2.localeCompare(date1);
|
|
18
|
-
}
|
|
19
|
-
return comp;
|
|
20
|
-
};
|
|
3
|
+
import { useElementConfig } from '../../ward-view/ward-view.resource';
|
|
21
4
|
|
|
22
5
|
export interface WardPatientIdentifierProps {
|
|
23
6
|
patient: Patient;
|
|
24
|
-
|
|
25
|
-
config?: IdentifierElementDefinition;
|
|
7
|
+
id?: string;
|
|
26
8
|
}
|
|
27
9
|
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
10
|
+
const WardPatientIdentifier: React.FC<WardPatientIdentifierProps> = ({ id, patient }) => {
|
|
11
|
+
const config = useElementConfig('patientIdentifier', id);
|
|
12
|
+
|
|
13
|
+
const fhirIdentifiers: fhir.Identifier[] = patient.identifiers.map((identifier: PatientIdentifier) => ({
|
|
14
|
+
value: identifier.identifier,
|
|
15
|
+
type: {
|
|
16
|
+
text: identifier.identifierType.name,
|
|
17
|
+
coding: [
|
|
18
|
+
{
|
|
19
|
+
code: identifier.identifierType.uuid,
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
}));
|
|
32
24
|
|
|
33
|
-
const WardPatientIdentifier: React.FC<WardPatientIdentifierProps> = ({ config: configProp, patient }) => {
|
|
34
|
-
const { t } = useTranslation();
|
|
35
|
-
const config = configProp ?? defaultConfig;
|
|
36
|
-
const { identifierTypeUuid, label } = config;
|
|
37
|
-
const patientIdentifiers = patient.identifiers.filter(
|
|
38
|
-
(patientIdentifier: PatientIdentifier) =>
|
|
39
|
-
identifierTypeUuid == null || patientIdentifier.identifierType?.uuid === identifierTypeUuid,
|
|
40
|
-
);
|
|
41
|
-
patientIdentifiers.sort(identifierCompareFunction);
|
|
42
|
-
const patientIdentifier = patientIdentifiers[0];
|
|
43
|
-
const labelToDisplay = label != null ? t(label) : patientIdentifier?.identifierType?.name;
|
|
44
25
|
return (
|
|
45
|
-
<
|
|
46
|
-
{labelToDisplay ? <Tag>{t('identifierTypelabel', '{{label}}:', { label: labelToDisplay })}</Tag> : <></>}
|
|
47
|
-
<span>{patientIdentifier?.identifier}</span>
|
|
48
|
-
</div>
|
|
26
|
+
<PatientBannerPatientIdentifier identifier={fhirIdentifiers} showIdentifierLabel={config?.showIdentifierLabel} />
|
|
49
27
|
);
|
|
50
28
|
};
|
|
51
29
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { restBaseUrl, useOpenmrsFetchAll, type Concept } from '@openmrs/esm-framework';
|
|
2
|
-
import { type TagConfigObject } from '../../config-schema-extension-colored-obs-tags';
|
|
3
2
|
import { type Observation } from '../../types';
|
|
4
3
|
import { type TFunction } from 'i18next';
|
|
4
|
+
import { type ColoredObsTagConfig } from '../../config-schema';
|
|
5
5
|
|
|
6
6
|
// prettier-ignore
|
|
7
7
|
export const obsCustomRepresentation =
|
|
@@ -13,7 +13,7 @@ export const obsCustomRepresentation =
|
|
|
13
13
|
// get the setMembers of a concept set
|
|
14
14
|
const conceptSetCustomRepresentation = 'custom:(uuid,setMembers:(uuid))';
|
|
15
15
|
|
|
16
|
-
export function useConceptToTagColorMap(tags: Array<
|
|
16
|
+
export function useConceptToTagColorMap(tags: Array<ColoredObsTagConfig> = []) {
|
|
17
17
|
// The TacConfigObject allows us to specify the mapping of
|
|
18
18
|
// concept sets to colors. However, we also need to build a map of
|
|
19
19
|
// concepts to colors. This function does that.
|
|
@@ -1,23 +1,30 @@
|
|
|
1
|
-
import { SkeletonText
|
|
2
|
-
import { Information } from '@carbon/react/icons';
|
|
1
|
+
import { SkeletonText } from '@carbon/react';
|
|
3
2
|
import { type OpenmrsResource, type Patient, type Visit } from '@openmrs/esm-framework';
|
|
4
3
|
import React from 'react';
|
|
5
4
|
import { useTranslation } from 'react-i18next';
|
|
6
|
-
import { type
|
|
5
|
+
import { type ObsElementConfig } from '../../config-schema';
|
|
7
6
|
import { useObs } from '../../hooks/useObs';
|
|
8
7
|
import styles from '../ward-patient-card.scss';
|
|
9
8
|
import { getObsEncounterString, obsCustomRepresentation } from './ward-patient-obs.resource';
|
|
10
9
|
import WardPatientResponsiveTooltip from './ward-patient-responsive-tooltip';
|
|
10
|
+
import { useElementConfig } from '../../ward-view/ward-view.resource';
|
|
11
11
|
|
|
12
12
|
export interface WardPatientObsProps {
|
|
13
|
-
|
|
13
|
+
id: string;
|
|
14
|
+
configOverride?: ObsElementConfig;
|
|
14
15
|
patient: Patient;
|
|
15
16
|
visit: Visit;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
const WardPatientObs: React.FC<WardPatientObsProps> = ({
|
|
19
|
-
const
|
|
20
|
-
const
|
|
19
|
+
const WardPatientObs: React.FC<WardPatientObsProps> = ({ id, configOverride, patient, visit }) => {
|
|
20
|
+
const config: ObsElementConfig = useElementConfig('obs', id);
|
|
21
|
+
const configToUse = configOverride ?? config;
|
|
22
|
+
const { conceptUuid, onlyWithinCurrentVisit, orderBy, limit, label } = configToUse ?? {};
|
|
23
|
+
const { data, isLoading } = useObs(
|
|
24
|
+
{ patient: patient.uuid, concept: conceptUuid },
|
|
25
|
+
conceptUuid != null,
|
|
26
|
+
obsCustomRepresentation,
|
|
27
|
+
);
|
|
21
28
|
const { t } = useTranslation();
|
|
22
29
|
|
|
23
30
|
if (isLoading) {
|
|
@@ -53,7 +60,7 @@ const WardPatientObs: React.FC<WardPatientObsProps> = ({ config, patient, visit
|
|
|
53
60
|
<span className={styles.wardPatientObsLabel}>
|
|
54
61
|
{labelToDisplay ? t('labelColon', '{{label}}:', { label: labelToDisplay }) : ''}
|
|
55
62
|
</span>
|
|
56
|
-
{obsNodes}
|
|
63
|
+
<div className={styles.dotSeparatedChildren}>{obsNodes}</div>
|
|
57
64
|
</div>
|
|
58
65
|
);
|
|
59
66
|
} else {
|