Skip to content

Commit

Permalink
U4X-520: Setting default program enrolled as HIV (#214)
Browse files Browse the repository at this point in the history
U4X-520: Setting default program enrolled as HIV (#214)
  • Loading branch information
Daphne210 authored Apr 12, 2024
1 parent a1ac0ec commit 2dab85b
Show file tree
Hide file tree
Showing 7 changed files with 203 additions and 108 deletions.
102 changes: 63 additions & 39 deletions packages/esm-care-panel-app/src/care-panel/care-panel.component.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { StructuredListSkeleton, ContentSwitcher, Switch } from '@carbon/react';
import styles from './care-panel.scss';
Expand All @@ -7,6 +7,7 @@ import ProgramEnrollment from '../program-enrollment/program-enrollment.componen
import { CardHeader, EmptyState } from '@openmrs/esm-patient-common-lib';
import { ErrorState } from '@openmrs/esm-framework';
import CarePrograms from '../care-programs/care-programs.component';
import ProgramEnrollmentTB from '../program-enrollment/program-enrollment-tb.component';

interface CarePanelProps {
patientUuid: string;
Expand All @@ -22,18 +23,33 @@ type SwitcherItem = {

const CarePanel: React.FC<CarePanelProps> = ({ patientUuid, formEntrySub, launchPatientWorkspace }) => {
const { t } = useTranslation();
const [programEnrolled, setProgramEnrolled] = useState('TB Program');
const { isLoading, error, enrollments } = usePatientPrograms(patientUuid);
const switcherHeaders = enrollments?.map((item) => item.program.name);
const [switchItem, setSwitcherItem] = useState<SwitcherItem>();
const [selectedIndex, setSelectedIndex] = useState(0);
const [switchItem, setSwitcherItem] = useState<SwitcherItem>(() => {
const firstEnrollment = enrollments?.[0];
return firstEnrollment ? { index: 0, name: firstEnrollment.program.name } : undefined;
});
const programs = {
hiv: 'HIV Program',
tb: 'TB Program',
mch: 'MCH Program',
nutrition: 'Nutrition Program',
};
const handleItemTabChange = (name) => {
setProgramEnrolled(name);
useEffect(() => {
if (!switchItem && enrollments && enrollments.length > 0) {
setSwitcherItem({ index: 0, name: enrollments[0].program.name });
}
}, [enrollments, switchItem]);

const handleItemTabChange = (index: number, name?: string) => {
const programName = enrollments?.[index]?.program?.name;
const switcherItem = { index, name: programName };

if (programName) {
setSwitcherItem(switcherItem);
setSelectedIndex(index);
}
};
if (isLoading) {
return (
Expand All @@ -46,44 +62,52 @@ const CarePanel: React.FC<CarePanelProps> = ({ patientUuid, formEntrySub, launch
if (error) {
return <ErrorState error={error} headerTitle={t('carePanelError', 'Care panel')} />;
}

if (Object.keys(enrollments).length === 0) {
return (
<div className={styles.careProgramContainer}>
<CarePrograms patientUuid={patientUuid} />
</div>
);
}
return (
<>
<div className={styles.widgetCard}>
<CardHeader title={t('carePanel', 'Care Panel')}>
<div className={styles.contextSwitcherContainer}>
<ContentSwitcher onChange={(event) => handleItemTabChange(event.name)}>
{switcherHeaders?.map((enrollment, index) => (
<Switch key={enrollment} name={enrollment} text={enrollment} />
))}
</ContentSwitcher>
</div>
</CardHeader>
<div style={{ width: '100%', minHeight: '20rem' }}>
{programEnrolled === programs.hiv && (
<ProgramEnrollment
patientUuid={patientUuid}
programName={switchItem?.name}
enrollments={enrollments}
formEntrySub={formEntrySub}
launchPatientWorkspace={launchPatientWorkspace}
PatientChartProps={''}
/>
)}
{programEnrolled === programs.tb && (
<div className={styles.emptyState}>
<span>No data to display for this program</span>
{Object.keys(enrollments).length > 0 ? (
<div className={styles.widgetCard}>
<CardHeader title={t('carePanel', 'Care Panel')}>
<div className={styles.contextSwitcherContainer}>
<ContentSwitcher
selectedIndex={selectedIndex}
onChange={(event) => handleItemTabChange(event.index, event.name)}
>
{switcherHeaders?.map((enrollment, index) => (
<Switch key={enrollment} name={enrollment} text={enrollment} />
))}
</ContentSwitcher>
</div>
</CardHeader>
<div style={{ width: '100%', minHeight: '20rem' }}>
{switchItem?.name === programs.hiv && (
<ProgramEnrollment
patientUuid={patientUuid}
programName={switchItem?.name}
enrollments={enrollments}
formEntrySub={formEntrySub}
launchPatientWorkspace={launchPatientWorkspace}
PatientChartProps={''}
/>
)}
<div style={{ width: '100%', minHeight: '20rem' }}>
{switchItem?.name === programs.tb && (
<ProgramEnrollmentTB
patientUuid={patientUuid}
programName={switchItem?.name}
enrollments={enrollments}
formEntrySub={formEntrySub}
launchPatientWorkspace={launchPatientWorkspace}
PatientChartProps={''}
/>
)}
</div>
)}
</div>
</div>
</div>
) : (
<div className={styles.careProgramContainer}>
<CarePrograms patientUuid={patientUuid} />
</div>
)}
<CarePrograms patientUuid={patientUuid} />
</>
);
Expand Down
16 changes: 16 additions & 0 deletions packages/esm-care-panel-app/src/config-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,20 @@ export const configSchema = {
_type: Type.ConceptUuid,
_default: '9dc21a72-0971-11e7-8037-507b9dc4c741',
},
dateStartedTBFirstRegimenUuid: {
_type: Type.ConceptUuid,
_default: '7326297e-0ccd-4355-9b86-dde1c056e2c2',
},
dsTbRegmimenUuid: {
_type: Type.ConceptUuid,
_default: '159958AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
},
tbDiseaseClassificationUuid: {
_type: Type.ConceptUuid,
_default: 'd45871ee-62d6-4d4d-b905-f7b75a3fd3bb',
},
tbPatientTypeUuid: {
_type: Type.ConceptUuid,
_default: 'e077f196-c19a-417f-adc6-b175a3343bfd',
},
};
9 changes: 9 additions & 0 deletions packages/esm-care-panel-app/src/hooks/useCarePrograms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ export type PatientCarePrograms = {
enrollmentDetails?: { uuid: string; dateCompleted: string; location: string; dateEnrolled: string };
};

export interface ProgramEnrollmentProps {
patientUuid: string;
programName: string;
enrollments: Array<any>;
formEntrySub: any;
launchPatientWorkspace: Function;
PatientChartProps: string;
}

export const useCarePrograms = (patientUuid: string) => {
const url = `/ws/rest/v1/ugandaemr/patientCohorts?patientUuid=${patientUuid}`;
const { data, error, isLoading, isValidating } = useSWR<{ data: Array<PatientCarePrograms> }>(url, openmrsFetch);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import React, { useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import styles from './program-enrollment.scss';
import { launchPatientWorkspace } from '@openmrs/esm-patient-common-lib';
import dayjs from 'dayjs';
import orderBy from 'lodash/orderBy';
import { mutate } from 'swr';
import { parseStageFromDisplay, usePatientObservations } from './program-enrollment.resource';
import { ProgramData } from '../types/index';
import { usePatient } from '@openmrs/esm-framework';
import { configSchema } from '../config-schema';
import { ProgramEnrollmentProps } from '../hooks/useCarePrograms';

const ProgramEnrollmentTB: React.FC<ProgramEnrollmentProps> = ({ enrollments = [], patientUuid }) => {
const { t } = useTranslation();

const { patient } = usePatient(patientUuid);

const observationConfig = useMemo(
() => [
{
key: 'dateStartedTBFirstLineRegimen',
uuidConfig: configSchema.dateStartedTBFirstRegimenUuid._default,
processValue: (date) => {
return date && dayjs(date).isValid() ? dayjs(date).format('DD-MM-YYYY') : '--';
},
},
{
key: 'dsTBRegimen',
uuidConfig: configSchema.dsTbRegmimenUuid._default,
},
{
key: 'tbPatientType',
uuidConfig: configSchema.tbPatientTypeUuid._default,
},
{
key: 'tbDiseaseClassification',
uuidConfig: configSchema.tbDiseaseClassificationUuid._default,
},
],
[],
);
const conceptUuids = observationConfig.map((config) => config.uuidConfig);

const orderedEnrollments = orderBy(enrollments, 'dateEnrolled', 'desc');

const [programData, setProgramData] = useState<ProgramData>({
dateStartedTBFirstLineRegimen: '--',
dsTBRegimen: '--',
tbDiseaseClassification: '--',
tbPatientType: '--',
});

const { observations, isLoading, isError } = usePatientObservations(patientUuid, conceptUuids);
useEffect(() => {
if (observations) {
const newData = observationConfig.reduce((acc, { key, uuidConfig, processValue }) => {
const value = observations[uuidConfig]?.[0] || '--';
acc[key] = processValue ? processValue(value) : value;
return acc;
}, {});

setProgramData((prevState) => ({ ...prevState, ...newData }));
}
}, [observationConfig, observations]);

if (orderedEnrollments?.length === 0) {
return null;
}
return (
<div className={styles.bodyContainer}>
<div className={styles.card}>
<h6>{t('diseasClassification', 'Disease Classification/Patient Type')}</h6>
<div className={styles.container}>
<div className={styles.content}>
<p className={styles.label}>{t('diseaseClassification', 'TB Disease Classification')}</p>
<p>
<span className={styles.value}>{programData.tbDiseaseClassification}</span>
</p>
</div>
<div className={styles.content}>
<p className={styles.label}>{t('tbPatientType', 'Patient Type')}</p>
<p>
<span className={styles.value}>{programData.tbPatientType}</span>
</p>
</div>
</div>
<br></br>
<h6>{t('firstLineTreatment', 'First Line Treatment')}</h6>
<div className={styles.container}>
<div className={styles.content}>
<p className={styles.label}>{t('dateStarted', 'Date Started')}</p>
<p>
<span className={styles.value}>{programData.dateStartedTBFirstLineRegimen}</span>
</p>
</div>
<div className={styles.content}>
<p className={styles.label}>{t('dsTbRegmien', 'DS TB Regimen')}</p>
<p>
<span className={styles.value}>{programData.dsTBRegimen}</span>
</p>
</div>
</div>
</div>
</div>
);
};
export default ProgramEnrollmentTB;
Original file line number Diff line number Diff line change
Expand Up @@ -9,52 +9,9 @@ import { parseStageFromDisplay, usePatientObservations } from './program-enrollm
import { ProgramData } from '../types/index';
import { usePatient } from '@openmrs/esm-framework';
import { configSchema } from '../config-schema';
import { ProgramEnrollmentProps } from '../hooks/useCarePrograms';

export interface ProgramEnrollmentProps {
patientUuid: string;
programName: string;
enrollments: Array<any>;
formEntrySub: any;
launchPatientWorkspace: Function;
PatientChartProps: string;
}
const shareObjProperty = { dateEnrolled: 'Enrolled on', dateCompleted: 'Date Completed' };
const programDetailsMap = {
HIV: {
dateEnrolled: 'Enrolled on',
whoStage: 'WHO Stage',
entryPoint: 'Entry Point',
regimenShortDisplay: 'Regimen',
changeReasons: 'Reason for regimen change',
},
TB: {
...shareObjProperty,
startDate: 'Date started regimen',
regimenShortName: 'Regimen',
},
TPT: {
...shareObjProperty,
tptDrugName: 'Regimen',
tptDrugStartDate: 'Date started regimen',
tptIndication: 'Indication for TPT',
},
'MCH - Mother Services': {
...shareObjProperty,
lmp: 'LMP',
eddLmp: 'EDD',
gravida: 'Gravida',
parity: 'Parity',
gestationInWeeks: 'Gestation in weeks',
},
'MCH - Child Services': { ...shareObjProperty, entryPoint: 'Entry Point' },
mchMother: {},
mchChild: {},
VMMC: {
...shareObjProperty,
},
};

const ProgramEnrollment: React.FC<ProgramEnrollmentProps> = ({ enrollments = [], programName, patientUuid }) => {
const ProgramEnrollment: React.FC<ProgramEnrollmentProps> = ({ enrollments = [], patientUuid }) => {
const { t } = useTranslation();

const { patient } = usePatient(patientUuid);
Expand Down Expand Up @@ -113,29 +70,6 @@ const ProgramEnrollment: React.FC<ProgramEnrollmentProps> = ({ enrollments = [],
const conceptUuids = observationConfig.map((config) => config.uuidConfig);

const orderedEnrollments = orderBy(enrollments, 'dateEnrolled', 'desc');
const headers = useMemo(
() =>
Object.entries(programDetailsMap[programName] ?? { ...shareObjProperty }).map(([key, value]) => ({
key,
header: value,
})),
[programName],
);
const rows = useMemo(
() =>
orderedEnrollments?.map((enrollment) => {
const firstEncounter = enrollment?.firstEncounter ?? {};
const enrollmentEncounterUuid = enrollment?.enrollmentEncounterUuid;
return {
id: `${enrollment.enrollmentUuid}`,
...enrollment,
...firstEncounter,
changeReasons: enrollment?.firstEncounter?.changeReasons?.join(', '),
enrollmentEncounterUuid: enrollmentEncounterUuid,
};
}),
[orderedEnrollments],
);

const handleDiscontinue = (enrollment) => {
launchPatientWorkspace('patient-form-entry-workspace', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@
.container {
display: flex;
flex-direction: row;
padding-left: 1rem;
flex-wrap: wrap;
justify-content: space-between;
}

.value {
Expand Down
4 changes: 4 additions & 0 deletions packages/esm-care-panel-app/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,4 +235,8 @@ export interface ProgramData {
hivViralLoadQualitative?: string;
hivViralLoad?: string;
lastEncounterDate?: string;
dateStartedTBFirstLineRegimen?: string;
dsTBRegimen?: string;
tbDiseaseClassification?: string;
tbPatientType?: string;
}

0 comments on commit 2dab85b

Please sign in to comment.