From f4eda87d734305d48997aea6ad434016dbf54b2e Mon Sep 17 00:00:00 2001 From: rithviknishad Date: Wed, 8 May 2024 11:50:50 +0530 Subject: [PATCH 1/2] Adds support for doctors and nurses discussions threads in Discussion Notes --- cypress/e2e/patient_spec/patient_manage.cy.ts | 2 +- src/Common/constants.tsx | 5 ++ .../Facility/ConsultationDetails/index.tsx | 4 +- .../ConsultationDoctorNotes/index.tsx | 45 ++++++++++++++--- src/Components/Facility/DoctorNote.tsx | 5 +- .../Facility/PatientConsultationNotesList.tsx | 12 +++-- src/Components/Facility/PatientNotesList.tsx | 16 ++++-- .../Facility/PatientNotesSlideover.tsx | 49 ++++++++++++++----- src/Components/Facility/models.tsx | 2 + src/Components/Patient/PatientNotes.tsx | 42 ++++++++++++++-- src/Redux/api.tsx | 3 ++ 11 files changed, 150 insertions(+), 35 deletions(-) diff --git a/cypress/e2e/patient_spec/patient_manage.cy.ts b/cypress/e2e/patient_spec/patient_manage.cy.ts index 00756f832f6..313877ac565 100644 --- a/cypress/e2e/patient_spec/patient_manage.cy.ts +++ b/cypress/e2e/patient_spec/patient_manage.cy.ts @@ -35,7 +35,7 @@ describe("Patient", () => { // }); // commented out the shifting request, as logic need to be re-visited - it("Post doctor notes for an already created patient", () => { + it("Post discussion notes for an already created patient", () => { patientPage.visitPatient("Dummy Patient 3"); patientConsultationPage.visitDoctorNotesPage(); patientConsultationPage.addDoctorsNotes("Test Doctor Notes"); diff --git a/src/Common/constants.tsx b/src/Common/constants.tsx index 4e9298422c9..a562fd70bf5 100644 --- a/src/Common/constants.tsx +++ b/src/Common/constants.tsx @@ -1311,3 +1311,8 @@ export const OCCUPATION_TYPES = [ { id: 31, text: "Don't Know", value: "UNKNOWN" }, { id: 32, text: "Not Applicable", value: "NOT_APPLICABLE" }, ]; + +export const PATIENT_NOTES_THREADS = { + Doctors: 10, + Nurses: 20, +} as const; diff --git a/src/Components/Facility/ConsultationDetails/index.tsx b/src/Components/Facility/ConsultationDetails/index.tsx index 77b6268e039..b670f60c84c 100644 --- a/src/Components/Facility/ConsultationDetails/index.tsx +++ b/src/Components/Facility/ConsultationDetails/index.tsx @@ -325,13 +325,13 @@ export const ConsultationDetails = (props: any) => { onClick={() => showPatientNotesPopup ? navigate( - `/facility/${facilityId}/patient/${patientId}/notes`, + `/facility/${facilityId}/patient/${patientId}/consultation/${consultationId}/notes`, ) : setShowPatientNotesPopup(true) } className="btn btn-primary m-1 w-full hover:text-white" > - Doctor's Notes + Discussion Notes diff --git a/src/Components/Facility/ConsultationDoctorNotes/index.tsx b/src/Components/Facility/ConsultationDoctorNotes/index.tsx index 8485c1ea8de..b6bd8a6dc29 100644 --- a/src/Components/Facility/ConsultationDoctorNotes/index.tsx +++ b/src/Components/Facility/ConsultationDoctorNotes/index.tsx @@ -11,8 +11,10 @@ import routes from "../../../Redux/api.js"; import request from "../../../Utils/request/request.js"; import useQuery from "../../../Utils/request/useQuery.js"; import useKeyboardShortcut from "use-keyboard-shortcut"; -import { isAppleDevice } from "../../../Utils/utils.js"; +import { classNames, isAppleDevice } from "../../../Utils/utils.js"; import AutoExpandingTextInputFormField from "../../Form/FormFields/AutoExpandingTextInputFormField.js"; +import { PATIENT_NOTES_THREADS } from "../../../Common/constants.js"; +import useAuthUser from "../../../Common/hooks/useAuthUser.js"; interface ConsultationDoctorNotesProps { patientId: string; @@ -23,6 +25,13 @@ interface ConsultationDoctorNotesProps { const ConsultationDoctorNotes = (props: ConsultationDoctorNotesProps) => { const { patientId, facilityId, consultationId } = props; + const authUser = useAuthUser(); + const [thread, setThread] = useState( + authUser.user_type === "Nurse" + ? PATIENT_NOTES_THREADS.Nurses + : PATIENT_NOTES_THREADS.Doctors, + ); + const [patientActive, setPatientActive] = useState(true); const [noteField, setNoteField] = useState(""); const [reload, setReload] = useState(false); @@ -40,10 +49,6 @@ const ConsultationDoctorNotes = (props: ConsultationDoctorNotesProps) => { const [state, setState] = useState(initialData); const onAddNote = async () => { - const payload = { - note: noteField, - consultation: consultationId, - }; if (!/\S+/.test(noteField)) { Notification.Error({ msg: "Note Should Contain At Least 1 Character", @@ -55,7 +60,11 @@ const ConsultationDoctorNotes = (props: ConsultationDoctorNotesProps) => { pathParams: { patientId: patientId, }, - body: payload, + body: { + note: noteField, + thread, + consultation: consultationId, + }, }); if (res?.status === 201) { @@ -111,12 +120,34 @@ const ConsultationDoctorNotes = (props: ConsultationDoctorNotesProps) => { }} backUrl={`/facility/${facilityId}/patient/${patientId}`} > -
+
+
+ {Object.values(PATIENT_NOTES_THREADS).map((current) => ( + + ))} +
diff --git a/src/Components/Facility/DoctorNote.tsx b/src/Components/Facility/DoctorNote.tsx index 13e490cbd05..b70ccfdf516 100644 --- a/src/Components/Facility/DoctorNote.tsx +++ b/src/Components/Facility/DoctorNote.tsx @@ -12,6 +12,7 @@ interface DoctorNoteProps { const DoctorNote = (props: DoctorNoteProps) => { const { state, handleNext, setReload, disableEdit } = props; + return (
{ dataLength={state.notes.length} scrollableTarget="patient-notes-list" > - {state.notes.map((note: any) => ( + {state.notes.map((note) => ( { ))} ) : ( -
+
No Notes Found
)} diff --git a/src/Components/Facility/PatientConsultationNotesList.tsx b/src/Components/Facility/PatientConsultationNotesList.tsx index 35822508d4b..e7e0bb25504 100644 --- a/src/Components/Facility/PatientConsultationNotesList.tsx +++ b/src/Components/Facility/PatientConsultationNotesList.tsx @@ -2,7 +2,7 @@ import { Dispatch, SetStateAction, useEffect, useState } from "react"; import { RESULTS_PER_PAGE_LIMIT } from "../../Common/constants"; import CircularProgress from "../Common/components/CircularProgress"; import routes from "../../Redux/api"; -import { PatientNoteStateType } from "./models"; +import { PatientNoteStateType, PatientNotesModel } from "./models"; import useSlug from "../../Common/hooks/useSlug"; import DoctorNote from "./DoctorNote"; import request from "../../Utils/request/request"; @@ -13,12 +13,13 @@ interface PatientNotesProps { reload?: boolean; setReload?: (value: boolean) => void; disableEdit?: boolean; + thread: PatientNotesModel["thread"]; } const pageSize = RESULTS_PER_PAGE_LIMIT; const PatientConsultationNotesList = (props: PatientNotesProps) => { - const { state, setState, reload, setReload, disableEdit } = props; + const { state, setState, reload, setReload, disableEdit, thread } = props; const consultationId = useSlug("consultation") ?? ""; const [isLoading, setIsLoading] = useState(true); @@ -31,6 +32,7 @@ const PatientConsultationNotesList = (props: PatientNotesProps) => { }, query: { consultation: consultationId, + thread, offset: (state.cPage - 1) * RESULTS_PER_PAGE_LIMIT, }, }); @@ -60,6 +62,10 @@ const PatientConsultationNotesList = (props: PatientNotesProps) => { } }, [reload]); + useEffect(() => { + fetchNotes(); + }, [thread]); + useEffect(() => { setReload?.(true); }, []); @@ -76,7 +82,7 @@ const PatientConsultationNotesList = (props: PatientNotesProps) => { if (isLoading && !state.notes.length) { return ( -
+
); diff --git a/src/Components/Facility/PatientNotesList.tsx b/src/Components/Facility/PatientNotesList.tsx index a36762072b9..9585ace5db7 100644 --- a/src/Components/Facility/PatientNotesList.tsx +++ b/src/Components/Facility/PatientNotesList.tsx @@ -2,7 +2,7 @@ import { useState, useEffect } from "react"; import { RESULTS_PER_PAGE_LIMIT } from "../../Common/constants"; import CircularProgress from "../Common/components/CircularProgress"; import DoctorNote from "./DoctorNote"; -import { PatientNoteStateType } from "./models"; +import { PatientNoteStateType, PatientNotesModel } from "./models"; import routes from "../../Redux/api"; import request from "../../Utils/request/request"; @@ -13,12 +13,13 @@ interface PatientNotesProps { facilityId: string; reload?: boolean; setReload?: any; + thread: PatientNotesModel["thread"]; } const pageSize = RESULTS_PER_PAGE_LIMIT; const PatientNotesList = (props: PatientNotesProps) => { - const { state, setState, reload, setReload } = props; + const { state, setState, reload, setReload, thread } = props; const [isLoading, setIsLoading] = useState(true); @@ -26,7 +27,10 @@ const PatientNotesList = (props: PatientNotesProps) => { setIsLoading(true); const { data }: any = await request(routes.getPatientNotes, { pathParams: { patientId: props.patientId }, - query: { offset: (state.cPage - 1) * RESULTS_PER_PAGE_LIMIT }, + query: { + offset: (state.cPage - 1) * RESULTS_PER_PAGE_LIMIT, + thread, + }, }); if (state.cPage === 1) { @@ -52,6 +56,10 @@ const PatientNotesList = (props: PatientNotesProps) => { } }, [reload]); + useEffect(() => { + fetchNotes(); + }, [thread]); + useEffect(() => { setReload(true); }, []); @@ -68,7 +76,7 @@ const PatientNotesList = (props: PatientNotesProps) => { if (isLoading && !state.notes.length) { return ( -
+
); diff --git a/src/Components/Facility/PatientNotesSlideover.tsx b/src/Components/Facility/PatientNotesSlideover.tsx index 038b980d24b..3fd46f92f57 100644 --- a/src/Components/Facility/PatientNotesSlideover.tsx +++ b/src/Components/Facility/PatientNotesSlideover.tsx @@ -14,6 +14,7 @@ import useKeyboardShortcut from "use-keyboard-shortcut"; import AutoExpandingTextInputFormField from "../Form/FormFields/AutoExpandingTextInputFormField.js"; import * as Sentry from "@sentry/browser"; import useAuthUser from "../../Common/hooks/useAuthUser"; +import { PATIENT_NOTES_THREADS } from "../../Common/constants.js"; interface PatientNotesProps { patientId: string; @@ -23,6 +24,12 @@ interface PatientNotesProps { } export default function PatientNotesSlideover(props: PatientNotesProps) { + const authUser = useAuthUser(); + const [thread, setThread] = useState( + authUser.user_type === "Nurse" + ? PATIENT_NOTES_THREADS.Nurses + : PATIENT_NOTES_THREADS.Doctors, + ); const [show, setShow] = useState(true); const [patientActive, setPatientActive] = useState(true); const [reload, setReload] = useState(false); @@ -39,11 +46,11 @@ export default function PatientNotesSlideover(props: PatientNotesProps) { const subscription = await reg.pushManager.getSubscription(); if (!subscription && !res.data?.pf_endpoint) { Notification.Warn({ - msg: "Please subscribe to notifications to get live updates on doctor notes.", + msg: "Please subscribe to notifications to get live updates on discussion notes.", }); } else if (subscription?.endpoint !== res.data?.pf_endpoint) { Notification.Warn({ - msg: "Please subscribe to notifications on this device to get live updates on doctor notes.", + msg: "Please subscribe to notifications on this device to get live updates on discussion notes.", }); } } catch (error) { @@ -73,10 +80,6 @@ export default function PatientNotesSlideover(props: PatientNotesProps) { ); const onAddNote = async () => { - const payload = { - note: noteField, - consultation: consultationId, - }; if (!/\S+/.test(noteField)) { Notification.Error({ msg: "Note Should Contain At Least 1 Character", @@ -85,7 +88,11 @@ export default function PatientNotesSlideover(props: PatientNotesProps) { } const { res } = await request(routes.addPatientNote, { pathParams: { patientId: patientId }, - body: payload, + body: { + note: noteField, + consultation: consultationId, + thread, + }, }); if (res?.status === 201) { Notification.Success({ msg: "Note added successfully" }); @@ -189,23 +196,43 @@ export default function PatientNotesSlideover(props: PatientNotesProps) { className="flex w-full cursor-pointer items-center justify-around rounded-t-md bg-primary-800 p-2 text-white" onClick={() => setShow(!show)} > - {"Doctor's Notes"} + Discussion Notes {notesActionIcons}
) : (
- {/* Doctor Notes Header */}
- {"Doctor's Notes"} + Discussion Notes {notesActionIcons}
- {/* Doctor Notes Body */} +
+ {Object.values(PATIENT_NOTES_THREADS).map((current) => ( + + ))} +
{ const { patientId, facilityId } = props; + const authUser = useAuthUser(); + const [thread, setThread] = useState( + authUser.user_type === "Nurse" + ? PATIENT_NOTES_THREADS.Nurses + : PATIENT_NOTES_THREADS.Doctors, + ); + const [patientActive, setPatientActive] = useState(true); const [noteField, setNoteField] = useState(""); const [reload, setReload] = useState(false); @@ -33,9 +43,6 @@ const PatientNotes = (props: PatientNotesProps) => { const [state, setState] = useState(initialData); const onAddNote = async () => { - const payload = { - note: noteField, - }; if (!/\S+/.test(noteField)) { Notification.Error({ msg: "Note Should Contain At Least 1 Character", @@ -45,7 +52,10 @@ const PatientNotes = (props: PatientNotesProps) => { const { res } = await request(routes.addPatientNote, { pathParams: { patientId: patientId }, - body: payload, + body: { + note: noteField, + thread, + }, }); if (res?.status === 201) { Notification.Success({ msg: "Note added successfully" }); @@ -93,7 +103,28 @@ const PatientNotes = (props: PatientNotesProps) => { }} backUrl={`/facility/${facilityId}/patient/${patientId}`} > -
+
+
+ {Object.values(PATIENT_NOTES_THREADS).map((current) => ( + + ))} +
{ facilityId={facilityId} reload={reload} setReload={setReload} + thread={thread} />
diff --git a/src/Redux/api.tsx b/src/Redux/api.tsx index eb924f03c51..82ae52f26a4 100644 --- a/src/Redux/api.tsx +++ b/src/Redux/api.tsx @@ -753,6 +753,9 @@ const routes = { path: "/api/v1/patient/{patientId}/notes/", method: "POST", TRes: Type(), + TBody: Type< + Pick & { consultation?: string } + >(), }, updatePatientNote: { path: "/api/v1/patient/{patientId}/notes/{noteId}/", From 93bf621d10c5e8ccb05da949b5d45500f477c81c Mon Sep 17 00:00:00 2001 From: rithviknishad Date: Wed, 8 May 2024 14:29:50 +0530 Subject: [PATCH 2/2] fix title --- src/Components/Facility/ConsultationDoctorNotes/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Facility/ConsultationDoctorNotes/index.tsx b/src/Components/Facility/ConsultationDoctorNotes/index.tsx index b6bd8a6dc29..522ad168b86 100644 --- a/src/Components/Facility/ConsultationDoctorNotes/index.tsx +++ b/src/Components/Facility/ConsultationDoctorNotes/index.tsx @@ -112,7 +112,7 @@ const ConsultationDoctorNotes = (props: ConsultationDoctorNotesProps) => { return (