Skip to content
Snippets Groups Projects
Commit 332d41b9 authored by Fatima Ezzahra Majidi's avatar Fatima Ezzahra Majidi
Browse files

Merge branch 'master' into 'main'

modification de l'affichage en fonction des rôles

See merge request !8
parents d588ccad 31857599
Branches
No related tags found
1 merge request!8modification de l'affichage en fonction des rôles
...@@ -45,7 +45,8 @@ function App() { ...@@ -45,7 +45,8 @@ function App() {
<Route path="/ajouter-etudiant" element={<StudentForm />} /> <Route path="/ajouter-etudiant" element={<StudentForm />} />
<Route path="/ajouter-candidature" element={<CandidacyForm />} /> <Route path="/ajouter-candidature" element={<CandidacyForm />} />
<Route path="/ajouter-univsuperviseur" element={<UnivSupervisorForm />} /> <Route path="/ajouter-univsuperviseur" element={<UnivSupervisorForm />} />
<Route path="/ajouter-ma-candidature" element={<CandidacyFormPrerempli />} /> <Route path="/ajouter-ma-candidature/:stageId" element={<CandidacyFormPrerempli />} />
{/* Routes for Updating */} {/* Routes for Updating */}
<Route path="/modifier-candidature/:id" element={<UpdateCandidacyForm />} /> <Route path="/modifier-candidature/:id" element={<UpdateCandidacyForm />} />
......
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { Navigate } from "react-router-dom"; import { useParams, useNavigate } from "react-router-dom";
const CandidacyFormPrerempli = () => { const CandidacyFormPrerempli = () => {
const [students, setStudents] = useState([]); const { stageId } = useParams(); // ✅ Get stageId from URL
const [stages, setStages] = useState([]); const navigate = useNavigate();
const [supervisors, setSupervisors] = useState([]);
// ✅ Initialise formData avec un studentId vide (sera mis à jour ensuite) const [supervisors, setSupervisors] = useState([]);
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
studentId: "", studentId: "",
stageId: "", stageId: stageId || "", // ✅ Pre-fill with stageId from URL
univSupervisorId: "", univSupervisorId: "",
}); });
/** 🔹 Charge le studentId à partir du localStorage */ /** 🔹 Load the logged-in student from localStorage */
useEffect(() => { useEffect(() => {
const storedUser = JSON.parse(localStorage.getItem("user")); const storedUser = JSON.parse(localStorage.getItem("user"));
if (storedUser && storedUser.username && storedUser.familyname) { if (storedUser && storedUser.id) {
setFormData((prevFormData) => ({ setFormData((prevFormData) => ({
...prevFormData, ...prevFormData,
studentId: storedUser.id || "", // ✅ Vérifie que l'ID existe studentId: storedUser.id, // ✅ Automatically set student ID
})); }));
} }
}, []); }, []);
/** 🔹 Charge les étudiants avec rôle ETUDIANT (si besoin) */ /** 🔹 Fetch available university supervisors */
useEffect(() => {
fetch("http://localhost:8080/api/students/with-role")
.then((res) => res.json())
.then((data) => setStudents(data))
.catch((err) => console.error("❌ Erreur lors du chargement des étudiants :", err));
}, []);
/** 🔹 Charge les stages */
useEffect(() => {
fetch("http://localhost:8080/api/stages")
.then((res) => res.json())
.then((data) => setStages(data));
}, []);
/** 🔹 Charge les superviseurs */
useEffect(() => { useEffect(() => {
fetch("http://localhost:8080/api/univsupervisors") fetch("http://localhost:8080/api/univsupervisors")
.then((res) => res.json()) .then((res) => res.json())
.then((data) => setSupervisors(data)); .then((data) => setSupervisors(data))
.catch((err) => console.error("❌ Error loading supervisors:", err));
}, []); }, []);
const handleChange = (e) => { const handleChange = (e) => {
...@@ -74,6 +59,7 @@ const CandidacyFormPrerempli = () => { ...@@ -74,6 +59,7 @@ const CandidacyFormPrerempli = () => {
.then((data) => { .then((data) => {
console.log("✅ Candidacy added successfully:", data); console.log("✅ Candidacy added successfully:", data);
alert("Candidature ajoutée avec succès !"); alert("Candidature ajoutée avec succès !");
navigate("/stages");
}) })
.catch((err) => console.error("❌ Error:", err.message)); .catch((err) => console.error("❌ Error:", err.message));
}; };
...@@ -82,7 +68,7 @@ const CandidacyFormPrerempli = () => { ...@@ -82,7 +68,7 @@ const CandidacyFormPrerempli = () => {
<div className="container mt-4"> <div className="container mt-4">
<h2>Ajouter ma Candidature</h2> <h2>Ajouter ma Candidature</h2>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
{/* ✅ Student (prérempli, non modifiable) */} {/* ✅ Student (pre-filled, non-editable) */}
<div className="mb-3"> <div className="mb-3">
<label className="form-label">Étudiant:</label> <label className="form-label">Étudiant:</label>
<input <input
...@@ -93,17 +79,15 @@ const CandidacyFormPrerempli = () => { ...@@ -93,17 +79,15 @@ const CandidacyFormPrerempli = () => {
/> />
</div> </div>
{/* Select Stage */} {/* ✅ Stage (pre-filled, non-editable) */}
<div className="mb-3"> <div className="mb-3">
<label className="form-label">Stage:</label> <label className="form-label">Stage:</label>
<select className="form-control" name="stageId" value={formData.stageId} onChange={handleChange} required> <input
<option value="">Sélectionnez un stage</option> type="text"
{stages.map((stage) => ( className="form-control"
<option key={stage.id} value={stage.id}> value={`Stage ID: ${formData.stageId}`}
{stage.name} - {stage.description} disabled
</option> />
))}
</select>
</div> </div>
{/* Select UnivSupervisor */} {/* Select UnivSupervisor */}
...@@ -126,8 +110,8 @@ const CandidacyFormPrerempli = () => { ...@@ -126,8 +110,8 @@ const CandidacyFormPrerempli = () => {
</div> </div>
<div className="d-flex gap-2"> <div className="d-flex gap-2">
<button type="submit" className="btn btn-primary">Ajouter Candidature</button> <button type="submit" className="btn btn-primary">📩 Postuler</button>
<button type="button" className="btn btn-secondary" onClick={() => Navigate("/candidatures")}>Annuler</button> <button type="button" className="btn btn-secondary" onClick={() => navigate("/stages")}>Annuler</button>
</div> </div>
</form> </form>
</div> </div>
......
...@@ -55,6 +55,7 @@ function CandidacyList() { ...@@ -55,6 +55,7 @@ function CandidacyList() {
<td>{candidacy.requestState}</td> <td>{candidacy.requestState}</td>
<td>{candidacy.acceptedState}</td> <td>{candidacy.acceptedState}</td>
<td> <td>
<button <button
className="btn btn-warning btn-sm me-2" className="btn btn-warning btn-sm me-2"
onClick={() => navigate(`/modifier-candidature/${candidacy.id}`)} onClick={() => navigate(`/modifier-candidature/${candidacy.id}`)}
......
...@@ -74,7 +74,7 @@ function Navbar() { ...@@ -74,7 +74,7 @@ function Navbar() {
)} )}
{/* 👨‍🎓 Étudiants */} {/* 👨‍🎓 Étudiants */}
{(hasRole("ROLE_ETUDIANT") || hasRole("ROLE_SUPERVISEUR") || hasRole("ROLE_ADMIN")) && ( {(hasRole("ROLE_ADMIN") || hasRole("ROLE_SUPERVISEUR") || hasRole("ROLE_ADMIN")) && (
<li className="nav-item dropdown"> <li className="nav-item dropdown">
<a className="nav-link dropdown-toggle" href="#" id="etudiantsDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> <a className="nav-link dropdown-toggle" href="#" id="etudiantsDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
👨‍🎓 Étudiants 👨‍🎓 Étudiants
...@@ -110,27 +110,26 @@ function Navbar() { ...@@ -110,27 +110,26 @@ function Navbar() {
)} )}
{/* 📝 Candidatures */} {/* 📝 Candidatures */}
{(hasRole("ROLE_ETUDIANT") || hasRole("ROLE_ADMIN") || hasRole("ROLE_SUPERVISEUR")) && ( {(hasRole("ROLE_ADMIN") || hasRole("ROLE_SUPERVISEUR")) && (
<li className="nav-item dropdown"> <li className="nav-item dropdown">
<a className="nav-link dropdown-toggle" href="#" id="candidaturesDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> <a className="nav-link dropdown-toggle" href="#" id="candidaturesDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
📝 Candidatures 📝 Candidatures
</a> </a>
<ul className="dropdown-menu" aria-labelledby="candidaturesDropdown"> <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> <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> <li><Link className="dropdown-item" to="/ajouter-candidature">➕ Ajouter une Candidature</Link></li>
{/* ALL Étudiants CAN apply */}
<li><Link className="dropdown-item" to="/ajouter-ma-candidature">➕ Ajouter ma candidature</Link></li>
</ul> </ul>
</li> </li>
)} )}
{/* 👨‍🏫 Superviseurs (Admin Only) */} {/* 👨‍🏫 Superviseurs (Admin Only) */}
{(hasRole("ROLE_ADMIN")||hasRole("ROLE_SUPERVISEUR")) && ( {hasRole("ROLE_ADMIN") && (
<li className="nav-item dropdown"> <li className="nav-item dropdown">
<a className="nav-link dropdown-toggle" href="#" id="superviseursDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> <a className="nav-link dropdown-toggle" href="#" id="superviseursDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
👨‍🏫 Superviseurs 👨‍🏫 Superviseurs
......
...@@ -4,23 +4,30 @@ import { Link, useNavigate } from "react-router-dom"; ...@@ -4,23 +4,30 @@ import { Link, useNavigate } from "react-router-dom";
function StageList() { function StageList() {
const [stages, setStages] = useState([]); const [stages, setStages] = useState([]);
const navigate = useNavigate(); const navigate = useNavigate();
const [roles, setRoles] = useState([]);
// Fetch Stages // Fetch Stages from Backend
useEffect(() => { useEffect(() => {
fetchStages(); fetchStages();
// ✅ Get roles from localStorage
const storedRoles = JSON.parse(localStorage.getItem("roles")) || [];
setRoles(storedRoles);
}, []); }, []);
const fetchStages = () => { const fetchStages = () => {
fetch("http://localhost:8080/api/stages") fetch("http://localhost:8080/api/stages")
.then((response) => response.json()) .then((response) => response.json())
.then((data) => { .then((data) => {
console.log("📌 Stages loaded:", data); // ✅ Debugging Log console.log("📌 Stages loaded:", data);
setStages(data); setStages(data);
}) })
.catch((error) => console.error("Error fetching stages:", error)); .catch((error) => console.error("Error fetching stages:", error));
}; };
// Handle Delete const isStudent = roles.includes("ROLE_ETUDIANT"); // ✅ Check if user is a student
// ✅ Handle Delete
const handleDelete = (id) => { const handleDelete = (id) => {
if (window.confirm("Voulez-vous vraiment supprimer ce stage ?")) { if (window.confirm("Voulez-vous vraiment supprimer ce stage ?")) {
fetch(`http://localhost:8080/api/stages/delete/${id}`, { fetch(`http://localhost:8080/api/stages/delete/${id}`, {
...@@ -34,7 +41,7 @@ function StageList() { ...@@ -34,7 +41,7 @@ function StageList() {
} }
}; };
// Handle Update // Handle Update
const handleUpdate = (id) => { const handleUpdate = (id) => {
navigate(`/modifier-stage/${id}`); navigate(`/modifier-stage/${id}`);
}; };
...@@ -42,11 +49,16 @@ function StageList() { ...@@ -42,11 +49,16 @@ function StageList() {
return ( return (
<div className="container mt-4"> <div className="container mt-4">
<h2 className="mb-4">Liste des Stages</h2> <h2 className="mb-4">Liste des Stages</h2>
<div>
<Link to="/ajouter-stage" className="btn btn-success mt-3"> {/* 🔹 Only Admin or Enterprise can add a stage */}
Ajouter un stage {!isStudent && (
</Link> <div>
</div> <Link to="/ajouter-stage" className="btn btn-success mt-3">
Ajouter un stage
</Link>
</div>
)}
<br /> <br />
<table className="table table-striped table-hover"> <table className="table table-striped table-hover">
...@@ -67,18 +79,31 @@ function StageList() { ...@@ -67,18 +79,31 @@ function StageList() {
<td>{stage.description}</td> <td>{stage.description}</td>
<td>{stage.enterprise?.name || "Non attribué"}</td> <td>{stage.enterprise?.name || "Non attribué"}</td>
<td> <td>
<button {/* 🔹 Show only "Candidater" for students */}
className="btn btn-warning btn-sm me-2" {isStudent ? (
onClick={() => handleUpdate(stage.id)} <button
> className="btn btn-primary btn-sm"
Modifier onClick={() => navigate(`/ajouter-ma-candidature/${stage.id}`)}
</button> >
<button Candidater
className="btn btn-danger btn-sm" </button>
onClick={() => handleDelete(stage.id)} ) : (
> <>
Supprimer {/* 🔹 Non-students can modify & delete */}
</button> <button
className="btn btn-warning btn-sm me-2"
onClick={() => handleUpdate(stage.id)}
>
Modifier
</button>
<button
className="btn btn-danger btn-sm"
onClick={() => handleDelete(stage.id)}
>
Supprimer
</button>
</>
)}
</td> </td>
</tr> </tr>
))} ))}
......
...@@ -4,6 +4,7 @@ import { Link, useNavigate } from "react-router-dom"; ...@@ -4,6 +4,7 @@ import { Link, useNavigate } from "react-router-dom";
function StudentList() { function StudentList() {
const [students, setStudents] = useState([]); const [students, setStudents] = useState([]);
const navigate = useNavigate(); const navigate = useNavigate();
// Fetch Students // Fetch Students
useEffect(() => { useEffect(() => {
...@@ -20,7 +21,7 @@ function StudentList() { ...@@ -20,7 +21,7 @@ function StudentList() {
// Handle Delete // Handle Delete
const handleDelete = (id) => { const handleDelete = (id) => {
if (window.confirm("Voulez-vous vraiment supprimer cet étudiant ?")) { if (window.confirm("Voulez-vous vraiment supprimer cet étudiant ?")) {
fetch(`http://localhost:8080/api/students/${id}`, { fetch(`http://localhost:8080/api/students/delete/${id}`, {
method: "DELETE", method: "DELETE",
}) })
.then(() => { .then(() => {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment