diff --git a/src/Components/Facility/Consultations/Mews.tsx b/src/Components/Facility/Consultations/Mews.tsx new file mode 100644 index 00000000000..6b8e7de806e --- /dev/null +++ b/src/Components/Facility/Consultations/Mews.tsx @@ -0,0 +1,174 @@ +import { DailyRoundsModel } from "../../Patient/models"; +import RecordMeta from "../../../CAREUI/display/RecordMeta"; +import { classNames } from "../../../Utils/utils"; + +const getRespScore = (value?: number) => { + if (typeof value !== "number") return; + + if (value < 8) return 2; + if (value <= 8) return 1; + if (value <= 17) return 0; + if (value <= 20) return 1; + if (value <= 29) return 2; + return 3; +}; + +const getHeartRateScore = (value?: number) => { + if (typeof value !== "number") return; + + if (value < 40) return 2; + if (value <= 50) return 1; + if (value <= 100) return 0; + if (value <= 110) return 1; + if (value <= 129) return 2; + return 3; +}; + +const getSystolicBPScore = (value?: number) => { + if (typeof value !== "number") return; + + if (value <= 70) return 3; + if (value <= 80) return 2; + if (value <= 100) return 1; + if (value <= 159) return 0; + if (value <= 199) return 1; + if (value <= 220) return 2; + return 3; +}; + +const getTempRange = (value?: number) => { + console.log(value); + if (typeof value !== "number") return; + + if (value < 95) return 2; + if (value <= 96.8) return 1; + if (value <= 100.4) return 0; + if (value <= 101.3) return 1; + return 2; +}; + +const getLOCRange = (value?: DailyRoundsModel["consciousness_level"]) => { + if (!value) return; + + return { + UNRESPONSIVE: 3, + RESPONDS_TO_PAIN: 2, + RESPONDS_TO_VOICE: 1, + ALERT: 0, + AGITATED_OR_CONFUSED: 1, + ONSET_OF_AGITATION_AND_CONFUSION: 2, + UNKNOWN: undefined, + }[value]; +}; + +export const Mews = ({ dailyRound }: { dailyRound: DailyRoundsModel }) => { + const mewsCard = (isMissing: boolean, data: string[] | number) => { + if (isMissing) { + return ( + <> +
+

N/A

+
+ {(data as string[]).join(", ")}{" "} + data is missing from the last log update. +
+
+
+ +
+
+ + ); + } else { + const value = Number(data); + return ( + <> +
+

{data}

+
+

+ Resp. Rate: {dailyRound.resp} +

+

+ Heart Rate:{" "} + {dailyRound.pulse} +

+

+ Systolic BP:{" "} + {dailyRound.bp?.systolic} +

+

+ Temperature:{" "} + {dailyRound.temperature} +

+

+ Consciousness:{" "} + + {dailyRound.consciousness_level + ?.replaceAll("_", " ") + .toLowerCase()} + +

+
+
+
+ +
6 && "bg-danger-500" + )} + >
+
+ + ); + } + }; + + const scores = { + "Respiratory rate": getRespScore(dailyRound.resp), + "Heart rate": getHeartRateScore(dailyRound.pulse), + "Systolic BP": getSystolicBPScore(dailyRound.bp?.systolic), + Temperature: getTempRange( + dailyRound.temperature ? parseFloat(dailyRound.temperature) : undefined + ), + "Level of Consciousness": getLOCRange(dailyRound.consciousness_level), + }; + + if (Object.values(scores).some((value) => value === undefined)) { + return ( +
+

MEWS Score

+ {mewsCard( + true, + Object.entries(scores) + .filter(([_, value]) => value === undefined) + .map(([key]) => key) + )} +
+ ); + } + + return ( +
+

MEWS Score

+ {mewsCard( + false, + Object.values(scores as Record).reduce((p, v) => p + v) + )} +
+ ); +}; diff --git a/src/Components/Facility/models.tsx b/src/Components/Facility/models.tsx index 0d8a112e021..64f79198cf9 100644 --- a/src/Components/Facility/models.tsx +++ b/src/Components/Facility/models.tsx @@ -1,4 +1,4 @@ -import { AssignedToObjectModel } from "../Patient/models"; +import { AssignedToObjectModel, DailyRoundsModel } from "../Patient/models"; import { ProcedureType } from "../Common/prescription-builder/ProcedureBuilder"; import { NormalPrescription, PRNPrescription } from "../Medicine/models"; import { AssetData } from "../Assets/AssetTypes"; @@ -151,7 +151,7 @@ export interface ConsultationModel { ett_tt?: number; cuff_pressure?: number; lines?: any; - last_daily_round?: any; + last_daily_round?: DailyRoundsModel; current_bed?: CurrentBed; review_interval?: number; cause_of_death?: string; diff --git a/src/Components/Patient/PatientInfoCard.tsx b/src/Components/Patient/PatientInfoCard.tsx index 8bf20a65f64..adcdcb1a98d 100644 --- a/src/Components/Patient/PatientInfoCard.tsx +++ b/src/Components/Patient/PatientInfoCard.tsx @@ -27,7 +27,9 @@ import request from "../../Utils/request/request.js"; import routes from "../../Redux/api.js"; import DropdownMenu from "../Common/components/Menu.js"; import { triggerGoal } from "../../Integrations/Plausible.js"; -import useAuthUser from "../../Common/hooks/useAuthUser.js"; + +import useAuthUser from "../../Common/hooks/useAuthUser"; +import { Mews } from "../Facility/Consultations/Mews.js"; import DischargeSummaryModal from "../Facility/DischargeSummaryModal.js"; import DischargeModal from "../Facility/DischargeModal.js"; import { useTranslation } from "react-i18next"; @@ -340,6 +342,11 @@ export default function PatientInfoCard(props: { )} + {consultation?.last_daily_round && ( +
+ +
+ )}
{!!consultation?.discharge_date && ( diff --git a/src/Components/Patient/models.tsx b/src/Components/Patient/models.tsx index af69d8464bc..3a856a04765 100644 --- a/src/Components/Patient/models.tsx +++ b/src/Components/Patient/models.tsx @@ -301,6 +301,14 @@ export interface DailyRoundsModel { created_date?: string; modified_date?: string; taken_at?: string; + consciousness_level?: + | "UNRESPONSIVE" + | "RESPONDS_TO_PAIN" + | "RESPONDS_TO_VOICE" + | "ALERT" + | "AGITATED_OR_CONFUSED" + | "ONSET_OF_AGITATION_AND_CONFUSION" + | "UNKNOWN"; rounds_type: (typeof DailyRoundTypes)[number]; last_updated_by_telemedicine?: boolean; created_by_telemedicine?: boolean;