import 'package:flutter/material.dart'; import 'package:geosector_app/core/services/api_service.dart'; import 'dart:math' as math; import 'package:hive_flutter/hive_flutter.dart'; import 'package:geosector_app/core/data/models/amicale_model.dart'; import 'package:geosector_app/core/data/models/membre_model.dart'; import 'package:geosector_app/core/data/models/user_model.dart'; import 'package:geosector_app/core/repositories/user_repository.dart'; import 'package:geosector_app/core/repositories/amicale_repository.dart'; import 'package:geosector_app/core/repositories/membre_repository.dart'; import 'package:geosector_app/presentation/widgets/amicale_table_widget.dart'; import 'package:geosector_app/presentation/widgets/membre_table_widget.dart'; /// Class pour dessiner les petits points blancs sur le fond class DotsPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { final paint = Paint() ..color = Colors.white.withOpacity(0.5) ..style = PaintingStyle.fill; final random = math.Random(42); // Seed fixe pour consistance final numberOfDots = (size.width * size.height) ~/ 1500; for (int i = 0; i < numberOfDots; i++) { final x = random.nextDouble() * size.width; final y = random.nextDouble() * size.height; final radius = 1.0 + random.nextDouble() * 2.0; canvas.drawCircle(Offset(x, y), radius, paint); } } @override bool shouldRepaint(covariant CustomPainter oldDelegate) => false; } /// Page d'administration de l'amicale et des membres /// Cette page est intégrée dans le tableau de bord administrateur class AdminAmicalePage extends StatefulWidget { final UserRepository userRepository; final AmicaleRepository amicaleRepository; final MembreRepository membreRepository; const AdminAmicalePage({ super.key, required this.userRepository, required this.amicaleRepository, required this.membreRepository, }); @override State createState() => _AdminAmicalePageState(); } class _AdminAmicalePageState extends State { UserModel? _currentUser; String? _errorMessage; @override void initState() { super.initState(); _loadCurrentUser(); } void _loadCurrentUser() { final currentUser = widget.userRepository.getCurrentUser(); debugPrint('🔍 _loadCurrentUser - Utilisateur: ${currentUser?.username} (ID: ${currentUser?.id})'); debugPrint('🔍 _loadCurrentUser - fkEntite: ${currentUser?.fkEntite}'); if (currentUser == null) { setState(() { _errorMessage = 'Utilisateur non connecté'; }); return; } if (currentUser.fkEntite == null) { setState(() { _errorMessage = 'Utilisateur non associé à une amicale'; }); return; } // Vérifier immédiatement si l'amicale existe final amicale = widget.amicaleRepository.getUserAmicale(currentUser.fkEntite!); debugPrint('🔍 Amicale trouvée dans le repository: ${amicale?.name ?? 'null'}'); setState(() { _currentUser = currentUser; _errorMessage = null; }); } void _handleEditMembre(MembreModel membre) { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Modifier le membre'), content: Text('Voulez-vous modifier le membre ${membre.firstName} ${membre.name} ?'), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Annuler'), ), ElevatedButton( onPressed: () { Navigator.of(context).pop(); // TODO: Naviguer vers la page de modification // Navigator.of(context).push( // MaterialPageRoute( // builder: (context) => EditMembrePage( // membre: membre, // membreRepository: widget.membreRepository, // ), // ), // ); }, child: const Text('Modifier'), ), ], ), ); } void _handleAddMembre() { if (_currentUser?.fkEntite == null) return; // TODO: Naviguer vers la page d'ajout de membre // Navigator.of(context).push( // MaterialPageRoute( // builder: (context) => AddMembrePage( // amicaleId: _currentUser!.fkEntite!, // membreRepository: widget.membreRepository, // ), // ), // ); } @override Widget build(BuildContext context) { final theme = Theme.of(context); return Stack( children: [ // Fond dégradé avec petits points blancs Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Colors.white, Colors.red.shade300], ), ), child: CustomPaint( painter: DotsPainter(), child: const SizedBox(width: double.infinity, height: double.infinity), ), ), // Contenu principal Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Titre de la page Text( 'Mon amicale et ses membres', style: theme.textTheme.headlineMedium?.copyWith( color: theme.colorScheme.primary, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 24), // Message d'erreur si présent if (_errorMessage != null) Container( padding: const EdgeInsets.all(12), margin: const EdgeInsets.only(bottom: 16), decoration: BoxDecoration( color: Colors.red.withOpacity(0.1), borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.red.withOpacity(0.3)), ), child: Row( children: [ const Icon(Icons.error_outline, color: Colors.red), const SizedBox(width: 12), Expanded( child: Text( _errorMessage!, style: const TextStyle(color: Colors.red), ), ), ], ), ), // Contenu principal avec ValueListenableBuilder if (_currentUser != null && _currentUser!.fkEntite != null) Expanded( child: ValueListenableBuilder>( valueListenable: widget.amicaleRepository.getAmicalesBox().listenable(), builder: (context, amicalesBox, child) { debugPrint('🔍 AmicalesBox - Nombre d\'amicales: ${amicalesBox.length}'); debugPrint('🔍 AmicalesBox - Clés disponibles: ${amicalesBox.keys.toList()}'); debugPrint('🔍 Recherche amicale avec fkEntite: ${_currentUser!.fkEntite}'); final amicale = amicalesBox.get(_currentUser!.fkEntite!); debugPrint('🔍 Amicale récupérée: ${amicale?.name ?? 'AUCUNE'}'); if (amicale == null) { // Ajouter plus d'informations de debug debugPrint('❌ PROBLÈME: Amicale non trouvée'); debugPrint('❌ fkEntite recherché: ${_currentUser!.fkEntite}'); debugPrint('❌ Contenu de la box: ${amicalesBox.values.map((a) => '${a.id}: ${a.name}').join(', ')}'); return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.business_outlined, size: 64, color: theme.colorScheme.primary.withOpacity(0.7), ), const SizedBox(height: 16), Text( 'Amicale non trouvée', style: theme.textTheme.titleLarge, ), const SizedBox(height: 8), Text( 'L\'amicale associée à votre compte n\'existe plus.\nfkEntite: ${_currentUser!.fkEntite}', textAlign: TextAlign.center, style: theme.textTheme.bodyLarge, ), ], ), ); } return ValueListenableBuilder>( valueListenable: widget.membreRepository.getMembresBox().listenable(), builder: (context, membresBox, child) { // Filtrer les membres par amicale // Note: Il faudra ajouter le champ fkEntite au modèle MembreModel final membres = membresBox.values.where((membre) => membre.fkEntite == _currentUser!.fkEntite).toList(); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Section Amicale Text( 'Informations de l\'amicale', style: theme.textTheme.titleLarge?.copyWith( color: theme.colorScheme.primary, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 16), // Tableau Amicale Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 4, offset: const Offset(0, 2), ), ], ), child: AmicaleTableWidget( amicales: [amicale], onEdit: null, onDelete: null, amicaleRepository: widget.amicaleRepository, userRepository: widget.userRepository, apiService: ApiService.instance, showActionsColumn: false, ), ), const SizedBox(height: 32), // Section Membres Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Membres de l\'amicale (${membres.length})', style: theme.textTheme.titleLarge?.copyWith( color: theme.colorScheme.primary, fontWeight: FontWeight.w600, ), ), ElevatedButton.icon( onPressed: _handleAddMembre, icon: const Icon(Icons.add), label: const Text('Ajouter un membre'), style: ElevatedButton.styleFrom( backgroundColor: theme.colorScheme.primary, foregroundColor: Colors.white, ), ), ], ), const SizedBox(height: 16), // Tableau Membres Expanded( child: Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 4, offset: const Offset(0, 2), ), ], ), child: MembreTableWidget( membres: membres, onEdit: _handleEditMembre, onDelete: null, // Géré par l'admin principal membreRepository: widget.membreRepository, ), ), ), ], ); }, ); }, ), ), // Message si pas d'utilisateur connecté if (_currentUser == null) const Expanded( child: Center( child: CircularProgressIndicator(), ), ), ], ), ), ], ); } }