@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
package/dist/routes.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"webservices.rest":"^2.2.0","emrapi":"^2.0.0 || 2.0.0-SNAPSHOT"},"optionalBackendDependencies":{"bedmanagement":{"version":"^6.0.0 || 6.0.0-SNAPSHOT","feature":{"flagName":"bedmanagement-module","label":"Ward App Patient Service","description":"This module, if installed, provides services for managing patients admitted to the ward."}}},"extensions":[{"name":"ward-dashboard-link","component":"wardDashboardLink","slot":"homepage-dashboard-slot","meta":{"name":"ward","slot":"ward-dashboard-slot","title":"Wards"}},{"component":"root","name":"ward-dashboard","slot":"ward-dashboard-slot"},{"component":"wardPatientActionButtonExtension","name":"ward-patient-action-button","slot":"action-menu-ward-patient-items-slot"},{"component":"wardPatientNotesActionButtonExtension","name":"ward-inpatient-notes-form-action-button","slot":"action-menu-ward-patient-items-slot"},{"component":"coloredObsTagCardRowExtension","name":"colored-obs-tags-card-row","slot":"ward-patient-card-slot"},{"name":"transfer-swap-patient-siderail-button","slot":"action-menu-ward-patient-items-slot","component":"patientTransferAndSwapWorkspaceSiderailIcon"},{"name":"patient-discharge-siderail-button","slot":"action-menu-ward-patient-items-slot","component":"patientDischargeWorkspaceSideRailIcon"},{"name":"clinical-forms-workspace-siderail-button","component":"clinicalFormWorkspaceSideRailIcon","slot":"action-menu-ward-patient-items-slot"},{"component":"
|
|
1
|
+
{"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"webservices.rest":"^2.2.0","emrapi":"^2.0.0 || 2.0.0-SNAPSHOT"},"optionalBackendDependencies":{"bedmanagement":{"version":"^6.0.0 || 6.0.0-SNAPSHOT","feature":{"flagName":"bedmanagement-module","label":"Ward App Patient Service","description":"This module, if installed, provides services for managing patients admitted to the ward."}}},"extensions":[{"name":"ward-dashboard-link","component":"wardDashboardLink","slot":"homepage-dashboard-slot","meta":{"name":"ward","slot":"ward-dashboard-slot","title":"Wards"}},{"component":"root","name":"ward-dashboard","slot":"ward-dashboard-slot"},{"component":"wardPatientActionButtonExtension","name":"ward-patient-action-button","slot":"action-menu-ward-patient-items-slot"},{"component":"wardPatientNotesActionButtonExtension","name":"ward-inpatient-notes-form-action-button","slot":"action-menu-ward-patient-items-slot"},{"component":"coloredObsTagCardRowExtension","name":"colored-obs-tags-card-row","slot":"ward-patient-card-slot"},{"name":"transfer-swap-patient-siderail-button","slot":"action-menu-ward-patient-items-slot","component":"patientTransferAndSwapWorkspaceSiderailIcon"},{"name":"patient-discharge-siderail-button","slot":"action-menu-ward-patient-items-slot","component":"patientDischargeWorkspaceSideRailIcon"},{"name":"clinical-forms-workspace-siderail-button","component":"clinicalFormWorkspaceSideRailIcon","slot":"action-menu-ward-patient-items-slot"},{"component":"defaultWardView","name":"default-ward","slot":"default-ward"},{"component":"maternalWardView","name":"maternal-ward","slot":"maternal-ward"}],"workspaces":[{"name":"admission-requests-workspace","component":"admissionRequestWorkspace","title":"admissionRequests","type":"admission-requests"},{"name":"ward-patient-notes-workspace","component":"wardPatientNotesWorkspace","type":"ward-patient-notes","title":"inpatientNotesWorkspaceTitle","sidebarFamily":"ward-patient","hasOwnSidebar":true},{"name":"admit-patient-form-workspace","component":"admitPatientFormWorkspace","title":"admissionRequests","type":"admission-requests"},{"name":"ward-patient-workspace","component":"wardPatientWorkspace","type":"ward","title":"Ward Patient","width":"extra-wide","hasOwnSidebar":true,"sidebarFamily":"ward-patient"},{"name":"patient-transfer-swap-workspace","component":"patientTransferAndSwapWorkspace","title":"transfers","type":"transfer-swap-bed-form","hasOwnSidebar":true,"sidebarFamily":"ward-patient"},{"name":"patient-transfer-request-workspace","component":"patientTransferRequestWorkspace","title":"transferRequest","type":"transfer-request-form"},{"name":"patient-discharge-workspace","component":"patientDischargeWorkspace","title":"discharge","type":"ward-patient-discharge","hasOwnSidebar":true,"sidebarFamily":"ward-patient"},{"name":"ward-patient-clinical-forms-workspace","component":"patientClinicalFormsWorkspace","title":"clinicalForms","type":"ward-patient-clinical-forms","hasOwnSidebar":true,"sidebarFamily":"ward-patient","width":"wider"}],"version":"8.1.1-pre.121"}
|
package/mock.tsx
CHANGED
|
@@ -4,6 +4,8 @@ import { useInpatientAdmission } from './src/hooks/useInpatientAdmission';
|
|
|
4
4
|
import { createAndGetWardPatientGrouping } from './src/ward-view/ward-view.resource';
|
|
5
5
|
import { useInpatientRequest } from './src/hooks/useInpatientRequest';
|
|
6
6
|
import { useWardPatientGrouping } from './src/hooks/useWardPatientGrouping';
|
|
7
|
+
import { type WardViewContext } from './src/types';
|
|
8
|
+
import DefaultWardPatientCardHeader from './src/ward-view/default-ward/default-ward-patient-card-header.component';
|
|
7
9
|
|
|
8
10
|
jest.mock('./src/hooks/useAdmissionLocation', () => ({
|
|
9
11
|
useAdmissionLocation: jest.fn(),
|
|
@@ -51,4 +53,10 @@ export const mockWardPatientGroupDetails = jest.mocked(useWardPatientGrouping).m
|
|
|
51
53
|
inpatientAdmissionResponse: mockInpatientAdmissionResponse(),
|
|
52
54
|
inpatientRequestResponse: mockInpatientRequestResponse(),
|
|
53
55
|
...createAndGetWardPatientGrouping(mockInpatientAdmissions, mockAdmissionLocation, mockInpatientRequest),
|
|
56
|
+
isLoading: false,
|
|
54
57
|
});
|
|
58
|
+
|
|
59
|
+
export const mockWardViewContext: WardViewContext = {
|
|
60
|
+
wardPatientGroupDetails: mockWardPatientGroupDetails(),
|
|
61
|
+
WardPatientHeader: DefaultWardPatientCardHeader,
|
|
62
|
+
};
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { SkeletonIcon } from '@carbon/react';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import styles from './
|
|
4
|
-
import WardPatientSkeletonText from '../ward-patient-card/row-elements/ward-
|
|
3
|
+
import styles from './ward-bed.scss';
|
|
4
|
+
import WardPatientSkeletonText from '../ward-patient-card/row-elements/ward-patient-skeleton-text';
|
|
5
5
|
|
|
6
6
|
const EmptyBedSkeleton = () => {
|
|
7
7
|
return (
|
|
8
|
-
<div className={styles.
|
|
8
|
+
<div className={styles.emptyBed + ' ' + styles.skeleton}>
|
|
9
9
|
<SkeletonIcon />
|
|
10
10
|
<WardPatientSkeletonText />
|
|
11
11
|
</div>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import styles from './
|
|
2
|
+
import styles from './ward-bed.scss';
|
|
3
3
|
import wardPatientCardStyles from '../ward-patient-card/ward-patient-card.scss';
|
|
4
4
|
import { type Bed } from '../types';
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
@@ -12,11 +12,11 @@ const EmptyBed: React.FC<EmptyBedProps> = ({ bed }) => {
|
|
|
12
12
|
const { t } = useTranslation();
|
|
13
13
|
|
|
14
14
|
return (
|
|
15
|
-
<div className={styles.
|
|
15
|
+
<div className={styles.emptyBed}>
|
|
16
16
|
<span className={`${wardPatientCardStyles.wardPatientBedNumber} ${wardPatientCardStyles.empty}`}>
|
|
17
17
|
{bed.bedNumber}
|
|
18
18
|
</span>
|
|
19
|
-
<p className={styles.
|
|
19
|
+
<p className={styles.emptyBedText}>{t('emptyBed', 'Empty bed')}</p>
|
|
20
20
|
</div>
|
|
21
21
|
);
|
|
22
22
|
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React, { type ReactNode } from 'react';
|
|
2
|
+
import { type Bed } from '../types';
|
|
3
|
+
import EmptyBed from './empty-bed.component';
|
|
4
|
+
import styles from './ward-bed.scss';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
import { Tag } from '@carbon/react';
|
|
7
|
+
|
|
8
|
+
export interface WardBedProps {
|
|
9
|
+
patientCards: Array<ReactNode>;
|
|
10
|
+
bed: Bed;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const WardBed: React.FC<WardBedProps> = ({ bed, patientCards }) => {
|
|
14
|
+
return patientCards?.length > 0 ? <OccupiedBed bed={bed} patientCards={patientCards} /> : <EmptyBed bed={bed} />;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const OccupiedBed: React.FC<WardBedProps> = ({ patientCards }) => {
|
|
18
|
+
// interlace patient card with bed dividers between each of them
|
|
19
|
+
const patientCardsWithDividers = patientCards.flatMap((patientCard, index) => {
|
|
20
|
+
if (index == 0) {
|
|
21
|
+
return [patientCard];
|
|
22
|
+
} else {
|
|
23
|
+
return [<BedShareDivider key={'divider-' + index} />, patientCard];
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
return <div className={styles.occupiedBed}>{patientCardsWithDividers}</div>;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const BedShareDivider = () => {
|
|
31
|
+
const { t } = useTranslation();
|
|
32
|
+
return (
|
|
33
|
+
<div className={styles.bedDivider}>
|
|
34
|
+
<div className={styles.bedDividerLine}></div>
|
|
35
|
+
<Tag>{t('bedShare', 'Bed share')}</Tag>
|
|
36
|
+
<div className={styles.bedDividerLine}></div>
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export default WardBed;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
@use '@carbon/layout';
|
|
2
|
+
@use '@openmrs/esm-styleguide/src/vars';
|
|
3
|
+
@use '@carbon/type';
|
|
4
|
+
|
|
5
|
+
.occupiedBed {
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-direction: column;
|
|
8
|
+
background-color: vars.$ui-02;
|
|
9
|
+
height: fit-content;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.bedDivider {
|
|
13
|
+
background-color: vars.$ui-02;
|
|
14
|
+
color: vars.$text-02;
|
|
15
|
+
padding: layout.$spacing-01;
|
|
16
|
+
display: flex;
|
|
17
|
+
align-items: center;
|
|
18
|
+
justify-content: space-between;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.bedDividerLine {
|
|
22
|
+
height: 1px;
|
|
23
|
+
background-color: vars.$ui-05;
|
|
24
|
+
width: 30%;
|
|
25
|
+
}
|
|
26
|
+
.emptyBed {
|
|
27
|
+
display: flex;
|
|
28
|
+
gap: layout.$spacing-04;
|
|
29
|
+
justify-content: center;
|
|
30
|
+
align-items: center;
|
|
31
|
+
border: 1px dashed vars.$ui-04;
|
|
32
|
+
padding: layout.$spacing-03 layout.$spacing-04;
|
|
33
|
+
height: fit-content;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.emptyBed:hover:not(.skeleton) {
|
|
37
|
+
border: 1px solid transparent;
|
|
38
|
+
box-shadow: inset 0px 0px 0px 2px vars.$color-blue-60-2;
|
|
39
|
+
cursor: pointer;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.emptyBedText {
|
|
43
|
+
@include type.type-style('heading-compact-01');
|
|
44
|
+
color: vars.$text-02;
|
|
45
|
+
}
|
|
@@ -10,7 +10,9 @@ import {
|
|
|
10
10
|
} from '../../../../__mocks__';
|
|
11
11
|
import { bedLayoutToBed, filterBeds } from '../ward-view/ward-view.resource';
|
|
12
12
|
import useWardLocation from '../hooks/useWardLocation';
|
|
13
|
-
import
|
|
13
|
+
import WardBed from './ward-bed.component';
|
|
14
|
+
import { type WardPatient } from '../types';
|
|
15
|
+
import DefaultWardPatientCard from '../ward-view/default-ward/default-ward-patient-card.component';
|
|
14
16
|
|
|
15
17
|
const defaultConfig: WardConfigObject = getDefaultsFromConfigSchema(configSchema);
|
|
16
18
|
|
|
@@ -31,34 +33,43 @@ mockedUseWardLocation.mockReturnValue({
|
|
|
31
33
|
const mockBedToUse = mockBedLayouts[0];
|
|
32
34
|
const mockBed = bedLayoutToBed(mockBedToUse);
|
|
33
35
|
|
|
34
|
-
const
|
|
35
|
-
admitted: true,
|
|
36
|
+
const mockWardPatientAliceProps: WardPatient = {
|
|
36
37
|
visit: null,
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
patient: mockPatientAlice,
|
|
39
|
+
bed: mockBed,
|
|
40
|
+
inpatientAdmission: null,
|
|
41
|
+
inpatientRequest: null,
|
|
39
42
|
};
|
|
40
43
|
|
|
41
|
-
|
|
44
|
+
const mockWardPatientBrianProps: WardPatient = {
|
|
45
|
+
visit: null,
|
|
46
|
+
patient: mockPatientBrian,
|
|
47
|
+
bed: mockBed,
|
|
48
|
+
inpatientAdmission: null,
|
|
49
|
+
inpatientRequest: null,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
describe('Ward bed', () => {
|
|
42
53
|
it('renders a single bed with patient details', () => {
|
|
43
|
-
render(
|
|
54
|
+
render(
|
|
55
|
+
<WardBed
|
|
56
|
+
patientCards={[<DefaultWardPatientCard key={mockPatientAlice.uuid} {...mockWardPatientAliceProps} />]}
|
|
57
|
+
bed={mockBed}
|
|
58
|
+
/>,
|
|
59
|
+
);
|
|
44
60
|
const patientName = screen.getByText('Alice Johnson');
|
|
45
61
|
expect(patientName).toBeInTheDocument();
|
|
46
62
|
const patientAge = `${mockPatientAlice.person.age} yrs`;
|
|
47
63
|
expect(screen.getByText(patientAge)).toBeInTheDocument();
|
|
48
|
-
const defaultAddressFields = ['cityVillage', 'country'];
|
|
49
|
-
defaultAddressFields.forEach((addressField) => {
|
|
50
|
-
const addressFieldValue = mockPatientAlice.person.preferredAddress[addressField] as string;
|
|
51
|
-
expect(screen.getByText(addressFieldValue)).toBeInTheDocument();
|
|
52
|
-
});
|
|
53
64
|
});
|
|
54
65
|
|
|
55
66
|
it('renders a divider for shared patients', () => {
|
|
56
67
|
render(
|
|
57
|
-
<
|
|
68
|
+
<WardBed
|
|
58
69
|
bed={mockBed}
|
|
59
|
-
|
|
60
|
-
{ ...
|
|
61
|
-
{ ...
|
|
70
|
+
patientCards={[
|
|
71
|
+
<DefaultWardPatientCard key={mockPatientAlice.uuid} {...mockWardPatientAliceProps} />,
|
|
72
|
+
<DefaultWardPatientCard key={mockPatientBrian.uuid} {...mockWardPatientBrianProps} />,
|
|
62
73
|
]}
|
|
63
74
|
/>,
|
|
64
75
|
);
|
package/src/config-schema.ts
CHANGED
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
import { type ConfigSchema, Type, validators } from '@openmrs/esm-framework';
|
|
2
2
|
|
|
3
|
-
export const defaultWardPatientCard: WardPatientCardDefinition = {
|
|
4
|
-
id: 'default',
|
|
5
|
-
headerRowElements: ['patient-age', 'patient-address', 'patient-identifier'],
|
|
6
|
-
footerRowElements: [],
|
|
7
|
-
appliedTo: null,
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export const builtInPatientCardElements = ['patient-age', 'time-on-ward', 'time-since-admission', 'patient-location'];
|
|
11
|
-
|
|
12
3
|
export const addressFields = [
|
|
13
4
|
'cityVillage',
|
|
14
5
|
'stateProvince',
|
|
@@ -37,11 +28,12 @@ export const addressFields = [
|
|
|
37
28
|
type AddressField = keyof typeof addressFields;
|
|
38
29
|
|
|
39
30
|
export const configSchema: ConfigSchema = {
|
|
40
|
-
|
|
41
|
-
_description:
|
|
42
|
-
|
|
31
|
+
patientCardElements: {
|
|
32
|
+
_description:
|
|
33
|
+
'Configuration of various patient card elements. Each configured element must have a unique id, defined in the ward React component being used.',
|
|
34
|
+
obs: {
|
|
43
35
|
_type: Type.Array,
|
|
44
|
-
_description: '
|
|
36
|
+
_description: 'Configures obs values to display.',
|
|
45
37
|
_default: [],
|
|
46
38
|
_elements: {
|
|
47
39
|
id: {
|
|
@@ -79,12 +71,16 @@ export const configSchema: ConfigSchema = {
|
|
|
79
71
|
},
|
|
80
72
|
},
|
|
81
73
|
},
|
|
82
|
-
|
|
74
|
+
pendingItems: {
|
|
83
75
|
_type: Type.Array,
|
|
84
|
-
_description:
|
|
76
|
+
_description: 'Configures pending orders and transfers to display.',
|
|
85
77
|
_default: [
|
|
86
78
|
{
|
|
87
|
-
id: '
|
|
79
|
+
id: 'pending-items',
|
|
80
|
+
orders: {
|
|
81
|
+
orderTypes: [{ label: 'Labs', uuid: '52a447d3-a64a-11e3-9aeb-50e549534c5e' }],
|
|
82
|
+
},
|
|
83
|
+
showPendingItems: true,
|
|
88
84
|
},
|
|
89
85
|
],
|
|
90
86
|
_elements: {
|
|
@@ -92,23 +88,55 @@ export const configSchema: ConfigSchema = {
|
|
|
92
88
|
_type: Type.String,
|
|
93
89
|
_description: 'The unique identifier for this patient card element',
|
|
94
90
|
},
|
|
95
|
-
|
|
96
|
-
|
|
91
|
+
orders: {
|
|
92
|
+
orderTypes: {
|
|
93
|
+
_type: Type.Array,
|
|
94
|
+
_description: 'Configures pending orders and transfers to display.',
|
|
95
|
+
_elements: {
|
|
96
|
+
uuid: {
|
|
97
|
+
_type: Type.UUID,
|
|
98
|
+
_description: 'Identifies the order type.',
|
|
99
|
+
},
|
|
100
|
+
label: {
|
|
101
|
+
_type: Type.String,
|
|
102
|
+
_description:
|
|
103
|
+
"The label or i18n key to the translated label to display. If not provided, defaults to 'Orders'",
|
|
104
|
+
_default: null,
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
showPendingItems: {
|
|
110
|
+
_type: Type.Boolean,
|
|
97
111
|
_description:
|
|
98
|
-
'
|
|
99
|
-
_default: null,
|
|
112
|
+
'Optional. If true, pending items (e.g., number of pending orders) will be displayed on the patient card.',
|
|
100
113
|
},
|
|
101
|
-
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
patientIdentifier: {
|
|
117
|
+
_type: Type.Array,
|
|
118
|
+
_description: `Configures patient identifier to display. An unconfigured element displays the preferred identifier.`,
|
|
119
|
+
_default: [
|
|
120
|
+
{
|
|
121
|
+
id: 'patient-identifier',
|
|
122
|
+
showIdentifierLabel: false,
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
_elements: {
|
|
126
|
+
id: {
|
|
102
127
|
_type: Type.String,
|
|
128
|
+
_description: 'The unique identifier for this patient card element',
|
|
129
|
+
},
|
|
130
|
+
showIdentifierLabel: {
|
|
131
|
+
_type: Type.Boolean,
|
|
103
132
|
_description:
|
|
104
|
-
'
|
|
105
|
-
_default: null,
|
|
133
|
+
'If true, the identifier type (eg: "OpenMRS ID") is shown along with the identifier itself. Defaults to false',
|
|
106
134
|
},
|
|
107
135
|
},
|
|
108
136
|
},
|
|
109
|
-
|
|
137
|
+
patientAddress: {
|
|
110
138
|
_type: Type.Array,
|
|
111
|
-
_description: '
|
|
139
|
+
_description: 'Configures patient address elements.',
|
|
112
140
|
_default: [
|
|
113
141
|
{
|
|
114
142
|
id: 'patient-address',
|
|
@@ -132,66 +160,116 @@ export const configSchema: ConfigSchema = {
|
|
|
132
160
|
},
|
|
133
161
|
},
|
|
134
162
|
},
|
|
135
|
-
|
|
163
|
+
admissionRequestNote: {
|
|
136
164
|
_type: Type.Array,
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
165
|
+
_description: 'Configures admission request notes to display.',
|
|
166
|
+
_default: [
|
|
167
|
+
{
|
|
168
|
+
id: 'admission-request-note',
|
|
169
|
+
conceptUuid: '161011AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
|
170
|
+
},
|
|
171
|
+
],
|
|
140
172
|
_elements: {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
_description:
|
|
144
|
-
'The unique identifier for this card definition. This is used to set the name of the extension slot the card has, where the rows go. The slot name is "ward-patient-card-<id>", unless the id is "default", in which case the slot name is "ward-patient-card".',
|
|
145
|
-
_default: 'default',
|
|
146
|
-
},
|
|
147
|
-
headerRowElements: {
|
|
148
|
-
_type: Type.Array,
|
|
149
|
-
_description: `IDs of patient card elements to appear in the header row. These can be built-in, or custom ones can be defined in patientCardElementDefinitions. Built-in elements are: '${builtInPatientCardElements.join(
|
|
150
|
-
"', '",
|
|
151
|
-
)}'.`,
|
|
152
|
-
_elements: {
|
|
173
|
+
fields: {
|
|
174
|
+
id: {
|
|
153
175
|
_type: Type.String,
|
|
176
|
+
_description: 'The unique identifier for this patient card element',
|
|
177
|
+
},
|
|
178
|
+
conceptUuid: {
|
|
179
|
+
_type: Type.UUID,
|
|
180
|
+
_description: 'Required. Identifies the concept for the admission request note.',
|
|
154
181
|
},
|
|
155
182
|
},
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
183
|
+
},
|
|
184
|
+
coloredObsTags: {
|
|
185
|
+
_type: Type.Array,
|
|
186
|
+
_description: 'Configures observation values to display as Carbon tags.',
|
|
187
|
+
_elements: {
|
|
188
|
+
conceptUuid: {
|
|
189
|
+
_type: Type.UUID,
|
|
190
|
+
_description: 'Required. Identifies the concept to use to identify the desired observations.',
|
|
191
|
+
// Problem list
|
|
192
|
+
_default: '1284AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
|
193
|
+
},
|
|
194
|
+
summaryLabel: {
|
|
162
195
|
_type: Type.String,
|
|
196
|
+
_description: `Optional. The custom label or i18n key to the translated label to display for the summary tag. The summary tag shows the count of the number of answers that are present but not configured to show as their own tags. If not provided, defaults to the name of the concept.`,
|
|
197
|
+
_default: null,
|
|
163
198
|
},
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
199
|
+
summaryLabelI18nModule: {
|
|
200
|
+
_type: Type.String,
|
|
201
|
+
_description: 'Optional. The custom module to use for translation of the summary label',
|
|
202
|
+
_default: null,
|
|
203
|
+
},
|
|
204
|
+
summaryLabelColor: {
|
|
205
|
+
_type: Type.String,
|
|
206
|
+
_description:
|
|
207
|
+
'The color of the summary tag. See https://react.carbondesignsystem.com/?path=/docs/components-tag--overview for a list of supported colors',
|
|
208
|
+
_default: null,
|
|
209
|
+
},
|
|
210
|
+
tags: {
|
|
211
|
+
_type: Type.Array,
|
|
212
|
+
_description: `An array specifying concept sets and color. Observations with coded values that are members of the specified concept sets will be displayed as their own tags with the specified color. Any observation with coded values not belonging to any concept sets specified will be summarized as a count in the summary tag. If a concept set is listed multiple times, the first matching applied-to rule takes precedence.`,
|
|
213
|
+
_default: [],
|
|
214
|
+
_elements: {
|
|
215
|
+
color: {
|
|
216
|
+
_type: Type.String,
|
|
217
|
+
_description:
|
|
218
|
+
'Color of the tag. See https://react.carbondesignsystem.com/?path=/docs/components-tag--overview for a list of supported colors.',
|
|
219
|
+
},
|
|
220
|
+
appliedToConceptSets: {
|
|
221
|
+
_type: Type.Array,
|
|
222
|
+
_description: `The concept sets which the color applies to. Observations with coded values that are members of the specified concept sets will be displayed as their own tag with the specified color. If an observation's coded value belongs to multiple concept sets, the first matching applied-to rule takes precedence.`,
|
|
223
|
+
_elements: {
|
|
224
|
+
_type: Type.UUID,
|
|
225
|
+
},
|
|
226
|
+
},
|
|
174
227
|
},
|
|
175
228
|
},
|
|
176
229
|
},
|
|
177
230
|
},
|
|
178
231
|
},
|
|
179
232
|
},
|
|
233
|
+
wards: {
|
|
234
|
+
_description: 'Configuration of what type of ward to use at different ward locations.',
|
|
235
|
+
_type: Type.Array,
|
|
236
|
+
_default: [{ id: 'default-ward' }],
|
|
237
|
+
_elements: {
|
|
238
|
+
id: {
|
|
239
|
+
_type: Type.String,
|
|
240
|
+
_description:
|
|
241
|
+
'The ward type to use. Currently, "default-ward" and "maternal-ward" are supported. This string also serves as the extension slot name for the ward view.',
|
|
242
|
+
},
|
|
243
|
+
appliedTo: {
|
|
244
|
+
_type: Type.Array,
|
|
245
|
+
_description:
|
|
246
|
+
'Optional. Conditions under which this card definition should be used. If not provided, the configuration is applied to all wards.',
|
|
247
|
+
_elements: {
|
|
248
|
+
location: {
|
|
249
|
+
_type: Type.UUID,
|
|
250
|
+
_description: 'The UUID of the location. If not provided, applies to all wards.',
|
|
251
|
+
_default: null,
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
},
|
|
180
257
|
};
|
|
181
258
|
|
|
182
259
|
export interface WardConfigObject {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
260
|
+
patientCardElements: {
|
|
261
|
+
obs: Array<ObsElementConfig>;
|
|
262
|
+
pendingItems: Array<PendingItemsElementConfig>;
|
|
263
|
+
patientIdentifier: Array<IdentifierElementConfig>;
|
|
264
|
+
patientAddress: Array<PatientAddressElementConfig>;
|
|
265
|
+
coloredObsTags: Array<ColoredObsTagsElementConfig>;
|
|
266
|
+
admissionRequestNote: Array<AdmissionRequestNoteElementConfig>;
|
|
267
|
+
};
|
|
268
|
+
wards: Array<WardDefinition>;
|
|
192
269
|
}
|
|
193
270
|
|
|
194
|
-
export interface
|
|
271
|
+
export interface PendingItemsElementConfig {
|
|
272
|
+
id: string;
|
|
195
273
|
showPendingItems: boolean;
|
|
196
274
|
orders: {
|
|
197
275
|
orderTypes: Array<{
|
|
@@ -201,7 +279,7 @@ export interface PendingItemsDefinition {
|
|
|
201
279
|
};
|
|
202
280
|
}
|
|
203
281
|
|
|
204
|
-
export interface
|
|
282
|
+
export interface ObsElementConfig {
|
|
205
283
|
id: string;
|
|
206
284
|
conceptUuid: string;
|
|
207
285
|
onlyWithinCurrentVisit: boolean;
|
|
@@ -210,21 +288,23 @@ export interface ObsElementDefinition {
|
|
|
210
288
|
label?: string;
|
|
211
289
|
}
|
|
212
290
|
|
|
213
|
-
export interface
|
|
291
|
+
export interface IdentifierElementConfig {
|
|
214
292
|
id: string;
|
|
215
|
-
|
|
216
|
-
label?: string;
|
|
293
|
+
showIdentifierLabel: boolean;
|
|
217
294
|
}
|
|
218
295
|
|
|
219
|
-
export interface
|
|
296
|
+
export interface PatientAddressElementConfig {
|
|
220
297
|
id: string;
|
|
221
298
|
fields: Array<AddressField>;
|
|
222
299
|
}
|
|
223
300
|
|
|
224
|
-
export interface
|
|
301
|
+
export interface AdmissionRequestNoteElementConfig {
|
|
302
|
+
id: string;
|
|
303
|
+
conceptUuid: string;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
export interface WardDefinition {
|
|
225
307
|
id: string;
|
|
226
|
-
headerRowElements: Array<string>;
|
|
227
|
-
footerRowElements: Array<string>;
|
|
228
308
|
appliedTo?: Array<{
|
|
229
309
|
/**
|
|
230
310
|
* locationUuid. If given, only applies to patients at the specified ward locations. (If not provided, applies to all locations)
|
|
@@ -232,3 +312,44 @@ export interface WardPatientCardDefinition {
|
|
|
232
312
|
location: string;
|
|
233
313
|
}>;
|
|
234
314
|
}
|
|
315
|
+
export interface ColoredObsTagsElementConfig {
|
|
316
|
+
/**
|
|
317
|
+
* Required. Identifies the concept to use to identify the desired observations.
|
|
318
|
+
*/
|
|
319
|
+
conceptUuid: string;
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Optional. The custom label or i18n key to the translated label to display for the summary tag. The summary tag
|
|
323
|
+
* shows the count of the number of answers that are present but not configured to show as their own tags. If not
|
|
324
|
+
* provided, defaults to the name of the concept.
|
|
325
|
+
*/
|
|
326
|
+
summaryLabel?: string;
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* The color of the summary tag.
|
|
330
|
+
* See https://react.carbondesignsystem.com/?path=/docs/components-tag--overview for a list of supported colors
|
|
331
|
+
*/
|
|
332
|
+
summaryLabelColor?: string;
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* An array specifying concept sets and color. Observations with coded values that are members of the specified concept sets
|
|
336
|
+
* will be displayed as their own tags with the specified color. Any observation with coded values not belonging to
|
|
337
|
+
* any concept sets specified will be summarized as a count in the summary tag. If a concept set is listed multiple times,
|
|
338
|
+
* the first matching applied-to rule takes precedence.
|
|
339
|
+
*/
|
|
340
|
+
tags: Array<ColoredObsTagConfig>;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export interface ColoredObsTagConfig {
|
|
344
|
+
/**
|
|
345
|
+
* Color of the tag. See https://react.carbondesignsystem.com/?path=/docs/components-tag--overview for a list of supported colors.
|
|
346
|
+
*/
|
|
347
|
+
color: string;
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* The concept sets which the color applies to. Observations with coded values that are members of the specified concept sets
|
|
351
|
+
* will be displayed as their own tag with the specified color.
|
|
352
|
+
* If an observation's coded value belongs to multiple concept sets, the first matching applied-to rule takes precedence.
|
|
353
|
+
*/
|
|
354
|
+
appliedToConceptSets: Array<string>;
|
|
355
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
|
|
2
|
+
import { type BedDetail } from '../types';
|
|
3
|
+
import useSWR from 'swr';
|
|
4
|
+
|
|
5
|
+
export function useAssignedBedByPatient(patientUuid: string) {
|
|
6
|
+
const url = `${restBaseUrl}/beds?patientUuid=${patientUuid}`;
|
|
7
|
+
|
|
8
|
+
return useSWR<{ data: { results: Array<BedDetail> } }, Error>(url, openmrsFetch);
|
|
9
|
+
}
|
|
@@ -8,7 +8,7 @@ export function useInpatientAdmission() {
|
|
|
8
8
|
// prettier-ignore
|
|
9
9
|
const customRepresentation =
|
|
10
10
|
'custom:(visit,' +
|
|
11
|
-
'patient:(uuid,identifiers,voided,' +
|
|
11
|
+
'patient:(uuid,identifiers:(uuid,display,identifier,identifierType),voided,' +
|
|
12
12
|
'person:(uuid,display,gender,age,birthdate,birthtime,preferredName,preferredAddress,dead,deathDate)),' +
|
|
13
13
|
'encounterAssigningToCurrentInpatientLocation:(encounterDatetime),' +
|
|
14
14
|
'currentInpatientRequest:(dispositionLocation,dispositionType,disposition:(uuid,display),dispositionEncounter:(uuid,display),dispositionObsGroup:(uuid,display),visit:(uuid),patient:(uuid)),' +
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { makeUrl, restBaseUrl, useOpenmrsFetchAll } from '@openmrs/esm-framework';
|
|
2
|
-
import { type
|
|
2
|
+
import { type MotherAndChild } from '../types';
|
|
3
3
|
|
|
4
4
|
export interface MothersAndChildrenSearchCriteria {
|
|
5
5
|
mothers?: Array<string>;
|
|
@@ -38,7 +38,7 @@ export function useMotherAndChildren(
|
|
|
38
38
|
requireChildBornDuringMothersActiveVisit?.toString() ?? 'false',
|
|
39
39
|
);
|
|
40
40
|
rep && url.searchParams.append('v', rep);
|
|
41
|
-
return useOpenmrsFetchAll<
|
|
41
|
+
return useOpenmrsFetchAll<MotherAndChild>(fetch ? url : null);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
function makeUrlUrl(path: string) {
|
package/src/hooks/useObs.ts
CHANGED
|
@@ -6,12 +6,12 @@ interface ObsSearchCriteria {
|
|
|
6
6
|
concept: string;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export function useObs(criteria?: ObsSearchCriteria, representation = 'default') {
|
|
9
|
+
export function useObs(criteria?: ObsSearchCriteria, fetch: boolean = true, representation = 'default') {
|
|
10
10
|
const params = new URLSearchParams({
|
|
11
11
|
...criteria,
|
|
12
12
|
v: representation,
|
|
13
13
|
});
|
|
14
14
|
|
|
15
15
|
const apiUrl = `${restBaseUrl}/obs?${params}`;
|
|
16
|
-
return useOpenmrsFetchAll<Observation>(apiUrl);
|
|
16
|
+
return useOpenmrsFetchAll<Observation>(fetch ? apiUrl : null);
|
|
17
17
|
}
|