From 675d5735b0c191a5928197ebf71fe040bd90442e Mon Sep 17 00:00:00 2001 From: Harshitha Shetty <141444342+HarshithaShetty27@users.noreply.github.com> Date: Fri, 24 Jan 2025 13:05:06 +0530 Subject: [PATCH] xlsx-css for mail and optimized --- client/src/Pages/ConsolidatedTable.jsx | 206 +-------------------- client/src/Pages/CourseTable.jsx | 17 -- client/src/Pages/FilterPage.jsx | 20 --- client/src/api.js | 236 +++++++++++++++---------- server/routes/optionsRoutes.js | 21 --- 5 files changed, 148 insertions(+), 352 deletions(-) diff --git a/client/src/Pages/ConsolidatedTable.jsx b/client/src/Pages/ConsolidatedTable.jsx index 0b64365..a87acaf 100644 --- a/client/src/Pages/ConsolidatedTable.jsx +++ b/client/src/Pages/ConsolidatedTable.jsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from "react"; import axios from "axios"; import * as XLSX from "xlsx-js-style"; import { sendEmail } from "../api"; +import { createExcelBook } from "../api"; const ConsolidatedTable = () => { const [data, setData] = useState([]); @@ -32,143 +33,7 @@ const ConsolidatedTable = () => { 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", - "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.Name, - 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); + const workbook = createExcelBook(teacherData, teacherName); XLSX.writeFile(workbook, `${teacherName.replace(/\s+/g, "_")}_Table.xlsx`); }; @@ -181,72 +46,13 @@ const ConsolidatedTable = () => { const handleSendEmail = async (teacher, teacherData) => { const facultyId = teacherData[0].facultyId; // This assumes all rows for a teacher have the same facultyId - console.log(facultyId); try { // Fetch email from the backend const response = await axios.get( `http://localhost:8080/api/faculty/${facultyId}` ); const facultyEmail = response.data.email; - 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", - "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.Name, - 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 workbook = createExcelBook(teacherData, teacher); const fileName = `${teacher.replace(/\s+/g, "_")}_table.xlsx`; const excelBlob = XLSX.write(workbook, { bookType: "xlsx", @@ -259,7 +65,7 @@ const ConsolidatedTable = () => { const formData = new FormData(); formData.append("teacher", teacher); - formData.append("fileName", fileName); + formData.append("fileName", fileName); formData.append("recipientEmail", facultyEmail); formData.append("file", file); @@ -272,8 +78,8 @@ const ConsolidatedTable = () => { alert("Failed to send email."); } } catch (error) { - console.error("Error sending email:", error); - alert("Failed to send email."); + console.error("Error fetching Faculty data:", error); + alert("Failed to fetch faculty data."); } }; diff --git a/client/src/Pages/CourseTable.jsx b/client/src/Pages/CourseTable.jsx index 5edf073..9933b3d 100644 --- a/client/src/Pages/CourseTable.jsx +++ b/client/src/Pages/CourseTable.jsx @@ -26,23 +26,6 @@ const CourseTable = () => { fetchAllCourses(); }, [state?.courses]); - // useEffect(() => { - // if (state?.updatedCourse) { - // setCourses((prevCourses) => { - // // Filter only the updated course - // const filteredCourses = prevCourses.filter((course) => - // course.courseId === state.updatedCourse.courseId - // ); - - // return filteredCourses.map((course) => - // course.courseId === state.updatedCourse.courseId - // ? { ...course, status: "Submitted" } // Update status - // : course - // ); - // }); - // } - // }, [state?.updatedCourse]); - useEffect(() => { if (state?.updatedCourse) { setCourses((prevCourses) => diff --git a/client/src/Pages/FilterPage.jsx b/client/src/Pages/FilterPage.jsx index 2b2572b..85de54f 100644 --- a/client/src/Pages/FilterPage.jsx +++ b/client/src/Pages/FilterPage.jsx @@ -23,26 +23,6 @@ const FilterPage = () => { } }; - // const handleApplyFilter = async () => { - // if (!formData.scheme || !formData.semester || !formData.department || !formData.program) { - // alert("Please fill all the fields before applying the filter."); - // return; - // } - - // try { - // const filteredCourses = await fetchCourses(formData); - // console.log(formData); - // if (filteredCourses.length > 0) { - // navigate("/courses", { state: { courses: filteredCourses } }); - // } else { - // alert("No courses found for the selected filters."); - // } - // } catch (error) { - // console.error("Error fetching courses:", error); - // alert("Failed to fetch courses. Please try again later."); - // } - // }; - const handleApplyFilter = async () => { if (!formData.scheme || !formData.semester || !formData.department || !formData.program) { alert("Please fill all the fields before applying the filter."); diff --git a/client/src/api.js b/client/src/api.js index 5e942f3..826784c 100644 --- a/client/src/api.js +++ b/client/src/api.js @@ -138,99 +138,6 @@ export const updateCourseStatus = async (courseId) => { }); }; -// Send email -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."); - } -}; - - export const sendEmail = async (formData) => { try { const url = `${BASE_URL}/send-email`; @@ -258,4 +165,145 @@ export const sendEmail = async (formData) => { console.error( error.message); throw error; } -}; \ No newline at end of file +}; + +export const createExcelBook = (teacherData, teacher) => { + 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", + "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.Name, + 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, teacher); + return workbook; +} \ No newline at end of file diff --git a/server/routes/optionsRoutes.js b/server/routes/optionsRoutes.js index 57c606d..93ce3a1 100644 --- a/server/routes/optionsRoutes.js +++ b/server/routes/optionsRoutes.js @@ -1,24 +1,3 @@ -// const express = require('express'); -// const router = express.Router(); - -// // Sample data (replace this with actual data fetching logic) -// const optionsData = { -// assessment: ["Option 1", "Option 2", "Option 3"], -// reassessment: ["Option A", "Option B"], -// paperSetting: ["Option X", "Option Y"], -// moderation: ["Option M", "Option N"], -// pwdPaperSetter: ["Option P", "Option Q"], -// oralsPracticals: ["Option O", "Option P"] -// }; - -// // GET route for fetching options -// router.get('/', (req, res) => { -// res.status(200).json(optionsData); -// }); - -// module.exports = router; - - const express = require('express'); const router = express.Router(); const { getFaculties } = require('../controller/facultyController'); // Import your controller that interacts with the database