Skip to content

Commit

Permalink
Adds support for Doctors Log Update round type (v1) (#7839)
Browse files Browse the repository at this point in the history
* Adds support for Doctors Log Update round type (except syptoms)

* Adds Prescription and Diagnosis

* fix investigations not working

* fix investigations not working

* fixes during QA

* disable disable save for doctors log

---------

Co-authored-by: Khavin Shankar <[email protected]>
  • Loading branch information
rithviknishad and khavinshankar authored May 28, 2024
1 parent 54a3244 commit fb9ba0e
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 37 deletions.
18 changes: 18 additions & 0 deletions src/Components/Facility/ConsultationDetails/Events/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import routes from "../../../../Redux/api";
import request from "../../../../Utils/request/request";
import { UserBareMinimum } from "../../../Users/models";

export type Type = {
Expand Down Expand Up @@ -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);
};
219 changes: 183 additions & 36 deletions src/Components/Patient/DailyRounds.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@ 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 } 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";
import { EncounterSymptomsBuilder } from "../Symptoms/SymptomsBuilder";
import { FieldLabel } from "../Form/FormFields/FormField";
const Loading = lazy(() => import("../Common/Loading"));
Expand All @@ -47,6 +58,8 @@ const initForm: any = {
taken_at: null,
rounds_type: "NORMAL",
systolic: null,
investigations: [],
investigations_dirty: false,
diastolic: null,
pulse: null,
resp: null,
Expand Down Expand Up @@ -97,6 +110,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<any>(
Expand All @@ -113,6 +127,7 @@ export const DailyRounds = (props: any) => {
...initForm,
action: "",
});
const [diagnoses, setDiagnoses] = useState<ConsultationDiagnosis[]>();
const headerText = !id ? "Add Consultation Update" : "Info";
const buttonText = !id ? "Save" : "Continue";

Expand All @@ -124,6 +139,7 @@ export const DailyRounds = (props: any) => {
"bp",
"pulse",
"resp",
"investigations",
"ventilator_spo2",
"rhythm",
"rhythm_detail",
Expand All @@ -132,6 +148,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, {
Expand Down Expand Up @@ -163,6 +180,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),
);
Expand All @@ -174,7 +198,11 @@ export const DailyRounds = (props: any) => {
...initialData,
action: getAction,
});
formData = { ...formData, ...{ action: getAction } };
formData = {
...formData,
action: getAction,
investigations: data.last_consultation?.investigation ?? [],
};
}
} else {
setPatientName("");
Expand Down Expand Up @@ -207,6 +235,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;
}
Expand All @@ -220,6 +275,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,
Expand Down Expand Up @@ -282,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}`,
);
} else {
Notification.Success({
msg: "Critical Care log update created successfully",
});
navigate(
`/facility/${facilityId}/patient/${patientId}/consultation/${consultationId}/daily_rounds/${obj.id}/update`,
);
Expand All @@ -300,10 +384,16 @@ export const DailyRounds = (props: any) => {
};

const handleFormFieldChange = (event: FieldChangeEvent<unknown>) => {
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) => {
Expand Down Expand Up @@ -390,6 +480,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"
Expand Down Expand Up @@ -426,34 +517,40 @@ export const DailyRounds = (props: any) => {
<EncounterSymptomsBuilder />
</div>

<SelectFormField
{...field("action")}
label="Action"
options={TELEMEDICINE_ACTIONS}
optionLabel={(option) => option.desc}
optionValue={(option) => option.text}
value={prevAction}
onChange={(event) => {
handleFormFieldChange(event);
setPreviousAction(event.value);
}}
/>
{state.form.rounds_type !== "DOCTORS_LOG" && (
<>
<SelectFormField
{...field("action")}
label="Action"
options={TELEMEDICINE_ACTIONS}
optionLabel={(option) => option.desc}
optionValue={(option) => option.text}
value={prevAction}
onChange={(event) => {
handleFormFieldChange(event);
setPreviousAction(event.value);
}}
/>

<SelectFormField
{...field("review_interval")}
label="Review After"
labelSuffix={getExpectedReviewTime()}
options={REVIEW_AT_CHOICES}
optionLabel={(option) => option.text}
optionValue={(option) => option.id}
value={prevReviewInterval}
onChange={(event) => {
handleFormFieldChange(event);
setPreviousReviewInterval(Number(event.value));
}}
/>
<SelectFormField
{...field("review_interval")}
label="Review After"
labelSuffix={getExpectedReviewTime()}
options={REVIEW_AT_CHOICES}
optionLabel={(option) => 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,
) && (
<>
<h3 className="mb-6 md:col-span-2">Vitals</h3>

Expand Down Expand Up @@ -572,6 +669,53 @@ export const DailyRounds = (props: any) => {
/>
</>
)}

{state.form.rounds_type === "DOCTORS_LOG" && (
<>
<div className="flex flex-col gap-10 divide-y-2 divide-dashed divide-gray-600 border-t-2 border-dashed border-gray-600 pt-6 md:col-span-2">
<div>
<h3 className="my-4 text-lg font-semibold">
{t("investigations")}
</h3>
<InvestigationBuilder
investigations={state.form.investigations}
setInvestigations={(investigations) => {
handleFormFieldChange({
name: "investigations",
value: investigations,
});
}}
/>
<FieldErrorText error={state.errors.investigation} />
</div>
<div>
<h3 className="mb-4 mt-8 text-lg font-semibold">
{t("prescription_medications")}
</h3>
<PrescriptionBuilder />
</div>
<div>
<h3 className="mb-4 mt-8 text-lg font-semibold">
{t("prn_prescriptions")}
</h3>
<PrescriptionBuilder is_prn />
</div>
<div>
<h3 className="mb-4 mt-8 text-lg font-semibold">
{t("diagnosis")}
</h3>
{/* */}
{diagnoses ? (
<EditDiagnosesBuilder value={diagnoses} />
) : (
<div className="flex animate-pulse justify-center py-4 text-center font-medium text-gray-800">
Fetching existing diagnosis of patient...
</div>
)}
</div>
</div>
</>
)}
</div>

<div className="mt-4 flex flex-col-reverse justify-end gap-2 md:flex-row">
Expand All @@ -580,11 +724,14 @@ 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)) &&
state.form.rounds_type !== "VENTILATOR"
state.form.rounds_type !== "VENTILATOR" &&
state.form.rounds_type !== "DOCTORS_LOG"
}
onClick={(e) => handleSubmit(e)}
label={buttonText}
Expand Down
1 change: 1 addition & 0 deletions src/Components/Patient/models.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ export interface DailyRoundsOutput {

export const DailyRoundTypes = [
"NORMAL",
"DOCTORS_LOG",
"VENTILATOR",
"AUTOMATED",
"TELEMEDICINE",
Expand Down
Loading

0 comments on commit fb9ba0e

Please sign in to comment.