Files
2025-11-17 16:02:04 +00:00

231 lines
6.2 KiB
Dart

import 'package:equatable/equatable.dart';
/// Entité pour les statistiques du dashboard
class DashboardStatsEntity extends Equatable {
final int totalMembers;
final int activeMembers;
final int totalEvents;
final int upcomingEvents;
final int totalContributions;
final double totalContributionAmount;
final int pendingRequests;
final int completedProjects;
final double monthlyGrowth;
final double engagementRate;
final DateTime lastUpdated;
const DashboardStatsEntity({
required this.totalMembers,
required this.activeMembers,
required this.totalEvents,
required this.upcomingEvents,
required this.totalContributions,
required this.totalContributionAmount,
required this.pendingRequests,
required this.completedProjects,
required this.monthlyGrowth,
required this.engagementRate,
required this.lastUpdated,
});
// Méthodes utilitaires
double get memberActivityRate => totalMembers > 0 ? activeMembers / totalMembers : 0.0;
bool get hasGrowth => monthlyGrowth > 0;
bool get isHighEngagement => engagementRate > 0.7;
String get formattedContributionAmount {
if (totalContributionAmount >= 1000000) {
return '${(totalContributionAmount / 1000000).toStringAsFixed(1)}M';
} else if (totalContributionAmount >= 1000) {
return '${(totalContributionAmount / 1000).toStringAsFixed(1)}K';
}
return totalContributionAmount.toStringAsFixed(0);
}
@override
List<Object?> get props => [
totalMembers,
activeMembers,
totalEvents,
upcomingEvents,
totalContributions,
totalContributionAmount,
pendingRequests,
completedProjects,
monthlyGrowth,
engagementRate,
lastUpdated,
];
}
/// Entité pour les activités récentes
class RecentActivityEntity extends Equatable {
final String id;
final String type;
final String title;
final String description;
final String? userAvatar;
final String userName;
final DateTime timestamp;
final String? actionUrl;
final Map<String, dynamic>? metadata;
const RecentActivityEntity({
required this.id,
required this.type,
required this.title,
required this.description,
this.userAvatar,
required this.userName,
required this.timestamp,
this.actionUrl,
this.metadata,
});
// Méthodes utilitaires
String get timeAgo {
final now = DateTime.now();
final difference = now.difference(timestamp);
if (difference.inDays > 0) {
return '${difference.inDays}j';
} else if (difference.inHours > 0) {
return '${difference.inHours}h';
} else if (difference.inMinutes > 0) {
return '${difference.inMinutes}min';
} else {
return 'maintenant';
}
}
bool get isRecent => DateTime.now().difference(timestamp).inHours < 24;
bool get hasAction => actionUrl != null && actionUrl!.isNotEmpty;
@override
List<Object?> get props => [
id,
type,
title,
description,
userAvatar,
userName,
timestamp,
actionUrl,
metadata,
];
}
/// Entité pour les événements à venir
class UpcomingEventEntity extends Equatable {
final String id;
final String title;
final String description;
final DateTime startDate;
final DateTime? endDate;
final String location;
final int maxParticipants;
final int currentParticipants;
final String status;
final String? imageUrl;
final List<String> tags;
const UpcomingEventEntity({
required this.id,
required this.title,
required this.description,
required this.startDate,
this.endDate,
required this.location,
required this.maxParticipants,
required this.currentParticipants,
required this.status,
this.imageUrl,
required this.tags,
});
// Méthodes utilitaires
bool get isAlmostFull => currentParticipants >= (maxParticipants * 0.8);
bool get isFull => currentParticipants >= maxParticipants;
double get fillPercentage => maxParticipants > 0 ? currentParticipants / maxParticipants : 0.0;
String get daysUntilEvent {
final now = DateTime.now();
final difference = startDate.difference(now);
if (difference.inDays > 0) {
return '${difference.inDays} jour${difference.inDays > 1 ? 's' : ''}';
} else if (difference.inHours > 0) {
return '${difference.inHours}h';
} else if (difference.inMinutes > 0) {
return '${difference.inMinutes}min';
} else {
return 'En cours';
}
}
bool get isToday {
final now = DateTime.now();
return startDate.year == now.year &&
startDate.month == now.month &&
startDate.day == now.day;
}
bool get isTomorrow {
final tomorrow = DateTime.now().add(const Duration(days: 1));
return startDate.year == tomorrow.year &&
startDate.month == tomorrow.month &&
startDate.day == tomorrow.day;
}
@override
List<Object?> get props => [
id,
title,
description,
startDate,
endDate,
location,
maxParticipants,
currentParticipants,
status,
imageUrl,
tags,
];
}
/// Entité principale du dashboard
class DashboardEntity extends Equatable {
final DashboardStatsEntity stats;
final List<RecentActivityEntity> recentActivities;
final List<UpcomingEventEntity> upcomingEvents;
final Map<String, dynamic> userPreferences;
final String organizationId;
final String userId;
const DashboardEntity({
required this.stats,
required this.recentActivities,
required this.upcomingEvents,
required this.userPreferences,
required this.organizationId,
required this.userId,
});
// Méthodes utilitaires
bool get hasRecentActivity => recentActivities.isNotEmpty;
bool get hasUpcomingEvents => upcomingEvents.isNotEmpty;
int get todayEventsCount => upcomingEvents.where((e) => e.isToday).length;
int get tomorrowEventsCount => upcomingEvents.where((e) => e.isTomorrow).length;
int get recentActivitiesCount => recentActivities.length;
@override
List<Object?> get props => [
stats,
recentActivities,
upcomingEvents,
userPreferences,
organizationId,
userId,
];
}