/// Modèle de données pour les organisations /// Correspond au OrganizationDTO du backend library organization_model; import 'package:equatable/equatable.dart'; import 'package:json_annotation/json_annotation.dart'; part 'organization_model.g.dart'; /// Énumération des statuts d'organisation enum StatutOrganization { @JsonValue('ACTIVE') active, @JsonValue('INACTIVE') inactive, @JsonValue('SUSPENDUE') suspendue, @JsonValue('DISSOUTE') dissoute, @JsonValue('EN_CREATION') enCreation, } /// Extension pour les statuts d'organisation extension StatutOrganizationExtension on StatutOrganization { String get displayName { switch (this) { case StatutOrganization.active: return 'Active'; case StatutOrganization.inactive: return 'Inactive'; case StatutOrganization.suspendue: return 'Suspendue'; case StatutOrganization.dissoute: return 'Dissoute'; case StatutOrganization.enCreation: return 'En création'; } } String get color { switch (this) { case StatutOrganization.active: return '#10B981'; // Vert case StatutOrganization.inactive: return '#6B7280'; // Gris case StatutOrganization.suspendue: return '#F59E0B'; // Orange case StatutOrganization.dissoute: return '#EF4444'; // Rouge case StatutOrganization.enCreation: return '#3B82F6'; // Bleu } } } /// Énumération des types de tri pour les organisations enum OrganizationSortType { name, creationDate, memberCount, type, status, } /// Extension pour les types de tri d'organisation extension OrganizationSortTypeExtension on OrganizationSortType { String get displayName { switch (this) { case OrganizationSortType.name: return 'Nom'; case OrganizationSortType.creationDate: return 'Date de création'; case OrganizationSortType.memberCount: return 'Nombre de membres'; case OrganizationSortType.type: return 'Type'; case OrganizationSortType.status: return 'Statut'; } } } /// Modèle d'organisation mobile @JsonSerializable() class OrganizationModel extends Equatable { /// Identifiant unique final String? id; /// Nom de l'organisation final String nom; /// Nom court ou sigle final String? nomCourt; /// Type d'organisation (code dynamique depuis /api/references/types-organisation) @JsonKey(name: 'typeOrganisation') final String typeOrganisation; /// Statut de l'organisation final StatutOrganization statut; /// Description final String? description; /// Date de fondation @JsonKey(name: 'dateFondation') final DateTime? dateFondation; /// Numéro d'enregistrement officiel @JsonKey(name: 'numeroEnregistrement') final String? numeroEnregistrement; /// Email de contact final String? email; /// 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; /// Ville final String? ville; /// Code postal @JsonKey(name: 'codePostal') final String? codePostal; /// Région final String? region; /// Pays final String? pays; /// Logo URL final String? logo; /// Nombre de membres @JsonKey(name: 'nombreMembres') final int nombreMembres; /// Nombre d'administrateurs @JsonKey(name: 'nombreAdministrateurs') final int nombreAdministrateurs; /// Nombre d'événements (fourni par l'API si disponible) @JsonKey(name: 'nombreEvenements') final int? nombreEvenements; /// Budget annuel @JsonKey(name: 'budgetAnnuel') final double? budgetAnnuel; /// Devise final String devise; /// Cotisation obligatoire @JsonKey(name: 'cotisationObligatoire') final bool cotisationObligatoire; /// Montant cotisation annuelle @JsonKey(name: 'montantCotisationAnnuelle') final double? montantCotisationAnnuelle; /// Objectifs final String? objectifs; /// Activités principales @JsonKey(name: 'activitesPrincipales') final String? activitesPrincipales; /// Certifications final String? certifications; /// 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; /// Accepte nouveaux membres @JsonKey(name: 'accepteNouveauxMembres') final bool accepteNouveauxMembres; /// Date de création @JsonKey(name: 'dateCreation') final DateTime? dateCreation; /// Date de modification @JsonKey(name: 'dateModification') final DateTime? dateModification; /// Actif final bool actif; const OrganizationModel({ this.id, required this.nom, this.nomCourt, 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, this.region, this.pays, this.logo, this.nombreMembres = 0, this.nombreAdministrateurs = 0, this.nombreEvenements, this.budgetAnnuel, this.devise = 'XOF', this.cotisationObligatoire = false, this.montantCotisationAnnuelle, this.objectifs, this.activitesPrincipales, this.certifications, this.partenaires, this.notes, this.typeOrganisationLibelle, this.statutLibelle, this.organisationPublique = true, this.accepteNouveauxMembres = true, this.dateCreation, this.dateModification, this.actif = true, }); /// Factory depuis JSON factory OrganizationModel.fromJson(Map json) => _$OrganizationModelFromJson(json); /// Conversion vers JSON Map toJson() => _$OrganizationModelToJson(this); /// Copie avec modifications OrganizationModel copyWith({ String? id, String? nom, String? nomCourt, 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, String? region, String? pays, String? logo, int? nombreMembres, int? nombreAdministrateurs, int? nombreEvenements, double? budgetAnnuel, String? devise, bool? cotisationObligatoire, double? montantCotisationAnnuelle, String? objectifs, String? activitesPrincipales, String? certifications, String? partenaires, String? notes, String? typeOrganisationLibelle, String? statutLibelle, bool? organisationPublique, bool? accepteNouveauxMembres, DateTime? dateCreation, DateTime? dateModification, bool? actif, }) { return OrganizationModel( id: id ?? this.id, nom: nom ?? this.nom, nomCourt: nomCourt ?? this.nomCourt, typeOrganisation: typeOrganisation ?? this.typeOrganisation, statut: statut ?? this.statut, description: description ?? this.description, dateFondation: dateFondation ?? this.dateFondation, 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, region: region ?? this.region, pays: pays ?? this.pays, logo: logo ?? this.logo, nombreMembres: nombreMembres ?? this.nombreMembres, nombreAdministrateurs: nombreAdministrateurs ?? this.nombreAdministrateurs, nombreEvenements: nombreEvenements ?? this.nombreEvenements, budgetAnnuel: budgetAnnuel ?? this.budgetAnnuel, devise: devise ?? this.devise, cotisationObligatoire: cotisationObligatoire ?? this.cotisationObligatoire, montantCotisationAnnuelle: montantCotisationAnnuelle ?? this.montantCotisationAnnuelle, objectifs: objectifs ?? this.objectifs, 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, dateModification: dateModification ?? this.dateModification, actif: actif ?? this.actif, ); } /// Ancienneté en années int get ancienneteAnnees { if (dateFondation == null) return 0; return DateTime.now().difference(dateFondation!).inDays ~/ 365; } /// Adresse complète formatée String get adresseComplete { final parts = []; if (adresse?.isNotEmpty == true) parts.add(adresse!); if (ville?.isNotEmpty == true) parts.add(ville!); if (codePostal?.isNotEmpty == true) parts.add(codePostal!); if (region?.isNotEmpty == true) parts.add(region!); if (pays?.isNotEmpty == true) parts.add(pays!); return parts.join(', '); } /// Nom d'affichage String get nomAffichage => nomCourt?.isNotEmpty == true ? '$nomCourt ($nom)' : nom; @override List get props => [ id, nom, nomCourt, typeOrganisation, statut, description, dateFondation, numeroEnregistrement, email, telephone, telephoneSecondaire, emailSecondaire, siteWeb, reseauxSociaux, adresse, ville, codePostal, region, pays, logo, nombreMembres, nombreAdministrateurs, nombreEvenements, budgetAnnuel, devise, cotisationObligatoire, montantCotisationAnnuelle, objectifs, activitesPrincipales, certifications, partenaires, notes, typeOrganisationLibelle, statutLibelle, organisationPublique, accepteNouveauxMembres, dateCreation, dateModification, actif, ]; @override String toString() => 'OrganisationModel(id: $id, nom: $nom, type: $typeOrganisation, statut: $statut)'; }