Ajout du responsive dashboard

This commit is contained in:
Mathis 2025-04-13 15:18:27 +02:00
parent 0cfd237f07
commit ae94dc9339
3 changed files with 62 additions and 72 deletions

View File

@ -78,8 +78,8 @@ public class QueryDeleteObject {
.put("id", row.getInteger("id")) .put("id", row.getInteger("id"))
.put("object_id", row.getInteger("object_id")) .put("object_id", row.getInteger("object_id"))
.put("requested_by", row.getInteger("requested_by")) .put("requested_by", row.getInteger("requested_by"))
.put("requested_at", row.getLocalDateTime("requested_at").toString()); // si tu as un champ .put("requested_at", row.getLocalDateTime("requested_at").toString());
// de type timestamp
jsonArray.add(json); jsonArray.add(json);
}); });

View File

@ -352,7 +352,7 @@ function AdminObjet() {
{deleteRequests.map((request) => ( {deleteRequests.map((request) => (
<tr key={request.id}> <tr key={request.id}>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{request.id}</td> <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{request.id}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{request.object_id}</td> <td className="px-6 py-4 whitespace-nowrap text-sm"><a className="text-indigo-600 hover:underline" href={`/objet?id=${request.object_id}`}>Objet n°{request.object_id}</a></td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{request.requested_by}</td> <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{request.requested_by}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{request.request_date}</td> <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{request.request_date}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900 flex gap-2"> <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900 flex gap-2">

View File

@ -1,4 +1,4 @@
import React, { useState,useEffect } from "react"; import React, { useState, useEffect } from "react";
import Sidebar from "./sidebar.jsx"; import Sidebar from "./sidebar.jsx";
import { RadioTower, ArrowRight, BadgePlus, Settings } from "lucide-react"; import { RadioTower, ArrowRight, BadgePlus, Settings } from "lucide-react";
import { API_BASE_URL } from "../../config.js"; import { API_BASE_URL } from "../../config.js";
@ -17,11 +17,7 @@ const exportCSV = () => {
const csvContent = const csvContent =
"\uFEFF" + "\uFEFF" +
[headers, ...rows] [headers, ...rows]
.map((row) => .map((row) => row.map((val) => `"${val.replace(/"/g, '""')}"`).join(","))
row
.map((val) => `"${val.replace(/"/g, '""')}"`)
.join(",")
)
.join("\n"); .join("\n");
const blob = new Blob([csvContent], { const blob = new Blob([csvContent], {
@ -36,18 +32,17 @@ const exportCSV = () => {
document.body.removeChild(link); document.body.removeChild(link);
}; };
const initialWidgets = [ const initialWidgets = [
{ id: 1, type: "summary" }, { id: 1, type: "summary" },
{ id: 2, type: "users" }, { id: 2, type: "users" },
{ id: 3, type: "reporting" }, { id: 3, type: "reporting" },
{ id: 4, type: "adminobjet" }, { id: 4, type: "adminobjet" },
{ id: 5, type: "objects" }, { id: 5, type: "objects" },
{ id: 6, type: "requestObject" } { id: 6, type: "requestObject" },
]; ];
function Dashboard() { function Dashboard() {
const [users, setUsers] = useState([]) const [users, setUsers] = useState([]);
const [logs, setLogs] = useState([ const [logs, setLogs] = useState([
{ {
@ -74,38 +69,10 @@ function Dashboard() {
axios.get(`${API_BASE_URL}/demandeSuppression`).then((response) => { axios.get(`${API_BASE_URL}/demandeSuppression`).then((response) => {
setRequestDeleteObject(response.data); setRequestDeleteObject(response.data);
}) });
}, []); }, []);
const [adminObjects, setAdminObjects] = useState([ const [adminObjects, setAdminObjects] = useState([]);
{
id: 101,
nom: "Objet A",
description: "Description A",
type: "Type A",
localisation: "Localisation A",
proprietaire: "Propriétaire A",
status: "active",
},
{
id: 102,
nom: "Objet B",
description: "Description B",
type: "Type B",
localisation: "Localisation B",
proprietaire: "Propriétaire B",
status: "inactive",
},
{
id: 103,
nom: "Objet C",
description: "Description C",
type: "Type C",
localisation: "Localisation C",
proprietaire: "Propriétaire C",
status: "active",
},
]);
const [manageMode, setManageMode] = useState(false); const [manageMode, setManageMode] = useState(false);
const [widgets, setWidgets] = useState(initialWidgets); const [widgets, setWidgets] = useState(initialWidgets);
@ -131,16 +98,22 @@ function Dashboard() {
<Sidebar /> <Sidebar />
<main className="flex-1 bg-gradient-to-br from-blue-50 to-indigo-50 p-8 overflow-auto"> <main className="flex-1 bg-gradient-to-br from-blue-50 to-indigo-50 p-8 overflow-auto">
<div className="flex items-center justify-between mb-6"> <div className="flex items-center justify-between mb-6">
<h1 className="text-3xl font-bold">Dashboard</h1> <h1 className="text-3xl font-bold truncate mr-2">Dashboard</h1>
<button <button
onClick={() => setManageMode(!manageMode)} onClick={() => setManageMode(!manageMode)}
className="flex items-center px-4 py-2 bg-gray-200 hover:bg-gray-300 rounded-md" className="flex items-center justify-center rounded-md hover:bg-gray-300"
aria-label={
manageMode ? "Terminer la gestion" : "Gérer les widgets"
}
> >
<Settings className="mr-2" size={20} /> <span className="p-2 sm:bg-gray-200 sm:px-4 sm:py-2 sm:rounded-md flex items-center">
{manageMode ? "Terminer la gestion" : "Gérer les widgets"} <Settings size={20} className="sm:mr-2" />
<span className="hidden sm:inline">
{manageMode ? "Terminer la gestion" : "Gérer les widgets"}
</span>
</span>
</button> </button>
</div> </div>
<section> <section>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{widgets.map((widget) => ( {widgets.map((widget) => (
@ -290,30 +263,37 @@ function Dashboard() {
</div> </div>
)} )}
{widget.type ==="requestObject" && ( {widget.type === "requestObject" && (
<div> <div>
<h2 className="text-xl font-semibold mb-4">Requête suppression objets</h2> <h2 className="text-xl font-semibold mb-4">
Requête suppression objets
</h2>
<div className="mb-4"> <div className="mb-4">
<p className="text-gray-700 mb-2">Générer des rapports d'utilisation :</p> <p className="text-gray-700 mb-2">
<div className="flex gap-4"> Générer des rapports d'utilisation :
<button </p>
className="bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700" <div className="flex gap-4">
onClick={() => exportCSV()} <button
> className="bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700"
Requête objets onClick={() => exportCSV()}
</button> >
Requête objets
</button>
</div>
</div> </div>
</div> </div>
</div>
)} )}
{widget.type === "reporting" && ( {widget.type === "reporting" && (
<div> <div>
<h2 className="text-xl font-semibold mb-4">Rapports et Statistiques</h2> <h2 className="text-xl font-semibold mb-4">
Rapports et Statistiques
</h2>
<div className="mb-4"> <div className="mb-4">
<p className="text-gray-700 mb-2">Générer des rapports d'utilisation :</p> <p className="text-gray-700 mb-2">
Générer des rapports d'utilisation :
</p>
<div className="flex gap-4"> <div className="flex gap-4">
<button <button
className="bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700" className="bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700"
@ -326,15 +306,25 @@ function Dashboard() {
<div className="mt-4 space-y-2"> <div className="mt-4 space-y-2">
<div> <div>
<h4 className="text-md font-medium">Consommation énergétique totale</h4> <h4 className="text-md font-medium">
<p className="text-gray-600">1372 kWh cumulés (estimation)</p> Consommation énergétique totale
</h4>
<p className="text-gray-600">
1372 kWh cumulés (estimation)
</p>
</div> </div>
<div> <div>
<h4 className="text-md font-medium">Taux de connexion des utilisateurs</h4> <h4 className="text-md font-medium">
<p className="text-gray-600">87% des utilisateurs actifs ce mois-ci</p> Taux de connexion des utilisateurs
</h4>
<p className="text-gray-600">
87% des utilisateurs actifs ce mois-ci
</p>
</div> </div>
<div> <div>
<h4 className="text-md font-medium">Services les plus utilisés</h4> <h4 className="text-md font-medium">
Services les plus utilisés
</h4>
<ul className="list-disc ml-6 text-gray-600"> <ul className="list-disc ml-6 text-gray-600">
<li>Consultation des données météo</li> <li>Consultation des données météo</li>
<li>Alertes et suivi de consommation</li> <li>Alertes et suivi de consommation</li>
@ -393,16 +383,16 @@ function Dashboard() {
<button <button
onClick={() => handleWidgetSelection("reporting")} onClick={() => handleWidgetSelection("reporting")}
className="px-4 py-2 bg-gray-200 hover:bg-gray-300 rounded-md text-left" className="px-4 py-2 bg-gray-200 hover:bg-gray-300 rounded-md text-left"
> >
Rapports et Statistiques Rapports et Statistiques
</button> </button>
<button <button
onClick={() => handleWidgetSelection("requestObject")} onClick={() => handleWidgetSelection("requestObject")}
className="px-4 py-2 bg-gray-200 hover:bg-gray-300 rounded-md text-left" className="px-4 py-2 bg-gray-200 hover:bg-gray-300 rounded-md text-left"
> >
Demande de suppression d'objets Demande de suppression d'objets
</button> </button>
</div> </div>
<button <button
onClick={() => setShowAddWidgetModal(false)} onClick={() => setShowAddWidgetModal(false)}
className="mt-4 px-4 py-2 bg-red-500 text-white rounded-md w-full" className="mt-4 px-4 py-2 bg-red-500 text-white rounded-md w-full"