From b39cb67b0fadda662cada43632b613dc8e991fc2 Mon Sep 17 00:00:00 2001
From: amNobodyyy <131776812+amNobodyyy@users.noreply.github.com>
Date: Thu, 23 Jan 2025 22:42:41 +0530
Subject: [PATCH] mailing-part 50%
---
client/src/Pages/ConsolidatedTable.jsx | 259 +++++++------------------
client/src/api.js | 28 +++
server/routes/emailRoutes.js | 58 ++++++
server/server.js | 2 +
4 files changed, 154 insertions(+), 193 deletions(-)
create mode 100644 server/routes/emailRoutes.js
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
-//
-//
-//
-// | 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 |
-//
-//
-//
-// {data.map((row, index) => (
-//
-// | {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
-//
-//
-//
-// | 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 |
-//
-//
-//
-// {teacherData.map((row, idx) => (
-//
-// | {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
-
+
| Semester |
@@ -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(