diff --git a/backend/config/db.js b/backend/config/db.js
new file mode 100644
index 0000000..fe775cf
--- /dev/null
+++ b/backend/config/db.js
@@ -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;
diff --git a/backend/controllers/departmentController.js b/backend/controllers/departmentController.js
new file mode 100644
index 0000000..7e752b5
--- /dev/null
+++ b/backend/controllers/departmentController.js
@@ -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" });
+ }
+};
diff --git a/backend/controllers/emailController.js b/backend/controllers/emailController.js
new file mode 100644
index 0000000..3dec681
--- /dev/null
+++ b/backend/controllers/emailController.js
@@ -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) => `
${index + 1}. ${item}`).join("")
+ : "No agenda provided";
+
+ 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: `
+ 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
+ ${
+ conflictDetails
+ ? `Conflict detected!
+ Conflicting Meeting Details:
+
+ - Department: ${conflictDetails.department}
+ - Date: ${conflictDetails.date}
+ - Time: ${conflictDetails.startTime} - ${conflictDetails.endTime}
+ - Subject: ${conflictDetails.subject}
+ - Agenda: ${conflictDetails.agenda}
+
`
+ : ""
+ }
+ `,
+ 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 };
diff --git a/backend/controllers/meetingController.js b/backend/controllers/meetingController.js
new file mode 100644
index 0000000..1b47f07
--- /dev/null
+++ b/backend/controllers/meetingController.js
@@ -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) => `${index + 1}. ${item}`).join("")
+ : "No agenda provided";
+ return { ...meeting.toObject(), formattedAgenda };
+ });
+
+ res.json(formattedMeetings);
+ } catch (error) {
+ console.error("Error fetching meetings:", error);
+ res.status(500).json({ error: "Error fetching meetings" });
+ }
+};
diff --git a/backend/middleware/upload.js b/backend/middleware/upload.js
new file mode 100644
index 0000000..bb5dce4
--- /dev/null
+++ b/backend/middleware/upload.js
@@ -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 });
diff --git a/backend/models/DepartmentEmail.js b/backend/models/DepartmentEmail.js
new file mode 100644
index 0000000..5a3560e
--- /dev/null
+++ b/backend/models/DepartmentEmail.js
@@ -0,0 +1,8 @@
+const mongoose = require("mongoose");
+
+const DepartmentEmailSchema = new mongoose.Schema({
+ department: String,
+ emails: [String]
+});
+
+module.exports = mongoose.model("DepartmentEmail", DepartmentEmailSchema);
diff --git a/backend/models/Meeting.js b/backend/models/Meeting.js
new file mode 100644
index 0000000..8502761
--- /dev/null
+++ b/backend/models/Meeting.js
@@ -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);
diff --git a/backend/models/Program.js b/backend/models/Program.js
new file mode 100644
index 0000000..684fc78
--- /dev/null
+++ b/backend/models/Program.js
@@ -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;
diff --git a/backend/routes/departmentRoutes.js b/backend/routes/departmentRoutes.js
new file mode 100644
index 0000000..684fc78
--- /dev/null
+++ b/backend/routes/departmentRoutes.js
@@ -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;
diff --git a/backend/routes/emailRoutes.js b/backend/routes/emailRoutes.js
new file mode 100644
index 0000000..35b1299
--- /dev/null
+++ b/backend/routes/emailRoutes.js
@@ -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;
diff --git a/backend/routes/meetingRoutes.js b/backend/routes/meetingRoutes.js
new file mode 100644
index 0000000..b52bd1d
--- /dev/null
+++ b/backend/routes/meetingRoutes.js
@@ -0,0 +1,8 @@
+const express = require("express");
+const { getMeetings } = require("../controllers/meetingController");
+
+const router = express.Router();
+
+router.get("/meetings", getMeetings);
+
+module.exports = router;
diff --git a/backend/server.js b/backend/server.js
index 0565a0f..2a665f5 100644
--- a/backend/server.js
+++ b/backend/server.js
@@ -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) => `${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}`));
diff --git a/backend/uploads/1743699686010.docx b/backend/uploads/1743699686010.docx
new file mode 100644
index 0000000..8b1dc6d
Binary files /dev/null and b/backend/uploads/1743699686010.docx differ
diff --git a/backend/uploads/1743699709610.docx b/backend/uploads/1743699709610.docx
new file mode 100644
index 0000000..8b1dc6d
Binary files /dev/null and b/backend/uploads/1743699709610.docx differ
diff --git a/backend/uploads/1743699844366.docx b/backend/uploads/1743699844366.docx
new file mode 100644
index 0000000..8b1dc6d
Binary files /dev/null and b/backend/uploads/1743699844366.docx differ
diff --git a/backend/uploads/1748321326875.pdf b/backend/uploads/1748321326875.pdf
new file mode 100644
index 0000000..f0bd1bd
Binary files /dev/null and b/backend/uploads/1748321326875.pdf differ
diff --git a/backend/uploads/1748321328791.pdf b/backend/uploads/1748321328791.pdf
new file mode 100644
index 0000000..f0bd1bd
Binary files /dev/null and b/backend/uploads/1748321328791.pdf differ
diff --git a/frontend/src/App.js b/frontend/src/App.js
index ced5cd2..b2a7757 100644
--- a/frontend/src/App.js
+++ b/frontend/src/App.js
@@ -1,22 +1,25 @@
import React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
-import Page1 from './Page1';
+import Page1 from './Page1';
import Page2 from './Page2';
-import Page3 from './Page3';
-import Page4 from './Page4';
-import Page5 from './Page5';
-import { GoogleOAuthProvider } from '@react-oauth/google';
+import Page3 from './Page3';
+import Page4 from './Page4';
+import Page5 from './Page5';
+import Page6 from './Page6';
+import { GoogleOAuthProvider } from '@react-oauth/google';
+
const App = () => {
return (
-
+
} />
- } />
+ } />
} />
} />
} />
+ } />
diff --git a/frontend/src/Page1.css b/frontend/src/Page1.css
index 772ce85..4d700b3 100644
--- a/frontend/src/Page1.css
+++ b/frontend/src/Page1.css
@@ -1,3 +1,5 @@
+/*Page1.css*/
+
/* General Styles */
* {
margin: 0;
diff --git a/frontend/src/Page1.js b/frontend/src/Page1.js
index 13c8a0c..8fe9858 100644
--- a/frontend/src/Page1.js
+++ b/frontend/src/Page1.js
@@ -1,3 +1,5 @@
+//Page1.js
+
import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { GoogleLogin } from '@react-oauth/google'; // Import GoogleLogin component
@@ -31,7 +33,7 @@ const Page1 = () => {
// Allowed credentials
const allowedCredentials = [
- { email: "hodcomp@somaiya.edu", password: "hodcomp123!" },
+ { email: "hodcomp@somaiya.edu", password: "hodcomp123" },
{ email: "director.kjsse@somaiya.edu", password: "directorkjsse2024" },
{ email: "dean.engg@somaiya.edu", password: "deanengg2024" },
{ email: "hodextc@somaiya.edu", password: "hodextc2024" },
diff --git a/frontend/src/Page2.css b/frontend/src/Page2.css
index 57d4560..8acc6e5 100644
--- a/frontend/src/Page2.css
+++ b/frontend/src/Page2.css
@@ -1,3 +1,5 @@
+/*Page2.css*/
+
/* General Styles */
body {
margin: 0;
diff --git a/frontend/src/Page2.js b/frontend/src/Page2.js
index bf72876..3f104f5 100644
--- a/frontend/src/Page2.js
+++ b/frontend/src/Page2.js
@@ -1,3 +1,5 @@
+//Page2.js
+
import React, { useState } from "react";
import { Link } from "react-router-dom";
import './Page2.css'; // CSS File import
@@ -30,7 +32,7 @@ const Page2 = () => {
Home
Schedule
Meeting DataBase
- Contact
+ Edit DataBase
Log Out
diff --git a/frontend/src/Page3.css b/frontend/src/Page3.css
index 3e94abc..052e2d3 100644
--- a/frontend/src/Page3.css
+++ b/frontend/src/Page3.css
@@ -1,4 +1,5 @@
/* Page3.css */
+
.container {
width: 100%;
max-width: 600px;
diff --git a/frontend/src/Page3.js b/frontend/src/Page3.js
index 43e75d2..1a78451 100644
--- a/frontend/src/Page3.js
+++ b/frontend/src/Page3.js
@@ -1,3 +1,5 @@
+//Page3.js
+
import React, { useState } from "react";
import './Page3.css'
diff --git a/frontend/src/Page4.css b/frontend/src/Page4.css
index 4438c3f..9ef79ae 100644
--- a/frontend/src/Page4.css
+++ b/frontend/src/Page4.css
@@ -1,3 +1,5 @@
+/*Page4.css*/
+
/* Container for the content area */
.content-area {
width: 100%;
diff --git a/frontend/src/Page4.js b/frontend/src/Page4.js
index e51a087..444f9a1 100644
--- a/frontend/src/Page4.js
+++ b/frontend/src/Page4.js
@@ -1,28 +1,20 @@
+//Page4.js
+
import React, { useState } from "react";
import { Link } from "react-router-dom";
import axios from "axios";
import './Page2.css';
-import './Page4.css'; // Import the same CSS file for consistent styling
-import { FaTimes } from "react-icons/fa"; // Red cross icon for agenda/removal
+import './Page4.css';
+import { FaTimes } from "react-icons/fa";
import image from './components/image.png';
import somaiyatrust from './components/somaiyatrust.png';
import redlines from './components/redlines.png';
-
-const programs = ["BTech", "MTech", "PhD"];
-const departments = [
- "Artificial Intelligence & Data Science",
- "Computer Engineering",
- "Computer & Communication Engineering",
- "Computer Science & Business Systems",
- "Electronics Engineering (VLSI Design & Technology)",
- "Electronics & Computer Engineering",
- "Electronics & Telecommunication Engineering",
- "Information Technology",
- "Mechanical Engineering",
- "Robotics & Artificial Intelligence",
-];
+import { useEffect } from "react";
const Page4 = () => {
+ const [programs, setPrograms] = useState([]);
+ const [departments, setDepartments] = useState([]);
+ const [departmentEmails, setDepartmentEmails] = useState([]);
const [program, setProgram] = useState("");
const [department, setDepartment] = useState("");
const [subject, setSubject] = useState("");
@@ -34,6 +26,33 @@ const Page4 = () => {
const [recipients, setRecipients] = useState([""]);
const [attachments, setAttachments] = useState([]);
+ useEffect(() => {
+ axios.get("http://localhost:5000/api/programs")
+ .then(response => setPrograms(response.data))
+ .catch(error => console.error("Error fetching programs:", error));
+ }, []);
+
+ useEffect(() => {
+ if (program) {
+ axios.get(`http://localhost:5000/api/departments/${program}`)
+ .then(response => setDepartments(response.data))
+ .catch(error => console.error("Error fetching departments:", error));
+ } else {
+ setDepartments([]);
+ }
+ }, [program]);
+
+ useEffect(() => {
+ if (department) {
+ axios.get(`http://localhost:5000/api/department-emails/${department}`)
+ .then(response => {
+ setDepartmentEmails(response.data.emails);
+ setRecipients([...response.data.emails]);
+ })
+ .catch(error => console.error("Error fetching department emails:", error));
+ }
+ }, [department]);
+
const addAgenda = () => setAgenda([...agenda, ""]);
const handleAgendaChange = (index, value) => {
const updatedAgenda = [...agenda];
@@ -86,7 +105,7 @@ const Page4 = () => {
} catch (err) {
if (err.response?.status === 409) {
const conflictDetails = err.response.data.conflictDetails;
- alert(`Conflict Detected:
+ alert(`Conflict Detected :
Department: ${conflictDetails.department}
Date: ${conflictDetails.date}
Time: ${conflictDetails.startTime} - ${conflictDetails.endTime}
@@ -114,7 +133,7 @@ const Page4 = () => {
Home
Schedule
Meeting DataBase
- Contact
+ Edit DataBase
Log Out
@@ -134,13 +153,11 @@ const Page4 = () => {
{/* Content Area (Right Side) */}
BOS Email Management System
-
+
diff --git a/frontend/src/Page5.css b/frontend/src/Page5.css
index 70c136c..c157270 100644
--- a/frontend/src/Page5.css
+++ b/frontend/src/Page5.css
@@ -1,141 +1,309 @@
-/* Ensure body has margin 0 and full height for scrolling */
-body {
- margin: 0;
- padding: 0;
- font-family: Arial, sans-serif;
- background-color: #f4f4f4;
- min-height: 100vh;
- overflow-y: auto; /* Ensure scrolling */
+/*Page5.css*/
+
+/* Base Styles */
+:root {
+ --primary-red: #B7202E;
+ --dark-red: #8a0000;
+ --light-red: #d32f2f;
+ --white: #ffffff;
+ --light-gray: #f5f5f5;
+ --medium-gray: #e0e0e0;
+ --dark-gray: #757575;
+ --black: #212121;
+ --shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+ --transition: all 0.3s ease;
+}
+
+/* Page Container */
+.page-container {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ background-color: #f4f4f4;
+}
+
+html, body {
+ margin: 0;
+ padding: 0;
+ height: auto; /* Let height grow naturally */
+ overflow-x: hidden; /* Hide only horizontal scroll */
+ overflow-y: auto; /* Allow vertical scroll */
+}
+
+/* Header Bar */
+.header-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 15px 20px;
+ background-color: var(--white);
+ box-shadow: var(--shadow);
+ position: sticky;
+ top: 0;
+ z-index: 100;
+}
+
+.leftlogo, .rightlogo {
+ height: 50px;
+ width: auto;
+}
+
+.college-name {
+ color: var(--primary-red);
+ font-size: 1.5rem;
+ margin: 0;
+}
+
+/* Navigation Bar */
+.navbar {
+ background-color: var(--primary-red);
+ padding: 0 20px;
+}
+
+.navbar ul {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+ display: flex;
+ justify-content: center;
+ flex-wrap: wrap;
+}
+
+.navbar li {
+ padding: 15px 20px;
+}
+
+.navbar a {
+ color: var(--white);
+ text-decoration: none;
+ font-weight: 500;
+ transition: var(--transition);
+}
+
+.navbar a:hover, .navbar a.active {
+ color: var(--white);
+ text-decoration: underline;
+ text-underline-offset: 5px;
+}
+
+/* Main Content */
+.meetings-page-container {
+ flex: 1;
+ padding: 30px;
+ max-width: 1400px;
+ margin: 40px auto 0 auto; /* 40px top margin to separate from navbar */
+ width: 100%;
+}
+
+.page-title {
+ text-align: center;
+ color: var(--primary-red);
+ margin-bottom: 30px;
+ font-size: 2rem;
+}
+
+.no-meetings {
+ text-align: center;
+ color: var(--dark-gray);
+ font-size: 1.2rem;
+ margin-top: 40px;
+}
+
+/* Meetings Grid Container */
+.meetings-grid-container {
+ width: 100%;
+ overflow: hidden;
+}
+
+.meetings-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
+ gap: 25px;
+ padding: 10px;
+}
+
+/* Meeting Cards */
+.meeting-card {
+ background-color: var(--white);
+ border-radius: 8px;
+ box-shadow: var(--shadow);
+ border-left: 4px solid var(--primary-red);
+ overflow: hidden;
+ transition: var(--transition);
+ display: flex;
+ flex-direction: column;
+ min-height: 150px;
+}
+
+.meeting-card:hover {
+ transform: translateY(-5px);
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15);
+}
+
+.card-summary {
+ padding: 20px;
+ cursor: pointer;
+}
+
+.meeting-title {
+ color: var(--black);
+ font-size: 1.2rem;
+ margin: 0 0 10px 0;
+ line-height: 1.3;
+}
+
+.meeting-meta {
+ display: flex;
+ justify-content: space-between;
+ color: var(--dark-gray);
+ font-size: 0.9rem;
+ margin-bottom: 8px;
+}
+
+.meeting-department {
+ color: var(--primary-red);
+ font-weight: 500;
+ font-size: 0.9rem;
+}
+
+.card-details {
+ padding: 20px;
+ background-color: var(--light-gray);
+ border-top: 1px solid var(--medium-gray);
+ flex: 1;
+}
+
+.detail-row {
+ display: flex;
+ margin-bottom: 10px;
+ line-height: 1.4;
+}
+
+.detail-label {
+ font-weight: 600;
+ color: var(--primary-red);
+ min-width: 100px;
+}
+
+.detail-section {
+ margin: 20px 0;
+}
+
+.detail-section h3 {
+ color: var(--primary-red);
+ font-size: 1.1rem;
+ margin-bottom: 10px;
+ border-bottom: 1px solid var(--medium-gray);
+ padding-bottom: 5px;
+}
+
+.agenda-list, .attachments-list {
+ padding-left: 20px;
+ margin: 10px 0;
+}
+
+.agenda-list li, .attachments-list li {
+ margin-bottom: 8px;
+ line-height: 1.4;
+}
+
+.attachments-list a {
+ color: var(--primary-red);
+ text-decoration: none;
+ transition: var(--transition);
+}
+
+.attachments-list a:hover {
+ text-decoration: underline;
+}
+
+.recipients-list {
+ word-break: break-all;
+}
+
+/* Calendar Button */
+.calendar-button {
+ display: block;
+ background-color: var(--primary-red);
+ color: var(--white) !important;
+ text-align: center;
+ padding: 10px;
+ border-radius: 5px;
+ margin-top: 20px;
+ text-decoration: none;
+ transition: var(--transition);
+}
+
+.calendar-button:hover {
+ background-color: var(--dark-red);
+}
+
+/* Footer */
+footer {
+ background-color: var(--primary-red);
+ color: var(--white);
+ padding: 20px;
+ text-align: center;
+}
+
+.terms {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 20px;
+}
+
+.terms a {
+ color: var(--white);
+ text-decoration: none;
+}
+
+.footer-image {
+ height: 30px;
+}
+
+/* Responsive Design */
+@media (max-width: 1024px) {
+ .meetings-grid {
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}
-
- /* Main container for the meetings */
- .meetings-container {
- background-color: #ffffff;
- border-radius: 10px; /* Rounded corners */
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
- border: 1px solid #e0e0e0; /* Light border for the box */
- box-sizing: border-box;
- max-width: 1200px;
- margin: 20px auto; /* Added margin to ensure some space from top */
- padding: 20px;
- }
-
- /* Heading for the page */
- h1 {
- text-align: center;
- font-size: 2rem;
- margin-bottom: 20px;
- }
-
- /* List of meetings */
- .meetings-list {
- display: flex;
+}
+
+@media (max-width: 768px) {
+ .header-bar {
flex-direction: column;
- gap: 20px;
- }
-
- /* Styling for each meeting box */
- .meeting-box {
- background-color: #ffffff;
- padding: 20px;
- border-radius: 10px; /* Rounded corners */
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
- border-left: 5px solid #B7202E; /* Changed to the new color */
- overflow: hidden; /* Prevents overflow */
- box-sizing: border-box;
- }
-
- /* Styling for meeting titles */
- .meeting-box h2 {
- font-size: 1.5rem;
- color: #333;
- margin-bottom: 10px;
- }
-
- /* Styling for meeting details like Program, Date, etc. */
- .meeting-box p {
- font-size: 1rem;
- color: #555;
- }
-
- /* Styling for links like Google Calendar and attachments */
- .meeting-box a {
- text-decoration: none;
- color: #B7202E; /* Changed to the new color */
- font-weight: bold;
- display: inline-block;
- margin-top: 10px;
- }
-
- .meeting-box a:hover {
- text-decoration: underline;
- }
-
- /* Button for Google Calendar link */
- .google-calendar-link {
- margin-top: 10px;
- display: inline-block;
- padding: 10px 20px;
- background-color: #B7202E; /* Changed to the new color */
- color: white;
- border-radius: 5px;
- text-align: center;
- }
-
- .google-calendar-link:hover {
- background-color: #9e1c25; /* Darkened shade of the same color */
- }
-
- /* Ensure that meetings overflow properly on the page */
- body {
- display: flex;
- flex-direction: column;
- justify-content: flex-start;
- overflow-y: auto;
- }
-
- .meeting-box ul {
- list-style-type: none;
- padding-left: 0;
- }
-
- .meeting-box ul li {
- font-size: 1rem;
- color: #444;
- margin-bottom: 5px;
- }
-
- /* Responsive Design for smaller screens */
- @media (max-width: 768px) {
- .meeting-box {
- padding: 15px;
- }
-
- .meeting-box h2 {
- font-size: 1.2rem;
- }
-
- .meeting-box p,
- .meeting-box ul li {
- font-size: 0.9rem;
- }
-
- .google-calendar-link {
- font-size: 0.9rem;
- }
+ padding: 10px;
}
- /* Button for Google Calendar link */
-.google-calendar-link {
- margin-top: 10px;
- display: inline-block;
- padding: 10px 20px;
- background-color: #B7202E; /* Red color */
- color: white !important; /* Text color set to white */
- border-radius: 5px;
- text-align: center;
+ .college-name {
+ margin: 10px 0;
+ font-size: 1.2rem;
}
-
- .google-calendar-link:hover {
- background-color: #9e1c25; /* Darkened shade of red on hover */
- }
\ No newline at end of file
+
+ .navbar li {
+ padding: 10px 15px;
+ }
+
+ .meetings-page-container {
+ padding: 20px 15px;
+ }
+}
+
+@media (max-width: 480px) {
+ .meetings-grid {
+ grid-template-columns: 1fr;
+ }
+
+ .detail-row {
+ flex-direction: column;
+ }
+
+ .detail-label {
+ margin-bottom: 5px;
+ }
+
+ .meeting-meta {
+ flex-direction: column;
+ gap: 5px;
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/Page5.js b/frontend/src/Page5.js
index ba72cbc..3b757ec 100644
--- a/frontend/src/Page5.js
+++ b/frontend/src/Page5.js
@@ -1,83 +1,164 @@
+//Page5.js
+
import React, { useState, useEffect } from 'react';
+import { Link } from 'react-router-dom';
import axios from 'axios';
import './Page5.css';
+import somaiyatrust from './components/somaiyatrust.png';
+import image from './components/image.png';
+import redlines from './components/redlines.png';
const Page5 = () => {
const [meetings, setMeetings] = useState([]);
+ const [expandedIndex, setExpandedIndex] = useState(null);
- // Fetch meetings data from the server
useEffect(() => {
- axios.get('http://localhost:5000/api/meetings') // Updated to backend URL
+ axios.get('http://localhost:5000/api/meetings')
.then((response) => {
- setMeetings(response.data);
+ // Sort meetings by date (newest first) and time
+ const sortedMeetings = response.data.sort((a, b) => {
+ const dateA = new Date(`${a.date}T${a.startTime}`);
+ const dateB = new Date(`${b.date}T${b.startTime}`);
+ return dateB - dateA;
+ });
+ setMeetings(sortedMeetings);
})
.catch((error) => {
console.error('Error fetching meetings:', error);
});
}, []);
+ const toggleExpand = (index) => {
+ setExpandedIndex(prev => (prev === index ? null : index));
+ };
+
return (
-
-
Meeting Details
-
+
+ {/* Header Bar */}
+
+
+ Somaiya Scheduler
+
+
+
+ {/* Navigation Bar */}
+
+
+ {/* Main Content */}
+
+
Meeting Details
+
{meetings.length === 0 ? (
-
No meetings available
+
No meetings available
) : (
- meetings.map((meeting, index) => (
-
-
{meeting.subject}
-
Program: {meeting.program}
-
Department: {meeting.department}
-
Date: {meeting.date}
-
Time: {meeting.startTime} - {meeting.endTime}
+
+
+ {meetings.map((meeting, index) => (
+
+
toggleExpand(index)}>
+
{meeting.subject}
+
+ {meeting.date}
+ {meeting.startTime} - {meeting.endTime}
+
+
{meeting.department}
+
-
Agenda:
- {meeting.agenda && meeting.agenda.length > 0 ? (
-
- {meeting.agenda.map((item, idx) => (
- - {item}
- ))}
-
- ) : (
-
No agenda provided
- )}
+ {expandedIndex === index && (
+
+
+ Program:
+ {meeting.program}
+
-
Body: {meeting.body}
+
+
Agenda
+ {meeting.agenda && meeting.agenda.length > 0 ? (
+
+ {meeting.agenda.map((item, idx) => (
+ - {item}
+ ))}
+
+ ) : (
+
No agenda provided
+ )}
+
-
Recipients: {meeting.recipients}
+
+
Details
+
{meeting.body}
+
- {/* Display Attachments if available */}
-
Attachments:
- {meeting.attachments && meeting.attachments.length > 0 ? (
-
- ) : (
-
No attachments available
- )}
-
-
- Add to Google Calendar
-
+
+ )}
+
+ ))}
- ))
+
)}
+
+ {/* Footer */}
+
);
};
-export default Page5;
+export default Page5;
\ No newline at end of file
diff --git a/frontend/src/Page6.css b/frontend/src/Page6.css
new file mode 100644
index 0000000..53d3724
--- /dev/null
+++ b/frontend/src/Page6.css
@@ -0,0 +1,307 @@
+/*Page6.css*/
+
+/* Root Variables (optional, for consistency) */
+:root {
+ --primary-red: #B7202E;
+ --dark-red: #8a0000;
+ --white: #ffffff;
+ --light-gray: #f5f5f5;
+ --medium-gray: #e0e0e0;
+ --dark-gray: #757575;
+ --shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+ --transition: all 0.3s ease;
+}
+
+/* Page Container */
+.page-container {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ background-color: #f4f4f4;
+}
+
+/* Header Bar */
+.header-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 15px 20px;
+ background-color: var(--white);
+ box-shadow: var(--shadow);
+ position: sticky;
+ top: 0;
+ z-index: 100;
+}
+
+.leftlogo, .rightlogo {
+ height: 50px;
+ width: auto;
+}
+
+.college-name {
+ color: var(--primary-red);
+ font-size: 1.5rem;
+ margin: 0;
+ text-align: center;
+}
+
+/* Navbar */
+.navbar {
+ background-color: var(--primary-red);
+ padding: 0 20px;
+}
+
+.navbar ul {
+ list-style: none;
+ display: flex;
+ justify-content: center;
+ flex-wrap: wrap;
+ margin: 0;
+ padding: 0;
+}
+
+.navbar li {
+ padding: 15px 20px;
+}
+
+.navbar a {
+ color: var(--white);
+ text-decoration: none;
+ font-weight: 500;
+ transition: var(--transition);
+}
+
+.navbar a:hover, .navbar a.active {
+ text-decoration: underline;
+ text-underline-offset: 5px;
+}
+
+/* Main Content */
+.email-management-container {
+ flex: 1;
+ padding: 30px;
+ max-width: 1400px;
+ margin: 0 auto;
+ width: 100%;
+}
+
+.email-management-container h1 {
+ text-align: center;
+ color: var(--primary-red);
+ margin-bottom: 30px;
+ font-size: 2rem;
+}
+
+/* Search Bar */
+.search-bar {
+ margin-bottom: 20px;
+}
+
+.search-bar input {
+ width: 100%;
+ padding: 10px;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ font-size: 16px;
+}
+
+/* Grid Layout */
+.departments-list {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
+ gap: 25px;
+ padding: 10px;
+}
+
+/* Department Card Style */
+.department-card {
+ background-color: var(--white);
+ border-radius: 8px;
+ box-shadow: var(--shadow);
+ border-left: 4px solid var(--primary-red);
+ padding: 20px;
+ transition: var(--transition);
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ min-height: 150px;
+}
+
+.department-card:hover {
+ transform: translateY(-5px);
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15);
+}
+
+.department-card h3 {
+ margin-top: 0;
+ color: var(--primary-red);
+ font-size: 1.1rem;
+ border-bottom: 1px solid var(--medium-gray);
+ padding-bottom: 8px;
+}
+
+.department-card ul {
+ list-style: none;
+ padding-left: 0;
+ margin-bottom: 10px;
+}
+
+.department-card li {
+ padding: 5px 0;
+ border-bottom: 1px solid var(--medium-gray);
+ color: var(--dark-gray);
+ font-size: 0.95rem;
+}
+
+/* Actions */
+.department-actions {
+ display: flex;
+ gap: 10px;
+ margin-top: 10px;
+}
+
+.edit-btn, .delete-btn, .add-department-btn, .save-btn, .cancel-btn {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ padding: 8px 12px;
+ border: none;
+ border-radius: 4px;
+ cursor: pointer;
+ font-size: 14px;
+}
+
+.edit-btn {
+ background-color: #4CAF50;
+ color: white;
+}
+
+.delete-btn {
+ background-color: #f44336;
+ color: white;
+}
+
+.add-department-btn {
+ background-color: #2196F3;
+ color: white;
+ margin-bottom: 20px;
+}
+
+/* Edit Form */
+.edit-form {
+ background-color: var(--light-gray);
+ padding: 20px;
+ border-radius: 8px;
+ margin-bottom: 20px;
+}
+
+.form-group {
+ margin-bottom: 15px;
+}
+
+.form-group label {
+ display: block;
+ margin-bottom: 5px;
+ font-weight: bold;
+}
+
+.form-group input {
+ width: 100%;
+ padding: 8px;
+ border: 1px solid var(--medium-gray);
+ border-radius: 4px;
+}
+
+.email-input-group {
+ display: flex;
+ gap: 10px;
+ margin-bottom: 10px;
+ align-items: center;
+}
+
+.email-input-group input {
+ flex: 1;
+}
+
+.remove-email {
+ background: none;
+ border: none;
+ color: #f44336;
+ cursor: pointer;
+ font-size: 16px;
+}
+
+.add-email {
+ background-color: #2196F3;
+ color: white;
+ border: none;
+ padding: 8px 12px;
+ border-radius: 4px;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ gap: 5px;
+}
+
+.form-actions {
+ display: flex;
+ gap: 10px;
+ margin-top: 20px;
+}
+
+/* Footer */
+footer {
+ background-color: var(--primary-red);
+ color: var(--white);
+ padding: 20px;
+ text-align: center;
+}
+
+.terms {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 20px;
+}
+
+.terms a {
+ color: var(--white);
+ text-decoration: none;
+}
+
+.footer-image {
+ height: 30px;
+}
+
+/* Responsive */
+@media (max-width: 1024px) {
+ .departments-list {
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
+ }
+}
+
+@media (max-width: 768px) {
+ .header-bar {
+ flex-direction: column;
+ padding: 10px;
+ }
+
+ .college-name {
+ margin: 10px 0;
+ font-size: 1.2rem;
+ }
+
+ .navbar li {
+ padding: 10px 15px;
+ }
+
+ .email-management-container {
+ padding: 20px 15px;
+ }
+}
+
+@media (max-width: 480px) {
+ .departments-list {
+ grid-template-columns: 1fr;
+ }
+}
diff --git a/frontend/src/Page6.js b/frontend/src/Page6.js
new file mode 100644
index 0000000..2be27a0
--- /dev/null
+++ b/frontend/src/Page6.js
@@ -0,0 +1,281 @@
+import React, { useState, useEffect } from 'react';
+import axios from 'axios';
+import { Link } from 'react-router-dom';
+import { FaEdit, FaTrash, FaPlus, FaSave, FaTimes } from 'react-icons/fa';
+import './Page6.css';
+import image from './components/image.png';
+import somaiyatrust from './components/somaiyatrust.png';
+import redlines from './components/redlines.png';
+
+const Page6 = () => {
+ const [departments, setDepartments] = useState([]);
+ const [programs, setPrograms] = useState([]);
+ const [newDepartment, setNewDepartment] = useState('');
+ const [newEmails, setNewEmails] = useState(['']);
+ const [selectedProgram, setSelectedProgram] = useState('');
+ const [editingDepartment, setEditingDepartment] = useState(null);
+ const [isAddingNew, setIsAddingNew] = useState(false);
+ const [searchTerm, setSearchTerm] = useState('');
+
+ useEffect(() => {
+ fetchDepartments();
+ fetchPrograms();
+ }, []);
+
+ const fetchDepartments = async () => {
+ try {
+ const response = await axios.get('http://localhost:5000/api/department-emails');
+ setDepartments(response.data);
+ } catch (error) {
+ console.error('Error fetching departments:', error);
+ }
+ };
+
+ const fetchPrograms = async () => {
+ try {
+ const response = await axios.get('http://localhost:5000/api/programs');
+ setPrograms(response.data);
+ } catch (error) {
+ console.error('Error fetching programs:', error);
+ }
+ };
+
+ const handleAddEmail = () => {
+ setNewEmails([...newEmails, '']);
+ };
+
+ const handleNewEmailChange = (index, value) => {
+ const updatedEmails = [...newEmails];
+ updatedEmails[index] = value;
+ setNewEmails(updatedEmails);
+ };
+
+ const handleRemoveEmail = (index) => {
+ const updatedEmails = newEmails.filter((_, i) => i !== index);
+ setNewEmails(updatedEmails);
+ };
+
+ const startEditing = (department) => {
+ setEditingDepartment(department);
+ setNewEmails([...department.emails]);
+ setIsAddingNew(false);
+ };
+
+ const cancelEditing = () => {
+ setEditingDepartment(null);
+ setIsAddingNew(false);
+ setNewDepartment('');
+ setNewEmails(['']);
+ setSelectedProgram('');
+ };
+
+ const saveDepartment = async () => {
+ try {
+ const emailsToSave = newEmails.filter(email => email.trim() !== '');
+
+ if (emailsToSave.length === 0) {
+ alert('At least one email is required');
+ return;
+ }
+
+ if (isAddingNew) {
+ if (!newDepartment.trim()) {
+ alert('Department name is required');
+ return;
+ }
+ if (!selectedProgram) {
+ alert('Please select a program');
+ return;
+ }
+
+ await axios.post('http://localhost:5000/api/department-emails', {
+ department: newDepartment,
+ emails: emailsToSave,
+ program: selectedProgram,
+ });
+ } else {
+ await axios.put(`http://localhost:5000/api/department-emails/${editingDepartment.department}`, {
+ emails: emailsToSave
+ });
+ }
+
+ fetchDepartments();
+ cancelEditing();
+ } catch (error) {
+ console.error('Error saving department:', error);
+ alert('Error saving department. Please try again.');
+ }
+ };
+
+ const deleteDepartment = async (departmentName) => {
+ if (window.confirm(`Are you sure you want to delete ${departmentName}?`)) {
+ try {
+ await axios.delete(`http://localhost:5000/api/department-emails/${departmentName}`);
+ fetchDepartments();
+ } catch (error) {
+ console.error('Error deleting department:', error);
+ alert('Error deleting department. Please try again.');
+ }
+ }
+ };
+
+ const filteredDepartments = departments.filter(dept =>
+ dept.department.toLowerCase().includes(searchTerm.toLowerCase())
+ );
+
+ return (
+
+ {/* Header Bar */}
+
+
+ Somaiya Scheduler
+
+
+
+ {/* Navigation Bar */}
+
+
+ {/* Main Content */}
+
+
Department Email Management
+
+
+ setSearchTerm(e.target.value)}
+ />
+
+
+ {editingDepartment || isAddingNew ? (
+
+
{isAddingNew ? 'Add New Department' : `Editing: ${editingDepartment.department}`}
+
+ {isAddingNew && (
+ <>
+
+
+
+
+
+
+
+ setNewDepartment(e.target.value)}
+ placeholder="Enter department name"
+ />
+
+ >
+ )}
+
+
+
+ {newEmails.map((email, index) => (
+
+ handleNewEmailChange(index, e.target.value)}
+ placeholder="Enter email"
+ />
+ {newEmails.length > 1 && (
+
+ )}
+
+ ))}
+
+
+
+
+
+
+
+
+ ) : (
+ <>
+
+
+
+ {filteredDepartments.length === 0 ? (
+
No departments found
+ ) : (
+ filteredDepartments.map((dept) => (
+
+
{dept.department}
+
+ {dept.emails.map((email, idx) => (
+ - {email}
+ ))}
+
+
+
+
+
+
+ ))
+ )}
+
+ >
+ )}
+
+
+ {/* Footer */}
+
+
+ );
+};
+
+export default Page6;