From 1c1db13c63337df7e5f2585023e00cf230b2e1b9 Mon Sep 17 00:00:00 2001 From: Aditya Jindal Date: Wed, 16 Oct 2024 17:39:46 +0530 Subject: [PATCH] Fixing: Switch Blood Pressure and temperature dropdown to use TextFormField with type="number" instead of a dropdown #8644 (#8728) --- .../e2e/patient_spec/PatientLogUpdate.cy.ts | 4 +- .../pageobject/Patient/PatientLogupdate.ts | 10 +- .../Common/BloodPressureFormField.tsx | 87 ++++------ .../Common/TemperatureFormField.tsx | 155 ++++++++++-------- src/Components/Patient/DailyRounds.tsx | 24 ++- src/Locale/en.json | 6 + 6 files changed, 155 insertions(+), 131 deletions(-) diff --git a/cypress/e2e/patient_spec/PatientLogUpdate.cy.ts b/cypress/e2e/patient_spec/PatientLogUpdate.cy.ts index 7faaeed5a9f..3907784b4b7 100644 --- a/cypress/e2e/patient_spec/PatientLogUpdate.cy.ts +++ b/cypress/e2e/patient_spec/PatientLogUpdate.cy.ts @@ -302,9 +302,9 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => { patientRhythm, ]); patientLogupdate.clickUpdateDetail(); - patientLogupdate.clickClearButtonInElement("#systolic"); + patientLogupdate.clearIntoElementById("#systolic"); patientLogupdate.typeSystolic(patientModifiedSystolic); - patientLogupdate.clickClearButtonInElement("#diastolic"); + patientLogupdate.clearIntoElementById("#diastolic"); patientLogupdate.typeDiastolic(patientModifiedDiastolic); cy.submitButton("Continue"); cy.verifyNotification("Brief Update updated successfully"); diff --git a/cypress/pageobject/Patient/PatientLogupdate.ts b/cypress/pageobject/Patient/PatientLogupdate.ts index 857fe7dd972..d7b49fde05e 100644 --- a/cypress/pageobject/Patient/PatientLogupdate.ts +++ b/cypress/pageobject/Patient/PatientLogupdate.ts @@ -43,11 +43,11 @@ class PatientLogupdate { } typeSystolic(systolic: string) { - cy.typeAndSelectOption("#systolic", systolic); + cy.get("#systolic").click().type(systolic); } typeDiastolic(diastolic: string) { - cy.typeAndSelectOption("#diastolic", diastolic); + cy.get("#diastolic").click().type(diastolic); } typePulse(pulse: string) { @@ -55,7 +55,7 @@ class PatientLogupdate { } typeTemperature(temperature: string) { - cy.typeAndSelectOption("#temperature", temperature); + cy.get("#temperature").click().type(temperature); } typeRespiratory(respiratory: string) { @@ -93,8 +93,8 @@ class PatientLogupdate { cy.wait(3000); } - clickClearButtonInElement(elementId: string) { - cy.get(elementId).find("#clear-button").click(); + clearIntoElementById(elementId) { + cy.get(elementId).click().clear(); } clickVitals() { diff --git a/src/Components/Common/BloodPressureFormField.tsx b/src/Components/Common/BloodPressureFormField.tsx index e6fff756d0f..beddd34cf38 100644 --- a/src/Components/Common/BloodPressureFormField.tsx +++ b/src/Components/Common/BloodPressureFormField.tsx @@ -1,13 +1,13 @@ import { useTranslation } from "react-i18next"; import { FieldValidator } from "../Form/FieldValidators"; import FormField from "../Form/FormFields/FormField"; -import RangeAutocompleteFormField from "../Form/FormFields/RangeAutocompleteFormField"; import { FieldChangeEvent, FormFieldBaseProps, useFormFieldPropsResolver, } from "../Form/FormFields/Utils"; import { BloodPressure } from "../Patient/models"; +import TextFormField from "../Form/FormFields/TextFormField"; type Props = FormFieldBaseProps; @@ -16,12 +16,13 @@ export default function BloodPressureFormField(props: Props) { const field = useFormFieldPropsResolver(props); const map = meanArterialPressure(props.value)?.toFixed(); - const handleChange = (event: FieldChangeEvent) => { + const handleChange = (event: FieldChangeEvent) => { + const value = event.value ? parseInt(event.value, 10) : ""; const bp = { systolic: field.value?.systolic, diastolic: field.value?.diastolic, }; - bp[event.name as keyof BloodPressure] = event.value; + bp[event.name as keyof BloodPressure] = value || undefined; field.handleChange(Object.values(bp).filter(Boolean).length ? bp : null); }; @@ -32,63 +33,35 @@ export default function BloodPressureFormField(props: Props) { labelSuffix: map && MAP: {map}, }} > -
- + - / - / +
@@ -102,14 +75,20 @@ export const meanArterialPressure = (bp?: BloodPressure | null) => { return (2 * bp.diastolic + bp.systolic) / 3; }; -export const BloodPressureValidator: FieldValidator = (bp) => { +export const BloodPressureValidator: FieldValidator = ( + bp, + t, +) => { if (Object.values(bp).every((v) => v == null)) { return; } - if (bp.diastolic == null) { - return "Diastolic is missing. Either specify both or clear both."; + if (bp.systolic == null || bp.diastolic == null) { + return t("blood_pressure_error.missing"); + } + if (bp.systolic > 250 || bp.diastolic > 250) { + return t("blood_pressure_error.exceed"); } - if (bp.systolic == null) { - return "Systolic is missing. Either specify both or clear both."; + if (bp.systolic < bp.diastolic) { + return t("blood_pressure_error.systolic_less_than_diastolic"); } }; diff --git a/src/Components/Common/TemperatureFormField.tsx b/src/Components/Common/TemperatureFormField.tsx index 236d87826e9..7b2d7124f09 100644 --- a/src/Components/Common/TemperatureFormField.tsx +++ b/src/Components/Common/TemperatureFormField.tsx @@ -1,77 +1,100 @@ -import { useState } from "react"; -import { FormFieldBaseProps } from "../Form/FormFields/Utils"; -import RangeAutocompleteFormField from "../Form/FormFields/RangeAutocompleteFormField"; +import { useState, useEffect } from "react"; +import { FieldChangeEvent, FormFieldBaseProps } from "../Form/FormFields/Utils"; +import { fahrenheitToCelsius, celsiusToFahrenheit } from "@/Utils/utils"; import CareIcon from "../../CAREUI/icons/CareIcon"; import ButtonV2 from "./components/ButtonV2"; -import { fahrenheitToCelsius } from "../../Utils/utils"; +import TextFormField from "../Form/FormFields/TextFormField"; type TemperatureUnit = "celsius" | "fahrenheit"; -type Props = FormFieldBaseProps & { - placeholder?: string; -}; +type TemperatureFormFieldProps = FormFieldBaseProps; -export default function TemperatureFormField(props: Props) { +export default function TemperatureFormField({ + onChange, + id, + label, + error, + value, + name, +}: TemperatureFormFieldProps) { const [unit, setUnit] = useState("fahrenheit"); + const [inputValue, setInputValue] = useState(value || ""); + + useEffect(() => { + if (value) { + const initialTemperature = + unit === "celsius" + ? fahrenheitToCelsius(parseFloat(value)).toFixed(1) + : value; + setInputValue(initialTemperature); + } + }, [value, unit]); + + const handleUnitChange = () => { + setUnit(unit === "celsius" ? "fahrenheit" : "celsius"); + if (inputValue) { + const convertedValue = + unit === "celsius" + ? celsiusToFahrenheit(parseFloat(inputValue)).toFixed(1) + : fahrenheitToCelsius(parseFloat(inputValue)).toFixed(1); + setInputValue(convertedValue); + } + }; + + const handleInputChange = (e: FieldChangeEvent) => { + const newValue = e.value; + + const regex = /^-?\d*\.?\d{0,1}$/; + if (regex.test(newValue)) { + setInputValue(newValue); + } + }; + + const handleBlur = () => { + if (!inputValue) return; + const parsedValue = parseFloat(inputValue); + if (isNaN(parsedValue)) return; + + const finalValue = + unit === "celsius" + ? celsiusToFahrenheit(parsedValue).toString() + : parsedValue.toString(); + + setInputValue(finalValue); + onChange({ name, value: finalValue }); + }; return ( - , - className: "text-danger-500", - }, - { - value: 96.6, - label: "Low", - icon: , - className: "text-warning-500", - }, - { - value: 97.6, - label: "Normal", - icon: , - className: "text-primary-500", - }, - { - value: 99.6, - label: "High", - icon: , - className: "text-warning-500", - }, - { - value: 101.6, - label: "High", - icon: , - className: "text-danger-500", - }, - ]} - optionLabel={(value) => { - const val = unit === "celsius" ? fahrenheitToCelsius(value) : value; - return val.toFixed(1); - }} - labelSuffix={ - setUnit(unit === "celsius" ? "fahrenheit" : "celsius")} - > - - - } - /> +
+ + + + + +
); } diff --git a/src/Components/Patient/DailyRounds.tsx b/src/Components/Patient/DailyRounds.tsx index bf25d48f6bf..3e10383e78a 100644 --- a/src/Components/Patient/DailyRounds.tsx +++ b/src/Components/Patient/DailyRounds.tsx @@ -1,5 +1,4 @@ import { navigate } from "raviger"; - import dayjs from "dayjs"; import { useCallback, useEffect, useState } from "react"; import { @@ -126,7 +125,6 @@ export const DailyRounds = (props: any) => { return state; } }; - const [state, dispatch] = useAutoSaveReducer( DailyRoundsFormReducer, initialState, @@ -249,7 +247,9 @@ export const DailyRounds = (props: any) => { } return; case "bp": { - const error = state.form.bp && BloodPressureValidator(state.form.bp); + const error = + state.form.bp && BloodPressureValidator(state.form.bp, t); + if (error) { errors.bp = error; invalidForm = true; @@ -258,6 +258,23 @@ export const DailyRounds = (props: any) => { return; } + case "temperature": { + const temperatureInputValue = state.form["temperature"]; + + if ( + temperatureInputValue && + (temperatureInputValue < 95 || temperatureInputValue > 106) + ) { + errors[field] = t("out_of_range_error", { + start: "95°F (35°C)", + end: "106°F (41.1°C)", + }); + invalidForm = true; + scrollTo("temperature"); + } + return; + } + case "investigations": { for (const investigation of state.form.investigations) { if (!investigation.type?.length) { @@ -773,7 +790,6 @@ export const DailyRounds = (props: any) => { /> )} - {["NORMAL", "TELEMEDICINE", "DOCTORS_LOG"].includes( state.form.rounds_type, ) && ( diff --git a/src/Locale/en.json b/src/Locale/en.json index 94e9bd0f3a9..5f2652fa91b 100644 --- a/src/Locale/en.json +++ b/src/Locale/en.json @@ -813,6 +813,12 @@ "map_acronym": "M.A.P.", "systolic": "Systolic", "diastolic": "Diastolic", + "blood_pressure_error": { + "missing": "Field is required. Either specify both or clear both.", + "exceed": "Value cannot exceed 250 mmHg.", + "systolic_less_than_diastolic": "Systolic must be greater than diastolic." + }, + "out_of_range_error": "Value must be between {{ start }} and {{ end }}.", "pain": "Pain", "pain_chart_description": "Mark region and intensity of pain", "bradycardia": "Bradycardia",