Skip to content

Commit

Permalink
Add edit option for doctor notes
Browse files Browse the repository at this point in the history
  • Loading branch information
Ashesh3 committed Dec 26, 2023
1 parent 9fc041c commit 430d8ec
Show file tree
Hide file tree
Showing 10 changed files with 236 additions and 39 deletions.
4 changes: 2 additions & 2 deletions src/Components/Facility/ConsultationDoctorNotes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ const ConsultationDoctorNotes = (props: ConsultationDoctorNotesProps) => {
notes: [],
cPage: 1,
totalPages: 1,
facilityId: facilityId,
patientId: patientId,
};
const [state, setState] = useState(initialData);

Expand Down Expand Up @@ -98,8 +100,6 @@ const ConsultationDoctorNotes = (props: ConsultationDoctorNotesProps) => {
<PatientConsultationNotesList
state={state}
setState={setState}
patientId={patientId}
facilityId={facilityId}
reload={reload}
setReload={setReload}
/>
Expand Down
10 changes: 8 additions & 2 deletions src/Components/Facility/DoctorNote.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ import { PatientNoteStateType } from "./models";

interface DoctorNoteProps {
state: PatientNoteStateType;
setReload: any;
handleNext: () => void;
}

const DoctorNote = (props: DoctorNoteProps) => {
const { state, handleNext } = props;
const { state, handleNext, setReload } = props;
return (
<div
className="m-2 flex h-[390px] grow flex-col-reverse overflow-auto bg-white"
Expand All @@ -30,7 +31,12 @@ const DoctorNote = (props: DoctorNoteProps) => {
scrollableTarget="patient-notes-list"
>
{state.notes.map((note: any) => (
<PatientNoteCard note={note} key={note.id} />
<PatientNoteCard
state={state}
note={note}
key={note.id}
setReload={setReload}
/>
))}
</InfiniteScroll>
) : (
Expand Down
8 changes: 4 additions & 4 deletions src/Components/Facility/PatientConsultationNotesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import request from "../../Utils/request/request";
interface PatientNotesProps {
state: PatientNoteStateType;
setState: any;
patientId: string;
facilityId: string;
reload?: boolean;
setReload?: any;
}
Expand All @@ -28,7 +26,7 @@ const PatientConsultationNotesList = (props: PatientNotesProps) => {
setIsLoading(true);
const { data }: any = await request(routes.getPatientNotes, {
pathParams: {
patientId: props.patientId,
patientId: props.state.patientId,
},
query: {
consultation: consultationId,
Expand Down Expand Up @@ -81,7 +79,9 @@ const PatientConsultationNotesList = (props: PatientNotesProps) => {
);
}

return <DoctorNote state={state} handleNext={handleNext} />;
return (
<DoctorNote state={state} handleNext={handleNext} setReload={setReload} />
);
};

export default PatientConsultationNotesList;
218 changes: 192 additions & 26 deletions src/Components/Facility/PatientNoteCard.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,202 @@
import { relativeDate, formatDateTime, classNames } from "../../Utils/utils";
import { USER_TYPES_MAP } from "../../Common/constants";
import { PatientNotesModel } from "./models";
import { PatientNoteStateType, PatientNotesModel } from "./models";
import ButtonV2 from "../Common/components/ButtonV2";
import CareIcon from "../../CAREUI/icons/CareIcon";
import { useState } from "react";
import { Error, Success } from "../../Utils/Notifications";
import request from "../../Utils/request/request";
import routes from "../../Redux/api";
import DialogModal from "../Common/Dialog";
import { t } from "i18next";

const PatientNoteCard = ({
state,
note,
setReload,
}: {
state: PatientNoteStateType;
note: PatientNotesModel;
setReload: any;
}) => {
const [isEditing, setIsEditing] = useState(false);
const [noteField, setNoteField] = useState(note.note);
const [showEditHistory, setShowEditHistory] = useState(false);

const onUpdateNote = async () => {
if (noteField === note.note) {
setIsEditing(false);
return;
}
const payload = {
note: noteField,
};
if (!/\S+/.test(noteField)) {
Error({
msg: "Note Should Contain At Least 1 Character",
});
return;
}

const { res } = await request(routes.updatePatientNote, {
pathParams: { patientId: state.patientId, noteId: note.id },
body: payload,
});
if (res?.status === 200) {
Success({ msg: "Note updated successfully" });
setIsEditing(false);
setReload(true);
}
};

const PatientNoteCard = ({ note }: { note: PatientNotesModel }) => {
return (
<div
className={classNames(
"mt-4 flex w-full flex-col rounded-lg border border-gray-300 bg-white p-3 text-gray-800",
note.user_type === "RemoteSpecialist" && "border-primary-400"
)}
>
<div className="flex">
<span className="text-sm font-semibold text-gray-700">
{note.created_by_object?.first_name || "Unknown"}{" "}
{note.created_by_object?.last_name}
</span>
{note.user_type && (
<span className="pl-2 text-sm text-gray-700">
{`(${USER_TYPES_MAP[note.user_type]})`}
</span>
<>
{" "}
<div
className={classNames(
"mt-4 flex w-full flex-col rounded-lg border border-gray-300 bg-white p-3 text-gray-800",
note.user_type === "RemoteSpecialist" && "border-primary-400"
)}
</div>
<span className="whitespace-pre-wrap break-words">{note.note}</span>
<div className="mt-3 text-end text-xs text-gray-500">
<div className="tooltip inline">
<span className="tooltip-text tooltip-left">
{formatDateTime(note.created_date)}
</span>
{relativeDate(note.created_date)}
>
<div className="flex justify-between">
<div>
<div>
<span className="text-sm font-semibold text-gray-700">
{note.created_by_object?.first_name || "Unknown"}{" "}
{note.created_by_object?.last_name}
</span>
{note.user_type && (
<span className="pl-2 text-sm text-gray-700">
{`(${USER_TYPES_MAP[note.user_type]})`}
</span>
)}
</div>
<div className="text-xs text-gray-600">
<div className="tooltip inline">
<span className="tooltip-text tooltip-bottom">
{formatDateTime(note.created_date)}
</span>
Created {relativeDate(note.created_date, true)}
</div>
</div>
{note.edits.length > 1 && (
<div className="flex">
<div
className="cursor-pointer text-xs text-gray-600"
onClick={() => {
setShowEditHistory(true);
}}
>
<div className="tooltip inline">
<span className="tooltip-text tooltip-bottom">
{formatDateTime(note.edits[0].edited_on)}
</span>
Edited {relativeDate(note.edits[0].edited_on, true)}
</div>
<CareIcon
icon="l-history"
className="ml-1 h-4 w-4 pt-[3px] text-primary-600"
/>
</div>
</div>
)}
</div>

<ButtonV2
className="text-gray-500"
ghost
onClick={() => {
if (!isEditing) setIsEditing(true);
}}
>
{isEditing ? (
<CareIcon
icon="l-check-circle"
className="h-5 w-5"
onClick={onUpdateNote}
/>
) : (
<CareIcon icon="l-pen" className="h-5 w-5" />
)}
</ButtonV2>
</div>
{
<div className="mt-2">
{isEditing ? (
<textarea
rows={2}
className="h-20 w-full resize-none rounded-lg border border-gray-300 p-2"
value={noteField}
onChange={(e) => setNoteField(e.target.value)}
></textarea>
) : (
<div className="text-sm text-gray-700">{noteField}</div>
)}
</div>
}
</div>
</div>
{showEditHistory && (
<DialogModal
show={showEditHistory}
onClose={() => setShowEditHistory(false)}
title={t("edit_history")}
>
<div>
<div className="mb-4">
<p className="text-md mt-1 text-gray-500">
Edit History for note
<strong> {note.id}</strong>
</p>
</div>
<div className="h-96 overflow-scroll">
{note.edits.map((edit, index) => {
const isLast = index === note.edits.length - 1;
return (
<div
key={index}
className="my-2 flex flex-col justify-between rounded-lg border border-gray-300 p-4 py-2 transition-colors duration-200 hover:bg-gray-100"
>
<div className="flex">
<div className="grow">
<p className="text-sm font-medium text-gray-500">
{isLast ? "Created" : "Edited"} On
</p>
<p className="text-sm text-gray-900">
{formatDateTime(edit.edited_on)}
</p>
</div>
<div className="grow">
<p className="text-sm font-medium text-gray-500">
{isLast ? "Created" : "Edited"} By
</p>
<p className="text-sm text-gray-900">
{edit.edited_by.username}
</p>
</div>
</div>
<div className="mt-2 grow">
<p className="text-sm font-medium text-gray-500">Note</p>
<p className="text-sm text-gray-900">{edit.note}</p>
</div>
</div>
);
})}
</div>
<div className="flex justify-end">
<ButtonV2
id="view-history-back-button"
variant="secondary"
onClick={() => {
setShowEditHistory(false);
}}
>
{t("close")}
</ButtonV2>
</div>
</div>
</DialogModal>
)}
</>
);
};

Expand Down
4 changes: 3 additions & 1 deletion src/Components/Facility/PatientNotesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ const PatientNotesList = (props: PatientNotesProps) => {
);
}

return <DoctorNote state={state} handleNext={handleNext} />;
return (
<DoctorNote state={state} handleNext={handleNext} setReload={setReload} />
);
};

export default PatientNotesList;
9 changes: 7 additions & 2 deletions src/Components/Facility/PatientNotesSlideover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export default function PatientNotesSlideover(props: PatientNotesProps) {
notes: [],
cPage: 1,
totalPages: 1,
patientId: props.patientId,
facilityId: props.facilityId,
};
const [state, setState] = useState(initialData);

Expand Down Expand Up @@ -141,8 +143,6 @@ export default function PatientNotesSlideover(props: PatientNotesProps) {
<PatientConsultationNotesList
state={state}
setState={setState}
facilityId={facilityId}
patientId={patientId}
reload={reload}
setReload={setReload}
/>
Expand All @@ -157,6 +157,11 @@ export default function PatientNotesSlideover(props: PatientNotesProps) {
errorClassName="hidden"
placeholder="Type your Note"
disabled={!patientActive}
onKeyDown={(e) => {
if (e.key === "Enter") {
onAddNote();
}
}}
/>
<ButtonV2
id="add_doctor_note_button"
Expand Down
11 changes: 11 additions & 0 deletions src/Components/Facility/models.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -487,16 +487,27 @@ export interface BaseUserModel {
last_login: string;
}

export interface PatientNotesEditModel {
id: string;
edited_by: BaseUserModel;
edited_on: string;
note: string;
}

export interface PatientNotesModel {
id: string;
note: string;
facility: BaseFacilityModel;
created_by_object: BaseUserModel;
user_type?: string;
created_date: string;
edits: PatientNotesEditModel[];
}

export interface PatientNoteStateType {
notes: PatientNotesModel[];
patientId: string;
facilityId: string;
cPage: number;
totalPages: number;
}
Expand Down
2 changes: 2 additions & 0 deletions src/Components/Form/FormFields/TextFormField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export type TextFormFieldProps = FormFieldBaseProps<string> & {
leadingPadding?: string | undefined;
min?: string | number;
max?: string | number;
onKeyDown?: (event: React.KeyboardEvent<HTMLInputElement>) => void;
onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void;
onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;
};
Expand Down Expand Up @@ -62,6 +63,7 @@ const TextFormField = forwardRef((props: TextFormFieldProps, ref) => {
onFocus={props.onFocus}
onBlur={props.onBlur}
onChange={(e) => field.handleChange(e.target.value)}
onKeyDown={props.onKeyDown}
/>
);

Expand Down
Loading

0 comments on commit 430d8ec

Please sign in to comment.