feat(mobile): consolidation modules epargne, messaging, organisations

- Epargne: badge LCB-FT (bouclier ambre) sur comptes avec fonds bloques + note recap
- EpargneDetail: historique pagine (page/size), affichage soldeAvant/soldeApres/motif dans chaque transaction, bouton "Charger plus"
- TransactionEpargneRepository: getByCompte accepte page et size, gere reponse paginee Spring (content[])
- MessagingDatasource: markMessageAsRead silencieuse (pas d'endpoint unitaire), getUnreadCount somme unreadCount des conversations
- OrganizationDetail: _memberCount charge le vrai nombre depuis GET /membres/count, affiche la valeur reelle au lieu de nombreMembres (toujours 0)
This commit is contained in:
dahoud
2026-04-05 13:37:21 +00:00
parent 65b5c79c43
commit 289efc4956
7 changed files with 160 additions and 38 deletions

View File

@@ -345,4 +345,20 @@ class OrganizationRepositoryImpl implements IOrganizationRepository {
throw Exception('Erreur inattendue lors de la récupération des statistiques: $e');
}
}
@override
Future<int> getMembreCount(String organizationId) async {
try {
final response = await _apiClient.get('$_baseUrl/$organizationId/membres/count');
if (response.statusCode == 200 && response.data is Map) {
return (response.data['count'] as num?)?.toInt() ?? 0;
}
return 0;
} on DioException catch (e) {
if (e.type == DioExceptionType.cancel) rethrow;
return 0;
} catch (_) {
return 0;
}
}
}

View File

@@ -58,4 +58,7 @@ abstract class IOrganizationRepository {
/// Récupère les statistiques des organisations
Future<Map<String, dynamic>> getOrganizationsStats();
/// Retourne le nombre réel de membres actifs d'une organisation.
Future<int> getMembreCount(String organizationId);
}

View File

@@ -3,11 +3,13 @@ library organisation_detail_page;
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:get_it/get_it.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../data/models/organization_model.dart';
import '../../bloc/organizations_bloc.dart';
import '../../bloc/organizations_event.dart';
import '../../bloc/organizations_state.dart';
import '../../domain/repositories/organization_repository.dart';
import 'edit_organization_page.dart';
import '../../../../shared/design_system/tokens/app_colors.dart';
import '../../../../features/authentication/presentation/bloc/auth_bloc.dart';
@@ -23,10 +25,20 @@ class OrganizationDetailPage extends StatefulWidget {
}
class _OrganizationDetailPageState extends State<OrganizationDetailPage> {
int? _memberCount;
@override
void initState() {
super.initState();
context.read<OrganizationsBloc>().add(LoadOrganizationById(widget.organizationId));
_loadMemberCount();
}
Future<void> _loadMemberCount() async {
try {
final count = await GetIt.I<IOrganizationRepository>().getMembreCount(widget.organizationId);
if (mounted) setState(() => _memberCount = count);
} catch (_) {}
}
@override
@@ -214,7 +226,7 @@ class _OrganizationDetailPageState extends State<OrganizationDetailPage> {
Widget _buildStatsCard(OrganizationModel org) {
return _buildCard('Statistiques', Icons.bar_chart, [
Row(children: [
Expanded(child: _buildStatItem(Icons.people, 'Membres', org.nombreMembres.toString(), AppColors.primaryGreen)),
Expanded(child: _buildStatItem(Icons.people, 'Membres', (_memberCount ?? org.nombreMembres).toString(), AppColors.primaryGreen)),
const SizedBox(width: 10),
Expanded(child: _buildStatItem(Icons.admin_panel_settings, 'Admins', org.nombreAdministrateurs.toString(), AppColors.brandGreen)),
const SizedBox(width: 10),