feat: Add calendar page, enhance activity search and approval logic, and refactor activity filtering UI.
This commit is contained in:
@@ -17,17 +17,22 @@ class ActivityRepository {
|
||||
Future<String?> addActivity(Activity activity) async {
|
||||
try {
|
||||
print('ActivityRepository: Ajout d\'une activité: ${activity.name}');
|
||||
|
||||
final docRef = await _firestore.collection(_collection).add(activity.toMap());
|
||||
|
||||
|
||||
final docRef = await _firestore
|
||||
.collection(_collection)
|
||||
.add(activity.toMap());
|
||||
|
||||
// Mettre à jour l'activité avec l'ID généré
|
||||
await docRef.update({'id': docRef.id});
|
||||
|
||||
|
||||
print('ActivityRepository: Activité ajoutée avec ID: ${docRef.id}');
|
||||
return docRef.id;
|
||||
} catch (e) {
|
||||
print('ActivityRepository: Erreur lors de l\'ajout: $e');
|
||||
_errorService.logError('activity_repository', 'Erreur ajout activité: $e');
|
||||
_errorService.logError(
|
||||
'activity_repository',
|
||||
'Erreur ajout activité: $e',
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -35,8 +40,10 @@ class ActivityRepository {
|
||||
/// Récupère toutes les activités d'un voyage
|
||||
Future<List<Activity>> getActivitiesByTrip(String tripId) async {
|
||||
try {
|
||||
print('ActivityRepository: Récupération des activités pour le voyage: $tripId');
|
||||
|
||||
print(
|
||||
'ActivityRepository: Récupération des activités pour le voyage: $tripId',
|
||||
);
|
||||
|
||||
// Modifié pour éviter l'erreur d'index composite
|
||||
// On récupère d'abord par tripId, puis on trie en mémoire
|
||||
final querySnapshot = await _firestore
|
||||
@@ -55,24 +62,38 @@ class ActivityRepository {
|
||||
return activities;
|
||||
} catch (e) {
|
||||
print('ActivityRepository: Erreur lors de la récupération: $e');
|
||||
_errorService.logError('activity_repository', 'Erreur récupération activités: $e');
|
||||
_errorService.logError(
|
||||
'activity_repository',
|
||||
'Erreur récupération activités: $e',
|
||||
);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/// Récupère une activité par son ID (alias pour getActivityById pour compatibilité)
|
||||
Future<Activity?> getActivity(String tripId, String activityId) async {
|
||||
return getActivityById(activityId);
|
||||
}
|
||||
|
||||
/// Récupère une activité par son ID
|
||||
Future<Activity?> getActivityById(String activityId) async {
|
||||
try {
|
||||
final doc = await _firestore.collection(_collection).doc(activityId).get();
|
||||
|
||||
final doc = await _firestore
|
||||
.collection(_collection)
|
||||
.doc(activityId)
|
||||
.get();
|
||||
|
||||
if (doc.exists) {
|
||||
return Activity.fromSnapshot(doc);
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
} catch (e) {
|
||||
print('ActivityRepository: Erreur récupération activité: $e');
|
||||
_errorService.logError('activity_repository', 'Erreur récupération activité: $e');
|
||||
_errorService.logError(
|
||||
'activity_repository',
|
||||
'Erreur récupération activité: $e',
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -81,17 +102,20 @@ class ActivityRepository {
|
||||
Future<bool> updateActivity(Activity activity) async {
|
||||
try {
|
||||
print('ActivityRepository: Mise à jour de l\'activité: ${activity.id}');
|
||||
|
||||
|
||||
await _firestore
|
||||
.collection(_collection)
|
||||
.doc(activity.id)
|
||||
.update(activity.copyWith(updatedAt: DateTime.now()).toMap());
|
||||
|
||||
|
||||
print('ActivityRepository: Activité mise à jour avec succès');
|
||||
return true;
|
||||
} catch (e) {
|
||||
print('ActivityRepository: Erreur lors de la mise à jour: $e');
|
||||
_errorService.logError('activity_repository', 'Erreur mise à jour activité: $e');
|
||||
_errorService.logError(
|
||||
'activity_repository',
|
||||
'Erreur mise à jour activité: $e',
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -100,49 +124,62 @@ class ActivityRepository {
|
||||
Future<bool> deleteActivity(String activityId) async {
|
||||
try {
|
||||
print('ActivityRepository: Suppression de l\'activité: $activityId');
|
||||
|
||||
|
||||
await _firestore.collection(_collection).doc(activityId).delete();
|
||||
|
||||
|
||||
print('ActivityRepository: Activité supprimée avec succès');
|
||||
return true;
|
||||
} catch (e) {
|
||||
print('ActivityRepository: Erreur lors de la suppression: $e');
|
||||
_errorService.logError('activity_repository', 'Erreur suppression activité: $e');
|
||||
_errorService.logError(
|
||||
'activity_repository',
|
||||
'Erreur suppression activité: $e',
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Vote pour une activité
|
||||
Future<bool> voteForActivity(String activityId, String userId, int vote) async {
|
||||
Future<bool> voteForActivity(
|
||||
String activityId,
|
||||
String userId,
|
||||
int vote,
|
||||
) async {
|
||||
try {
|
||||
// Validation des paramètres
|
||||
if (activityId.isEmpty) {
|
||||
print('ActivityRepository: ID d\'activité vide');
|
||||
_errorService.logError('activity_repository', 'ID d\'activité vide pour le vote');
|
||||
_errorService.logError(
|
||||
'activity_repository',
|
||||
'ID d\'activité vide pour le vote',
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (userId.isEmpty) {
|
||||
print('ActivityRepository: ID d\'utilisateur vide');
|
||||
_errorService.logError('activity_repository', 'ID d\'utilisateur vide pour le vote');
|
||||
_errorService.logError(
|
||||
'activity_repository',
|
||||
'ID d\'utilisateur vide pour le vote',
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
print('ActivityRepository: Vote pour l\'activité $activityId: $vote');
|
||||
|
||||
|
||||
// vote: 1 pour positif, -1 pour négatif, 0 pour supprimer le vote
|
||||
final activityRef = _firestore.collection(_collection).doc(activityId);
|
||||
|
||||
|
||||
await _firestore.runTransaction((transaction) async {
|
||||
final snapshot = await transaction.get(activityRef);
|
||||
|
||||
|
||||
if (!snapshot.exists) {
|
||||
throw Exception('Activité non trouvée');
|
||||
}
|
||||
|
||||
|
||||
final activity = Activity.fromSnapshot(snapshot);
|
||||
final newVotes = Map<String, int>.from(activity.votes);
|
||||
|
||||
|
||||
if (vote == 0) {
|
||||
// Supprimer le vote
|
||||
newVotes.remove(userId);
|
||||
@@ -150,13 +187,13 @@ class ActivityRepository {
|
||||
// Ajouter ou modifier le vote
|
||||
newVotes[userId] = vote;
|
||||
}
|
||||
|
||||
|
||||
transaction.update(activityRef, {
|
||||
'votes': newVotes,
|
||||
'updatedAt': Timestamp.fromDate(DateTime.now()),
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
print('ActivityRepository: Vote enregistré avec succès');
|
||||
return true;
|
||||
} catch (e) {
|
||||
@@ -174,18 +211,21 @@ class ActivityRepository {
|
||||
.where('tripId', isEqualTo: tripId)
|
||||
.snapshots()
|
||||
.map((snapshot) {
|
||||
final activities = snapshot.docs
|
||||
.map((doc) => Activity.fromSnapshot(doc))
|
||||
.toList();
|
||||
|
||||
// Tri en mémoire par date de mise à jour (plus récent en premier)
|
||||
activities.sort((a, b) => b.updatedAt.compareTo(a.updatedAt));
|
||||
|
||||
return activities;
|
||||
});
|
||||
final activities = snapshot.docs
|
||||
.map((doc) => Activity.fromSnapshot(doc))
|
||||
.toList();
|
||||
|
||||
// Tri en mémoire par date de mise à jour (plus récent en premier)
|
||||
activities.sort((a, b) => b.updatedAt.compareTo(a.updatedAt));
|
||||
|
||||
return activities;
|
||||
});
|
||||
} catch (e) {
|
||||
print('ActivityRepository: Erreur stream activités: $e');
|
||||
_errorService.logError('activity_repository', 'Erreur stream activités: $e');
|
||||
_errorService.logError(
|
||||
'activity_repository',
|
||||
'Erreur stream activités: $e',
|
||||
);
|
||||
return Stream.value([]);
|
||||
}
|
||||
}
|
||||
@@ -193,20 +233,22 @@ class ActivityRepository {
|
||||
/// Ajoute plusieurs activités en lot
|
||||
Future<List<String>> addActivitiesBatch(List<Activity> activities) async {
|
||||
try {
|
||||
print('ActivityRepository: Ajout en lot de ${activities.length} activités');
|
||||
|
||||
print(
|
||||
'ActivityRepository: Ajout en lot de ${activities.length} activités',
|
||||
);
|
||||
|
||||
final batch = _firestore.batch();
|
||||
final addedIds = <String>[];
|
||||
|
||||
|
||||
for (final activity in activities) {
|
||||
final docRef = _firestore.collection(_collection).doc();
|
||||
final activityWithId = activity.copyWith(id: docRef.id);
|
||||
batch.set(docRef, activityWithId.toMap());
|
||||
addedIds.add(docRef.id);
|
||||
}
|
||||
|
||||
|
||||
await batch.commit();
|
||||
|
||||
|
||||
print('ActivityRepository: ${addedIds.length} activités ajoutées en lot');
|
||||
return addedIds;
|
||||
} catch (e) {
|
||||
@@ -217,10 +259,15 @@ class ActivityRepository {
|
||||
}
|
||||
|
||||
/// Recherche des activités par catégorie
|
||||
Future<List<Activity>> getActivitiesByCategory(String tripId, String category) async {
|
||||
Future<List<Activity>> getActivitiesByCategory(
|
||||
String tripId,
|
||||
String category,
|
||||
) async {
|
||||
try {
|
||||
print('ActivityRepository: Recherche par catégorie: $category pour le voyage: $tripId');
|
||||
|
||||
print(
|
||||
'ActivityRepository: Recherche par catégorie: $category pour le voyage: $tripId',
|
||||
);
|
||||
|
||||
// Récupérer toutes les activités du voyage puis filtrer en mémoire
|
||||
final querySnapshot = await _firestore
|
||||
.collection(_collection)
|
||||
@@ -238,28 +285,34 @@ class ActivityRepository {
|
||||
return activities;
|
||||
} catch (e) {
|
||||
print('ActivityRepository: Erreur recherche par catégorie: $e');
|
||||
_errorService.logError('activity_repository', 'Erreur recherche par catégorie: $e');
|
||||
_errorService.logError(
|
||||
'activity_repository',
|
||||
'Erreur recherche par catégorie: $e',
|
||||
);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/// Récupère les activités les mieux notées d'un voyage
|
||||
Future<List<Activity>> getTopRatedActivities(String tripId, {int limit = 10}) async {
|
||||
Future<List<Activity>> getTopRatedActivities(
|
||||
String tripId, {
|
||||
int limit = 10,
|
||||
}) async {
|
||||
try {
|
||||
final activities = await getActivitiesByTrip(tripId);
|
||||
|
||||
|
||||
// Trier par nombre de votes positifs puis par note Google
|
||||
activities.sort((a, b) {
|
||||
final aScore = a.totalVotes;
|
||||
final bScore = b.totalVotes;
|
||||
|
||||
|
||||
if (aScore != bScore) {
|
||||
return bScore.compareTo(aScore);
|
||||
}
|
||||
|
||||
|
||||
return (b.rating ?? 0).compareTo(a.rating ?? 0);
|
||||
});
|
||||
|
||||
|
||||
return activities.take(limit).toList();
|
||||
} catch (e) {
|
||||
print('ActivityRepository: Erreur activités top rated: $e');
|
||||
@@ -281,11 +334,11 @@ class ActivityRepository {
|
||||
if (querySnapshot.docs.isNotEmpty) {
|
||||
return Activity.fromSnapshot(querySnapshot.docs.first);
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
} catch (e) {
|
||||
print('ActivityRepository: Erreur recherche activité existante: $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user