Skip to content

Commit

Permalink
Merge pull request #7774 from coronasafe/doctors-and-nurses-discussions
Browse files Browse the repository at this point in the history
Adds support for doctors and nurses discussions threads in Discussion Notes
  • Loading branch information
khavinshankar authored May 13, 2024
2 parents 0b042f2 + 358d3f6 commit 7300824
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 36 deletions.
2 changes: 1 addition & 1 deletion cypress/e2e/patient_spec/patient_manage.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
5 changes: 5 additions & 0 deletions src/Common/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1342,3 +1342,8 @@ export const OCCUPATION_TYPES = [
{ id: 6, text: "Others", value: "OTHERS" },
{ id: 32, text: "Not Applicable", value: "NOT_APPLICABLE" },
];

export const PATIENT_NOTES_THREADS = {
Doctors: 10,
Nurses: 20,
} as const;
4 changes: 2 additions & 2 deletions src/Components/Facility/ConsultationDetails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
</Link>
</div>
</nav>
Expand Down
47 changes: 39 additions & 8 deletions src/Components/Facility/ConsultationDoctorNotes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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",
Expand All @@ -55,7 +60,11 @@ const ConsultationDoctorNotes = (props: ConsultationDoctorNotesProps) => {
pathParams: {
patientId: patientId,
},
body: payload,
body: {
note: noteField,
thread,
consultation: consultationId,
},
});

if (res?.status === 201) {
Expand Down Expand Up @@ -103,20 +112,42 @@ const ConsultationDoctorNotes = (props: ConsultationDoctorNotesProps) => {

return (
<Page
title="Doctor Notes"
title="Discussion Notes"
className="flex h-screen flex-col"
crumbsReplacements={{
[facilityId]: { name: facilityName },
[patientId]: { name: patientName },
}}
backUrl={`/facility/${facilityId}/patient/${patientId}`}
>
<div className="mx-3 my-2 flex grow flex-col rounded-lg bg-white p-2 sm:mx-10 sm:my-5 sm:p-5">
<div className="relative mx-3 my-2 flex grow flex-col overflow-hidden rounded-lg border border-gray-300 bg-white p-2 sm:mx-10 sm:my-5 sm:p-5">
<div className="absolute inset-x-0 top-0 flex bg-gray-200 text-sm shadow-md">
{Object.values(PATIENT_NOTES_THREADS).map((current) => (
<button
key={current}
className={classNames(
"flex flex-1 justify-center border-b-2 py-2",
thread === current
? "border-primary-500 font-bold text-gray-800"
: "border-gray-300 text-gray-800",
)}
onClick={() => setThread(current)}
>
{
{
10: "Doctor's Discussions",
20: "Nurse's Discussions",
}[current]
}
</button>
))}
</div>
<PatientConsultationNotesList
state={state}
setState={setState}
reload={reload}
setReload={setReload}
thread={thread}
/>

<div className="relative mx-4 flex items-center">
Expand Down
5 changes: 3 additions & 2 deletions src/Components/Facility/DoctorNote.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ interface DoctorNoteProps {

const DoctorNote = (props: DoctorNoteProps) => {
const { state, handleNext, setReload, disableEdit } = props;

return (
<div
className="m-2 flex h-[390px] grow flex-col-reverse overflow-auto bg-white"
Expand All @@ -31,7 +32,7 @@ const DoctorNote = (props: DoctorNoteProps) => {
dataLength={state.notes.length}
scrollableTarget="patient-notes-list"
>
{state.notes.map((note: any) => (
{state.notes.map((note) => (
<PatientNoteCard
note={note}
key={note.id}
Expand All @@ -41,7 +42,7 @@ const DoctorNote = (props: DoctorNoteProps) => {
))}
</InfiniteScroll>
) : (
<div className="mt-2 flex items-center justify-center text-2xl font-bold text-gray-500">
<div className="mt-2 flex h-full items-center justify-center text-2xl font-bold text-gray-500">
No Notes Found
</div>
)}
Expand Down
12 changes: 9 additions & 3 deletions src/Components/Facility/PatientConsultationNotesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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);
Expand All @@ -31,6 +32,7 @@ const PatientConsultationNotesList = (props: PatientNotesProps) => {
},
query: {
consultation: consultationId,
thread,
offset: (state.cPage - 1) * RESULTS_PER_PAGE_LIMIT,
},
});
Expand Down Expand Up @@ -60,6 +62,10 @@ const PatientConsultationNotesList = (props: PatientNotesProps) => {
}
}, [reload]);

useEffect(() => {
fetchNotes();
}, [thread]);

useEffect(() => {
setReload?.(true);
}, []);
Expand All @@ -76,7 +82,7 @@ const PatientConsultationNotesList = (props: PatientNotesProps) => {

if (isLoading && !state.notes.length) {
return (
<div className=" flex h-[400px] w-full items-center justify-center bg-white">
<div className="flex h-full w-full items-center justify-center bg-white">
<CircularProgress />
</div>
);
Expand Down
16 changes: 12 additions & 4 deletions src/Components/Facility/PatientNotesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand All @@ -13,20 +13,24 @@ 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);

const fetchNotes = async () => {
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) {
Expand All @@ -52,6 +56,10 @@ const PatientNotesList = (props: PatientNotesProps) => {
}
}, [reload]);

useEffect(() => {
fetchNotes();
}, [thread]);

useEffect(() => {
setReload(true);
}, []);
Expand All @@ -68,7 +76,7 @@ const PatientNotesList = (props: PatientNotesProps) => {

if (isLoading && !state.notes.length) {
return (
<div className=" flex h-[400px] w-full items-center justify-center bg-white">
<div className="flex h-full w-full items-center justify-center bg-white">
<CircularProgress />
</div>
);
Expand Down
49 changes: 38 additions & 11 deletions src/Components/Facility/PatientNotesSlideover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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) {
Expand Down Expand Up @@ -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",
Expand All @@ -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" });
Expand Down Expand Up @@ -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)}
>
<span className="font-semibold">{"Doctor's Notes"}</span>
<span className="font-semibold">Discussion Notes</span>
{notesActionIcons}
</div>
) : (
<div className="flex h-screen w-full -translate-y-0 flex-col text-clip border-2 border-b-0 border-primary-800 bg-white pb-3 transition-all sm:h-[500px] sm:rounded-t-md ">
{/* Doctor Notes Header */}
<div className="flex w-full items-center justify-between bg-primary-800 p-2 px-4 text-white">
<span className="font-semibold">{"Doctor's Notes"}</span>
<span className="font-semibold">Discussion Notes</span>
{notesActionIcons}
</div>
{/* Doctor Notes Body */}
<div className="flex bg-primary-800 text-sm">
{Object.values(PATIENT_NOTES_THREADS).map((current) => (
<button
key={current}
className={classNames(
"flex flex-1 justify-center border-b-4 py-1",
thread === current
? "border-primary-500 font-medium text-white"
: "border-primary-800 text-white/70",
)}
onClick={() => setThread(current)}
>
{
{
10: "Doctor's Discussions",
20: "Nurse's Discussions",
}[current]
}
</button>
))}
</div>
<PatientConsultationNotesList
state={state}
setState={setState}
reload={reload}
setReload={setReload}
disableEdit={!patientActive}
thread={thread}
/>
<div className="relative mx-4 flex items-center">
<AutoExpandingTextInputFormField
Expand Down
2 changes: 2 additions & 0 deletions src/Components/Facility/models.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
ConsultationSuggestionValue,
DISCHARGE_REASONS,
PATIENT_NOTES_THREADS,
UserRole,
} from "../../Common/constants";
import { AssetData, AssetLocationType } from "../Assets/AssetTypes";
Expand Down Expand Up @@ -512,6 +513,7 @@ export interface PatientNotesModel {
facility: BaseFacilityModel;
created_by_object: BaseUserModel;
user_type?: UserRole | "RemoteSpecialist";
thread: (typeof PATIENT_NOTES_THREADS)[keyof typeof PATIENT_NOTES_THREADS];
created_date: string;
last_edited_by?: BaseUserModel;
last_edited_date?: string;
Expand Down
Loading

0 comments on commit 7300824

Please sign in to comment.