@ampath/esm-patient-registration-app 6.0.1-pre.17 → 6.0.1-pre.172

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.
Files changed (124) hide show
  1. package/.turbo/turbo-build.log +20 -20
  2. package/dist/132.js +1 -1
  3. package/dist/197.js +1 -1
  4. package/dist/236.js +1 -1
  5. package/dist/300.js +1 -1
  6. package/dist/335.js +1 -1
  7. package/dist/41.js +1 -1
  8. package/dist/41.js.map +1 -1
  9. package/dist/449.js +1 -0
  10. package/dist/449.js.map +1 -0
  11. package/dist/55.js +1 -1
  12. package/dist/56.js +1 -1
  13. package/dist/56.js.map +1 -1
  14. package/dist/621.js +1 -0
  15. package/dist/621.js.map +1 -0
  16. package/dist/629.js +2 -0
  17. package/dist/629.js.LICENSE.txt +24 -0
  18. package/dist/629.js.map +1 -0
  19. package/dist/652.js +1 -1
  20. package/dist/661.js +1 -1
  21. package/dist/757.js +1 -0
  22. package/dist/757.js.map +1 -0
  23. package/dist/828.js +1 -0
  24. package/dist/828.js.map +1 -0
  25. package/dist/830.js +1 -0
  26. package/dist/830.js.map +1 -0
  27. package/dist/831.js +1 -1
  28. package/dist/831.js.map +1 -1
  29. package/dist/879.js +1 -1
  30. package/dist/913.js +1 -1
  31. package/dist/913.js.LICENSE.txt +3 -3
  32. package/dist/913.js.map +1 -1
  33. package/dist/927.js +1 -0
  34. package/dist/927.js.map +1 -0
  35. package/dist/99.js +1 -1
  36. package/dist/ampath-esm-patient-registration-app.js +1 -1
  37. package/dist/ampath-esm-patient-registration-app.js.buildmanifest.json +183 -111
  38. package/dist/ampath-esm-patient-registration-app.js.map +1 -1
  39. package/dist/main.js +1 -1
  40. package/dist/main.js.LICENSE.txt +0 -32
  41. package/dist/main.js.map +1 -1
  42. package/dist/routes.json +1 -1
  43. package/package.json +7 -10
  44. package/src/config-schema.ts +19 -10
  45. package/src/index.ts +11 -4
  46. package/src/offline.resources.ts +13 -18
  47. package/src/offline.ts +6 -4
  48. package/src/patient-photo.extension.tsx +9 -0
  49. package/src/patient-registration/field/address/custom-address-field.component.tsx +1 -0
  50. package/src/patient-registration/field/custom-field.component.tsx +6 -0
  51. package/src/patient-registration/field/dob/dob.component.tsx +17 -14
  52. package/src/patient-registration/field/field.resource.ts +3 -3
  53. package/src/patient-registration/field/person-attributes/coded-person-attribute-field.component.tsx +4 -0
  54. package/src/patient-registration/field/person-attributes/custom-person-attribute-field.component.tsx +56 -0
  55. package/src/patient-registration/field/person-attributes/person-attribute-field.component.tsx +22 -7
  56. package/src/patient-registration/field/person-attributes/person-attributes.resource.ts +2 -2
  57. package/src/patient-registration/field/phone/phone-field.component.tsx +1 -0
  58. package/src/patient-registration/form-manager.ts +13 -6
  59. package/src/patient-registration/patient-registration-hooks.ts +133 -9
  60. package/src/patient-registration/patient-registration.component.tsx +55 -13
  61. package/src/patient-registration/{patient-registration.resource.test.tsx → patient-registration.resource.testt.tsx} +4 -4
  62. package/src/patient-registration/patient-registration.resource.ts +15 -75
  63. package/src/patient-registration/patient-registration.scss +0 -8
  64. package/src/patient-registration/patient-registration.types.ts +7 -1
  65. package/src/patient-registration/section/patient-relationships/relationships-section.component.tsx +5 -1
  66. package/src/patient-registration/section/patient-relationships/relationships.resource.tsx +2 -2
  67. package/src/patient-verification/assets/counties.json +236 -0
  68. package/src/patient-verification/assets/verification-assets.ts +11 -0
  69. package/src/patient-verification/patient-verification-hook.tsx +176 -0
  70. package/src/patient-verification/patient-verification-utils.ts +179 -0
  71. package/src/patient-verification/patient-verification.component.tsx +124 -0
  72. package/src/patient-verification/patient-verification.scss +25 -0
  73. package/src/patient-verification/verification-modal/confirm-prompt.component.tsx +72 -0
  74. package/src/patient-verification/verification-modal/empty-prompt.component.tsx +35 -0
  75. package/src/patient-verification/verification-types.ts +50 -0
  76. package/src/routes.json +12 -3
  77. package/translations/am.json +26 -12
  78. package/translations/ar.json +26 -12
  79. package/translations/en.json +18 -4
  80. package/translations/es.json +10 -0
  81. package/translations/fr.json +6 -0
  82. package/translations/he.json +18 -0
  83. package/translations/km.json +18 -0
  84. package/translations/zh.json +30 -22
  85. package/translations/zh_CN.json +30 -22
  86. package/dist/229.js +0 -2
  87. package/dist/229.js.LICENSE.txt +0 -56
  88. package/dist/229.js.map +0 -1
  89. package/dist/537.js +0 -1
  90. package/dist/537.js.map +0 -1
  91. package/dist/885.js +0 -1
  92. package/dist/885.js.map +0 -1
  93. package/dist/918.js +0 -1
  94. package/dist/918.js.map +0 -1
  95. package/src/patient-registration/field/address/tests/address-hierarchy.test.tsx +0 -214
  96. package/src/patient-registration/field/address/tests/address-search-component.test.tsx +0 -135
  97. package/src/patient-registration/field/dob/dob.test.tsx +0 -75
  98. package/src/patient-registration/field/field.test.tsx +0 -294
  99. package/src/patient-registration/field/id/id-field.test.tsx +0 -107
  100. package/src/patient-registration/field/person-attributes/coded-attributes.component.tsx +0 -60
  101. package/src/patient-registration/field/person-attributes/coded-person-attribute-field.test.tsx +0 -127
  102. package/src/patient-registration/field/person-attributes/person-attribute-field.test.tsx +0 -187
  103. package/src/patient-registration/field/person-attributes/text-person-attribute-field.test.tsx +0 -88
  104. package/src/patient-registration/form-manager.test.ts +0 -67
  105. package/src/patient-registration/input/basic-input/select/select-input.test.tsx +0 -49
  106. package/src/patient-registration/input/custom-input/autosuggest/autosuggest.test.tsx +0 -132
  107. package/src/patient-registration/input/custom-input/identifier/identifier-input.test.tsx +0 -107
  108. package/src/patient-registration/patient-registration.test.tsx +0 -471
  109. package/src/patient-registration/section/death-info/death-info-section.test.tsx +0 -64
  110. package/src/patient-registration/section/demographics/demographics-section.test.tsx +0 -83
  111. package/src/patient-registration/section/patient-relationships/relationships-section.test.tsx +0 -100
  112. package/src/patient-verification/client-registry-constants.ts +0 -13
  113. package/src/patient-verification/client-registry.component.tsx +0 -66
  114. package/src/patient-verification/client-registry.scss +0 -1
  115. package/src/patient-verification/utils.tsx +0 -56
  116. package/src/patient-verification/verification-modal.scss +0 -20
  117. package/src/patient-verification/verification.component.tsx +0 -48
  118. package/src/root.test.tsx +0 -32
  119. package/src/widgets/cancel-patient-edit.test.tsx +0 -27
  120. package/src/widgets/display-photo.component.tsx +0 -30
  121. package/src/widgets/display-photo.test.tsx +0 -37
  122. package/src/widgets/edit-patient-details-button.test.tsx +0 -41
  123. /package/src/patient-registration/input/custom-input/identifier/{utils.test.ts → utils.testt.ts} +0 -0
  124. /package/src/widgets/{delete-identifier-confirmation-modal.test.tsx → delete-identifier-confirmation-modal.testt.tsx} +0 -0
@@ -5,13 +5,16 @@ import {
5
5
  openmrsFetch,
6
6
  useConfig,
7
7
  usePatient,
8
+ restBaseUrl,
8
9
  } from '@openmrs/esm-framework';
10
+ import last from 'lodash-es/last';
9
11
  import camelCase from 'lodash-es/camelCase';
10
12
  import { type Dispatch, useEffect, useMemo, useState } from 'react';
11
13
  import useSWR from 'swr';
12
14
  import { v4 } from 'uuid';
13
15
  import { type RegistrationConfig } from '../config-schema';
14
16
  import { patientRegistration } from '../constants';
17
+ import { useConceptAnswers, useGlobalProperties } from '../patient-verification/patient-verification-hook';
15
18
  import {
16
19
  type FormValues,
17
20
  type PatientRegistration,
@@ -19,6 +22,8 @@ import {
19
22
  type PersonAttributeResponse,
20
23
  type PatientIdentifierResponse,
21
24
  type Encounter,
25
+ type ConceptAnswers,
26
+ type ObsResponse,
22
27
  } from './patient-registration.types';
23
28
  import {
24
29
  getAddressFieldValuesFromFhirPatient,
@@ -31,12 +36,13 @@ import { useInitialPatientRelationships } from './section/patient-relationships/
31
36
  import dayjs from 'dayjs';
32
37
 
33
38
  export function useInitialFormValues(patientUuid: string): [FormValues, Dispatch<FormValues>] {
39
+ const { martialStatus, education, occupation, educationLoad } = useConcepts();
34
40
  const { isLoading: isLoadingPatientToEdit, patient: patientToEdit } = usePatient(patientUuid);
35
41
  const { data: attributes, isLoading: isLoadingAttributes } = useInitialPersonAttributes(patientUuid);
36
42
  const { data: identifiers, isLoading: isLoadingIdentifiers } = useInitialPatientIdentifiers(patientUuid);
37
43
  const { data: relationships, isLoading: isLoadingRelationships } = useInitialPatientRelationships(patientUuid);
38
- const { data: encounters } = useInitialEncounters(patientUuid, patientToEdit);
39
-
44
+ const { data: obs, isLoading: isLoadingObs, obs: observations } = usePatientObs(patientUuid);
45
+ const { data: token, isLoading: isLoadingToken } = useGlobalProperties();
40
46
  const [initialFormValues, setInitialFormValues] = useState<FormValues>({
41
47
  patientUuid: v4(),
42
48
  givenName: '',
@@ -95,6 +101,14 @@ export function useInitialFormValues(patientUuid: string): [FormValues, Dispatch
95
101
  })();
96
102
  }, [isLoadingPatientToEdit, patientToEdit, patientUuid]);
97
103
 
104
+ // Setting authentication token
105
+
106
+ useEffect(() => {
107
+ if (!isLoadingToken && token) {
108
+ setInitialFormValues((initialFormValues) => ({ ...initialFormValues, token: String(token.access_token) }));
109
+ }
110
+ }, [isLoadingToken, token]);
111
+
98
112
  // Set initial patient relationships
99
113
  useEffect(() => {
100
114
  if (!isLoadingRelationships && relationships) {
@@ -133,15 +147,24 @@ export function useInitialFormValues(patientUuid: string): [FormValues, Dispatch
133
147
  }
134
148
  }, [attributes, setInitialFormValues, isLoadingAttributes]);
135
149
 
136
- // Set Initial registration encounters
150
+ // Set initial patient obs
151
+
152
+ useEffect(() => {
153
+ if (!isLoadingObs) {
154
+ setInitialFormValues((initialFormValues) => ({ ...initialFormValues, obs: obs, observation: observations }));
155
+ }
156
+ }, [isLoadingObs]);
157
+
158
+ // Set Initial encounter
159
+
137
160
  useEffect(() => {
138
- if (patientToEdit && encounters) {
161
+ if (!educationLoad) {
139
162
  setInitialFormValues((initialFormValues) => ({
140
163
  ...initialFormValues,
141
- obs: encounters as Record<string, string>,
164
+ concepts: [...occupation, ...martialStatus, ...education],
142
165
  }));
143
166
  }
144
- }, [encounters, patientToEdit]);
167
+ }, [educationLoad]);
145
168
 
146
169
  return [initialFormValues, setInitialFormValues];
147
170
  }
@@ -210,7 +233,7 @@ export function useInitialPatientIdentifiers(patientUuid: string): {
210
233
 
211
234
  const { data, error, isLoading } = useSWR<FetchResponse<{ results: Array<PatientIdentifierResponse> }>, Error>(
212
235
  shouldFetch
213
- ? `/ws/rest/v1/patient/${patientUuid}/identifier?v=custom:(uuid,identifier,identifierType:(uuid,required,name),preferred)`
236
+ ? `${restBaseUrl}/patient/${patientUuid}/identifier?v=custom:(uuid,identifier,identifierType:(uuid,required,name),preferred)`
214
237
  : null,
215
238
  openmrsFetch,
216
239
  );
@@ -247,7 +270,7 @@ function useInitialEncounters(patientUuid: string, patientToEdit: fhir.Patient)
247
270
  const { registrationObs } = useConfig() as RegistrationConfig;
248
271
  const { data, error, isLoading } = useSWR<FetchResponse<{ results: Array<Encounter> }>>(
249
272
  patientToEdit && registrationObs.encounterTypeUuid
250
- ? `/ws/rest/v1/encounter?patient=${patientUuid}&v=custom:(encounterDatetime,obs:(concept:ref,value:ref))&encounterType=${registrationObs.encounterTypeUuid}`
273
+ ? `${restBaseUrl}/encounter?patient=${patientUuid}&v=custom:(encounterDatetime,obs:(concept:ref,value:ref))&encounterType=${registrationObs.encounterTypeUuid}`
251
274
  : null,
252
275
  openmrsFetch,
253
276
  );
@@ -265,7 +288,7 @@ function useInitialPersonAttributes(personUuid: string) {
265
288
  const shouldFetch = !!personUuid;
266
289
  const { data, error, isLoading } = useSWR<FetchResponse<{ results: Array<PersonAttributeResponse> }>, Error>(
267
290
  shouldFetch
268
- ? `/ws/rest/v1/person/${personUuid}/attribute?v=custom:(uuid,display,attributeType:(uuid,display,format),value)`
291
+ ? `${restBaseUrl}/person/${personUuid}/attribute?v=custom:(uuid,display,attributeType:(uuid,display,format),value)`
269
292
  : null,
270
293
  openmrsFetch,
271
294
  );
@@ -285,3 +308,104 @@ function getPatientAttributeUuidMapForPatient(attributes: Array<PersonAttributeR
285
308
  });
286
309
  return attributeUuidMap;
287
310
  }
311
+
312
+ export function usePatientObs(patientUuid: string) {
313
+ const {
314
+ registrationObs: { encounterTypeUuid },
315
+ } = useConfig() as RegistrationConfig;
316
+ const url = `/ws/rest/v1/encounter?patient=${patientUuid}&encounterType=${encounterTypeUuid}&v=custom:(obs:(uuid,display,concept:(uuid,display),value:(uuid,display)))`;
317
+ const { data, isLoading, error } = useSWR<{ data: ObsResponse }>(patientUuid ? url : null, openmrsFetch);
318
+ let obsObject = {};
319
+ const patientObs = last(data?.data?.results)?.obs?.forEach((ob) => {
320
+ Object.assign(obsObject, { [ob.concept.uuid]: ob.value.uuid });
321
+ });
322
+ return { data: obsObject, isLoading, error, obs: data?.data };
323
+ }
324
+
325
+ function useConcepts() {
326
+ const config = useConfig<RegistrationConfig>();
327
+ const { data: education, isLoading: educationLoad } = useConceptAnswers('a89e48ae-1350-11df-a1f1-0026b9348838');
328
+ const { data: occupation, isLoading: occupationLoad } = useConceptAnswers('a8a0a00e-1350-11df-a1f1-0026b9348838');
329
+ const { data: martialStatus, isLoading: martialStatusLoad } = useConceptAnswers(
330
+ 'a899a9f2-1350-11df-a1f1-0026b9348838',
331
+ );
332
+
333
+ /* const occupation: Array<ConceptAnswers> = [
334
+ {
335
+ uuid: '1538AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
336
+ display: 'Farmer',
337
+ },
338
+ {
339
+ uuid: '1540AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
340
+ display: 'Employee',
341
+ },
342
+ {
343
+ uuid: '1539AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
344
+ display: 'Trader',
345
+ },
346
+ {
347
+ uuid: '159465AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
348
+ display: 'Student',
349
+ },
350
+ {
351
+ uuid: '159466AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
352
+ display: 'Driver',
353
+ },
354
+ {
355
+ uuid: '1107AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
356
+ display: 'None',
357
+ },
358
+ {
359
+ uuid: '5622AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
360
+ display: 'Other',
361
+ },
362
+ ]; */
363
+ /* const martialStatus: Array<ConceptAnswers> = [
364
+ {
365
+ uuid: 'a8b03712-1350-11df-a1f1-0026b9348838',
366
+ display: 'Married polygamous',
367
+ },
368
+ {
369
+ uuid: 'a8aa76b0-1350-11df-a1f1-0026b9348838',
370
+ display: 'Married monogamous',
371
+ },
372
+ {
373
+ uuid: 'a899ad58-1350-11df-a1f1-0026b9348838',
374
+ display: 'Divorced',
375
+ },
376
+ {
377
+ uuid: 'a899ae34-1350-11df-a1f1-0026b9348838',
378
+ display: 'Widowed',
379
+ },
380
+ {
381
+ uuid: 'a899af10-1350-11df-a1f1-0026b9348838',
382
+ display: 'Cohabiting',
383
+ },
384
+ {
385
+ uuid: 'a899ac7c-1350-11df-a1f1-0026b9348838',
386
+ display: 'Single',
387
+ },
388
+ {
389
+ uuid: 'a899aba0-1350-11df-a1f1-0026b9348838',
390
+ display: 'Separated',
391
+ },
392
+ {
393
+ uuid: '7831f002-331d-4f07-bf91-6bb65cd31050',
394
+ display: 'Sexual Partner/Sexual Partner',
395
+ },
396
+ {
397
+ uuid: 'a89ad3a4-1350-11df-a1f1-0026b9348838',
398
+ display: 'Not Applicable',
399
+ },
400
+ {
401
+ uuid: 'a8aaf3e2-1350-11df-a1f1-0026b9348838',
402
+ display: 'Other Non-Coded',
403
+ },
404
+ ];
405
+ */
406
+ //const martialStatus: Array<ConceptAnswers> = config.fieldDefinitions
407
+ // .find((fieldDefinition) => fieldDefinition.id === 'maritalStatus')
408
+ // .customConceptAnswers.map((concept) => ({ uuid: concept.uuid, display: concept.label }));
409
+
410
+ return { martialStatus, education, occupation, educationLoad, occupationLoad };
411
+ }
@@ -1,7 +1,7 @@
1
1
  import React, { useState, useEffect, useContext, useMemo, useRef } from 'react';
2
2
  import classNames from 'classnames';
3
- import { Button, Link, InlineLoading, Dropdown } from '@carbon/react';
4
- import { XAxis } from '@carbon/react/icons';
3
+ import { Button, Link, InlineLoading } from '@carbon/react';
4
+ import { XAxis, ShareKnowledge } from '@carbon/react/icons';
5
5
  import { useLocation, useParams } from 'react-router-dom';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import { Formik, Form, type FormikHelpers } from 'formik';
@@ -11,23 +11,32 @@ import {
11
11
  useConfig,
12
12
  interpolateUrl,
13
13
  usePatient,
14
- showModal,
14
+ usePatientPhoto,
15
15
  } from '@openmrs/esm-framework';
16
16
  import { getValidationSchema } from './validation/patient-registration-validation';
17
17
  import { type FormValues, type CapturePhotoProps } from './patient-registration.types';
18
18
  import { PatientRegistrationContext } from './patient-registration-context';
19
19
  import { type SavePatientForm, SavePatientTransactionManager } from './form-manager';
20
- import { fetchPatientRecordFromClientRegistry, usePatientPhoto, fetchPerson } from './patient-registration.resource';
21
20
  import { DummyDataInput } from './input/dummy-data/dummy-data-input.component';
22
- import { cancelRegistration, filterUndefinedPatientIdenfier, scrollIntoView } from './patient-registration-utils';
23
- import { useInitialAddressFieldValues, useInitialFormValues, usePatientUuidMap } from './patient-registration-hooks';
21
+ import {
22
+ cancelRegistration,
23
+ filterUndefinedPatientIdenfier,
24
+ parseAddressTemplateXml,
25
+ scrollIntoView,
26
+ } from './patient-registration-utils';
27
+ import {
28
+ useInitialAddressFieldValues,
29
+ useInitialFormValues,
30
+ usePatientObs,
31
+ usePatientUuidMap,
32
+ } from './patient-registration-hooks';
24
33
  import { ResourcesContext } from '../offline.resources';
25
34
  import { builtInSections, type RegistrationConfig, type SectionDefinition } from '../config-schema';
26
35
  import { SectionWrapper } from './section/section-wrapper.component';
27
36
  import BeforeSavePrompt from './before-save-prompt';
28
37
  import styles from './patient-registration.scss';
29
- import { TextInput } from '@carbon/react';
30
- import { ClientRegistry } from '../patient-verification/client-registry.component';
38
+ import PatientVerification from '../patient-verification/patient-verification.component';
39
+ import { handleSavePatientToClientRegistry } from '../patient-verification/patient-verification-hook';
31
40
 
32
41
  let exportedInitialFormValuesForTesting = {} as FormValues;
33
42
 
@@ -55,6 +64,9 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
55
64
  const savePatientTransactionManager = useRef(new SavePatientTransactionManager());
56
65
  const fieldDefinition = config?.fieldDefinitions?.filter((def) => def.type === 'address');
57
66
  const validationSchema = getValidationSchema(config);
67
+ const [enableClientRegistry, setEnableClientRegistry] = useState(
68
+ inEditMode ? initialFormValues.identifiers['nationalUniquePatientIdentifier']?.identifierValue : false,
69
+ );
58
70
 
59
71
  useEffect(() => {
60
72
  exportedInitialFormValuesForTesting = initialFormValues;
@@ -109,6 +121,26 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
109
121
 
110
122
  setTarget(redirectUrl);
111
123
  } catch (error) {
124
+ const fieldErrors = Object.entries(error.responseBody?.error?.fieldErrors || {}) as Array<
125
+ [string, Array<{ code: string; message: string }>]
126
+ >;
127
+
128
+ if (savePatientTransactionManager.current.patientSaved) {
129
+ fieldErrors.forEach(([field, error]) => {
130
+ const errorMessage = error.map((e) => e.message).join(', ');
131
+ showSnackbar({
132
+ subtitle: errorMessage,
133
+ title: `Patient registration successful, with errors for registration encounter`,
134
+ kind: 'warning',
135
+ timeoutInMs: 8000,
136
+ });
137
+ });
138
+ const afterUrl = new URLSearchParams(search).get('afterUrl');
139
+ const redirectUrl = interpolateUrl(afterUrl || config.links.submitButton, { patientUuid: values.patientUuid });
140
+
141
+ setTarget(redirectUrl);
142
+ }
143
+
112
144
  if (error.responseBody?.error?.globalErrors) {
113
145
  error.responseBody.error.globalErrors.forEach((error) => {
114
146
  showSnackbar({
@@ -129,6 +161,7 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
129
161
  });
130
162
  } else {
131
163
  createErrorHandler()(error);
164
+ console.error(error);
132
165
  }
133
166
 
134
167
  helpers.setSubmitting(false);
@@ -173,6 +206,18 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
173
206
  </Link>
174
207
  </div>
175
208
  ))}
209
+ <Button
210
+ renderIcon={ShareKnowledge}
211
+ disabled={!currentSession || !identifierTypes}
212
+ onClick={() => {
213
+ setEnableClientRegistry(true);
214
+ props.isValid
215
+ ? handleSavePatientToClientRegistry(props.values, props.setValues, inEditMode)
216
+ : props.validateForm().then((errors) => displayErrors(errors));
217
+ }}
218
+ className={styles.submitButton}>
219
+ {t('postToRegistry', 'Post to registry')}
220
+ </Button>
176
221
  <Button
177
222
  className={styles.submitButton}
178
223
  type="submit"
@@ -180,7 +225,7 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
180
225
  // Current session and identifiers are required for patient registration.
181
226
  // If currentSession or identifierTypes are not available, then the
182
227
  // user should be blocked to register the patient.
183
- disabled={!currentSession || !identifierTypes || props.isSubmitting}>
228
+ disabled={!currentSession || !identifierTypes || props.isSubmitting || !enableClientRegistry}>
184
229
  {props.isSubmitting ? (
185
230
  <InlineLoading
186
231
  className={styles.spinner}
@@ -213,7 +258,7 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
213
258
  initialFormValues: props.initialValues,
214
259
  setInitialFormValues,
215
260
  }}>
216
- <ClientRegistry initialFormValues={initialFormValues} setInitialFormValues={setInitialFormValues} />
261
+ <PatientVerification props={props} setInitialFormValues={setInitialFormValues} />
217
262
  {sections.map((section, index) => (
218
263
  <SectionWrapper
219
264
  key={`registration-section-${section.id}`}
@@ -235,6 +280,3 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
235
280
  * Just exported for testing
236
281
  */
237
282
  export { exportedInitialFormValuesForTesting as initialFormValues };
238
- function dispose() {
239
- throw new Error('Function not implemented.');
240
- }
@@ -1,4 +1,4 @@
1
- import { openmrsFetch } from '@openmrs/esm-framework';
1
+ import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
2
2
  import { savePatient } from './patient-registration.resource';
3
3
 
4
4
  const mockOpenmrsFetch = openmrsFetch as jest.Mock;
@@ -14,13 +14,13 @@ describe('savePatient', () => {
14
14
 
15
15
  it('appends patient uuid in url if provided', () => {
16
16
  mockOpenmrsFetch.mockImplementationOnce((url) => url);
17
- savePatient(null, '12345');
18
- expect(mockOpenmrsFetch.mock.calls[0][0]).toEqual('/ws/rest/v1/patient/12345');
17
+ savePatient(null, '1234');
18
+ expect(mockOpenmrsFetch.mock.calls[0][0]).toEqual(`${restBaseUrl}/patient/1234`);
19
19
  });
20
20
 
21
21
  it('does not append patient uuid in url', () => {
22
22
  mockOpenmrsFetch.mockImplementationOnce(() => {});
23
23
  savePatient(null);
24
- expect(mockOpenmrsFetch.mock.calls[0][0]).toEqual('/ws/rest/v1/patient/');
24
+ expect(mockOpenmrsFetch.mock.calls[0][0]).toEqual(`${restBaseUrl}/patient/`);
25
25
  });
26
26
  });
@@ -1,9 +1,8 @@
1
- import useSWR from 'swr';
2
- import { openmrsFetch, useConfig } from '@openmrs/esm-framework';
1
+ import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
3
2
  import { type Patient, type Relationship, type PatientIdentifier, type Encounter } from './patient-registration.types';
4
3
 
5
- export const uuidIdentifier = '05a29f94-c0ed-11e2-94be-8c13b969e334';
6
- export const uuidTelephoneNumber = '14d4f066-15f5-102d-96e4-000c29c2a5d7';
4
+ export const uuidIdentifier = '58a4732e-1359-11df-a1f1-0026b9348838';
5
+ export const uuidTelephoneNumber = '72a759a8-1359-11df-a1f1-0026b9348838';
7
6
 
8
7
  function dataURItoFile(dataURI: string) {
9
8
  const byteString = atob(dataURI.split(',')[1]);
@@ -22,7 +21,7 @@ function dataURItoFile(dataURI: string) {
22
21
  export function savePatient(patient: Patient | null, updatePatientUuid?: string) {
23
22
  const abortController = new AbortController();
24
23
 
25
- return openmrsFetch(`/ws/rest/v1/patient/${updatePatientUuid || ''}`, {
24
+ return openmrsFetch(`${restBaseUrl}/patient/${updatePatientUuid || ''}`, {
26
25
  headers: {
27
26
  'Content-Type': 'application/json',
28
27
  },
@@ -35,7 +34,7 @@ export function savePatient(patient: Patient | null, updatePatientUuid?: string)
35
34
  export function saveEncounter(encounter: Encounter) {
36
35
  const abortController = new AbortController();
37
36
 
38
- return openmrsFetch(`/ws/rest/v1/encounter`, {
37
+ return openmrsFetch(`${restBaseUrl}/encounter`, {
39
38
  headers: {
40
39
  'Content-Type': 'application/json',
41
40
  },
@@ -48,7 +47,7 @@ export function saveEncounter(encounter: Encounter) {
48
47
  export function generateIdentifier(source: string) {
49
48
  const abortController = new AbortController();
50
49
 
51
- return openmrsFetch(`/ws/rest/v1/idgen/identifiersource/${source}/identifier`, {
50
+ return openmrsFetch(`${restBaseUrl}/idgen/identifiersource/${source}/identifier`, {
52
51
  headers: {
53
52
  'Content-Type': 'application/json',
54
53
  },
@@ -61,7 +60,7 @@ export function generateIdentifier(source: string) {
61
60
  export function deletePersonName(nameUuid: string, personUuid: string) {
62
61
  const abortController = new AbortController();
63
62
 
64
- return openmrsFetch(`/ws/rest/v1/person/${personUuid}/name/${nameUuid}`, {
63
+ return openmrsFetch(`${restBaseUrl}/person/${personUuid}/name/${nameUuid}`, {
65
64
  method: 'DELETE',
66
65
  signal: abortController.signal,
67
66
  });
@@ -70,7 +69,7 @@ export function deletePersonName(nameUuid: string, personUuid: string) {
70
69
  export function saveRelationship(relationship: Relationship) {
71
70
  const abortController = new AbortController();
72
71
 
73
- return openmrsFetch('/ws/rest/v1/relationship', {
72
+ return openmrsFetch(`${restBaseUrl}/relationship`, {
74
73
  headers: {
75
74
  'Content-Type': 'application/json',
76
75
  },
@@ -83,7 +82,7 @@ export function saveRelationship(relationship: Relationship) {
83
82
  export function updateRelationship(relationshipUuid, relationship: { relationshipType: string }) {
84
83
  const abortController = new AbortController();
85
84
 
86
- return openmrsFetch(`/ws/rest/v1/relationship/${relationshipUuid}`, {
85
+ return openmrsFetch(`${restBaseUrl}/relationship/${relationshipUuid}`, {
87
86
  headers: {
88
87
  'Content-Type': 'application/json',
89
88
  },
@@ -96,7 +95,7 @@ export function updateRelationship(relationshipUuid, relationship: { relationshi
96
95
  export function deleteRelationship(relationshipUuid) {
97
96
  const abortController = new AbortController();
98
97
 
99
- return openmrsFetch(`/ws/rest/v1/relationship/${relationshipUuid}`, {
98
+ return openmrsFetch(`${restBaseUrl}/relationship/${relationshipUuid}`, {
100
99
  headers: {
101
100
  'Content-Type': 'application/json',
102
101
  },
@@ -134,57 +133,12 @@ export async function savePatientPhoto(
134
133
  });
135
134
  }
136
135
 
137
- interface ObsFetchResponse {
138
- results: Array<PhotoObs>;
139
- }
140
-
141
- interface PhotoObs {
142
- display: string;
143
- obsDatetime: string;
144
- uuid: string;
145
- value: {
146
- display: string;
147
- links: {
148
- rel: string;
149
- uri: string;
150
- };
151
- };
152
- }
153
-
154
- interface UsePatientPhotoResult {
155
- data: { dateTime: string; imageSrc: string } | null;
156
- isError: Error;
157
- isLoading: boolean;
158
- }
159
-
160
- export function usePatientPhoto(patientUuid: string): UsePatientPhotoResult {
161
- const {
162
- concepts: { patientPhotoUuid },
163
- } = useConfig();
164
- const url = `/ws/rest/v1/obs?patient=${patientUuid}&concept=${patientPhotoUuid}&v=full`;
165
-
166
- const { data, error, isLoading } = useSWR<{ data: ObsFetchResponse }, Error>(patientUuid ? url : null, openmrsFetch);
167
-
168
- const item = data?.data?.results[0];
169
-
170
- return {
171
- data: item
172
- ? {
173
- dateTime: item?.obsDatetime,
174
- imageSrc: item?.value?.links?.uri,
175
- }
176
- : null,
177
- isError: error,
178
- isLoading,
179
- };
180
- }
181
-
182
136
  export async function fetchPerson(query: string, abortController: AbortController) {
183
137
  const [patientsRes, personsRes] = await Promise.all([
184
- openmrsFetch(`/ws/rest/v1/patient?q=${query}`, {
138
+ openmrsFetch(`${restBaseUrl}/patient?q=${query}`, {
185
139
  signal: abortController.signal,
186
140
  }),
187
- openmrsFetch(`/ws/rest/v1/person?q=${query}`, {
141
+ openmrsFetch(`${restBaseUrl}/person?q=${query}`, {
188
142
  signal: abortController.signal,
189
143
  }),
190
144
  ]);
@@ -202,7 +156,7 @@ export async function fetchPerson(query: string, abortController: AbortControlle
202
156
 
203
157
  export async function addPatientIdentifier(patientUuid: string, patientIdentifier: PatientIdentifier) {
204
158
  const abortController = new AbortController();
205
- return openmrsFetch(`/ws/rest/v1/patient/${patientUuid}/identifier/`, {
159
+ return openmrsFetch(`${restBaseUrl}/patient/${patientUuid}/identifier/`, {
206
160
  method: 'POST',
207
161
  headers: {
208
162
  'Content-Type': 'application/json',
@@ -214,7 +168,7 @@ export async function addPatientIdentifier(patientUuid: string, patientIdentifie
214
168
 
215
169
  export async function updatePatientIdentifier(patientUuid: string, identifierUuid: string, identifier: string) {
216
170
  const abortController = new AbortController();
217
- return openmrsFetch(`/ws/rest/v1/patient/${patientUuid}/identifier/${identifierUuid}`, {
171
+ return openmrsFetch(`${restBaseUrl}/patient/${patientUuid}/identifier/${identifierUuid}`, {
218
172
  method: 'POST',
219
173
  headers: {
220
174
  'Content-Type': 'application/json',
@@ -226,7 +180,7 @@ export async function updatePatientIdentifier(patientUuid: string, identifierUui
226
180
 
227
181
  export async function deletePatientIdentifier(patientUuid: string, patientIdentifierUuid: string) {
228
182
  const abortController = new AbortController();
229
- return openmrsFetch(`/ws/rest/v1/patient/${patientUuid}/identifier/${patientIdentifierUuid}?purge`, {
183
+ return openmrsFetch(`${restBaseUrl}/patient/${patientUuid}/identifier/${patientIdentifierUuid}?purge`, {
230
184
  method: 'DELETE',
231
185
  headers: {
232
186
  'Content-Type': 'application/json',
@@ -234,17 +188,3 @@ export async function deletePatientIdentifier(patientUuid: string, patientIdenti
234
188
  signal: abortController.signal,
235
189
  });
236
190
  }
237
- export const fetchPatientRecordFromClientRegistry = (
238
- patientIdentifier: string,
239
- identifierType: string,
240
- country: string,
241
- ) => {
242
- const url = `
243
- https://ngx.ampath.or.ke/registry/api/uno?uno=${patientIdentifier}&idType=${identifierType}&countryCode=${country}`;
244
-
245
- return fetch(url)
246
- .then((response) => {
247
- return response.json();
248
- })
249
- .then((data) => data);
250
- };
@@ -112,11 +112,3 @@ html[dir='rtl'] {
112
112
  padding-right: spacing.$spacing-07;
113
113
  }
114
114
  }
115
- .patientVerification {
116
- & > * {
117
- margin-top: spacing.$spacing-03;
118
- }
119
- & > :last-child {
120
- margin-top: spacing.$spacing-03;
121
- }
122
- }
@@ -118,7 +118,7 @@ export type Patient = {
118
118
  };
119
119
 
120
120
  export interface Encounter {
121
- encounterDatetime: Date;
121
+ encounterDatetime?: Date;
122
122
  patient: string;
123
123
  encounterType: string;
124
124
  location: string;
@@ -184,6 +184,9 @@ export interface FormValues {
184
184
  address: {
185
185
  [addressField: string]: string;
186
186
  };
187
+ observation?: ObsResponse;
188
+ concepts?: Array<ConceptAnswers>;
189
+ token?: string;
187
190
  }
188
191
 
189
192
  export interface PatientUuidMapType {
@@ -316,3 +319,6 @@ export interface RestAddressTemplate {
316
319
  display: string;
317
320
  value: string;
318
321
  }
322
+ export interface ObsResponse {
323
+ results: Array<{ obs: Array<{ uuid: string; display: string; value: OpenmrsResource; concept: OpenmrsResource }> }>;
324
+ }
@@ -177,7 +177,11 @@ export const RelationshipsSection = () => {
177
177
  uuid: type.uuid,
178
178
  direction: 'bIsToA',
179
179
  };
180
- aIsToB.display === bIsToA.display ? tmp.push(aIsToB) : tmp.push(aIsToB, bIsToA);
180
+ aIsToB.display === bIsToA.display
181
+ ? tmp.push(aIsToB)
182
+ : bIsToA.display === 'Patient'
183
+ ? tmp.push(aIsToB, { display: `Patient (${aIsToB.display})`, uuid: type.uuid, direction: 'bIsToA' })
184
+ : tmp.push(aIsToB, bIsToA);
181
185
  });
182
186
  setDisplayRelationshipTypes(tmp);
183
187
  }
@@ -1,6 +1,6 @@
1
1
  import { useMemo } from 'react';
2
2
  import useSWR from 'swr';
3
- import { type FetchResponse, openmrsFetch } from '@openmrs/esm-framework';
3
+ import { type FetchResponse, openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
4
4
  import { type RelationshipValue } from '../../patient-registration.types';
5
5
  import { personRelationshipRepresentation } from '../../../constants';
6
6
 
@@ -10,7 +10,7 @@ export function useInitialPatientRelationships(patientUuid: string): {
10
10
  } {
11
11
  const shouldFetch = !!patientUuid;
12
12
  const { data, error, isLoading } = useSWR<FetchResponse<RelationshipsResponse>, Error>(
13
- shouldFetch ? `/ws/rest/v1/relationship?v=${personRelationshipRepresentation}&person=${patientUuid}` : null,
13
+ shouldFetch ? `${restBaseUrl}/relationship?v=${personRelationshipRepresentation}&person=${patientUuid}` : null,
14
14
  openmrsFetch,
15
15
  );
16
16