forked from CSI-KJSCE/appointment_to_examiner
411 lines
12 KiB
JavaScript
411 lines
12 KiB
JavaScript
import React, { useState, useEffect } from "react";
|
|
import axios from "axios";
|
|
import * as XLSX from "xlsx-js-style";
|
|
import { sendEmail } from "../api";
|
|
|
|
const ConsolidatedTable = () => {
|
|
const [data, setData] = useState([]);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
const fetchData = async () => {
|
|
try {
|
|
const response = await axios.get(
|
|
"http://localhost:8080/api/table/consolidated-table"
|
|
);
|
|
setData(response.data);
|
|
setLoading(false);
|
|
} catch (error) {
|
|
console.error("Error fetching table data:", error);
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
fetchData();
|
|
}, []);
|
|
|
|
if (loading) {
|
|
return <div>Loading...</div>;
|
|
}
|
|
|
|
// Extract unique faculty names
|
|
const uniqueTeachers = [...new Set(data.map((row) => row.Name))];
|
|
|
|
const createExcelFile = (teacherData, teacherName) => {
|
|
const workbook = XLSX.utils.book_new();
|
|
|
|
// Define header information
|
|
const headerInfo = [
|
|
["Somaiya Vidyavihar University"],
|
|
["K. J. SOMAIYA COLLEGE OF ENGINEERING"],
|
|
[
|
|
"Appointment of Internal Examiners for Paper Setting / OR/PR/Assessment/Reassessment",
|
|
],
|
|
["Class: B Tech/M Tech/Honour/Minor"],
|
|
["Department - Computer Engineering"],
|
|
[],
|
|
];
|
|
|
|
const tableHeaders = [
|
|
[
|
|
"Sr No",
|
|
"Semester",
|
|
"Course Code",
|
|
"Course Name",
|
|
"Exam Type",
|
|
"Year",
|
|
"Marks",
|
|
"Surname",
|
|
"First Name",
|
|
"Middle Name",
|
|
"Affiliation/College",
|
|
"Highest Qualification",
|
|
"Career Experience",
|
|
"Oral/Practical",
|
|
"Assessment",
|
|
"Reassessment",
|
|
"Paper Setting",
|
|
"Moderation",
|
|
"PwD Paper Setting",
|
|
],
|
|
];
|
|
|
|
const dataRows = teacherData.map((row, index) => [
|
|
index + 1,
|
|
row.semester,
|
|
row.courseCode,
|
|
row.courseName,
|
|
row.examType,
|
|
row.year,
|
|
row.marks,
|
|
row.surname,
|
|
row.firstName,
|
|
row.middleName,
|
|
row.affiliation,
|
|
row.qualification,
|
|
row.experience,
|
|
row.oralPractical,
|
|
row.assessment,
|
|
row.reassessment,
|
|
row.paperSetting,
|
|
row.moderation,
|
|
row.pwdPaperSetting,
|
|
]);
|
|
|
|
const sheetData = [...headerInfo, ...tableHeaders, ...dataRows];
|
|
const worksheet = XLSX.utils.aoa_to_sheet(sheetData);
|
|
|
|
// Add merged cells
|
|
worksheet["!merges"] = [
|
|
{ s: { r: 0, c: 0 }, e: { r: 0, c: 18 } },
|
|
{ s: { r: 1, c: 0 }, e: { r: 1, c: 18 } },
|
|
{ s: { r: 2, c: 0 }, e: { r: 2, c: 18 } },
|
|
{ s: { r: 3, c: 0 }, e: { r: 3, c: 18 } },
|
|
{ s: { r: 4, c: 0 }, e: { r: 4, c: 18 } },
|
|
];
|
|
|
|
// Define styles
|
|
const boldStyle = {
|
|
font: { bold: true, name: "Times New Roman", sz: 14 },
|
|
alignment: { horizontal: "center", vertical: "center" },
|
|
};
|
|
|
|
const redStyle = {
|
|
font: { bold: true, color: { rgb: "FF0000" }, name: "Times New Roman", sz: 14 },
|
|
alignment: { horizontal: "center", vertical: "center" },
|
|
};
|
|
|
|
const normalStyle = {
|
|
font: { name: "Times New Roman", sz: 12 },
|
|
};
|
|
|
|
// Apply styles to headers
|
|
const headerRanges = [
|
|
{ row: 0, style: boldStyle },
|
|
{ row: 1, style: boldStyle },
|
|
{ row: 2, style: boldStyle },
|
|
{ row: 3, style: boldStyle },
|
|
{ row: 4, style: redStyle },
|
|
];
|
|
|
|
headerRanges.forEach(({ row, style }) => {
|
|
for (let col = 0; col <= 18; col++) {
|
|
const cellAddress = XLSX.utils.encode_cell({ r: row, c: col });
|
|
if (!worksheet[cellAddress]) continue; // Skip empty cells
|
|
worksheet[cellAddress].s = style;
|
|
}
|
|
});
|
|
|
|
// Set column widths for better readability
|
|
worksheet["!cols"] = [
|
|
{ wch: 10 }, // Sr No
|
|
{ wch: 12 }, // Semester
|
|
{ wch: 15 }, // Course Code
|
|
{ wch: 25 }, // Course Name
|
|
{ wch: 15 }, // Exam Type
|
|
{ wch: 10 }, // Year
|
|
{ wch: 10 }, // Marks
|
|
{ wch: 15 }, // Surname
|
|
{ wch: 15 }, // First Name
|
|
{ wch: 15 }, // Middle Name
|
|
{ wch: 20 }, // Affiliation
|
|
{ wch: 20 }, // Qualification
|
|
{ wch: 15 }, // Career Experience
|
|
{ wch: 15 }, // Oral/Practical
|
|
{ wch: 15 }, // Assessment
|
|
{ wch: 15 }, // Reassessment
|
|
{ wch: 15 }, // Paper Setting
|
|
{ wch: 15 }, // Moderation
|
|
{ wch: 15 }, // PwD Paper Setting
|
|
];
|
|
|
|
// Apply normal font style to all cells
|
|
Object.keys(worksheet).forEach((key) => {
|
|
if (worksheet[key] && key[0] !== "!") {
|
|
worksheet[key].s = worksheet[key].s || normalStyle;
|
|
}
|
|
});
|
|
|
|
// Add worksheet to workbook and save file
|
|
XLSX.utils.book_append_sheet(workbook, worksheet, teacherName);
|
|
XLSX.writeFile(workbook, `${teacherName.replace(/\s+/g, "_")}_Table.xlsx`);
|
|
};
|
|
|
|
const bulkDownload = () => {
|
|
uniqueTeachers.forEach((teacher) => {
|
|
const teacherData = data.filter((row) => row.Name === teacher);
|
|
createExcelFile(teacherData, teacher);
|
|
});
|
|
};
|
|
|
|
const handleSendEmail = async (teacher, teacherData) => {
|
|
const workbook = XLSX.utils.book_new();
|
|
|
|
const headerInfo = [
|
|
["Somaiya Vidyavihar University"],
|
|
["K. J. SOMAIYA COLLEGE OF ENGINEERING"],
|
|
[
|
|
"Appointment of Internal Examiners for Paper Setting / OR/PR/Assessment/Reassessment",
|
|
],
|
|
["Class: B Tech/M Tech/Honour/Minor"],
|
|
["Department - Computer Engineering"],
|
|
[],
|
|
];
|
|
|
|
const tableHeaders = [
|
|
[
|
|
"Sr No",
|
|
"Semester",
|
|
"Course Code",
|
|
"Course Name",
|
|
"Exam Type",
|
|
"Year",
|
|
"Marks",
|
|
"Surname",
|
|
"First Name",
|
|
"Middle Name",
|
|
"Affiliation/College",
|
|
"Highest Qualification",
|
|
"Career Experience",
|
|
"Oral/Practical",
|
|
"Assessment",
|
|
"Reassessment",
|
|
"Paper Setting",
|
|
"Moderation",
|
|
"PwD Paper Setting",
|
|
],
|
|
];
|
|
|
|
const dataRows = teacherData.map((row, index) => [
|
|
index + 1,
|
|
row.semester,
|
|
row.courseCode,
|
|
row.courseName,
|
|
row.examType,
|
|
row.year,
|
|
row.marks,
|
|
row.surname,
|
|
row.firstName,
|
|
row.middleName,
|
|
row.affiliation,
|
|
row.qualification,
|
|
row.experience,
|
|
row.oralPractical,
|
|
row.assessment,
|
|
row.reassessment,
|
|
row.paperSetting,
|
|
row.moderation,
|
|
row.pwdPaperSetting,
|
|
]);
|
|
|
|
const sheetData = [...headerInfo, ...tableHeaders, ...dataRows];
|
|
const worksheet = XLSX.utils.aoa_to_sheet(sheetData);
|
|
XLSX.utils.book_append_sheet(workbook, worksheet, teacher);
|
|
|
|
const fileName = `${teacher.replace(/\s+/g, "_")}_table.xlsx`;
|
|
const excelBlob = XLSX.write(workbook, {
|
|
bookType: "xlsx",
|
|
type: "array",
|
|
});
|
|
|
|
const file = new File([excelBlob], fileName, {
|
|
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
});
|
|
|
|
const formData = new FormData();
|
|
formData.append("teacher", teacher);
|
|
formData.append("fileName", fileName);
|
|
const recipientEmail = prompt(`Enter recipient email for ${teacher}:`);
|
|
formData.append("recipientEmail", recipientEmail);
|
|
formData.append("file", file);
|
|
|
|
try {
|
|
const response = await sendEmail(formData);
|
|
alert(`Email sent successfully to ${recipientEmail}`);
|
|
console.log("Response from server:", response);
|
|
} catch (error) {
|
|
console.error("Error sending email:", error);
|
|
alert("Failed to send email.");
|
|
}
|
|
};
|
|
|
|
|
|
return (
|
|
<div>
|
|
<h1 style={{ textAlign: "center" }}>Faculty Tables with Download Options</h1>
|
|
|
|
<div style={{ marginBottom: "20px", textAlign: "center" }}>
|
|
<button
|
|
onClick={bulkDownload}
|
|
className="btn btn-primary"
|
|
style={{
|
|
padding: "10px 15px",
|
|
backgroundColor: "#17a2b8",
|
|
color: "white",
|
|
textDecoration: "none",
|
|
borderRadius: "5px",
|
|
marginRight: "10px",
|
|
}}
|
|
>
|
|
Bulk Download All Tables
|
|
</button>
|
|
<button
|
|
onClick={() => createExcelFile(data, "Consolidated Table")}
|
|
className="btn btn-primary"
|
|
style={{
|
|
padding: "10px 15px",
|
|
backgroundColor: "#28a745",
|
|
color: "white",
|
|
textDecoration: "none",
|
|
borderRadius: "5px",
|
|
}}
|
|
>
|
|
Download Consolidated Table
|
|
</button>
|
|
</div>
|
|
|
|
<div
|
|
style={{
|
|
maxHeight: "70vh",
|
|
overflowY: "auto",
|
|
border: "1px solid #ccc",
|
|
padding: "10px",
|
|
borderRadius: "5px",
|
|
backgroundColor: "#f9f9f9",
|
|
}}
|
|
>
|
|
{uniqueTeachers.map((teacher, index) => {
|
|
const teacherData = data.filter((row) => row.Name === teacher);
|
|
|
|
return (
|
|
<div key={index} style={{ marginBottom: "20px" }}>
|
|
<h2 style={{ textAlign: "center" }}>{teacher}'s Table</h2>
|
|
<table
|
|
border="1"
|
|
style={{
|
|
width: "100%",
|
|
textAlign: "left",
|
|
marginBottom: "10px",
|
|
}}
|
|
>
|
|
<thead>
|
|
<tr>
|
|
<th>Semester</th>
|
|
<th>Course Code</th>
|
|
<th>Course Name</th>
|
|
<th>Exam Type</th>
|
|
<th>Year</th>
|
|
<th>Marks</th>
|
|
<th>Name</th>
|
|
<th>Affiliation/College</th>
|
|
<th>Highest Qualification</th>
|
|
<th>Career Experience</th>
|
|
<th>Oral/Practical</th>
|
|
<th>Assessment</th>
|
|
<th>Reassessment</th>
|
|
<th>Paper Setting</th>
|
|
<th>Moderation</th>
|
|
<th>PwD Paper Setting</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{teacherData.map((row, idx) => (
|
|
<tr key={idx}>
|
|
<td>{row.semester}</td>
|
|
<td>{row.courseCode}</td>
|
|
<td>{row.courseName}</td>
|
|
<td>{row.examType}</td>
|
|
<td>{row.year}</td>
|
|
<td>{row.marks}</td>
|
|
<td>{row.Name}</td>
|
|
<td>{row.affiliation}</td>
|
|
<td>{row.qualification}</td>
|
|
<td>{row.experience}</td>
|
|
<td>{row.oralPractical}</td>
|
|
<td>{row.assessment}</td>
|
|
<td>{row.reassessment}</td>
|
|
<td>{row.paperSetting}</td>
|
|
<td>{row.moderation}</td>
|
|
<td>{row.pwdPaperSetting}</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
|
|
<button
|
|
onClick={() => createExcelFile(teacherData, teacher)}
|
|
className="btn btn-primary"
|
|
style={{
|
|
padding: "10px 15px",
|
|
backgroundColor: "#007bff",
|
|
color: "white",
|
|
textDecoration: "none",
|
|
borderRadius: "5px",
|
|
}}
|
|
>
|
|
Download {teacher}'s Table
|
|
</button>
|
|
{/* Send Email Button */}
|
|
<button
|
|
onClick={() => handleSendEmail(teacher, teacherData)}
|
|
className="btn btn-secondary"
|
|
style={{
|
|
padding: "10px 15px",
|
|
backgroundColor: "#6c757d",
|
|
color: "white",
|
|
textDecoration: "none",
|
|
borderRadius: "5px",
|
|
}}
|
|
>
|
|
Send {teacher}'s CSV via Email
|
|
</button>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ConsolidatedTable;
|