feat(mobile): Contribution Totale + KPI dashboard membre

- MembreDashboardSyntheseModel: totalCotisationsPayeesToutTemps
- DashboardStatsEntity: contributionsAmountOnly (cotisations seules)
- Mapping: Mon Solde Total = cotisations tout temps + épargne, Contribution Totale = cotisations seules
- Engagement: fallback tauxCotisationsPerso si tauxParticipation absent
- Carte Contribution Totale utilise contributionsAmountOnly

Made-with: Cursor
This commit is contained in:
dahoud
2026-03-09 19:58:39 +00:00
parent 0a9dece955
commit 553e731a51
4 changed files with 613 additions and 260 deletions

View File

@@ -8,11 +8,15 @@ class DashboardStatsEntity extends Equatable {
final int upcomingEvents;
final int totalContributions;
final double totalContributionAmount;
/// Montant des cotisations seules (sans épargne), pour la carte « Contribution Totale » membre.
final double? contributionsAmountOnly;
final int pendingRequests;
final int completedProjects;
final double monthlyGrowth;
final double engagementRate;
final DateTime lastUpdated;
final int? totalOrganizations;
final Map<String, int>? organizationTypeDistribution;
const DashboardStatsEntity({
required this.totalMembers,
@@ -21,11 +25,14 @@ class DashboardStatsEntity extends Equatable {
required this.upcomingEvents,
required this.totalContributions,
required this.totalContributionAmount,
this.contributionsAmountOnly,
required this.pendingRequests,
required this.completedProjects,
required this.monthlyGrowth,
required this.engagementRate,
required this.lastUpdated,
this.totalOrganizations,
this.organizationTypeDistribution,
});
// Méthodes utilitaires
@@ -50,11 +57,14 @@ class DashboardStatsEntity extends Equatable {
upcomingEvents,
totalContributions,
totalContributionAmount,
contributionsAmountOnly,
pendingRequests,
completedProjects,
monthlyGrowth,
engagementRate,
lastUpdated,
totalOrganizations,
organizationTypeDistribution,
];
}
@@ -148,10 +158,16 @@ class UpcomingEventEntity extends Equatable {
bool get isFull => currentParticipants >= maxParticipants;
double get fillPercentage => maxParticipants > 0 ? currentParticipants / maxParticipants : 0.0;
int get daysUntilEventInt {
final now = DateTime.now();
final difference = startDate.difference(now);
return difference.inDays;
}
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) {
@@ -163,6 +179,14 @@ class UpcomingEventEntity extends Equatable {
}
}
String get formattedDate {
final months = ['Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Jun',
'Jul', 'Aoû', 'Sep', 'Oct', 'Nov', 'Déc'];
return '${startDate.day} ${months[startDate.month - 1]} ${startDate.year}';
}
bool get hasParticipantInfo => maxParticipants > 0;
bool get isToday {
final now = DateTime.now();
return startDate.year == now.year &&