Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(feat) HIE-9: Add MPI workflows to OpenMRS frontend #1313

Merged
merged 11 commits into from
Nov 14, 2024
16 changes: 16 additions & 0 deletions packages/esm-patient-registration-app/src/config-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export interface RegistrationConfig {
month: number;
};
};
identifier: [{ identifierTypeSystem: string; identifierTypeUuid: string }];
phone: {
personAttributeUuid: string;
validation?: {
Expand Down Expand Up @@ -351,6 +352,21 @@ export const esmPatientRegistrationSchema = {
},
},
},
identifier: {
_type: Type.Array,
_elements: {
identifierTypeSystem: {
_type: Type.String,
_description: 'Identifier system from the fhir server',
},
identifierTypeUuid: {
_type: Type.String,
_default: null,
_description: 'Identifier type uuid of OpenMRS to map the identifier system',
},
},
_default: [],
},
phone: {
personAttributeUuid: {
_type: Type.UUID,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { fhirBaseUrl, openmrsFetch } from '@openmrs/esm-framework';
import useSWR from 'swr';

export function useMpiPatient(patientId: string) {
const url = `${fhirBaseUrl}/Patient/${patientId}/$cr`;

const {
data: patient,
error: error,
isLoading: isLoading,
} = useSWR<{ data: fhir.Patient }, Error>(url, openmrsFetch);

return {
isLoading,
patient,
error: error,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,27 @@ import {
import {
getAddressFieldValuesFromFhirPatient,
getFormValuesFromFhirPatient,
getIdentifierFieldValuesFromFhirPatient,
getPatientUuidMapFromFhirPatient,
getPhonePersonAttributeValueFromFhirPatient,
latestFirstEncounter,
} from './patient-registration-utils';
import { useInitialPatientRelationships } from './section/patient-relationships/relationships.resource';
import dayjs from 'dayjs';

export function useInitialFormValues(patientUuid: string): [FormValues, Dispatch<FormValues>] {
const { freeTextFieldConceptUuid } = useConfig<RegistrationConfig>();
const { isLoading: isLoadingPatientToEdit, patient: patientToEdit } = usePatient(patientUuid);
const { data: deathInfo, isLoading: isLoadingDeathInfo } = useInitialPersonDeathInfo(patientUuid);
const { data: attributes, isLoading: isLoadingAttributes } = useInitialPersonAttributes(patientUuid);
const { data: identifiers, isLoading: isLoadingIdentifiers } = useInitialPatientIdentifiers(patientUuid);
const { data: relationships, isLoading: isLoadingRelationships } = useInitialPatientRelationships(patientUuid);
import { useMpiPatient } from './mpi/mpi-patient.resource';

export function useInitialFormValues(patientUuid: string, isLocal: boolean): [FormValues, Dispatch<FormValues>] {
const { freeTextFieldConceptUuid, fieldConfigurations } = useConfig<RegistrationConfig>();
const { isLoading: isLoadingPatientToEdit, patient: patientToEdit } = usePatient(isLocal ? patientUuid : null);
const { isLoading: isLoadingMpiPatient, patient: mpiPatient } = useMpiPatient(!isLocal ? patientUuid : null);
const { data: deathInfo, isLoading: isLoadingDeathInfo } = useInitialPersonDeathInfo(isLocal ? patientUuid : null);
const { data: attributes, isLoading: isLoadingAttributes } = useInitialPersonAttributes(isLocal ? patientUuid : null);
const { data: identifiers, isLoading: isLoadingIdentifiers } = useInitialPatientIdentifiers(
isLocal ? patientUuid : null,
);
const { data: relationships, isLoading: isLoadingRelationships } = useInitialPatientRelationships(
isLocal ? patientUuid : null,
);
const { data: encounters } = useInitialEncounters(patientUuid, patientToEdit);

const [initialFormValues, setInitialFormValues] = useState<FormValues>({
Expand Down Expand Up @@ -81,12 +88,12 @@ export function useInitialFormValues(patientUuid: string): [FormValues, Dispatch
...initialFormValues,
...getFormValuesFromFhirPatient(patientToEdit),
address: getAddressFieldValuesFromFhirPatient(patientToEdit),
...getPhonePersonAttributeValueFromFhirPatient(patientToEdit),
...getPhonePersonAttributeValueFromFhirPatient(patientToEdit, fieldConfigurations.phone.personAttributeUuid),
birthdateEstimated: !/^\d{4}-\d{2}-\d{2}$/.test(patientToEdit.birthDate),
yearsEstimated,
monthsEstimated,
});
} else if (!isLoadingPatientToEdit && patientUuid) {
} else if (!isLoadingPatientToEdit && patientUuid && isLocal) {
const registration = await getPatientRegistration(patientUuid);

if (!registration._patientRegistrationData.formValues) {
Expand All @@ -101,6 +108,32 @@ export function useInitialFormValues(patientUuid: string): [FormValues, Dispatch
})();
}, [isLoadingPatientToEdit, patientToEdit, patientUuid]);

useEffect(() => {
const fetchValues = async () => {
if (mpiPatient?.data?.identifier) {
const identifiers = await getIdentifierFieldValuesFromFhirPatient(
mpiPatient.data,
fieldConfigurations.identifier,
);

const values = {
...initialFormValues,
...getFormValuesFromFhirPatient(mpiPatient.data),
address: getAddressFieldValuesFromFhirPatient(mpiPatient.data),
identifiers,
attributes: getPhonePersonAttributeValueFromFhirPatient(
mpiPatient.data,
fieldConfigurations.phone.personAttributeUuid,
),
};

setInitialFormValues(values);
}
};

fetchValues();
}, [mpiPatient, isLoadingMpiPatient]);

// Set initial patient death info
useEffect(() => {
if (!isLoadingDeathInfo && deathInfo?.dead) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as Yup from 'yup';
import camelCase from 'lodash-es/camelCase';
import { parseDate } from '@openmrs/esm-framework';
import { openmrsFetch, parseDate, restBaseUrl } from '@openmrs/esm-framework';
import {
type AddressValidationSchemaType,
type Encounter,
Expand Down Expand Up @@ -192,10 +192,48 @@ export function getPatientIdentifiersFromFhirPatient(patient: fhir.Patient): Arr
});
}

export function getPhonePersonAttributeValueFromFhirPatient(patient: fhir.Patient) {
export async function getIdentifierFieldValuesFromFhirPatient(
patient: fhir.Patient,
identifierConfig,
): Promise<{ [identifierFieldName: string]: PatientIdentifierValue }> {
const identifiers: FormValues['identifiers'] = {};

for (const identifier of patient.identifier) {
for (const config of identifierConfig) {
const identifierConfig = config.identifierTypeSystem === identifier.system ? config : null;

if (identifierConfig) {
let identifierTypeName;

const url = `${restBaseUrl}/patientidentifiertype/${identifierConfig.identifierTypeUuid}`;
await openmrsFetch(url).then((response) => {
if (response.status == 200 && response.data) {
identifierTypeName = response.data.name;
}
});

identifiers[identifierTypeName] = {
identifierUuid: null,
preferred: false, // consider identifier.use === 'official' ?? by default autogen is preferred
initialValue: identifier.value,
identifierValue: identifier.value,
identifierTypeUuid: identifierConfig.identifierTypeUuid,
identifierName: identifierTypeName,
required: false,
selectedSource: null,
autoGeneration: false,
};
}
}
}

return identifiers;
}

export function getPhonePersonAttributeValueFromFhirPatient(patient: fhir.Patient, phoneUuid) {
const result = {};
if (patient.telecom) {
result['phone'] = patient.telecom[0].value;
result[phoneUuid] = patient.telecom[0].value;
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,14 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
const config = useConfig() as RegistrationConfig;
const [target, setTarget] = useState<undefined | string>();
const { patientUuid: uuidOfPatientToEdit } = useParams();
const sourcePatientId = new URLSearchParams(search).get('sourceRecord');
const { isLoading: isLoadingPatientToEdit, patient: patientToEdit } = usePatient(uuidOfPatientToEdit);
const { t } = useTranslation();
const [capturePhotoProps, setCapturePhotoProps] = useState<CapturePhotoProps | null>(null);
const [initialFormValues, setInitialFormValues] = useInitialFormValues(uuidOfPatientToEdit);
const [initialFormValues, setInitialFormValues] = useInitialFormValues(
uuidOfPatientToEdit || sourcePatientId,
!!uuidOfPatientToEdit,
);
const [initialAddressFieldValues] = useInitialAddressFieldValues(uuidOfPatientToEdit);
const [patientUuidMap] = usePatientUuidMap(uuidOfPatientToEdit);
const location = currentSession?.sessionLocation?.uuid;
Expand Down
Loading
Loading