Aligné avec le backend MessagingResource : - Nouveau module communication (conversations, messages, participants) - Respect des ContactPolicy (qui peut parler à qui par rôle) - Gestion MemberBlock (blocages individuels) - UI : conversations list, conversation detail, broadcast, tiles - BLoC : MessagingBloc avec events (envoyer, démarrer conversation rôle, etc.)
121 lines
3.7 KiB
Dart
121 lines
3.7 KiB
Dart
/// Entités métier Conversation v4
|
|
///
|
|
/// Correspond aux DTOs backend : ConversationSummaryResponse et ConversationResponse
|
|
library conversation;
|
|
|
|
import 'package:equatable/equatable.dart';
|
|
import 'message.dart';
|
|
|
|
// ── Résumé de conversation (liste) ───────────────────────────────────────────
|
|
|
|
/// Résumé d'une conversation pour l'affichage en liste
|
|
class ConversationSummary extends Equatable {
|
|
final String id;
|
|
final String typeConversation; // DIRECTE | ROLE_CANAL | GROUPE
|
|
final String titre;
|
|
final String statut; // ACTIVE | ARCHIVEE
|
|
final String? dernierMessageApercu;
|
|
final String? dernierMessageType;
|
|
final DateTime? dernierMessageAt;
|
|
final int nonLus;
|
|
final String? organisationId;
|
|
|
|
const ConversationSummary({
|
|
required this.id,
|
|
required this.typeConversation,
|
|
required this.titre,
|
|
required this.statut,
|
|
this.dernierMessageApercu,
|
|
this.dernierMessageType,
|
|
this.dernierMessageAt,
|
|
this.nonLus = 0,
|
|
this.organisationId,
|
|
});
|
|
|
|
bool get hasUnread => nonLus > 0;
|
|
bool get isDirecte => typeConversation == 'DIRECTE';
|
|
bool get isRoleCanal => typeConversation == 'ROLE_CANAL';
|
|
bool get isGroupe => typeConversation == 'GROUPE';
|
|
bool get isActive => statut == 'ACTIVE';
|
|
|
|
@override
|
|
List<Object?> get props => [
|
|
id, typeConversation, titre, statut,
|
|
dernierMessageApercu, dernierMessageType, dernierMessageAt,
|
|
nonLus, organisationId,
|
|
];
|
|
}
|
|
|
|
// ── Participant ───────────────────────────────────────────────────────────────
|
|
|
|
/// Participant dans une conversation
|
|
class ConversationParticipant extends Equatable {
|
|
final String membreId;
|
|
final String? prenom;
|
|
final String? nom;
|
|
final String? roleDansConversation;
|
|
final DateTime? luJusqua;
|
|
|
|
const ConversationParticipant({
|
|
required this.membreId,
|
|
this.prenom,
|
|
this.nom,
|
|
this.roleDansConversation,
|
|
this.luJusqua,
|
|
});
|
|
|
|
String get nomComplet {
|
|
if (prenom != null && nom != null) return '$prenom $nom';
|
|
if (prenom != null) return prenom!;
|
|
if (nom != null) return nom!;
|
|
return membreId;
|
|
}
|
|
|
|
@override
|
|
List<Object?> get props => [membreId, prenom, nom, roleDansConversation, luJusqua];
|
|
}
|
|
|
|
// ── Conversation complète (détail) ───────────────────────────────────────────
|
|
|
|
/// Conversation complète avec participants et messages
|
|
class Conversation extends Equatable {
|
|
final String id;
|
|
final String typeConversation;
|
|
final String titre;
|
|
final String statut;
|
|
final String? organisationId;
|
|
final String? organisationNom;
|
|
final DateTime? dateCreation;
|
|
final int nombreMessages;
|
|
final List<ConversationParticipant> participants;
|
|
final List<Message> messages;
|
|
final int nonLus;
|
|
final String? roleCible;
|
|
|
|
const Conversation({
|
|
required this.id,
|
|
required this.typeConversation,
|
|
required this.titre,
|
|
required this.statut,
|
|
this.organisationId,
|
|
this.organisationNom,
|
|
this.dateCreation,
|
|
this.nombreMessages = 0,
|
|
this.participants = const [],
|
|
this.messages = const [],
|
|
this.nonLus = 0,
|
|
this.roleCible,
|
|
});
|
|
|
|
bool get isDirecte => typeConversation == 'DIRECTE';
|
|
bool get isRoleCanal => typeConversation == 'ROLE_CANAL';
|
|
bool get isGroupe => typeConversation == 'GROUPE';
|
|
bool get isActive => statut == 'ACTIVE';
|
|
|
|
@override
|
|
List<Object?> get props => [
|
|
id, typeConversation, titre, statut, organisationId, organisationNom,
|
|
dateCreation, nombreMessages, participants, messages, nonLus, roleCible,
|
|
];
|
|
}
|