reclaim/app/lib/pages/shell_page.dart
flemming-it 1ad523a91a fix(ui): make T1–T4 readable + lift Recl∆Im into the nav rail
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 <sf@flemming.it>
2026-06-18 14:44:14 +02:00

106 lines
3.4 KiB
Dart

import 'package:flutter/material.dart';
import '../data/repository.dart';
import '../theme/reclaim_tokens.dart';
import '../widgets/delta_mark.dart';
import 'about_page.dart';
import 'heatmap_page.dart';
import 'hub_status_page.dart';
import 'legal_page.dart';
import 'norms_list_page.dart';
/// App shell with a NavigationRail. Each rail destination is one
/// page; pages do their own scrolling.
class ShellPage extends StatefulWidget {
const ShellPage({super.key, required this.repository});
final EvaluationRepository repository;
@override
State<ShellPage> createState() => _ShellPageState();
}
class _ShellPageState extends State<ShellPage> {
int _index = 0;
@override
Widget build(BuildContext context) {
final t = Theme.of(context).textTheme;
final pages = <Widget>[
HeatmapPage(repository: widget.repository),
NormsListPage(repository: widget.repository),
HubStatusPage(repository: widget.repository),
const AboutPage(),
const LegalPage(),
];
return Scaffold(
body: Row(
children: [
NavigationRail(
backgroundColor: Theme.of(context).colorScheme.surface,
extended: MediaQuery.of(context).size.width > 1100,
selectedIndex: _index,
onDestinationSelected: (i) => setState(() => _index = i),
leading: Padding(
padding: const EdgeInsets.symmetric(
vertical: ReclaimSpace.lg,
horizontal: ReclaimSpace.md,
),
child: Column(
children: [
const DeltaMark(size: 36),
const SizedBox(height: ReclaimSpace.sm),
Text(
'Recl∆Im',
style: t.labelLarge?.copyWith(
letterSpacing: 1.5,
color: ReclaimColors.signal,
fontWeight: FontWeight.w600,
),
),
Text(
'F∆I',
style: t.labelSmall?.copyWith(
letterSpacing: 2,
color: ReclaimColors.mute,
),
),
],
),
),
destinations: const [
NavigationRailDestination(
icon: Icon(Icons.grid_view_outlined),
selectedIcon: Icon(Icons.grid_view),
label: Text('Heatmap'),
),
NavigationRailDestination(
icon: Icon(Icons.list_alt_outlined),
selectedIcon: Icon(Icons.list_alt),
label: Text('Normen'),
),
NavigationRailDestination(
icon: Icon(Icons.hub_outlined),
selectedIcon: Icon(Icons.hub),
label: Text('Hub'),
),
NavigationRailDestination(
icon: Icon(Icons.info_outline),
selectedIcon: Icon(Icons.info),
label: Text('Methodik'),
),
NavigationRailDestination(
icon: Icon(Icons.gavel_outlined),
selectedIcon: Icon(Icons.gavel),
label: Text('Recht'),
),
],
),
const VerticalDivider(width: 1),
Expanded(child: pages[_index]),
],
),
);
}
}