From 5fcab8ea134cd6a65d8da33c212b4a5da95a039b Mon Sep 17 00:00:00 2001
From: NikhilA8606
Date: Tue, 16 Jun 2026 09:18:23 +0530
Subject: [PATCH 01/27] ENG-500 Support for creating multiple diagnostic
reports in a service request
---
public/locale/en.json | 5 +-
.../components/DiagnosticReportForm.tsx | 1139 ++++++++++-------
.../components/DiagnosticReportReview.tsx | 298 ++---
3 files changed, 811 insertions(+), 631 deletions(-)
diff --git a/public/locale/en.json b/public/locale/en.json
index c925ea88482..c58f2f25666 100644
--- a/public/locale/en.json
+++ b/public/locale/en.json
@@ -691,6 +691,7 @@
"and_more_medications": "+{{count}} more medication(s)",
"and_more_service_requests": "+{{count}} more service request(s)",
"and_the_status_of_request_is": "and the status of request is",
+ "another_diagnostic_report": "Another Diagnostic Report",
"answer": "Answer",
"answer_options": "Answer options",
"answer_options_description": "Define possible answers for this question",
@@ -5035,7 +5036,7 @@
"result_date": "Result Date",
"result_details": "Result details",
"result_on": "Result on",
- "result_review": "Result Review",
+ "result_review": "Result Review of {{name}}",
"result_value": "Result value",
"resume": "Resume",
"retake": "Retake",
@@ -5067,6 +5068,7 @@
"review_and_finalise_request_description": "Add more items if needed, or approve to mark this delivery as requested.",
"review_before": "Review Before",
"review_missed": "Review Missed",
+ "review_test_results": "Review Test Reult",
"revisit_days_non_negative": "Re-visit allowed days cannot be negative",
"revoke": "Revoke",
"revoke_token": "Revoke Token",
@@ -5532,6 +5534,7 @@
"select_register_patient": "Select/Register Patient",
"select_report": "Select Report",
"select_report_type": "Select Report Type",
+ "select_report_type_to_create": "Select 'Select Diagnostic Report Type' and create Report",
"select_requester": "Select requester",
"select_resource": "Select the resource",
"select_resource_category": "Select resource category",
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
index 7355ce7bb43..e096c8788db 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
@@ -3,7 +3,9 @@ import {
ChevronsDownUp,
ChevronsUpDown,
CloudUpload,
+ FileUp,
NotepadText,
+ Plus,
PlusCircle,
Save,
Trash2,
@@ -15,7 +17,6 @@ import { toast } from "sonner";
import { cn } from "@/lib/utils";
-import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import {
@@ -33,18 +34,9 @@ import {
SelectValue,
} from "@/components/ui/select";
import { Separator } from "@/components/ui/separator";
-import { Skeleton } from "@/components/ui/skeleton";
-
-import { Avatar } from "@/components/Common/Avatar";
-import { FileListTable } from "@/components/Files/FileListTable";
-import FileUploadDialog from "@/components/Files/FileUploadDialog";
import useFileUpload from "@/hooks/useFileUpload";
-import mutate from "@/Utils/request/mutate";
-import query from "@/Utils/request/query";
-import { PaginatedResponse } from "@/Utils/request/types";
-import { formatName } from "@/Utils/utils";
import { Code } from "@/types/base/code/code";
import {
DIAGNOSTIC_REPORT_STATUS_COLORS,
@@ -68,11 +60,20 @@ import { SpecimenDefinitionRead } from "@/types/emr/specimenDefinition/specimenD
import {
BACKEND_ALLOWED_EXTENSIONS,
FileReadMinimal,
+ FileType,
} from "@/types/files/file";
import fileApi from "@/types/files/fileApi";
+import mutate from "@/Utils/request/mutate";
+import query from "@/Utils/request/query";
+import { PaginatedResponse } from "@/Utils/request/types";
+import { Avatar } from "@/components/Common/Avatar";
+import { FileListTable } from "@/components/Files/FileListTable";
+import FileUploadDialog from "@/components/Files/FileUploadDialog";
+import { Badge } from "@/components/ui/badge";
import { PLUGIN_Component } from "@/PluginEngine";
import { Interpretation } from "@/types/base/qualifiedRange/qualifiedRange";
+import { formatName } from "@/Utils/utils";
interface DiagnosticReportFormProps {
patientId: string;
@@ -121,54 +122,21 @@ export function DiagnosticReportForm({
disableEdit,
}: DiagnosticReportFormProps) {
const { t } = useTranslation();
- const [observations, setObservations] = useState(
- {},
- );
- const [isExpanded, setIsExpanded] = useState(true);
+ const queryClient = useQueryClient();
+
+ const [showReportTypeSelect, setShowReportTypeSelect] = useState(false);
const [selectedReportCode, setSelectedReportCode] = useState(
null,
);
- const [openUploadDialog, setOpenUploadDialog] = useState(false);
- const [conclusion, setConclusion] = useState("");
- const queryClient = useQueryClient();
-
- // Get the latest report if any exists
- const latestReport =
- diagnosticReports.length > 0 ? diagnosticReports[0] : null;
- const hasReport = !!latestReport;
// Check if all required specimens are collected
const hasCollectedSpecimens =
activityDefinition?.specimen_requirements?.length === 0 ||
specimens.some((specimen) => specimen.status === SpecimenStatus.available);
- // Fetch the full diagnostic report to get observations
- const { data: fullReport, isLoading: isLoadingReport } = useQuery({
- queryKey: ["diagnosticReport", latestReport?.id],
- queryFn: query(diagnosticReportApi.retrieveDiagnosticReport, {
- pathParams: {
- patient_external_id: patientId,
- external_id: latestReport?.id || "",
- },
- }),
- enabled: !!latestReport?.id,
- });
-
- // Query to fetch files for the diagnostic report
- const { data: files = { results: [], count: 0 } } = useQuery<
- PaginatedResponse
- >({
- queryKey: ["files", "diagnostic_report", fullReport?.id],
- queryFn: query(fileApi.list, {
- queryParams: {
- file_type: "diagnostic_report",
- associating_id: fullReport?.id,
- limit: 100,
- offset: 0,
- },
- }),
- enabled: !!fullReport?.id,
- });
+ const isMultipleDiagnosticReport =
+ !!activityDefinition?.diagnostic_report_codes &&
+ activityDefinition.diagnostic_report_codes.length > 0;
// Creating a new diagnostic report
const { mutate: createDiagnosticReport, isPending: isCreatingReport } =
@@ -183,35 +151,180 @@ export function DiagnosticReportForm({
queryClient.invalidateQueries({
queryKey: ["serviceRequest"],
});
- // Fetch the newly created report
queryClient.invalidateQueries({
queryKey: ["diagnosticReport"],
});
},
- onError: (err: any) => {
+ onError: (err: Error) => {
toast.error(
`Failed to create diagnostic report: ${err.message || "Unknown error"}`,
);
},
});
- // Effect to handle diagnostic reports changes
- useEffect(() => {
- const latestReport = diagnosticReports[0];
- if (latestReport) {
- // If we have a new report, update the UI accordingly
- setSelectedReportCode(latestReport.code || null);
- setIsExpanded(true);
+ function handleCreateReport(code?: Code) {
+ if (!hasCollectedSpecimens) {
+ toast.error(t("specimen_collection_required"));
+ return;
}
- }, [diagnosticReports]);
- // Effect to handle fullReport changes
- useEffect(() => {
- if (fullReport) {
- // When we get the full report details, ensure UI is in correct state
- setSelectedReportCode(fullReport.code || null);
- }
- }, [fullReport]);
+ const category: Code = {
+ code: "LAB",
+ display: "Laboratory",
+ system: "http://terminology.hl7.org/CodeSystem/v2-0074",
+ };
+
+ createDiagnosticReport({
+ status: DiagnosticReportStatus.preliminary,
+ category,
+ service_request: serviceRequestId,
+ code: code || undefined,
+ });
+ }
+
+ return (
+ <>
+ {diagnosticReports.length > 0 && (
+
+
+ {diagnosticReports.map((report) => (
+
+ ))}
+
+ {isMultipleDiagnosticReport && (
+
+ {showReportTypeSelect ? (
+
{
+ const code =
+ activityDefinition?.diagnostic_report_codes?.find(
+ (c) => c.code === value,
+ );
+ setSelectedReportCode(code || null);
+ if (code) {
+ handleCreateReport(code);
+ setShowReportTypeSelect(false);
+ setSelectedReportCode(null);
+ }
+ }}
+ disabled={!hasCollectedSpecimens || disableEdit}
+ >
+
+
+
+
+ {isMultipleDiagnosticReport &&
+ activityDefinition?.diagnostic_report_codes?.map(
+ (code) => (
+
+
+
+ {code.display} ({code.code})
+
+
+
+ ),
+ )}
+
+
+ ) : (
+
{
+ if (isMultipleDiagnosticReport) {
+ setShowReportTypeSelect(true);
+ } else {
+ handleCreateReport();
+ }
+ }}
+ disabled={
+ disableEdit || isCreatingReport || !hasCollectedSpecimens
+ }
+ >
+
+ {t("another_diagnostic_report")}
+
+ )}
+
+ )}
+
+ )}
+ {diagnosticReports.length === 0 && (
+
+ )}
+ >
+ );
+}
+
+function DiagnosticReportItem({
+ report,
+ patientId,
+ serviceRequestId,
+ observationDefinitions,
+ disableEdit,
+ isMultipleDiagnosticReport,
+}: {
+ report: DiagnosticReportRead;
+ patientId: string;
+ serviceRequestId: string;
+ observationDefinitions: ObservationDefinitionReadSpec[];
+ disableEdit: boolean;
+ isMultipleDiagnosticReport: boolean;
+}) {
+ const { t } = useTranslation();
+ const queryClient = useQueryClient();
+ const [observations, setObservations] = useState(
+ {},
+ );
+ const [isExpanded, setIsExpanded] = useState(true);
+ const [openUploadDialog, setOpenUploadDialog] = useState(false);
+ const [conclusion, setConclusion] = useState("");
+
+ const { data: fullReport } = useQuery({
+ queryKey: ["diagnosticReport", report.id],
+ queryFn: query(diagnosticReportApi.retrieveDiagnosticReport, {
+ pathParams: {
+ patient_external_id: patientId,
+ external_id: report.id,
+ },
+ }),
+ enabled: !!report.id,
+ });
+
+ // Query to fetch files for the diagnostic report
+ const { data: files = { results: [], count: 0 } } = useQuery<
+ PaginatedResponse
+ >({
+ queryKey: ["files", "diagnostic_report", report.id],
+ queryFn: query(fileApi.list, {
+ queryParams: {
+ file_type: "diagnostic_report",
+ associating_id: report.id,
+ limit: 100,
+ offset: 0,
+ },
+ }),
+ enabled: !!report.id,
+ });
// Upserting observations for a diagnostic report
const { mutate: upsertObservations, isPending: isUpsertingObservations } =
@@ -219,7 +332,7 @@ export function DiagnosticReportForm({
mutationFn: mutate(observationApi.upsertObservations, {
pathParams: {
patient_external_id: patientId,
- external_id: latestReport?.id || "",
+ external_id: report.id,
},
}),
onSuccess: () => {
@@ -228,10 +341,10 @@ export function DiagnosticReportForm({
queryKey: ["serviceRequest", serviceRequestId],
});
queryClient.invalidateQueries({
- queryKey: ["diagnosticReport", latestReport?.id],
+ queryKey: ["diagnosticReport", report.id],
});
},
- onError: (err: any) => {
+ onError: (err: Error) => {
toast.error(
`Failed to save test results: ${err.message || "Unknown error"}`,
);
@@ -243,13 +356,13 @@ export function DiagnosticReportForm({
mutationFn: mutate(diagnosticReportApi.updateDiagnosticReport, {
pathParams: {
patient_external_id: patientId,
- external_id: latestReport?.id || "",
+ external_id: report.id,
},
}),
onSuccess: () => {
toast.success(t("conclusion_updated_successfully"));
queryClient.invalidateQueries({
- queryKey: ["diagnosticReport", latestReport?.id],
+ queryKey: ["diagnosticReport", report.id],
});
setIsExpanded(false);
},
@@ -260,13 +373,13 @@ export function DiagnosticReportForm({
// Initialize file upload hook
const fileUpload = useFileUpload({
- type: "diagnostic_report" as any,
+ type: "diagnostic_report" as FileType,
multiple: true,
allowedExtensions: BACKEND_ALLOWED_EXTENSIONS,
allowNameFallback: false,
onUpload: () => {
queryClient.invalidateQueries({
- queryKey: ["diagnosticReport", latestReport?.id],
+ queryKey: ["diagnosticReport", report.id],
});
},
compress: false,
@@ -289,9 +402,10 @@ export function DiagnosticReportForm({
if (!openUploadDialog) {
fileUpload.clearFiles();
}
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [openUploadDialog]);
- // Initialize form with existing observations from the full report
+ // Initialize form with existing observations from the report
useEffect(() => {
if (fullReport?.observations && fullReport.observations.length > 0) {
const initialObservations: ObservationsByDefinition = {};
@@ -333,10 +447,10 @@ export function DiagnosticReportForm({
});
setObservations(initialObservations);
+ }
- if (fullReport.conclusion) {
- setConclusion(fullReport.conclusion);
- }
+ if (fullReport?.conclusion) {
+ setConclusion(fullReport.conclusion);
}
}, [fullReport]);
@@ -467,36 +581,7 @@ export function DiagnosticReportForm({
});
}
- function handleCreateReport() {
- // Only create a new report if no reports exist
- if (!hasReport) {
- if (!hasCollectedSpecimens) {
- toast.error(t("specimen_collection_required"));
- return;
- }
-
- const category: Code = {
- code: "LAB",
- display: "Laboratory",
- system: "http://terminology.hl7.org/CodeSystem/v2-0074",
- };
-
- createDiagnosticReport({
- status: DiagnosticReportStatus.preliminary,
- category,
- service_request: serviceRequestId,
- code: selectedReportCode || undefined,
- });
- }
- }
-
function handleSubmit() {
- if (!hasReport) {
- // First create a report if none exists
- handleCreateReport();
- return;
- }
-
try {
// Check if all observations have values
const hasObservationValue = Object.values(observations).some((obsList) =>
@@ -645,23 +730,21 @@ export function DiagnosticReportForm({
)
.filter((obs): obs is ObservationUpsertRequest => obs !== null);
- if (fullReport) {
- // Upsert observations
- if (formattedObservations.length > 0) {
- upsertObservations({
- observations: formattedObservations,
- });
- }
-
- updateDiagnosticReport({
- id: fullReport.id,
- status: fullReport.status,
- category: fullReport.category,
- code: fullReport.code,
- note: fullReport.note,
- conclusion,
+ // Upsert observations
+ if (formattedObservations.length > 0) {
+ upsertObservations({
+ observations: formattedObservations,
});
}
+
+ updateDiagnosticReport({
+ id: report.id,
+ status: report.status,
+ category: report.category,
+ code: report.code,
+ note: report.note,
+ conclusion,
+ });
} catch (_error) {
toast.error(t("error_validating_form"));
}
@@ -808,23 +891,7 @@ export function DiagnosticReportForm({
);
}
- const isSubmitting =
- isCreatingReport || isUpsertingObservations || isUpdatingReport;
-
- // Show loading state while fetching the report
- if (hasReport && isLoadingReport) {
- return (
-
-
-
-
-
-
-
-
-
- );
- }
+ const isSubmitting = isUpsertingObservations || isUpdatingReport;
return (
{" "}
- {t("test_results_entry")}
+ {isMultipleDiagnosticReport
+ ? report.code?.display
+ : t("test_results_entry")}
- {hasReport && fullReport?.created_by && (
-
+
+ {report.created_by && (
-
- {formatName(fullReport.created_by)}
-
-
- )}
-
- {hasReport && fullReport && (
-
- {t(fullReport.status)}
-
)}
+
+ {formatName(report.created_by)}
+
+
+
+
+ {t(report.status)}
+
- {hasReport && fullReport ? (
-
- {fullReport.status !== DiagnosticReportStatus.final && (
-
- )}
- {fullReport.status !== DiagnosticReportStatus.final &&
- observationDefinitions.map((definition) => {
- const observationsList = observations[definition.id] || [
- {
- id: "",
- value: "",
- unit: definition.permitted_unit?.code || "",
- interpretation: "",
- status: ObservationStatus.AMENDED,
- components: {},
- },
- ];
-
- return (
-
-
-
-
-
- {definition.title || definition.code?.display}
-
-
+
+ {report.status !== DiagnosticReportStatus.final && (
+
+ )}
+ {report.status !== DiagnosticReportStatus.final &&
+ observationDefinitions.map((definition) => {
+ const observationsList = observations[definition.id] || [
+ {
+ id: "",
+ value: "",
+ unit: definition.permitted_unit?.code || "",
+ interpretation: "",
+ status: ObservationStatus.AMENDED,
+ components: {},
+ },
+ ];
+
+ return (
+
+
+
+
+
+ {definition.title || definition.code?.display}
+
+
- {observationsList.map((observationData, index) => {
- const hasComponents =
- definition.component &&
- definition.component.length > 0;
- const isErrored =
- observationData.status ===
- ObservationStatus.ENTERED_IN_ERROR;
- return (
-
{
+ const hasComponents =
+ definition.component &&
+ definition.component.length > 0;
+ const isErrored =
+ observationData.status ===
+ ObservationStatus.ENTERED_IN_ERROR;
+ return (
+
+
+
+ {t("observation") + " " + (index + 1)}
+
+ {isErrored ? (
+
+ {t("marked_for_deletion")}
+
+ ) : (
+ !disableEdit && (
+
+ handleDeleteObservation(
+ definition.id,
+ index,
+ )
+ }
+ disabled={
+ isErrored ||
+ (index === 0 && !observationData.id)
+ }
+ >
+
+
+ )
)}
- >
-
-
- {t("observation") + " " + (index + 1)}
-
- {isErrored ? (
-
- {t("marked_for_deletion")}
-
- ) : (
- !disableEdit && (
-
- handleDeleteObservation(
- definition.id,
- index,
- )
- }
- disabled={
- isErrored ||
- (index === 0 && !observationData.id)
- }
- >
-
-
- )
- )}
-
+
- {/* For blood pressure and similar observations with components, we may or may not need to show the main value field */}
- {!hasComponents && (
-
- {definition.permitted_unit && (
-
-
- {t("unit")}
-
-
- handleUnitChange(
- definition.id,
- index,
- unit,
- )
- }
- disabled={isErrored || disableEdit}
- >
-
-
-
-
-
- {definition.permitted_unit
- .code ||
- definition.permitted_unit
- .display}
-
-
-
-
- )}
-
-
+ {/* For blood pressure and similar observations with components, we may or may not need to show the main value field */}
+ {!hasComponents && (
+
+ )}
+
+ {/* Render component inputs for multi-component observations */}
+ {hasComponents &&
+ renderComponentInputs(
+ definition,
+ observationData,
+ index,
)}
+
+ );
+ })}
+
+ {/* Add button for multiple observations */}
+
{
+ setObservations((prev) => {
+ const currentList = prev[definition.id] || [];
+ return {
+ ...prev,
+ [definition.id]: [
+ ...currentList,
+ {
+ id: "",
+ value: "",
+ unit:
+ definition.permitted_unit?.code || "",
+ status: ObservationStatus.AMENDED,
+ components: {},
+ },
+ ],
+ };
+ });
+ }}
+ disabled={disableEdit}
+ >
+
+ {t("add_another_result")}
+
+
+
+
+ );
+ })}
+
+
+ {files?.results && files.results.length > 0 && (
+
+
+ {t("uploaded_files")}
+
+
+
+ )}
- {/* Render component inputs for multi-component observations */}
- {hasComponents &&
- renderComponentInputs(
- definition,
- observationData,
- index,
- )}
-
- );
+ {report?.status === DiagnosticReportStatus.preliminary && (
+
+
+
+
+
+
+ {t("choose_file")}
+
+
+ {t("allowed_formats_are", {
+ formats:
+ BACKEND_ALLOWED_EXTENSIONS.slice(0, 5).join(
+ ", ",
+ ) +
+ ", " +
+ t("etc"),
})}
-
- {/* Add button for multiple observations */}
-
{
- setObservations((prev) => {
- const currentList = prev[definition.id] || [];
- return {
- ...prev,
- [definition.id]: [
- ...currentList,
- {
- id: "",
- value: "",
- unit:
- definition.permitted_unit?.code || "",
- status: ObservationStatus.AMENDED,
- components: {},
- },
- ],
- };
- });
- }}
- disabled={disableEdit}
- >
-
- {t("add_another_result")}
-
-
-
- );
- })}
+
+
+ file.name)
+ .join(", ")}
+ >
+ {fileUpload.files.length > 0
+ ? fileUpload.files
+ .map((file) => file.name)
+ .join(", ")
+ : t("select_files")}
+
+ {fileUpload.Input({ className: "hidden" })}
+
+
- {fullReport.status !== DiagnosticReportStatus.final && (
+ {fileUpload.files.length > 0 && (
+
fileUpload.clearFiles()}
+ >
+ {t("clear")}
+
+ )}
+
+
+
+ )}
+ {report.status !== DiagnosticReportStatus.final && (
)}
+ {report?.status === DiagnosticReportStatus.preliminary && (
+
+
+
+ {t("save_results")}
+
+
+ )}
+
+
+
+
+
-
- {fullReport?.status ===
- DiagnosticReportStatus.preliminary && (
-
-
-
- {t("save_results")}
-
-
- )}
+ {fileUpload.Dialogues}
+
+
+ );
+}
- {files?.results && files.results.length > 0 && (
-
-
- {t("uploaded_files")}
-
-
-
- )}
+const CreateDiagnosticReportForm = ({
+ activityDefinition,
+ specimens,
+ isCreatingReport,
+ disableEdit,
+ serviceRequestId,
+ handleCreateReport,
+}: {
+ activityDefinition?: {
+ diagnostic_report_codes?: Code[];
+ classification?: string;
+ specimen_requirements?: SpecimenDefinitionRead[];
+ };
+ specimens: SpecimenRead[];
+ isCreatingReport: boolean;
+ disableEdit: boolean;
+ serviceRequestId: string;
+ handleCreateReport: (code?: Code) => void;
+}) => {
+ const [isExpanded, setIsExpanded] = useState(false);
+ const { t } = useTranslation();
+ // Check if all required specimens are collected
+ const hasCollectedSpecimens =
+ activityDefinition?.specimen_requirements?.length === 0 ||
+ specimens.some((specimen) => specimen.status === SpecimenStatus.available);
- {fullReport?.status ===
- DiagnosticReportStatus.preliminary && (
-
-
-
-
-
-
- {t("choose_file")}
-
-
- {t("allowed_formats_are", {
- formats:
- BACKEND_ALLOWED_EXTENSIONS.slice(0, 5).join(
- ", ",
- ) +
- ", " +
- t("etc"),
- })}
-
-
-
- file.name)
- .join(", ")}
- >
- {fileUpload.files.length > 0
- ? fileUpload.files
- .map((file) => file.name)
- .join(", ")
- : t("select_files")}
-
- {fileUpload.Input({ className: "hidden" })}
-
-
+ const isMultipleDiagnosticReport =
+ !!activityDefinition?.diagnostic_report_codes &&
+ activityDefinition.diagnostic_report_codes.length > 0;
- {fileUpload.files.length > 0 && (
-
fileUpload.clearFiles()}
- >
- {t("clear")}
-
- )}
-
-
-
- )}
+ const [selectedReportCode, setSelectedReportCode] = useState
(
+ null,
+ );
+
+ return (
+
+
+
+
+
+
+
+
+ {" "}
+
+ {t("test_results_entry")}
+
+
+
+
+
+
+ {
+ e.stopPropagation();
+ setIsExpanded(!isExpanded);
+ }}
+ >
+ {isExpanded ? (
+
+ ) : (
+
+ )}
+
- ) : (
-
-
-
- {!hasCollectedSpecimens
- ? t("collect_specimen_before_report")
- : t("no_test_results_recorded")}
+
+
+
+
+
+
+
+
+
+
+
+ {!hasCollectedSpecimens
+ ? t("collect_specimen_before_report")
+ : t("no_test_results_recorded")}
+
+ {isMultipleDiagnosticReport && (
+
+ {t("select_report_type_to_create")}
-
-
- {activityDefinition?.diagnostic_report_codes &&
- activityDefinition.diagnostic_report_codes.length > 0 && (
-
-
{
- const code =
- activityDefinition.diagnostic_report_codes?.find(
- (c) => c.code === value,
- );
- setSelectedReportCode(code || null);
- }}
- disabled={!hasCollectedSpecimens || disableEdit}
- >
-
-
-
-
- {activityDefinition.diagnostic_report_codes.map(
- (code) => (
-
-
-
- {code.display} ({code.code})
-
-
-
- ),
- )}
-
-
-
- )}
+ )}
+
+
+ {isMultipleDiagnosticReport && (
+
+
+ {t("select_diagnostic_report_type")}
+
+
{
+ const code =
+ activityDefinition?.diagnostic_report_codes?.find(
+ (c) => c.code === value,
+ );
+ setSelectedReportCode(code || null);
+ }}
+ disabled={!hasCollectedSpecimens || disableEdit}
+ >
+
+
+
+
+ {isMultipleDiagnosticReport &&
+ activityDefinition?.diagnostic_report_codes?.map(
+ (code) => (
+
+
+
+ {code.display} ({code.code})
+
+
+
+ ),
+ )}
+
+
+
+ )}
+
{
+ setSelectedReportCode(null);
+ }}
disabled={
disableEdit ||
isCreatingReport ||
@@ -1260,26 +1432,31 @@ export function DiagnosticReportForm({
(!!activityDefinition?.diagnostic_report_codes?.length &&
!selectedReportCode)
}
- className="w-full sm:w-auto sm:shrink-0"
>
-
+ {t("clear")}
+
+
+ handleCreateReport(selectedReportCode || undefined)
+ }
+ disabled={
+ disableEdit ||
+ isCreatingReport ||
+ !hasCollectedSpecimens ||
+ (!!activityDefinition?.diagnostic_report_codes?.length &&
+ !selectedReportCode)
+ }
+ className="w-full sm:w-auto"
+ >
+
{t("create_report")}
- )}
+
-
- {fileUpload.Dialogues}
-
);
-}
+};
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
index 475213daf45..d2727c0bc69 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
@@ -22,7 +22,6 @@ import {
CollapsibleTrigger,
} from "@/components/ui/collapsible";
import { Label } from "@/components/ui/label";
-import { Skeleton } from "@/components/ui/skeleton";
import { Avatar } from "@/components/Common/Avatar";
import ConfirmActionDialog from "@/components/Common/ConfirmActionDialog";
@@ -57,44 +56,68 @@ export function DiagnosticReportReview({
diagnosticReports,
disableEdit,
}: DiagnosticReportReviewProps) {
+ return (
+ <>
+ {diagnosticReports.map((report) => (
+
+ ))}
+ >
+ );
+}
+
+function DiagnosticReportReviewItem({
+ report,
+ facilityId,
+ patientId,
+ disableEdit,
+}: {
+ report: DiagnosticReportRead;
+ facilityId: string;
+ patientId: string;
+ disableEdit: boolean;
+}) {
const { t } = useTranslation();
+ const queryClient = useQueryClient();
const [isExpanded, setIsExpanded] = useState(true);
const [conclusion, setConclusion] = useState
("");
const [showApproveDialog, setShowApproveDialog] = useState(false);
- const queryClient = useQueryClient();
- const latestReport = diagnosticReports[0];
- // Fetch the full diagnostic report to get observations
- const { data: fullReport, isLoading: isLoadingReport } = useQuery({
- queryKey: ["diagnosticReport", latestReport?.id],
+ const { data: fullReport } = useQuery({
+ queryKey: ["diagnosticReport", report.id],
queryFn: query(diagnosticReportApi.retrieveDiagnosticReport, {
pathParams: {
patient_external_id: patientId,
- external_id: latestReport?.id || "",
+ external_id: report.id,
},
}),
- enabled: !!latestReport?.id,
+ enabled: !!report.id,
});
useEffect(() => {
if (fullReport?.conclusion) {
setConclusion(fullReport.conclusion);
}
- }, [fullReport]);
+ }, [fullReport?.conclusion]);
const { data: files = { results: [], count: 0 } } = useQuery<
PaginatedResponse
>({
- queryKey: ["files", "diagnostic_report", fullReport?.id],
+ queryKey: ["files", "diagnostic_report", report.id],
queryFn: query(fileApi.list, {
queryParams: {
file_type: "diagnostic_report",
- associating_id: fullReport?.id,
+ associating_id: report.id,
limit: 100,
offset: 0,
},
}),
- enabled: !!fullReport?.id,
+ enabled: !!report.id,
});
const { mutate: updateDiagnosticReport, isPending: isUpdatingReport } =
@@ -102,7 +125,7 @@ export function DiagnosticReportReview({
mutationFn: mutate(diagnosticReportApi.updateDiagnosticReport, {
pathParams: {
patient_external_id: patientId,
- external_id: latestReport?.id || "",
+ external_id: report.id,
},
}),
onSuccess: () => {
@@ -118,47 +141,30 @@ export function DiagnosticReportReview({
queryKey: ["files"],
});
},
- onError: (err: any) => {
+ onError: (err: Error) => {
toast.error(
`Failed to approve diagnostic report: ${err.message || "Unknown error"}`,
);
},
});
+ // Prefer the full detail (with observations); fall back to the list report
+ // while the detail request is still loading.
+ const reportDetail = fullReport ?? report;
+
const handleApprove = () => {
- if (latestReport) {
- updateDiagnosticReport({
- ...latestReport,
- status: DiagnosticReportStatus.final,
- conclusion,
- });
- }
+ updateDiagnosticReport({
+ ...reportDetail,
+ status: DiagnosticReportStatus.final,
+ conclusion,
+ });
};
- if (!latestReport) {
- return null;
- }
-
- // Show loading state while fetching the report
- if (isLoadingReport) {
- return (
-
-
-
-
-
-
-
-
-
- );
- }
-
- // Don't show the report review if there are no observations and no files and no conclusion
+ // Don't show the report review if there are no observations, files or conclusion
if (
- (!fullReport?.observations || fullReport.observations.length === 0) &&
+ (!reportDetail.observations || reportDetail.observations.length === 0) &&
(!files?.results || files.results.length === 0) &&
- !fullReport?.conclusion
+ !reportDetail.conclusion
) {
return null;
}
@@ -179,31 +185,27 @@ export function DiagnosticReportReview({
{" "}
- {t("result_review")}
+ {t("result_review", { name: report.code?.display })}
- {fullReport?.created_by && (
+ {report.created_by && (
- {formatName(fullReport.created_by)}
+ {formatName(report.created_by)}
)}
- {fullReport && (
-
- {t(fullReport.status)}
-
- )}
+
+ {t(report.status)}
+
- {fullReport && (
-
+
+
+
+
+ {reportDetail.code?.display}
+
+
+
+ {(reportDetail.observations?.length ?? 0) === 0 && (
+
+ {t("no_observations_entered")}
+
+ )}
+
+ obs.status !== ObservationStatus.ENTERED_IN_ERROR,
+ )}
+ />
+
+
+
+
+
+
+ {t("conclusion")}
+
+ {reportDetail.status === DiagnosticReportStatus.final ? (
+
+ {reportDetail.conclusion || t("no_conclusion_entered")}
+
+ ) : (
+
+
+
+ {files?.results && files.results.length > 0 && (
-
- {fullReport?.code?.display}
+
+ {t("uploaded_files")}
- {fullReport.observations.length == 0 && (
-
- {t("no_observations_entered")}
-
- )}
-
- obs.status !== ObservationStatus.ENTERED_IN_ERROR,
- )}
+
+ )}
-
-
-
- {t("conclusion")}
-
- {fullReport?.status === DiagnosticReportStatus.final ? (
-
- {fullReport?.conclusion || t("no_conclusion_entered")}
-
- ) : (
-
-
-
- {files?.results && files.results.length > 0 && (
-
-
-
- {t("uploaded_files")}
-
-
-
-
-
-
- )}
-
- {fullReport?.status === DiagnosticReportStatus.final && (
-
-
-
-
- {t("view_report")}
-
-
-
- )}
-
- {fullReport?.status === DiagnosticReportStatus.preliminary && (
-
-
setShowApproveDialog(true)}
- >
-
- {t("approve_results")}
+ {report.status === DiagnosticReportStatus.final && (
+
+
+
+
+ {t("view_report")}
-
-
- )}
-
- )}
+
+
+ )}
+
+ {report.status === DiagnosticReportStatus.preliminary && (
+
+ setShowApproveDialog(true)}
+ >
+
+ {t("approve_results")}
+
+
+
+ )}
+
From 7df41e270f6accffb69de31a65e8494fdcc971d8 Mon Sep 17 00:00:00 2001
From: NikhilA8606
Date: Fri, 19 Jun 2026 13:31:35 +0530
Subject: [PATCH 02/27] applied grayish to notReviewable tests
---
public/locale/en.json | 5 ++-
.../components/DiagnosticReportForm.tsx | 19 ++++----
.../components/DiagnosticReportReview.tsx | 45 ++++++++++---------
3 files changed, 36 insertions(+), 33 deletions(-)
diff --git a/public/locale/en.json b/public/locale/en.json
index c58f2f25666..199b2b729d1 100644
--- a/public/locale/en.json
+++ b/public/locale/en.json
@@ -2547,6 +2547,7 @@
"failed_to_check_appointments": "Failed to check appointments",
"failed_to_create_appointment": "Failed to create an appointment",
"failed_to_create_category": "Failed to create category",
+ "failed_to_create_diagnostic_report": "Failed to create diagnostic report: {{error}}",
"failed_to_create_invoice": "Failed to create invoice",
"failed_to_create_questionnaire": "Failed to create Questionnaire",
"failed_to_create_queue": "Failed to create queue",
@@ -5068,7 +5069,7 @@
"review_and_finalise_request_description": "Add more items if needed, or approve to mark this delivery as requested.",
"review_before": "Review Before",
"review_missed": "Review Missed",
- "review_test_results": "Review Test Reult",
+ "review_test_results": "Review Test Result",
"revisit_days_non_negative": "Re-visit allowed days cannot be negative",
"revoke": "Revoke",
"revoke_token": "Revoke Token",
@@ -5534,7 +5535,7 @@
"select_register_patient": "Select/Register Patient",
"select_report": "Select Report",
"select_report_type": "Select Report Type",
- "select_report_type_to_create": "Select 'Select Diagnostic Report Type' and create Report",
+ "select_report_type_to_create": "Select a diagnostic report type to create a new report",
"select_requester": "Select requester",
"select_resource": "Select the resource",
"select_resource_category": "Select resource category",
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
index e096c8788db..74c2431cd1a 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
@@ -157,7 +157,9 @@ export function DiagnosticReportForm({
},
onError: (err: Error) => {
toast.error(
- `Failed to create diagnostic report: ${err.message || "Unknown error"}`,
+ t("failed_to_create_diagnostic_report", {
+ error: err.message || "Unknown error",
+ }),
);
},
});
@@ -263,6 +265,8 @@ export function DiagnosticReportForm({
)}
{diagnosticReports.length === 0 && (
void;
+ hasCollectedSpecimens: boolean;
+ isMultipleDiagnosticReport: boolean;
}) => {
const [isExpanded, setIsExpanded] = useState(false);
const { t } = useTranslation();
- // Check if all required specimens are collected
- const hasCollectedSpecimens =
- activityDefinition?.specimen_requirements?.length === 0 ||
- specimens.some((specimen) => specimen.status === SpecimenStatus.available);
-
- const isMultipleDiagnosticReport =
- !!activityDefinition?.diagnostic_report_codes &&
- activityDefinition.diagnostic_report_codes.length > 0;
const [selectedReportCode, setSelectedReportCode] = useState(
null,
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
index d2727c0bc69..5dc77c8b48a 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
@@ -7,7 +7,7 @@ import {
FileCheck2,
} from "lucide-react";
import { Link } from "raviger";
-import { useEffect, useState } from "react";
+import { useState } from "react";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
@@ -56,8 +56,10 @@ export function DiagnosticReportReview({
diagnosticReports,
disableEdit,
}: DiagnosticReportReviewProps) {
+ const { t } = useTranslation();
return (
- <>
+
+
{t("review_test_results")}
{diagnosticReports.map((report) => (
))}
- >
+
);
}
@@ -85,7 +87,7 @@ function DiagnosticReportReviewItem({
const { t } = useTranslation();
const queryClient = useQueryClient();
const [isExpanded, setIsExpanded] = useState(true);
- const [conclusion, setConclusion] = useState("");
+ const [conclusion, setConclusion] = useState(report.conclusion || "");
const [showApproveDialog, setShowApproveDialog] = useState(false);
const { data: fullReport } = useQuery({
@@ -99,12 +101,6 @@ function DiagnosticReportReviewItem({
enabled: !!report.id,
});
- useEffect(() => {
- if (fullReport?.conclusion) {
- setConclusion(fullReport.conclusion);
- }
- }, [fullReport?.conclusion]);
-
const { data: files = { results: [], count: 0 } } = useQuery<
PaginatedResponse
>({
@@ -160,20 +156,17 @@ function DiagnosticReportReviewItem({
});
};
- // Don't show the report review if there are no observations, files or conclusion
- if (
+ const isReportNotReviewable =
(!reportDetail.observations || reportDetail.observations.length === 0) &&
(!files?.results || files.results.length === 0) &&
- !reportDetail.conclusion
- ) {
- return null;
- }
+ !reportDetail.conclusion;
return (
@@ -181,16 +174,26 @@ function DiagnosticReportReviewItem({
-
-
- {" "}
-
- {t("result_review", { name: report.code?.display })}
+
+
+ {" "}
+
+ {report.code?.display}
+ {isReportNotReviewable && (
+
+ {t("no_observations_entered")}
+
+ )}
{report.created_by && (
Date: Tue, 23 Jun 2026 12:59:41 +0530
Subject: [PATCH 03/27] copilot and greptile suggestions
---
public/locale/en.json | 1 +
.../serviceRequests/ServiceRequestShow.tsx | 39 +++---
.../components/DiagnosticReportForm.tsx | 130 ++++++++++--------
.../components/DiagnosticReportReview.tsx | 21 ++-
4 files changed, 111 insertions(+), 80 deletions(-)
diff --git a/public/locale/en.json b/public/locale/en.json
index 622c90c57b9..16bd1f3df75 100644
--- a/public/locale/en.json
+++ b/public/locale/en.json
@@ -2568,6 +2568,7 @@
"failed_to_remove_tags": "Failed to remove the tag",
"failed_to_restart_encounter": "Failed to restart encounter",
"failed_to_revoke_token": "Failed to revoke token",
+ "failed_to_save_test_results": "Failed to save test results: {{error}}",
"failed_to_send_message": "Failed to send message",
"failed_to_stop_camera": "Failed to stop camera",
"failed_to_unlock_invoice": "Failed to unlock invoice",
diff --git a/src/pages/Facility/services/serviceRequests/ServiceRequestShow.tsx b/src/pages/Facility/services/serviceRequests/ServiceRequestShow.tsx
index 538204c0156..d7a8af3e8f8 100644
--- a/src/pages/Facility/services/serviceRequests/ServiceRequestShow.tsx
+++ b/src/pages/Facility/services/serviceRequests/ServiceRequestShow.tsx
@@ -267,6 +267,10 @@ export default function ServiceRequestShow({
activityDefinition.observation_result_requirements ?? [];
const diagnosticReports = request.diagnostic_reports || [];
+ const activeDiagnosticReports = diagnosticReports.filter(
+ (report) => report.status !== DiagnosticReportStatus.final,
+ );
+
const assignedSpecimenIds = new Set();
const preparePrintAllQRCodes = async () => {
@@ -596,31 +600,26 @@ export default function ServiceRequestShow({
)}
- {(!diagnosticReports.length ||
- diagnosticReports[0]?.status !==
- DiagnosticReportStatus.final) && (
-
- )}
-
- {diagnosticReports.length > 0 && (
-
- )}
+
+
+
{!isMobile && (
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
index 74c2431cd1a..b00fd9ee4ed 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
@@ -301,7 +301,7 @@ function DiagnosticReportItem({
);
const [isExpanded, setIsExpanded] = useState(true);
const [openUploadDialog, setOpenUploadDialog] = useState(false);
- const [conclusion, setConclusion] = useState("");
+ const [conclusion, setConclusion] = useState(report.conclusion || "");
const { data: fullReport } = useQuery({
queryKey: ["diagnosticReport", report.id],
@@ -350,7 +350,9 @@ function DiagnosticReportItem({
},
onError: (err: Error) => {
toast.error(
- `Failed to save test results: ${err.message || "Unknown error"}`,
+ t("failed_to_save_test_results", {
+ error: err.message || "Unknown error",
+ }),
);
},
});
@@ -456,7 +458,7 @@ function DiagnosticReportItem({
if (fullReport?.conclusion) {
setConclusion(fullReport.conclusion);
}
- }, [fullReport]);
+ }, [fullReport, conclusion]);
function handleValueChange(
definitionId: string,
@@ -915,7 +917,7 @@ function DiagnosticReportItem({
{isMultipleDiagnosticReport
? report.code?.display
- : t("test_results_entry")}
+ : report.service_request?.title}
@@ -1365,7 +1367,7 @@ const CreateDiagnosticReportForm = ({
/>
-
+
{!hasCollectedSpecimens
@@ -1377,9 +1379,27 @@ const CreateDiagnosticReportForm = ({
{t("select_report_type_to_create")}
)}
+ {!isMultipleDiagnosticReport && (
+
+ handleCreateReport(selectedReportCode || undefined)
+ }
+ disabled={
+ disableEdit ||
+ isCreatingReport ||
+ !hasCollectedSpecimens ||
+ (!!activityDefinition?.diagnostic_report_codes?.length &&
+ !selectedReportCode)
+ }
+ className="w-full sm:w-auto"
+ >
+
+ {t("create_report")}
+
+ )}
-
- {isMultipleDiagnosticReport && (
+ {isMultipleDiagnosticReport && (
+
{t("select_diagnostic_report_type")}
@@ -1401,57 +1421,59 @@ const CreateDiagnosticReportForm = ({
/>
- {isMultipleDiagnosticReport &&
- activityDefinition?.diagnostic_report_codes?.map(
- (code) => (
-
-
-
- {code.display} ({code.code})
-
-
-
- ),
- )}
+ {activityDefinition?.diagnostic_report_codes?.map(
+ (code) => (
+
+
+
+ {code.display} ({code.code})
+
+
+
+ ),
+ )}
- )}
-
-
{
- setSelectedReportCode(null);
- }}
- disabled={
- disableEdit ||
- isCreatingReport ||
- !hasCollectedSpecimens ||
- (!!activityDefinition?.diagnostic_report_codes?.length &&
- !selectedReportCode)
- }
- >
- {t("clear")}
-
-
- handleCreateReport(selectedReportCode || undefined)
- }
- disabled={
- disableEdit ||
- isCreatingReport ||
- !hasCollectedSpecimens ||
- (!!activityDefinition?.diagnostic_report_codes?.length &&
- !selectedReportCode)
- }
- className="w-full sm:w-auto"
- >
-
- {t("create_report")}
-
+
+
+
{
+ setSelectedReportCode(null);
+ }}
+ disabled={
+ disableEdit ||
+ isCreatingReport ||
+ !hasCollectedSpecimens ||
+ (!!activityDefinition?.diagnostic_report_codes
+ ?.length &&
+ !selectedReportCode)
+ }
+ >
+ {t("clear")}
+
+
+ handleCreateReport(selectedReportCode || undefined)
+ }
+ disabled={
+ disableEdit ||
+ isCreatingReport ||
+ !hasCollectedSpecimens ||
+ (!!activityDefinition?.diagnostic_report_codes
+ ?.length &&
+ !selectedReportCode)
+ }
+ className="w-full sm:w-auto"
+ >
+
+ {t("create_report")}
+
+
-
+ )}
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
index 5dc77c8b48a..9803af3d605 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
@@ -59,7 +59,13 @@ export function DiagnosticReportReview({
const { t } = useTranslation();
return (
-
{t("review_test_results")}
+ {(!diagnosticReports.length ||
+ diagnosticReports.some(
+ (report) => report.status !== DiagnosticReportStatus.final,
+ )) && (
+
{t("review_test_results")}
+ )}
+
{diagnosticReports.map((report) => (
{
updateDiagnosticReport({
- ...reportDetail,
+ id: reportDetail.id,
status: DiagnosticReportStatus.final,
- conclusion,
+ category: reportDetail.category,
+ code: reportDetail.code,
+ note: reportDetail.note,
+ conclusion: conclusion || reportDetail.conclusion,
});
};
@@ -183,7 +192,7 @@ function DiagnosticReportReviewItem({
{" "}
- {report.code?.display}
+ {report.code?.display ?? report.service_request?.title}
@@ -287,7 +296,7 @@ function DiagnosticReportReviewItem({
files={files.results}
type="diagnostic_report"
associatingId={report.id}
- canEdit={true}
+ canEdit={!disableEdit}
showHeader={false}
/>
@@ -312,7 +321,7 @@ function DiagnosticReportReviewItem({
setShowApproveDialog(true)}
>
From 13acde30766582992063ed4569f196057b501e5f Mon Sep 17 00:00:00 2001
From: NikhilA8606
Date: Thu, 25 Jun 2026 15:34:16 +0530
Subject: [PATCH 04/27] ai suggestions
---
public/locale/en.json | 2 ++
src/hooks/useFileUpload.tsx | 4 +++-
.../serviceRequests/ServiceRequestShow.tsx | 17 ++++++++--------
.../components/DiagnosticReportForm.tsx | 20 +++++++++++++------
.../components/DiagnosticReportReview.tsx | 19 ++++++++++--------
5 files changed, 39 insertions(+), 23 deletions(-)
diff --git a/public/locale/en.json b/public/locale/en.json
index 16bd1f3df75..f085ef58ff6 100644
--- a/public/locale/en.json
+++ b/public/locale/en.json
@@ -2538,6 +2538,7 @@
"failed_to_add_service_request": "Failed to add service request",
"failed_to_add_to_template": "Failed to add medication to template",
"failed_to_apply_template": "Failed to apply template",
+ "failed_to_approve_diagnostic_report": "Failed to approve diagnostic report: {{error}}",
"failed_to_archive_child_tag": "Failed to archive child tag",
"failed_to_cancel_invoice": "Failed to cancel invoice",
"failed_to_cancel_payment": "Failed to cancel payment",
@@ -6067,6 +6068,7 @@
"test_results": "Test Results",
"test_results_actions": "Test Results actions",
"test_results_entry": "Test Results Entry",
+ "test_results_saved_successfully": "Test results saved successfully",
"test_type": "Type of test done",
"tested_on": "Tested on",
"tests": "Tests",
diff --git a/src/hooks/useFileUpload.tsx b/src/hooks/useFileUpload.tsx
index 89074727668..ad18399b71e 100644
--- a/src/hooks/useFileUpload.tsx
+++ b/src/hooks/useFileUpload.tsx
@@ -29,6 +29,7 @@ import fileApi from "@/types/files/fileApi";
export type FileUploadOptions = {
multiple?: boolean;
type: FileType;
+ inputId?: string;
category?: FileCategory;
onUpload?: (file: FileReadMinimal) => void;
// if allowed, will fallback to the name of the file if a seperate filename is not defined.
@@ -80,6 +81,7 @@ export default function useFileUpload(
category = FileCategory.UNSPECIFIED,
multiple,
allowNameFallback = true,
+ inputId,
} = options;
const { t } = useTranslation();
@@ -355,7 +357,7 @@ export default function useFileUpload(
const Input = (props: FileInputProps) => (
-
-
+ {diagnosticReports.length > 0 && (
+
+ )}
{!isMobile && (
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
index b00fd9ee4ed..8e111adbf39 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
@@ -105,6 +105,8 @@ interface ObservationValue {
interpretation?: Interpretation;
status: ObservationStatus;
components: Record
;
+
+ facilityId?: string;
}
// New interface to handle multiple observations per definition
@@ -120,6 +122,7 @@ export function DiagnosticReportForm({
activityDefinition,
specimens,
disableEdit,
+ facilityId,
}: DiagnosticReportFormProps) {
const { t } = useTranslation();
const queryClient = useQueryClient();
@@ -198,6 +201,7 @@ export function DiagnosticReportForm({
observationDefinitions={observationDefinitions}
disableEdit={disableEdit}
isMultipleDiagnosticReport={isMultipleDiagnosticReport}
+ facilityId={facilityId}
/>
))}
@@ -265,8 +269,8 @@ export function DiagnosticReportForm({
)}
{diagnosticReports.length === 0 && (
{
- toast.success("Test results saved successfully");
+ toast.success(t("test_results_saved_successfully"));
queryClient.invalidateQueries({
- queryKey: ["serviceRequest", serviceRequestId],
+ queryKey: ["serviceRequest", facilityId, serviceRequestId],
});
queryClient.invalidateQueries({
queryKey: ["diagnosticReport", report.id],
@@ -378,8 +384,10 @@ function DiagnosticReportItem({
});
// Initialize file upload hook
+ const inputId = `file_upload_diagnostic_report_${report.id}`;
const fileUpload = useFileUpload({
type: "diagnostic_report" as FileType,
+ inputId,
multiple: true,
allowedExtensions: BACKEND_ALLOWED_EXTENSIONS,
allowNameFallback: false,
@@ -458,7 +466,7 @@ function DiagnosticReportItem({
if (fullReport?.conclusion) {
setConclusion(fullReport.conclusion);
}
- }, [fullReport, conclusion]);
+ }, [fullReport]);
function handleValueChange(
definitionId: string,
@@ -1202,7 +1210,7 @@ function DiagnosticReportItem({
})}
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
index 9803af3d605..418c922ddeb 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
@@ -31,6 +31,7 @@ import mutate from "@/Utils/request/mutate";
import query from "@/Utils/request/query";
import { PaginatedResponse } from "@/Utils/request/types";
import { formatName } from "@/Utils/utils";
+import { Textarea } from "@/components/ui/textarea";
import { DiagnosticReportResultsTable } from "@/pages/Facility/services/diagnosticReports/components/DiagnosticReportResultsTable";
import {
DIAGNOSTIC_REPORT_STATUS_COLORS,
@@ -59,10 +60,9 @@ export function DiagnosticReportReview({
const { t } = useTranslation();
return (
- {(!diagnosticReports.length ||
- diagnosticReports.some(
- (report) => report.status !== DiagnosticReportStatus.final,
- )) && (
+ {diagnosticReports.some(
+ (report) => report.status !== DiagnosticReportStatus.final,
+ ) && (
{t("review_test_results")}
)}
@@ -145,7 +145,7 @@ function DiagnosticReportReviewItem({
},
onError: (err: Error) => {
toast.error(
- `Failed to approve diagnostic report: ${err.message || "Unknown error"}`,
+ t("failed_to_approve_diagnostic_report", { error: err.message }),
);
},
});
@@ -264,7 +264,10 @@ function DiagnosticReportReviewItem({
-
+
{t("conclusion")}
{reportDetail.status === DiagnosticReportStatus.final ? (
@@ -272,8 +275,8 @@ function DiagnosticReportReviewItem({
{reportDetail.conclusion || t("no_conclusion_entered")}
) : (
-
{t("mark_as_complete")}
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
index 581b014ea1c..5a59d9ca70f 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
@@ -10,6 +10,7 @@ import {
Save,
Trash2,
Upload,
+ X,
} from "lucide-react";
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
@@ -194,43 +195,84 @@ export function DiagnosticReportForm({
))}
{isMultipleDiagnosticReport && (
-
+
{showReportTypeSelect ? (
-
{
- const code =
- activityDefinition?.diagnostic_report_codes?.find(
- (c) => c.code === value,
- );
- setSelectedReportCode(code || null);
- if (code) {
- handleCreateReport(code);
- setShowReportTypeSelect(false);
- setSelectedReportCode(null);
- }
- }}
- disabled={!hasCollectedSpecimens || disableEdit}
- >
-
-
-
-
- {activityDefinition?.diagnostic_report_codes?.map(
- (code) => (
-
-
-
- {code.display} ({code.code})
-
-
-
- ),
- )}
-
-
+
+
setShowReportTypeSelect(false)}
+ variant="ghost"
+ size="icon"
+ className="self-end"
+ >
+
+
+
+
+ {t("select_diagnostic_report_type")}
+
+
{
+ const code =
+ activityDefinition?.diagnostic_report_codes?.find(
+ (c) => c.code === value,
+ );
+ setSelectedReportCode(code || null);
+ }}
+ disabled={!hasCollectedSpecimens || disableEdit}
+ >
+
+
+
+
+ {activityDefinition?.diagnostic_report_codes?.map(
+ (code) => (
+
+
+
+ {code.display} ({code.code})
+
+
+
+ ),
+ )}
+
+
+
+
+
+
{
+ setSelectedReportCode(null);
+ }}
+ disabled={disableEdit || isCreatingReport}
+ >
+ {t("clear")}
+
+
{
+ if (!selectedReportCode) return;
+ handleCreateReport(selectedReportCode);
+ setShowReportTypeSelect(false);
+ setSelectedReportCode(null);
+ }}
+ disabled={
+ disableEdit ||
+ isCreatingReport ||
+ !hasCollectedSpecimens ||
+ !selectedReportCode
+ }
+ className="w-full sm:w-auto"
+ >
+
+ {t("create_report")}
+
+
+
) : (
(
{},
);
- const [isExpanded, setIsExpanded] = useState(true);
+ const [isExpanded, setIsExpanded] = useState(false);
const [openUploadDialog, setOpenUploadDialog] = useState(false);
- const [conclusion, setConclusion] = useState(report.conclusion || "");
+ const [conclusion, setConclusion] = useState("");
const { data: fullReport } = useQuery({
queryKey: ["diagnosticReport", report.id],
@@ -434,10 +476,10 @@ function DiagnosticReportItem({
setObservations(initialObservations);
}
- if (fullReport?.conclusion && conclusion === (report.conclusion || "")) {
- setConclusion(fullReport.conclusion);
+ if (fullReport) {
+ setConclusion(fullReport.conclusion || "");
}
- }, [fullReport, report.conclusion, conclusion]);
+ }, [fullReport]);
function handleValueChange(
definitionId: string,
@@ -1289,7 +1331,7 @@ const CreateDiagnosticReportForm = ({
hasCollectedSpecimens: boolean;
isMultipleDiagnosticReport: boolean;
}) => {
- const [isExpanded, setIsExpanded] = useState(false);
+ const [isExpanded, setIsExpanded] = useState(true);
const { t } = useTranslation();
const [selectedReportCode, setSelectedReportCode] = useState(
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
index 9007c7e7288..a1f5cd85e61 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
@@ -3,8 +3,9 @@ import {
CheckCircle2,
ChevronsDownUp,
ChevronsUpDown,
- ExternalLink,
+ Download,
FileCheck2,
+ FileText,
} from "lucide-react";
import { Link } from "raviger";
import { useEffect, useState } from "react";
@@ -92,7 +93,7 @@ function DiagnosticReportReviewItem({
}) {
const { t } = useTranslation();
const queryClient = useQueryClient();
- const [isExpanded, setIsExpanded] = useState(true);
+ const [isExpanded, setIsExpanded] = useState(false);
const [conclusion, setConclusion] = useState(report.conclusion || "");
const [showApproveDialog, setShowApproveDialog] = useState(false);
@@ -306,16 +307,27 @@ function DiagnosticReportReviewItem({
)}
{report.status === DiagnosticReportStatus.final && (
-
-
-
-
+
+
+
+
+ {t("download_report")}
+
+
+
+
+
{t("view_report")}
-
-
+
+
)}
From 0e5afd598d948eef492a65d23c29be57d6451056 Mon Sep 17 00:00:00 2001
From: NikhilA8606
Date: Mon, 6 Jul 2026 12:49:34 +0530
Subject: [PATCH 12/27] cleanups
---
.../services/diagnosticReports/DiagnosticReportPreview.tsx | 2 +-
.../services/diagnosticReports/DiagnosticReportView.tsx | 2 +-
.../serviceRequests/components/DiagnosticReportReview.tsx | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx
index eaf2a2b2b40..4b11d3189b2 100644
--- a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx
+++ b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx
@@ -101,7 +101,7 @@ export const DiagnosticReportPreview = ({
const { diagnosticReports, isLoading } = useQueries({
queries: diagnosticReportIds.map((diagnosticReportId) => ({
- queryKey: ["diagnosticReport", patientId, diagnosticReportId],
+ queryKey: ["diagnosticReport", diagnosticReportId],
queryFn: query(diagnosticReportApi.retrieveDiagnosticReport, {
pathParams: {
patient_external_id: patientId,
diff --git a/src/pages/Facility/services/diagnosticReports/DiagnosticReportView.tsx b/src/pages/Facility/services/diagnosticReports/DiagnosticReportView.tsx
index 6b3ce6b0d01..f94a1caaccb 100644
--- a/src/pages/Facility/services/diagnosticReports/DiagnosticReportView.tsx
+++ b/src/pages/Facility/services/diagnosticReports/DiagnosticReportView.tsx
@@ -89,7 +89,7 @@ export default function DiagnosticReportView({
{t("back")}
-
+
-
+
-
+
Date: Mon, 6 Jul 2026 21:03:24 +0530
Subject: [PATCH 13/27] removed org routes
---
src/Routers/routes/FacilityRoutes.tsx | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/Routers/routes/FacilityRoutes.tsx b/src/Routers/routes/FacilityRoutes.tsx
index 931b2dd300a..a43195eee61 100644
--- a/src/Routers/routes/FacilityRoutes.tsx
+++ b/src/Routers/routes/FacilityRoutes.tsx
@@ -81,7 +81,6 @@ const FacilityRoutes: AppRoutes = {
}, {}),
...[
"/facility/:facilityId/patient/:patientId/service_request/:serviceRequestId/diagnostic_report/:diagnosticReportId/print",
- "/organization/organizationId/patient/:patientId/service_request/:serviceRequestId/diagnostic_report/:diagnosticReportId/print",
].reduce((acc: AppRoutes, path) => {
acc[path] = ({
patientId,
@@ -100,7 +99,6 @@ const FacilityRoutes: AppRoutes = {
}, {}),
...[
"/facility/:facilityId/patient/:patientId/service_request/:serviceRequestId/diagnostic_reports/print",
- "/organization/organizationId/patient/:patientId/service_request/:serviceRequestId/diagnostic_reports/print",
].reduce((acc: AppRoutes, path) => {
acc[path] = ({ patientId, serviceRequestId, facilityId }) => (
Date: Tue, 7 Jul 2026 12:18:04 +0530
Subject: [PATCH 14/27] revert the facility route
---
src/Routers/routes/FacilityRoutes.tsx | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/Routers/routes/FacilityRoutes.tsx b/src/Routers/routes/FacilityRoutes.tsx
index a43195eee61..43bbc8a3248 100644
--- a/src/Routers/routes/FacilityRoutes.tsx
+++ b/src/Routers/routes/FacilityRoutes.tsx
@@ -81,6 +81,7 @@ const FacilityRoutes: AppRoutes = {
}, {}),
...[
"/facility/:facilityId/patient/:patientId/service_request/:serviceRequestId/diagnostic_report/:diagnosticReportId/print",
+ "organization/organizationId/patient/:patientId/service_request/:serviceRequestId/diagnostic_report/:diagnosticReportId/print",
].reduce((acc: AppRoutes, path) => {
acc[path] = ({
patientId,
@@ -99,6 +100,7 @@ const FacilityRoutes: AppRoutes = {
}, {}),
...[
"/facility/:facilityId/patient/:patientId/service_request/:serviceRequestId/diagnostic_reports/print",
+ "organization/organizationId/patient/:patientId/service_request/:serviceRequestId/diagnostic_reports/print",
].reduce((acc: AppRoutes, path) => {
acc[path] = ({ patientId, serviceRequestId, facilityId }) => (
Date: Tue, 7 Jul 2026 12:41:01 +0530
Subject: [PATCH 15/27] revert the facility route
---
src/Routers/routes/FacilityRoutes.tsx | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/Routers/routes/FacilityRoutes.tsx b/src/Routers/routes/FacilityRoutes.tsx
index 43bbc8a3248..f30fc03d00f 100644
--- a/src/Routers/routes/FacilityRoutes.tsx
+++ b/src/Routers/routes/FacilityRoutes.tsx
@@ -68,7 +68,6 @@ const FacilityRoutes: AppRoutes = {
...[
"/facility/:facilityId/patient/:patientId/diagnostic_reports/:diagnosticReportId",
- "/organization/organizationId/patient/:patientId/diagnostic_reports/:diagnosticReportId",
].reduce((acc: AppRoutes, path) => {
acc[path] = ({ facilityId, patientId, diagnosticReportId }) => (
{
acc[path] = ({
patientId,
@@ -100,7 +98,6 @@ const FacilityRoutes: AppRoutes = {
}, {}),
...[
"/facility/:facilityId/patient/:patientId/service_request/:serviceRequestId/diagnostic_reports/print",
- "organization/organizationId/patient/:patientId/service_request/:serviceRequestId/diagnostic_reports/print",
].reduce((acc: AppRoutes, path) => {
acc[path] = ({ patientId, serviceRequestId, facilityId }) => (
Date: Wed, 8 Jul 2026 12:57:13 +0530
Subject: [PATCH 16/27] minor cleanups
---
public/locale/en.json | 2 +-
.../components/DiagnosticReportForm.tsx | 2 +-
.../components/DiagnosticReportReview.tsx | 10 +++++-----
3 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/public/locale/en.json b/public/locale/en.json
index fab92dd5e7b..dcc4178f44d 100644
--- a/public/locale/en.json
+++ b/public/locale/en.json
@@ -2025,7 +2025,6 @@
"download_discharge_summary": "Download Discharge Summary",
"download_failed": "Failed to download",
"download_latest_report": "Download Latest Report",
- "download_report": "Download Report",
"download_started": "Download started",
"download_to_play": "Download to play locally",
"download_type": "Download Type",
@@ -4552,6 +4551,7 @@
"print_prescriptions": "Print Prescriptions",
"print_qr_codes": "Print QR Codes",
"print_receipt": "Print Receipt",
+ "print_report": "Print Report",
"print_selected": "Print Selected",
"print_setup": "Print Setup",
"print_templates": "Print Templates",
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
index 5a59d9ca70f..b09d6ec09b2 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
@@ -330,7 +330,7 @@ function DiagnosticReportItem({
const [observations, setObservations] = useState(
{},
);
- const [isExpanded, setIsExpanded] = useState(false);
+ const [isExpanded, setIsExpanded] = useState(true);
const [openUploadDialog, setOpenUploadDialog] = useState(false);
const [conclusion, setConclusion] = useState("");
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
index 2f6ad637620..239f9dd1b8e 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
@@ -3,9 +3,9 @@ import {
CheckCircle2,
ChevronsDownUp,
ChevronsUpDown,
- Download,
FileCheck2,
FileText,
+ Printer,
} from "lucide-react";
import { Link } from "raviger";
import { useEffect, useState } from "react";
@@ -308,14 +308,14 @@ function DiagnosticReportReviewItem({
{report.status === DiagnosticReportStatus.final && (
-
+
-
- {t("download_report")}
+
+ {t("print_report")}
From 257deb55f43bf2cedc57036e65e12cc63d84b483 Mon Sep 17 00:00:00 2001
From: NikhilA8606
Date: Wed, 8 Jul 2026 17:32:28 +0530
Subject: [PATCH 17/27] Copilot suggestions
---
public/locale/en.json | 1 -
.../Encounters/tabs/diagnostic-reports.tsx | 2 +-
.../DiagnosticReportPreview.tsx | 13 +++---
.../DiagnosticReportPrint.tsx | 6 +--
.../DiagnosticReportView.tsx | 22 +++++-----
.../serviceRequests/ServiceRequestShow.tsx | 8 ++--
.../components/DiagnosticReportReview.tsx | 42 +++++++++++--------
7 files changed, 50 insertions(+), 44 deletions(-)
diff --git a/public/locale/en.json b/public/locale/en.json
index dcc4178f44d..729c81ad2db 100644
--- a/public/locale/en.json
+++ b/public/locale/en.json
@@ -5032,7 +5032,6 @@
"result_date": "Result Date",
"result_details": "Result details",
"result_on": "Result on",
- "result_review": "Result Review of {{name}}",
"result_value": "Result value",
"resume": "Resume",
"retake": "Retake",
diff --git a/src/pages/Encounters/tabs/diagnostic-reports.tsx b/src/pages/Encounters/tabs/diagnostic-reports.tsx
index da11f076cdf..fa7c87889cc 100644
--- a/src/pages/Encounters/tabs/diagnostic-reports.tsx
+++ b/src/pages/Encounters/tabs/diagnostic-reports.tsx
@@ -170,7 +170,7 @@ function DiagnosticReportDetailCard({
navigate(
buildEncounterUrl(
patientId,
- `/diagnostic_reports/${report.id}/print`,
+ `/service_request/${report.service_request?.id}/diagnostic_report/${report.id}/print`,
facilityId,
),
)
diff --git a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx
index 4b11d3189b2..9009893e55d 100644
--- a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx
+++ b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx
@@ -242,13 +242,16 @@ const DiagnosticReportPreviewItem = ({
if (!files.results.length) return;
const fetchAllUrls = async () => {
- const urls: Record = {};
+ const entries = await Promise.all(
+ files.results
+ .filter((file) => file.id)
+ .map(async (file) => [file.id!, await getFileUrl(file)] as const),
+ );
- for (const file of files.results) {
- if (!file.id) continue;
- const url = await getFileUrl(file);
+ const urls: Record = {};
+ for (const [id, url] of entries) {
if (url) {
- urls[file.id] = url;
+ urls[id] = url;
}
}
diff --git a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPrint.tsx b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPrint.tsx
index 6ad200b0565..4a0ae7c895b 100644
--- a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPrint.tsx
+++ b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPrint.tsx
@@ -34,11 +34,7 @@ export default function DiagnosticReportPrint({
?.filter((report) => report.status === DiagnosticReportStatus.final)
?.map((report) => report.id);
- if (!diagnosticReportId && !serviceRequestId) {
- return {t("service_request_not_found")}
;
- }
-
- if (serviceRequestId && isLoadingRequest) {
+ if (isLoadingRequest) {
return ;
}
diff --git a/src/pages/Facility/services/diagnosticReports/DiagnosticReportView.tsx b/src/pages/Facility/services/diagnosticReports/DiagnosticReportView.tsx
index f94a1caaccb..27c9c78b449 100644
--- a/src/pages/Facility/services/diagnosticReports/DiagnosticReportView.tsx
+++ b/src/pages/Facility/services/diagnosticReports/DiagnosticReportView.tsx
@@ -89,16 +89,18 @@ export default function DiagnosticReportView({
{t("back")}
-
-
-
- {t("print")}
-
-
-
+ {report.service_request?.id && (
+
+
+
+ {t("print")}
+
+
+
+ )}
diff --git a/src/pages/Facility/services/serviceRequests/ServiceRequestShow.tsx b/src/pages/Facility/services/serviceRequests/ServiceRequestShow.tsx
index 05620ba8a4e..3122368f685 100644
--- a/src/pages/Facility/services/serviceRequests/ServiceRequestShow.tsx
+++ b/src/pages/Facility/services/serviceRequests/ServiceRequestShow.tsx
@@ -326,12 +326,12 @@ export default function ServiceRequestShow({
}
};
- const isFinal = request.diagnostic_reports.some(
+ const isFinal = diagnosticReports.some(
(report) => report.status === DiagnosticReportStatus.final,
);
- const totalReports = request.diagnostic_reports.length;
- const pendingReports = request.diagnostic_reports.filter(
+ const totalReports = diagnosticReports.length;
+ const pendingReports = diagnosticReports.filter(
(report) => report.status !== DiagnosticReportStatus.final,
).length;
const hasPendingReports = pendingReports > 0;
@@ -623,8 +623,8 @@ export default function ServiceRequestShow({
)}
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
index 239f9dd1b8e..ebfe044f4df 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
@@ -47,8 +47,9 @@ import fileApi from "@/types/files/fileApi";
interface DiagnosticReportReviewProps {
facilityId: string;
patientId: string;
- serviceRequestId: string;
diagnosticReports: DiagnosticReportRead[];
+
+ serviceRequestId?: string;
disableEdit: boolean;
}
@@ -56,6 +57,7 @@ export function DiagnosticReportReview({
facilityId,
patientId,
diagnosticReports,
+ serviceRequestId,
disableEdit,
}: DiagnosticReportReviewProps) {
const { t } = useTranslation();
@@ -73,6 +75,7 @@ export function DiagnosticReportReview({
report={report}
facilityId={facilityId}
patientId={patientId}
+ serviceRequestId={serviceRequestId}
disableEdit={disableEdit}
/>
))}
@@ -84,11 +87,13 @@ function DiagnosticReportReviewItem({
report,
facilityId,
patientId,
+ serviceRequestId,
disableEdit,
}: {
report: DiagnosticReportRead;
facilityId: string;
patientId: string;
+ serviceRequestId?: string;
disableEdit: boolean;
}) {
const { t } = useTranslation();
@@ -97,7 +102,7 @@ function DiagnosticReportReviewItem({
const [conclusion, setConclusion] = useState
(report.conclusion || "");
const [showApproveDialog, setShowApproveDialog] = useState(false);
- const { data: fullReport } = useQuery({
+ const { data: fullReport, isFetched: isReportFetched } = useQuery({
queryKey: ["diagnosticReport", report.id],
queryFn: query(diagnosticReportApi.retrieveDiagnosticReport, {
pathParams: {
@@ -108,20 +113,19 @@ function DiagnosticReportReviewItem({
enabled: !!report.id && isExpanded,
});
- const { data: files = { results: [], count: 0 } } = useQuery<
- PaginatedResponse
- >({
- queryKey: ["files", "diagnostic_report", report.id],
- queryFn: query(fileApi.list, {
- queryParams: {
- file_type: "diagnostic_report",
- associating_id: report.id,
- limit: 100,
- offset: 0,
- },
- }),
- enabled: !!report.id && isExpanded,
- });
+ const { data: files = { results: [], count: 0 }, isFetched: isFilesFetched } =
+ useQuery>({
+ queryKey: ["files", "diagnostic_report", report.id],
+ queryFn: query(fileApi.list, {
+ queryParams: {
+ file_type: "diagnostic_report",
+ associating_id: report.id,
+ limit: 100,
+ offset: 0,
+ },
+ }),
+ enabled: !!report.id && isExpanded,
+ });
const { mutate: updateDiagnosticReport, isPending: isUpdatingReport } =
useMutation({
@@ -166,6 +170,8 @@ function DiagnosticReportReviewItem({
};
const isReportNotReviewable =
+ isReportFetched &&
+ isFilesFetched &&
(!reportDetail.observations || reportDetail.observations.length === 0) &&
(!files?.results || files.results.length === 0) &&
!reportDetail.conclusion;
@@ -311,7 +317,7 @@ function DiagnosticReportReviewItem({
@@ -321,7 +327,7 @@ function DiagnosticReportReviewItem({
From ac46a0323b709962c53c644bb868b9e673f30684 Mon Sep 17 00:00:00 2001
From: NikhilA8606
Date: Mon, 13 Jul 2026 01:21:21 +0530
Subject: [PATCH 18/27] review and product suggestions
---
src/components/Files/FileUploadDialog.tsx | 4 +-
.../Encounters/tabs/diagnostic-reports.tsx | 1 +
.../DiagnosticReportPreview.tsx | 2 +-
.../components/DiagnosticReportForm.tsx | 61 ++++++++-----
.../components/DiagnosticReportReview.tsx | 88 +++++++++++--------
.../components/WorkflowProgress.tsx | 45 ++++++----
6 files changed, 121 insertions(+), 80 deletions(-)
diff --git a/src/components/Files/FileUploadDialog.tsx b/src/components/Files/FileUploadDialog.tsx
index 9d3ef985248..1f66e57892f 100644
--- a/src/components/Files/FileUploadDialog.tsx
+++ b/src/components/Files/FileUploadDialog.tsx
@@ -215,14 +215,14 @@ export default function FileUploadDialog({
{fileUpload.files.length > 1 && (
setIsPdf(checked)}
disabled={fileUpload.uploading}
className="cursor-pointer"
/>
{t("combine_files_pdf")}
diff --git a/src/pages/Encounters/tabs/diagnostic-reports.tsx b/src/pages/Encounters/tabs/diagnostic-reports.tsx
index fa7c87889cc..615fcc75096 100644
--- a/src/pages/Encounters/tabs/diagnostic-reports.tsx
+++ b/src/pages/Encounters/tabs/diagnostic-reports.tsx
@@ -176,6 +176,7 @@ function DiagnosticReportDetailCard({
)
}
data-shortcut-id="print-button"
+ disabled={!report.service_request?.id}
>
diff --git a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx
index 9009893e55d..fa7573c3e2b 100644
--- a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx
+++ b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx
@@ -128,7 +128,7 @@ export const DiagnosticReportPreview = ({
return (
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
index b09d6ec09b2..a69e5fdfe0e 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
@@ -70,6 +70,7 @@ import { Badge } from "@/components/ui/badge";
import { PLUGIN_Component } from "@/PluginEngine";
import { Interpretation } from "@/types/base/qualifiedRange/qualifiedRange";
import { formatName } from "@/Utils/utils";
+import { format } from "date-fns";
interface DiagnosticReportFormProps {
patientId: string;
@@ -930,33 +931,45 @@ function DiagnosticReportItem({
-
-
-
-
- {" "}
-
- {isMultipleDiagnosticReport
- ? report.code?.display
- : report.service_request?.title}
-
-
+
+
+
+
+
+
+
+ {isMultipleDiagnosticReport
+ ? report.code?.display
+ : report.service_request?.title}
+
+
+ {t("last_updated")}:{" "}
+ {fullReport
+ ? format(
+ fullReport.modified_date,
+ "hh:mm a, MMM dd, yyyy",
+ )
+ : "-"}
+
+
+
-
-
- {report.created_by && (
+
+ {fullReport && (
+
- )}
-
- {formatName(report.created_by)}
-
-
-
+
+ {formatName(fullReport.created_by)}
+
+
+ )}
+
+
@@ -965,7 +978,7 @@ function DiagnosticReportItem({
{
e.stopPropagation();
setIsExpanded(!isExpanded);
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
index 13a694a0111..5daa12f36c6 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
@@ -43,6 +43,7 @@ import diagnosticReportApi from "@/types/emr/diagnosticReport/diagnosticReportAp
import { ObservationStatus } from "@/types/emr/observation/observation";
import { FileReadMinimal } from "@/types/files/file";
import fileApi from "@/types/files/fileApi";
+import { format } from "date-fns";
interface DiagnosticReportReviewProps {
facilityId: string;
@@ -187,58 +188,73 @@ function DiagnosticReportReviewItem({
-
-
+
+
-
- {" "}
-
- {report.code?.display ?? report.service_request?.title}
-
-
+
+
+
+
+ {report.code?.display ?? report.service_request?.title}
+
+
+ {t("last_updated")}:{" "}
+ {fullReport
+ ? format(
+ fullReport.modified_date,
+ "hh:mm a, MMM dd, yyyy",
+ )
+ : "-"}
+
+
+
-
+
{isReportNotReviewable && (
-
+
{t("no_observations_entered")}
)}
- {report.created_by && (
-
+ {reportDetail.created_by && (
+
-
- {formatName(report.created_by)}
+
+ {formatName(reportDetail.created_by)}
)}
-
- {t(report.status)}
-
-
{
- e.stopPropagation();
- setIsExpanded(!isExpanded);
- }}
- >
- {isExpanded ? (
-
- ) : (
-
- )}
-
+
+
+ {t(report.status)}
+
+ {
+ e.stopPropagation();
+ setIsExpanded(!isExpanded);
+ }}
+ >
+ {isExpanded ? (
+
+ ) : (
+
+ )}
+
+
diff --git a/src/pages/Facility/services/serviceRequests/components/WorkflowProgress.tsx b/src/pages/Facility/services/serviceRequests/components/WorkflowProgress.tsx
index 6cd9dc224bb..284c0fc4bf9 100644
--- a/src/pages/Facility/services/serviceRequests/components/WorkflowProgress.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/WorkflowProgress.tsx
@@ -5,6 +5,7 @@ import { cn } from "@/lib/utils";
import CareIcon from "@/CAREUI/icons/CareIcon";
+import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { Drawer, DrawerContent, DrawerTrigger } from "@/components/ui/drawer";
@@ -32,7 +33,14 @@ interface WorkflowProgressProps {
variant?: "sheet" | "card";
}
-function TimelineNode({ event }: { event: TimelineEvent }) {
+function TimelineNode({
+ event,
+ isLatest,
+}: {
+ event: TimelineEvent;
+ isLatest?: boolean;
+}) {
+ const { t } = useTranslation();
return (
@@ -60,16 +68,19 @@ function TimelineNode({ event }: { event: TimelineEvent }) {
-
- {event.title}
-
+
+
+ {event.title}
+
+ {isLatest && {t("latest")} }
+
{event.description}
{event.additional_info}
@@ -93,7 +104,7 @@ function WorkflowContent({ events }: { events: TimelineEvent[] }) {
{events.map((event, index) => (
-
+
))}
@@ -153,7 +164,7 @@ export function WorkflowProgress({
request.diagnostic_reports?.forEach((report: DiagnosticReportRead) => {
events.push({
title: "Diagnostic Report Created",
- description: `${request.title} diagnostic report created`,
+ description: `${report.code?.display} report created`,
timestamp: report.created_date,
status: "completed",
});
@@ -167,17 +178,17 @@ export function WorkflowProgress({
: "Diagnostic Report In Progress",
description:
report.status === "final"
- ? `Report approved and finalized`
- : `Report created and pending approval`,
+ ? `${report.code?.display} report approved and finalized`
+ : `${report.code?.display} report created and pending approval`,
timestamp:
report.status === "final" ? report.modified_date : report.created_date,
status: report.status === "final" ? "completed" : "in_progress",
});
});
- // Sort events by timestamp
+ // Sort events by timestamp (latest first)
events.sort(
- (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime(),
+ (a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime(),
);
if (variant === "sheet") {
From 8fb53bf29a885fe291f471dc383caf99bc71ddf6 Mon Sep 17 00:00:00 2001
From: NikhilA8606
Date: Mon, 13 Jul 2026 02:15:43 +0530
Subject: [PATCH 19/27] resolved copilot suggestions
---
.../diagnosticReports/DiagnosticReportPreview.tsx | 4 ++--
.../services/diagnosticReports/DiagnosticReportPrint.tsx | 6 +-----
.../serviceRequests/components/DiagnosticReportForm.tsx | 2 +-
.../serviceRequests/components/DiagnosticReportReview.tsx | 6 +++---
.../serviceRequests/components/WorkflowProgress.tsx | 8 +++++---
5 files changed, 12 insertions(+), 14 deletions(-)
diff --git a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx
index fa7573c3e2b..96508b0beba 100644
--- a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx
+++ b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx
@@ -19,8 +19,8 @@ import { Loader } from "lucide-react";
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
-import { Document, Page, pdfjs } from "react-pdf";
-pdfjs.GlobalWorkerOptions.workerSrc = "/pdf.worker.min.mjs";
+import "@/lib/pdfWorker";
+import { Document, Page } from "react-pdf";
// TODO: Replace with PDFViewer or extract this to a component
function PDFRenderer({ fileUrl }: { fileUrl: string }) {
diff --git a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPrint.tsx b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPrint.tsx
index 4a0ae7c895b..934c2d36c40 100644
--- a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPrint.tsx
+++ b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPrint.tsx
@@ -34,14 +34,10 @@ export default function DiagnosticReportPrint({
?.filter((report) => report.status === DiagnosticReportStatus.final)
?.map((report) => report.id);
- if (isLoadingRequest) {
+ if (isLoadingRequest || !request) {
return ;
}
- if (!request) {
- return null;
- }
-
const resolvedDiagnosticReportIds = diagnosticReportId
? [diagnosticReportId]
: (diagnosticReportIds ?? []);
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
index 775fcc7118f..8f16978d833 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
@@ -945,7 +945,7 @@ function DiagnosticReportItem({
{t("last_updated")}:{" "}
{fullReport
? format(
- fullReport.modified_date,
+ new Date(fullReport.modified_date),
"hh:mm a, MMM dd, yyyy",
)
: "-"}
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
index 5daa12f36c6..96c467b9b18 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
@@ -50,7 +50,7 @@ interface DiagnosticReportReviewProps {
patientId: string;
diagnosticReports: DiagnosticReportRead[];
- serviceRequestId?: string;
+ serviceRequestId: string;
disableEdit: boolean;
}
@@ -94,7 +94,7 @@ function DiagnosticReportReviewItem({
report: DiagnosticReportRead;
facilityId: string;
patientId: string;
- serviceRequestId?: string;
+ serviceRequestId: string;
disableEdit: boolean;
}) {
const { t } = useTranslation();
@@ -206,7 +206,7 @@ function DiagnosticReportReviewItem({
{t("last_updated")}:{" "}
{fullReport
? format(
- fullReport.modified_date,
+ new Date(fullReport.modified_date),
"hh:mm a, MMM dd, yyyy",
)
: "-"}
diff --git a/src/pages/Facility/services/serviceRequests/components/WorkflowProgress.tsx b/src/pages/Facility/services/serviceRequests/components/WorkflowProgress.tsx
index 284c0fc4bf9..dd6ccfe3255 100644
--- a/src/pages/Facility/services/serviceRequests/components/WorkflowProgress.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/WorkflowProgress.tsx
@@ -164,13 +164,15 @@ export function WorkflowProgress({
request.diagnostic_reports?.forEach((report: DiagnosticReportRead) => {
events.push({
title: "Diagnostic Report Created",
- description: `${report.code?.display} report created`,
+ description: `${report.code?.display ?? report.service_request?.title ?? "Diagnostic"} report created`,
timestamp: report.created_date,
status: "completed",
});
});
request.diagnostic_reports?.forEach((report: DiagnosticReportRead) => {
+ const diagnosticReportName =
+ report.code?.display ?? report.service_request?.title ?? "Diagnostic";
events.push({
title:
report.status === "final"
@@ -178,8 +180,8 @@ export function WorkflowProgress({
: "Diagnostic Report In Progress",
description:
report.status === "final"
- ? `${report.code?.display} report approved and finalized`
- : `${report.code?.display} report created and pending approval`,
+ ? `${diagnosticReportName} report approved and finalized`
+ : `${diagnosticReportName} report created and pending approval`,
timestamp:
report.status === "final" ? report.modified_date : report.created_date,
status: report.status === "final" ? "completed" : "in_progress",
From 53d39eb22bc84bbab22d061c569be002b970c0fb Mon Sep 17 00:00:00 2001
From: NikhilA8606
Date: Mon, 13 Jul 2026 02:42:27 +0530
Subject: [PATCH 20/27] fix print page error
---
.../DiagnosticReportPreview.tsx | 60 ++++++++++---------
.../components/DiagnosticReportForm.tsx | 2 +-
.../components/DiagnosticReportReview.tsx | 10 ++--
3 files changed, 37 insertions(+), 35 deletions(-)
diff --git a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx
index 96508b0beba..55858b207f9 100644
--- a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx
+++ b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx
@@ -292,41 +292,43 @@ const DiagnosticReportPreviewItem = ({
});
return (
-
+
{/* Report header with per-report details */}
-
{report.code?.display}
-
-
- {t("category")}
- :
-
- {report.category?.display || "-"}
-
-
-
- {t("report_date")}
- :
-
- {report.created_date &&
- format(new Date(report.created_date), "dd-MM-yyyy")}
-
-
-
- {t("requested_by")}
- :
-
- {formatName(report.requester)}
-
-
- {report.encounter.current_location && (
+
+
{report.code?.display}
+
+
+ {t("category")}
+ :
+
+ {report.category?.display || "-"}
+
+
- {t("location")}
+ {t("report_date")}
:
- {report.encounter.current_location.name}
+ {report.created_date &&
+ format(new Date(report.created_date), "dd-MM-yyyy")}
- )}
+
+ {t("requested_by")}
+ :
+
+ {formatName(report.requester)}
+
+
+ {report.encounter.current_location && (
+
+ {t("location")}
+ :
+
+ {report.encounter.current_location.name}
+
+
+ )}
+
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
index 8f16978d833..7eb5c9a47df 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
@@ -152,7 +152,7 @@ export function DiagnosticReportForm({
onSuccess: () => {
toast.success(t("diagnostic_report_created_successfully"));
queryClient.invalidateQueries({
- queryKey: ["serviceRequest"],
+ queryKey: ["serviceRequest", facilityId, serviceRequestId],
});
queryClient.invalidateQueries({
queryKey: ["diagnosticReport"],
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
index 96c467b9b18..a791dcac700 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
@@ -99,7 +99,7 @@ function DiagnosticReportReviewItem({
}) {
const { t } = useTranslation();
const queryClient = useQueryClient();
- const [isExpanded, setIsExpanded] = useState(false);
+ const [isExpanded, setIsExpanded] = useState(true);
const [conclusion, setConclusion] = useState
(report.conclusion || "");
const [showApproveDialog, setShowApproveDialog] = useState(false);
@@ -138,15 +138,15 @@ function DiagnosticReportReviewItem({
}),
onSuccess: () => {
toast.success(t("diagnostic_report_approved_successfully"));
- // Invalidate all related queries to update workflow status
+ // Invalidate only the queries affected by this approval
queryClient.invalidateQueries({
- queryKey: ["serviceRequest"],
+ queryKey: ["serviceRequest", facilityId, serviceRequestId],
});
queryClient.invalidateQueries({
- queryKey: ["diagnosticReport"],
+ queryKey: ["diagnosticReport", report.id],
});
queryClient.invalidateQueries({
- queryKey: ["files"],
+ queryKey: ["files", "diagnostic_report", report.id],
});
},
});
From 3cea86c375e8cd36e148f92e4fad8d8f258cae78 Mon Sep 17 00:00:00 2001
From: NikhilA8606
Date: Mon, 13 Jul 2026 18:08:02 +0530
Subject: [PATCH 21/27] cleanup observation history
---
.../serviceRequests/ServiceRequestShow.tsx | 30 +----
.../components/DiagnosticReportForm.tsx | 111 ++++++------------
.../components/DiagnosticReportReview.tsx | 41 ++++++-
3 files changed, 79 insertions(+), 103 deletions(-)
diff --git a/src/pages/Facility/services/serviceRequests/ServiceRequestShow.tsx b/src/pages/Facility/services/serviceRequests/ServiceRequestShow.tsx
index 3122368f685..4d700f513e8 100644
--- a/src/pages/Facility/services/serviceRequests/ServiceRequestShow.tsx
+++ b/src/pages/Facility/services/serviceRequests/ServiceRequestShow.tsx
@@ -62,7 +62,6 @@ import { Classification } from "@/types/emr/activityDefinition/activityDefinitio
import { DiagnosticReportForm } from "./components/DiagnosticReportForm";
import { DiagnosticReportReview } from "./components/DiagnosticReportReview";
import { MultiQRCodePrintSheet } from "./components/MultiQRCodePrintSheet";
-import { ObservationHistorySheet } from "./components/ObservationHistorySheet";
import { ServiceRequestDetails } from "./components/ServiceRequestDetails";
import { SpecimenForm } from "./components/SpecimenForm";
import { SpecimenHistorySheet } from "./components/SpecimenHistorySheet";
@@ -579,33 +578,7 @@ export default function ServiceRequestShow({
{observationRequirements.length > 0 && (
-
-
{t("test_results")}
-
-
-
-
-
-
-
-
- e.preventDefault()}
- onClick={(e) => {
- e.stopPropagation();
- }}
- >
- {t("view_observation_history")}
-
-
-
-
-
+
{t("test_results")}
)}
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
index 7eb5c9a47df..86bbfc0175b 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
@@ -3,8 +3,8 @@ import {
Camera,
ChevronsDownUp,
ChevronsUpDown,
- CloudUpload,
FileUp,
+ MoreVertical,
NotepadText,
Plus,
PlusCircle,
@@ -71,6 +71,13 @@ import { Badge } from "@/components/ui/badge";
import { PLUGIN_Component } from "@/PluginEngine";
import { DottedDivider } from "@/components/careui/dotted-divider";
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
+import { ObservationHistorySheet } from "@/pages/Facility/services/serviceRequests/components/ObservationHistorySheet";
import { Interpretation } from "@/types/base/qualifiedRange/qualifiedRange";
import { formatName } from "@/Utils/utils";
import { format } from "date-fns";
@@ -203,7 +210,10 @@ export function DiagnosticReportForm({
{showReportTypeSelect ? (
setShowReportTypeSelect(false)}
+ onClick={() => {
+ setShowReportTypeSelect(false);
+ setSelectedReportCode(null);
+ }}
variant="ghost"
size="icon"
className="self-end"
@@ -968,7 +978,7 @@ function DiagnosticReportItem({
)}
-
+
@@ -989,6 +999,30 @@ function DiagnosticReportItem({
)}
+ {observationDefinitions.length > 0 && (
+
+
+
+
+
+
+
+
+ e.preventDefault()}
+ onClick={(e) => {
+ e.stopPropagation();
+ }}
+ >
+ {t("view_observation_history")}
+
+
+
+
+ )}
@@ -1200,75 +1234,6 @@ function DiagnosticReportItem({
})}
- {files?.results && files.results.length > 0 && (
-
-
- {t("uploaded_files")}
-
-
-
- )}
-
- {report?.status === DiagnosticReportStatus.preliminary && (
-
-
-
-
-
-
- {t("choose_file")}
-
-
- {t("allowed_formats_are", {
- formats:
- BACKEND_ALLOWED_EXTENSIONS.slice(0, 5).join(
- ", ",
- ) +
- ", " +
- t("etc"),
- })}
-
-
-
- file.name)
- .join(", ")}
- >
- {fileUpload.files.length > 0
- ? fileUpload.files
- .map((file) => file.name)
- .join(", ")
- : t("select_files")}
-
- {fileUpload.Input({ className: "hidden" })}
-
-
-
- {fileUpload.files.length > 0 && (
-
fileUpload.clearFiles()}
- >
- {t("clear")}
-
- )}
-
-
-
- )}
{report.status !== DiagnosticReportStatus.final && (
@@ -1476,7 +1441,7 @@ const CreateDiagnosticReportForm = ({
{
e.stopPropagation();
setIsExpanded(!isExpanded);
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
index a791dcac700..1496076cf54 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportReview.tsx
@@ -5,6 +5,7 @@ import {
ChevronsUpDown,
FileCheck2,
FileText,
+ MoreVertical,
Printer,
} from "lucide-react";
import { Link } from "raviger";
@@ -32,8 +33,15 @@ import mutate from "@/Utils/request/mutate";
import query from "@/Utils/request/query";
import { PaginatedResponse } from "@/Utils/request/types";
import { formatName } from "@/Utils/utils";
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
import { Textarea } from "@/components/ui/textarea";
import { DiagnosticReportResultsTable } from "@/pages/Facility/services/diagnosticReports/components/DiagnosticReportResultsTable";
+import { ObservationHistorySheet } from "@/pages/Facility/services/serviceRequests/components/ObservationHistorySheet";
import {
DIAGNOSTIC_REPORT_STATUS_COLORS,
DiagnosticReportRead,
@@ -41,6 +49,7 @@ import {
} from "@/types/emr/diagnosticReport/diagnosticReport";
import diagnosticReportApi from "@/types/emr/diagnosticReport/diagnosticReportApi";
import { ObservationStatus } from "@/types/emr/observation/observation";
+import { ObservationDefinitionReadSpec } from "@/types/emr/observationDefinition/observationDefinition";
import { FileReadMinimal } from "@/types/files/file";
import fileApi from "@/types/files/fileApi";
import { format } from "date-fns";
@@ -49,7 +58,7 @@ interface DiagnosticReportReviewProps {
facilityId: string;
patientId: string;
diagnosticReports: DiagnosticReportRead[];
-
+ observationDefinitions: ObservationDefinitionReadSpec[];
serviceRequestId: string;
disableEdit: boolean;
}
@@ -59,6 +68,7 @@ export function DiagnosticReportReview({
patientId,
diagnosticReports,
serviceRequestId,
+ observationDefinitions,
disableEdit,
}: DiagnosticReportReviewProps) {
const { t } = useTranslation();
@@ -77,6 +87,7 @@ export function DiagnosticReportReview({
facilityId={facilityId}
patientId={patientId}
serviceRequestId={serviceRequestId}
+ observationDefinitions={observationDefinitions}
disableEdit={disableEdit}
/>
))}
@@ -89,12 +100,14 @@ function DiagnosticReportReviewItem({
facilityId,
patientId,
serviceRequestId,
+ observationDefinitions,
disableEdit,
}: {
report: DiagnosticReportRead;
facilityId: string;
patientId: string;
serviceRequestId: string;
+ observationDefinitions: ObservationDefinitionReadSpec[];
disableEdit: boolean;
}) {
const { t } = useTranslation();
@@ -242,7 +255,7 @@ function DiagnosticReportReviewItem({
{
e.stopPropagation();
setIsExpanded(!isExpanded);
@@ -254,6 +267,30 @@ function DiagnosticReportReviewItem({
)}
+ {observationDefinitions.length > 0 && (
+
+
+
+
+
+
+
+
+ e.preventDefault()}
+ onClick={(e) => {
+ e.stopPropagation();
+ }}
+ >
+ {t("view_observation_history")}
+
+
+
+
+ )}
From 79ff661709ae662be622560e54092d74eeed2ffb Mon Sep 17 00:00:00 2001
From: NikhilA8606
Date: Mon, 13 Jul 2026 19:29:25 +0530
Subject: [PATCH 22/27] Copilot suggestions
---
.../services/diagnosticReports/DiagnosticReportPrint.tsx | 6 +++++-
.../serviceRequests/components/DiagnosticReportForm.tsx | 2 --
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPrint.tsx b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPrint.tsx
index 934c2d36c40..df29a525eef 100644
--- a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPrint.tsx
+++ b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPrint.tsx
@@ -34,10 +34,14 @@ export default function DiagnosticReportPrint({
?.filter((report) => report.status === DiagnosticReportStatus.final)
?.map((report) => report.id);
- if (isLoadingRequest || !request) {
+ if (isLoadingRequest) {
return ;
}
+ if (!request) {
+ return {t("service_request_not_found")}
;
+ }
+
const resolvedDiagnosticReportIds = diagnosticReportId
? [diagnosticReportId]
: (diagnosticReportIds ?? []);
diff --git a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
index 86bbfc0175b..1e3a257675e 100644
--- a/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/DiagnosticReportForm.tsx
@@ -112,8 +112,6 @@ interface ObservationValue {
interpretation?: Interpretation;
status: ObservationStatus;
components: Record;
-
- facilityId?: string;
}
// New interface to handle multiple observations per definition
From 30a15178bd8fb5dbe2043006d57e0e1efd961536 Mon Sep 17 00:00:00 2001
From: NikhilA8606
Date: Tue, 14 Jul 2026 13:17:36 +0530
Subject: [PATCH 23/27] added translation
---
public/locale/en.json | 12 +++++
.../components/WorkflowProgress.tsx | 44 +++++++++++++------
2 files changed, 42 insertions(+), 14 deletions(-)
diff --git a/public/locale/en.json b/public/locale/en.json
index c9597acb7e5..7311d22e912 100644
--- a/public/locale/en.json
+++ b/public/locale/en.json
@@ -1855,12 +1855,19 @@
"diagnosis_history": "Diagnosis History",
"diagnosis_status_placeholder": "Select diagnosis status",
"diagnosis_verification_placeholder": "Select verification status",
+ "diagnostic": "Diagnostic",
"diagnostic_report": "Diagnostic Report",
+ "diagnostic_report_approved": "Diagnostic Report Approved",
+ "diagnostic_report_approved_description": "{{name}} report approved and finalized",
"diagnostic_report_approved_successfully": "Diagnostic report approved successfully",
"diagnostic_report_codes": "Diagnostic Report Codes",
"diagnostic_report_codes_description": "Diagnostic Reports that will be generated.",
+ "diagnostic_report_created": "Diagnostic Report Created",
+ "diagnostic_report_created_description": "{{name}} report created",
"diagnostic_report_created_successfully": "Diagnostic report created successfully",
"diagnostic_report_image": "Diagnostic Report Image",
+ "diagnostic_report_in_progress": "Diagnostic Report In Progress",
+ "diagnostic_report_in_progress_description": "{{name}} report created and pending approval",
"diagnostic_report_not_found": "Diagnostic Report Not Found",
"diagnostic_report_one": "Diagnostic Report",
"diagnostic_report_other": "Diagnostic Reports",
@@ -4947,6 +4954,7 @@
"request_details": "Request Details",
"request_for": "Request for",
"request_id": "Request ID",
+ "request_initiated_by": "Request initiated by {{name}}",
"request_letter": "Request Letter",
"request_order": "Request Order",
"request_order_details": "Request Order Details",
@@ -5688,6 +5696,7 @@
"service_request_completed": "Service request marked as completed",
"service_request_completion_confirmation": "Are you sure you want to mark this service request as complete? This action cannot be undone.",
"service_request_completion_note_description": "Document key findings or remarks before completing this request.",
+ "service_request_created": "Service Request Created",
"service_request_detail_page_description_prefix": "{{count}} deliveries have been received",
"service_request_details": "Service Request Details",
"service_request_invoice_alert": "Back to Service Request",
@@ -5820,6 +5829,7 @@
"specimen_collect_error": "Failed to collect specimen",
"specimen_collect_success": "Specimen collected successfully",
"specimen_collected": "Specimen Collected",
+ "specimen_collected_description": "{{specimen}} collected",
"specimen_collection": "Specimen Collection",
"specimen_collection_info": "Collection Information",
"specimen_collection_instructions": "Specimen Collection Instructions",
@@ -5843,6 +5853,8 @@
"specimen_id": "Specimen ID",
"specimen_identification": "Sample Identification",
"specimen_not_found": "Specimen not found",
+ "specimen_processed": "Specimen Processed",
+ "specimen_processed_description": "{{specimen}} processed",
"specimen_qrcode_scan_info": "QR code scanning to be implemented",
"specimen_requirements": "Specimen Requirements",
"specimen_requirements_description": "Specimen that are the requird to be collected.",
diff --git a/src/pages/Facility/services/serviceRequests/components/WorkflowProgress.tsx b/src/pages/Facility/services/serviceRequests/components/WorkflowProgress.tsx
index dd6ccfe3255..e27ced3d9fb 100644
--- a/src/pages/Facility/services/serviceRequests/components/WorkflowProgress.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/WorkflowProgress.tsx
@@ -117,6 +117,7 @@ export function WorkflowProgress({
className,
variant = "card",
}: WorkflowProgressProps) {
+ const { t } = useTranslation();
const events: TimelineEvent[] = [];
const direction = useBreakpoints({
default: "bottom" as const,
@@ -126,8 +127,10 @@ export function WorkflowProgress({
// Add service request creation
if (request.created_by && request.created_date) {
events.push({
- title: "Service Request Created",
- description: `Request initiated by ${formatName(request.created_by)}`,
+ title: t("service_request_created"),
+ description: t("request_initiated_by", {
+ name: formatName(request.created_by),
+ }),
timestamp: request.created_date,
status: "completed",
});
@@ -137,8 +140,10 @@ export function WorkflowProgress({
request.specimens?.forEach((specimen: SpecimenRead) => {
if (specimen.collection?.collected_date_time) {
events.push({
- title: "Specimen Collected",
- description: `${specimen.specimen_type?.display || "Specimen"} collected`,
+ title: t("specimen_collected"),
+ description: t("specimen_collected_description", {
+ specimen: specimen.specimen_type?.display || t("specimen"),
+ }),
timestamp: specimen.collection.collected_date_time,
status: "completed",
});
@@ -150,9 +155,11 @@ export function WorkflowProgress({
specimen.processing.forEach((processing) => {
if (processing.time_date_time) {
events.push({
- title: "Specimen Processed",
- description: `${specimen.specimen_type?.display || "Specimen"} processed`,
- additional_info: `${processing.method?.display || "Method"}`,
+ title: t("specimen_processed"),
+ description: t("specimen_processed_description", {
+ specimen: specimen.specimen_type?.display || t("specimen"),
+ }),
+ additional_info: processing.method?.display || t("method"),
timestamp: processing.time_date_time,
status: "completed",
});
@@ -163,8 +170,13 @@ export function WorkflowProgress({
// Add diagnostic report events
request.diagnostic_reports?.forEach((report: DiagnosticReportRead) => {
events.push({
- title: "Diagnostic Report Created",
- description: `${report.code?.display ?? report.service_request?.title ?? "Diagnostic"} report created`,
+ title: t("diagnostic_report_created"),
+ description: t("diagnostic_report_created_description", {
+ name:
+ report.code?.display ??
+ report.service_request?.title ??
+ t("diagnostic"),
+ }),
timestamp: report.created_date,
status: "completed",
});
@@ -172,16 +184,20 @@ export function WorkflowProgress({
request.diagnostic_reports?.forEach((report: DiagnosticReportRead) => {
const diagnosticReportName =
- report.code?.display ?? report.service_request?.title ?? "Diagnostic";
+ report.code?.display ?? report.service_request?.title ?? t("diagnostic");
events.push({
title:
report.status === "final"
- ? "Diagnostic Report Approved"
- : "Diagnostic Report In Progress",
+ ? t("diagnostic_report_approved")
+ : t("diagnostic_report_in_progress"),
description:
report.status === "final"
- ? `${diagnosticReportName} report approved and finalized`
- : `${diagnosticReportName} report created and pending approval`,
+ ? t("diagnostic_report_approved_description", {
+ name: diagnosticReportName,
+ })
+ : t("diagnostic_report_in_progress_description", {
+ name: diagnosticReportName,
+ }),
timestamp:
report.status === "final" ? report.modified_date : report.created_date,
status: report.status === "final" ? "completed" : "in_progress",
From ef3e1853f79aee7a9b836bd684e7774a0ec4c4f4 Mon Sep 17 00:00:00 2001
From: NikhilA8606
Date: Thu, 23 Jul 2026 15:48:11 +0530
Subject: [PATCH 24/27] requested changes
---
.../serviceRequests/ServiceRequestShow.tsx | 12 +--
.../components/DiagnosticReportForm.tsx | 77 +++++++++++--------
.../components/WorkflowProgress.tsx | 30 ++++----
3 files changed, 65 insertions(+), 54 deletions(-)
diff --git a/src/pages/Facility/services/serviceRequests/ServiceRequestShow.tsx b/src/pages/Facility/services/serviceRequests/ServiceRequestShow.tsx
index 4d700f513e8..a779e2ad505 100644
--- a/src/pages/Facility/services/serviceRequests/ServiceRequestShow.tsx
+++ b/src/pages/Facility/services/serviceRequests/ServiceRequestShow.tsx
@@ -266,10 +266,6 @@ export default function ServiceRequestShow({
activityDefinition.observation_result_requirements ?? [];
const diagnosticReports = request.diagnostic_reports || [];
- const activeDiagnosticReports = diagnosticReports.filter(
- (report) => report.status !== DiagnosticReportStatus.final,
- );
-
const assignedSpecimenIds = new Set();
const preparePrintAllQRCodes = async () => {
@@ -325,7 +321,7 @@ export default function ServiceRequestShow({
}
};
- const isFinal = diagnosticReports.some(
+ const hasFinalizedReport = diagnosticReports.some(
(report) => report.status === DiagnosticReportStatus.final,
);
@@ -336,7 +332,7 @@ export default function ServiceRequestShow({
const hasPendingReports = pendingReports > 0;
const canMarkAsComplete =
- isFinal ||
+ hasFinalizedReport ||
CLASSIFICATIONS_CAN_BE_MARKED_AS_COMPLETE.includes(request.category);
const canShowCompleteCta =
!request?.activity_definition?.diagnostic_report_codes || canMarkAsComplete;
@@ -361,7 +357,7 @@ export default function ServiceRequestShow({
{canShowCompleteCta && (
<>
- {isFinal && (
+ {hasFinalizedReport && (
0;
+ // Report codes already used by existing diagnostic reports
+ const usedReportCodes = new Set(
+ diagnosticReports
+ .map((report) => report.code?.code)
+ .filter((code): code is string => !!code),
+ );
+
+ // Report codes still available to create a new diagnostic report for
+ const availableReportCodes =
+ activityDefinition?.diagnostic_report_codes?.filter(
+ (code) => !usedReportCodes.has(code.code),
+ ) ?? [];
+
+ const activeDiagnosticReports = diagnosticReports.filter(
+ (report) => report.status !== DiagnosticReportStatus.final,
+ );
+
// Creating a new diagnostic report
const { mutate: createDiagnosticReport, isPending: isCreatingReport } =
useMutation({
@@ -187,10 +204,10 @@ export function DiagnosticReportForm({
return (
<>
- {diagnosticReports.length > 0 && (
+ {activeDiagnosticReports.length > 0 && (
- {diagnosticReports.map((report) => (
+ {activeDiagnosticReports.map((report) => (
))}
- {isMultipleDiagnosticReport && (
+ {isMultipleDiagnosticReport && availableReportCodes.length > 0 && (
{showReportTypeSelect ? (
@@ -239,17 +256,15 @@ export function DiagnosticReportForm({
/>
- {activityDefinition?.diagnostic_report_codes?.map(
- (code) => (
-
-
-
- {code.display} ({code.code})
-
-
-
- ),
- )}
+ {availableReportCodes.map((code) => (
+
+
+
+ {code.display} ({code.code})
+
+
+
+ ))}
@@ -304,8 +319,12 @@ export function DiagnosticReportForm({
)}
)}
- {diagnosticReports.length === 0 && (
+ {((availableReportCodes.length > 0 &&
+ activeDiagnosticReports.length === 0) ||
+ (availableReportCodes.length === 0 &&
+ diagnosticReports.length === 0)) && (
{t("upload_files")}
@@ -1392,6 +1407,7 @@ const CreateDiagnosticReportForm = ({
handleCreateReport,
hasCollectedSpecimens,
isMultipleDiagnosticReport,
+ availableReportCodes,
}: {
activityDefinition?: {
diagnostic_report_codes?: Code[];
@@ -1405,6 +1421,7 @@ const CreateDiagnosticReportForm = ({
handleCreateReport: (code?: Code) => void;
hasCollectedSpecimens: boolean;
isMultipleDiagnosticReport: boolean;
+ availableReportCodes: Code[];
}) => {
const [isExpanded, setIsExpanded] = useState(true);
const { t } = useTranslation();
@@ -1518,17 +1535,15 @@ const CreateDiagnosticReportForm = ({
/>
- {activityDefinition?.diagnostic_report_codes?.map(
- (code) => (
-
-
-
- {code.display} ({code.code})
-
-
-
- ),
- )}
+ {availableReportCodes.map((code) => (
+
+
+
+ {code.display} ({code.code})
+
+
+
+ ))}
diff --git a/src/pages/Facility/services/serviceRequests/components/WorkflowProgress.tsx b/src/pages/Facility/services/serviceRequests/components/WorkflowProgress.tsx
index e27ced3d9fb..35fe4a92b99 100644
--- a/src/pages/Facility/services/serviceRequests/components/WorkflowProgress.tsx
+++ b/src/pages/Facility/services/serviceRequests/components/WorkflowProgress.tsx
@@ -167,21 +167,6 @@ export function WorkflowProgress({
});
});
- // Add diagnostic report events
- request.diagnostic_reports?.forEach((report: DiagnosticReportRead) => {
- events.push({
- title: t("diagnostic_report_created"),
- description: t("diagnostic_report_created_description", {
- name:
- report.code?.display ??
- report.service_request?.title ??
- t("diagnostic"),
- }),
- timestamp: report.created_date,
- status: "completed",
- });
- });
-
request.diagnostic_reports?.forEach((report: DiagnosticReportRead) => {
const diagnosticReportName =
report.code?.display ?? report.service_request?.title ?? t("diagnostic");
@@ -204,6 +189,21 @@ export function WorkflowProgress({
});
});
+ // Add diagnostic report events
+ request.diagnostic_reports?.forEach((report: DiagnosticReportRead) => {
+ events.push({
+ title: t("diagnostic_report_created"),
+ description: t("diagnostic_report_created_description", {
+ name:
+ report.code?.display ??
+ report.service_request?.title ??
+ t("diagnostic"),
+ }),
+ timestamp: report.created_date,
+ status: "completed",
+ });
+ });
+
// Sort events by timestamp (latest first)
events.sort(
(a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime(),
From ae41da75ece6f2ce17cb31ab1e84fb36aa21abb2 Mon Sep 17 00:00:00 2001
From: NikhilA8606
Date: Tue, 28 Jul 2026 16:30:51 +0530
Subject: [PATCH 25/27] used DR api instead of getting it from SR
---
.../DiagnosticReportPreview.tsx | 55 +++++++------------
.../DiagnosticReportPrint.tsx | 45 +++++++++++----
2 files changed, 53 insertions(+), 47 deletions(-)
diff --git a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx
index 55858b207f9..97fda93a350 100644
--- a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx
+++ b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPreview.tsx
@@ -3,9 +3,7 @@ import PrintFooter from "@/components/Common/PrintFooter";
import { DiagnosticReportResultsTable } from "@/pages/Facility/services/diagnosticReports/components/DiagnosticReportResultsTable";
import useCurrentFacility from "@/pages/Facility/utils/useCurrentFacility";
import { DiagnosticReportRead } from "@/types/emr/diagnosticReport/diagnosticReport";
-import diagnosticReportApi from "@/types/emr/diagnosticReport/diagnosticReportApi";
import { ObservationStatus } from "@/types/emr/observation/observation";
-import { ServiceRequestReadSpec } from "@/types/emr/serviceRequest/serviceRequest";
import { PrintTemplateType } from "@/types/facility/printTemplate";
import { FileReadMinimal } from "@/types/files/file";
import fileApi from "@/types/files/fileApi";
@@ -13,13 +11,14 @@ import { PatientIdentifierUse } from "@/types/patient/patientIdentifierConfig/pa
import query from "@/Utils/request/query";
import { PaginatedResponse } from "@/Utils/request/types";
import { formatName, formatPatientAge } from "@/Utils/utils";
-import { useQueries, useQuery } from "@tanstack/react-query";
+import { useQuery } from "@tanstack/react-query";
import { format } from "date-fns";
import { Loader } from "lucide-react";
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import "@/lib/pdfWorker";
+import { ServiceRequestReadSpec } from "@/types/emr/serviceRequest/serviceRequest";
import { Document, Page } from "react-pdf";
// TODO: Replace with PDFViewer or extract this to a component
@@ -88,35 +87,17 @@ function ImageRenderer({
);
}
export const DiagnosticReportPreview = ({
- diagnosticReportIds,
- patientId,
+ diagnosticReports,
+ isLoading,
serviceRequest,
}: {
- diagnosticReportIds: string[];
- patientId: string;
+ diagnosticReports: DiagnosticReportRead[];
+ isLoading: boolean;
serviceRequest: ServiceRequestReadSpec;
}) => {
const { facility } = useCurrentFacility();
const { t } = useTranslation();
- const { diagnosticReports, isLoading } = useQueries({
- queries: diagnosticReportIds.map((diagnosticReportId) => ({
- queryKey: ["diagnosticReport", diagnosticReportId],
- queryFn: query(diagnosticReportApi.retrieveDiagnosticReport, {
- pathParams: {
- patient_external_id: patientId,
- external_id: diagnosticReportId,
- },
- }),
- })),
- combine: (results) => ({
- diagnosticReports: results
- .map((r) => r.data)
- .filter((data): data is DiagnosticReportRead => !!data),
- isLoading: results.some((r) => r.isLoading || r.isFetching),
- }),
- });
-
if (isLoading) {
return (
@@ -125,10 +106,12 @@ export const DiagnosticReportPreview = ({
);
}
+ const diagnosticReportLength = diagnosticReports.length;
+
return (
@@ -146,7 +129,7 @@ export const DiagnosticReportPreview = ({
{serviceRequest.encounter.patient.name}
- {serviceRequest.encounter?.patient &&
+ {serviceRequest.encounter.patient &&
"instance_identifiers" in serviceRequest.encounter.patient &&
serviceRequest.encounter.patient.instance_identifiers
.filter(
@@ -319,7 +302,7 @@ const DiagnosticReportPreviewItem = ({
{formatName(report.requester)}
- {report.encounter.current_location && (
+ {report.encounter?.current_location && (
{t("location")}
:
@@ -333,13 +316,15 @@ const DiagnosticReportPreviewItem = ({
{/* Test Results */}
-
- obs.status !== ObservationStatus.ENTERED_IN_ERROR,
- )}
- />
-
+ {!!report.observations && report.observations.length > 0 && (
+
+ obs.status !== ObservationStatus.ENTERED_IN_ERROR,
+ )}
+ />
+
+ )}
{report.note && (
diff --git a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPrint.tsx b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPrint.tsx
index df29a525eef..ee57c4b2312 100644
--- a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPrint.tsx
+++ b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPrint.tsx
@@ -5,6 +5,7 @@ import query from "@/Utils/request/query";
import Loading from "@/components/Common/Loading";
import { DiagnosticReportPreview } from "@/pages/Facility/services/diagnosticReports/DiagnosticReportPreview";
import { DiagnosticReportStatus } from "@/types/emr/diagnosticReport/diagnosticReport";
+import diagnosticReportApi from "@/types/emr/diagnosticReport/diagnosticReportApi";
import serviceRequestApi from "@/types/emr/serviceRequest/serviceRequestApi";
export default function DiagnosticReportPrint({
@@ -20,7 +21,29 @@ export default function DiagnosticReportPrint({
}) {
const { t } = useTranslation();
- const { data: request, isLoading: isLoadingRequest } = useQuery({
+ const { data: data, isLoading: isLoadingReports } = useQuery({
+ queryKey: ["diagnosticReports", patientId, serviceRequestId],
+ queryFn: query(diagnosticReportApi.listDiagnosticReports, {
+ pathParams: { patient_external_id: patientId },
+ queryParams: {
+ service_request: serviceRequestId,
+ },
+ }),
+ enabled: !diagnosticReportId,
+ });
+
+ const { data: fullReport, isLoading: isLoadingReport } = useQuery({
+ queryKey: ["diagnosticReport", diagnosticReportId],
+ queryFn: query(diagnosticReportApi.retrieveDiagnosticReport, {
+ pathParams: {
+ patient_external_id: patientId,
+ external_id: diagnosticReportId,
+ },
+ }),
+ enabled: !!diagnosticReportId,
+ });
+
+ const { data: request } = useQuery({
queryKey: ["serviceRequest", facilityId, serviceRequestId],
queryFn: query(serviceRequestApi.retrieveServiceRequest, {
pathParams: {
@@ -30,11 +53,13 @@ export default function DiagnosticReportPrint({
}),
});
- const diagnosticReportIds = request?.diagnostic_reports
- ?.filter((report) => report.status === DiagnosticReportStatus.final)
- ?.map((report) => report.id);
+ const diagnosticReports = fullReport
+ ? [fullReport]
+ : data?.results?.filter(
+ (report) => report.status === DiagnosticReportStatus.final,
+ );
- if (isLoadingRequest) {
+ if (isLoadingReport || isLoadingReports) {
return
;
}
@@ -42,18 +67,14 @@ export default function DiagnosticReportPrint({
return
{t("service_request_not_found")}
;
}
- const resolvedDiagnosticReportIds = diagnosticReportId
- ? [diagnosticReportId]
- : (diagnosticReportIds ?? []);
-
- if (resolvedDiagnosticReportIds.length === 0) {
+ if (!diagnosticReports) {
return
{t("no_diagnostic_reports_found")}
;
}
return (
);
From 0256a28f9b0945c6b35a7d8645ed9b1577f8572b Mon Sep 17 00:00:00 2001
From: NikhilA8606
Date: Wed, 29 Jul 2026 14:31:43 +0530
Subject: [PATCH 26/27] added DR name in right pannel of DR list in encounter
---
src/pages/Encounters/tabs/diagnostic-reports.tsx | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/src/pages/Encounters/tabs/diagnostic-reports.tsx b/src/pages/Encounters/tabs/diagnostic-reports.tsx
index 615fcc75096..a06b5de6379 100644
--- a/src/pages/Encounters/tabs/diagnostic-reports.tsx
+++ b/src/pages/Encounters/tabs/diagnostic-reports.tsx
@@ -150,10 +150,12 @@ function DiagnosticReportDetailCard({
return (
-
- {report.service_request?.title ||
- report.code?.display ||
- t("diagnostic_report", { count: 1 })}
+
+
+ {report.service_request?.title ||
+ t("diagnostic_report", { count: 1 })}
+
+ {report.code?.display && - {report.code.display} }
@@ -219,7 +221,7 @@ function DiagnosticReportDetailCard({
{/* Report Details Grid */}
{report.service_request?.code?.display && (
-
+
{t("procedure")}
{report.service_request.code.display}
From cfcaa110a18eae2dad770e44c222dec5f513d090 Mon Sep 17 00:00:00 2001
From: NikhilA8606
Date: Sat, 1 Aug 2026 14:08:59 +0530
Subject: [PATCH 27/27] useQueries to retrieve all report in detail
---
.../DiagnosticReportPrint.tsx | 36 ++++++++++++++++---
1 file changed, 31 insertions(+), 5 deletions(-)
diff --git a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPrint.tsx b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPrint.tsx
index ee57c4b2312..c881fc6eca1 100644
--- a/src/pages/Facility/services/diagnosticReports/DiagnosticReportPrint.tsx
+++ b/src/pages/Facility/services/diagnosticReports/DiagnosticReportPrint.tsx
@@ -1,10 +1,13 @@
-import { useQuery } from "@tanstack/react-query";
+import { useQueries, useQuery } from "@tanstack/react-query";
import { useTranslation } from "react-i18next";
import query from "@/Utils/request/query";
import Loading from "@/components/Common/Loading";
import { DiagnosticReportPreview } from "@/pages/Facility/services/diagnosticReports/DiagnosticReportPreview";
-import { DiagnosticReportStatus } from "@/types/emr/diagnosticReport/diagnosticReport";
+import {
+ DiagnosticReportRead,
+ DiagnosticReportStatus,
+} from "@/types/emr/diagnosticReport/diagnosticReport";
import diagnosticReportApi from "@/types/emr/diagnosticReport/diagnosticReportApi";
import serviceRequestApi from "@/types/emr/serviceRequest/serviceRequestApi";
@@ -21,7 +24,7 @@ export default function DiagnosticReportPrint({
}) {
const { t } = useTranslation();
- const { data: data, isLoading: isLoadingReports } = useQuery({
+ const { data: data } = useQuery({
queryKey: ["diagnosticReports", patientId, serviceRequestId],
queryFn: query(diagnosticReportApi.listDiagnosticReports, {
pathParams: { patient_external_id: patientId },
@@ -43,6 +46,29 @@ export default function DiagnosticReportPrint({
enabled: !!diagnosticReportId,
});
+ const diagnosticReportResults = data?.results;
+
+ const { allDiagnosticReports, isLoading: isLoadingReports } = useQueries({
+ queries:
+ diagnosticReportResults?.map((report) => ({
+ queryKey: ["diagnosticReport", report.id, patientId, facilityId],
+ queryFn: query(diagnosticReportApi.retrieveDiagnosticReport, {
+ pathParams: {
+ patient_external_id: patientId,
+ external_id: report.id,
+ },
+ queryParams: { facility: facilityId },
+ }),
+ enabled: !diagnosticReportId,
+ })) ?? [],
+ combine: (results) => ({
+ allDiagnosticReports: results
+ .map((r) => r.data)
+ .filter((data): data is DiagnosticReportRead => !!data),
+ isLoading: results.some((r) => r.isLoading || r.isFetching),
+ }),
+ });
+
const { data: request } = useQuery({
queryKey: ["serviceRequest", facilityId, serviceRequestId],
queryFn: query(serviceRequestApi.retrieveServiceRequest, {
@@ -55,7 +81,7 @@ export default function DiagnosticReportPrint({
const diagnosticReports = fullReport
? [fullReport]
- : data?.results?.filter(
+ : allDiagnosticReports.filter(
(report) => report.status === DiagnosticReportStatus.final,
);
@@ -74,7 +100,7 @@ export default function DiagnosticReportPrint({
return (
);