@ampath/esm-dha-workflow-app 4.0.0-next.4 → 4.0.0-next.41
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/dist/104.js +2 -0
- package/dist/104.js.LICENSE.txt +9 -0
- package/dist/104.js.map +1 -0
- package/dist/15.js +1 -0
- package/dist/15.js.map +1 -0
- package/dist/246.js +2 -0
- package/dist/246.js.LICENSE.txt +54 -0
- package/dist/246.js.map +1 -0
- package/dist/327.js +1 -0
- package/dist/327.js.map +1 -0
- package/dist/339.js +1 -0
- package/dist/339.js.map +1 -0
- package/dist/709.js +1 -0
- package/dist/709.js.map +1 -0
- package/dist/710.js +2 -0
- package/dist/710.js.map +1 -0
- package/dist/729.js +1 -0
- package/dist/729.js.map +1 -0
- package/dist/752.js +1 -0
- package/dist/752.js.map +1 -0
- package/dist/833.js +1 -0
- package/dist/833.js.map +1 -0
- package/dist/91.js +1 -1
- package/dist/91.js.map +1 -1
- package/dist/93.js +1 -0
- package/dist/93.js.map +1 -0
- package/dist/938.js +1 -0
- package/dist/938.js.map +1 -0
- package/dist/esm-dha-workflow-app.js +1 -0
- package/dist/{openmrs-esm-home-app.js.buildmanifest.json → esm-dha-workflow-app.js.buildmanifest.json} +294 -55
- package/dist/{openmrs-esm-home-app.js.map → esm-dha-workflow-app.js.map} +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +3 -3
- package/src/accounting/accounting.component.tsx +13 -0
- package/src/appointments/appointments.component.tsx +13 -0
- package/src/bookings/daily/daily-bookings.component.scss +38 -0
- package/src/bookings/daily/daily-bookings.component.tsx +138 -0
- package/src/bookings/daily/daily-bookings.resource.ts +27 -0
- package/src/bookings/daily/filters/daily-bookings-filter.component.scss +15 -0
- package/src/bookings/daily/filters/daily-bookings-filter.component.tsx +80 -0
- package/src/bookings/daily/patient-list/daily-bookings-patient-list.component.tsx +97 -0
- package/src/bookings/types/index.ts +68 -0
- package/src/config-schema.ts +132 -32
- package/src/dashboard/dashboard.component.scss +7 -0
- package/src/dashboard/dashboard.component.tsx +63 -0
- package/src/dashboard/overview/overview.component.scss +70 -0
- package/src/dashboard/overview/overview.component.tsx +107 -0
- package/src/dashboard/patient-list/patient-list.component.tsx +41 -0
- package/src/hooks/useActions.ts +165 -0
- package/src/index.ts +23 -2
- package/src/laboratory/laboratory.component.tsx +13 -0
- package/src/left-panel/left-panel.component.tsx +20 -0
- package/src/left-panel/left-panel.scss +42 -0
- package/src/mch/queues/consultation/mch-consultation.tsx +18 -0
- package/src/mch/queues/triage/mch-triage.tsx +15 -0
- package/src/modals/sign-off-modal.scss +7 -0
- package/src/modals/sign-off-modal.tsx +52 -0
- package/src/mortuary/mortuary.component.tsx +13 -0
- package/src/pharmacy/pharmacy.component.tsx +13 -0
- package/src/registry/client-details/client-details.tsx +40 -0
- package/src/registry/modal/client-details-modal/client-details-modal.scss +28 -0
- package/src/registry/modal/client-details-modal/client-details-modal.tsx +81 -0
- package/src/registry/modal/otp-verification-modal/otp-verification-modal.scss +31 -0
- package/src/registry/modal/otp-verification-modal/otp-verification-modal.tsx +186 -0
- package/src/registry/modal/send-to-triage/send-to-triage.modal.scss +34 -0
- package/src/registry/modal/send-to-triage/send-to-triage.modal.tsx +302 -0
- package/src/registry/payment-details/payment-options/payment-options.tsx +21 -0
- package/src/registry/registry.component.scss +83 -0
- package/src/registry/registry.component.tsx +397 -2
- package/src/registry/registry.resource.ts +60 -0
- package/src/registry/types/index.ts +309 -0
- package/src/registry/utils/error-handler.ts +37 -0
- package/src/registry/utils/format-dependant-display-data.ts +8 -0
- package/src/registry/utils/hie-adapter.ts +56 -0
- package/src/registry/utils/hie-client-adapter.ts +309 -0
- package/src/registry/utils/mask-data.ts +21 -0
- package/src/resources/hie-amrs-automatic-registration.service.ts +16 -0
- package/src/resources/identifier-types.ts +27 -0
- package/src/resources/patient-resource.ts +62 -0
- package/src/resources/patient-search.resource.ts +22 -0
- package/src/resources/queue.resource.ts +60 -0
- package/src/resources/visit.resource.ts +38 -0
- package/src/root.component.tsx +42 -30
- package/src/root.scss +5 -9
- package/src/routes.json +43 -4
- package/src/service-queues/action-button.component.tsx +34 -0
- package/src/service-queues/action-overflow-menu-item.component.tsx +34 -0
- package/src/service-queues/consultation/consultation.component.scss +7 -0
- package/src/service-queues/consultation/consultation.component.tsx +15 -0
- package/src/service-queues/metrics/metrics-cards/attended-patients.extension.tsx +38 -0
- package/src/service-queues/metrics/metrics-cards/metrics-card.component.tsx +86 -0
- package/src/service-queues/metrics/metrics-cards/metrics-card.scss +106 -0
- package/src/service-queues/metrics/metrics-cards/waiting-patients.extension.tsx +34 -0
- package/src/service-queues/metrics/metrics-container.component.tsx +23 -0
- package/src/service-queues/metrics/metrics-container.scss +36 -0
- package/src/service-queues/metrics/metrics.resource.ts +65 -0
- package/src/service-queues/modals/move/move-patient.component.scss +35 -0
- package/src/service-queues/modals/move/move-patient.component.tsx +138 -0
- package/src/service-queues/modals/serve/serve-patient.comppnent.scss +0 -0
- package/src/service-queues/modals/serve/serve-patient.comppnent.tsx +80 -0
- package/src/service-queues/modals/sign-off/sign-off.modal.scss +0 -0
- package/src/service-queues/modals/sign-off/sign-off.modal.tsx +79 -0
- package/src/service-queues/modals/transition/transition-patient.component.scss +0 -0
- package/src/service-queues/modals/transition/transition-patient.component.tsx +122 -0
- package/src/service-queues/queue-list/queue-list.component.scss +19 -0
- package/src/service-queues/queue-list/queue-list.component.tsx +169 -0
- package/src/service-queues/queue-room.component.tsx +39 -0
- package/src/service-queues/room/room.component.tsx +58 -0
- package/src/service-queues/service-queue/service-queue.component.scss +14 -0
- package/src/service-queues/service-queue/service-queue.component.tsx +245 -0
- package/src/service-queues/service-queue/stats/stat-card/stat-card.component.scss +10 -0
- package/src/service-queues/service-queue/stats/stat-card/stat-card.component.tsx +23 -0
- package/src/service-queues/service-queue/stats/stat-details/stat-details.component.scss +7 -0
- package/src/service-queues/service-queue/stats/stat-details/stat-details.component.tsx +34 -0
- package/src/service-queues/service-queue.scss +27 -0
- package/src/service-queues/service-queue.tsx +31 -0
- package/src/service-queues/service-queues.resource.ts +177 -0
- package/src/service-queues/service.resource.ts +28 -0
- package/src/shared/constants/civil-status.ts +29 -0
- package/src/shared/constants/concepts.ts +30 -0
- package/src/shared/constants/index.ts +1 -0
- package/src/shared/constants/person-attributes.ts +33 -0
- package/src/shared/services/location.resource.ts +9 -0
- package/src/shared/ui/otp-input/otp-input.component.scss +14 -0
- package/src/shared/ui/otp-input/otp-input.component.tsx +90 -0
- package/src/shared/ui/timer/timer.component.scss +5 -0
- package/src/shared/ui/timer/timer.component.tsx +40 -0
- package/src/shared/utils/get-base-url.ts +17 -0
- package/src/side-nav-menu/nav-link-config.ts +82 -0
- package/src/side-nav-menu/nav-links.tsx +31 -11
- package/src/triage/metrics/attended-patients.extension.tsx +42 -0
- package/src/triage/metrics/metrics.scss +36 -0
- package/src/triage/metrics/triage-metrics.component.tsx +21 -0
- package/src/triage/metrics/waiting-patients.extension.tsx +39 -0
- package/src/triage/room/room.scss +29 -0
- package/src/triage/triage.component.tsx +15 -0
- package/src/triage/triage.resource.ts +19 -0
- package/src/triage/types.ts +16 -0
- package/src/types/types.ts +128 -0
- package/dist/561.js +0 -2
- package/dist/561.js.map +0 -1
- package/dist/70.js +0 -1
- package/dist/70.js.map +0 -1
- package/dist/731.js +0 -2
- package/dist/731.js.LICENSE.txt +0 -39
- package/dist/731.js.map +0 -1
- package/dist/819.js +0 -1
- package/dist/819.js.map +0 -1
- package/dist/openmrs-esm-home-app.js +0 -1
- package/src/boxes/extensions/blue-box.component.tsx +0 -15
- package/src/boxes/extensions/box.scss +0 -23
- package/src/boxes/extensions/brand-box.component.tsx +0 -15
- package/src/boxes/extensions/red-box.component.tsx +0 -15
- package/src/boxes/slot/boxes.component.tsx +0 -25
- package/src/boxes/slot/boxes.scss +0 -29
- package/src/greeter/greeter.component.tsx +0 -42
- package/src/greeter/greeter.scss +0 -20
- package/src/greeter/greeter.test.tsx +0 -28
- package/src/patient-getter/patient-getter.component.tsx +0 -40
- package/src/patient-getter/patient-getter.resource.ts +0 -39
- package/src/patient-getter/patient-getter.scss +0 -16
- package/src/patient-getter/patient-getter.test.tsx +0 -40
- package/src/resources/resources.component.tsx +0 -56
- package/src/resources/resources.scss +0 -68
- /package/dist/{561.js.LICENSE.txt → 710.js.LICENSE.txt} +0 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
@use '@carbon/layout';
|
|
2
|
+
@use '@carbon/type';
|
|
3
|
+
@use '@carbon/colors';
|
|
4
|
+
@use '@openmrs/esm-styleguide/src/vars' as *;
|
|
5
|
+
|
|
6
|
+
.tileContainer {
|
|
7
|
+
border: 1px solid $ui-03;
|
|
8
|
+
min-height: 7.875rem;
|
|
9
|
+
height: 100%;
|
|
10
|
+
padding: layout.$spacing-05;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.tileHeader {
|
|
14
|
+
display: flex;
|
|
15
|
+
justify-content: space-between;
|
|
16
|
+
align-items: baseline;
|
|
17
|
+
margin-bottom: layout.$spacing-03;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.headerLabelContainer {
|
|
21
|
+
display: flex;
|
|
22
|
+
height: layout.$spacing-07;
|
|
23
|
+
align-items: center;
|
|
24
|
+
|
|
25
|
+
:global(.cds--dropdown__wrapper--inline) {
|
|
26
|
+
gap: 0;
|
|
27
|
+
|
|
28
|
+
label {
|
|
29
|
+
@include type.type-style('heading-compact-01');
|
|
30
|
+
color: $text-02;
|
|
31
|
+
margin-right: layout.$spacing-03;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
:global(.cds--list-box__menu-icon) {
|
|
36
|
+
height: layout.$spacing-05;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.link {
|
|
41
|
+
text-decoration: none;
|
|
42
|
+
display: flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
color: $interactive-01;
|
|
45
|
+
|
|
46
|
+
svg {
|
|
47
|
+
margin-left: layout.$spacing-03;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.headerLabel {
|
|
52
|
+
@include type.type-style('heading-compact-01');
|
|
53
|
+
color: $text-02;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.metricsContainer {
|
|
57
|
+
display: flex;
|
|
58
|
+
gap: layout.$spacing-07;
|
|
59
|
+
align-items: stretch;
|
|
60
|
+
flex-wrap: wrap;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.metricItem {
|
|
64
|
+
display: inline-block;
|
|
65
|
+
flex-direction: column;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.metricLabel {
|
|
69
|
+
@include type.type-style('label-01');
|
|
70
|
+
color: $text-02;
|
|
71
|
+
margin-bottom: layout.$spacing-02;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.metricValue {
|
|
75
|
+
@include type.type-style('heading-04');
|
|
76
|
+
color: $ui-05;
|
|
77
|
+
margin: 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.mainItem {
|
|
81
|
+
margin-right: layout.$spacing-07;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.smallItem {
|
|
85
|
+
flex-direction: row;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.smallValue {
|
|
89
|
+
font-size: 1rem !important;
|
|
90
|
+
margin-top: layout.$spacing-02;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.red {
|
|
94
|
+
color: colors.$red-50;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Overriding styles for RTL support
|
|
98
|
+
html[dir='rtl'] {
|
|
99
|
+
.link {
|
|
100
|
+
svg {
|
|
101
|
+
margin-right: layout.$spacing-03;
|
|
102
|
+
margin-left: unset;
|
|
103
|
+
transform: scale(-1, 1);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { MetricsCard, MetricsCardHeader, MetricsCardBody, MetricsCardItem } from './metrics-card.component';
|
|
4
|
+
import { getServiceQueueByLocationUuid } from '../../service-queues.resource';
|
|
5
|
+
import { QUEUE_SERVICE_UUIDS } from '../../../shared/constants/concepts';
|
|
6
|
+
import { useSession } from '@openmrs/esm-framework';
|
|
7
|
+
import { type QueueEntryResult } from '../../../registry/types';
|
|
8
|
+
|
|
9
|
+
export default function WaitingPatientsExtension() {
|
|
10
|
+
const { t } = useTranslation();
|
|
11
|
+
const [consultationQueueEntries, setConsultationQueueEntries] = useState<QueueEntryResult[]>([]);
|
|
12
|
+
const session = useSession();
|
|
13
|
+
const locationUuid = session.sessionLocation.uuid;
|
|
14
|
+
const consultationServiceUuid = QUEUE_SERVICE_UUIDS.CLINICAL_CONSULTATION_SERVICE_UUID;
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
getConsultationEntryQueues();
|
|
17
|
+
}, []);
|
|
18
|
+
|
|
19
|
+
const getConsultationEntryQueues = async () => {
|
|
20
|
+
const res = await getServiceQueueByLocationUuid(consultationServiceUuid, locationUuid);
|
|
21
|
+
setConsultationQueueEntries(res);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const waitingPatientsCount = consultationQueueEntries?.filter((p) => p.status === 'WAITING').length ?? 0;
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<MetricsCard>
|
|
28
|
+
<MetricsCardHeader title={t('patientsInWaiting', 'Patients in waiting')} />
|
|
29
|
+
<MetricsCardBody>
|
|
30
|
+
<MetricsCardItem label={t('patients', 'Patients')} value={waitingPatientsCount ? waitingPatientsCount : '--'} />
|
|
31
|
+
</MetricsCardBody>
|
|
32
|
+
</MetricsCard>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ExtensionSlot } from '@openmrs/esm-framework';
|
|
3
|
+
import styles from './metrics-container.scss';
|
|
4
|
+
import AttendedToPatientsExtension from './metrics-cards/attended-patients.extension';
|
|
5
|
+
import WaitingPatientsExtension from './metrics-cards/waiting-patients.extension';
|
|
6
|
+
|
|
7
|
+
export interface Service {
|
|
8
|
+
display: string;
|
|
9
|
+
uuid?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function MetricsContainer() {
|
|
13
|
+
return (
|
|
14
|
+
<>
|
|
15
|
+
<div className={styles.cardContainer}>
|
|
16
|
+
<WaitingPatientsExtension />
|
|
17
|
+
<AttendedToPatientsExtension />;
|
|
18
|
+
</div>
|
|
19
|
+
</>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default MetricsContainer;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
@use '@carbon/layout';
|
|
2
|
+
@use '@openmrs/esm-styleguide/src/vars' as *;
|
|
3
|
+
|
|
4
|
+
.cardContainer {
|
|
5
|
+
background-color: $ui-02;
|
|
6
|
+
display: flex;
|
|
7
|
+
padding: layout.$spacing-05;
|
|
8
|
+
flex-flow: row wrap;
|
|
9
|
+
gap: layout.$spacing-05;
|
|
10
|
+
align-items: stretch;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.cardContainer > * {
|
|
14
|
+
flex: 1 0 0%;
|
|
15
|
+
min-width: 16rem;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// If we're on tablet and the screen is too small for 3 cards across
|
|
19
|
+
// @TODO: This will do nonsense things if there are not exactly 3 cards
|
|
20
|
+
@media (max-width: calc(layout.$spacing-05 * 4 + 18.75rem * 3)) {
|
|
21
|
+
:global(.omrs-breakpoint-lt-desktop) {
|
|
22
|
+
.cardContainer > *:has(:global(.cardWithChildren)) {
|
|
23
|
+
order: 999;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// If we're on desktop and the screen is too small for the left nav bar
|
|
29
|
+
// plus 3 cards across
|
|
30
|
+
@media (max-width: calc(16rem + layout.$spacing-05 * 4 + 18.75rem * 3)) {
|
|
31
|
+
:global(.omrs-breakpoint-gt-tablet) {
|
|
32
|
+
.cardContainer > *:has(:global(.cardWithChildren)) {
|
|
33
|
+
order: 999;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { useSession, type Visit, openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
|
|
2
|
+
import dayjs from 'dayjs';
|
|
3
|
+
import useSWR from 'swr';
|
|
4
|
+
|
|
5
|
+
// export function useActiveVisits() {
|
|
6
|
+
// const currentUserSession = useSession();
|
|
7
|
+
// const startDate = dayjs().format('YYYY-MM-DD');
|
|
8
|
+
// const sessionLocation = currentUserSession?.sessionLocation?.uuid;
|
|
9
|
+
|
|
10
|
+
// const customRepresentation =
|
|
11
|
+
// 'custom:(uuid,patient:(uuid,identifiers:(identifier,uuid),person:(age,display,gender,uuid)),' +
|
|
12
|
+
// 'visitType:(uuid,name,display),location:(uuid,name,display),startDatetime,' +
|
|
13
|
+
// 'stopDatetime)&fromStartDate=' +
|
|
14
|
+
// startDate +
|
|
15
|
+
// '&location=' +
|
|
16
|
+
// sessionLocation;
|
|
17
|
+
// const url = `${restBaseUrl}/visit?includeInactive=false&v=${customRepresentation}`;
|
|
18
|
+
// const { data, error, isLoading, isValidating } = useSWR<{ data: { results: Array<Visit> } }, Error>(
|
|
19
|
+
// sessionLocation ? url : null,
|
|
20
|
+
// openmrsFetch,
|
|
21
|
+
// );
|
|
22
|
+
|
|
23
|
+
// // Create a Set to store unique patient UUIDs
|
|
24
|
+
// const uniquePatientUUIDs = new Set();
|
|
25
|
+
|
|
26
|
+
// data?.data?.results.forEach((visit) => {
|
|
27
|
+
// const patientUUID = visit.patient?.uuid;
|
|
28
|
+
// const isToday = dayjs(visit.startDatetime).isToday();
|
|
29
|
+
// if (patientUUID && isToday) {
|
|
30
|
+
// uniquePatientUUIDs.add(patientUUID);
|
|
31
|
+
// }
|
|
32
|
+
// });
|
|
33
|
+
|
|
34
|
+
// return {
|
|
35
|
+
// activeVisitsCount: uniquePatientUUIDs.size,
|
|
36
|
+
// isLoading,
|
|
37
|
+
// error,
|
|
38
|
+
// isValidating,
|
|
39
|
+
// };
|
|
40
|
+
// }
|
|
41
|
+
|
|
42
|
+
// Statuses: Waiting, Finished Service, In Service
|
|
43
|
+
export function useServiceMetricsCount(status: string = 'Waiting', service: string = "7f7ec7ad-cdd7-4ed9-bc2e-5c5bd9f065b2") {
|
|
44
|
+
const currentUserSession = useSession();
|
|
45
|
+
const location = currentUserSession?.sessionLocation?.uuid;
|
|
46
|
+
|
|
47
|
+
const apiUrl =
|
|
48
|
+
`${restBaseUrl}/queue-entry-metrics?status=${status}&isEnded=false` +
|
|
49
|
+
(service ? `&service=${service}` : '') +
|
|
50
|
+
(location ? `&location=${location}` : '');
|
|
51
|
+
|
|
52
|
+
const { data, isLoading } = useSWR<
|
|
53
|
+
{
|
|
54
|
+
data: {
|
|
55
|
+
count: number;
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
Error
|
|
59
|
+
>(service ? apiUrl : null, openmrsFetch);
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
serviceCount: data ? data?.data?.count : 0,
|
|
63
|
+
isLoading
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
.modelLayout{
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
width: 100%;
|
|
5
|
+
padding: 15px 15px;
|
|
6
|
+
}
|
|
7
|
+
.formSection{
|
|
8
|
+
display: flex;
|
|
9
|
+
flex-direction: column;
|
|
10
|
+
width: 100%;
|
|
11
|
+
row-gap: 5px;
|
|
12
|
+
}
|
|
13
|
+
.sectionHeader{
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-direction: column;
|
|
16
|
+
width: 100%;
|
|
17
|
+
row-gap: 5px;
|
|
18
|
+
}
|
|
19
|
+
.formRow{
|
|
20
|
+
display: flex;
|
|
21
|
+
flex-direction: row;
|
|
22
|
+
width: 100%;
|
|
23
|
+
column-gap: 5px;
|
|
24
|
+
}
|
|
25
|
+
.formControl{
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-direction: column;
|
|
28
|
+
width: 45%;
|
|
29
|
+
}
|
|
30
|
+
.actionSection{
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-direction: row;
|
|
33
|
+
width: 100%;
|
|
34
|
+
column-gap: 5px;
|
|
35
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { Button, Modal, ModalBody, Select, SelectItem, TextArea } from '@carbon/react';
|
|
2
|
+
import React, { useEffect, useState } from 'react';
|
|
3
|
+
import styles from './move-patient.component.scss';
|
|
4
|
+
import { type ServiceQueue } from '../../../registry/types';
|
|
5
|
+
import { getServiceQueueByLocation, transitionQueueEntry } from '../../service.resource';
|
|
6
|
+
import { type TransitionQueueEntryDto } from '../../../types/types';
|
|
7
|
+
import { QUEUE_PRIORITIES_UUIDS, QUEUE_STATUS_UUIDS } from '../../../shared/constants/concepts';
|
|
8
|
+
import { showSnackbar } from '@openmrs/esm-framework';
|
|
9
|
+
interface MovePatientModalProps {
|
|
10
|
+
open: boolean;
|
|
11
|
+
onModalClose: () => void;
|
|
12
|
+
locationUuid: string;
|
|
13
|
+
serviceUuid: string;
|
|
14
|
+
currentQueueEntryUuid: string;
|
|
15
|
+
}
|
|
16
|
+
const MovePatientModal: React.FC<MovePatientModalProps> = ({
|
|
17
|
+
open,
|
|
18
|
+
onModalClose,
|
|
19
|
+
locationUuid,
|
|
20
|
+
serviceUuid,
|
|
21
|
+
currentQueueEntryUuid,
|
|
22
|
+
}) => {
|
|
23
|
+
const [serviceQueues, setServiceQueues] = useState<ServiceQueue[]>([]);
|
|
24
|
+
const [selectedComment, setSelectedComment] = useState<string>();
|
|
25
|
+
const [selectedPriority, setSelectedPriority] = useState<string>();
|
|
26
|
+
const [selectedNewService, setSelectedNewService] = useState<ServiceQueue>();
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
getQueues();
|
|
29
|
+
}, [locationUuid]);
|
|
30
|
+
const serviceChangeHandler = (serviceQueueUuid: string) => {
|
|
31
|
+
const serviceQueue = serviceQueues.find((sq) => {
|
|
32
|
+
return sq.uuid === serviceQueueUuid;
|
|
33
|
+
});
|
|
34
|
+
setSelectedNewService(serviceQueue);
|
|
35
|
+
};
|
|
36
|
+
const getQueues = async () => {
|
|
37
|
+
const res = await getServiceQueueByLocation(locationUuid);
|
|
38
|
+
setServiceQueues(res);
|
|
39
|
+
};
|
|
40
|
+
const transtionQueueEntry = async () => {
|
|
41
|
+
const payload = getTransitionQueueEntryPayload();
|
|
42
|
+
try {
|
|
43
|
+
const resp = await transitionQueueEntry(payload);
|
|
44
|
+
showAlert('success', 'Cleint succesfully moved', '');
|
|
45
|
+
onModalClose();
|
|
46
|
+
} catch (e) {
|
|
47
|
+
showAlert('error', e.message, '');
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const showAlert = (alertType: 'error' | 'success', title: string, subtitle: string) => {
|
|
52
|
+
showSnackbar({
|
|
53
|
+
kind: alertType,
|
|
54
|
+
title: title,
|
|
55
|
+
subtitle: subtitle,
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
const getTransitionQueueEntryPayload = (): TransitionQueueEntryDto => {
|
|
59
|
+
const payload: TransitionQueueEntryDto = {
|
|
60
|
+
queueEntryToTransition: currentQueueEntryUuid,
|
|
61
|
+
newQueue: selectedNewService.uuid,
|
|
62
|
+
newStatus: QUEUE_STATUS_UUIDS.WAITING_UUID,
|
|
63
|
+
newPriority: selectedPriority,
|
|
64
|
+
newPriorityComment: selectedComment,
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
return payload;
|
|
68
|
+
};
|
|
69
|
+
const priorityChangeHandler = (priorityUuid: string) => {
|
|
70
|
+
setSelectedPriority(priorityUuid);
|
|
71
|
+
};
|
|
72
|
+
const handleCommentChange = (comment: string) => {};
|
|
73
|
+
return (
|
|
74
|
+
<>
|
|
75
|
+
<Modal
|
|
76
|
+
open={open}
|
|
77
|
+
size="md"
|
|
78
|
+
onSecondarySubmit={() => onModalClose()}
|
|
79
|
+
onRequestClose={() => onModalClose()}
|
|
80
|
+
onRequestSubmit={transtionQueueEntry}
|
|
81
|
+
primaryButtonText="Move"
|
|
82
|
+
secondaryButtonText="Cancel"
|
|
83
|
+
>
|
|
84
|
+
<ModalBody>
|
|
85
|
+
<div className={styles.modelLayout}>
|
|
86
|
+
<div className={styles.sectionHeader}>
|
|
87
|
+
<h4>Move Client</h4>
|
|
88
|
+
</div>
|
|
89
|
+
<div className={styles.formSection}>
|
|
90
|
+
<div className={styles.formRow}>
|
|
91
|
+
<div className={styles.formControl}>
|
|
92
|
+
<Select
|
|
93
|
+
id="service-queue"
|
|
94
|
+
labelText="Select the new Queue"
|
|
95
|
+
onChange={(e) => serviceChangeHandler(e.target.value)}
|
|
96
|
+
>
|
|
97
|
+
<SelectItem value="" text="" />;
|
|
98
|
+
{serviceQueues &&
|
|
99
|
+
serviceQueues.map((vt) => {
|
|
100
|
+
return <SelectItem value={vt.uuid} text={vt.name} />;
|
|
101
|
+
})}
|
|
102
|
+
</Select>
|
|
103
|
+
</div>
|
|
104
|
+
<div className={styles.formControl}>
|
|
105
|
+
<Select
|
|
106
|
+
id="priority"
|
|
107
|
+
labelText="Select a Priority"
|
|
108
|
+
onChange={(e) => priorityChangeHandler(e.target.value)}
|
|
109
|
+
>
|
|
110
|
+
<SelectItem value="" text="Select" />;
|
|
111
|
+
<SelectItem value={QUEUE_PRIORITIES_UUIDS.NORMAL_PRIORITY_UUID} text="NORMAL" />;
|
|
112
|
+
<SelectItem value={QUEUE_PRIORITIES_UUIDS.EMERGENCY_PRIORITY_UUID} text="EMERGENCY" />;
|
|
113
|
+
</Select>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
<div className={styles.formRow}>
|
|
117
|
+
<div className={styles.formControl}>
|
|
118
|
+
<TextArea
|
|
119
|
+
enableCounter
|
|
120
|
+
helperText="Comment"
|
|
121
|
+
id="comment"
|
|
122
|
+
labelText="Comment"
|
|
123
|
+
maxCount={500}
|
|
124
|
+
placeholder="Comment"
|
|
125
|
+
onChange={(e) => handleCommentChange(e.target.value)}
|
|
126
|
+
rows={4}
|
|
127
|
+
/>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
</ModalBody>
|
|
133
|
+
</Modal>
|
|
134
|
+
</>
|
|
135
|
+
);
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
export default MovePatientModal;
|
|
File without changes
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Modal, ModalBody } from '@carbon/react';
|
|
3
|
+
import { type QueueEntryResult } from '../../../registry/types';
|
|
4
|
+
import styles from './serve-patient.comppnent.scss';
|
|
5
|
+
import { type TransitionQueueEntryDto } from '../../../types/types';
|
|
6
|
+
import { QUEUE_STATUS_UUIDS } from '../../../shared/constants/concepts';
|
|
7
|
+
import { transitionQueueEntry } from '../../service.resource';
|
|
8
|
+
import { showSnackbar } from '@openmrs/esm-framework';
|
|
9
|
+
|
|
10
|
+
interface ServePatientModal {
|
|
11
|
+
open: boolean;
|
|
12
|
+
onModalClose: () => void;
|
|
13
|
+
currentQueueEntry: QueueEntryResult;
|
|
14
|
+
onSuccessfullServe: () => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const ServePatientModal: React.FC<ServePatientModal> = ({
|
|
18
|
+
open,
|
|
19
|
+
onModalClose,
|
|
20
|
+
currentQueueEntry,
|
|
21
|
+
onSuccessfullServe,
|
|
22
|
+
}) => {
|
|
23
|
+
const servePatient = async () => {
|
|
24
|
+
const payload = getServePatientPayload();
|
|
25
|
+
try {
|
|
26
|
+
await transitionQueueEntry(payload);
|
|
27
|
+
showAlert('success', 'Client succesfully served', '');
|
|
28
|
+
onSuccessfullServe();
|
|
29
|
+
} catch (e) {
|
|
30
|
+
showAlert('error', e.message, '');
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
const showAlert = (alertType: 'error' | 'success', title: string, subtitle: string) => {
|
|
34
|
+
showSnackbar({
|
|
35
|
+
kind: alertType,
|
|
36
|
+
title: title,
|
|
37
|
+
subtitle: subtitle,
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
const getServePatientPayload = (): TransitionQueueEntryDto => {
|
|
41
|
+
const payload: TransitionQueueEntryDto = {
|
|
42
|
+
queueEntryToTransition: currentQueueEntry.queue_entry_uuid,
|
|
43
|
+
newQueue: currentQueueEntry.service_uuid,
|
|
44
|
+
newStatus: QUEUE_STATUS_UUIDS.IN_SERVICE_UUID,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
return payload;
|
|
48
|
+
};
|
|
49
|
+
return (
|
|
50
|
+
<>
|
|
51
|
+
<Modal
|
|
52
|
+
modalHeading="Serve Client"
|
|
53
|
+
open={open}
|
|
54
|
+
size="md"
|
|
55
|
+
onSecondarySubmit={() => onModalClose()}
|
|
56
|
+
onRequestClose={() => onModalClose()}
|
|
57
|
+
onRequestSubmit={servePatient}
|
|
58
|
+
primaryButtonText="Serve"
|
|
59
|
+
secondaryButtonText="Cancel"
|
|
60
|
+
>
|
|
61
|
+
<ModalBody>
|
|
62
|
+
<div className={styles.serveModalLayout}>
|
|
63
|
+
<div className={styles.serveModalContentSection}>
|
|
64
|
+
<div className={styles.formRow}>
|
|
65
|
+
<p>
|
|
66
|
+
Name: {currentQueueEntry.family_name} {currentQueueEntry.middle_name} {currentQueueEntry.given_name}
|
|
67
|
+
</p>
|
|
68
|
+
<p>Ticket No: {currentQueueEntry.queue_entry_id}</p>
|
|
69
|
+
<p>Status: {currentQueueEntry.status}</p>
|
|
70
|
+
<p>Priority: {currentQueueEntry.priority}</p>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
</ModalBody>
|
|
75
|
+
</Modal>
|
|
76
|
+
</>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export default ServePatientModal;
|
|
File without changes
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Modal, ModalBody, TextInput } from '@carbon/react';
|
|
3
|
+
import { type EndVisitDto, type QueueEntryResult } from '../../../registry/types';
|
|
4
|
+
import styles from './sign-off.modal.scss';
|
|
5
|
+
import { showSnackbar } from '@openmrs/esm-framework';
|
|
6
|
+
import { endVisit } from '../../../resources/visit.resource';
|
|
7
|
+
import { closeQueueEntry } from '../../service-queues.resource';
|
|
8
|
+
|
|
9
|
+
interface SignOffEntryModalProps {
|
|
10
|
+
open: boolean;
|
|
11
|
+
onModalClose: () => void;
|
|
12
|
+
currentQueueEntry: QueueEntryResult;
|
|
13
|
+
onSuccessfullSignOff: () => void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const SignOffEntryModal: React.FC<SignOffEntryModalProps> = ({
|
|
17
|
+
open,
|
|
18
|
+
onModalClose,
|
|
19
|
+
currentQueueEntry,
|
|
20
|
+
onSuccessfullSignOff,
|
|
21
|
+
}) => {
|
|
22
|
+
const signOffEntry = async () => {
|
|
23
|
+
const payload = getEndVisitPayload();
|
|
24
|
+
try {
|
|
25
|
+
await removePatientFromQueue(currentQueueEntry);
|
|
26
|
+
await endVisit(currentQueueEntry.visit_uuid, payload);
|
|
27
|
+
showAlert('success', 'Visit Ended successfully', '');
|
|
28
|
+
onSuccessfullSignOff();
|
|
29
|
+
} catch (e) {
|
|
30
|
+
showAlert('error', e.message, '');
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
const showAlert = (alertType: 'error' | 'success', title: string, subtitle: string) => {
|
|
34
|
+
showSnackbar({
|
|
35
|
+
kind: alertType,
|
|
36
|
+
title: title,
|
|
37
|
+
subtitle: subtitle,
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
const getEndVisitPayload = (): EndVisitDto => {
|
|
41
|
+
return {
|
|
42
|
+
stopDatetime: new Date().toISOString(),
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
const removePatientFromQueue = async (currentQueueEntry: QueueEntryResult) => {
|
|
46
|
+
try {
|
|
47
|
+
await closeQueueEntry(currentQueueEntry.queue_entry_uuid);
|
|
48
|
+
showAlert('success', 'Patient removal from queue successfully!', '');
|
|
49
|
+
} catch (e) {
|
|
50
|
+
showAlert('error', 'Patient removal from queue failed!', '');
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
return (
|
|
54
|
+
<>
|
|
55
|
+
<Modal
|
|
56
|
+
modalHeading="Sign Off"
|
|
57
|
+
open={open}
|
|
58
|
+
size="md"
|
|
59
|
+
onSecondarySubmit={() => onModalClose()}
|
|
60
|
+
onRequestClose={() => onModalClose()}
|
|
61
|
+
onRequestSubmit={signOffEntry}
|
|
62
|
+
primaryButtonText="Sign Off"
|
|
63
|
+
secondaryButtonText="Cancel"
|
|
64
|
+
>
|
|
65
|
+
<ModalBody>
|
|
66
|
+
<div className={styles.serveModalLayout}>
|
|
67
|
+
<div className={styles.serveModalContentSection}>
|
|
68
|
+
<div className={styles.formRow}>
|
|
69
|
+
<TextInput id="health-worker-id" labelText="Enter your Provider ID" onChange={() => {}} type="text" />
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
</ModalBody>
|
|
74
|
+
</Modal>
|
|
75
|
+
</>
|
|
76
|
+
);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export default SignOffEntryModal;
|
|
File without changes
|