diff --git a/src/App.js b/src/App.js index d40c68750439d282098bfafa9539b53f883430ad..299b45eb803e330557e233c1a746c653bdd32f76 100644 --- a/src/App.js +++ b/src/App.js @@ -1,25 +1,27 @@ 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"; function App() { return ( @@ -32,6 +34,9 @@ function App() { <Route path="/entreprises" element={<EnterpriseList />} /> <Route path="/candidatures" element={<CandidacyList />} /> <Route path="/superviseurs" element={<UnivSupervisorList />} /> + <Route path="/login" element={<Login />} /> + <Route path="/logout" element={<Logout />} /> + {/* Routes for Forms */} <Route path="/ajouter-stage" element={<StageForm />} /> @@ -44,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 98% rename from src/components/CandidacyForm.jsx rename to src/components/Candidatures/CandidacyForm.jsx index 6a7bb6a84ca71ff2669a878235e65a3ee0a9d4b1..79953db0a5d5dc12dad1e33909e51b5cdedfdc0b 100644 --- a/src/components/CandidacyForm.jsx +++ b/src/components/Candidatures/CandidacyForm.jsx @@ -33,7 +33,7 @@ const CandidacyForm = () => { const handleSubmit = (e) => { e.preventDefault(); - fetch("http://localhost:8080/api/candidacies", { + fetch("http://localhost:8080/api/candidacies/add", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ diff --git a/src/components/CandidacyList.jsx b/src/components/Candidatures/CandidacyList.jsx similarity index 96% rename from src/components/CandidacyList.jsx rename to src/components/Candidatures/CandidacyList.jsx index cfc2733dc1b625606b67c0ea8a85e0fe64569e13..1e39ddb35f472ee1d2ebb469cab4ad28e86d3e6c 100644 --- a/src/components/CandidacyList.jsx +++ b/src/components/Candidatures/CandidacyList.jsx @@ -15,7 +15,7 @@ function CandidacyList() { // Function to delete candidacy const handleDelete = (id) => { if (window.confirm("Êtes-vous sûr de vouloir supprimer cette candidature ?")) { - fetch(`http://localhost:8080/api/candidacies/${id}`, { method: "DELETE" }) + fetch(`http://localhost:8080/api/candidacies/delete/${id}`, { method: "DELETE" }) .then(() => { alert("Candidature supprimée avec succès !"); setCandidacies(candidacies.filter((candidacy) => candidacy.id !== id)); 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 96% rename from src/components/EnterpriseForm.jsx rename to src/components/Entreprises/EnterpriseForm.jsx index 08249a253093980f0af14edf836a722b213c8105..01a66f43f6d2074f9d0812029e87b2afefef2731 100644 --- a/src/components/EnterpriseForm.jsx +++ b/src/components/Entreprises/EnterpriseForm.jsx @@ -10,7 +10,7 @@ function EnterpriseForm() { const newEnterprise = { name, address }; - fetch("http://localhost:8080/api/enterprises", { + fetch("http://localhost:8080/api/enterprises/add", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(newEnterprise) diff --git a/src/components/EnterpriseList.jsx b/src/components/Entreprises/EnterpriseList.jsx similarity index 97% rename from src/components/EnterpriseList.jsx rename to src/components/Entreprises/EnterpriseList.jsx index 3546fb2ed6b681c3b0e734a039a7f56b4964f6d2..6bcdfcb1bff16c0d3c52360f27f20dec0d4e0af2 100644 --- a/src/components/EnterpriseList.jsx +++ b/src/components/Entreprises/EnterpriseList.jsx @@ -20,7 +20,7 @@ function EnterpriseList() { // Handle Delete const handleDelete = (id) => { if (window.confirm("Voulez-vous vraiment supprimer cette entreprise ?")) { - fetch(`http://localhost:8080/api/enterprises/${id}`, { + fetch(`http://localhost:8080/api/enterprises/delete/${id}`, { method: "DELETE", }) .then(() => { 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 new file mode 100644 index 0000000000000000000000000000000000000000..39b181ec792dbf287d32aa47e1fbf1a436726848 --- /dev/null +++ b/src/components/Login.jsx @@ -0,0 +1,80 @@ +import { useState, useEffect } from "react"; +import { useNavigate } from "react-router-dom"; + +const Login = () => { + const [username, setUsername] = useState(""); + const [password, setPassword] = useState(""); + const [error, setError] = useState(""); + const navigate = useNavigate(); + + useEffect(() => { + const token = localStorage.getItem("token"); + if (token) { + navigate("/"); // Redirect if already logged in + } + }, [navigate]); + + const handleLogin = async (e) => { + 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 }), + }); + + if (!response.ok) { + throw new Error("Invalid credentials"); + } + + const data = await response.json(); // ✅ Parse JSON properly + console.log("✅ Login successful!", data); + + 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"); + } + }; + + + return ( + <div style={{ textAlign: "center", marginTop: "50px" }}> + <h2>Login</h2> + <form onSubmit={handleLogin}> + <div> + <input + type="text" + placeholder="Username" + value={username} + onChange={(e) => setUsername(e.target.value)} + required + /> + </div> + <div> + <input + type="password" + placeholder="Password" + value={password} + onChange={(e) => setPassword(e.target.value)} + required + /> + </div> + {error && <p style={{ color: "red" }}>{error}</p>} + <button type="submit">Login</button> + </form> + </div> + ); +}; + +export default Login; diff --git a/src/components/Logout.jsx b/src/components/Logout.jsx new file mode 100644 index 0000000000000000000000000000000000000000..27924f2a2441c1544a8d6ea5e162eaf23aaf253c --- /dev/null +++ b/src/components/Logout.jsx @@ -0,0 +1,40 @@ +import { useEffect } from "react"; +import { useNavigate } from "react-router-dom"; + +const Logout = () => { + const navigate = useNavigate(); + + useEffect(() => { + const logoutUser = async () => { + try { + const response = await fetch("http://localhost:8080/api/auth/logout", { + method: "POST", + credentials: "include", // Ensures cookies are sent and removed + }); + + if (response.ok) { + console.log("✅ Logout successful"); + } else { + console.error("❌ Logout request failed:", response.status); + } + } catch (error) { + console.error("❌ Error during logout:", error); + } + + // ✅ 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"); + }; + + logoutUser(); + }, [navigate]); + + return <h2>Logging out... Redirecting</h2>; +}; + +export default Logout; diff --git a/src/components/Navbar.jsx b/src/components/Navbar.jsx index 9f0dbc61405d3158b4a25893334976d930d5eb49..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"> @@ -19,38 +39,98 @@ function Navbar() { </button> <div className="collapse navbar-collapse" id="navbarNav"> <ul className="navbar-nav ms-auto"> + + {/* 📚 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 */} + {(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> + + {/* BUT ONLY ADMIN CAN ADD */} + {hasRole("ROLE_ADMIN") && ( + <> + + <li><Link className="dropdown-item" to="/ajouter-etudiant">➕ Ajouter/Modifier un Étudiant</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> + )} + + {/* 🔑 Authentification */} <li className="nav-item"> <Link className="nav-link" to="/login">🔑 Login</Link> </li> <li className="nav-item"> - <Link className="nav-link" to="/stages">📚 Stages</Link> - </li> - <li className="nav-item"> - <Link className="nav-link" to="/etudiants">👨🎓 Étudiants</Link> - </li> - <li className="nav-item"> - <Link className="nav-link" to="/entreprises">🏢 Entreprises</Link> - </li> - <li className="nav-item"> - <Link className="nav-link" to="/candidatures">📝 Candidatures</Link> - </li> - <li className="nav-item"> - <Link className="nav-link" to="/superviseurs">👨🏫 Superviseurs</Link> + <Link className="nav-link" to="/logout">🔓 Logout</Link> </li> - {/* Dropdown for adding new entries */} - <li className="nav-item dropdown"> - <a className="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> - ➕ Ajouter - </a> - <ul className="dropdown-menu" aria-labelledby="navbarDropdown"> - <li><Link className="dropdown-item" to="/ajouter-stage">Ajouter Stage</Link></li> - <li><Link className="dropdown-item" to="/ajouter-entreprise">Ajouter Entreprise</Link></li> - <li><Link className="dropdown-item" to="/ajouter-etudiant">Ajouter Étudiant</Link></li> - <li><Link className="dropdown-item" to="/ajouter-candidature">Ajouter Candidature</Link></li> - <li><Link className="dropdown-item" to="/ajouter-univsuperviseur">Ajouter Superviseur</Link></li> - </ul> - </li> </ul> </div> </div> diff --git a/src/components/StageForm.jsx b/src/components/StageForm.jsx deleted file mode 100644 index 07f669f9e0ab538ba39fd675a6bf0944fe8074df..0000000000000000000000000000000000000000 --- a/src/components/StageForm.jsx +++ /dev/null @@ -1,76 +0,0 @@ -import React, { useState, useEffect } from "react"; -import { Navigate } from "react-router-dom"; - -function StageForm() { - const [name, setName] = useState(""); - const [description, setDescription] = useState(""); - const [enterpriseId, setEnterpriseId] = useState(""); - const [enterprises, setEnterprises] = useState([]); - - useEffect(() => { - fetch("http://localhost:8080/api/enterprises") - .then((res) => res.json()) - .then((data) => setEnterprises(data)) - .catch((err) => console.error("Error fetching enterprises:", err)); - }, []); - - const handleSubmit = (e) => { - e.preventDefault(); - - const newStage = { - name, - description, - enterprise: { id: enterpriseId } - }; - - fetch("http://localhost:8080/api/stages", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(newStage) - }) - .then((res) => res.json()) - .then(() => { - alert("Stage added successfully!"); - setName(""); - setDescription(""); - setEnterpriseId(""); - }) - .catch((err) => console.error("Error adding stage:", err)); - }; - // Handle cancel button - const handleCancel = () => { - Navigate("/stages"); // Redirect back to candidacy list - }; - - return ( - <div className="container mt-4"> - <h2>Ajouter un Stage</h2> - <form onSubmit={handleSubmit}> - <div className="mb-3"> - <label className="form-label">Nom du Stage</label> - <input type="text" className="form-control" value={name} onChange={(e) => setName(e.target.value)} required /> - </div> - <div className="mb-3"> - <label className="form-label">Description</label> - <input type="text" className="form-control" value={description} onChange={(e) => setDescription(e.target.value)} required /> - </div> - <div className="mb-3"> - <label className="form-label">Entreprise</label> - <select className="form-select" value={enterpriseId} onChange={(e) => setEnterpriseId(e.target.value)} required> - <option value="">Sélectionner une entreprise</option> - {enterprises.map((enterprise) => ( - <option key={enterprise.id} value={enterprise.id}>{enterprise.name}</option> - ))} - </select> - </div> - <div className="d-flex gap-2"> - <button type="submit" className="btn btn-primary"> - Ajouter - </button> - <button type="button" className="btn btn-secondary" onClick={handleCancel}>Annuler</button> - </div> </form> - </div> - ); -} - -export default StageForm; diff --git a/src/components/Stages/StageForm.jsx b/src/components/Stages/StageForm.jsx new file mode 100644 index 0000000000000000000000000000000000000000..ce4841c449394c1c94556eedc157ef246b2c16bc --- /dev/null +++ b/src/components/Stages/StageForm.jsx @@ -0,0 +1,131 @@ +import React, { useState, useEffect } from "react"; +import { useNavigate } from "react-router-dom"; + +function StageForm() { + const [title, setTitle] = useState(""); + const [description, setDescription] = useState(""); + const [enterpriseId, setEnterpriseId] = useState(""); // Stores selected enterprise ID + const [enterprises, setEnterprises] = useState([]); // List of enterprises for dropdown + const navigate = useNavigate(); + + /** Fetch the list of enterprises from the backend **/ + useEffect(() => { + fetch("http://localhost:8080/api/enterprises", { + method: "GET", + headers: { "Content-Type": "application/json" }, + credentials: "include", + }) + .then((res) => res.json()) + .then((data) => { + console.log("📌 Enterprises loaded:", data); + setEnterprises(data); + }) + .catch((err) => console.error("❌ Erreur lors du chargement des entreprises :", err)); + }, []); + + /** Handle form submission **/ + const handleSubmit = (e) => { + e.preventDefault(); + + // Ensure enterpriseId is selected + if (!enterpriseId || enterpriseId === "none") { + alert("❌ Veuillez sélectionner une entreprise !"); + return; + } + + const newStage = { + title, + description, + enterprise: { id: parseInt(enterpriseId, 10) }, // Send enterprise as an object + }; + + console.log("📌 Sending stage data:", newStage); + + fetch("http://localhost:8080/api/stages/add", { + method: "POST", + headers: { "Content-Type": "application/json" }, + credentials: "include", + body: JSON.stringify(newStage), // Ensure correct format + }) + .then((res) => { + console.log("📌 Response status:", res.status); + + if (!res.ok) { + return res.text().then((text) => { + console.error("❌ Backend Error (text):", text); + throw new Error(text || "Erreur inconnue"); + }); + } + + return res.json(); + }) + .then((data) => { + console.log("✅ Stage added successfully:", data); + alert("Stage ajouté avec succès !"); + setTitle(""); + setDescription(""); + setEnterpriseId(""); // Reset dropdown + navigate("/stages"); + }) + .catch((err) => console.error("❌ Erreur lors de l'ajout du stage :", err.message)); + }; + + + /** Handle cancel button **/ + const handleCancel = () => { + navigate("/stages"); // Redirect back to stages list + }; + + return ( + <div className="container mt-4"> + <h2>Ajouter un Stage</h2> + <form onSubmit={handleSubmit}> + <div className="mb-3"> + <label className="form-label">Titre du Stage</label> + <input + type="text" + className="form-control" + value={title} + onChange={(e) => setTitle(e.target.value)} + required + /> + </div> + <div className="mb-3"> + <label className="form-label">Description</label> + <textarea + className="form-control" + value={description} + onChange={(e) => setDescription(e.target.value)} + required + ></textarea> + </div> + <div className="mb-3"> + <label className="form-label">Entreprise</label> + <select + className="form-control" + value={enterpriseId} + onChange={(e) => setEnterpriseId(e.target.value)} + required + > + <option value="none">Sélectionnez une entreprise</option> + {enterprises.map((enterprise) => ( + <option key={enterprise.id} value={enterprise.id}> + {enterprise.name} + </option> + ))} + </select> + </div> + <div className="d-flex gap-2"> + <button type="submit" className="btn btn-primary"> + Ajouter + </button> + <button type="button" className="btn btn-secondary" onClick={handleCancel}> + Annuler + </button> + </div> + </form> + </div> + ); +} + +export default StageForm; 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 83% rename from src/components/StudentForm.jsx rename to src/components/Students/StudentForm.jsx index 1332107a1b3f49ea39a7b2885866799b1309af55..b6977f150232fb479fab59bd9d7a0a4c4e6594ba 100644 --- a/src/components/StudentForm.jsx +++ b/src/components/Students/StudentForm.jsx @@ -1,16 +1,18 @@ import React, { useState } from "react"; -import { Navigate } from "react-router-dom"; +import { useNavigate } from "react-router-dom"; function StudentForm() { const [firstname, setFirstname] = useState(""); const [lastname, setLastname] = useState(""); + const navigate = useNavigate(); // Correct use of useNavigate + const handleSubmit = (e) => { e.preventDefault(); const newStudent = { firstname, lastname }; - fetch("http://localhost:8080/api/students", { + fetch("http://localhost:8080/api/students/add", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(newStudent) @@ -23,9 +25,9 @@ function StudentForm() { }) .catch((err) => console.error("Erreur lors de l'ajout de l'étudiant :", err)); }; - // Handle cancel button - const handleCancel = () => { - Navigate("/etudiants"); // Redirect back to candidacy list + // Handle cancel button correctly + const handleCancel = () => { + navigate("/etudiants"); // Redirect back to student list }; return ( 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 96% rename from src/components/UnivSupervisorForm.jsx rename to src/components/Supervisors/UnivSupervisorForm.jsx index 03c2fab8a5b4dc1f61c692ba47fab668438994c6..eb7875799f2d496284725638410eee95b0b8ee52 100644 --- a/src/components/UnivSupervisorForm.jsx +++ b/src/components/Supervisors/UnivSupervisorForm.jsx @@ -9,7 +9,7 @@ function UnivSupervisorForm() { const newSupervisor = { name }; - fetch("http://localhost:8080/api/univsupervisors", { + fetch("http://localhost:8080/api/univsupervisors/add", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(newSupervisor), 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 96% rename from src/components/UpdateUnivSupervisorForm.jsx rename to src/components/Supervisors/UpdateUnivSupervisorForm.jsx index f86fb81d0da69948aa75368f4629112ef2d42ee3..20df9cca1dd5876bb146d105891da31c7b003d24 100644 --- a/src/components/UpdateUnivSupervisorForm.jsx +++ b/src/components/Supervisors/UpdateUnivSupervisorForm.jsx @@ -22,7 +22,7 @@ function UpdateUnivSupervisorForm() { const handleSubmit = (e) => { e.preventDefault(); - fetch(`http://localhost:8080/api/univsupervisors/${id}`, { + fetch(`http://localhost:8080/api/univsupervisors/update/${id}`, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify(supervisor),