Skip to content

Commit

Permalink
Merge pull request #10447 from ohcnetwork/treatment-summary-ui
Browse files Browse the repository at this point in the history
Treatment Summary UI
  • Loading branch information
amjithtitus09 authored Feb 11, 2025
2 parents af4e4c1 + a411570 commit 30ecfd2
Show file tree
Hide file tree
Showing 20 changed files with 844 additions and 382 deletions.
5 changes: 5 additions & 0 deletions public/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@
"administered_on": "Administered on",
"administration_dosage_range_error": "Dosage should be between start and target dosage",
"administration_notes": "Administration Notes",
"admission_source": "Admission Source",
"admit_source": "Admit Source",
"admitted": "Admitted",
"admitted_on": "Admitted On",
Expand Down Expand Up @@ -699,6 +700,7 @@
"deleting": "Deleting...",
"demography": "Demography",
"denied_on": "Denied On",
"department": "Department",
"departments": "Departments",
"departments_and_teams": "Departments and Teams",
"describe_why_the_asset_is_not_working": "Describe why the asset is not working",
Expand Down Expand Up @@ -920,6 +922,7 @@
"encounter_suggestion__OP": "Out-patient visit",
"encounter_suggestion__R": "Consultation",
"encounter_suggestion_edit_disallowed": "Not allowed to switch to this option in edit consultation",
"encounter_type": "Encounter Type",
"encounters": "Encounters",
"end_date": "End date",
"end_datetime": "End Date/Time",
Expand Down Expand Up @@ -1303,6 +1306,7 @@
"medication_administration_saved": "Medicine Administration saved",
"medication_already_marked_as_error": "Medication already marked as entered in error",
"medication_taken_between": "Medication Taken Between",
"medications": "Medications",
"medicine": "Medicine",
"medicine_administration": "Medicine Administration",
"medicine_administration_history": "Medicine Administration History",
Expand Down Expand Up @@ -2197,6 +2201,7 @@
"update_available": "Update Available",
"update_bed": "Update Bed",
"update_department": "Update Department",
"update_encounter": "Update Encounter",
"update_encounter_details": "Update Encounter Details",
"update_existing_facility": "Update the details of the existing facility.",
"update_facility": "Update Facility",
Expand Down
17 changes: 13 additions & 4 deletions src/Routers/routes/ConsultationRoutes.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
import QuestionnaireResponseView from "@/components/Facility/ConsultationDetails/QuestionnaireResponseView";
import EncounterQuestionnaire from "@/components/Patient/EncounterQuestionnaire";
import FileUploadPage from "@/components/Patient/FileUploadPage";
import TreatmentSummary from "@/components/Patient/TreatmentSummary";

import { AppRoutes } from "@/Routers/AppRouter";
import { EncounterShow } from "@/pages/Encounters/EncounterShow";
import { PrintPrescription } from "@/pages/Encounters/PrintPrescription";

const consultationRoutes: AppRoutes = {
"/facility/:facilityId/encounter/:encounterId/prescriptions/print": ({
facilityId,
encounterId,
}) => <PrintPrescription facilityId={facilityId} encounterId={encounterId} />,
"/facility/:facilityId/patient/:patientId/encounter/:encounterId/prescriptions/print":
({ facilityId, encounterId, patientId }) => (
<PrintPrescription
facilityId={facilityId}
encounterId={encounterId}
patientId={patientId}
/>
),
"/facility/:facilityId/patient/:patientId/encounter/:encounterId/treatment_summary":
({ facilityId, encounterId }) => (
<TreatmentSummary facilityId={facilityId} encounterId={encounterId} />
),
"/facility/:facilityId/encounter/:encounterId/:tab": ({
facilityId,
encounterId,
Expand Down
4 changes: 2 additions & 2 deletions src/Utils/request/api.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { PaginatedResponse } from "@/Utils/request/types";
import { AppointmentPatientRegister } from "@/pages/Patient/Utils";
import { Encounter, EncounterEditRequest } from "@/types/emr/encounter";
import { MedicationAdministration } from "@/types/emr/medicationAdministration/medicationAdministration";
import { MedicationStatement } from "@/types/emr/medicationStatement";
import { MedicationStatementRead } from "@/types/emr/medicationStatement";
import { PartialPatientModel, Patient } from "@/types/emr/newPatient";
import {
Observation,
Expand Down Expand Up @@ -655,7 +655,7 @@ const routes = {
list: {
path: "/api/v1/patient/{patientId}/medication/statement/",
method: "GET",
TRes: Type<PaginatedResponse<MedicationStatement>>(),
TRes: Type<PaginatedResponse<MedicationStatementRead>>(),
},
},

Expand Down
75 changes: 74 additions & 1 deletion src/Utils/request/query.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import careConfig from "@careConfig";

import { RESULTS_PER_PAGE_LIMIT } from "@/common/constants";

import { getResponseBody } from "@/Utils/request/request";
import { ApiCallOptions, ApiRoute, HTTPError } from "@/Utils/request/types";
import {
ApiCallOptions,
ApiRoute,
HTTPError,
PaginatedResponse,
} from "@/Utils/request/types";
import { makeHeaders, makeUrl } from "@/Utils/request/utils";
import { sleep } from "@/Utils/utils";

Expand Down Expand Up @@ -113,3 +120,69 @@ const debouncedQuery = <Route extends ApiRoute<unknown, unknown>>(
};
};
query.debounced = debouncedQuery;

/**
* Creates a TanStack Query compatible paginated query function.
*
* This function is useful for fetching paginated data from an API.
* It will fetch all pages of data and return a single array of results.
*
* To disable pagination, set the `maxPages` option to `1`.
* Leaving it unset will fetch all pages.
*
* Example:
* ```tsx
* const { data, isLoading } = useQuery({
* queryKey: ["patient-search", facilityId, search],
* queryFn: query.paginated(patientsApi.search, {
* pathParams: { facilityId },
* queryParams: { limit: 10, offset: 0, search },
* }),
* });
* ```
*/
const paginatedQuery = <
Route extends ApiRoute<PaginatedResponse<unknown>, unknown>,
>(
route: Route,
options?: ApiCallOptions<Route> & { pageSize?: number; maxPages?: number },
) => {
return async ({ signal }: { signal: AbortSignal }) => {
const items: Route["TRes"]["results"] = [];
let hasNextPage = true;
let page = 0;
let count = 0;

const pageSize = options?.pageSize ?? RESULTS_PER_PAGE_LIMIT;

while (hasNextPage) {
const res = await query(route, {
...options,
queryParams: {
limit: pageSize,
offset: page * pageSize,
...options?.queryParams,
},
})({ signal });

count = res.count;
items.push(...res.results);

if (options?.maxPages && page >= options.maxPages - 1) {
hasNextPage = false;
}

if (items.length >= res.count) {
hasNextPage = false;
}

page++;
}

return {
count,
results: items,
};
};
};
query.paginated = paginatedQuery;
2 changes: 0 additions & 2 deletions src/Utils/request/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,5 @@ declare module "@tanstack/react-query" {

export interface PaginatedResponse<TItem> {
count: number;
next: string | null;
previous: string | null;
results: TItem[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import { QuestionnaireResponse } from "@/types/questionnaire/questionnaireRespon
interface Props {
encounter?: Encounter;
patientId: string;
isPrintPreview?: boolean;
onlyUnstructured?: boolean;
}

interface QuestionResponseProps {
Expand Down Expand Up @@ -282,19 +284,26 @@ function ResponseCard({ item }: { item: QuestionnaireResponse }) {
export default function QuestionnaireResponsesList({
encounter,
patientId,
isPrintPreview = false,
onlyUnstructured,
}: Props) {
const { t } = useTranslation();
const [qParams, setQueryParams] = useQueryParams<{ page?: number }>();

const { data: questionnarieResponses, isLoading } = useQuery({
queryKey: ["questionnaireResponses", patientId, qParams],
queryFn: query(routes.getQuestionnaireResponses, {
queryFn: query.paginated(routes.getQuestionnaireResponses, {
pathParams: { patientId },
queryParams: {
...(!isPrintPreview && {
limit: RESULTS_PER_PAGE_LIMIT,
offset: ((qParams.page ?? 1) - 1) * RESULTS_PER_PAGE_LIMIT,
}),
encounter: encounter?.id,
limit: RESULTS_PER_PAGE_LIMIT,
offset: ((qParams.page ?? 1) - 1) * RESULTS_PER_PAGE_LIMIT,
only_unstructured: onlyUnstructured,
},
maxPages: isPrintPreview ? undefined : 1,
pageSize: isPrintPreview ? 100 : RESULTS_PER_PAGE_LIMIT,
}),
});

Expand Down Expand Up @@ -322,24 +331,28 @@ export default function QuestionnaireResponsesList({
</li>
),
)}
<div className="flex w-full items-center justify-center mt-4">
<div
className={cn(
"flex w-full justify-center",
(questionnarieResponses?.count ?? 0) >
RESULTS_PER_PAGE_LIMIT
? "visible"
: "invisible",
)}
>
<PaginationComponent
cPage={qParams.page ?? 1}
defaultPerPage={RESULTS_PER_PAGE_LIMIT}
data={{ totalCount: questionnarieResponses?.count ?? 0 }}
onChange={(page) => setQueryParams({ page })}
/>
{!isPrintPreview && (
<div className="flex w-full items-center justify-center mt-4">
<div
className={cn(
"flex w-full justify-center",
(questionnarieResponses?.count ?? 0) >
RESULTS_PER_PAGE_LIMIT
? "visible"
: "invisible",
)}
>
<PaginationComponent
cPage={qParams.page ?? 1}
defaultPerPage={RESULTS_PER_PAGE_LIMIT}
data={{
totalCount: questionnarieResponses?.count ?? 0,
}}
onChange={(page) => setQueryParams({ page })}
/>
</div>
</div>
</div>
)}
</ul>
)}
</div>
Expand Down
30 changes: 2 additions & 28 deletions src/components/Facility/ConsultationDetails/QuickAccess.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ export default function QuickAccess({ encounter }: QuickAccessProps) {
const { t } = useTranslation();
const questionnaireOptions = useQuestionnaireOptions("encounter_actions");

const encounterSettings = [
{ id: "encounter_settings", label: t("encounter_settings") },
];

return (
<div className="flex flex-col gap-6">
{/* Questionnaire Section */}
Expand All @@ -47,32 +43,10 @@ export default function QuickAccess({ encounter }: QuickAccessProps) {
</section>
)}

{/* Update Encounter Details */}
{encounter.status !== "completed" && (
<section className="text-gray-950 space-y-2">
<h3 className="text-lg font-medium mb-3">
{t("update_encounter_details")}
</h3>
<div>
{encounterSettings.map((item) => (
<div key={item.id} className="flex items-center space-x-2 px-4">
<Link
href={`/facility/${encounter.facility.id}/patient/${encounter.patient.id}/encounter/${encounter.id}/questionnaire/encounter`}
className="text-sm text-gray-950 underline font-semibold"
>
{item.label}
</Link>
</div>
))}
</div>
<div className="w-full border-t border-dashed border-gray-300" />
</section>
)}

{/* Departments and Teams */}
<section>
<div className="flex items-center justify-between mb-3">
<h3 className="text-lg font-medium text-gray-950">
<div className="items-center justify-between mb-3">
<h3 className="text-lg font-medium text-gray-950 mb-1">
{t("departments_and_teams")}
</h3>
<LinkDepartmentsSheet
Expand Down
7 changes: 5 additions & 2 deletions src/components/Medicine/MedicationRequestTable/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ export default function MedicationRequestTable({
className="text-gray-950 hover:text-gray-700 h-9"
>
<Link
href={`/facility/${facilityId}/encounter/${encounterId}/prescriptions/print`}
href={`/facility/${facilityId}/patient/${patientId}/encounter/${encounterId}/prescriptions/print`}
>
<CareIcon icon="l-print" className="mr-2" />
{t("print")}
Expand All @@ -194,7 +194,10 @@ export default function MedicationRequestTable({
<ScrollArea className="h-[calc(100vh-16rem)]">
<div className="min-w-[800px]">
<div className="p-2">
<MedicationsTable medications={displayedMedications} />
<MedicationsTable
patientId={patientId}
encounterId={encounterId}
/>
</div>
{!!stoppedMedications?.results?.length && (
<div
Expand Down
Loading

0 comments on commit 30ecfd2

Please sign in to comment.