Amélioration de l'affichage
This commit is contained in:
parent
d229dc9467
commit
b278cb16e1
22
Front-end/src/components/AlertInactive.jsx
Normal file
22
Front-end/src/components/AlertInactive.jsx
Normal 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 dû à son manque de données. Vous pouvez le
|
||||
rendre inactif en appuyant <a>ici</a>.
|
||||
</p>
|
||||
</div>
|
||||
)));
|
||||
}
|
||||
|
||||
export default AlertInactive;
|
||||
@ -6,14 +6,14 @@ function BoutonGraphique({ TypeAff, setAffichage }) {
|
||||
className="bg-blue-200 py-2 my-2 px-4 rounded-full mr-2"
|
||||
onClick={() => setAffichage(true)}
|
||||
>
|
||||
<ChartLine className="text-red-500" size={24} />
|
||||
<ChartLine className="text-indigo-600" size={24} />
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
className="bg-blue-400 py-2 my-2 px-4 rounded-full mr-2"
|
||||
onClick={() => setAffichage(false)}
|
||||
>
|
||||
<ChartLine className="text-red-500" size={24} />
|
||||
<ChartLine className="text-indigo-600" size={24} />
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,16 +1,27 @@
|
||||
import React from "react";
|
||||
import { LogIn, UserPlus } from "lucide-react";
|
||||
import React, { useState } from "react";
|
||||
import { LogIn, UserPlus, Menu, X } from "lucide-react";
|
||||
|
||||
function Header() {
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<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">
|
||||
{/* Logo */}
|
||||
<div className=" max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-4 flex justify-between items-center">
|
||||
<h1 className="text-2xl font-bold text-indigo-600">VigiMétéo</h1>
|
||||
|
||||
{/* Navigation */}
|
||||
<nav>
|
||||
<ul className="flex gap-6 text-gray-600">
|
||||
<button
|
||||
className="sm:hidden text-gray-600 hover:text-indigo-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>
|
||||
<a href="/" className="hover:text-indigo-600">
|
||||
Accueil
|
||||
@ -26,11 +37,22 @@ function Header() {
|
||||
Gestion
|
||||
</a>
|
||||
</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>
|
||||
</nav>
|
||||
|
||||
{/* Actions */}
|
||||
<div className="flex gap-4">
|
||||
<div className="hidden sm:flex gap-4">
|
||||
<button className="flex items-center gap-2 text-gray-600 hover:text-indigo-600">
|
||||
<LogIn size={20} />
|
||||
<span>Connexion</span>
|
||||
|
||||
@ -18,7 +18,7 @@ function InfoObject({ object,defafficherModif }) {
|
||||
|
||||
<div className="flex items-center gap-4 mb-1">
|
||||
<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 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">
|
||||
<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 className="flex items-center gap-4 mb-1">
|
||||
|
||||
@ -33,7 +33,6 @@ function MeteoGraph({ object, categorie, Logo }) {
|
||||
});
|
||||
return moyenne / rawData.length;
|
||||
}
|
||||
console.log(getAvg());
|
||||
return (
|
||||
<div
|
||||
key={object.id}
|
||||
@ -81,7 +80,7 @@ function MeteoGraph({ object, categorie, Logo }) {
|
||||
stroke="#8884d8"
|
||||
activeDot={{ r: 8 }}
|
||||
/>
|
||||
<ReferenceLine y={getAvg()} label="Moy" stroke="red" />
|
||||
<ReferenceLine y={getAvg()} label="Moyenne" stroke="red" />
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
|
||||
@ -4,6 +4,7 @@ import React, { useEffect, useState } from "react";
|
||||
import axios from "axios";
|
||||
import { API_BASE_URL } from "../config";
|
||||
import BoutonGraphique from "./BoutonGraphique";
|
||||
import AlertInactive from "./AlertInactive";
|
||||
|
||||
function MeteoInfos({
|
||||
object,
|
||||
@ -15,17 +16,24 @@ function MeteoInfos({
|
||||
AffHumiditeGraph,
|
||||
}) {
|
||||
const [rawData, setRawData] = useState([]);
|
||||
const [AffAlert,setAffAlert] = useState(false);
|
||||
const identifiant = object.id;
|
||||
useEffect(() => {
|
||||
axios.get(`${API_BASE_URL}/meteo?id=${identifiant}`).then((response) => {
|
||||
setRawData(response.data);
|
||||
if(rawData.length <5){
|
||||
setAffAlert(true);
|
||||
}
|
||||
});
|
||||
}, [object]);
|
||||
|
||||
const lastData = rawData.length > 0 ? rawData[rawData.length - 1] : null;
|
||||
|
||||
console.log(rawData.length);
|
||||
return (
|
||||
<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="w-12 h-12 bg-indigo-100 rounded-lg flex items-center justify-center mb-4">
|
||||
<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 ml-3 gap-2">
|
||||
<div className="flex items-center">
|
||||
<Thermometer className="text-red-600" size={40} />
|
||||
<Thermometer className="text-indigo-600" size={40} />
|
||||
</div>
|
||||
<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
|
||||
</h1>
|
||||
<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 ml-3 gap-2">
|
||||
<div className="flex items-center">
|
||||
<CircleGauge className="text-red-600" size={40} />
|
||||
<CircleGauge className="text-indigo-600" size={40} />
|
||||
</div>
|
||||
<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
|
||||
</h1>
|
||||
<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 ml-3 gap-2">
|
||||
<div className="flex items-center">
|
||||
<Droplet className="text-red-600" size={40} />
|
||||
<Droplet className="text-indigo-600" size={40} />
|
||||
</div>
|
||||
<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é
|
||||
</h1>
|
||||
<h1 className="text-gray-700 text-4xl font-bold">
|
||||
|
||||
@ -1,24 +1,25 @@
|
||||
import React, { use } from "react";
|
||||
import { Info } from "lucide-react";
|
||||
import { Check, Info } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import axios from "axios";
|
||||
import { API_BASE_URL } from "../config";
|
||||
|
||||
function ModifObject({ object,defafficherModif }) {
|
||||
const [description,setDescription] = useState(object.description || "");
|
||||
const [type,setType] = useState(object.type || "");
|
||||
const [location,setLocalisation] = useState(object.location || "");
|
||||
const [status,setStatus] = useState(object.status || "");
|
||||
const [response, setResponse] = useState(null);
|
||||
function ModifObject({ object, defafficherModif }) {
|
||||
const [description, setDescription] = useState(object.description || "");
|
||||
const [type, setType] = useState(object.type || "");
|
||||
const [location, setLocalisation] = useState(object.location || "");
|
||||
const [status, setStatus] = useState(object.status || "");
|
||||
const [Response, setResponse] = useState(null);
|
||||
const [isActive,setActive] = useState(object.status==="active");
|
||||
|
||||
function makeChange(){
|
||||
function makeChange() {
|
||||
axios
|
||||
.post(`${API_BASE_URL}/modifObjet`, {
|
||||
id : object.id,
|
||||
id: object.id,
|
||||
description: description,
|
||||
type: type,
|
||||
location: location,
|
||||
status: status
|
||||
status: status,
|
||||
})
|
||||
.then((response) => {
|
||||
setResponse(response.data[0]);
|
||||
@ -26,20 +27,26 @@ function ModifObject({ object,defafficherModif }) {
|
||||
defafficherModif(false);
|
||||
window.location.reload();
|
||||
}
|
||||
function cancelChange(){
|
||||
function cancelChange() {
|
||||
defafficherModif(false);
|
||||
}
|
||||
function handleDescriptionChange(event){
|
||||
function handleDescriptionChange(event) {
|
||||
setDescription(event.target.value);
|
||||
}
|
||||
function handleTypeChange(event){
|
||||
function handleTypeChange(event) {
|
||||
setType(event.target.value);
|
||||
}
|
||||
function handleLocalisationChange(event){
|
||||
function handleLocalisationChange(event) {
|
||||
setLocalisation(event.target.value);
|
||||
}
|
||||
function handleStatusChange(event){
|
||||
setStatus(event.target.value);
|
||||
function handleStatusChange(event) {
|
||||
setActive((prevIsActive) => {
|
||||
const newIsActive = !prevIsActive;
|
||||
const newStatus = newIsActive ? "active" : "inactive";
|
||||
console.log(newStatus);
|
||||
setStatus(newStatus);
|
||||
return newIsActive;
|
||||
});
|
||||
}
|
||||
return (
|
||||
<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">
|
||||
<Info className="text-indigo-600" size={24} />
|
||||
</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 className="flex flex-col gap-4">
|
||||
<div className="flex items-center gap-4 mb-1">
|
||||
<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 className="flex items-center gap-4 mb-1">
|
||||
<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 className="flex items-center gap-4 mb-1">
|
||||
<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 className="flex items-center gap-4 mb-1">
|
||||
<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 className="flex items-center gap-4 mb-1">
|
||||
<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>
|
||||
<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>
|
||||
|
||||
@ -3,6 +3,7 @@ import React, { useEffect, useState } from "react";
|
||||
|
||||
import axios from "axios";
|
||||
import { API_BASE_URL } from "../config";
|
||||
import BoutonGraphique from "./BoutonGraphique";
|
||||
|
||||
function WindInfo({ object, defAffWindGraph, AffWindGraph }) {
|
||||
const [rawData, setRawData] = useState([]);
|
||||
@ -18,52 +19,40 @@ function WindInfo({ object, defAffWindGraph, AffWindGraph }) {
|
||||
return (
|
||||
<div key={object.id} className="bg-white p-6 rounded-xl min-w-5xl">
|
||||
<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} />
|
||||
</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>
|
||||
{lastData ? (
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<div className="flex flex-row gap-4">
|
||||
<div className="flex flex-col items-center g-2">
|
||||
<img
|
||||
src={`./src/img/${lastData.wind_direction}.png`}
|
||||
alt="Wind Direction"
|
||||
className="h-45"
|
||||
/>
|
||||
<h1 className="text-gray-600 text-xl font-bold mb-1 ">
|
||||
{lastData.wind_direction}
|
||||
</h1>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<div className="flex align-items gap-1">
|
||||
<div className="flex flex-col items-center gap-1">
|
||||
<img
|
||||
src={`./src/img/${lastData.wind_direction}.png`}
|
||||
alt="Wind Direction"
|
||||
className="h-25"
|
||||
/>
|
||||
<h1 className="text-gray-600 text-xl font-bold mb-1 ">
|
||||
{lastData.wind_direction}
|
||||
</h1>
|
||||
<div className="bg-indigo-50 rounded-lg flex flex-col items-center mb-1 w-full">
|
||||
<div className="flex align-items gap-3 w-full justify-between">
|
||||
<div className="flex align-items ml-3 gap-2">
|
||||
<div className="flex items-center">
|
||||
<Wind className="text-red-600" size={24} />
|
||||
<Wind className="text-indigo-600" size={40} />
|
||||
</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">
|
||||
{lastData.wind_speed} <span className="text-lg">Km/h</span>
|
||||
</h1>
|
||||
</div>
|
||||
<h1 className="text-red-600 text-xl font-bold ">Valeur</h1>
|
||||
</div>
|
||||
<h1 className="text-gray-700 text-4xl font-bold">
|
||||
{lastData.wind_speed} <span className="text-lg">km/h</span>
|
||||
</h1>
|
||||
<BoutonGraphique
|
||||
TypeAff={AffWindGraph}
|
||||
setAffichage={defAffWindGraph}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{!AffWindGraph ? (
|
||||
<button
|
||||
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 mt-4 px-4 rounded-full"
|
||||
onClick={() => defAffWindGraph(true)}
|
||||
>
|
||||
Afficher l'historique
|
||||
</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">
|
||||
Dernier enregistrement : {lastData.timestamp}
|
||||
</h1>
|
||||
|
||||
@ -22,7 +22,7 @@ function Gestion() {
|
||||
Bienvenue dans le module <b>Gestion</b>.
|
||||
</h2>
|
||||
<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>
|
||||
</div>
|
||||
|
||||
|
||||
@ -14,12 +14,34 @@ import {
|
||||
} from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import axios from "axios";
|
||||
import { useFetcher } from "react-router-dom";
|
||||
|
||||
function ObjectManagement() {
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [activeFilter, setActiveFilter] = useState("all");
|
||||
const [activeFilter, setActiveFilter] = 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(() => {
|
||||
axios.get("http://localhost:8888/objets").then((response) => {
|
||||
setObjects(response.data);
|
||||
@ -49,9 +71,9 @@ function ObjectManagement() {
|
||||
</div>
|
||||
<div className="flex gap-4 mt-4 justify-center">
|
||||
<button
|
||||
onClick={() => setActiveFilter("all")}
|
||||
onClick={() => setActiveFilter("")}
|
||||
className={`px-4 py-2 rounded-lg ${
|
||||
activeFilter === "all"
|
||||
activeFilter === ""
|
||||
? "bg-indigo-600 text-white"
|
||||
: "bg-white text-gray-600"
|
||||
}`}
|
||||
@ -59,19 +81,9 @@ function ObjectManagement() {
|
||||
Tout
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveFilter("locations")}
|
||||
onClick={() => setActiveFilter("Station")}
|
||||
className={`px-4 py-2 rounded-lg ${
|
||||
activeFilter === "locations"
|
||||
? "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"
|
||||
activeFilter === "Station"
|
||||
? "bg-indigo-600 text-white"
|
||||
: "bg-white text-gray-600"
|
||||
}`}
|
||||
@ -79,37 +91,75 @@ function ObjectManagement() {
|
||||
Station météo
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveFilter("transport")}
|
||||
onClick={() => setActiveFilter("Capteur")}
|
||||
className={`px-4 py-2 rounded-lg ${
|
||||
activeFilter === "transport"
|
||||
activeFilter === "Capteur"
|
||||
? "bg-indigo-600 text-white"
|
||||
: "bg-white text-gray-600"
|
||||
}`}
|
||||
>
|
||||
Capteur
|
||||
</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 className="grid md:grid-cols-3 gap-8">
|
||||
{objects.map(object =>(
|
||||
<div key={object.id} className="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition-shadow">
|
||||
{filteredDATA.length === 0 ? (
|
||||
<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">
|
||||
<RadioTower className="text-indigo-600" size={24} />
|
||||
<RadioTower className="text-indigo-600" size={24} />
|
||||
</div>
|
||||
<h3 className="text-xl font-semibold mb-2">
|
||||
{object.name}
|
||||
</h3>
|
||||
<p className="text-gray-600 mb-4">
|
||||
{object.description}
|
||||
</p>
|
||||
<h3 className="text-xl font-semibold mb-2">{object.name}</h3>
|
||||
<p className="text-gray-600 mb-4">{object.description}</p>
|
||||
<a
|
||||
href={`/objet?id=${object.id}`}
|
||||
className="flex items-center text-indigo-600 hover:text-indigo-700"
|
||||
href={`/objet?id=${object.id}`}
|
||||
className="flex items-center text-indigo-600 hover:text-indigo-700"
|
||||
>
|
||||
Plus d'infos <ArrowRight size={16} className="ml-2" />
|
||||
Plus d'infos <ArrowRight size={16} className="ml-2" />
|
||||
</a>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -3,7 +3,6 @@ import { Thermometer, CircleGauge, Droplet } from "lucide-react";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import axios from "axios";
|
||||
import { useFetcher } from "react-router-dom";
|
||||
import InfoObjet from "../../components/InfoObject";
|
||||
import ModifObject from "../../components/ModifObject";
|
||||
import WindGraph from "../../components/WindGraph";
|
||||
@ -37,10 +36,9 @@ function Objet() {
|
||||
</h2>
|
||||
</div>
|
||||
<div className="grid md:grid-cols-3 gap-8 mb-5">
|
||||
{!afficherModif && (
|
||||
{(!afficherModif) ? (
|
||||
<InfoObjet object={object} defafficherModif={defafficherModif} />
|
||||
)}
|
||||
{afficherModif && (
|
||||
):(
|
||||
<ModifObject object={object} defafficherModif={defafficherModif} />
|
||||
)}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user