@kenyaemr/esm-patient-registration-app 4.5.3 → 4.5.5

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 (101) hide show
  1. package/dist/117.js +2 -0
  2. package/dist/117.js.map +1 -0
  3. package/dist/130.js +1 -1
  4. package/dist/130.js.map +1 -1
  5. package/dist/208.js +1 -1
  6. package/dist/218.js +1 -0
  7. package/dist/218.js.map +1 -0
  8. package/dist/275.js +1 -0
  9. package/dist/275.js.map +1 -0
  10. package/dist/319.js +1 -1
  11. package/dist/{821.js → 348.js} +1 -1
  12. package/dist/{821.js.map → 348.js.map} +1 -1
  13. package/dist/574.js +1 -1
  14. package/dist/68.js +1 -1
  15. package/dist/68.js.map +1 -1
  16. package/dist/693.js +1 -0
  17. package/dist/693.js.map +1 -0
  18. package/dist/757.js +1 -1
  19. package/dist/788.js +1 -1
  20. package/dist/807.js +1 -1
  21. package/dist/833.js +1 -1
  22. package/dist/879.js +1 -0
  23. package/dist/879.js.map +1 -0
  24. package/dist/kenyaemr-esm-patient-registration-app.js +1 -1
  25. package/dist/kenyaemr-esm-patient-registration-app.js.buildmanifest.json +171 -122
  26. package/dist/kenyaemr-esm-patient-registration-app.js.map +1 -1
  27. package/dist/main.js +1 -1
  28. package/dist/main.js.map +1 -1
  29. package/dist/routes.json +1 -1
  30. package/jest.config.js +3 -0
  31. package/package.json +5 -2
  32. package/src/config-schema.ts +11 -5
  33. package/src/index.ts +9 -2
  34. package/src/offline.resources.ts +8 -4
  35. package/src/offline.ts +1 -1
  36. package/src/patient-registration/field/__mocks__/field.resource.ts +1 -1
  37. package/src/patient-registration/field/address/address-field.component.tsx +25 -70
  38. package/src/patient-registration/field/address/address-hierarchy-levels.component.tsx +11 -9
  39. package/src/patient-registration/field/address/address-hierarchy.resource.tsx +57 -3
  40. package/src/patient-registration/field/address/address-search.component.tsx +1 -1
  41. package/src/patient-registration/field/address/tests/address-hierarchy.test.tsx +137 -63
  42. package/src/patient-registration/field/address/tests/address-search-component.test.tsx +128 -0
  43. package/src/patient-registration/field/address/tests/mocks.ts +93 -99
  44. package/src/patient-registration/field/dob/dob.component.tsx +48 -44
  45. package/src/patient-registration/field/dob/dob.test.tsx +6 -1
  46. package/src/patient-registration/field/field.resource.ts +1 -1
  47. package/src/patient-registration/field/id/id-field.component.tsx +1 -1
  48. package/src/patient-registration/field/id/identifier-selection-overlay.tsx +1 -1
  49. package/src/patient-registration/field/name/name-field.component.tsx +38 -22
  50. package/src/patient-registration/field/obs/obs-field.component.tsx +14 -13
  51. package/src/patient-registration/field/person-attributes/coded-attributes.component.tsx +1 -1
  52. package/src/patient-registration/field/person-attributes/coded-person-attribute-field.component.tsx +1 -1
  53. package/src/patient-registration/field/person-attributes/coded-person-attribute-field.test.tsx +103 -0
  54. package/src/patient-registration/field/person-attributes/person-attribute-field.test.tsx +187 -0
  55. package/src/patient-registration/field/person-attributes/person-attributes.resource.tsx +1 -1
  56. package/src/patient-registration/field/person-attributes/text-person-attribute-field.component.tsx +3 -3
  57. package/src/patient-registration/field/person-attributes/text-person-attribute-field.test.tsx +88 -0
  58. package/src/patient-registration/form-manager.test.ts +1 -2
  59. package/src/patient-registration/form-manager.ts +1 -9
  60. package/src/patient-registration/input/basic-input/input/input.test.tsx +0 -135
  61. package/src/patient-registration/input/basic-input/select/select-input.test.tsx +8 -4
  62. package/src/patient-registration/input/combo-input/combo-input.component.tsx +8 -6
  63. package/src/patient-registration/input/custom-input/identifier/identifier-input.component.tsx +1 -1
  64. package/src/patient-registration/input/custom-input/identifier/utils.test.ts +81 -0
  65. package/src/patient-registration/input/custom-input/identifier/utils.ts +1 -1
  66. package/src/patient-registration/input/dummy-data/dummy-data-input.component.tsx +1 -2
  67. package/src/patient-registration/patient-registration-context.ts +1 -1
  68. package/src/patient-registration/patient-registration-hooks.ts +14 -2
  69. package/src/patient-registration/patient-registration-utils.ts +1 -4
  70. package/src/patient-registration/patient-registration.component.tsx +1 -12
  71. package/src/patient-registration/patient-registration.resource.tsx +1 -72
  72. package/src/patient-registration/patient-registration.test.tsx +250 -247
  73. package/src/patient-registration/{patient-registration-types.tsx → patient-registration.types.tsx} +45 -1
  74. package/src/patient-registration/section/patient-relationships/relationships-section.component.tsx +83 -79
  75. package/src/patient-registration/section/patient-relationships/relationships-section.test.tsx +88 -0
  76. package/src/patient-registration/section/patient-relationships/relationships.resource.tsx +1 -1
  77. package/src/patient-registration/validation/patient-registration-validation.tsx +1 -1
  78. package/src/patient-verification/patient-verification-hook.tsx +12 -1
  79. package/src/patient-verification/patient-verification-utils.ts +1 -1
  80. package/src/patient-verification/patient-verification.component.tsx +1 -1
  81. package/src/patient-verification/verification-modal/confirm-prompt.component.tsx +11 -0
  82. package/src/root.component.tsx +1 -1
  83. package/src/routes.json +62 -51
  84. package/src/widgets/cancel-patient-edit.test.tsx +24 -0
  85. package/src/widgets/delete-identifier-confirmation-modal.test.tsx +31 -0
  86. package/src/widgets/display-photo.test.tsx +37 -0
  87. package/src/widgets/edit-patient-details-button.test.tsx +36 -0
  88. package/translations/am.json +0 -7
  89. package/translations/en.json +2 -5
  90. package/translations/es.json +0 -7
  91. package/translations/fr.json +0 -7
  92. package/translations/he.json +0 -7
  93. package/translations/km.json +0 -7
  94. package/__mocks__/react-i18next.js +0 -49
  95. package/dist/196.js +0 -1
  96. package/dist/196.js.map +0 -1
  97. package/dist/59.js +0 -1
  98. package/dist/59.js.map +0 -1
  99. package/dist/9.js +0 -2
  100. package/dist/9.js.map +0 -1
  101. /package/dist/{9.js.LICENSE.txt → 117.js.LICENSE.txt} +0 -0
@@ -0,0 +1,81 @@
1
+ import { isUniqueIdentifierTypeForOffline, shouldBlockPatientIdentifierInOfflineMode } from './utils';
2
+
3
+ interface IdentifierTypeOptions {
4
+ uniquenessBehavior?: 'UNIQUE' | 'LOCATION' | 'NON_UNIQUE';
5
+ manualEntryEnabled?: boolean;
6
+ automaticGenerationEnabled?: boolean;
7
+ }
8
+
9
+ function createIdentifierType(options: IdentifierTypeOptions) {
10
+ return {
11
+ uniquenessBehavior: options.uniquenessBehavior,
12
+ identifierSources: [
13
+ {
14
+ uuid: 'identifier-source-uuid',
15
+ name: 'Identifier Source Name',
16
+ autoGenerationOption: {
17
+ manualEntryEnabled: options.manualEntryEnabled,
18
+ automaticGenerationEnabled: options.automaticGenerationEnabled,
19
+ },
20
+ },
21
+ ],
22
+ name: 'Identifier Type Name',
23
+ required: true,
24
+ uuid: 'identifier-type-uuid',
25
+ fieldName: 'identifierFieldName',
26
+ format: 'identifierFormat',
27
+ isPrimary: true,
28
+ };
29
+ }
30
+
31
+ describe('shouldBlockPatientIdentifierInOfflineMode function', () => {
32
+ it('should return false if identifierType is not unique', () => {
33
+ const identifierType = createIdentifierType({ uniquenessBehavior: null });
34
+
35
+ const result = shouldBlockPatientIdentifierInOfflineMode(identifierType);
36
+
37
+ expect(result).toBe(false);
38
+ });
39
+
40
+ it('should return false if identifierType is unique and no manual entry is enabled', () => {
41
+ const identifierType = createIdentifierType({ uniquenessBehavior: null });
42
+
43
+ const result = shouldBlockPatientIdentifierInOfflineMode(identifierType);
44
+
45
+ expect(result).toBe(false);
46
+ });
47
+
48
+ it('should return true if identifierType is unique and manual entry is enabled', () => {
49
+ const identifierType = createIdentifierType({ manualEntryEnabled: true, uniquenessBehavior: 'UNIQUE' });
50
+
51
+ const result = shouldBlockPatientIdentifierInOfflineMode(identifierType);
52
+
53
+ expect(result).toBe(true);
54
+ });
55
+ });
56
+
57
+ describe('isUniqueIdentifierTypeForOffline function', () => {
58
+ it('should return true if uniquenessBehavior is UNIQUE', () => {
59
+ const identifierType = createIdentifierType({ uniquenessBehavior: 'UNIQUE' });
60
+
61
+ const result = isUniqueIdentifierTypeForOffline(identifierType);
62
+
63
+ expect(result).toBe(true);
64
+ });
65
+
66
+ it('should return true if uniquenessBehavior is LOCATION', () => {
67
+ const identifierType = createIdentifierType({ uniquenessBehavior: 'LOCATION' });
68
+
69
+ const result = isUniqueIdentifierTypeForOffline(identifierType);
70
+
71
+ expect(result).toBe(true);
72
+ });
73
+
74
+ it('should return false for other uniqueness behaviors', () => {
75
+ const identifierType = createIdentifierType({ uniquenessBehavior: null });
76
+
77
+ const result = isUniqueIdentifierTypeForOffline(identifierType);
78
+
79
+ expect(result).toBe(false);
80
+ });
81
+ });
@@ -1,4 +1,4 @@
1
- import { FetchedPatientIdentifierType, PatientIdentifierType } from '../../../patient-registration-types';
1
+ import { FetchedPatientIdentifierType, PatientIdentifierType } from '../../../patient-registration.types';
2
2
 
3
3
  export function shouldBlockPatientIdentifierInOfflineMode(identifierType: PatientIdentifierType) {
4
4
  // Patient Identifiers which are unique and can be manually entered are prohibited while offline because
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { v4 } from 'uuid';
3
- import { FormValues } from '../../patient-registration-types';
3
+ import { FormValues } from '../../patient-registration.types';
4
4
  import styles from './../input.scss';
5
5
 
6
6
  interface DummyDataInputProps {
@@ -12,7 +12,6 @@ export const dummyFormValues: FormValues = {
12
12
  givenName: 'John',
13
13
  middleName: '',
14
14
  familyName: 'Smith',
15
- unidentifiedPatient: false,
16
15
  additionalGivenName: 'Joey',
17
16
  additionalMiddleName: '',
18
17
  additionalFamilyName: 'Smitty',
@@ -1,7 +1,7 @@
1
1
  import { useConfig } from '@openmrs/esm-framework';
2
2
  import { createContext, SetStateAction } from 'react';
3
3
  import { RegistrationConfig } from '../config-schema';
4
- import { FormValues, CapturePhotoProps } from './patient-registration-types';
4
+ import { FormValues, CapturePhotoProps } from './patient-registration.types';
5
5
 
6
6
  export interface PatientRegistrationContextProps {
7
7
  identifierTypes: Array<any>;
@@ -16,7 +16,7 @@ import {
16
16
  ObsResponse,
17
17
  ConceptAnswers,
18
18
  Encounter,
19
- } from './patient-registration-types';
19
+ } from './patient-registration.types';
20
20
  import {
21
21
  getAddressFieldValuesFromFhirPatient,
22
22
  getFormValuesFromFhirPatient,
@@ -25,6 +25,7 @@ import {
25
25
  latestFirstEncounter,
26
26
  } from './patient-registration-utils';
27
27
  import { useInitialPatientRelationships } from './section/patient-relationships/relationships.resource';
28
+ import dayjs from 'dayjs';
28
29
 
29
30
  export function useInitialFormValues(patientUuid: string): [FormValues, Dispatch<FormValues>] {
30
31
  const { martialStatus, education, occupation, educationLoad, loadingStatus } = useConcepts();
@@ -39,7 +40,6 @@ export function useInitialFormValues(patientUuid: string): [FormValues, Dispatch
39
40
  givenName: '',
40
41
  middleName: '',
41
42
  familyName: '',
42
- unidentifiedPatient: false,
43
43
  additionalGivenName: '',
44
44
  additionalMiddleName: '',
45
45
  additionalFamilyName: '',
@@ -61,11 +61,22 @@ export function useInitialFormValues(patientUuid: string): [FormValues, Dispatch
61
61
  useEffect(() => {
62
62
  (async () => {
63
63
  if (patientToEdit) {
64
+ const birthdateEstimated = !/^\d{4}-\d{2}-\d{2}$/.test(patientToEdit.birthDate);
65
+ const [years = 0, months = 0] = patientToEdit.birthDate.split('-').map((val) => parseInt(val));
66
+ // Please refer: https://github.com/openmrs/openmrs-esm-patient-management/pull/697#issuecomment-1562706118
67
+ const estimatedMonthsAvailable = patientToEdit.birthDate.split('-').length > 1;
68
+ const yearsEstimated = birthdateEstimated ? Math.floor(dayjs().diff(patientToEdit.birthDate, 'month') / 12) : 0;
69
+ const monthsEstimated =
70
+ birthdateEstimated && estimatedMonthsAvailable ? dayjs().diff(patientToEdit.birthDate, 'month') % 12 : 0;
71
+
64
72
  setInitialFormValues({
65
73
  ...initialFormValues,
66
74
  ...getFormValuesFromFhirPatient(patientToEdit),
67
75
  address: getAddressFieldValuesFromFhirPatient(patientToEdit),
68
76
  ...getPhonePersonAttributeValueFromFhirPatient(patientToEdit),
77
+ birthdateEstimated: !/^\d{4}-\d{2}-\d{2}$/.test(patientToEdit.birthDate),
78
+ yearsEstimated,
79
+ monthsEstimated,
69
80
  });
70
81
  } else if (!isLoadingPatientToEdit && patientUuid) {
71
82
  const registration = await getPatientRegistration(patientUuid);
@@ -120,6 +131,7 @@ export function useInitialFormValues(patientUuid: string): [FormValues, Dispatch
120
131
  ? attribute.value?.uuid
121
132
  : attribute.value;
122
133
  });
134
+
123
135
  setInitialFormValues((initialFormValues) => ({
124
136
  ...initialFormValues,
125
137
  attributes: personAttributes,
@@ -6,7 +6,7 @@ import {
6
6
  PatientUuidMapType,
7
7
  PatientIdentifierValue,
8
8
  Encounter,
9
- } from './patient-registration-types';
9
+ } from './patient-registration.types';
10
10
  import { parseDate } from '@openmrs/esm-framework';
11
11
  import camelCase from 'lodash-es/camelCase';
12
12
  import capitalize from 'lodash-es/capitalize';
@@ -115,9 +115,6 @@ export function getFormValuesFromFhirPatient(patient: fhir.Patient) {
115
115
  result.givenName = patientName?.given[0];
116
116
  result.middleName = patientName?.given[1];
117
117
  result.familyName = patientName?.family;
118
- result.unidentifiedPatient =
119
- patientName.given[0] === 'UNKNOWN' && patientName.family === 'unknown' ? true : undefined;
120
-
121
118
  result.addNameInLocalLanguage = !!additionalPatientName ? true : undefined;
122
119
  result.additionalGivenName = additionalPatientName?.given[0];
123
120
  result.additionalMiddleName = additionalPatientName?.given[1];
@@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next';
6
6
  import { Formik, Form, FormikHelpers } from 'formik';
7
7
  import { createErrorHandler, showToast, useConfig, interpolateUrl, usePatient } from '@openmrs/esm-framework';
8
8
  import { validationSchema as initialSchema } from './validation/patient-registration-validation';
9
- import { FormValues, CapturePhotoProps, PatientIdentifierValue } from './patient-registration-types';
9
+ import { FormValues, CapturePhotoProps, PatientIdentifierValue } from './patient-registration.types';
10
10
  import { PatientRegistrationContext } from './patient-registration-context';
11
11
  import { SavePatientForm, SavePatientTransactionManager } from './form-manager';
12
12
  import { usePatientPhoto } from './patient-registration.resource';
@@ -75,17 +75,6 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
75
75
  .filter((s) => s);
76
76
  }, [config.sections, config.sectionDefinitions]);
77
77
 
78
- useEffect(() => {
79
- if (addressTemplate) {
80
- const addressTemplateXml = addressTemplate?.results[0].value;
81
- if (!addressTemplateXml) {
82
- return;
83
- }
84
- const { addressValidationSchema } = parseAddressTemplateXml(addressTemplateXml);
85
- setValidationSchema((validationSchema) => validationSchema.concat(addressValidationSchema));
86
- }
87
- }, [inEditMode, addressTemplate, initialAddressFieldValues]);
88
-
89
78
  const onFormSubmit = async (values: FormValues, helpers: FormikHelpers<FormValues>) => {
90
79
  const abortController = new AbortController();
91
80
  helpers.setSubmitting(true);
@@ -2,7 +2,7 @@ import { useMemo } from 'react';
2
2
  import useSWR from 'swr';
3
3
  import useSWRImmutable from 'swr/immutable';
4
4
  import { FetchResponse, openmrsFetch, useConfig } from '@openmrs/esm-framework';
5
- import { Patient, Relationship, PatientIdentifier, Encounter } from './patient-registration-types';
5
+ import { Patient, Relationship, PatientIdentifier, Encounter } from './patient-registration.types';
6
6
 
7
7
  export const uuidIdentifier = '05a29f94-c0ed-11e2-94be-8c13b969e334';
8
8
  export const uuidTelephoneNumber = '14d4f066-15f5-102d-96e4-000c29c2a5d7';
@@ -223,74 +223,3 @@ export async function deletePatientIdentifier(patientUuid: string, patientIdenti
223
223
  signal: abortController.signal,
224
224
  });
225
225
  }
226
-
227
- export function useAddressHierarchy(
228
- searchString,
229
- separator,
230
- ): {
231
- addresses: Array<string>;
232
- isLoading: boolean;
233
- error: Error;
234
- } {
235
- const { data, error, isLoading } = useSWRImmutable<
236
- FetchResponse<
237
- Array<{
238
- address: string;
239
- }>
240
- >,
241
- Error
242
- >(
243
- searchString
244
- ? `/module/addresshierarchy/ajax/getPossibleFullAddresses.form?separator=${separator}&searchString=${searchString}`
245
- : null,
246
- openmrsFetch,
247
- );
248
-
249
- const results = useMemo(
250
- () => ({
251
- addresses: data?.data?.map((address) => address.address) ?? [],
252
- error,
253
- isLoading,
254
- }),
255
- [data?.data, error, isLoading],
256
- );
257
- return results;
258
- }
259
-
260
- export function useAdressHierarchyWithParentSearch(
261
- addressField,
262
- parentid,
263
- query,
264
- ): {
265
- error: Error;
266
- isLoading: boolean;
267
- addresses: Array<{
268
- uuid: string;
269
- name: string;
270
- }>;
271
- } {
272
- const { data, error, isLoading } = useSWRImmutable<
273
- FetchResponse<
274
- Array<{
275
- uuid: string;
276
- name: string;
277
- }>
278
- >
279
- >(
280
- query
281
- ? `/module/addresshierarchy/ajax/getPossibleAddressHierarchyEntriesWithParents.form?addressField=${addressField}&limit=20&searchString=${query}&parentUuid=${parentid}`
282
- : null,
283
- openmrsFetch,
284
- );
285
-
286
- const results = useMemo(
287
- () => ({
288
- error: error,
289
- isLoading,
290
- addresses: data?.data ?? [],
291
- }),
292
- [data?.data, error, isLoading],
293
- );
294
-
295
- return results;
296
- }