feat: Enhance trip management features and improve UI responsiveness

- Implemented AutomaticKeepAliveClientMixin in HomeContent to maintain state during navigation.
- Modified trip loading logic to trigger after the first frame for better performance.
- Updated trip loading events to use LoadTripsByUserId for consistency.
- Added temporary success messages for trip creation and operations.
- Improved UI elements for better user experience, including updated text styles and spacing.
- Refactored trip model to support Firestore timestamps and improved error handling during parsing.
- Streamlined trip repository methods for better clarity and performance.
- Enhanced trip service methods to ensure correct mapping from Firestore documents.
- Removed unnecessary trip reset logic on logout.
This commit is contained in:
Dayron
2025-10-20 14:31:41 +02:00
parent af93ac54ff
commit d0a76b5043
12 changed files with 863 additions and 756 deletions

View File

@@ -1,4 +1,5 @@
import 'dart:convert';
import 'package:cloud_firestore/cloud_firestore.dart';
class Trip {
final String? id;
@@ -9,10 +10,10 @@ class Trip {
final DateTime endDate;
final double? budget;
final List<String> participants;
final String createdBy; // ID de l'utilisateur créateur
final String createdBy;
final DateTime createdAt;
final DateTime updatedAt;
final String status; // 'draft', 'active', 'completed', 'cancelled'
final String status;
Trip({
this.id,
@@ -29,74 +30,71 @@ class Trip {
this.status = 'draft',
});
// Constructeur pour créer un Trip depuis un Map (utile pour Firebase)
factory Trip.fromMap(Map<String, dynamic> 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<String>.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();
// NOUVELLE MÉTHODE HELPER pour convertir n'importe quel format de date
static DateTime _parseDateTime(dynamic value) {
if (value == null) return DateTime.now();
// Si c'est déjà un Timestamp Firebase
if (value is Timestamp) {
return value.toDate();
}
if (dateValue is DateTime) {
return dateValue;
// Si c'est un int (millisecondes depuis epoch)
if (value is int) {
return DateTime.fromMillisecondsSinceEpoch(value);
}
if (dateValue is String) {
try {
// Essayer de parser comme ISO 8601
return DateTime.parse(dateValue);
} catch (e) {
return DateTime.now();
}
// Si c'est un String (ISO 8601)
if (value is String) {
return DateTime.parse(value);
}
if (dateValue is int) {
try {
// Traiter comme millisecondes
return DateTime.fromMillisecondsSinceEpoch(dateValue);
} catch (e) {
return DateTime.now();
}
// Si c'est déjà un DateTime
if (value is DateTime) {
return value;
}
// Par défaut
return DateTime.now();
}
// Constructeur pour créer un Trip depuis JSON
factory Trip.fromJson(String jsonStr) {
Map<String, dynamic> map = json.decode(jsonStr);
return Trip.fromMap(map);
// Constructeur pour créer un Trip depuis un Map (utile pour Firebase)
factory Trip.fromMap(Map<String, dynamic> map, String id) {
try {
return Trip(
id: id,
title: map['title'] as String? ?? '',
description: map['description'] as String? ?? '',
location: map['location'] as String? ?? '',
startDate: _parseDateTime(map['startDate']),
endDate: _parseDateTime(map['endDate']),
budget: (map['budget'] as num?)?.toDouble(),
createdBy: map['createdBy'] as String? ?? '',
participants: List<String>.from(map['participants'] as List? ?? []),
createdAt: _parseDateTime(map['createdAt']),
updatedAt: _parseDateTime(map['updatedAt']),
status: map['status'] as String? ?? 'draft',
);
} catch (e) {
print('❌ Erreur parsing Trip: $e');
print('Map reçue: $map');
rethrow;
}
}
// Méthode pour convertir un Trip en Map (utile pour Firebase)
// MODIFIÉ : Convertir en Map avec Timestamp pour Firestore
Map<String, dynamic> toMap() {
return {
'id': id,
'title': title,
'description': description,
'location': location,
'startDate': startDate.millisecondsSinceEpoch,
'endDate': endDate.millisecondsSinceEpoch,
'startDate': Timestamp.fromDate(startDate),
'endDate': Timestamp.fromDate(endDate),
'budget': budget,
'participants': participants,
'createdBy': createdBy,
'createdAt': createdAt.millisecondsSinceEpoch,
'updatedAt': updatedAt.millisecondsSinceEpoch,
'createdAt': Timestamp.fromDate(createdAt),
'updatedAt': Timestamp.fromDate(updatedAt),
'status': status,
};
}
@@ -166,12 +164,12 @@ class Trip {
// 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
return budget! / (participants.length + 1);
}
// 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
return participants.length + 1;
}
// Méthode pour formater les dates
@@ -197,7 +195,7 @@ class Trip {
@override
String toString() {
return 'Trip(id: $id, title: $title, location: $location, dates: $formattedDates, participants: ${participants.length})';
return 'Trip(id: $id, title: $title, location: $location, status: $status)';
}
@override
@@ -208,4 +206,4 @@ class Trip {
@override
int get hashCode => id.hashCode;
}
}