@ampath/esm-patient-registration-app 6.0.1-pre.96 → 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
@@ -25,7 +25,10 @@ export const dummyFormValues: FormValues = {
25
25
  telephoneNumber: '0800001066',
26
26
  isDead: false,
27
27
  deathDate: '',
28
+ deathTime: '',
29
+ deathTimeFormat: 'AM',
28
30
  deathCause: '',
31
+ nonCodedCauseOfDeath: '',
29
32
  relationships: [],
30
33
  address: {
31
34
  address1: 'Bom Jesus Street',
@@ -3,18 +3,9 @@ import { render, screen } from '@testing-library/react';
3
3
  import userEvent from '@testing-library/user-event';
4
4
  import { DummyDataInput, dummyFormValues } from './dummy-data-input.component';
5
5
  import { initialFormValues } from '../../patient-registration.component';
6
- import { type FormValues } from '../../patient-registration-types';
6
+ import { type FormValues } from '../../patient-registration.types';
7
7
 
8
- jest.mock('@openmrs/esm-framework', () => {
9
- const originalModule = jest.requireActual('@openmrs/esm-framework');
10
-
11
- return {
12
- ...originalModule,
13
- validator: jest.fn(),
14
- };
15
- });
16
-
17
- describe('dummy data input', () => {
8
+ describe('Dummy data input', () => {
18
9
  let formValues: FormValues = initialFormValues;
19
10
 
20
11
  const setupInput = async () => {
@@ -1,6 +1,6 @@
1
- @use '@carbon/styles/scss/spacing';
2
- @use '@carbon/styles/scss/type';
3
- @import '../../patient-registration/patient-registration.scss';
1
+ @use '@carbon/layout';
2
+ @use '@carbon/type';
3
+ @use '@openmrs/esm-styleguide/src/vars' as *;
4
4
 
5
5
  .fieldRow {
6
6
  display: flex;
@@ -10,7 +10,7 @@
10
10
  }
11
11
 
12
12
  .subFieldRow {
13
- margin-bottom: 5px;
13
+ margin-bottom: 0.3125rem;
14
14
  }
15
15
 
16
16
  .label {
@@ -20,7 +20,7 @@
20
20
 
21
21
  .textID,
22
22
  .comboInput {
23
- margin-bottom: spacing.$spacing-05;
23
+ margin-bottom: layout.$spacing-05;
24
24
  }
25
25
 
26
26
  .requiredField {
@@ -28,15 +28,15 @@
28
28
  }
29
29
 
30
30
  .input {
31
- margin-right: 5px;
31
+ margin-right: 0.3125rem;
32
32
  }
33
33
 
34
34
  .checkboxField {
35
35
  display: flex;
36
36
  flex-direction: row;
37
37
  justify-content: flex-start;
38
- width: 400px;
39
- margin-left: 10px;
38
+ width: 25rem;
39
+ margin-left: 0.625rem;
40
40
  }
41
41
 
42
42
  .textInput {
@@ -50,9 +50,9 @@
50
50
  }
51
51
 
52
52
  .checkboxInput {
53
- height: 1.5rem !important;
54
- width: 1.5rem !important;
55
- margin-top: 8px;
53
+ height: layout.$spacing-06 !important;
54
+ width: layout.$spacing-06 !important;
55
+ margin-top: layout.$spacing-03;
56
56
  }
57
57
 
58
58
  .selectInput {
@@ -89,7 +89,7 @@
89
89
  .IDInput {
90
90
  display: grid;
91
91
  grid-template-columns: 1fr auto;
92
- align-items: end;
92
+ align-items: center;
93
93
  }
94
94
 
95
95
  .trashCan {
@@ -114,5 +114,9 @@
114
114
 
115
115
  .comboInputItemOption {
116
116
  margin: 0;
117
- padding-left: 1rem;
117
+ padding-left: layout.$spacing-05;
118
+ }
119
+
120
+ .actionButtonContainer {
121
+ margin-left: layout.$spacing-05;
118
122
  }
@@ -1,24 +1,35 @@
1
- import { useConfig } from '@openmrs/esm-framework';
2
- import { createContext, type SetStateAction } from 'react';
1
+ import { createContext, type SetStateAction, useContext } from 'react';
2
+ import { type PatientIdentifierType, useConfig } from '@openmrs/esm-framework';
3
+ import { type CapturePhotoProps, type FormValues } from './patient-registration.types';
3
4
  import { type RegistrationConfig } from '../config-schema';
4
- import { type FormValues, type CapturePhotoProps } from './patient-registration.types';
5
5
 
6
6
  export interface PatientRegistrationContextProps {
7
- identifierTypes: Array<any>;
8
- values: FormValues;
9
- validationSchema: any;
10
- inEditMode: boolean;
11
- setFieldValue(field: string, value: any, shouldValidate?: boolean): void;
12
- setCapturePhotoProps(value: SetStateAction<CapturePhotoProps>): void;
13
7
  currentPhoto: string;
14
- isOffline: boolean;
8
+ identifierTypes: Array<PatientIdentifierType>;
9
+ inEditMode: boolean;
15
10
  initialFormValues: FormValues;
11
+ isOffline: boolean;
12
+ setCapturePhotoProps(value: SetStateAction<CapturePhotoProps>): void;
13
+ setFieldTouched(field: string, isTouched?: any, shouldValidate?: boolean): void;
14
+ setFieldValue(field: string, value: any, shouldValidate?: boolean): void;
16
15
  setInitialFormValues?: React.Dispatch<SetStateAction<FormValues>>;
16
+ validationSchema: any;
17
+ values: FormValues;
17
18
  }
18
19
 
19
20
  export const PatientRegistrationContext = createContext<PatientRegistrationContextProps | undefined>(undefined);
20
21
 
22
+ export const PatientRegistrationContextProvider = PatientRegistrationContext.Provider;
23
+
24
+ export const usePatientRegistrationContext = () => {
25
+ const context = useContext(PatientRegistrationContext);
26
+ if (!context) {
27
+ throw new Error('usePatientRegistrationContext must be used within a PatientRegistrationContextProvider');
28
+ }
29
+ return context;
30
+ };
31
+
21
32
  export function useFieldConfig(field: string) {
22
- const { fieldConfigurations } = useConfig() as RegistrationConfig;
33
+ const { fieldConfigurations } = useConfig<RegistrationConfig>();
23
34
  return fieldConfigurations[field];
24
35
  }
@@ -1,29 +1,26 @@
1
+ import { type Dispatch, useEffect, useMemo, useState, useRef } from 'react';
2
+ import { camelCase } from 'lodash-es';
3
+ import { v4 } from 'uuid';
4
+ import dayjs from 'dayjs';
5
+ import useSWR from 'swr';
1
6
  import {
2
7
  type FetchResponse,
3
8
  type OpenmrsResource,
4
9
  getSynchronizationItems,
5
10
  openmrsFetch,
6
- useConfig,
7
- usePatient,
8
11
  restBaseUrl,
12
+ useConfig,
9
13
  } from '@openmrs/esm-framework';
10
- import last from 'lodash-es/last';
11
- import camelCase from 'lodash-es/camelCase';
12
- import { type Dispatch, useEffect, useMemo, useState } from 'react';
13
- import useSWR from 'swr';
14
- import { v4 } from 'uuid';
15
14
  import { type RegistrationConfig } from '../config-schema';
16
15
  import { patientRegistration } from '../constants';
17
- import { useConceptAnswers, useGlobalProperties } from '../patient-verification/patient-verification-hook';
16
+ import { useInitialPatientRelationships } from './section/patient-relationships/relationships.resource';
18
17
  import {
18
+ type Encounter,
19
19
  type FormValues,
20
+ type PatientIdentifierResponse,
20
21
  type PatientRegistration,
21
22
  type PatientUuidMapType,
22
23
  type PersonAttributeResponse,
23
- type PatientIdentifierResponse,
24
- type Encounter,
25
- type ConceptAnswers,
26
- type ObsResponse,
27
24
  } from './patient-registration.types';
28
25
  import {
29
26
  getAddressFieldValuesFromFhirPatient,
@@ -32,38 +29,63 @@ import {
32
29
  getPhonePersonAttributeValueFromFhirPatient,
33
30
  latestFirstEncounter,
34
31
  } from './patient-registration-utils';
35
- import { useInitialPatientRelationships } from './section/patient-relationships/relationships.resource';
36
- import dayjs from 'dayjs';
37
32
 
38
- export function useInitialFormValues(patientUuid: string): [FormValues, Dispatch<FormValues>] {
39
- const { martialStatus, education, occupation, educationLoad } = useConcepts();
40
- const { isLoading: isLoadingPatientToEdit, patient: patientToEdit } = usePatient(patientUuid);
33
+ interface AddressFieldValues {
34
+ address?: {
35
+ cityVillage?: string;
36
+ country?: string;
37
+ countyDistrict?: string;
38
+ postalCode?: string;
39
+ stateProvince?: string;
40
+ [key: string]: string | undefined;
41
+ };
42
+ }
43
+
44
+ interface DeathInfoResults {
45
+ causeOfDeath: OpenmrsResource | null;
46
+ causeOfDeathNonCoded: string | null;
47
+ dead: boolean;
48
+ deathDate: string;
49
+ display: string;
50
+ uuid: string;
51
+ }
52
+
53
+ export function useInitialFormValues(
54
+ isLoadingPatientToEdit: boolean,
55
+ patientToEdit: fhir.Patient,
56
+ patientUuid: string,
57
+ ): [FormValues, Dispatch<FormValues>] {
58
+ const { freeTextFieldConceptUuid } = useConfig<RegistrationConfig>();
59
+ const { data: deathInfo, isLoading: isLoadingDeathInfo } = useInitialPersonDeathInfo(patientUuid);
41
60
  const { data: attributes, isLoading: isLoadingAttributes } = useInitialPersonAttributes(patientUuid);
42
61
  const { data: identifiers, isLoading: isLoadingIdentifiers } = useInitialPatientIdentifiers(patientUuid);
43
62
  const { data: relationships, isLoading: isLoadingRelationships } = useInitialPatientRelationships(patientUuid);
44
- const { data: obs, isLoading: isLoadingObs, obs: observations } = usePatientObs(patientUuid);
45
- const { data: token, isLoading: isLoadingToken } = useGlobalProperties();
63
+ const { data: encounters } = useInitialEncounters(patientUuid, patientToEdit);
64
+
46
65
  const [initialFormValues, setInitialFormValues] = useState<FormValues>({
47
- patientUuid: v4(),
48
- givenName: '',
49
- middleName: '',
50
- familyName: '',
66
+ additionalFamilyName: '',
51
67
  additionalGivenName: '',
52
68
  additionalMiddleName: '',
53
- additionalFamilyName: '',
54
69
  addNameInLocalLanguage: false,
55
- gender: '',
70
+ address: {},
56
71
  birthdate: null,
57
- yearsEstimated: 0,
58
- monthsEstimated: 0,
59
72
  birthdateEstimated: false,
60
- telephoneNumber: '',
61
- isDead: false,
62
- deathDate: '',
63
73
  deathCause: '',
64
- relationships: [],
74
+ deathDate: undefined,
75
+ deathTime: undefined,
76
+ deathTimeFormat: 'AM',
77
+ familyName: '',
78
+ gender: '',
79
+ givenName: '',
65
80
  identifiers: {},
66
- address: {},
81
+ isDead: false,
82
+ middleName: '',
83
+ monthsEstimated: 0,
84
+ nonCodedCauseOfDeath: '',
85
+ patientUuid: v4(),
86
+ relationships: [],
87
+ telephoneNumber: '',
88
+ yearsEstimated: 0,
67
89
  });
68
90
 
69
91
  useEffect(() => {
@@ -71,21 +93,20 @@ export function useInitialFormValues(patientUuid: string): [FormValues, Dispatch
71
93
  if (patientToEdit) {
72
94
  const birthdateEstimated = !/^\d{4}-\d{2}-\d{2}$/.test(patientToEdit.birthDate);
73
95
  const [years = 0, months = 0] = patientToEdit.birthDate.split('-').map((val) => parseInt(val));
74
- // Please refer: https://github.com/openmrs/openmrs-esm-patient-management/pull/697#issuecomment-1562706118
75
96
  const estimatedMonthsAvailable = patientToEdit.birthDate.split('-').length > 1;
76
97
  const yearsEstimated = birthdateEstimated ? Math.floor(dayjs().diff(patientToEdit.birthDate, 'month') / 12) : 0;
77
98
  const monthsEstimated =
78
99
  birthdateEstimated && estimatedMonthsAvailable ? dayjs().diff(patientToEdit.birthDate, 'month') % 12 : 0;
79
100
 
80
- setInitialFormValues({
81
- ...initialFormValues,
101
+ setInitialFormValues((currentValues) => ({
102
+ ...currentValues,
82
103
  ...getFormValuesFromFhirPatient(patientToEdit),
83
104
  address: getAddressFieldValuesFromFhirPatient(patientToEdit),
84
105
  ...getPhonePersonAttributeValueFromFhirPatient(patientToEdit),
85
106
  birthdateEstimated: !/^\d{4}-\d{2}-\d{2}$/.test(patientToEdit.birthDate),
86
107
  yearsEstimated,
87
108
  monthsEstimated,
88
- });
109
+ }));
89
110
  } else if (!isLoadingPatientToEdit && patientUuid) {
90
111
  const registration = await getPatientRegistration(patientUuid);
91
112
 
@@ -101,15 +122,26 @@ export function useInitialFormValues(patientUuid: string): [FormValues, Dispatch
101
122
  })();
102
123
  }, [isLoadingPatientToEdit, patientToEdit, patientUuid]);
103
124
 
104
- // Setting authentication token
105
-
125
+ // Set initial patient death info
106
126
  useEffect(() => {
107
- if (!isLoadingToken && token) {
108
- setInitialFormValues((initialFormValues) => ({ ...initialFormValues, token: String(token.access_token) }));
127
+ if (!isLoadingDeathInfo && deathInfo?.dead) {
128
+ const deathDatetime = deathInfo.deathDate || null;
129
+ const deathDate = deathDatetime ? new Date(deathDatetime) : undefined;
130
+ const time = deathDate ? dayjs(deathDate).format('hh:mm') : undefined;
131
+ const timeFormat = deathDate ? (dayjs(deathDate).hour() >= 12 ? 'PM' : 'AM') : 'AM';
132
+ setInitialFormValues((initialFormValues) => ({
133
+ ...initialFormValues,
134
+ isDead: deathInfo.dead || false,
135
+ deathDate: deathDate,
136
+ deathTime: time,
137
+ deathTimeFormat: timeFormat,
138
+ deathCause: deathInfo.causeOfDeathNonCoded ? freeTextFieldConceptUuid : deathInfo.causeOfDeath?.uuid,
139
+ nonCodedCauseOfDeath: deathInfo.causeOfDeathNonCoded,
140
+ }));
109
141
  }
110
- }, [isLoadingToken, token]);
142
+ }, [isLoadingDeathInfo, deathInfo, freeTextFieldConceptUuid]);
111
143
 
112
- // Set initial patient relationships
144
+ // Combined effect for relationships and identifiers
113
145
  useEffect(() => {
114
146
  if (!isLoadingRelationships && relationships) {
115
147
  setInitialFormValues((initialFormValues) => ({
@@ -117,101 +149,118 @@ export function useInitialFormValues(patientUuid: string): [FormValues, Dispatch
117
149
  relationships,
118
150
  }));
119
151
  }
120
- }, [isLoadingRelationships, relationships, setInitialFormValues]);
121
152
 
122
- // Set Initial patient identifiers
123
- useEffect(() => {
124
153
  if (!isLoadingIdentifiers && identifiers) {
125
154
  setInitialFormValues((initialFormValues) => ({
126
155
  ...initialFormValues,
127
156
  identifiers,
128
157
  }));
129
158
  }
130
- }, [isLoadingIdentifiers, identifiers, setInitialFormValues]);
159
+ }, [isLoadingRelationships, relationships, isLoadingIdentifiers, identifiers]);
131
160
 
132
161
  // Set Initial person attributes
133
162
  useEffect(() => {
134
163
  if (!isLoadingAttributes && attributes) {
135
- let personAttributes = {};
136
- attributes.forEach((attribute) => {
137
- personAttributes[attribute.attributeType.uuid] =
138
- attribute.attributeType.format === 'org.openmrs.Concept' && typeof attribute.value === 'object'
139
- ? attribute.value?.uuid
140
- : attribute.value;
141
- });
164
+ const personAttributes = attributes.reduce(
165
+ (acc, attribute) => ({
166
+ ...acc,
167
+ [attribute.attributeType.uuid]:
168
+ attribute.attributeType.format === 'org.openmrs.Concept' && typeof attribute.value === 'object'
169
+ ? attribute.value?.uuid
170
+ : attribute.value,
171
+ }),
172
+ {},
173
+ );
142
174
 
143
175
  setInitialFormValues((initialFormValues) => ({
144
176
  ...initialFormValues,
145
177
  attributes: personAttributes,
146
178
  }));
147
179
  }
148
- }, [attributes, setInitialFormValues, isLoadingAttributes]);
149
-
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
180
+ }, [attributes, isLoadingAttributes]);
159
181
 
182
+ // Set Initial registration encounters
160
183
  useEffect(() => {
161
- if (!educationLoad) {
184
+ if (patientToEdit && encounters) {
162
185
  setInitialFormValues((initialFormValues) => ({
163
186
  ...initialFormValues,
164
- concepts: [...occupation, ...martialStatus, ...education],
187
+ obs: encounters as Record<string, string>,
165
188
  }));
166
189
  }
167
- }, [educationLoad]);
190
+ }, [encounters, patientToEdit]);
168
191
 
169
192
  return [initialFormValues, setInitialFormValues];
170
193
  }
171
194
 
172
- export function useInitialAddressFieldValues(patientUuid: string, fallback = {}): [object, Dispatch<object>] {
173
- const { isLoading, patient } = usePatient(patientUuid);
174
- const [initialAddressFieldValues, setInitialAddressFieldValues] = useState<object>(fallback);
195
+ export function useInitialAddressFieldValues(
196
+ fallback: AddressFieldValues = {},
197
+ isLoadingPatientToEdit: boolean,
198
+ patientToEdit: fhir.Patient,
199
+ patientUuid: string,
200
+ ): [AddressFieldValues, Dispatch<AddressFieldValues>] {
201
+ const fallbackRef = useRef(fallback);
202
+ const [initialAddressFieldValues, setInitialAddressFieldValues] = useState<AddressFieldValues>(fallbackRef.current);
175
203
 
176
204
  useEffect(() => {
177
205
  (async () => {
178
- if (patient) {
179
- setInitialAddressFieldValues({
180
- ...initialAddressFieldValues,
181
- address: getAddressFieldValuesFromFhirPatient(patient),
182
- });
183
- } else if (!isLoading && patientUuid) {
206
+ if (patientToEdit) {
207
+ setInitialAddressFieldValues((currentValues) => ({
208
+ ...currentValues,
209
+ address: getAddressFieldValuesFromFhirPatient(patientToEdit),
210
+ }));
211
+ } else if (!isLoadingPatientToEdit && patientUuid) {
184
212
  const registration = await getPatientRegistration(patientUuid);
185
- setInitialAddressFieldValues(registration?._patientRegistrationData.initialAddressFieldValues ?? fallback);
213
+ setInitialAddressFieldValues(
214
+ registration?._patientRegistrationData.initialAddressFieldValues ?? fallbackRef.current,
215
+ );
186
216
  }
187
217
  })();
188
- }, [isLoading, patient, patientUuid]);
218
+ }, [isLoadingPatientToEdit, patientToEdit, patientUuid]);
189
219
 
190
220
  return [initialAddressFieldValues, setInitialAddressFieldValues];
191
221
  }
192
222
 
193
223
  export function usePatientUuidMap(
194
- patientUuid: string,
195
224
  fallback: PatientUuidMapType = {},
225
+ isLoadingPatientToEdit: boolean,
226
+ patientToEdit: fhir.Patient,
227
+ patientUuid: string,
196
228
  ): [PatientUuidMapType, Dispatch<PatientUuidMapType>] {
197
- const { isLoading: isLoadingPatientToEdit, patient: patientToEdit } = usePatient(patientUuid);
229
+ const fallbackRef = useRef(fallback);
230
+ const [patientUuidMap, setPatientUuidMap] = useState(fallbackRef.current);
198
231
  const { data: attributes } = useInitialPersonAttributes(patientUuid);
199
- const [patientUuidMap, setPatientUuidMap] = useState(fallback);
200
232
 
201
233
  useEffect(() => {
202
- if (patientToEdit) {
203
- setPatientUuidMap({ ...patientUuidMap, ...getPatientUuidMapFromFhirPatient(patientToEdit) });
204
- } else if (!isLoadingPatientToEdit && patientUuid) {
205
- getPatientRegistration(patientUuid).then((registration) =>
206
- setPatientUuidMap(registration?._patientRegistrationData.initialAddressFieldValues ?? fallback),
207
- );
234
+ const abortController = new AbortController();
235
+
236
+ async function updatePatientMap() {
237
+ if (patientToEdit) {
238
+ setPatientUuidMap((prevMap) => ({
239
+ ...prevMap,
240
+ ...getPatientUuidMapFromFhirPatient(patientToEdit),
241
+ }));
242
+ } else if (!isLoadingPatientToEdit && patientUuid) {
243
+ try {
244
+ const registration = await getPatientRegistration(patientUuid);
245
+ if (!abortController.signal.aborted) {
246
+ setPatientUuidMap(registration?._patientRegistrationData.initialAddressFieldValues ?? fallbackRef.current);
247
+ }
248
+ } catch (error) {
249
+ if (!abortController.signal.aborted) {
250
+ console.error('Failed to get patient registration:', error);
251
+ }
252
+ }
253
+ }
208
254
  }
255
+
256
+ updatePatientMap();
257
+ return () => abortController.abort();
209
258
  }, [isLoadingPatientToEdit, patientToEdit, patientUuid]);
210
259
 
211
260
  useEffect(() => {
212
261
  if (attributes) {
213
- setPatientUuidMap((prevPatientUuidMap) => ({
214
- ...prevPatientUuidMap,
262
+ setPatientUuidMap((prevMap) => ({
263
+ ...prevMap,
215
264
  ...getPatientAttributeUuidMapForPatient(attributes),
216
265
  }));
217
266
  }
@@ -261,13 +310,13 @@ export function useInitialPatientIdentifiers(patientUuid: string): {
261
310
  data: identifiers,
262
311
  isLoading,
263
312
  };
264
- }, [data, error]);
313
+ }, [data?.data?.results, isLoading]);
265
314
 
266
315
  return result;
267
316
  }
268
317
 
269
318
  function useInitialEncounters(patientUuid: string, patientToEdit: fhir.Patient) {
270
- const { registrationObs } = useConfig() as RegistrationConfig;
319
+ const { registrationObs } = useConfig<RegistrationConfig>();
271
320
  const { data, error, isLoading } = useSWR<FetchResponse<{ results: Array<Encounter> }>>(
272
321
  patientToEdit && registrationObs.encounterTypeUuid
273
322
  ? `${restBaseUrl}/encounter?patient=${patientUuid}&v=custom:(encounterDatetime,obs:(concept:ref,value:ref))&encounterType=${registrationObs.encounterTypeUuid}`
@@ -297,7 +346,24 @@ function useInitialPersonAttributes(personUuid: string) {
297
346
  data: data?.data?.results,
298
347
  isLoading,
299
348
  };
300
- }, [data, error]);
349
+ }, [data?.data?.results, isLoading]);
350
+ return result;
351
+ }
352
+
353
+ function useInitialPersonDeathInfo(personUuid: string) {
354
+ const { data, error, isLoading } = useSWR<FetchResponse<DeathInfoResults>, Error>(
355
+ !!personUuid
356
+ ? `${restBaseUrl}/person/${personUuid}?v=custom:(uuid,display,causeOfDeath,dead,deathDate,causeOfDeathNonCoded)`
357
+ : null,
358
+ openmrsFetch,
359
+ );
360
+
361
+ const result = useMemo(() => {
362
+ return {
363
+ data: data?.data,
364
+ isLoading,
365
+ };
366
+ }, [data?.data, isLoading]);
301
367
  return result;
302
368
  }
303
369
 
@@ -308,104 +374,3 @@ function getPatientAttributeUuidMapForPatient(attributes: Array<PersonAttributeR
308
374
  });
309
375
  return attributeUuidMap;
310
376
  }
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
- }
@@ -0,0 +1,33 @@
1
+ import { filterOutUndefinedPatientIdentifiers } from './patient-registration-utils';
2
+
3
+ describe('filterOutUndefinedPatientIdentifiers', () => {
4
+ const getIdentifiers = (autoGeneration = true, manualEntryEnabled = false) => ({
5
+ OpenMRSId: {
6
+ autoGeneration: autoGeneration,
7
+ identifierName: 'OpenMRS ID',
8
+ identifierTypeUuid: '05a29f94-c0ed-11e2-94be-8c13b969e334',
9
+ identifierValue: undefined,
10
+ initialValue: '100GEJ',
11
+ preferred: true,
12
+ required: true,
13
+ selectedSource: {
14
+ uuid: '01af8526-cea4-4175-aa90-340acb411771',
15
+ name: 'Generator for OpenMRS ID',
16
+ autoGenerationOption: {
17
+ manualEntryEnabled: manualEntryEnabled,
18
+ automaticGenerationEnabled: autoGeneration,
19
+ },
20
+ },
21
+ },
22
+ });
23
+
24
+ it('should fitler out undefined identifiers', () => {
25
+ const filteredIdentifiers = filterOutUndefinedPatientIdentifiers(getIdentifiers());
26
+ expect(filteredIdentifiers.OpenMRSId).not.toBeDefined();
27
+ });
28
+
29
+ it('should retain auto-generated identifiers with manual entry', () => {
30
+ const filteredIdentifiers = filterOutUndefinedPatientIdentifiers(getIdentifiers(true, true));
31
+ expect(filteredIdentifiers.OpenMRSId).toBeDefined();
32
+ });
33
+ });