Skip to content

Commit

Permalink
OHRI-2295 Update OHRI endpoints to use SWR
Browse files Browse the repository at this point in the history
  • Loading branch information
CynthiaKamau committed Jul 12, 2024
1 parent 41f1f66 commit 73e4092
Show file tree
Hide file tree
Showing 11 changed files with 268 additions and 373 deletions.
59 changes: 26 additions & 33 deletions packages/esm-commons-lib/src/api.resource.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
import { openmrsFetch } from '@openmrs/esm-framework';
import dayjs from 'dayjs';
import {
finalHIVCodeConcept,
finalPositiveHIVValueConcept,
computedHIV_StatusConcept,
encounterRepresentation,
covidOutcomesCohortUUID,
} from './constants';
import { BASE_FHIR_API_URL, BASE_WS_API_URL, encounterRepresentation } from './constants';
import useSWR from 'swr';

const BASE_WS_API_URL = '/ws/rest/v1/';
const BASE_FHIR_API_URL = '/ws/fhir2/R4/';
import { configSchema } from './config-schema';

export function fetchLastVisit(uuid: string) {
return openmrsFetch(`/ws/fhir2/R4/Encounter?patient=${uuid}&_sort=-date&_count=1`);
Expand Down Expand Up @@ -145,7 +137,7 @@ export async function getPatientListsForPatient(patientUuid: string) {

export function fetchPatientsFinalHIVStatus(patientUUID: string) {
return openmrsFetch(
`/ws/fhir2/R4/Observation?code=${finalHIVCodeConcept}&value-concept=${finalPositiveHIVValueConcept}&patient=${patientUUID}&_sort=-date&_count=1`,
`/ws/fhir2/R4/Observation?code=${configSchema.obsConcepts._default.finalHIVCodeConcept}&value-concept=${configSchema.obsConcepts._default.finalPositiveHIVValueConcept}&patient=${patientUUID}&_sort=-date&_count=1`,
).then(({ data }) => {
if (data.entry?.length) {
return data.entry[0].resource.valueCodeableConcept.coding[0].display;
Expand All @@ -166,7 +158,7 @@ export function fetchPatientObservationFromEncounter(

export function fetchPatientComputedConcept_HIV_Status(patientUUID: string) {
return openmrsFetch(
`/ws/fhir2/R4/Observation?code=${computedHIV_StatusConcept}&value-concept=${computedHIV_StatusConcept}&patient=${patientUUID}&_sort=-date&_count=1`,
`/ws/fhir2/R4/Observation?code=${configSchema.obsConcepts._default.computedHIV_StatusConcept}&value-concept=${configSchema.obsConcepts._default.computedHIV_StatusConcept}&patient=${patientUUID}&_sort=-date&_count=1`,
).then(({ data }) => {
if (data.entry?.length) {
return data.entry[0].resource.valueCodeableConcept.coding[0].display;
Expand All @@ -191,21 +183,23 @@ export function fetchPatientLastEncounter(patientUuid: string, encounterType) {
}

export function fetchPatientCovidOutcome() {
return openmrsFetch(`/ws/rest/v1/reportingrest/cohort/${covidOutcomesCohortUUID}`).then(({ data }) => {
if (data.members?.length) {
let patientRefs = data.members.map((member) => {
return member.uuid;
});
patientRefs = new Set([...patientRefs]);
patientRefs = Array.from(patientRefs);
return Promise.all(
patientRefs.map((ref) => {
return openmrsFetch(BASE_FHIR_API_URL + '/Person/' + ref);
}),
);
}
return [];
});
return openmrsFetch(`/ws/rest/v1/reportingrest/cohort/${configSchema.obsConcepts._default.covidOutcomesCohortUUID}`).then(
({ data }) => {
if (data.members?.length) {
let patientRefs = data.members.map((member) => {
return member.uuid;
});
patientRefs = new Set([...patientRefs]);
patientRefs = Array.from(patientRefs);
return Promise.all(
patientRefs.map((ref) => {
return openmrsFetch(BASE_FHIR_API_URL + '/Person/' + ref);
}),
);
}
return [];
},
);
}

export function fetchConceptNameByUuid(conceptUuid: string) {
Expand Down Expand Up @@ -358,12 +352,11 @@ export async function getCohortList(
`/ws/rest/v1/encounter?encounterType=${encounterType}&patient=${member.patient.uuid}&v=${encounterRepresentation}`,
).then(({ data }) => {
if (data.results.length) {
const sortedEncounters = data.results
.sort(
(firstEncounter, secondEncounter) =>
new Date(secondEncounter.encounterDatetime).getTime() -
new Date(firstEncounter.encounterDatetime).getTime(),
);
const sortedEncounters = data.results.sort(
(firstEncounter, secondEncounter) =>
new Date(secondEncounter.encounterDatetime).getTime() -
new Date(firstEncounter.encounterDatetime).getTime(),
);
return sortedEncounters[0];
}
return null;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import React, { useEffect, useState } from 'react';
import React from 'react';
import { Tag } from '@carbon/react';
import { useTranslation } from 'react-i18next';
import { isPatientHivPositive } from './patientHivStatus';
import { usePatientsFinalHIVStatus } from './usePatientHivStatus';
import { useConfig } from '@openmrs/esm-framework';

export function PatientStatusBannerTag({ patientUuid }) {
const { t } = useTranslation();
const [hivPositive, setHivPositive] = useState(false);
const { obsConcepts } = useConfig();
const { isLoading, hivStatus, error } = usePatientsFinalHIVStatus(
patientUuid,
obsConcepts.finalHIVCodeConcept,
obsConcepts.finalPositiveHIVValueConcept,
);

useEffect(() => {
isPatientHivPositive(patientUuid).then((result) => setHivPositive(result));
}, [hivPositive, patientUuid]);
if (isLoading) {
return <p>{t('loading', 'Loading...')}</p>;
}

//TODO: Improve refresh time
// forceRerender();
if (error) {
return <p>{t('error', 'Error...')}</p>;
}

return <>{hivPositive && <Tag type="red">{t('hivPositive', 'HIV Positive')}</Tag>}</>;
return <>{hivStatus && <Tag type="red">{t('hivPositive', 'HIV Positive')}</Tag>}</>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import { PatientStatusBannerTag } from './patient-status-tag.component';
import { usePatientsFinalHIVStatus } from './usePatientHivStatus';

const mockedUsePatientsFinalHIVStatus = jest.mocked(usePatientsFinalHIVStatus);

jest.mock('./usePatientHivStatus', () => {
const originalModule = jest.requireActual('./usePatientHivStatus');

return {
...originalModule,
usePatientsFinalHIVStatus: jest.fn().mockImplementation(() => ({
hivStatus: true,
isLoading: false,
})),
};
});

describe('PatientStatusBannerTag', () => {
beforeEach(() => {
jest.clearAllMocks();
});

const samplePatientUuid = '703AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';

it('renders red tag when patient is HIV positive', async () => {
render(<PatientStatusBannerTag patientUuid={samplePatientUuid} />);
expect(screen.getByText(/HIV Positive/i)).toBeInTheDocument();
});

it('does not render red tag when patient is not HIV positive', async () => {
mockedUsePatientsFinalHIVStatus.mockReturnValue({ hivStatus: false, isLoading: false, error: null });
render(<PatientStatusBannerTag patientUuid={samplePatientUuid} />);
expect(screen.queryByText('HIV Positive')).not.toBeInTheDocument();
});
});

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { fhirBaseUrl, openmrsFetch } from '@openmrs/esm-framework';
import useSWR from 'swr';

export function usePatientsFinalHIVStatus(
patientUuid: string,
finalHIVCodeConcept: string,
finalPositiveHIVValueConcept: string,
) {
const url = `${fhirBaseUrl}/Observation?code=${finalHIVCodeConcept}&value-concept=${finalPositiveHIVValueConcept}&patient=${patientUuid}&_sort=-date&_count=1`;
const { data, error, isLoading, mutate } = useSWR<{ data: any }, Error>(url, openmrsFetch);

const hivStatusResult = data?.data?.entry[0].resource.valueCodeableConcept.coding[0].display;
const hivStatus = hivStatusResult.toLowerCase().includes('positive') ? true : false;

return { hivStatus: hivStatus, isLoading: isLoading, error: error };
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import dayjs from 'dayjs';
import localizedFormat from 'dayjs/plugin/localizedFormat';
import relativeTime from 'dayjs/plugin/relativeTime';
import { AddPatientToListOverflowMenuItem } from '../modals/add-patient-to-list-modal.component';
import { fetchPatientLastEncounter } from '../../api.resource';
import { launchForm } from '../../utils/ohri-forms-commons';
import { navigate, WorkspaceContainer } from '@openmrs/esm-framework';
import { useLastEncounter } from '../../hooks/useLastEncounter';

interface PatientMetaConfig {
location: { name: string };
Expand Down Expand Up @@ -38,23 +38,25 @@ export const LaunchableFormMenuItem = ({
}) => {
const [actionText, setActionText] = useState(launchableForm.actionText);
const [encounterUuid, setEncounterUuid] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const continueEncounterActionText = launchableForm.actionText || 'Continue encounter ';
const { lastEncounter, isLoading } = useLastEncounter(patientUuid, encounterType);

useEffect(() => {
if (launchableForm.editLatestEncounter && encounterType && !encounterUuid) {
setIsLoading(true);
fetchPatientLastEncounter(patientUuid, encounterType).then((latestEncounter) => {
if (latestEncounter) {
setActionText(continueEncounterActionText);
setEncounterUuid(latestEncounter.uuid);
}
setIsLoading(false);
});
} else {
setIsLoading(false);
if (!isLoading && lastEncounter) {
setActionText(continueEncounterActionText);
setEncounterUuid(lastEncounter.uuid);
}
}
}, [continueEncounterActionText, encounterType, encounterUuid, launchableForm.editLatestEncounter, patientUuid]);
}, [
continueEncounterActionText,
encounterType,
encounterUuid,
launchableForm.editLatestEncounter,
patientUuid,
lastEncounter,
isLoading,
]);

return (
<>
Expand All @@ -79,21 +81,15 @@ export const LaunchableFormMenuItem = ({
export const ViewSummaryMenuItem = ({ patientUuid, ViewSummary, encounterType }) => {
const [actionText, setActionText] = useState(ViewSummary.actionText);
const [encounterUuid, setEncounterUuid] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const viewSummaryActionText = ViewSummary.actionText || 'View Summary ';
const { lastEncounter, isLoading } = useLastEncounter(patientUuid, encounterType);

useEffect(() => {
if (ViewSummary.editLatestEncounter && encounterType && !encounterUuid) {
setIsLoading(true);
fetchPatientLastEncounter(patientUuid, encounterType).then((latestEncounter) => {
if (latestEncounter) {
setActionText(viewSummaryActionText);
setEncounterUuid(latestEncounter.uuid);
}
setIsLoading(false);
});
} else {
setIsLoading(false);
if (!isLoading && lastEncounter) {
setActionText(viewSummaryActionText);
setEncounterUuid(lastEncounter.uuid);
}
}
}, [ViewSummary.editLatestEncounter, encounterType, encounterUuid, patientUuid, viewSummaryActionText]);

Expand All @@ -114,24 +110,19 @@ export const ViewSummaryMenuItem = ({ patientUuid, ViewSummary, encounterType })
</>
);
};

export const ViewTptSummaryMenuItem = ({ patientUuid, ViewTptSummary, encounterType }) => {
const [actionText, setActionText] = useState(ViewTptSummary.actionText);
const [encounterUuid, setEncounterUuid] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const viewTptSummaryActionText = ViewTptSummary.actionText || 'View Summary ';
const { lastEncounter, isLoading } = useLastEncounter(patientUuid, encounterType);

useEffect(() => {
if (ViewTptSummary.editLatestEncounter && encounterType && !encounterUuid) {
setIsLoading(true);
fetchPatientLastEncounter(patientUuid, encounterType).then((latestEncounter) => {
if (latestEncounter) {
setActionText(viewTptSummaryActionText);
setEncounterUuid(latestEncounter.uuid);
}
setIsLoading(false);
});
} else {
setIsLoading(false);
if (!isLoading && lastEncounter) {
setActionText(viewTptSummaryActionText);
setEncounterUuid(lastEncounter.uuid);
}
}
}, [ViewTptSummary.editLatestEncounter, encounterType, patientUuid, encounterUuid, viewTptSummaryActionText]);

Expand All @@ -152,6 +143,7 @@ export const ViewTptSummaryMenuItem = ({ patientUuid, ViewTptSummary, encounterT
</>
);
};

export function consolidatatePatientMeta(rawPatientMeta, form, config: PatientMetaConfig) {
const {
isDynamicCohort,
Expand Down
Loading

0 comments on commit 73e4092

Please sign in to comment.