Merge remote-tracking branch 'origin/main' into Ruben

This commit is contained in:
Arcade69 2025-04-11 15:52:01 +02:00
commit c4648ccad4
17 changed files with 226 additions and 71 deletions

View File

@ -94,11 +94,11 @@ public class AuthHandler {
if (verification.verified) { if (verification.verified) {
JsonObject claims = new JsonObject().put("sub", email); JsonObject claims = new JsonObject().put("sub", email);
if(nbPointsUser<=30){ if(nbPointsUser<=60){
claims.put("role", "user"); claims.put("role", "user");
}else if(nbPointsUser<=60){ }else if(nbPointsUser<=100){
claims.put("role", "complexe"); claims.put("role", "complexe");
}else if(nbPointsUser>=100){ }else if(nbPointsUser>=200){
claims.put("role", "admin"); claims.put("role", "admin");
} }

View File

@ -41,6 +41,9 @@ public class MainVerticle extends AbstractVerticle {
AuthHandler authHandler = new AuthHandler(databaseService, jwtAuth); AuthHandler authHandler = new AuthHandler(databaseService, jwtAuth);
QueryUsers queryUsers = new QueryUsers(databaseService); QueryUsers queryUsers = new QueryUsers(databaseService);
SetUser setUser = new SetUser(databaseService); SetUser setUser = new SetUser(databaseService);
setObjects.setUserHandler(setUser);
queryObjects.setUserHandler(setUser);
// Déclaration des routes // Déclaration des routes
router.get("/objets").handler(queryObjects::getObjects); router.get("/objets").handler(queryObjects::getObjects);
@ -54,6 +57,8 @@ public class MainVerticle extends AbstractVerticle {
router.post("/deleteObject").handler(setObjects::deleteObject); router.post("/deleteObject").handler(setObjects::deleteObject);
router.get("/users").handler(queryUsers::getUsers); router.get("/users").handler(queryUsers::getUsers);
router.post("/setUserPoints").handler(setUser::setUserPoints); router.post("/setUserPoints").handler(setUser::setUserPoints);
router.post("/deleteUser").handler(setUser::deleteUser);
// Routes d'authentification // Routes d'authentification
router.post("/signup").handler(authHandler::handleSignup); router.post("/signup").handler(authHandler::handleSignup);
router.post("/login").handler(authHandler::handleLogin); router.post("/login").handler(authHandler::handleLogin);

View File

@ -10,13 +10,19 @@ import java.time.format.DateTimeFormatter;
import io.vertx.ext.web.RoutingContext; import io.vertx.ext.web.RoutingContext;
public class QueryObjects { public class QueryObjects {
private DatabaseService databaseService; private DatabaseService databaseService;
public QueryObjects(DatabaseService dtbS) { public QueryObjects(DatabaseService dtbS) {
this.databaseService = dtbS; this.databaseService = dtbS;
} }
private SetUser setUser;
public void setUserHandler(SetUser setUser) {
this.setUser = setUser;
}
public void getObjects(RoutingContext context) { public void getObjects(RoutingContext context) {
databaseService.pool databaseService.pool
.query("SELECT * FROM weather_objects;") .query("SELECT * FROM weather_objects;")
@ -36,6 +42,8 @@ public class QueryObjects {
public void getParticularObject(RoutingContext context) { public void getParticularObject(RoutingContext context) {
String id = context.request().getParam("id"); String id = context.request().getParam("id");
// Integer idUser = body.getInteger("idUser");
Integer idUser = 4;
if (id == null) { if (id == null) {
context.response() context.response()
.setStatusCode(400) .setStatusCode(400)
@ -58,6 +66,10 @@ public class QueryObjects {
.end(new JsonObject().put("error", "Objet non trouvé").encode()); .end(new JsonObject().put("error", "Objet non trouvé").encode());
return; return;
} }
if (idUser != null) {
setUser.updateUserPoints(idUser, 1);
}
;
context.response() context.response()
.putHeader("content-type", "application/json: charset=UTF-8") .putHeader("content-type", "application/json: charset=UTF-8")
.end(getInfosObjects(rows).encode()); .end(getInfosObjects(rows).encode());

View File

@ -33,11 +33,11 @@ public class QueryUsers {
.put("email", row.getString("email")) .put("email", row.getString("email"))
.put("gender", row.getString("gender")) .put("gender", row.getString("gender"))
.put("points",points); .put("points",points);
if(points<=30){ if(points<=60){
user.put("role", "user"); user.put("role", "user");
}else if(points<=60){ }else if(points<=100){
user.put("role", "complexe"); user.put("role", "complexe");
}else if(points>=100){ }else if(points>=200){
user.put("role", "admin"); user.put("role", "admin");
} }
users.add(user); users.add(user);

View File

@ -6,11 +6,13 @@ import io.vertx.sqlclient.Tuple;
public class SetObjects { public class SetObjects {
private DatabaseService databaseService; private DatabaseService databaseService;
private SetUser setUser;
public SetObjects(DatabaseService ddbs) { public SetObjects(DatabaseService ddbs) {
this.databaseService = ddbs; this.databaseService = ddbs;
} }
public void setUserHandler(SetUser setUser){
this.setUser = setUser;
}
public void setInfoObjet(RoutingContext context) { public void setInfoObjet(RoutingContext context) {
JsonObject body = context.body().asJsonObject(); JsonObject body = context.body().asJsonObject();
if (body == null) { if (body == null) {
@ -20,6 +22,8 @@ public class SetObjects {
return; return;
} }
Integer id = body.getInteger("id"); Integer id = body.getInteger("id");
// Integer idUser = body.getInteger("idUser");
Integer idUser = 4;
String description = body.getString("description"); String description = body.getString("description");
String type = body.getString("type"); String type = body.getString("type");
String location = body.getString("location"); String location = body.getString("location");
@ -42,6 +46,9 @@ public class SetObjects {
.end(new JsonObject().put("error", "Objet non trouvé").encode()); .end(new JsonObject().put("error", "Objet non trouvé").encode());
return; return;
} }
if(idUser!=null){
setUser.updateUserPoints(idUser,1);
};
context.response() context.response()
.putHeader("content-type", "application/json: charset=UTF-8") .putHeader("content-type", "application/json: charset=UTF-8")
.end(new JsonObject().put("success", "L'objet à bien été mis à jour").encode()); .end(new JsonObject().put("success", "L'objet à bien été mis à jour").encode());
@ -88,6 +95,8 @@ public class SetObjects {
.end(new JsonObject().put("error","Corps de la requête manquant").encode()); .end(new JsonObject().put("error","Corps de la requête manquant").encode());
return; return;
} }
// Integer idUser = body.getInteger("idUser");
Integer idUser = 4;
String name = body.getString("nom"); String name = body.getString("nom");
String description = body.getString("description"); String description = body.getString("description");
String type = body.getString("type"); String type = body.getString("type");
@ -111,12 +120,14 @@ public class SetObjects {
.end(new JsonObject().put("error", "Objet non trouvé").encode()); .end(new JsonObject().put("error", "Objet non trouvé").encode());
return; return;
} }
if(idUser!=null){
setUser.updateUserPoints(idUser,2);
};
context.response() context.response()
.putHeader("content-type","application/json: charset=UTF-8") .putHeader("content-type","application/json: charset=UTF-8")
.end(new JsonObject().put("success", "L'objet à bien été ajouté").encode()); .end(new JsonObject().put("success", "L'objet à bien été ajouté").encode());
return; return;
}); });
} }
} }

View File

@ -10,7 +10,21 @@ public class SetUser {
public SetUser(DatabaseService ddbs) { public SetUser(DatabaseService ddbs) {
this.databaseService = ddbs; this.databaseService = ddbs;
} }
public void updateUserPoints(Integer userId, Integer points) {
databaseService.pool
.preparedQuery("UPDATE users SET points=points+? WHERE id=?")
.execute(Tuple.of(points, userId))
.onFailure(e -> {
System.err.println("Erreur de mise à jour des points :" + e.getMessage());
})
.onSuccess(rows -> {
if (rows.rowCount() > 0) {
System.out.println("Points de l'utilisateur mis à jour avec succès");
} else {
System.out.println("Utilisateur non trouvé pour la mise à jour des points");
}
});
}
public void setUserPoints(RoutingContext context) { public void setUserPoints(RoutingContext context) {
JsonObject body = context.body().asJsonObject(); JsonObject body = context.body().asJsonObject();
if (body == null) { if (body == null) {
@ -21,7 +35,6 @@ public class SetUser {
} }
Integer id = body.getInteger("id"); Integer id = body.getInteger("id");
Integer points = body.getInteger("points"); Integer points = body.getInteger("points");
databaseService.pool databaseService.pool
.preparedQuery( .preparedQuery(
"UPDATE users SET points=? WHERE id=?") "UPDATE users SET points=? WHERE id=?")
@ -41,8 +54,41 @@ public class SetUser {
} }
context.response() context.response()
.putHeader("content-type", "application/json: charset=UTF-8") .putHeader("content-type", "application/json: charset=UTF-8")
.end(new JsonObject().put("success", "Les points de l'utilisateur ont bien été mis à jour").encode()); .end(new JsonObject().put("success", "Les points de l'utilisateur ont bien été mis à jour")
.encode());
return; return;
}); });
} }
public void deleteUser(RoutingContext context){
JsonObject body = context.body().asJsonObject();
if(body== null){
context.response()
.setStatusCode(400)
.end(new JsonObject().put("error","Corps de la requête manquant").encode());
return;
}
Integer id = body.getInteger("id");
databaseService.pool
.preparedQuery("DELETE FROM users WHERE id=?")
.execute(Tuple.of(id))
.onFailure(e->{
System.err.println("Erreur de récupération de la BDD :"+e.getMessage());
context.response()
.setStatusCode(500)
.end(new JsonObject().put("error","Erreur de récupération de la BDD").encode());
})
.onSuccess(rows -> {
if(rows.rowCount()==0){
context.response()
.setStatusCode(404)
.end(new JsonObject().put("error", "Utilisateur non trouvé").encode());
return;
}
context.response()
.putHeader("content-type","application/json: charset=UTF-8")
.end(new JsonObject().put("success", "L'utilisateur à bien été supprimé").encode());
return;
});
}
} }

View File

@ -6,11 +6,15 @@ import io.vertx.sqlclient.Tuple;
public class SetWeatherData { public class SetWeatherData {
private DatabaseService databaseService; private DatabaseService databaseService;
private SetUser setUser;
public SetWeatherData(DatabaseService ddbs) { public SetWeatherData(DatabaseService ddbs) {
this.databaseService = ddbs; this.databaseService = ddbs;
} }
public void setUserHandler(SetUser setUser) {
this.setUser = setUser;
}
public void setRangeData(RoutingContext context) { public void setRangeData(RoutingContext context) {
JsonObject body = context.body().asJsonObject(); JsonObject body = context.body().asJsonObject();
if (body == null) { if (body == null) {
@ -37,7 +41,8 @@ public class SetWeatherData {
return; return;
} }
String query = String.format("UPDATE range_data SET %s_min=?, %s_max=? WHERE station_id=?", type, type); String query = String.format("UPDATE range_data SET %s_min=?, %s_max=? WHERE station_id=?", type, type);
// Integer idUser = body.getInteger("idUser");
Integer idUser = 4;
databaseService.pool databaseService.pool
.preparedQuery( .preparedQuery(
query) query)
@ -55,6 +60,9 @@ public class SetWeatherData {
.end(new JsonObject().put("error", "Objet non trouvé").encode()); .end(new JsonObject().put("error", "Objet non trouvé").encode());
return; return;
} }
if (idUser != null) {
setUser.updateUserPoints(idUser, 1);
}
context.response() context.response()
.putHeader("content-type", "application/json: charset=UTF-8") .putHeader("content-type", "application/json: charset=UTF-8")
.end(new JsonObject().put("success", "Les limites ont bien été mis à jour").encode()); .end(new JsonObject().put("success", "Les limites ont bien été mis à jour").encode());

View File

@ -14,6 +14,7 @@ import Sidebar from "./pages/Admin/sidebar.jsx";
import User from "./pages/Admin/User.jsx"; import User from "./pages/Admin/User.jsx";
import Dashboard from "./pages/Admin/Dashboard.jsx"; import Dashboard from "./pages/Admin/Dashboard.jsx";
import AdminObjet from "./pages/Admin/AdminObjet.jsx"; import AdminObjet from "./pages/Admin/AdminObjet.jsx";
import ProtectedRoute from './ProtectedRoute.jsx'; // Correction de l'import
function App() { function App() {
return ( return (
@ -24,17 +25,17 @@ function App() {
<Routes> <Routes>
<Route path="/" element={<Home />} /> <Route path="/" element={<Home />} />
<Route path="/about" element={<About />} /> <Route path="/about" element={<About />} />
<Route path="/gestion" element={<Gestion />} /> <Route path="/gestion" element={<ProtectedRoute element={<Gestion />} />} />
<Route path="/gestionObjets" element={<ObjectManagement />} /> <Route path="/gestionObjets" element={<ProtectedRoute element={<ObjectManagement />} />} />
<Route path="/objet" element={<Objet />} /> <Route path="/objet" element={<ProtectedRoute element={<Objet />} />} />
<Route path="/signup" element={<Signup />} /> <Route path="/signup" element={<Signup />} />
<Route path="/login" element={<Login />} /> <Route path="/login" element={<Login />} />
<Route path="/ajouterObjet" element={<AddObject />} /> <Route path="/ajouterObjet" element={<ProtectedRoute element={<AddObject />} />} />
<Route path="/settings" element={<Settings />} /> <Route path="/settings" element={<Settings />} />
<Route path="/sidebar" element={<Sidebar />} /> <Route path="/sidebar" element={<Sidebar />} />
<Route path="/user" element={<User />} /> <Route path="/user" element={<User />} />
<Route path="/dashboard" element={<Dashboard />} /> <Route path="/dashboard" element={<Dashboard />} />
<Route path="/adminobjet" element={<AdminObjet />} /> <Route path="/adminobjet" element={<ProtectedRoute element={<AdminObjet />} />} />
</Routes> </Routes>
</div> </div>
</Router> </Router>

View File

@ -0,0 +1,16 @@
import { useAuth } from './AuthContext'; // Utilisation du contexte d'authentification
import { Navigate } from 'react-router-dom'; // Utilisation de React Router pour la redirection
function ProtectedRoute({ element }) {
const { token } = useAuth(); // Vérifier si un token existe, donc si l'utilisateur est authentifié
// Si l'utilisateur n'est pas authentifié, redirigez-le vers la page de login
if (!token) {
return <Navigate to="/login" />;
}
// Si l'utilisateur est authentifié, permettez l'accès à la route
return element;
}
export default ProtectedRoute; // Export de la fonction

View File

@ -4,7 +4,7 @@ import { TriangleAlert,X } from "lucide-react";
function AlertInactive({affAlert,setAffAlert}) { function AlertInactive({affAlert,setAffAlert}) {
return ( return (
(affAlert&&( (affAlert&&(
<div className="flex flex-col md:flex-row bg-slate-600 w-full md:w-1/2 lg:w-1/3 fixed top-20 right-4 rounded-lg p-4 md:p-5 items-center gap-4 md:gap-6 shadow-lg opacity-90"> <div className="flex flex-col md:flex-row bg-slate-600 w-full md:w-1/2 lg:w-1/3 fixed top-20 right-1 sm:right-4 rounded-lg p-4 md:p-5 items-center gap-4 md:gap-6 shadow-lg opacity-90">
<button onClick={()=>setAffAlert(false)}className="absolute top-2 right-2 text-white hover:text-gray-300"> <button onClick={()=>setAffAlert(false)}className="absolute top-2 right-2 text-white hover:text-gray-300">
<X/> <X/>
</button> </button>
@ -13,7 +13,7 @@ function AlertInactive({affAlert,setAffAlert}) {
<p className="text-sm md:text-base text-white text-center md:text-left"> <p className="text-sm md:text-base text-white text-center md:text-left">
Cet objet peut être inactif à son manque de données. Vous pouvez le Cet objet peut être inactif à son manque de données. Vous pouvez le
rendre inactif en appuyant <a>ici</a>. rendre inactif en changeant son status.
</p> </p>
</div> </div>
))); )));

View File

@ -33,21 +33,33 @@ function Header() {
<nav <nav
className={`${ className={`${
isMenuOpen ? "block" : "hidden" isMenuOpen ? "block" : "hidden"
} absolute top-16 left-0 w-full bg-white shadow-md sm:static sm:w-auto sm:flex sm:gap-6 sm:shadow-none z-50`} } absolute z-[1000] top-16 left-0 w-full bg-white shadow-md sm:static sm:w-auto sm:z-auto sm:flex sm:gap-6 sm:shadow-none`}
> >
<ul className="flex flex-col sm:flex-row gap-4 sm:gap-6 text-gray-600 p-4 sm:p-0"> <ul className="flex flex-col sm:flex-row gap-4 sm:gap-6 text-gray-600 p-4 sm:p-0">
<li> <li>
<Link to="/" className="hover:text-indigo-600"> <Link
to="/"
onClick={() => setIsMenuOpen(false)}
className="text-gray-600 hover:text-indigo-600"
>
Accueil Accueil
</Link> </Link>
</li> </li>
<li> <li>
<Link to="/about" className="hover:text-indigo-600"> <Link
to="/about"
onClick={() => setIsMenuOpen(false)}
className="text-gray-600 hover:text-indigo-600"
>
À propos À propos
</Link> </Link>
</li> </li>
<li> <li>
<Link to="/gestion" className="hover:text-indigo-600"> <Link
to="/gestion"
onClick={() => setIsMenuOpen(false)}
className="text-gray-600 hover:text-indigo-600"
>
Gestion Gestion
</Link> </Link>
</li> </li>
@ -96,7 +108,8 @@ function Header() {
<li className="sm:hidden"> <li className="sm:hidden">
<Link <Link
to="/login" to="/login"
className="flex items-center gap-2 hover:text-indigo-600" onClick={() => setIsMenuOpen(false)}
className="hover:text-indigo-600 flex items-center gap-2"
> >
<LogIn size={20} /> <LogIn size={20} />
Connexion Connexion
@ -105,6 +118,7 @@ function Header() {
<li className="sm:hidden"> <li className="sm:hidden">
<Link <Link
to="/signup" to="/signup"
onClick={() => setIsMenuOpen(false)}
className="flex items-center gap-2 bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700" className="flex items-center gap-2 bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700"
> >
<UserPlus size={20} /> <UserPlus size={20} />
@ -117,14 +131,19 @@ function Header() {
<li className="sm:hidden"> <li className="sm:hidden">
<Link <Link
to="/settings" to="/settings"
onClick={()=>setIsMenuOpen(false)}
className="flex items-center gap-2 text-gray-600 hover:text-indigo-600" className="flex items-center gap-2 text-gray-600 hover:text-indigo-600"
> >
<Settings size={20} /> <Settings size={20} />
<span>Paramètres</span>
<span></span>
</Link> </Link>
</li> </li>
<li className="sm:hidden"> <li className="sm:hidden">
<button <button
onClick={logout} onClick={()=>{
logout();
setIsMenuOpen(false)}}
className="flex items-center gap-2 text-gray-600 hover:text-red-600" className="flex items-center gap-2 text-gray-600 hover:text-red-600"
> >
<LogOut size={20} /> <LogOut size={20} />
@ -137,12 +156,17 @@ function Header() {
</nav> </nav>
{!token ? ( {!token ? (
<div className="hidden sm:flex gap-4 "> <div className="hidden sm:flex gap-4 ">
<Link to="/login" className="flex items-center gap-2 hover:text-indigo-600"> <Link
to="/login"
onClick={()=>setIsMenuOpen(false)}
className="hover:text-indigo-600 flex items-center gap-2"
>
<LogIn size={20} /> <LogIn size={20} />
Connexion Connexion
</Link> </Link>
<Link <Link
to="/signup" to="/signup"
onClick={()=>setIsMenuOpen(false)}
className="flex items-center gap-2 bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700" className="flex items-center gap-2 bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700"
> >
<UserPlus size={20} /> <UserPlus size={20} />
@ -150,8 +174,12 @@ function Header() {
</Link> </Link>
</div> </div>
) : ( ) : (
<div className="hidden sm:flex gap-4 items-center"> <div className="hidden sm:flex gap-4">
<Link to="/settings" className="flex items-center gap-2 text-gray-600 hover:text-indigo-600"> <Link
to="/settings"
onClick={()=>setIsMenuOpen(false)}
className="flex items-center gap-2 text-gray-600 hover:text-indigo-600"
>
<Settings size={20} /> <Settings size={20} />
</Link> </Link>
<button <button

View File

@ -146,16 +146,15 @@ function AdminObjet() {
{/*Formulaire d'ajout d'objet*/} {/*Formulaire d'ajout d'objet*/}
<FormNewObject isAdmin={true} /> <FormNewObject isAdmin={true} />
{/* Tri des objets */}
<section className="bg-white p-6 rounded-xl shadow-md mt-12 mb-12"> <section className="bg-white p-6 rounded-xl shadow-md mt-12 mb-12">
<div className="flex items-center justify-between mb-4"> <div className="flex flex-col md:flex-row md:items-center md:justify-between mb-4 gap-4">
<h2 className="text-2xl font-semibold"> <h2 className="text-2xl font-semibold">
Liste des Objets et Outils/Services Liste des Objets et Outils/Services
</h2> </h2>
<select <select
value={sortCriteria} value={sortCriteria}
onChange={(e) => setSortCriteria(e.target.value)} onChange={(e) => setSortCriteria(e.target.value)}
className="border border-gray-300 rounded-lg p-2" className="border border-gray-300 rounded-lg p-2 w-full md:w-auto"
> >
<option value="">-- Trier par --</option> <option value="">-- Trier par --</option>
<option value="proprietaire">Propriétaire</option> <option value="proprietaire">Propriétaire</option>
@ -172,7 +171,7 @@ function AdminObjet() {
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Nom Nom
</th> </th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider w-48">
Description Description
</th> </th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
@ -196,7 +195,7 @@ function AdminObjet() {
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900"> <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
{obj.name} {obj.name}
</td> </td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500"> <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500 w-48 truncate">
{obj.description} {obj.description}
</td> </td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500"> <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">

View File

@ -45,10 +45,24 @@ function User() {
const handleDeleteUser = (userId) => { const handleDeleteUser = (userId) => {
const user = users.find((u) => u.id === userId); const user = users.find((u) => u.id === userId);
if (user) { if (user) {
logAction(user.name, "User deleted"); axios
.post(`${API_BASE_URL}/deleteUser`, {
id: userId,
})
.then((response) => {
alert("L'utilisateur à bien été supprimé !");
console.log("L'utilisateur à été supprimé :", response.data);
window.location.reload();
})
.catch((error) => {
console.error(
"Erreur lors de la suppression de l'utilisateur :",
error
);
});
logAction(user.name, "Utilisateur supprimé");
} }
setUsers(users.filter((u) => u.id !== userId)); setUsers(users.filter((u) => u.id !== userId));
// TODO : Envoyer la suppression au backend.
}; };
// Changement du niveau d'accès // Changement du niveau d'accès
@ -92,6 +106,7 @@ function User() {
setUsers( setUsers(
users.map((user) => { users.map((user) => {
if (user.id === userId) { if (user.id === userId) {
user.points = pointsToAdd;
// On additionne au lieu de remplacer // On additionne au lieu de remplacer
user.points = (user.points || 0) + pointsToAdd; user.points = (user.points || 0) + pointsToAdd;
axios axios
@ -203,6 +218,7 @@ function User() {
</td> </td>
<td className={thTd}> <td className={thTd}>
<input <input
className="border ml-4 w-16"
type="number" type="number"
min="0" min="0"
value={pointsInput[user.id] ?? user.points} value={pointsInput[user.id] ?? user.points}
@ -219,6 +235,7 @@ function User() {
className="p-2 bg-green-600 text-white rounded-md ml-2" className="p-2 bg-green-600 text-white rounded-md ml-2"
> >
Changer Changer
Changer
</button> </button>
</td> </td>
<td className={thTd}> <td className={thTd}>
@ -227,6 +244,7 @@ function User() {
className="p-2 bg-red-600 text-white rounded-md" className="p-2 bg-red-600 text-white rounded-md"
> >
Supprimer Supprimer
Supprimer
</button> </button>
</td> </td>
</tr> </tr>

View File

@ -2,6 +2,7 @@ import React from "react";
import { Search, ArrowRight, RadioTower,Plus } from "lucide-react"; import { Search, ArrowRight, RadioTower,Plus } from "lucide-react";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import axios from "axios"; import axios from "axios";
import { API_BASE_URL } from "../../config";
function ObjectManagement() { function ObjectManagement() {
const [searchQuery, setSearchQuery] = useState(""); const [searchQuery, setSearchQuery] = useState("");
@ -24,7 +25,7 @@ function ObjectManagement() {
}); });
useEffect(() => { useEffect(() => {
axios.get("http://localhost:8888/objets").then((response) => { axios.get(`${API_BASE_URL}/objets`).then((response) => {
setObjects(response.data); setObjects(response.data);
}); });
}, []); }, []);

View File

@ -1,13 +1,14 @@
import React, { useState } from 'react'; import React, { useState } from "react";
import { Mail, Lock } from 'lucide-react'; import { Mail, Lock } from "lucide-react";
import { useNavigate, Link } from 'react-router-dom'; import { useNavigate, Link } from "react-router-dom";
import axios from 'axios'; // Assurez-vous d'avoir axios importé import axios from "axios"; // Assurez-vous d'avoir axios importé
import { useAuth } from '../AuthContext'; import { useAuth } from "../AuthContext";
import { API_BASE_URL } from "../config";
function Login() { function Login() {
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
email: '', email: "",
password: '' password: "",
}); });
const { login } = useAuth(); // Utilisation du hook useAuth pour accéder à la fonction login const { login } = useAuth(); // Utilisation du hook useAuth pour accéder à la fonction login
const navigate = useNavigate(); // Initialisation de useNavigate const navigate = useNavigate(); // Initialisation de useNavigate
@ -16,7 +17,7 @@ function Login() {
const { name, value } = e.target; const { name, value } = e.target;
setFormData((prev) => ({ setFormData((prev) => ({
...prev, ...prev,
[name]: value [name]: value,
})); }));
}; };
@ -24,7 +25,7 @@ function Login() {
e.preventDefault(); e.preventDefault();
try { try {
const response = await fetch("http://localhost:8888/login", { const response = await fetch(`${API_BASE_URL}/login`, {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
@ -41,18 +42,20 @@ function Login() {
login(data.token); login(data.token);
// Rediriger vers la page d'accueil après la connexion // Rediriger vers la page d'accueil après la connexion
navigate('/'); navigate("/");
} else { } else {
console.error('Token manquant dans la réponse'); console.error("Token manquant dans la réponse");
} }
} catch (error) { } catch (error) {
console.error('Erreur lors de la connexion', error); console.error("Erreur lors de la connexion", error);
} }
}; };
return ( return (
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-50 py-12 px-4 sm:px-6 lg:px-8"> <div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-50 py-12 px-4 sm:px-6 lg:px-8">
<div className="w-96 bg-white rounded-lg shadow-md p-6 mx-auto"> <div className="md:w-96 w-full bg-white rounded-lg shadow-md p-6 mx-auto">
<h2 className="text-2xl font-bold text-gray-800 mb-6 text-center">Connexion</h2> <h2 className="text-2xl font-bold text-gray-800 mb-6 text-center">
Connexion
</h2>
<form onSubmit={handleSubmit} className="space-y-4"> <form onSubmit={handleSubmit} className="space-y-4">
{/* Email */} {/* Email */}
<div> <div>
@ -109,7 +112,13 @@ function Login() {
<div className="mt-4 text-sm text-center"> <div className="mt-4 text-sm text-center">
<p> <p>
Vous n'avez pas de compte ? Vous n'avez pas de compte ?
<Link to="/signup" className="text-indigo-600 hover:text-indigo-700 font-medium"> Inscrivez-vous ici</Link> <Link
to="/signup"
className="text-indigo-600 hover:text-indigo-700 font-medium"
>
{" "}
Inscrivez-vous ici
</Link>
</p> </p>
</div> </div>
</form> </form>

View File

@ -30,7 +30,7 @@ function Settings() {
} }
try { try {
const response = await fetch("http://localhost:8888/settings", { const response = await fetch(`${API_BASE_URL}/settings`, {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",

View File

@ -1,6 +1,7 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Mail, User, Lock } from 'lucide-react'; import { Mail, User, Lock } from 'lucide-react';
import { useNavigate, Link} from 'react-router-dom'; // Importation du hook useNavigate import { useNavigate, Link} from 'react-router-dom'; // Importation du hook useNavigate
import { API_BASE_URL } from "../config.js";
function Signup() { function Signup() {
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
@ -11,7 +12,7 @@ function Signup() {
password: '', password: '',
confirmPassword: '' confirmPassword: ''
}); });
const navigate = useNavigate(); // Initialisation de useNavigate const navigate = useNavigate();
const handleChange = (e) => { const handleChange = (e) => {
const { name, value } = e.target; const { name, value } = e.target;
@ -30,7 +31,7 @@ function Signup() {
} }
try { try {
const response = await fetch("http://localhost:8888/signup", { const response = await fetch(`${API_BASE_URL}/signup`, {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
@ -46,8 +47,8 @@ function Signup() {
alert("Inscription réussie !"); alert("Inscription réussie !");
// Redirection vers la page d'accueil après une inscription réussie
navigate("/home"); // Remplace "/home" par l'URL de ta page d'accueil navigate("/");
} catch (error) { } catch (error) {
alert(error.message); alert(error.message);
} }
@ -55,7 +56,7 @@ function Signup() {
return ( return (
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-50 py-12 px-4 sm:px-6 lg:px-8"> <div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-50 py-12 px-4 sm:px-6 lg:px-8">
<div className="w-96 bg-white rounded-lg shadow-md p-6 mx-auto"> <div className="w-full md:w-96 bg-white rounded-lg shadow-md p-6 mx-auto">
<h2 className="text-2xl font-bold text-gray-800 mb-6 text-center">Inscription</h2> <h2 className="text-2xl font-bold text-gray-800 mb-6 text-center">Inscription</h2>
<form onSubmit={handleSubmit} className="space-y-4"> <form onSubmit={handleSubmit} className="space-y-4">
{/* Formulaire (Nom, Prénom, Sexe, Email, Mot de passe) */} {/* Formulaire (Nom, Prénom, Sexe, Email, Mot de passe) */}