Le seuil de 10 erreurs qui fait basculer un monitoring en « Critique » était réécrit dans trois fichiers (MonitoringCard, MonitoringDetail, VueConso), la version de VueConso ne renvoyant qu'une couleur. Faire évoluer ce seuil imposait de corriger trois endroits sans en oublier. Il vit maintenant dans utils/statutMonitoring.js, avec la constante SEUIL_ATTENTION nommée. Les colonnes du tableau de monitorings étaient également identiques entre VueConso et ServiceMonitorings : extraites dans utils/monitoringColumns.jsx.
89 lines
3.2 KiB
React
89 lines
3.2 KiB
React
// src/pages/VueConso/VueConso.jsx
|
|
// Page Vue consolidée : graphique barres + tableau avec export CSV
|
|
import { useState, useEffect } from 'react';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import { Download } from 'lucide-react';
|
|
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';
|
|
import { getDashboard, exportToCSV } from '../../services/api';
|
|
import DataTable from '../../components/common/DataTable';
|
|
import LoadingSpinner from '../../components/common/LoadingSpinner';
|
|
import ErrorMessage from '../../components/common/ErrorMessage';
|
|
import Button from '../../components/common/Button';
|
|
import { getStatutMonitoring } from '../../utils/statutMonitoring';
|
|
import { buildMonitoringColumns } from '../../utils/monitoringColumns';
|
|
import styles from './VueConso.module.css';
|
|
|
|
export default function VueConso() {
|
|
const navigate = useNavigate();
|
|
const [data, setData] = useState([]);
|
|
const [loading, setLoading] = useState(true);
|
|
const [erreur, setErreur] = useState('');
|
|
|
|
useEffect(() => {
|
|
async function loadData() {
|
|
setLoading(true);
|
|
setErreur('');
|
|
try {
|
|
const result = await getDashboard();
|
|
setData(Array.isArray(result) ? result : []);
|
|
} catch (e) {
|
|
setErreur(e.message || 'Erreur lors du chargement de la vue consolidée.');
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}
|
|
loadData();
|
|
}, []);
|
|
|
|
if (loading) return <LoadingSpinner message="Chargement de la vue consolidée..." />;
|
|
if (erreur) return <ErrorMessage message={erreur} />;
|
|
|
|
/* Préparation des données pour le graphique */
|
|
const chartData = data.map(item => ({
|
|
name: item.nom || item.nom_monito || item.libelle || 'Monitoring',
|
|
erreurs: item.nb_erreurs ?? item.count ?? 0,
|
|
fill: getStatutMonitoring(item.nb_erreurs ?? item.count ?? 0).color
|
|
}));
|
|
|
|
const columns = buildMonitoringColumns(navigate);
|
|
|
|
return (
|
|
<div className={styles.page}>
|
|
<div className={styles.header}>
|
|
<h1 className={styles.title}>Vue consolidée</h1>
|
|
<Button variant="secondary" onClick={() => exportToCSV(data, `vue_consolidee_${new Date().toISOString().split('T')[0]}.csv`)}>
|
|
<Download size={14} />
|
|
Exporter tout ({data.length} lignes)
|
|
</Button>
|
|
</div>
|
|
|
|
{/* Graphique */}
|
|
<div className={styles.chartContainer}>
|
|
<ResponsiveContainer width="100%" height={400}>
|
|
<BarChart data={chartData} margin={{ top: 20, right: 30, left: 20, bottom: 60 }}>
|
|
<CartesianGrid strokeDasharray="3 3" />
|
|
<XAxis dataKey="name" angle={-45} textAnchor="end" height={80} />
|
|
<YAxis />
|
|
<Tooltip
|
|
contentStyle={{
|
|
backgroundColor: 'var(--color-black)',
|
|
color: 'var(--color-white)',
|
|
border: 'none',
|
|
borderRadius: 'var(--radius)'
|
|
}}
|
|
/>
|
|
<Bar dataKey="erreurs" fill="var(--color-primary)" />
|
|
</BarChart>
|
|
</ResponsiveContainer>
|
|
</div>
|
|
|
|
{/* Tableau */}
|
|
<DataTable
|
|
columns={columns}
|
|
data={data}
|
|
pageSize={50}
|
|
emptyMessage="Aucune donnée disponible."
|
|
/>
|
|
</div>
|
|
);
|
|
} |