import 'package:flutter/material.dart'; /// Page Sauvegarde & Restauration - UnionFlow Mobile /// /// Page complète de gestion des sauvegardes avec création, restauration, /// planification et monitoring des sauvegardes système. class BackupPage extends StatefulWidget { const BackupPage({super.key}); @override State createState() => _BackupPageState(); } class _BackupPageState extends State with TickerProviderStateMixin { late TabController _tabController; bool _autoBackupEnabled = true; String _selectedFrequency = 'Quotidien'; String _selectedRetention = '30 jours'; final List _frequencies = ['Horaire', 'Quotidien', 'Hebdomadaire']; final List _retentions = ['7 jours', '30 jours', '90 jours', '1 an']; @override void initState() { super.initState(); _tabController = TabController(length: 3, vsync: this); } @override void dispose() { _tabController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFFF8F9FA), body: Column( children: [ _buildHeader(), _buildTabBar(), Expanded( child: TabBarView( controller: _tabController, children: [ _buildBackupsTab(), _buildScheduleTab(), _buildRestoreTab(), ], ), ), ], ), ); } /// Header harmonisé Widget _buildHeader() { return Container( margin: const EdgeInsets.all(12), padding: const EdgeInsets.all(20), decoration: BoxDecoration( gradient: const LinearGradient( colors: [Color(0xFF6C5CE7), Color(0xFF5A4FCF)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: const Color(0xFF6C5CE7).withOpacity(0.3), blurRadius: 20, offset: const Offset(0, 8), ), ], ), child: Column( children: [ Row( children: [ Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(12), ), child: const Icon( Icons.backup, color: Colors.white, size: 24, ), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Sauvegarde & Restauration', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Colors.white, ), ), Text( 'Gestion des sauvegardes système', style: TextStyle( fontSize: 14, color: Colors.white.withOpacity(0.8), ), ), ], ), ), Container( decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(8), ), child: IconButton( onPressed: () => _createBackupNow(), icon: const Icon( Icons.save, color: Colors.white, ), tooltip: 'Sauvegarde immédiate', ), ), ], ), const SizedBox(height: 16), Row( children: [ Expanded( child: _buildStatCard('Dernière sauvegarde', '2h', Icons.schedule), ), const SizedBox(width: 12), Expanded( child: _buildStatCard('Taille totale', '2.3 GB', Icons.storage), ), const SizedBox(width: 12), Expanded( child: _buildStatCard('Statut', 'OK', Icons.check_circle), ), ], ), ], ), ); } /// Carte de statistique Widget _buildStatCard(String label, String value, IconData icon) { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.white.withOpacity(0.15), borderRadius: BorderRadius.circular(12), ), child: Column( children: [ Icon(icon, color: Colors.white, size: 20), const SizedBox(height: 4), Text( value, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: Colors.white, ), ), Text( label, style: TextStyle( fontSize: 10, color: Colors.white.withOpacity(0.8), ), textAlign: TextAlign.center, ), ], ), ); } /// Barre d'onglets Widget _buildTabBar() { return Container( margin: const EdgeInsets.symmetric(horizontal: 12), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: TabBar( controller: _tabController, labelColor: const Color(0xFF6C5CE7), unselectedLabelColor: Colors.grey[600], indicatorColor: const Color(0xFF6C5CE7), indicatorWeight: 3, labelStyle: const TextStyle(fontWeight: FontWeight.w600, fontSize: 12), tabs: const [ Tab(icon: Icon(Icons.folder, size: 18), text: 'Sauvegardes'), Tab(icon: Icon(Icons.schedule, size: 18), text: 'Planification'), Tab(icon: Icon(Icons.restore, size: 18), text: 'Restauration'), ], ), ); } /// Onglet sauvegardes Widget _buildBackupsTab() { return SingleChildScrollView( padding: const EdgeInsets.all(12), child: Column( children: [ const SizedBox(height: 16), _buildBackupsList(), const SizedBox(height: 80), ], ), ); } /// Liste des sauvegardes Widget _buildBackupsList() { final backups = [ {'name': 'Sauvegarde automatique', 'date': '15/12/2024 02:00', 'size': '2.3 GB', 'type': 'Auto'}, {'name': 'Sauvegarde manuelle', 'date': '14/12/2024 14:30', 'size': '2.1 GB', 'type': 'Manuel'}, {'name': 'Sauvegarde automatique', 'date': '14/12/2024 02:00', 'size': '2.2 GB', 'type': 'Auto'}, ]; return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Icon(Icons.folder, color: Color(0xFF6C5CE7), size: 20), const SizedBox(width: 8), Text( 'Sauvegardes disponibles', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: Colors.grey[800], ), ), ], ), const SizedBox(height: 16), ...backups.map((backup) => _buildBackupItem(backup)), ], ), ); } /// Élément de sauvegarde Widget _buildBackupItem(Map backup) { return Container( margin: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.grey[50], borderRadius: BorderRadius.circular(12), ), child: Row( children: [ Icon( backup['type'] == 'Auto' ? Icons.schedule : Icons.touch_app, color: backup['type'] == 'Auto' ? Colors.blue : Colors.green, size: 20, ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( backup['name']!, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFF1F2937), ), ), Text( '${backup['date']} • ${backup['size']}', style: TextStyle( fontSize: 12, color: Colors.grey[600], ), ), ], ), ), PopupMenuButton( onSelected: (action) => _handleBackupAction(backup, action), itemBuilder: (context) => [ const PopupMenuItem(value: 'restore', child: Text('Restaurer')), const PopupMenuItem(value: 'download', child: Text('Télécharger')), const PopupMenuItem(value: 'delete', child: Text('Supprimer')), ], child: const Icon(Icons.more_vert, color: Colors.grey), ), ], ), ); } /// Onglet planification Widget _buildScheduleTab() { return SingleChildScrollView( padding: const EdgeInsets.all(12), child: Column( children: [ const SizedBox(height: 16), _buildScheduleSettings(), const SizedBox(height: 80), ], ), ); } /// Paramètres de planification Widget _buildScheduleSettings() { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Icon(Icons.schedule, color: Color(0xFF6C5CE7), size: 20), const SizedBox(width: 8), Text( 'Configuration automatique', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: Colors.grey[800], ), ), ], ), const SizedBox(height: 16), _buildSwitchSetting( 'Sauvegarde automatique', 'Activer les sauvegardes programmées', _autoBackupEnabled, (value) => setState(() => _autoBackupEnabled = value), ), const SizedBox(height: 12), _buildDropdownSetting( 'Fréquence', _selectedFrequency, _frequencies, (value) => setState(() => _selectedFrequency = value!), ), const SizedBox(height: 12), _buildDropdownSetting( 'Rétention', _selectedRetention, _retentions, (value) => setState(() => _selectedRetention = value!), ), ], ), ); } /// Onglet restauration Widget _buildRestoreTab() { return SingleChildScrollView( padding: const EdgeInsets.all(12), child: Column( children: [ const SizedBox(height: 16), _buildRestoreOptions(), const SizedBox(height: 80), ], ), ); } /// Options de restauration Widget _buildRestoreOptions() { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Icon(Icons.restore, color: Color(0xFF6C5CE7), size: 20), const SizedBox(width: 8), Text( 'Options de restauration', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: Colors.grey[800], ), ), ], ), const SizedBox(height: 16), _buildActionButton( 'Restaurer depuis un fichier', 'Importer une sauvegarde externe', Icons.file_upload, const Color(0xFF0984E3), () => _restoreFromFile(), ), const SizedBox(height: 12), _buildActionButton( 'Restauration sélective', 'Restaurer uniquement certaines données', Icons.checklist, const Color(0xFF00B894), () => _selectiveRestore(), ), const SizedBox(height: 12), _buildActionButton( 'Point de restauration', 'Créer un point de restauration avant modification', Icons.bookmark, const Color(0xFFE17055), () => _createRestorePoint(), ), ], ), ); } // Méthodes de construction des composants Widget _buildSwitchSetting(String title, String subtitle, bool value, Function(bool) onChanged) { return Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(title, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600)), Text(subtitle, style: TextStyle(fontSize: 12, color: Colors.grey[600])), ], ), ), Switch(value: value, onChanged: onChanged, activeColor: const Color(0xFF6C5CE7)), ], ); } Widget _buildDropdownSetting(String title, String value, List options, Function(String?) onChanged) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(title, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600)), const SizedBox(height: 8), Container( padding: const EdgeInsets.symmetric(horizontal: 12), decoration: BoxDecoration( color: Colors.grey[50], borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.grey[300]!), ), child: DropdownButtonHideUnderline( child: DropdownButton( value: value, isExpanded: true, onChanged: onChanged, items: options.map((option) => DropdownMenuItem(value: option, child: Text(option))).toList(), ), ), ), ], ); } Widget _buildActionButton(String title, String subtitle, IconData icon, Color color, VoidCallback onTap) { return InkWell( onTap: onTap, borderRadius: BorderRadius.circular(12), child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: color.withOpacity(0.05), borderRadius: BorderRadius.circular(12), border: Border.all(color: color.withOpacity(0.1)), ), child: Row( children: [ Icon(icon, color: color, size: 20), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(title, style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600, color: color)), Text(subtitle, style: TextStyle(fontSize: 12, color: Colors.grey[600])), ], ), ), Icon(Icons.arrow_forward_ios, color: Colors.grey[400], size: 16), ], ), ), ); } // Méthodes d'action void _createBackupNow() => _showSuccessSnackBar('Sauvegarde créée avec succès'); void _handleBackupAction(Map backup, String action) => _showSuccessSnackBar('Action "$action" exécutée'); void _restoreFromFile() => _showSuccessSnackBar('Sélection de fichier de restauration'); void _selectiveRestore() => _showSuccessSnackBar('Mode de restauration sélective'); void _createRestorePoint() => _showSuccessSnackBar('Point de restauration créé'); void _showSuccessSnackBar(String message) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(message), backgroundColor: const Color(0xFF00B894), behavior: SnackBarBehavior.floating), ); } }