I am trying to generate a long report in react. I used different libraries but there are some limitations like no proper header footer or not able to create layout I am trying to create. I am able to generate report with I am having some issues.
- I am getting first page duplicate
- Its not responsive for small screen it crop pages
const handleDownloadPdf = async (id) => {
let element = document.getElementById(id);
const ft = document.getElementById("report-footer");
ft.style.display = "flex";
const pg = document.getElementById("pagination");
pg.style.display = "none";
element.style.boxShadow = "none";
element.classList.remove("shadow");
const pdf = new jsPDF();
const loadingIndicator = document.createElement("div");
loadingIndicator.style.backgroundColor = "rgba(0, 0, 0, 0.4)";
loadingIndicator.style.color = "white";
loadingIndicator.innerHTML = "Generating Report...";
loadingIndicator.style.position = "fixed";
loadingIndicator.style.top = "0";
loadingIndicator.style.width = "100vw";
loadingIndicator.style.height = "100vh";
loadingIndicator.style.left = "0";
loadingIndicator.style.display = "flex";
loadingIndicator.style.justifyContent = "center";
loadingIndicator.style.alignItems = "center";
document.body.appendChild(loadingIndicator);
// Async function to add a new page
const addPageAsync = async (pdf) => {
return new Promise((resolve) => {
setTimeout(() => {
pdf.addPage();
resolve();
}, 0);
});
};
// Iterate from 0 to totalPages - 1
for (let i = 0; i <= totalPages; i++) {
let element = document.getElementById(id);
console.log(element);
let pageCount = pdf.internal.getNumberOfPages(); // Get total number of pages
if (pageCount > 0 && i === page) continue;
// Capture a section of the element based on the current offset
const canvas = await html2canvas(element, {
useCORS: true,
proxy: "",
scrollY: i * pdf.internal.pageSize.getHeight(),
});
const data = canvas.toDataURL("image/png");
const imgProperties = pdf.getImageProperties(data);
console.log(i);
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = (imgProperties.height * pdfWidth) / imgProperties.width;
// Add the captured section to the PDF
pdf.addImage(data, "PNG", 0, 0, pdfWidth, pdfHeight);
// If there are more sections to capture, add a new page
if (i < totalPages) {
await addPageAsync(pdf).then(() => {
setPage(i);
});
}
}
ft.style.display = "none";
pg.style.display = "block";
loadingIndicator.remove();
// if (pageCount > 1) pdf.deletePage(0);
console.log("PDF");
console.log(pdf);
// Save the PDF
pdf.save(`allottee-report.pdf`);
// Reset styles
element.style.boxShadow = `rgba(17, 17, 26, 0.1) 0px 4px 16px, rgba(17, 17, 26, 0.05) 0px 8px 32px`;
element.classList.add("shadow");
};
<div id="report" style={{ padding: "5px" }}>
<Box
sx={{
background: "url(/assets/report-bg.svg) no-repeat",
minHeight: "300px",
}}
>
<Box display={"flex"} pt="3rem" alignItems={"start"}>
<Box flex={1}>
<img src="/assets/report-logo.svg" alt="Logo" />
</Box>
<Box>
<Box
border={"1px solid rgba(97, 89, 252, 1)"}
borderRadius={"5px"}
>
<Box
display={"flex"}
flexWrap={"wrap"}
alignItems={"center"}
borderBottom={"1px solid rgba(97,89,252,1)"}
p={"10px"}
>
<Box flex={1}>
<Typography fontWeight={"bold"}>Building Name: </Typography>
</Box>
<Box ml={"10px"}>
<Typography>
{paginatedData[0]?.building_information_id?.building_name}{" "}
</Typography>
</Box>
</Box>{" "}
<Box
display={"flex"}
flexWrap={"wrap"}
alignItems={"center"}
borderBottom={"1px solid rgba(97,89,252,1)"}
p={"10px"}
>
<Box flex={1}>
<Typography fontWeight={"bold"}>Address: </Typography>
</Box>
<Box ml={"10px"}>
<Typography>
{paginatedData[0]?.building_information_id?.address_line}
</Typography>
</Box>
</Box>{" "}
<Box
display={"flex"}
flexWrap={"wrap"}
alignItems={"center"}
p={"10px"}
>
<Box flex={1}>
<Typography fontWeight={"bold"}>City: </Typography>
</Box>
<Box ml={"10px"}>
<Typography>
{
paginatedData[0]?.building_information_id
?.area_information?.thana_details?.district_details
?.name
}
</Typography>
</Box>
</Box>
</Box>
</Box>
</Box>
</Box>
<Typography fontSize={"32px"}>Allottee List</Typography>
<Box>
<TableContainer sx={{ width: "100%" }}>
<Table sx={{ width: "100%" }}>
<TableHead sx={{ bgcolor: "rgba(16, 36, 62, 1)", width: "100%" }}>
<TableRow sx={{ width: "100%" }}>
<TableCell sx={{ color: "white" }}>Sl.</TableCell>
<TableCell sx={{ color: "white" }}>Name</TableCell>
<TableCell sx={{ color: "white" }}>Father Name</TableCell>
<TableCell sx={{ color: "white" }}>Flat</TableCell>
<TableCell sx={{ color: "white" }}>Family Members</TableCell>
<TableCell sx={{ color: "white" }}>Phone</TableCell>
<TableCell sx={{ color: "white" }}>Living Status</TableCell>
</TableRow>
</TableHead>
<TableBody>
{paginatedData?.map((a, i) => (
<TableRow
key={a?.id}
sx={{
"&:nth-of-type(even)": {
backgroundColor: "rgba(0, 212, 255, 0.1)",
},
}}
>
<TableCell>{i + 1 + page * rowsPerPage}</TableCell>
<TableCell>{a?.first_name}</TableCell>
<TableCell>{a?.father_name}</TableCell>
<TableCell>{a?.flat_information?.flat_name}</TableCell>
<TableCell>{a?.family_member_no}</TableCell>
<TableCell>{a?.phone}</TableCell>
<TableCell>{a?.living_building}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[5, 10, 15, 20, 25, 30, 35]}
component="div"
id="pagination"
sx={{
width: "100%",
"& .MuiToolbar-root": {
alignItems: "baseline!important",
},
}}
count={allottee.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
<Box
bgcolor={"primary.main"}
display={"none"}
p={"5px"}
height={"52px"}
alignItems={"center"}
color={"white"}
id="report-footer"
flex={"wrap"}
justifyContent={"space-between"}
>
<Box>
<Typography>
Page {page + 1} of {totalPages}
</Typography>
</Box>
<Box>
<Typography> © Copyright by Smartnir </Typography>
</Box>
<Box>
<Typography>
Generated Date: {new Date().toLocaleDateString()}
</Typography>
</Box>
</Box>
</Box>
</div>
I am trying to generate a long report in react. and I want to generate fully responsive proper report