Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
16d2116
tokenExpiryChecks and reminder emails implemented
TheJob21 Apr 17, 2025
a7a64cd
Fixed some bugs, Tested functionality
TheJob21 Apr 18, 2025
be80fff
Token Renewal API with secure validation and expiry extension
Apr 18, 2025
22902b7
Implemented student dashboard with conditional UI and navigation
Apr 18, 2025
fbd3186
Add page for redirection after successful token renewal
kushi-3 Apr 18, 2025
05a2bd3
Remove unused variable
kushi-3 Apr 18, 2025
ed1458e
auto-deactivation changes
Apr 19, 2025
7649a53
Implemented Auto-Deactivation after token expiry
Apr 19, 2025
1e408f6
Merge pull request #123 from IPMS-Project/GroupF/token-expiry-monitor…
kushi-3 Apr 19, 2025
d7abafa
Revert "Remove unused variable"
kushi-3 Apr 19, 2025
86868e6
Revert "Add page for redirection after successful token renewal"
kushi-3 Apr 19, 2025
a039d99
Implemented Auto deactivation after token expiry with 24-hour window
Apr 19, 2025
47b3407
Implemented Auto deactivation after token expiry with 24-hour window …
Apr 19, 2025
cc2672f
Implemented Auto deactivation after token expiry with 24-hour window …
Apr 19, 2025
311d40a
Resolved conflicts
Apr 19, 2025
24fea5b
Merge branch 'GroupF/development' of https://github.com/IPMS-Project/…
kushi-3 Apr 19, 2025
e4a74d4
Merge pull request #125 from IPMS-Project/GroupF/studentDashboard
kushi-3 Apr 19, 2025
ab52519
Merge branch 'GroupF/development' of https://github.com/IPMS-Project/…
kushi-3 Apr 19, 2025
9205dc3
Update code to search for given token
kushi-3 Apr 19, 2025
72e6c5f
Add sooner id to the sign up
kushi-3 Apr 19, 2025
8c1dca6
Merge pull request #129 from IPMS-Project/GroupF/tokenrenewal
kushi-3 Apr 19, 2025
f242362
a1form scheme reference changed
Apr 20, 2025
d52df8a
Update to make sooner id field mandatory only to studnets
kushi-3 Apr 20, 2025
df706ca
Merge branch 'GroupF/development' of https://github.com/IPMS-Project/…
kushi-3 Apr 20, 2025
15f6fa3
Student Dashboard logic updated
Apr 20, 2025
f3b6bc4
Show renewal link for deactivated accounts on login page
kushi-3 Apr 20, 2025
4ef0dea
Merge branch 'GroupF/development' of https://github.com/IPMS-Project/…
kushi-3 Apr 20, 2025
29cb7a7
Merge branch 'main' of https://github.com/IPMS-Project/IPMS into Grou…
kushi-3 Apr 21, 2025
afa2f21
Resolve missing dependency issue
kushi-3 Apr 21, 2025
0659888
Remove unnecessary package.json
kushi-3 Apr 21, 2025
bad4057
Role based navigation added
Apr 21, 2025
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
3 changes: 2 additions & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"@testing-library/user-event": "^13.5.0",
"axios": "^1.8.2",
"bootstrap": "^5.3.5",
"client": "file:",
"react": "^19.0.0",
"react-bootstrap": "^2.10.9",
"react-dom": "^19.0.0",
Expand Down Expand Up @@ -42,6 +43,6 @@
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
]
}
}
54 changes: 40 additions & 14 deletions client/src/pages/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +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",
Expand All @@ -61,25 +61,50 @@ function Home() {
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") {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not remove the coordinator and supervisor-based navigation.
If any logic needs to be updated, adapt it accordingly without breaking role-based routing.
Alternatively, inform the respective team about the changes so they can adjust on their end.

Copy link
Contributor

@Aakash452 Aakash452 Apr 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The coordinator and supervisor-based navigation was never added from this side, I think it was a merge issue cause when I worked on student-dashboard navigation, there was no navigation logic for other roles

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that this wasn’t added from your side, but I just want to clarify that this is not a merge issue. The coordinator and supervisor-based navigation was added by Team A (I believe), and the logic does exist. So please either add the necessary navigation logic accordingly or inform the respective team, so they can make the required adjustments

navigate("/coordinator-dashboard");
} else if (role === "student") {
navigate("/student-dashboard");
} else if (role === "supervisor") {
const user = data.user;
if(role === "student"){
// Store only required fields
const limitedUserInfo = {
fullName: user.fullName,
id: user._id,
email:user.ouEmail
};

localStorage.setItem("ipmsUser", JSON.stringify(limitedUserInfo));
navigate("/student-dashboard");
}else if(role === "supervisor"){
Swal.fire({
icon: "success",
title: "Login Successful 🌟",
text: `Welcome back, ${role}!`,
});
navigate("/supervisor-dashboard");
}else{
Swal.fire({
icon: "success",
title: "Login Successful 🌟",
text: `Welcome back, ${role}!`,
});
navigate("/coordinator-dashboard");
}



// Swal.fire({
// icon: "success",
// title: "Login Successful",
// text: `Welcome back, `,
// });


} else {
Swal.fire({
icon: "error",
title: "Login Failed",
text: data.message || "Something went wrong ",
html: data.message + " " +
(data.renewalLink
? `Please click <a href="${data.renewalLink}" target="_blank" rel="noopener noreferrer">here</a> to request a new token.`
: "Something went wrong."),
});
}
} catch (error) {
Expand Down Expand Up @@ -126,6 +151,7 @@ function Home() {
role: r,
})
}

>
<Icon />
<p className="role-label">
Expand Down
16 changes: 16 additions & 0 deletions client/src/pages/ProtectedRouteStudent.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// src/components/ProtectedRouteStudent.js
import React from "react";
import { Navigate } from "react-router-dom";

const ProtectedRouteStudent = ({ children }) => {
const user = JSON.parse(localStorage.getItem("ipmsUser"));

// Check if user info is missing
if (!user || !user.id || !user.fullName) {
return <Navigate to="/" replace />;
}

return children;
};

export default ProtectedRouteStudent;
38 changes: 36 additions & 2 deletions client/src/pages/SignUp.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ function SignUp() {
const [step, setStep] = useState(1);
const [fullName, setFullName] = useState("");
const [ouEmail, setOuEmail] = useState("");
const [soonerId, setSoonerId] = useState("");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [showPassword, setShowPassword] = useState(false);
Expand Down Expand Up @@ -61,12 +62,22 @@ function SignUp() {
return;
}

if (role=== "student" && !/^\d{9}$/.test(soonerId)) {
Swal.fire({
icon: "error",
title: "Invalid Sooner ID",
text: "Sooner ID must be a 9-digit number.",
});
return;
}

try {
const response = await axios.post(
`${process.env.REACT_APP_API_URL}/api/token/request`,
{
fullName,
ouEmail,
soonerId : role === "student" ? soonerId : "",
password,
semester,
academicAdvisor: role === "student" ? academicAdvisor : "",
Expand All @@ -88,6 +99,7 @@ function SignUp() {
// Clear form
setFullName("");
setOuEmail("");
setSoonerId("");
setPassword("");
setConfirmPassword("");
setSemester("");
Expand All @@ -100,13 +112,22 @@ function SignUp() {
} catch (error) {
console.error("Error creating user:", error);

if (error.response && error.response.status === 400) {
if (error.response && error.response.status === 401) {
Swal.fire({
icon: "error",
title: "Email Already Exists",
text: "The provided email ID is already registered. Try logging in.",
});
} else {
}
else if(role=== "student" && error.response && error.response.status === 402){
Swal.fire({
icon: "error",
title: "Sooner ID Already Exists",
text: "The provided Sooner ID is already registered.",
});
}
else {
console.log("Error response:", error.response);
Swal.fire({
icon: "error",
title: "Something went wrong",
Expand Down Expand Up @@ -255,6 +276,19 @@ function SignUp() {
required
/>
</div>

{role === "student" && <div className="form-group">
<label htmlFor="soonerId">Sooner ID</label>
<input
type="text"
id="soonerId"
value={soonerId}
onChange={(e) => setSoonerId(e.target.value)}
placeholder="Enter your 9-digit Sooner ID"
required
/>
</div>}

<div className="password-row">
<div className="form-group password-col">
<label htmlFor="password">New password</label>
Expand Down
141 changes: 141 additions & 0 deletions client/src/pages/StudentDashboard.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import React, { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import "../styles/StudentDashboard.css"; // Make sure you create this CSS

const StudentDashboard = () => {
const navigate = useNavigate();

const user = JSON.parse(localStorage.getItem("ipmsUser"));
const ouEmail = user?.email;
const [approvalStatus, setApprovalStatus] = useState("not_submitted");

useEffect(() => {
const fetchData = async () => {
try {
const res = await fetch(`${process.env.REACT_APP_API_URL}/api/student`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ ouEmail }),
});

const data = await res.json();
setApprovalStatus(data.approvalStatus);
} catch (err) {
console.error("Error fetching internship data", err);
}
};

if (ouEmail) {
fetchData();
}
}, [ouEmail]);
console.log(approvalStatus);

return (
<div className="student-dashboard">
<div className="dashboard-header">
<h2>Welcome, {user.fullName}</h2>
</div>

<div className="dashboard-card">
{/* ------ FORM A1 Card ------ */}
<div className="card-section">
<div className="card-content">
<h3>Request Internship (FORM A1)</h3>
<p>Track your internship journey</p>

{approvalStatus === "not_submitted" && (
<p style={{ fontSize: "0.85rem", color: "#888" }}>
You have not submitted the form yet
</p>
)}

{(approvalStatus === "submitted" ||
approvalStatus === "pending manual review") && (
<p style={{ fontSize: "0.85rem", color: "#888" }}>
Your form is submitted and under review
</p>
)}

{approvalStatus === "approved" && (
<p style={{ fontSize: "0.85rem", color: "green" }}>Approved</p>
)}
</div>

<button
className="card-button"
onClick={() => {
if (
approvalStatus === "draft" ||
approvalStatus === "not_submitted"
) {
navigate("/a1-form");
}
}}
disabled={
approvalStatus !== "draft" && approvalStatus !== "not_submitted"
}
style={{
backgroundColor:
approvalStatus !== "draft" && approvalStatus !== "not_submitted"
? "#ccc"
: "",
cursor:
approvalStatus !== "draft" && approvalStatus !== "not_submitted"
? "not-allowed"
: "pointer",
}}
>
{approvalStatus === "approved" ? "Track" : "Request Internship"}
</button>
</div>

{/* ------ FORM A2 Card ------ */}
<div className="card-section">
<div className="card-content">
<h3>Weekly Report (Form A2)</h3>

{approvalStatus === "not_submitted" && (
<p style={{ fontSize: "0.85rem", color: "#888" }}>
Please fill your Form A1 first
</p>
)}

{approvalStatus === "draft" && (
<p style={{ fontSize: "0.85rem", color: "#888" }}>
Finish your Form A1 first
</p>
)}

{(approvalStatus === "submitted" ||
approvalStatus === "pending manual review") && (
<p style={{ fontSize: "0.85rem", color: "#888" }}>
Wait for your Form A1 to be approved
</p>
)}
</div>

<button
className="card-button"
disabled={approvalStatus !== "approved"}
onClick={() => {
if (approvalStatus === "approved") {
navigate("/weekly-report");
}
}}
style={{
backgroundColor: approvalStatus !== "approved" ? "#ccc" : "",
cursor: approvalStatus !== "approved" ? "not-allowed" : "pointer",
}}
>
Request
</button>
</div>
</div>
</div>
);
};

export default StudentDashboard;
Loading