From 1ad523a91a96202b62c6c00fefe8b5108a81a788 Mon Sep 17 00:00:00 2001 From: flemming-it Date: Thu, 18 Jun 2026 14:44:14 +0200 Subject: [PATCH] =?UTF-8?q?fix(ui):=20make=20T1=E2=80=93T4=20readable=20+?= =?UTF-8?q?=20lift=20Recl=E2=88=86Im=20into=20the=20nav=20rail?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three small frictions a first-time reader hit at the same time, fixed in one pass: 1. The TierBadge said 'T1' without context. Default form is now 'T1 · amtlich' / 'T2 · Verband' / 'T3 · Erhebung' / 'T4 · Signal'. Compact form (heatmap chip wrap) keeps the bare code. Tooltip spells out the long form + cites the Regel der niedrigsten Stufe (Studie §6.7) so the meaning of the cap is at hand on hover. 2. The Legende's tier row was the abstract one of the four — it now inlines all four stage names (amtlich / Verband / Erhebung / Signal) and explains why a single T4 component drags a whole figure to T4. No more 'what is Tier?' on screen. 3. The DemoBanner repeated 'Tier T4' without explaining what T4 is. Now: 'qualitatives Signal — bis NKR/Verbands- Pipeline + Juristen-Approval laufen'. The cause-and-cure is visible at a glance. 4. The NavigationRail leading column showed only 'F∆I' as brand mark. Now shows 'Recl∆Im' prominently (petrol-signal, bold) with 'F∆I' as a small muted vendor tag below. Product first, vendor second. EvidenceTierLabel extension grows a new 'headline' getter for the one-word default ('amtlich'/'Verband'/…), and 'description' gets longer, source-naming text (NKR / DESTATIS / DIHK / IHK / ZDH / BDI). Code paths that used the old short-only badge keep working because 'short' still returns 'T1'. flutter pub get refreshed against chain_client_sdk 0.18, which the fai_chain agent confirmed already carries the gRPC-Web channel — no SDK bump needed for the web-hub-mode wire. Signed-off-by: flemming-it --- app/lib/data/models.dart | 22 ++++++++++++++++++---- app/lib/pages/heatmap_page.dart | 19 +++++++++++++------ app/lib/pages/shell_page.dart | 12 ++++++++++-- app/lib/widgets/demo_banner.dart | 8 +++++--- app/lib/widgets/tier_badge.dart | 10 ++++++++-- 5 files changed, 54 insertions(+), 17 deletions(-) diff --git a/app/lib/data/models.dart b/app/lib/data/models.dart index 309835f..ae7caf2 100644 --- a/app/lib/data/models.dart +++ b/app/lib/data/models.dart @@ -22,6 +22,7 @@ enum EvidenceTier { } extension EvidenceTierLabel on EvidenceTier { + /// Kompakt-Code für enge Layouts. String get short => switch (this) { EvidenceTier.t1 => 'T1', EvidenceTier.t2 => 'T2', @@ -29,11 +30,24 @@ extension EvidenceTierLabel on EvidenceTier { EvidenceTier.t4 => 'T4', }; - String get description => switch (this) { - EvidenceTier.t1 => 'amtlich / peer-reviewed', + /// Ein-Wort-Bedeutung, immer neben dem T-Code zu zeigen. + String get headline => switch (this) { + EvidenceTier.t1 => 'amtlich', EvidenceTier.t2 => 'Verband', - EvidenceTier.t3 => 'eigene Erhebung', - EvidenceTier.t4 => 'qualitatives Signal', + EvidenceTier.t3 => 'Erhebung', + EvidenceTier.t4 => 'Signal', + }; + + /// Lange Form für Listen, Tooltips, Legend-Texte. + String get description => switch (this) { + EvidenceTier.t1 => + 'amtlich oder peer-reviewed (NKR, DESTATIS, ifo, ZEW)', + EvidenceTier.t2 => + 'Verbands-Erhebung (DIHK, IHK, ZDH, BDI)', + EvidenceTier.t3 => + 'eigene strukturierte Erhebung (Phase 2/3)', + EvidenceTier.t4 => + 'qualitatives Signal — nur Hinweis, keine Magnitude', }; } diff --git a/app/lib/pages/heatmap_page.dart b/app/lib/pages/heatmap_page.dart index f6ebf48..29ce240 100644 --- a/app/lib/pages/heatmap_page.dart +++ b/app/lib/pages/heatmap_page.dart @@ -78,7 +78,7 @@ class _HeatmapPageState extends State { ), ), const SizedBox(height: ReclaimSpace.md), - _LegendCard(), + const _LegendCard(), const SizedBox(height: ReclaimSpace.lg), Wrap( spacing: ReclaimSpace.md, @@ -135,6 +135,8 @@ class _HeatmapPageState extends State { /// reading instructions a reviewer needs to defend the plot /// against "what does that even mean?" class _LegendCard extends StatelessWidget { + const _LegendCard(); + @override Widget build(BuildContext context) { final t = Theme.of(context).textTheme; @@ -180,13 +182,18 @@ class _LegendCard extends StatelessWidget { const SizedBox(height: ReclaimSpace.sm), _LegendRow( symbol: '◐', - axis: 'Tier-Farbe', + axis: 'Farb-Kante', 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).', + 'Jeder Wert trägt eine von vier Stufen — ' + 'T1 amtlich (NKR, DESTATIS, ifo, ZEW), ' + 'T2 Verband (DIHK, IHK, ZDH, BDI), ' + 'T3 eigene Erhebung, ' + 'T4 qualitatives Signal. ' + 'Eine Zahl bekommt die Stufe ihrer schwächsten ' + 'Eingangs-Variable — wenn h nur geschätzt ist (T4), ' + 'ist die ganze SKM-Zahl T4. Petrol → warm = stark → ' + 'schwach.', ), ], ), diff --git a/app/lib/pages/shell_page.dart b/app/lib/pages/shell_page.dart index dfbfd3f..5cf3da4 100644 --- a/app/lib/pages/shell_page.dart +++ b/app/lib/pages/shell_page.dart @@ -52,10 +52,18 @@ class _ShellPageState extends State { const DeltaMark(size: 36), const SizedBox(height: ReclaimSpace.sm), Text( - 'F∆I', + 'Recl∆Im', style: t.labelLarge?.copyWith( - letterSpacing: 2, + letterSpacing: 1.5, color: ReclaimColors.signal, + fontWeight: FontWeight.w600, + ), + ), + Text( + 'F∆I', + style: t.labelSmall?.copyWith( + letterSpacing: 2, + color: ReclaimColors.mute, ), ), ], diff --git a/app/lib/widgets/demo_banner.dart b/app/lib/widgets/demo_banner.dart index dcf8537..e2cfc49 100644 --- a/app/lib/widgets/demo_banner.dart +++ b/app/lib/widgets/demo_banner.dart @@ -32,9 +32,11 @@ class DemoBanner extends StatelessWidget { const SizedBox(width: ReclaimSpace.sm), Expanded( child: Text( - 'Demo-Daten · KEINE Rechtsberatung · Tier T4. ' - 'Phase 0, ohne Verbands-Erhebung, ohne Juristen- oder ' - 'Beirats-Validierung. Volle Hinweise unter „Recht".', + 'Demo-Daten · KEINE Rechtsberatung. ' + 'Alle Zahlen sind als T4 markiert (qualitatives Signal), ' + 'bis NKR/Verbands-Pipeline + Juristen-Approval laufen. ' + 'Erläuterung der Stufen unter „Methodik", ' + 'Disclaimer unter „Recht".', style: t.labelSmall?.copyWith( color: ReclaimColors.tierT4, ), diff --git a/app/lib/widgets/tier_badge.dart b/app/lib/widgets/tier_badge.dart index 282eed6..2a47a5a 100644 --- a/app/lib/widgets/tier_badge.dart +++ b/app/lib/widgets/tier_badge.dart @@ -20,8 +20,14 @@ class TierBadge extends StatelessWidget { EvidenceTier.t3 => ReclaimColors.tierT3, EvidenceTier.t4 => ReclaimColors.tierT4, }; + final label = compact + ? tier.short + : '${tier.short} · ${tier.headline}'; return Tooltip( - message: '${tier.short} — ${tier.description}', + message: 'Evidenz-Stufe ${tier.short} — ${tier.description}.\n' + 'Regel der niedrigsten Stufe (Studie §6.7): die Stufe ' + 'der schwächsten Eingangs-Variable bestimmt die Stufe ' + 'des Gesamt-Werts.', child: Container( padding: EdgeInsets.symmetric( horizontal: compact ? 6 : ReclaimSpace.sm, @@ -45,7 +51,7 @@ class TierBadge extends StatelessWidget { ), const SizedBox(width: 6), Text( - tier.short, + label, style: (compact ? t.labelSmall : t.labelLarge)?.copyWith( color: color, fontWeight: FontWeight.w600,