Initial commit: unionflow-mobile-apps
Application Flutter complète (sans build artifacts). Signed-off-by: lions dev Team
This commit is contained in:
127
lib/features/communication/domain/entities/conversation.dart
Normal file
127
lib/features/communication/domain/entities/conversation.dart
Normal file
@@ -0,0 +1,127 @@
|
||||
/// Entité métier Conversation
|
||||
///
|
||||
/// Représente une conversation (fil de messages) dans UnionFlow
|
||||
library conversation;
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'message.dart';
|
||||
|
||||
/// Type de conversation
|
||||
enum ConversationType {
|
||||
/// Conversation individuelle (1-1)
|
||||
individual,
|
||||
|
||||
/// Conversation de groupe
|
||||
group,
|
||||
|
||||
/// Canal broadcast (lecture seule pour la plupart)
|
||||
broadcast,
|
||||
|
||||
/// Canal d'annonces organisation
|
||||
announcement,
|
||||
}
|
||||
|
||||
/// Entité Conversation
|
||||
class Conversation extends Equatable {
|
||||
final String id;
|
||||
final String name;
|
||||
final String? description;
|
||||
final ConversationType type;
|
||||
final List<String> participantIds;
|
||||
final String? organizationId;
|
||||
final Message? lastMessage;
|
||||
final int unreadCount;
|
||||
final bool isMuted;
|
||||
final bool isPinned;
|
||||
final bool isArchived;
|
||||
final DateTime createdAt;
|
||||
final DateTime? updatedAt;
|
||||
final String? avatarUrl;
|
||||
final Map<String, dynamic>? metadata;
|
||||
|
||||
const Conversation({
|
||||
required this.id,
|
||||
required this.name,
|
||||
this.description,
|
||||
required this.type,
|
||||
required this.participantIds,
|
||||
this.organizationId,
|
||||
this.lastMessage,
|
||||
this.unreadCount = 0,
|
||||
this.isMuted = false,
|
||||
this.isPinned = false,
|
||||
this.isArchived = false,
|
||||
required this.createdAt,
|
||||
this.updatedAt,
|
||||
this.avatarUrl,
|
||||
this.metadata,
|
||||
});
|
||||
|
||||
/// Vérifie si la conversation a des messages non lus
|
||||
bool get hasUnread => unreadCount > 0;
|
||||
|
||||
/// Vérifie si c'est une conversation individuelle
|
||||
bool get isIndividual => type == ConversationType.individual;
|
||||
|
||||
/// Vérifie si c'est un broadcast
|
||||
bool get isBroadcast => type == ConversationType.broadcast;
|
||||
|
||||
/// Nombre de participants
|
||||
int get participantCount => participantIds.length;
|
||||
|
||||
/// Copie avec modifications
|
||||
Conversation copyWith({
|
||||
String? id,
|
||||
String? name,
|
||||
String? description,
|
||||
ConversationType? type,
|
||||
List<String>? participantIds,
|
||||
String? organizationId,
|
||||
Message? lastMessage,
|
||||
int? unreadCount,
|
||||
bool? isMuted,
|
||||
bool? isPinned,
|
||||
bool? isArchived,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
String? avatarUrl,
|
||||
Map<String, dynamic>? metadata,
|
||||
}) {
|
||||
return Conversation(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
description: description ?? this.description,
|
||||
type: type ?? this.type,
|
||||
participantIds: participantIds ?? this.participantIds,
|
||||
organizationId: organizationId ?? this.organizationId,
|
||||
lastMessage: lastMessage ?? this.lastMessage,
|
||||
unreadCount: unreadCount ?? this.unreadCount,
|
||||
isMuted: isMuted ?? this.isMuted,
|
||||
isPinned: isPinned ?? this.isPinned,
|
||||
isArchived: isArchived ?? this.isArchived,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
avatarUrl: avatarUrl ?? this.avatarUrl,
|
||||
metadata: metadata ?? this.metadata,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
type,
|
||||
participantIds,
|
||||
organizationId,
|
||||
lastMessage,
|
||||
unreadCount,
|
||||
isMuted,
|
||||
isPinned,
|
||||
isArchived,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
avatarUrl,
|
||||
metadata,
|
||||
];
|
||||
}
|
||||
173
lib/features/communication/domain/entities/message.dart
Normal file
173
lib/features/communication/domain/entities/message.dart
Normal file
@@ -0,0 +1,173 @@
|
||||
/// Entité métier Message
|
||||
///
|
||||
/// Représente un message dans le système de communication UnionFlow
|
||||
library message;
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
/// Type de message
|
||||
enum MessageType {
|
||||
/// Message individuel (membre à membre)
|
||||
individual,
|
||||
|
||||
/// Broadcast organisation (OrgAdmin → tous)
|
||||
broadcast,
|
||||
|
||||
/// Message ciblé par rôle (Moderator → groupe)
|
||||
targeted,
|
||||
|
||||
/// Notification système
|
||||
system,
|
||||
}
|
||||
|
||||
/// Statut de lecture du message
|
||||
enum MessageStatus {
|
||||
/// Envoyé mais non lu
|
||||
sent,
|
||||
|
||||
/// Livré (reçu par le serveur)
|
||||
delivered,
|
||||
|
||||
/// Lu par le destinataire
|
||||
read,
|
||||
|
||||
/// Échec d'envoi
|
||||
failed,
|
||||
}
|
||||
|
||||
/// Priorité du message
|
||||
enum MessagePriority {
|
||||
/// Priorité normale
|
||||
normal,
|
||||
|
||||
/// Priorité élevée (important)
|
||||
high,
|
||||
|
||||
/// Priorité urgente (critique)
|
||||
urgent,
|
||||
}
|
||||
|
||||
/// Entité Message
|
||||
class Message extends Equatable {
|
||||
final String id;
|
||||
final String conversationId;
|
||||
final String senderId;
|
||||
final String senderName;
|
||||
final String? senderAvatar;
|
||||
final String content;
|
||||
final MessageType type;
|
||||
final MessageStatus status;
|
||||
final MessagePriority priority;
|
||||
final List<String> recipientIds;
|
||||
final List<String>? recipientRoles;
|
||||
final String? organizationId;
|
||||
final DateTime createdAt;
|
||||
final DateTime? readAt;
|
||||
final Map<String, dynamic>? metadata;
|
||||
final List<String>? attachments;
|
||||
final bool isEdited;
|
||||
final DateTime? editedAt;
|
||||
final bool isDeleted;
|
||||
|
||||
const Message({
|
||||
required this.id,
|
||||
required this.conversationId,
|
||||
required this.senderId,
|
||||
required this.senderName,
|
||||
this.senderAvatar,
|
||||
required this.content,
|
||||
required this.type,
|
||||
required this.status,
|
||||
this.priority = MessagePriority.normal,
|
||||
required this.recipientIds,
|
||||
this.recipientRoles,
|
||||
this.organizationId,
|
||||
required this.createdAt,
|
||||
this.readAt,
|
||||
this.metadata,
|
||||
this.attachments,
|
||||
this.isEdited = false,
|
||||
this.editedAt,
|
||||
this.isDeleted = false,
|
||||
});
|
||||
|
||||
/// Vérifie si le message a été lu
|
||||
bool get isRead => status == MessageStatus.read;
|
||||
|
||||
/// Vérifie si le message est urgent
|
||||
bool get isUrgent => priority == MessagePriority.urgent;
|
||||
|
||||
/// Vérifie si le message est un broadcast
|
||||
bool get isBroadcast => type == MessageType.broadcast;
|
||||
|
||||
/// Vérifie si le message a des pièces jointes
|
||||
bool get hasAttachments => attachments != null && attachments!.isNotEmpty;
|
||||
|
||||
/// Copie avec modifications
|
||||
Message copyWith({
|
||||
String? id,
|
||||
String? conversationId,
|
||||
String? senderId,
|
||||
String? senderName,
|
||||
String? senderAvatar,
|
||||
String? content,
|
||||
MessageType? type,
|
||||
MessageStatus? status,
|
||||
MessagePriority? priority,
|
||||
List<String>? recipientIds,
|
||||
List<String>? recipientRoles,
|
||||
String? organizationId,
|
||||
DateTime? createdAt,
|
||||
DateTime? readAt,
|
||||
Map<String, dynamic>? metadata,
|
||||
List<String>? attachments,
|
||||
bool? isEdited,
|
||||
DateTime? editedAt,
|
||||
bool? isDeleted,
|
||||
}) {
|
||||
return Message(
|
||||
id: id ?? this.id,
|
||||
conversationId: conversationId ?? this.conversationId,
|
||||
senderId: senderId ?? this.senderId,
|
||||
senderName: senderName ?? this.senderName,
|
||||
senderAvatar: senderAvatar ?? this.senderAvatar,
|
||||
content: content ?? this.content,
|
||||
type: type ?? this.type,
|
||||
status: status ?? this.status,
|
||||
priority: priority ?? this.priority,
|
||||
recipientIds: recipientIds ?? this.recipientIds,
|
||||
recipientRoles: recipientRoles ?? this.recipientRoles,
|
||||
organizationId: organizationId ?? this.organizationId,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
readAt: readAt ?? this.readAt,
|
||||
metadata: metadata ?? this.metadata,
|
||||
attachments: attachments ?? this.attachments,
|
||||
isEdited: isEdited ?? this.isEdited,
|
||||
editedAt: editedAt ?? this.editedAt,
|
||||
isDeleted: isDeleted ?? this.isDeleted,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
conversationId,
|
||||
senderId,
|
||||
senderName,
|
||||
senderAvatar,
|
||||
content,
|
||||
type,
|
||||
status,
|
||||
priority,
|
||||
recipientIds,
|
||||
recipientRoles,
|
||||
organizationId,
|
||||
createdAt,
|
||||
readAt,
|
||||
metadata,
|
||||
attachments,
|
||||
isEdited,
|
||||
editedAt,
|
||||
isDeleted,
|
||||
];
|
||||
}
|
||||
154
lib/features/communication/domain/entities/message_template.dart
Normal file
154
lib/features/communication/domain/entities/message_template.dart
Normal file
@@ -0,0 +1,154 @@
|
||||
/// Entité métier Template de Message
|
||||
///
|
||||
/// Templates réutilisables pour notifications et broadcasts
|
||||
library message_template;
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
/// Catégorie de template
|
||||
enum TemplateCategory {
|
||||
/// Événements
|
||||
events,
|
||||
|
||||
/// Finances
|
||||
finances,
|
||||
|
||||
/// Adhésions
|
||||
membership,
|
||||
|
||||
/// Solidarité
|
||||
solidarity,
|
||||
|
||||
/// Système
|
||||
system,
|
||||
|
||||
/// Personnalisé
|
||||
custom,
|
||||
}
|
||||
|
||||
/// Variables dynamiques dans les templates
|
||||
class TemplateVariable {
|
||||
final String name;
|
||||
final String description;
|
||||
final String placeholder;
|
||||
final bool required;
|
||||
|
||||
const TemplateVariable({
|
||||
required this.name,
|
||||
required this.description,
|
||||
required this.placeholder,
|
||||
this.required = true,
|
||||
});
|
||||
}
|
||||
|
||||
/// Entité Template de Message
|
||||
class MessageTemplate extends Equatable {
|
||||
final String id;
|
||||
final String name;
|
||||
final String description;
|
||||
final TemplateCategory category;
|
||||
final String subject;
|
||||
final String body;
|
||||
final List<TemplateVariable> variables;
|
||||
final String? organizationId;
|
||||
final String createdBy;
|
||||
final DateTime createdAt;
|
||||
final DateTime? updatedAt;
|
||||
final bool isActive;
|
||||
final bool isSystem;
|
||||
final int usageCount;
|
||||
final Map<String, dynamic>? metadata;
|
||||
|
||||
const MessageTemplate({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.description,
|
||||
required this.category,
|
||||
required this.subject,
|
||||
required this.body,
|
||||
this.variables = const [],
|
||||
this.organizationId,
|
||||
required this.createdBy,
|
||||
required this.createdAt,
|
||||
this.updatedAt,
|
||||
this.isActive = true,
|
||||
this.isSystem = false,
|
||||
this.usageCount = 0,
|
||||
this.metadata,
|
||||
});
|
||||
|
||||
/// Vérifie si le template est éditable (pas système)
|
||||
bool get isEditable => !isSystem;
|
||||
|
||||
/// Génère un message à partir du template avec des valeurs
|
||||
String generateMessage(Map<String, String> values) {
|
||||
String result = body;
|
||||
|
||||
for (final variable in variables) {
|
||||
final value = values[variable.name];
|
||||
if (value != null) {
|
||||
result = result.replaceAll('{{${variable.name}}}', value);
|
||||
} else if (variable.required) {
|
||||
throw ArgumentError('Variable requise manquante: ${variable.name}');
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Copie avec modifications
|
||||
MessageTemplate copyWith({
|
||||
String? id,
|
||||
String? name,
|
||||
String? description,
|
||||
TemplateCategory? category,
|
||||
String? subject,
|
||||
String? body,
|
||||
List<TemplateVariable>? variables,
|
||||
String? organizationId,
|
||||
String? createdBy,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
bool? isActive,
|
||||
bool? isSystem,
|
||||
int? usageCount,
|
||||
Map<String, dynamic>? metadata,
|
||||
}) {
|
||||
return MessageTemplate(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
description: description ?? this.description,
|
||||
category: category ?? this.category,
|
||||
subject: subject ?? this.subject,
|
||||
body: body ?? this.body,
|
||||
variables: variables ?? this.variables,
|
||||
organizationId: organizationId ?? this.organizationId,
|
||||
createdBy: createdBy ?? this.createdBy,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
isActive: isActive ?? this.isActive,
|
||||
isSystem: isSystem ?? this.isSystem,
|
||||
usageCount: usageCount ?? this.usageCount,
|
||||
metadata: metadata ?? this.metadata,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
category,
|
||||
subject,
|
||||
body,
|
||||
variables,
|
||||
organizationId,
|
||||
createdBy,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
isActive,
|
||||
isSystem,
|
||||
usageCount,
|
||||
metadata,
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user