diff --git a/client/src/Pages/ConsolidatedTable.jsx b/client/src/Pages/ConsolidatedTable.jsx index d38dea5..d6e1f95 100644 --- a/client/src/Pages/ConsolidatedTable.jsx +++ b/client/src/Pages/ConsolidatedTable.jsx @@ -1,197 +1,7 @@ -// import React, { useState, useEffect } from "react"; -// import axios from "axios"; - -// 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
Loading...
; -// } - -// return ( -//
-//

Consolidated Table

-// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// {data.map((row, index) => ( -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// ))} -// -//
SemesterCourse CodeCourse NameExam TypeYearMarksNameAffiliation/CollegeHighest QualificationCareer ExperienceOral/PracticalAssessmentReassessmentPaper SettingModerationPwD Paper Setting
{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}
-//
-// ); -// }; - -// export default ConsolidatedTable; - - - -// import React, { useState, useEffect } from "react"; -// import axios from "axios"; -// import { CSVLink } from "react-csv"; - -// 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
Loading...
; -// } - -// // Extract unique faculty names -// const uniqueTeachers = [...new Set(data.map((row) => row.Name))]; - -// return ( -//
-//

Faculty Tables with Download Option

-// {uniqueTeachers.map((teacher, index) => { -// // Filter rows for the current teacher -// const teacherData = data.filter((row) => row.Name === teacher); - -// return ( -//
-//

{teacher}'s Table

-// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// {teacherData.map((row, idx) => ( -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// ))} -// -//
SemesterCourse CodeCourse NameExam TypeYearMarksNameAffiliation/CollegeHighest QualificationCareer ExperienceOral/PracticalAssessmentReassessmentPaper SettingModerationPwD Paper Setting
{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}
-// {/* CSV Download Button */} -// -// Download CSV -// -//
-// ); -// })} -//
-// ); -// }; - -// export default ConsolidatedTable; - - - import React, { useState, useEffect, useRef } from "react"; import axios from "axios"; import { CSVLink } from "react-csv"; +import { sendEmail } from "../api"; const ConsolidatedTable = () => { const [data, setData] = useState([]); @@ -201,7 +11,9 @@ const ConsolidatedTable = () => { useEffect(() => { const fetchData = async () => { try { - const response = await axios.get("http://localhost:8080/api/table/consolidated-table"); + const response = await axios.get( + "http://localhost:8080/api/table/consolidated-table" + ); setData(response.data); setLoading(false); } catch (error) { @@ -229,6 +41,46 @@ const ConsolidatedTable = () => { }); }; + const handleSendEmail = async (teacher, teacherData) => { + const csvHeaders = Object.keys(teacherData[0]); + const csvRows = teacherData.map((row) => + csvHeaders + .map( + (header) => `"${row[header]?.toString().replace(/"/g, '""') || ""}"` + ) + .join(",") + ); + const csvContent = [csvHeaders.join(","), ...csvRows].join("\n"); + const fileName = `${teacher.replace(/\s+/g, "_")}_table.csv`; + + try { + const recipientEmail = prompt(`Enter recipient email for ${teacher}:`); + if (!recipientEmail) { + alert("Email is required!"); + return; + } + + // Create email data object + const emailData = { + teacher, + csvData: csvContent, + fileName, + recipientEmail, + }; + + // Call sendEmail from api.js + const response = await sendEmail(emailData); + + // Handle success + alert(`Email sent successfully to ${recipientEmail}`); + console.log("Response from server:", response); + alert(`Email sent successfully to ${recipientEmail}`); + } catch (error) { + console.error("Error sending email:", error); + alert("Failed to send email."); + } + }; + return (

Faculty Tables with Download Options

@@ -285,7 +137,14 @@ const ConsolidatedTable = () => { return (

{teacher}'s Table

- +
@@ -345,6 +204,20 @@ const ConsolidatedTable = () => { > Download {teacher}'s CSV + {/* Send Email Button */} + ); })} diff --git a/client/src/api.js b/client/src/api.js index 3e58baf..5ab5e71 100644 --- a/client/src/api.js +++ b/client/src/api.js @@ -137,3 +137,31 @@ export const updateCourseStatus = async (courseId) => { }); }; +// Send email +export const sendEmail = async (emailData) => { + console.log("Sending email with data:", emailData); + + // Validate input + // if (!emailData.to || !emailData.subject || !emailData.message) { + // const errorMessage = "Missing required fields: to, subject, message"; + // console.error(errorMessage); + // throw new Error(errorMessage); + // } + + try { + const url = `${BASE_URL}/send-email`; + const response = await fetchData(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(emailData), // Pass the email data to the server + }); + + console.log("Email sent successfully:", response); + return response; + } catch (error) { + console.error("Error sending email:", error.message); + throw error; + } +}; \ No newline at end of file diff --git a/server/routes/emailRoutes.js b/server/routes/emailRoutes.js new file mode 100644 index 0000000..17cb07b --- /dev/null +++ b/server/routes/emailRoutes.js @@ -0,0 +1,58 @@ +// /routes/email.js +const express = require("express"); +const nodemailer = require("nodemailer"); +const fs = require("fs"); +const router = express.Router(); + +router.post("/", async (req, res) => { + const { teacher, csvData, fileName, recipientEmail } = req.body; + + if (!teacher || !csvData || !fileName || !recipientEmail) { + return res.status(400).json({ error: "Missing required fields" }); + } + + // Save the CSV data to a temporary file + const filePath = `./${fileName}`; + fs.writeFileSync(filePath, csvData); + + // Configure Nodemailer transporter + const transporter = nodemailer.createTransport({ + service: "gmail", + auth: { + user: "swdc.ate@gmail.com", // Replace with your email + pass: "umlc hbkr dpga iywd", // Replace with your app-specific password or token + }, + // tls: { + // rejectUnauthorized: false, // Disable SSL verification + // } + }); + + // Email options + const mailOptions = { + from: "swdc.ate@gmail.com", // Replace with your email + to: recipientEmail, + subject: `CSV File for ${teacher}`, + text: `Attached is the CSV file for ${teacher}.`, + attachments: [ + { + filename: fileName, + path: filePath, + }, + ], + }; + + try { + // Send email + await transporter.sendMail(mailOptions); + + // Delete the temporary file after sending the email + fs.unlinkSync(filePath); + + res.status(200).json({ message: "Email sent successfully" }); + } catch (error) { + console.error("Error sending email:", error); + res.status(500).json({ error: "Failed to send email" }); + } +}); + +module.exports = router; diff --git a/server/server.js b/server/server.js index 5558ae2..2b1baa9 100644 --- a/server/server.js +++ b/server/server.js @@ -15,6 +15,7 @@ const facultyRoutes = require("./routes/facultyRoutes"); const appointmentRoutes = require("./routes/appointmentRoutes"); const optionsRoutes = require("./routes/optionsRoutes"); const consolidatedRoutes = require("./routes/consolidatedRoutes"); +const emailRoutes = require("./routes/emailRoutes"); const Course = require("./models/Course"); // MongoDB Connection @@ -56,6 +57,7 @@ app.use("/api/faculty", facultyRoutes); app.use("/api/appointments", appointmentRoutes); app.use("/api/options", optionsRoutes); app.use("/api/data", consolidatedRoutes); // Moved after `app` initialization +app.use("/api/send-email", emailRoutes); // Google OAuth Routes app.get(
Semester