diff --git a/src/App.js b/src/App.js index 311dfa22942594d3a662b34701b21c61799b32a4..982aba5576c9badf9aa3627e129115edeb601ac3 100644 --- a/src/App.js +++ b/src/App.js @@ -45,7 +45,8 @@ function App() { <Route path="/ajouter-etudiant" element={<StudentForm />} /> <Route path="/ajouter-candidature" element={<CandidacyForm />} /> <Route path="/ajouter-univsuperviseur" element={<UnivSupervisorForm />} /> - <Route path="/ajouter-ma-candidature" element={<CandidacyFormPrerempli />} /> + <Route path="/ajouter-ma-candidature/:stageId" element={<CandidacyFormPrerempli />} /> + {/* Routes for Updating */} <Route path="/modifier-candidature/:id" element={<UpdateCandidacyForm />} /> diff --git a/src/components/Candidatures/CandidacyFormPrerempli.jsx b/src/components/Candidatures/CandidacyFormPrerempli.jsx index c0a2e2b42ef0132198d22a0b8381fe32564f10f0..a306359e559a731bba740499a8575d7e5d259e1f 100644 --- a/src/components/Candidatures/CandidacyFormPrerempli.jsx +++ b/src/components/Candidatures/CandidacyFormPrerempli.jsx @@ -1,49 +1,34 @@ import React, { useState, useEffect } from "react"; -import { Navigate } from "react-router-dom"; +import { useParams, useNavigate } from "react-router-dom"; const CandidacyFormPrerempli = () => { - const [students, setStudents] = useState([]); - const [stages, setStages] = useState([]); - const [supervisors, setSupervisors] = useState([]); + const { stageId } = useParams(); // ✅ Get stageId from URL + const navigate = useNavigate(); - // ✅ Initialise formData avec un studentId vide (sera mis à jour ensuite) + const [supervisors, setSupervisors] = useState([]); const [formData, setFormData] = useState({ studentId: "", - stageId: "", + stageId: stageId || "", // ✅ Pre-fill with stageId from URL univSupervisorId: "", }); - /** 🔹 Charge le studentId à partir du localStorage */ + /** 🔹 Load the logged-in student from localStorage */ useEffect(() => { const storedUser = JSON.parse(localStorage.getItem("user")); - if (storedUser && storedUser.username && storedUser.familyname) { + if (storedUser && storedUser.id) { setFormData((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) */ - 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 */ + /** 🔹 Fetch available university supervisors */ useEffect(() => { fetch("http://localhost:8080/api/univsupervisors") .then((res) => res.json()) - .then((data) => setSupervisors(data)); + .then((data) => setSupervisors(data)) + .catch((err) => console.error("❌ Error loading supervisors:", err)); }, []); const handleChange = (e) => { @@ -74,6 +59,7 @@ const CandidacyFormPrerempli = () => { .then((data) => { console.log("✅ Candidacy added successfully:", data); alert("Candidature ajoutée avec succès !"); + navigate("/stages"); }) .catch((err) => console.error("❌ Error:", err.message)); }; @@ -82,7 +68,7 @@ const CandidacyFormPrerempli = () => { <div className="container mt-4"> <h2>Ajouter ma Candidature</h2> <form onSubmit={handleSubmit}> - {/* ✅ Student (prérempli, non modifiable) */} + {/* ✅ Student (pre-filled, non-editable) */} <div className="mb-3"> <label className="form-label">Étudiant:</label> <input @@ -93,17 +79,15 @@ const CandidacyFormPrerempli = () => { /> </div> - {/* Select Stage */} + {/* ✅ Stage (pre-filled, non-editable) */} <div className="mb-3"> <label className="form-label">Stage:</label> - <select className="form-control" name="stageId" value={formData.stageId} onChange={handleChange} required> - <option value="">Sélectionnez un stage</option> - {stages.map((stage) => ( - <option key={stage.id} value={stage.id}> - {stage.name} - {stage.description} - </option> - ))} - </select> + <input + type="text" + className="form-control" + value={`Stage ID: ${formData.stageId}`} + disabled + /> </div> {/* Select UnivSupervisor */} @@ -126,8 +110,8 @@ const CandidacyFormPrerempli = () => { </div> <div className="d-flex gap-2"> - <button type="submit" className="btn btn-primary">Ajouter Candidature</button> - <button type="button" className="btn btn-secondary" onClick={() => Navigate("/candidatures")}>Annuler</button> + <button type="submit" className="btn btn-primary">📩 Postuler</button> + <button type="button" className="btn btn-secondary" onClick={() => navigate("/stages")}>Annuler</button> </div> </form> </div> diff --git a/src/components/Candidatures/CandidacyList.jsx b/src/components/Candidatures/CandidacyList.jsx index 1e39ddb35f472ee1d2ebb469cab4ad28e86d3e6c..069bbfb415d74b8ff531dd3d75930398213e072f 100644 --- a/src/components/Candidatures/CandidacyList.jsx +++ b/src/components/Candidatures/CandidacyList.jsx @@ -55,6 +55,7 @@ function CandidacyList() { <td>{candidacy.requestState}</td> <td>{candidacy.acceptedState}</td> <td> + <button className="btn btn-warning btn-sm me-2" onClick={() => navigate(`/modifier-candidature/${candidacy.id}`)} diff --git a/src/components/Navbar.jsx b/src/components/Navbar.jsx index 4bfa1576a927a3186a17276d92394dd187f8d19c..166f00702875d7d05e38c4a9ee19582a126a569c 100644 --- a/src/components/Navbar.jsx +++ b/src/components/Navbar.jsx @@ -74,7 +74,7 @@ function Navbar() { )} {/* 👨🎓 Étudiants */} - {(hasRole("ROLE_ETUDIANT") || hasRole("ROLE_SUPERVISEUR") || hasRole("ROLE_ADMIN")) && ( + {(hasRole("ROLE_ADMIN") || 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 @@ -110,27 +110,26 @@ function Navbar() { )} {/* 📝 Candidatures */} - {(hasRole("ROLE_ETUDIANT") || hasRole("ROLE_ADMIN") || hasRole("ROLE_SUPERVISEUR")) && ( + {(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> - {/* ALL Étudiants CAN apply */} - <li><Link className="dropdown-item" to="/ajouter-ma-candidature">➕ Ajouter ma candidature</Link></li> + </ul> </li> )} {/* 👨🏫 Superviseurs (Admin Only) */} - {(hasRole("ROLE_ADMIN")||hasRole("ROLE_SUPERVISEUR")) && ( + {hasRole("ROLE_ADMIN") && ( <li className="nav-item dropdown"> <a className="nav-link dropdown-toggle" href="#" id="superviseursDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> 👨🏫 Superviseurs diff --git a/src/components/Stages/StageList.jsx b/src/components/Stages/StageList.jsx index 4572bdb0ec7d70ba91d01eaa2919398609fffadc..ba48696f2ac80fe335bacbb922900bc32a892ba7 100644 --- a/src/components/Stages/StageList.jsx +++ b/src/components/Stages/StageList.jsx @@ -4,23 +4,30 @@ import { Link, useNavigate } from "react-router-dom"; function StageList() { const [stages, setStages] = useState([]); const navigate = useNavigate(); + const [roles, setRoles] = useState([]); - // Fetch Stages + // ✅ Fetch Stages from Backend useEffect(() => { fetchStages(); + + // ✅ Get roles from localStorage + const storedRoles = JSON.parse(localStorage.getItem("roles")) || []; + setRoles(storedRoles); }, []); const fetchStages = () => { fetch("http://localhost:8080/api/stages") - .then((response) => response.json()) - .then((data) => { - console.log("📌 Stages loaded:", data); // ✅ Debugging Log - setStages(data); - }) - .catch((error) => console.error("Error fetching stages:", error)); + .then((response) => response.json()) + .then((data) => { + console.log("📌 Stages loaded:", data); + setStages(data); + }) + .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) => { if (window.confirm("Voulez-vous vraiment supprimer ce stage ?")) { fetch(`http://localhost:8080/api/stages/delete/${id}`, { @@ -34,7 +41,7 @@ function StageList() { } }; - // Handle Update + // ✅ Handle Update const handleUpdate = (id) => { navigate(`/modifier-stage/${id}`); }; @@ -42,11 +49,16 @@ function StageList() { return ( <div className="container mt-4"> <h2 className="mb-4">Liste des Stages</h2> - <div> - <Link to="/ajouter-stage" className="btn btn-success mt-3"> - Ajouter un stage - </Link> - </div> + + {/* 🔹 Only Admin or Enterprise can add a stage */} + {!isStudent && ( + <div> + <Link to="/ajouter-stage" className="btn btn-success mt-3"> + Ajouter un stage + </Link> + </div> + )} + <br /> <table className="table table-striped table-hover"> @@ -67,18 +79,31 @@ function StageList() { <td>{stage.description}</td> <td>{stage.enterprise?.name || "Non attribué"}</td> <td> - <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> + {/* 🔹 Show only "Candidater" for students */} + {isStudent ? ( + <button + className="btn btn-primary btn-sm" + onClick={() => navigate(`/ajouter-ma-candidature/${stage.id}`)} + > + Candidater + </button> + ) : ( + <> + {/* 🔹 Non-students can modify & delete */} + <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> </tr> ))} diff --git a/src/components/Students/StudentList.jsx b/src/components/Students/StudentList.jsx index 80266ec3034f00945d6c22c911b67883f640e09b..29fd7db65864069d3cecfcf6bea285f2e1a96053 100644 --- a/src/components/Students/StudentList.jsx +++ b/src/components/Students/StudentList.jsx @@ -4,6 +4,7 @@ import { Link, useNavigate } from "react-router-dom"; function StudentList() { const [students, setStudents] = useState([]); const navigate = useNavigate(); + // Fetch Students useEffect(() => { @@ -20,7 +21,7 @@ function StudentList() { // Handle Delete const handleDelete = (id) => { 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", }) .then(() => {