diff --git a/src/App.js b/src/App.js index e1ae369eb33599ae835b35c0027904b12bb5b7f9..299b45eb803e330557e233c1a746c653bdd32f76 100644 --- a/src/App.js +++ b/src/App.js @@ -1,25 +1,25 @@ import React from "react"; import { BrowserRouter as Router, Route, Routes } from "react-router-dom"; import Navbar from "./components/Navbar"; -import StageList from "./components/StageList"; -import EnterpriseList from "./components/EnterpriseList"; -import StudentList from "./components/StudentList"; -import CandidacyList from "./components/CandidacyList"; -import UnivSupervisorList from "./components/UnivSupervisorList"; +import StageList from "./components/Stages/StageList.jsx"; +import EnterpriseList from "./components/Entreprises/EnterpriseList.jsx"; +import StudentList from "./components/Students/StudentList.jsx"; +import CandidacyList from "./components/Candidatures/CandidacyList.jsx"; +import UnivSupervisorList from "./components/Supervisors/UnivSupervisorList.jsx"; // Import the forms -import StageForm from "./components/StageForm"; -import EnterpriseForm from "./components/EnterpriseForm"; -import StudentForm from "./components/StudentForm"; -import CandidacyForm from "./components/CandidacyForm"; -import UnivSupervisorForm from "./components/UnivSupervisorForm"; +import StageForm from "./components/Stages/StageForm.jsx"; +import EnterpriseForm from "./components/Entreprises/EnterpriseForm.jsx"; +import StudentForm from "./components/Students/StudentForm.jsx"; +import CandidacyForm from "./components/Candidatures/CandidacyForm.jsx"; +import UnivSupervisorForm from "./components/Supervisors/UnivSupervisorForm.jsx"; // Import the update form -import UpdateCandidacyForm from "./components/UpdateCandidacyForm"; -import UpdateEnterpriseForm from "./components/UpdateEnterpriseForm.jsx"; -import UpdateStageForm from "./components/UpdateStageForm.jsx"; -import UpdateStudentForm from "./components/UpdateStudentForm.jsx"; -import UpdateUnivSupervisorForm from "./components/UpdateUnivSupervisorForm.jsx"; +import UpdateCandidacyForm from "./components/Candidatures/UpdateCandidacyForm.jsx"; +import UpdateEnterpriseForm from "./components/Entreprises/UpdateEnterpriseForm.jsx"; +import UpdateStageForm from "./components/Stages/UpdateStageForm.jsx"; +import UpdateStudentForm from "./components/Students/UpdateStudentForm.jsx"; +import UpdateUnivSupervisorForm from "./components/Supervisors/UpdateUnivSupervisorForm.jsx"; import Login from "./components/Login.jsx"; import Logout from "./components/Logout.jsx"; @@ -49,7 +49,7 @@ function App() { <Route path="/modifier-candidature/:id" element={<UpdateCandidacyForm />} /> <Route path="/modifier-entreprise/:id" element={<UpdateEnterpriseForm />} /> <Route path="/modifier-etudiant/:id" element={<UpdateStudentForm/>} /> - <Route path="/modifier-etudiant/:id" element={<UpdateStudentForm/>} /> + <Route path="/modifier-stage/:id" element={<UpdateStageForm/>} /> <Route path="/modifier-univsuperviseur/:id" element={<UpdateUnivSupervisorForm />} /> {/* Default Route */} <Route path="/" element={<h2>Bienvenue sur l'Application de Gestion des Stages</h2>} /> diff --git a/src/components/CandidacyForm.jsx b/src/components/Candidatures/CandidacyForm.jsx similarity index 100% rename from src/components/CandidacyForm.jsx rename to src/components/Candidatures/CandidacyForm.jsx diff --git a/src/components/CandidacyList.jsx b/src/components/Candidatures/CandidacyList.jsx similarity index 100% rename from src/components/CandidacyList.jsx rename to src/components/Candidatures/CandidacyList.jsx diff --git a/src/components/UpdateCandidacyForm.jsx b/src/components/Candidatures/UpdateCandidacyForm.jsx similarity index 100% rename from src/components/UpdateCandidacyForm.jsx rename to src/components/Candidatures/UpdateCandidacyForm.jsx diff --git a/src/components/EnterpriseForm.jsx b/src/components/Entreprises/EnterpriseForm.jsx similarity index 100% rename from src/components/EnterpriseForm.jsx rename to src/components/Entreprises/EnterpriseForm.jsx diff --git a/src/components/EnterpriseList.jsx b/src/components/Entreprises/EnterpriseList.jsx similarity index 100% rename from src/components/EnterpriseList.jsx rename to src/components/Entreprises/EnterpriseList.jsx diff --git a/src/components/UpdateEnterpriseForm.jsx b/src/components/Entreprises/UpdateEnterpriseForm.jsx similarity index 100% rename from src/components/UpdateEnterpriseForm.jsx rename to src/components/Entreprises/UpdateEnterpriseForm.jsx diff --git a/src/components/Login.jsx b/src/components/Login.jsx index d6eb8c5239f949e2754a87ffacdeaf1ad43c8849..39b181ec792dbf287d32aa47e1fbf1a436726848 100644 --- a/src/components/Login.jsx +++ b/src/components/Login.jsx @@ -18,28 +18,35 @@ const Login = () => { e.preventDefault(); try { - const response = await fetch("http://localhost:8080/api/auth/login", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ username, password }), - }); + const response = await fetch("http://localhost:8080/api/auth/login", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ username, password }), + }); - if (!response.ok) { - throw new Error("Invalid credentials"); - } + if (!response.ok) { + throw new Error("Invalid credentials"); + } - const data = await response.text(); // Adjust this if backend returns JSON - console.log("✅ Login successful!", data); + const data = await response.json(); // ✅ Parse JSON properly + console.log("✅ Login successful!", data); - localStorage.setItem("token", "dummy-token"); // Store token (if applicable) - navigate("/"); // Redirect after login + localStorage.setItem("token", "dummy-token"); // Store token (if applicable) + + // ✅ Store roles properly if they exist + if (data.roles) { + localStorage.setItem("roles", JSON.stringify(data.roles)); + } + + navigate("/"); // Redirect after login } catch (error) { - console.error("❌ Login failed:", error.message); - setError("Invalid username or password"); + console.error("❌ Login failed:", error.message); + setError("Invalid username or password"); } - }; + }; + return ( <div style={{ textAlign: "center", marginTop: "50px" }}> diff --git a/src/components/Logout.jsx b/src/components/Logout.jsx index fb00d82617de7ca4d9b01191ded168b23fda96f5..27924f2a2441c1544a8d6ea5e162eaf23aaf253c 100644 --- a/src/components/Logout.jsx +++ b/src/components/Logout.jsx @@ -21,9 +21,13 @@ const Logout = () => { console.error("❌ Error during logout:", error); } - // Clear stored auth details and redirect + // ✅ Clear stored authentication details localStorage.removeItem("token"); localStorage.removeItem("user"); + localStorage.removeItem("roles"); // ✅ This is the missing part that clears the roles + localStorage.clear(); // Optional: Clears all localStorage data + + // ✅ Redirect to login page navigate("/login"); }; diff --git a/src/components/Navbar.jsx b/src/components/Navbar.jsx index 4274267238f37dbee74857a36f42161893a21b79..ac4edbdd3651dcd94cf070d21ee369533b50a979 100644 --- a/src/components/Navbar.jsx +++ b/src/components/Navbar.jsx @@ -1,7 +1,27 @@ -import React from "react"; +import React, { useEffect, useState } from "react"; import { Link } from "react-router-dom"; function Navbar() { + const [roles, setRoles] = useState([]); + + useEffect(() => { + // ✅ Ensure roles are properly fetched + const storedRoles = localStorage.getItem("roles"); + if (storedRoles) { + try { + setRoles(JSON.parse(storedRoles)); + } catch (error) { + console.error("❌ Error parsing roles from localStorage", error); + setRoles([]); // Fallback if parsing fails + } + } else { + setRoles([]); // Ensure empty roles if none exist + } + }, []); + + // 🔥 Function to check if user has a specific role + const hasRole = (role) => roles.includes(role); + return ( <nav className="navbar navbar-expand-lg navbar-dark bg-primary"> <div className="container"> @@ -20,62 +40,90 @@ function Navbar() { <div className="collapse navbar-collapse" id="navbarNav"> <ul className="navbar-nav ms-auto"> - {/* Stages Dropdown */} - <li className="nav-item dropdown"> - <a className="nav-link dropdown-toggle" href="#" id="stagesDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> - 📚 Stages - </a> - <ul className="dropdown-menu" aria-labelledby="stagesDropdown"> - <li><Link className="dropdown-item" to="/stages">📜 Liste des Stages</Link></li> - <li><Link className="dropdown-item" to="/ajouter-stage">➕ Ajouter un Stage</Link></li> - </ul> - </li> + {/* 📚 Stages */} + {(hasRole("ROLE_ETUDIANT") || hasRole("ROLE_ENTREPRISE") || hasRole("ROLE_SUPERVISEUR") || hasRole("ROLE_ADMIN")) && ( + <li className="nav-item dropdown"> + <a className="nav-link dropdown-toggle" href="#" id="stagesDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> + 📚 Stages + </a> + <ul className="dropdown-menu" aria-labelledby="stagesDropdown"> + <li><Link className="dropdown-item" to="/stages">📜 Liste des Stages</Link></li> + {(hasRole("ROLE_ENTREPRISE") || hasRole("ROLE_SUPERVISEUR") || hasRole("ROLE_ADMIN")) && ( + <li><Link className="dropdown-item" to="/ajouter-stage">➕ Ajouter/Modifier un Stage</Link></li> + )} + </ul> + </li> + )} - {/* Étudiants Dropdown */} - <li className="nav-item dropdown"> - <a className="nav-link dropdown-toggle" href="#" id="etudiantsDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> - 👨🎓 Étudiants - </a> - <ul className="dropdown-menu" aria-labelledby="etudiantsDropdown"> - <li><Link className="dropdown-item" to="/etudiants">📜 Liste des Étudiants</Link></li> - <li><Link className="dropdown-item" to="/ajouter-etudiant">➕ Ajouter un Étudiant</Link></li> - </ul> - </li> + {/* 👨🎓 Étudiants */} + {(hasRole("ROLE_ETUDIANT") || hasRole("ROLE_SUPERVISEUR") || hasRole("ROLE_ADMIN")) && ( + <li className="nav-item dropdown"> + <a className="nav-link dropdown-toggle" href="#" id="etudiantsDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> + 👨🎓 Étudiants + </a> + <ul className="dropdown-menu" aria-labelledby="etudiantsDropdown"> + {/* Everyone with ETUDIANT, SUPERVISEUR, ADMIN can see the list */} + <li><Link className="dropdown-item" to="/etudiants">📜 Liste des Étudiants</Link></li> - {/* Entreprises Dropdown */} - <li className="nav-item dropdown"> - <a className="nav-link dropdown-toggle" href="#" id="entreprisesDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> - 🏢 Entreprises - </a> - <ul className="dropdown-menu" aria-labelledby="entreprisesDropdown"> - <li><Link className="dropdown-item" to="/entreprises">📜 Liste des Entreprises</Link></li> - <li><Link className="dropdown-item" to="/ajouter-entreprise">➕ Ajouter une Entreprise</Link></li> - </ul> - </li> + {/* BUT ONLY ADMIN CAN ADD */} + {hasRole("ROLE_ADMIN") && ( + <> - {/* Candidatures Dropdown */} - <li className="nav-item dropdown"> - <a className="nav-link dropdown-toggle" href="#" id="candidaturesDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> - 📝 Candidatures - </a> - <ul className="dropdown-menu" aria-labelledby="candidaturesDropdown"> - <li><Link className="dropdown-item" to="/candidatures">📜 Liste des Candidatures</Link></li> - <li><Link className="dropdown-item" to="/ajouter-candidature">➕ Ajouter une Candidature</Link></li> - </ul> - </li> + <li><Link className="dropdown-item" to="/ajouter-etudiant">➕ Ajouter/Modifier un Étudiant</Link></li> + </> + )} + </ul> + </li> + )} - {/* Superviseurs Dropdown */} - <li className="nav-item dropdown"> - <a className="nav-link dropdown-toggle" href="#" id="superviseursDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> - 👨🏫 Superviseurs - </a> - <ul className="dropdown-menu" aria-labelledby="superviseursDropdown"> - <li><Link className="dropdown-item" to="/superviseurs">📜 Liste des Superviseurs</Link></li> - <li><Link className="dropdown-item" to="/ajouter-univsuperviseur">➕ Ajouter un Superviseur</Link></li> - </ul> - </li> + {/* 🏢 Entreprises */} + {(hasRole("ROLE_ENTREPRISE") || hasRole("ROLE_ADMIN")) && ( + <li className="nav-item dropdown"> + <a className="nav-link dropdown-toggle" href="#" id="entreprisesDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> + 🏢 Entreprises + </a> + <ul className="dropdown-menu" aria-labelledby="entreprisesDropdown"> + <li><Link className="dropdown-item" to="/entreprises">📜 Liste des Entreprises</Link></li> + {(hasRole("ROLE_ENTREPRISE") || hasRole("ROLE_ADMIN")) && ( + <li><Link className="dropdown-item" to="/ajouter-entreprise">➕ Ajouter/Modifier une Entreprise</Link></li> + )} + </ul> + </li> + )} + + {/* 📝 Candidatures */} + {(hasRole("ROLE_ETUDIANT") || hasRole("ROLE_ADMIN") || hasRole("ROLE_SUPERVISEUR")) && ( + <li className="nav-item dropdown"> + <a className="nav-link dropdown-toggle" href="#" id="candidaturesDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> + 📝 Candidatures + </a> + <ul className="dropdown-menu" aria-labelledby="candidaturesDropdown"> + {/* ADMIN can see the list, but ETUDIANT cannot */} + {(hasRole("ROLE_ADMIN") || hasRole("ROLE_SUPERVISEUR")) && ( + <li><Link className="dropdown-item" to="/candidatures">📜 Liste des Candidatures</Link></li> + )} + {/* ALL Étudiants CAN apply */} + <li><Link className="dropdown-item" to="/ajouter-candidature">➕ Ajouter une Candidature</Link></li> + </ul> + </li> + )} + + + {/* 👨🏫 Superviseurs (Admin Only) */} + {(hasRole("ROLE_ADMIN")||hasRole("ROLE_SUPERVISEUR")) && ( + <li className="nav-item dropdown"> + <a className="nav-link dropdown-toggle" href="#" id="superviseursDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> + 👨🏫 Superviseurs + </a> + <ul className="dropdown-menu" aria-labelledby="superviseursDropdown"> + <li><Link className="dropdown-item" to="/superviseurs">📜 Liste des Superviseurs</Link></li> + {hasRole("ROLE_ADMIN") && ( + <li><Link className="dropdown-item" to="/ajouter-univsuperviseur">➕ Ajouter un Superviseur</Link></li>)} + </ul> + </li> + )} - {/* Authentication Links */} + {/* 🔑 Authentification */} <li className="nav-item"> <Link className="nav-link" to="/login">🔑 Login</Link> </li> diff --git a/src/components/StageForm.jsx b/src/components/Stages/StageForm.jsx similarity index 100% rename from src/components/StageForm.jsx rename to src/components/Stages/StageForm.jsx diff --git a/src/components/StageList.jsx b/src/components/Stages/StageList.jsx similarity index 100% rename from src/components/StageList.jsx rename to src/components/Stages/StageList.jsx diff --git a/src/components/UpdateStageForm.jsx b/src/components/Stages/UpdateStageForm.jsx similarity index 100% rename from src/components/UpdateStageForm.jsx rename to src/components/Stages/UpdateStageForm.jsx diff --git a/src/components/StudentForm.jsx b/src/components/Students/StudentForm.jsx similarity index 100% rename from src/components/StudentForm.jsx rename to src/components/Students/StudentForm.jsx diff --git a/src/components/StudentList.jsx b/src/components/Students/StudentList.jsx similarity index 100% rename from src/components/StudentList.jsx rename to src/components/Students/StudentList.jsx diff --git a/src/components/UpdateStudentForm.jsx b/src/components/Students/UpdateStudentForm.jsx similarity index 100% rename from src/components/UpdateStudentForm.jsx rename to src/components/Students/UpdateStudentForm.jsx diff --git a/src/components/UnivSupervisorForm.jsx b/src/components/Supervisors/UnivSupervisorForm.jsx similarity index 100% rename from src/components/UnivSupervisorForm.jsx rename to src/components/Supervisors/UnivSupervisorForm.jsx diff --git a/src/components/UnivSupervisorList.jsx b/src/components/Supervisors/UnivSupervisorList.jsx similarity index 100% rename from src/components/UnivSupervisorList.jsx rename to src/components/Supervisors/UnivSupervisorList.jsx diff --git a/src/components/UpdateUnivSupervisorForm.jsx b/src/components/Supervisors/UpdateUnivSupervisorForm.jsx similarity index 100% rename from src/components/UpdateUnivSupervisorForm.jsx rename to src/components/Supervisors/UpdateUnivSupervisorForm.jsx