import 'dart:convert'; class Trip { final String? id; final String title; final String description; final String location; final DateTime startDate; final DateTime endDate; final double? budget; final List participants; final String createdBy; // ID de l'utilisateur créateur final DateTime createdAt; final DateTime updatedAt; final String status; // 'draft', 'active', 'completed', 'cancelled' Trip({ this.id, required this.title, required this.description, required this.location, required this.startDate, required this.endDate, this.budget, required this.participants, required this.createdBy, required this.createdAt, required this.updatedAt, this.status = 'draft', }); // Constructeur pour créer un Trip depuis un Map (utile pour Firebase) factory Trip.fromMap(Map map) { return Trip( id: map['id'], title: map['title'] ?? '', description: map['description'] ?? '', location: map['location'] ?? '', startDate: _parseDateTime(map['startDate']), endDate: _parseDateTime(map['endDate']), budget: map['budget']?.toDouble(), participants: List.from(map['participants'] ?? []), createdBy: map['createdBy'] ?? '', createdAt: _parseDateTime(map['createdAt']), updatedAt: _parseDateTime(map['updatedAt']), status: map['status'] ?? 'draft', ); } // Méthode helper pour parser les dates depuis différents formats static DateTime _parseDateTime(dynamic dateValue) { if (dateValue == null) { return DateTime.now(); } if (dateValue is DateTime) { return dateValue; } if (dateValue is String) { try { // Essayer de parser comme ISO 8601 return DateTime.parse(dateValue); } catch (e) { return DateTime.now(); } } if (dateValue is int) { try { // Traiter comme millisecondes return DateTime.fromMillisecondsSinceEpoch(dateValue); } catch (e) { return DateTime.now(); } } return DateTime.now(); } // Constructeur pour créer un Trip depuis JSON factory Trip.fromJson(String jsonStr) { Map map = json.decode(jsonStr); return Trip.fromMap(map); } // Méthode pour convertir un Trip en Map (utile pour Firebase) Map toMap() { return { 'id': id, 'title': title, 'description': description, 'location': location, 'startDate': startDate.millisecondsSinceEpoch, 'endDate': endDate.millisecondsSinceEpoch, 'budget': budget, 'participants': participants, 'createdBy': createdBy, 'createdAt': createdAt.millisecondsSinceEpoch, 'updatedAt': updatedAt.millisecondsSinceEpoch, 'status': status, }; } // Méthode pour convertir un Trip en JSON String toJson() { return json.encode(toMap()); } // Méthode pour créer une copie avec des modifications Trip copyWith({ String? id, String? title, String? description, String? location, DateTime? startDate, DateTime? endDate, double? budget, List? participants, String? createdBy, DateTime? createdAt, DateTime? updatedAt, String? status, }) { return Trip( id: id ?? this.id, title: title ?? this.title, description: description ?? this.description, location: location ?? this.location, startDate: startDate ?? this.startDate, endDate: endDate ?? this.endDate, budget: budget ?? this.budget, participants: participants ?? this.participants, createdBy: createdBy ?? this.createdBy, createdAt: createdAt ?? this.createdAt, updatedAt: updatedAt ?? this.updatedAt, status: status ?? this.status, ); } // Méthode pour obtenir la durée du voyage en jours int get durationInDays { return endDate.difference(startDate).inDays + 1; } // Méthode pour vérifier si le voyage est en cours bool get isActive { final now = DateTime.now(); return status == 'active' && now.isAfter(startDate) && now.isBefore(endDate.add(Duration(days: 1))); } // Méthode pour vérifier si le voyage est à venir bool get isUpcoming { final now = DateTime.now(); return status == 'active' && now.isBefore(startDate); } // Méthode pour vérifier si le voyage est terminé bool get isCompleted { final now = DateTime.now(); return status == 'completed' || (status == 'active' && now.isAfter(endDate)); } // Méthode pour obtenir le budget par participant double? get budgetPerParticipant { if (budget == null || participants.isEmpty) return null; return budget! / (participants.length + 1); // +1 pour le créateur } // Méthode pour obtenir le nombre total de participants (incluant le créateur) int get totalParticipants { return participants.length + 1; // +1 pour le créateur } // Méthode pour formater les dates String get formattedDates { return '${startDate.day}/${startDate.month}/${startDate.year} - ${endDate.day}/${endDate.month}/${endDate.year}'; } // Méthode pour obtenir le statut formaté String get formattedStatus { switch (status) { case 'draft': return 'Brouillon'; case 'active': return 'Actif'; case 'completed': return 'Terminé'; case 'cancelled': return 'Annulé'; default: return 'Inconnu'; } } @override String toString() { return 'Trip(id: $id, title: $title, location: $location, dates: $formattedDates, participants: ${participants.length})'; } @override bool operator ==(Object other) { if (identical(this, other)) return true; return other is Trip && other.id == id; } @override int get hashCode => id.hashCode; }