@ampath/esm-patient-registration-app 9.2.0-next.16 → 9.2.0-next.18
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/2498.js +2 -0
- package/dist/2498.js.map +1 -0
- package/dist/4395.js +1 -1
- package/dist/4395.js.map +1 -1
- package/dist/5239.js +1 -1
- package/dist/5239.js.map +1 -1
- package/dist/6276.js +1 -1
- package/dist/6276.js.map +1 -1
- package/dist/6741.js +1 -0
- package/dist/6741.js.map +1 -0
- package/dist/7821.js +1 -1
- package/dist/7821.js.map +1 -1
- package/dist/8414.js +1 -1
- package/dist/8414.js.map +1 -1
- package/dist/8434.js +1 -1
- package/dist/8434.js.map +1 -1
- package/dist/8882.js +1 -1
- package/dist/8882.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-patient-registration-app.js +1 -1
- package/dist/openmrs-esm-patient-registration-app.js.buildmanifest.json +56 -56
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/patient-registration/client-registry/client-dependants/list/client-depandants.component.tsx +55 -0
- package/src/patient-registration/client-registry/client-details/client-details.tsx +42 -0
- package/src/patient-registration/client-registry/client-registry-search.component.tsx +156 -69
- package/src/patient-registration/client-registry/client-registry-search.scss +26 -0
- package/src/patient-registration/client-registry/client-registry.resource.ts +1 -1
- package/src/patient-registration/client-registry/hie-client-adapter.ts +56 -0
- package/src/patient-registration/client-registry/types/index.ts +200 -0
- package/src/patient-registration/client-registry-search/client-registry.resource.ts +1 -1
- package/src/patient-registration/custom-patient-registration.scss +6 -0
- package/src/patient-registration/patient-registration.component.tsx +23 -12
- package/src/patient-registration/patient-registration.resource.ts +4 -5
- package/dist/6996.js +0 -1
- package/dist/6996.js.map +0 -1
- package/dist/9933.js +0 -2
- package/dist/9933.js.map +0 -1
- /package/dist/{9933.js.LICENSE.txt → 2498.js.LICENSE.txt} +0 -0
|
@@ -1,13 +1,31 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
TextInput,
|
|
5
|
+
InlineLoading,
|
|
6
|
+
InlineNotification,
|
|
7
|
+
Dropdown,
|
|
8
|
+
Modal,
|
|
9
|
+
ModalBody,
|
|
10
|
+
Tabs,
|
|
11
|
+
TabList,
|
|
12
|
+
Tab,
|
|
13
|
+
TabPanels,
|
|
14
|
+
TabPanel,
|
|
15
|
+
} from '@carbon/react';
|
|
3
16
|
import { showSnackbar, useSession } from '@openmrs/esm-framework';
|
|
4
17
|
import { useFormikContext } from 'formik';
|
|
5
|
-
import styles from '
|
|
18
|
+
import styles from './client-registry-search.scss';
|
|
6
19
|
import { requestCustomOtp, validateCustomOtp, fetchClientRegistryData } from './client-registry.resource';
|
|
7
20
|
import { applyClientRegistryMapping } from './map-client-registry-to-form-utils';
|
|
21
|
+
import ClientDetails from './client-details/client-details';
|
|
22
|
+
import { type HieClient } from './types';
|
|
23
|
+
import ClientDependantList from './client-dependants/list/client-depandants.component';
|
|
8
24
|
|
|
9
25
|
export interface ClientRegistryLookupSectionProps {
|
|
10
26
|
onClientVerified?: () => void;
|
|
27
|
+
onModalClose: () => void;
|
|
28
|
+
open: boolean;
|
|
11
29
|
}
|
|
12
30
|
|
|
13
31
|
export type IdentifierType = 'National ID' | 'Alien ID' | 'Passport' | 'Mandate Number' | 'Refugee ID';
|
|
@@ -20,7 +38,11 @@ export const IDENTIFIER_TYPES: IdentifierType[] = [
|
|
|
20
38
|
'Refugee ID',
|
|
21
39
|
];
|
|
22
40
|
|
|
23
|
-
const ClientRegistryLookupSection: React.FC<ClientRegistryLookupSectionProps> = ({
|
|
41
|
+
const ClientRegistryLookupSection: React.FC<ClientRegistryLookupSectionProps> = ({
|
|
42
|
+
onClientVerified,
|
|
43
|
+
open,
|
|
44
|
+
onModalClose,
|
|
45
|
+
}) => {
|
|
24
46
|
const { setFieldValue } = useFormikContext<any>();
|
|
25
47
|
const [identifierType, setIdentifierType] = useState<IdentifierType>('National ID');
|
|
26
48
|
const [identifierValue, setIdentifierValue] = useState('');
|
|
@@ -31,6 +53,7 @@ const ClientRegistryLookupSection: React.FC<ClientRegistryLookupSectionProps> =
|
|
|
31
53
|
const [sessionId, setSessionId] = useState('');
|
|
32
54
|
const [error, setError] = useState<string>('');
|
|
33
55
|
const { sessionLocation } = useSession();
|
|
56
|
+
const [client, setClient] = useState<HieClient>();
|
|
34
57
|
const locationUuid = sessionLocation?.uuid;
|
|
35
58
|
|
|
36
59
|
async function withTimeout<T>(promise: Promise<T>, ms = 10000): Promise<T> {
|
|
@@ -64,8 +87,7 @@ const ClientRegistryLookupSection: React.FC<ClientRegistryLookupSectionProps> =
|
|
|
64
87
|
if (patients.length === 0) throw new Error('No matching patient found in Client Registry.');
|
|
65
88
|
|
|
66
89
|
const patient = patients[0];
|
|
67
|
-
|
|
68
|
-
|
|
90
|
+
setClient(patient);
|
|
69
91
|
showSnackbar({
|
|
70
92
|
kind: 'success',
|
|
71
93
|
title: 'Client Data Loaded',
|
|
@@ -156,77 +178,142 @@ const ClientRegistryLookupSection: React.FC<ClientRegistryLookupSectionProps> =
|
|
|
156
178
|
}
|
|
157
179
|
};
|
|
158
180
|
|
|
181
|
+
const useHieData = () => {
|
|
182
|
+
applyClientRegistryMapping(client, setFieldValue);
|
|
183
|
+
onModalClose();
|
|
184
|
+
};
|
|
185
|
+
const registerOnAfyaYangu = () => {
|
|
186
|
+
window.open('https://afyayangu.go.ke/', '_blank');
|
|
187
|
+
};
|
|
188
|
+
|
|
159
189
|
return (
|
|
160
|
-
<
|
|
161
|
-
|
|
190
|
+
<Modal
|
|
191
|
+
open={open}
|
|
192
|
+
size="lg"
|
|
193
|
+
onSecondarySubmit={onModalClose}
|
|
194
|
+
onRequestClose={onModalClose}
|
|
195
|
+
onRequestSubmit={registerOnAfyaYangu}
|
|
196
|
+
primaryButtonText="Register on Afya Yangu"
|
|
197
|
+
secondaryButtonText="Cancel">
|
|
198
|
+
<ModalBody>
|
|
199
|
+
<div className={styles.modalVerificationLayout}>
|
|
200
|
+
<h4 className={styles.sectionTitle}>Client Registry Verification</h4>
|
|
162
201
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
</div>
|
|
167
|
-
)}
|
|
168
|
-
|
|
169
|
-
<div className={styles.fieldGroup}>
|
|
170
|
-
<Dropdown
|
|
171
|
-
id="identifier-type-dropdown"
|
|
172
|
-
label="Identifier Type"
|
|
173
|
-
titleText="Select Identifier Type"
|
|
174
|
-
items={IDENTIFIER_TYPES}
|
|
175
|
-
selectedItem={identifierType}
|
|
176
|
-
onChange={({ selectedItem }) => setIdentifierType(selectedItem as IdentifierType)}
|
|
177
|
-
disabled={otpSent}
|
|
178
|
-
/>
|
|
179
|
-
</div>
|
|
180
|
-
|
|
181
|
-
<div className={styles.fieldGroup}>
|
|
182
|
-
<TextInput
|
|
183
|
-
id="identifier-value"
|
|
184
|
-
labelText={`${identifierType} Value`}
|
|
185
|
-
value={identifierValue}
|
|
186
|
-
onChange={(e) => setIdentifierValue(e.target.value)}
|
|
187
|
-
disabled={otpSent}
|
|
188
|
-
placeholder={`Enter ${identifierType.toLowerCase()} value`}
|
|
189
|
-
/>
|
|
190
|
-
</div>
|
|
191
|
-
|
|
192
|
-
<div style={{ marginTop: '0.75rem' }}>
|
|
193
|
-
{!otpSent ? (
|
|
194
|
-
<Button kind="secondary" onClick={handleSendOtp} disabled={loading}>
|
|
195
|
-
{loading ? <InlineLoading description="Sending..." /> : 'Send OTP'}
|
|
196
|
-
</Button>
|
|
197
|
-
) : (
|
|
198
|
-
<>
|
|
199
|
-
<div style={{ marginTop: '0.75rem' }}>
|
|
200
|
-
<TextInput
|
|
201
|
-
id="otp-input"
|
|
202
|
-
labelText="Enter OTP"
|
|
203
|
-
value={otp}
|
|
204
|
-
onChange={(e) => setOtp(e.target.value)}
|
|
205
|
-
disabled={otpVerified}
|
|
206
|
-
placeholder="Enter the code sent to your phone"
|
|
207
|
-
/>
|
|
202
|
+
{error && (
|
|
203
|
+
<div className={styles.notificationSpacing}>
|
|
204
|
+
<InlineNotification title="Error" subtitle={error} kind="error" lowContrast />
|
|
208
205
|
</div>
|
|
206
|
+
)}
|
|
207
|
+
{!client ? (
|
|
208
|
+
<div className={styles.formSection}>
|
|
209
|
+
{!otpSent ? (
|
|
210
|
+
<>
|
|
211
|
+
<div className={styles.formRow}>
|
|
212
|
+
<div className={styles.formControl}>
|
|
213
|
+
<Dropdown
|
|
214
|
+
id="identifier-type-dropdown"
|
|
215
|
+
label="Identifier Type"
|
|
216
|
+
titleText="Select Identifier Type"
|
|
217
|
+
items={IDENTIFIER_TYPES}
|
|
218
|
+
selectedItem={identifierType}
|
|
219
|
+
onChange={({ selectedItem }) => setIdentifierType(selectedItem as IdentifierType)}
|
|
220
|
+
disabled={otpSent}
|
|
221
|
+
/>
|
|
222
|
+
</div>
|
|
209
223
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
224
|
+
<div className={styles.formControl}>
|
|
225
|
+
<TextInput
|
|
226
|
+
id="identifier-value"
|
|
227
|
+
labelText={`${identifierType} Value`}
|
|
228
|
+
value={identifierValue}
|
|
229
|
+
onChange={(e) => setIdentifierValue(e.target.value)}
|
|
230
|
+
disabled={otpSent}
|
|
231
|
+
placeholder={`Enter ${identifierType.toLowerCase()} value`}
|
|
232
|
+
/>
|
|
233
|
+
</div>
|
|
234
|
+
</div>
|
|
235
|
+
<div className={styles.formRow}>
|
|
236
|
+
<div className={styles.formControl}>
|
|
237
|
+
<Button kind="primary" onClick={handleSendOtp} disabled={loading}>
|
|
238
|
+
{loading ? <InlineLoading description="Sending..." /> : 'Send OTP'}
|
|
239
|
+
</Button>
|
|
240
|
+
</div>
|
|
241
|
+
</div>
|
|
242
|
+
</>
|
|
215
243
|
) : (
|
|
216
|
-
|
|
217
|
-
{
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
244
|
+
<>
|
|
245
|
+
{!otpVerified ? (
|
|
246
|
+
<>
|
|
247
|
+
<div className={styles.formRow}>
|
|
248
|
+
<div className={styles.formControl}>
|
|
249
|
+
<TextInput
|
|
250
|
+
id="otp-input"
|
|
251
|
+
labelText="Enter OTP"
|
|
252
|
+
value={otp}
|
|
253
|
+
onChange={(e) => setOtp(e.target.value)}
|
|
254
|
+
disabled={otpVerified}
|
|
255
|
+
placeholder="Enter the code sent to your phone"
|
|
256
|
+
/>
|
|
257
|
+
</div>
|
|
258
|
+
</div>
|
|
259
|
+
<div className={styles.formRow}>
|
|
260
|
+
<div className={styles.actionBtn}>
|
|
261
|
+
<Button kind="primary" onClick={handleVerifyOtp} disabled={loading}>
|
|
262
|
+
{loading ? <InlineLoading description="Verifying..." /> : 'Verify OTP'}
|
|
263
|
+
</Button>
|
|
264
|
+
</div>
|
|
265
|
+
<div className={styles.actionBtn}>
|
|
266
|
+
<Button kind="secondary" onClick={handleSendOtp} disabled={loading}>
|
|
267
|
+
{loading ? <InlineLoading description="Resending OTP..." /> : 'Resend OTP'}
|
|
268
|
+
</Button>
|
|
269
|
+
</div>
|
|
270
|
+
<div className={styles.actionBtn}>
|
|
271
|
+
<Button kind="tertiary" onClick={() => setOtpSent(false)}>
|
|
272
|
+
Back
|
|
273
|
+
</Button>
|
|
274
|
+
</div>
|
|
275
|
+
</div>
|
|
276
|
+
</>
|
|
277
|
+
) : (
|
|
278
|
+
<>
|
|
279
|
+
<div className={styles.formRow}>
|
|
280
|
+
<div className={styles.formControl}>
|
|
281
|
+
<Button kind="primary" onClick={handleFetchCR} disabled={loading}>
|
|
282
|
+
{loading ? <InlineLoading description="Fetching..." /> : 'Fetch Client Registry Data'}
|
|
283
|
+
</Button>
|
|
284
|
+
</div>
|
|
285
|
+
</div>
|
|
286
|
+
</>
|
|
287
|
+
)}
|
|
288
|
+
</>
|
|
224
289
|
)}
|
|
225
290
|
</div>
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
291
|
+
) : (
|
|
292
|
+
<></>
|
|
293
|
+
)}
|
|
294
|
+
|
|
295
|
+
{otpVerified && client ? (
|
|
296
|
+
<div className="clientDataSection">
|
|
297
|
+
<Tabs>
|
|
298
|
+
<TabList contained>
|
|
299
|
+
<Tab>Patient</Tab>
|
|
300
|
+
<Tab>Dependants</Tab>
|
|
301
|
+
</TabList>
|
|
302
|
+
<TabPanels>
|
|
303
|
+
<TabPanel>{client ? <ClientDetails client={client} /> : <></>}</TabPanel>
|
|
304
|
+
<TabPanel>
|
|
305
|
+
{client.dependants ? <ClientDependantList hieDependants={client.dependants} /> : <></>}
|
|
306
|
+
</TabPanel>
|
|
307
|
+
</TabPanels>
|
|
308
|
+
</Tabs>
|
|
309
|
+
<Button onClick={useHieData}>Use Data</Button>
|
|
310
|
+
</div>
|
|
311
|
+
) : (
|
|
312
|
+
<></>
|
|
313
|
+
)}
|
|
314
|
+
</div>
|
|
315
|
+
</ModalBody>
|
|
316
|
+
</Modal>
|
|
230
317
|
);
|
|
231
318
|
};
|
|
232
319
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
.modalVerificationLayout {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
row-gap: 10px;
|
|
5
|
+
width: 100%;
|
|
6
|
+
}
|
|
7
|
+
.formSection {
|
|
8
|
+
display: flex;
|
|
9
|
+
flex-direction: column;
|
|
10
|
+
width: 100%;
|
|
11
|
+
}
|
|
12
|
+
.formControl {
|
|
13
|
+
width: 45%;
|
|
14
|
+
}
|
|
15
|
+
.formRow {
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: row;
|
|
18
|
+
width: 100%;
|
|
19
|
+
column-gap: 10px;
|
|
20
|
+
padding-top: 5px;
|
|
21
|
+
padding-bottom: 5px;
|
|
22
|
+
}
|
|
23
|
+
.actionBtn {
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type HieIdentifications, type HieClient } from './types';
|
|
2
|
+
|
|
3
|
+
const clientDatailsFields = [
|
|
4
|
+
'id',
|
|
5
|
+
'other_identifications',
|
|
6
|
+
'first_name',
|
|
7
|
+
'middle_name',
|
|
8
|
+
'last_name',
|
|
9
|
+
'gender',
|
|
10
|
+
'date_of_birth',
|
|
11
|
+
'is_alive',
|
|
12
|
+
'deceased_datetime',
|
|
13
|
+
'phone',
|
|
14
|
+
'email',
|
|
15
|
+
'civil_status',
|
|
16
|
+
'place_of_birth',
|
|
17
|
+
'citizenship',
|
|
18
|
+
'country',
|
|
19
|
+
'county',
|
|
20
|
+
'sub_county',
|
|
21
|
+
'ward',
|
|
22
|
+
'village_estate',
|
|
23
|
+
'longitude',
|
|
24
|
+
'latitude',
|
|
25
|
+
'identification_type',
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
export function generateHieClientDetails(hieClient: HieClient) {
|
|
29
|
+
let data = {};
|
|
30
|
+
Object.keys(hieClient)
|
|
31
|
+
.filter((key) => {
|
|
32
|
+
return clientDatailsFields.includes(key);
|
|
33
|
+
})
|
|
34
|
+
.forEach((key) => {
|
|
35
|
+
if (key === 'other_identifications') {
|
|
36
|
+
const otherIds = generateOtherIdentifications(hieClient[key]);
|
|
37
|
+
data = {
|
|
38
|
+
...data,
|
|
39
|
+
...otherIds,
|
|
40
|
+
};
|
|
41
|
+
} else if (key === 'identification_type') {
|
|
42
|
+
data[hieClient['identification_type']] = hieClient.identification_number;
|
|
43
|
+
} else {
|
|
44
|
+
const value = hieClient[key];
|
|
45
|
+
data[key] = value;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
return data;
|
|
49
|
+
}
|
|
50
|
+
function generateOtherIdentifications(hieIdentifications: HieIdentifications[]) {
|
|
51
|
+
const other = {};
|
|
52
|
+
hieIdentifications.forEach((id) => {
|
|
53
|
+
other[id.identification_type] = id.identification_number;
|
|
54
|
+
});
|
|
55
|
+
return other;
|
|
56
|
+
}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
export enum HieIdentificationType {
|
|
2
|
+
NationalID = 'National ID',
|
|
3
|
+
SHANumber = 'SHA Number',
|
|
4
|
+
HouseholdNumber = 'Household Number',
|
|
5
|
+
RefugeeID = 'Refugee ID',
|
|
6
|
+
AlienID = 'Alien ID',
|
|
7
|
+
MandateNumber = 'Mandate Number',
|
|
8
|
+
Cr = 'id',
|
|
9
|
+
TemporaryDependantID = 'Temporary Dependant ID',
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface HieIdentifications {
|
|
13
|
+
identification_number: string;
|
|
14
|
+
identification_type: HieIdentificationType;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface HieDependant {
|
|
18
|
+
date_added: string;
|
|
19
|
+
relationship: string;
|
|
20
|
+
total: number;
|
|
21
|
+
result: HieClient[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface AlternateContact {
|
|
25
|
+
contact_type: string;
|
|
26
|
+
contact_id: string;
|
|
27
|
+
contact_name: string;
|
|
28
|
+
relationship: string;
|
|
29
|
+
remarks: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface HieClient {
|
|
33
|
+
resourceType: string;
|
|
34
|
+
id: string;
|
|
35
|
+
meta: {
|
|
36
|
+
versionId: string;
|
|
37
|
+
creationTime: string;
|
|
38
|
+
lastUpdated: string;
|
|
39
|
+
source: string;
|
|
40
|
+
};
|
|
41
|
+
originSystem: {
|
|
42
|
+
system: string;
|
|
43
|
+
record_id: string;
|
|
44
|
+
};
|
|
45
|
+
title: string;
|
|
46
|
+
first_name: string;
|
|
47
|
+
middle_name: string;
|
|
48
|
+
last_name: string;
|
|
49
|
+
gender: string;
|
|
50
|
+
date_of_birth: string;
|
|
51
|
+
place_of_birth: string;
|
|
52
|
+
person_with_disability: number;
|
|
53
|
+
citizenship: string;
|
|
54
|
+
kra_pin: string;
|
|
55
|
+
preferred_primary_care_network: string;
|
|
56
|
+
employment_type: string;
|
|
57
|
+
domestic_worker_type: string;
|
|
58
|
+
civil_status: string;
|
|
59
|
+
identification_type: HieIdentificationType;
|
|
60
|
+
identification_number: string;
|
|
61
|
+
other_identifications: HieIdentifications[];
|
|
62
|
+
dependants: HieDependant[];
|
|
63
|
+
is_alive: number;
|
|
64
|
+
deceased_datetime: string;
|
|
65
|
+
phone: string;
|
|
66
|
+
biometrics_verified: number;
|
|
67
|
+
biometrics_score: number;
|
|
68
|
+
email: string;
|
|
69
|
+
country: string;
|
|
70
|
+
county: string;
|
|
71
|
+
sub_county: string;
|
|
72
|
+
ward: string;
|
|
73
|
+
village_estate: string;
|
|
74
|
+
building_house_no: string;
|
|
75
|
+
latitude: string;
|
|
76
|
+
longitude: string;
|
|
77
|
+
province_state_country: string;
|
|
78
|
+
zip_code: string;
|
|
79
|
+
identification_residence: string;
|
|
80
|
+
employer_name: string;
|
|
81
|
+
employer_pin: string;
|
|
82
|
+
disability_category: string;
|
|
83
|
+
disability_subcategory: string;
|
|
84
|
+
disability_cause: string;
|
|
85
|
+
in_lawful_custody: string;
|
|
86
|
+
admission_remand_number: string;
|
|
87
|
+
document_uploads: any[];
|
|
88
|
+
alternative_contacts: AlternateContact[];
|
|
89
|
+
gross_income: number;
|
|
90
|
+
gross_income_currency: string;
|
|
91
|
+
postal_address: string;
|
|
92
|
+
estimated_contribution: number;
|
|
93
|
+
estimated_annual_contribution: number;
|
|
94
|
+
city: string;
|
|
95
|
+
id_serial: string;
|
|
96
|
+
learning_institution_code: string;
|
|
97
|
+
learning_institution_name: string;
|
|
98
|
+
grade_level: string;
|
|
99
|
+
admission_number: string;
|
|
100
|
+
expected_year_of_graduation: string;
|
|
101
|
+
unconfirmed_dependants: HieDependant[];
|
|
102
|
+
is_agent: number;
|
|
103
|
+
agent_id: string;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface HieClientSearchDto {
|
|
107
|
+
identificationNumber: number | string;
|
|
108
|
+
identificationType: HieIdentificationType;
|
|
109
|
+
locationUuid: string;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface HieAmrsObj {
|
|
113
|
+
key: string;
|
|
114
|
+
title: string;
|
|
115
|
+
hieValue: string | number | boolean;
|
|
116
|
+
amrsValue: string | number | boolean;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface ValidateHieCustomOtpDto {
|
|
120
|
+
sessionId: string;
|
|
121
|
+
otp: number | string;
|
|
122
|
+
locationUuid: string;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export type HieOtpValidationStatus = 'valid' | 'invalid';
|
|
126
|
+
|
|
127
|
+
export interface ValidateHieCustomOtpResponse {
|
|
128
|
+
data: {
|
|
129
|
+
identification_type: string;
|
|
130
|
+
identification_number: string;
|
|
131
|
+
status: HieOtpValidationStatus;
|
|
132
|
+
};
|
|
133
|
+
source?: string;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export interface ValidateHieCustomOtpErrorResponse {
|
|
137
|
+
error: string;
|
|
138
|
+
details: string;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export interface RequestCustomOtpDto {
|
|
142
|
+
identificationNumber: string | number;
|
|
143
|
+
identificationType: string;
|
|
144
|
+
locationUuid: string;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export interface RequestCustomOtpResponse {
|
|
148
|
+
message: string;
|
|
149
|
+
sessionId: string;
|
|
150
|
+
maskedPhone: string;
|
|
151
|
+
}
|
|
152
|
+
export interface RequestCustomOtpErrorResponse {
|
|
153
|
+
error: string;
|
|
154
|
+
details: string;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface HieClientDependant extends HieClient {
|
|
158
|
+
date_added: string;
|
|
159
|
+
relationship: string;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export interface HieFacility {
|
|
163
|
+
id: string;
|
|
164
|
+
facility_name: string;
|
|
165
|
+
registration_number: string;
|
|
166
|
+
facility_code: string;
|
|
167
|
+
regulator: string;
|
|
168
|
+
facility_level: string;
|
|
169
|
+
facility_category: string;
|
|
170
|
+
facility_owner: string;
|
|
171
|
+
facility_type: string;
|
|
172
|
+
county: string;
|
|
173
|
+
sub_county: string;
|
|
174
|
+
ward: string;
|
|
175
|
+
found: number;
|
|
176
|
+
approved: number;
|
|
177
|
+
operational_status: string;
|
|
178
|
+
current_license_expiry_date: string;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export interface HieFacilitySearchResponse {
|
|
182
|
+
message: HieFacility;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export interface FacilitySearchFilter {
|
|
186
|
+
filterType: string;
|
|
187
|
+
filterValue: string;
|
|
188
|
+
locationUuid: string;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export enum FacilitySearchFilterType {
|
|
192
|
+
location = 'location',
|
|
193
|
+
facilityCode = 'facilityCode',
|
|
194
|
+
registrationNumber = 'registrationNumber',
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export interface PatientShrSummaryFilter {
|
|
198
|
+
cr_id: string;
|
|
199
|
+
locationUuid: string;
|
|
200
|
+
}
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from './client-registry.types';
|
|
11
11
|
import { mapAmrsPatientRelationship } from './map-client-registry-to-form-utils';
|
|
12
12
|
|
|
13
|
-
const HIE_BASE_URL = 'https://
|
|
13
|
+
const HIE_BASE_URL = 'https://staging.ampath.or.ke/hie';
|
|
14
14
|
|
|
15
15
|
async function postJson<T>(url: string, payload: unknown): Promise<T> {
|
|
16
16
|
const response = await fetch(url, {
|
|
@@ -25,6 +25,7 @@ import { type SavePatientForm, SavePatientTransactionManager } from './form-mana
|
|
|
25
25
|
import { useInitialAddressFieldValues, useInitialFormValues, usePatientUuidMap } from './patient-registration-hooks';
|
|
26
26
|
import BeforeSavePrompt from './before-save-prompt';
|
|
27
27
|
import styles from './patient-registration.scss';
|
|
28
|
+
import customStyles from './custom-patient-registration.scss';
|
|
28
29
|
import ClientRegistryLookupSection from './client-registry/client-registry-search.component';
|
|
29
30
|
|
|
30
31
|
let exportedInitialFormValuesForTesting = {} as FormValues;
|
|
@@ -65,6 +66,7 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
|
|
|
65
66
|
const { data: photo } = usePatientPhoto(patientToEdit?.id);
|
|
66
67
|
const savePatientTransactionManager = useRef(new SavePatientTransactionManager());
|
|
67
68
|
const validationSchema = getValidationSchema(config, t);
|
|
69
|
+
const [showVerifyModal, setShowVerifyModal] = useState<boolean>(false);
|
|
68
70
|
|
|
69
71
|
useEffect(() => {
|
|
70
72
|
exportedInitialFormValuesForTesting = initialFormValues;
|
|
@@ -166,6 +168,13 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
|
|
|
166
168
|
}
|
|
167
169
|
};
|
|
168
170
|
|
|
171
|
+
const openVerifyModal = () => {
|
|
172
|
+
setShowVerifyModal(true);
|
|
173
|
+
};
|
|
174
|
+
const closeVerifyModal = () => {
|
|
175
|
+
setShowVerifyModal(false);
|
|
176
|
+
};
|
|
177
|
+
|
|
169
178
|
const createContextValue = useCallback(
|
|
170
179
|
(formikProps) => ({
|
|
171
180
|
identifierTypes,
|
|
@@ -244,20 +253,22 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
|
|
|
244
253
|
</div>
|
|
245
254
|
<div className={styles.infoGrid}>
|
|
246
255
|
<PatientRegistrationContextProvider value={createContextValue(props)}>
|
|
247
|
-
<div>
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
256
|
+
<div className={customStyles.patientVerification}>
|
|
257
|
+
<h4>Patient Verification</h4>
|
|
258
|
+
<Button onClick={openVerifyModal}>Verify CR</Button>
|
|
259
|
+
{showVerifyModal ? (
|
|
260
|
+
<>
|
|
261
|
+
<ClientRegistryLookupSection
|
|
262
|
+
onClientVerified={() => setIsClientVerified(true)}
|
|
263
|
+
onModalClose={closeVerifyModal}
|
|
264
|
+
open={showVerifyModal}
|
|
255
265
|
/>
|
|
256
|
-
|
|
266
|
+
</>
|
|
267
|
+
) : (
|
|
268
|
+
<></>
|
|
257
269
|
)}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
270
|
+
</div>
|
|
271
|
+
<div>
|
|
261
272
|
{sections.map((section, index) => (
|
|
262
273
|
<SectionWrapper
|
|
263
274
|
key={`registration-section-${section.id}`}
|
|
@@ -47,21 +47,20 @@ export function saveEncounter(encounter: Encounter) {
|
|
|
47
47
|
|
|
48
48
|
export function generateIdentifier(source: string) {
|
|
49
49
|
const abortController = new AbortController();
|
|
50
|
-
|
|
50
|
+
|
|
51
|
+
return openmrsFetch(`${restBaseUrl}/idgen/identifiersource/${source}/identifier`, {
|
|
51
52
|
headers: {
|
|
52
53
|
'Content-Type': 'application/json',
|
|
53
54
|
},
|
|
54
55
|
method: 'POST',
|
|
55
|
-
body: {
|
|
56
|
-
user: 1,
|
|
57
|
-
},
|
|
56
|
+
body: {},
|
|
58
57
|
signal: abortController.signal,
|
|
59
58
|
});
|
|
60
59
|
}
|
|
61
60
|
|
|
62
61
|
export async function generateAmrsUniversalIdentifier() {
|
|
63
62
|
const abortController = new AbortController();
|
|
64
|
-
const resp = await openmrsFetch(`https://
|
|
63
|
+
const resp = await openmrsFetch(`https://staging.ampath.or.ke/amrs-id-generator/generateidentifier`, {
|
|
65
64
|
headers: {
|
|
66
65
|
'Content-Type': 'application/json',
|
|
67
66
|
},
|