import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import '../../../../core/models/membre_model.dart'; import '../../../../shared/theme/app_theme.dart'; /// Section d'informations détaillées d'un membre class MembreInfoSection extends StatelessWidget { const MembreInfoSection({ super.key, required this.membre, this.showActions = false, this.onEdit, this.onCall, this.onMessage, }); final MembreModel membre; final bool showActions; final VoidCallback? onEdit; final VoidCallback? onCall; final VoidCallback? onMessage; @override Widget build(BuildContext context) { return Card( elevation: 2, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), child: Padding( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildHeader(), const SizedBox(height: 20), _buildPersonalInfo(), const SizedBox(height: 16), _buildContactInfo(), const SizedBox(height: 16), _buildMembershipInfo(), if (showActions) ...[ const SizedBox(height: 20), _buildActionButtons(), ], ], ), ), ); } Widget _buildHeader() { return Row( children: [ _buildAvatar(), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( membre.nomComplet, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: AppTheme.textPrimary, ), ), const SizedBox(height: 4), Text( membre.numeroMembre, style: const TextStyle( fontSize: 14, color: AppTheme.textSecondary, fontWeight: FontWeight.w500, ), ), const SizedBox(height: 8), _buildStatusBadge(), ], ), ), ], ); } Widget _buildAvatar() { return Container( width: 80, height: 80, decoration: BoxDecoration( color: AppTheme.primaryColor.withOpacity(0.1), borderRadius: BorderRadius.circular(40), border: Border.all( color: AppTheme.primaryColor.withOpacity(0.3), width: 2, ), ), child: Icon( Icons.person, size: 40, color: AppTheme.primaryColor, ), ); } Widget _buildStatusBadge() { final isActive = membre.actif; return Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: isActive ? AppTheme.successColor : AppTheme.errorColor, borderRadius: BorderRadius.circular(20), ), child: Text( isActive ? 'Actif' : 'Inactif', style: const TextStyle( color: Colors.white, fontSize: 12, fontWeight: FontWeight.w600, ), ), ); } Widget _buildPersonalInfo() { return _buildSection( title: 'Informations personnelles', icon: Icons.person_outline, children: [ _buildInfoRow( icon: Icons.cake_outlined, label: 'Date de naissance', value: membre.dateNaissance != null ? DateFormat('dd/MM/yyyy').format(membre.dateNaissance!) : 'Non renseignée', ), _buildInfoRow( icon: Icons.work_outline, label: 'Profession', value: membre.profession ?? 'Non renseignée', ), _buildInfoRow( icon: Icons.location_on_outlined, label: 'Adresse', value: _buildFullAddress(), ), ], ); } Widget _buildContactInfo() { return _buildSection( title: 'Contact', icon: Icons.contact_phone_outlined, children: [ _buildInfoRow( icon: Icons.email_outlined, label: 'Email', value: membre.email, isSelectable: true, ), _buildInfoRow( icon: Icons.phone_outlined, label: 'Téléphone', value: membre.telephone, isSelectable: true, ), ], ); } Widget _buildMembershipInfo() { return _buildSection( title: 'Adhésion', icon: Icons.card_membership_outlined, children: [ _buildInfoRow( icon: Icons.calendar_today_outlined, label: 'Date d\'adhésion', value: DateFormat('dd/MM/yyyy').format(membre.dateAdhesion), ), _buildInfoRow( icon: Icons.access_time_outlined, label: 'Membre depuis', value: _calculateMembershipDuration(), ), _buildInfoRow( icon: Icons.update_outlined, label: 'Dernière modification', value: membre.dateModification != null ? DateFormat('dd/MM/yyyy à HH:mm').format(membre.dateModification!) : 'Jamais modifié', ), ], ); } Widget _buildSection({ required String title, required IconData icon, required List children, }) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon( icon, size: 20, color: AppTheme.primaryColor, ), const SizedBox(width: 8), Text( title, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: AppTheme.textPrimary, ), ), ], ), const SizedBox(height: 12), ...children, ], ); } Widget _buildInfoRow({ required IconData icon, required String label, required String value, bool isSelectable = false, }) { return Padding( padding: const EdgeInsets.only(bottom: 12), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Icon( icon, size: 16, color: AppTheme.textSecondary, ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: const TextStyle( fontSize: 12, color: AppTheme.textSecondary, fontWeight: FontWeight.w500, ), ), const SizedBox(height: 2), isSelectable ? SelectableText( value, style: const TextStyle( fontSize: 14, color: AppTheme.textPrimary, ), ) : Text( value, style: const TextStyle( fontSize: 14, color: AppTheme.textPrimary, ), ), ], ), ), ], ), ); } Widget _buildActionButtons() { return Row( children: [ Expanded( child: ElevatedButton.icon( onPressed: onEdit, icon: const Icon(Icons.edit, size: 18), label: const Text('Modifier'), style: ElevatedButton.styleFrom( backgroundColor: AppTheme.primaryColor, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), ), ), const SizedBox(width: 12), Expanded( child: OutlinedButton.icon( onPressed: onCall, icon: const Icon(Icons.phone, size: 18), label: const Text('Appeler'), style: OutlinedButton.styleFrom( foregroundColor: AppTheme.primaryColor, side: const BorderSide(color: AppTheme.primaryColor), padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), ), ), const SizedBox(width: 12), OutlinedButton( onPressed: onMessage, style: OutlinedButton.styleFrom( foregroundColor: AppTheme.infoColor, side: const BorderSide(color: AppTheme.infoColor), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), child: const Icon(Icons.message, size: 18), ), ], ); } String _buildFullAddress() { final parts = []; if (membre.adresse != null && membre.adresse!.isNotEmpty) { parts.add(membre.adresse!); } if (membre.ville != null && membre.ville!.isNotEmpty) { parts.add(membre.ville!); } if (membre.codePostal != null && membre.codePostal!.isNotEmpty) { parts.add(membre.codePostal!); } if (membre.pays != null && membre.pays!.isNotEmpty) { parts.add(membre.pays!); } return parts.isNotEmpty ? parts.join(', ') : 'Non renseignée'; } String _calculateMembershipDuration() { final now = DateTime.now(); final adhesion = membre.dateAdhesion; final difference = now.difference(adhesion); final years = (difference.inDays / 365).floor(); final months = ((difference.inDays % 365) / 30).floor(); if (years > 0) { return months > 0 ? '$years an${years > 1 ? 's' : ''} et $months mois' : '$years an${years > 1 ? 's' : ''}'; } else if (months > 0) { return '$months mois'; } else { return '${difference.inDays} jour${difference.inDays > 1 ? 's' : ''}'; } } }