From 7fce8cfa6daed7473bed91496906b9cda57acdbb Mon Sep 17 00:00:00 2001 From: rithviknishad Date: Fri, 17 May 2024 11:21:51 +0530 Subject: [PATCH 1/6] Adds support for Doctors Log Update round type (except syptoms) --- .../ConsultationDetails/Events/types.ts | 18 ++ src/Components/Patient/DailyRounds.tsx | 162 ++++++++++++++---- src/Components/Patient/models.tsx | 1 + src/Redux/api.tsx | 13 +- 4 files changed, 162 insertions(+), 32 deletions(-) diff --git a/src/Components/Facility/ConsultationDetails/Events/types.ts b/src/Components/Facility/ConsultationDetails/Events/types.ts index f5cf3c9abec..053450ea346 100644 --- a/src/Components/Facility/ConsultationDetails/Events/types.ts +++ b/src/Components/Facility/ConsultationDetails/Events/types.ts @@ -1,3 +1,5 @@ +import routes from "../../../../Redux/api"; +import request from "../../../../Utils/request/request"; import { UserBareMinimum } from "../../../Users/models"; export type Type = { @@ -28,3 +30,19 @@ export type EventGeneric = { }; // TODO: Once event types are finalized, define specific types for each event + +let cachedEventTypes: Type[] | null = null; + +export const fetchEventTypeByName = async (name: Type["name"]) => { + if (!cachedEventTypes) { + const { data } = await request(routes.listEventTypes, { + query: { limit: 100 }, + }); + + if (data?.results) { + cachedEventTypes = data.results; + } + } + + return cachedEventTypes?.find((t) => t.name === name); +}; diff --git a/src/Components/Patient/DailyRounds.tsx b/src/Components/Patient/DailyRounds.tsx index dd15d44facc..1d554b2aeda 100644 --- a/src/Components/Patient/DailyRounds.tsx +++ b/src/Components/Patient/DailyRounds.tsx @@ -33,6 +33,10 @@ import routes from "../../Redux/api"; import { Scribe } from "../Scribe/Scribe"; import { DAILY_ROUND_FORM_SCRIBE_DATA } from "../Scribe/formDetails"; import { DailyRoundsModel } from "./models"; +import { fetchEventTypeByName } from "../Facility/ConsultationDetails/Events/types"; +import InvestigationBuilder from "../Common/prescription-builder/InvestigationBuilder"; +import { FieldErrorText, FieldLabel } from "../Form/FormFields/FormField"; +import { error } from "@pnotify/core"; const Loading = lazy(() => import("../Common/Loading")); const initForm: any = { @@ -48,6 +52,8 @@ const initForm: any = { taken_at: null, rounds_type: "NORMAL", systolic: null, + investigations: [], + investigations_dirty: false, diastolic: null, pulse: null, resp: null, @@ -126,6 +132,7 @@ export const DailyRounds = (props: any) => { "bp", "pulse", "resp", + "investigations", "ventilator_spo2", "rhythm", "rhythm_detail", @@ -134,6 +141,7 @@ export const DailyRounds = (props: any) => { const fetchRoundDetails = useCallback(async () => { setIsLoading(true); + fetchEventTypeByName(""); let formData: any = initialData; if (id) { const { data } = await request(routes.getDailyReport, { @@ -176,7 +184,11 @@ export const DailyRounds = (props: any) => { ...initialData, action: getAction, }); - formData = { ...formData, ...{ action: getAction } }; + formData = { + ...formData, + action: getAction, + investigations: data.last_consultation?.investigation ?? [], + }; } } else { setPatientName(""); @@ -218,6 +230,33 @@ export const DailyRounds = (props: any) => { } return; } + + case "investigations": { + for (const investigation of state.form.investigations) { + if (!investigation.type?.length) { + errors[field] = "Investigation field can not be empty"; + invalidForm = true; + break; + } + if ( + investigation.repetitive && + !investigation.frequency?.replace(/\s/g, "").length + ) { + errors[field] = "Frequency field cannot be empty"; + invalidForm = true; + break; + } + if ( + !investigation.repetitive && + !investigation.time?.replace(/\s/g, "").length + ) { + errors[field] = "Time field cannot be empty"; + invalidForm = true; + break; + } + } + return; + } default: return; } @@ -231,6 +270,25 @@ export const DailyRounds = (props: any) => { const validForm = validateForm(); if (validForm) { setIsLoading(true); + + if ( + state.form.rounds_type === "DOCTORS_LOG" && + state.form.investigations_dirty + ) { + const { error: investigationError } = await request( + routes.partialUpdateConsultation, + { + body: { investigation: state.form.investigations }, + pathParams: { id: consultationId }, + }, + ); + + if (investigationError) { + Notification.Error({ msg: error }); + return; + } + } + let data: DailyRoundsModel = { rounds_type: state.form.rounds_type, patient_category: state.form.patient_category, @@ -298,14 +356,24 @@ export const DailyRounds = (props: any) => { setIsLoading(false); if (obj) { dispatch({ type: "set_form", form: initForm }); - Notification.Success({ - msg: `${obj.rounds_type === "VENTILATOR" ? "Critical Care" : capitalize(obj.rounds_type)} Log Updates details created successfully`, - }); if (["NORMAL", "TELEMEDICINE"].includes(state.form.rounds_type)) { + Notification.Success({ + msg: `${state.form.rounds_type === "NORMAL" ? "Normal" : "Tele-medicine"} log update created successfully`, + }); navigate( `/facility/${facilityId}/patient/${patientId}/consultation/${consultationId}`, ); + } else if (state.form.rounds_type === "DOCTORS_LOG") { + Notification.Success({ + msg: "Doctors log update created successfully", + }); + navigate( + `/facility/${facilityId}/patient/${patientId}/consultation/${consultationId}/prescriptions`, + ); } else { + Notification.Success({ + msg: "Critical Care log update created successfully", + }); navigate( `/facility/${facilityId}/patient/${patientId}/consultation/${consultationId}/daily_rounds/${obj.id}/update`, ); @@ -406,6 +474,7 @@ export const DailyRounds = (props: any) => { options={[ ...[ { id: "NORMAL", text: "Normal" }, + { id: "DOCTORS_LOG", text: "Doctor's Log Update" }, { id: "VENTILATOR", text: "Critical Care" }, ], ...(consultationSuggestion == "DC" @@ -453,34 +522,63 @@ export const DailyRounds = (props: any) => { )} - option.desc} - optionValue={(option) => option.text} - value={prevAction} - onChange={(event) => { - handleFormFieldChange(event); - setPreviousAction(event.value); - }} - /> + {state.form.rounds_type === "DOCTORS_LOG" && ( + <> +
+ Investigations Suggestions + { + handleFormFieldChange({ + name: "investigations", + value: investigations, + }); + + handleFormFieldChange({ + name: "investigations_dirty", + value: true, + }); + }} + /> + +
+ + )} - option.text} - optionValue={(option) => option.id} - value={prevReviewInterval} - onChange={(event) => { - handleFormFieldChange(event); - setPreviousReviewInterval(Number(event.value)); - }} - /> + {state.form.rounds_type !== "DOCTORS_LOG" && ( + <> + option.desc} + optionValue={(option) => option.text} + value={prevAction} + onChange={(event) => { + handleFormFieldChange(event); + setPreviousAction(event.value); + }} + /> + + option.text} + optionValue={(option) => option.id} + value={prevReviewInterval} + onChange={(event) => { + handleFormFieldChange(event); + setPreviousReviewInterval(Number(event.value)); + }} + /> + + )} - {["NORMAL", "TELEMEDICINE"].includes(state.form.rounds_type) && ( + {["NORMAL", "TELEMEDICINE", "DOCTORS_LOG"].includes( + state.form.rounds_type, + ) && ( <>

Vitals

@@ -607,7 +705,9 @@ export const DailyRounds = (props: any) => { disabled={ buttonText === "Save" && formFields.every( - (field: string) => state.form[field] == initialData[field], + (field: string) => + JSON.stringify(state.form[field]) === + JSON.stringify(initialData[field]), ) && (state.form.temperature == initialData.temperature || isNaN(state.form.temperature)) && diff --git a/src/Components/Patient/models.tsx b/src/Components/Patient/models.tsx index 81a06ff659d..7de59556f8f 100644 --- a/src/Components/Patient/models.tsx +++ b/src/Components/Patient/models.tsx @@ -284,6 +284,7 @@ export interface DailyRoundsOutput { export const DailyRoundTypes = [ "NORMAL", + "DOCTORS_LOG", "VENTILATOR", "AUTOMATED", "TELEMEDICINE", diff --git a/src/Redux/api.tsx b/src/Redux/api.tsx index 58147f68943..f4a9732a40c 100644 --- a/src/Redux/api.tsx +++ b/src/Redux/api.tsx @@ -97,7 +97,10 @@ import { import { PaginatedResponse } from "../Utils/request/types"; import { ICD11DiagnosisModel } from "../Components/Diagnosis/types"; -import { EventGeneric } from "../Components/Facility/ConsultationDetails/Events/types"; +import { + EventGeneric, + type Type, +} from "../Components/Facility/ConsultationDetails/Events/types"; import { InvestigationGroup, InvestigationType, @@ -628,6 +631,14 @@ const routes = { TRes: Type(), }, + // Event Types + + listEventTypes: { + path: "/api/v1/event_types/", + method: "GET", + TRes: Type>(), + }, + // Hospital Beds createCapacity: { path: "/api/v1/facility/{facilityId}/capacity/", From 0e6ab2dd9acd9190de3235e86cab14bf2295595b Mon Sep 17 00:00:00 2001 From: rithviknishad Date: Mon, 20 May 2024 13:35:44 +0530 Subject: [PATCH 2/6] Adds Prescription and Diagnosis --- src/Components/Patient/DailyRounds.tsx | 92 +++++++++++++++++++------- 1 file changed, 68 insertions(+), 24 deletions(-) diff --git a/src/Components/Patient/DailyRounds.tsx b/src/Components/Patient/DailyRounds.tsx index 1d554b2aeda..6e30cebd423 100644 --- a/src/Components/Patient/DailyRounds.tsx +++ b/src/Components/Patient/DailyRounds.tsx @@ -35,8 +35,15 @@ import { DAILY_ROUND_FORM_SCRIBE_DATA } from "../Scribe/formDetails"; import { DailyRoundsModel } from "./models"; import { fetchEventTypeByName } from "../Facility/ConsultationDetails/Events/types"; import InvestigationBuilder from "../Common/prescription-builder/InvestigationBuilder"; -import { FieldErrorText, FieldLabel } from "../Form/FormFields/FormField"; +import { FieldErrorText } from "../Form/FormFields/FormField"; import { error } from "@pnotify/core"; +import { useTranslation } from "react-i18next"; +import PrescriptionBuilder from "../Medicine/PrescriptionBuilder"; +import { EditDiagnosesBuilder } from "../Diagnosis/ConsultationDiagnosisBuilder/ConsultationDiagnosisBuilder"; +import { + ConditionVerificationStatuses, + ConsultationDiagnosis, +} from "../Diagnosis/types"; const Loading = lazy(() => import("../Common/Loading")); const initForm: any = { @@ -104,6 +111,7 @@ const DailyRoundsFormReducer = (state = initialState, action: any) => { }; export const DailyRounds = (props: any) => { + const { t } = useTranslation(); const { goBack } = useAppHistory(); const { facilityId, patientId, consultationId, id } = props; const [state, dispatch] = useAutoSaveReducer( @@ -120,6 +128,7 @@ export const DailyRounds = (props: any) => { ...initForm, action: "", }); + const [diagnoses, setDiagnoses] = useState(); const headerText = !id ? "Add Consultation Update" : "Info"; const buttonText = !id ? "Save" : "Continue"; @@ -173,6 +182,13 @@ export const DailyRounds = (props: any) => { setPatientName(data.name!); setFacilityName(data.facility_object!.name); setConsultationSuggestion(data.last_consultation?.suggestion); + setDiagnoses( + data.last_consultation?.diagnoses?.sort( + (a: ConsultationDiagnosis, b: ConsultationDiagnosis) => + ConditionVerificationStatuses.indexOf(a.verification_status) - + ConditionVerificationStatuses.indexOf(b.verification_status), + ), + ); setPreviousReviewInterval( Number(data.last_consultation?.review_interval), ); @@ -522,29 +538,6 @@ export const DailyRounds = (props: any) => { )} - {state.form.rounds_type === "DOCTORS_LOG" && ( - <> -
- Investigations Suggestions - { - handleFormFieldChange({ - name: "investigations", - value: investigations, - }); - - handleFormFieldChange({ - name: "investigations_dirty", - value: true, - }); - }} - /> - -
- - )} - {state.form.rounds_type !== "DOCTORS_LOG" && ( <> { /> )} + + {state.form.rounds_type === "DOCTORS_LOG" && ( + <> +
+
+

+ {t("investigations")} +

+ { + handleFormFieldChange({ + name: "investigations", + value: investigations, + }); + handleFormFieldChange({ + name: "investigations_dirty", + value: true, + }); + }} + /> + +
+
+

+ {t("prescription_medications")} +

+ +
+
+

+ {t("prn_prescriptions")} +

+ +
+
+

+ {t("diagnosis")} +

+ {/* */} + {diagnoses ? ( + + ) : ( +
+ Fetching existing diagnosis of patient... +
+ )} +
+
+ + )}
From ab83f1c9cfcc9a622e8e9d45c0d835f2bc6f152d Mon Sep 17 00:00:00 2001 From: rithviknishad Date: Tue, 21 May 2024 22:38:48 +0530 Subject: [PATCH 3/6] fix investigations not working --- src/Components/Patient/DailyRounds.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Components/Patient/DailyRounds.tsx b/src/Components/Patient/DailyRounds.tsx index 6e30cebd423..d3286c5732c 100644 --- a/src/Components/Patient/DailyRounds.tsx +++ b/src/Components/Patient/DailyRounds.tsx @@ -400,10 +400,11 @@ export const DailyRounds = (props: any) => { }; const handleFormFieldChange = (event: FieldChangeEvent) => { - dispatch({ - type: "set_form", - form: { ...state.form, [event.name]: event.value }, - }); + let form = { ...state.form, [event.name]: event.value }; + if (event.name === "investigations") { + form = { ...form, investigations_dirty: true }; + } + dispatch({ type: "set_form", form }); }; const field = (name: string) => { From ec2f7158db8526926889b1ff08a439e1ee049074 Mon Sep 17 00:00:00 2001 From: rithviknishad Date: Tue, 21 May 2024 22:42:09 +0530 Subject: [PATCH 4/6] fix investigations not working --- src/Components/Patient/DailyRounds.tsx | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/Components/Patient/DailyRounds.tsx b/src/Components/Patient/DailyRounds.tsx index d3286c5732c..f952b241398 100644 --- a/src/Components/Patient/DailyRounds.tsx +++ b/src/Components/Patient/DailyRounds.tsx @@ -400,11 +400,10 @@ export const DailyRounds = (props: any) => { }; const handleFormFieldChange = (event: FieldChangeEvent) => { - let form = { ...state.form, [event.name]: event.value }; - if (event.name === "investigations") { - form = { ...form, investigations_dirty: true }; - } - dispatch({ type: "set_form", form }); + dispatch({ + type: "set_form", + form: { ...state.form, [event.name]: event.value }, + }); }; const field = (name: string) => { @@ -706,10 +705,6 @@ export const DailyRounds = (props: any) => { name: "investigations", value: investigations, }); - handleFormFieldChange({ - name: "investigations_dirty", - value: true, - }); }} /> From 62e23062ea5154c908cb904bea592dfeaa001e82 Mon Sep 17 00:00:00 2001 From: rithviknishad Date: Wed, 22 May 2024 00:32:31 +0530 Subject: [PATCH 5/6] fixes during QA --- src/Components/Patient/DailyRounds.tsx | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Components/Patient/DailyRounds.tsx b/src/Components/Patient/DailyRounds.tsx index f952b241398..0dbf5eb1612 100644 --- a/src/Components/Patient/DailyRounds.tsx +++ b/src/Components/Patient/DailyRounds.tsx @@ -384,7 +384,7 @@ export const DailyRounds = (props: any) => { msg: "Doctors log update created successfully", }); navigate( - `/facility/${facilityId}/patient/${patientId}/consultation/${consultationId}/prescriptions`, + `/facility/${facilityId}/patient/${patientId}/consultation/${consultationId}`, ); } else { Notification.Success({ @@ -400,10 +400,16 @@ export const DailyRounds = (props: any) => { }; const handleFormFieldChange = (event: FieldChangeEvent) => { - dispatch({ - type: "set_form", - form: { ...state.form, [event.name]: event.value }, - }); + const form = { + ...state.form, + [event.name]: event.value, + }; + + if (event.name === "investigations") { + form["investigations_dirty"] = true; + } + + dispatch({ type: "set_form", form }); }; const field = (name: string) => { From 4c1c035c6379749700e1bda444ecd27ab4b334b7 Mon Sep 17 00:00:00 2001 From: rithviknishad Date: Wed, 22 May 2024 21:29:42 +0530 Subject: [PATCH 6/6] disable disable save for doctors log --- src/Components/Patient/DailyRounds.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Components/Patient/DailyRounds.tsx b/src/Components/Patient/DailyRounds.tsx index 0dbf5eb1612..d39d1feac7d 100644 --- a/src/Components/Patient/DailyRounds.tsx +++ b/src/Components/Patient/DailyRounds.tsx @@ -757,7 +757,8 @@ export const DailyRounds = (props: any) => { ) && (state.form.temperature == initialData.temperature || isNaN(state.form.temperature)) && - state.form.rounds_type !== "VENTILATOR" + state.form.rounds_type !== "VENTILATOR" && + state.form.rounds_type !== "DOCTORS_LOG" } onClick={(e) => handleSubmit(e)} label={buttonText}