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

ajout de roles

parent 1aaee02b
No related branches found
No related tags found
1 merge request!5Master
......@@ -20,6 +20,8 @@ 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 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 />} />
......
......@@ -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({
......
......@@ -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));
......
......@@ -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)
......
......@@ -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(() => {
......
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.text(); // Adjust this if backend returns JSON
console.log("✅ Login successful!", data);
localStorage.setItem("token", "dummy-token"); // Store token (if applicable)
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;
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 auth details and redirect
localStorage.removeItem("token");
localStorage.removeItem("user");
navigate("/login");
};
logoutUser();
}, [navigate]);
return <h2>Logging out... Redirecting</h2>;
};
export default Logout;
......@@ -19,38 +19,70 @@ function Navbar() {
</button>
<div className="collapse navbar-collapse" id="navbarNav">
<ul className="navbar-nav ms-auto">
<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>
{/* 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>
<li className="nav-item">
<Link className="nav-link" to="/entreprises">🏢 Entreprises</Link>
{/* É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>
<li className="nav-item">
<Link className="nav-link" to="/candidatures">📝 Candidatures</Link>
{/* 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>
<li className="nav-item">
<Link className="nav-link" to="/superviseurs">👨‍🏫 Superviseurs</Link>
{/* 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>
{/* Dropdown for adding new entries */}
{/* Superviseurs Dropdown */}
<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 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="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 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>
{/* Authentication Links */}
<li className="nav-item">
<Link className="nav-link" to="/login">🔑 Login</Link>
</li>
<li className="nav-item">
<Link className="nav-link" to="/logout">🔓 Logout</Link>
</li>
</ul>
</div>
</div>
......
import React, { useState, useEffect } from "react";
import { Navigate } from "react-router-dom";
import { useNavigate } from "react-router-dom";
function StageForm() {
const [name, setName] = useState("");
const [title, setTitle] = useState("");
const [description, setDescription] = useState("");
const [enterpriseId, setEnterpriseId] = useState("");
const [enterprises, setEnterprises] = 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")
fetch("http://localhost:8080/api/enterprises", {
method: "GET",
headers: { "Content-Type": "application/json" },
credentials: "include",
})
.then((res) => res.json())
.then((data) => setEnterprises(data))
.catch((err) => console.error("Error fetching enterprises:", err));
.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 = {
name,
title,
description,
enterprise: { id: enterpriseId }
enterprise: { id: parseInt(enterpriseId, 10) }, // Send enterprise as an object
};
fetch("http://localhost:8080/api/stages", {
console.log("📌 Sending stage data:", newStage);
fetch("http://localhost:8080/api/stages/add", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(newStage)
credentials: "include",
body: JSON.stringify(newStage), // Ensure correct format
})
.then((res) => res.json())
.then(() => {
alert("Stage added successfully!");
setName("");
.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("");
setEnterpriseId(""); // Reset dropdown
navigate("/stages");
})
.catch((err) => console.error("Error adding stage:", err));
.catch((err) => console.error("Erreur lors de l'ajout du stage :", err.message));
};
// Handle cancel button
const handleCancel = () => {
Navigate("/stages"); // Redirect back to candidacy list
/** Handle cancel button **/
const handleCancel = () => {
navigate("/stages"); // Redirect back to stages list
};
return (
......@@ -47,28 +81,49 @@ function StageForm() {
<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 />
<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>
<input type="text" className="form-control" value={description} onChange={(e) => setDescription(e.target.value)} required />
<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-select" value={enterpriseId} onChange={(e) => setEnterpriseId(e.target.value)} required>
<option value="">Sélectionner une entreprise</option>
<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>
<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">
<button type="submit" className="btn btn-primary">
Ajouter
</button>
<button type="button" className="btn btn-secondary" onClick={handleCancel}>Annuler</button>
</div> </form>
</button>
<button type="button" className="btn btn-secondary" onClick={handleCancel}>
Annuler
</button>
</div>
</form>
</div>
);
}
......
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 (
......
......@@ -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),
......
......@@ -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),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment