/// Widget tuile de conversation v4 library conversation_tile; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import '../../../../shared/design_system/unionflow_design_system.dart'; import '../../domain/entities/conversation.dart'; class ConversationTile extends StatelessWidget { final ConversationSummary conversation; final VoidCallback onTap; const ConversationTile({ super.key, required this.conversation, required this.onTap, }); String _formatDate(DateTime date) { final now = DateTime.now(); final difference = now.difference(date); if (difference.inDays == 0) { return DateFormat('HH:mm').format(date); } else if (difference.inDays == 1) { return 'Hier'; } else if (difference.inDays < 7) { return DateFormat('EEEE', 'fr_FR').format(date); } else { return DateFormat('dd/MM/yy').format(date); } } IconData _typeIcon() { switch (conversation.typeConversation) { case 'DIRECTE': return Icons.person_outline; case 'ROLE_CANAL': return Icons.account_circle_outlined; case 'GROUPE': return Icons.group_outlined; default: return Icons.chat_bubble_outline; } } String _apercuMessage() { if (conversation.dernierMessageApercu == null) return 'Aucun message'; final type = conversation.dernierMessageType ?? 'TEXTE'; if (type == 'VOCAL') return '🎙️ Note vocale'; if (type == 'IMAGE') return '📷 Image'; return conversation.dernierMessageApercu!; } @override Widget build(BuildContext context) { final isDark = Theme.of(context).brightness == Brightness.dark; return InkWell( onTap: onTap, borderRadius: BorderRadius.circular(SpacingTokens.radiusMd), child: Container( padding: const EdgeInsets.all(SpacingTokens.md), decoration: BoxDecoration( color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(SpacingTokens.radiusMd), border: Border.all( color: conversation.hasUnread ? AppColors.primary.withOpacity(0.3) : ColorTokens.outline, ), ), child: Row( children: [ // Avatar type Container( width: 48, height: 48, decoration: BoxDecoration( color: AppColors.primary.withOpacity(0.1), borderRadius: BorderRadius.circular(SpacingTokens.radiusCircular), ), child: Icon(_typeIcon(), color: AppColors.primary, size: 24), ), const SizedBox(width: SpacingTokens.md), // Contenu Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Text( conversation.titre, style: AppTypography.actionText.copyWith( fontWeight: conversation.hasUnread ? FontWeight.bold : FontWeight.normal, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), if (conversation.dernierMessageAt != null) Text( _formatDate(conversation.dernierMessageAt!), style: AppTypography.subtitleSmall.copyWith( color: isDark ? AppColors.textSecondaryDark : AppColors.textSecondary, ), ), ], ), const SizedBox(height: 4), Text( _apercuMessage(), style: AppTypography.bodyTextSmall.copyWith( color: isDark ? AppColors.textSecondaryDark : AppColors.textSecondary, fontWeight: conversation.hasUnread ? FontWeight.w600 : FontWeight.normal, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), ], ), ), // Badge non lus if (conversation.hasUnread) ...[ const SizedBox(width: SpacingTokens.sm), Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: AppColors.primary, borderRadius: BorderRadius.circular(SpacingTokens.radiusCircular), ), child: Text( '${conversation.nonLus}', style: AppTypography.badgeText.copyWith( color: Colors.white, fontWeight: FontWeight.bold, ), ), ), ], ], ), ), ); } }