391 lines
14 KiB
JavaScript
391 lines
14 KiB
JavaScript
import React, { useState,useEffect } from "react";
|
||
import Sidebar from "./sidebar.jsx";
|
||
import { RadioTower, ArrowRight, BadgePlus, Settings } from "lucide-react";
|
||
import { API_BASE_URL } from "../../config.js";
|
||
import axios from "axios";
|
||
|
||
const exportCSV = () => {
|
||
const headers = ["Catégorie", "Valeur"];
|
||
const rows = [
|
||
["Consommation énergétique", "1372 kWh"],
|
||
["Taux de connexion", "87%"],
|
||
["Service", "Consultation des données météo"],
|
||
["Service", "Alertes et suivi de consommation"],
|
||
["Service", "Ajout d'objets connectés"],
|
||
];
|
||
|
||
const csvContent =
|
||
"\uFEFF" +
|
||
[headers, ...rows]
|
||
.map((row) =>
|
||
row
|
||
.map((val) => `"${val.replace(/"/g, '""')}"`)
|
||
.join(",")
|
||
)
|
||
.join("\n");
|
||
|
||
const blob = new Blob([csvContent], {
|
||
type: "text/csv;charset=utf-8;",
|
||
});
|
||
|
||
const link = document.createElement("a");
|
||
link.href = URL.createObjectURL(blob);
|
||
link.setAttribute("download", "rapport_plateforme.csv");
|
||
document.body.appendChild(link);
|
||
link.click();
|
||
document.body.removeChild(link);
|
||
};
|
||
|
||
|
||
const initialWidgets = [
|
||
{ id: 1, type: "summary" },
|
||
{ id: 2, type: "users" },
|
||
{ id: 3, type: "reporting" },
|
||
{ id: 4, type: "adminobjet" },
|
||
{ id: 5, type: "objects" },
|
||
];
|
||
|
||
function Dashboard() {
|
||
const [users, setUsers] = useState([])
|
||
|
||
const [logs, setLogs] = useState([
|
||
{
|
||
id: 1,
|
||
username: "complexe",
|
||
action: "Accès attribué",
|
||
timestamp: new Date().toLocaleString(),
|
||
},
|
||
{
|
||
id: 2,
|
||
username: "admin",
|
||
action: "Accès attribué",
|
||
timestamp: new Date().toLocaleString(),
|
||
},
|
||
]);
|
||
useEffect(() => {
|
||
axios.get(`${API_BASE_URL}/users`).then((response) => {
|
||
setUsers(response.data);
|
||
});
|
||
|
||
axios.get(`${API_BASE_URL}/objets`).then((response) => {
|
||
setAdminObjects(response.data);
|
||
});
|
||
}, []);
|
||
|
||
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 [widgets, setWidgets] = useState(initialWidgets);
|
||
|
||
const [showAddWidgetModal, setShowAddWidgetModal] = useState(false);
|
||
|
||
const handleDeleteWidget = (id) => {
|
||
setWidgets(widgets.filter((widget) => widget.id !== id));
|
||
};
|
||
|
||
const openAddWidgetModal = () => {
|
||
setShowAddWidgetModal(true);
|
||
};
|
||
|
||
const handleWidgetSelection = (widgetType) => {
|
||
const newWidget = { id: Date.now(), type: widgetType };
|
||
setWidgets([...widgets, newWidget]);
|
||
setShowAddWidgetModal(false);
|
||
};
|
||
|
||
return (
|
||
<div className="flex min-h-screen">
|
||
<Sidebar />
|
||
<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">
|
||
<h1 className="text-3xl font-bold">Dashboard</h1>
|
||
<button
|
||
onClick={() => setManageMode(!manageMode)}
|
||
className="flex items-center px-4 py-2 bg-gray-200 hover:bg-gray-300 rounded-md"
|
||
>
|
||
<Settings className="mr-2" size={20} />
|
||
{manageMode ? "Terminer la gestion" : "Gérer les widgets"}
|
||
</button>
|
||
</div>
|
||
|
||
<section>
|
||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||
{widgets.map((widget) => (
|
||
<div
|
||
key={widget.id}
|
||
className="relative bg-white p-6 rounded-xl shadow hover:shadow-md"
|
||
>
|
||
{manageMode && (
|
||
<button
|
||
onClick={() => handleDeleteWidget(widget.id)}
|
||
className="absolute top-2 right-2 bg-red-600 text-white rounded-full w-6 h-6 flex items-center justify-center"
|
||
>
|
||
–
|
||
</button>
|
||
)}
|
||
|
||
{widget.type === "summary" && (
|
||
<div>
|
||
<h2 className="text-xl font-semibold mb-4">
|
||
Résumé du tableau de bord
|
||
</h2>
|
||
<div className="mb-4">
|
||
<h3 className="text-lg font-medium">Total Utilisateur</h3>
|
||
<p className="text-2xl">{users.length}</p>
|
||
</div>
|
||
<div>
|
||
<h3 className="text-lg font-medium">Dernier Log</h3>
|
||
{logs.length > 0 ? (
|
||
<p>
|
||
{logs[logs.length - 1].username} -{" "}
|
||
{logs[logs.length - 1].action}
|
||
</p>
|
||
) : (
|
||
<p>Aucun log</p>
|
||
)}
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{widget.type === "users" && (
|
||
<div>
|
||
<h2 className="text-xl font-semibold mb-4">
|
||
Gestion des Utilisateurs
|
||
</h2>
|
||
<div className="overflow-x-auto">
|
||
<table className="min-w-[320px] w-full border border-gray-200">
|
||
<thead>
|
||
<tr>
|
||
<th className="px-2 py-1 border border-gray-200 bg-gray-100 text-left">
|
||
Username
|
||
</th>
|
||
<th className="px-2 py-1 border border-gray-200 bg-gray-100 text-left">
|
||
Email
|
||
</th>
|
||
<th className="px-2 py-1 border border-gray-200 bg-gray-100 text-left">
|
||
Access
|
||
</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{users.slice(0, 5).map((user) => (
|
||
<tr key={user.id}>
|
||
<td className="px-2 py-1 border border-gray-200">
|
||
{user.pseudo}
|
||
</td>
|
||
<td className="px-2 py-1 border border-gray-200">
|
||
{user.email}
|
||
</td>
|
||
<td className="px-2 py-1 border border-gray-200">
|
||
{user.role}
|
||
</td>
|
||
</tr>
|
||
))}
|
||
{users.length === 0 && (
|
||
<tr>
|
||
<td
|
||
colSpan="3"
|
||
className="px-2 py-1 border border-gray-200 text-center"
|
||
>
|
||
Aucun utilisateur disponible
|
||
</td>
|
||
</tr>
|
||
)}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<button
|
||
className="mt-4 px-4 py-2 bg-blue-600 text-white rounded-md"
|
||
onClick={() => (window.location.href = "/user")}
|
||
>
|
||
Voir plus
|
||
</button>
|
||
</div>
|
||
)}
|
||
|
||
{widget.type === "objects" && (
|
||
<div>
|
||
<h2 className="text-xl font-semibold mb-4">
|
||
Gestion des Objets Connectés
|
||
</h2>
|
||
<div className="mb-4">
|
||
<a
|
||
href="/gestionObjets"
|
||
className="flex items-center text-indigo-600 hover:text-indigo-700"
|
||
>
|
||
<RadioTower size={24} className="mr-2" />
|
||
Consulter les objets connectés
|
||
<ArrowRight size={16} className="ml-2" />
|
||
</a>
|
||
</div>
|
||
<div>
|
||
<a
|
||
href="/adminobjet"
|
||
className="flex items-center text-indigo-600 hover:text-indigo-700"
|
||
>
|
||
<BadgePlus size={24} className="mr-2" />
|
||
Ajouter un nouvel objet
|
||
<ArrowRight size={16} className="ml-2" />
|
||
</a>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{widget.type === "adminobjet" && (
|
||
<div>
|
||
<h2 className="text-xl font-semibold mb-4">
|
||
Liste des Objets et Outils/Services
|
||
</h2>
|
||
<ul className="mb-4 space-y-2">
|
||
{adminObjects.slice(0, 2).map((obj) => (
|
||
<li
|
||
key={obj.id}
|
||
className="border border-gray-200 p-2 rounded"
|
||
>
|
||
<p className="font-medium">{obj.name}</p>
|
||
<p className="text-sm text-gray-500">{obj.type}</p>
|
||
<p className="text-sm text-gray-500">{obj.status}</p>
|
||
</li>
|
||
))}
|
||
</ul>
|
||
<button
|
||
onClick={() => (window.location.href = "/adminobjet")}
|
||
className="mt-4 px-4 py-2 bg-blue-600 text-white rounded-md"
|
||
>
|
||
Voir plus
|
||
</button>
|
||
</div>
|
||
)}
|
||
{widget.type === "reporting" && (
|
||
<div>
|
||
<h2 className="text-xl font-semibold mb-4">Rapports et Statistiques</h2>
|
||
|
||
<div className="mb-4">
|
||
<p className="text-gray-700 mb-2">Générer des rapports d'utilisation :</p>
|
||
<div className="flex gap-4">
|
||
<button
|
||
className="bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700"
|
||
onClick={() => exportCSV()}
|
||
>
|
||
Exporter en CSV
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="mt-4 space-y-2">
|
||
<div>
|
||
<h4 className="text-md font-medium">Consommation énergétique totale</h4>
|
||
<p className="text-gray-600">1372 kWh cumulés (estimation)</p>
|
||
</div>
|
||
<div>
|
||
<h4 className="text-md font-medium">Taux de connexion des utilisateurs</h4>
|
||
<p className="text-gray-600">87% des utilisateurs actifs ce mois-ci</p>
|
||
</div>
|
||
<div>
|
||
<h4 className="text-md font-medium">Services les plus utilisés</h4>
|
||
<ul className="list-disc ml-6 text-gray-600">
|
||
<li>Consultation des données météo</li>
|
||
<li>Alertes et suivi de consommation</li>
|
||
<li>Ajout d'objets connectés</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
))}
|
||
|
||
<div
|
||
onClick={openAddWidgetModal}
|
||
className="flex items-center justify-center border-2 border-dashed border-gray-300 rounded-xl p-6 hover:bg-gray-50 cursor-pointer"
|
||
>
|
||
<button className="flex items-center">
|
||
<span className="text-3xl font-bold mr-2">+</span>
|
||
<span>Ajouter un widget</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
{showAddWidgetModal && (
|
||
<div className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 z-50">
|
||
<div className="bg-white rounded-lg p-6 w-80">
|
||
<h3 className="text-xl font-semibold mb-4">
|
||
Choisir un type de widget
|
||
</h3>
|
||
<div className="flex flex-col gap-4">
|
||
<button
|
||
onClick={() => handleWidgetSelection("summary")}
|
||
className="px-4 py-2 bg-gray-200 hover:bg-gray-300 rounded-md text-left"
|
||
>
|
||
Dashboard Summary
|
||
</button>
|
||
<button
|
||
onClick={() => handleWidgetSelection("users")}
|
||
className="px-4 py-2 bg-gray-200 hover:bg-gray-300 rounded-md text-left"
|
||
>
|
||
Gestion des Utilisateurs
|
||
</button>
|
||
<button
|
||
onClick={() => handleWidgetSelection("objects")}
|
||
className="px-4 py-2 bg-gray-200 hover:bg-gray-300 rounded-md text-left"
|
||
>
|
||
Gestion des Objets Connectés
|
||
</button>
|
||
<button
|
||
onClick={() => handleWidgetSelection("adminobjet")}
|
||
className="px-4 py-2 bg-gray-200 hover:bg-gray-300 rounded-md text-left"
|
||
>
|
||
Liste des Objets et Outils/Services
|
||
</button>
|
||
<button
|
||
onClick={() => handleWidgetSelection("reporting")}
|
||
className="px-4 py-2 bg-gray-200 hover:bg-gray-300 rounded-md text-left"
|
||
>
|
||
Rapports et Statistiques
|
||
</button>
|
||
</div>
|
||
<button
|
||
onClick={() => setShowAddWidgetModal(false)}
|
||
className="mt-4 px-4 py-2 bg-red-500 text-white rounded-md w-full"
|
||
>
|
||
Annuler
|
||
</button>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</main>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export default Dashboard;
|