forked from CSI-KJSCE/BOS-React-
final changes
This commit is contained in:
16
backend/config/db.js
Normal file
16
backend/config/db.js
Normal file
@@ -0,0 +1,16 @@
|
||||
const mongoose = require("mongoose");
|
||||
|
||||
const connectDB = async () => {
|
||||
try {
|
||||
await mongoose.connect(process.env.MONGODB_URI, {
|
||||
useNewUrlParser: true,
|
||||
useUnifiedTopology: true,
|
||||
});
|
||||
console.log("MongoDB connected");
|
||||
} catch (err) {
|
||||
console.error("MongoDB connection error:", err);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = connectDB;
|
||||
78
backend/controllers/departmentController.js
Normal file
78
backend/controllers/departmentController.js
Normal file
@@ -0,0 +1,78 @@
|
||||
const DepartmentEmail = require("../models/DepartmentEmail");
|
||||
const Program = require("../models/Program");
|
||||
|
||||
exports.getAllDepartmentEmails = async (req, res) => {
|
||||
try {
|
||||
const departmentEmails = await DepartmentEmail.find();
|
||||
res.json(departmentEmails);
|
||||
} catch (error) {
|
||||
console.error("Error fetching department emails:", error);
|
||||
res.status(500).json({ error: "Error fetching department emails" });
|
||||
}
|
||||
};
|
||||
|
||||
exports.getDepartmentsByProgram = async (req, res) => {
|
||||
const program = await Program.findOne({ name: req.params.program });
|
||||
res.json(program ? program.departments : []);
|
||||
};
|
||||
|
||||
exports.getEmailsByDepartment = async (req, res) => {
|
||||
const departmentEmails = await DepartmentEmail.findOne({ department: req.params.department });
|
||||
res.json(departmentEmails ? { emails: departmentEmails.emails } : { emails: [] });
|
||||
};
|
||||
|
||||
exports.updateDepartmentEmails = async (req, res) => {
|
||||
const { department } = req.params;
|
||||
const { emails } = req.body;
|
||||
|
||||
if (!emails || !Array.isArray(emails)) {
|
||||
return res.status(400).json({ error: "Emails array is required" });
|
||||
}
|
||||
|
||||
try {
|
||||
const updatedDepartment = await DepartmentEmail.findOneAndUpdate(
|
||||
{ department },
|
||||
{ emails },
|
||||
{ new: true, upsert: true }
|
||||
);
|
||||
res.json(updatedDepartment);
|
||||
} catch (error) {
|
||||
console.error("Error updating department emails:", error);
|
||||
res.status(500).json({ error: "Error updating department emails" });
|
||||
}
|
||||
};
|
||||
|
||||
exports.createDepartment = async (req, res) => {
|
||||
const { department, emails, program } = req.body;
|
||||
|
||||
if (!department || !emails || !Array.isArray(emails) || !program) {
|
||||
return res.status(400).json({ error: "Department, program, and emails array are required" });
|
||||
}
|
||||
|
||||
try {
|
||||
const newDepartment = new DepartmentEmail({ department, emails });
|
||||
await newDepartment.save();
|
||||
|
||||
await Program.findOneAndUpdate(
|
||||
{ name: program },
|
||||
{ $addToSet: { departments: department } },
|
||||
{ upsert: true }
|
||||
);
|
||||
|
||||
res.status(201).json(newDepartment);
|
||||
} catch (error) {
|
||||
console.error("Error creating department:", error);
|
||||
res.status(500).json({ error: "Error creating department" });
|
||||
}
|
||||
};
|
||||
|
||||
exports.deleteDepartment = async (req, res) => {
|
||||
try {
|
||||
const { department } = req.params;
|
||||
await DepartmentEmail.findOneAndDelete({ department });
|
||||
res.json({ message: "Department deleted successfully" });
|
||||
} catch (error) {
|
||||
console.error("Error deleting department:", error);
|
||||
res.status(500).json({ error: "Error deleting department" });
|
||||
}
|
||||
};
|
||||
136
backend/controllers/emailController.js
Normal file
136
backend/controllers/emailController.js
Normal file
@@ -0,0 +1,136 @@
|
||||
const nodemailer = require("nodemailer");
|
||||
const moment = require("moment");
|
||||
const Meeting = require("../models/Meeting");
|
||||
const DepartmentEmail = require("../models/DepartmentEmail");
|
||||
|
||||
const sendEmail = async (req, res) => {
|
||||
try {
|
||||
const { program, department, subject, body, agenda, date, startTime, endTime, recipients } = req.body;
|
||||
const files = req.files;
|
||||
|
||||
console.log({ program, department, subject, body, agenda, date, startTime, endTime, recipients, files });
|
||||
|
||||
if (!program || !department || !subject || !body || !date || !startTime || !endTime || !recipients) {
|
||||
return res.status(400).json({ error: "All fields are required!" });
|
||||
}
|
||||
|
||||
const departmentEmails = await DepartmentEmail.findOne({ department });
|
||||
if (!departmentEmails) {
|
||||
return res.status(404).json({ error: "Department emails not found" });
|
||||
}
|
||||
|
||||
const allRecipients = [...new Set([...departmentEmails.emails, ...recipients])];
|
||||
|
||||
const conflict = await Meeting.findOne({
|
||||
date,
|
||||
startTime: { $lt: endTime },
|
||||
endTime: { $gt: startTime },
|
||||
});
|
||||
|
||||
const formattedDate = moment(date, "YYYY-MM-DD").format("dddd, MMMM Do YYYY");
|
||||
const formattedStartTime = moment(startTime, "HH:mm").format("hh:mm A");
|
||||
const formattedEndTime = moment(endTime, "HH:mm").format("hh:mm A");
|
||||
|
||||
const formattedStart = moment(`${date} ${startTime}`, "YYYY-MM-DD HH:mm").utc().format("YYYYMMDDTHHmmss[Z]");
|
||||
const formattedEnd = moment(`${date} ${endTime}`, "YYYY-MM-DD HH:mm").utc().format("YYYYMMDDTHHmmss[Z]");
|
||||
|
||||
const zoomLink = "https://us05web.zoom.us/j/2655616202?pwd=S3d6RjVPNnhmQ3AzTlZsRC9GYmNHQT09";
|
||||
const calendarLink = `https://calendar.google.com/calendar/render?action=TEMPLATE&text=${encodeURIComponent(
|
||||
subject
|
||||
)}&details=${encodeURIComponent(`${body}\nJoin Zoom Meeting: ${zoomLink}`)}&dates=${formattedStart}/${formattedEnd}`;
|
||||
|
||||
const formattedAgenda = Array.isArray(agenda) && agenda.length > 0
|
||||
? agenda.map((item, index) => `<li>${index + 1}. ${item}</li>`).join("")
|
||||
: "<li>No agenda provided</li>";
|
||||
|
||||
const newMeeting = new Meeting({
|
||||
program,
|
||||
department,
|
||||
subject,
|
||||
body,
|
||||
agenda,
|
||||
date,
|
||||
startTime,
|
||||
endTime,
|
||||
recipients,
|
||||
attachments: files.map((file) => ({ filename: file.filename, path: file.path })),
|
||||
});
|
||||
await newMeeting.save();
|
||||
|
||||
let conflictDetails = null;
|
||||
|
||||
if (conflict) {
|
||||
conflictDetails = {
|
||||
department: conflict.department,
|
||||
date: conflict.date,
|
||||
startTime: conflict.startTime,
|
||||
endTime: conflict.endTime,
|
||||
recipients: conflict.recipients,
|
||||
subject: conflict.subject,
|
||||
agenda: conflict.agenda || "No agenda provided",
|
||||
};
|
||||
console.log("Conflict detected! Details:", conflictDetails);
|
||||
}
|
||||
|
||||
const transporter = nodemailer.createTransport({
|
||||
service: "gmail",
|
||||
auth: {
|
||||
user: process.env.EMAIL,
|
||||
pass: process.env.EMAIL_PASSWORD,
|
||||
},
|
||||
});
|
||||
|
||||
const mailOptions = {
|
||||
from: process.env.EMAIL,
|
||||
to: recipients,
|
||||
subject,
|
||||
html: `
|
||||
<p><strong>Respected Board Members,</strong></p>
|
||||
<p><strong>Greetings from Somaiya Vidyavihar University !!</strong></p>
|
||||
<p><strong>We are glad to invite you to the Board of Studies meeting: </strong></p>
|
||||
<p>${body}</p>
|
||||
<p><strong>Program:</strong> ${program}</p>
|
||||
<p><strong>Department:</strong> ${department}</p>
|
||||
<p><strong>Date:</strong> ${formattedDate}</p>
|
||||
<p><strong>Time:</strong> ${formattedStartTime} - ${formattedEndTime}</p>
|
||||
<p><strong>Zoom Meeting Details:</strong></p>
|
||||
<p><strong>Meeting ID: </strong>265 561 6202</p>
|
||||
<p><strong>Meeting Password: </strong>123456</p>
|
||||
<p><strong>Zoom Meeting Link: </strong><a href="${zoomLink}" target="_blank">Join the Meeting</a></p>
|
||||
<p><strong>Agenda:</strong></p>
|
||||
<ul>${formattedAgenda}</ul>
|
||||
<p><a href="${calendarLink}">📅 Click here to add this event to Google Calendar</a></p>
|
||||
${
|
||||
conflictDetails
|
||||
? `<p><strong>Conflict detected!</strong></p>
|
||||
<p><strong>Conflicting Meeting Details:</strong></p>
|
||||
<ul>
|
||||
<li><strong>Department:</strong> ${conflictDetails.department}</li>
|
||||
<li><strong>Date:</strong> ${conflictDetails.date}</li>
|
||||
<li><strong>Time:</strong> ${conflictDetails.startTime} - ${conflictDetails.endTime}</li>
|
||||
<li><strong>Subject:</strong> ${conflictDetails.subject}</li>
|
||||
<li><strong>Agenda:</strong> ${conflictDetails.agenda}</li>
|
||||
</ul>`
|
||||
: ""
|
||||
}
|
||||
`,
|
||||
attachments: files.map((file) => ({
|
||||
filename: file.filename,
|
||||
path: file.path,
|
||||
})),
|
||||
};
|
||||
|
||||
await transporter.sendMail(mailOptions);
|
||||
|
||||
res.status(200).json({
|
||||
message: conflictDetails ? "Conflict detected! Email sent successfully." : "Email sent successfully!",
|
||||
conflictDetails,
|
||||
calendarLink,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error sending email:", error);
|
||||
res.status(500).json({ error: "Error sending email" });
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = { sendEmail };
|
||||
18
backend/controllers/meetingController.js
Normal file
18
backend/controllers/meetingController.js
Normal file
@@ -0,0 +1,18 @@
|
||||
const Meeting = require("../models/Meeting");
|
||||
|
||||
exports.getMeetings = async (req, res) => {
|
||||
try {
|
||||
const meetings = await Meeting.find();
|
||||
const formattedMeetings = meetings.map((meeting) => {
|
||||
const formattedAgenda = meeting.agenda
|
||||
? meeting.agenda.map((item, index) => `<li>${index + 1}. ${item}</li>`).join("")
|
||||
: "<li>No agenda provided</li>";
|
||||
return { ...meeting.toObject(), formattedAgenda };
|
||||
});
|
||||
|
||||
res.json(formattedMeetings);
|
||||
} catch (error) {
|
||||
console.error("Error fetching meetings:", error);
|
||||
res.status(500).json({ error: "Error fetching meetings" });
|
||||
}
|
||||
};
|
||||
11
backend/middleware/upload.js
Normal file
11
backend/middleware/upload.js
Normal file
@@ -0,0 +1,11 @@
|
||||
const multer = require("multer");
|
||||
const path = require("path");
|
||||
|
||||
const storage = multer.diskStorage({
|
||||
destination: "uploads/",
|
||||
filename: (req, file, cb) => {
|
||||
cb(null, Date.now() + path.extname(file.originalname));
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = multer({ storage });
|
||||
8
backend/models/DepartmentEmail.js
Normal file
8
backend/models/DepartmentEmail.js
Normal file
@@ -0,0 +1,8 @@
|
||||
const mongoose = require("mongoose");
|
||||
|
||||
const DepartmentEmailSchema = new mongoose.Schema({
|
||||
department: String,
|
||||
emails: [String]
|
||||
});
|
||||
|
||||
module.exports = mongoose.model("DepartmentEmail", DepartmentEmailSchema);
|
||||
16
backend/models/Meeting.js
Normal file
16
backend/models/Meeting.js
Normal file
@@ -0,0 +1,16 @@
|
||||
const mongoose = require("mongoose");
|
||||
|
||||
const meetingSchema = new mongoose.Schema({
|
||||
program: String,
|
||||
department: String,
|
||||
subject: String,
|
||||
body: String,
|
||||
agenda: [String],
|
||||
date: String,
|
||||
startTime: String,
|
||||
endTime: String,
|
||||
recipients: [String],
|
||||
attachments: [{ filename: String, path: String }],
|
||||
});
|
||||
|
||||
module.exports = mongoose.model("Meeting", meetingSchema);
|
||||
26
backend/models/Program.js
Normal file
26
backend/models/Program.js
Normal file
@@ -0,0 +1,26 @@
|
||||
const express = require("express");
|
||||
const {
|
||||
getAllDepartmentEmails,
|
||||
getDepartmentsByProgram,
|
||||
getEmailsByDepartment,
|
||||
updateDepartmentEmails,
|
||||
createDepartment,
|
||||
deleteDepartment,
|
||||
} = require("../controllers/departmentController");
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.get("/programs", async (req, res) => {
|
||||
const Program = require("../models/Program");
|
||||
const programs = await Program.find();
|
||||
res.json(programs);
|
||||
});
|
||||
|
||||
router.get("/departments/:program", getDepartmentsByProgram);
|
||||
router.get("/department-emails/:department", getEmailsByDepartment);
|
||||
router.get("/department-emails", getAllDepartmentEmails);
|
||||
router.put("/department-emails/:department", updateDepartmentEmails);
|
||||
router.post("/department-emails", createDepartment);
|
||||
router.delete("/department-emails/:department", deleteDepartment);
|
||||
|
||||
module.exports = router;
|
||||
26
backend/routes/departmentRoutes.js
Normal file
26
backend/routes/departmentRoutes.js
Normal file
@@ -0,0 +1,26 @@
|
||||
const express = require("express");
|
||||
const {
|
||||
getAllDepartmentEmails,
|
||||
getDepartmentsByProgram,
|
||||
getEmailsByDepartment,
|
||||
updateDepartmentEmails,
|
||||
createDepartment,
|
||||
deleteDepartment,
|
||||
} = require("../controllers/departmentController");
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.get("/programs", async (req, res) => {
|
||||
const Program = require("../models/Program");
|
||||
const programs = await Program.find();
|
||||
res.json(programs);
|
||||
});
|
||||
|
||||
router.get("/departments/:program", getDepartmentsByProgram);
|
||||
router.get("/department-emails/:department", getEmailsByDepartment);
|
||||
router.get("/department-emails", getAllDepartmentEmails);
|
||||
router.put("/department-emails/:department", updateDepartmentEmails);
|
||||
router.post("/department-emails", createDepartment);
|
||||
router.delete("/department-emails/:department", deleteDepartment);
|
||||
|
||||
module.exports = router;
|
||||
9
backend/routes/emailRoutes.js
Normal file
9
backend/routes/emailRoutes.js
Normal file
@@ -0,0 +1,9 @@
|
||||
const express = require("express");
|
||||
const upload = require("../middleware/upload");
|
||||
const { sendEmail } = require("../controllers/emailController");
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.post("/send-email", upload.array("attachments"), sendEmail);
|
||||
|
||||
module.exports = router;
|
||||
8
backend/routes/meetingRoutes.js
Normal file
8
backend/routes/meetingRoutes.js
Normal file
@@ -0,0 +1,8 @@
|
||||
const express = require("express");
|
||||
const { getMeetings } = require("../controllers/meetingController");
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.get("/meetings", getMeetings);
|
||||
|
||||
module.exports = router;
|
||||
@@ -1,185 +1,26 @@
|
||||
//server.js
|
||||
|
||||
require("dotenv").config();
|
||||
const express = require("express");
|
||||
const mongoose = require("mongoose");
|
||||
const bodyParser = require("body-parser");
|
||||
const cors = require("cors");
|
||||
const nodemailer = require("nodemailer");
|
||||
const multer = require("multer");
|
||||
const bodyParser = require("body-parser");
|
||||
const path = require("path");
|
||||
const moment = require("moment");
|
||||
|
||||
const connectDB = require("./config/db");
|
||||
const emailRoutes = require("./routes/emailRoutes");
|
||||
const meetingRoutes = require("./routes/meetingRoutes");
|
||||
const departmentRoutes = require("./routes/departmentRoutes");
|
||||
|
||||
const app = express();
|
||||
|
||||
app.use(cors());
|
||||
app.use(bodyParser.json());
|
||||
app.use(bodyParser.urlencoded({ extended: true }));
|
||||
app.use("/uploads", express.static("uploads"));
|
||||
app.use("/uploads", express.static(path.join(__dirname, "uploads")));
|
||||
|
||||
// Multer setup for file uploads
|
||||
const storage = multer.diskStorage({
|
||||
destination: "uploads/",
|
||||
filename: (req, file, cb) => {
|
||||
cb(null, Date.now() + path.extname(file.originalname));
|
||||
},
|
||||
});
|
||||
const upload = multer({ storage });
|
||||
connectDB();
|
||||
|
||||
// MongoDB connection
|
||||
mongoose
|
||||
.connect(process.env.MONGODB_URI, { useNewUrlParser: true, useUnifiedTopology: true })
|
||||
.then(() => console.log("Connected to MongoDB"))
|
||||
.catch((err) => console.error("MongoDB Connection Error:", err));
|
||||
app.use("/api", emailRoutes);
|
||||
app.use("/api", meetingRoutes);
|
||||
app.use("/api", departmentRoutes);
|
||||
|
||||
// Meeting Schema
|
||||
const meetingSchema = new mongoose.Schema({
|
||||
program: String,
|
||||
department: String,
|
||||
subject: String,
|
||||
body: String,
|
||||
agenda: [String],
|
||||
date: String,
|
||||
startTime: String,
|
||||
endTime: String,
|
||||
recipients: [String],
|
||||
attachments: [{ filename: String, path: String }],
|
||||
});
|
||||
const Meeting = mongoose.model("Meeting", meetingSchema);
|
||||
|
||||
app.get("/api/meetings", async (req, res) => {
|
||||
try {
|
||||
const meetings = await Meeting.find(); // Fetching all meetings
|
||||
|
||||
// Format agenda in HTML for each meeting
|
||||
const formattedMeetings = meetings.map((meeting) => {
|
||||
const formattedAgenda = meeting.agenda
|
||||
? meeting.agenda.map((item, index) => `<li>${index + 1}. ${item}</li>`).join("")
|
||||
: "<li>No agenda provided</li>";
|
||||
return { ...meeting.toObject(), formattedAgenda }; // Add formatted agenda to each meeting
|
||||
});
|
||||
|
||||
res.json(formattedMeetings); // Send formatted meetings
|
||||
} catch (error) {
|
||||
console.error("Error fetching meetings:", error);
|
||||
res.status(500).json({ error: "Error fetching meetings" });
|
||||
}
|
||||
});
|
||||
|
||||
// API to send email
|
||||
app.post("/api/send-email", upload.array("attachments"), async (req, res) => {
|
||||
try {
|
||||
const { program, department, subject, body, agenda, date, startTime, endTime, recipients } = req.body;
|
||||
const files = req.files;
|
||||
|
||||
console.log({ program, department, subject, body, agenda, date, startTime, endTime, recipients, files });
|
||||
|
||||
if (!program || !department || !subject || !body || !date || !startTime || !endTime || !recipients) {
|
||||
return res.status(400).json({ error: "All fields are required!" });
|
||||
}
|
||||
|
||||
// Check for meeting conflicts
|
||||
const conflict = await Meeting.findOne({
|
||||
date,
|
||||
startTime: { $lt: endTime },
|
||||
endTime: { $gt: startTime },
|
||||
});
|
||||
|
||||
if (conflict) {
|
||||
// Return the details of the conflicting meeting
|
||||
const conflictDetails = {
|
||||
department: conflict.department,
|
||||
date: conflict.date,
|
||||
startTime: conflict.startTime,
|
||||
endTime: conflict.endTime,
|
||||
recipients: conflict.recipients,
|
||||
subject: conflict.subject,
|
||||
};
|
||||
|
||||
return res.status(409).json({
|
||||
error: "Meeting conflict detected! Please choose a different time.",
|
||||
conflictDetails
|
||||
});
|
||||
}
|
||||
|
||||
// Format date and time properly
|
||||
const formattedDate = moment(date, "YYYY-MM-DD").format("dddd, MMMM Do YYYY");
|
||||
const formattedStartTime = moment(startTime, "HH:mm").format("hh:mm A");
|
||||
const formattedEndTime = moment(endTime, "HH:mm").format("hh:mm A");
|
||||
|
||||
// Format Google Calendar event link
|
||||
const formattedStart = moment(`${date} ${startTime}`, "YYYY-MM-DD HH:mm").utc().format("YYYYMMDDTHHmmss[Z]");
|
||||
const formattedEnd = moment(`${date} ${endTime}`, "YYYY-MM-DD HH:mm").utc().format("YYYYMMDDTHHmmss[Z]");
|
||||
const zoomLink = "https://us05web.zoom.us/j/2655616202?pwd=S3d6RjVPNnhmQ3AzTlZsRC9GYmNHQT09";
|
||||
const calendarLink = `https://calendar.google.com/calendar/render?action=TEMPLATE&text=${encodeURIComponent(
|
||||
subject
|
||||
)}&details=${encodeURIComponent(`${body}\nJoin Zoom Meeting: ${zoomLink}`)}&dates=${formattedStart}/${formattedEnd}`;
|
||||
|
||||
// Format agenda into pointwise list
|
||||
const formattedAgenda = agenda
|
||||
? agenda.map((item, index) => `<li>${index + 1}. ${item}</li>`).join("")
|
||||
: "<li>No agenda provided</li>";
|
||||
|
||||
// Store meeting in DB
|
||||
const newMeeting = new Meeting({
|
||||
program,
|
||||
department,
|
||||
subject,
|
||||
body,
|
||||
agenda,
|
||||
date,
|
||||
startTime,
|
||||
endTime,
|
||||
recipients,
|
||||
attachments: files.map((file) => ({ filename: file.filename, path: file.path })),
|
||||
});
|
||||
await newMeeting.save();
|
||||
|
||||
// Email transporter
|
||||
const transporter = nodemailer.createTransport({
|
||||
service: "gmail",
|
||||
auth: {
|
||||
user: process.env.EMAIL,
|
||||
pass: process.env.EMAIL_PASSWORD,
|
||||
},
|
||||
});
|
||||
|
||||
// Email options
|
||||
const mailOptions = {
|
||||
from: process.env.EMAIL,
|
||||
to: recipients,
|
||||
subject,
|
||||
html: `
|
||||
<p><strong>Respected Board Members,</strong></p>
|
||||
<p><strong>Greetings from Somaiya Vidyavihar University !!</strong></p>
|
||||
<p><strong>We are glad to invite you to the Board of Studies meeting: </strong></p>
|
||||
<p>${body}</p>
|
||||
<p><strong>Program:</strong> ${program}</p>
|
||||
<p><strong>Department:</strong> ${department}</p>
|
||||
<p><strong>Date:</strong> ${formattedDate}</p>
|
||||
<p><strong>Time:</strong> ${formattedStartTime} - ${formattedEndTime}</p>
|
||||
<p><strong>Zoom Meeting Details:</strong></p>
|
||||
<p><strong>Meeting ID: </strong>265 561 6202</p>
|
||||
<p><strong>Meeting Password: </strong>123456</p>
|
||||
<p><strong>Zoom Meeting Link: </strong><a href="https://us05web.zoom.us/j/2655616202?pwd=S3d6RjVPNnhmQ3AzTlZsRC9GYmNHQT09" target="_blank">Join the Meeting</a></p>
|
||||
<p><strong>Agenda:</strong></p>
|
||||
<ul>${formattedAgenda}</ul>
|
||||
<p><a href="${calendarLink}">📅 Click here to add this event to Google Calendar</a></p>
|
||||
`,
|
||||
attachments: files.map((file) => ({
|
||||
filename: file.filename,
|
||||
path: file.path,
|
||||
})),
|
||||
};
|
||||
|
||||
// Send email
|
||||
await transporter.sendMail(mailOptions);
|
||||
res.status(200).json({ message: "Email sent successfully!", calendarLink });
|
||||
} catch (error) {
|
||||
console.error("Error sending email:", error);
|
||||
res.status(500).json({ error: "Error sending email" });
|
||||
}
|
||||
});
|
||||
|
||||
// Start server
|
||||
const PORT = process.env.PORT || 5000;
|
||||
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
|
||||
|
||||
BIN
backend/uploads/1743699686010.docx
Normal file
BIN
backend/uploads/1743699686010.docx
Normal file
Binary file not shown.
BIN
backend/uploads/1743699709610.docx
Normal file
BIN
backend/uploads/1743699709610.docx
Normal file
Binary file not shown.
BIN
backend/uploads/1743699844366.docx
Normal file
BIN
backend/uploads/1743699844366.docx
Normal file
Binary file not shown.
BIN
backend/uploads/1748321326875.pdf
Normal file
BIN
backend/uploads/1748321326875.pdf
Normal file
Binary file not shown.
BIN
backend/uploads/1748321328791.pdf
Normal file
BIN
backend/uploads/1748321328791.pdf
Normal file
Binary file not shown.
Reference in New Issue
Block a user