diff --git a/src/App.js b/src/App.js index 54121deb615845189c5ced145e3c404c5ecf89ea..2fe0fce98378cb9e25a62d627a0a0a8c57065054 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,5 @@ import React from "react"; -import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; +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"; @@ -7,17 +7,37 @@ import StudentList from "./components/StudentList"; import CandidacyList from "./components/CandidacyList"; import UnivSupervisorList from "./components/UnivSupervisorList"; +// Import the new 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.jsx"; + function App() { return ( <Router> <Navbar /> - <Routes> - <Route path="/stages" element={<StageList />} /> - <Route path="/entreprises" element={<EnterpriseList />} /> - <Route path="/etudiants" element={<StudentList />} /> - <Route path="/candidatures" element={<CandidacyList />} /> - <Route path="/superviseurs" element={<UnivSupervisorList />} /> - </Routes> + <div className="container mt-4"> + <Routes> + <Route path="/stages" element={<StageList />} /> + <Route path="/etudiants" element={<StudentList />} /> + <Route path="/entreprises" element={<EnterpriseList />} /> + <Route path="/candidatures" element={<CandidacyList />} /> + <Route path="/superviseurs" element={<UnivSupervisorList />} /> + + {/* Routes for Forms */} + <Route path="/ajouter-stage" element={<StageForm />} /> + <Route path="/ajouter-entreprise" element={<EnterpriseForm />} /> + <Route path="/ajouter-etudiant" element={<StudentForm />} /> + <Route path="/ajouter-candidature" element={<CandidacyForm />} /> + <Route path="/ajouter-univsuperviseur" element={<UnivSupervisorForm />} /> + + + {/* Default Route */} + <Route path="/" element={<h2>Bienvenue sur l'Application de Gestion des Stages</h2>} /> + </Routes> + </div> </Router> ); } diff --git a/src/components/CandidacyForm.jsx b/src/components/CandidacyForm.jsx new file mode 100644 index 0000000000000000000000000000000000000000..80fd32fb34e3783f89c11efab36738d77dd452d4 --- /dev/null +++ b/src/components/CandidacyForm.jsx @@ -0,0 +1,122 @@ +import React, { useState, useEffect } from "react"; + +const CandidacyForm = () => { + const [students, setStudents] = useState([]); + const [stages, setStages] = useState([]); + const [supervisors, setSupervisors] = useState([]); // Load supervisors + + const [formData, setFormData] = useState({ + studentId: "", + stageId: "", + univSupervisorId: "", // Add supervisor field + }); + + useEffect(() => { + fetch("http://localhost:8080/api/students") + .then((res) => res.json()) + .then((data) => setStudents(data)); + + fetch("http://localhost:8080/api/stages") + .then((res) => res.json()) + .then((data) => setStages(data)); + + fetch("http://localhost:8080/api/univsupervisors") // Load supervisors + .then((res) => res.json()) + .then((data) => setSupervisors(data)); + }, []); + + const handleChange = (e) => { + setFormData({ ...formData, [e.target.name]: e.target.value }); + }; + + const handleSubmit = (e) => { + e.preventDefault(); + + fetch("http://localhost:8080/api/candidacies", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + student: { id: formData.studentId }, + stage: { id: formData.stageId }, + univSupervisor: { id: formData.univSupervisorId }, // Include supervisor + }), + }) + .then((res) => res.json()) + .then((data) => { + console.log("Candidacy added:", data); + alert("Candidacy added successfully!"); + }) + .catch((err) => console.error("Error:", err)); + }; + + return ( + <div className="container mt-4"> + <h2>Ajouter une Candidature</h2> + <form onSubmit={handleSubmit}> + {/* Select Student */} + <div className="mb-3"> + <label className="form-label">Étudiant:</label> + <select + className="form-control" + name="studentId" + value={formData.studentId} + onChange={handleChange} + required + > + <option value="">Sélectionnez un étudiant</option> + {students.map((student) => ( + <option key={student.id} value={student.id}> + {student.firstname} {student.lastname} + </option> + ))} + </select> + </div> + + {/* Select Stage */} + <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> + </div> + + {/* Select UnivSupervisor */} + <div className="mb-3"> + <label className="form-label">Superviseur Universitaire:</label> + <select + className="form-control" + name="univSupervisorId" + value={formData.univSupervisorId} + onChange={handleChange} + required + > + <option value="">Sélectionnez un superviseur</option> + {supervisors.map((supervisor) => ( + <option key={supervisor.id} value={supervisor.id}> + {supervisor.name} + </option> + ))} + </select> + </div> + + {/* Submit Button */} + <button type="submit" className="btn btn-primary"> + Ajouter Candidature + </button> + </form> + </div> + ); +}; + +export default CandidacyForm; diff --git a/src/components/CandidacyList.jsx b/src/components/CandidacyList.jsx index b360b224a1d869a37c8c4f857fa86741871dc58b..4a8cd8bfe486720b26b2c8c4117744d560a6f27d 100644 --- a/src/components/CandidacyList.jsx +++ b/src/components/CandidacyList.jsx @@ -1,20 +1,20 @@ -import React, { useState, useEffect } from "react"; +import React, { useEffect, useState } from "react"; -function CandidacyList() { +const CandidacyList = () => { const [candidacies, setCandidacies] = useState([]); useEffect(() => { fetch("http://localhost:8080/api/candidacies") - .then((response) => response.json()) + .then((res) => res.json()) .then((data) => setCandidacies(data)) - .catch((error) => console.error("Error fetching candidacies:", error)); + .catch((err) => console.error("Erreur lors du chargement:", err)); }, []); return ( <div className="container mt-4"> - <h2 className="mb-4">Liste des Candidatures</h2> - <table className="table table-striped table-hover"> - <thead className="table-warning"> + <h2>Liste des Candidatures</h2> + <table className="table table-striped"> + <thead> <tr> <th>ID</th> <th>Étudiant</th> @@ -26,15 +26,18 @@ function CandidacyList() { {candidacies.map((candidacy) => ( <tr key={candidacy.id}> <td>{candidacy.id}</td> - <td>{candidacy.student?.firstname} {candidacy.student?.lastname}</td> - <td>{candidacy.stage?.name}</td> - <td>{candidacy.univSupervisor?.name}</td> + <td> + {candidacy.student.firstname} {candidacy.student.lastname} + </td> + <td>{candidacy.stage.name}</td> + + <td>{candidacy.univSupervisor.name}</td> </tr> ))} </tbody> </table> </div> ); -} +}; export default CandidacyList; diff --git a/src/components/EnterpriseForm.jsx b/src/components/EnterpriseForm.jsx new file mode 100644 index 0000000000000000000000000000000000000000..1086700519988360ab0b7aa8fabd6f185c1eaf83 --- /dev/null +++ b/src/components/EnterpriseForm.jsx @@ -0,0 +1,44 @@ +import React, { useState } from "react"; + +function EnterpriseForm() { + const [name, setName] = useState(""); + const [address, setAddress] = useState(""); + + const handleSubmit = (e) => { + e.preventDefault(); + + const newEnterprise = { name, address }; + + fetch("http://localhost:8080/api/enterprises", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(newEnterprise) + }) + .then((res) => res.json()) + .then(() => { + alert("Entreprise ajoutée avec succès !"); + setName(""); + setAddress(""); + }) + .catch((err) => console.error("Erreur lors de l'ajout de l'entreprise :", err)); + }; + + return ( + <div className="container mt-4"> + <h2>Ajouter une Entreprise</h2> + <form onSubmit={handleSubmit}> + <div className="mb-3"> + <label className="form-label">Nom de l'entreprise</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">Adresse</label> + <input type="text" className="form-control" value={address} onChange={(e) => setAddress(e.target.value)} required /> + </div> + <button type="submit" className="btn btn-primary">Ajouter</button> + </form> + </div> + ); +} + +export default EnterpriseForm; diff --git a/src/components/Navbar.jsx b/src/components/Navbar.jsx index 86ce3bea11a9b8b47e9fdf8f79b81595d888a569..9f0dbc61405d3158b4a25893334976d930d5eb49 100644 --- a/src/components/Navbar.jsx +++ b/src/components/Navbar.jsx @@ -1,16 +1,11 @@ import React from "react"; -import { Link, useLocation } from "react-router-dom"; -import "./Navbar.css"; // Optional: Add this for extra styling +import { Link } from "react-router-dom"; function Navbar() { - const location = useLocation(); - return ( - <nav className="navbar navbar-expand-lg navbar-dark bg-primary shadow-sm"> + <nav className="navbar navbar-expand-lg navbar-dark bg-primary"> <div className="container"> - <Link className="navbar-brand fw-bold" to="/"> - <i className="fas fa-graduation-cap"></i> Gestion Stages - </Link> + <Link className="navbar-brand" to="/">🏫 Gestion Stages</Link> <button className="navbar-toggler" type="button" @@ -22,56 +17,39 @@ function Navbar() { > <span className="navbar-toggler-icon"></span> </button> - <div className="collapse navbar-collapse" id="navbarNav"> <ul className="navbar-nav ms-auto"> <li className="nav-item"> - <Link - className={`nav-link ${location.pathname === "/login" ? "active" : ""}`} - to="/login" - > - <i className="fas fa-sign-in-alt"></i> Login - </Link> + <Link className="nav-link" to="/login">🔑 Login</Link> </li> <li className="nav-item"> - <Link - className={`nav-link ${location.pathname === "/stages" ? "active" : ""}`} - to="/stages" - > - <i className="fas fa-book"></i> Stages - </Link> + <Link className="nav-link" to="/stages">📚 Stages</Link> </li> <li className="nav-item"> - <Link - className={`nav-link ${location.pathname === "/etudiants" ? "active" : ""}`} - to="/etudiants" - > - <i className="fas fa-user-graduate"></i> Étudiants - </Link> + <Link className="nav-link" to="/etudiants">👨🎓 Étudiants</Link> </li> <li className="nav-item"> - <Link - className={`nav-link ${location.pathname === "/entreprises" ? "active" : ""}`} - to="/entreprises" - > - <i className="fas fa-building"></i> Entreprises - </Link> + <Link className="nav-link" to="/entreprises">🏢 Entreprises</Link> </li> <li className="nav-item"> - <Link - className={`nav-link ${location.pathname === "/candidatures" ? "active" : ""}`} - to="/candidatures" - > - <i className="fas fa-file-alt"></i> Candidatures - </Link> + <Link className="nav-link" to="/candidatures">📝 Candidatures</Link> </li> <li className="nav-item"> - <Link - className={`nav-link ${location.pathname === "/superviseurs" ? "active" : ""}`} - to="/superviseurs" - > - <i className="fas fa-chalkboard-teacher"></i> Superviseurs - </Link> + <Link className="nav-link" to="/superviseurs">👨🏫 Superviseurs</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> diff --git a/src/components/StageForm.jsx b/src/components/StageForm.jsx new file mode 100644 index 0000000000000000000000000000000000000000..ff8f36808c2e1bf35d5d2bc84577510e39b6a59c --- /dev/null +++ b/src/components/StageForm.jsx @@ -0,0 +1,67 @@ +import React, { useState, useEffect } from "react"; + +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)); + }; + + 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> + <button type="submit" className="btn btn-primary">Ajouter</button> + </form> + </div> + ); +} + +export default StageForm; diff --git a/src/components/StudentForm.jsx b/src/components/StudentForm.jsx new file mode 100644 index 0000000000000000000000000000000000000000..cbfcea051c9c53d059df67c6f16df9bce30bcc45 --- /dev/null +++ b/src/components/StudentForm.jsx @@ -0,0 +1,44 @@ +import React, { useState } from "react"; + +function StudentForm() { + const [firstname, setFirstname] = useState(""); + const [lastname, setLastname] = useState(""); + + const handleSubmit = (e) => { + e.preventDefault(); + + const newStudent = { firstname, lastname }; + + fetch("http://localhost:8080/api/students", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(newStudent) + }) + .then((res) => res.json()) + .then(() => { + alert("Étudiant ajouté avec succès !"); + setFirstname(""); + setLastname(""); + }) + .catch((err) => console.error("Erreur lors de l'ajout de l'étudiant :", err)); + }; + + return ( + <div className="container mt-4"> + <h2>Ajouter un Étudiant</h2> + <form onSubmit={handleSubmit}> + <div className="mb-3"> + <label className="form-label">Prénom</label> + <input type="text" className="form-control" value={firstname} onChange={(e) => setFirstname(e.target.value)} required /> + </div> + <div className="mb-3"> + <label className="form-label">Nom</label> + <input type="text" className="form-control" value={lastname} onChange={(e) => setLastname(e.target.value)} required /> + </div> + <button type="submit" className="btn btn-primary">Ajouter</button> + </form> + </div> + ); +} + +export default StudentForm; diff --git a/src/components/UnivSupervisorForm.jsx b/src/components/UnivSupervisorForm.jsx new file mode 100644 index 0000000000000000000000000000000000000000..3019495f1ad62780c6fdc1a8a6f13d390a488989 --- /dev/null +++ b/src/components/UnivSupervisorForm.jsx @@ -0,0 +1,44 @@ +import React, { useState } from "react"; + +function UnivSupervisorForm() { + const [name, setName] = useState(""); + + const handleSubmit = (e) => { + e.preventDefault(); + + const newSupervisor = { name }; + + fetch("http://localhost:8080/api/univsupervisors", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(newSupervisor), + }) + .then((res) => res.json()) + .then(() => { + alert("Superviseur ajouté avec succès !"); + setName(""); + }) + .catch((err) => console.error("Erreur lors de l'ajout du superviseur :", err)); + }; + + return ( + <div className="container mt-4"> + <h2>Ajouter un Tuteur Universitaire</h2> + <form onSubmit={handleSubmit}> + <div className="mb-3"> + <label className="form-label">Nom du Superviseur</label> + <input + type="text" + className="form-control" + value={name} + onChange={(e) => setName(e.target.value)} + required + /> + </div> + <button type="submit" className="btn btn-primary">Ajouter</button> + </form> + </div> + ); +} + +export default UnivSupervisorForm; diff --git a/src/components/UnivSupervisorList.jsx b/src/components/UnivSupervisorList.jsx index 86aeb5f06201882539a6ab77461f378f536dc110..0b271d02451ac95b1e35c1f537995d45fed547af 100644 --- a/src/components/UnivSupervisorList.jsx +++ b/src/components/UnivSupervisorList.jsx @@ -4,7 +4,7 @@ function UnivSupervisorList() { const [univSupervisors, setUnivSupervisors] = useState([]); useEffect(() => { - fetch("http://localhost:8080/api/univSupervisors") + fetch("http://localhost:8080/api/univsupervisors") .then((response) => response.json()) .then((data) => setUnivSupervisors(data)) .catch((error) => console.error("Error fetching university supervisors:", error)); @@ -14,10 +14,11 @@ function UnivSupervisorList() { <div className="container mt-4"> <h2 className="mb-4">Liste des Superviseurs Universitaires</h2> <table className="table table-striped table-hover"> - <thead className="table-danger"> + <thead className="table-primary"> <tr> <th>ID</th> - <th>Nom du Superviseur Universitaire</th> + <th>Nom</th> + <th>Stages Supervisés</th> </tr> </thead> <tbody> @@ -25,6 +26,17 @@ function UnivSupervisorList() { <tr key={supervisor.id}> <td>{supervisor.id}</td> <td>{supervisor.name}</td> + <td> + {supervisor.supervisedStages && supervisor.supervisedStages.length > 0 ? ( + <ul> + {supervisor.supervisedStages.map((stage) => ( + <li key={stage.id}>{stage.stage?.name}</li> + ))} + </ul> + ) : ( + "Aucun stage" + )} + </td> </tr> ))} </tbody>