Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds support for doctors and nurses discussions threads in Discussion Notes #7774

Merged
merged 4 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading