diff --git a/cypress/pageObject/Patients/PatientEncounter.ts b/cypress/pageObject/Patients/PatientEncounter.ts index 95e3b8c1fe0..1ed9dab31cf 100644 --- a/cypress/pageObject/Patients/PatientEncounter.ts +++ b/cypress/pageObject/Patients/PatientEncounter.ts @@ -76,10 +76,10 @@ export class PatientEncounter { } clickPatientDetailsButton() { - cy.verifyAndClickElement( - '[data-cy="patient-details-button"]', - "Patient Details", - ); + cy.get('[data-cy="patient-details-button"]') + .filter(":visible") + .first() + .click(); return this; } diff --git a/public/locale/en.json b/public/locale/en.json index a962bbde003..0297e69b30c 100644 --- a/public/locale/en.json +++ b/public/locale/en.json @@ -562,6 +562,7 @@ "claim__use__claim": "Claim", "claim__use__preauthorization": "Pre Authorization", "claims": "Claims", + "class_history": "Class History", "clear": "Clear", "clear_all_filters": "Clear all filters", "clear_home_facility": "Clear Home Facility", @@ -1242,6 +1243,7 @@ "location_created": "Location Created", "location_details": "Location Details", "location_form": "Location Form", + "location_history": "Location History", "location_management": "Location Management", "location_updated": "Location Updated", "location_updated_successfully": "Location updated successfully", @@ -1482,6 +1484,7 @@ "on": "on", "on_emergency_basis": " on emergency basis", "on_hold": "On Hold", + "ongoing": "Ongoing", "ongoing_medications": "Ongoing Medications", "online": "Online", "only_indian_mobile_numbers_supported": "Currently only Indian numbers are supported", @@ -2053,6 +2056,7 @@ "state": "State", "state_reason_for_archiving": "State reason for archiving {{name}} file?", "status": "Status", + "status_history": "Status History", "stop": "Stop", "stop_recording": "Stop Recording", "stopped": "Stopped", @@ -2198,6 +2202,7 @@ "update_facility": "Update Facility", "update_facility_middleware_success": "Facility middleware updated successfully", "update_hospitalisation_details": "Update Hospitalisation Details", + "update_location": "Update Location", "update_log": "Update Log", "update_password": "Update Password", "update_patient_details": "Update Patient Details", diff --git a/src/components/Location/LocationHistorySheet.tsx b/src/components/Location/LocationHistorySheet.tsx new file mode 100644 index 00000000000..9e642c5fd89 --- /dev/null +++ b/src/components/Location/LocationHistorySheet.tsx @@ -0,0 +1,49 @@ +import { useTranslation } from "react-i18next"; + +import { ScrollArea } from "@/components/ui/scroll-area"; +import { + Sheet, + SheetContent, + SheetHeader, + SheetTitle, + SheetTrigger, +} from "@/components/ui/sheet"; + +import { LocationHistory } from "@/types/emr/encounter"; + +import { LocationTree } from "./LocationTree"; + +interface LocationHistorySheetProps { + trigger: React.ReactNode; + history: LocationHistory[]; +} + +export function LocationHistorySheet({ + trigger, + history, +}: LocationHistorySheetProps) { + const { t } = useTranslation(); + + return ( + + {trigger} + + + {t("location_history")} + + + {history.map((item, index) => ( +
+ +
+ ))} +
+
+
+ ); +} diff --git a/src/components/Location/LocationTree.tsx b/src/components/Location/LocationTree.tsx new file mode 100644 index 00000000000..d93b57d3edc --- /dev/null +++ b/src/components/Location/LocationTree.tsx @@ -0,0 +1,105 @@ +import { format } from "date-fns"; +import React from "react"; + +import CareIcon from "@/CAREUI/icons/CareIcon"; + +import { LocationList } from "@/types/location/location"; + +interface LocationPathProps { + location: LocationList; + datetime?: string; + isLatest?: boolean; + showTimeline?: boolean; +} + +interface LocationNodeProps { + location: LocationList; + isLast: boolean; + datetime?: string; + children?: React.ReactNode; +} + +function LocationNode({ + location, + isLast, + datetime, + children, +}: LocationNodeProps) { + if (!location.parent?.id) { + return ( +
+
+ + + {location.name} + +
+ {children} + {isLast && datetime && ( +
+ {format(new Date(datetime), "MMM d, yyyy h:mm a")} +
+ )} +
+ ); + } + + return ( + +
+
+ + + {location.name} + +
+ {children} + {isLast && datetime && ( +
+ {format(new Date(datetime), "MMM d, yyyy h:mm a")} +
+ )} +
+
+ ); +} + +export function LocationTree({ + location, + datetime, + isLatest, + showTimeline = false, +}: LocationPathProps) { + return ( +
+ {showTimeline && ( +
+
+
+ +
+ {!isLatest &&
} +
+ )} +
+ +
+
+ ); +} diff --git a/src/components/Patient/PatientInfoCard.tsx b/src/components/Patient/PatientInfoCard.tsx index ed4877359a5..85c99f2846b 100644 --- a/src/components/Patient/PatientInfoCard.tsx +++ b/src/components/Patient/PatientInfoCard.tsx @@ -43,6 +43,8 @@ import { } from "@/components/ui/popover"; import { Avatar } from "@/components/Common/Avatar"; +import { LocationHistorySheet } from "@/components/Location/LocationHistorySheet"; +import { LocationTree } from "@/components/Location/LocationTree"; import { PLUGIN_Component } from "@/PluginEngine"; import routes from "@/Utils/request/api"; @@ -110,7 +112,18 @@ export default function PatientInfoCard(props: PatientInfoCardProps) { className="mb-2 flex flex-col text-xl font-semibold capitalize lg:hidden" id="patient-name-consultation" > - {patient.name} + + {patient.name} + +
{formatPatientAge(patient, true)} •{" "} {t(`GENDER__${patient.gender}`)} @@ -124,7 +137,18 @@ export default function PatientInfoCard(props: PatientInfoCardProps) { className="hidden flex-row text-xl font-semibold capitalize lg:flex" id="patient-name-consultation" > - {patient.name} + + {patient.name} + +
{formatPatientAge(patient, true)} •{" "} {t(`GENDER__${patient.gender}`)} @@ -133,28 +157,28 @@ export default function PatientInfoCard(props: PatientInfoCardProps) {
- Start Date + {t("start_date")} {props.encounter.period.start ? formatDateTime(props.encounter.period.start) - : "Not started"} + : t("not_started")}
- End Date + {t("end_date")} {props.encounter.period.end ? formatDateTime(props.encounter.period.end) - : "Ongoing"} + : t("ongoing")}
{props.encounter.external_identifier && (
- Hospital Identifier + {t("hospital_identifier")} {props.encounter.external_identifier} @@ -192,7 +216,9 @@ export default function PatientInfoCard(props: PatientInfoCardProps) {
-

Status History

+

+ {t("status_history")} +

{encounter.status_history.history.map( (history, index) => (
- {props.encounter.current_location && ( - - -
- - - {props.encounter.current_location.name} - - -
-
- -
-

- Current Location -

-

- {props.encounter.current_location.name} -

-

- {props.encounter.current_location.description} -

-
- -
-
- )}
@@ -270,7 +259,9 @@ export default function PatientInfoCard(props: PatientInfoCardProps) {
-

Class History

+

+ {t(`class_history`)} +

{encounter.encounter_class_history.history.map( (history, index) => (
} /> + {props.encounter.current_location ? ( + + +
+ + + {props.encounter.current_location.name} + + +
+
+ +
+
+

+ {t("location")} +

+ + + + +
+ } + /> +
+
+ +
+ +
+ + + ) : ( + + + + {t("add_location")} + + + )}
diff --git a/src/pages/Encounters/EncounterShow.tsx b/src/pages/Encounters/EncounterShow.tsx index 1f065b6e50c..b060fcc3d2c 100644 --- a/src/pages/Encounters/EncounterShow.tsx +++ b/src/pages/Encounters/EncounterShow.tsx @@ -145,14 +145,6 @@ export const EncounterShow = (props: Props) => { )} )} */} - - {t("patient_details")} -
diff --git a/src/types/emr/encounter.ts b/src/types/emr/encounter.ts index f63a118a83f..45c6602b763 100644 --- a/src/types/emr/encounter.ts +++ b/src/types/emr/encounter.ts @@ -117,6 +117,12 @@ export type StatusHistory = { history: History[]; }; +export type LocationHistory = { + start_datetime: string; + location: LocationList; + status: string; +}; + export interface Encounter { id: string; patient: Patient; @@ -138,6 +144,7 @@ export interface Encounter { status_history: StatusHistory; organizations: FacilityOrganization[]; current_location: LocationList; + location_history: LocationHistory[]; } export interface EncounterEditRequest { diff --git a/src/types/location/location.ts b/src/types/location/location.ts index cfb16dd13c3..3738dce63f7 100644 --- a/src/types/location/location.ts +++ b/src/types/location/location.ts @@ -45,6 +45,7 @@ export interface LocationDetail extends LocationBase { export interface LocationList extends LocationBase { id: string; has_children: boolean; + parent?: LocationList; } export interface LocationWrite extends LocationBase {