feat(ui): add legend card below the heatmap
The four-line description above the heatmap was concise but opaque: 'X: log10 €/year. Y: 0–5. Punktgröße.' said the right words, but a reviewer who isn't already methodologically oriented can't tell what they're looking at. Adds a dedicated Legende-Karte directly under the heatmap. Four rows, each: leading symbol (↔ ↕ ● ◐), axis-or-quantity label, prominent name (Schaden / Nutzen / Betroffenheit / Evidenz-Stufe), and a short prose explanation tying the visual back to the Studie: ↔ Abszisse (X) Schaden — log10 €/Jahr, SKM §3.1 ↕ Ordinate (Y) Nutzen — 7-dim. Komposit §3.2 ● Punktgröße Betroffenheit — sqrt scale, DESTATIS-/IHK ◐ Tier-Farbe Evidenz-Stufe — Regel der niedrigsten §6.7 Top description tightened to one line of context only: 'Schaden × Nutzen × Betroffenheit pro Norm. Klick auf einen Punkt öffnet das Detail …'. No redundancy with the legend, no jargon up top. Signed-off-by: flemming-it <sf@flemming.it>
This commit is contained in:
parent
91a87e2bd8
commit
f61865a3c2
1 changed files with 136 additions and 3 deletions
|
|
@ -50,9 +50,9 @@ class _HeatmapPageState extends State<HeatmapPage> {
|
|||
Text('Heatmap', style: t.displaySmall),
|
||||
const SizedBox(height: ReclaimSpace.xs),
|
||||
Text(
|
||||
'X: jährliche Bürokratiekosten (€, log10). '
|
||||
'Y: Nutzen-Score 0–5. Punktgröße: Betroffenheit. '
|
||||
'Klick auf einen Punkt → Detail mit Pflichten + Quellen.',
|
||||
'Schaden × Nutzen × Betroffenheit pro Norm. '
|
||||
'Klick auf einen Punkt öffnet das Detail mit '
|
||||
'Pflichten, Quellen und Gesetzestext.',
|
||||
style: t.bodyLarge?.copyWith(
|
||||
color: ReclaimColors.mute,
|
||||
),
|
||||
|
|
@ -77,6 +77,8 @@ class _HeatmapPageState extends State<HeatmapPage> {
|
|||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: ReclaimSpace.md),
|
||||
_LegendCard(),
|
||||
const SizedBox(height: ReclaimSpace.lg),
|
||||
Wrap(
|
||||
spacing: ReclaimSpace.md,
|
||||
|
|
@ -126,3 +128,134 @@ class _HeatmapPageState extends State<HeatmapPage> {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Axis + circle legend below the heatmap. Spells out what is
|
||||
/// plotted and how — the four-line top description deliberately
|
||||
/// stays short and high-level, this card carries the precise
|
||||
/// reading instructions a reviewer needs to defend the plot
|
||||
/// against "what does that even mean?"
|
||||
class _LegendCard extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final t = Theme.of(context).textTheme;
|
||||
return ReclaimCard(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Legende', style: t.headlineSmall),
|
||||
const SizedBox(height: ReclaimSpace.md),
|
||||
_LegendRow(
|
||||
symbol: '↔',
|
||||
axis: 'Abszisse (X)',
|
||||
label: 'Schaden',
|
||||
description:
|
||||
'Bürokratiekosten pro Jahr in Euro, logarithmisch '
|
||||
'skaliert (10⁴ = 10 k, 10⁶ = 1 Mio, 10⁹ = 1 Mrd). '
|
||||
'Berechnet nach Standardkostenmodell '
|
||||
'P × F × T × h (Studie §3.1).',
|
||||
),
|
||||
const SizedBox(height: ReclaimSpace.sm),
|
||||
_LegendRow(
|
||||
symbol: '↕',
|
||||
axis: 'Ordinate (Y)',
|
||||
label: 'Nutzen',
|
||||
description:
|
||||
'Komposit-Score von 0–5, Mittelwert aus den sieben '
|
||||
'Dimensionen Schutz · Markt · Rechtssicherheit · '
|
||||
'EU-Binnenmarkt · Sicherheit · Umwelt · Einnahmen '
|
||||
'(Studie §3.2). Jede Dimension einzeln '
|
||||
'quellen-begründet.',
|
||||
),
|
||||
const SizedBox(height: ReclaimSpace.sm),
|
||||
_LegendRow(
|
||||
symbol: '●',
|
||||
axis: 'Punktgröße',
|
||||
label: 'Betroffenheit',
|
||||
description:
|
||||
'Anzahl der Adressaten (KMU, Bürger, Behörden), '
|
||||
'wurzel-skaliert. Mehr Adressaten → größerer Kreis. '
|
||||
'Quellen: DESTATIS Unternehmensregister, '
|
||||
'IHK-/Handwerkskammer-Mitgliederzahlen.',
|
||||
),
|
||||
const SizedBox(height: ReclaimSpace.sm),
|
||||
_LegendRow(
|
||||
symbol: '◐',
|
||||
axis: 'Tier-Farbe',
|
||||
label: 'Evidenz-Stufe',
|
||||
description:
|
||||
'Petrol → warm-orange markiert die Stufe (T1–T4) der '
|
||||
'schwächsten Eingangs-Variable. Eine SKM-Zahl mit '
|
||||
'T4-Schätzwert für h trägt die ganze Zahl als T4 '
|
||||
'(Regel der niedrigsten Stufe, Studie §6.7).',
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _LegendRow extends StatelessWidget {
|
||||
const _LegendRow({
|
||||
required this.symbol,
|
||||
required this.axis,
|
||||
required this.label,
|
||||
required this.description,
|
||||
});
|
||||
|
||||
final String symbol;
|
||||
final String axis;
|
||||
final String label;
|
||||
final String description;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final t = Theme.of(context).textTheme;
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 28,
|
||||
child: Text(
|
||||
symbol,
|
||||
style: t.titleMedium?.copyWith(
|
||||
color: ReclaimColors.signal,
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 140,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
axis,
|
||||
style: t.labelSmall?.copyWith(
|
||||
color: ReclaimColors.mute,
|
||||
letterSpacing: 0.4,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
label,
|
||||
style: t.titleMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: ReclaimSpace.md),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 2),
|
||||
child: Text(
|
||||
description,
|
||||
style: t.bodyLarge?.copyWith(
|
||||
color: ReclaimColors.mute,
|
||||
height: 1.5,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue