@ampath/esm-patient-registration-app 9.2.0-next.14 → 9.2.0-next.16
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/4300.js +1 -1
- package/dist/4395.js +1 -0
- package/dist/4395.js.map +1 -0
- package/dist/5239.js +1 -1
- package/dist/5239.js.LICENSE.txt +10 -0
- package/dist/5239.js.map +1 -1
- package/dist/6276.js +1 -1
- package/dist/6276.js.map +1 -1
- package/dist/6687.js +1 -0
- package/dist/6687.js.map +1 -0
- package/dist/6996.js +1 -0
- package/dist/6996.js.map +1 -0
- package/dist/7125.js +2 -0
- package/dist/7125.js.map +1 -0
- package/dist/7821.js +1 -0
- package/dist/7821.js.map +1 -0
- package/dist/8414.js +1 -0
- package/dist/8414.js.map +1 -0
- package/dist/8434.js +1 -1
- package/dist/8434.js.map +1 -1
- package/dist/8882.js +1 -0
- package/dist/8882.js.map +1 -0
- package/dist/9898.js +1 -0
- package/dist/9898.js.map +1 -0
- package/dist/9933.js +2 -0
- package/dist/{1909.js.LICENSE.txt → 9933.js.LICENSE.txt} +9 -0
- package/dist/9933.js.map +1 -0
- 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 +226 -150
- package/dist/openmrs-esm-patient-registration-app.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/index.ts +9 -0
- package/src/patient-registration/client-registry/client-registry-search.component.tsx +233 -0
- package/src/patient-registration/client-registry/client-registry.resource.ts +79 -0
- package/src/patient-registration/client-registry/map-client-registry-to-form-utils.ts +190 -0
- package/src/patient-registration/client-registry-search/client-registry-dependant-details.component.tsx +237 -0
- package/src/patient-registration/client-registry-search/client-registry-details.component.tsx +111 -0
- package/src/patient-registration/client-registry-search/client-registry-patient-details.component.tsx +234 -0
- package/src/patient-registration/client-registry-search/client-registry-search.component.tsx +234 -0
- package/src/patient-registration/client-registry-search/client-registry-verification-tag.component.tsx +78 -0
- package/src/patient-registration/client-registry-search/client-registry.resource.ts +135 -0
- package/src/patient-registration/client-registry-search/client-registry.types.ts +243 -0
- package/src/patient-registration/client-registry-search/map-client-registry-to-form-utils.ts +590 -0
- package/src/patient-registration/field/field.component.tsx +3 -0
- package/src/patient-registration/field/id/id-field.component.tsx +1 -1
- package/src/patient-registration/field/id/id-field.test.tsx +1 -1
- package/src/patient-registration/form-manager.test.ts +1 -0
- package/src/patient-registration/patient-registration.component.tsx +25 -9
- package/src/patient-registration/patient-registration.resource.ts +4 -3
- package/src/patient-registration/patient-registration.scss +4 -0
- package/src/routes.json +12 -1
- package/src/widgets/client-registry-verification.modal.tsx +27 -0
- package/translations/en.json +4 -0
- package/dist/1909.js +0 -2
- package/dist/1909.js.map +0 -1
- package/dist/320.js +0 -2
- package/dist/320.js.LICENSE.txt +0 -8
- package/dist/320.js.map +0 -1
- package/dist/3474.js +0 -2
- package/dist/3474.js.LICENSE.txt +0 -8
- package/dist/3474.js.map +0 -1
- package/dist/627.js +0 -1
- package/dist/627.js.map +0 -1
- package/dist/7071.js +0 -1
- package/dist/7071.js.map +0 -1
- package/dist/729.js +0 -2
- package/dist/729.js.map +0 -1
- /package/dist/{729.js.LICENSE.txt → 7125.js.LICENSE.txt} +0 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Column,
|
|
3
|
+
Row,
|
|
4
|
+
Select,
|
|
5
|
+
SelectItem,
|
|
6
|
+
Button,
|
|
7
|
+
ExpandableTile,
|
|
8
|
+
TileAboveTheFoldContent,
|
|
9
|
+
TileBelowTheFoldContent,
|
|
10
|
+
Accordion,
|
|
11
|
+
AccordionItem,
|
|
12
|
+
ButtonSet,
|
|
13
|
+
} from '@carbon/react';
|
|
14
|
+
import React, { useState } from 'react';
|
|
15
|
+
import { useTranslation } from 'react-i18next';
|
|
16
|
+
import {
|
|
17
|
+
type CustomRelationship,
|
|
18
|
+
HieIdentificationType,
|
|
19
|
+
type AmrsPerson,
|
|
20
|
+
type ClientRegistryDependantBody,
|
|
21
|
+
} from './client-registry.types';
|
|
22
|
+
import {
|
|
23
|
+
createPerson,
|
|
24
|
+
createRelationship,
|
|
25
|
+
fetchAmrsPersonData,
|
|
26
|
+
updateAmrsPersonIdentifiers,
|
|
27
|
+
} from './client-registry.resource';
|
|
28
|
+
import ClientRegistryPatientDetails from './client-registry-patient-details.component';
|
|
29
|
+
import {
|
|
30
|
+
addressFields,
|
|
31
|
+
getIdentifierUuid,
|
|
32
|
+
getPatientAttributes,
|
|
33
|
+
getPatientRelationshipPayload,
|
|
34
|
+
identifiersSyncFields,
|
|
35
|
+
mapFieldValue,
|
|
36
|
+
nameFields,
|
|
37
|
+
patientObjFields,
|
|
38
|
+
personSyncFields,
|
|
39
|
+
} from './map-client-registry-to-form-utils';
|
|
40
|
+
import { showSnackbar } from '@openmrs/esm-framework';
|
|
41
|
+
|
|
42
|
+
interface ClientRegistryDependantDetailsProps {
|
|
43
|
+
hieDependants: Array<ClientRegistryDependantBody>;
|
|
44
|
+
amrsPerson: AmrsPerson;
|
|
45
|
+
patientRelationships: Array<CustomRelationship>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface ClientDependantTileProps {
|
|
49
|
+
dependant: ClientRegistryDependantBody;
|
|
50
|
+
patientRelationships: Array<CustomRelationship>;
|
|
51
|
+
amrsPerson: AmrsPerson;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const ClientDependantTile: React.FC<ClientDependantTileProps> = ({ dependant, patientRelationships, amrsPerson }) => {
|
|
55
|
+
const { t } = useTranslation();
|
|
56
|
+
const [amrsRelationExists, setAmrsRelationExists] = useState(false);
|
|
57
|
+
const [amrsDependantData, setAmrsDependantData] = useState<AmrsPerson>();
|
|
58
|
+
const [selectedRelationship, setSelectedRelationship] = useState('');
|
|
59
|
+
const locationUuid = '18c343eb-b353-462a-9139-b16606e6b6c2';
|
|
60
|
+
|
|
61
|
+
const handleCreateDependant = async (dependantBody: ClientRegistryDependantBody) => {
|
|
62
|
+
try {
|
|
63
|
+
const syncFields = {};
|
|
64
|
+
patientObjFields.forEach((field) => {
|
|
65
|
+
let fieldArr = mapFieldValue(field, dependantBody.result[0], amrsPerson);
|
|
66
|
+
const hieFieldValue = fieldArr[1];
|
|
67
|
+
syncFields[field] = hieFieldValue;
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Person
|
|
71
|
+
const patientPayload = {};
|
|
72
|
+
const names = {};
|
|
73
|
+
const addresses = {};
|
|
74
|
+
const otherFields = {};
|
|
75
|
+
const attributes = getPatientAttributes(dependantBody.result[0]);
|
|
76
|
+
Object.entries(syncFields).forEach(([k, v]) => {
|
|
77
|
+
if (personSyncFields.includes(k)) {
|
|
78
|
+
// names
|
|
79
|
+
if (nameFields.includes(k)) {
|
|
80
|
+
names[k] = v;
|
|
81
|
+
}
|
|
82
|
+
// addresses
|
|
83
|
+
else if (addressFields.includes(k)) {
|
|
84
|
+
if (v) {
|
|
85
|
+
addresses[k] = v;
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
otherFields[k] = v;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
Object.assign(
|
|
93
|
+
patientPayload,
|
|
94
|
+
otherFields,
|
|
95
|
+
{ addresses: [addresses] },
|
|
96
|
+
{ names: [names] },
|
|
97
|
+
{ attributes: attributes },
|
|
98
|
+
);
|
|
99
|
+
const response = await createPerson(patientPayload);
|
|
100
|
+
if (response && response.data) {
|
|
101
|
+
showSnackbar({
|
|
102
|
+
kind: 'success',
|
|
103
|
+
title: 'Dependant created successfully.',
|
|
104
|
+
});
|
|
105
|
+
const relationshipPayload = getPatientRelationshipPayload(
|
|
106
|
+
amrsPerson,
|
|
107
|
+
dependantBody.relationship,
|
|
108
|
+
response.data.uuid,
|
|
109
|
+
);
|
|
110
|
+
await createRelationship(relationshipPayload);
|
|
111
|
+
showSnackbar({
|
|
112
|
+
kind: 'success',
|
|
113
|
+
title: 'Dependant relationship created successfully.',
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
} catch (err) {
|
|
117
|
+
showSnackbar({
|
|
118
|
+
kind: 'error',
|
|
119
|
+
title: 'Error syncing patient data.',
|
|
120
|
+
subtitle: JSON.stringify(err),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const handleSelectAmrsDependant = async (e: any) => {
|
|
126
|
+
const uuid = e.target.value;
|
|
127
|
+
if (!uuid) {
|
|
128
|
+
setAmrsRelationExists(false);
|
|
129
|
+
setAmrsDependantData(null);
|
|
130
|
+
}
|
|
131
|
+
const response = await fetchAmrsPersonData(uuid);
|
|
132
|
+
if (response && response.data) {
|
|
133
|
+
setAmrsRelationExists(true);
|
|
134
|
+
setAmrsDependantData((prev) => ({ ...prev, person: response.data }));
|
|
135
|
+
} else {
|
|
136
|
+
setAmrsRelationExists(false);
|
|
137
|
+
setAmrsDependantData(null);
|
|
138
|
+
const relationshipUuid = patientRelationships.find((v) => v.relatedPersonUuid === uuid);
|
|
139
|
+
if (relationshipUuid && relationshipUuid.relationshipType) {
|
|
140
|
+
setSelectedRelationship(relationshipUuid.relationshipType);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const getDependantName = () => {
|
|
146
|
+
const name = dependant.result[0];
|
|
147
|
+
return `${name.first_name} ${name.middle_name} ${name.last_name} (${dependant.relationship})`;
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
return (
|
|
151
|
+
<>
|
|
152
|
+
<AccordionItem title={getDependantName()}>
|
|
153
|
+
<Row>
|
|
154
|
+
<Column>
|
|
155
|
+
<Select labelText={t('amrsDependants', 'AMRS dependants')} onChange={handleSelectAmrsDependant}>
|
|
156
|
+
<SelectItem text={t('selectAmrsRelation', 'Select AMRS relation')} value="" />
|
|
157
|
+
{patientRelationships.map((relationship) => (
|
|
158
|
+
<SelectItem
|
|
159
|
+
text={`${relationship.display} (${relationship.relationshipType})`}
|
|
160
|
+
value={relationship.relatedPerson.uuid}
|
|
161
|
+
/>
|
|
162
|
+
))}
|
|
163
|
+
</Select>
|
|
164
|
+
</Column>
|
|
165
|
+
{!amrsRelationExists ? (
|
|
166
|
+
<Column>
|
|
167
|
+
<Button onClick={() => handleCreateDependant(dependant)}>
|
|
168
|
+
{t('createDependant', 'Create dependant in AMRS')}
|
|
169
|
+
</Button>
|
|
170
|
+
</Column>
|
|
171
|
+
) : null}
|
|
172
|
+
</Row>
|
|
173
|
+
<Row>
|
|
174
|
+
<ClientRegistryPatientDetails
|
|
175
|
+
hieData={dependant.result[0]}
|
|
176
|
+
amrsPerson={amrsDependantData}
|
|
177
|
+
fromDependant={true}
|
|
178
|
+
/>
|
|
179
|
+
</Row>
|
|
180
|
+
</AccordionItem>
|
|
181
|
+
{/* <ExpandableTile
|
|
182
|
+
tileCollapsedIconText="Expand to view dependant details"
|
|
183
|
+
tileExpandedIconText="Click to collapse dependant details">
|
|
184
|
+
<TileAboveTheFoldContent>{dependant.relationship}</TileAboveTheFoldContent>
|
|
185
|
+
<TileBelowTheFoldContent>
|
|
186
|
+
<Row>
|
|
187
|
+
<Column>
|
|
188
|
+
<Select labelText={t('amrsDependants', 'AMRS dependants')} onChange={handleSelectAmrsDependant}>
|
|
189
|
+
<SelectItem text={t('selectAmrsRelation', 'Select AMRS relation')} value="" />
|
|
190
|
+
{patientRelationships.map((relationship) => (
|
|
191
|
+
<SelectItem
|
|
192
|
+
text={`${relationship.display} (${relationship.relationshipType})`}
|
|
193
|
+
value={relationship.relatedPerson.uuid}
|
|
194
|
+
/>
|
|
195
|
+
))}
|
|
196
|
+
</Select>
|
|
197
|
+
</Column>
|
|
198
|
+
{!amrsRelationExists ? (
|
|
199
|
+
<Column>
|
|
200
|
+
<Button onClick={() => handleCreateDependant(dependant)}>
|
|
201
|
+
{t('createDependant', 'Create dependant in AMRS')}
|
|
202
|
+
</Button>
|
|
203
|
+
</Column>
|
|
204
|
+
) : null}
|
|
205
|
+
</Row>
|
|
206
|
+
<Row>
|
|
207
|
+
{amrsRelationExists ? (
|
|
208
|
+
<ClientRegistryPatientDetails hieData={dependant.result[0]} amrsPerson={amrsDependantData} />
|
|
209
|
+
) : null}
|
|
210
|
+
</Row>
|
|
211
|
+
</TileBelowTheFoldContent>
|
|
212
|
+
</ExpandableTile> */}
|
|
213
|
+
</>
|
|
214
|
+
);
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
const ClientRegistryDependantDetails: React.FC<ClientRegistryDependantDetailsProps> = ({
|
|
218
|
+
hieDependants,
|
|
219
|
+
amrsPerson,
|
|
220
|
+
patientRelationships,
|
|
221
|
+
}) => {
|
|
222
|
+
return (
|
|
223
|
+
<div>
|
|
224
|
+
<Accordion size="lg">
|
|
225
|
+
{hieDependants.map((dependant) => (
|
|
226
|
+
<ClientDependantTile
|
|
227
|
+
dependant={dependant}
|
|
228
|
+
amrsPerson={amrsPerson}
|
|
229
|
+
patientRelationships={patientRelationships}
|
|
230
|
+
/>
|
|
231
|
+
))}
|
|
232
|
+
</Accordion>
|
|
233
|
+
</div>
|
|
234
|
+
);
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
export default ClientRegistryDependantDetails;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { Tabs, TabList, Tab, TabPanels, TabPanel, InlineLoading } from '@carbon/react';
|
|
3
|
+
import { showSnackbar, usePatient } from '@openmrs/esm-framework';
|
|
4
|
+
import {
|
|
5
|
+
type RequestCustomOtpDto,
|
|
6
|
+
type ClientRegistryBody,
|
|
7
|
+
type AmrsPerson,
|
|
8
|
+
type CustomRelationship,
|
|
9
|
+
} from './client-registry.types';
|
|
10
|
+
import ClientRegistryPatientDetails from './client-registry-patient-details.component';
|
|
11
|
+
import ClientRegistryDependantDetails from './client-registry-dependant-details.component';
|
|
12
|
+
import { fetchAmrsPatientData, fetchClientRegistryData, getRelationships } from './client-registry.resource';
|
|
13
|
+
|
|
14
|
+
interface ClientRegistryDetailsProps {
|
|
15
|
+
payload: RequestCustomOtpDto;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const ClientRegistryDetails: React.FC<ClientRegistryDetailsProps> = ({ payload }) => {
|
|
19
|
+
const [hieData, setHieData] = useState<ClientRegistryBody>();
|
|
20
|
+
const [amrsPerson, setAmrsPerson] = useState<AmrsPerson>();
|
|
21
|
+
const [loading, setLoading] = useState<boolean>(false);
|
|
22
|
+
const { patientUuid } = usePatient();
|
|
23
|
+
const [relationships, setRelationships] = useState<Array<CustomRelationship>>([]);
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
handleHiePatientDetails();
|
|
27
|
+
if (patientUuid) {
|
|
28
|
+
handleAmrsPersonDetails();
|
|
29
|
+
handleFetchPatientRelationships();
|
|
30
|
+
}
|
|
31
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
32
|
+
}, [patientUuid]);
|
|
33
|
+
|
|
34
|
+
const handleFetchPatientRelationships = async () => {
|
|
35
|
+
const resp = await getRelationships(patientUuid);
|
|
36
|
+
if (resp) {
|
|
37
|
+
setRelationships(resp);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const handleAmrsPersonDetails = async () => {
|
|
42
|
+
try {
|
|
43
|
+
setLoading(true);
|
|
44
|
+
const response = await fetchAmrsPatientData(patientUuid);
|
|
45
|
+
if (response) {
|
|
46
|
+
setAmrsPerson(response.data);
|
|
47
|
+
}
|
|
48
|
+
showSnackbar({
|
|
49
|
+
kind: 'success',
|
|
50
|
+
title: 'AMRS person data fetched successfully.',
|
|
51
|
+
});
|
|
52
|
+
} catch (er) {
|
|
53
|
+
showSnackbar({
|
|
54
|
+
kind: 'error',
|
|
55
|
+
title: 'Error fetching AMRS person data.',
|
|
56
|
+
subtitle: JSON.stringify(er),
|
|
57
|
+
});
|
|
58
|
+
} finally {
|
|
59
|
+
setLoading(false);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const handleHiePatientDetails = async () => {
|
|
64
|
+
try {
|
|
65
|
+
setLoading(true);
|
|
66
|
+
const response = await fetchClientRegistryData(payload);
|
|
67
|
+
setHieData(response[0]);
|
|
68
|
+
showSnackbar({
|
|
69
|
+
kind: 'success',
|
|
70
|
+
title: 'HIE person data fetched successfully.',
|
|
71
|
+
});
|
|
72
|
+
} catch (er) {
|
|
73
|
+
showSnackbar({
|
|
74
|
+
kind: 'error',
|
|
75
|
+
title: 'Error fetching HIE person data.',
|
|
76
|
+
subtitle: JSON.stringify(er),
|
|
77
|
+
});
|
|
78
|
+
} finally {
|
|
79
|
+
setLoading(false);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
return loading ? (
|
|
84
|
+
<InlineLoading description="Verifying..." />
|
|
85
|
+
) : (
|
|
86
|
+
<Tabs>
|
|
87
|
+
<TabList contained>
|
|
88
|
+
<Tab>Patient</Tab>
|
|
89
|
+
<Tab>Dependants</Tab>
|
|
90
|
+
</TabList>
|
|
91
|
+
<TabPanels>
|
|
92
|
+
<TabPanel>
|
|
93
|
+
{hieData && <ClientRegistryPatientDetails hieData={hieData} amrsPerson={amrsPerson} fromDependant={false} />}
|
|
94
|
+
</TabPanel>
|
|
95
|
+
<TabPanel>
|
|
96
|
+
{hieData && hieData.dependants ? (
|
|
97
|
+
<ClientRegistryDependantDetails
|
|
98
|
+
hieDependants={hieData.dependants}
|
|
99
|
+
amrsPerson={amrsPerson}
|
|
100
|
+
patientRelationships={relationships}
|
|
101
|
+
/>
|
|
102
|
+
) : (
|
|
103
|
+
<div>Dependants not found.</div>
|
|
104
|
+
)}
|
|
105
|
+
</TabPanel>
|
|
106
|
+
</TabPanels>
|
|
107
|
+
</Tabs>
|
|
108
|
+
);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export default ClientRegistryDetails;
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import React, { useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
TableRow,
|
|
4
|
+
TableCell,
|
|
5
|
+
Checkbox,
|
|
6
|
+
Table,
|
|
7
|
+
TableHead,
|
|
8
|
+
TableHeader,
|
|
9
|
+
TableBody,
|
|
10
|
+
Button,
|
|
11
|
+
Row,
|
|
12
|
+
InlineLoading,
|
|
13
|
+
} from '@carbon/react';
|
|
14
|
+
import { HieIdentificationType, type AmrsPerson, type ClientRegistryBody } from './client-registry.types';
|
|
15
|
+
import {
|
|
16
|
+
addressFields,
|
|
17
|
+
getIdentifierUuid,
|
|
18
|
+
identifiersSyncFields,
|
|
19
|
+
mapFieldValue,
|
|
20
|
+
nameFields,
|
|
21
|
+
patientObjFields,
|
|
22
|
+
personSyncFields,
|
|
23
|
+
} from './map-client-registry-to-form-utils';
|
|
24
|
+
import { updatePerson, updateAmrsPersonIdentifiers } from './client-registry.resource';
|
|
25
|
+
import { showSnackbar } from '@openmrs/esm-framework';
|
|
26
|
+
|
|
27
|
+
interface ClientRegistryPatientDetailsProps {
|
|
28
|
+
hieData: ClientRegistryBody;
|
|
29
|
+
amrsPerson: AmrsPerson;
|
|
30
|
+
fromDependant?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface GetTableDataRowProps {
|
|
34
|
+
field: string;
|
|
35
|
+
label: string;
|
|
36
|
+
amrsPerson: string;
|
|
37
|
+
hiePatient: string;
|
|
38
|
+
onChange?(e: boolean, field: string, value: string, multiple: boolean): void;
|
|
39
|
+
allChecked: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const TableDataRow: React.FC<GetTableDataRowProps> = ({
|
|
43
|
+
field,
|
|
44
|
+
label,
|
|
45
|
+
amrsPerson,
|
|
46
|
+
hiePatient,
|
|
47
|
+
onChange,
|
|
48
|
+
allChecked,
|
|
49
|
+
}) => {
|
|
50
|
+
const [checked, setChecked] = useState(false);
|
|
51
|
+
const randomString = Math.random().toString(36).substring(2, 6).toUpperCase();
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
onChange?.(allChecked, field, hiePatient, true);
|
|
54
|
+
setChecked(allChecked);
|
|
55
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
56
|
+
}, [allChecked]);
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<TableRow>
|
|
60
|
+
<TableCell>{label}</TableCell>
|
|
61
|
+
<TableCell>{amrsPerson}</TableCell>
|
|
62
|
+
<TableCell>{hiePatient}</TableCell>
|
|
63
|
+
<TableCell>
|
|
64
|
+
<Checkbox
|
|
65
|
+
id={`cbox-${randomString}`}
|
|
66
|
+
onChange={(e) => {
|
|
67
|
+
onChange(e.target.checked, field, hiePatient, false);
|
|
68
|
+
setChecked(e.target.checked);
|
|
69
|
+
}}
|
|
70
|
+
checked={checked}
|
|
71
|
+
/>
|
|
72
|
+
</TableCell>
|
|
73
|
+
</TableRow>
|
|
74
|
+
);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const ClientRegistryPatientDetails: React.FC<ClientRegistryPatientDetailsProps> = ({
|
|
78
|
+
hieData,
|
|
79
|
+
amrsPerson,
|
|
80
|
+
fromDependant,
|
|
81
|
+
}) => {
|
|
82
|
+
const [syncFields, setSyncFields] = useState<Array<Record<string, string>>>([]);
|
|
83
|
+
const [allChecked, setAllChecked] = useState(false);
|
|
84
|
+
const [loading, setLoading] = useState(false);
|
|
85
|
+
const locationUuid = '18c343eb-b353-462a-9139-b16606e6b6c2';
|
|
86
|
+
const randomString = Math.random().toString(36).substring(2, 6).toUpperCase();
|
|
87
|
+
|
|
88
|
+
const handleFieldChange = (checked: boolean, field: string, value: string, multiple: boolean) => {
|
|
89
|
+
if (multiple) {
|
|
90
|
+
if (checked) {
|
|
91
|
+
setSyncFields((prev) => [...prev, { [field]: value }]);
|
|
92
|
+
} else {
|
|
93
|
+
setSyncFields([]);
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
if (checked) {
|
|
97
|
+
setSyncFields([...syncFields, { [field]: value }]);
|
|
98
|
+
} else {
|
|
99
|
+
setSyncFields((prev) => prev.filter((p) => !Object.keys(p).includes(field)));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const handleCheckAll = (e) => {
|
|
105
|
+
setAllChecked(e.target.checked);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const handleSync = async () => {
|
|
109
|
+
try {
|
|
110
|
+
const payload = {};
|
|
111
|
+
syncFields.forEach((field) => {
|
|
112
|
+
let key = Object.keys(field)[0];
|
|
113
|
+
payload[key] = field[key];
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Person
|
|
117
|
+
const patientPayload = {};
|
|
118
|
+
const names = {};
|
|
119
|
+
const addresses = {};
|
|
120
|
+
const otherFields = {};
|
|
121
|
+
Object.entries(payload).forEach(([k, v]) => {
|
|
122
|
+
if (personSyncFields.includes(k)) {
|
|
123
|
+
// names
|
|
124
|
+
if (nameFields.includes(k)) {
|
|
125
|
+
names[k] = v;
|
|
126
|
+
}
|
|
127
|
+
// addresses
|
|
128
|
+
else if (addressFields.includes(k)) {
|
|
129
|
+
if (v) {
|
|
130
|
+
addresses[k] = v;
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
otherFields[k] = v;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
Object.assign(patientPayload, otherFields, { addresses: [addresses] }, { names: [names] });
|
|
138
|
+
await updatePerson(amrsPerson.person.uuid, patientPayload);
|
|
139
|
+
showSnackbar({
|
|
140
|
+
kind: 'success',
|
|
141
|
+
title: 'Patient successfully synced.',
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Identifiers
|
|
145
|
+
Object.entries(payload).forEach(async ([k, v]) => {
|
|
146
|
+
if (identifiersSyncFields().includes(k)) {
|
|
147
|
+
if (v) {
|
|
148
|
+
const identifierUuid = getIdentifierUuid(HieIdentificationType[k]);
|
|
149
|
+
const identifierPayload = {
|
|
150
|
+
identifier: v,
|
|
151
|
+
location: locationUuid,
|
|
152
|
+
identifierType: identifierUuid,
|
|
153
|
+
};
|
|
154
|
+
try {
|
|
155
|
+
// Check if the identifier exists
|
|
156
|
+
if (amrsPerson?.person?.identifiers?.find((i) => i.identifierType.uuid === identifierUuid)) {
|
|
157
|
+
// update to have the selected identifier
|
|
158
|
+
await updateAmrsPersonIdentifiers(
|
|
159
|
+
amrsPerson.person.uuid,
|
|
160
|
+
identifierUuid + '',
|
|
161
|
+
identifierPayload,
|
|
162
|
+
fromDependant,
|
|
163
|
+
);
|
|
164
|
+
} else {
|
|
165
|
+
// create to have the blank identifier
|
|
166
|
+
await updateAmrsPersonIdentifiers(amrsPerson.person.uuid, '', identifierPayload, fromDependant);
|
|
167
|
+
}
|
|
168
|
+
} catch (err) {
|
|
169
|
+
showSnackbar({
|
|
170
|
+
kind: 'error',
|
|
171
|
+
title: 'Error syncing patient identifiers.',
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
showSnackbar({
|
|
178
|
+
kind: 'success',
|
|
179
|
+
title: 'Patient identifiers successfully synced.',
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
setSyncFields([]);
|
|
183
|
+
} catch (err) {
|
|
184
|
+
showSnackbar({
|
|
185
|
+
kind: 'error',
|
|
186
|
+
title: 'Error syncing patient data.',
|
|
187
|
+
subtitle: JSON.stringify(err?.error?.message),
|
|
188
|
+
});
|
|
189
|
+
} finally {
|
|
190
|
+
setLoading(false);
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
return (
|
|
195
|
+
<>
|
|
196
|
+
<Row>
|
|
197
|
+
{syncFields.length ? <Button onClick={handleSync}>Sync data</Button> : null}
|
|
198
|
+
{loading ? <InlineLoading description="Syncing patient details..." /> : null}
|
|
199
|
+
</Row>
|
|
200
|
+
<Table>
|
|
201
|
+
<TableHead>
|
|
202
|
+
<TableRow>
|
|
203
|
+
<TableHeader>Field</TableHeader>
|
|
204
|
+
<TableHeader>AMRS Person</TableHeader>
|
|
205
|
+
<TableHeader>HIE Patient</TableHeader>
|
|
206
|
+
<TableHeader>
|
|
207
|
+
<Checkbox id={`cbox-multiple-${randomString}`} onChange={(e) => handleCheckAll(e)} />
|
|
208
|
+
</TableHeader>
|
|
209
|
+
</TableRow>
|
|
210
|
+
</TableHead>
|
|
211
|
+
<TableBody>
|
|
212
|
+
{patientObjFields.map((field) => {
|
|
213
|
+
const fieldValue = mapFieldValue(field, hieData, amrsPerson);
|
|
214
|
+
const amrsField = fieldValue[0];
|
|
215
|
+
const hieField = fieldValue[1];
|
|
216
|
+
|
|
217
|
+
return (
|
|
218
|
+
<TableDataRow
|
|
219
|
+
label={field}
|
|
220
|
+
field={field}
|
|
221
|
+
amrsPerson={amrsField}
|
|
222
|
+
hiePatient={hieField}
|
|
223
|
+
onChange={handleFieldChange}
|
|
224
|
+
allChecked={allChecked}
|
|
225
|
+
/>
|
|
226
|
+
);
|
|
227
|
+
})}
|
|
228
|
+
</TableBody>
|
|
229
|
+
</Table>
|
|
230
|
+
</>
|
|
231
|
+
);
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
export default ClientRegistryPatientDetails;
|