Documentation — Tableaux de bord

Tableau de bord à widgets personnalisable : catalogue de widgets, modèle de configuration (ordre, taille, visibilité) et persistance de la disposition.

Catalogue de widgets

Le catalogue définit les widgets disponibles : chaque entrée associe un identifiant stable, un titre, une taille par défaut et une fonction de rendu vers un vrai composant bpm.*. Les widgets non placés sur la grille restent disponibles dans la bibliothèque (visible en mode personnalisation).

IdentifiantTypeWidgetTaille par défaut
metric-caMetricCA du mois (142,5 k€, +12,3 %)1 colonne
metric-commandesMetricCommandes (1 248, +8 %)1 colonne
metric-panierMetricPanier moyen (114,20 €)1 colonne
line-ventesLineChartVentes — 12 derniers mois2 colonnes
bar-regionsBarChartCA par région (6 régions)1 colonne
table-top-produitsTableTop 5 produits (réf. / nom / CA)1 colonne
ring-objectifProgressRingObjectif trimestre (78 %)1 colonne
feed-commandesActivityFeedDernières commandes (4 entrées)2 colonnes

Modèle de configuration

La disposition est un tableau ordonné : l'ordre des entrées est l'ordre d'affichage dans la grille (md:grid-cols-2), size vaut 1 ou 2 colonnes, et la visibilité est implicite — un widget absent du tableau est masqué (il apparaît alors dans la bibliothèque). Aucune donnée métier n'est stockée : la configuration ne référence que des identifiants du catalogue.

[
  { "id": "metric-ca",         "size": 1 },
  { "id": "metric-commandes",  "size": 1 },
  { "id": "line-ventes",       "size": 2 },
  { "id": "bar-regions",       "size": 1 },
  { "id": "table-top-produits","size": 1 }
]

Opérations de personnalisation

  • Réordonner (↑ / ↓) — permutation de deux entrées adjacentes du tableau ; boutons désactivés aux extrémités.
  • Redimensionner (⤢) — bascule size entre 1 et 2 colonnes.
  • Masquer — retire l'entrée du tableau ; le widget rejoint la bibliothèque.
  • Ajouter — ajoute l'entrée en fin de tableau avec la taille par défaut du catalogue.
  • Réinitialiser — restaure la disposition par défaut et purge la sauvegarde (confirmation via bpm.confirmModal).

Persistance

Dans le simulateur, la disposition est écrite dans localStorage (clé bpm.tableaux-de-bord.layout.v1) à chaque changement, puis relue au montage via useEffect. Le rendu initial utilise toujours la disposition par défaut pour rester identique côté serveur et côté client (SSR-safe) ; la configuration sauvegardée est appliquée juste après l'hydratation, après validation (identifiants connus du catalogue, tailles 1 ou 2, sans doublon — toute valeur invalide est ignorée).

// Lecture au montage (jamais au render)
useEffect(() => {
  const raw = window.localStorage.getItem("bpm.tableaux-de-bord.layout.v1");
  const stored = raw ? parseStoredLayout(raw) : null; // validation stricte
  if (stored) setLayout(stored);
  setHydrated(true);
}, []);

// Écriture à chaque changement, uniquement après hydratation
useEffect(() => {
  if (!hydrated) return;
  window.localStorage.setItem("bpm.tableaux-de-bord.layout.v1", JSON.stringify(layout));
}, [layout, hydrated]);

En production, remplacer localStorage par un enregistrement par utilisateur (table dashboard_layouts : user_id, layout JSON, updated_at) avec la même validation côté serveur ; le suffixe de version de la clé (.v1) permet d'invalider proprement les anciennes dispositions quand le catalogue évolue.

Ouvrir le simulateur