refactor(front): centralise la règle de statut et les colonnes dupliquées

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.
This commit is contained in:
2026-08-15 14:29:09 +02:00
parent 270283e96d
commit 8b8121ca1c
6 changed files with 50 additions and 57 deletions
@@ -2,20 +2,14 @@
import { useNavigate } from 'react-router-dom';
import Badge from './Badge';
import { getStatutMonitoring } from '../../utils/statutMonitoring';
import styles from './MonitoringCard.module.css';
/* Détermine le statut visuel selon le nombre d'erreurs */
function getStatut(nbErreurs) {
if (nbErreurs === 0) return { label: 'OK', variant: 'ok', color: 'var(--color-ok)' };
if (nbErreurs < 10) return { label: 'Attention', variant: 'warning', color: 'var(--color-warning)' };
return { label: 'Critique', variant: 'critical', color: 'var(--color-primary)' };
}
export default function MonitoringCard({ monitoring }) {
const navigate = useNavigate();
const nbErreurs = monitoring.nb_erreurs ?? monitoring.count ?? 0;
const monitoringId = monitoring.id ?? monitoring.id_monito;
const statut = getStatut(nbErreurs);
const statut = getStatutMonitoring(nbErreurs);
/* Calcul du pourcentage de la barre de progression (max 100%) */
const progressPct = Math.min((nbErreurs / 20) * 100, 100);
@@ -9,15 +9,9 @@ import LoadingSpinner from '../../components/common/LoadingSpinner';
import ErrorMessage from '../../components/common/ErrorMessage';
import Badge from '../../components/common/Badge';
import Button from '../../components/common/Button';
import { getStatutMonitoring } from '../../utils/statutMonitoring';
import styles from './MonitoringDetail.module.css';
/* Détermine le statut selon le nombre d'erreurs */
function getStatut(nbErreurs) {
if (nbErreurs === 0) return { label: 'OK', variant: 'ok' };
if (nbErreurs < 10) return { label: 'Attention', variant: 'warning' };
return { label: 'Critique', variant: 'critical' };
}
export default function MonitoringDetail() {
const { id } = useParams();
const navigate = useNavigate();
@@ -72,7 +66,7 @@ export default function MonitoringDetail() {
if (loading) return <LoadingSpinner message="Chargement du monitoring..." />;
if (erreur) return <ErrorMessage message={erreur} />;
const statut = getStatut(count);
const statut = getStatutMonitoring(count);
return (
<div className={styles.page}>
@@ -7,6 +7,7 @@ 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 { buildMonitoringColumns } from '../../utils/monitoringColumns';
import styles from './ServiceMonitorings.module.css';
export default function ServiceMonitorings({ serviceLabel, serviceName }) {
@@ -34,22 +35,7 @@ export default function ServiceMonitorings({ serviceLabel, serviceName }) {
if (loading) return <LoadingSpinner message={`Chargement des monitorings ${serviceLabel.toLowerCase()}...`} />;
if (erreur) return <ErrorMessage message={erreur} />;
const columns = [
{ key: 'nom', label: 'Monitoring' },
{ key: 'service', label: 'Service' },
{ key: 'categorie', label: 'Catégorie' },
{ key: 'bdd_source', label: 'Source' },
{ key: 'nb_erreurs', label: 'Erreurs', render: (val) => val ?? 0 },
{
key: 'actions',
label: 'Actions',
render: (val, row) => (
<Button variant="link" onClick={() => navigate(`/monitoring/${row.id || row.id_monito}`)}>
Voir détail
</Button>
)
}
];
const columns = buildMonitoringColumns(navigate);
return (
<div className={styles.page}>
+4 -25
View File
@@ -9,15 +9,10 @@ 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';
/* Détermine la couleur selon le statut */
function getStatusColor(nbErreurs) {
if (nbErreurs === 0) return 'var(--color-ok)';
if (nbErreurs < 10) return 'var(--color-warning)';
return 'var(--color-primary)';
}
export default function VueConso() {
const navigate = useNavigate();
const [data, setData] = useState([]);
@@ -47,26 +42,10 @@ export default function VueConso() {
const chartData = data.map(item => ({
name: item.nom || item.nom_monito || item.libelle || 'Monitoring',
erreurs: item.nb_erreurs ?? item.count ?? 0,
fill: getStatusColor(item.nb_erreurs ?? item.count ?? 0)
fill: getStatutMonitoring(item.nb_erreurs ?? item.count ?? 0).color
}));
/* Colonnes du tableau */
const columns = [
{ key: 'nom', label: 'Monitoring' },
{ key: 'service', label: 'Service' },
{ key: 'categorie', label: 'Catégorie' },
{ key: 'bdd_source', label: 'Source' },
{ key: 'nb_erreurs', label: 'Erreurs', render: (val) => val ?? 0 },
{
key: 'actions',
label: 'Actions',
render: (val, row) => (
<Button variant="link" onClick={() => navigate(`/monitoring/${row.id || row.id_monito}`)}>
Voir détail
</Button>
)
}
];
const columns = buildMonitoringColumns(navigate);
return (
<div className={styles.page}>
@@ -0,0 +1,24 @@
import Button from '../components/common/Button';
/* Colonnes du tableau de monitorings partagées par VueConso et
ServiceMonitorings (Contrat/Fournisseur) : même jeu de données
(GET /dashboard), même tableau. Centralisé pour qu'une évolution des
colonnes (ajout, renommage) ne soit faite qu'à un seul endroit. */
export function buildMonitoringColumns(navigate) {
return [
{ key: 'nom', label: 'Monitoring' },
{ key: 'service', label: 'Service' },
{ key: 'categorie', label: 'Catégorie' },
{ key: 'bdd_source', label: 'Source' },
{ key: 'nb_erreurs', label: 'Erreurs', render: (val) => val ?? 0 },
{
key: 'actions',
label: 'Actions',
render: (val, row) => (
<Button variant="link" onClick={() => navigate(`/monitoring/${row.id || row.id_monito}`)}>
Voir détail
</Button>
)
}
];
}
@@ -0,0 +1,16 @@
/* Règle de statut partagée : un monitoring est "OK" sans erreur, "Attention"
en-dessous du seuil, "Critique" au-delà. Centralisé ici pour que le seuil
ne soit corrigé qu'à un seul endroit (il était dupliqué dans MonitoringCard,
MonitoringDetail et VueConso, avec le risque que l'une des copies diverge). */
export const SEUIL_ATTENTION = 10;
export function getStatutMonitoring(nbErreurs) {
if (nbErreurs === 0) {
return { label: 'OK', variant: 'ok', color: 'var(--color-ok)' };
}
if (nbErreurs < SEUIL_ATTENTION) {
return { label: 'Attention', variant: 'warning', color: 'var(--color-warning)' };
}
return { label: 'Critique', variant: 'critical', color: 'var(--color-primary)' };
}