diff --git a/public/locale/en.json b/public/locale/en.json index 6c3c92de78c..623daadcb55 100644 --- a/public/locale/en.json +++ b/public/locale/en.json @@ -744,7 +744,10 @@ "discharge_disposition": "Discharge Disposition", "discharge_from_care": "Discharge from CARE", "discharge_prescription": "Discharge Prescription", + "discharge_summaries": "Discharge Summaries", "discharge_summary": "Discharge Summary", + "discharge_summary_emailed": "Discharged Summary emailed", + "discharge_summary_generated": "Discharge Summary generated", "discharge_summary_not_ready": "Discharge summary is not ready yet.", "discharged": "Discharged", "discharged_on": "Discharged On", @@ -752,6 +755,7 @@ "discharged_patients_empty": "No discharged patients present in this facility", "discharged_to": "Discharged to", "disclaimer": "Disclaimer", + "disclaimer_computer_generated_summary": "Disclaimer: This is a computer generated summary and may not be 100% accurate. Please verify the details before using it.", "discontinue": "Discontinue", "discontinue_caution_note": "Are you sure you want to discontinue this prescription?", "discontinued": "Discontinued", @@ -777,7 +781,7 @@ "dosage_instructions": "Dosage Instructions", "down": "Down", "download": "Download", - "download_discharge_summary": "Download discharge summary", + "download_discharge_summary": "Download Discharge Summary", "download_type": "Download Type", "downloading": "Downloading", "downloading_abha_card": "Generating ABHA Card, Please hold on", @@ -961,6 +965,7 @@ "enter_valid_dob": "Enter a valid date of birth", "enter_valid_dob_age": "Please enter an age greater than 15 years", "enter_year_of_birth_to_verify": "Enter year of birth to verify", + "enter_your_valid_email_address_to_receive_the_discharge_summary": "Enter your valid email address to receive the discharge summary", "entered_in_error": "Entered in Error", "entered_in_error_warning": "This action cannot be undone. The appointment will be marked as entered in error and removed from the system.", "entity_count_one": "{{count}} {{entity}}", @@ -974,6 +979,7 @@ "error_fetching_user_data": "Error while fetching user data", "error_fetching_user_details": "Error while fetching user details: ", "error_fetching_users_data": "Failed to load user data. Please try again later.", + "error_generating_discharge_summary": "Error generating discharge summary", "error_loading_questionnaire_response": "Error loading questionnaire response", "error_updating_encounter": "Error to Updating Encounter", "error_verifying_otp": "Error while verifying OTP, Please request a new OTP", @@ -983,6 +989,7 @@ "etiology_identified": "Etiology identified", "evening_slots": "Evening Slots", "events": "Events", + "example_email_address": "example@email.com", "exception": "Exception", "exception_created": "Exception created successfully", "exception_deleted": "Exception deleted", @@ -1088,6 +1095,8 @@ "gender_is_required": "Gender is required", "general": "General", "general_info_detail": "Provide the patient's personal details, including name, date of birth, gender, and contact information for accurate identification and communication.", + "generate": "Generate", + "generate_discharge_summary": "Generate Discharge Summary", "generate_link_abha": "Generate/Link ABHA Number", "generate_report": "Generate Report", "generated_on": "Generated on:", @@ -1411,6 +1420,7 @@ "no_data_found": "No data found", "no_departments_teams_found": "No Departments or Teams found", "no_diagnoses_recorded": "No diagnoses recorded", + "no_discharge_summaries_found": "No Discharge Summaries found", "no_doctors_found": "No Doctors Found", "no_duplicate_facility": "You should not create duplicate facilities", "no_encounters_found": "No encounters found", @@ -1656,6 +1666,7 @@ "please_enter_confirm_password": "Please confirm your new password", "please_enter_correct_birth_year": "Please enter the correct birth year to verify the patient details.", "please_enter_current_password": "Please enter your current password.", + "please_enter_email_address": "Please enter email address", "please_enter_new_password": "Please enter your new password.", "please_enter_organization_name": "Please enter an organization name", "please_enter_username": "Please enter the username", @@ -1777,7 +1788,9 @@ "referred_to": "Referred to", "refresh": "Refresh", "refresh_list": "Refresh List", + "refreshed": "Refreshed", "refuted": "Refuted", + "regenerate_discharge_summary": "Regenerate Discharge Summary", "register_hospital": "Register Hospital", "register_page_title": "Register As Hospital Administrator", "register_patient": "Register Patient", @@ -2020,6 +2033,7 @@ "send_reset_link": "Send Reset Link", "send_sample_to_collection_centre_description": "Are you sure you want to send the sample to Collection Centre?", "send_sample_to_collection_centre_title": "Send sample to collection centre", + "sending": "Sending", "serial_number": "Serial Number", "serviced_on": "Serviced on", "session_capacity": "Session Capacity", diff --git a/src/Routers/routes/ConsultationRoutes.tsx b/src/Routers/routes/ConsultationRoutes.tsx index 2aaa8c115e8..699964122f3 100644 --- a/src/Routers/routes/ConsultationRoutes.tsx +++ b/src/Routers/routes/ConsultationRoutes.tsx @@ -30,6 +30,19 @@ const consultationRoutes: AppRoutes = { tab={tab} /> ), + "/facility/:facilityId/encounter/:encounterId/:tab/:subPage": ({ + facilityId, + encounterId, + tab, + subPage, + }) => ( + + ), "/facility/:facilityId/patient/:patientId/consultation": ({ facilityId, patientId, diff --git a/src/Utils/request/api.tsx b/src/Utils/request/api.tsx index 5da5881de59..d6084393f41 100644 --- a/src/Utils/request/api.tsx +++ b/src/Utils/request/api.tsx @@ -525,6 +525,11 @@ const routes = { TRes: Type(), TBody: Type<{ organization: string }>(), }, + generateDischargeSummary: { + path: "/api/v1/encounter/{encounterId}/generate_discharge_summary/", + method: "POST", + TRes: Type<{ detail: string }>(), + }, }, // New Patient Routes diff --git a/src/Utils/utils.ts b/src/Utils/utils.ts index 78987ad8c59..3198b10bcd3 100644 --- a/src/Utils/utils.ts +++ b/src/Utils/utils.ts @@ -5,10 +5,6 @@ import dayjs from "@/Utils/dayjs"; import { Time } from "@/Utils/types"; import { Patient } from "@/types/emr/newPatient"; import { PatientModel } from "@/types/emr/patient"; -import { - Organization, - OrganizationParent, -} from "@/types/organization/organization"; const DATE_FORMAT = "DD/MM/YYYY"; const TIME_FORMAT = "hh:mm A"; @@ -230,16 +226,28 @@ export const conditionalAttribute = ( return condition ? attributes : {}; }; -export const stringifyGeoOrganization = (org: Organization) => { +export const conditionalArrayAttribute = ( + condition: boolean, + attributes: T[], +) => { + return condition ? attributes : []; +}; + +export const stringifyNestedObject = < + T extends { name: string; parent?: Partial }, +>( + obj: T, + separator = ", ", +) => { const levels: string[] = []; - let current: OrganizationParent | undefined = org; + let current: Partial | undefined = obj; while (current?.name) { levels.push(current.name); current = current.parent; } - return levels.join(", "); + return levels.join(separator); }; export const mergeAutocompleteOptions = ( diff --git a/src/components/Facility/ConsultationDetails/QuickAccess.tsx b/src/components/Facility/ConsultationDetails/QuickAccess.tsx index 9100c0efc37..649bfe6ef8b 100644 --- a/src/components/Facility/ConsultationDetails/QuickAccess.tsx +++ b/src/components/Facility/ConsultationDetails/QuickAccess.tsx @@ -10,6 +10,7 @@ import LinkDepartmentsSheet from "@/components/Patient/LinkDepartmentsSheet"; import useQuestionnaireOptions from "@/hooks/useQuestionnaireOptions"; +import { stringifyNestedObject } from "@/Utils/utils"; import { Encounter } from "@/types/emr/encounter"; interface QuickAccessProps { @@ -85,7 +86,7 @@ export default function QuickAccess({ encounter }: QuickAccessProps) { variant="outline" title={`Organization: ${org.name}${org.description ? ` - ${org.description}` : ""}`} > - {org.name} + {stringifyNestedObject(org)} )) : t("no_organizations_added_yet")} diff --git a/src/components/Files/FilesTab.tsx b/src/components/Files/FilesTab.tsx index 634831c61f1..e092adfcae7 100644 --- a/src/components/Files/FilesTab.tsx +++ b/src/components/Files/FilesTab.tsx @@ -1,7 +1,9 @@ -import { useQuery } from "@tanstack/react-query"; +import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import dayjs from "dayjs"; import { t } from "i18next"; +import { Link } from "raviger"; import { useEffect, useState } from "react"; +import { toast } from "sonner"; import { cn } from "@/lib/utils"; @@ -25,7 +27,7 @@ import { TableHeader, TableRow, } from "@/components/ui/table"; -import { Tabs, TabsContent } from "@/components/ui/tabs"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Tooltip, TooltipContent, @@ -46,7 +48,9 @@ import useFilters from "@/hooks/useFilters"; import { FILE_EXTENSIONS } from "@/common/constants"; import routes from "@/Utils/request/api"; +import mutate from "@/Utils/request/mutate"; import query from "@/Utils/request/query"; +import { HTTPError } from "@/Utils/request/types"; import { usePermissions } from "@/context/PermissionContext"; import { Encounter } from "@/types/emr/encounter"; import { Patient } from "@/types/emr/newPatient"; @@ -57,10 +61,11 @@ export interface FilesTabProps { patientId?: string; encounter?: Encounter; patient?: Patient; + subPage?: string; } export const FilesTab = (props: FilesTabProps) => { - const { patientId, type, encounter } = props; + const { patientId, type, encounter, subPage = "all" } = props; const { qParams, updateQuery, Pagination, resultsPerPage } = useFilters({ limit: 14, }); @@ -72,6 +77,7 @@ export const FilesTab = (props: FilesTabProps) => { useState(null); const [openAudioPlayerDialog, setOpenAudioPlayerDialog] = useState(false); const { hasPermission } = usePermissions(); + const queryClient = useQueryClient(); const associatingId = { @@ -81,22 +87,30 @@ export const FilesTab = (props: FilesTabProps) => { const fileCategories = [ { value: "all", label: "All" }, - { value: "imaging", label: "Imaging" }, - { value: "lab_reports", label: "Lab Reports" }, - { value: "documents", label: "Documents" }, { value: "audio", label: "Audio" }, + { value: "xray", label: "X-Ray" }, + { value: "identity_proof", label: "Identity Proof" }, + { value: "unspecified", label: "Unspecified" }, + { value: "discharge_summary", label: "Discharge Summary" }, ] as const; - const handleTabChange = (value: (typeof fileCategories)[number]["value"]) => { - updateQuery({ file_category: value === "all" ? undefined : value }); - }; + const { mutate: generateDischargeSummary, isPending: isGenerating } = + useMutation<{ detail: string }, HTTPError>({ + mutationFn: mutate(routes.encounter.generateDischargeSummary, { + pathParams: { encounterId: encounter?.id || "" }, + }), + onSuccess: (response) => { + toast.success(response.detail); + refetch(); + }, + }); const { data: files, isLoading: filesLoading, refetch, } = useQuery({ - queryKey: ["files", type, associatingId, qParams], + queryKey: ["files", type, associatingId, qParams, subPage], queryFn: query(routes.viewUpload, { queryParams: { file_type: type, @@ -106,7 +120,7 @@ export const FilesTab = (props: FilesTabProps) => { ...(qParams.is_archived !== undefined && { is_archived: qParams.is_archived, }), - //file_category: qParams.file_category, + ...(subPage !== "all" && { file_category: subPage }), }, }), }); @@ -636,17 +650,61 @@ export const FilesTab = (props: FilesTabProps) => { fileUpload={fileUpload} associatingId={associatingId} /> - - handleTabChange(value as (typeof fileCategories)[number]["value"]) - } - > -
-
- -
+ + + + + {t("all")} + + + + + {t("discharge_summary")} + + + +
+ + {subPage === "discharge_summary" && ( + <> + + + )} + {subPage === "discharge_summary" && ( + <> + + + )}
diff --git a/src/components/Location/LocationHistorySheet.tsx b/src/components/Location/LocationHistorySheet.tsx index 9e642c5fd89..de0ddb25abb 100644 --- a/src/components/Location/LocationHistorySheet.tsx +++ b/src/components/Location/LocationHistorySheet.tsx @@ -27,7 +27,7 @@ export function LocationHistorySheet({ return ( {trigger} - + {t("location_history")} diff --git a/src/components/Location/LocationTree.tsx b/src/components/Location/LocationTree.tsx index d93b57d3edc..dfc12a235a5 100644 --- a/src/components/Location/LocationTree.tsx +++ b/src/components/Location/LocationTree.tsx @@ -48,7 +48,7 @@ function LocationNode({ return ( -
+
- +