Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated blood pressure range and remove hyphen for infusion "nor-adrenaline" #8498

Merged
Merged
41 changes: 16 additions & 25 deletions src/Components/Common/BloodPressureFormField.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useTranslation } from "react-i18next";
import { FieldValidator } from "../Form/FieldValidators";
import FormField from "../Form/FormFields/FormField";
import RangeAutocompleteFormField from "../Form/FormFields/RangeAutocompleteFormField";
Expand All @@ -8,42 +9,34 @@ import {
} from "../Form/FormFields/Utils";
import { BloodPressure } from "../Patient/models";

type Props = FormFieldBaseProps<BloodPressure>;
type Props = FormFieldBaseProps<BloodPressure | null>;

export default function BloodPressureFormField(props: Props) {
const { t } = useTranslation();
const field = useFormFieldPropsResolver(props);
const map = meanArterialPressure(props.value)?.toFixed();

const handleChange = (event: FieldChangeEvent<number>) => {
const value: BloodPressure = {
...field.value,
[event.name]: event.value,
};
value.mean = meanArterialPressure(value);
field.onChange({ name: field.name, value });
const bp = field.value ?? {};
bp[event.name as keyof BloodPressure] = event.value;
field.handleChange(Object.values(bp).filter(Boolean).length ? bp : null);
};

const map =
!!props.value?.diastolic &&
!!props.value.systolic &&
meanArterialPressure(props.value);

return (
<FormField
field={{
...field,
labelSuffix: map ? (
<span className="font-medium">MAP: {map.toFixed(1)}</span>
) : undefined,
labelSuffix: map && <span className="font-medium">MAP: {map}</span>,
}}
>
<div className="flex flex-row items-center">
<RangeAutocompleteFormField
name="systolic"
placeholder="Systolic"
placeholder={t("systolic")}
start={0}
end={250}
step={1}
value={field.value?.systolic}
value={field.value?.systolic ?? undefined}
onChange={handleChange}
labelClassName="hidden"
errorClassName="hidden"
Expand All @@ -68,11 +61,11 @@ export default function BloodPressureFormField(props: Props) {
<span className="px-2 text-lg font-medium text-secondary-400">/</span>
<RangeAutocompleteFormField
name="diastolic"
placeholder="Diastolic"
placeholder={t("diastolic")}
start={0}
end={250}
step={1}
value={field.value?.diastolic}
value={field.value?.diastolic ?? undefined}
onChange={handleChange}
labelClassName="hidden"
errorClassName="hidden"
Expand All @@ -99,13 +92,11 @@ export default function BloodPressureFormField(props: Props) {
);
}

export const meanArterialPressure = ({
diastolic,
systolic,
}: BloodPressure) => {
if (diastolic != null && systolic != null) {
return (2 * diastolic + systolic) / 3;
export const meanArterialPressure = (bp?: BloodPressure | null) => {
if (bp?.diastolic == null || bp?.systolic == null) {
return;
}
return (2 * bp.diastolic + bp.systolic) / 3;
};

export const BloodPressureValidator: FieldValidator<BloodPressure> = (bp) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import { useTranslation } from "react-i18next";
import PatientCategoryBadge from "../../../Common/PatientCategoryBadge";
import {
BloodPressure,
DailyRoundsModel,
NameQuantity,
} from "../../../Patient/models";
import { DailyRoundsModel, NameQuantity } from "../../../Patient/models";
import { PatientCategory } from "../../models";

interface Props<T extends keyof DailyRoundsModel> {
Expand Down Expand Up @@ -45,8 +41,8 @@ const LogUpdateCardAttribute = <T extends keyof DailyRoundsModel>({
<div className="flex flex-col items-center gap-2 md:flex-row">
<AttributeLabel attributeKey={attributeKey} />
<span className="text-sm font-semibold text-secondary-700">
{(attributeValue as BloodPressure).systolic}/
{(attributeValue as BloodPressure).diastolic} mmHg
{(attributeValue as DailyRoundsModel["bp"])?.systolic || "--"}/
{(attributeValue as DailyRoundsModel["bp"])?.diastolic || "--"} mmHg
</span>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion src/Components/Facility/Consultations/Mews.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const getHeartRateScore = (value?: number) => {
return 3;
};

const getSystolicBPScore = (value?: number) => {
const getSystolicBPScore = (value?: number | null) => {
if (typeof value !== "number") return;

if (value <= 70) return 3;
Expand Down
18 changes: 4 additions & 14 deletions src/Components/Facility/Consultations/PrimaryParametersPlot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import CareIcon from "../../../CAREUI/icons/CareIcon";
import { PainDiagrams } from "./PainDiagrams";
import PageTitle from "../../Common/PageTitle";
import dayjs from "../../../Utils/dayjs";
import { meanArterialPressure } from "../../Common/BloodPressureFormField";
import { PrimaryParametersPlotFields } from "../models";

interface PrimaryParametersPlotProps {
Expand All @@ -18,17 +19,6 @@ interface PrimaryParametersPlotProps {
consultationId: string;
}

const sanitizeBPAttribute = (value: number | undefined) => {
// Temp. hack until the cleaning of daily rounds as a db migration is done.
// TODO: remove once migration is merged.

if (value == null || value < 0) {
return;
}

return value;
};

export const PrimaryParametersPlot = ({
consultationId,
}: PrimaryParametersPlotProps) => {
Expand Down Expand Up @@ -77,19 +67,19 @@ export const PrimaryParametersPlot = ({
{
name: "diastolic",
data: Object.values(results)
.map((p: any) => p.bp && sanitizeBPAttribute(p.bp.diastolic))
.map((p: any) => p.bp?.diastolic)
.reverse(),
},
{
name: "systolic",
data: Object.values(results)
.map((p: any) => p.bp && sanitizeBPAttribute(p.bp.systolic))
.map((p: any) => p.bp?.systolic)
.reverse(),
},
{
name: "mean",
data: Object.values(results)
.map((p: any) => p.bp && sanitizeBPAttribute(p.bp.mean))
.map((p: any) => meanArterialPressure(p.bp))
.reverse(),
},
];
Expand Down
7 changes: 2 additions & 5 deletions src/Components/Facility/models.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { ConsultationDiagnosis, CreateDiagnosis } from "../Diagnosis/types";
import { NormalPrescription, PRNPrescription } from "../Medicine/models";
import {
AssignedToObjectModel,
BloodPressure,
DailyRoundsModel,
FileUploadModel,
} from "../Patient/models";
Expand Down Expand Up @@ -427,11 +428,7 @@ export const PrimaryParametersPlotFields = [
] as const satisfies (keyof DailyRoundsModel)[];

export type PrimaryParametersPlotRes = {
bp: {
mean?: number;
systolic?: number;
diastolic?: number;
};
bp: BloodPressure;
pulse: number;
temperature: string;
resp: number;
Expand Down
48 changes: 32 additions & 16 deletions src/Components/Form/FormFields/RangeFormField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ import { SelectFormField } from "./SelectFormField";
type BaseProps = FormFieldBaseProps<number> & {
min: number;
max: number;
sliderMin?: number;
sliderMax?: number;
step?: number;
valueDescriptions?: ValueDescription[];
hideInput?: boolean;
hideUnitInLabel?: boolean;
};

type PropsWithUnit = BaseProps & {
Expand Down Expand Up @@ -75,18 +78,20 @@ export default function RangeFormField(props: Props) {
? props.valueDescriptions?.find((vd) => (vd.till || props.max) >= value)
: undefined;

const roundedValue =
Math.round(((value || min) + Number.EPSILON) * 100) / 100;

const allValueColors = props.valueDescriptions?.every((vd) => vd.color);

const trailPercent = ((roundedValue - min) / ((max || 0) - (min || 0))) * 100;
const [sliderMin, sliderMax] = [
props.sliderMin ?? props.min,
props.sliderMax ?? props.max,
].map(unit.conversionFn);

const snapStopLength = Math.min(
(props.max - props.min) / (props.step || 1),
props.max - props.min,
20,
);
const sliderDelta = sliderMax - sliderMin;

const trailPercent =
((Math.round(((value || sliderMin) + Number.EPSILON) * 100) / 100 -
sliderMin) /
sliderDelta) *
100;

const handleChange = (v: number) => field.handleChange(unit.inversionFn(v));

Expand All @@ -98,7 +103,10 @@ export default function RangeFormField(props: Props) {
...field,
label: (
<>
{field.label} {unit.label && <span>({unit.label})</span>}
{field.label}{" "}
{!props.hideUnitInLabel && unit.label && (
<span>({unit.label})</span>
)}
</>
),
labelSuffix: (
Expand All @@ -124,6 +132,7 @@ export default function RangeFormField(props: Props) {
max={max}
errorClassName="hidden"
inputClassName="py-1.5 mr-4"
disabled={props.disabled}
/>
{props.units?.length ? (
<SelectFormField
Expand Down Expand Up @@ -166,7 +175,11 @@ export default function RangeFormField(props: Props) {
<input
type="range"
id={field.id}
className={classNames("cui-range-slider", field.className)}
className={classNames(
"cui-range-slider",
field.className,
props.disabled && "opacity-50",
)}
style={
allValueColors
? {
Expand All @@ -179,22 +192,25 @@ export default function RangeFormField(props: Props) {
disabled={field.disabled}
name={field.name}
value={displayValue}
min={min}
max={max}
min={sliderMin}
max={sliderMax}
step={props.step}
onChange={(e) => handleChange(e.target.valueAsNumber)}
/>
</div>

<div className="flex justify-between">
{Array.from({ length: snapStopLength + 1 }).map((_, index) => (
{Array.from({
length:
1 + Math.min(sliderDelta / (props.step || 1), sliderDelta, 20),
}).map((_, index) => (
<div key={index} className="h-1 w-px bg-black/20" />
))}
</div>

<div className="flex justify-between text-xs text-black/30">
<span>{properRoundOf(min)}</span>
<span>{properRoundOf(max)}</span>
<span>{properRoundOf(sliderMin)}</span>
<span>{properRoundOf(sliderMax)}</span>
</div>
</FormField>
);
Expand Down
3 changes: 2 additions & 1 deletion src/Components/LogUpdate/CriticalCarePreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { VentilatorFields } from "./Sections/RespiratorySupport/Ventilator";
import PressureSore from "./Sections/PressureSore/PressureSore";
import { IOBalanceSections } from "./Sections/IOBalance";
import PainChart from "./components/PainChart";
import { meanArterialPressure } from "../Common/BloodPressureFormField";
import { DailyRoundsModel } from "../Patient/models";

type Props = {
Expand Down Expand Up @@ -255,7 +256,7 @@ export default function CriticalCarePreview(props: Props) {
/>
<Detail
label="Mean"
value={data.bp.mean && properRoundOf(data.bp.mean)}
value={meanArterialPressure(data.bp)?.toFixed()}
/>
</div>
)}
Expand Down
2 changes: 1 addition & 1 deletion src/Components/LogUpdate/Sections/IOBalance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const IOBalanceSections = [
name: "Infusions",
options: [
"Adrenalin",
"Nor-adrenalin",
"Noradrenalin",
"Vasopressin",
"Dopamine",
"Dobutamine",
Expand Down
Loading
Loading