feat: Add ErrorContent widget for displaying error messages in dialogs and bottom sheets refactor: Update GroupBloc and GroupRepository to utilize ErrorService for error logging refactor: Enhance user and trip services to log errors using ErrorService refactor: Clean up debug print statements in GroupContent and related components
265 lines
8.7 KiB
Dart
265 lines
8.7 KiB
Dart
import 'package:cloud_firestore/cloud_firestore.dart';
|
|
import 'package:travel_mate/services/error_service.dart';
|
|
import '../data/models/trip.dart';
|
|
|
|
class TripService {
|
|
final _errorService = ErrorService();
|
|
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
|
|
static const String _tripsCollection = 'trips';
|
|
|
|
// Charger tous les voyages
|
|
Future<List<Trip>> loadTrips() async {
|
|
try {
|
|
final QuerySnapshot querySnapshot = await _firestore
|
|
.collection(_tripsCollection)
|
|
.orderBy('createdAt', descending: true)
|
|
.get();
|
|
|
|
return querySnapshot.docs.map((doc) {
|
|
final data = doc.data() as Map<String, dynamic>;
|
|
return Trip.fromMap({...data, 'id': doc.id});
|
|
}).toList();
|
|
} catch (e) {
|
|
_errorService.logError('Erreur lors du chargement des voyages: $e', StackTrace.current);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
// Ajouter un nouveau voyage
|
|
Future<bool> addTrip(Trip trip) async {
|
|
try {
|
|
final tripData = trip.toMap();
|
|
// Retirer l'ID vide du map
|
|
tripData.remove('id');
|
|
|
|
// Convertir les dates en Timestamp pour Firestore
|
|
tripData['startDate'] = Timestamp.fromDate(trip.startDate);
|
|
tripData['endDate'] = Timestamp.fromDate(trip.endDate);
|
|
tripData['createdAt'] = FieldValue.serverTimestamp();
|
|
tripData['updatedAt'] = FieldValue.serverTimestamp();
|
|
|
|
await _firestore.collection(_tripsCollection).add(tripData);
|
|
return true;
|
|
} catch (e) {
|
|
_errorService.logError('Erreur lors de l\'ajout du voyage: $e', StackTrace.current);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Stream pour écouter les voyages d'un utilisateur en temps réel
|
|
Stream<List<Trip>> getTripsStreamByUser(String userId, String userEmail) {
|
|
return _firestore
|
|
.collection(_tripsCollection)
|
|
.snapshots()
|
|
.map((snapshot) {
|
|
|
|
final List<Trip> trips = [];
|
|
|
|
for (int i = 0; i < snapshot.docs.length; i++) {
|
|
var doc = snapshot.docs[i];
|
|
|
|
try {
|
|
final data = doc.data();
|
|
|
|
// Vérifier si l'utilisateur est impliqué dans ce voyage
|
|
final String createdBy = data['createdBy']?.toString() ?? '';
|
|
final List<dynamic> participants = data['participants'] ?? [];
|
|
|
|
bool userIsInvolved = false;
|
|
String reason = '';
|
|
|
|
// L'utilisateur est le créateur
|
|
if (createdBy == userId) {
|
|
userIsInvolved = true;
|
|
reason = 'Créateur du voyage';
|
|
}
|
|
|
|
// L'utilisateur est dans la liste des participants (par ID uniquement)
|
|
if (participants.contains(userId)) {
|
|
userIsInvolved = true;
|
|
reason = reason.isEmpty ? 'Participant par ID' : '$reason + Participant par ID';
|
|
}
|
|
|
|
if (userIsInvolved) {
|
|
final trip = _convertDocumentToTrip(doc.id, data);
|
|
if (trip != null) {
|
|
trips.add(trip);
|
|
}
|
|
}
|
|
} catch (e, stackTrace) {
|
|
_errorService.logError('Erreur lors du traitement du document ${doc.id}: $e', stackTrace);
|
|
}
|
|
}
|
|
|
|
// Trier par date de création (les plus récents en premier)
|
|
trips.sort((a, b) {
|
|
try {
|
|
return b.createdAt.compareTo(a.createdAt);
|
|
} catch (e) {
|
|
_errorService.logError('Erreur lors du tri: $e', StackTrace.current);
|
|
return 0;
|
|
}
|
|
});
|
|
|
|
return trips;
|
|
}).handleError((error, stackTrace) {
|
|
_errorService.logError('Erreur dans le stream: $error', stackTrace);
|
|
return <Trip>[];
|
|
});
|
|
}
|
|
|
|
// Obtenir les voyages d'un utilisateur (version simplifiée)
|
|
Future<List<Trip>> getTripsByUser(String userId) async {
|
|
try {
|
|
// Récupérer d'abord les voyages créés par l'utilisateur
|
|
final QuerySnapshot createdTrips = await _firestore
|
|
.collection(_tripsCollection)
|
|
.where('createdBy', isEqualTo: userId)
|
|
.get();
|
|
|
|
final List<Trip> trips = [];
|
|
|
|
for (var doc in createdTrips.docs) {
|
|
try {
|
|
final data = doc.data() as Map<String, dynamic>;
|
|
final trip = _convertDocumentToTrip(doc.id, data);
|
|
if (trip != null) {
|
|
trips.add(trip);
|
|
}
|
|
} catch (e) {
|
|
_errorService.logError('Erreur lors de la conversion du voyage créé ${doc.id}: $e', StackTrace.current);
|
|
}
|
|
}
|
|
|
|
// Trier par date de création
|
|
trips.sort((a, b) {
|
|
try {
|
|
return b.createdAt.compareTo(a.createdAt);
|
|
} catch (e) {
|
|
return 0;
|
|
}
|
|
});
|
|
return trips;
|
|
} catch (e) {
|
|
_errorService.logError('Erreur lors de la récupération des voyages: $e', StackTrace.current);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
// Méthode helper pour convertir un document Firestore en Trip
|
|
Trip? _convertDocumentToTrip(String docId, Map<String, dynamic> data) {
|
|
try {
|
|
// Créer une copie des données pour ne pas modifier l'original
|
|
Map<String, dynamic> processedData = Map<String, dynamic>.from(data);
|
|
|
|
// Convertir les Timestamps Firestore en String ISO
|
|
if (processedData['createdAt'] is Timestamp) {
|
|
processedData['createdAt'] = (processedData['createdAt'] as Timestamp).toDate().toIso8601String();
|
|
}
|
|
|
|
if (processedData['updatedAt'] is Timestamp) {
|
|
processedData['updatedAt'] = (processedData['updatedAt'] as Timestamp).toDate().toIso8601String();
|
|
}
|
|
|
|
if (processedData['startDate'] is Timestamp) {
|
|
processedData['startDate'] = (processedData['startDate'] as Timestamp).toDate().toIso8601String();
|
|
}
|
|
|
|
if (processedData['endDate'] is Timestamp) {
|
|
processedData['endDate'] = (processedData['endDate'] as Timestamp).toDate().toIso8601String();
|
|
}
|
|
|
|
// Assurer que tous les champs requis sont présents
|
|
processedData['id'] = docId;
|
|
processedData['participants'] = processedData['participants'] ?? [];
|
|
processedData['budget'] = (processedData['budget'] is num) ? (processedData['budget'] as num).toDouble() : 0.0;
|
|
processedData['description'] = processedData['description'] ?? '';
|
|
processedData['status'] = processedData['status'] ?? 'draft';
|
|
|
|
final trip = Trip.fromMap(processedData);
|
|
return trip;
|
|
|
|
} catch (e, stackTrace) {
|
|
_errorService.logError('Erreur lors de la conversion du document $docId: $e', stackTrace);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Mettre à jour un voyage
|
|
Future<bool> updateTrip(Trip updatedTrip) async {
|
|
try {
|
|
final tripData = updatedTrip.toMap();
|
|
tripData['updatedAt'] = FieldValue.serverTimestamp();
|
|
tripData.remove('id'); // Retirer l'ID des données à mettre à jour
|
|
|
|
await _firestore
|
|
.collection(_tripsCollection)
|
|
.doc(updatedTrip.id)
|
|
.update(tripData);
|
|
return true;
|
|
} catch (e) {
|
|
_errorService.logError('Erreur lors de la mise à jour du voyage: $e', StackTrace.current);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Supprimer un voyage
|
|
Future<bool> deleteTrip(String tripId) async {
|
|
try {
|
|
await _firestore.collection(_tripsCollection).doc(tripId).delete();
|
|
return true;
|
|
} catch (e) {
|
|
_errorService.logError('Erreur lors de la suppression du voyage: $e', StackTrace.current);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Obtenir un voyage par son ID
|
|
Future<Trip?> getTripById(String tripId) async {
|
|
try {
|
|
final DocumentSnapshot doc = await _firestore
|
|
.collection(_tripsCollection)
|
|
.doc(tripId)
|
|
.get();
|
|
|
|
if (doc.exists) {
|
|
final data = doc.data() as Map<String, dynamic>;
|
|
return Trip.fromMap({...data, 'id': doc.id});
|
|
}
|
|
return null;
|
|
} catch (e) {
|
|
_errorService.logError('Erreur lors de la récupération du voyage: $e', StackTrace.current);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Ajouter un participant à un voyage
|
|
Future<bool> addParticipant(String tripId, String userId) async {
|
|
try {
|
|
await _firestore.collection(_tripsCollection).doc(tripId).update({
|
|
'participants': FieldValue.arrayUnion([userId]),
|
|
'updatedAt': FieldValue.serverTimestamp(),
|
|
});
|
|
return true;
|
|
} catch (e) {
|
|
_errorService.logError('Erreur lors de l\'ajout du participant: $e', StackTrace.current);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Retirer un participant d'un voyage
|
|
Future<bool> removeParticipant(String tripId, String userId) async {
|
|
try {
|
|
await _firestore.collection(_tripsCollection).doc(tripId).update({
|
|
'participants': FieldValue.arrayRemove([userId]),
|
|
'updatedAt': FieldValue.serverTimestamp(),
|
|
});
|
|
return true;
|
|
} catch (e) {
|
|
_errorService.logError('Erreur lors du retrait du participant: $e', StackTrace.current);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|