Merge remote-tracking branch 'origin/main' into Ruben
This commit is contained in:
commit
c4648ccad4
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -10,14 +10,20 @@ 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){
|
|
||||||
this.databaseService = dtbS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void getObjects(RoutingContext context) {
|
public QueryObjects(DatabaseService dtbS) {
|
||||||
|
this.databaseService = dtbS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SetUser setUser;
|
||||||
|
|
||||||
|
public void setUserHandler(SetUser setUser) {
|
||||||
|
this.setUser = setUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getObjects(RoutingContext context) {
|
||||||
databaseService.pool
|
databaseService.pool
|
||||||
.query("SELECT * FROM weather_objects;")
|
.query("SELECT * FROM weather_objects;")
|
||||||
.execute()
|
.execute()
|
||||||
@ -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());
|
||||||
@ -77,9 +89,9 @@ public class QueryObjects {
|
|||||||
.put("location", row.getString("location"))
|
.put("location", row.getString("location"))
|
||||||
.put("last_update", row.getLocalDateTime("last_update").format(formatter))
|
.put("last_update", row.getLocalDateTime("last_update").format(formatter))
|
||||||
.put("status", row.getString("status"))
|
.put("status", row.getString("status"))
|
||||||
.put("batterie",row.getInteger("batterie"))
|
.put("batterie", row.getInteger("batterie"))
|
||||||
.put("type_batterie",row.getString("type_batterie"))
|
.put("type_batterie", row.getString("type_batterie"))
|
||||||
.put("proprio",row.getString("proprio"));
|
.put("proprio", row.getString("proprio"));
|
||||||
objects.add(object);
|
objects.add(object);
|
||||||
}
|
}
|
||||||
return objects;
|
return objects;
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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;
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,11 +35,10 @@ 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=?")
|
||||||
.execute(Tuple.of(points,id))
|
.execute(Tuple.of(points, id))
|
||||||
.onFailure(e -> {
|
.onFailure(e -> {
|
||||||
System.err.println("Erreur de récupération de la BDD :" + e.getMessage());
|
System.err.println("Erreur de récupération de la BDD :" + e.getMessage());
|
||||||
context.response()
|
context.response()
|
||||||
@ -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;
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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());
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
16
Front-end/src/ProtectedRoute.jsx
Normal file
16
Front-end/src/ProtectedRoute.jsx
Normal 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
|
||||||
@ -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 dû à son manque de données. Vous pouvez le
|
Cet objet peut être inactif dû à 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>
|
||||||
)));
|
)));
|
||||||
|
|||||||
@ -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} />
|
||||||
@ -136,13 +155,18 @@ function Header() {
|
|||||||
</ul>
|
</ul>
|
||||||
</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
|
||||||
|
|||||||
@ -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">
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|||||||
@ -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>
|
||||||
@ -108,8 +111,14 @@ function Login() {
|
|||||||
{/* Lien vers la page d'inscription */}
|
{/* Lien vers la page d'inscription */}
|
||||||
<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>
|
||||||
|
|||||||
@ -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",
|
||||||
|
|||||||
@ -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) */}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user