Files
2026-07-27 14:42:23 +02:00

86 lines
2.9 KiB
Dart

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<QuickActionsRow> createState() => _QuickActionsRowState();
}
class _QuickActionsRowState extends ConsumerState<QuickActionsRow> {
bool _busy = false;
Future<void> _guarded(Future<String> 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<void> _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<void> _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<void> _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'),
),
],
),
),
);
}
}