From 159bfa48116e6232ea6fd863e493f560dca2e491 Mon Sep 17 00:00:00 2001 From: Amjith Titus Date: Mon, 24 Feb 2025 14:35:03 +0530 Subject: [PATCH 1/5] Encounter Info Card --- public/locale/en.json | 1 + .../Patient/EncounterQuestionnaire.tsx | 5 + src/pages/Encounters/EncounterInfoCard.tsx | 128 ++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 src/pages/Encounters/EncounterInfoCard.tsx diff --git a/public/locale/en.json b/public/locale/en.json index 1418c94c8ec..d0b8ca7c1c1 100644 --- a/public/locale/en.json +++ b/public/locale/en.json @@ -1537,6 +1537,7 @@ "onset": "Onset", "op_encounter": "OP Encounter", "op_file_closed": "OP file closed", + "op_number": "OP Number", "open": "Open", "open_camera": "Open Camera", "open_live_monitoring": "Open Live Monitoring", diff --git a/src/components/Patient/EncounterQuestionnaire.tsx b/src/components/Patient/EncounterQuestionnaire.tsx index 90de3924f2c..2189482c72b 100644 --- a/src/components/Patient/EncounterQuestionnaire.tsx +++ b/src/components/Patient/EncounterQuestionnaire.tsx @@ -8,6 +8,8 @@ import { QuestionnaireForm } from "@/components/Questionnaire/QuestionnaireForm" import useAppHistory from "@/hooks/useAppHistory"; +import EncounterInfoCard from "@/pages/Encounters/EncounterInfoCard"; + interface Props { facilityId: string; patientId: string; @@ -26,6 +28,9 @@ export default function EncounterQuestionnaire({ const { goBack } = useAppHistory(); return ( + {encounterId && ( + + )} ; + } + + if (!encounter) { + return null; + } + + const { patient } = encounter; + + return ( +
+
+
+ +
+ +
+
+
+

{patient.name}

+
+ {formatPatientAge(patient, true)} •{" "} + {t(`GENDER__${patient.gender}`)} +
+
+
+
+
+
+ + {t("start_date")}: + + {encounter.period.start + ? formatDateTime(encounter.period.start) + : t("not_started")} + + + + {t("end_date")}: + + {encounter.period.end + ? formatDateTime(encounter.period.end) + : t("ongoing")} + + + + {t("op_number")}:{" "} + {encounter.external_identifier} + + + {completedEncounterStatus.includes(encounter.status) ? ( + + ) : ( + + )} + {t(`encounter_status__${encounter.status}`)} + + {patient.blood_group && ( + + + {patient.blood_group?.replace("_", " ")} + + )} +
+
+ ); +} From d9e254a83b2517e83eab79e4c6723a9641cc6046 Mon Sep 17 00:00:00 2001 From: Amjith Titus Date: Tue, 25 Feb 2025 13:08:57 +0530 Subject: [PATCH 2/5] OP number, Mobile view --- public/locale/en.json | 1 - src/pages/Encounters/EncounterInfoCard.tsx | 20 +++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/public/locale/en.json b/public/locale/en.json index d0b8ca7c1c1..1418c94c8ec 100644 --- a/public/locale/en.json +++ b/public/locale/en.json @@ -1537,7 +1537,6 @@ "onset": "Onset", "op_encounter": "OP Encounter", "op_file_closed": "OP file closed", - "op_number": "OP Number", "open": "Open", "open_camera": "Open Camera", "open_live_monitoring": "Open Live Monitoring", diff --git a/src/pages/Encounters/EncounterInfoCard.tsx b/src/pages/Encounters/EncounterInfoCard.tsx index 15d6aa13099..35cd456ce07 100644 --- a/src/pages/Encounters/EncounterInfoCard.tsx +++ b/src/pages/Encounters/EncounterInfoCard.tsx @@ -59,7 +59,7 @@ export default function PatientInfoCard(props: PatientInfoCardProps) { -
+
- - {t("op_number")}:{" "} - {encounter.external_identifier} - + {encounter.external_identifier && ( + + {t("ip_op_obs_emr_number")}:{" "} + {encounter.external_identifier} + + )} Date: Tue, 25 Feb 2025 15:17:04 +0530 Subject: [PATCH 3/5] Reuse existing PatientInfoCard in disabled state --- .../Patient/EncounterQuestionnaire.tsx | 83 ++++-- src/components/Patient/PatientInfoCard.tsx | 243 ++++++++++-------- src/pages/Encounters/EncounterInfoCard.tsx | 130 ---------- 3 files changed, 192 insertions(+), 264 deletions(-) delete mode 100644 src/pages/Encounters/EncounterInfoCard.tsx diff --git a/src/components/Patient/EncounterQuestionnaire.tsx b/src/components/Patient/EncounterQuestionnaire.tsx index 2189482c72b..a74a5f240af 100644 --- a/src/components/Patient/EncounterQuestionnaire.tsx +++ b/src/components/Patient/EncounterQuestionnaire.tsx @@ -1,14 +1,18 @@ +import { useQuery } from "@tanstack/react-query"; import { t } from "i18next"; import { navigate } from "raviger"; import { Card, CardContent } from "@/components/ui/card"; import Page from "@/components/Common/Page"; +import PatientInfoCard from "@/components/Patient/PatientInfoCard"; import { QuestionnaireForm } from "@/components/Questionnaire/QuestionnaireForm"; import useAppHistory from "@/hooks/useAppHistory"; -import EncounterInfoCard from "@/pages/Encounters/EncounterInfoCard"; +import routes from "@/Utils/request/api"; +import query from "@/Utils/request/query"; +import { formatDateTime } from "@/Utils/utils"; interface Props { facilityId: string; @@ -26,32 +30,61 @@ export default function EncounterQuestionnaire({ subjectType, }: Props) { const { goBack } = useAppHistory(); + const { data: encounter } = useQuery({ + queryKey: ["encounter", encounterId], + queryFn: query(routes.encounter.get, { + pathParams: { id: encounterId ?? "" }, + queryParams: { facility: facilityId }, + }), + enabled: !!encounterId, + }); return ( - {encounterId && ( - - )} - - - { - if (encounterId) { - navigate( - `/facility/${facilityId}/patient/${patientId}/encounter/${encounterId}/updates`, - ); - } else { - navigate(`/patient/${patientId}/updates`); - } - }} - onCancel={() => goBack()} - /> - - +
+ {encounter && ( +
+ {}} + disabled={true} + /> + +
+
+
+ + {t("last_modified")}:{" "} + +   + {formatDateTime(encounter.modified_date)} +
+
+
+
+ )} + + + { + if (encounterId) { + navigate( + `/facility/${facilityId}/patient/${patientId}/encounter/${encounterId}/updates`, + ); + } else { + navigate(`/patient/${patientId}/updates`); + } + }} + onCancel={() => goBack()} + /> + + +
); } diff --git a/src/components/Patient/PatientInfoCard.tsx b/src/components/Patient/PatientInfoCard.tsx index 1212a95300d..21fa39b3908 100644 --- a/src/components/Patient/PatientInfoCard.tsx +++ b/src/components/Patient/PatientInfoCard.tsx @@ -45,6 +45,7 @@ import { import { Avatar } from "@/components/Common/Avatar"; import { LocationHistorySheet } from "@/components/Location/LocationHistorySheet"; import { LocationTree } from "@/components/Location/LocationTree"; +import LinkDepartmentsSheet from "@/components/Patient/LinkDepartmentsSheet"; import { PLUGIN_Component } from "@/PluginEngine"; import routes from "@/Utils/request/api"; @@ -52,17 +53,17 @@ import mutate from "@/Utils/request/mutate"; import { formatDateTime, formatPatientAge } from "@/Utils/utils"; import { Encounter, completedEncounterStatus } from "@/types/emr/encounter"; import { Patient } from "@/types/emr/newPatient"; - -import LinkDepartmentsSheet from "./LinkDepartmentsSheet"; +import { FacilityOrganization } from "@/types/facilityOrganization/facilityOrganization"; export interface PatientInfoCardProps { patient: Patient; encounter: Encounter; fetchPatientData?: (state: { aborted: boolean }) => void; + disabled?: boolean; } export default function PatientInfoCard(props: PatientInfoCardProps) { - const { patient, encounter } = props; + const { patient, encounter, disabled = false } = props; const { t } = useTranslation(); const queryClient = useQueryClient(); @@ -324,36 +325,36 @@ export default function PatientInfoCard(props: PatientInfoCardProps) { ) } - - {encounter.organizations.map((org) => ( - - - {org.name} - - ))} - {encounter.organizations.length === 0 && ( - - - Add Organizations - - )} -
- } - /> + {!disabled ? ( + + {encounter.organizations.map((org) => + organizationBadge(org), + )} + {encounter.organizations.length === 0 && ( + + + Add Organizations + + )} +
+ } + /> + ) : ( +
+ {encounter.organizations.map((org) => + organizationBadge(org), + )} +
+ )} {props.encounter.current_location ? ( @@ -401,18 +402,22 @@ export default function PatientInfoCard(props: PatientInfoCardProps) { -
- + {!disabled && ( + <> +
+ + + )}
@@ -439,78 +444,98 @@ export default function PatientInfoCard(props: PatientInfoCardProps) { className="flex flex-col items-center justify-end gap-4 px-4 py-1 2xl:flex-row" id="consultation-buttons" > - {!completedEncounterStatus.includes(encounter.status) && ( -
- - - - - - - {t("actions")} - - - {t("treatment_summary")} - - - - - {t("discharge_summary")} - - - - e.preventDefault()}> - {t("mark_as_complete")} + {!completedEncounterStatus.includes(encounter.status) && + !disabled && ( +
+ + + + + + + {t("actions")} + + + {t("treatment_summary")} + - + + + {t("discharge_summary")} + + + + e.preventDefault()}> + {t("mark_as_complete")} + + + + + + + + + {t("mark_as_complete")} + + + {t("mark_encounter_as_complete_confirmation")} + + + - - - - - {t("mark_as_complete")} - - {t("mark_encounter_as_complete_confirmation")} - - - - - - {t("cancel")} + + {t("cancel")} - - {t("mark_as_complete")} - - - - -
- )} + + {t("mark_as_complete")} + + + +
+
+ )}
); + + function organizationBadge(org: FacilityOrganization) { + return ( + + + {org.name} + + ); + } } diff --git a/src/pages/Encounters/EncounterInfoCard.tsx b/src/pages/Encounters/EncounterInfoCard.tsx deleted file mode 100644 index 35cd456ce07..00000000000 --- a/src/pages/Encounters/EncounterInfoCard.tsx +++ /dev/null @@ -1,130 +0,0 @@ -import { useQuery } from "@tanstack/react-query"; -import { CircleCheck, CircleDashed, Droplet } from "lucide-react"; -import { useTranslation } from "react-i18next"; - -import { Badge } from "@/components/ui/badge"; - -import { Avatar } from "@/components/Common/Avatar"; -import Loading from "@/components/Common/Loading"; - -import routes from "@/Utils/request/api"; -import query from "@/Utils/request/query"; -import { formatDateTime, formatPatientAge } from "@/Utils/utils"; -import { completedEncounterStatus } from "@/types/emr/encounter"; - -export interface PatientInfoCardProps { - encounterId: string; - facilityId: string; -} - -export default function PatientInfoCard(props: PatientInfoCardProps) { - const { encounterId, facilityId } = props; - const { t } = useTranslation(); - - const { data: encounter, isLoading } = useQuery({ - queryKey: ["encounter", encounterId], - queryFn: query(routes.encounter.get, { - pathParams: { id: encounterId }, - queryParams: { facility: facilityId }, - }), - enabled: !!encounterId, - }); - - if (isLoading) { - return ; - } - - if (!encounter) { - return null; - } - - const { patient } = encounter; - - return ( -
-
-
- -
- -
-
-
-

{patient.name}

-
- {formatPatientAge(patient, true)} •{" "} - {t(`GENDER__${patient.gender}`)} -
-
-
-
-
-
- - {t("start_date")}: - - {encounter.period.start - ? formatDateTime(encounter.period.start) - : t("not_started")} - - - - {t("end_date")}: - - {encounter.period.end - ? formatDateTime(encounter.period.end) - : t("ongoing")} - - - {encounter.external_identifier && ( - - {t("ip_op_obs_emr_number")}:{" "} - {encounter.external_identifier} - - )} - - {completedEncounterStatus.includes(encounter.status) ? ( - - ) : ( - - )} - {t(`encounter_status__${encounter.status}`)} - - {patient.blood_group && ( - - - {patient.blood_group?.replace("_", " ")} - - )} -
-
- ); -} From 2c7121b219c5914062de79e15a13919d866c9972 Mon Sep 17 00:00:00 2001 From: Amjith Titus Date: Wed, 26 Feb 2025 20:21:52 +0530 Subject: [PATCH 4/5] Rename prop to disableButtons --- src/components/Patient/EncounterQuestionnaire.tsx | 2 +- src/components/Patient/PatientInfoCard.tsx | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/Patient/EncounterQuestionnaire.tsx b/src/components/Patient/EncounterQuestionnaire.tsx index a74a5f240af..10799afe296 100644 --- a/src/components/Patient/EncounterQuestionnaire.tsx +++ b/src/components/Patient/EncounterQuestionnaire.tsx @@ -47,7 +47,7 @@ export default function EncounterQuestionnaire({ patient={encounter.patient} encounter={encounter} fetchPatientData={() => {}} - disabled={true} + disableButtons={true} />
diff --git a/src/components/Patient/PatientInfoCard.tsx b/src/components/Patient/PatientInfoCard.tsx index 21fa39b3908..e9e58409fd3 100644 --- a/src/components/Patient/PatientInfoCard.tsx +++ b/src/components/Patient/PatientInfoCard.tsx @@ -59,11 +59,11 @@ export interface PatientInfoCardProps { patient: Patient; encounter: Encounter; fetchPatientData?: (state: { aborted: boolean }) => void; - disabled?: boolean; + disableButtons?: boolean; } export default function PatientInfoCard(props: PatientInfoCardProps) { - const { patient, encounter, disabled = false } = props; + const { patient, encounter, disableButtons = false } = props; const { t } = useTranslation(); const queryClient = useQueryClient(); @@ -325,7 +325,7 @@ export default function PatientInfoCard(props: PatientInfoCardProps) { ) } - {!disabled ? ( + {!disableButtons ? ( - {!disabled && ( + {!disableButtons && ( <>
+ } + /> {props.encounter.current_location ? ( @@ -422,18 +414,21 @@ export default function PatientInfoCard(props: PatientInfoCardProps) { ) : ( - - - - {t("add_location")} - - + encounter.status !== "completed" && + !disableButtons && ( + + + + {t("add_location")} + + + ) )}