From 8b09a2e580d44ad330c840044f3270407e02370b Mon Sep 17 00:00:00 2001 From: Van Leemput Dayron Date: Fri, 7 Nov 2025 08:39:06 +0100 Subject: [PATCH] Refactor settings components to organize theme content and update import paths --- .../settings/image_management_page.dart | 398 ------------------ lib/components/settings/settings_content.dart | 2 +- .../{ => theme}/settings_theme_content.dart | 10 +- 3 files changed, 5 insertions(+), 405 deletions(-) delete mode 100644 lib/components/settings/image_management_page.dart rename lib/components/settings/{ => theme}/settings_theme_content.dart (96%) diff --git a/lib/components/settings/image_management_page.dart b/lib/components/settings/image_management_page.dart deleted file mode 100644 index 41e7401..0000000 --- a/lib/components/settings/image_management_page.dart +++ /dev/null @@ -1,398 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:firebase_auth/firebase_auth.dart'; -import '../../services/trip_image_service.dart'; - -/// Page d'administration pour gérer les images des voyages -class ImageManagementPage extends StatefulWidget { - const ImageManagementPage({super.key}); - - @override - State createState() => _ImageManagementPageState(); -} - -class _ImageManagementPageState extends State { - final TripImageService _tripImageService = TripImageService(); - - Map? _statistics; - bool _isLoading = false; - bool _isCleaningUp = false; - bool _isCleaningDuplicates = false; - String? _cleanupResult; - String? _duplicateCleanupResult; - - @override - void initState() { - super.initState(); - _loadStatistics(); - } - - Future _loadStatistics() async { - setState(() { - _isLoading = true; - }); - - try { - final userId = FirebaseAuth.instance.currentUser?.uid; - if (userId != null) { - final stats = await _tripImageService.getImageStatistics(userId); - setState(() { - _statistics = stats; - }); - } - } catch (e) { - if (mounted) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Erreur lors du chargement des statistiques: $e')), - ); - } - } finally { - setState(() { - _isLoading = false; - }); - } - } - - Future _cleanupUnusedImages() async { - // Demander confirmation - final shouldCleanup = await showDialog( - context: context, - builder: (context) => AlertDialog( - title: const Text('Nettoyer les images inutilisées'), - content: const Text( - 'Cette action supprimera définitivement toutes les images qui ne sont plus utilisées par vos voyages. ' - 'Voulez-vous continuer ?' - ), - actions: [ - TextButton( - onPressed: () => Navigator.of(context).pop(false), - child: const Text('Annuler'), - ), - ElevatedButton( - onPressed: () => Navigator.of(context).pop(true), - child: const Text('Nettoyer'), - ), - ], - ), - ); - - if (shouldCleanup != true) return; - - setState(() { - _isCleaningUp = true; - _cleanupResult = null; - }); - - try { - final userId = FirebaseAuth.instance.currentUser?.uid; - if (userId != null) { - await _tripImageService.cleanupUnusedImages(userId); - setState(() { - _cleanupResult = 'Nettoyage terminé avec succès !'; - }); - - // Recharger les statistiques - await _loadStatistics(); - } - } catch (e) { - setState(() { - _cleanupResult = 'Erreur lors du nettoyage: $e'; - }); - } finally { - setState(() { - _isCleaningUp = false; - }); - } - } - - Future _cleanupDuplicateImages() async { - // Demander confirmation - final shouldCleanup = await showDialog( - context: context, - builder: (context) => AlertDialog( - title: const Text('Nettoyer les doublons d\'images'), - content: const Text( - 'Cette action analysera vos images et supprimera automatiquement les doublons pour la même destination. ' - 'Seule l\'image la plus récente sera conservée. Voulez-vous continuer ?' - ), - actions: [ - TextButton( - onPressed: () => Navigator.of(context).pop(false), - child: const Text('Annuler'), - ), - ElevatedButton( - onPressed: () => Navigator.of(context).pop(true), - child: const Text('Nettoyer les doublons'), - ), - ], - ), - ); - - if (shouldCleanup != true) return; - - setState(() { - _isCleaningDuplicates = true; - _duplicateCleanupResult = null; - }); - - try { - await _tripImageService.cleanupDuplicateImages(); - setState(() { - _duplicateCleanupResult = 'Doublons supprimés avec succès !'; - }); - - // Recharger les statistiques - await _loadStatistics(); - } catch (e) { - setState(() { - _duplicateCleanupResult = 'Erreur lors du nettoyage des doublons: $e'; - }); - } finally { - setState(() { - _isCleaningDuplicates = false; - }); - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Gestion des Images'), - backgroundColor: Colors.blue, - foregroundColor: Colors.white, - ), - body: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Statistiques - Card( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Statistiques', - style: Theme.of(context).textTheme.headlineSmall, - ), - const SizedBox(height: 16), - if (_isLoading) - const Center(child: CircularProgressIndicator()) - else if (_statistics != null) ...[ - _buildStatItem( - 'Voyages totaux', - _statistics!['totalTrips']?.toString() ?? '0' - ), - _buildStatItem( - 'Voyages avec image', - _statistics!['tripsWithImages']?.toString() ?? '0' - ), - _buildStatItem( - 'Voyages sans image', - _statistics!['tripsWithoutImages']?.toString() ?? '0' - ), - const SizedBox(height: 8), - Text( - 'Dernière mise à jour: ${_formatTimestamp(_statistics!['timestamp'])}', - style: Theme.of(context).textTheme.bodySmall, - ), - ] else - const Text('Impossible de charger les statistiques'), - ], - ), - ), - ), - - const SizedBox(height: 24), - - // Actions - Card( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Actions', - style: Theme.of(context).textTheme.headlineSmall, - ), - const SizedBox(height: 16), - - // Bouton recharger statistiques - SizedBox( - width: double.infinity, - child: ElevatedButton.icon( - onPressed: _isLoading ? null : _loadStatistics, - icon: const Icon(Icons.refresh), - label: const Text('Recharger les statistiques'), - ), - ), - - const SizedBox(height: 12), - - // Bouton nettoyer les images inutilisées - SizedBox( - width: double.infinity, - child: ElevatedButton.icon( - onPressed: _isCleaningUp ? null : _cleanupUnusedImages, - icon: _isCleaningUp - ? const SizedBox( - width: 16, - height: 16, - child: CircularProgressIndicator(strokeWidth: 2), - ) - : const Icon(Icons.cleaning_services), - label: Text(_isCleaningUp ? 'Nettoyage en cours...' : 'Nettoyer les images inutilisées'), - style: ElevatedButton.styleFrom( - backgroundColor: Colors.orange, - foregroundColor: Colors.white, - ), - ), - ), - - const SizedBox(height: 12), - - // Bouton nettoyer les doublons - SizedBox( - width: double.infinity, - child: ElevatedButton.icon( - onPressed: _isCleaningDuplicates ? null : _cleanupDuplicateImages, - icon: _isCleaningDuplicates - ? const SizedBox( - width: 16, - height: 16, - child: CircularProgressIndicator(strokeWidth: 2), - ) - : const Icon(Icons.content_copy), - label: Text(_isCleaningDuplicates ? 'Suppression doublons...' : 'Supprimer les doublons d\'images'), - style: ElevatedButton.styleFrom( - backgroundColor: Colors.red, - foregroundColor: Colors.white, - ), - ), - ), - - if (_cleanupResult != null) ...[ - const SizedBox(height: 12), - Container( - width: double.infinity, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: _cleanupResult!.contains('Erreur') - ? Colors.red.withValues(alpha: 0.1) - : Colors.green.withValues(alpha: 0.1), - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: _cleanupResult!.contains('Erreur') - ? Colors.red - : Colors.green, - width: 1, - ), - ), - child: Text( - _cleanupResult!, - style: TextStyle( - color: _cleanupResult!.contains('Erreur') - ? Colors.red - : Colors.green, - fontWeight: FontWeight.bold, - ), - ), - ), - ], - - if (_duplicateCleanupResult != null) ...[ - const SizedBox(height: 12), - Container( - width: double.infinity, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: _duplicateCleanupResult!.contains('Erreur') - ? Colors.red.withValues(alpha: 0.1) - : Colors.blue.withValues(alpha: 0.1), - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: _duplicateCleanupResult!.contains('Erreur') - ? Colors.red - : Colors.blue, - width: 1, - ), - ), - child: Text( - _duplicateCleanupResult!, - style: TextStyle( - color: _duplicateCleanupResult!.contains('Erreur') - ? Colors.red - : Colors.blue, - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ], - ), - ), - ), - - const SizedBox(height: 24), - - // Informations - Card( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Explications', - style: Theme.of(context).textTheme.headlineSmall, - ), - const SizedBox(height: 12), - const Text( - '• Chaque voyage peut avoir une image automatiquement téléchargée depuis Google Places\n' - '• Les images sont stockées dans Firebase Storage\n' - '• Il peut y avoir des images inutilisées si des voyages ont été supprimés ou modifiés\n' - '• Le nettoyage supprime uniquement les images qui ne sont plus référencées par vos voyages', - style: TextStyle(height: 1.5), - ), - ], - ), - ), - ), - ], - ), - ), - ); - } - - Widget _buildStatItem(String label, String value) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 4), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(label), - Text( - value, - style: const TextStyle(fontWeight: FontWeight.bold), - ), - ], - ), - ); - } - - String _formatTimestamp(String? timestamp) { - if (timestamp == null) return 'Inconnue'; - - try { - final dateTime = DateTime.parse(timestamp); - return '${dateTime.day}/${dateTime.month}/${dateTime.year} ' - '${dateTime.hour.toString().padLeft(2, '0')}:' - '${dateTime.minute.toString().padLeft(2, '0')}'; - } catch (e) { - return 'Format invalide'; - } - } -} \ No newline at end of file diff --git a/lib/components/settings/settings_content.dart b/lib/components/settings/settings_content.dart index 70121c3..764a2c0 100644 --- a/lib/components/settings/settings_content.dart +++ b/lib/components/settings/settings_content.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:travel_mate/components/settings/policies/policies_content.dart'; -import 'settings_theme_content.dart'; +import 'theme/settings_theme_content.dart'; import 'profile/profile_content.dart'; class SettingsContent extends StatelessWidget { diff --git a/lib/components/settings/settings_theme_content.dart b/lib/components/settings/theme/settings_theme_content.dart similarity index 96% rename from lib/components/settings/settings_theme_content.dart rename to lib/components/settings/theme/settings_theme_content.dart index a0537fa..d5322c4 100644 --- a/lib/components/settings/settings_theme_content.dart +++ b/lib/components/settings/theme/settings_theme_content.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import '../../blocs/theme/theme_bloc.dart'; -import '../../blocs/theme/theme_state.dart'; -import '../../blocs/theme/theme_event.dart'; +import '../../../blocs/theme/theme_bloc.dart'; +import '../../../blocs/theme/theme_state.dart'; +import '../../../blocs/theme/theme_event.dart'; class SettingsThemeContent extends StatelessWidget { const SettingsThemeContent({super.key}); @@ -10,9 +10,7 @@ class SettingsThemeContent extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: const Text('Thème'), - ), + appBar: AppBar(title: const Text('Thème')), body: BlocBuilder( builder: (context, state) { return ListView(