import 'package:flutter/material.dart'; import 'dart:math' as math; import 'package:geosector_app/app.dart'; // Pour accéder aux instances globales import 'package:geosector_app/core/data/models/amicale_model.dart'; import 'package:geosector_app/core/data/models/membre_model.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 AdminEntitePage extends StatefulWidget { const AdminEntitePage({Key? key}) : super(key: key); @override State createState() => _AdminEntitePageState(); } class _AdminEntitePageState extends State { bool _isLoading = true; AmicaleModel? _amicale; List _membres = []; String? _errorMessage; @override void initState() { super.initState(); _loadData(); } Future _loadData() async { setState(() { _isLoading = true; _errorMessage = null; }); try { // Récupérer l'utilisateur connecté en utilisant l'instance globale final currentUser = userRepository.getCurrentUser(); if (currentUser == null) { setState(() { _errorMessage = 'Utilisateur non connecté'; _isLoading = false; }); return; } // Vérifier si fkEntite est null if (currentUser.fkEntite == null) { setState(() { _errorMessage = 'Utilisateur non associé à une amicale'; _isLoading = false; }); return; } // Récupérer l'amicale de l'utilisateur en utilisant l'instance globale final amicale = amicaleRepository.getAmicaleById(currentUser.fkEntite!); if (amicale == null) { setState(() { _errorMessage = 'Amicale non trouvée'; _isLoading = false; }); return; } // Récupérer tous les membres // Note: Dans un cas réel, nous devrions filtrer les membres par amicale, // mais le modèle MembreModel n'a pas de champ fkEntite pour le moment final membres = membreRepository.getAllMembres(); setState(() { _amicale = amicale; _membres = membres; _isLoading = false; }); } catch (e) { setState(() { _errorMessage = 'Erreur lors du chargement des données: $e'; _isLoading = false; }); } } void _handleEditAmicale(AmicaleModel amicale) { // Afficher une boîte de dialogue de confirmation showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Modifier l\'amicale'), content: Text('Voulez-vous modifier l\'amicale ${amicale.name} ?'), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Annuler'), ), ElevatedButton( onPressed: () { Navigator.of(context).pop(); // Naviguer vers la page de modification // Navigator.of(context).push( // MaterialPageRoute( // builder: (context) => EditAmicalePage(amicale: amicale), // ), // ); }, child: const Text('Modifier'), ), ], ), ); } void _handleEditMembre(MembreModel membre) { // Afficher une boîte de dialogue de confirmation 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(); // Naviguer vers la page de modification // Navigator.of(context).push( // MaterialPageRoute( // builder: (context) => EditMembrePage(membre: membre), // ), // ); }, child: const Text('Modifier'), ), ], ), ); } @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: Container(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 if (_isLoading) const Expanded( child: Center( child: CircularProgressIndicator(), ), ) else if (_amicale == null) Expanded( child: 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( 'Aucune amicale associée', style: theme.textTheme.titleLarge, ), const SizedBox(height: 8), Text( 'Vous n\'êtes pas associé à une amicale.', textAlign: TextAlign.center, style: theme.textTheme.bodyLarge, ), ], ), ), ) else Expanded( child: 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!], // Pas de bouton de suppression pour sa propre amicale onDelete: null, ), ), const SizedBox(height: 32), // Section Membres Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Membres de l\'amicale', style: theme.textTheme.titleLarge?.copyWith( color: theme.colorScheme.primary, fontWeight: FontWeight.w600, ), ), ElevatedButton.icon( onPressed: () { // Naviguer vers la page d'ajout de membre // Navigator.of(context).push( // MaterialPageRoute( // builder: (context) => AddMembrePage(amicaleId: _amicale!.id), // ), // ); }, 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, // Pas de bouton de suppression pour les membres de sa propre amicale // sauf si l'utilisateur a un rôle élevé onDelete: null, ), ), ), ], ), ), ], ), ), ], ); } }