diff --git a/client/package.json b/client/package.json index ddbbc14ce..75898d4e2 100644 --- a/client/package.json +++ b/client/package.json @@ -42,6 +42,6 @@ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" - ] + ] } } diff --git a/client/src/pages/CoordinatorDashboard.js b/client/src/pages/CoordinatorDashboard.js index 082ff2478..8259b6507 100644 --- a/client/src/pages/CoordinatorDashboard.js +++ b/client/src/pages/CoordinatorDashboard.js @@ -1,12 +1,48 @@ -import React from "react"; +import React, { useEffect, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import axios from "axios"; +import "../styles/dashboard.css"; + +function CoordinatorDashboard() { + const [requests, setRequests] = useState([]); + const navigate = useNavigate(); + + const fetchRequests = async () => { + try { + const res = await axios.get( + `${process.env.REACT_APP_API_URL}/api/coordinator/requests` + ); + setRequests(res.data); + } catch (err) { + console.error("Failed to fetch requests:", err); + } + }; + + useEffect(() => { + fetchRequests(); + }, []); -const CoordinatorDashboard = () => { return ( -
-

Coordinator Dashboard

-

Welcome, Coordinator!

+
+

Coordinator Dashboard

+ + {requests.length === 0 ? ( +

No Pending Requests

+ ) : ( + requests.map((req) => ( +
navigate(`/coordinator/request/${req._id}`)} + > + {/*

{req.student.userName}

+

Email: {req.student.email}

*/} +

Company: {req.workplace.name}

+
+ )) + )}
); -}; +} -export default CoordinatorDashboard; \ No newline at end of file +export default CoordinatorDashboard; diff --git a/client/src/pages/CoordinatorRequestDetailView.js b/client/src/pages/CoordinatorRequestDetailView.js new file mode 100644 index 000000000..8c8a12f58 --- /dev/null +++ b/client/src/pages/CoordinatorRequestDetailView.js @@ -0,0 +1,107 @@ +import React, { useEffect, useState } from "react"; +import { useParams, useNavigate } from "react-router-dom"; +import axios from "axios"; +import "../styles/CoordinatorRequestDetailView.css"; + +const CoordinatorRequestDetailView = () => { + const { id } = useParams(); + const navigate = useNavigate(); + 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]); + + const handleApprove = async () => { + try { + const res = await axios.post( + `${process.env.REACT_APP_API_URL}/api/coordinator/request/${id}/approve` + ); + alert(res.data.message); + navigate("/coordinator-dashboard"); + } catch (err) { + console.error("Approval failed:", err); + alert("Error approving request."); + } + }; + + const handleReject = async () => { + const reason = prompt("Please enter a reason for rejection:"); + if (!reason) return alert("Rejection reason required!"); + + try { + const res = await axios.post( + `${process.env.REACT_APP_API_URL}/api/coordinator/request/${id}/reject`, + { reason } + ); + alert(res.data.message); + navigate("/coordinator-dashboard"); + } catch (err) { + console.error("Rejection failed:", err); + alert("Error rejecting request."); + } + }; + + if (!data) return

Loading...

; + + const { requestData, supervisorStatus } = data; + + return ( +
+

Internship Request Details

+ +
+

+ Student: {requestData.student.userName} +

+

+ Email: {requestData.student.email} +

+

+ Company: {requestData.workplace.name} +

+

+ Supervisor Status: {supervisorStatus} +

+ +

Tasks & CS Outcomes

+ + + + + + + + + {requestData.tasks.map((task, idx) => ( + + + + + ))} + +
TaskOutcomes
{task.description}{task.outcomes.join(", ")}
+ +
+ + + +
+
+
+ ); +}; + +export default CoordinatorRequestDetailView; diff --git a/client/src/pages/Home.js b/client/src/pages/Home.js index c1fdf9e6c..c8ed3df5d 100644 --- a/client/src/pages/Home.js +++ b/client/src/pages/Home.js @@ -1,5 +1,4 @@ -import React from 'react'; -import { useState } from "react"; +import React, { useState, useEffect } from "react"; import { Link, useNavigate } from "react-router-dom"; import "../styles/App.css"; import { FaEnvelope, FaLock, FaEye, FaEyeSlash } from "react-icons/fa"; @@ -7,17 +6,23 @@ import "../styles/login.css"; import StudentIcon from "../Icons/StudentIcon"; import CoordinatorIcon from "../Icons/CoordinatorIcon"; import SupervisorIcon from "../Icons/SupervisorIcon"; -import Swal from 'sweetalert2'; +import Swal from "sweetalert2"; function Home() { const navigate = useNavigate(); const [formData, setFormData] = useState({ email: "", password: "", - role: "", + + role: "student", }); const [showPassword, setShowPassword] = useState(false); - + const [role] = useState("student"); + + // Sync role into formData.role + useEffect(() => { + setFormData((prev) => ({ ...prev, role })); + }, [role]); const handleInputChange = (e) => { const { name, value } = e.target; @@ -29,9 +34,10 @@ function Home() { const handleSubmit = async (e) => { e.preventDefault(); - + console.log(`${formData.role} sign in attempted`, formData); + const { email: ouEmail, password, role } = formData; - + if (!ouEmail || !password || !role) { return Swal.fire({ icon: "warning", @@ -39,24 +45,36 @@ function Home() { text: "Please fill in all fields to sign in 💫", }); } - + try { - const response = await fetch(`${process.env.REACT_APP_API_URL}/api/token/user-login`, { - method: "POST", - headers: { - "Content-Type": "application/json", + const response = await fetch( + `${process.env.REACT_APP_API_URL}/api/token/user-login`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ ouEmail, password, role }), }, - body: JSON.stringify({ ouEmail, password, role }), - }); - + ); + const data = await response.json(); - + if (response.ok) { Swal.fire({ icon: "success", title: "Login Successful 🌟", text: `Welcome back, ${role}!`, }); + + // Redirect user based on role + if (role === "coordinator") { + navigate("/coordinator-dashboard"); + } else if (role === "student") { + navigate("/student-dashboard"); + } else if (role === "supervisor") { + navigate("/supervisor-dashboard"); + } } else { Swal.fire({ icon: "error", @@ -73,8 +91,6 @@ function Home() { }); } }; - - return (
@@ -101,26 +117,20 @@ function Home() { ].map(({ role: r, Icon }) => (
setFormData({ - ...formData, - role: r, - })} + className={`role-card ${ + formData.role === r ? "selected" : "" + }`} + onClick={() => + setFormData({ + ...formData, + role: r, + }) + } >

{r.charAt(0).toUpperCase() + r.slice(1)}

-
))}
@@ -179,17 +189,20 @@ function Home() { marginBottom: "1rem", }} > -