Skip to content

Commit

Permalink
(feat)O3-4175 add ability to view and edit completed lab results (#2100)
Browse files Browse the repository at this point in the history
* Cleaned state management, launching form in edit mode

* Fixed obs update for none grouped obs

* Fixed form mutation, added lab results component for complete lab orders

* update lab result test

* updated translations

* optimized imports

* Diplay results in accordion  in a tabular form same as in orders

---------

Co-authored-by: makombe <[email protected]>
  • Loading branch information
Omoshlawi and makombe authored Dec 16, 2024
1 parent b7ef97b commit ee59431
Show file tree
Hide file tree
Showing 17 changed files with 277 additions and 84 deletions.
3 changes: 2 additions & 1 deletion packages/esm-patient-banner-app/src/config-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ export const configSchema = {
},
printScale: {
_type: Type.String,
_description: 'Set the scale for the printed content. A value between 0 and 1 shrinks the content, while a value greater than 1 enlarges it. The scale must be greater than 0.',
_description:
'Set the scale for the printed content. A value between 0 and 1 shrinks the content, while a value greater than 1 enlarges it. The scale must be greater than 0.',
_default: '1',
},
identifiersToDisplay: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@ const StartVisitOverflowMenuItem: React.FC<StartVisitOverflowMenuItemProps> = ({
const { currentVisit } = useVisit(patient?.id);
const isDeceased = Boolean(patient?.deceasedDateTime);

const handleLaunchModal = useCallback(() => launchPatientWorkspace('start-visit-workspace-form', {
openedFrom: "patient-chart-start-visit",
}), []);
const handleLaunchModal = useCallback(
() =>
launchPatientWorkspace('start-visit-workspace-form', {
openedFrom: 'patient-chart-start-visit',
}),
[],
);

return (
!currentVisit &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ const PatientInfo: React.FC<PatientInfoProps> = ({ patient }) => {
};

function launchStartVisitForm() {
launchPatientWorkspace('start-visit-workspace-form', {openedFrom: "patient-chart-start-visit"});
launchPatientWorkspace('start-visit-workspace-form', { openedFrom: 'patient-chart-start-visit' });
}

const VisitHeader: React.FC<{ patient: fhir.Patient }> = ({ patient }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ const StartVisitButton = ({ patientUuid }) => {
patientUuid,
workspaceName: 'start-visit-workspace-form',
additionalProps: {
openedFrom: 'patient-chart-start-visit'
}
openedFrom: 'patient-chart-start-visit',
},
});
}, [patientUuid]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const EditVisitDetailsActionItem: React.FC<EditVisitDetailsActionItemProps> = ({
launchPatientWorkspace('start-visit-workspace-form', {
workspaceTitle: t('editVisitDetails', 'Edit visit details'),
visitToEdit: visit,
openedFrom: 'patient-chart-edit-visit'
openedFrom: 'patient-chart-edit-visit',
});
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ const StartVisitDialog: React.FC<StartVisitDialogProps> = ({
launchPatientChartWithWorkspaceOpen({
patientUuid,
workspaceName: 'start-visit-workspace-form',
additionalProps: {openedFrom: 'patient-chart-start-visit'}
additionalProps: { openedFrom: 'patient-chart-start-visit' },
});
} else {
launchPatientWorkspace('start-visit-workspace-form', {openedFrom: 'patient-chart-start-visit'});
launchPatientWorkspace('start-visit-workspace-form', { openedFrom: 'patient-chart-start-visit' });
}

closeModal();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ const CurrentVisitSummary: React.FC<CurrentVisitSummaryProps> = ({ patientUuid }
<EmptyState
headerTitle={t('currentVisit', 'Current visit')}
displayText={t('noActiveVisitMessage', 'active visit')}
launchForm={() => launchPatientWorkspace('start-visit-workspace-form', {openedFrom: 'patient-chart-current-visit-summary'})}
launchForm={() =>
launchPatientWorkspace('start-visit-workspace-form', { openedFrom: 'patient-chart-current-visit-summary' })
}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const TestOrder: React.FC<TestOrderProps> = ({ testOrder }) => {
result: isLoadingResult ? (
<SkeletonText />
) : (
testResultObs?.groupMembers?.find((obs) => obs.concept.uuid === memberConcept.uuid)?.value.display ?? '--'
testResultObs?.groupMembers?.find((obs) => obs.concept.uuid === memberConcept.uuid)?.value ?? '--'
),
normalRange:
memberConcept.hiNormal && memberConcept.lowNormal
Expand All @@ -68,14 +68,14 @@ const TestOrder: React.FC<TestOrderProps> = ({ testOrder }) => {
{
id: concept.uuid,
testType: <div className={styles.testType}>{concept.display}</div>,
result: isLoadingResult ? <SkeletonText /> : testResultObs?.value.display ?? '--',
result: isLoadingResult ? <SkeletonText /> : testResultObs?.value ?? '--',
normalRange: concept.hiNormal && concept.lowNormal ? `${concept.lowNormal} - ${concept.hiNormal}` : 'N/A',
},
];
} else {
return [];
}
}, [concept, isLoadingResult, testResultObs?.groupMembers, testResultObs?.value?.display]);
}, [concept, isLoadingResult, testResultObs?.groupMembers, testResultObs?.value]);

return (
<div className={styles.testOrder}>
Expand Down
1 change: 1 addition & 0 deletions packages/esm-patient-orders-app/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export const ordersDashboardLink =
);

export const ordersDashboard = getSyncLifecycle(OrdersSummary, options);
export const labResult = getAsyncLifecycle(() => import('./lab-results/lab-result.component'), options);

// t('searchOrderables','Search orderables')
export const orderableConceptSearch = getAsyncLifecycle(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Tile, InlineLoading , InlineNotification } from '@carbon/react';
import { type Order } from '@openmrs/esm-patient-common-lib';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { useCompletedLabResults, useOrderConceptByUuid } from './lab-results.resource';
import styles from './lab-result.scss';
import TestOrder from '../components/test-order.component';

type LabResultsProps = {
order: Order;
};
const LabResults: React.FC<LabResultsProps> = ({ order }) => {
const { t } = useTranslation();
const { concept, isLoading: isLoadingConcepts, error: conceptError } = useOrderConceptByUuid(order.concept.uuid);
const { isLoading, error, completeLabResult, mutate } = useCompletedLabResults(order);

if (isLoading || isLoadingConcepts)
return (
<InlineLoading
status="active"
iconDescription="Loading"
description={t('loadinglabresults', 'Loading lab results') + '...'}
/>
);

if (error || conceptError)
return (
<InlineNotification
kind="error"
title={t('labResultError', 'Error loading lab results')}
subtitle={error?.message ?? conceptError?.message}
/>
);

return (
<Tile className={styles.resultsCiontainer}>
<OrderDetail order={order} />
</Tile>
);
};

export default LabResults;

const OrderDetail = ({ order }: { order: Order }) => {
return <TestOrder testOrder={order} />;
};
18 changes: 18 additions & 0 deletions packages/esm-patient-orders-app/src/lab-results/lab-result.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
@use '@carbon/layout';
@use '@carbon/type';

.resultsCiontainer {
margin-top: layout.$spacing-05;
}

.detailsContainer {
display: flex;
flex-direction: column;
gap: layout.$spacing-03;
}

.resultDetail {
display: flex;
flex-direction: row;
gap: layout.$spacing-05;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import { NumberInput, Select, SelectItem, TextInput } from '@carbon/react';
import { useTranslation } from 'react-i18next';
import { type Control, Controller, type FieldErrors } from 'react-hook-form';
import { type LabOrderConcept } from './lab-results.resource';
import { isCoded, isNumeric, isPanel, isText, type LabOrderConcept } from './lab-results.resource';
import styles from './lab-results-form.scss';

interface ResultFormFieldProps {
Expand All @@ -15,11 +15,6 @@ interface ResultFormFieldProps {
const ResultFormField: React.FC<ResultFormFieldProps> = ({ concept, control, defaultValue, errors }) => {
const { t } = useTranslation();

const isCoded = (concept: LabOrderConcept) => concept.datatype?.display === 'Coded';
const isNumeric = (concept: LabOrderConcept) => concept.datatype?.display === 'Numeric';
const isPanel = (concept: LabOrderConcept) => concept.setMembers?.length > 0;
const isText = (concept: LabOrderConcept) => concept.datatype?.display === 'Text';

const printValueRange = (concept: LabOrderConcept) => {
if (concept?.datatype?.display === 'Numeric') {
const maxVal = Math.max(concept?.hiAbsolute, concept?.hiCritical, concept?.hiNormal);
Expand Down
Loading

0 comments on commit ee59431

Please sign in to comment.