@ampath/esm-dha-workflow-app 4.0.0-next.10 → 4.0.0-next.12
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/16.js +1 -0
- package/dist/16.js.map +1 -0
- package/dist/198.js +1 -1
- package/dist/860.js +1 -1
- package/dist/860.js.map +1 -1
- package/dist/91.js +1 -1
- package/dist/91.js.map +1 -1
- package/dist/970.js +2 -0
- package/dist/970.js.map +1 -0
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-home-app.js +1 -1
- package/dist/openmrs-esm-home-app.js.buildmanifest.json +43 -43
- package/dist/openmrs-esm-home-app.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/registry/modal/client-details-modal/client-details-modal.tsx +11 -5
- package/src/registry/modal/send-to-triage/send-to-triage.modal.scss +24 -0
- package/src/registry/modal/send-to-triage/send-to-triage.modal.tsx +258 -0
- package/src/registry/registry.component.scss +9 -0
- package/src/registry/registry.component.tsx +60 -8
- package/src/registry/registry.resource.ts +1 -2
- package/src/registry/types/index.ts +63 -0
- package/src/registry/utils/error-handler.ts +4 -0
- package/src/resources/patient-search.resource.ts +22 -0
- package/src/resources/queue.resource.ts +37 -0
- package/src/resources/visit.resource.ts +20 -0
- package/src/root.component.tsx +2 -0
- package/src/shared/constants/concepts.ts +17 -0
- package/src/shared/constants/index.ts +2 -0
- package/dist/161.js +0 -1
- package/dist/161.js.map +0 -1
- package/dist/916.js +0 -2
- package/dist/916.js.map +0 -1
- package/src/resources/resources.component.tsx +0 -56
- package/src/resources/resources.scss +0 -68
- /package/dist/{916.js.LICENSE.txt → 970.js.LICENSE.txt} +0 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
Checkbox,
|
|
5
|
+
Dropdown,
|
|
6
|
+
InlineLoading,
|
|
7
|
+
Modal,
|
|
8
|
+
ModalBody,
|
|
9
|
+
Select,
|
|
10
|
+
SelectItem,
|
|
11
|
+
Table,
|
|
12
|
+
TableBody,
|
|
13
|
+
TableCell,
|
|
14
|
+
TableHead,
|
|
15
|
+
TableHeader,
|
|
16
|
+
TableRow,
|
|
17
|
+
} from '@carbon/react';
|
|
18
|
+
import styles from './send-to-triage.modal.scss';
|
|
19
|
+
import {
|
|
20
|
+
type VisitType,
|
|
21
|
+
type Patient,
|
|
22
|
+
useVisitTypes,
|
|
23
|
+
useSession,
|
|
24
|
+
showSnackbar,
|
|
25
|
+
type Visit,
|
|
26
|
+
} from '@openmrs/esm-framework';
|
|
27
|
+
import { type CreateVisitDto, type QueueEntryDto, type ServiceQueue } from '../../types';
|
|
28
|
+
import { createQueueEntry, fetchServiceQueuesByLocationUuid } from '../../../resources/queue.resource';
|
|
29
|
+
import { QUEUE_PRIORITIES_UUIDS, QUEUE_STATUS_UUIDS } from '../../../shared/constants/concepts';
|
|
30
|
+
import { createVisit } from '../../../resources/visit.resource';
|
|
31
|
+
|
|
32
|
+
interface SendToTriageModalProps {
|
|
33
|
+
patients: Patient[];
|
|
34
|
+
open: boolean;
|
|
35
|
+
onModalClose: (modalCloseResp?: { success: boolean }) => void;
|
|
36
|
+
onSubmit: () => void;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const SendToTriageModal: React.FC<SendToTriageModalProps> = ({ patients, open, onModalClose, onSubmit }) => {
|
|
40
|
+
const [selectedPatient, setSelectedPatient] = useState<Patient>();
|
|
41
|
+
const [selectedVisitType, setSelectedVisitType] = useState<string>();
|
|
42
|
+
const [serviceQueues, setServiceQueues] = useState<ServiceQueue[]>();
|
|
43
|
+
const [selectedServiceQueue, setSelectedServiceQueue] = useState<string>();
|
|
44
|
+
const [selectedPriority, setSelectedPriority] = useState<string>('');
|
|
45
|
+
const [loading, setLoading] = useState<boolean>(false);
|
|
46
|
+
const visitTypes = useVisitTypes();
|
|
47
|
+
const session = useSession();
|
|
48
|
+
const locationUuid = session.sessionLocation.uuid;
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
getServiceQueues();
|
|
51
|
+
}, [patients]);
|
|
52
|
+
if (!patients) {
|
|
53
|
+
return <>No Client data</>;
|
|
54
|
+
}
|
|
55
|
+
const registerOnAfyaYangu = () => {
|
|
56
|
+
window.open('https://afyayangu.go.ke/', '_blank');
|
|
57
|
+
};
|
|
58
|
+
const sendToTriage = async () => {
|
|
59
|
+
setLoading(true);
|
|
60
|
+
try {
|
|
61
|
+
const newVisit = await createPatientVisit();
|
|
62
|
+
if (newVisit) {
|
|
63
|
+
const addToTriageQueueDto: QueueEntryDto = generateAddToTriageDto(newVisit.uuid);
|
|
64
|
+
const queueEntryResp = await createQueueEntry(addToTriageQueueDto);
|
|
65
|
+
if (queueEntryResp) {
|
|
66
|
+
showAlert('success', 'Patient has succesfully been moved to the Triage queue', '');
|
|
67
|
+
onModalClose({ success: true });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
} catch (error) {
|
|
71
|
+
showAlert('error', 'Error creating visit', '');
|
|
72
|
+
} finally {
|
|
73
|
+
setLoading(false);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const generateAddToTriageDto = (newVisitUuid: string): QueueEntryDto => {
|
|
77
|
+
const payload: QueueEntryDto = {
|
|
78
|
+
visit: {
|
|
79
|
+
uuid: newVisitUuid,
|
|
80
|
+
},
|
|
81
|
+
queueEntry: {
|
|
82
|
+
status: {
|
|
83
|
+
uuid: QUEUE_STATUS_UUIDS.WAITING_UUID,
|
|
84
|
+
},
|
|
85
|
+
priority: {
|
|
86
|
+
uuid: selectedPriority,
|
|
87
|
+
},
|
|
88
|
+
queue: {
|
|
89
|
+
uuid: selectedServiceQueue,
|
|
90
|
+
},
|
|
91
|
+
patient: {
|
|
92
|
+
uuid: selectedPatient.uuid,
|
|
93
|
+
},
|
|
94
|
+
startedAt: new Date().toISOString(),
|
|
95
|
+
sortWeight: 0,
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
return payload;
|
|
99
|
+
};
|
|
100
|
+
const onPatientSelect = (patient: Patient) => {
|
|
101
|
+
setSelectedPatient(patient);
|
|
102
|
+
};
|
|
103
|
+
const getServiceQueues = async () => {
|
|
104
|
+
const resp = await fetchServiceQueuesByLocationUuid(locationUuid);
|
|
105
|
+
if (resp && resp.results) {
|
|
106
|
+
setServiceQueues(resp.results);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
const visitTypeChangeHandler = ($event: any) => {
|
|
110
|
+
const vt = $event.target.value as unknown as string;
|
|
111
|
+
setSelectedVisitType(vt);
|
|
112
|
+
};
|
|
113
|
+
const serviceChangeHandler = ($event: any) => {
|
|
114
|
+
const sq = $event.target.value as unknown as string;
|
|
115
|
+
setSelectedServiceQueue(sq);
|
|
116
|
+
};
|
|
117
|
+
const priorityChangeHandler = (priorityUuid: string) => {
|
|
118
|
+
setSelectedPriority(priorityUuid);
|
|
119
|
+
};
|
|
120
|
+
const createPatientVisit = async () => {
|
|
121
|
+
const visitDto = getCreateVisitDto();
|
|
122
|
+
if (!isValidCreateVisitDto(visitDto)) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const result = await createVisit(visitDto);
|
|
127
|
+
if (result) {
|
|
128
|
+
showAlert('success', 'Visit has been created succesfully', '');
|
|
129
|
+
return result;
|
|
130
|
+
} else {
|
|
131
|
+
showAlert('error', 'Error creating patient visit', '');
|
|
132
|
+
throw new Error('Error creating patient visit');
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
const isValidCreateVisitDto = (createVisitDto: CreateVisitDto): boolean => {
|
|
136
|
+
if (!createVisitDto.location) {
|
|
137
|
+
showAlert('error', 'Missing location in create visits', '');
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
if (!createVisitDto.patient) {
|
|
141
|
+
showAlert('error', 'Please select a patient', '');
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (!createVisitDto.visitType) {
|
|
146
|
+
showAlert('error', 'Please select a visit', '');
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
return true;
|
|
150
|
+
};
|
|
151
|
+
const getCreateVisitDto = (): CreateVisitDto => {
|
|
152
|
+
return {
|
|
153
|
+
visitType: selectedVisitType,
|
|
154
|
+
location: locationUuid,
|
|
155
|
+
startDatetime: null,
|
|
156
|
+
stopDatetime: null,
|
|
157
|
+
patient: selectedPatient?.uuid ?? '',
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
const showAlert = (alertType: 'error' | 'success', title: string, subtitle: string) => {
|
|
161
|
+
showSnackbar({
|
|
162
|
+
kind: alertType,
|
|
163
|
+
title: title,
|
|
164
|
+
subtitle: subtitle,
|
|
165
|
+
});
|
|
166
|
+
};
|
|
167
|
+
return (
|
|
168
|
+
<>
|
|
169
|
+
<Modal
|
|
170
|
+
open={open}
|
|
171
|
+
size="md"
|
|
172
|
+
onSecondarySubmit={() => onModalClose({ success: false })}
|
|
173
|
+
onRequestClose={() => onModalClose({ success: false })}
|
|
174
|
+
onRequestSubmit={registerOnAfyaYangu}
|
|
175
|
+
primaryButtonText="Register on Afya Yangu"
|
|
176
|
+
secondaryButtonText="Cancel"
|
|
177
|
+
>
|
|
178
|
+
<ModalBody>
|
|
179
|
+
<div className={styles.clientDetailsLayout}>
|
|
180
|
+
<div className={styles.sectionHeader}>
|
|
181
|
+
<h4 className={styles.sectionTitle}>Send To Triage</h4>
|
|
182
|
+
</div>
|
|
183
|
+
<div className={styles.sectionContent}>
|
|
184
|
+
<div className={styles.patientSelect}>
|
|
185
|
+
<Table>
|
|
186
|
+
<TableHead>
|
|
187
|
+
<TableRow>
|
|
188
|
+
<TableHeader>No</TableHeader>
|
|
189
|
+
<TableHeader>Name</TableHeader>
|
|
190
|
+
<TableHeader>DOB</TableHeader>
|
|
191
|
+
<TableHeader>Select Patient</TableHeader>
|
|
192
|
+
</TableRow>
|
|
193
|
+
</TableHead>
|
|
194
|
+
<TableBody>
|
|
195
|
+
{patients.map((p, index) => (
|
|
196
|
+
<TableRow key={p.uuid}>
|
|
197
|
+
<TableCell>{index + 1}</TableCell>
|
|
198
|
+
<TableCell>{p.person.preferredName.display}</TableCell>
|
|
199
|
+
<TableCell>{p.person.birthdate}</TableCell>
|
|
200
|
+
<TableCell>
|
|
201
|
+
<Checkbox id={p.uuid} labelText="" onChange={() => onPatientSelect(p)} />
|
|
202
|
+
</TableCell>
|
|
203
|
+
</TableRow>
|
|
204
|
+
))}
|
|
205
|
+
</TableBody>
|
|
206
|
+
</Table>
|
|
207
|
+
</div>
|
|
208
|
+
<div className={styles.formSection}>
|
|
209
|
+
<div className={styles.formRow}>
|
|
210
|
+
<div className={styles.formControl}>
|
|
211
|
+
<Select id="visit-type" labelText="Select a Visit Type" onChange={visitTypeChangeHandler}>
|
|
212
|
+
<SelectItem value="" text="Select" />;
|
|
213
|
+
{visitTypes &&
|
|
214
|
+
visitTypes.map((vt) => {
|
|
215
|
+
return <SelectItem value={vt.uuid} text={vt.display} />;
|
|
216
|
+
})}
|
|
217
|
+
</Select>
|
|
218
|
+
</div>
|
|
219
|
+
<div className={styles.formControl}>
|
|
220
|
+
<Select id="service" labelText="Select a Service" onChange={serviceChangeHandler}>
|
|
221
|
+
<SelectItem value="" text="Select" />;
|
|
222
|
+
{serviceQueues &&
|
|
223
|
+
serviceQueues.map((sq) => {
|
|
224
|
+
return <SelectItem value={sq.uuid} text={sq.display} />;
|
|
225
|
+
})}
|
|
226
|
+
</Select>
|
|
227
|
+
</div>
|
|
228
|
+
</div>
|
|
229
|
+
<div className={styles.formRow}>
|
|
230
|
+
<div className={styles.formControl}>
|
|
231
|
+
<Select
|
|
232
|
+
id="priority"
|
|
233
|
+
labelText="Select Priority"
|
|
234
|
+
onChange={($event) => priorityChangeHandler($event.target.value)}
|
|
235
|
+
>
|
|
236
|
+
<SelectItem value="" text="Select" />;
|
|
237
|
+
<SelectItem value={QUEUE_PRIORITIES_UUIDS.NORMAL_PRIORITY_UUID} text="NORMAL" />;
|
|
238
|
+
<SelectItem value={QUEUE_PRIORITIES_UUIDS.EMERGENCY_PRIORITY_UUID} text="EMERGENCY" />;
|
|
239
|
+
</Select>
|
|
240
|
+
</div>
|
|
241
|
+
</div>
|
|
242
|
+
</div>
|
|
243
|
+
</div>
|
|
244
|
+
<div className={styles.actionSection}>
|
|
245
|
+
<div className={styles.btnContainer}>
|
|
246
|
+
<Button kind="primary" onClick={sendToTriage}>
|
|
247
|
+
{loading ? <InlineLoading description="Sending To Triage..." /> : 'Send To Triage'}
|
|
248
|
+
</Button>
|
|
249
|
+
</div>
|
|
250
|
+
</div>
|
|
251
|
+
</div>
|
|
252
|
+
</ModalBody>
|
|
253
|
+
</Modal>
|
|
254
|
+
</>
|
|
255
|
+
);
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
export default SendToTriageModal;
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
flex-direction: row;
|
|
27
27
|
width: 100%;
|
|
28
28
|
column-gap: 5px;
|
|
29
|
+
margin-top: 10px;
|
|
29
30
|
}
|
|
30
31
|
.formControl{
|
|
31
32
|
width: 30%;
|
|
@@ -60,4 +61,12 @@
|
|
|
60
61
|
flex-direction: row;
|
|
61
62
|
width: 30%;
|
|
62
63
|
column-gap: 5px;
|
|
64
|
+
}
|
|
65
|
+
.formBtn{
|
|
66
|
+
display: flex;
|
|
67
|
+
flex-direction: row;
|
|
68
|
+
column-gap: 5px;
|
|
69
|
+
}
|
|
70
|
+
.registrySearchBtn{
|
|
71
|
+
height: 30px;
|
|
63
72
|
}
|
|
@@ -17,23 +17,29 @@ import React, { useState } from 'react';
|
|
|
17
17
|
import styles from './registry.component.scss';
|
|
18
18
|
import { type HieClient, IDENTIFIER_TYPES, type IdentifierType, type RequestCustomOtpDto } from './types';
|
|
19
19
|
import { fetchClientRegistryData } from './registry.resource';
|
|
20
|
-
import {
|
|
20
|
+
import { type Patient, showSnackbar, useSession } from '@openmrs/esm-framework';
|
|
21
21
|
import OtpVerificationModal from './modal/otp-verification-modal/otp-verification-modal';
|
|
22
22
|
import { maskExceptFirstAndLast, maskValue } from './utils/mask-data';
|
|
23
23
|
import ClientDetailsModal from './modal/client-details-modal/client-details-modal';
|
|
24
|
-
import
|
|
24
|
+
import { searchPatientByCrNumber } from '../resources/patient-search.resource';
|
|
25
|
+
import SendToTriageModal from './modal/send-to-triage/send-to-triage.modal';
|
|
26
|
+
import { useNavigate } from 'react-router-dom';
|
|
27
|
+
|
|
25
28
|
interface RegistryComponentProps {}
|
|
26
29
|
const RegistryComponent: React.FC<RegistryComponentProps> = () => {
|
|
27
30
|
const [identifierType, setIdentifierType] = useState<IdentifierType>('National ID');
|
|
28
31
|
const [identifierValue, setIdentifierValue] = useState('');
|
|
29
32
|
const [loading, setLoading] = useState<boolean>(false);
|
|
30
33
|
const [client, setClient] = useState<HieClient>();
|
|
34
|
+
const [amrsPatients, setAmrsPatient] = useState<Patient[]>();
|
|
31
35
|
const [selectedPatient, setSelectedPatient] = useState<string>('principal');
|
|
32
36
|
const [displayOtpModal, setDisplayOtpModal] = useState<boolean>(false);
|
|
33
37
|
const [displayClientDetailsModal, setDisplayClientDetailsModal] = useState<boolean>(false);
|
|
38
|
+
const [displaytriageModal, setDisplaytriageModal] = useState<boolean>(false);
|
|
34
39
|
const [requestCustomOtpDto, setRequestCustomOtpDto] = useState<RequestCustomOtpDto>();
|
|
35
40
|
const session = useSession();
|
|
36
41
|
const locationUuid = session.sessionLocation.uuid;
|
|
42
|
+
const navigate = useNavigate();
|
|
37
43
|
|
|
38
44
|
const handleSearchPatient = async () => {
|
|
39
45
|
setLoading(true);
|
|
@@ -101,10 +107,25 @@ const RegistryComponent: React.FC<RegistryComponentProps> = () => {
|
|
|
101
107
|
const handleClientDetailsSubmit = () => {
|
|
102
108
|
return;
|
|
103
109
|
};
|
|
110
|
+
const handleEmergencyRegistration = () => {
|
|
111
|
+
window.location.href = `${window.spaBase}/patient-registration`;
|
|
112
|
+
};
|
|
113
|
+
const handleSendClientToTriage = async (crId: string) => {
|
|
114
|
+
onClientDetailsModalClose();
|
|
115
|
+
const resp = await searchPatientByCrNumber(crId);
|
|
116
|
+
if (resp.totalCount > 0) {
|
|
117
|
+
setAmrsPatient(resp.results);
|
|
118
|
+
setDisplaytriageModal(true);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
const onSendToTriageModalClose = (modalCloseResp?: { success: boolean }) => {
|
|
122
|
+
setDisplaytriageModal(false);
|
|
123
|
+
if (modalCloseResp && modalCloseResp.success) {
|
|
124
|
+
navigate('/triage');
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
const handleSendToTriageModalSubmit = () => {};
|
|
104
128
|
return (
|
|
105
|
-
/*
|
|
106
|
-
To be refactored ton use gloab-nav-slot
|
|
107
|
-
*/
|
|
108
129
|
<>
|
|
109
130
|
<div className={styles.registryLayout}>
|
|
110
131
|
<div className={styles.mainContent}>
|
|
@@ -134,10 +155,27 @@ const RegistryComponent: React.FC<RegistryComponentProps> = () => {
|
|
|
134
155
|
placeholder={`Enter ${identifierType.toLowerCase()} value`}
|
|
135
156
|
/>
|
|
136
157
|
</div>
|
|
158
|
+
</div>
|
|
159
|
+
<div className={styles.formRow}>
|
|
137
160
|
<div className={styles.formControl}>
|
|
138
|
-
<
|
|
139
|
-
|
|
140
|
-
|
|
161
|
+
<div className={styles.formBtn}>
|
|
162
|
+
<Button
|
|
163
|
+
className={styles.registrySearchBtn}
|
|
164
|
+
kind="primary"
|
|
165
|
+
onClick={handleSearchPatient}
|
|
166
|
+
disabled={loading}
|
|
167
|
+
>
|
|
168
|
+
{loading ? <InlineLoading description="Searching..." /> : 'Search'}
|
|
169
|
+
</Button>
|
|
170
|
+
<Button
|
|
171
|
+
className={styles.registrySearchBtn}
|
|
172
|
+
kind="secondary"
|
|
173
|
+
onClick={handleEmergencyRegistration}
|
|
174
|
+
disabled={loading}
|
|
175
|
+
>
|
|
176
|
+
Emergency Registration
|
|
177
|
+
</Button>
|
|
178
|
+
</div>
|
|
141
179
|
</div>
|
|
142
180
|
</div>
|
|
143
181
|
{client ? (
|
|
@@ -249,11 +287,25 @@ const RegistryComponent: React.FC<RegistryComponentProps> = () => {
|
|
|
249
287
|
open={displayClientDetailsModal}
|
|
250
288
|
onModalClose={onClientDetailsModalClose}
|
|
251
289
|
onSubmit={handleClientDetailsSubmit}
|
|
290
|
+
onSendClientToTriage={handleSendClientToTriage}
|
|
252
291
|
/>{' '}
|
|
253
292
|
</>
|
|
254
293
|
) : (
|
|
255
294
|
<></>
|
|
256
295
|
)}
|
|
296
|
+
|
|
297
|
+
{client && displaytriageModal ? (
|
|
298
|
+
<>
|
|
299
|
+
<SendToTriageModal
|
|
300
|
+
patients={amrsPatients}
|
|
301
|
+
open={displaytriageModal}
|
|
302
|
+
onModalClose={onSendToTriageModalClose}
|
|
303
|
+
onSubmit={handleSendToTriageModalSubmit}
|
|
304
|
+
/>
|
|
305
|
+
</>
|
|
306
|
+
) : (
|
|
307
|
+
<></>
|
|
308
|
+
)}
|
|
257
309
|
</div>
|
|
258
310
|
</div>
|
|
259
311
|
) : (
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HIE_BASE_URL } from '../shared/constants';
|
|
1
2
|
import {
|
|
2
3
|
type ClientRegistrySearchRequest,
|
|
3
4
|
type RequestCustomOtpDto,
|
|
@@ -6,8 +7,6 @@ import {
|
|
|
6
7
|
type ValidateHieCustomOtpDto,
|
|
7
8
|
} from './types';
|
|
8
9
|
|
|
9
|
-
const HIE_BASE_URL = 'https://staging.ampath.or.ke/hie';
|
|
10
|
-
|
|
11
10
|
export type ClientRegistrySearchResponse = any[];
|
|
12
11
|
|
|
13
12
|
async function postJson<T>(url: string, payload: unknown): Promise<T> {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Location, type Patient } from '@openmrs/esm-framework';
|
|
2
|
+
|
|
1
3
|
export type IdentifierType = 'National ID' | 'Alien ID' | 'Passport' | 'Mandate Number' | 'Refugee ID';
|
|
2
4
|
|
|
3
5
|
export const IDENTIFIER_TYPES: IdentifierType[] = [
|
|
@@ -158,3 +160,64 @@ export interface HieClient {
|
|
|
158
160
|
is_agent: number;
|
|
159
161
|
agent_id: string;
|
|
160
162
|
}
|
|
163
|
+
|
|
164
|
+
export type PatientSearchResponse = {
|
|
165
|
+
results: Patient[];
|
|
166
|
+
totalCount: number;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
export type QueuePriority = {
|
|
170
|
+
uuid: string;
|
|
171
|
+
display: string;
|
|
172
|
+
};
|
|
173
|
+
export type QueueStatus = {
|
|
174
|
+
uuid: string;
|
|
175
|
+
display: string;
|
|
176
|
+
};
|
|
177
|
+
export type ServiceQueue = {
|
|
178
|
+
uuid: string;
|
|
179
|
+
display: string;
|
|
180
|
+
name: string;
|
|
181
|
+
description: string;
|
|
182
|
+
service: {
|
|
183
|
+
uuid: string;
|
|
184
|
+
display: string;
|
|
185
|
+
};
|
|
186
|
+
allowedPriorities: QueuePriority[];
|
|
187
|
+
allowedStatuses: QueueStatus[];
|
|
188
|
+
location: Location;
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
export type ServiceQueueApiResponse = {
|
|
192
|
+
results: ServiceQueue[];
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
export type QueueEntryDto = {
|
|
196
|
+
visit: {
|
|
197
|
+
uuid: string;
|
|
198
|
+
};
|
|
199
|
+
queueEntry: {
|
|
200
|
+
status: {
|
|
201
|
+
uuid: string;
|
|
202
|
+
};
|
|
203
|
+
priority: {
|
|
204
|
+
uuid: string;
|
|
205
|
+
};
|
|
206
|
+
queue: {
|
|
207
|
+
uuid: string;
|
|
208
|
+
};
|
|
209
|
+
patient: {
|
|
210
|
+
uuid: string;
|
|
211
|
+
};
|
|
212
|
+
startedAt: string;
|
|
213
|
+
sortWeight: number;
|
|
214
|
+
};
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
export type CreateVisitDto = {
|
|
218
|
+
visitType: string;
|
|
219
|
+
location: string;
|
|
220
|
+
startDatetime: null | string;
|
|
221
|
+
stopDatetime: null | string;
|
|
222
|
+
patient: string;
|
|
223
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
|
|
2
|
+
import { type PatientSearchResponse } from '../registry/types';
|
|
3
|
+
|
|
4
|
+
export async function searchPatientByCrNumber<T>(cr_id: string): Promise<PatientSearchResponse> {
|
|
5
|
+
const url = `${restBaseUrl}/patient`;
|
|
6
|
+
const params = {
|
|
7
|
+
q: cr_id,
|
|
8
|
+
v: 'full',
|
|
9
|
+
includeDead: 'true',
|
|
10
|
+
limit: '10',
|
|
11
|
+
totalCount: 'true',
|
|
12
|
+
};
|
|
13
|
+
const queryString = new URLSearchParams(params).toString();
|
|
14
|
+
const response = await openmrsFetch(`${url}?${queryString}`);
|
|
15
|
+
|
|
16
|
+
if (!response.ok) {
|
|
17
|
+
const errorText = await response.text();
|
|
18
|
+
throw new Error(`Request failed with ${response.status}: ${errorText}`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return response.json();
|
|
22
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
|
|
2
|
+
import { type QueueEntryDto, type ServiceQueueApiResponse } from '../registry/types';
|
|
3
|
+
|
|
4
|
+
export async function fetchServiceQueuesByLocationUuid<T>(locationUuid: string): Promise<ServiceQueueApiResponse> {
|
|
5
|
+
const url = `${restBaseUrl}/queue`;
|
|
6
|
+
const params = {
|
|
7
|
+
v: 'custom:(uuid,display,name,description,service:(uuid,display),allowedPriorities:(uuid,display),allowedStatuses:(uuid,display),location:(uuid,display))',
|
|
8
|
+
location: locationUuid,
|
|
9
|
+
};
|
|
10
|
+
const queryString = new URLSearchParams(params).toString();
|
|
11
|
+
const response = await openmrsFetch(`${url}?${queryString}`);
|
|
12
|
+
|
|
13
|
+
if (!response.ok) {
|
|
14
|
+
const errorText = await response.text();
|
|
15
|
+
throw new Error(`Request failed with ${response.status}: ${errorText}`);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return response.json();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function createQueueEntry(createQueueEntryDto: QueueEntryDto) {
|
|
22
|
+
const url = `${restBaseUrl}/visit-queue-entry`;
|
|
23
|
+
const response = await openmrsFetch(url, {
|
|
24
|
+
method: 'POST',
|
|
25
|
+
headers: {
|
|
26
|
+
'content-type': 'application/json',
|
|
27
|
+
},
|
|
28
|
+
body: JSON.stringify(createQueueEntryDto),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
const errorText = await response.text();
|
|
33
|
+
throw new Error(`Request failed with ${response.status}: ${errorText}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return response.json();
|
|
37
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
|
|
2
|
+
import { type CreateVisitDto } from '../registry/types';
|
|
3
|
+
|
|
4
|
+
export async function createVisit(createVisitDto: CreateVisitDto) {
|
|
5
|
+
const url = `${restBaseUrl}/visit`;
|
|
6
|
+
const response = await openmrsFetch(url, {
|
|
7
|
+
method: 'POST',
|
|
8
|
+
headers: {
|
|
9
|
+
'content-type': 'application/json',
|
|
10
|
+
},
|
|
11
|
+
body: JSON.stringify(createVisitDto),
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
if (!response.ok) {
|
|
15
|
+
const errorText = await response.text();
|
|
16
|
+
throw new Error(`Request failed with ${response.status}: ${errorText}`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return response.json();
|
|
20
|
+
}
|
package/src/root.component.tsx
CHANGED
|
@@ -14,7 +14,9 @@ const Root: React.FC = () => {
|
|
|
14
14
|
<Routes>
|
|
15
15
|
<Route path="" element={<RegistryComponent />} />
|
|
16
16
|
<Route path="registry" element={<RegistryComponent />} />
|
|
17
|
+
<Route path="triage" element={<Consultation />} />
|
|
17
18
|
<Route path="consultation" element={<Consultation />} />
|
|
19
|
+
<Route path="*" element={<RegistryComponent />} />
|
|
18
20
|
</Routes>
|
|
19
21
|
</main>
|
|
20
22
|
<WorkspaceContainer contextKey="home" />
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const NORMAL_PRIORITY_UUID = 'bbd99c12-67e9-4381-8b4c-1f231e86f8e2';
|
|
2
|
+
const EMERGENCY_PRIORITY_UUID = '8e86ff12-ec83-41e8-a534-bb410739d880';
|
|
3
|
+
|
|
4
|
+
const WAITING_UUID = '89d01aa5-0ab0-4626-934b-37766b4cd779';
|
|
5
|
+
const IN_SERVICE_UUID = 'f9cf5768-508f-45de-8d40-eaf6ea3f3b02';
|
|
6
|
+
const COMPLETED_UUID = 'a89c1ef8-1350-11df-a1f1-0026b9348838';
|
|
7
|
+
|
|
8
|
+
export const QUEUE_PRIORITIES_UUIDS = {
|
|
9
|
+
NORMAL_PRIORITY_UUID,
|
|
10
|
+
EMERGENCY_PRIORITY_UUID,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const QUEUE_STATUS_UUIDS = {
|
|
14
|
+
WAITING_UUID,
|
|
15
|
+
IN_SERVICE_UUID,
|
|
16
|
+
COMPLETED_UUID,
|
|
17
|
+
};
|