import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../core/network/api_exception.dart'; import '../../../data/repositories/node_repository.dart'; import '../../../data/repositories/nodes_repository.dart'; import '../providers/dashboard_summary_provider.dart'; class QuickActionsRow extends ConsumerStatefulWidget { const QuickActionsRow({super.key}); @override ConsumerState createState() => _QuickActionsRowState(); } class _QuickActionsRowState extends ConsumerState { bool _busy = false; Future _guarded(Future Function() action) async { setState(() => _busy = true); try { final message = await action(); if (mounted) ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(message))); } catch (e) { final message = e is ApiException ? e.userMessage : e.toString(); if (mounted) ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(message))); } finally { if (mounted) setState(() => _busy = false); } } Future _scan() => _guarded(() async { final repo = ref.read(nodeRepositoryProvider); if (repo == null) throw StateError('No active connection.'); final result = await repo.scan(); await ref.read(dashboardSummaryProvider.notifier).refresh(); final changed = result.created.length + result.updated.length; return changed == 0 ? 'Scan complete — no changes (${result.found} compose file(s) found)' : 'Scan complete — ${result.created.length} new, ${result.updated.length} updated'; }); Future _runBackup() => _guarded(() async { final repo = ref.read(nodeRepositoryProvider); if (repo == null) throw StateError('No active connection.'); await repo.runBackup(); await ref.read(dashboardSummaryProvider.notifier).refresh(); return 'Backup started'; }); Future _recheckFleet() => _guarded(() async { await ref.read(aggregatedNodesProvider.notifier).refresh(); return 'Fleet status refreshed'; }); @override Widget build(BuildContext context) { return Card( child: Padding( padding: const EdgeInsets.all(14), child: Wrap( spacing: 10, runSpacing: 10, children: [ FilledButton.icon( onPressed: _busy ? null : _scan, icon: const Icon(Icons.search_rounded, size: 17), label: const Text('Scan for services'), ), OutlinedButton.icon( onPressed: _busy ? null : _runBackup, icon: const Icon(Icons.cloud_outlined, size: 17), label: const Text('Run backup now'), ), OutlinedButton.icon( onPressed: _busy ? null : _recheckFleet, icon: const Icon(Icons.refresh_rounded, size: 17), label: const Text('Re-check fleet'), ), ], ), ), ); } }