/// Modèle complet de données pour un événement /// Aligné avec le backend EvenementDTO library evenement_model; import 'package:equatable/equatable.dart'; import 'package:json_annotation/json_annotation.dart'; part 'evenement_model.g.dart'; /// Énumération des types d'événements enum TypeEvenement { @JsonValue('ASSEMBLEE_GENERALE') assembleeGenerale, @JsonValue('REUNION') reunion, @JsonValue('FORMATION') formation, @JsonValue('CONFERENCE') conference, @JsonValue('ATELIER') atelier, @JsonValue('SEMINAIRE') seminaire, @JsonValue('EVENEMENT_SOCIAL') evenementSocial, @JsonValue('MANIFESTATION') manifestation, @JsonValue('CELEBRATION') celebration, @JsonValue('AUTRE') autre, } /// Énumération des statuts d'événements enum StatutEvenement { @JsonValue('PLANIFIE') planifie, @JsonValue('CONFIRME') confirme, @JsonValue('EN_COURS') enCours, @JsonValue('TERMINE') termine, @JsonValue('ANNULE') annule, @JsonValue('REPORTE') reporte, } /// Énumération des priorités enum PrioriteEvenement { @JsonValue('BASSE') basse, @JsonValue('MOYENNE') moyenne, @JsonValue('HAUTE') haute, } /// Modèle complet d'un événement @JsonSerializable() class EvenementModel extends Equatable { /// Identifiant unique final int? id; /// Titre de l'événement final String titre; /// Description détaillée final String? description; /// Date et heure de début @JsonKey(name: 'dateDebut') final DateTime dateDebut; /// Date et heure de fin @JsonKey(name: 'dateFin') final DateTime dateFin; /// Lieu de l'événement final String? lieu; /// Adresse complète final String? adresse; /// Ville final String? ville; /// Code postal @JsonKey(name: 'codePostal') final String? codePostal; /// Type d'événement final TypeEvenement type; /// Statut de l'événement final StatutEvenement statut; /// Nombre maximum de participants @JsonKey(name: 'maxParticipants') final int? maxParticipants; /// Nombre de participants actuels @JsonKey(name: 'participantsActuels') final int participantsActuels; /// ID de l'organisateur @JsonKey(name: 'organisateurId') final int? organisateurId; /// Nom de l'organisateur (pour affichage) @JsonKey(name: 'organisateurNom') final String? organisateurNom; /// ID de l'organisation @JsonKey(name: 'organisationId') final int? organisationId; /// Nom de l'organisation (pour affichage) @JsonKey(name: 'organisationNom') final String? organisationNom; /// Priorité de l'événement final PrioriteEvenement priorite; /// Événement public @JsonKey(name: 'estPublic') final bool estPublic; /// Inscription requise @JsonKey(name: 'inscriptionRequise') final bool inscriptionRequise; /// Coût de participation final double? cout; /// Devise final String devise; /// Tags/mots-clés final List tags; /// URL de l'image @JsonKey(name: 'imageUrl') final String? imageUrl; /// URL du document @JsonKey(name: 'documentUrl') final String? documentUrl; /// Notes internes final String? notes; /// Date de création @JsonKey(name: 'dateCreation') final DateTime? dateCreation; /// Date de modification @JsonKey(name: 'dateModification') final DateTime? dateModification; /// Actif final bool actif; const EvenementModel({ this.id, required this.titre, this.description, required this.dateDebut, required this.dateFin, this.lieu, this.adresse, this.ville, this.codePostal, this.type = TypeEvenement.autre, this.statut = StatutEvenement.planifie, this.maxParticipants, this.participantsActuels = 0, this.organisateurId, this.organisateurNom, this.organisationId, this.organisationNom, this.priorite = PrioriteEvenement.moyenne, this.estPublic = true, this.inscriptionRequise = false, this.cout, this.devise = 'XOF', this.tags = const [], this.imageUrl, this.documentUrl, this.notes, this.dateCreation, this.dateModification, this.actif = true, }); /// Création depuis JSON factory EvenementModel.fromJson(Map json) => _$EvenementModelFromJson(json); /// Conversion vers JSON Map toJson() => _$EvenementModelToJson(this); /// Copie avec modifications EvenementModel copyWith({ int? id, String? titre, String? description, DateTime? dateDebut, DateTime? dateFin, String? lieu, String? adresse, String? ville, String? codePostal, TypeEvenement? type, StatutEvenement? statut, int? maxParticipants, int? participantsActuels, int? organisateurId, String? organisateurNom, int? organisationId, String? organisationNom, PrioriteEvenement? priorite, bool? estPublic, bool? inscriptionRequise, double? cout, String? devise, List? tags, String? imageUrl, String? documentUrl, String? notes, DateTime? dateCreation, DateTime? dateModification, bool? actif, }) { return EvenementModel( id: id ?? this.id, titre: titre ?? this.titre, description: description ?? this.description, dateDebut: dateDebut ?? this.dateDebut, dateFin: dateFin ?? this.dateFin, lieu: lieu ?? this.lieu, adresse: adresse ?? this.adresse, ville: ville ?? this.ville, codePostal: codePostal ?? this.codePostal, type: type ?? this.type, statut: statut ?? this.statut, maxParticipants: maxParticipants ?? this.maxParticipants, participantsActuels: participantsActuels ?? this.participantsActuels, organisateurId: organisateurId ?? this.organisateurId, organisateurNom: organisateurNom ?? this.organisateurNom, organisationId: organisationId ?? this.organisationId, organisationNom: organisationNom ?? this.organisationNom, priorite: priorite ?? this.priorite, estPublic: estPublic ?? this.estPublic, inscriptionRequise: inscriptionRequise ?? this.inscriptionRequise, cout: cout ?? this.cout, devise: devise ?? this.devise, tags: tags ?? this.tags, imageUrl: imageUrl ?? this.imageUrl, documentUrl: documentUrl ?? this.documentUrl, notes: notes ?? this.notes, dateCreation: dateCreation ?? this.dateCreation, dateModification: dateModification ?? this.dateModification, actif: actif ?? this.actif, ); } /// Durée de l'événement en heures double get dureeHeures { return dateFin.difference(dateDebut).inMinutes / 60.0; } /// Nombre de jours avant l'événement int get joursAvantEvenement { return dateDebut.difference(DateTime.now()).inDays; } /// Est dans le futur bool get estAVenir => dateDebut.isAfter(DateTime.now()); /// Est en cours bool get estEnCours { final now = DateTime.now(); return now.isAfter(dateDebut) && now.isBefore(dateFin); } /// Est passé bool get estPasse => dateFin.isBefore(DateTime.now()); /// Places disponibles int? get placesDisponibles { if (maxParticipants == null) return null; return maxParticipants! - participantsActuels; } /// Est complet bool get estComplet { if (maxParticipants == null) return false; return participantsActuels >= maxParticipants!; } /// Peut s'inscrire bool get peutSinscrire { return estAVenir && !estComplet && statut == StatutEvenement.confirme && inscriptionRequise; } @override List get props => [ id, titre, description, dateDebut, dateFin, lieu, adresse, ville, codePostal, type, statut, maxParticipants, participantsActuels, organisateurId, organisateurNom, organisationId, organisationNom, priorite, estPublic, inscriptionRequise, cout, devise, tags, imageUrl, documentUrl, notes, dateCreation, dateModification, actif, ]; @override String toString() => 'EvenementModel(id: $id, titre: $titre, dateDebut: $dateDebut, statut: $statut)'; }