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>
106 lines
3.4 KiB
Dart
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]),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|