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) => {
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) {
case "csv":
exportToCSV(currentItems, "employees");
exportToCSV(exportData, "employees");
break;
case "excel":
exportToExcel(currentItems, "employees");
exportToExcel(exportData, "employees");
break;
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;
case "print":
printTable(tableRef.current);
break;
@ -171,12 +208,10 @@ const EmployeeList = () => {
useEffect(() => {
if (!loading && Array.isArray(employees)) {
const sorted = [...employees].sort((a, b) => {
const nameA = `${a.firstName || ""}${a.middleName || ""}${
a.lastName || ""
}`.toLowerCase();
const nameB = `${b.firstName || ""}${b.middleName || ""}${
b.lastName || ""
}`.toLowerCase();
const nameA = `${a.firstName || ""}${a.middleName || ""}${a.lastName || ""
}`.toLowerCase();
const nameB = `${b.firstName || ""}${b.middleName || ""}${b.lastName || ""
}`.toLowerCase();
return nameA?.localeCompare(nameB);
});
@ -254,9 +289,8 @@ const EmployeeList = () => {
? "Suspend Employee"
: "Reactivate Employee"
}
message={`Are you sure you want to ${
selectedEmpFordelete?.isActive ? "suspend" : "reactivate"
} this employee?`}
message={`Are you sure you want to ${selectedEmpFordelete?.isActive ? "suspend" : "reactivate"
} this employee?`}
onSubmit={(id) =>
suspendEmployee({
employeeId: id,
@ -486,9 +520,8 @@ const EmployeeList = () => {
Status
</th>
<th
className={`sorting_disabled ${
!Manage_Employee && "d-none"
}`}
className={`sorting_disabled ${!Manage_Employee && "d-none"
}`}
rowSpan="1"
colSpan="1"
style={{ width: "50px" }}
@ -508,24 +541,24 @@ const EmployeeList = () => {
)}
{/* Conditional messages for no data or no search results */}
{!loading &&
displayData?.length === 0 &&
searchText ? (
displayData?.length === 0 &&
searchText ? (
<tr>
<td colSpan={8} className="border-0">
<div className="py-12">
<small className="muted">
'{searchText}' employee not found
</small>{" "}
</div>
<div className="py-12">
<small className="muted">
'{searchText}' employee not found
</small>{" "}
</div>
</td>
</tr>
) : null}
{!loading &&
displayData?.length === 0 &&
(!searchText ) ? (
displayData?.length === 0 &&
(!searchText) ? (
<tr>
<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>
</tr>
) : null}
@ -577,9 +610,10 @@ const EmployeeList = () => {
</span>
</td>
<td className=" d-none d-md-table-cell">
{moment(item.joiningDate)?.format("DD-MMM-YYYY")}
<td className="d-none d-md-table-cell">
{item.joiningDate ? moment(item.joiningDate).format("DD-MMM-YYYY") : "NA"}
</td>
<td>
{showInactive ? (
<span

View File

@ -40,112 +40,44 @@ export const exportToExcel = (data, fileName = "data") => {
* @param {Array} data - Array of objects to export
* @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;
// Create a new PDF document
const pdfDoc = await PDFDocument.create();
const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
// Set up the font
const font = await pdfDoc.embedFont(StandardFonts.Helvetica); // Use Helvetica font
// Calculate column widths dynamically based on data content
const headers = Object.keys(data[0]);
const rows = data.map(item => headers.map(header => item[header] || ''));
// Landscape dimensions
const pageWidth = 1000; // wider for more space
const pageHeight = 600;
let page = pdfDoc.addPage([pageWidth, pageHeight]);
const margin = 30;
let y = pageHeight - margin;
const getMaxColumnWidth = (columnIndex) => {
let maxWidth = font.widthOfTextAtSize(headers[columnIndex], 12);
rows.forEach(row => {
const cellText = row[columnIndex].toString();
maxWidth = Math.max(maxWidth, font.widthOfTextAtSize(cellText, 10));
const headers = columns || Object.keys(data[0]);
const rowHeight = 25; // slightly taller rows for readability
const columnSpacing = 150; // increase space between columns
// 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));
const tableX = 30; // X-coordinate for the table start
const rowHeight = 20; // Height of each row (can be adjusted)
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
if (y < margin) {
page = pdfDoc.addPage([pageWidth, pageHeight]); // landscape for new page
y = pageHeight - margin;
}
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();
// Trigger a download of the PDF
const blob = new Blob([pdfBytes], { type: 'application/pdf' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
@ -153,15 +85,21 @@ export const exportToPDF = async (data, fileName = "data") => {
link.click();
};
/**
* Print the HTML table by accepting the table element or a reference.
* @param {HTMLElement} table - The table element (or ref) to print
*/
export const printTable = (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>");
const style = document.createElement('style');
style.innerHTML = `
@ -171,16 +109,14 @@ export const printTable = (table) => {
th { background-color: #f2f2f2; }
`;
newWindow.document.head.appendChild(style);
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.close(); // Close the document stream
// Wait for the document to load before triggering print
newWindow.document.close();
newWindow.onload = () => {
newWindow.print(); // Trigger the print dialog after the content is loaded
newWindow.print();
};
}
};