import 'package:chain_client_sdk/chain_client_sdk.dart' as chain; import 'package:flutter/material.dart'; import '../data/hub_repository.dart'; import '../data/repository.dart'; import '../theme/lawheatmap_tokens.dart'; import 'lawheatmap_card.dart'; /// Lists the capabilities the connected hub has installed. /// Empty / explanatory state when the active repository is not /// a live [HubRepository]. Real wire to HubClient.listCapabilities(). class HubCapabilitiesCard extends StatefulWidget { const HubCapabilitiesCard({super.key, required this.repository}); final EvaluationRepository repository; @override State createState() => _HubCapabilitiesCardState(); } class _HubCapabilitiesCardState extends State { late Future> _future; @override void initState() { super.initState(); _future = _load(); } Future> _load() async { final repo = widget.repository; if (repo is! HubRepository || !repo.isHealthy) return const []; return repo.client.listCapabilities(); } @override Widget build(BuildContext context) { final t = Theme.of(context).textTheme; final repo = widget.repository; final liveHub = repo is HubRepository && repo.isHealthy; return LawHeatmapCard( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row(children: [ Text('Installierte Capabilities', style: t.headlineSmall), const Spacer(), if (liveHub) IconButton( tooltip: 'Neu laden', onPressed: () => setState(() => _future = _load()), icon: const Icon(Icons.refresh), ), ]), const SizedBox(height: LawHeatmapSpace.sm), if (!liveHub) Text( 'Sichtbar sobald die App im Hub-Modus startet und ' 'der Hub erreichbar ist (siehe Verbindung oben).', style: t.labelSmall?.copyWith( color: LawHeatmapColors.mute, ), ) else FutureBuilder>( future: _future, builder: (context, snap) { if (snap.connectionState == ConnectionState.waiting) { return const Padding( padding: EdgeInsets.all(LawHeatmapSpace.md), child: CircularProgressIndicator(), ); } if (snap.hasError) { return Text('Fehler: ${snap.error}', style: t.labelLarge ?.copyWith(color: LawHeatmapColors.harmWarm)); } final items = snap.data ?? const []; if (items.isEmpty) { return Text( 'Hub hat noch keine Capabilities installiert. ' 'Mit `chain install ` hinzufügen.', style: t.bodyLarge?.copyWith( color: LawHeatmapColors.mute, ), ); } return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ for (final c in items) Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: 280, child: Text( '${c.capability}@${c.version}', style: t.bodyLarge?.copyWith( fontFamily: LawHeatmapTypography.mono, ), ), ), Expanded( child: Text( '${c.moduleName} ${c.moduleVersion}' '${c.kind.isEmpty ? "" : " · ${c.kind}"}', style: t.labelSmall?.copyWith( color: LawHeatmapColors.mute, ), ), ), ], ), ), ], ); }, ), ], ), ); } }