@olaboot/esm-patient-registration-app 9.2.0

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 (250) hide show
  1. package/ADDRESS_CONFIGURATION.md +152 -0
  2. package/IDENTIFIER_CONFIGURATION.md +142 -0
  3. package/IMPLEMENTATION_SUMMARY.md +111 -0
  4. package/QUICK_START.md +95 -0
  5. package/README.md +7 -0
  6. package/address-required-fields-config.json +26 -0
  7. package/dist/126.js +1 -0
  8. package/dist/15.js +1 -0
  9. package/dist/1564.js +1 -0
  10. package/dist/1567.js +1 -0
  11. package/dist/1845.js +1 -0
  12. package/dist/1953.js +1 -0
  13. package/dist/200.js +1 -0
  14. package/dist/200.js.map +1 -0
  15. package/dist/215.js +1 -0
  16. package/dist/2178.js +1 -0
  17. package/dist/250.js +1 -0
  18. package/dist/250.js.map +1 -0
  19. package/dist/2523.js +1 -0
  20. package/dist/2523.js.map +1 -0
  21. package/dist/2566.js +1 -0
  22. package/dist/2586.js +1 -0
  23. package/dist/2586.js.map +1 -0
  24. package/dist/2716.js +1 -0
  25. package/dist/2716.js.map +1 -0
  26. package/dist/2759.js +1 -0
  27. package/dist/2821.js +6 -0
  28. package/dist/2821.js.map +1 -0
  29. package/dist/3089.js +1 -0
  30. package/dist/3089.js.map +1 -0
  31. package/dist/3230.js +1 -0
  32. package/dist/3441.js +1 -0
  33. package/dist/3565.js +1 -0
  34. package/dist/3571.js +1 -0
  35. package/dist/3571.js.map +1 -0
  36. package/dist/3746.js +1 -0
  37. package/dist/3925.js +1 -0
  38. package/dist/3946.js +1 -0
  39. package/dist/4024.js +1 -0
  40. package/dist/4024.js.map +1 -0
  41. package/dist/4744.js +1 -0
  42. package/dist/4744.js.map +1 -0
  43. package/dist/4809.js +1 -0
  44. package/dist/4894.js +1 -0
  45. package/dist/4970.js +1 -0
  46. package/dist/4970.js.map +1 -0
  47. package/dist/5130.js +1 -0
  48. package/dist/5187.js +1 -0
  49. package/dist/5491.js +1 -0
  50. package/dist/5491.js.map +1 -0
  51. package/dist/5595.js +1 -0
  52. package/dist/5961.js +1 -0
  53. package/dist/6133.js +1 -0
  54. package/dist/634.js +1 -0
  55. package/dist/634.js.map +1 -0
  56. package/dist/6456.js +1 -0
  57. package/dist/6466.js +1 -0
  58. package/dist/6613.js +1 -0
  59. package/dist/6783.js +1 -0
  60. package/dist/7073.js +38 -0
  61. package/dist/7073.js.map +1 -0
  62. package/dist/7154.js +1 -0
  63. package/dist/7154.js.map +1 -0
  64. package/dist/7348.js +1 -0
  65. package/dist/7439.js +1 -0
  66. package/dist/7439.js.map +1 -0
  67. package/dist/7543.js +1 -0
  68. package/dist/7607.js +1 -0
  69. package/dist/772.js +1 -0
  70. package/dist/7984.js +1 -0
  71. package/dist/7984.js.map +1 -0
  72. package/dist/8538.js +1 -0
  73. package/dist/8538.js.map +1 -0
  74. package/dist/8599.js +1 -0
  75. package/dist/8727.js +1 -0
  76. package/dist/8847.js +1 -0
  77. package/dist/9015.js +1 -0
  78. package/dist/906.js +1 -0
  79. package/dist/9065.js +1 -0
  80. package/dist/9182.js +1 -0
  81. package/dist/9339.js +1 -0
  82. package/dist/9453.js +1 -0
  83. package/dist/9833.js +1 -0
  84. package/dist/9833.js.map +1 -0
  85. package/dist/9856.js +1 -0
  86. package/dist/9856.js.map +1 -0
  87. package/dist/9920.js +1 -0
  88. package/dist/9938.js +1 -0
  89. package/dist/9943.js +1 -0
  90. package/dist/9943.js.map +1 -0
  91. package/dist/main.js +10 -0
  92. package/dist/main.js.map +1 -0
  93. package/dist/olaboot-esm-patient-registration-app.js +5 -0
  94. package/dist/olaboot-esm-patient-registration-app.js.buildmanifest.json +1627 -0
  95. package/dist/olaboot-esm-patient-registration-app.js.map +1 -0
  96. package/dist/routes.json +1 -0
  97. package/docs/images/patient-registration-hierarchy.png +0 -0
  98. package/example-config.json +14 -0
  99. package/jest.config.js +3 -0
  100. package/package.json +60 -0
  101. package/rspack.config.js +1 -0
  102. package/src/add-patient-link.extension.tsx +21 -0
  103. package/src/add-patient-link.scss +3 -0
  104. package/src/add-patient-link.test.tsx +16 -0
  105. package/src/config-schema.ts +507 -0
  106. package/src/constants.ts +14 -0
  107. package/src/declarations.d.ts +4 -0
  108. package/src/index.ts +59 -0
  109. package/src/nav-link.test.tsx +13 -0
  110. package/src/nav-link.tsx +10 -0
  111. package/src/offline.resources.ts +157 -0
  112. package/src/offline.ts +93 -0
  113. package/src/patient-photo.extension.tsx +11 -0
  114. package/src/patient-registration/before-save-prompt.component.tsx +72 -0
  115. package/src/patient-registration/field/__mocks__/field.resource.ts +60 -0
  116. package/src/patient-registration/field/address/address-field.component.tsx +186 -0
  117. package/src/patient-registration/field/address/address-hierarchy-levels.component.tsx +71 -0
  118. package/src/patient-registration/field/address/address-hierarchy.resource.tsx +157 -0
  119. package/src/patient-registration/field/address/address-hierarchy.test.tsx +296 -0
  120. package/src/patient-registration/field/address/address-search.component.tsx +87 -0
  121. package/src/patient-registration/field/address/address-search.scss +53 -0
  122. package/src/patient-registration/field/address/address-search.test.tsx +141 -0
  123. package/src/patient-registration/field/address/custom-address-field.component.tsx +32 -0
  124. package/src/patient-registration/field/cause-of-death/cause-of-death.component.tsx +98 -0
  125. package/src/patient-registration/field/custom-field.component.tsx +25 -0
  126. package/src/patient-registration/field/date-and-time-of-death/date-and-time-of-death.component.tsx +79 -0
  127. package/src/patient-registration/field/dob/dob.component.tsx +167 -0
  128. package/src/patient-registration/field/dob/dob.test.tsx +90 -0
  129. package/src/patient-registration/field/field.component.tsx +53 -0
  130. package/src/patient-registration/field/field.resource.ts +42 -0
  131. package/src/patient-registration/field/field.scss +171 -0
  132. package/src/patient-registration/field/field.test.tsx +330 -0
  133. package/src/patient-registration/field/gender/gender-field.component.tsx +54 -0
  134. package/src/patient-registration/field/gender/gender-field.test.tsx +99 -0
  135. package/src/patient-registration/field/id/id-field.component.tsx +136 -0
  136. package/src/patient-registration/field/id/id-field.test.tsx +121 -0
  137. package/src/patient-registration/field/id/identifier-selection-overlay.component.tsx +200 -0
  138. package/src/patient-registration/field/id/identifier-selection.scss +41 -0
  139. package/src/patient-registration/field/name/name-field.component.tsx +148 -0
  140. package/src/patient-registration/field/obs/obs-field.component.tsx +261 -0
  141. package/src/patient-registration/field/obs/obs-field.test.tsx +299 -0
  142. package/src/patient-registration/field/person-attributes/coded-person-attribute-field.component.tsx +120 -0
  143. package/src/patient-registration/field/person-attributes/coded-person-attribute-field.test.tsx +141 -0
  144. package/src/patient-registration/field/person-attributes/location-person-attribute-field.component.tsx +105 -0
  145. package/src/patient-registration/field/person-attributes/location-person-attribute-field.resource.tsx +48 -0
  146. package/src/patient-registration/field/person-attributes/person-attribute-field.component.tsx +100 -0
  147. package/src/patient-registration/field/person-attributes/person-attribute-field.test.tsx +193 -0
  148. package/src/patient-registration/field/person-attributes/person-attributes.resource.ts +20 -0
  149. package/src/patient-registration/field/person-attributes/text-person-attribute-field.component.tsx +58 -0
  150. package/src/patient-registration/field/person-attributes/text-person-attribute-field.test.tsx +90 -0
  151. package/src/patient-registration/field/phone/phone-field.component.tsx +17 -0
  152. package/src/patient-registration/form-manager.test.ts +91 -0
  153. package/src/patient-registration/form-manager.ts +443 -0
  154. package/src/patient-registration/input/basic-input/input/input.component.tsx +183 -0
  155. package/src/patient-registration/input/basic-input/input/input.test.tsx +72 -0
  156. package/src/patient-registration/input/basic-input/select/select-input.component.tsx +32 -0
  157. package/src/patient-registration/input/basic-input/select/select-input.test.tsx +49 -0
  158. package/src/patient-registration/input/combo-input/combo-input.component.tsx +130 -0
  159. package/src/patient-registration/input/combo-input/selection-tick.component.tsx +20 -0
  160. package/src/patient-registration/input/custom-input/autosuggest/autosuggest.component.tsx +187 -0
  161. package/src/patient-registration/input/custom-input/autosuggest/autosuggest.scss +62 -0
  162. package/src/patient-registration/input/custom-input/autosuggest/autosuggest.test.tsx +164 -0
  163. package/src/patient-registration/input/custom-input/identifier/identifier-input.component.tsx +193 -0
  164. package/src/patient-registration/input/custom-input/identifier/identifier-input.test.tsx +335 -0
  165. package/src/patient-registration/input/custom-input/identifier/utils.test.ts +81 -0
  166. package/src/patient-registration/input/custom-input/identifier/utils.ts +19 -0
  167. package/src/patient-registration/input/dummy-data/dummy-data-input.component.tsx +56 -0
  168. package/src/patient-registration/input/dummy-data/dummy-data-input.test.tsx +34 -0
  169. package/src/patient-registration/input/input.scss +122 -0
  170. package/src/patient-registration/patient-registration-context.ts +35 -0
  171. package/src/patient-registration/patient-registration-hooks.ts +376 -0
  172. package/src/patient-registration/patient-registration-utils.test.ts +33 -0
  173. package/src/patient-registration/patient-registration-utils.ts +214 -0
  174. package/src/patient-registration/patient-registration.component.tsx +266 -0
  175. package/src/patient-registration/patient-registration.resource.test.tsx +22 -0
  176. package/src/patient-registration/patient-registration.resource.ts +198 -0
  177. package/src/patient-registration/patient-registration.scss +103 -0
  178. package/src/patient-registration/patient-registration.test.tsx +580 -0
  179. package/src/patient-registration/patient-registration.types.ts +322 -0
  180. package/src/patient-registration/section/death-info/death-info-section.component.tsx +36 -0
  181. package/src/patient-registration/section/death-info/death-info-section.test.tsx +47 -0
  182. package/src/patient-registration/section/demographics/demographics-section.component.tsx +30 -0
  183. package/src/patient-registration/section/demographics/demographics-section.test.tsx +98 -0
  184. package/src/patient-registration/section/generic-section.component.tsx +17 -0
  185. package/src/patient-registration/section/patient-relationships/relationships-section.component.tsx +234 -0
  186. package/src/patient-registration/section/patient-relationships/relationships-section.test.tsx +113 -0
  187. package/src/patient-registration/section/patient-relationships/relationships.resource.tsx +78 -0
  188. package/src/patient-registration/section/patient-relationships/relationships.scss +35 -0
  189. package/src/patient-registration/section/section-wrapper.component.tsx +40 -0
  190. package/src/patient-registration/section/section.component.tsx +23 -0
  191. package/src/patient-registration/section/section.scss +21 -0
  192. package/src/patient-registration/ui-components/overlay/overlay.component.tsx +51 -0
  193. package/src/patient-registration/ui-components/overlay/overlay.scss +63 -0
  194. package/src/patient-registration/validation/patient-registration-validation.test.ts +205 -0
  195. package/src/patient-registration/validation/patient-registration-validation.ts +123 -0
  196. package/src/resource.ts +12 -0
  197. package/src/resources-context.ts +14 -0
  198. package/src/root.component.tsx +63 -0
  199. package/src/root.scss +7 -0
  200. package/src/routes.json +61 -0
  201. package/src/widgets/cancel-patient-edit.modal.tsx +33 -0
  202. package/src/widgets/cancel-patient-edit.test.tsx +22 -0
  203. package/src/widgets/delete-identifier-confirmation.modal.tsx +48 -0
  204. package/src/widgets/delete-identifier-confirmation.test.tsx +32 -0
  205. package/src/widgets/edit-patient-details-button.component.tsx +33 -0
  206. package/src/widgets/edit-patient-details-button.scss +3 -0
  207. package/src/widgets/edit-patient-details-button.test.tsx +35 -0
  208. package/translations/am.json +120 -0
  209. package/translations/ar.json +120 -0
  210. package/translations/ar_SY.json +120 -0
  211. package/translations/bn.json +120 -0
  212. package/translations/cs.json +120 -0
  213. package/translations/de.json +120 -0
  214. package/translations/en.json +120 -0
  215. package/translations/en_US.json +120 -0
  216. package/translations/es.json +120 -0
  217. package/translations/es_MX.json +120 -0
  218. package/translations/fr.json +120 -0
  219. package/translations/he.json +120 -0
  220. package/translations/hi.json +120 -0
  221. package/translations/hi_IN.json +120 -0
  222. package/translations/id.json +120 -0
  223. package/translations/it.json +120 -0
  224. package/translations/ka.json +120 -0
  225. package/translations/km.json +120 -0
  226. package/translations/ku.json +120 -0
  227. package/translations/ky.json +120 -0
  228. package/translations/lg.json +120 -0
  229. package/translations/ne.json +120 -0
  230. package/translations/pl.json +120 -0
  231. package/translations/pt.json +120 -0
  232. package/translations/pt_BR.json +120 -0
  233. package/translations/qu.json +120 -0
  234. package/translations/ro_RO.json +120 -0
  235. package/translations/ru_RU.json +120 -0
  236. package/translations/si.json +120 -0
  237. package/translations/sq.json +120 -0
  238. package/translations/sw.json +120 -0
  239. package/translations/sw_KE.json +120 -0
  240. package/translations/tr.json +120 -0
  241. package/translations/tr_TR.json +120 -0
  242. package/translations/uk.json +120 -0
  243. package/translations/uz.json +120 -0
  244. package/translations/uz@Latn.json +120 -0
  245. package/translations/uz_UZ.json +120 -0
  246. package/translations/vi.json +120 -0
  247. package/translations/zh.json +120 -0
  248. package/translations/zh_CN.json +120 -0
  249. package/translations/zh_TW.json +120 -0
  250. package/tsconfig.json +5 -0
@@ -0,0 +1,322 @@
1
+ import { type OpenmrsResource, type Session } from '@openmrs/esm-framework';
2
+ import { type RegistrationConfig } from '../config-schema';
3
+ import { type SavePatientTransactionManager } from './form-manager';
4
+
5
+ interface NameValue {
6
+ uuid: string;
7
+ preferred: boolean;
8
+ givenName: string;
9
+ middleName: string;
10
+ familyName: string;
11
+ }
12
+
13
+ export interface AttributeValue {
14
+ attributeType: string;
15
+ value: string;
16
+ }
17
+
18
+ /**
19
+ * Patient Identifier data as it is fetched and composed from the APIs.
20
+ */
21
+ export interface FetchedPatientIdentifierType {
22
+ name: string;
23
+ required: boolean;
24
+ uuid: string;
25
+ fieldName: string;
26
+ format: string;
27
+ formatDescription?: string;
28
+ isPrimary: boolean;
29
+ /** See: https://github.com/openmrs/openmrs-core/blob/e3fb1ac0a052aeff0f957a150731757dd319693b/api/src/main/java/org/openmrs/PatientIdentifierType.java#L41 */
30
+ uniquenessBehavior: undefined | null | 'UNIQUE' | 'NON_UNIQUE' | 'LOCATION';
31
+ }
32
+
33
+ export interface PatientIdentifierValue {
34
+ identifierUuid?: string;
35
+ identifierTypeUuid: string;
36
+ initialValue: string;
37
+ identifierValue: string;
38
+ identifierName: string;
39
+ selectedSource: IdentifierSource;
40
+ autoGeneration?: boolean;
41
+ preferred: boolean;
42
+ required: boolean;
43
+ }
44
+
45
+ /**
46
+ * Extends the `FetchedPatientIdentifierType` with aggregated data.
47
+ */
48
+ export interface PatientIdentifierType extends FetchedPatientIdentifierType {
49
+ identifierSources: Array<IdentifierSource>;
50
+ autoGenerationSource?: IdentifierSource;
51
+ checked?: boolean;
52
+ source?: IdentifierSource;
53
+ }
54
+
55
+ export interface IdentifierSource {
56
+ uuid: string;
57
+ name: string;
58
+ autoGenerationOption?: IdentifierSourceAutoGenerationOption;
59
+ }
60
+
61
+ export interface IdentifierSourceAutoGenerationOption {
62
+ manualEntryEnabled: boolean;
63
+ automaticGenerationEnabled: boolean;
64
+ }
65
+
66
+ export interface PatientIdentifier {
67
+ uuid?: string;
68
+ identifier: string;
69
+ identifierType?: string;
70
+ location?: string;
71
+ preferred?: boolean;
72
+ }
73
+
74
+ export interface PatientRegistration {
75
+ id?: number;
76
+ /**
77
+ * The preliminary patient in the FHIR format.
78
+ */
79
+ fhirPatient: fhir.Patient;
80
+ /**
81
+ * Internal data collected by patient-registration. Required for later syncing and editing.
82
+ * Not supposed to be used outside of this module.
83
+ */
84
+ _patientRegistrationData: {
85
+ isNewPatient: boolean;
86
+ formValues: FormValues;
87
+ patientUuidMap: PatientUuidMapType;
88
+ initialAddressFieldValues: Record<string, any>;
89
+ capturePhotoProps: CapturePhotoProps;
90
+ currentLocation: string;
91
+ initialIdentifierValues: FormValues['identifiers'];
92
+ currentUser: Session;
93
+ config: RegistrationConfig;
94
+ savePatientTransactionManager: SavePatientTransactionManager;
95
+ };
96
+ }
97
+
98
+ export type Relationship = {
99
+ relationshipType: string;
100
+ personA: string;
101
+ personB: string;
102
+ };
103
+
104
+ export type Patient = {
105
+ uuid: string;
106
+ identifiers: Array<PatientIdentifier>;
107
+ person: {
108
+ uuid: string;
109
+ names: Array<NameValue>;
110
+ gender: string;
111
+ birthdate: string;
112
+ birthdateEstimated: boolean;
113
+ attributes: Array<AttributeValue>;
114
+ addresses: Array<Record<string, string>>;
115
+ dead: boolean;
116
+ deathDate?: string;
117
+ causeOfDeath?: string;
118
+ };
119
+ };
120
+
121
+ export interface Encounter {
122
+ encounterDatetime: Date;
123
+ patient: string;
124
+ encounterType: string;
125
+ location: string;
126
+ encounterProviders: Array<{
127
+ provider: string;
128
+ encounterRole: string;
129
+ }>;
130
+ form: string;
131
+ obs: Array<{
132
+ concept: string | OpenmrsResource;
133
+ value: string | number | OpenmrsResource;
134
+ }>;
135
+ }
136
+
137
+ export interface RelationshipValue {
138
+ relatedPersonName?: string;
139
+ relatedPersonUuid: string;
140
+ relation?: string;
141
+ relationshipType: string;
142
+ /**
143
+ * Defines the action to be taken on the existing relationship
144
+ * @kind ADD -> adds a new relationship
145
+ * @kind UPDATE -> updates an existing relationship
146
+ * @kind DELETE -> deletes an existing relationship
147
+ * @kind undefined -> no operation on the existing relationship
148
+ */
149
+ action?: 'ADD' | 'UPDATE' | 'DELETE';
150
+ /**
151
+ * Value kept for restoring initial relationshipType value
152
+ */
153
+ initialrelationshipTypeValue?: string;
154
+ uuid?: string;
155
+ }
156
+
157
+ export interface FormValues {
158
+ additionalFamilyName: string;
159
+ additionalGivenName: string;
160
+ additionalMiddleName: string;
161
+ addNameInLocalLanguage: boolean;
162
+ address: {
163
+ [addressField: string]: string;
164
+ };
165
+ attributes?: {
166
+ [attributeTypeUuid: string]: string;
167
+ };
168
+ birthdate: Date | string;
169
+ birthdateEstimated: boolean;
170
+ deathCause: string;
171
+ deathDate: string | Date;
172
+ deathTime: string;
173
+ deathTimeFormat: 'AM' | 'PM';
174
+ familyName: string;
175
+ gender: string;
176
+ givenName: string;
177
+ identifiers: {
178
+ [identifierFieldName: string]: PatientIdentifierValue;
179
+ };
180
+ isDead: boolean;
181
+ middleName: string;
182
+ monthsEstimated: number;
183
+ nonCodedCauseOfDeath: string;
184
+ obs?: {
185
+ [conceptUuid: string]: string;
186
+ };
187
+ patientUuid: string;
188
+ relationships: Array<RelationshipValue>;
189
+ telephoneNumber: string;
190
+ yearsEstimated: number;
191
+ }
192
+
193
+ export interface PatientUuidMapType {
194
+ additionalNameUuid?: string;
195
+ preferredNameUuid?: string;
196
+ preferredAddressUuid?: string;
197
+ }
198
+
199
+ export interface CapturePhotoProps {
200
+ imageData: string;
201
+ dateTime: string;
202
+ }
203
+
204
+ export interface AddressValidationSchemaType {
205
+ name: string;
206
+ label: string;
207
+ regex: RegExp;
208
+ regexFormat: string;
209
+ }
210
+
211
+ export interface CodedPersonAttributeConfig {
212
+ personAttributeUuid: string;
213
+ conceptUuid: string;
214
+ }
215
+
216
+ export interface TextBasedPersonAttributeConfig {
217
+ personAttributeUuid: string;
218
+ validationRegex: string;
219
+ }
220
+ export interface PatientIdentifierResponse {
221
+ uuid: string;
222
+ identifier: string;
223
+ preferred: boolean;
224
+ identifierType: {
225
+ uuid: string;
226
+ required: boolean;
227
+ name: string;
228
+ };
229
+ }
230
+ export interface PersonAttributeTypeResponse {
231
+ uuid: string;
232
+ display: string;
233
+ name: string;
234
+ description: string;
235
+ format: string;
236
+ }
237
+
238
+ export interface PersonAttributeResponse {
239
+ display: string;
240
+ uuid: string;
241
+ value:
242
+ | string
243
+ | {
244
+ uuid: string;
245
+ display: string;
246
+ };
247
+ attributeType: {
248
+ display: string;
249
+ uuid: string;
250
+ format: 'org.openmrs.Concept' | string;
251
+ };
252
+ }
253
+
254
+ export interface ConceptResponse {
255
+ uuid: string;
256
+ display: string;
257
+ datatype: {
258
+ uuid: string;
259
+ display: string;
260
+ };
261
+ answers: Array<ConceptAnswers>;
262
+ setMembers: Array<ConceptAnswers>;
263
+ }
264
+
265
+ export interface ConceptAnswers {
266
+ display: string;
267
+ uuid: string;
268
+ }
269
+
270
+ export type AddressProperties =
271
+ | 'cityVillage'
272
+ | 'stateProvince'
273
+ | 'countyDistrict'
274
+ | 'postalCode'
275
+ | 'country'
276
+ | 'address1'
277
+ | 'address2'
278
+ | 'address3'
279
+ | 'address4'
280
+ | 'address5'
281
+ | 'address6'
282
+ | 'address7'
283
+ | 'address8'
284
+ | 'address9'
285
+ | 'address10'
286
+ | 'address11'
287
+ | 'address12'
288
+ | 'address13'
289
+ | 'address14'
290
+ | 'address15';
291
+
292
+ export type ExtensibleAddressProperties = { [p in AddressProperties]?: string } | null;
293
+
294
+ export interface AddressTemplate {
295
+ displayName: string | null;
296
+ codeName: string | null;
297
+ country: string | null;
298
+ lines: Array<
299
+ Array<{
300
+ isToken: 'IS_NOT_ADDR_TOKEN' | 'IS_ADDR_TOKEN';
301
+ displayText: string;
302
+ codeName?: AddressProperties;
303
+ displaySize?: string;
304
+ }>
305
+ > | null;
306
+ lineByLineFormat: Array<string> | null;
307
+ nameMappings: ExtensibleAddressProperties;
308
+ sizeMappings: ExtensibleAddressProperties;
309
+ elementDefaults: ExtensibleAddressProperties;
310
+ elementRegex: ExtensibleAddressProperties;
311
+ elementRegexFormats: ExtensibleAddressProperties;
312
+ requiredElements: Array<AddressProperties> | null;
313
+ }
314
+
315
+ // https://rest.openmrs.org/#address-template
316
+ export interface RestAddressTemplate {
317
+ uuid: string;
318
+ description: string;
319
+ property: string;
320
+ display: string;
321
+ value: string;
322
+ }
@@ -0,0 +1,36 @@
1
+ import React from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { Checkbox, Layer } from '@carbon/react';
4
+ import { useField } from 'formik';
5
+ import { usePatientRegistrationContext } from '../../patient-registration-context';
6
+ import { Field } from '../../field/field.component';
7
+ import styles from './../section.scss';
8
+
9
+ export interface DeathInfoSectionProps {
10
+ fields: Array<string>;
11
+ }
12
+
13
+ export const DeathInfoSection: React.FC<DeathInfoSectionProps> = ({ fields }) => {
14
+ const { t } = useTranslation();
15
+ const { values, setFieldValue } = usePatientRegistrationContext();
16
+ const [deathDate, deathDateMeta] = useField('deathDate');
17
+ const today = new Date();
18
+
19
+ return (
20
+ <section className={styles.formSection} aria-label="Death Info Section">
21
+ <section className={styles.fieldGroup}>
22
+ <Layer>
23
+ <div className={styles.isDeadFieldContainer}>
24
+ <Checkbox
25
+ checked={values.isDead}
26
+ id="isDead"
27
+ labelText={t('isDeadInputLabel', 'Is dead')}
28
+ onChange={(event, { checked, id }) => setFieldValue(id, checked)}
29
+ />
30
+ </div>
31
+ </Layer>
32
+ {values.isDead ? fields.map((field) => <Field key={`death-info-${field}`} name={field} />) : null}
33
+ </section>
34
+ </section>
35
+ );
36
+ };
@@ -0,0 +1,47 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { Form, Formik } from 'formik';
4
+ import { type FormValues } from '../../patient-registration.types';
5
+ import { renderWithContext } from 'tools';
6
+ import { initialFormValues } from '../../patient-registration.component';
7
+ import { PatientRegistrationContextProvider } from '../../patient-registration-context';
8
+ import { DeathInfoSection } from './death-info-section.component';
9
+
10
+ const initialContextValues = {
11
+ currentPhoto: 'data:image/png;base64,1234567890',
12
+ identifierTypes: [],
13
+ inEditMode: false,
14
+ initialFormValues: {} as FormValues,
15
+ isOffline: false,
16
+ setCapturePhotoProps: jest.fn(),
17
+ setFieldValue: jest.fn(),
18
+ setFieldTouched: jest.fn(),
19
+ setInitialFormValues: jest.fn(),
20
+ validationSchema: null,
21
+ values: {
22
+ isDead: true,
23
+ } as FormValues,
24
+ };
25
+
26
+ describe('Death info section', () => {
27
+ const renderDeathInfoSection = (isDead) => {
28
+ initialContextValues.values.isDead = isDead;
29
+
30
+ renderWithContext(
31
+ <Formik initialValues={initialFormValues} onSubmit={jest.fn()}>
32
+ <Form>
33
+ <DeathInfoSection fields={[]} />
34
+ </Form>
35
+ </Formik>,
36
+ PatientRegistrationContextProvider,
37
+ initialContextValues,
38
+ );
39
+ };
40
+
41
+ it('shows fields for recording death info when the patient is marked as dead', () => {
42
+ renderDeathInfoSection(true);
43
+
44
+ expect(screen.getByRole('region', { name: /death info section/i })).toBeInTheDocument();
45
+ expect(screen.getByRole('checkbox', { name: /is dead/i })).toBeInTheDocument();
46
+ });
47
+ });
@@ -0,0 +1,30 @@
1
+ import React, { useEffect } from 'react';
2
+ import { useField } from 'formik';
3
+ import { Field } from '../../field/field.component';
4
+ import { usePatientRegistrationContext } from '../../patient-registration-context';
5
+ import styles from './../section.scss';
6
+
7
+ export interface DemographicsSectionProps {
8
+ fields: Array<string>;
9
+ }
10
+
11
+ export const DemographicsSection: React.FC<DemographicsSectionProps> = ({ fields }) => {
12
+ const [field, meta] = useField('addNameInLocalLanguage');
13
+ const { setFieldValue } = usePatientRegistrationContext();
14
+
15
+ useEffect(() => {
16
+ if (!field.value && meta.touched) {
17
+ setFieldValue('additionalGivenName', '');
18
+ setFieldValue('additionalMiddleName', '');
19
+ setFieldValue('additionalFamilyName', '');
20
+ }
21
+ }, [field.value, meta.touched, setFieldValue]);
22
+
23
+ return (
24
+ <section className={styles.formSection} aria-label="Demographics Section">
25
+ {fields.map((field) => (
26
+ <Field key={`demographics-${field}`} name={field} />
27
+ ))}
28
+ </section>
29
+ );
30
+ };
@@ -0,0 +1,98 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { Formik, Form } from 'formik';
4
+ import { initialFormValues } from '../../patient-registration.component';
5
+ import { getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework';
6
+ import { DemographicsSection } from './demographics-section.component';
7
+ import { PatientRegistrationContext } from '../../patient-registration-context';
8
+ import { type RegistrationConfig, esmPatientRegistrationSchema } from '../../../config-schema';
9
+
10
+ const mockUseConfig = jest.mocked(useConfig<RegistrationConfig>);
11
+
12
+ jest.mock('../../field/name/name-field.component', () => {
13
+ return {
14
+ NameField: () => (
15
+ <div>
16
+ <input type="text" name="name" />
17
+ </div>
18
+ ),
19
+ };
20
+ });
21
+
22
+ jest.mock('../../field/gender/gender-field.component', () => {
23
+ return {
24
+ GenderField: () => (
25
+ <div>
26
+ <input type="text" name="name" />
27
+ </div>
28
+ ),
29
+ };
30
+ });
31
+
32
+ jest.mock('../../field/id/id-field.component', () => {
33
+ return {
34
+ IdField: () => (
35
+ <div>
36
+ <input type="text" name="name" />
37
+ </div>
38
+ ),
39
+ };
40
+ });
41
+
42
+ describe('Demographics section', () => {
43
+ beforeEach(() => {
44
+ mockUseConfig.mockReturnValue({
45
+ ...getDefaultsFromConfigSchema(esmPatientRegistrationSchema),
46
+ fieldConfigurations: {
47
+ dateOfBirth: {
48
+ allowEstimatedDateOfBirth: true,
49
+ useEstimatedDateOfBirth: { enabled: true, dayOfMonth: 0, month: 0 },
50
+ },
51
+ } as RegistrationConfig['fieldConfigurations'],
52
+ });
53
+ });
54
+
55
+ const setupSection = async (birthdateEstimated?: boolean, addNameInLocalLanguage?: boolean) => {
56
+ render(
57
+ <Formik initialValues={{ ...initialFormValues, birthdateEstimated, addNameInLocalLanguage }} onSubmit={null}>
58
+ <Form>
59
+ <PatientRegistrationContext.Provider
60
+ value={{
61
+ initialFormValues: null,
62
+ identifierTypes: [],
63
+ validationSchema: {},
64
+ values: { ...initialFormValues, birthdateEstimated, addNameInLocalLanguage },
65
+ inEditMode: false,
66
+ setFieldValue: () => {},
67
+ currentPhoto: 'TEST',
68
+ isOffline: true,
69
+ setCapturePhotoProps: (value) => {},
70
+ setFieldTouched: () => {},
71
+ }}>
72
+ <DemographicsSection fields={['name', 'gender', 'dob']} />
73
+ </PatientRegistrationContext.Provider>
74
+ </Form>
75
+ </Formik>,
76
+ );
77
+ const allInputs = screen.getAllByRole('textbox') as Array<HTMLInputElement>;
78
+ return allInputs.map((input) => input.name);
79
+ };
80
+
81
+ it('renders demographics fields and date of birth inputs', async () => {
82
+ const inputNames = await setupSection();
83
+ expect(inputNames.length).toBe(3);
84
+
85
+ expect(screen.getByText(/date of birth known\?/i)).toBeInTheDocument();
86
+ expect(
87
+ screen.getByRole('tab', {
88
+ name: /yes/i,
89
+ }),
90
+ ).toBeInTheDocument();
91
+ expect(
92
+ screen.getByRole('tab', {
93
+ name: /no/i,
94
+ }),
95
+ ).toBeInTheDocument();
96
+ expect(screen.getByLabelText(/date of birth/i)).toBeInTheDocument();
97
+ });
98
+ });
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { type SectionDefinition } from '../../config-schema';
3
+ import { Field } from '../field/field.component';
4
+
5
+ export interface GenericSectionProps {
6
+ sectionDefinition: SectionDefinition;
7
+ }
8
+
9
+ export const GenericSection = ({ sectionDefinition }: GenericSectionProps) => {
10
+ return (
11
+ <section aria-label={`${sectionDefinition.name} Section`}>
12
+ {sectionDefinition.fields.map((name) => (
13
+ <Field key={`${sectionDefinition.name}-${name}`} name={name} />
14
+ ))}
15
+ </section>
16
+ );
17
+ };