Amélioration de l'affichage

This commit is contained in:
Mathis 2025-03-30 22:21:58 +02:00
parent d229dc9467
commit b278cb16e1
11 changed files with 269 additions and 119 deletions

View File

@ -0,0 +1,22 @@
import React, {useState} from "react";
import { TriangleAlert,X } from "lucide-react";
function AlertInactive({affAlert,setAffAlert}) {
return (
(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">
<button onClick={()=>setAffAlert(false)}className="absolute top-2 right-2 text-white hover:text-gray-300">
<X/>
</button>
<TriangleAlert className="text-red-700 w-12 h-12 md:w-16 md:h-16" />
<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
rendre inactif en appuyant <a>ici</a>.
</p>
</div>
)));
}
export default AlertInactive;

View File

@ -6,14 +6,14 @@ function BoutonGraphique({ TypeAff, setAffichage }) {
className="bg-blue-200 py-2 my-2 px-4 rounded-full mr-2" className="bg-blue-200 py-2 my-2 px-4 rounded-full mr-2"
onClick={() => setAffichage(true)} onClick={() => setAffichage(true)}
> >
<ChartLine className="text-red-500" size={24} /> <ChartLine className="text-indigo-600" size={24} />
</button> </button>
) : ( ) : (
<button <button
className="bg-blue-400 py-2 my-2 px-4 rounded-full mr-2" className="bg-blue-400 py-2 my-2 px-4 rounded-full mr-2"
onClick={() => setAffichage(false)} onClick={() => setAffichage(false)}
> >
<ChartLine className="text-red-500" size={24} /> <ChartLine className="text-indigo-600" size={24} />
</button> </button>
); );
} }

View File

@ -1,16 +1,27 @@
import React from "react"; import React, { useState } from "react";
import { LogIn, UserPlus } from "lucide-react"; import { LogIn, UserPlus, Menu, X } from "lucide-react";
function Header() { function Header() {
const [isMenuOpen, setIsMenuOpen] = useState(false);
return ( return (
<header className="bg-white shadow-sm"> <header className="bg-white shadow-sm">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4 flex justify-between items-center"> <div className=" max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-4 flex justify-between items-center">
{/* Logo */}
<h1 className="text-2xl font-bold text-indigo-600">VigiMétéo</h1> <h1 className="text-2xl font-bold text-indigo-600">VigiMétéo</h1>
{/* Navigation */} <button
<nav> className="sm:hidden text-gray-600 hover:text-indigo-600"
<ul className="flex gap-6 text-gray-600"> onClick={() => setIsMenuOpen(!isMenuOpen)}
>
{isMenuOpen ? <X size={24} /> : <Menu size={24} />}
</button>
<nav
className={`${
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`}
>
<ul className="flex flex-col sm:flex-row gap-4 sm:gap-6 text-gray-600 p-4 sm:p-0">
<li> <li>
<a href="/" className="hover:text-indigo-600"> <a href="/" className="hover:text-indigo-600">
Accueil Accueil
@ -26,11 +37,22 @@ function Header() {
Gestion Gestion
</a> </a>
</li> </li>
<li className="sm:hidden">
<a href="/login" className="hover:text-indigo-600 flex items-center gap-2">
<LogIn size={20} />
Connexion
</a>
</li>
<li className="sm:hidden">
<a href="/signup" className="hover:text-indigo-600 flex items-center gap-2">
<UserPlus size={20} />
Inscription
</a>
</li>
</ul> </ul>
</nav> </nav>
{/* Actions */} <div className="hidden sm:flex gap-4">
<div className="flex gap-4">
<button className="flex items-center gap-2 text-gray-600 hover:text-indigo-600"> <button className="flex items-center gap-2 text-gray-600 hover:text-indigo-600">
<LogIn size={20} /> <LogIn size={20} />
<span>Connexion</span> <span>Connexion</span>

View File

@ -18,7 +18,7 @@ function InfoObject({ object,defafficherModif }) {
<div className="flex items-center gap-4 mb-1"> <div className="flex items-center gap-4 mb-1">
<p className="text-black-900 font-bold">Type :</p> <p className="text-black-900 font-bold">Type :</p>
<p className="text-gray-600">{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="flex items-center gap-4 mb-1">
@ -28,7 +28,7 @@ function InfoObject({ object,defafficherModif }) {
<div className="flex items-center gap-4 mb-1"> <div className="flex items-center gap-4 mb-1">
<p className="text-black-900 font-bold">Status :</p> <p className="text-black-900 font-bold">Status :</p>
<p className="text-gray-600">{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="flex items-center gap-4 mb-1">

View File

@ -33,7 +33,6 @@ function MeteoGraph({ object, categorie, Logo }) {
}); });
return moyenne / rawData.length; return moyenne / rawData.length;
} }
console.log(getAvg());
return ( return (
<div <div
key={object.id} key={object.id}
@ -81,7 +80,7 @@ function MeteoGraph({ object, categorie, Logo }) {
stroke="#8884d8" stroke="#8884d8"
activeDot={{ r: 8 }} activeDot={{ r: 8 }}
/> />
<ReferenceLine y={getAvg()} label="Moy" stroke="red" /> <ReferenceLine y={getAvg()} label="Moyenne" stroke="red" />
</LineChart> </LineChart>
</ResponsiveContainer> </ResponsiveContainer>
</div> </div>

View File

@ -4,6 +4,7 @@ import React, { useEffect, useState } from "react";
import axios from "axios"; import axios from "axios";
import { API_BASE_URL } from "../config"; import { API_BASE_URL } from "../config";
import BoutonGraphique from "./BoutonGraphique"; import BoutonGraphique from "./BoutonGraphique";
import AlertInactive from "./AlertInactive";
function MeteoInfos({ function MeteoInfos({
object, object,
@ -15,17 +16,24 @@ function MeteoInfos({
AffHumiditeGraph, AffHumiditeGraph,
}) { }) {
const [rawData, setRawData] = useState([]); const [rawData, setRawData] = useState([]);
const [AffAlert,setAffAlert] = useState(false);
const identifiant = object.id; const identifiant = object.id;
useEffect(() => { useEffect(() => {
axios.get(`${API_BASE_URL}/meteo?id=${identifiant}`).then((response) => { axios.get(`${API_BASE_URL}/meteo?id=${identifiant}`).then((response) => {
setRawData(response.data); setRawData(response.data);
if(rawData.length <5){
setAffAlert(true);
}
}); });
}, [object]); }, [object]);
const lastData = rawData.length > 0 ? rawData[rawData.length - 1] : null; const lastData = rawData.length > 0 ? rawData[rawData.length - 1] : null;
console.log(rawData.length);
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">
{(AffAlert) && (
<AlertInactive affAlert={AffAlert} setAffAlert={setAffAlert} />
)}
<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-4">
<Sun className="text-indigo-600" size={24} /> <Sun className="text-indigo-600" size={24} />
@ -39,10 +47,10 @@ function MeteoInfos({
<div className="flex align-items gap-3 w-full justify-between"> <div className="flex align-items gap-3 w-full justify-between">
<div className="flex align-items ml-3 gap-2"> <div className="flex align-items ml-3 gap-2">
<div className="flex items-center"> <div className="flex items-center">
<Thermometer className="text-red-600" size={40} /> <Thermometer className="text-indigo-600" size={40} />
</div> </div>
<div className="flex flex-col items-start"> <div className="flex flex-col items-start">
<h1 className="text-red-600 text-xl font-bold "> <h1 className="text-indigo-600 text-xl font-bold ">
Température Température
</h1> </h1>
<h1 className="text-gray-700 text-4xl font-bold"> <h1 className="text-gray-700 text-4xl font-bold">
@ -62,10 +70,10 @@ function MeteoInfos({
<div className="flex align-items gap-3 w-full justify-between"> <div className="flex align-items gap-3 w-full justify-between">
<div className="flex align-items ml-3 gap-2"> <div className="flex align-items ml-3 gap-2">
<div className="flex items-center"> <div className="flex items-center">
<CircleGauge className="text-red-600" size={40} /> <CircleGauge className="text-indigo-600" size={40} />
</div> </div>
<div className="flex flex-col items-start"> <div className="flex flex-col items-start">
<h1 className="text-red-600 text-xl font-bold "> <h1 className="text-indigo-600 text-xl font-bold ">
Pression Pression
</h1> </h1>
<h1 className="text-gray-700 text-4xl font-bold"> <h1 className="text-gray-700 text-4xl font-bold">
@ -85,10 +93,10 @@ function MeteoInfos({
<div className="flex align-items gap-3 w-full justify-between"> <div className="flex align-items gap-3 w-full justify-between">
<div className="flex align-items ml-3 gap-2"> <div className="flex align-items ml-3 gap-2">
<div className="flex items-center"> <div className="flex items-center">
<Droplet className="text-red-600" size={40} /> <Droplet className="text-indigo-600" size={40} />
</div> </div>
<div className="flex flex-col items-start"> <div className="flex flex-col items-start">
<h1 className="text-red-600 text-xl font-bold "> <h1 className="text-indigo-600 text-xl font-bold ">
Humidité Humidité
</h1> </h1>
<h1 className="text-gray-700 text-4xl font-bold"> <h1 className="text-gray-700 text-4xl font-bold">

View File

@ -1,24 +1,25 @@
import React, { use } from "react"; import React, { use } from "react";
import { Info } from "lucide-react"; import { Check, Info } from "lucide-react";
import { useState } from "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";
function ModifObject({ object,defafficherModif }) { 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 || "");
const [response, setResponse] = useState(null); const [Response, setResponse] = useState(null);
const [isActive,setActive] = useState(object.status==="active");
function makeChange(){ function makeChange() {
axios axios
.post(`${API_BASE_URL}/modifObjet`, { .post(`${API_BASE_URL}/modifObjet`, {
id : object.id, id: object.id,
description: description, description: description,
type: type, type: type,
location: location, location: location,
status: status status: status,
}) })
.then((response) => { .then((response) => {
setResponse(response.data[0]); setResponse(response.data[0]);
@ -26,20 +27,26 @@ function ModifObject({ object,defafficherModif }) {
defafficherModif(false); defafficherModif(false);
window.location.reload(); window.location.reload();
} }
function cancelChange(){ function cancelChange() {
defafficherModif(false); defafficherModif(false);
} }
function handleDescriptionChange(event){ function handleDescriptionChange(event) {
setDescription(event.target.value); setDescription(event.target.value);
} }
function handleTypeChange(event){ function handleTypeChange(event) {
setType(event.target.value); setType(event.target.value);
} }
function handleLocalisationChange(event){ function handleLocalisationChange(event) {
setLocalisation(event.target.value); setLocalisation(event.target.value);
} }
function handleStatusChange(event){ function handleStatusChange(event) {
setStatus(event.target.value); setActive((prevIsActive) => {
const newIsActive = !prevIsActive;
const newStatus = newIsActive ? "active" : "inactive";
console.log(newStatus);
setStatus(newStatus);
return newIsActive;
});
} }
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">
@ -47,31 +54,86 @@ function ModifObject({ object,defafficherModif }) {
<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 ">Modifier les infos</h1> <h1 className="text-black text-2xl font-bold mb-1 ">
Modifier les infos
</h1>
</div> </div>
<div className="flex flex-col gap-4"> <div className="flex flex-col gap-4">
<div className="flex items-center gap-4 mb-1"> <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>
<input className="text-gray-600 border" type="text" value={description} onChange={handleDescriptionChange}/> <input
className="text-gray-600 border"
type="text"
value={description}
onChange={handleDescriptionChange}
/>
</div> </div>
<div className="flex items-center gap-4 mb-1"> <div className="flex items-center gap-4 mb-1">
<p className="text-black-900 font-bold">Type :</p> <p className="text-black-900 font-bold">Type :</p>
<input className="text-gray-600 border" type="text" value={type} onChange={handleTypeChange}/> <input
className="text-gray-600 border"
type="text"
value={type}
onChange={handleTypeChange}
/>
</div> </div>
<div className="flex items-center gap-4 mb-1"> <div className="flex items-center gap-4 mb-1">
<p className="text-black-900 font-bold">Localisation :</p> <p className="text-black-900 font-bold">Localisation :</p>
<input className="text-gray-600 border" type="text" value={location} onChange={handleLocalisationChange}/> <input
className="text-gray-600 border"
type="text"
value={location}
onChange={handleLocalisationChange}
/>
</div> </div>
<div className="flex items-center gap-4 mb-1"> <div className="flex items-center gap-4 mb-1">
<p className="text-black-900 font-bold">Status :</p> <p className="text-black-900 font-bold">Status :</p>
<input className="text-gray-600 border" type="text" value={status} onChange={handleStatusChange}/> <div class="inline-flex items-center gap-2">
<label
htmlFor="switch-component-on"
className="text-slate-600 text-sm cursor-pointer"
>
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>
<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={(()=>makeChange())}>Confirmer les modifs</a> <a
<a className="text-blue-500 hover:cursor-pointer" onClick={(()=>cancelChange())}>Annuler les modifs</a> className="text-blue-500 hover:cursor-pointer"
onClick={() => makeChange()}
>
Confirmer les modifs
</a>
<a
className="text-blue-500 hover:cursor-pointer"
onClick={() => cancelChange()}
>
Annuler les modifs
</a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -3,6 +3,7 @@ import React, { useEffect, useState } from "react";
import axios from "axios"; import axios from "axios";
import { API_BASE_URL } from "../config"; import { API_BASE_URL } from "../config";
import BoutonGraphique from "./BoutonGraphique";
function WindInfo({ object, defAffWindGraph, AffWindGraph }) { function WindInfo({ object, defAffWindGraph, AffWindGraph }) {
const [rawData, setRawData] = useState([]); const [rawData, setRawData] = useState([]);
@ -18,52 +19,40 @@ function WindInfo({ object, defAffWindGraph, AffWindGraph }) {
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">
<Wind className="text-indigo-600" size={24} /> <Wind className="text-indigo-600" size={24} />
</div> </div>
<h1 className="text-black text-2xl font-bold mb-1 ">Vent actuel</h1> <h1 className="text-black text-2xl font-bold">Vent actuel</h1>
</div> </div>
{lastData ? ( {lastData ? (
<div className="flex flex-col items-center gap-4"> <div className="flex flex-col items-center gap-1">
<div className="flex flex-row gap-4">
<div className="flex flex-col items-center g-2">
<img <img
src={`./src/img/${lastData.wind_direction}.png`} src={`./src/img/${lastData.wind_direction}.png`}
alt="Wind Direction" alt="Wind Direction"
className="h-45" className="h-25"
/> />
<h1 className="text-gray-600 text-xl font-bold mb-1 "> <h1 className="text-gray-600 text-xl font-bold mb-1 ">
{lastData.wind_direction} {lastData.wind_direction}
</h1> </h1>
</div> <div className="bg-indigo-50 rounded-lg flex flex-col items-center mb-1 w-full">
<div className="flex flex-col items-center gap-4"> <div className="flex align-items gap-3 w-full justify-between">
<div className="flex align-items gap-1"> <div className="flex align-items ml-3 gap-2">
<div className="flex items-center"> <div className="flex items-center">
<Wind className="text-red-600" size={24} /> <Wind className="text-indigo-600" size={40} />
</div>
<h1 className="text-red-600 text-xl font-bold ">Valeur</h1>
</div> </div>
<div className="flex flex-col items-start">
<h1 className="text-indigo-600 text-xl font-bold ">Valeur</h1>
<h1 className="text-gray-700 text-4xl font-bold"> <h1 className="text-gray-700 text-4xl font-bold">
{lastData.wind_speed} <span className="text-lg">km/h</span> {lastData.wind_speed} <span className="text-lg">Km/h</span>
</h1> </h1>
</div> </div>
</div> </div>
{!AffWindGraph ? ( <BoutonGraphique
<button TypeAff={AffWindGraph}
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 mt-4 px-4 rounded-full" setAffichage={defAffWindGraph}
onClick={() => defAffWindGraph(true)} />
> </div>
Afficher l'historique </div>
</button>
) : (
<button
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 mt-4 px-4 rounded-full"
onClick={() => defAffWindGraph(false)}
>
Masquer l'historique
</button>
)}
<h1 className="text-gray-500 text-sm"> <h1 className="text-gray-500 text-sm">
Dernier enregistrement : {lastData.timestamp} Dernier enregistrement : {lastData.timestamp}
</h1> </h1>

View File

@ -22,7 +22,7 @@ function Gestion() {
Bienvenue dans le module <b>Gestion</b>. Bienvenue dans le module <b>Gestion</b>.
</h2> </h2>
<p className="text-xl text-gray-600 max-w-3xl mx-auto"> <p className="text-xl text-gray-600 max-w-3xl mx-auto">
Ce module vous permet de gérer les objets connectés de l'hôpital de manière simple et efficace. Ce module vous permet de gérer les capteur et stations connectés de France de manière simple et efficace.
</p> </p>
</div> </div>

View File

@ -14,12 +14,34 @@ import {
} from "lucide-react"; } from "lucide-react";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import axios from "axios"; import axios from "axios";
import { useFetcher } from "react-router-dom";
function ObjectManagement() { function ObjectManagement() {
const [searchQuery, setSearchQuery] = useState(""); const [searchQuery, setSearchQuery] = useState("");
const [activeFilter, setActiveFilter] = useState("all"); const [activeFilter, setActiveFilter] = useState("");
const [objects, setObjects] = useState([]); const [objects, setObjects] = useState([]);
const filteredDATA = objects.filter((node) => {
const matchesSearchQuery =
searchQuery === "" ||
node.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
node.description.toLowerCase().includes(searchQuery.toLowerCase());
const matchesTag =
activeFilter === "" ||
node.name.toLowerCase().includes(activeFilter.toLowerCase()) ||
node.description.includes(activeFilter.toLowerCase())||
(activeFilter=== "Active" && node.status.toLowerCase()==="active")||
(activeFilter=== "Inactive" && node.status.toLowerCase()==="inactive");
return matchesSearchQuery && matchesTag;
});
const handleSearchChange = (event) => {
setSearchQuery(event.target.value);
};
const handleTagFilterChange = (selectedTags) => {
setFilterTags(selectedTags);
};
useEffect(() => { useEffect(() => {
axios.get("http://localhost:8888/objets").then((response) => { axios.get("http://localhost:8888/objets").then((response) => {
setObjects(response.data); setObjects(response.data);
@ -49,9 +71,9 @@ function ObjectManagement() {
</div> </div>
<div className="flex gap-4 mt-4 justify-center"> <div className="flex gap-4 mt-4 justify-center">
<button <button
onClick={() => setActiveFilter("all")} onClick={() => setActiveFilter("")}
className={`px-4 py-2 rounded-lg ${ className={`px-4 py-2 rounded-lg ${
activeFilter === "all" activeFilter === ""
? "bg-indigo-600 text-white" ? "bg-indigo-600 text-white"
: "bg-white text-gray-600" : "bg-white text-gray-600"
}`} }`}
@ -59,19 +81,9 @@ function ObjectManagement() {
Tout Tout
</button> </button>
<button <button
onClick={() => setActiveFilter("locations")} onClick={() => setActiveFilter("Station")}
className={`px-4 py-2 rounded-lg ${ className={`px-4 py-2 rounded-lg ${
activeFilter === "locations" activeFilter === "Station"
? "bg-indigo-600 text-white"
: "bg-white text-gray-600"
}`}
>
Villes
</button>
<button
onClick={() => setActiveFilter("events")}
className={`px-4 py-2 rounded-lg ${
activeFilter === "events"
? "bg-indigo-600 text-white" ? "bg-indigo-600 text-white"
: "bg-white text-gray-600" : "bg-white text-gray-600"
}`} }`}
@ -79,29 +91,66 @@ function ObjectManagement() {
Station météo Station météo
</button> </button>
<button <button
onClick={() => setActiveFilter("transport")} onClick={() => setActiveFilter("Capteur")}
className={`px-4 py-2 rounded-lg ${ className={`px-4 py-2 rounded-lg ${
activeFilter === "transport" activeFilter === "Capteur"
? "bg-indigo-600 text-white" ? "bg-indigo-600 text-white"
: "bg-white text-gray-600" : "bg-white text-gray-600"
}`} }`}
> >
Capteur Capteur
</button> </button>
<button
onClick={() => setActiveFilter("Active")}
className={`px-4 py-2 rounded-lg ${
activeFilter === "Active"
? "bg-indigo-600 text-white"
: "bg-white text-gray-600"
}`}
>
Actif
</button>
<button
onClick={() => setActiveFilter("Inactive")}
className={`px-4 py-2 rounded-lg ${
activeFilter === "Inactive"
? "bg-indigo-600 text-white"
: "bg-white text-gray-600"
}`}
>
Inactif
</button>
</div> </div>
</div> </div>
<div className="grid md:grid-cols-3 gap-8"> <div className="grid md:grid-cols-3 gap-8">
{objects.map(object =>( {filteredDATA.length === 0 ? (
<div key={object.id} className="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition-shadow"> <p>Aucun objet trouvé</p>
) : (
filteredDATA.map((object) => (
<div
key={object.id}
className="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition-shadow "
>
{(object.status==="active")?(
<div className="relative w-full">
<span className="absolute right-0 flex size-3">
<span className="absolute inline-flex h-full w-full rounded-full animate-ping bg-green-400 opacity-75"></span>
<span className="relative inline-flex size-3 rounded-full bg-green-500"></span>
</span>
</div>
):(
<div className="relative w-full">
<span className="absolute right-0 flex size-3">
<span className="relative inline-flex size-3 rounded-full bg-red-600"></span>
</span>
</div>
)}
<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} />
</div> </div>
<h3 className="text-xl font-semibold mb-2"> <h3 className="text-xl font-semibold mb-2">{object.name}</h3>
{object.name} <p className="text-gray-600 mb-4">{object.description}</p>
</h3>
<p className="text-gray-600 mb-4">
{object.description}
</p>
<a <a
href={`/objet?id=${object.id}`} href={`/objet?id=${object.id}`}
className="flex items-center text-indigo-600 hover:text-indigo-700" className="flex items-center text-indigo-600 hover:text-indigo-700"
@ -109,7 +158,8 @@ function ObjectManagement() {
Plus d'infos <ArrowRight size={16} className="ml-2" /> Plus d'infos <ArrowRight size={16} className="ml-2" />
</a> </a>
</div> </div>
))} ))
)}
</div> </div>
</div> </div>
</div> </div>

View File

@ -3,7 +3,6 @@ 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 { useFetcher } from "react-router-dom";
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";
@ -37,10 +36,9 @@ function Objet() {
</h2> </h2>
</div> </div>
<div className="grid md:grid-cols-3 gap-8 mb-5"> <div className="grid md:grid-cols-3 gap-8 mb-5">
{!afficherModif && ( {(!afficherModif) ? (
<InfoObjet object={object} defafficherModif={defafficherModif} /> <InfoObjet object={object} defafficherModif={defafficherModif} />
)} ):(
{afficherModif && (
<ModifObject object={object} defafficherModif={defafficherModif} /> <ModifObject object={object} defafficherModif={defafficherModif} />
)} )}