refactoring

This commit is contained in:
dahoud
2026-03-31 09:14:47 +00:00
parent 9bfffeeebe
commit 5383df6dcb
200 changed files with 11192 additions and 7063 deletions

View File

@@ -0,0 +1,65 @@
import 'package:dio/dio.dart';
import 'package:injectable/injectable.dart';
import 'package:unionflow_mobile_apps/core/network/api_client.dart';
import '../models/type_reference_model.dart';
@injectable
class OrgTypesRemoteDataSource {
final ApiClient _apiClient;
static const _basePath = '/api/references/types-organisation';
const OrgTypesRemoteDataSource(this._apiClient);
Future<List<TypeReferenceModel>> getOrgTypes() async {
final response = await _apiClient.get(_basePath);
if (response.statusCode == 200) {
final dynamic raw = response.data;
final List<dynamic> data = raw is List<dynamic>
? raw
: ((raw as Map<String, dynamic>)['data'] as List<dynamic>? ?? []);
return data
.map((e) => TypeReferenceModel.fromJson(e as Map<String, dynamic>))
.toList();
}
throw DioException(
requestOptions: response.requestOptions,
response: response,
message: 'Erreur lors de la récupération des types: ${response.statusCode}',
);
}
Future<TypeReferenceModel> createOrgType(Map<String, dynamic> body) async {
final response = await _apiClient.post(_basePath, data: body);
if (response.statusCode == 200 || response.statusCode == 201) {
return TypeReferenceModel.fromJson(response.data as Map<String, dynamic>);
}
throw DioException(
requestOptions: response.requestOptions,
response: response,
message: 'Erreur lors de la création du type: ${response.statusCode}',
);
}
Future<TypeReferenceModel> updateOrgType(String id, Map<String, dynamic> body) async {
final response = await _apiClient.put('$_basePath/$id', data: body);
if (response.statusCode == 200) {
return TypeReferenceModel.fromJson(response.data as Map<String, dynamic>);
}
throw DioException(
requestOptions: response.requestOptions,
response: response,
message: 'Erreur lors de la mise à jour du type: ${response.statusCode}',
);
}
Future<void> deleteOrgType(String id) async {
final response = await _apiClient.delete('$_basePath/$id');
if (response.statusCode != 200 && response.statusCode != 204) {
throw DioException(
requestOptions: response.requestOptions,
response: response,
message: 'Erreur lors de la suppression du type: ${response.statusCode}',
);
}
}
}

View File

@@ -7,26 +7,6 @@ import 'package:json_annotation/json_annotation.dart';
part 'organization_model.g.dart';
/// Énumération des types d'organisation
enum TypeOrganization {
@JsonValue('ASSOCIATION')
association,
@JsonValue('COOPERATIVE')
cooperative,
@JsonValue('LIONS_CLUB')
lionsClub,
@JsonValue('ENTREPRISE')
entreprise,
@JsonValue('ONG')
ong,
@JsonValue('FONDATION')
fondation,
@JsonValue('SYNDICAT')
syndicat,
@JsonValue('AUTRE')
autre,
}
/// Énumération des statuts d'organisation
enum StatutOrganization {
@JsonValue('ACTIVE')
@@ -41,51 +21,6 @@ enum StatutOrganization {
enCreation,
}
/// Extension pour les types d'organisation
extension TypeOrganizationExtension on TypeOrganization {
String get displayName {
switch (this) {
case TypeOrganization.association:
return 'Association';
case TypeOrganization.cooperative:
return 'Coopérative';
case TypeOrganization.lionsClub:
return 'Lions Club';
case TypeOrganization.entreprise:
return 'Entreprise';
case TypeOrganization.ong:
return 'ONG';
case TypeOrganization.fondation:
return 'Fondation';
case TypeOrganization.syndicat:
return 'Syndicat';
case TypeOrganization.autre:
return 'Autre';
}
}
String get icon {
switch (this) {
case TypeOrganization.association:
return '🏛️';
case TypeOrganization.cooperative:
return '🤝';
case TypeOrganization.lionsClub:
return '🦁';
case TypeOrganization.entreprise:
return '🏢';
case TypeOrganization.ong:
return '🌍';
case TypeOrganization.fondation:
return '🏛️';
case TypeOrganization.syndicat:
return '⚖️';
case TypeOrganization.autre:
return '📋';
}
}
}
/// Extension pour les statuts d'organisation
extension StatutOrganizationExtension on StatutOrganization {
String get displayName {
@@ -158,9 +93,9 @@ class OrganizationModel extends Equatable {
/// Nom court ou sigle
final String? nomCourt;
/// Type d'organisation
/// Type d'organisation (code dynamique depuis /api/references/types-organisation)
@JsonKey(name: 'typeOrganisation')
final TypeOrganization typeOrganisation;
final String typeOrganisation;
/// Statut de l'organisation
final StatutOrganization statut;
@@ -182,10 +117,22 @@ class OrganizationModel extends Equatable {
/// Téléphone
final String? telephone;
/// Téléphone secondaire
@JsonKey(name: 'telephoneSecondaire')
final String? telephoneSecondaire;
/// Email secondaire
@JsonKey(name: 'emailSecondaire')
final String? emailSecondaire;
/// Site web
@JsonKey(name: 'siteWeb')
final String? siteWeb;
/// Réseaux sociaux (JSON string)
@JsonKey(name: 'reseauxSociaux')
final String? reseauxSociaux;
/// Adresse complète
final String? adresse;
@@ -245,6 +192,17 @@ class OrganizationModel extends Equatable {
/// Partenaires
final String? partenaires;
/// Notes internes
final String? notes;
/// Libellé résolu du type d'organisation (lecture seule, depuis la réponse API)
@JsonKey(name: 'typeOrganisationLibelle')
final String? typeOrganisationLibelle;
/// Libellé résolu du statut (lecture seule, depuis la réponse API)
@JsonKey(name: 'statutLibelle')
final String? statutLibelle;
/// Organisation publique
@JsonKey(name: 'organisationPublique')
final bool organisationPublique;
@@ -268,14 +226,17 @@ class OrganizationModel extends Equatable {
this.id,
required this.nom,
this.nomCourt,
this.typeOrganisation = TypeOrganization.association,
this.typeOrganisation = 'ASSOCIATION',
this.statut = StatutOrganization.active,
this.description,
this.dateFondation,
this.numeroEnregistrement,
this.email,
this.telephone,
this.telephoneSecondaire,
this.emailSecondaire,
this.siteWeb,
this.reseauxSociaux,
this.adresse,
this.ville,
this.codePostal,
@@ -293,6 +254,9 @@ class OrganizationModel extends Equatable {
this.activitesPrincipales,
this.certifications,
this.partenaires,
this.notes,
this.typeOrganisationLibelle,
this.statutLibelle,
this.organisationPublique = true,
this.accepteNouveauxMembres = true,
this.dateCreation,
@@ -312,14 +276,17 @@ class OrganizationModel extends Equatable {
String? id,
String? nom,
String? nomCourt,
TypeOrganization? typeOrganisation,
String? typeOrganisation,
StatutOrganization? statut,
String? description,
DateTime? dateFondation,
String? numeroEnregistrement,
String? email,
String? telephone,
String? telephoneSecondaire,
String? emailSecondaire,
String? siteWeb,
String? reseauxSociaux,
String? adresse,
String? ville,
String? codePostal,
@@ -337,6 +304,9 @@ class OrganizationModel extends Equatable {
String? activitesPrincipales,
String? certifications,
String? partenaires,
String? notes,
String? typeOrganisationLibelle,
String? statutLibelle,
bool? organisationPublique,
bool? accepteNouveauxMembres,
DateTime? dateCreation,
@@ -354,7 +324,10 @@ class OrganizationModel extends Equatable {
numeroEnregistrement: numeroEnregistrement ?? this.numeroEnregistrement,
email: email ?? this.email,
telephone: telephone ?? this.telephone,
telephoneSecondaire: telephoneSecondaire ?? this.telephoneSecondaire,
emailSecondaire: emailSecondaire ?? this.emailSecondaire,
siteWeb: siteWeb ?? this.siteWeb,
reseauxSociaux: reseauxSociaux ?? this.reseauxSociaux,
adresse: adresse ?? this.adresse,
ville: ville ?? this.ville,
codePostal: codePostal ?? this.codePostal,
@@ -372,6 +345,9 @@ class OrganizationModel extends Equatable {
activitesPrincipales: activitesPrincipales ?? this.activitesPrincipales,
certifications: certifications ?? this.certifications,
partenaires: partenaires ?? this.partenaires,
notes: notes ?? this.notes,
typeOrganisationLibelle: typeOrganisationLibelle ?? this.typeOrganisationLibelle,
statutLibelle: statutLibelle ?? this.statutLibelle,
organisationPublique: organisationPublique ?? this.organisationPublique,
accepteNouveauxMembres: accepteNouveauxMembres ?? this.accepteNouveauxMembres,
dateCreation: dateCreation ?? this.dateCreation,
@@ -412,7 +388,10 @@ class OrganizationModel extends Equatable {
numeroEnregistrement,
email,
telephone,
telephoneSecondaire,
emailSecondaire,
siteWeb,
reseauxSociaux,
adresse,
ville,
codePostal,
@@ -430,6 +409,9 @@ class OrganizationModel extends Equatable {
activitesPrincipales,
certifications,
partenaires,
notes,
typeOrganisationLibelle,
statutLibelle,
organisationPublique,
accepteNouveauxMembres,
dateCreation,

View File

@@ -11,9 +11,7 @@ OrganizationModel _$OrganizationModelFromJson(Map<String, dynamic> json) =>
id: json['id'] as String?,
nom: json['nom'] as String,
nomCourt: json['nomCourt'] as String?,
typeOrganisation: $enumDecodeNullable(
_$TypeOrganizationEnumMap, json['typeOrganisation']) ??
TypeOrganization.association,
typeOrganisation: json['typeOrganisation'] as String? ?? 'ASSOCIATION',
statut:
$enumDecodeNullable(_$StatutOrganizationEnumMap, json['statut']) ??
StatutOrganization.active,
@@ -24,7 +22,10 @@ OrganizationModel _$OrganizationModelFromJson(Map<String, dynamic> json) =>
numeroEnregistrement: json['numeroEnregistrement'] as String?,
email: json['email'] as String?,
telephone: json['telephone'] as String?,
telephoneSecondaire: json['telephoneSecondaire'] as String?,
emailSecondaire: json['emailSecondaire'] as String?,
siteWeb: json['siteWeb'] as String?,
reseauxSociaux: json['reseauxSociaux'] as String?,
adresse: json['adresse'] as String?,
ville: json['ville'] as String?,
codePostal: json['codePostal'] as String?,
@@ -44,6 +45,9 @@ OrganizationModel _$OrganizationModelFromJson(Map<String, dynamic> json) =>
activitesPrincipales: json['activitesPrincipales'] as String?,
certifications: json['certifications'] as String?,
partenaires: json['partenaires'] as String?,
notes: json['notes'] as String?,
typeOrganisationLibelle: json['typeOrganisationLibelle'] as String?,
statutLibelle: json['statutLibelle'] as String?,
organisationPublique: json['organisationPublique'] as bool? ?? true,
accepteNouveauxMembres: json['accepteNouveauxMembres'] as bool? ?? true,
dateCreation: json['dateCreation'] == null
@@ -60,14 +64,17 @@ Map<String, dynamic> _$OrganizationModelToJson(OrganizationModel instance) =>
'id': instance.id,
'nom': instance.nom,
'nomCourt': instance.nomCourt,
'typeOrganisation': _$TypeOrganizationEnumMap[instance.typeOrganisation]!,
'typeOrganisation': instance.typeOrganisation,
'statut': _$StatutOrganizationEnumMap[instance.statut]!,
'description': instance.description,
'dateFondation': instance.dateFondation?.toIso8601String(),
'numeroEnregistrement': instance.numeroEnregistrement,
'email': instance.email,
'telephone': instance.telephone,
'telephoneSecondaire': instance.telephoneSecondaire,
'emailSecondaire': instance.emailSecondaire,
'siteWeb': instance.siteWeb,
'reseauxSociaux': instance.reseauxSociaux,
'adresse': instance.adresse,
'ville': instance.ville,
'codePostal': instance.codePostal,
@@ -85,6 +92,9 @@ Map<String, dynamic> _$OrganizationModelToJson(OrganizationModel instance) =>
'activitesPrincipales': instance.activitesPrincipales,
'certifications': instance.certifications,
'partenaires': instance.partenaires,
'notes': instance.notes,
'typeOrganisationLibelle': instance.typeOrganisationLibelle,
'statutLibelle': instance.statutLibelle,
'organisationPublique': instance.organisationPublique,
'accepteNouveauxMembres': instance.accepteNouveauxMembres,
'dateCreation': instance.dateCreation?.toIso8601String(),
@@ -92,17 +102,6 @@ Map<String, dynamic> _$OrganizationModelToJson(OrganizationModel instance) =>
'actif': instance.actif,
};
const _$TypeOrganizationEnumMap = {
TypeOrganization.association: 'ASSOCIATION',
TypeOrganization.cooperative: 'COOPERATIVE',
TypeOrganization.lionsClub: 'LIONS_CLUB',
TypeOrganization.entreprise: 'ENTREPRISE',
TypeOrganization.ong: 'ONG',
TypeOrganization.fondation: 'FONDATION',
TypeOrganization.syndicat: 'SYNDICAT',
TypeOrganization.autre: 'AUTRE',
};
const _$StatutOrganizationEnumMap = {
StatutOrganization.active: 'ACTIVE',
StatutOrganization.inactive: 'INACTIVE',

View File

@@ -0,0 +1,75 @@
import 'package:json_annotation/json_annotation.dart';
import '../../domain/entities/type_reference_entity.dart';
part 'type_reference_model.g.dart';
@JsonSerializable()
class TypeReferenceModel {
final String id;
final String domaine;
final String code;
final String libelle;
final String? description;
final String? icone;
final String? couleur;
final String? severity;
@JsonKey(defaultValue: 0)
final int ordreAffichage;
@JsonKey(defaultValue: false)
final bool estDefaut;
@JsonKey(defaultValue: false)
final bool estSysteme;
@JsonKey(defaultValue: true)
final bool actif;
const TypeReferenceModel({
required this.id,
required this.domaine,
required this.code,
required this.libelle,
this.description,
this.icone,
this.couleur,
this.severity,
this.ordreAffichage = 0,
this.estDefaut = false,
this.estSysteme = false,
this.actif = true,
});
factory TypeReferenceModel.fromJson(Map<String, dynamic> json) =>
_$TypeReferenceModelFromJson(json);
Map<String, dynamic> toJson() => _$TypeReferenceModelToJson(this);
TypeReferenceEntity toEntity() => TypeReferenceEntity(
id: id,
domaine: domaine,
code: code,
libelle: libelle,
description: description,
icone: icone,
couleur: couleur,
severity: severity,
ordreAffichage: ordreAffichage,
estDefaut: estDefaut,
estSysteme: estSysteme,
actif: actif,
);
factory TypeReferenceModel.fromEntity(TypeReferenceEntity entity) =>
TypeReferenceModel(
id: entity.id,
domaine: entity.domaine,
code: entity.code,
libelle: entity.libelle,
description: entity.description,
icone: entity.icone,
couleur: entity.couleur,
severity: entity.severity,
ordreAffichage: entity.ordreAffichage,
estDefaut: entity.estDefaut,
estSysteme: entity.estSysteme,
actif: entity.actif,
);
}

View File

@@ -0,0 +1,39 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'type_reference_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
TypeReferenceModel _$TypeReferenceModelFromJson(Map<String, dynamic> json) =>
TypeReferenceModel(
id: json['id'] as String,
domaine: json['domaine'] as String,
code: json['code'] as String,
libelle: json['libelle'] as String,
description: json['description'] as String?,
icone: json['icone'] as String?,
couleur: json['couleur'] as String?,
severity: json['severity'] as String?,
ordreAffichage: (json['ordreAffichage'] as num?)?.toInt() ?? 0,
estDefaut: json['estDefaut'] as bool? ?? false,
estSysteme: json['estSysteme'] as bool? ?? false,
actif: json['actif'] as bool? ?? true,
);
Map<String, dynamic> _$TypeReferenceModelToJson(TypeReferenceModel instance) =>
<String, dynamic>{
'id': instance.id,
'domaine': instance.domaine,
'code': instance.code,
'libelle': instance.libelle,
'description': instance.description,
'icone': instance.icone,
'couleur': instance.couleur,
'severity': instance.severity,
'ordreAffichage': instance.ordreAffichage,
'estDefaut': instance.estDefaut,
'estSysteme': instance.estSysteme,
'actif': instance.actif,
};

View File

@@ -0,0 +1,81 @@
import 'package:dio/dio.dart';
import 'package:injectable/injectable.dart';
import '../../domain/entities/type_reference_entity.dart';
import '../../domain/repositories/org_types_repository.dart';
import '../datasources/org_types_remote_datasource.dart';
@LazySingleton(as: IOrgTypesRepository)
class OrgTypesRepositoryImpl implements IOrgTypesRepository {
final OrgTypesRemoteDataSource _dataSource;
const OrgTypesRepositoryImpl(this._dataSource);
@override
Future<List<TypeReferenceEntity>> getOrgTypes() async {
try {
final models = await _dataSource.getOrgTypes();
return models.map((m) => m.toEntity()).toList();
} on DioException catch (e) {
throw Exception('Erreur réseau: ${e.message}');
}
}
@override
Future<TypeReferenceEntity> createOrgType({
required String code,
required String libelle,
String? description,
String? couleur,
int ordreAffichage = 0,
}) async {
try {
final model = await _dataSource.createOrgType({
'domaine': 'TYPE_ORGANISATION',
'code': code.toUpperCase().replaceAll(' ', '_'),
'libelle': libelle,
if (description != null) 'description': description,
if (couleur != null) 'couleur': couleur,
'ordreAffichage': ordreAffichage,
'estDefaut': false,
'estSysteme': false,
'actif': true,
});
return model.toEntity();
} on DioException catch (e) {
throw Exception('Erreur réseau: ${e.message}');
}
}
@override
Future<TypeReferenceEntity> updateOrgType({
required String id,
required String code,
required String libelle,
String? description,
String? couleur,
int ordreAffichage = 0,
}) async {
try {
final model = await _dataSource.updateOrgType(id, {
'domaine': 'TYPE_ORGANISATION',
'code': code.toUpperCase().replaceAll(' ', '_'),
'libelle': libelle,
if (description != null) 'description': description,
if (couleur != null) 'couleur': couleur,
'ordreAffichage': ordreAffichage,
});
return model.toEntity();
} on DioException catch (e) {
throw Exception('Erreur réseau: ${e.message}');
}
}
@override
Future<void> deleteOrgType(String id) async {
try {
await _dataSource.deleteOrgType(id);
} on DioException catch (e) {
throw Exception('Erreur réseau: ${e.message}');
}
}
}

View File

@@ -38,8 +38,9 @@ class OrganizationRepositoryImpl implements IOrganizationRepository {
);
if (response.statusCode == 200) {
// Le backend retourne directement une liste [...]
final List<dynamic> data = response.data as List<dynamic>;
// Le backend retourne une réponse paginée {"data":[...],"total":0,...}
final responseData = response.data as Map<String, dynamic>;
final List<dynamic> data = (responseData['data'] as List<dynamic>?) ?? [];
return data
.map((json) => OrganizationModel.fromJson(json as Map<String, dynamic>))
.toList();
@@ -47,6 +48,7 @@ class OrganizationRepositoryImpl implements IOrganizationRepository {
throw Exception('Erreur lors de la récupération des organisations: ${response.statusCode}');
}
} on DioException catch (e) {
if (e.type == DioExceptionType.cancel) rethrow;
throw Exception('Erreur réseau lors de la récupération des organisations: ${e.message}');
} catch (e) {
throw Exception('Erreur inattendue lors de la récupération des organisations: $e');
@@ -59,13 +61,17 @@ class OrganizationRepositoryImpl implements IOrganizationRepository {
const String path = '$_baseUrl/mes';
final response = await _apiClient.get(path);
if (response.statusCode == 200) {
final List<dynamic> data = response.data as List<dynamic>;
final dynamic raw = response.data;
final List<dynamic> data = raw is List<dynamic>
? raw
: ((raw as Map<String, dynamic>)['data'] as List<dynamic>? ?? []);
return data
.map((json) => OrganizationModel.fromJson(json as Map<String, dynamic>))
.toList();
}
throw Exception('Erreur lors de la récupération de mes organisations: ${response.statusCode}');
} on DioException catch (e) {
if (e.type == DioExceptionType.cancel) rethrow;
throw Exception('Erreur réseau lors de la récupération de mes organisations: ${e.message}');
} catch (e) {
throw Exception('Erreur inattendue lors de la récupération de mes organisations: $e');
@@ -85,6 +91,7 @@ class OrganizationRepositoryImpl implements IOrganizationRepository {
throw Exception('Erreur lors de la récupération de l\'organisation: ${response.statusCode}');
}
} on DioException catch (e) {
if (e.type == DioExceptionType.cancel) rethrow;
if (e.response?.statusCode == 404) {
return null;
}
@@ -108,6 +115,7 @@ class OrganizationRepositoryImpl implements IOrganizationRepository {
throw Exception('Erreur lors de la création de l\'organisation: ${response.statusCode}');
}
} on DioException catch (e) {
if (e.type == DioExceptionType.cancel) rethrow;
if (e.response?.statusCode == 400) {
final errorData = e.response?.data;
if (errorData is Map<String, dynamic> && errorData.containsKey('error')) {
@@ -136,6 +144,7 @@ class OrganizationRepositoryImpl implements IOrganizationRepository {
throw Exception('Erreur lors de la mise à jour de l\'organisation: ${response.statusCode}');
}
} on DioException catch (e) {
if (e.type == DioExceptionType.cancel) rethrow;
if (e.response?.statusCode == 404) {
throw Exception('Organisation non trouvée');
} else if (e.response?.statusCode == 400) {
@@ -159,6 +168,7 @@ class OrganizationRepositoryImpl implements IOrganizationRepository {
throw Exception('Erreur lors de la suppression de l\'organisation: ${response.statusCode}');
}
} on DioException catch (e) {
if (e.type == DioExceptionType.cancel) rethrow;
if (e.response?.statusCode == 404) {
throw Exception('Organisation non trouvée');
} else if (e.response?.statusCode == 400) {
@@ -184,6 +194,7 @@ class OrganizationRepositoryImpl implements IOrganizationRepository {
throw Exception('Erreur lors de l\'activation de l\'organisation: ${response.statusCode}');
}
} on DioException catch (e) {
if (e.type == DioExceptionType.cancel) rethrow;
if (e.response?.statusCode == 404) {
throw Exception('Organisation non trouvée');
}
@@ -204,6 +215,7 @@ class OrganizationRepositoryImpl implements IOrganizationRepository {
throw Exception('Erreur lors de la suspension de l\'organisation: ${response.statusCode}');
}
} on DioException catch (e) {
if (e.type == DioExceptionType.cancel) rethrow;
if (e.response?.statusCode == 404) {
throw Exception('Organisation non trouvée');
}
@@ -216,7 +228,7 @@ class OrganizationRepositoryImpl implements IOrganizationRepository {
@override
Future<List<OrganizationModel>> searchOrganizations({
String? nom,
TypeOrganization? type,
String? type,
StatutOrganization? statut,
String? ville,
String? region,
@@ -231,7 +243,7 @@ class OrganizationRepositoryImpl implements IOrganizationRepository {
};
if (nom?.isNotEmpty == true) queryParams['nom'] = nom;
if (type != null) queryParams['type'] = type.name.toUpperCase();
if (type != null) queryParams['type'] = type.toUpperCase();
if (statut != null) queryParams['statut'] = statut.name.toUpperCase();
if (ville?.isNotEmpty == true) queryParams['ville'] = ville;
if (region?.isNotEmpty == true) queryParams['region'] = region;
@@ -243,8 +255,8 @@ class OrganizationRepositoryImpl implements IOrganizationRepository {
);
if (response.statusCode == 200) {
// Le backend retourne directement une liste [...]
final List<dynamic> data = response.data as List<dynamic>;
final responseData = response.data as Map<String, dynamic>;
final List<dynamic> data = (responseData['data'] as List<dynamic>?) ?? [];
return data
.map((json) => OrganizationModel.fromJson(json as Map<String, dynamic>))
.toList();
@@ -252,6 +264,7 @@ class OrganizationRepositoryImpl implements IOrganizationRepository {
throw Exception('Erreur lors de la recherche d\'organisations: ${response.statusCode}');
}
} on DioException catch (e) {
if (e.type == DioExceptionType.cancel) rethrow;
throw Exception('Erreur réseau lors de la recherche d\'organisations: ${e.message}');
} catch (e) {
throw Exception('Erreur inattendue lors de la recherche d\'organisations: $e');
@@ -264,12 +277,16 @@ class OrganizationRepositoryImpl implements IOrganizationRepository {
final response = await _apiClient.get('$_baseUrl/$organizationId/membres');
if (response.statusCode == 200) {
final List<dynamic> data = response.data as List<dynamic>;
final dynamic raw = response.data;
final List<dynamic> data = raw is List<dynamic>
? raw
: ((raw as Map<String, dynamic>)['data'] as List<dynamic>? ?? []);
return data.map((e) => Map<String, dynamic>.from(e as Map)).toList();
} else {
throw Exception('Erreur lors de la récupération des membres: ${response.statusCode}');
}
} on DioException catch (e) {
if (e.type == DioExceptionType.cancel) rethrow;
if (e.response?.statusCode == 404) {
throw Exception('Organisation non trouvée');
}
@@ -296,6 +313,7 @@ class OrganizationRepositoryImpl implements IOrganizationRepository {
throw Exception('Erreur lors de la mise à jour de la configuration: ${response.statusCode}');
}
} on DioException catch (e) {
if (e.type == DioExceptionType.cancel) rethrow;
if (e.response?.statusCode == 404) {
throw Exception('Organisation non trouvée');
} else if (e.response?.statusCode == 400) {
@@ -321,6 +339,7 @@ class OrganizationRepositoryImpl implements IOrganizationRepository {
throw Exception('Erreur lors de la récupération des statistiques: ${response.statusCode}');
}
} on DioException catch (e) {
if (e.type == DioExceptionType.cancel) rethrow;
throw Exception('Erreur réseau lors de la récupération des statistiques: ${e.message}');
} catch (e) {
throw Exception('Erreur inattendue lors de la récupération des statistiques: $e');

View File

@@ -122,7 +122,7 @@ class OrganizationService {
/// Recherche avancée d'organisations
Future<List<OrganizationModel>> searchOrganizations({
String? nom,
TypeOrganization? type,
String? type,
StatutOrganization? statut,
String? ville,
String? region,
@@ -166,7 +166,7 @@ class OrganizationService {
/// Filtre les organisations par type
List<OrganizationModel> filterByType(
List<OrganizationModel> organizations,
TypeOrganization type,
String type,
) {
return organizations.where((org) => org.typeOrganisation == type).toList();
}
@@ -251,7 +251,7 @@ class OrganizationService {
// Statistiques par type
final parType = <String, int>{};
for (final org in organizations) {
final type = org.typeOrganisation.displayName;
final type = org.typeOrganisation;
parType[type] = (parType[type] ?? 0) + 1;
}