From 652374cb95497987155ba9b709755c129fe47e42 Mon Sep 17 00:00:00 2001 From: felix Date: Wed, 31 Jul 2024 15:58:03 +0300 Subject: [PATCH 1/8] fix :grouped orders by patient --- .../listOrderDetails.component.tsx | 135 +++++++++++++++ .../orders-table/listOrderDetails.scss | 55 +++++++ .../orders-table/orderDetail.component.tsx | 17 ++ src/components/orders-table/orderDetail.scss | 15 ++ .../orders-data-table.component.tsx | 154 +++++++----------- ...completed-lab-requests-table.extension.tsx | 9 +- ...-progress-lab-requests-table.extension.tsx | 6 + .../tests-ordered-table.extension.tsx | 10 +- src/laboratory-resource.ts | 23 ++- src/types.ts | 26 +++ 10 files changed, 354 insertions(+), 96 deletions(-) create mode 100644 src/components/orders-table/listOrderDetails.component.tsx create mode 100644 src/components/orders-table/listOrderDetails.scss create mode 100644 src/components/orders-table/orderDetail.component.tsx create mode 100644 src/components/orders-table/orderDetail.scss diff --git a/src/components/orders-table/listOrderDetails.component.tsx b/src/components/orders-table/listOrderDetails.component.tsx new file mode 100644 index 00000000..26d8b310 --- /dev/null +++ b/src/components/orders-table/listOrderDetails.component.tsx @@ -0,0 +1,135 @@ +import React, { useMemo } from "react"; +import styles from "./listOrderDetails.scss"; + +import { useTranslation } from "react-i18next"; +import { formatDate, parseDate, showModal } from "@openmrs/esm-framework"; +import { Button, Tile } from "@carbon/react"; +import { OrderDetail } from "./orderDetail.component"; +import { ListOrdersDetailsProps } from "../../types"; +import { launchOverlay } from "../overlay/store"; +import ResultForm from "../../results/result-form.component"; + +// can render orders of a patient +const ListOrderDetails: React.FC = (props) => { + const orders = props.groupedOrders?.orders; + const { t } = useTranslation(); + const orderrows = useMemo(() => { + return orders + ?.filter((item) => item.action === "NEW") + .map((entry) => ({ + ...entry, + id: entry.uuid, + orderNumber: entry.orderNumber, + procedure: entry.display, + status: entry.fulfillerStatus ? entry.fulfillerStatus : "--", + urgency: entry.urgency, + orderer: entry.orderer?.display, + instructions: entry.instructions ? entry.instructions : "--", + date: ( + + {formatDate(parseDate(entry?.dateActivated))} + + ), + })); + }, [orders]); + return ( +
+ {orderrows.map((row) => ( + +
+ {props.actions + .sort((a, b) => { + // Replace 'property' with the actual property you want to sort by + if (a.displayPosition < b.displayPosition) return -1; + if (a.displayPosition > b.displayPosition) return 1; + return 0; + }) + .map((action) => { + if (action.actionName === "pickupLabRequest") { + return ( + + ); + } + if (action.actionName === "labResultsForm") { + return ( + + ); + } + if (action.actionName === "rejectLabRequest") { + return ( + + ); + } + })} +
+
+ + + + + + + + +
+
+ ))} +
+ ); +}; + +export default ListOrderDetails; diff --git a/src/components/orders-table/listOrderDetails.scss b/src/components/orders-table/listOrderDetails.scss new file mode 100644 index 00000000..d7f1feed --- /dev/null +++ b/src/components/orders-table/listOrderDetails.scss @@ -0,0 +1,55 @@ +@use '@carbon/layout'; +@use '@carbon/colors'; +@use '@openmrs/esm-styleguide/src/vars' as *; + +.orderTile { + width: 100%; + margin: 2px 0 8px; + padding: 0 8px 0 8px; + background-color: colors.$white-0; + border-left: 4px solid var(--brand-03); + color: $text-02; + margin-bottom: 1rem !important; + &:hover{ + background-color: colors.$white-hover; + } +} + +.ordersContainer { + display: flex; + flex-direction: column; + max-width: 100%; + margin-bottom: 1rem; + + &:global(.cds--tile) { + min-height: 3rem !important; + padding-left: 10px !important; + } +} + +.ordersContainer > :global(.cds--tile) { + min-height: 3rem !important; + padding-left: 10px !important; + margin: auto; +} + +.orderPropertyDisplay { + font-size: 15px !important; + } + + .bodyLong01 { + font-size: 13px !important; + } + + .displayValue { + color: #525252; + font-weight: bold; + width: layout.$spacing-05; + height: layout.$spacing-05; + } + + .actionBtns { + float: right; + margin-left: layout.$spacing-05; + margin-top: layout.$spacing-07; + } \ No newline at end of file diff --git a/src/components/orders-table/orderDetail.component.tsx b/src/components/orders-table/orderDetail.component.tsx new file mode 100644 index 00000000..25b06ae7 --- /dev/null +++ b/src/components/orders-table/orderDetail.component.tsx @@ -0,0 +1,17 @@ +import React from "react"; +import styles from "./orderDetail.scss"; + +export const OrderDetail: React.FC<{ label: string; value: string | any }> = ({ + label, + value, +}) => { + return ( +
+

+ {label} + {" : "} + {value} +

+
+ ); +}; diff --git a/src/components/orders-table/orderDetail.scss b/src/components/orders-table/orderDetail.scss new file mode 100644 index 00000000..592dc155 --- /dev/null +++ b/src/components/orders-table/orderDetail.scss @@ -0,0 +1,15 @@ +@use '@carbon/layout'; +@use '@carbon/colors'; +@use '@openmrs/esm-styleguide/src/vars' as *; + + .bodyLong01 { + font-size: 13px !important; + } + + .displayValue { + color: #525252; + font-weight: bold; + width: layout.$spacing-05; + height: layout.$spacing-05; + } + \ No newline at end of file diff --git a/src/components/orders-table/orders-data-table.component.tsx b/src/components/orders-table/orders-data-table.component.tsx index 5864b550..e9434fbe 100644 --- a/src/components/orders-table/orders-data-table.component.tsx +++ b/src/components/orders-table/orders-data-table.component.tsx @@ -10,6 +10,9 @@ import { TableContainer, TableHead, TableHeader, + TableExpandHeader, + TableExpandRow, + TableExpandedRow, TableRow, Tile, Dropdown, @@ -20,41 +23,22 @@ import { DatePicker, DatePickerInput, } from "@carbon/react"; -import { OverflowMenuVertical } from "@carbon/react/icons"; import { ConfigurableLink, - CustomOverflowMenu, - ExtensionSlot, - formatDate, - parseDate, useConfig, - useDebounce, usePagination, } from "@openmrs/esm-framework"; import styles from "./orders-data-table.scss"; -import { getStatusColor } from "../../utils"; -import { FulfillerStatus } from "../../types"; -import { useLabOrders } from "../../laboratory-resource"; +import { FulfillerStatus, OrdersDataTableProps } from "../../types"; +import { + useLabOrders, + useSearchGroupedResults, +} from "../../laboratory-resource"; import dayjs from "dayjs"; import { isoDateTimeString } from "../../constants"; -import useSearchResults from "./orders-data-table.resource"; -interface OrdersDataTableProps { - useFilter?: boolean; - actionsSlotName?: string; - excludeColumns?: string[]; - fulfillerStatus?: FulfillerStatus; - excludeCanceledAndDiscontinuedOrders?: boolean; - useActivatedOnOrAfterDateFilter?: boolean; -} +import ListOrderDetails from "./listOrderDetails.component"; -const OrdersDataTable: React.FC = ({ - useFilter = false, - actionsSlotName, - excludeColumns = [], - fulfillerStatus, - excludeCanceledAndDiscontinuedOrders = true, - useActivatedOnOrAfterDateFilter = true, -}) => { +const OrdersDataTable: React.FC = (props) => { const { t } = useTranslation(); const { targetPatientDashboard: { redirectToResultsViewer, redirectToOrders }, @@ -67,29 +51,34 @@ const OrdersDataTable: React.FC = ({ const [searchString, setSearchString] = useState(""); const { labOrders, isLoading } = useLabOrders( - useFilter ? filter : fulfillerStatus, - excludeCanceledAndDiscontinuedOrders, + props.useFilter ? filter : props.fulfillerStatus, + props.excludeCanceledAndDiscontinuedOrders, activatedOnOrAfterDate ); - const flattenedLabOrders = useMemo(() => { - return labOrders.map((eachObject) => { - return { - ...eachObject, - dateActivated: formatDate(parseDate(eachObject.dateActivated)), - patient: eachObject.patient?.display.split("-")[1], - patientUuid: eachObject.patient?.uuid, - status: eachObject.fulfillerStatus ?? "--", - orderer: eachObject.orderer?.display.split("-")[1], - }; - }); - }, [labOrders]); - - const debouncedSearchString = useDebounce(searchString); + function groupOrdersById(orders) { + if (orders && orders.length > 0) { + const groupedOrders = orders.reduce((acc, item) => { + if (!acc[item.patient.uuid]) { + acc[item.patient.uuid] = []; + } + acc[item.patient.uuid].push(item); + return acc; + }, {}); - const searchResults = useSearchResults( - flattenedLabOrders, - debouncedSearchString + // Convert the result to an array of objects with patientId and orders + return Object.keys(groupedOrders).map((patientId) => ({ + patientId: patientId, + orders: groupedOrders[patientId], + })); + } else { + return []; + } + } + const groupedOrdersByPatient = groupOrdersById(labOrders); + const searchResults = useSearchGroupedResults( + groupedOrdersByPatient, + searchString ); const orderStatuses = [ @@ -129,19 +118,10 @@ const OrdersDataTable: React.FC = ({ const columns = useMemo(() => { return [ - { key: "date", header: t("date", "Date") }, - { - key: "orderNumber", - header: t("orderNumber", "Order Number"), - }, - { key: "patient", header: t("patient", "Patient") }, - { key: "test", header: t("test", "Test") }, - { key: "status", header: t("status", "Status") }, - { key: "orderedBy", header: t("orderedBy", "Ordered By") }, - { key: "urgency", header: t("urgency", "Urgency") }, - { key: "actions", header: t("actions", "Actions") }, - ].filter((column) => !excludeColumns.includes(column.key)); - }, [excludeColumns, t]); + { id: 0, header: t("patient", "Patient"), key: "patientName" }, + { id: 1, header: t("totalorders", "Total Orders"), key: "totalOrders" }, + ]; + }, [props.excludeColumns, t]); const pageSizes = [10, 20, 30, 40, 50]; const [currentPageSize, setPageSize] = useState(10); @@ -160,49 +140,28 @@ const OrdersDataTable: React.FC = ({ ); const tableRows = useMemo(() => { - return paginatedLabOrders.map((order, index) => ({ - id: order.uuid, - date: ( - {order.dateActivated} - ), + return paginatedLabOrders.map((patient, index) => ({ + id: patient.patientId, + patientName: patient.orders[0].patient?.display?.split("-")[1], + orders: patient.orders, + totalOrders: patient.orders?.length, patient: ( - {order.patient} + {patient.orders[0].patient?.display?.split("-")[1]} ), - orderNumber: order.orderNumber, - test: order.concept?.display, - status: ( - - {order.fulfillerStatus} - - ), - orderedBy: order.orderer, - urgency: order.urgency, - actions: ( - }> - - - ), })); }, [ paginatedLabOrders, redirectToResultsViewer, redirectToOrders, - actionsSlotName, + props.actionsSlotName, ]); if (isLoading) { @@ -213,7 +172,7 @@ const OrdersDataTable: React.FC = ({ rows={tableRows} headers={columns} useZebraStyles - overflowMenuOnHover={true} + overflowMenuOnHover={false} > {({ rows, headers, getHeaderProps, getTableProps, getRowProps }) => ( @@ -221,7 +180,7 @@ const OrdersDataTable: React.FC = ({ { - {useFilter && ( + {props.useFilter && ( = ({ itemToString={(item) => item?.display} /> )} - {useActivatedOnOrAfterDateFilter && ( + {props.useActivatedOnOrAfterDateFilter && ( <>

{t( @@ -281,6 +240,7 @@ const OrdersDataTable: React.FC = ({ + {headers.map((header) => ( {header.header?.content ?? header.header} @@ -292,13 +252,21 @@ const OrdersDataTable: React.FC = ({ {rows.map((row, index) => { return ( - + {row.cells.map((cell) => ( {cell.value?.content ?? cell.value} ))} - + + + item.patientId === row.id + )} + /> + ); })} diff --git a/src/lab-tabs/data-table-extensions/completed-lab-requests-table.extension.tsx b/src/lab-tabs/data-table-extensions/completed-lab-requests-table.extension.tsx index 3ca20cd9..e6dc2590 100644 --- a/src/lab-tabs/data-table-extensions/completed-lab-requests-table.extension.tsx +++ b/src/lab-tabs/data-table-extensions/completed-lab-requests-table.extension.tsx @@ -5,8 +5,15 @@ const CompletedLabRequestsTable: React.FC = () => { return ( ); }; diff --git a/src/lab-tabs/data-table-extensions/in-progress-lab-requests-table.extension.tsx b/src/lab-tabs/data-table-extensions/in-progress-lab-requests-table.extension.tsx index a73993a5..c514fa89 100644 --- a/src/lab-tabs/data-table-extensions/in-progress-lab-requests-table.extension.tsx +++ b/src/lab-tabs/data-table-extensions/in-progress-lab-requests-table.extension.tsx @@ -4,8 +4,14 @@ import OrdersDataTable from "../../components/orders-table/orders-data-table.com const InProgressLabRequestsTable: React.FC = () => { return ( ); }; diff --git a/src/lab-tabs/data-table-extensions/tests-ordered-table.extension.tsx b/src/lab-tabs/data-table-extensions/tests-ordered-table.extension.tsx index 42411d5f..204bce7d 100644 --- a/src/lab-tabs/data-table-extensions/tests-ordered-table.extension.tsx +++ b/src/lab-tabs/data-table-extensions/tests-ordered-table.extension.tsx @@ -3,7 +3,15 @@ import OrdersDataTable from "../../components/orders-table/orders-data-table.com const TestsOrderedTable: React.FC = () => { return ( - + ); }; diff --git a/src/laboratory-resource.ts b/src/laboratory-resource.ts index e13bfd87..1df9ab37 100644 --- a/src/laboratory-resource.ts +++ b/src/laboratory-resource.ts @@ -1,5 +1,5 @@ import { openmrsFetch, restBaseUrl, useConfig } from "@openmrs/esm-framework"; -import { FulfillerStatus } from "./types"; +import { FulfillerStatus, GroupedOrders } from "./types"; import { Order } from "@openmrs/esm-patient-common-lib"; import useSWR from "swr"; import { useMemo } from "react"; @@ -49,7 +49,28 @@ export function useLabOrders( isValidating, }; } +export function useSearchGroupedResults( + data: Array, + searchString: string +) { + const searchResults = useMemo(() => { + if (searchString && searchString.trim() !== "") { + // Normalize the search string to lowercase + const lowerSearchString = searchString.toLowerCase(); + return data.filter((orderGroup) => + orderGroup.orders.some( + (order) => + order.orderNumber.toLowerCase().includes(lowerSearchString) || + order.patient.display.toLowerCase().includes(lowerSearchString) + ) + ); + } + + return data; + }, [searchString, data]); + return searchResults; +} export function setFulfillerStatus( orderId: string, status: FulfillerStatus, diff --git a/src/types.ts b/src/types.ts index 9b56c27b..3d955841 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,3 +1,5 @@ +import { Order } from "@openmrs/esm-patient-common-lib"; + export type FulfillerStatus = | "EXCEPTION" | "RECEIVED" @@ -5,3 +7,27 @@ export type FulfillerStatus = | "IN_PROGRESS" | "ON_HOLD" | "DECLINED"; + +export interface GroupedOrders { + patientId: string; + orders: Array; +} + +export interface ListOrdersDetailsProps { + groupedOrders: GroupedOrders; + actions: Array; +} + +export interface OrderAction { + actionName: string; + displayPosition: 0 | number; +} +export interface OrdersDataTableProps { + useFilter?: boolean; + actionsSlotName?: string; + excludeColumns?: string[]; + fulfillerStatus?: FulfillerStatus; + excludeCanceledAndDiscontinuedOrders?: boolean; + useActivatedOnOrAfterDateFilter?: boolean; + actions: Array; +} From 812278e06d2a87ff467e80fd638e017e8f9c7196 Mon Sep 17 00:00:00 2001 From: felix Date: Wed, 31 Jul 2024 16:00:43 +0300 Subject: [PATCH 2/8] translations updated --- translations/am.json | 7 ++++--- translations/en.json | 7 ++++--- translations/es.json | 7 ++++--- translations/fr.json | 7 ++++--- translations/he.json | 7 ++++--- translations/km.json | 7 ++++--- 6 files changed, 24 insertions(+), 18 deletions(-) diff --git a/translations/am.json b/translations/am.json index cda341e7..74aff9ef 100644 --- a/translations/am.json +++ b/translations/am.json @@ -1,5 +1,4 @@ { - "actions": "Actions", "all": "All", "allFieldsRequired": "All fields are required", "cancel": "Cancel", @@ -19,6 +18,7 @@ "generateSuccessfully": "You have successfully updated test results", "inProgress": "In progress", "inProgressStatus": "IN_PROGRESS", + "instructions": "Instructions", "laboratory": "Laboratory", "labResultsForm": "Lab Results Form", "loading": "Loading", @@ -29,7 +29,7 @@ "onHoldStatus": "ON_HOLD", "onOrAfterDateFilter": "Filter orders on or after : ", "option": "Choose an Option", - "orderedBy": "Ordered By", + "orderer": "orderer", "orderNumber": "Order Number", "orderPickedSuccessfully": "You have successfully picked an order", "orders": "Orders", @@ -39,6 +39,7 @@ "pickRequestConfirmationText": "Continuing will update the request status to \"In Progress\" and advance it to the next stage. Are you sure you want to proceed?", "pickupLabRequest": "Pickup Lab Request", "previousPage": "Previous page", + "procedure": "procedure", "receivedStatus": "RECEIVED", "reject": "Reject", "rejectLabRequest": "Reject Lab Request", @@ -49,10 +50,10 @@ "searchThisList": "Search this list", "status": "Status", "tabletOverlay": "Tablet overlay", - "test": "Test", "testOrderCompletedSuccessfully": "You have successfully completed the test order", "testsOrdered": "Tests ordered", "testType": "Test Type", + "totalorders": "Total Orders", "updateEncounter": "Update lab results", "urgency": "Urgency", "view": "View ", diff --git a/translations/en.json b/translations/en.json index 480a6302..1f223119 100644 --- a/translations/en.json +++ b/translations/en.json @@ -1,5 +1,4 @@ { - "actions": "Actions", "all": "All", "allFieldsRequired": "All fields are required", "cancel": "Cancel", @@ -19,6 +18,7 @@ "generateSuccessfully": "You have successfully updated test results", "inProgress": "In progress", "inProgressStatus": "IN_PROGRESS", + "instructions": "Instructions", "laboratory": "Laboratory", "labResultsForm": "Lab Results Form", "loading": "Loading", @@ -29,7 +29,7 @@ "onHoldStatus": "ON_HOLD", "onOrAfterDateFilter": "Filter orders on or after : ", "option": "Choose an Option", - "orderedBy": "Ordered By", + "orderer": "orderer", "orderNumber": "Order Number", "orderPickedSuccessfully": "You have successfully picked an order", "orders": "Orders", @@ -39,6 +39,7 @@ "pickRequestConfirmationText": "Continuing will update the request status to \"In Progress\" and advance it to the next stage. Are you sure you want to proceed?", "pickupLabRequest": "Pickup Lab Request", "previousPage": "Previous page", + "procedure": "procedure", "receivedStatus": "RECEIVED", "reject": "Reject", "rejectLabRequest": "Reject Lab Request", @@ -49,10 +50,10 @@ "searchThisList": "Search this list", "status": "Status", "tabletOverlay": "Tablet overlay", - "test": "Test", "testOrderCompletedSuccessfully": "You have successfully completed the test order", "testsOrdered": "Tests ordered", "testType": "Test Type", + "totalorders": "Total Orders", "updateEncounter": "Update lab results", "urgency": "Urgency", "view": "View ", diff --git a/translations/es.json b/translations/es.json index c62f612d..12fdc074 100644 --- a/translations/es.json +++ b/translations/es.json @@ -1,5 +1,4 @@ { - "actions": "Actions", "all": "All", "allFieldsRequired": "All fields are required", "cancel": "Cancel", @@ -19,6 +18,7 @@ "generateSuccessfully": "You have successfully updated test results", "inProgress": "In progress", "inProgressStatus": "IN_PROGRESS", + "instructions": "Instructions", "laboratory": "Laboratory", "labResultsForm": "Lab Results Form", "loading": "Cargando", @@ -29,7 +29,7 @@ "onHoldStatus": "ON_HOLD", "onOrAfterDateFilter": "Filter orders on or after : ", "option": "Choose an Option", - "orderedBy": "Ordered By", + "orderer": "orderer", "orderNumber": "Order Number", "orderPickedSuccessfully": "You have successfully picked an order", "orders": "Orders", @@ -39,6 +39,7 @@ "pickRequestConfirmationText": "Continuing will update the request status to \"In Progress\" and advance it to the next stage. Are you sure you want to proceed?", "pickupLabRequest": "Pickup Lab Request", "previousPage": "Previous page", + "procedure": "procedure", "receivedStatus": "RECEIVED", "reject": "Reject", "rejectLabRequest": "Reject Lab Request", @@ -49,10 +50,10 @@ "searchThisList": "Search this list", "status": "Status", "tabletOverlay": "Tablet overlay", - "test": "Test", "testOrderCompletedSuccessfully": "You have successfully completed the test order", "testsOrdered": "Tests ordered", "testType": "Test Type", + "totalorders": "Total Orders", "updateEncounter": "Update lab results", "urgency": "Urgency", "view": "View ", diff --git a/translations/fr.json b/translations/fr.json index b1d48cc3..2a83894e 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -1,5 +1,4 @@ { - "actions": "Actions", "all": "All", "allFieldsRequired": "All fields are required", "cancel": "Cancel", @@ -19,6 +18,7 @@ "generateSuccessfully": "You have successfully updated test results", "inProgress": "In progress", "inProgressStatus": "IN_PROGRESS", + "instructions": "Instructions", "laboratory": "Laboratory", "labResultsForm": "Lab Results Form", "loading": "Chargement", @@ -29,7 +29,7 @@ "onHoldStatus": "ON_HOLD", "onOrAfterDateFilter": "Filter orders on or after : ", "option": "Choose an Option", - "orderedBy": "Ordered By", + "orderer": "orderer", "orderNumber": "Order Number", "orderPickedSuccessfully": "You have successfully picked an order", "orders": "Orders", @@ -39,6 +39,7 @@ "pickRequestConfirmationText": "Continuing will update the request status to \"In Progress\" and advance it to the next stage. Are you sure you want to proceed?", "pickupLabRequest": "Pickup Lab Request", "previousPage": "Previous page", + "procedure": "procedure", "receivedStatus": "RECEIVED", "reject": "Reject", "rejectLabRequest": "Reject Lab Request", @@ -49,10 +50,10 @@ "searchThisList": "Search this list", "status": "Status", "tabletOverlay": "Tablet overlay", - "test": "Test", "testOrderCompletedSuccessfully": "You have successfully completed the test order", "testsOrdered": "Tests ordered", "testType": "Test Type", + "totalorders": "Total Orders", "updateEncounter": "Update lab results", "urgency": "Urgency", "view": "View ", diff --git a/translations/he.json b/translations/he.json index cda341e7..74aff9ef 100644 --- a/translations/he.json +++ b/translations/he.json @@ -1,5 +1,4 @@ { - "actions": "Actions", "all": "All", "allFieldsRequired": "All fields are required", "cancel": "Cancel", @@ -19,6 +18,7 @@ "generateSuccessfully": "You have successfully updated test results", "inProgress": "In progress", "inProgressStatus": "IN_PROGRESS", + "instructions": "Instructions", "laboratory": "Laboratory", "labResultsForm": "Lab Results Form", "loading": "Loading", @@ -29,7 +29,7 @@ "onHoldStatus": "ON_HOLD", "onOrAfterDateFilter": "Filter orders on or after : ", "option": "Choose an Option", - "orderedBy": "Ordered By", + "orderer": "orderer", "orderNumber": "Order Number", "orderPickedSuccessfully": "You have successfully picked an order", "orders": "Orders", @@ -39,6 +39,7 @@ "pickRequestConfirmationText": "Continuing will update the request status to \"In Progress\" and advance it to the next stage. Are you sure you want to proceed?", "pickupLabRequest": "Pickup Lab Request", "previousPage": "Previous page", + "procedure": "procedure", "receivedStatus": "RECEIVED", "reject": "Reject", "rejectLabRequest": "Reject Lab Request", @@ -49,10 +50,10 @@ "searchThisList": "Search this list", "status": "Status", "tabletOverlay": "Tablet overlay", - "test": "Test", "testOrderCompletedSuccessfully": "You have successfully completed the test order", "testsOrdered": "Tests ordered", "testType": "Test Type", + "totalorders": "Total Orders", "updateEncounter": "Update lab results", "urgency": "Urgency", "view": "View ", diff --git a/translations/km.json b/translations/km.json index cda341e7..74aff9ef 100644 --- a/translations/km.json +++ b/translations/km.json @@ -1,5 +1,4 @@ { - "actions": "Actions", "all": "All", "allFieldsRequired": "All fields are required", "cancel": "Cancel", @@ -19,6 +18,7 @@ "generateSuccessfully": "You have successfully updated test results", "inProgress": "In progress", "inProgressStatus": "IN_PROGRESS", + "instructions": "Instructions", "laboratory": "Laboratory", "labResultsForm": "Lab Results Form", "loading": "Loading", @@ -29,7 +29,7 @@ "onHoldStatus": "ON_HOLD", "onOrAfterDateFilter": "Filter orders on or after : ", "option": "Choose an Option", - "orderedBy": "Ordered By", + "orderer": "orderer", "orderNumber": "Order Number", "orderPickedSuccessfully": "You have successfully picked an order", "orders": "Orders", @@ -39,6 +39,7 @@ "pickRequestConfirmationText": "Continuing will update the request status to \"In Progress\" and advance it to the next stage. Are you sure you want to proceed?", "pickupLabRequest": "Pickup Lab Request", "previousPage": "Previous page", + "procedure": "procedure", "receivedStatus": "RECEIVED", "reject": "Reject", "rejectLabRequest": "Reject Lab Request", @@ -49,10 +50,10 @@ "searchThisList": "Search this list", "status": "Status", "tabletOverlay": "Tablet overlay", - "test": "Test", "testOrderCompletedSuccessfully": "You have successfully completed the test order", "testsOrdered": "Tests ordered", "testType": "Test Type", + "totalorders": "Total Orders", "updateEncounter": "Update lab results", "urgency": "Urgency", "view": "View ", From 823ea05fa9cdd0887ecc4aa124a9b4e6532d3aba Mon Sep 17 00:00:00 2001 From: felix Date: Wed, 31 Jul 2024 18:36:37 +0300 Subject: [PATCH 3/8] fixed ui issues --- .../listOrderDetails.component.tsx | 217 +++++++++--------- .../orders-data-table.component.tsx | 44 ++-- .../reject-lab-request-modal.component.tsx | 2 +- 3 files changed, 125 insertions(+), 138 deletions(-) diff --git a/src/components/orders-table/listOrderDetails.component.tsx b/src/components/orders-table/listOrderDetails.component.tsx index 26d8b310..926b1791 100644 --- a/src/components/orders-table/listOrderDetails.component.tsx +++ b/src/components/orders-table/listOrderDetails.component.tsx @@ -1,8 +1,8 @@ -import React, { useMemo } from "react"; +import React from "react"; import styles from "./listOrderDetails.scss"; import { useTranslation } from "react-i18next"; -import { formatDate, parseDate, showModal } from "@openmrs/esm-framework"; +import { showModal } from "@openmrs/esm-framework"; import { Button, Tile } from "@carbon/react"; import { OrderDetail } from "./orderDetail.component"; import { ListOrdersDetailsProps } from "../../types"; @@ -12,122 +12,111 @@ import ResultForm from "../../results/result-form.component"; // can render orders of a patient const ListOrderDetails: React.FC = (props) => { const orders = props.groupedOrders?.orders; + const patientId = props.groupedOrders?.patientId; + const { t } = useTranslation(); - const orderrows = useMemo(() => { - return orders - ?.filter((item) => item.action === "NEW") - .map((entry) => ({ - ...entry, - id: entry.uuid, - orderNumber: entry.orderNumber, - procedure: entry.display, - status: entry.fulfillerStatus ? entry.fulfillerStatus : "--", - urgency: entry.urgency, - orderer: entry.orderer?.display, - instructions: entry.instructions ? entry.instructions : "--", - date: ( - - {formatDate(parseDate(entry?.dateActivated))} - - ), - })); - }, [orders]); return (
- {orderrows.map((row) => ( - -
- {props.actions - .sort((a, b) => { - // Replace 'property' with the actual property you want to sort by - if (a.displayPosition < b.displayPosition) return -1; - if (a.displayPosition > b.displayPosition) return 1; - return 0; - }) - .map((action) => { - if (action.actionName === "pickupLabRequest") { - return ( - - ); - } - if (action.actionName === "labResultsForm") { - return ( - - ); - } - if (action.actionName === "rejectLabRequest") { - return ( - - ); - } - })} -
-
- - - + {orders.length > 0 && + orders.map((row) => ( + +
+
+ {props.actions + .sort((a, b) => { + // Replace 'property' with the actual property you want to sort by + if (a.displayPosition < b.displayPosition) return -1; + if (a.displayPosition > b.displayPosition) return 1; + return 0; + }) + .map((action) => { + if (action.actionName === "pickupLabRequest") { + return ( + + ); + } + if (action.actionName === "labResultsForm") { + return ( + + ); + } + if (action.actionName === "rejectLabRequest") { + return ( + + ); + } + })} +
+
+ + + - - - - -
- - ))} + + + + +
+
+
+ ))}
); }; diff --git a/src/components/orders-table/orders-data-table.component.tsx b/src/components/orders-table/orders-data-table.component.tsx index e9434fbe..fed7d3d2 100644 --- a/src/components/orders-table/orders-data-table.component.tsx +++ b/src/components/orders-table/orders-data-table.component.tsx @@ -24,7 +24,8 @@ import { DatePickerInput, } from "@carbon/react"; import { - ConfigurableLink, + formatDate, + parseDate, useConfig, usePagination, } from "@openmrs/esm-framework"; @@ -56,13 +57,26 @@ const OrdersDataTable: React.FC = (props) => { activatedOnOrAfterDate ); + const flattenedLabOrders = useMemo(() => { + return labOrders.map((eachObject) => { + return { + ...eachObject, + dateActivated: formatDate(parseDate(eachObject.dateActivated)), + patientName: eachObject.patient?.display.split("-")[1], + patientUuid: eachObject.patient?.uuid, + status: eachObject.fulfillerStatus ?? "--", + orderer: eachObject.orderer?.display.split("-")[1], + }; + }); + }, [labOrders]); + function groupOrdersById(orders) { if (orders && orders.length > 0) { const groupedOrders = orders.reduce((acc, item) => { - if (!acc[item.patient.uuid]) { - acc[item.patient.uuid] = []; + if (!acc[item.patientUuid]) { + acc[item.patientUuid] = []; } - acc[item.patient.uuid].push(item); + acc[item.patientUuid].push(item); return acc; }, {}); @@ -75,7 +89,7 @@ const OrdersDataTable: React.FC = (props) => { return []; } } - const groupedOrdersByPatient = groupOrdersById(labOrders); + const groupedOrdersByPatient = groupOrdersById(flattenedLabOrders); const searchResults = useSearchGroupedResults( groupedOrdersByPatient, searchString @@ -145,17 +159,6 @@ const OrdersDataTable: React.FC = (props) => { patientName: patient.orders[0].patient?.display?.split("-")[1], orders: patient.orders, totalOrders: patient.orders?.length, - patient: ( - - {patient.orders[0].patient?.display?.split("-")[1]} - - ), })); }, [ paginatedLabOrders, @@ -168,12 +171,7 @@ const OrdersDataTable: React.FC = (props) => { return ; } return ( - + {({ rows, headers, getHeaderProps, getTableProps, getRowProps }) => ( @@ -292,7 +290,7 @@ const OrdersDataTable: React.FC = (props) => { page={currentPage} pageSize={currentPageSize} pageSizes={pageSizes} - totalItems={labOrders?.length} + totalItems={groupedOrdersByPatient?.length} className={styles.pagination} onChange={({ pageSize, page }) => { if (pageSize !== currentPageSize) { diff --git a/src/lab-tabs/modals/reject-lab-request-modal.component.tsx b/src/lab-tabs/modals/reject-lab-request-modal.component.tsx index d53db88d..cdfc2e63 100644 --- a/src/lab-tabs/modals/reject-lab-request-modal.component.tsx +++ b/src/lab-tabs/modals/reject-lab-request-modal.component.tsx @@ -75,7 +75,7 @@ const RejectLabRequestModal: React.FC = ({

- {`${t("testType", "Test Type")}: ${order.concept.display}`} + {`${t("testType", "Test Type")}: ${order.concept?.display}`}


From 1a221a4667a00d639ca11870119bdbcf00235071 Mon Sep 17 00:00:00 2001 From: felix Date: Wed, 31 Jul 2024 18:57:56 +0300 Subject: [PATCH 4/8] handle undefined error --- src/components/orders-table/listOrderDetails.component.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/orders-table/listOrderDetails.component.tsx b/src/components/orders-table/listOrderDetails.component.tsx index 926b1791..c2e651a8 100644 --- a/src/components/orders-table/listOrderDetails.component.tsx +++ b/src/components/orders-table/listOrderDetails.component.tsx @@ -13,11 +13,10 @@ import ResultForm from "../../results/result-form.component"; const ListOrderDetails: React.FC = (props) => { const orders = props.groupedOrders?.orders; const patientId = props.groupedOrders?.patientId; - const { t } = useTranslation(); return (
- {orders.length > 0 && + {orders && orders.map((row) => (
From a1175bfae52593c32be8645ff7ea86c2bfc0ff53 Mon Sep 17 00:00:00 2001 From: felix Date: Wed, 31 Jul 2024 21:05:13 +0300 Subject: [PATCH 5/8] removed comments --- .../completed-lab-requests-table.extension.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/lab-tabs/data-table-extensions/completed-lab-requests-table.extension.tsx b/src/lab-tabs/data-table-extensions/completed-lab-requests-table.extension.tsx index e6dc2590..dbdd1c6d 100644 --- a/src/lab-tabs/data-table-extensions/completed-lab-requests-table.extension.tsx +++ b/src/lab-tabs/data-table-extensions/completed-lab-requests-table.extension.tsx @@ -8,12 +8,7 @@ const CompletedLabRequestsTable: React.FC = () => { excludeColumns={[]} useActivatedOnOrAfterDateFilter={true} excludeCanceledAndDiscontinuedOrders={false} - actions={ - [ - // { actionName: "labResultsForm", displayPosition: 0 }, - // { actionName: "rejectLabRequest", displayPosition: 1 }, - ] - } + actions={[]} /> ); }; From a0db23f01614f118fd544203900dfeb5df74713c Mon Sep 17 00:00:00 2001 From: Felix Kiprotich <72152368+FelixKiprotich350@users.noreply.github.com> Date: Fri, 2 Aug 2024 07:59:44 +0300 Subject: [PATCH 6/8] Update src/components/orders-table/listOrderDetails.component.tsx Co-authored-by: Donald Kibet --- src/components/orders-table/listOrderDetails.component.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/orders-table/listOrderDetails.component.tsx b/src/components/orders-table/listOrderDetails.component.tsx index c2e651a8..2d8f8bbe 100644 --- a/src/components/orders-table/listOrderDetails.component.tsx +++ b/src/components/orders-table/listOrderDetails.component.tsx @@ -9,7 +9,6 @@ import { ListOrdersDetailsProps } from "../../types"; import { launchOverlay } from "../overlay/store"; import ResultForm from "../../results/result-form.component"; -// can render orders of a patient const ListOrderDetails: React.FC = (props) => { const orders = props.groupedOrders?.orders; const patientId = props.groupedOrders?.patientId; From 419bc7019306317584889bed00c3651e51932780 Mon Sep 17 00:00:00 2001 From: Felix Kiprotich <72152368+FelixKiprotich350@users.noreply.github.com> Date: Fri, 2 Aug 2024 08:01:52 +0300 Subject: [PATCH 7/8] Update src/types.ts Co-authored-by: Donald Kibet --- src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types.ts b/src/types.ts index 3d955841..e12b3d52 100644 --- a/src/types.ts +++ b/src/types.ts @@ -20,7 +20,7 @@ export interface ListOrdersDetailsProps { export interface OrderAction { actionName: string; - displayPosition: 0 | number; + order: 0 | number; } export interface OrdersDataTableProps { useFilter?: boolean; From df5dd097fb3633065598851958427608cdff8034 Mon Sep 17 00:00:00 2001 From: felix Date: Fri, 2 Aug 2024 08:14:06 +0300 Subject: [PATCH 8/8] code cleanup --- src/components/orders-table/listOrderDetails.component.tsx | 4 ++-- src/components/orders-table/orders-data-table.component.tsx | 2 +- .../in-progress-lab-requests-table.extension.tsx | 4 ++-- .../data-table-extensions/tests-ordered-table.extension.tsx | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/orders-table/listOrderDetails.component.tsx b/src/components/orders-table/listOrderDetails.component.tsx index 2d8f8bbe..159aabc0 100644 --- a/src/components/orders-table/listOrderDetails.component.tsx +++ b/src/components/orders-table/listOrderDetails.component.tsx @@ -23,8 +23,8 @@ const ListOrderDetails: React.FC = (props) => { {props.actions .sort((a, b) => { // Replace 'property' with the actual property you want to sort by - if (a.displayPosition < b.displayPosition) return -1; - if (a.displayPosition > b.displayPosition) return 1; + if (a.order < b.order) return -1; + if (a.order > b.order) return 1; return 0; }) .map((action) => { diff --git a/src/components/orders-table/orders-data-table.component.tsx b/src/components/orders-table/orders-data-table.component.tsx index fed7d3d2..fc7ca01d 100644 --- a/src/components/orders-table/orders-data-table.component.tsx +++ b/src/components/orders-table/orders-data-table.component.tsx @@ -135,7 +135,7 @@ const OrdersDataTable: React.FC = (props) => { { id: 0, header: t("patient", "Patient"), key: "patientName" }, { id: 1, header: t("totalorders", "Total Orders"), key: "totalOrders" }, ]; - }, [props.excludeColumns, t]); + }, [t]); const pageSizes = [10, 20, 30, 40, 50]; const [currentPageSize, setPageSize] = useState(10); diff --git a/src/lab-tabs/data-table-extensions/in-progress-lab-requests-table.extension.tsx b/src/lab-tabs/data-table-extensions/in-progress-lab-requests-table.extension.tsx index c514fa89..ab9ce918 100644 --- a/src/lab-tabs/data-table-extensions/in-progress-lab-requests-table.extension.tsx +++ b/src/lab-tabs/data-table-extensions/in-progress-lab-requests-table.extension.tsx @@ -9,8 +9,8 @@ const InProgressLabRequestsTable: React.FC = () => { useActivatedOnOrAfterDateFilter={true} fulfillerStatus="IN_PROGRESS" actions={[ - { actionName: "labResultsForm", displayPosition: 0 }, - { actionName: "rejectLabRequest", displayPosition: 1 }, + { actionName: "labResultsForm", order: 0 }, + { actionName: "rejectLabRequest", order: 1 }, ]} /> ); diff --git a/src/lab-tabs/data-table-extensions/tests-ordered-table.extension.tsx b/src/lab-tabs/data-table-extensions/tests-ordered-table.extension.tsx index 204bce7d..d067f84b 100644 --- a/src/lab-tabs/data-table-extensions/tests-ordered-table.extension.tsx +++ b/src/lab-tabs/data-table-extensions/tests-ordered-table.extension.tsx @@ -8,8 +8,8 @@ const TestsOrderedTable: React.FC = () => { actionsSlotName="tests-ordered-actions-slot" useFilter actions={[ - { actionName: "pickupLabRequest", displayPosition: 0 }, - { actionName: "rejectLabRequest", displayPosition: 1 }, + { actionName: "pickupLabRequest", order: 0 }, + { actionName: "rejectLabRequest", order: 1 }, ]} /> );