@ampath/esm-patient-registration-app 6.0.1-pre.98 → 9.2.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.
Files changed (288) hide show
  1. package/dist/1119.js +1 -0
  2. package/dist/1197.js +1 -0
  3. package/dist/21.js +1 -0
  4. package/dist/21.js.map +1 -0
  5. package/dist/2146.js +1 -0
  6. package/dist/2372.js +1 -0
  7. package/dist/2372.js.map +1 -0
  8. package/dist/2470.js +1 -0
  9. package/dist/2470.js.map +1 -0
  10. package/dist/2690.js +1 -0
  11. package/dist/2913.js +2 -0
  12. package/dist/{913.js.LICENSE.txt → 2913.js.LICENSE.txt} +3 -23
  13. package/dist/2913.js.map +1 -0
  14. package/dist/3093.js +1 -0
  15. package/dist/3093.js.map +1 -0
  16. package/dist/3099.js +1 -0
  17. package/dist/3144.js +2 -0
  18. package/dist/3144.js.LICENSE.txt +19 -0
  19. package/dist/3144.js.map +1 -0
  20. package/dist/320.js +2 -0
  21. package/dist/{876.js.LICENSE.txt → 320.js.LICENSE.txt} +2 -3
  22. package/dist/320.js.map +1 -0
  23. package/dist/3464.js +1 -0
  24. package/dist/3464.js.map +1 -0
  25. package/dist/3474.js +2 -0
  26. package/dist/3474.js.LICENSE.txt +8 -0
  27. package/dist/3474.js.map +1 -0
  28. package/dist/3584.js +1 -0
  29. package/dist/4041.js +2 -0
  30. package/dist/4041.js.map +1 -0
  31. package/dist/4055.js +1 -0
  32. package/dist/4132.js +1 -0
  33. package/dist/4300.js +1 -0
  34. package/dist/4335.js +1 -0
  35. package/dist/4463.js +1 -0
  36. package/dist/4463.js.map +1 -0
  37. package/dist/4618.js +1 -0
  38. package/dist/4652.js +1 -0
  39. package/dist/4944.js +1 -0
  40. package/dist/5173.js +1 -0
  41. package/dist/5220.js +2 -0
  42. package/dist/5220.js.LICENSE.txt +29 -0
  43. package/dist/5220.js.map +1 -0
  44. package/dist/5241.js +1 -0
  45. package/dist/5442.js +1 -0
  46. package/dist/5661.js +1 -0
  47. package/dist/6022.js +1 -0
  48. package/dist/6078.js +2 -0
  49. package/dist/6078.js.LICENSE.txt +9 -0
  50. package/dist/6078.js.map +1 -0
  51. package/dist/627.js +1 -0
  52. package/dist/627.js.map +1 -0
  53. package/dist/6276.js +1 -0
  54. package/dist/6276.js.map +1 -0
  55. package/dist/6468.js +1 -0
  56. package/dist/6679.js +1 -0
  57. package/dist/6737.js +2 -0
  58. package/dist/6737.js.LICENSE.txt +9 -0
  59. package/dist/6737.js.map +1 -0
  60. package/dist/6840.js +1 -0
  61. package/dist/6859.js +1 -0
  62. package/dist/7092.js +1 -0
  63. package/dist/7092.js.map +1 -0
  64. package/dist/7097.js +1 -0
  65. package/dist/7159.js +1 -0
  66. package/dist/723.js +1 -0
  67. package/dist/7495.js +2 -0
  68. package/dist/7495.js.LICENSE.txt +9 -0
  69. package/dist/7495.js.map +1 -0
  70. package/dist/7617.js +1 -0
  71. package/dist/795.js +1 -0
  72. package/dist/8163.js +1 -0
  73. package/dist/8349.js +1 -0
  74. package/dist/8404.js +2 -0
  75. package/dist/{629.js.LICENSE.txt → 8404.js.LICENSE.txt} +9 -3
  76. package/dist/8404.js.map +1 -0
  77. package/dist/8434.js +1 -0
  78. package/dist/8434.js.map +1 -0
  79. package/dist/8618.js +1 -0
  80. package/dist/89.js +2 -0
  81. package/dist/89.js.LICENSE.txt +9 -0
  82. package/dist/89.js.map +1 -0
  83. package/dist/890.js +1 -0
  84. package/dist/9214.js +1 -0
  85. package/dist/9538.js +1 -0
  86. package/dist/9569.js +1 -0
  87. package/dist/986.js +1 -0
  88. package/dist/9876.js +1 -0
  89. package/dist/9876.js.map +1 -0
  90. package/dist/9879.js +1 -0
  91. package/dist/9895.js +1 -0
  92. package/dist/9900.js +1 -0
  93. package/dist/9913.js +1 -0
  94. package/dist/main.js +1 -1
  95. package/dist/main.js.LICENSE.txt +36 -1
  96. package/dist/main.js.map +1 -1
  97. package/dist/openmrs-esm-patient-registration-app.js +1 -0
  98. package/dist/openmrs-esm-patient-registration-app.js.buildmanifest.json +1576 -0
  99. package/dist/openmrs-esm-patient-registration-app.js.map +1 -0
  100. package/dist/routes.json +1 -1
  101. package/package.json +16 -15
  102. package/src/{add-patient-link.tsx → add-patient-link.extension.tsx} +4 -2
  103. package/src/add-patient-link.test.tsx +6 -10
  104. package/src/config-schema.ts +109 -55
  105. package/src/constants.ts +1 -1
  106. package/src/declarations.d.ts +5 -4
  107. package/src/index.ts +10 -29
  108. package/src/nav-link.test.tsx +3 -3
  109. package/src/offline.resources.ts +26 -18
  110. package/src/patient-photo.extension.tsx +3 -1
  111. package/src/patient-registration/field/address/address-field.component.tsx +58 -37
  112. package/src/patient-registration/field/address/address-hierarchy-levels.component.tsx +16 -18
  113. package/src/patient-registration/field/address/address-hierarchy.resource.tsx +3 -3
  114. package/src/patient-registration/field/address/address-hierarchy.test.tsx +290 -0
  115. package/src/patient-registration/field/address/address-search.component.tsx +7 -5
  116. package/src/patient-registration/field/address/address-search.scss +5 -5
  117. package/src/patient-registration/field/address/address-search.test.tsx +140 -0
  118. package/src/patient-registration/field/cause-of-death/cause-of-death.component.tsx +98 -0
  119. package/src/patient-registration/field/custom-field.component.tsx +3 -9
  120. package/src/patient-registration/field/date-and-time-of-death/date-and-time-of-death.component.tsx +84 -0
  121. package/src/patient-registration/field/dob/dob.component.tsx +55 -50
  122. package/src/patient-registration/field/dob/dob.test.tsx +90 -0
  123. package/src/patient-registration/field/field.component.tsx +12 -6
  124. package/src/patient-registration/field/field.resource.ts +11 -4
  125. package/src/patient-registration/field/field.scss +69 -25
  126. package/src/patient-registration/field/field.test.tsx +329 -0
  127. package/src/patient-registration/field/gender/gender-field.component.tsx +14 -9
  128. package/src/patient-registration/field/gender/gender-field.test.tsx +73 -33
  129. package/src/patient-registration/field/id/id-field.component.tsx +24 -23
  130. package/src/patient-registration/field/id/id-field.test.tsx +147 -0
  131. package/src/patient-registration/field/id/identifier-selection-overlay.component.tsx +12 -10
  132. package/src/patient-registration/field/id/identifier-selection.scss +12 -8
  133. package/src/patient-registration/field/name/name-field.component.tsx +10 -5
  134. package/src/patient-registration/field/obs/obs-field.component.tsx +59 -2
  135. package/src/patient-registration/field/obs/obs-field.test.tsx +133 -39
  136. package/src/patient-registration/field/person-attributes/coded-person-attribute-field.component.tsx +3 -3
  137. package/src/patient-registration/field/person-attributes/coded-person-attribute-field.test.tsx +141 -0
  138. package/src/patient-registration/field/person-attributes/location-person-attribute-field.component.tsx +105 -0
  139. package/src/patient-registration/field/person-attributes/location-person-attribute-field.resource.tsx +48 -0
  140. package/src/patient-registration/field/person-attributes/person-attribute-field.component.tsx +19 -22
  141. package/src/patient-registration/field/person-attributes/person-attribute-field.test.tsx +193 -0
  142. package/src/patient-registration/field/person-attributes/text-person-attribute-field.test.tsx +90 -0
  143. package/src/patient-registration/form-manager.test.ts +91 -0
  144. package/src/patient-registration/form-manager.ts +49 -23
  145. package/src/patient-registration/input/basic-input/input/input.component.tsx +6 -2
  146. package/src/patient-registration/input/basic-input/select/select-input.test.tsx +49 -0
  147. package/src/patient-registration/input/custom-input/autosuggest/autosuggest.scss +5 -5
  148. package/src/patient-registration/input/custom-input/autosuggest/autosuggest.test.tsx +164 -0
  149. package/src/patient-registration/input/custom-input/identifier/identifier-input.component.tsx +73 -36
  150. package/src/patient-registration/input/custom-input/identifier/identifier-input.test.tsx +335 -0
  151. package/src/patient-registration/input/dummy-data/dummy-data-input.component.tsx +3 -0
  152. package/src/patient-registration/input/dummy-data/dummy-data-input.test.tsx +2 -11
  153. package/src/patient-registration/input/input.scss +17 -13
  154. package/src/patient-registration/patient-registration-context.ts +22 -11
  155. package/src/patient-registration/patient-registration-hooks.ts +158 -193
  156. package/src/patient-registration/patient-registration-utils.test.ts +33 -0
  157. package/src/patient-registration/patient-registration-utils.ts +11 -13
  158. package/src/patient-registration/patient-registration.component.tsx +87 -103
  159. package/src/patient-registration/{patient-registration.resource.testt.tsx → patient-registration.resource.test.tsx} +0 -4
  160. package/src/patient-registration/patient-registration.resource.ts +27 -3
  161. package/src/patient-registration/patient-registration.scss +27 -38
  162. package/src/patient-registration/patient-registration.test.tsx +579 -0
  163. package/src/patient-registration/patient-registration.types.ts +23 -25
  164. package/src/patient-registration/section/death-info/death-info-section.component.tsx +22 -17
  165. package/src/patient-registration/section/death-info/death-info-section.test.tsx +47 -0
  166. package/src/patient-registration/section/demographics/demographics-section.component.tsx +5 -5
  167. package/src/patient-registration/section/demographics/demographics-section.test.tsx +98 -0
  168. package/src/patient-registration/section/patient-relationships/relationships-section.component.tsx +8 -7
  169. package/src/patient-registration/section/patient-relationships/relationships-section.test.tsx +113 -0
  170. package/src/patient-registration/section/patient-relationships/relationships.resource.tsx +28 -28
  171. package/src/patient-registration/section/patient-relationships/relationships.scss +4 -4
  172. package/src/patient-registration/section/section-wrapper.component.tsx +1 -1
  173. package/src/patient-registration/section/section.component.tsx +1 -1
  174. package/src/patient-registration/section/section.scss +21 -1
  175. package/src/patient-registration/ui-components/overlay/overlay.scss +8 -8
  176. package/src/patient-registration/validation/{patient-registration-validation.test.tsx → patient-registration-validation.test.ts} +71 -23
  177. package/src/patient-registration/validation/patient-registration-validation.ts +123 -0
  178. package/src/resources-context.ts +14 -0
  179. package/src/root.component.tsx +3 -3
  180. package/src/routes.json +10 -24
  181. package/src/widgets/cancel-patient-edit.modal.tsx +33 -0
  182. package/src/widgets/cancel-patient-edit.test.tsx +22 -0
  183. package/src/widgets/delete-identifier-confirmation.modal.tsx +48 -0
  184. package/src/widgets/{delete-identifier-confirmation-modal.testt.tsx → delete-identifier-confirmation.test.tsx} +5 -7
  185. package/src/widgets/edit-patient-details-button.component.tsx +0 -1
  186. package/src/widgets/edit-patient-details-button.test.tsx +35 -0
  187. package/translations/am.json +43 -35
  188. package/translations/ar.json +41 -33
  189. package/translations/ar_SY.json +119 -0
  190. package/translations/bn.json +119 -0
  191. package/translations/de.json +119 -0
  192. package/translations/en.json +44 -42
  193. package/translations/en_US.json +119 -0
  194. package/translations/es.json +69 -57
  195. package/translations/es_MX.json +119 -0
  196. package/translations/fr.json +74 -58
  197. package/translations/he.json +44 -40
  198. package/translations/hi.json +119 -0
  199. package/translations/hi_IN.json +119 -0
  200. package/translations/id.json +119 -0
  201. package/translations/it.json +119 -0
  202. package/translations/ka.json +119 -0
  203. package/translations/km.json +44 -40
  204. package/translations/ku.json +119 -0
  205. package/translations/ky.json +119 -0
  206. package/translations/lg.json +119 -0
  207. package/translations/ne.json +119 -0
  208. package/translations/pl.json +119 -0
  209. package/translations/pt.json +119 -0
  210. package/translations/pt_BR.json +119 -0
  211. package/translations/qu.json +119 -0
  212. package/translations/ro_RO.json +119 -0
  213. package/translations/ru_RU.json +119 -0
  214. package/translations/si.json +119 -0
  215. package/translations/sw.json +119 -0
  216. package/translations/sw_KE.json +119 -0
  217. package/translations/tr.json +119 -0
  218. package/translations/tr_TR.json +119 -0
  219. package/translations/uk.json +119 -0
  220. package/translations/uz.json +119 -0
  221. package/translations/uz@Latn.json +119 -0
  222. package/translations/uz_UZ.json +119 -0
  223. package/translations/vi.json +119 -0
  224. package/translations/zh.json +45 -23
  225. package/translations/zh_CN.json +39 -17
  226. package/.turbo/turbo-build.log +0 -40
  227. package/dist/132.js +0 -1
  228. package/dist/197.js +0 -1
  229. package/dist/236.js +0 -1
  230. package/dist/236.js.map +0 -1
  231. package/dist/300.js +0 -1
  232. package/dist/335.js +0 -1
  233. package/dist/372.js +0 -1
  234. package/dist/372.js.map +0 -1
  235. package/dist/41.js +0 -2
  236. package/dist/41.js.map +0 -1
  237. package/dist/449.js +0 -1
  238. package/dist/449.js.map +0 -1
  239. package/dist/464.js +0 -1
  240. package/dist/464.js.map +0 -1
  241. package/dist/495.js +0 -1
  242. package/dist/495.js.map +0 -1
  243. package/dist/55.js +0 -1
  244. package/dist/56.js +0 -1
  245. package/dist/56.js.map +0 -1
  246. package/dist/621.js +0 -1
  247. package/dist/621.js.map +0 -1
  248. package/dist/629.js +0 -2
  249. package/dist/629.js.map +0 -1
  250. package/dist/652.js +0 -1
  251. package/dist/661.js +0 -1
  252. package/dist/757.js +0 -1
  253. package/dist/757.js.map +0 -1
  254. package/dist/828.js +0 -1
  255. package/dist/828.js.map +0 -1
  256. package/dist/830.js +0 -1
  257. package/dist/830.js.map +0 -1
  258. package/dist/831.js +0 -2
  259. package/dist/831.js.LICENSE.txt +0 -3
  260. package/dist/831.js.map +0 -1
  261. package/dist/876.js +0 -2
  262. package/dist/876.js.map +0 -1
  263. package/dist/879.js +0 -1
  264. package/dist/913.js +0 -2
  265. package/dist/913.js.map +0 -1
  266. package/dist/927.js +0 -1
  267. package/dist/927.js.map +0 -1
  268. package/dist/99.js +0 -1
  269. package/dist/ampath-esm-patient-registration-app.js +0 -1
  270. package/dist/ampath-esm-patient-registration-app.js.buildmanifest.json +0 -694
  271. package/dist/ampath-esm-patient-registration-app.js.map +0 -1
  272. package/src/patient-registration/date-util.ts +0 -52
  273. package/src/patient-registration/field/person-attributes/custom-person-attribute-field.component.tsx +0 -56
  274. package/src/patient-registration/validation/patient-registration-validation.tsx +0 -60
  275. package/src/patient-verification/assets/counties.json +0 -236
  276. package/src/patient-verification/assets/verification-assets.ts +0 -11
  277. package/src/patient-verification/patient-verification-hook.tsx +0 -176
  278. package/src/patient-verification/patient-verification-utils.ts +0 -179
  279. package/src/patient-verification/patient-verification.component.tsx +0 -124
  280. package/src/patient-verification/patient-verification.scss +0 -25
  281. package/src/patient-verification/verification-modal/confirm-prompt.component.tsx +0 -72
  282. package/src/patient-verification/verification-modal/empty-prompt.component.tsx +0 -35
  283. package/src/patient-verification/verification-types.ts +0 -50
  284. package/src/widgets/cancel-patient-edit.component.tsx +0 -37
  285. package/src/widgets/delete-identifier-confirmation-modal.tsx +0 -41
  286. package/src/widgets/delete-identifier-modal.scss +0 -34
  287. /package/dist/{41.js.LICENSE.txt → 4041.js.LICENSE.txt} +0 -0
  288. /package/src/patient-registration/input/custom-input/identifier/{utils.testt.ts → utils.test.ts} +0 -0
@@ -1,15 +1,14 @@
1
1
  import * as Yup from 'yup';
2
+ import camelCase from 'lodash-es/camelCase';
3
+ import { parseDate } from '@openmrs/esm-framework';
2
4
  import {
3
5
  type AddressValidationSchemaType,
6
+ type Encounter,
4
7
  type FormValues,
5
8
  type PatientIdentifier,
6
- type PatientUuidMapType,
7
9
  type PatientIdentifierValue,
8
- type Encounter,
10
+ type PatientUuidMapType,
9
11
  } from './patient-registration.types';
10
- import { parseDate } from '@openmrs/esm-framework';
11
- import camelCase from 'lodash-es/camelCase';
12
- import capitalize from 'lodash-es/capitalize';
13
12
 
14
13
  export function parseAddressTemplateXml(addressTemplate: string) {
15
14
  const templateXmlDoc = new DOMParser().parseFromString(addressTemplate, 'text/xml');
@@ -48,6 +47,7 @@ export function parseAddressTemplateXml(addressTemplate: string) {
48
47
  addressValidationSchema,
49
48
  };
50
49
  }
50
+
51
51
  export function parseAddressTemplateXmlOld(addressTemplate: string) {
52
52
  const templateXmlDoc = new DOMParser().parseFromString(addressTemplate, 'text/xml');
53
53
  const nameMappings = templateXmlDoc.querySelector('nameMappings').querySelectorAll('property');
@@ -124,11 +124,6 @@ export function getFormValuesFromFhirPatient(patient: fhir.Patient) {
124
124
  result.birthdate = patient.birthDate ? parseDate(patient.birthDate) : undefined;
125
125
  result.telephoneNumber = patient.telecom ? patient.telecom[0].value : '';
126
126
 
127
- if (patient.deceasedBoolean || patient.deceasedDateTime) {
128
- result.isDead = true;
129
- result.deathDate = patient.deceasedDateTime ? patient.deceasedDateTime.split('T')[0] : '';
130
- }
131
-
132
127
  return {
133
128
  ...result,
134
129
  ...patient.identifier.map((identifier) => {
@@ -205,10 +200,13 @@ export function getPhonePersonAttributeValueFromFhirPatient(patient: fhir.Patien
205
200
  return result;
206
201
  }
207
202
 
208
- export const filterUndefinedPatientIdenfier = (patientIdenfiers) =>
203
+ type IdentifierMap = { [identifierFieldName: string]: PatientIdentifierValue };
204
+ export const filterOutUndefinedPatientIdentifiers = (patientIdentifiers: IdentifierMap): IdentifierMap =>
209
205
  Object.fromEntries(
210
- Object.entries<PatientIdentifierValue>(patientIdenfiers).filter(
211
- ([key, value]) => value.identifierValue !== undefined,
206
+ Object.entries(patientIdentifiers).filter(
207
+ ([key, value]) =>
208
+ (value.autoGeneration && value.selectedSource.autoGenerationOption.manualEntryEnabled) ||
209
+ value.identifierValue !== undefined,
212
210
  ),
213
211
  );
214
212
 
@@ -1,42 +1,30 @@
1
- import React, { useState, useEffect, useContext, useMemo, useRef } from 'react';
1
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
2
  import classNames from 'classnames';
3
- import { Button, Link, InlineLoading } from '@carbon/react';
4
- import { XAxis, ShareKnowledge } from '@carbon/react/icons';
3
+ import { Button, InlineLoading, Link } from '@carbon/react';
4
+ import { XAxis } from '@carbon/react/icons';
5
5
  import { useLocation, useParams } from 'react-router-dom';
6
6
  import { useTranslation } from 'react-i18next';
7
- import { Formik, Form, type FormikHelpers } from 'formik';
7
+ import { Form, Formik, type FormikHelpers } from 'formik';
8
8
  import {
9
9
  createErrorHandler,
10
+ interpolateUrl,
10
11
  showSnackbar,
11
12
  useConfig,
12
- interpolateUrl,
13
13
  usePatient,
14
14
  usePatientPhoto,
15
15
  } from '@openmrs/esm-framework';
16
+ import { builtInSections, type RegistrationConfig, type SectionDefinition } from '../config-schema';
17
+ import { cancelRegistration, filterOutUndefinedPatientIdentifiers, scrollIntoView } from './patient-registration-utils';
16
18
  import { getValidationSchema } from './validation/patient-registration-validation';
17
- import { type FormValues, type CapturePhotoProps } from './patient-registration.types';
18
- import { PatientRegistrationContext } from './patient-registration-context';
19
- import { type SavePatientForm, SavePatientTransactionManager } from './form-manager';
20
19
  import { DummyDataInput } from './input/dummy-data/dummy-data-input.component';
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';
33
- import { ResourcesContext } from '../offline.resources';
34
- import { builtInSections, type RegistrationConfig, type SectionDefinition } from '../config-schema';
20
+ import { PatientRegistrationContextProvider } from './patient-registration-context';
21
+ import { useResourcesContext } from '../resources-context';
35
22
  import { SectionWrapper } from './section/section-wrapper.component';
23
+ import { type CapturePhotoProps, type FormValues } from './patient-registration.types';
24
+ import { type SavePatientForm, SavePatientTransactionManager } from './form-manager';
25
+ import { useInitialAddressFieldValues, useInitialFormValues, usePatientUuidMap } from './patient-registration-hooks';
36
26
  import BeforeSavePrompt from './before-save-prompt';
37
27
  import styles from './patient-registration.scss';
38
- import PatientVerification from '../patient-verification/patient-verification.component';
39
- import { handleSavePatientToClientRegistry } from '../patient-verification/patient-verification-hook';
40
28
 
41
29
  let exportedInitialFormValuesForTesting = {} as FormValues;
42
30
 
@@ -46,27 +34,36 @@ export interface PatientRegistrationProps {
46
34
  }
47
35
 
48
36
  export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePatientForm, isOffline }) => {
49
- const { currentSession, addressTemplate, identifierTypes } = useContext(ResourcesContext);
50
- const { search } = useLocation();
51
- const config = useConfig() as RegistrationConfig;
52
- const [target, setTarget] = useState<undefined | string>();
37
+ const { t } = useTranslation();
38
+ const { currentSession, identifierTypes } = useResourcesContext();
53
39
  const { patientUuid: uuidOfPatientToEdit } = useParams();
40
+ const { search } = useLocation();
54
41
  const { isLoading: isLoadingPatientToEdit, patient: patientToEdit } = usePatient(uuidOfPatientToEdit);
55
- const { t } = useTranslation();
42
+ const config = useConfig<RegistrationConfig>();
43
+
44
+ const [initialFormValues, setInitialFormValues] = useInitialFormValues(
45
+ isLoadingPatientToEdit,
46
+ patientToEdit,
47
+ uuidOfPatientToEdit,
48
+ );
49
+ const [initialAddressFieldValues] = useInitialAddressFieldValues(
50
+ {},
51
+ isLoadingPatientToEdit,
52
+ patientToEdit,
53
+ uuidOfPatientToEdit,
54
+ );
55
+
56
+ const [patientUuidMap] = usePatientUuidMap({}, isLoadingPatientToEdit, patientToEdit, uuidOfPatientToEdit);
57
+
58
+ const [target, setTarget] = useState<undefined | string>();
56
59
  const [capturePhotoProps, setCapturePhotoProps] = useState<CapturePhotoProps | null>(null);
57
- const [initialFormValues, setInitialFormValues] = useInitialFormValues(uuidOfPatientToEdit);
58
- const [initialAddressFieldValues] = useInitialAddressFieldValues(uuidOfPatientToEdit);
59
- const [patientUuidMap] = usePatientUuidMap(uuidOfPatientToEdit);
60
+
60
61
  const location = currentSession?.sessionLocation?.uuid;
61
62
  const inEditMode = isLoadingPatientToEdit ? undefined : !!(uuidOfPatientToEdit && patientToEdit);
62
63
  const showDummyData = useMemo(() => localStorage.getItem('openmrs:devtools') === 'true' && !inEditMode, [inEditMode]);
63
64
  const { data: photo } = usePatientPhoto(patientToEdit?.id);
64
65
  const savePatientTransactionManager = useRef(new SavePatientTransactionManager());
65
- const fieldDefinition = config?.fieldDefinitions?.filter((def) => def.type === 'address');
66
- const validationSchema = getValidationSchema(config);
67
- const [enableClientRegistry, setEnableClientRegistry] = useState(
68
- inEditMode ? initialFormValues.identifiers['nationalUniquePatientIdentifier']?.identifierValue : false,
69
- );
66
+ const validationSchema = getValidationSchema(config, t);
70
67
 
71
68
  useEffect(() => {
72
69
  exportedInitialFormValuesForTesting = initialFormValues;
@@ -86,7 +83,7 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
86
83
  const abortController = new AbortController();
87
84
  helpers.setSubmitting(true);
88
85
 
89
- const updatedFormValues = { ...values, identifiers: filterUndefinedPatientIdenfier(values.identifiers) };
86
+ const updatedFormValues = { ...values, identifiers: filterOutUndefinedPatientIdentifiers(values.identifiers) };
90
87
  try {
91
88
  await savePatientForm(
92
89
  !inEditMode,
@@ -121,26 +118,6 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
121
118
 
122
119
  setTarget(redirectUrl);
123
120
  } 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
-
144
121
  if (error.responseBody?.error?.globalErrors) {
145
122
  error.responseBody.error.globalErrors.forEach((error) => {
146
123
  showSnackbar({
@@ -161,41 +138,74 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
161
138
  });
162
139
  } else {
163
140
  createErrorHandler()(error);
164
- console.error(error);
165
141
  }
166
142
 
167
143
  helpers.setSubmitting(false);
168
144
  }
169
145
  };
170
146
 
147
+ const getDescription = (errors) => {
148
+ return (
149
+ <ul style={{ listStyle: 'inside' }}>
150
+ {Object.keys(errors).map((error, index) => {
151
+ return <li key={index}>{t(`${error}LabelText`, error)}</li>;
152
+ })}
153
+ </ul>
154
+ );
155
+ };
156
+
171
157
  const displayErrors = (errors) => {
172
158
  if (errors && typeof errors === 'object' && !!Object.keys(errors).length) {
173
- Object.keys(errors).forEach((error) => {
174
- showSnackbar({
175
- subtitle: t(`${error}LabelText`, error),
176
- title: t('incompleteForm', 'The following field has errors:'),
177
- kind: 'warning',
178
- isLowContrast: true,
179
- timeoutInMs: 5000,
180
- });
159
+ showSnackbar({
160
+ isLowContrast: true,
161
+ kind: 'warning',
162
+ title: t('fieldsWithErrors', 'The following fields have errors:'),
163
+ subtitle: <>{getDescription(errors)}</>,
181
164
  });
182
165
  }
183
166
  };
184
167
 
168
+ const createContextValue = useCallback(
169
+ (formikProps) => ({
170
+ identifierTypes,
171
+ validationSchema,
172
+ values: formikProps.values,
173
+ inEditMode,
174
+ setFieldValue: formikProps.setFieldValue,
175
+ setFieldTouched: formikProps.setFieldTouched,
176
+ setCapturePhotoProps,
177
+ currentPhoto: photo?.imageSrc,
178
+ isOffline,
179
+ initialFormValues: formikProps.initialValues,
180
+ setInitialFormValues,
181
+ }),
182
+ [
183
+ identifierTypes,
184
+ validationSchema,
185
+ inEditMode,
186
+ setCapturePhotoProps,
187
+ photo?.imageSrc,
188
+ isOffline,
189
+ setInitialFormValues,
190
+ ],
191
+ );
192
+
185
193
  return (
186
194
  <Formik
187
195
  enableReinitialize
188
196
  initialValues={initialFormValues}
189
- validationSchema={validationSchema}
190
- onSubmit={onFormSubmit}>
197
+ onSubmit={onFormSubmit}
198
+ validationSchema={validationSchema}>
191
199
  {(props) => (
192
200
  <Form className={styles.form}>
193
- <BeforeSavePrompt when={props.dirty} redirect={target} />
201
+ <BeforeSavePrompt when={Object.keys(props.touched).length > 0} redirect={target} />
194
202
  <div className={styles.formContainer}>
195
203
  <div>
196
204
  <div className={styles.stickyColumn}>
197
205
  <h4>
198
- {inEditMode ? t('edit', 'Edit') : t('createNew', 'Create New')} {t('patient', 'Patient')}
206
+ {inEditMode
207
+ ? t('editPatientDetails', 'Edit patient details')
208
+ : t('createNewPatient', 'Create new patient')}
199
209
  </h4>
200
210
  {showDummyData && <DummyDataInput setValues={props.setValues} />}
201
211
  <p className={styles.label01}>{t('jumpTo', 'Jump to')}</p>
@@ -206,18 +216,6 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
206
216
  </Link>
207
217
  </div>
208
218
  ))}
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>
221
219
  <Button
222
220
  className={styles.submitButton}
223
221
  type="submit"
@@ -225,40 +223,26 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
225
223
  // Current session and identifiers are required for patient registration.
226
224
  // If currentSession or identifierTypes are not available, then the
227
225
  // user should be blocked to register the patient.
228
- disabled={!currentSession || !identifierTypes || props.isSubmitting || !enableClientRegistry}>
226
+ disabled={!currentSession || !identifierTypes || props.isSubmitting}>
229
227
  {props.isSubmitting ? (
230
228
  <InlineLoading
231
229
  className={styles.spinner}
232
230
  description={`${t('submitting', 'Submitting')} ...`}
233
231
  iconDescription="submitting"
234
- status="active"
235
232
  />
236
233
  ) : inEditMode ? (
237
- t('updatePatient', 'Update Patient')
234
+ t('updatePatient', 'Update patient')
238
235
  ) : (
239
- t('registerPatient', 'Register Patient')
236
+ t('registerPatient', 'Register patient')
240
237
  )}
241
238
  </Button>
242
- <Button className={styles.cancelButton} kind="tertiary" onClick={cancelRegistration}>
239
+ <Button className={styles.cancelButton} kind="secondary" onClick={cancelRegistration}>
243
240
  {t('cancel', 'Cancel')}
244
241
  </Button>
245
242
  </div>
246
243
  </div>
247
244
  <div className={styles.infoGrid}>
248
- <PatientRegistrationContext.Provider
249
- value={{
250
- identifierTypes: identifierTypes,
251
- validationSchema,
252
- values: props.values,
253
- inEditMode,
254
- setFieldValue: props.setFieldValue,
255
- setCapturePhotoProps,
256
- currentPhoto: photo?.imageSrc,
257
- isOffline,
258
- initialFormValues: props.initialValues,
259
- setInitialFormValues,
260
- }}>
261
- <PatientVerification props={props} setInitialFormValues={setInitialFormValues} />
245
+ <PatientRegistrationContextProvider value={createContextValue(props)}>
262
246
  {sections.map((section, index) => (
263
247
  <SectionWrapper
264
248
  key={`registration-section-${section.id}`}
@@ -266,7 +250,7 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
266
250
  index={index}
267
251
  />
268
252
  ))}
269
- </PatientRegistrationContext.Provider>
253
+ </PatientRegistrationContextProvider>
270
254
  </div>
271
255
  </div>
272
256
  </Form>
@@ -8,10 +8,6 @@ jest.mock('@openmrs/esm-framework', () => ({
8
8
  }));
9
9
 
10
10
  describe('savePatient', () => {
11
- afterEach(() => {
12
- jest.resetAllMocks();
13
- });
14
-
15
11
  it('appends patient uuid in url if provided', () => {
16
12
  mockOpenmrsFetch.mockImplementationOnce((url) => url);
17
13
  savePatient(null, '1234');
@@ -1,11 +1,12 @@
1
1
  import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
2
2
  import { type Patient, type Relationship, type PatientIdentifier, type Encounter } from './patient-registration.types';
3
+ import dayjs from 'dayjs';
3
4
 
4
- export const uuidIdentifier = '58a4732e-1359-11df-a1f1-0026b9348838';
5
- export const uuidTelephoneNumber = '72a759a8-1359-11df-a1f1-0026b9348838';
5
+ export const uuidIdentifier = '05a29f94-c0ed-11e2-94be-8c13b969e334';
6
+ export const uuidTelephoneNumber = '14d4f066-15f5-102d-96e4-000c29c2a5d7';
6
7
 
7
8
  function dataURItoFile(dataURI: string) {
8
- const byteString = atob(dataURI.split(',')[1]);
9
+ const byteString = window.atob(dataURI.split(',')[1]);
9
10
  const mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
10
11
  // write the bytes of the string to a typed array
11
12
  const buffer = new Uint8Array(byteString.length);
@@ -57,6 +58,22 @@ export function generateIdentifier(source: string) {
57
58
  });
58
59
  }
59
60
 
61
+ export async function generateAmrsUniversalIdentifier() {
62
+ const abortController = new AbortController();
63
+ const resp = await openmrsFetch(`https://ngx.ampath.or.ke/amrs-id-generator/generateidentifier`, {
64
+ headers: {
65
+ 'Content-Type': 'application/json',
66
+ },
67
+ method: 'POST',
68
+ body: {
69
+ user: 1,
70
+ },
71
+ signal: abortController.signal,
72
+ });
73
+ const data = await resp.json();
74
+ return data['identifier'] ?? '';
75
+ }
76
+
60
77
  export function deletePersonName(nameUuid: string, personUuid: string) {
61
78
  const abortController = new AbortController();
62
79
 
@@ -188,3 +205,10 @@ export async function deletePatientIdentifier(patientUuid: string, patientIdenti
188
205
  signal: abortController.signal,
189
206
  });
190
207
  }
208
+
209
+ export function getDatetime(date: Date | string, time: string, timeFormat: 'AM' | 'PM') {
210
+ const datetime = new Date(date);
211
+ const [hours, minutes] = time.split(':').map(Number);
212
+ const fullHours = timeFormat === 'PM' ? (hours % 12) + 12 : hours % 12;
213
+ return dayjs(datetime).hour(fullHours).minute(minutes).second(0).millisecond(0).toDate();
214
+ }
@@ -1,13 +1,9 @@
1
- @use '@carbon/styles/scss/spacing';
2
- @use '@carbon/styles/scss/type';
3
- @import '~@openmrs/esm-styleguide/src/vars';
4
-
5
- .title {
6
- color: var(--omrs-color-brand-teal);
7
- }
1
+ @use '@carbon/layout';
2
+ @use '@carbon/type';
3
+ @use '@openmrs/esm-styleguide/src/vars' as *;
8
4
 
9
5
  .submit {
10
- width: 250px;
6
+ width: 15.625rem;
11
7
  }
12
8
 
13
9
  .submit:hover {
@@ -19,34 +15,34 @@
19
15
  }
20
16
 
21
17
  .submitButton {
22
- margin-bottom: spacing.$spacing-05;
18
+ margin-bottom: layout.$spacing-05;
23
19
  width: 11.688rem;
24
20
  display: block;
25
21
  }
26
22
 
27
23
  .infoGrid {
28
24
  width: 100%;
29
- padding-left: spacing.$spacing-07;
25
+ padding-left: layout.$spacing-07;
30
26
  margin-bottom: 40vh;
31
- margin-top: spacing.$spacing-05;
27
+ margin-top: layout.$spacing-05;
32
28
  max-width: 50rem;
33
29
  }
34
30
 
35
- .label01 {
36
- @include type.type-style('label-01');
37
- margin-top: spacing.$spacing-05;
38
- margin-bottom: spacing.$spacing-05;
39
- color: $ui-04;
31
+ :global(.omrs-breakpoint-lt-desktop) {
32
+ .infoGrid {
33
+ max-width: unset;
34
+ }
40
35
  }
41
36
 
42
- .productiveHeading02 {
43
- @include type.type-style('heading-compact-02');
44
- color: $ui-04;
45
- cursor: pointer;
37
+ .label01 {
38
+ @include type.type-style('label-01');
39
+ margin-top: layout.$spacing-05;
40
+ margin-bottom: layout.$spacing-05;
41
+ color: $ui-05;
46
42
  }
47
43
 
48
44
  .space05 {
49
- margin: spacing.$spacing-05 0 spacing.$spacing-05 0;
45
+ margin: layout.$spacing-05 0;
50
46
  }
51
47
 
52
48
  .formContainer {
@@ -56,9 +52,9 @@
56
52
 
57
53
  .stickyColumn {
58
54
  position: sticky;
59
- margin-top: spacing.$spacing-05;
60
- // 3rem for the nav height and 1rem for top margin
61
- top: 4rem;
55
+ margin-top: layout.$spacing-05;
56
+ // layout.$spacing-09 for the nav height and layout.$spacing-05 for top margin
57
+ top: layout.$spacing-10;
62
58
  }
63
59
 
64
60
  .touchTarget a:active {
@@ -68,7 +64,7 @@
68
64
  .linkName {
69
65
  color: $color-gray-70;
70
66
  line-height: 1.38;
71
- font-size: spacing.$spacing-05;
67
+ font-size: layout.$spacing-05;
72
68
  font-weight: 600;
73
69
 
74
70
  &:active {
@@ -83,19 +79,12 @@
83
79
  }
84
80
  }
85
81
 
86
- .main {
87
- background-color: white;
88
- }
89
-
90
- :global(.omrs-breakpoint-lt-desktop) {
91
- .infoGrid {
92
- max-width: unset;
93
- }
94
- }
95
-
96
82
  .spinner {
97
- &:global(.cds--inline-loading) {
98
- min-height: 1rem;
83
+ min-height: layout.$spacing-05;
84
+ width: max-content;
85
+
86
+ :global(.cds--inline-loading__text) {
87
+ @include type.type-style('body-01');
99
88
  }
100
89
  }
101
90
 
@@ -109,6 +98,6 @@ html[dir='rtl'] {
109
98
 
110
99
  .infoGrid {
111
100
  padding-left: unset;
112
- padding-right: spacing.$spacing-07;
101
+ padding-right: layout.$spacing-07;
113
102
  }
114
103
  }