//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 path = require("path"); const moment = require("moment"); const app = express(); app.use(cors()); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use("/uploads", express.static("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 }); // 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)); // 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) => `
  • ${index + 1}. ${item}
  • `).join("") : "
  • No agenda provided
  • "; 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) => `
  • ${index + 1}. ${item}
  • `).join("") : "
  • No agenda provided
  • "; // 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: `

    Respected Board Members,

    Greetings from Somaiya Vidyavihar University !!

    We are glad to invite you to the Board of Studies meeting:

    ${body}

    Program: ${program}

    Department: ${department}

    Date: ${formattedDate}

    Time: ${formattedStartTime} - ${formattedEndTime}

    Zoom Meeting Details:

    Meeting ID: 265 561 6202

    Meeting Password: 123456

    Zoom Meeting Link: Join the Meeting

    Agenda:

    📅 Click here to add this event to Google Calendar

    `, 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}`));