Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions client/src/pages/CoordinatorRequestDetailView.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React, { useEffect, useState } from "react";
import axios from "axios";
import { useParams } from "react-router-dom";
import "../styles/CoordinatorRequestDetailView.css";

const CoordinatorRequestDetailView = () => {
const { id } = useParams();
const [data, setData] = useState(null);

useEffect(() => {
axios
.get(`${process.env.REACT_APP_API_URL}/api/coordinator/request/${id}`)
.then((res) => setData(res.data))
.catch((err) => console.log(err));
}, [id]);

if (!data) return <h2>Loading...</h2>;

const { requestData, supervisorStatus } = data;

return (
<div className="request-form">
<h2 className="dashboard-title">Internship Request Details</h2>

<div className="dashboard-card">
<p>
<b>Student Name:</b> {requestData.student.userName}
</p>
<p>
<b>Student Email:</b> {requestData.student.email}
</p>
<p>
<b>Company:</b> {requestData.workplace.name}
</p>
<p>
<b>Company Website:</b> {requestData.workplace.website}
</p>
<p>
<b>Company Phone:</b> {requestData.workplace.phone}
</p>
<p>
<b>Internship Advisor:</b> {requestData.internshipAdvisor.name} (
{requestData.internshipAdvisor.email})
</p>
<p>
<b>Credit Hours:</b> {requestData.creditHours}
</p>
<p>
<b>Start Date:</b>{" "}
{new Date(requestData.startDate).toLocaleDateString()}
</p>
<p>
<b>End Date:</b> {new Date(requestData.endDate).toLocaleDateString()}
</p>
<p>
<b>Supervisor Approval Status:</b> {supervisorStatus}
</p>

<h3 className="section-title">Tasks & CS Outcomes</h3>
<table className="data-table">
<thead>
<tr>
<th>Task Description</th>
<th>CS Outcomes</th>
</tr>
</thead>
<tbody>
{requestData.tasks.map((task, idx) => (
<tr key={idx}>
<td>{task.description}</td>
<td>{task.outcomes.join(", ")}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
);
};

export default CoordinatorRequestDetailView;
7 changes: 5 additions & 2 deletions client/src/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import React from "react";
import { createBrowserRouter } from "react-router-dom";
import A1InternshipRequestForm from "./pages/A1InternshipRequestForm";


// Layout
import Layout from "./components/Layout";

Expand All @@ -15,6 +14,7 @@ import WeeklyProgressReportForm from "./pages/WeeklyProgressReportForm";
import A3JobEvaluationForm from "./pages/A3JobEvaluationForm";
import SupervisorDashboard from "./pages/SupervisorDashboard";
import CoordinatorDashboard from "./pages/CoordinatorDashboard";
import CoordinatorRequestDetailView from "./pages/CoordinatorRequestDetailView";

// Create and export the router configuration
const router = createBrowserRouter([
Expand Down Expand Up @@ -51,9 +51,12 @@ const router = createBrowserRouter([
path: "coordinator-dashboard",
element: <CoordinatorDashboard />,
},
{
path: "coordinator/request/:id",
element: <CoordinatorRequestDetailView />,
},
],
},
]);


export default router;
17 changes: 17 additions & 0 deletions client/src/styles/CoordinatorRequestDetailView.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
@import "./App.css";

.request-form {
max-width: 700px;
margin: 40px auto;
padding: 30px;
background-color: white;
border-radius: 12px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
}

.section-title {
color: #9d2235;
margin-top: 20px;
font-weight: 600;
font-size: 1.1rem;
}
37 changes: 32 additions & 5 deletions server/controllers/approvalController.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
const Submission = require("../models/Submission");
const InternshipRequest = require("../models/InternshipRequest");
const EmailService = require("../services/emailService");

// ✅ Get pending submissions for supervisor
exports.getPendingSubmissions = async (req, res) => {
try {
const submissions = await Submission.find({ supervisor_status: "pending" });
res.json(submissions);
} catch (err) {
res.status(500).json({ message: "Failed to fetch pending submissions", error: err });
res
.status(500)
.json({ message: "Failed to fetch pending submissions", error: err });
}
};

Expand All @@ -27,9 +31,8 @@ exports.approveSubmission = async (req, res) => {

res.json({
message: "Submission approved and forwarded to Coordinator",
updatedSubmission: submission
updatedSubmission: submission,
});

} catch (err) {
res.status(500).json({ message: "Approval failed", error: err });
}
Expand All @@ -52,10 +55,34 @@ exports.rejectSubmission = async (req, res) => {

res.json({
message: "Submission rejected",
updatedSubmission: submission
updatedSubmission: submission,
});

} catch (err) {
res.status(500).json({ message: "Rejection failed", error: err });
}
};
// Coordinator: Get Request Details
exports.getCoordinatorRequestDetails = async (req, res) => {
try {
const requestData = await InternshipRequest.findById(
req.params.id
).populate("student", "userName email");

if (!requestData) {
return res.status(404).json({ message: "Request not found" });
}

const submissionData = await Submission.findOne({
student_name: requestData.student.userName,
});

res.status(200).json({
requestData,
supervisorStatus: submissionData
? submissionData.supervisor_status
: "Not Submitted",
});
} catch (err) {
res.status(500).json({ message: "Failed to fetch details", error: err });
}
};
1 change: 0 additions & 1 deletion server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ const cronJobManager = require("./utils/cronUtils");
const { registerAllJobs } = require("./jobs/registerCronJobs");
const Evaluation = require("./models/Evaluation");


const app = express();
app.use(express.json());
app.use(cors());
Expand Down
15 changes: 12 additions & 3 deletions server/middleware/authMiddleware.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
exports.isSupervisor = (req, res, next) => {
// const supervisor = Sup.find({$id: username})


req.user = { role: 'supervisor' }; // Mocking user role for demo
req.user = { role: "supervisor" }; // Mocking user role for demo
if (req.user.role === "supervisor") {
next();
} else {
res.status(403).json({ message: "Access denied. Not a supervisor." });
}
};
};

exports.isCoordinator = (req, res, next) => {
req.user = { role: "coordinator" }; // Mocking role for now (or fetch from DB if implemented)

if (req.user.role === "coordinator") {
next();
} else {
res.status(403).json({ message: "Access denied. Not a coordinator." });
}
};
20 changes: 17 additions & 3 deletions server/routes/approvalRoutes.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
const express = require("express");
const router = express.Router();
const { getPendingSubmissions, approveSubmission, rejectSubmission } = require("../controllers/approvalController");
const { isSupervisor } = require("../middleware/authMiddleware");
const {
getPendingSubmissions,
approveSubmission,
rejectSubmission,
} = require("../controllers/approvalController");
const { isSupervisor, isCoordinator } = require("../middleware/authMiddleware");
const {
getCoordinatorRequestDetails,
coordinatorApproveRequest,
coordinatorRejectRequest,
} = require("../controllers/approvalController");

router.get("/submissions/pending", isSupervisor, getPendingSubmissions);
router.post("/submissions/:id/approve", isSupervisor, approveSubmission);
router.post("/submissions/:id/reject", isSupervisor, rejectSubmission);
router.get(
"/coordinator/request/:id",
isCoordinator,
getCoordinatorRequestDetails
);

module.exports = router;
module.exports = router;