etm-powersync-app/lib/widgets/chart_tooltip.dart
Patrick Schurig 09556039e4 feat(énergie): infobulles avec l'heure sur tous les graphes
Puissances, Qui consomme et Prévision PV affichent au toucher l'heure puis
une ligne par série (nommée comme la légende) ; Qui consomme donne la part
de chaque charge, pas le cumul empilé. Les barres Jour / Semaine / Mois /
Année donnent leur période et le détail autoconsommé / exporté / soutiré.
Les bandes invisibles de la fourchette se taisent ; -0,00 kW se lit 0,00.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011fNqASdws99s94UqQqBYoB
2026-10-17 08:48:15 +02:00

66 lines
2.4 KiB
Dart

import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import '../theme/etm_tokens.dart';
/// Une ligne d'infobulle : la pastille de la série, son nom, sa valeur.
typedef LigneInfobulle = ({Color couleur, String nom, String valeur});
/// Fond commun des infobulles de graphe.
Color fondInfobulle(_) => EtmTokens.navy.withValues(alpha: 0.9);
/// Les infobulles d'un graphe en lignes, **alignées sur `lignes`** (une par série touchée,
/// `null` = série tue — une bande invisible, une valeur nulle).
///
/// L'[entete] (l'heure, le jour) ne s'écrit qu'une fois, en tête de la première ligne
/// affichée : fl_chart empile les items dans une seule bulle, et répéter l'heure à chaque
/// série la ferait lire comme quatre instants différents.
List<LineTooltipItem?> itemsInfobulle(String? entete, List<LigneInfobulle?> lignes) {
final premiere = lignes.indexWhere((l) => l != null);
return [
for (final (i, l) in lignes.indexed)
if (l == null)
null
else
LineTooltipItem(
'',
EtmTokens.mono(size: 11, color: Colors.white),
textAlign: TextAlign.left,
children: [
if (i == premiere && entete != null)
TextSpan(
text: '$entete\n',
style: EtmTokens.sans(
size: 11, weight: FontWeight.w600, color: Colors.white)),
TextSpan(
text: '● ', style: EtmTokens.mono(size: 11, color: l.couleur)),
TextSpan(
text: '${l.nom} ${l.valeur}',
style: EtmTokens.mono(size: 11, color: Colors.white)),
],
),
];
}
/// Une bulle de barre : l'en-tête puis une ligne par part.
BarTooltipItem itemBarre(String? entete, List<LigneInfobulle> lignes) =>
BarTooltipItem(
'',
EtmTokens.mono(size: 11, color: Colors.white),
textAlign: TextAlign.left,
children: [
if (entete != null)
TextSpan(
text: entete,
style: EtmTokens.sans(
size: 11, weight: FontWeight.w600, color: Colors.white)),
for (final l in lignes) ...[
const TextSpan(text: '\n'),
TextSpan(text: '● ', style: EtmTokens.mono(size: 11, color: l.couleur)),
TextSpan(
text: '${l.nom} ${l.valeur}',
style: EtmTokens.mono(size: 11, color: Colors.white)),
],
],
);