@ampath/esm-dha-workflow-app 4.0.0-next.18 → 4.0.0-next.19
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 +1 -1
- package/dist/104.js.map +1 -1
- package/dist/15.js +1 -1
- package/dist/15.js.map +1 -1
- package/dist/321.js +1 -0
- package/dist/321.js.map +1 -0
- package/dist/339.js +1 -1
- package/dist/339.js.map +1 -1
- package/dist/468.js +2 -0
- package/dist/468.js.map +1 -0
- package/dist/602.js +1 -0
- package/dist/602.js.map +1 -0
- package/dist/635.js +1 -0
- package/dist/635.js.map +1 -0
- package/dist/710.js +1 -1
- package/dist/733.js +1 -0
- package/dist/733.js.map +1 -0
- package/dist/{454.js → 844.js} +1 -1
- package/dist/844.js.map +1 -0
- package/dist/91.js +1 -1
- package/dist/91.js.map +1 -1
- package/dist/93.js +1 -1
- package/dist/esm-dha-workflow-app.js +1 -1
- package/dist/esm-dha-workflow-app.js.buildmanifest.json +107 -82
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/registry/types/index.ts +20 -0
- package/src/root.component.tsx +2 -1
- package/src/service-queues/consultation/consultation.component.scss +7 -0
- package/src/service-queues/consultation/consultation.component.tsx +15 -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 +82 -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 +117 -0
- package/src/service-queues/service-queue/service-queue.component.scss +7 -0
- package/src/service-queues/service-queue/service-queue.component.tsx +165 -0
- package/src/service-queues/service-queues.resource.ts +73 -20
- package/src/service-queues/service.resource.ts +28 -0
- package/src/shared/constants/concepts.ts +8 -0
- package/src/shared/constants/index.ts +1 -0
- package/src/triage/triage.component.tsx +3 -26
- package/src/types/types.ts +17 -2
- package/dist/178.js +0 -1
- package/dist/178.js.map +0 -1
- package/dist/22.js +0 -1
- package/dist/22.js.map +0 -1
- package/dist/306.js +0 -1
- package/dist/306.js.map +0 -1
- package/dist/454.js.map +0 -1
- package/dist/875.js +0 -2
- package/dist/875.js.map +0 -1
- /package/dist/{875.js.LICENSE.txt → 468.js.LICENSE.txt} +0 -0
|
@@ -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,82 @@
|
|
|
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', 'Cleint 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
|
+
open={open}
|
|
53
|
+
size="md"
|
|
54
|
+
onSecondarySubmit={() => onModalClose()}
|
|
55
|
+
onRequestClose={() => onModalClose()}
|
|
56
|
+
onRequestSubmit={servePatient}
|
|
57
|
+
primaryButtonText="Serve"
|
|
58
|
+
secondaryButtonText="Cancel"
|
|
59
|
+
>
|
|
60
|
+
<ModalBody>
|
|
61
|
+
<div className={styles.serveModalLayout}>
|
|
62
|
+
<div className={styles.serveModalSectionHeader}>
|
|
63
|
+
<h4>Serve Client</h4>
|
|
64
|
+
</div>
|
|
65
|
+
<div className={styles.serveModalContentSection}>
|
|
66
|
+
<div className={styles.formRow}>
|
|
67
|
+
<p>
|
|
68
|
+
Name: {currentQueueEntry.family_name} {currentQueueEntry.family_name}
|
|
69
|
+
</p>
|
|
70
|
+
<p>Ticket No: {currentQueueEntry.queue_entry_id}</p>
|
|
71
|
+
<p>Status: {currentQueueEntry.status}</p>
|
|
72
|
+
<p>Priority: {currentQueueEntry.priority}</p>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
</ModalBody>
|
|
77
|
+
</Modal>
|
|
78
|
+
</>
|
|
79
|
+
);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export default ServePatientModal;
|
|
File without changes
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { Modal, ModalBody, Select, SelectItem, TextArea } from '@carbon/react';
|
|
3
|
+
import styles from './transition-patient.component.scss';
|
|
4
|
+
import { type QueueEntryResult } from '../../../registry/types';
|
|
5
|
+
import { 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 TransitionPatientModalProps {
|
|
10
|
+
open: boolean;
|
|
11
|
+
onModalClose: () => void;
|
|
12
|
+
currentQueueEntry: QueueEntryResult;
|
|
13
|
+
}
|
|
14
|
+
const TransitionPatientModal: React.FC<TransitionPatientModalProps> = ({ open, onModalClose, currentQueueEntry }) => {
|
|
15
|
+
const [selectedComment, setSelectedComment] = useState<string>();
|
|
16
|
+
const [selectedPriority, setSelectedPriority] = useState<string>();
|
|
17
|
+
const [selectedStatus, setSelectedStatus] = useState<string>();
|
|
18
|
+
|
|
19
|
+
const statusChangeHandler = (statusUuid: string) => {
|
|
20
|
+
setSelectedStatus(statusUuid);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const transtionQueueEntry = async () => {
|
|
24
|
+
const payload = getTransitionQueueEntryPayload();
|
|
25
|
+
try {
|
|
26
|
+
await transitionQueueEntry(payload);
|
|
27
|
+
showAlert('success', 'Cleint succesfully Transitioned', '');
|
|
28
|
+
onModalClose();
|
|
29
|
+
} catch (e) {
|
|
30
|
+
showAlert('error', e.message, '');
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const showAlert = (alertType: 'error' | 'success', title: string, subtitle: string) => {
|
|
35
|
+
showSnackbar({
|
|
36
|
+
kind: alertType,
|
|
37
|
+
title: title,
|
|
38
|
+
subtitle: subtitle,
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
const getTransitionQueueEntryPayload = (): TransitionQueueEntryDto => {
|
|
42
|
+
const payload: TransitionQueueEntryDto = {
|
|
43
|
+
queueEntryToTransition: currentQueueEntry.queue_entry_uuid,
|
|
44
|
+
newQueue: currentQueueEntry.service_uuid,
|
|
45
|
+
newStatus: selectedStatus,
|
|
46
|
+
newPriority: selectedPriority,
|
|
47
|
+
newPriorityComment: selectedComment,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
return payload;
|
|
51
|
+
};
|
|
52
|
+
const priorityChangeHandler = (priorityUuid: string) => {
|
|
53
|
+
setSelectedPriority(priorityUuid);
|
|
54
|
+
};
|
|
55
|
+
const handleCommentChange = (comment: string) => {
|
|
56
|
+
setSelectedComment(comment);
|
|
57
|
+
};
|
|
58
|
+
return (
|
|
59
|
+
<>
|
|
60
|
+
<Modal
|
|
61
|
+
open={open}
|
|
62
|
+
size="md"
|
|
63
|
+
onSecondarySubmit={() => onModalClose()}
|
|
64
|
+
onRequestClose={() => onModalClose()}
|
|
65
|
+
onRequestSubmit={transtionQueueEntry}
|
|
66
|
+
primaryButtonText="Transition"
|
|
67
|
+
secondaryButtonText="Cancel"
|
|
68
|
+
>
|
|
69
|
+
<ModalBody>
|
|
70
|
+
<div className={styles.modelLayout}>
|
|
71
|
+
<div className={styles.sectionHeader}>
|
|
72
|
+
<h4>Move Client</h4>
|
|
73
|
+
</div>
|
|
74
|
+
<div className={styles.formSection}>
|
|
75
|
+
<div className={styles.formRow}>
|
|
76
|
+
<div className={styles.formControl}>
|
|
77
|
+
<Select
|
|
78
|
+
id="queue-status"
|
|
79
|
+
labelText="Select Queue Status"
|
|
80
|
+
onChange={(e) => statusChangeHandler(e.target.value)}
|
|
81
|
+
>
|
|
82
|
+
<SelectItem value="" text="" />;
|
|
83
|
+
<SelectItem value={QUEUE_STATUS_UUIDS.WAITING_UUID} text="IN WAITING" />;
|
|
84
|
+
<SelectItem value={QUEUE_STATUS_UUIDS.IN_SERVICE_UUID} text="IN SERVICE" />;
|
|
85
|
+
<SelectItem value={QUEUE_STATUS_UUIDS.COMPLETED_UUID} text="COMPLETED" />;
|
|
86
|
+
</Select>
|
|
87
|
+
</div>
|
|
88
|
+
<div className={styles.formControl}>
|
|
89
|
+
<Select
|
|
90
|
+
id="priority"
|
|
91
|
+
labelText="Select a Priority"
|
|
92
|
+
onChange={(e) => priorityChangeHandler(e.target.value)}
|
|
93
|
+
>
|
|
94
|
+
<SelectItem value="" text="Select" />;
|
|
95
|
+
<SelectItem value={QUEUE_PRIORITIES_UUIDS.NORMAL_PRIORITY_UUID} text="NORMAL" />;
|
|
96
|
+
<SelectItem value={QUEUE_PRIORITIES_UUIDS.EMERGENCY_PRIORITY_UUID} text="EMERGENCY" />;
|
|
97
|
+
</Select>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
<div className={styles.formRow}>
|
|
101
|
+
<div className={styles.formControl}>
|
|
102
|
+
<TextArea
|
|
103
|
+
enableCounter
|
|
104
|
+
helperText="Comment"
|
|
105
|
+
id="comment"
|
|
106
|
+
labelText="Comment"
|
|
107
|
+
maxCount={500}
|
|
108
|
+
placeholder="Comment"
|
|
109
|
+
onChange={(e) => handleCommentChange(e.target.value)}
|
|
110
|
+
rows={4}
|
|
111
|
+
/>
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
</ModalBody>
|
|
117
|
+
</Modal>
|
|
118
|
+
</>
|
|
119
|
+
);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export default TransitionPatientModal;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
.queueListLayout{
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
width: 100%;
|
|
5
|
+
row-gap: 15px;
|
|
6
|
+
padding: 5px 5px;
|
|
7
|
+
}
|
|
8
|
+
.actionHeader{
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: row;
|
|
11
|
+
justify-content: flex-end;
|
|
12
|
+
width: 100%;
|
|
13
|
+
}
|
|
14
|
+
.tableSection{
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-direction: column;
|
|
17
|
+
width: 100%;
|
|
18
|
+
row-gap: 10px;
|
|
19
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Button,
|
|
3
|
+
Link,
|
|
4
|
+
OverflowMenu,
|
|
5
|
+
OverflowMenuItem,
|
|
6
|
+
Table,
|
|
7
|
+
TableBody,
|
|
8
|
+
TableCell,
|
|
9
|
+
TableHead,
|
|
10
|
+
TableHeader,
|
|
11
|
+
TableRow,
|
|
12
|
+
} from '@carbon/react';
|
|
13
|
+
import { type QueueEntryResult } from '../../registry/types';
|
|
14
|
+
import React, { useState } from 'react';
|
|
15
|
+
import styles from './queue-list.component.scss';
|
|
16
|
+
|
|
17
|
+
interface QueueListProps {
|
|
18
|
+
queueEntries: QueueEntryResult[];
|
|
19
|
+
handleMovePatient: (queueEntryResult: QueueEntryResult) => void;
|
|
20
|
+
handleTransitionPatient: (queueEntryResult: QueueEntryResult) => void;
|
|
21
|
+
handleServePatient: (queueEntryResult: QueueEntryResult) => void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const QueueList: React.FC<QueueListProps> = ({
|
|
25
|
+
queueEntries,
|
|
26
|
+
handleMovePatient,
|
|
27
|
+
handleTransitionPatient,
|
|
28
|
+
handleServePatient,
|
|
29
|
+
}) => {
|
|
30
|
+
const [checkIn, setCheckIn] = useState<boolean>(false);
|
|
31
|
+
const handleCheckin = () => {
|
|
32
|
+
setCheckIn((prev) => !prev);
|
|
33
|
+
};
|
|
34
|
+
return (
|
|
35
|
+
<>
|
|
36
|
+
<div className={styles.queueListLayout}>
|
|
37
|
+
<div className={styles.actionHeader}>
|
|
38
|
+
{checkIn ? (
|
|
39
|
+
<>
|
|
40
|
+
<Button kind="danger" onClick={handleCheckin}>
|
|
41
|
+
{' '}
|
|
42
|
+
Check Out
|
|
43
|
+
</Button>
|
|
44
|
+
</>
|
|
45
|
+
) : (
|
|
46
|
+
<>
|
|
47
|
+
<Button kind="primary" onClick={handleCheckin}>
|
|
48
|
+
{' '}
|
|
49
|
+
Check In
|
|
50
|
+
</Button>
|
|
51
|
+
</>
|
|
52
|
+
)}
|
|
53
|
+
</div>
|
|
54
|
+
<div className={styles.tableSection}>
|
|
55
|
+
<Table>
|
|
56
|
+
<TableHead>
|
|
57
|
+
<TableRow>
|
|
58
|
+
<TableHeader>No</TableHeader>
|
|
59
|
+
<TableHeader>Name</TableHeader>
|
|
60
|
+
<TableHeader>Ticket</TableHeader>
|
|
61
|
+
<TableHeader>Status</TableHeader>
|
|
62
|
+
<TableHeader>Priority</TableHeader>
|
|
63
|
+
<TableHeader>Action</TableHeader>
|
|
64
|
+
</TableRow>
|
|
65
|
+
</TableHead>
|
|
66
|
+
<TableBody>
|
|
67
|
+
{queueEntries.map((val, index) => (
|
|
68
|
+
<TableRow>
|
|
69
|
+
<TableCell>{index + 1}</TableCell>
|
|
70
|
+
<TableCell>
|
|
71
|
+
{checkIn ? (
|
|
72
|
+
<Link href={`${window.spaBase}/patient/${val.patient_uuid}/chart/`}>
|
|
73
|
+
{val.family_name} {val.middle_name}
|
|
74
|
+
</Link>
|
|
75
|
+
) : (
|
|
76
|
+
<>
|
|
77
|
+
{val.family_name} {val.middle_name}
|
|
78
|
+
</>
|
|
79
|
+
)}
|
|
80
|
+
</TableCell>
|
|
81
|
+
<TableCell>{val.queue_entry_id}</TableCell>
|
|
82
|
+
<TableCell>{val.status}</TableCell>
|
|
83
|
+
<TableCell>{val.priority}</TableCell>
|
|
84
|
+
<TableCell>
|
|
85
|
+
{val.status === 'WAITING' ? (
|
|
86
|
+
<>
|
|
87
|
+
<Button kind="ghost" disabled={!checkIn} onClick={() => handleServePatient(val)}>
|
|
88
|
+
Serve
|
|
89
|
+
</Button>
|
|
90
|
+
</>
|
|
91
|
+
) : (
|
|
92
|
+
<>
|
|
93
|
+
{checkIn ? (
|
|
94
|
+
<>
|
|
95
|
+
<OverflowMenu aria-label="overflow-menu">
|
|
96
|
+
<OverflowMenuItem itemText="Move" onClick={() => handleMovePatient(val)} />
|
|
97
|
+
<OverflowMenuItem itemText="Transition" onClick={() => handleTransitionPatient(val)} />
|
|
98
|
+
<OverflowMenuItem itemText="Remove Patient" />
|
|
99
|
+
</OverflowMenu>
|
|
100
|
+
</>
|
|
101
|
+
) : (
|
|
102
|
+
<></>
|
|
103
|
+
)}
|
|
104
|
+
</>
|
|
105
|
+
)}
|
|
106
|
+
</TableCell>
|
|
107
|
+
</TableRow>
|
|
108
|
+
))}
|
|
109
|
+
</TableBody>
|
|
110
|
+
</Table>
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
</>
|
|
114
|
+
);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export default QueueList;
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import React, { useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { type QueueEntryResult } from '../../registry/types';
|
|
3
|
+
import { useSession } from '@openmrs/esm-framework';
|
|
4
|
+
import { getServiceQueueByLocationUuid } from '../service-queues.resource';
|
|
5
|
+
import { Tab, TabList, TabPanel, TabPanels, Tabs } from '@carbon/react';
|
|
6
|
+
import QueueList from '../queue-list/queue-list.component';
|
|
7
|
+
import styles from './service-queue.component.scss';
|
|
8
|
+
import MovePatientModal from '../modals/move/move-patient.component';
|
|
9
|
+
import TransitionPatientModal from '../modals/transition/transition-patient.component';
|
|
10
|
+
import ServePatientModal from '../modals/serve/serve-patient.comppnent';
|
|
11
|
+
|
|
12
|
+
interface ServiceQueueComponentProps {
|
|
13
|
+
serviceTypeUuid: string;
|
|
14
|
+
title: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const ServiceQueueComponent: React.FC<ServiceQueueComponentProps> = ({ serviceTypeUuid, title }) => {
|
|
18
|
+
const [queueEntries, setQueueEntries] = useState<QueueEntryResult[]>([]);
|
|
19
|
+
const [selectedQueueEntry, setSelectedQueueEntry] = useState<QueueEntryResult>();
|
|
20
|
+
const [displayMoveModal, setDisplayMoveModal] = useState<boolean>();
|
|
21
|
+
const [displayTransitionModal, setDisplayTransitionModal] = useState<boolean>();
|
|
22
|
+
const [displayServeModal, setDisplayServeModal] = useState<boolean>();
|
|
23
|
+
const session = useSession();
|
|
24
|
+
const locationUuid = session.sessionLocation.uuid;
|
|
25
|
+
|
|
26
|
+
const groupEntriesByRooms = () => {
|
|
27
|
+
const roomEntries = {};
|
|
28
|
+
if (!queueEntries || queueEntries.length === 0) return {};
|
|
29
|
+
queueEntries.forEach((qe) => {
|
|
30
|
+
const room = qe.queue_room;
|
|
31
|
+
if (!roomEntries[room]) {
|
|
32
|
+
roomEntries[room] = [qe];
|
|
33
|
+
} else {
|
|
34
|
+
roomEntries[room].push(qe);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
return roomEntries;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const groupedByRoom: { [key: string]: QueueEntryResult[] } = useMemo(() => groupEntriesByRooms(), [queueEntries]);
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
getEntryQueues();
|
|
44
|
+
}, []);
|
|
45
|
+
|
|
46
|
+
const getEntryQueues = async () => {
|
|
47
|
+
const res = await getServiceQueueByLocationUuid(serviceTypeUuid, locationUuid);
|
|
48
|
+
setQueueEntries(res);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
if (!groupedByRoom) {
|
|
52
|
+
return <>No Data to Display</>;
|
|
53
|
+
}
|
|
54
|
+
const handleMovePatient = (queueEntry: QueueEntryResult) => {
|
|
55
|
+
setDisplayMoveModal(true);
|
|
56
|
+
setSelectedQueueEntry(queueEntry);
|
|
57
|
+
};
|
|
58
|
+
const handleModalCloes = () => {
|
|
59
|
+
setDisplayMoveModal(false);
|
|
60
|
+
setDisplayTransitionModal(false);
|
|
61
|
+
setDisplayServeModal(false);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const handleTransitionPatient = (queueEntry: QueueEntryResult) => {
|
|
65
|
+
setDisplayTransitionModal(true);
|
|
66
|
+
setSelectedQueueEntry(queueEntry);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const handleServePatient = (queueEntry: QueueEntryResult) => {
|
|
70
|
+
setDisplayServeModal(true);
|
|
71
|
+
setSelectedQueueEntry(queueEntry);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const navigateToPatientChart = () => {
|
|
75
|
+
if (selectedQueueEntry && selectedQueueEntry.patient_uuid) {
|
|
76
|
+
window.location.href = `${window.spaBase}/patient/${selectedQueueEntry.patient_uuid}/chart`;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const handleSuccessfullServe = () => {
|
|
81
|
+
handleModalCloes();
|
|
82
|
+
navigateToPatientChart();
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
if (!serviceTypeUuid) {
|
|
86
|
+
return <>No service type defined</>;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<>
|
|
91
|
+
<div className={styles.consultationLayout}>
|
|
92
|
+
<div className={styles.headerSection}>
|
|
93
|
+
<h4>{title}</h4>
|
|
94
|
+
</div>
|
|
95
|
+
<div className={styles.contentSection}>
|
|
96
|
+
<Tabs>
|
|
97
|
+
<TabList contained>
|
|
98
|
+
{groupedByRoom &&
|
|
99
|
+
Object.keys(groupedByRoom).map((key) => {
|
|
100
|
+
return <Tab>{key}</Tab>;
|
|
101
|
+
})}
|
|
102
|
+
</TabList>
|
|
103
|
+
<TabPanels>
|
|
104
|
+
{groupedByRoom &&
|
|
105
|
+
Object.keys(groupedByRoom).map((key) => {
|
|
106
|
+
return (
|
|
107
|
+
<TabPanel>
|
|
108
|
+
{
|
|
109
|
+
<QueueList
|
|
110
|
+
queueEntries={groupedByRoom[key]}
|
|
111
|
+
handleMovePatient={handleMovePatient}
|
|
112
|
+
handleTransitionPatient={handleTransitionPatient}
|
|
113
|
+
handleServePatient={handleServePatient}
|
|
114
|
+
/>
|
|
115
|
+
}
|
|
116
|
+
</TabPanel>
|
|
117
|
+
);
|
|
118
|
+
})}
|
|
119
|
+
</TabPanels>
|
|
120
|
+
</Tabs>
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
{displayMoveModal && selectedQueueEntry ? (
|
|
124
|
+
<>
|
|
125
|
+
<MovePatientModal
|
|
126
|
+
open={displayMoveModal}
|
|
127
|
+
locationUuid={locationUuid}
|
|
128
|
+
serviceUuid={serviceTypeUuid}
|
|
129
|
+
onModalClose={handleModalCloes}
|
|
130
|
+
currentQueueEntryUuid={selectedQueueEntry.queue_entry_uuid}
|
|
131
|
+
/>
|
|
132
|
+
</>
|
|
133
|
+
) : (
|
|
134
|
+
<></>
|
|
135
|
+
)}
|
|
136
|
+
|
|
137
|
+
{displayTransitionModal ? (
|
|
138
|
+
<>
|
|
139
|
+
<TransitionPatientModal
|
|
140
|
+
open={displayTransitionModal}
|
|
141
|
+
onModalClose={handleModalCloes}
|
|
142
|
+
currentQueueEntry={selectedQueueEntry}
|
|
143
|
+
/>
|
|
144
|
+
</>
|
|
145
|
+
) : (
|
|
146
|
+
<></>
|
|
147
|
+
)}
|
|
148
|
+
|
|
149
|
+
{displayServeModal ? (
|
|
150
|
+
<>
|
|
151
|
+
<ServePatientModal
|
|
152
|
+
open={displayServeModal}
|
|
153
|
+
onModalClose={handleModalCloes}
|
|
154
|
+
currentQueueEntry={selectedQueueEntry}
|
|
155
|
+
onSuccessfullServe={handleSuccessfullServe}
|
|
156
|
+
/>
|
|
157
|
+
</>
|
|
158
|
+
) : (
|
|
159
|
+
<></>
|
|
160
|
+
)}
|
|
161
|
+
</>
|
|
162
|
+
);
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
export default ServiceQueueComponent;
|