From 0fd3547ac6044f7f27d827dcab89018488d797aa Mon Sep 17 00:00:00 2001 From: Shivank Kacker Date: Tue, 28 Jan 2025 14:53:45 +0530 Subject: [PATCH] dummy care plan UI --- public/locale/en.json | 2 + src/Routers/routes/ConsultationRoutes.tsx | 12 ++ src/pages/CarePlan/CarePlan.tsx | 104 +++++++++++++ src/pages/Encounters/EncounterShow.tsx | 2 + .../Encounters/tabs/EncounterCarePlanTab.tsx | 62 ++++++++ src/types/emr/careplan/careplan.ts | 37 +++++ src/types/emr/careplan/careplanApi.ts | 143 ++++++++++++++++++ tailwind.config.js | 3 +- 8 files changed, 363 insertions(+), 2 deletions(-) create mode 100644 src/pages/CarePlan/CarePlan.tsx create mode 100644 src/pages/Encounters/tabs/EncounterCarePlanTab.tsx create mode 100644 src/types/emr/careplan/careplan.ts create mode 100644 src/types/emr/careplan/careplanApi.ts diff --git a/public/locale/en.json b/public/locale/en.json index 1262e486770..68d48cef39c 100644 --- a/public/locale/en.json +++ b/public/locale/en.json @@ -48,6 +48,7 @@ "DOMESTIC_HEALTHCARE_SUPPORT__NO_SUPPORT": "No support", "DOMESTIC_HEALTHCARE_SUPPORT__PAID_CAREGIVER": "Paid caregiver", "ENCOUNTER_TAB__abdm": "ABDM Records", + "ENCOUNTER_TAB__care-plan": "Care Plan", "ENCOUNTER_TAB__feed": "Feed", "ENCOUNTER_TAB__files": "Files", "ENCOUNTER_TAB__medicines": "Medicines", @@ -491,6 +492,7 @@ "care": "CARE", "care_backend": "Care Backend", "care_frontend": "Care Frontend", + "care_plan": "Care Plan", "category": "Category", "category_description": "Choose the category that best describes the resource needed.", "caution": "Caution", diff --git a/src/Routers/routes/ConsultationRoutes.tsx b/src/Routers/routes/ConsultationRoutes.tsx index 41fee1a8479..e58b913c343 100644 --- a/src/Routers/routes/ConsultationRoutes.tsx +++ b/src/Routers/routes/ConsultationRoutes.tsx @@ -3,6 +3,7 @@ import EncounterQuestionnaire from "@/components/Patient/EncounterQuestionnaire" import FileUploadPage from "@/components/Patient/FileUploadPage"; import { AppRoutes } from "@/Routers/AppRouter"; +import CarePlan from "@/pages/CarePlan/CarePlan"; import { EncounterShow } from "@/pages/Encounters/EncounterShow"; import { PrintPrescription } from "@/pages/Encounters/PrintPrescription"; @@ -75,6 +76,17 @@ const consultationRoutes: AppRoutes = { type="encounter" /> ), + "/facility/:facilityId/encounter/:encounterId/care-plan/:careplanId": ({ + facilityId, + encounterId, + careplanId, + }) => ( + + ), }; export default consultationRoutes; diff --git a/src/pages/CarePlan/CarePlan.tsx b/src/pages/CarePlan/CarePlan.tsx new file mode 100644 index 00000000000..fab8823ecd6 --- /dev/null +++ b/src/pages/CarePlan/CarePlan.tsx @@ -0,0 +1,104 @@ +import { useQuery } from "@tanstack/react-query"; +import dayjs from "dayjs"; +import { useTranslation } from "react-i18next"; + +import { Button } from "@/components/ui/button"; +import { + Table, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; + +import PageTitle from "@/components/Common/PageTitle"; + +import { DummyCarePlanRetrieve } from "@/types/emr/careplan/careplanApi"; + +export default function CarePlan(props: { + facilityId: string; + encounterId: string; + careplanId: string; +}) { + const { t } = useTranslation(); + + const planQuery = useQuery({ + queryKey: ["care-plan", props.careplanId], + queryFn: () => DummyCarePlanRetrieve(props.careplanId), + }); + + const careplan = planQuery.data; + + return ( +
+
+ +
+ {dayjs(careplan?.end_date).isBefore(dayjs()) ? ( + "Completed" + ) : dayjs(careplan?.start_date).isAfter(dayjs()) ? ( + Upcoming + ) : ( +
+
+ Active +
+ )} +
+
+ {dayjs(careplan?.start_date).isAfter(dayjs()) + ? "Starts on" + : "Started On"}{" "} + : {dayjs(careplan?.start_date).format("DD/MM/YYYY hh:mm a")} +
+ {dayjs(careplan?.end_date).isAfter(dayjs()) + ? "Ends on" + : "Ended On"}{" "} + : {dayjs(careplan?.end_date).format("DD/MM/YYYY hh:mm a")} +
+
{careplan?.description}
+
+ Addresses + + + + Code + Detail + + + {careplan?.addresses.map((code, i) => ( + + {code.code} + {code.display} + + ))} +
+
+
+ Goals +
+
+
+ + + + + +
+
+ ); +} diff --git a/src/pages/Encounters/EncounterShow.tsx b/src/pages/Encounters/EncounterShow.tsx index 5776ed85fe8..49f9d67143f 100644 --- a/src/pages/Encounters/EncounterShow.tsx +++ b/src/pages/Encounters/EncounterShow.tsx @@ -20,6 +20,7 @@ import { EncounterUpdatesTab } from "@/pages/Encounters/tabs/EncounterUpdatesTab import { Encounter } from "@/types/emr/encounter"; import { Patient } from "@/types/emr/newPatient"; +import { EncounterCarePlanTab } from "./tabs/EncounterCarePlanTab"; import { EncounterNotesTab } from "./tabs/EncounterNotesTab"; export interface EncounterTabProps { @@ -35,6 +36,7 @@ const defaultTabs = { medicines: EncounterMedicinesTab, files: EncounterFilesTab, notes: EncounterNotesTab, + "care-plan": EncounterCarePlanTab, // nursing: EncounterNursingTab, // neurological_monitoring: EncounterNeurologicalMonitoringTab, // pressure_sore: EncounterPressureSoreTab, diff --git a/src/pages/Encounters/tabs/EncounterCarePlanTab.tsx b/src/pages/Encounters/tabs/EncounterCarePlanTab.tsx new file mode 100644 index 00000000000..4269d5a4ab3 --- /dev/null +++ b/src/pages/Encounters/tabs/EncounterCarePlanTab.tsx @@ -0,0 +1,62 @@ +import { useQuery } from "@tanstack/react-query"; +import dayjs from "dayjs"; +import { Link } from "raviger"; + +import SubHeading from "@/CAREUI/display/SubHeading"; + +import { EncounterTabProps } from "@/pages/Encounters/EncounterShow"; +import { DummyCarePlanGet } from "@/types/emr/careplan/careplanApi"; + +export const EncounterCarePlanTab = (props: EncounterTabProps) => { + const { patient, encounter, facilityId } = props; + const { data: carePlans } = useQuery({ + queryKey: ["patient", patient.id, "care-plans"], + queryFn: DummyCarePlanGet, + }); + return ( +
+ +
+ {carePlans?.results.map((careplan, i) => ( + + {careplan.title} +
+ {dayjs(careplan.end_date).isBefore(dayjs()) ? ( + "Completed" + ) : dayjs(careplan.start_date).isAfter(dayjs()) ? ( + Upcoming + ) : ( +
+
+ Active +
+ )} +
+
{careplan.description}
+
+ {dayjs(careplan.start_date).isAfter(dayjs()) + ? "Starts on" + : "Started On"}{" "} + : {dayjs(careplan.start_date).format("DD/MM/YYYY hh:mm a")} +
+ {dayjs(careplan.end_date).isAfter(dayjs()) + ? "Ends on" + : "Ended On"}{" "} + : {dayjs(careplan.end_date).format("DD/MM/YYYY hh:mm a")} +
+
+ 3/4 Goals Complete +
+
+
+
+ + ))} +
+
+ ); +}; diff --git a/src/types/emr/careplan/careplan.ts b/src/types/emr/careplan/careplan.ts new file mode 100644 index 00000000000..9b83a1b9537 --- /dev/null +++ b/src/types/emr/careplan/careplan.ts @@ -0,0 +1,37 @@ +import { BaseModel } from "@/Utils/types"; + +export const CARE_PLAN_STATUS = [ + "draft", + "active", + "completed", + "on-hold", + "cancelled", +] as const; + +export const CARE_PLAN_INTENT = [ + "proposal", + "plan", + "order", + "option", + "directive", +] as const; + +interface Code { + code: string; + display: string; + system: string; +} + +export interface CarePlan extends BaseModel { + status: (typeof CARE_PLAN_STATUS)[number]; + intent: (typeof CARE_PLAN_INTENT)[number]; + title: string; + description: string; + start_date: string; + end_date: string; + patient: string; + encounter: string; + custodian: string; + addresses: Code[]; + notes?: string; +} diff --git a/src/types/emr/careplan/careplanApi.ts b/src/types/emr/careplan/careplanApi.ts new file mode 100644 index 00000000000..5a0d3a1d34a --- /dev/null +++ b/src/types/emr/careplan/careplanApi.ts @@ -0,0 +1,143 @@ +import { UserBareMinimum } from "@/components/Users/models"; + +import { HttpMethod, Type } from "@/Utils/request/api"; +import { PaginatedResponse } from "@/Utils/request/types"; + +import { CarePlan } from "./careplan"; + +const dummyUser: UserBareMinimum = { + id: 1, + first_name: "District", + last_name: "Admin", + last_login: "2025-01-28T07:38:56.574089Z", + user_type: "staff", + username: "devdistrictadmin", + email: "sample@email.com", + external_id: "123", +}; + +const dummyCarePlans: CarePlan[] = [ + { + id: "12345", + created_date: "2025-01-28T10:30:00Z", + modified_date: "2025-01-28T10:45:00Z", + status: "active", + intent: "plan", + title: "Chronic Condition Management Plan", + description: + "A care plan designed to manage the patient's chronic diabetes condition with regular check-ups and medication adherence.", + start_date: "2025-01-01", + end_date: "2025-12-31", + patient: "patient-001", + encounter: "encounter-456", + custodian: "Dr. John Doe", + addresses: [ + { + code: "E11", + display: "Type 2 diabetes mellitus without complications", + system: "ICD-10", + }, + { + code: "R73.03", + display: "Prediabetes", + system: "ICD-10", + }, + ], + notes: + "Patient to follow up every three months with the care team. Adherence to medication and diet plan is critical for achieving desired outcomes.", + created_by: dummyUser, + updated_by: dummyUser, + }, + { + id: "12345", + created_date: "2025-01-28T10:30:00Z", + modified_date: "2025-01-28T10:45:00Z", + status: "active", + intent: "plan", + title: "Chronic Condition Management Plan", + description: + "A care plan designed to manage the patient's chronic diabetes condition with regular check-ups and medication adherence.", + start_date: "2025-01-01", + end_date: "2025-1-21", + patient: "patient-001", + encounter: "encounter-456", + custodian: "Dr. John Doe", + addresses: [ + { + code: "E11", + display: "Type 2 diabetes mellitus without complications", + system: "ICD-10", + }, + { + code: "R73.03", + display: "Prediabetes", + system: "ICD-10", + }, + ], + notes: + "Patient to follow up every three months with the care team. Adherence to medication and diet plan is critical for achieving desired outcomes.", + created_by: dummyUser, + updated_by: dummyUser, + }, + { + id: "12345", + created_date: "2025-01-28T10:30:00Z", + modified_date: "2025-01-28T10:45:00Z", + status: "active", + intent: "plan", + title: "Chronic Condition Management Plan", + description: + "A care plan designed to manage the patient's chronic diabetes condition with regular check-ups and medication adherence.", + start_date: "2025-02-01", + end_date: "2025-12-31", + patient: "patient-001", + encounter: "encounter-456", + custodian: "Dr. John Doe", + addresses: [ + { + code: "E11", + display: "Type 2 diabetes mellitus without complications", + system: "ICD-10", + }, + { + code: "R73.03", + display: "Prediabetes", + system: "ICD-10", + }, + ], + notes: + "Patient to follow up every three months with the care team. Adherence to medication and diet plan is critical for achieving desired outcomes.", + created_by: dummyUser, + updated_by: dummyUser, + }, +]; + +export const DummyCarePlanGet: () => Promise< + PaginatedResponse +> = async () => { + return { + count: 1, + next: "", + previous: "", + results: dummyCarePlans, + }; +}; + +export const DummyCarePlanRetrieve: ( + id: string, +) => Promise = async (id: string) => { + return dummyCarePlans.find((cp) => cp.id === id); +}; + +export default { + getCarePlans: { + path: "/api/v1/patient/{patientId}/care_plan/", + method: HttpMethod.GET, + TRes: Type>(), + }, + retrieveCarePlan: { + path: "/api/v1/patient/{patientId}/care_plan/{carePlanId}/", + method: HttpMethod.GET, + TRes: Type(), + }, +}; diff --git a/tailwind.config.js b/tailwind.config.js index 3235b2673d7..9494c606cfe 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ const colors = require("tailwindcss/colors"); const secondary = { @@ -116,7 +115,7 @@ module.exports = { }, content: [ "./src/**/*.{html,md,js,jsx,ts,tsx}", - "./apps/**/*.{html,md,js,jsx,ts,tsx}", + "./apps/**/!(node_modules)/*.{html,md,js,jsx,ts,tsx}", "./index.html", ], plugins: [