import 'package:flutter/material.dart'; /// Widget réutilisable pour afficher un élément d'activité /// /// Composant standardisé pour les listes d'activités récentes, /// notifications, historiques, etc. class ActivityItem extends StatelessWidget { /// Titre principal de l'activité final String title; /// Description ou détails de l'activité final String? description; /// Horodatage de l'activité final String timestamp; /// Icône représentative de l'activité final IconData? icon; /// Couleur thématique de l'activité final Color? color; /// Type d'activité pour le style automatique final ActivityType? type; /// Callback lors du tap sur l'élément final VoidCallback? onTap; /// Style de l'élément d'activité final ActivityItemStyle style; /// Afficher ou non l'indicateur de statut final bool showStatusIndicator; const ActivityItem({ super.key, required this.title, this.description, required this.timestamp, this.icon, this.color, this.type, this.onTap, this.style = ActivityItemStyle.normal, this.showStatusIndicator = true, }); /// Constructeur pour une activité système const ActivityItem.system({ super.key, required this.title, this.description, required this.timestamp, this.onTap, }) : icon = Icons.settings, color = const Color(0xFF6C5CE7), type = ActivityType.system, style = ActivityItemStyle.normal, showStatusIndicator = true; /// Constructeur pour une activité utilisateur const ActivityItem.user({ super.key, required this.title, this.description, required this.timestamp, this.onTap, }) : icon = Icons.person, color = const Color(0xFF00B894), type = ActivityType.user, style = ActivityItemStyle.normal, showStatusIndicator = true; /// Constructeur pour une alerte const ActivityItem.alert({ super.key, required this.title, this.description, required this.timestamp, this.onTap, }) : icon = Icons.warning, color = Colors.orange, type = ActivityType.alert, style = ActivityItemStyle.alert, showStatusIndicator = true; /// Constructeur pour une erreur const ActivityItem.error({ super.key, required this.title, this.description, required this.timestamp, this.onTap, }) : icon = Icons.error, color = Colors.red, type = ActivityType.error, style = ActivityItemStyle.alert, showStatusIndicator = true; /// Constructeur pour une activité de succès const ActivityItem.success({ super.key, required this.title, this.description, required this.timestamp, this.onTap, }) : icon = Icons.check_circle, color = const Color(0xFF00B894), type = ActivityType.success, style = ActivityItemStyle.normal, showStatusIndicator = true; @override Widget build(BuildContext context) { final effectiveColor = _getEffectiveColor(); final effectiveIcon = _getEffectiveIcon(); return GestureDetector( onTap: onTap, child: Container( margin: const EdgeInsets.only(bottom: 8), padding: _getPadding(), decoration: _getDecoration(effectiveColor), child: _buildContent(effectiveColor, effectiveIcon), ), ); } /// Contenu principal de l'élément Widget _buildContent(Color effectiveColor, IconData effectiveIcon) { switch (style) { case ActivityItemStyle.minimal: return _buildMinimalContent(effectiveColor, effectiveIcon); case ActivityItemStyle.normal: return _buildNormalContent(effectiveColor, effectiveIcon); case ActivityItemStyle.detailed: return _buildDetailedContent(effectiveColor, effectiveIcon); case ActivityItemStyle.alert: return _buildAlertContent(effectiveColor, effectiveIcon); } } /// Contenu minimal (ligne simple) Widget _buildMinimalContent(Color effectiveColor, IconData effectiveIcon) { return Row( children: [ if (showStatusIndicator) Container( width: 8, height: 8, decoration: BoxDecoration( color: effectiveColor, shape: BoxShape.circle, ), ), if (showStatusIndicator) const SizedBox(width: 8), Expanded( child: Text( title, style: const TextStyle( fontSize: 12, fontWeight: FontWeight.w500, ), ), ), Text( timestamp, style: const TextStyle( color: Colors.grey, fontSize: 10, ), ), ], ); } /// Contenu normal avec icône Widget _buildNormalContent(Color effectiveColor, IconData effectiveIcon) { return Row( children: [ if (showStatusIndicator) ...[ Container( padding: const EdgeInsets.all(6), decoration: BoxDecoration( color: effectiveColor.withOpacity(0.1), shape: BoxShape.circle, ), child: Icon( effectiveIcon, color: effectiveColor, size: 16, ), ), const SizedBox(width: 12), ], Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFF1F2937), ), ), if (description != null) ...[ const SizedBox(height: 2), Text( description!, style: TextStyle( fontSize: 12, color: Colors.grey[600], ), ), ], ], ), ), const SizedBox(width: 8), Text( timestamp, style: TextStyle( color: Colors.grey[500], fontSize: 11, fontWeight: FontWeight.w500, ), ), ], ); } /// Contenu détaillé avec plus d'informations Widget _buildDetailedContent(Color effectiveColor, IconData effectiveIcon) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: effectiveColor.withOpacity(0.1), borderRadius: BorderRadius.circular(8), ), child: Icon( effectiveIcon, color: effectiveColor, size: 18, ), ), const SizedBox(width: 12), Expanded( child: Text( title, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xFF1F2937), ), ), ), Text( timestamp, style: TextStyle( color: Colors.grey[500], fontSize: 12, fontWeight: FontWeight.w500, ), ), ], ), if (description != null) ...[ const SizedBox(height: 8), Padding( padding: const EdgeInsets.only(left: 42), child: Text( description!, style: TextStyle( fontSize: 14, color: Colors.grey[700], height: 1.4, ), ), ), ], ], ); } /// Contenu pour les alertes avec style spécial Widget _buildAlertContent(Color effectiveColor, IconData effectiveIcon) { return Row( children: [ Icon( effectiveIcon, color: effectiveColor, size: 18, ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: effectiveColor, ), ), if (description != null) ...[ const SizedBox(height: 2), Text( description!, style: TextStyle( fontSize: 12, color: Colors.grey[600], ), ), ], ], ), ), const SizedBox(width: 8), Text( timestamp, style: TextStyle( color: Colors.grey[500], fontSize: 11, ), ), ], ); } /// Couleur effective selon le type Color _getEffectiveColor() { if (color != null) return color!; switch (type) { case ActivityType.system: return const Color(0xFF6C5CE7); case ActivityType.user: return const Color(0xFF00B894); case ActivityType.organization: return const Color(0xFF0984E3); case ActivityType.event: return const Color(0xFFE17055); case ActivityType.alert: return Colors.orange; case ActivityType.error: return Colors.red; case ActivityType.success: return const Color(0xFF00B894); case null: return const Color(0xFF6C5CE7); } } /// Icône effective selon le type IconData _getEffectiveIcon() { if (icon != null) return icon!; switch (type) { case ActivityType.system: return Icons.settings; case ActivityType.user: return Icons.person; case ActivityType.organization: return Icons.business; case ActivityType.event: return Icons.event; case ActivityType.alert: return Icons.warning; case ActivityType.error: return Icons.error; case ActivityType.success: return Icons.check_circle; case null: return Icons.circle; } } /// Padding selon le style EdgeInsets _getPadding() { switch (style) { case ActivityItemStyle.minimal: return const EdgeInsets.symmetric(vertical: 4, horizontal: 8); case ActivityItemStyle.normal: return const EdgeInsets.all(8); case ActivityItemStyle.detailed: return const EdgeInsets.all(12); case ActivityItemStyle.alert: return const EdgeInsets.all(10); } } /// Décoration selon le style BoxDecoration _getDecoration(Color effectiveColor) { switch (style) { case ActivityItemStyle.minimal: return const BoxDecoration(); case ActivityItemStyle.normal: return BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.02), blurRadius: 4, offset: const Offset(0, 1), ), ], ); case ActivityItemStyle.detailed: return BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 8, offset: const Offset(0, 2), ), ], ); case ActivityItemStyle.alert: return BoxDecoration( color: effectiveColor.withOpacity(0.05), borderRadius: BorderRadius.circular(8), border: Border.all( color: effectiveColor.withOpacity(0.2), width: 1, ), ); } } } /// Types d'activité enum ActivityType { system, user, organization, event, alert, error, success, } /// Styles d'élément d'activité enum ActivityItemStyle { minimal, normal, detailed, alert, }