@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.
- package/dist/117.js +2 -0
- package/dist/117.js.map +1 -0
- package/dist/130.js +1 -1
- package/dist/130.js.map +1 -1
- package/dist/208.js +1 -1
- package/dist/218.js +1 -0
- package/dist/218.js.map +1 -0
- package/dist/275.js +1 -0
- package/dist/275.js.map +1 -0
- package/dist/319.js +1 -1
- package/dist/{821.js → 348.js} +1 -1
- package/dist/{821.js.map → 348.js.map} +1 -1
- package/dist/574.js +1 -1
- package/dist/68.js +1 -1
- package/dist/68.js.map +1 -1
- package/dist/693.js +1 -0
- package/dist/693.js.map +1 -0
- package/dist/757.js +1 -1
- package/dist/788.js +1 -1
- package/dist/807.js +1 -1
- package/dist/833.js +1 -1
- package/dist/879.js +1 -0
- package/dist/879.js.map +1 -0
- package/dist/kenyaemr-esm-patient-registration-app.js +1 -1
- package/dist/kenyaemr-esm-patient-registration-app.js.buildmanifest.json +171 -122
- package/dist/kenyaemr-esm-patient-registration-app.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/jest.config.js +3 -0
- package/package.json +5 -2
- package/src/config-schema.ts +11 -5
- package/src/index.ts +9 -2
- package/src/offline.resources.ts +8 -4
- package/src/offline.ts +1 -1
- package/src/patient-registration/field/__mocks__/field.resource.ts +1 -1
- package/src/patient-registration/field/address/address-field.component.tsx +25 -70
- package/src/patient-registration/field/address/address-hierarchy-levels.component.tsx +11 -9
- package/src/patient-registration/field/address/address-hierarchy.resource.tsx +57 -3
- package/src/patient-registration/field/address/address-search.component.tsx +1 -1
- package/src/patient-registration/field/address/tests/address-hierarchy.test.tsx +137 -63
- package/src/patient-registration/field/address/tests/address-search-component.test.tsx +128 -0
- package/src/patient-registration/field/address/tests/mocks.ts +93 -99
- package/src/patient-registration/field/dob/dob.component.tsx +48 -44
- package/src/patient-registration/field/dob/dob.test.tsx +6 -1
- package/src/patient-registration/field/field.resource.ts +1 -1
- package/src/patient-registration/field/id/id-field.component.tsx +1 -1
- package/src/patient-registration/field/id/identifier-selection-overlay.tsx +1 -1
- package/src/patient-registration/field/name/name-field.component.tsx +38 -22
- package/src/patient-registration/field/obs/obs-field.component.tsx +14 -13
- package/src/patient-registration/field/person-attributes/coded-attributes.component.tsx +1 -1
- package/src/patient-registration/field/person-attributes/coded-person-attribute-field.component.tsx +1 -1
- package/src/patient-registration/field/person-attributes/coded-person-attribute-field.test.tsx +103 -0
- package/src/patient-registration/field/person-attributes/person-attribute-field.test.tsx +187 -0
- package/src/patient-registration/field/person-attributes/person-attributes.resource.tsx +1 -1
- package/src/patient-registration/field/person-attributes/text-person-attribute-field.component.tsx +3 -3
- package/src/patient-registration/field/person-attributes/text-person-attribute-field.test.tsx +88 -0
- package/src/patient-registration/form-manager.test.ts +1 -2
- package/src/patient-registration/form-manager.ts +1 -9
- package/src/patient-registration/input/basic-input/input/input.test.tsx +0 -135
- package/src/patient-registration/input/basic-input/select/select-input.test.tsx +8 -4
- package/src/patient-registration/input/combo-input/combo-input.component.tsx +8 -6
- package/src/patient-registration/input/custom-input/identifier/identifier-input.component.tsx +1 -1
- package/src/patient-registration/input/custom-input/identifier/utils.test.ts +81 -0
- package/src/patient-registration/input/custom-input/identifier/utils.ts +1 -1
- package/src/patient-registration/input/dummy-data/dummy-data-input.component.tsx +1 -2
- package/src/patient-registration/patient-registration-context.ts +1 -1
- package/src/patient-registration/patient-registration-hooks.ts +14 -2
- package/src/patient-registration/patient-registration-utils.ts +1 -4
- package/src/patient-registration/patient-registration.component.tsx +1 -12
- package/src/patient-registration/patient-registration.resource.tsx +1 -72
- package/src/patient-registration/patient-registration.test.tsx +250 -247
- package/src/patient-registration/{patient-registration-types.tsx → patient-registration.types.tsx} +45 -1
- package/src/patient-registration/section/patient-relationships/relationships-section.component.tsx +83 -79
- package/src/patient-registration/section/patient-relationships/relationships-section.test.tsx +88 -0
- package/src/patient-registration/section/patient-relationships/relationships.resource.tsx +1 -1
- package/src/patient-registration/validation/patient-registration-validation.tsx +1 -1
- package/src/patient-verification/patient-verification-hook.tsx +12 -1
- package/src/patient-verification/patient-verification-utils.ts +1 -1
- package/src/patient-verification/patient-verification.component.tsx +1 -1
- package/src/patient-verification/verification-modal/confirm-prompt.component.tsx +11 -0
- package/src/root.component.tsx +1 -1
- package/src/routes.json +62 -51
- package/src/widgets/cancel-patient-edit.test.tsx +24 -0
- package/src/widgets/delete-identifier-confirmation-modal.test.tsx +31 -0
- package/src/widgets/display-photo.test.tsx +37 -0
- package/src/widgets/edit-patient-details-button.test.tsx +36 -0
- package/translations/am.json +0 -7
- package/translations/en.json +2 -5
- package/translations/es.json +0 -7
- package/translations/fr.json +0 -7
- package/translations/he.json +0 -7
- package/translations/km.json +0 -7
- package/__mocks__/react-i18next.js +0 -49
- package/dist/196.js +0 -1
- package/dist/196.js.map +0 -1
- package/dist/59.js +0 -1
- package/dist/59.js.map +0 -1
- package/dist/9.js +0 -2
- package/dist/9.js.map +0 -1
- /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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
}
|