Adding NA and updation in Excel,PDF and Print functionality in Employee list.

This commit is contained in:
Kartik Sharma 2025-10-08 18:00:53 +05:30 committed by pramod.mahajan
parent 6246dbd23f
commit 0b1a276898
2 changed files with 101 additions and 131 deletions

View File

@ -131,16 +131,53 @@ const EmployeeList = () => {
const handleExport = (type) => { const handleExport = (type) => {
if (!currentItems || currentItems.length === 0) return; if (!currentItems || currentItems.length === 0) return;
// Map and format employee data for export
const exportData = currentItems.map((item) => ({
"First Name": item.firstName || "",
"Middle Name": item.middleName || "",
"Last Name": item.lastName || "",
"Email": item.email || "",
"Gender": item.gender || "",
"Birth Date": item.birthdate
? moment(item.birthdate).format("DD-MMM-YYYY")
: "",
"Joining Date": item.joiningDate
? moment(item.joiningDate).format("DD-MMM-YYYY")
: "",
"Permanent Address": item.permanentAddress || "",
"Current Address": item.currentAddress || "",
"Phone Number": item.phoneNumber || "",
"Emergency Phone Number": item.emergencyPhoneNumber || "",
"Emergency Contact Person": item.emergencyContactPerson || "",
"Is Active": item.isActive ? "Active" : "Inactive",
"Job Role": item.jobRole || "",
}));
switch (type) { switch (type) {
case "csv": case "csv":
exportToCSV(currentItems, "employees"); exportToCSV(exportData, "employees");
break; break;
case "excel": case "excel":
exportToExcel(currentItems, "employees"); exportToExcel(exportData, "employees");
break; break;
case "pdf": case "pdf":
exportToPDF(currentItems, "employees"); exportToPDF(
currentItems.map((item) => ({
Name: `${item.firstName || ""} ${item.lastName || ""}`.trim(),
Email: item.email || "",
"Phone Number": item.phoneNumber || "",
"Job Role": item.jobRole || "",
"Joining Date": item.joiningDate
? moment(item.joiningDate).format("DD-MMM-YYYY")
: "",
"Gender": item.gender || "",
Status: item.isActive ? "Active" : "Inactive",
})),
"employees",
["Name", "Email", "Phone Number", "Job Role", "Joining Date", "Gender", "Status"]
);
break; break;
case "print": case "print":
printTable(tableRef.current); printTable(tableRef.current);
break; break;
@ -171,12 +208,10 @@ const EmployeeList = () => {
useEffect(() => { useEffect(() => {
if (!loading && Array.isArray(employees)) { if (!loading && Array.isArray(employees)) {
const sorted = [...employees].sort((a, b) => { const sorted = [...employees].sort((a, b) => {
const nameA = `${a.firstName || ""}${a.middleName || ""}${ const nameA = `${a.firstName || ""}${a.middleName || ""}${a.lastName || ""
a.lastName || "" }`.toLowerCase();
}`.toLowerCase(); const nameB = `${b.firstName || ""}${b.middleName || ""}${b.lastName || ""
const nameB = `${b.firstName || ""}${b.middleName || ""}${ }`.toLowerCase();
b.lastName || ""
}`.toLowerCase();
return nameA?.localeCompare(nameB); return nameA?.localeCompare(nameB);
}); });
@ -254,9 +289,8 @@ const EmployeeList = () => {
? "Suspend Employee" ? "Suspend Employee"
: "Reactivate Employee" : "Reactivate Employee"
} }
message={`Are you sure you want to ${ message={`Are you sure you want to ${selectedEmpFordelete?.isActive ? "suspend" : "reactivate"
selectedEmpFordelete?.isActive ? "suspend" : "reactivate" } this employee?`}
} this employee?`}
onSubmit={(id) => onSubmit={(id) =>
suspendEmployee({ suspendEmployee({
employeeId: id, employeeId: id,
@ -486,9 +520,8 @@ const EmployeeList = () => {
Status Status
</th> </th>
<th <th
className={`sorting_disabled ${ className={`sorting_disabled ${!Manage_Employee && "d-none"
!Manage_Employee && "d-none" }`}
}`}
rowSpan="1" rowSpan="1"
colSpan="1" colSpan="1"
style={{ width: "50px" }} style={{ width: "50px" }}
@ -508,24 +541,24 @@ const EmployeeList = () => {
)} )}
{/* Conditional messages for no data or no search results */} {/* Conditional messages for no data or no search results */}
{!loading && {!loading &&
displayData?.length === 0 && displayData?.length === 0 &&
searchText ? ( searchText ? (
<tr> <tr>
<td colSpan={8} className="border-0"> <td colSpan={8} className="border-0">
<div className="py-12"> <div className="py-12">
<small className="muted"> <small className="muted">
'{searchText}' employee not found '{searchText}' employee not found
</small>{" "} </small>{" "}
</div> </div>
</td> </td>
</tr> </tr>
) : null} ) : null}
{!loading && {!loading &&
displayData?.length === 0 && displayData?.length === 0 &&
(!searchText ) ? ( (!searchText) ? (
<tr> <tr>
<td colSpan={8} className="border-0"> <td colSpan={8} className="border-0">
<div className="py-12">{showInactive ? "No In-active Employeee Found" : "No Employeee Found" }</div> <div className="py-12">{showInactive ? "No In-active Employeee Found" : "No Employeee Found"}</div>
</td> </td>
</tr> </tr>
) : null} ) : null}
@ -577,9 +610,10 @@ const EmployeeList = () => {
</span> </span>
</td> </td>
<td className=" d-none d-md-table-cell"> <td className="d-none d-md-table-cell">
{moment(item.joiningDate)?.format("DD-MMM-YYYY")} {item.joiningDate ? moment(item.joiningDate).format("DD-MMM-YYYY") : "NA"}
</td> </td>
<td> <td>
{showInactive ? ( {showInactive ? (
<span <span

View File

@ -40,112 +40,44 @@ export const exportToExcel = (data, fileName = "data") => {
* @param {Array} data - Array of objects to export * @param {Array} data - Array of objects to export
* @param {string} fileName - File name for the PDF (optional) * @param {string} fileName - File name for the PDF (optional)
*/ */
export const exportToPDF = async (data, fileName = "data") => { export const exportToPDF = async (data, fileName = "data", columns = null) => {
if (!data || data.length === 0) return; if (!data || data.length === 0) return;
// Create a new PDF document
const pdfDoc = await PDFDocument.create(); const pdfDoc = await PDFDocument.create();
const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
// Set up the font // Landscape dimensions
const font = await pdfDoc.embedFont(StandardFonts.Helvetica); // Use Helvetica font const pageWidth = 1000; // wider for more space
const pageHeight = 600;
// Calculate column widths dynamically based on data content let page = pdfDoc.addPage([pageWidth, pageHeight]);
const headers = Object.keys(data[0]); const margin = 30;
const rows = data.map(item => headers.map(header => item[header] || '')); let y = pageHeight - margin;
const getMaxColumnWidth = (columnIndex) => { const headers = columns || Object.keys(data[0]);
let maxWidth = font.widthOfTextAtSize(headers[columnIndex], 12); const rowHeight = 25; // slightly taller rows for readability
rows.forEach(row => { const columnSpacing = 150; // increase space between columns
const cellText = row[columnIndex].toString();
maxWidth = Math.max(maxWidth, font.widthOfTextAtSize(cellText, 10)); // Draw headers
headers.forEach((header, i) => {
page.drawText(header, { x: margin + i * columnSpacing, y, font, size: 12 });
});
y -= rowHeight;
// Draw rows
data.forEach(row => {
headers.forEach((header, i) => {
const text = row[header] ? row[header].toString() : '';
page.drawText(text, { x: margin + i * columnSpacing, y, font, size: 10 });
}); });
return maxWidth + 10; // Padding for better spacing y -= rowHeight;
};
const columnWidths = headers.map((_, index) => getMaxColumnWidth(index)); if (y < margin) {
const tableX = 30; // X-coordinate for the table start page = pdfDoc.addPage([pageWidth, pageHeight]); // landscape for new page
const rowHeight = 20; // Height of each row (can be adjusted) y = pageHeight - margin;
const maxPageHeight = 750; // Max available height for content (before a new page is added)
const pageMargin = 30; // Margin from the top of the page
let tableY = maxPageHeight; // Start Y position for the table
const maxPageWidth = 600; // Max available width for content (before a new page is added)
// Add the headers and rows to the page
const addHeadersToPage = (page, scaleFactor) => {
let xPosition = tableX;
headers.forEach((header, index) => {
page.drawText(header, {
x: xPosition,
y: tableY,
font,
size: 12 * scaleFactor, // Scale the header font size
color: rgb(0, 0, 0),
});
xPosition += columnWidths[index] * scaleFactor; // Adjust X position based on scaling
});
tableY -= rowHeight; // Move down after adding headers
};
// Add a new page and reset the table position
const addNewPage = (scaleFactor) => {
const page = pdfDoc.addPage([600, 800]);
tableY = maxPageHeight; // Reset Y position for the new page
addHeadersToPage(page, scaleFactor); // Re-add headers to the new page
return page;
};
// Create the first page and add headers
let page = pdfDoc.addPage([600, 800]);
// Check if the content fits within the page width, scale if necessary
const checkPageWidth = (row) => {
let totalWidth = columnWidths.reduce((acc, width) => acc + width, 0);
let scaleFactor = 1;
if (totalWidth > maxPageWidth) {
scaleFactor = maxPageWidth / totalWidth; // Scale down if necessary
} }
return scaleFactor;
};
// Function to check for page breaks when adding a new row
const checkPageBreak = () => {
if (tableY - rowHeight < pageMargin) {
page = addNewPage(scaleFactor); // Add a new page if there is no space for the next row
}
};
// Add rows to the PDF with pagination and horizontal scaling
rows.forEach(row => {
checkPageBreak(); // Check for page break before adding each row
const scaleFactor = checkPageWidth(row); // Get the scaling factor for the row
// Add headers to the first page and each new page with the same scale factor
if (tableY === maxPageHeight) {
addHeadersToPage(page, scaleFactor); // Add headers only on the first page
}
let xPosition = tableX;
row.forEach((value, index) => {
page.drawText(value.toString(), {
x: xPosition,
y: tableY,
font,
size: 10 * scaleFactor, // Scale the font size
color: rgb(0, 0, 0),
});
xPosition += columnWidths[index] * scaleFactor; // Adjust X position based on scaling
});
tableY -= rowHeight; // Move down to the next row position
}); });
// Serialize the document to bytes
const pdfBytes = await pdfDoc.save(); const pdfBytes = await pdfDoc.save();
// Trigger a download of the PDF
const blob = new Blob([pdfBytes], { type: 'application/pdf' }); const blob = new Blob([pdfBytes], { type: 'application/pdf' });
const link = document.createElement('a'); const link = document.createElement('a');
link.href = URL.createObjectURL(blob); link.href = URL.createObjectURL(blob);
@ -153,15 +85,21 @@ export const exportToPDF = async (data, fileName = "data") => {
link.click(); link.click();
}; };
/** /**
* Print the HTML table by accepting the table element or a reference. * Print the HTML table by accepting the table element or a reference.
* @param {HTMLElement} table - The table element (or ref) to print * @param {HTMLElement} table - The table element (or ref) to print
*/ */
export const printTable = (table) => { export const printTable = (table) => {
if (table) { if (table) {
const newWindow = window.open("", "", "width=600,height=600"); // Open a new window const clone = table.cloneNode(true);
// Remove last column (Actions) from all rows
clone.querySelectorAll("tr").forEach((row) => {
row.removeChild(row.lastElementChild);
});
// Inject styles for the table and body const newWindow = window.open("", "", "width=600,height=600");
newWindow.document.write("<html><head><title>Print Table</title>"); newWindow.document.write("<html><head><title>Print Table</title>");
const style = document.createElement('style'); const style = document.createElement('style');
style.innerHTML = ` style.innerHTML = `
@ -171,16 +109,14 @@ export const printTable = (table) => {
th { background-color: #f2f2f2; } th { background-color: #f2f2f2; }
`; `;
newWindow.document.head.appendChild(style); newWindow.document.head.appendChild(style);
newWindow.document.write("</head><body>"); newWindow.document.write("</head><body>");
newWindow.document.write(table.outerHTML); // Write the table HTML to the new window newWindow.document.write(clone.outerHTML);
newWindow.document.write("</body></html>"); newWindow.document.write("</body></html>");
newWindow.document.close();
newWindow.document.close(); // Close the document stream
// Wait for the document to load before triggering print
newWindow.onload = () => { newWindow.onload = () => {
newWindow.print(); // Trigger the print dialog after the content is loaded newWindow.print();
}; };
} }
}; };