sync_page.dart 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_riverpod/flutter_riverpod.dart';
  3. import 'package:go_router/go_router.dart';
  4. import '../../../providers/auth_provider.dart';
  5. import '../../../providers/sync_provider.dart';
  6. class SyncPage extends ConsumerStatefulWidget {
  7. const SyncPage({super.key});
  8. @override
  9. ConsumerState<SyncPage> createState() => _SyncPageState();
  10. }
  11. class _SyncPageState extends ConsumerState<SyncPage> {
  12. bool _forceFullSync = false;
  13. @override
  14. Widget build(BuildContext context) {
  15. final authState = ref.watch(authProvider);
  16. final syncState = ref.watch(syncProvider);
  17. final theme = Theme.of(context);
  18. final agente = authState.agente;
  19. return Scaffold(
  20. appBar: AppBar(
  21. title: const Text('Sincronizzazione'),
  22. actions: [
  23. IconButton(
  24. icon: const Icon(Icons.settings),
  25. onPressed: () => context.push('/dashboard/sync/settings'),
  26. ),
  27. ],
  28. ),
  29. body: Center(
  30. child: Padding(
  31. padding: const EdgeInsets.all(32),
  32. child: Column(
  33. mainAxisSize: MainAxisSize.min,
  34. children: [
  35. Icon(
  36. syncState.isSyncing ? Icons.sync : Icons.sync_outlined,
  37. size: 64,
  38. color: syncState.isSyncing ? theme.colorScheme.primary : theme.colorScheme.outline,
  39. ),
  40. const SizedBox(height: 24),
  41. Text(
  42. syncState.isSyncing ? 'Sincronizzazione in corso...' : 'Sincronizzazione dati',
  43. style: theme.textTheme.titleLarge,
  44. ),
  45. const SizedBox(height: 16),
  46. if (syncState.isSyncing) ...[
  47. LinearProgressIndicator(value: syncState.progress),
  48. const SizedBox(height: 12),
  49. Text(syncState.message, style: theme.textTheme.bodyMedium),
  50. const SizedBox(height: 8),
  51. Text('${(syncState.progress * 100).toInt()}%', style: theme.textTheme.bodySmall),
  52. ] else if (syncState.error != null) ...[
  53. Card(
  54. color: theme.colorScheme.errorContainer,
  55. child: Padding(
  56. padding: const EdgeInsets.all(12),
  57. child: Text(syncState.error!, style: TextStyle(color: theme.colorScheme.onErrorContainer)),
  58. ),
  59. ),
  60. ] else if (syncState.progress >= 1.0) ...[
  61. Icon(Icons.check_circle, size: 48, color: Colors.green),
  62. const SizedBox(height: 8),
  63. const Text('Completato!'),
  64. ],
  65. const SizedBox(height: 12),
  66. CheckboxListTile(
  67. value: _forceFullSync,
  68. onChanged: syncState.isSyncing ? null : (v) => setState(() => _forceFullSync = v!),
  69. title: const Text('Sincronizzazione completa'),
  70. subtitle: const Text('Forza il download completo di tutti i dati'),
  71. controlAffinity: ListTileControlAffinity.leading,
  72. enabled: !syncState.isSyncing,
  73. ),
  74. const SizedBox(height: 12),
  75. FilledButton.icon(
  76. onPressed: syncState.isSyncing || agente == null
  77. ? null
  78. : () => ref.read(syncProvider.notifier).startFullSync(
  79. agente.idAgente,
  80. agente.codAgente,
  81. forceFullSync: _forceFullSync,
  82. ),
  83. icon: syncState.isSyncing
  84. ? const SizedBox(width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2))
  85. : const Icon(Icons.sync),
  86. label: Text(syncState.isSyncing ? 'In corso...' : 'Avvia Sincronizzazione'),
  87. ),
  88. ],
  89. ),
  90. ),
  91. ),
  92. );
  93. }
  94. }