Skip to content

Commit

Permalink
added final components to los dashboard (#139)
Browse files Browse the repository at this point in the history
Problem
- The postevent dashboard length of stay needed implementing

Solution
- added components as per design

Ticket:
N/A

Documentation:
N/A

Tests
- manual testing
- `yarn build` passes

<details>
<summary>Images</summary>

![Screenshot 2024-03-23 121637](https://github.com/jon-funk/project-ct/assets/22301841/4643f939-9c7b-4fbf-9430-e1c306e362d3)
</details>
  • Loading branch information
critch646 authored Mar 23, 2024
1 parent 22784ba commit f1508d0
Show file tree
Hide file tree
Showing 10 changed files with 472 additions and 84 deletions.
108 changes: 97 additions & 11 deletions app/web/components/dashboard/LengthOfStayComponents.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
import React from "react";
import { Paper, Typography } from "@mui/material";
import { Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Typography } from "@mui/material";
import { BoxPlot } from "@visx/stats";
import { Group } from "@visx/group";
import { scaleBand, scaleLinear } from "@visx/scale";
import { AxisLeft, AxisBottom } from "@visx/axis";
import { BoxPlotData } from "../../interfaces/PosteventDashboard";
import { BoxPlotData, LengthOfStayMedianRow, LengthOfStayTransportsListProps, LengthOfStayStyle } from "../../interfaces/PosteventDashboard";
import { DataGrid, GridColDef } from "@mui/x-data-grid";
import { tableColorStylesLight } from "../../constants/colorPalettes";


export interface LengthOfStayStyle {
title: string;
titleColor: string;
titleBackground: string;
boxFill: string;
boxStroke: string;
}

export const LengthOfStayWhiskerBoxPlot: React.FC<{ boxPlotData: BoxPlotData[], style: LengthOfStayStyle }> = ({ boxPlotData: dataByDay, style }) => {


Expand Down Expand Up @@ -146,4 +140,96 @@ function calculateQuartiles(data: number[]) {
const thirdQuartile = sortedData[Math.ceil((sortedData.length + mid - 1) / 2)];

return { firstQuartile, median, thirdQuartile };
}
}


export const LengthOfStayMedianTable: React.FC<{ tableData: LengthOfStayMedianRow[]; acuityMedianMinutes: number; style: LengthOfStayStyle }> = ({ tableData, acuityMedianMinutes, style }) => {

const titleText = style.title;
const titleColor = style.titleColor;
const titleBackground = style.titleBackground;



return (
<Paper sx={{ width: "auto", overflow: "hidden", display: "inline-block" }}>
<Typography
variant="h6"
sx={{
padding: 2,
backgroundColor: titleBackground,
color: titleColor,
textAlign: "center"
}}
>
{titleText} Median LOS: {acuityMedianMinutes} mins
</Typography>
<TableContainer sx={{ maxHeight: 440 }}>
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow>
<TableCell>Chief Complaint</TableCell>
<TableCell align="right">Median LOS (minutes)</TableCell>
<TableCell align="right">Hospital</TableCell>
</TableRow>
</TableHead>
<TableBody>
{tableData.map((row, index) => (
<TableRow key={index} hover role="checkbox" tabIndex={-1}>
<TableCell>{row.chiefComplaint}</TableCell>
<TableCell align="right">{row.medianLosMinutes}</TableCell>
<TableCell align="right">{row.hospital}</TableCell>
</TableRow>
))}

</TableBody>
</Table>
</TableContainer>
</Paper>
);
}

export const LengthOfStayTransportsList: React.FC<LengthOfStayTransportsListProps> = ({ data }) => {

const columns: GridColDef[] = [
{ field: "triage_acuity", headerName: "Acuity", minWidth: 100, flex: 0.5 },
{ field: "chief_complaint", headerName: "Chief Complaint", minWidth: 200, flex: 2 },
{ field: "length_of_stay", headerName: "Length of Stay", minWidth: 100, flex: 1 },
];

return (
<Paper
elevation={0}
sx={{
width: "auto",
"& .MuiDataGrid-columnHeaders": {
...tableColorStylesLight.subHeader,
},
"& .MuiDataGrid-row:nth-of-type(odd)": {
...tableColorStylesLight.oddRow,
},
"& .MuiDataGrid-row:nth-of-type(even)": {
...tableColorStylesLight.evenRow,
},
"& .MuiDataGrid-columnHeaderTitle": {
whiteSpace: "normal",
lineHeight: "normal",
wordBreak: "break-word",
},
"& .MuiDataGrid-footerContainer": {
borderTop: "none",
},
}}
>
<Typography variant="h5" align="center" sx={{ ...tableColorStylesLight.header, padding: "16px 0" }}>Offsite Transports List</Typography>

<DataGrid
rows={data}
columns={columns}
autoHeight
getRowId={(row) => row.patient_encounter_uuid}
hideFooter
/>
</Paper>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,6 @@ export const OffsiteTransportStackedBarChart: React.FC<{ offsiteTransportsPerDay
}

const allTransportTypes = ["Ambulance", "Private Vehicle"];
console.log("offsiteTransportsPerDayCount: ", offsiteTransportsPerDayCount)

// Convert data to an array format that can be used with visx
const data: DayData[] = Object.keys(offsiteTransportsPerDayCount).map(date => {
Expand Down
101 changes: 71 additions & 30 deletions app/web/components/dashboard/PostFestivalDashboards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { AcuityCountsData } from "../../interfaces/AcuityCountsData";
import { AcuityCountPerDay, OffsiteTransportCountTotals, OffsiteTransportEntry } from "../../interfaces/PosteventDashboard";
import { PatientEncounterCountByDayStackedBarChart, PatientEncounterCountByDayTable, OffsiteTransportBreakdownSideBarChart, OffsiteTransportList, OffsiteTransportStackedBarChart } from "./PatientEncounterCountsByDay";
import { triageColorStyles, offsiteTransportColorStyles, tableColorStylesLight } from "../../constants/colorPalettes";
import { LengthOfStayWhiskerBoxPlot } from "./LengthOfStayComponents";
import { LengthOfStayWhiskerBoxPlot, LengthOfStayMedianTable, LengthOfStayTransportsList } from "./LengthOfStayComponents";
import { LengthOfStayDashboardProps } from "../../interfaces/PosteventDashboard";

interface PostFestivalSummaryProps {
Expand All @@ -34,10 +34,10 @@ export const PostFestivalSummaryComponent: React.FC<PostFestivalSummaryProps> =
return <Grid container spacing={2} style={{ padding: 1 + "rem" }}>
<Grid>
<Grid container direction="column" spacing={2}>
<Grid item>
<Grid item xs="auto">
<PatientEncounterAcuityBarChart acuityCountsData={acuityCountsData} />
</Grid>
<Grid item>
<Grid item xs="auto">
<ChiefComplaintEncounterCountsTable encounterCounts={chiefComplaintEncounterCountsData} />
</Grid>
</Grid>
Expand Down Expand Up @@ -77,18 +77,18 @@ export const PatientEncountersDashboardComponent: React.FC<PatientEncountersDash
}
) => {
return <>
<Grid container spacing={2} style={{ padding: "1rem", justifyContent: "center" }}>
<Grid item xs={12} md={6} lg={5} xl={3} sx={{ maxWidth: "400px" }}>
<Grid container spacing={2} style={{ padding: "1rem", justifyContent: "left" }}>
<Grid item xs="auto" sx={{ maxWidth: "400px" }}>
<PatientEncounterCountByDayStackedBarChart acuityCountPerDay={acuityCountPerDay} />
</Grid>
<Grid item xs={12} md={6} lg={5} xl={3} sx={{ maxWidth: "400px" }}>
<Grid item xs="auto" sx={{ maxWidth: "400px" }}>
<PatientEncounterCountByDayStackedBarChart acuityCountPerDay={acuityCountPerDay} displayCounts={false} />
</Grid>

<Grid item xs={12} md={6} lg={4} xl={2} sx={{ maxWidth: "400px" }}>
<Grid item xs="auto" sx={{ maxWidth: "400px" }}>
<PatientEncounterCountByDayTable acuityCountPerDay={acuityCountPerDay} />
</Grid>
<Grid item xs={2}>
<Grid item xs="auto">
<TriageAcuityLegend triageColorStyles={triageColorStyles} />
</Grid>
</Grid>
Expand All @@ -105,24 +105,24 @@ export const OffsiteTransportsDashboardComponent: React.FC<OffsiteTransportsDash


return <Grid container spacing={2} style={{ padding: 1 + "rem" }}>
<Grid item xs={12} md={8} lg={7} xl={6} sx={{ maxWidth: "400px" }}>
<Grid item xs="auto" sx={{ maxWidth: "400px" }}>
<OffsiteTransportBreakdownSideBarChart offsiteTransportCounts={offsiteTransportCounts} />
</Grid>
<Grid item xs={12} md={9} lg={8} xl={7} sx={{ maxWidth: "800px" }}>
<OffsiteTransportList offsiteTransportEntries={offsiteTransportEntries} />
</Grid>

<Grid item xs={12} md={8} lg={7} xl={6} sx={{ maxWidth: "400px" }}>
<Grid item xs="auto" sx={{ maxWidth: "400px" }}>
<OffsiteTransportStackedBarChart offsiteTransportsPerDayCount={offsiteTransportsPerDayCount} />
</Grid>
<Grid item xs={2}>
<Grid item xs="auto">
<OffsiteTransportLegend transportColorStyles={offsiteTransportColorStyles} />
</Grid>
</Grid>
}


export const LengthOfStayDashboardComponent: React.FC<LengthOfStayDashboardProps> = ({ losBoxPlotData }) => {
export const LengthOfStayDashboardComponent: React.FC<LengthOfStayDashboardProps> = ({ losBoxPlotData, losMedianData, transportLosListData }) => {

// Styles for the box plots
const styleLosAll = {
Expand Down Expand Up @@ -165,26 +165,67 @@ export const LengthOfStayDashboardComponent: React.FC<LengthOfStayDashboardProps
boxStroke: "#000000",
};

console.log("losBoxPlotData:", losBoxPlotData);
// Table styles for the median tablea
const styleMedianTableRed = {
title: "Red",
titleColor: triageColorStyles.red.color,
titleBackground: triageColorStyles.red.backgroundColor,
};

const styleMedianTableYellow = {
title: "Yellow",
titleColor: triageColorStyles.yellow.color,
titleBackground: triageColorStyles.yellow.backgroundColor,
};

const styleMedianTableGreen = {
title: "Green",
titleColor: triageColorStyles.green.color,
titleBackground: triageColorStyles.green.backgroundColor,
};

const styleMedianTableWhite = {
title: "White",
titleColor: triageColorStyles.white.color,
titleBackground: triageColorStyles.white.backgroundColor,
};

return (<>
<Grid container spacing={2} justifyContent="left" style={{ padding: 1 + "rem" }} >
<Grid item xs="auto">
<LengthOfStayWhiskerBoxPlot boxPlotData={losBoxPlotData.all} style={styleLosAll} />
</Grid>
<Grid item xs="auto">
<LengthOfStayWhiskerBoxPlot boxPlotData={losBoxPlotData.red} style={styleLosRed} />
</Grid>
<Grid item xs="auto">
<LengthOfStayWhiskerBoxPlot boxPlotData={losBoxPlotData.yellow} style={styleLosYellow} />
</Grid>
<Grid item xs="auto">
<LengthOfStayWhiskerBoxPlot boxPlotData={losBoxPlotData.green} style={styleLosGreen} />
</Grid>
<Grid item xs="auto">
<LengthOfStayWhiskerBoxPlot boxPlotData={losBoxPlotData.white} style={styleLosWhite} />
</Grid>
<Grid item xs="auto">
<LengthOfStayMedianTable tableData={losMedianData.red.tableData} acuityMedianMinutes={losMedianData.red.acuityMedianMinutes} style={styleMedianTableRed} />
</Grid>
<Grid item xs="auto">
<LengthOfStayMedianTable tableData={losMedianData.yellow.tableData} acuityMedianMinutes={losMedianData.yellow.acuityMedianMinutes} style={styleMedianTableYellow} />
</Grid>
<Grid item xs="auto">
<LengthOfStayMedianTable tableData={losMedianData.green.tableData} acuityMedianMinutes={losMedianData.green.acuityMedianMinutes} style={styleMedianTableGreen} />
</Grid>
<Grid item xs="auto">
<LengthOfStayMedianTable tableData={losMedianData.white.tableData} acuityMedianMinutes={losMedianData.white.acuityMedianMinutes} style={styleMedianTableWhite} />
</Grid>
<Grid item xs={12} md={8} lg={8} xl={4}>
<LengthOfStayTransportsList data={transportLosListData} />
</Grid >
</Grid >
</>);


return <Grid container spacing={2} style={{ padding: 1 + "rem" }} >
<Grid item xs={12} md={8} lg={8} xl={4}>
<LengthOfStayWhiskerBoxPlot boxPlotData={losBoxPlotData.all} style={styleLosAll} />
</Grid>
<Grid item xs={12} md={8} lg={8} xl={4}>
<LengthOfStayWhiskerBoxPlot boxPlotData={losBoxPlotData.red} style={styleLosRed} />
</Grid>
<Grid item xs={12} md={8} lg={8} xl={4}>
<LengthOfStayWhiskerBoxPlot boxPlotData={losBoxPlotData.yellow} style={styleLosYellow} />
</Grid>
<Grid item xs={12} md={8} lg={8} xl={4}>
<LengthOfStayWhiskerBoxPlot boxPlotData={losBoxPlotData.green} style={styleLosGreen} />
</Grid>
<Grid item xs={12} md={8} lg={8} xl={4}>
<LengthOfStayWhiskerBoxPlot boxPlotData={losBoxPlotData.white} style={styleLosWhite} />
</Grid>
</Grid >
}

interface ColorStyle {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ export const CommonPresentationsAndTransportsTables = (props: TopTenCommonPresen

return (
<>
<Grid item xs={12} md={8} lg={8} xl={2}>
<Grid item xs="auto">
<CommonPresentationsTable commonPresentationsData={commonPresentationsDataRed} />
<CommonPresentationsTable commonPresentationsData={transportsDataRed} />
</Grid>
<Grid item xs={12} md={8} lg={8} xl={2}>
<Grid item xs="auto">
<CommonPresentationsTable commonPresentationsData={commonPresentationsDataYellow} />
<CommonPresentationsTable commonPresentationsData={transportsDataYellow} />
</Grid>
Expand Down
2 changes: 1 addition & 1 deletion app/web/contexts/auth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
setUser(true);
}
} else {
console.log("auth token was not retrieved from local storage");
console.warn("auth token was not retrieved from local storage");
}
setLoading(false);
}
Expand Down
59 changes: 59 additions & 0 deletions app/web/interfaces/PosteventDashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,63 @@ export interface LengthOfStayDashboardData {

export interface LengthOfStayDashboardProps {
losBoxPlotData: LengthOfStayDashboardData;
losMedianData: LengthOfStayMedianTableAllData;
transportLosListData: LengthOfStayTransportItem[];
}

export interface LengthOfStayMedianRow {
chiefComplaint: string;
medianLosMinutes: number;
hospital: number;
}

export interface LengthOfStayMedianTableAllData {
red: LengthOfStayMedianTableData;
yellow: LengthOfStayMedianTableData;
green: LengthOfStayMedianTableData;
white: LengthOfStayMedianTableData;
}

export interface LengthOfStayMedianTableData {
tableData: LengthOfStayMedianRow[];
acuityMedianMinutes: number;
}

export interface LengthOfStayStyle {
title: string;
titleColor: string;
titleBackground: string;
boxFill?: string;
boxStroke?: string;
}

export const defaultStyle: LengthOfStayStyle = {
title: "",
titleColor: "",
titleBackground: "",
boxFill: "",
boxStroke: "",
};

export const defaultLosMedianTableData: LengthOfStayMedianTableData = {
tableData: [],
acuityMedianMinutes: 0,
};

export const defaultLosMedianTableAllData: LengthOfStayMedianTableAllData = {
red: defaultLosMedianTableData,
yellow: defaultLosMedianTableData,
green: defaultLosMedianTableData,
white: defaultLosMedianTableData,
};

export interface LengthOfStayTransportItem {
patient_encounter_uuid: string;
triage_acuity: string;
chief_complaint: string;
length_of_stay: string;
}

export interface LengthOfStayTransportsListProps {
data: LengthOfStayTransportItem[];
}
Loading

0 comments on commit f1508d0

Please sign in to comment.