zkt26/Front-end/src/pages/Admin/Dashboard.jsx
Arcade69 09897a5181
Update Dashboard.jsx
ajout du widget qui génère des rapports détaillés du site sur un csv
2025-04-13 01:36:50 +02:00

391 lines
14 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;