diff --git a/packages/esm-patient-registration-app/src/patient-registration/field/id/id-field.component.tsx b/packages/esm-patient-registration-app/src/patient-registration/field/id/id-field.component.tsx index cfd27ba5e..9fb88e79e 100644 --- a/packages/esm-patient-registration-app/src/patient-registration/field/id/id-field.component.tsx +++ b/packages/esm-patient-registration-app/src/patient-registration/field/id/id-field.component.tsx @@ -25,14 +25,16 @@ export function setIdentifierSource( selectedSource: IdentifierSource; } { const autoGeneration = identifierSource?.autoGenerationOption?.automaticGenerationEnabled; + const manualEntryEnabled = identifierSource?.autoGenerationOption?.manualEntryEnabled; return { selectedSource: identifierSource, autoGeneration, - identifierValue: autoGeneration - ? 'auto-generated' - : identifierValue !== 'auto-generated' - ? identifierValue - : initialValue, + identifierValue: + autoGeneration && !manualEntryEnabled + ? 'auto-generated' + : identifierValue !== 'auto-generated' + ? identifierValue + : initialValue, }; } diff --git a/packages/esm-patient-registration-app/src/patient-registration/field/id/id-field.test.tsx b/packages/esm-patient-registration-app/src/patient-registration/field/id/id-field.test.tsx index 0b9e2ab20..49f28bc4b 100644 --- a/packages/esm-patient-registration-app/src/patient-registration/field/id/id-field.test.tsx +++ b/packages/esm-patient-registration-app/src/patient-registration/field/id/id-field.test.tsx @@ -1,13 +1,14 @@ -import React from 'react'; -import userEvent from '@testing-library/user-event'; +import { getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework'; import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import { Form, Formik } from 'formik'; -import { getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework'; -import { Identifiers } from './id-field.component'; -import { mockOpenmrsId, mockIdentifierTypes, mockPatient, mockSession } from '__mocks__'; -import { type RegistrationConfig, esmPatientRegistrationSchema } from '../../../config-schema'; -import { type Resources, ResourcesContext } from '../../../offline.resources'; +import React from 'react'; +import { mockIdentifierTypes, mockOpenmrsId, mockPatient, mockSession } from '__mocks__'; +import { esmPatientRegistrationSchema, type RegistrationConfig } from '../../../config-schema'; +import { ResourcesContext, type Resources } from '../../../offline.resources'; import { PatientRegistrationContext, type PatientRegistrationContextProps } from '../../patient-registration-context'; +import { type IdentifierSource } from '../../patient-registration.types'; +import { Identifiers, setIdentifierSource } from './id-field.component'; const mockUseConfig = jest.mocked(useConfig); @@ -120,3 +121,21 @@ describe('Identifiers', () => { expect(screen.getByRole('button', { name: 'Close overlay' })).toBeInTheDocument(); }); }); + +describe('setIdentifierSource', () => { + describe('auto-generation', () => { + it('should return auto-generated as the identifier value', () => { + const identifierSource = { autoGenerationOption: { automaticGenerationEnabled: true } } as IdentifierSource; + const { identifierValue } = setIdentifierSource(identifierSource, '', ''); + expect(identifierValue).toBe('auto-generated'); + }); + + it('should return the identifier value when manual entry enabled', () => { + const identifierSource = { + autoGenerationOption: { automaticGenerationEnabled: true, manualEntryEnabled: true }, + } as IdentifierSource; + const { identifierValue } = setIdentifierSource(identifierSource, '10001V', ''); + expect(identifierValue).toBe('10001V'); + }); + }); +}); diff --git a/packages/esm-patient-registration-app/src/patient-registration/form-manager.test.ts b/packages/esm-patient-registration-app/src/patient-registration/form-manager.test.ts index ae625319e..e2e6eea63 100644 --- a/packages/esm-patient-registration-app/src/patient-registration/form-manager.test.ts +++ b/packages/esm-patient-registration-app/src/patient-registration/form-manager.test.ts @@ -1,8 +1,11 @@ import { FormManager } from './form-manager'; import { type FormValues } from './patient-registration.types'; +import { generateIdentifier } from './patient-registration.resource'; jest.mock('./patient-registration.resource'); +const mockGenerateIdentifier = generateIdentifier as jest.Mock; + const formValues: FormValues = { patientUuid: '', givenName: '', @@ -66,5 +69,19 @@ describe('FormManager', () => { }, ]); }); + it('should generate identifier if it has autoGeneration and manual entry disabled', async () => { + formValues.identifiers.foo.autoGeneration = true; + formValues.identifiers.foo.selectedSource.autoGenerationOption.manualEntryEnabled = false; + mockGenerateIdentifier.mockResolvedValue({ data: { identifier: '10001V' } }); + await FormManager.savePatientIdentifiers(true, undefined, formValues.identifiers, {}, 'Nyc'); + expect(mockGenerateIdentifier.mock.calls).toHaveLength(1); + }); + + it('should not generate identifiers if manual entry enabled and identifier value given', async () => { + formValues.identifiers.foo.autoGeneration = true; + formValues.identifiers.foo.selectedSource.autoGenerationOption.manualEntryEnabled = true; + await FormManager.savePatientIdentifiers(true, undefined, formValues.identifiers, {}, 'Nyc'); + expect(mockGenerateIdentifier.mock.calls).toHaveLength(0); + }); }); }); diff --git a/packages/esm-patient-registration-app/src/patient-registration/form-manager.ts b/packages/esm-patient-registration-app/src/patient-registration/form-manager.ts index b682d038f..d1b9c9c05 100644 --- a/packages/esm-patient-registration-app/src/patient-registration/form-manager.ts +++ b/packages/esm-patient-registration-app/src/patient-registration/form-manager.ts @@ -241,11 +241,15 @@ export class FormManager { initialValue, } = patientIdentifier; - const identifier = !autoGeneration - ? identifierValue - : await ( - await generateIdentifier(selectedSource.uuid) - ).data.identifier; + const autoGenerationManualEntry = + autoGeneration && selectedSource?.autoGenerationOption?.manualEntryEnabled && !!identifierValue; + + const identifier = + !autoGeneration || autoGenerationManualEntry + ? identifierValue + : await ( + await generateIdentifier(selectedSource.uuid) + ).data.identifier; const identifierToCreate = { uuid: identifierUuid, identifier, diff --git a/packages/esm-patient-registration-app/src/patient-registration/input/custom-input/identifier/identifier-input.component.tsx b/packages/esm-patient-registration-app/src/patient-registration/input/custom-input/identifier/identifier-input.component.tsx index 3a3166ceb..3a8dd0490 100644 --- a/packages/esm-patient-registration-app/src/patient-registration/input/custom-input/identifier/identifier-input.component.tsx +++ b/packages/esm-patient-registration-app/src/patient-registration/input/custom-input/identifier/identifier-input.component.tsx @@ -26,7 +26,8 @@ const IdentifierInput: React.FC = ({ patientIdentifier, fi () => identifierTypes.find((identifierType) => identifierType.uuid === patientIdentifier.identifierTypeUuid), [patientIdentifier, identifierTypes], ); - const { autoGeneration, initialValue, identifierValue, identifierName, required } = patientIdentifier; + const { autoGeneration, initialValue, identifierValue, identifierName, required, selectedSource } = patientIdentifier; + const manualEntryEnabled = selectedSource?.autoGenerationOption?.manualEntryEnabled; const [hideInputField, setHideInputField] = useState(autoGeneration || initialValue === identifierValue); const name = `identifiers.${fieldName}.identifierValue`; const [identifierField, identifierFieldMeta] = useField(name); @@ -46,8 +47,8 @@ const IdentifierInput: React.FC = ({ patientIdentifier, fi setFieldValue(`identifiers.${fieldName}`, { ...patientIdentifier, identifierValue: initialValue, - selectedSource: null, - autoGeneration: false, + selectedSource, + autoGeneration, } as PatientIdentifierValue); // eslint-disable-next-line react-hooks/exhaustive-deps }, [initialValue, setHideInputField]); @@ -57,6 +58,7 @@ const IdentifierInput: React.FC = ({ patientIdentifier, fi setFieldValue(`identifiers.${fieldName}`, { ...patientIdentifier, ...setIdentifierSource(identifierType?.identifierSources?.[0], initialValue, initialValue), + ...(autoGeneration && manualEntryEnabled && { identifierValue: initialValue ?? '' }), }); }; @@ -83,9 +85,12 @@ const IdentifierInput: React.FC = ({ patientIdentifier, fi } }; + const showEditButton = !required && hideInputField && (!!initialValue || manualEntryEnabled); + const showResetButton = + (!!initialValue && initialValue !== identifierValue) || (!hideInputField && manualEntryEnabled); return (
- {!autoGeneration && !hideInputField ? ( + {!hideInputField ? ( = ({ patientIdentifier, fi /> ) : (
-

{identifierName}

-

+

+ {required ? identifierName : `${t('optionalIdentifierLabel', { identifierName })}`} +

+

{autoGeneration ? t('autoGeneratedPlaceholderText', 'Auto-generated') : identifierValue}

@@ -111,9 +118,10 @@ const IdentifierInput: React.FC = ({ patientIdentifier, fi
)}
- {!patientIdentifier.required && patientIdentifier.initialValue && hideInputField && ( + {showEditButton && ( )} - {initialValue && initialValue !== identifierValue && ( + {showResetButton && (