Ajout de la possibilité d'ajouter un objet

This commit is contained in:
Mathis 2025-03-31 20:41:43 +02:00
parent b278cb16e1
commit 6d561a5f1e
10 changed files with 422 additions and 172 deletions

View File

@ -49,7 +49,7 @@
<dependency> <dependency>
<groupId>io.agroal</groupId> <groupId>io.agroal</groupId>
<artifactId>agroal-pool</artifactId> <artifactId>agroal-pool</artifactId>
<version>1.16</version> <!-- Utilisez la version la plus récente --> <version>1.16</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.vertx</groupId> <groupId>io.vertx</groupId>

View File

@ -16,6 +16,7 @@ public class MainVerticle extends AbstractVerticle {
databaseService = new DatabaseService(vertx); databaseService = new DatabaseService(vertx);
QueryObjects queryObjects = new QueryObjects(databaseService); QueryObjects queryObjects = new QueryObjects(databaseService);
QueryWeatherData queryWeather = new QueryWeatherData(databaseService); QueryWeatherData queryWeather = new QueryWeatherData(databaseService);
SetObjects setObjects = new SetObjects(databaseService);
// Create a Router // Create a Router
Router router = Router.router(vertx); Router router = Router.router(vertx);
router.route().handler(BodyHandler.create()); router.route().handler(BodyHandler.create());
@ -27,9 +28,10 @@ public class MainVerticle extends AbstractVerticle {
.allowedHeader("Authorization")); .allowedHeader("Authorization"));
router.get("/objets").handler(queryObjects::getObjects); router.get("/objets").handler(queryObjects::getObjects);
router.get("/objet").handler(queryObjects::getParticularObject); router.get("/objet").handler(queryObjects::getParticularObject);
router.post("/modifObjet").handler(queryObjects::setInfoObjet); router.post("/modifObjet").handler(setObjects::setInfoObjet);
router.get("/wind").handler(queryWeather::getWindInfos); router.get("/wind").handler(queryWeather::getWindInfos);
router.get("/meteo").handler(queryWeather::getMeteoInfos); router.get("/meteo").handler(queryWeather::getMeteoInfos);
router.post("/addObject").handler(setObjects::newObject);
vertx.createHttpServer() vertx.createHttpServer()
.requestHandler(router) .requestHandler(router)

View File

@ -81,44 +81,4 @@ public class QueryObjects {
} }
return objects; return objects;
} }
public void setInfoObjet(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");
String description = body.getString("description");
String type = body.getString("type");
String location = body.getString("location");
String status = body.getString("status");
databaseService.pool
.preparedQuery(
"UPDATE weather_objects SET description=?,type=?,location=?,status=?,last_update=CURRENT_TIMESTAMP WHERE id=?")
.execute(Tuple.of(description, type, location, status, id))
.onFailure(e -> {
System.err.println("Erreur de récupération de la BDD :" + e.getMessage());
context.response()
.setStatusCode(500)
.end(new JsonObject().put("Erreur", "Erreur de récupération de la BDD").encode());
})
.onSuccess(rows -> {
if (rows.rowCount() == 0) {
context.response()
.setStatusCode(404)
.end(new JsonObject().put("error", "Objet non trouvé").encode());
return;
}
context.response()
.putHeader("content-type", "application/json: charset=UTF-8")
.end(new JsonObject().put("success", "L'objet à bien été mis à jour").encode());
return;
});
}
} }

View File

@ -0,0 +1,89 @@
package com.example.starter;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import io.vertx.sqlclient.Tuple;
public class SetObjects {
private DatabaseService databaseService;
public SetObjects(DatabaseService ddbs) {
this.databaseService = ddbs;
}
public void setInfoObjet(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");
String description = body.getString("description");
String type = body.getString("type");
String location = body.getString("location");
String status = body.getString("status");
databaseService.pool
.preparedQuery(
"UPDATE weather_objects SET description=?,type=?,location=?,status=?,last_update=CURRENT_TIMESTAMP WHERE id=?")
.execute(Tuple.of(description, type, location, status, id))
.onFailure(e -> {
System.err.println("Erreur de récupération de la BDD :" + e.getMessage());
context.response()
.setStatusCode(500)
.end(new JsonObject().put("Erreur", "Erreur de récupération de la BDD").encode());
})
.onSuccess(rows -> {
if (rows.rowCount() == 0) {
context.response()
.setStatusCode(404)
.end(new JsonObject().put("error", "Objet non trouvé").encode());
return;
}
context.response()
.putHeader("content-type", "application/json: charset=UTF-8")
.end(new JsonObject().put("success", "L'objet à bien été mis à jour").encode());
return;
});
}
public void newObject(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;
}
String name = body.getString("nom");
String description = body.getString("description");
String type = body.getString("type");
String location = body.getString("location");
String status = body.getString("status");
databaseService.pool
.preparedQuery("INSERT INTO weather_objects (name,description,type,location,status) VALUES (?,?,?,?,?)")
.execute(Tuple.of(name,description,type,location,status))
.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", "Objet non trouvé").encode());
return;
}
context.response()
.putHeader("content-type","application/json: charset=UTF-8")
.end(new JsonObject().put("success", "L'objet à bien été ajouté").encode());
return;
});
}
}

View File

@ -5,6 +5,7 @@ import Gestion from "./pages/Gestion/Gestion.jsx";
import Header from "./components/Header.jsx"; import Header from "./components/Header.jsx";
import ObjectManagement from "./pages/Gestion/ObjectManagement.jsx"; import ObjectManagement from "./pages/Gestion/ObjectManagement.jsx";
import Objet from "./pages/Gestion/Objet.jsx"; import Objet from "./pages/Gestion/Objet.jsx";
import AddObject from "./pages/Gestion/AddObject.jsx";
function App() { function App() {
return ( return (
@ -17,6 +18,7 @@ function App() {
<Route path="/gestion" element={<Gestion />} /> <Route path="/gestion" element={<Gestion />} />
<Route path="/gestionObjets" element={<ObjectManagement />} /> <Route path="/gestionObjets" element={<ObjectManagement />} />
<Route path="/objet" element={<Objet />} /> <Route path="/objet" element={<Objet />} />
<Route path="/ajouterObjet" element={<AddObject />} />
</Routes> </Routes>
</div> </div>
</Router> </Router>

View File

@ -5,33 +5,32 @@ function InfoObject({ object,defafficherModif }) {
return ( return (
<div key={object.id} className="bg-white p-6 rounded-xl min-w-5xl"> <div key={object.id} className="bg-white p-6 rounded-xl min-w-5xl">
<div className="flex align-items gap-6"> <div className="flex align-items gap-6">
<div className="w-12 h-12 bg-indigo-100 rounded-lg flex items-center justify-center mb-4"> <div className="w-12 h-12 bg-indigo-100 rounded-lg flex items-center justify-center mb-1">
<Info className="text-indigo-600" size={24} /> <Info className="text-indigo-600" size={24} />
</div> </div>
<h1 className="text-black text-2xl font-bold mb-1 ">Informations</h1> <h1 className="text-black text-2xl font-bold mb-1 ">Informations</h1>
</div> </div>
<div className="flex flex-col gap-4"> <div className="mb-5">
<div className="flex items-center gap-4 mb-1">
<p className="text-black-900 font-bold">Description :</p> <p className="text-black-900 font-bold">Description :</p>
<p className="text-gray-600">{object.description}</p> <p className="text-gray-600 capitalize">{object.description}</p>
</div> </div>
<div className="flex items-center gap-4 mb-1"> <div className="mb-5">
<p className="text-black-900 font-bold">Type :</p> <p className="text-black-900 font-bold">Type :</p>
<p className="text-gray-600 capitalize">{object.type}</p> <p className="text-gray-600 capitalize">{object.type}</p>
</div> </div>
<div className="flex items-center gap-4 mb-1"> <div className="mb-5">
<p className="text-black-900 font-bold">Localisation :</p> <p className="text-black-900 font-bold">Localisation :</p>
<p className="text-gray-600">{object.location}</p> <p className="text-gray-600">{object.location}</p>
</div> </div>
<div className="flex items-center gap-4 mb-1"> <div className="mb-5">
<p className="text-black-900 font-bold">Status :</p> <p className="text-black-900 font-bold">Status :</p>
<p className="text-gray-600 capitalize">{object.status}</p> <p className="text-gray-600 capitalize">{object.status}</p>
</div> </div>
<div className="flex items-center gap-4 mb-1"> <div className="mb-5">
<p className="text-black-900 font-bold"> <p className="text-black-900 font-bold">
Derniere mise à jour : Derniere mise à jour :
</p> </p>
@ -40,7 +39,6 @@ function InfoObject({ object,defafficherModif }) {
<div className="flex items-center gap-4 mb-1"> <div className="flex items-center gap-4 mb-1">
<a className="text-blue-500 hover:cursor-pointer" onClick={(()=>defafficherModif(true))}>Modifier ces infos</a> <a className="text-blue-500 hover:cursor-pointer" onClick={(()=>defafficherModif(true))}>Modifier ces infos</a>
</div> </div>
</div>
</div> </div>
); );
} }

View File

@ -1,6 +1,5 @@
import React, { use } from "react"; import React, { useState } from "react";
import { Check, Info } from "lucide-react"; import { Info } from "lucide-react";
import { useState } from "react";
import axios from "axios"; import axios from "axios";
import { API_BASE_URL } from "../config"; import { API_BASE_URL } from "../config";
@ -8,135 +7,144 @@ function ModifObject({ object, defafficherModif }) {
const [description, setDescription] = useState(object.description || ""); const [description, setDescription] = useState(object.description || "");
const [type, setType] = useState(object.type || ""); const [type, setType] = useState(object.type || "");
const [location, setLocalisation] = useState(object.location || ""); const [location, setLocalisation] = useState(object.location || "");
const [status, setStatus] = useState(object.status || ""); const [status, setStatus] = useState(object.status || "inactive");
const [Response, setResponse] = useState(null); const [isActive, setActive] = useState(object.status === "active");
const [isActive,setActive] = useState(object.status==="active");
function makeChange() { function handleSubmit(event) {
event.preventDefault(); // Empêche le rechargement de la page
axios axios
.post(`${API_BASE_URL}/modifObjet`, { .post(`${API_BASE_URL}/modifObjet`, {
id: object.id, id: object.id,
description: description, description,
type: type, type,
location: location, location,
status: status, status,
}) })
.then((response) => { .then((response) => {
setResponse(response.data[0]); console.log("Modification réussie :", response.data);
})
.catch((error) => {
console.error("Erreur lors de la modification :", error);
}); });
defafficherModif(false); defafficherModif(false);
window.location.reload(); window.location.reload();
} }
function cancelChange() {
function handleCancel() {
defafficherModif(false); defafficherModif(false);
} }
function handleDescriptionChange(event) {
setDescription(event.target.value); function handleStatusChange() {
}
function handleTypeChange(event) {
setType(event.target.value);
}
function handleLocalisationChange(event) {
setLocalisation(event.target.value);
}
function handleStatusChange(event) {
setActive((prevIsActive) => { setActive((prevIsActive) => {
const newIsActive = !prevIsActive; const newIsActive = !prevIsActive;
const newStatus = newIsActive ? "active" : "inactive"; setStatus(newIsActive ? "active" : "inactive");
console.log(newStatus);
setStatus(newStatus);
return newIsActive; return newIsActive;
}); });
} }
return ( return (
<div key={object.id} className="bg-white p-6 rounded-xl min-w-5xl"> <form onSubmit={handleSubmit} className="bg-white p-6 rounded-xl min-w-5xl">
<div className="flex align-items gap-9"> <div className="flex align-items gap-9">
<div className="w-12 h-12 bg-indigo-100 rounded-lg flex items-center justify-center mb-4"> <div className="w-12 h-12 bg-indigo-100 rounded-lg flex items-center justify-center mb-4">
<Info className="text-indigo-600" size={24} /> <Info className="text-indigo-600" size={24} />
</div> </div>
<h1 className="text-black text-2xl font-bold mb-1 "> <h1 className="text-black text-2xl font-bold mb-1">
Modifier les infos Modifier les infos
</h1> </h1>
</div> </div>
<div className="flex flex-col gap-4"> <div className="mb-5">
<div className="flex items-center gap-4 mb-1"> <label
<p className="text-black-900 font-bold">Description :</p> htmlFor="description"
<input className="block mb-2 text-sm font-medium text-gray-900"
className="text-gray-600 border" >
type="text" Description
value={description} </label>
onChange={handleDescriptionChange} <input
/> id="description"
</div> className="text-gray-600 border rounded-lg p-2 w-full"
type="text"
value={description}
onChange={(e) => setDescription(e.target.value)}
required
/>
</div>
<div className="flex items-center gap-4 mb-1"> <div className="mb-5">
<p className="text-black-900 font-bold">Type :</p> <label htmlFor="type" className="block mb-2 text-sm font-medium text-gray-900">
<input Type :
className="text-gray-600 border" </label>
type="text" <input
value={type} id="type"
onChange={handleTypeChange} className="text-gray-600 border rounded-lg p-2 w-full"
/> type="text"
</div> value={type}
onChange={(e) => setType(e.target.value)}
required
/>
</div>
<div className="flex items-center gap-4 mb-1"> <div className="mb-5">
<p className="text-black-900 font-bold">Localisation :</p> <label htmlFor="location" className="block mb-2 text-sm font-medium text-gray-900">
<input Localisation :
className="text-gray-600 border" </label>
type="text" <input
value={location} id="location"
onChange={handleLocalisationChange} className="text-gray-600 border rounded-lg p-2 w-full"
/> type="text"
</div> value={location}
onChange={(e) => setLocalisation(e.target.value)}
required
/>
</div>
<div className="flex items-center gap-4 mb-1"> <div className="mb-5">
<p className="text-black-900 font-bold">Status :</p> <label className="block mb-2 text-sm font-medium text-gray-900">Status :</label>
<div class="inline-flex items-center gap-2"> <div className="inline-flex items-center gap-2">
<label
htmlFor="switch-component-on"
className="text-slate-600 text-sm cursor-pointer"
>
Inactive
</label>
<div className="relative inline-block w-11 h-5">
<input
id="switch-component-on"
type="checkbox"
checked={isActive}
onChange={handleStatusChange}
className="peer appearance-none w-11 h-5 bg-slate-100 rounded-full checked:bg-slate-800 cursor-pointer transition-colors duration-300"
/>
<label <label
htmlFor="switch-component-on" htmlFor="switch-component-on"
className="text-slate-600 text-sm cursor-pointer" className="absolute top-0 left-0 w-5 h-5 bg-white rounded-full border border-slate-300 shadow-sm transition-transform duration-300 peer-checked:translate-x-6 peer-checked:border-slate-800 cursor-pointer"
> ></label>
Inactive
</label>
<div class="relative inline-block w-11 h-5">
<input
id="switch-component-on"
type="checkbox"
checked={isActive}
onChange={handleStatusChange}
className="peer appearance-none w-11 h-5 bg-slate-100 rounded-full checked:bg-slate-800 cursor-pointer transition-colors duration-300"
/>
<label
htmlFor="switch-component-on"
className="absolute top-0 left-0 w-5 h-5 bg-white rounded-full border border-slate-300 shadow-sm transition-transform duration-300 peer-checked:translate-x-6 peer-checked:border-slate-800 cursor-pointer"
></label>
</div>
<label
htmlFor="switch-component-on"
className="text-slate-600 text-sm cursor-pointer"
>
Active
</label>
</div> </div>
</div> <label
<div className="flex items-center gap-4 mb-1"> htmlFor="switch-component-on"
<a className="text-slate-600 text-sm cursor-pointer"
className="text-blue-500 hover:cursor-pointer"
onClick={() => makeChange()}
> >
Confirmer les modifs Active
</a> </label>
<a
className="text-blue-500 hover:cursor-pointer"
onClick={() => cancelChange()}
>
Annuler les modifs
</a>
</div> </div>
</div> </div>
</div>
<div className="mb-5 flex flex-col">
<button
type="submit"
className="text-blue-500 hover:cursor-pointer hover:underline"
>
Confirmer les modifications
</button>
<button
type="button"
className="text-red-500 hover:cursor-pointer hover:underline"
onClick={handleCancel}
>
Annuler les modifications
</button>
</div>
</form>
); );
} }
export default ModifObject; export default ModifObject;

View File

@ -0,0 +1,206 @@
import React, { useState } from "react";
import { BadgePlus } from "lucide-react";
import axios from "axios";
import { API_BASE_URL } from "../../config";
function AddObject() {
const [description, setDescription] = useState("");
const [type, setType] = useState("");
const [location, setLocalisation] = useState("");
const [status, setStatus] = useState("active");
const [nom, setNom] = useState("");
const [Response, setResponse] = useState(null);
const [isActive, setActive] = useState(true);
const [verif, setVerif] = useState(false);
function handleSubmit(event) {
event.preventDefault();
if (verif) {
console.log("Envoi requete");
axios
.post(`${API_BASE_URL}/addObject`, {
nom,
description,
type,
location,
status,
})
.then((response) => {
console.log("Modification réussie :", response.data);
})
.catch((error) => {
console.error("Erreur lors de la modification :", error);
});
}else{
setVerif(true);
}
}
function handleCancel() {
if(verif){
setVerif(false);
}else{
setNom("");
setStatus("");
setDescription("");
setType("");
setLocalisation("");
setActive(true);
}
}
function handleStatusChange() {
setActive((prevIsActive) => {
const newIsActive = !prevIsActive;
setStatus(newIsActive ? "active" : "inactive");
return newIsActive;
});
}
return (
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-50">
<div className=" max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<div className="text-center mb-5">
<h2 className="text-4xl font-bold text-gray-900 mb-12">
Nouvel objet
</h2>
</div>
<form
onSubmit={handleSubmit}
className="bg-white p-6 rounded-xl min-w-5xl"
>
<div className="flex align-items gap-9">
<div className="w-12 h-12 bg-indigo-100 rounded-lg flex items-center justify-center mb-4">
<BadgePlus className="text-indigo-600" size={24} />
</div>
<h1 className="text-black text-2xl font-bold mb-1">
{(!verif)?("Entrez les données de votre nouvel objet"):("Êtes-vous sûr de ces données ?")}
</h1>
</div>
<div className="mb-5">
<label
htmlFor="nom"
className="block mb-2 text-sm font-medium text-gray-900"
>
Nom :
</label>
<input
id="nom"
className="text-gray-600 border rounded-lg p-2 w-full"
type="text"
value={nom}
onChange={(e) => setNom(e.target.value)}
required
disabled={verif}
/>
</div>
<div className="mb-5">
<label
htmlFor="description"
className="block mb-2 text-sm font-medium text-gray-900"
>
Description :
</label>
<input
id="description"
className="text-gray-600 border rounded-lg p-2 w-full"
type="text"
value={description}
onChange={(e) => setDescription(e.target.value)}
required
disabled={verif}
/>
</div>
<div className="mb-5">
<label
htmlFor="type"
className="block mb-2 text-sm font-medium text-gray-900"
>
Type :
</label>
<input
id="type"
className="text-gray-600 border rounded-lg p-2 w-full"
type="text"
value={type}
onChange={(e) => setType(e.target.value)}
required
disabled={verif}
/>
</div>
<div className="mb-5">
<label
htmlFor="location"
className="block mb-2 text-sm font-medium text-gray-900"
>
Localisation :
</label>
<input
id="location"
className="text-gray-600 border rounded-lg p-2 w-full"
type="text"
value={location}
onChange={(e) => setLocalisation(e.target.value)}
required
disabled={verif}
/>
</div>
<div className="mb-5">
<label className="block mb-2 text-sm font-medium text-gray-900">
Status :
</label>
<div className="inline-flex items-center gap-2">
<label
htmlFor="switch-component-on"
className="text-slate-600 text-sm cursor-pointer"
>
Inactive
</label>
<div className="relative inline-block w-11 h-5">
<input
id="switch-component-on"
type="checkbox"
checked={isActive}
onChange={handleStatusChange}
className="peer appearance-none w-11 h-5 bg-slate-100 rounded-full checked:bg-slate-800 cursor-pointer transition-colors duration-300"
disabled={verif}
/>
<label
htmlFor="switch-component-on"
className="absolute top-0 left-0 w-5 h-5 bg-white rounded-full border border-slate-300 shadow-sm transition-transform duration-300 peer-checked:translate-x-6 peer-checked:border-slate-800 cursor-pointer"
></label>
</div>
<label
htmlFor="switch-component-on"
className="text-slate-600 text-sm cursor-pointer"
>
Active
</label>
</div>
</div>
<div className="flex flex-col mb-5 ">
<button
type={"submit"}
className="text-blue-500 hover:cursor-pointer hover:underline mb-2"
>
{(!verif)?("Confirmer les informations"):("Oui je suis sûr !")}
</button>
<button
type="button"
className="text-red-500 hover:cursor-pointer hover:underline"
onClick={handleCancel}
>
{(!verif)?("Supprimer les informations"):("Non je veux changer !")}
</button>
</div>
</form>
</div>
</div>
);
}
export default AddObject;

View File

@ -10,7 +10,7 @@ import {
RadioTower, RadioTower,
Binoculars, Binoculars,
Settings, Settings,
ChartArea, BadgePlus,
} from "lucide-react"; } from "lucide-react";
function Gestion() { function Gestion() {
@ -26,8 +26,7 @@ function Gestion() {
</p> </p>
</div> </div>
{/* Features Grid */} <div className="grid md:grid-cols-2 gap-8">
<div className="grid md:grid-cols-3 gap-8">
<div className="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition-shadow"> <div className="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition-shadow">
<div className="w-12 h-12 bg-indigo-100 rounded-lg flex items-center justify-center mb-4"> <div className="w-12 h-12 bg-indigo-100 rounded-lg flex items-center justify-center mb-4">
<RadioTower className="text-indigo-600" size={24} /> <RadioTower className="text-indigo-600" size={24} />
@ -47,7 +46,7 @@ function Gestion() {
</div> </div>
<div className="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition-shadow"> <div className="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition-shadow">
<div className="w-12 h-12 bg-indigo-100 rounded-lg flex items-center justify-center mb-4"> <div className="w-12 h-12 bg-indigo-100 rounded-lg flex items-center justify-center mb-4">
<Settings className="text-indigo-600" size={24} /> <BadgePlus className="text-indigo-600" size={24} />
</div> </div>
<h3 className="text-xl font-semibold mb-2"> <h3 className="text-xl font-semibold mb-2">
Ajouter un nouvel objet connecté Ajouter un nouvel objet connecté
@ -56,29 +55,13 @@ function Gestion() {
Intégrez facilement un nouvel objet connecté en renseignant ses informations et en configurant ses paramètres pour une gestion optimale. Intégrez facilement un nouvel objet connecté en renseignant ses informations et en configurant ses paramètres pour une gestion optimale.
</p> </p>
<a <a
href="#" href="/ajouterObjet"
className="flex items-center text-indigo-600 hover:text-indigo-700" className="flex items-center text-indigo-600 hover:text-indigo-700"
> >
Ajouter un objet <ArrowRight size={16} className="ml-2" /> Ajouter un objet <ArrowRight size={16} className="ml-2" />
</a> </a>
</div> </div>
<div className="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition-shadow">
<div className="w-12 h-12 bg-indigo-100 rounded-lg flex items-center justify-center mb-4">
<Binoculars className="text-indigo-600" size={24} />
</div>
<h3 className="text-xl font-semibold mb-2">
Optimisation et surveillance des ressources
</h3>
<p className="text-gray-600 mb-4">
Suivez les performances des dispositifs connectés et optimisez leur utilisation pour une gestion efficace des ressources.
</p>
<a
href="#"
className="flex items-center text-indigo-600 hover:text-indigo-700"
>
En savoir plus <ArrowRight size={16} className="ml-2" />
</a>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -3,6 +3,8 @@ import { Thermometer, CircleGauge, Droplet } 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";
import InfoObjet from "../../components/InfoObject"; import InfoObjet from "../../components/InfoObject";
import ModifObject from "../../components/ModifObject"; import ModifObject from "../../components/ModifObject";
import WindGraph from "../../components/WindGraph"; import WindGraph from "../../components/WindGraph";
@ -22,7 +24,7 @@ function Objet() {
useEffect(() => { useEffect(() => {
axios axios
.get(`http://localhost:8888/objet?id=${identifiant}`) .get(`${API_BASE_URL}/objet?id=${identifiant}`)
.then((response) => { .then((response) => {
setObject(response.data[0]); setObject(response.data[0]);
}); });