From 5fcab8ea134cd6a65d8da33c212b4a5da95a039b Mon Sep 17 00:00:00 2001
From: NikhilA8606
Date: Tue, 16 Jun 2026 09:18:23 +0530
Subject: [PATCH 1/6] 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 2/6] 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 3/6] 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 4/6] 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")}
) : (
-