import 'package:flutter/material.dart'; import '../../../../core/models/membre_model.dart'; import '../../../../shared/theme/app_theme.dart'; /// Card pour afficher un membre dans la liste class MembreCard extends StatelessWidget { const MembreCard({ super.key, required this.membre, this.onTap, this.onEdit, this.onDelete, }); final MembreModel membre; final VoidCallback? onTap; final VoidCallback? onEdit; final VoidCallback? onDelete; @override Widget build(BuildContext context) { return Card( elevation: 2, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), child: InkWell( onTap: onTap, borderRadius: BorderRadius.circular(12), child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Header avec avatar et actions Row( children: [ // Avatar CircleAvatar( radius: 24, backgroundColor: AppTheme.primaryColor, child: Text( membre.initiales, style: const TextStyle( color: Colors.white, fontWeight: FontWeight.w600, fontSize: 16, ), ), ), const SizedBox(width: 12), // Informations principales Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( membre.nomComplet, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: AppTheme.textPrimary, ), ), const SizedBox(height: 2), Text( membre.numeroMembre, style: const TextStyle( fontSize: 12, color: AppTheme.textSecondary, fontFamily: 'monospace', ), ), ], ), ), // Badge de statut Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4, ), decoration: BoxDecoration( color: _getStatusColor(membre.statut).withOpacity(0.1), borderRadius: BorderRadius.circular(12), border: Border.all( color: _getStatusColor(membre.statut), width: 1, ), ), child: Text( _getStatusLabel(membre.statut), style: TextStyle( fontSize: 10, fontWeight: FontWeight.w600, color: _getStatusColor(membre.statut), ), ), ), // Menu d'actions PopupMenuButton( icon: const Icon( Icons.more_vert, color: AppTheme.textSecondary, ), onSelected: (value) { switch (value) { case 'edit': onEdit?.call(); break; case 'delete': onDelete?.call(); break; } }, itemBuilder: (context) => [ const PopupMenuItem( value: 'edit', child: Row( children: [ Icon(Icons.edit, size: 16), SizedBox(width: 8), Text('Modifier'), ], ), ), const PopupMenuItem( value: 'delete', child: Row( children: [ Icon(Icons.delete, size: 16, color: AppTheme.errorColor), SizedBox(width: 8), Text('Supprimer', style: TextStyle(color: AppTheme.errorColor)), ], ), ), ], ), ], ), const SizedBox(height: 12), // Informations de contact Row( children: [ Expanded( child: _buildInfoItem( icon: Icons.email_outlined, text: membre.email, ), ), const SizedBox(width: 16), Expanded( child: _buildInfoItem( icon: Icons.phone_outlined, text: membre.telephone, ), ), ], ), // Adresse si disponible if (membre.adresseComplete.isNotEmpty) ...[ const SizedBox(height: 8), _buildInfoItem( icon: Icons.location_on_outlined, text: membre.adresseComplete, ), ], // Profession si disponible if (membre.profession?.isNotEmpty == true) ...[ const SizedBox(height: 8), _buildInfoItem( icon: Icons.work_outline, text: membre.profession!, ), ], const SizedBox(height: 8), // Footer avec date d'adhésion Row( children: [ Icon( Icons.calendar_today_outlined, size: 14, color: AppTheme.textHint, ), const SizedBox(width: 4), Text( 'Membre depuis ${_formatDate(membre.dateAdhesion)}', style: const TextStyle( fontSize: 12, color: AppTheme.textHint, ), ), ], ), ], ), ), ), ); } /// Widget pour afficher une information avec icône Widget _buildInfoItem({ required IconData icon, required String text, }) { return Row( children: [ Icon( icon, size: 14, color: AppTheme.textSecondary, ), const SizedBox(width: 4), Expanded( child: Text( text, style: const TextStyle( fontSize: 12, color: AppTheme.textSecondary, ), overflow: TextOverflow.ellipsis, ), ), ], ); } /// Retourne la couleur associée au statut Color _getStatusColor(String statut) { switch (statut.toUpperCase()) { case 'ACTIF': return AppTheme.successColor; case 'INACTIF': return AppTheme.warningColor; case 'SUSPENDU': return AppTheme.errorColor; default: return AppTheme.textSecondary; } } /// Retourne le label du statut String _getStatusLabel(String statut) { switch (statut.toUpperCase()) { case 'ACTIF': return 'ACTIF'; case 'INACTIF': return 'INACTIF'; case 'SUSPENDU': return 'SUSPENDU'; default: return statut.toUpperCase(); } } /// Formate une date pour l'affichage String _formatDate(DateTime date) { final now = DateTime.now(); final difference = now.difference(date); if (difference.inDays < 30) { return '${difference.inDays} jours'; } else if (difference.inDays < 365) { final months = (difference.inDays / 30).floor(); return '$months mois'; } else { final years = (difference.inDays / 365).floor(); return '$years an${years > 1 ? 's' : ''}'; } } }