Skip to content

Commit

Permalink
(feat): updated the functionality of the imaging order (#12)
Browse files Browse the repository at this point in the history
* (feat) Add Age,  Gender and clinical diagnosis as part of  the patient info on the imaging panel

* (feat) updated translation json
  • Loading branch information
its-kios09 authored Dec 17, 2024
1 parent 6be2553 commit e345190
Show file tree
Hide file tree
Showing 28 changed files with 1,109 additions and 437 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import styles from './empty-state.scss';
import { EmptyDataIllustration } from '@openmrs/esm-patient-common-lib';

interface EmptyStateProps {
subTitle: string;
}

const EmptyState: React.FC<EmptyStateProps> = ({ subTitle }) => {
const { t } = useTranslation();

return (
<div className={styles.emptyStateContainer}>
<EmptyDataIllustration />
<p className={styles.subTitle}>{subTitle}</p>
</div>
);
};

export default EmptyState;
23 changes: 23 additions & 0 deletions packages/esm-imaging-orders-app/src/empty-state/empty-state.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
@use '@carbon/colors';
@use '@carbon/layout';
@use '@carbon/type';

.emptyStateContainer {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 300px;
background-color: colors.$white;
row-gap: layout.$spacing-02;

& form {
border: none;
}

.subTitle {
@include type.type-style('body-compact-01');
color: colors.$cool-gray-70;
font-weight: bold;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
@use '@carbon/layout';
@use '@carbon/type';
@use '@carbon/colors';

.widgetContainer {
padding: layout.$spacing-03;
}

.actionButton {
--cds-layout-size-height-context: var(--cds-layout-size-height-sm, 2rem);
--cds-layout-size-height: var(--cds-layout-size-height-context);
display: flex;
align-items: center;
justify-content: center;
text-align: justify;
padding: 0 layout.$spacing-04;
gap: layout.$spacing-05;
margin-right: layout.$spacing-05;
}

.textAreaInput {
@include type.type-style('body-compact-01');
color: colors.$cool-gray-70;
margin: layout.$spacing-03 0;
width: 100%;
}
.buttonSet {
position: absolute;
bottom: layout.$spacing-05;
left: 4%;
width: 80%;
display: flex;
gap: layout.$spacing-02;

& > button {
max-width: 40%;
width: 40%;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { mutate } from 'swr';
import styles from './review-imaging-form.scss';
import { useTranslation } from 'react-i18next';
import {
createAttachment,
showModal,
showNotification,
showSnackbar,
useLayoutType,
type UploadedFile,
} from '@openmrs/esm-framework';
import {
Stack,
Button,
ButtonSet,
InlineLoading,
Table,
TableBody,
TextArea,
TableRow,
TableCell,
Column,
} from '@carbon/react';
import classNames from 'classnames';
import { CardHeader, useAllowedFileExtensions } from '@openmrs/esm-patient-common-lib';
import { updateImagingProcedure } from '../../imaging-tabs/test-ordered/pick-imaging-order/add-to-worklist-dialog.resource';
import { DocumentAttachment } from '@carbon/react/icons';
import { Result } from '../../imaging-tabs/work-list/work-list.resource';

interface ReviewOrderDialogProps {
order: Result;
closeWorkspace: () => void;
}

const ImagingReviewForm: React.FC<ReviewOrderDialogProps> = ({ order, closeWorkspace }) => {
const { t } = useTranslation();
const isTablet = useLayoutType() === 'tablet';
const { allowedFileExtensions } = useAllowedFileExtensions();
const [notes, setNotes] = useState('');
const [isSubmitting, setIsSubmitting] = useState(false);

const patientUuid = order?.patient?.uuid;

const tableData = useMemo(
() => [
{ key: t('orderUrgency', 'Order Urgency'), value: order.urgency },
{
key: t('scheduleDate', 'Schedule date'),
value: order.scheduledDate || new Date().toLocaleDateString(),
},
{ key: t('bodySite', 'Body Site'), value: order.display },
{ key: t('laterality', 'Laterality'), value: order.laterality },
{ key: t('numberOfRepeats', 'Number of repeats'), value: order.numberOfRepeats },
{ key: t('frequency', 'Frequency'), value: order.frequency?.display },
],
[order, t],
);

const showAddAttachmentModal = useCallback(() => {
const close = showModal('capture-photo-modal', {
saveFile: (file: UploadedFile) => createAttachment(patientUuid, file),
allowedExtensions: allowedFileExtensions,
closeModal: () => close(),
multipleFiles: true,
collectDescription: true,
});
}, [allowedFileExtensions, patientUuid]);

const updateProcedures = async (event: React.FormEvent) => {
event.preventDefault();
setIsSubmitting(true);

try {
await updateImagingProcedure(order?.procedures[0]?.uuid, { outcome: 'SUCCESSFUL' });
showSnackbar({
isLowContrast: true,
title: t('createResponse', 'Create Review'),
kind: 'success',
subtitle: t('pickSuccessfully', 'You have successfully created a review'),
});
closeWorkspace();
mutate((key) => typeof key === 'string' && key.startsWith('/ws/rest/v1/procedure'));
mutate((key) => typeof key === 'string' && key.startsWith('/ws/rest/v1/order'));
} catch (error: any) {
showNotification({
title: t('errorPicking', 'Error Creating Review'),
kind: 'error',
critical: true,
description: error?.message,
});
} finally {
setIsSubmitting(false);
}
};

return (
<form aria-label="imaging form" className={styles.form} onSubmit={updateProcedures}>
<div className={styles.formContainer}>
<Stack gap={7}>
<div>
<Column className={styles.widgetContainer}>
<div className={styles.widgetCard}>
<CardHeader title={t('imagingReport', 'Imaging Report')}>
<Button
kind="tertiary"
className={styles.actionButton}
onClick={showAddAttachmentModal}
size="sm"
renderIcon={() => <DocumentAttachment size={18} />}>
{t('attachReport', 'Attach report')}
</Button>
</CardHeader>
</div>
</Column>
<div className={styles.widgetContainer}>
<div className={styles.orderDetails}>
<Table size="lg" useZebraStyles={false} aria-label="sample table">
<TableBody>
{tableData.map(
(row, index) =>
row.key &&
row.value && (
<TableRow key={index}>
<TableCell>{row.key}</TableCell>
<TableCell>{row.value}</TableCell>
</TableRow>
),
)}
</TableBody>
</Table>
<TextArea
className={styles.textAreaInput}
labelText={t('imagingReports', 'Imaging report')}
id="report"
name="report"
value={order?.procedures[0]?.procedureReport || ''}
readOnly
/>
<TextArea
className={styles.textAreaInput}
labelText={t('nextNotes', "Reviewer's notes")}
id="nextNotes"
name="nextNotes"
value={notes}
onChange={(e) => setNotes(e.target.value)}
/>
</div>
</div>
</div>
<ButtonSet className={styles.buttonSet}>
<Button size="lg" kind="secondary" onClick={closeWorkspace}>
{t('cancel', 'Cancel')}
</Button>
<Button disabled={isSubmitting} kind="primary" type="submit">
{isSubmitting ? (
<span style={{ display: 'flex', justifyItems: 'center' }}>
{t('submitting', 'Submitting...')} <InlineLoading status="active" iconDescription="Loading" />
</span>
) : (
t('approveClose', 'Approve & close')
)}
</Button>
</ButtonSet>
</Stack>
</div>
</form>
);
};

export default ImagingReviewForm;
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const createApiUrl = (
fulfillerStatus: string,
) => {
const responseFormat =
'custom:(uuid,orderNumber,patient:ref,concept:(uuid,display,conceptClass),action,careSetting,orderer:ref,urgency,instructions,orderReasonNonCoded,bodySite,laterality,commentToFulfiller,procedures,display,fulfillerStatus,dateStopped,scheduledDate,dateActivated,fulfillerComment)';
'custom:(uuid,orderNumber,patient:(uuid,display,person:(uuid,display,age,gender)),concept:(uuid,display,conceptClass),action,careSetting,orderer:ref,urgency,instructions,bodySite,laterality,commentToFulfiller,procedures,display,fulfillerStatus,dateStopped,scheduledDate,dateActivated,fulfillerComment)';
const orderTypeParam = `orderTypes=${OrderTypeUuid}&activatedOnOrAfterDate=${activatedOnOrAfterDate}&activatedOnOrBeforeDate=${activatedOnOrBeforeDate}&isStopped=false&fulfillerStatus=${fulfillerStatus}&v=${responseFormat}`;

return `${restBaseUrl}/order?${orderTypeParam}`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,19 @@ export const ApprovedOrders: React.FC = () => {
item.procedures?.some((procedure) => procedure.outcome === 'SUCCESSFUL'),
);

const approvedWithStatus = approved.map((order) => ({
...order,
isApproved: true,
}));

if (isLoading) {
return <DataTableSkeleton />;
}

return (
<div>
<GroupedOrdersTable
orders={approved}
orders={approvedWithStatus}
showStatus={false}
showStartButton={false}
showActions={false}
Expand Down
Loading

0 comments on commit e345190

Please sign in to comment.