Skip to content
4 changes: 2 additions & 2 deletions src/Routers/routes/ConsultationRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,11 @@ const consultationRoutes: AppRoutes = {
),
"/facility/:facilityId/patient/:patientId/encounter/:encounterId/report/template/:templateSlug":
({ encounterId, templateSlug }) => (
<ReportViewer encounterId={encounterId} templateSlug={templateSlug} />
<ReportViewer associatingId={encounterId} templateSlug={templateSlug} />
),
"/facility/:facilityId/patient/:patientId/encounter/:encounterId/report/:reportId":
({ encounterId, reportId }) => (
<ReportViewer encounterId={encounterId} reportId={reportId} />
<ReportViewer associatingId={encounterId} reportId={reportId} />
),
"/facility/:facilityId/patient/:patientId/encounter/:encounterId/questionnaire":
({ facilityId, encounterId, patientId }) => (
Expand Down
20 changes: 20 additions & 0 deletions src/Routers/routes/FacilityRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import MedicationDispenseRedirect from "@/pages/Facility/billing/account/compone
import BedAvailabilityDashboard from "@/pages/Facility/BedAvailabilityDashboard";

import { AppRoutes } from "@/Routers/AppRouter";
import ReportViewer from "@/pages/Encounters/ReportViewer";
import TemplateBuilder from "@/pages/Encounters/TemplateBuilder/TemplateBuilder";
import TemplatePage from "@/pages/Encounters/TemplateBuilder/TemplatePage";
import AccountList from "@/pages/Facility/billing/account/AccountList";
Expand All @@ -28,6 +29,7 @@ import DiagnosticReportPrint from "@/pages/Facility/services/diagnosticReports/D
import DiagnosticReportView from "@/pages/Facility/services/diagnosticReports/DiagnosticReportView";
import ServiceRequestShow from "@/pages/Facility/services/serviceRequests/ServiceRequestShow";
import { SettingsLayout } from "@/pages/Facility/settings/layout";
import { ReportType } from "@/types/emr/report/report";

const FacilityRoutes: AppRoutes = {
"/facility": () => <Redirect to="/" />,
Expand Down Expand Up @@ -104,6 +106,24 @@ const FacilityRoutes: AppRoutes = {
facilityId,
accountId,
}) => <PrintChargeItems facilityId={facilityId} accountId={accountId} />,
"/facility/:facilityId/billing/account/:accountId/report/template/:templateSlug":
({ accountId, templateSlug }) => (
<ReportViewer
associatingId={accountId}
templateSlug={templateSlug}
reportType={ReportType.ACCOUNT_REPORT}
/>
),
"/facility/:facilityId/billing/account/:accountId/report/:reportId": ({
accountId,
reportId,
}) => (
<ReportViewer
associatingId={accountId}
reportId={reportId}
reportType={ReportType.ACCOUNT_REPORT}
/>
),
"/facility/:facilityId/billing/account/:accountId/:tab": ({
facilityId,
accountId,
Expand Down
22 changes: 22 additions & 0 deletions src/Routers/routes/PatientRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import { AppRoutes } from "@/Routers/AppRouter";
import { PatientRegistration } from "@/components/Patient/PatientRegistration";
import { ConsentDetailPage } from "@/pages/Encounters/ConsentDetail";
import EncountersOverview from "@/pages/Encounters/EncountersOverview";
import ReportViewer from "@/pages/Encounters/ReportViewer";
import { EncounterProvider } from "@/pages/Encounters/utils/EncounterProvider";
import ClinicalHistoryPage from "@/pages/Patient/History";
import PatientHome from "@/pages/Patient/PatientHome";
import { ReportType } from "@/types/emr/report/report";
import careConfig from "@careConfig";

const ExcalidrawEditor = lazy(
Expand Down Expand Up @@ -164,6 +166,26 @@ const PatientRoutes: AppRoutes = {
fallBackUrl={`/patient/${patientId}`}
/>
),
"/facility/:facilityId/patient/:patientId/report/template/:templateSlug": ({
patientId,
templateSlug,
}) => (
<ReportViewer
associatingId={patientId}
templateSlug={templateSlug}
reportType={ReportType.PATIENT_SUMMARY}
/>
),
"/facility/:facilityId/patient/:patientId/report/:reportId": ({
patientId,
reportId,
}) => (
<ReportViewer
associatingId={patientId}
reportId={reportId}
reportType={ReportType.PATIENT_SUMMARY}
/>
),
};

export default PatientRoutes;
37 changes: 0 additions & 37 deletions src/components/Common/FilePreviewDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ import {
FileReadMinimal,
getVideoMimeType,
} from "@/types/files/file";
import { ShortcutBadge } from "@/Utils/keyboardShortcutComponents";
import { Printer } from "lucide-react";

const PDFViewer = lazy(() => import("@/components/Common/PDFViewer"));
export interface StateInterface {
Expand Down Expand Up @@ -247,41 +245,6 @@ export default function FilePreviewDialog(props: FilePreviewProps) {
)}
</div>
<div className="flex gap-2">
{file_state.extension === "pdf" && (
<Button
variant="outline"
onClick={async () => {
try {
const response = await fetch(fileUrl);
const blob = await response.blob();
const blobUrl = window.URL.createObjectURL(blob);
const iframe = document.createElement("iframe");
iframe.style.display = "none";
iframe.src = blobUrl;

iframe.onload = () => {
try {
iframe.contentWindow?.print();
} catch {
window.open(blobUrl, "_blank");
}
setTimeout(() => {
document.body.removeChild(iframe);
window.URL.revokeObjectURL(blobUrl);
}, 10000);
};

document.body.appendChild(iframe);
} catch {
toast.error(t("print_failed"));
}
}}
>
<Printer className="size-4" />
<span className="hidden sm:block">{t("print")}</span>
<ShortcutBadge actionId="print-button" />
</Button>
)}
{file_state.extension === "pdf" && fileUrl && (
<Button
variant="outline"
Expand Down
156 changes: 136 additions & 20 deletions src/components/Files/ReportSubTab.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { useQuery } from "@tanstack/react-query";
import dayjs from "dayjs";
import { SearchIcon } from "lucide-react";
import { FileText, Plus, SearchIcon } from "lucide-react";
import { navigate } from "raviger";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";

import { cn } from "@/lib/utils";

Expand All @@ -26,30 +29,33 @@ import {
} from "@/components/ui/table";
import { TooltipComponent } from "@/components/ui/tooltip";

import { PERMISSION_LIST_TEMPLATE } from "@/common/Permissions";
import Loading from "@/components/Common/Loading";
import { FilterBadges, FilterButton } from "@/components/Files/FileFilters";
import { EmptyState } from "@/components/ui/empty-state";
import { usePermissions } from "@/context/PermissionContext";

import useFilters from "@/hooks/useFilters";
import useReportManager from "@/hooks/useReportManager";

import query from "@/Utils/request/query";
import queryClient from "@/Utils/request/queryClient";
import TemplateReportSheet from "@/pages/Encounters/TemplateBuilder/TemplateReportSheet";
import NavigationHelper from "@/components/ui/multi-filter/utils/navigation-helper";
import { useCurrentFacilitySilently } from "@/pages/Facility/utils/useCurrentFacility";
import {
ReportRead,
ReportReadList,
ReportType,
} from "@/types/emr/report/report";
import { navigate } from "raviger";
import { toast } from "sonner";
import templateApi from "@/types/emr/template/templateApi";

interface ReportTabProps {
associatingId: string;
reportType?: ReportType;
facilityId?: string;
patientId?: string;
encounterId?: string;
billingAccountId?: string;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Associating Id is encounterId, patientId or accountId based on report type, so we can derive the url based on that.

Remove patientId, encounterId and billingAccountId props.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cant remove patient id, can remove the encounter id and billingAccountID

}

export function ReportSubTab({
Expand All @@ -58,6 +64,7 @@ export function ReportSubTab({
facilityId,
patientId,
encounterId,
billingAccountId,
}: ReportTabProps) {
const { t } = useTranslation();
const { facility } = useCurrentFacilitySilently();
Expand All @@ -72,7 +79,6 @@ export function ReportSubTab({
viewFile,
downloadFile,
archiveReport,
refetch,
Dialogs,
} = useReportManager({
associatingId,
Expand All @@ -98,13 +104,32 @@ export function ReportSubTab({
return iconMap[reportType] || "l-file-alt";
};

const canNavigateToPreview = !!(facilityId && patientId && encounterId);
const canNavigateToEncounterPreview = !!(
facilityId &&
patientId &&
encounterId
);
const canNavigateToBillingPreview = !!(facilityId && billingAccountId);
const canNavigateToPatientPreview = !!(patientId && !encounterId);

const handleView = (report: ReportReadList) => {
if (canNavigateToPreview) {
if (canNavigateToEncounterPreview) {
navigate(
`/facility/${facilityId}/patient/${patientId}/encounter/${encounterId}/report/${report.id}`,
);
} else if (canNavigateToBillingPreview) {
navigate(
`/facility/${facilityId}/billing/account/${billingAccountId}/report/${report.id}`,
);
} else if (canNavigateToPatientPreview) {
const effectiveFacilityId = facilityId ?? facility?.id;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can move defining effectiveFacilityId to 116 and use it in other blocks as well; allows to remove the else block in 130.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replacing with switch

if (effectiveFacilityId) {
navigate(
`/facility/${effectiveFacilityId}/patient/${patientId}/report/${report.id}`,
);
} else {
viewFile(report);
}
} else {
viewFile(report);
}
Comment thread
abhimanyurajeesh marked this conversation as resolved.
Expand Down Expand Up @@ -374,20 +399,12 @@ export function ReportSubTab({
</Button>
</div>
{facility && (
<TemplateReportSheet
facilityId={facility.id}
associatingId={associatingId}
permissions={facility.permissions ?? []}
<GenerateReportDropdown
facilityId={facilityId ?? facility.id}
patientId={patientId}
encounterId={encounterId}
billingAccountId={billingAccountId}
reportType={reportType}
trigger={
<Button variant="outline_primary">
<CareIcon icon="l-plus" className="mr-1" />
<span>{t("generate_report")}</span>
</Button>
}
onSuccess={() => {
refetch();
}}
/>
)}
</div>
Expand Down Expand Up @@ -426,3 +443,102 @@ export function ReportSubTab({
</div>
);
}

function GenerateReportDropdown({
facilityId,
patientId,
encounterId,
billingAccountId,
reportType,
}: {
facilityId: string;
patientId?: string;
encounterId?: string;
billingAccountId?: string;
reportType?: ReportType;
}) {
const { t } = useTranslation();
const { facility } = useCurrentFacilitySilently();
const { hasPermission } = usePermissions();

const canListTemplate = hasPermission(
PERMISSION_LIST_TEMPLATE,
facility?.permissions,
);

const { data: templatesData } = useQuery({
queryKey: ["templates", facilityId, reportType],
queryFn: query(templateApi.listTemplates, {
queryParams: {
facility: facilityId,
template_type: reportType,
status: "active",
},
}),
enabled: canListTemplate && !!reportType,
});

const getTemplateUrl = (slug: string) => {
if (encounterId && patientId) {
return `/facility/${facilityId}/patient/${patientId}/encounter/${encounterId}/report/template/${slug}`;
}
if (billingAccountId) {
return `/facility/${facilityId}/billing/account/${billingAccountId}/report/template/${slug}`;
}
if (patientId) {
return `/facility/${facilityId}/patient/${patientId}/report/template/${slug}`;
}
return null;
};

const templates = (templatesData?.results ?? []).flatMap((template) => {
const url = getTemplateUrl(template.slug);
return url ? [{ template, url }] : [];
});

if (templates.length === 0) return null;
Comment thread
abhimanyurajeesh marked this conversation as resolved.
Outdated

if (templates.length === 1) {
Comment thread
abhimanyurajeesh marked this conversation as resolved.
Outdated
return (
<Button
variant="outline_primary"
onClick={() => navigate(templates[0].url)}
>
<Plus className="size-4" />
<span>{t("generate_report")}</span>
</Button>
);
}

return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline_primary">
<Plus className="size-4" />
<span>{t("generate_report")}</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent
align="end"
className="w-full max-w-[calc(100vw-3rem)] sm:max-w-xs p-0"
>
<div className="px-2 pt-2">
<div className="max-h-[30vh] overflow-y-auto pb-2">
{templates.map(({ template, url }) => {
return (
<DropdownMenuItem
key={template.id}
onClick={() => navigate(url)}
>
<FileText className="size-4 shrink-0" />
<span className="truncate">{template.name}</span>
</DropdownMenuItem>
);
})}
</div>
<NavigationHelper hideRightArrow />
Comment thread
abhimanyurajeesh marked this conversation as resolved.
</div>
</DropdownMenuContent>
</DropdownMenu>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import useBreakpoints from "@/hooks/useBreakpoints";

export default function NavigationHelper({
isActiveFilter,
hideRightArrow,
}: {
isActiveFilter?: boolean;
hideRightArrow?: boolean;
}) {
const { t } = useTranslation();
const isMobile = useBreakpoints({ sm: false, default: true });
Expand All @@ -33,7 +35,7 @@ export default function NavigationHelper({
<div className="bg-gray-100 shadow-full rounded-md px-1 border border-gray-300">
<CareIcon icon="l-arrow-up" className="h-4 w-4" />
</div>
{!isActiveFilter && (
{!isActiveFilter && !hideRightArrow && (
<div className="bg-gray-100 shadow-full rounded-md px-1 border border-gray-300">
<CareIcon icon="l-arrow-right" className="h-4 w-4" />
</div>
Expand Down
Loading
Loading