Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions src/Routers/routes/ConsultationRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { EncounterShow } from "@/pages/Encounters/EncounterShow";
import { PrintPrescription } from "@/pages/Encounters/PrintPrescription";
import ReportViewer from "@/pages/Encounters/ReportViewer";
import { EncounterProvider } from "@/pages/Encounters/utils/EncounterProvider";
import { ReportType } from "@/types/emr/report/report";

const ExcalidrawEditor = lazy(
() => import("@/components/Common/Drawings/ExcalidrawEditor"),
Expand Down Expand Up @@ -91,12 +92,32 @@ 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/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}
/>
),
"/facility/:facilityId/patient/:patientId/encounter/:encounterId/questionnaire":
({ facilityId, encounterId, patientId }) => (
<EncounterQuestionnaire
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/reports/template/:templateSlug":
({ accountId, templateSlug }) => (
<ReportViewer
associatingId={accountId}
templateSlug={templateSlug}
reportType={ReportType.ACCOUNT_REPORT}
/>
),
"/facility/:facilityId/billing/account/:accountId/reports/:reportId": ({
accountId,
reportId,
}) => (
<ReportViewer
associatingId={accountId}
reportId={reportId}
reportType={ReportType.ACCOUNT_REPORT}
/>
),
Comment thread
coderabbitai[bot] marked this conversation as resolved.
"/facility/:facilityId/billing/account/:accountId/:tab": ({
facilityId,
accountId,
Expand Down
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
92 changes: 92 additions & 0 deletions src/components/Files/GenerateReportDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { useQuery } from "@tanstack/react-query";
import { FileText, Loader2, Plus } from "lucide-react";
import { Link } from "raviger";
import { useState } from "react";
import { useTranslation } from "react-i18next";

import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import NavigationHelper from "@/components/ui/multi-filter/utils/navigation-helper";

import query from "@/Utils/request/query";
import { ReportType } from "@/types/emr/report/report";
import templateApi from "@/types/emr/template/templateApi";

interface GenerateReportDropdownProps {
facilityId: string;
reportType?: ReportType;
getReportUrl: (templateSlug: string) => string;
}
Comment thread
abhimanyurajeesh marked this conversation as resolved.
Comment thread
abhimanyurajeesh marked this conversation as resolved.

export function GenerateReportDropdown({
facilityId,
reportType,
getReportUrl,
}: GenerateReportDropdownProps) {
Comment thread
coderabbitai[bot] marked this conversation as resolved.
const { t } = useTranslation();
const [open, setOpen] = useState(false);

const { data: templatesData, isLoading } = useQuery({
Comment thread
abhimanyurajeesh marked this conversation as resolved.
queryKey: ["templates", facilityId, reportType, "active"],
queryFn: query(templateApi.listTemplates, {
queryParams: {
facility: facilityId,
template_type: reportType,
status: "active",
},
}),
enabled: open,
});
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
abhimanyurajeesh marked this conversation as resolved.

const templates = templatesData?.results ?? [];

return (
<DropdownMenu open={open} onOpenChange={setOpen}>
<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">
{isLoading && (
<div className="px-3 py-4 text-sm text-gray-500 text-center flex items-center justify-center gap-2">
<Loader2 className="size-4 animate-spin" />
{t("loading")}
</div>
)}
{!isLoading && templatesData && templates.length === 0 && (
<div className="px-3 py-4 text-sm text-gray-500 text-center">
{t("no_templates_found")}
</div>
)}
{templates.map((template) => (
<DropdownMenuItem key={template.id} asChild>
<Link
href={getReportUrl(template.slug)}
className="flex items-center gap-2 px-3 py-2 cursor-pointer"
>
<FileText className="size-4 shrink-0 text-gray-500" />
<span className="text-sm truncate">{template.name}</span>
</Link>
</DropdownMenuItem>
))}
</div>
{!isLoading && templatesData && templates.length > 0 && (
<NavigationHelper hideRight />
)}
Comment thread
abhimanyurajeesh marked this conversation as resolved.
</div>
</DropdownMenuContent>
</DropdownMenu>
);
}
59 changes: 40 additions & 19 deletions src/components/Files/ReportSubTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import useFilters from "@/hooks/useFilters";
import useReportManager from "@/hooks/useReportManager";

import queryClient from "@/Utils/request/queryClient";
import TemplateReportSheet from "@/pages/Encounters/TemplateBuilder/TemplateReportSheet";
import { GenerateReportDropdown } from "@/components/Files/GenerateReportDropdown";
import { useCurrentFacilitySilently } from "@/pages/Facility/utils/useCurrentFacility";
import {
ReportRead,
Expand All @@ -50,6 +50,25 @@ interface ReportTabProps {
facilityId?: string;
patientId?: string;
encounterId?: string;
getViewUrl?: (reportId: string) => string;
}

function buildReportPath(
facilityId: string,
reportIdOrSlug: string,
options?: { patientId?: string; encounterId?: string; isTemplate?: boolean },
) {
const segment = options?.isTemplate
? `template/${reportIdOrSlug}`
: reportIdOrSlug;

if (options?.patientId && options?.encounterId) {
return `/facility/${facilityId}/patient/${options.patientId}/encounter/${options.encounterId}/report/${segment}`;
}
if (options?.patientId) {
return `/facility/${facilityId}/patient/${options.patientId}/report/${segment}`;
}
return `/facility/${facilityId}/reports/${segment}`;
}

export function ReportSubTab({
Expand All @@ -58,9 +77,11 @@ export function ReportSubTab({
facilityId,
patientId,
encounterId,
getViewUrl,
}: ReportTabProps) {
const { t } = useTranslation();
const { facility } = useCurrentFacilitySilently();
const resolvedFacilityId = facilityId ?? facility?.id;
const { qParams, updateQuery, Pagination } = useFilters({
limit: 15,
disableCache: true,
Expand All @@ -72,7 +93,6 @@ export function ReportSubTab({
viewFile,
downloadFile,
archiveReport,
refetch,
Dialogs,
} = useReportManager({
associatingId,
Expand All @@ -98,12 +118,15 @@ export function ReportSubTab({
return iconMap[reportType] || "l-file-alt";
};

const canNavigateToPreview = !!(facilityId && patientId && encounterId);

const handleView = (report: ReportReadList) => {
if (canNavigateToPreview) {
if (getViewUrl) {
navigate(getViewUrl(report.id));
} else if (resolvedFacilityId && patientId) {
navigate(
`/facility/${facilityId}/patient/${patientId}/encounter/${encounterId}/report/${report.id}`,
buildReportPath(resolvedFacilityId, report.id, {
patientId,
encounterId,
}),
);
} else {
viewFile(report);
Expand Down Expand Up @@ -373,21 +396,19 @@ export function ReportSubTab({
{t("refresh")}
</Button>
</div>
{facility && (
<TemplateReportSheet
facilityId={facility.id}
associatingId={associatingId}
permissions={facility.permissions ?? []}
{resolvedFacilityId && (
<GenerateReportDropdown
facilityId={resolvedFacilityId}
reportType={reportType}
trigger={
<Button variant="outline_primary">
<CareIcon icon="l-plus" className="mr-1" />
<span>{t("generate_report")}</span>
</Button>
getReportUrl={(slug) =>
Comment thread
abhimanyurajeesh marked this conversation as resolved.
getViewUrl
? getViewUrl(`template/${slug}`)
: buildReportPath(resolvedFacilityId, slug, {
patientId,
encounterId,
isTemplate: true,
})
}
onSuccess={() => {
refetch();
}}
/>
)}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
</div>
Expand Down
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,
hideRight,
}: {
isActiveFilter?: boolean;
hideRight?: boolean;
Comment thread
abhimanyurajeesh marked this conversation as resolved.
}) {
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 && !hideRight && (
<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