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

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -65,6 +65,7 @@ export interface RegistrationConfig {
month: number;
};
};
identifier: [{ identifierTypeSystem: string; identifierTypeUuid: string }];
phone: {
personAttributeUuid: string;
validation?: {
Expand Down Expand Up @@ -332,6 +333,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
Expand Up @@ -9,6 +9,7 @@ import {
type PatientIdentifierValue,
type PatientUuidMapType,
} from './patient-registration.types';
import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';

export function parseAddressTemplateXml(addressTemplate: string) {
const templateXmlDoc = new DOMParser().parseFromString(addressTemplate, 'text/xml');
Expand Down Expand Up @@ -192,10 +193,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