231 lines
6.2 KiB
Dart
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,
|
|
];
|
|
}
|