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).
| Identifiant | Type | Widget | Taille par défaut |
|---|---|---|---|
metric-ca | Metric | CA du mois (142,5 k€, +12,3 %) | 1 colonne |
metric-commandes | Metric | Commandes (1 248, +8 %) | 1 colonne |
metric-panier | Metric | Panier moyen (114,20 €) | 1 colonne |
line-ventes | LineChart | Ventes — 12 derniers mois | 2 colonnes |
bar-regions | BarChart | CA par région (6 régions) | 1 colonne |
table-top-produits | Table | Top 5 produits (réf. / nom / CA) | 1 colonne |
ring-objectif | ProgressRing | Objectif trimestre (78 %) | 1 colonne |
feed-commandes | ActivityFeed | Derniè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
sizeentre 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.