217 lines
5.6 KiB
Dart
217 lines
5.6 KiB
Dart
import 'package:equatable/equatable.dart';
|
|
import 'package:json_annotation/json_annotation.dart';
|
|
|
|
part 'dashboard_stats_model.g.dart';
|
|
|
|
/// Modèle pour les statistiques du dashboard
|
|
@JsonSerializable()
|
|
class DashboardStatsModel 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 DashboardStatsModel({
|
|
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,
|
|
});
|
|
|
|
factory DashboardStatsModel.fromJson(Map<String, dynamic> json) =>
|
|
_$DashboardStatsModelFromJson(json);
|
|
|
|
Map<String, dynamic> toJson() => _$DashboardStatsModelToJson(this);
|
|
|
|
// Getters calculés
|
|
String get formattedContributionAmount {
|
|
return '${totalContributionAmount.toStringAsFixed(2)} €';
|
|
}
|
|
|
|
bool get hasGrowth => monthlyGrowth > 0;
|
|
|
|
bool get isHighEngagement => engagementRate > 0.7;
|
|
|
|
double get activeMemberPercentage {
|
|
return totalMembers > 0 ? (activeMembers / totalMembers) : 0.0;
|
|
}
|
|
|
|
@override
|
|
List<Object?> get props => [
|
|
totalMembers,
|
|
activeMembers,
|
|
totalEvents,
|
|
upcomingEvents,
|
|
totalContributions,
|
|
totalContributionAmount,
|
|
pendingRequests,
|
|
completedProjects,
|
|
monthlyGrowth,
|
|
engagementRate,
|
|
lastUpdated,
|
|
];
|
|
}
|
|
|
|
/// Modèle pour les activités récentes
|
|
@JsonSerializable()
|
|
class RecentActivityModel 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 RecentActivityModel({
|
|
required this.id,
|
|
required this.type,
|
|
required this.title,
|
|
required this.description,
|
|
this.userAvatar,
|
|
required this.userName,
|
|
required this.timestamp,
|
|
this.actionUrl,
|
|
this.metadata,
|
|
});
|
|
|
|
factory RecentActivityModel.fromJson(Map<String, dynamic> json) =>
|
|
_$RecentActivityModelFromJson(json);
|
|
|
|
Map<String, dynamic> toJson() => _$RecentActivityModelToJson(this);
|
|
|
|
// Getter calculé pour l'affichage du temps
|
|
String get timeAgo {
|
|
final now = DateTime.now();
|
|
final difference = now.difference(timestamp);
|
|
|
|
if (difference.inDays > 0) {
|
|
return 'il y a ${difference.inDays} jour${difference.inDays > 1 ? 's' : ''}';
|
|
} else if (difference.inHours > 0) {
|
|
return 'il y a ${difference.inHours} heure${difference.inHours > 1 ? 's' : ''}';
|
|
} else if (difference.inMinutes > 0) {
|
|
return 'il y a ${difference.inMinutes} minute${difference.inMinutes > 1 ? 's' : ''}';
|
|
} else {
|
|
return 'à l\'instant';
|
|
}
|
|
}
|
|
|
|
@override
|
|
List<Object?> get props => [
|
|
id,
|
|
type,
|
|
title,
|
|
description,
|
|
userAvatar,
|
|
userName,
|
|
timestamp,
|
|
actionUrl,
|
|
metadata,
|
|
];
|
|
}
|
|
|
|
/// Modèle pour les événements à venir
|
|
@JsonSerializable()
|
|
class UpcomingEventModel 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 UpcomingEventModel({
|
|
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,
|
|
});
|
|
|
|
factory UpcomingEventModel.fromJson(Map<String, dynamic> json) =>
|
|
_$UpcomingEventModelFromJson(json);
|
|
|
|
Map<String, dynamic> toJson() => _$UpcomingEventModelToJson(this);
|
|
|
|
bool get isAlmostFull => currentParticipants >= (maxParticipants * 0.8);
|
|
bool get isFull => currentParticipants >= maxParticipants;
|
|
double get fillPercentage => maxParticipants > 0 ? currentParticipants / maxParticipants : 0.0;
|
|
|
|
@override
|
|
List<Object?> get props => [
|
|
id,
|
|
title,
|
|
description,
|
|
startDate,
|
|
endDate,
|
|
location,
|
|
maxParticipants,
|
|
currentParticipants,
|
|
status,
|
|
imageUrl,
|
|
tags,
|
|
];
|
|
}
|
|
|
|
/// Modèle pour les données du dashboard complet
|
|
@JsonSerializable()
|
|
class DashboardDataModel extends Equatable {
|
|
final DashboardStatsModel stats;
|
|
final List<RecentActivityModel> recentActivities;
|
|
final List<UpcomingEventModel> upcomingEvents;
|
|
final Map<String, dynamic> userPreferences;
|
|
final String organizationId;
|
|
final String userId;
|
|
|
|
const DashboardDataModel({
|
|
required this.stats,
|
|
required this.recentActivities,
|
|
required this.upcomingEvents,
|
|
required this.userPreferences,
|
|
required this.organizationId,
|
|
required this.userId,
|
|
});
|
|
|
|
factory DashboardDataModel.fromJson(Map<String, dynamic> json) =>
|
|
_$DashboardDataModelFromJson(json);
|
|
|
|
Map<String, dynamic> toJson() => _$DashboardDataModelToJson(this);
|
|
|
|
@override
|
|
List<Object?> get props => [
|
|
stats,
|
|
recentActivities,
|
|
upcomingEvents,
|
|
userPreferences,
|
|
organizationId,
|
|
userId,
|
|
];
|
|
}
|