Skip to content

Commit 0887575

Browse files
authored
Merge pull request #294 from nitheesh-aot/develop
ir report html preview
2 parents 9fb042d + 079530e commit 0887575

File tree

4 files changed

+135
-5
lines changed

4 files changed

+135
-5
lines changed

compliance-api/src/compliance_api/services/inspection_record/inspection_record_builder.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ def build_requirement_details(self):
337337
"requirement_id": requirement.id,
338338
"requirement_findings": requirement.findings,
339339
"sort_order": requirement.sort_order,
340-
"compliance_finding": requirement.compliance_finding.name,
340+
"compliance_finding": requirement.compliance_finding.name if requirement.compliance_finding else None,
341341
"enforcement_action": (
342342
"Not Applicable"
343343
if requirement.compliance_finding_id
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { Box, DialogContent } from "@mui/material";
2+
import { FC } from "react";
3+
import ModalTitleBar from "@/components/Shared/Modals/ModalTitleBar";
4+
5+
type ReportPreviewModalProps = {
6+
previewHtml: string;
7+
};
8+
9+
const ReportPreviewModal: FC<ReportPreviewModalProps> = ({ previewHtml }) => {
10+
return (
11+
<>
12+
<ModalTitleBar title="Report Preview" />
13+
<DialogContent dividers sx={{ maxHeight: "80vh" }}>
14+
{previewHtml ? (
15+
<Box
16+
sx={{
17+
height: "100%",
18+
overflow: "auto",
19+
"& img": { maxWidth: "100%" },
20+
}}
21+
dangerouslySetInnerHTML={{ __html: previewHtml }}
22+
/>
23+
) : (
24+
<Box
25+
sx={{
26+
display: "flex",
27+
justifyContent: "center",
28+
alignItems: "center",
29+
height: "100%",
30+
}}
31+
>
32+
No preview available
33+
</Box>
34+
)}
35+
</DialogContent>
36+
</>
37+
);
38+
};
39+
40+
export default ReportPreviewModal;

compliance-web/src/components/App/Inspections/Profile/Reports/ReportTopSection.tsx

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ import {
55
IRProgressEnum,
66
STAFF_USER_POSITION,
77
} from "@/utils/constants";
8-
import { useMemo } from "react";
9-
import { useUpdateIRApprovalStatus } from "@/hooks/useInspectionReports";
8+
import { useMemo, useState } from "react";
9+
import {
10+
useInspectionRecordRender,
11+
useUpdateIRApprovalStatus,
12+
} from "@/hooks/useInspectionReports";
1013
import { notify } from "@/store/snackbarStore";
1114
import { useReportStore } from "./reportStore";
1215
import { IRApproval } from "@/models/IRApproval";
@@ -15,10 +18,12 @@ import { useStaffUsersData } from "@/hooks/useStaff";
1518
import SendForApprovalModal from "./SendForApprovalModal";
1619
import { useModal } from "@/store/modalStore";
1720
import OfficerStepper from "./OfficerSteppr/OfficerStepper";
21+
import ReportPreviewModal from "./ReportPreviewModal";
1822

1923
export default function ReportTopSection() {
2024
const { setOpen, setClose } = useModal();
2125
const currentUser = useCurrentLoggedInUser();
26+
const [previewClicked, setPreviewClicked] = useState(false);
2227

2328
const {
2429
queryClient,
@@ -30,6 +35,54 @@ export default function ReportTopSection() {
3035

3136
const { data: staffData } = useStaffUsersData();
3237

38+
const { refetch: refetchIrRenderData } = useInspectionRecordRender(
39+
inspectionData?.id ?? 0,
40+
inspectionReportsData?.id ?? 0,
41+
"html",
42+
false
43+
);
44+
45+
const handlePreviewClick = async () => {
46+
setPreviewClicked(true);
47+
try {
48+
const result = await refetchIrRenderData();
49+
if (result.data) {
50+
setPreviewClicked(false);
51+
52+
if (result.data.html) {
53+
// Handle HTML preview
54+
const html = result.data.html ?? "";
55+
setOpen({
56+
content: <ReportPreviewModal previewHtml={html} />,
57+
width: "612px",
58+
});
59+
} else {
60+
// Create a Blob from the PDF data
61+
const blob = new Blob([result.data], { type: "application/pdf" });
62+
63+
// Create a URL for the Blob
64+
const url = URL.createObjectURL(blob);
65+
66+
// Create an anchor element and set properties for download
67+
const link = document.createElement("a");
68+
link.href = url;
69+
link.download = `inspection-report-${inspectionReportsData?.id || "download"}.pdf`;
70+
71+
// Append to body, click and clean up
72+
document.body.appendChild(link);
73+
link.click();
74+
document.body.removeChild(link);
75+
76+
// Release the blob URL
77+
URL.revokeObjectURL(url);
78+
}
79+
}
80+
} catch (error) {
81+
notify.error("Failed to generate PDF preview");
82+
setPreviewClicked(false);
83+
}
84+
};
85+
3386
const isCurrentUserApprover = useMemo(() => {
3487
return staffData?.some(
3588
(staff) =>
@@ -170,9 +223,14 @@ export default function ReportTopSection() {
170223
</Button>
171224
</>
172225
) : null}
173-
<Button variant="text" color="primary">
226+
<Button
227+
variant="text"
228+
color="primary"
229+
onClick={handlePreviewClick}
230+
disabled={previewClicked}
231+
>
174232
<PictureAsPdfOutlined sx={{ mr: 1, fontSize: 20 }} />
175-
Preview
233+
{previewClicked ? "Loading..." : "Preview"}
176234
</Button>
177235
</Box>
178236
</Box>

compliance-web/src/hooks/useInspectionReports.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,23 @@ const updateIRApprovalStatus = ({
134134
});
135135
};
136136

137+
const inspectionRecordRender = ({
138+
inspectionId,
139+
inspectionRecordId,
140+
format,
141+
}: {
142+
inspectionId: number;
143+
inspectionRecordId: number;
144+
format: "html" | "pdf";
145+
}) => {
146+
return request({
147+
url: `/inspections/${inspectionId}/inspection-records/${inspectionRecordId}/render`,
148+
params: {
149+
output_format: format,
150+
},
151+
});
152+
};
153+
137154
export const useInspectionReportsData = (inspectionId: number) => {
138155
return useQuery({
139156
queryKey: ["inspection-reports", inspectionId],
@@ -196,3 +213,18 @@ export const useUpdateIRApprovalStatus = (onSuccess: OnSuccessType) => {
196213
onSuccess,
197214
});
198215
};
216+
217+
export const useInspectionRecordRender = (
218+
inspectionId: number,
219+
inspectionRecordId: number,
220+
format: "html" | "pdf",
221+
isEnabled: boolean = true
222+
) => {
223+
return useQuery({
224+
queryKey: ["ir-render", inspectionId, inspectionRecordId],
225+
queryFn: () =>
226+
inspectionRecordRender({ inspectionId, inspectionRecordId, format }),
227+
enabled: !!inspectionId && !!inspectionRecordId && isEnabled,
228+
refetchOnWindowFocus: false,
229+
});
230+
};

0 commit comments

Comments
 (0)