refactor: Clean up code by removing unnecessary whitespace and improving readability
This commit is contained in:
@@ -10,10 +10,7 @@ import '../activities/add_activity_bottom_sheet.dart';
|
|||||||
class ActivitiesPage extends StatefulWidget {
|
class ActivitiesPage extends StatefulWidget {
|
||||||
final Trip trip;
|
final Trip trip;
|
||||||
|
|
||||||
const ActivitiesPage({
|
const ActivitiesPage({super.key, required this.trip});
|
||||||
super.key,
|
|
||||||
required this.trip,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ActivitiesPage> createState() => _ActivitiesPageState();
|
State<ActivitiesPage> createState() => _ActivitiesPageState();
|
||||||
@@ -35,9 +32,12 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
List<Activity> _tripActivities = [];
|
List<Activity> _tripActivities = [];
|
||||||
List<Activity> _approvedActivities = [];
|
List<Activity> _approvedActivities = [];
|
||||||
bool _isLoadingTripActivities = false;
|
bool _isLoadingTripActivities = false;
|
||||||
int _totalGoogleActivitiesRequested = 0; // Compteur pour les recherches progressives
|
int _totalGoogleActivitiesRequested =
|
||||||
bool _autoReloadInProgress = false; // Protection contre les rechargements en boucle
|
0; // Compteur pour les recherches progressives
|
||||||
int _lastAutoReloadTriggerCount = 0; // Éviter de redéclencher pour le même nombre
|
bool _autoReloadInProgress =
|
||||||
|
false; // Protection contre les rechargements en boucle
|
||||||
|
int _lastAutoReloadTriggerCount =
|
||||||
|
0; // Éviter de redéclencher pour le même nombre
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool get wantKeepAlive => true; // Maintient l'état de la page
|
bool get wantKeepAlive => true; // Maintient l'état de la page
|
||||||
@@ -131,14 +131,20 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_tripActivities = state.activities;
|
_tripActivities = state.activities;
|
||||||
_approvedActivities = state.activities.where((a) => a.totalVotes > 0).toList();
|
_approvedActivities = state.activities
|
||||||
|
.where((a) => a.totalVotes > 0)
|
||||||
|
.toList();
|
||||||
_isLoadingTripActivities = false;
|
_isLoadingTripActivities = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
print('🔄 [ActivityLoaded] Activités du voyage mises à jour: ${_tripActivities.length}');
|
print(
|
||||||
|
'🔄 [ActivityLoaded] Activités du voyage mises à jour: ${_tripActivities.length}',
|
||||||
|
);
|
||||||
// Vérifier si on a besoin de charger plus d'activités dans les suggestions
|
// Vérifier si on a besoin de charger plus d'activités dans les suggestions
|
||||||
Future.delayed(const Duration(milliseconds: 500), () {
|
Future.delayed(const Duration(milliseconds: 500), () {
|
||||||
print('🚀 [ActivityLoaded] Déclenchement de la vérification auto-reload');
|
print(
|
||||||
|
'🚀 [ActivityLoaded] Déclenchement de la vérification auto-reload',
|
||||||
|
);
|
||||||
_checkAndLoadMoreActivitiesIfNeeded();
|
_checkAndLoadMoreActivitiesIfNeeded();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -150,7 +156,9 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
// et pas pour les rechargements automatiques
|
// et pas pour les rechargements automatiques
|
||||||
if (state.searchResults.length <= 6 && !_autoReloadInProgress) {
|
if (state.searchResults.length <= 6 && !_autoReloadInProgress) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
print('🎯 [ActivitySearchResults] Première recherche avec peu de résultats, vérification auto-reload');
|
print(
|
||||||
|
'🎯 [ActivitySearchResults] Première recherche avec peu de résultats, vérification auto-reload',
|
||||||
|
);
|
||||||
Future.delayed(const Duration(milliseconds: 500), () {
|
Future.delayed(const Duration(milliseconds: 500), () {
|
||||||
_checkAndLoadMoreActivitiesIfNeeded();
|
_checkAndLoadMoreActivitiesIfNeeded();
|
||||||
});
|
});
|
||||||
@@ -296,9 +304,7 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border.all(
|
border: Border.all(color: theme.colorScheme.outline.withOpacity(0.5)),
|
||||||
color: theme.colorScheme.outline.withOpacity(0.5),
|
|
||||||
),
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
color: theme.colorScheme.surface,
|
color: theme.colorScheme.surface,
|
||||||
),
|
),
|
||||||
@@ -383,7 +389,8 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxHeight: MediaQuery.of(context).size.height * 0.7, // Limite à 70% de l'écran
|
maxHeight:
|
||||||
|
MediaQuery.of(context).size.height * 0.7, // Limite à 70% de l'écran
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@@ -399,19 +406,26 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
Flexible(
|
Flexible(
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: categories.map((category) => ListTile(
|
children: categories
|
||||||
title: Text(category),
|
.map(
|
||||||
onTap: () {
|
(category) => ListTile(
|
||||||
setState(() {
|
title: Text(category),
|
||||||
_selectedCategory = category;
|
onTap: () {
|
||||||
});
|
setState(() {
|
||||||
Navigator.pop(context);
|
_selectedCategory = category;
|
||||||
_applyFilters();
|
});
|
||||||
},
|
Navigator.pop(context);
|
||||||
trailing: _selectedCategory == category
|
_applyFilters();
|
||||||
? Icon(Icons.check, color: theme.colorScheme.primary)
|
},
|
||||||
: null,
|
trailing: _selectedCategory == category
|
||||||
)).toList(),
|
? Icon(
|
||||||
|
Icons.check,
|
||||||
|
color: theme.colorScheme.primary,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -422,7 +436,14 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
|
|
||||||
Widget _buildPriceFilterSheet() {
|
Widget _buildPriceFilterSheet() {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final prices = ['Prix', 'Gratuit', 'Bon marché', 'Modéré', 'Cher', 'Très cher'];
|
final prices = [
|
||||||
|
'Prix',
|
||||||
|
'Gratuit',
|
||||||
|
'Bon marché',
|
||||||
|
'Modéré',
|
||||||
|
'Cher',
|
||||||
|
'Très cher',
|
||||||
|
];
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
@@ -443,19 +464,26 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
Flexible(
|
Flexible(
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: prices.map((price) => ListTile(
|
children: prices
|
||||||
title: Text(price),
|
.map(
|
||||||
onTap: () {
|
(price) => ListTile(
|
||||||
setState(() {
|
title: Text(price),
|
||||||
_selectedPrice = price;
|
onTap: () {
|
||||||
});
|
setState(() {
|
||||||
Navigator.pop(context);
|
_selectedPrice = price;
|
||||||
_applyFilters();
|
});
|
||||||
},
|
Navigator.pop(context);
|
||||||
trailing: _selectedPrice == price
|
_applyFilters();
|
||||||
? Icon(Icons.check, color: theme.colorScheme.primary)
|
},
|
||||||
: null,
|
trailing: _selectedPrice == price
|
||||||
)).toList(),
|
? Icon(
|
||||||
|
Icons.check,
|
||||||
|
color: theme.colorScheme.primary,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -466,7 +494,13 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
|
|
||||||
Widget _buildRatingFilterSheet() {
|
Widget _buildRatingFilterSheet() {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final ratings = ['Note', '4+ étoiles', '3+ étoiles', '2+ étoiles', '1+ étoiles'];
|
final ratings = [
|
||||||
|
'Note',
|
||||||
|
'4+ étoiles',
|
||||||
|
'3+ étoiles',
|
||||||
|
'2+ étoiles',
|
||||||
|
'1+ étoiles',
|
||||||
|
];
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
@@ -487,19 +521,26 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
Flexible(
|
Flexible(
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: ratings.map((rating) => ListTile(
|
children: ratings
|
||||||
title: Text(rating),
|
.map(
|
||||||
onTap: () {
|
(rating) => ListTile(
|
||||||
setState(() {
|
title: Text(rating),
|
||||||
_selectedRating = rating;
|
onTap: () {
|
||||||
});
|
setState(() {
|
||||||
Navigator.pop(context);
|
_selectedRating = rating;
|
||||||
_applyFilters();
|
});
|
||||||
},
|
Navigator.pop(context);
|
||||||
trailing: _selectedRating == rating
|
_applyFilters();
|
||||||
? Icon(Icons.check, color: theme.colorScheme.primary)
|
},
|
||||||
: null,
|
trailing: _selectedRating == rating
|
||||||
)).toList(),
|
? Icon(
|
||||||
|
Icons.check,
|
||||||
|
color: theme.colorScheme.primary,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -509,13 +550,14 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _applyFilters() {
|
void _applyFilters() {
|
||||||
String? category = _selectedCategory == 'Toutes les catégories' ? null : _selectedCategory;
|
String? category = _selectedCategory == 'Toutes les catégories'
|
||||||
|
? null
|
||||||
|
: _selectedCategory;
|
||||||
double? minRating = _getMinRatingFromString(_selectedRating);
|
double? minRating = _getMinRatingFromString(_selectedRating);
|
||||||
|
|
||||||
context.read<ActivityBloc>().add(FilterActivities(
|
context.read<ActivityBloc>().add(
|
||||||
category: category,
|
FilterActivities(category: category, minRating: minRating),
|
||||||
minRating: minRating,
|
);
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double? _getMinRatingFromString(String rating) {
|
double? _getMinRatingFromString(String rating) {
|
||||||
@@ -605,11 +647,16 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
|
|
||||||
// Filtrer les activités déjà présentes dans le voyage
|
// Filtrer les activités déjà présentes dans le voyage
|
||||||
final filteredActivities = googleActivities.where((googleActivity) {
|
final filteredActivities = googleActivities.where((googleActivity) {
|
||||||
return !_tripActivities.any((tripActivity) =>
|
return !_tripActivities.any(
|
||||||
tripActivity.name.toLowerCase().trim() == googleActivity.name.toLowerCase().trim());
|
(tripActivity) =>
|
||||||
|
tripActivity.name.toLowerCase().trim() ==
|
||||||
|
googleActivity.name.toLowerCase().trim(),
|
||||||
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
print('🔍 [Google Search] ${googleActivities.length} résultats trouvés, ${filteredActivities.length} après filtrage');
|
print(
|
||||||
|
'🔍 [Google Search] ${googleActivities.length} résultats trouvés, ${filteredActivities.length} après filtrage',
|
||||||
|
);
|
||||||
|
|
||||||
if (filteredActivities.isEmpty && googleActivities.isNotEmpty) {
|
if (filteredActivities.isEmpty && googleActivities.isNotEmpty) {
|
||||||
return Column(
|
return Column(
|
||||||
@@ -626,7 +673,10 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
icon: const Icon(Icons.add_circle_outline),
|
icon: const Icon(Icons.add_circle_outline),
|
||||||
label: const Text('Rechercher plus d\'activités'),
|
label: const Text('Rechercher plus d\'activités'),
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 24,
|
||||||
|
vertical: 12,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -648,7 +698,10 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
icon: const Icon(Icons.refresh),
|
icon: const Icon(Icons.refresh),
|
||||||
label: const Text('Rechercher à nouveau'),
|
label: const Text('Rechercher à nouveau'),
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 24,
|
||||||
|
vertical: 12,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -668,7 +721,10 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
itemCount: filteredActivities.length,
|
itemCount: filteredActivities.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final activity = filteredActivities[index];
|
final activity = filteredActivities[index];
|
||||||
return _buildActivityCard(activity, isGoogleSuggestion: true);
|
return _buildActivityCard(
|
||||||
|
activity,
|
||||||
|
isGoogleSuggestion: true,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -678,9 +734,7 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
if (state.isLoading)
|
if (state.isLoading)
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: const Center(
|
child: const Center(child: CircularProgressIndicator()),
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
Column(
|
Column(
|
||||||
@@ -694,7 +748,9 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
label: const Text('Rechercher plus d\'activités'),
|
label: const Text('Rechercher plus d\'activités'),
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
backgroundColor: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary,
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
@@ -708,10 +764,18 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
child: OutlinedButton.icon(
|
child: OutlinedButton.icon(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
print('🧪 [DEBUG] Force auto-reload check - État actuel:');
|
print(
|
||||||
print('🧪 [DEBUG] _tripActivities: ${_tripActivities.length}');
|
'🧪 [DEBUG] Force auto-reload check - État actuel:',
|
||||||
print('🧪 [DEBUG] _autoReloadInProgress: $_autoReloadInProgress');
|
);
|
||||||
print('🧪 [DEBUG] _lastAutoReloadTriggerCount: $_lastAutoReloadTriggerCount');
|
print(
|
||||||
|
'🧪 [DEBUG] _tripActivities: ${_tripActivities.length}',
|
||||||
|
);
|
||||||
|
print(
|
||||||
|
'🧪 [DEBUG] _autoReloadInProgress: $_autoReloadInProgress',
|
||||||
|
);
|
||||||
|
print(
|
||||||
|
'🧪 [DEBUG] _lastAutoReloadTriggerCount: $_lastAutoReloadTriggerCount',
|
||||||
|
);
|
||||||
_checkAndLoadMoreActivitiesIfNeeded();
|
_checkAndLoadMoreActivitiesIfNeeded();
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.bug_report, size: 16),
|
icon: const Icon(Icons.bug_report, size: 16),
|
||||||
@@ -742,7 +806,10 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
icon: const Icon(Icons.search),
|
icon: const Icon(Icons.search),
|
||||||
label: const Text('Rechercher des activités (6 résultats)'),
|
label: const Text('Rechercher des activités (6 résultats)'),
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 16),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 32,
|
||||||
|
vertical: 16,
|
||||||
|
),
|
||||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
),
|
),
|
||||||
@@ -768,11 +835,7 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Icon(
|
Icon(icon, size: 64, color: theme.colorScheme.outline),
|
||||||
icon,
|
|
||||||
size: 64,
|
|
||||||
color: theme.colorScheme.outline,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Text(
|
Text(
|
||||||
title,
|
title,
|
||||||
@@ -809,36 +872,43 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: activities.isEmpty
|
child: activities.isEmpty
|
||||||
? ListView(
|
? ListView(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: MediaQuery.of(context).size.height * 0.6,
|
height: MediaQuery.of(context).size.height * 0.6,
|
||||||
child: _buildEmptyState(
|
child: _buildEmptyState(
|
||||||
'Aucune activité',
|
'Aucune activité',
|
||||||
'Tirez vers le bas pour actualiser',
|
'Tirez vers le bas pour actualiser',
|
||||||
Icons.refresh,
|
Icons.refresh,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
)
|
||||||
)
|
: ListView.builder(
|
||||||
: ListView.builder(
|
padding: const EdgeInsets.all(16),
|
||||||
padding: const EdgeInsets.all(16),
|
itemCount: activities.length,
|
||||||
itemCount: activities.length,
|
itemBuilder: (context, index) {
|
||||||
itemBuilder: (context, index) {
|
final activity = activities[index];
|
||||||
final activity = activities[index];
|
return _buildActivityCard(activity);
|
||||||
return _buildActivityCard(activity);
|
},
|
||||||
},
|
),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildActivityCard(Activity activity, {bool isGoogleSuggestion = false}) {
|
Widget _buildActivityCard(
|
||||||
|
Activity activity, {
|
||||||
|
bool isGoogleSuggestion = false,
|
||||||
|
}) {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
|
|
||||||
// Vérifier si l'activité existe déjà dans le voyage (pour les suggestions Google)
|
// Vérifier si l'activité existe déjà dans le voyage (pour les suggestions Google)
|
||||||
final bool activityAlreadyExists = isGoogleSuggestion &&
|
final bool activityAlreadyExists =
|
||||||
_tripActivities.any((tripActivity) =>
|
isGoogleSuggestion &&
|
||||||
tripActivity.name.toLowerCase().trim() == activity.name.toLowerCase().trim());
|
_tripActivities.any(
|
||||||
|
(tripActivity) =>
|
||||||
|
tripActivity.name.toLowerCase().trim() ==
|
||||||
|
activity.name.toLowerCase().trim(),
|
||||||
|
);
|
||||||
|
|
||||||
return Card(
|
return Card(
|
||||||
margin: const EdgeInsets.only(bottom: 12),
|
margin: const EdgeInsets.only(bottom: 12),
|
||||||
@@ -848,8 +918,10 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
// Image de l'activité
|
// Image de l'activité
|
||||||
if (activity.imageUrl != null && activity.imageUrl!.isNotEmpty)
|
if (activity.imageUrl != null && activity.imageUrl!.isNotEmpty)
|
||||||
ClipRRect(
|
ClipRRect(
|
||||||
borderRadius: const BorderRadius.vertical(top: Radius.circular(12)),
|
borderRadius: const BorderRadius.vertical(
|
||||||
child: Container(
|
top: Radius.circular(12),
|
||||||
|
),
|
||||||
|
child: SizedBox(
|
||||||
height: 200,
|
height: 200,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: Image.network(
|
child: Image.network(
|
||||||
@@ -887,7 +959,7 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
child: CircularProgressIndicator(
|
child: CircularProgressIndicator(
|
||||||
value: loadingProgress.expectedTotalBytes != null
|
value: loadingProgress.expectedTotalBytes != null
|
||||||
? loadingProgress.cumulativeBytesLoaded /
|
? loadingProgress.cumulativeBytesLoaded /
|
||||||
loadingProgress.expectedTotalBytes!
|
loadingProgress.expectedTotalBytes!
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -942,7 +1014,10 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
// Note
|
// Note
|
||||||
if (activity.rating != null)
|
if (activity.rating != null)
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 4,
|
||||||
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.amber.withOpacity(0.1),
|
color: Colors.amber.withOpacity(0.1),
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
@@ -950,7 +1025,11 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.star, color: Colors.amber, size: 16),
|
const Icon(
|
||||||
|
Icons.star,
|
||||||
|
color: Colors.amber,
|
||||||
|
size: 16,
|
||||||
|
),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
Text(
|
Text(
|
||||||
activity.rating!.toStringAsFixed(1),
|
activity.rating!.toStringAsFixed(1),
|
||||||
@@ -1004,11 +1083,16 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
if (activityAlreadyExists) ...[
|
if (activityAlreadyExists) ...[
|
||||||
// Activité déjà dans le voyage
|
// Activité déjà dans le voyage
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 12,
|
||||||
|
vertical: 8,
|
||||||
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.orange.withOpacity(0.1),
|
color: Colors.orange.withOpacity(0.1),
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
border: Border.all(color: Colors.orange.withOpacity(0.3)),
|
border: Border.all(
|
||||||
|
color: Colors.orange.withOpacity(0.3),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@@ -1055,7 +1139,10 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
children: [
|
children: [
|
||||||
// Votes positifs (pouces verts)
|
// Votes positifs (pouces verts)
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 4,
|
||||||
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.green.withOpacity(0.1),
|
color: Colors.green.withOpacity(0.1),
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
@@ -1082,7 +1169,10 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
// Votes négatifs (pouces rouges)
|
// Votes négatifs (pouces rouges)
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 4,
|
||||||
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.red.withOpacity(0.1),
|
color: Colors.red.withOpacity(0.1),
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
@@ -1167,14 +1257,14 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
// Pour l'instant, on utilise un ID temporaire
|
// Pour l'instant, on utilise un ID temporaire
|
||||||
final userId = 'current_user_id';
|
final userId = 'current_user_id';
|
||||||
|
|
||||||
context.read<ActivityBloc>().add(VoteForActivity(
|
context.read<ActivityBloc>().add(
|
||||||
activityId: activityId,
|
VoteForActivity(activityId: activityId, userId: userId, vote: vote),
|
||||||
userId: userId,
|
);
|
||||||
vote: vote,
|
|
||||||
));
|
|
||||||
|
|
||||||
// Afficher un feedback à l'utilisateur
|
// Afficher un feedback à l'utilisateur
|
||||||
final message = vote == 1 ? 'Vote positif ajouté !' : 'Vote négatif ajouté !';
|
final message = vote == 1
|
||||||
|
? 'Vote positif ajouté !'
|
||||||
|
: 'Vote négatif ajouté !';
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text(message),
|
content: Text(message),
|
||||||
@@ -1225,24 +1315,35 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
if (currentState is ActivitySearchResults) {
|
if (currentState is ActivitySearchResults) {
|
||||||
final googleActivities = currentState.searchResults;
|
final googleActivities = currentState.searchResults;
|
||||||
|
|
||||||
print('🔍 [Auto-reload] Activités du voyage en mémoire: ${_tripActivities.length}');
|
print(
|
||||||
print('🔍 [Auto-reload] Activités Google total: ${googleActivities.length}');
|
'🔍 [Auto-reload] Activités du voyage en mémoire: ${_tripActivities.length}',
|
||||||
|
);
|
||||||
|
print(
|
||||||
|
'🔍 [Auto-reload] Activités Google total: ${googleActivities.length}',
|
||||||
|
);
|
||||||
|
|
||||||
// Filtrer les activités déjà présentes dans le voyage
|
// Filtrer les activités déjà présentes dans le voyage
|
||||||
final filteredActivities = googleActivities.where((googleActivity) {
|
final filteredActivities = googleActivities.where((googleActivity) {
|
||||||
final isDuplicate = _tripActivities.any((tripActivity) =>
|
final isDuplicate = _tripActivities.any(
|
||||||
tripActivity.name.toLowerCase().trim() == googleActivity.name.toLowerCase().trim());
|
(tripActivity) =>
|
||||||
|
tripActivity.name.toLowerCase().trim() ==
|
||||||
|
googleActivity.name.toLowerCase().trim(),
|
||||||
|
);
|
||||||
if (isDuplicate) {
|
if (isDuplicate) {
|
||||||
print('🔍 [Auto-reload] Activité filtrée: ${googleActivity.name}');
|
print('🔍 [Auto-reload] Activité filtrée: ${googleActivity.name}');
|
||||||
}
|
}
|
||||||
return !isDuplicate;
|
return !isDuplicate;
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
print('🔍 [Auto-reload] ${filteredActivities.length} activités visibles après filtrage sur ${googleActivities.length} total');
|
print(
|
||||||
|
'🔍 [Auto-reload] ${filteredActivities.length} activités visibles après filtrage sur ${googleActivities.length} total',
|
||||||
|
);
|
||||||
|
|
||||||
// Protection: ne pas redéclencher pour le même nombre d'activités Google
|
// Protection: ne pas redéclencher pour le même nombre d'activités Google
|
||||||
if (googleActivities.length == _lastAutoReloadTriggerCount) {
|
if (googleActivities.length == _lastAutoReloadTriggerCount) {
|
||||||
print('🔒 [Auto-reload] Même nombre qu\'avant (${googleActivities.length}), skip pour éviter la boucle');
|
print(
|
||||||
|
'🔒 [Auto-reload] Même nombre qu\'avant (${googleActivities.length}), skip pour éviter la boucle',
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1252,11 +1353,19 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
_lastAutoReloadTriggerCount = googleActivities.length;
|
_lastAutoReloadTriggerCount = googleActivities.length;
|
||||||
|
|
||||||
// Calculer combien d'activités on doit demander
|
// Calculer combien d'activités on doit demander
|
||||||
final activitiesNeeded = 6 - filteredActivities.length; // Manque pour arriver à 6
|
final activitiesNeeded =
|
||||||
final newTotalToRequest = googleActivities.length + activitiesNeeded + 6; // Activités actuelles + ce qui manque + buffer de 6
|
6 - filteredActivities.length; // Manque pour arriver à 6
|
||||||
|
final newTotalToRequest =
|
||||||
|
googleActivities.length +
|
||||||
|
activitiesNeeded +
|
||||||
|
6; // Activités actuelles + ce qui manque + buffer de 6
|
||||||
|
|
||||||
print('🔄 [Auto-reload] DÉCLENCHEMENT: Besoin de ${activitiesNeeded} activités supplémentaires');
|
print(
|
||||||
print('📊 [Auto-reload] Demande totale: ${newTotalToRequest} activités (actuellement: ${googleActivities.length})');
|
'🔄 [Auto-reload] DÉCLENCHEMENT: Besoin de $activitiesNeeded activités supplémentaires',
|
||||||
|
);
|
||||||
|
print(
|
||||||
|
'📊 [Auto-reload] Demande totale: $newTotalToRequest activités (actuellement: ${googleActivities.length})',
|
||||||
|
);
|
||||||
|
|
||||||
// Mettre à jour le compteur et recharger avec le nouveau total
|
// Mettre à jour le compteur et recharger avec le nouveau total
|
||||||
_totalGoogleActivitiesRequested = newTotalToRequest;
|
_totalGoogleActivitiesRequested = newTotalToRequest;
|
||||||
@@ -1268,12 +1377,18 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
print('🔓 [Auto-reload] Verrou libéré');
|
print('🔓 [Auto-reload] Verrou libéré');
|
||||||
});
|
});
|
||||||
} else if (filteredActivities.length >= 4) {
|
} else if (filteredActivities.length >= 4) {
|
||||||
print('✅ [Auto-reload] Suffisamment d\'activités visibles (${filteredActivities.length} >= 4)');
|
print(
|
||||||
|
'✅ [Auto-reload] Suffisamment d\'activités visibles (${filteredActivities.length} >= 4)',
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
print('🚫 [Auto-reload] Trop d\'activités Google déjà chargées (${googleActivities.length} >= 20), arrêt auto-reload');
|
print(
|
||||||
|
'🚫 [Auto-reload] Trop d\'activités Google déjà chargées (${googleActivities.length} >= 20), arrêt auto-reload',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
print('⚠️ [Auto-reload] État pas prêt pour auto-chargement: ${currentState.runtimeType}');
|
print(
|
||||||
|
'⚠️ [Auto-reload] État pas prêt pour auto-chargement: ${currentState.runtimeType}',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1285,24 +1400,32 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
|
|
||||||
// Utiliser les coordonnées pré-géolocalisées du voyage si disponibles
|
// Utiliser les coordonnées pré-géolocalisées du voyage si disponibles
|
||||||
if (widget.trip.hasCoordinates) {
|
if (widget.trip.hasCoordinates) {
|
||||||
print('🌍 [Google Search] Using pre-geocoded coordinates: ${widget.trip.latitude}, ${widget.trip.longitude}');
|
print(
|
||||||
context.read<ActivityBloc>().add(SearchActivitiesWithCoordinates(
|
'🌍 [Google Search] Using pre-geocoded coordinates: ${widget.trip.latitude}, ${widget.trip.longitude}',
|
||||||
tripId: widget.trip.id!,
|
);
|
||||||
latitude: widget.trip.latitude!,
|
context.read<ActivityBloc>().add(
|
||||||
longitude: widget.trip.longitude!,
|
SearchActivitiesWithCoordinates(
|
||||||
category: null, // Rechercher dans toutes les catégories
|
tripId: widget.trip.id!,
|
||||||
maxResults: 6, // Charger 6 résultats à la fois
|
latitude: widget.trip.latitude!,
|
||||||
reset: true, // Nouveau flag pour reset
|
longitude: widget.trip.longitude!,
|
||||||
));
|
category: null, // Rechercher dans toutes les catégories
|
||||||
|
maxResults: 6, // Charger 6 résultats à la fois
|
||||||
|
reset: true, // Nouveau flag pour reset
|
||||||
|
),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
print('⚠️ [Google Search] No coordinates available, falling back to destination geocoding');
|
print(
|
||||||
context.read<ActivityBloc>().add(SearchActivities(
|
'⚠️ [Google Search] No coordinates available, falling back to destination geocoding',
|
||||||
tripId: widget.trip.id!,
|
);
|
||||||
destination: widget.trip.location,
|
context.read<ActivityBloc>().add(
|
||||||
category: null, // Rechercher dans toutes les catégories
|
SearchActivities(
|
||||||
maxResults: 6, // Charger 6 résultats à la fois
|
tripId: widget.trip.id!,
|
||||||
reset: true, // Nouveau flag pour reset
|
destination: widget.trip.location,
|
||||||
));
|
category: null, // Rechercher dans toutes les catégories
|
||||||
|
maxResults: 6, // Charger 6 résultats à la fois
|
||||||
|
reset: true, // Nouveau flag pour reset
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
_googleSearchPerformed = true;
|
_googleSearchPerformed = true;
|
||||||
}
|
}
|
||||||
@@ -1315,24 +1438,32 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
|
|
||||||
// Utiliser les coordonnées pré-géolocalisées du voyage si disponibles
|
// Utiliser les coordonnées pré-géolocalisées du voyage si disponibles
|
||||||
if (widget.trip.hasCoordinates) {
|
if (widget.trip.hasCoordinates) {
|
||||||
print('🌍 [Google Search] Using pre-geocoded coordinates: ${widget.trip.latitude}, ${widget.trip.longitude}');
|
print(
|
||||||
context.read<ActivityBloc>().add(SearchActivitiesWithCoordinates(
|
'🌍 [Google Search] Using pre-geocoded coordinates: ${widget.trip.latitude}, ${widget.trip.longitude}',
|
||||||
tripId: widget.trip.id!,
|
);
|
||||||
latitude: widget.trip.latitude!,
|
context.read<ActivityBloc>().add(
|
||||||
longitude: widget.trip.longitude!,
|
SearchActivitiesWithCoordinates(
|
||||||
category: null,
|
tripId: widget.trip.id!,
|
||||||
maxResults: 6,
|
latitude: widget.trip.latitude!,
|
||||||
reset: true,
|
longitude: widget.trip.longitude!,
|
||||||
));
|
category: null,
|
||||||
|
maxResults: 6,
|
||||||
|
reset: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
print('⚠️ [Google Search] No coordinates available, falling back to destination geocoding');
|
print(
|
||||||
context.read<ActivityBloc>().add(SearchActivities(
|
'⚠️ [Google Search] No coordinates available, falling back to destination geocoding',
|
||||||
tripId: widget.trip.id!,
|
);
|
||||||
destination: widget.trip.location,
|
context.read<ActivityBloc>().add(
|
||||||
category: null,
|
SearchActivities(
|
||||||
maxResults: 6,
|
tripId: widget.trip.id!,
|
||||||
reset: true,
|
destination: widget.trip.location,
|
||||||
));
|
category: null,
|
||||||
|
maxResults: 6,
|
||||||
|
reset: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
_googleSearchPerformed = true;
|
_googleSearchPerformed = true;
|
||||||
}
|
}
|
||||||
@@ -1344,36 +1475,48 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
if (currentState is ActivitySearchResults) {
|
if (currentState is ActivitySearchResults) {
|
||||||
final currentCount = currentState.searchResults.length;
|
final currentCount = currentState.searchResults.length;
|
||||||
final newTotal = currentCount + 6;
|
final newTotal = currentCount + 6;
|
||||||
print('📊 [Google Search] Current results count: $currentCount, requesting total: $newTotal');
|
print(
|
||||||
|
'📊 [Google Search] Current results count: $currentCount, requesting total: $newTotal',
|
||||||
|
);
|
||||||
|
|
||||||
_totalGoogleActivitiesRequested = newTotal;
|
_totalGoogleActivitiesRequested = newTotal;
|
||||||
|
|
||||||
// Utiliser les coordonnées pré-géolocalisées du voyage si disponibles
|
// Utiliser les coordonnées pré-géolocalisées du voyage si disponibles
|
||||||
if (widget.trip.hasCoordinates) {
|
if (widget.trip.hasCoordinates) {
|
||||||
print('🌍 [Google Search] Using pre-geocoded coordinates for more results');
|
print(
|
||||||
context.read<ActivityBloc>().add(SearchActivitiesWithCoordinates(
|
'🌍 [Google Search] Using pre-geocoded coordinates for more results',
|
||||||
tripId: widget.trip.id!,
|
);
|
||||||
latitude: widget.trip.latitude!,
|
context.read<ActivityBloc>().add(
|
||||||
longitude: widget.trip.longitude!,
|
SearchActivitiesWithCoordinates(
|
||||||
category: null,
|
tripId: widget.trip.id!,
|
||||||
maxResults: newTotal, // Demander le total cumulé
|
latitude: widget.trip.latitude!,
|
||||||
reset: true, // Reset pour avoir tous les résultats d'un coup
|
longitude: widget.trip.longitude!,
|
||||||
));
|
category: null,
|
||||||
|
maxResults: newTotal, // Demander le total cumulé
|
||||||
|
reset: true, // Reset pour avoir tous les résultats d'un coup
|
||||||
|
),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
print('⚠️ [Google Search] No coordinates available, falling back to destination geocoding');
|
print(
|
||||||
context.read<ActivityBloc>().add(SearchActivities(
|
'⚠️ [Google Search] No coordinates available, falling back to destination geocoding',
|
||||||
tripId: widget.trip.id!,
|
);
|
||||||
destination: widget.trip.location,
|
context.read<ActivityBloc>().add(
|
||||||
category: null,
|
SearchActivities(
|
||||||
maxResults: newTotal, // Demander le total cumulé
|
tripId: widget.trip.id!,
|
||||||
reset: true, // Reset pour avoir tous les résultats d'un coup
|
destination: widget.trip.location,
|
||||||
));
|
category: null,
|
||||||
|
maxResults: newTotal, // Demander le total cumulé
|
||||||
|
reset: true, // Reset pour avoir tous les résultats d'un coup
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _loadMoreGoogleActivitiesWithTotal(int totalToRequest) {
|
void _loadMoreGoogleActivitiesWithTotal(int totalToRequest) {
|
||||||
print('📈 [Google Search] Loading activities with specific total: $totalToRequest');
|
print(
|
||||||
|
'📈 [Google Search] Loading activities with specific total: $totalToRequest',
|
||||||
|
);
|
||||||
|
|
||||||
// Au lieu de reset, on utilise l'offset et append pour forcer plus de résultats
|
// Au lieu de reset, on utilise l'offset et append pour forcer plus de résultats
|
||||||
final currentState = context.read<ActivityBloc>().state;
|
final currentState = context.read<ActivityBloc>().state;
|
||||||
@@ -1381,31 +1524,41 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
final currentCount = currentState.searchResults.length;
|
final currentCount = currentState.searchResults.length;
|
||||||
final additionalNeeded = totalToRequest - currentCount;
|
final additionalNeeded = totalToRequest - currentCount;
|
||||||
|
|
||||||
print('📊 [Google Search] Current: $currentCount, Total demandé: $totalToRequest, Additional: $additionalNeeded');
|
print(
|
||||||
|
'📊 [Google Search] Current: $currentCount, Total demandé: $totalToRequest, Additional: $additionalNeeded',
|
||||||
|
);
|
||||||
|
|
||||||
if (additionalNeeded > 0) {
|
if (additionalNeeded > 0) {
|
||||||
// Utiliser les coordonnées pré-géolocalisées du voyage si disponibles
|
// Utiliser les coordonnées pré-géolocalisées du voyage si disponibles
|
||||||
if (widget.trip.hasCoordinates) {
|
if (widget.trip.hasCoordinates) {
|
||||||
print('🌍 [Google Search] Using pre-geocoded coordinates for additional results');
|
print(
|
||||||
context.read<ActivityBloc>().add(SearchActivitiesWithCoordinates(
|
'🌍 [Google Search] Using pre-geocoded coordinates for additional results',
|
||||||
tripId: widget.trip.id!,
|
);
|
||||||
latitude: widget.trip.latitude!,
|
context.read<ActivityBloc>().add(
|
||||||
longitude: widget.trip.longitude!,
|
SearchActivitiesWithCoordinates(
|
||||||
category: null,
|
tripId: widget.trip.id!,
|
||||||
maxResults: additionalNeeded,
|
latitude: widget.trip.latitude!,
|
||||||
offset: currentCount,
|
longitude: widget.trip.longitude!,
|
||||||
appendToExisting: true, // Ajouter aux résultats existants
|
category: null,
|
||||||
));
|
maxResults: additionalNeeded,
|
||||||
|
offset: currentCount,
|
||||||
|
appendToExisting: true, // Ajouter aux résultats existants
|
||||||
|
),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
print('⚠️ [Google Search] No coordinates available, falling back to destination geocoding');
|
print(
|
||||||
context.read<ActivityBloc>().add(SearchActivities(
|
'⚠️ [Google Search] No coordinates available, falling back to destination geocoding',
|
||||||
tripId: widget.trip.id!,
|
);
|
||||||
destination: widget.trip.location,
|
context.read<ActivityBloc>().add(
|
||||||
category: null,
|
SearchActivities(
|
||||||
maxResults: additionalNeeded,
|
tripId: widget.trip.id!,
|
||||||
offset: currentCount,
|
destination: widget.trip.location,
|
||||||
appendToExisting: true, // Ajouter aux résultats existants
|
category: null,
|
||||||
));
|
maxResults: additionalNeeded,
|
||||||
|
offset: currentCount,
|
||||||
|
appendToExisting: true, // Ajouter aux résultats existants
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
print('⚠️ [Google Search] Pas besoin de charger plus (déjà suffisant)');
|
print('⚠️ [Google Search] Pas besoin de charger plus (déjà suffisant)');
|
||||||
@@ -1413,24 +1566,32 @@ class _ActivitiesPageState extends State<ActivitiesPage>
|
|||||||
} else {
|
} else {
|
||||||
// Si pas de résultats existants, faire une recherche complète
|
// Si pas de résultats existants, faire une recherche complète
|
||||||
if (widget.trip.hasCoordinates) {
|
if (widget.trip.hasCoordinates) {
|
||||||
print('🌍 [Google Search] Using pre-geocoded coordinates for fresh search');
|
print(
|
||||||
context.read<ActivityBloc>().add(SearchActivitiesWithCoordinates(
|
'🌍 [Google Search] Using pre-geocoded coordinates for fresh search',
|
||||||
tripId: widget.trip.id!,
|
);
|
||||||
latitude: widget.trip.latitude!,
|
context.read<ActivityBloc>().add(
|
||||||
longitude: widget.trip.longitude!,
|
SearchActivitiesWithCoordinates(
|
||||||
category: null,
|
tripId: widget.trip.id!,
|
||||||
maxResults: totalToRequest,
|
latitude: widget.trip.latitude!,
|
||||||
reset: true,
|
longitude: widget.trip.longitude!,
|
||||||
));
|
category: null,
|
||||||
|
maxResults: totalToRequest,
|
||||||
|
reset: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
print('⚠️ [Google Search] No coordinates available, falling back to destination geocoding');
|
print(
|
||||||
context.read<ActivityBloc>().add(SearchActivities(
|
'⚠️ [Google Search] No coordinates available, falling back to destination geocoding',
|
||||||
tripId: widget.trip.id!,
|
);
|
||||||
destination: widget.trip.location,
|
context.read<ActivityBloc>().add(
|
||||||
category: null,
|
SearchActivities(
|
||||||
maxResults: totalToRequest,
|
tripId: widget.trip.id!,
|
||||||
reset: true,
|
destination: widget.trip.location,
|
||||||
));
|
category: null,
|
||||||
|
maxResults: totalToRequest,
|
||||||
|
reset: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,10 +11,7 @@ import '../../services/error_service.dart';
|
|||||||
class AddActivityBottomSheet extends StatefulWidget {
|
class AddActivityBottomSheet extends StatefulWidget {
|
||||||
final Trip trip;
|
final Trip trip;
|
||||||
|
|
||||||
const AddActivityBottomSheet({
|
const AddActivityBottomSheet({super.key, required this.trip});
|
||||||
Key? key,
|
|
||||||
required this.trip,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<AddActivityBottomSheet> createState() => _AddActivityBottomSheetState();
|
State<AddActivityBottomSheet> createState() => _AddActivityBottomSheetState();
|
||||||
@@ -47,12 +44,7 @@ class _AddActivityBottomSheetState extends State<AddActivityBottomSheet> {
|
|||||||
return AnimatedContainer(
|
return AnimatedContainer(
|
||||||
duration: const Duration(milliseconds: 200),
|
duration: const Duration(milliseconds: 200),
|
||||||
height: mediaQuery.size.height * 0.85,
|
height: mediaQuery.size.height * 0.85,
|
||||||
margin: EdgeInsets.only(
|
margin: EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 16),
|
||||||
left: 16,
|
|
||||||
right: 16,
|
|
||||||
top: 16,
|
|
||||||
bottom: 16,
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: theme.cardColor,
|
color: theme.cardColor,
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
@@ -167,7 +159,9 @@ class _AddActivityBottomSheetState extends State<AddActivityBottomSheet> {
|
|||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(context),
|
||||||
style: OutlinedButton.styleFrom(
|
style: OutlinedButton.styleFrom(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
side: BorderSide(color: theme.colorScheme.outline),
|
side: BorderSide(
|
||||||
|
color: theme.colorScheme.outline,
|
||||||
|
),
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
),
|
),
|
||||||
@@ -193,7 +187,9 @@ class _AddActivityBottomSheetState extends State<AddActivityBottomSheet> {
|
|||||||
height: 20,
|
height: 20,
|
||||||
child: CircularProgressIndicator(
|
child: CircularProgressIndicator(
|
||||||
strokeWidth: 2,
|
strokeWidth: 2,
|
||||||
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
|
valueColor: AlwaysStoppedAnimation<Color>(
|
||||||
|
Colors.white,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: const Text('Ajouter'),
|
: const Text('Ajouter'),
|
||||||
@@ -214,9 +210,9 @@ class _AddActivityBottomSheetState extends State<AddActivityBottomSheet> {
|
|||||||
Widget _buildSectionTitle(String title) {
|
Widget _buildSectionTitle(String title) {
|
||||||
return Text(
|
return Text(
|
||||||
title,
|
title,
|
||||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
style: Theme.of(
|
||||||
fontWeight: FontWeight.w600,
|
context,
|
||||||
),
|
).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,16 +237,16 @@ class _AddActivityBottomSheetState extends State<AddActivityBottomSheet> {
|
|||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: isDarkMode
|
color: isDarkMode
|
||||||
? Colors.white.withOpacity(0.2)
|
? Colors.white.withOpacity(0.2)
|
||||||
: Colors.black.withOpacity(0.2),
|
: Colors.black.withOpacity(0.2),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: isDarkMode
|
color: isDarkMode
|
||||||
? Colors.white.withOpacity(0.2)
|
? Colors.white.withOpacity(0.2)
|
||||||
: Colors.black.withOpacity(0.2),
|
: Colors.black.withOpacity(0.2),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
@@ -271,9 +267,7 @@ class _AddActivityBottomSheetState extends State<AddActivityBottomSheet> {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: theme.colorScheme.surface,
|
color: theme.colorScheme.surface,
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
border: Border.all(
|
border: Border.all(color: theme.colorScheme.outline.withOpacity(0.5)),
|
||||||
color: theme.colorScheme.outline.withOpacity(0.5),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@@ -298,12 +292,17 @@ class _AddActivityBottomSheetState extends State<AddActivityBottomSheet> {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 12,
|
||||||
|
vertical: 8,
|
||||||
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: isSelected ? Colors.blue : Colors.transparent,
|
color: isSelected ? Colors.blue : Colors.transparent,
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: isSelected ? Colors.blue : theme.colorScheme.outline,
|
color: isSelected
|
||||||
|
? Colors.blue
|
||||||
|
: theme.colorScheme.outline,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -313,16 +312,16 @@ class _AddActivityBottomSheetState extends State<AddActivityBottomSheet> {
|
|||||||
_getCategoryIcon(category),
|
_getCategoryIcon(category),
|
||||||
size: 16,
|
size: 16,
|
||||||
color: isSelected
|
color: isSelected
|
||||||
? Colors.white
|
? Colors.white
|
||||||
: theme.colorScheme.onSurface,
|
: theme.colorScheme.onSurface,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 6),
|
const SizedBox(width: 6),
|
||||||
Text(
|
Text(
|
||||||
category.displayName,
|
category.displayName,
|
||||||
style: theme.textTheme.bodySmall?.copyWith(
|
style: theme.textTheme.bodySmall?.copyWith(
|
||||||
color: isSelected
|
color: isSelected
|
||||||
? Colors.white
|
? Colors.white
|
||||||
: theme.colorScheme.onSurface,
|
: theme.colorScheme.onSurface,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -362,8 +361,8 @@ class _AddActivityBottomSheetState extends State<AddActivityBottomSheet> {
|
|||||||
description: _descriptionController.text.trim(),
|
description: _descriptionController.text.trim(),
|
||||||
category: _selectedCategory.displayName,
|
category: _selectedCategory.displayName,
|
||||||
address: _addressController.text.trim().isNotEmpty
|
address: _addressController.text.trim().isNotEmpty
|
||||||
? _addressController.text.trim()
|
? _addressController.text.trim()
|
||||||
: null,
|
: null,
|
||||||
votes: {},
|
votes: {},
|
||||||
createdAt: DateTime.now(),
|
createdAt: DateTime.now(),
|
||||||
updatedAt: DateTime.now(),
|
updatedAt: DateTime.now(),
|
||||||
@@ -373,7 +372,6 @@ class _AddActivityBottomSheetState extends State<AddActivityBottomSheet> {
|
|||||||
|
|
||||||
// Fermer le bottom sheet
|
// Fermer le bottom sheet
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
_errorService.showSnackbar(
|
_errorService.showSnackbar(
|
||||||
message: 'Erreur lors de l\'ajout de l\'activité',
|
message: 'Erreur lors de l\'ajout de l\'activité',
|
||||||
|
|||||||
@@ -8,11 +8,7 @@ class TripCard extends StatefulWidget {
|
|||||||
final Trip trip;
|
final Trip trip;
|
||||||
final VoidCallback? onTap;
|
final VoidCallback? onTap;
|
||||||
|
|
||||||
const TripCard({
|
const TripCard({super.key, required this.trip, this.onTap});
|
||||||
super.key,
|
|
||||||
required this.trip,
|
|
||||||
this.onTap,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<TripCard> createState() => _TripCardState();
|
State<TripCard> createState() => _TripCardState();
|
||||||
@@ -45,14 +41,15 @@ class _TripCardState extends State<TripCard> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// D'abord vérifier si une image existe déjà dans le Storage
|
// D'abord vérifier si une image existe déjà dans le Storage
|
||||||
String? imageUrl = await _placeImageService.getExistingImageUrl(widget.trip.location);
|
String? imageUrl = await _placeImageService.getExistingImageUrl(
|
||||||
|
widget.trip.location,
|
||||||
|
);
|
||||||
|
|
||||||
// Si aucune image n'existe, en télécharger une nouvelle
|
// Si aucune image n'existe, en télécharger une nouvelle
|
||||||
if (imageUrl == null) {
|
imageUrl ??= await _placeImageService.getPlaceImageUrl(
|
||||||
imageUrl = await _placeImageService.getPlaceImageUrl(widget.trip.location);
|
widget.trip.location,
|
||||||
}
|
);
|
||||||
|
|
||||||
if (mounted && imageUrl != null) {
|
if (mounted && imageUrl != null) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@@ -118,11 +115,10 @@ class _TripCardState extends State<TripCard> {
|
|||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
placeholder: (context, url) => Container(
|
placeholder: (context, url) => Container(
|
||||||
color: Colors.grey[200],
|
color: Colors.grey[200],
|
||||||
child: const Center(
|
child: const Center(child: CircularProgressIndicator()),
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
errorWidget: (context, url, error) => _buildPlaceholderImage(isDarkMode),
|
errorWidget: (context, url, error) =>
|
||||||
|
_buildPlaceholderImage(isDarkMode),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,9 +136,7 @@ class _TripCardState extends State<TripCard> {
|
|||||||
elevation: 4,
|
elevation: 4,
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
color: cardColor,
|
color: cardColor,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
),
|
|
||||||
child: Material(
|
child: Material(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
@@ -153,7 +147,9 @@ class _TripCardState extends State<TripCard> {
|
|||||||
children: [
|
children: [
|
||||||
// Image du voyage
|
// Image du voyage
|
||||||
ClipRRect(
|
ClipRRect(
|
||||||
borderRadius: const BorderRadius.vertical(top: Radius.circular(12)),
|
borderRadius: const BorderRadius.vertical(
|
||||||
|
top: Radius.circular(12),
|
||||||
|
),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 200,
|
height: 200,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
@@ -214,7 +210,10 @@ class _TripCardState extends State<TripCard> {
|
|||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.blue,
|
backgroundColor: Colors.blue,
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 20,
|
||||||
|
vertical: 8,
|
||||||
|
),
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
),
|
),
|
||||||
@@ -229,8 +228,8 @@ class _TripCardState extends State<TripCard> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ class Activity {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'Activity(id: $id, name: $name, category: $category, votes: ${totalVotes})';
|
return 'Activity(id: $id, name: $name, category: $category, votes: $totalVotes)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import '../lib/services/trip_image_service.dart';
|
import 'package:travel_mate/services/trip_image_service.dart';
|
||||||
|
|
||||||
/// Script utilitaire pour nettoyer les images inutilisées
|
/// Script utilitaire pour nettoyer les images inutilisées
|
||||||
/// À exécuter manuellement si nécessaire
|
/// À exécuter manuellement si nécessaire
|
||||||
void main() async {
|
void main() async {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final tripImageService = TripImageService();
|
final tripImageService = TripImageService();
|
||||||
|
|
||||||
@@ -18,15 +17,11 @@ void main() async {
|
|||||||
|
|
||||||
final stats = await tripImageService.getImageStatistics(userId);
|
final stats = await tripImageService.getImageStatistics(userId);
|
||||||
|
|
||||||
|
|
||||||
if (stats['tripsWithImages'] > 0) {
|
if (stats['tripsWithImages'] > 0) {
|
||||||
await tripImageService.cleanupUnusedImages(userId);
|
await tripImageService.cleanupUnusedImages(userId);
|
||||||
|
|
||||||
final newStats = await tripImageService.getImageStatistics(userId);
|
final newStats = await tripImageService.getImageStatistics(userId);
|
||||||
} else {
|
} else {}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import 'package:firebase_core/firebase_core.dart';
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
import 'package:firebase_storage/firebase_storage.dart';
|
import 'package:firebase_storage/firebase_storage.dart';
|
||||||
import '../lib/firebase_options.dart';
|
import 'package:travel_mate/firebase_options.dart';
|
||||||
|
|
||||||
/// Script de diagnostic pour analyser les images dans Firebase Storage
|
/// Script de diagnostic pour analyser les images dans Firebase Storage
|
||||||
void main() async {
|
void main() async {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Initialiser Firebase
|
// Initialiser Firebase
|
||||||
await Firebase.initializeApp(
|
await Firebase.initializeApp(
|
||||||
@@ -19,30 +18,30 @@ void main() async {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
final Map<String, List<Map<String, dynamic>>> locationGroups = {};
|
final Map<String, List<Map<String, dynamic>>> locationGroups = {};
|
||||||
|
|
||||||
for (int i = 0; i < listResult.items.length; i++) {
|
for (int i = 0; i < listResult.items.length; i++) {
|
||||||
final item = listResult.items[i];
|
final item = listResult.items[i];
|
||||||
final fileName = item.name;
|
final fileName = item.name;
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Récupérer les métadonnées
|
// Récupérer les métadonnées
|
||||||
final metadata = await item.getMetadata();
|
final metadata = await item.getMetadata();
|
||||||
final customMeta = metadata.customMetadata ?? {};
|
final customMeta = metadata.customMetadata ?? {};
|
||||||
|
|
||||||
final location = customMeta['location'] ?? 'Inconnue';
|
final location = customMeta['location'] ?? 'Inconnue';
|
||||||
final normalizedLocation = customMeta['normalizedLocation'] ?? 'Non définie';
|
final normalizedLocation =
|
||||||
|
customMeta['normalizedLocation'] ?? 'Non définie';
|
||||||
final source = customMeta['source'] ?? 'Inconnue';
|
final source = customMeta['source'] ?? 'Inconnue';
|
||||||
final uploadedAt = customMeta['uploadedAt'] ?? 'Inconnue';
|
final uploadedAt = customMeta['uploadedAt'] ?? 'Inconnue';
|
||||||
|
|
||||||
|
|
||||||
// Récupérer l'URL de téléchargement
|
// Récupérer l'URL de téléchargement
|
||||||
final downloadUrl = await item.getDownloadURL();
|
final downloadUrl = await item.getDownloadURL();
|
||||||
|
|
||||||
// Grouper par location normalisée
|
// Grouper par location normalisée
|
||||||
final groupKey = normalizedLocation != 'Non définie' ? normalizedLocation : location.toLowerCase();
|
final groupKey = normalizedLocation != 'Non définie'
|
||||||
|
? normalizedLocation
|
||||||
|
: location.toLowerCase();
|
||||||
if (!locationGroups.containsKey(groupKey)) {
|
if (!locationGroups.containsKey(groupKey)) {
|
||||||
locationGroups[groupKey] = [];
|
locationGroups[groupKey] = [];
|
||||||
}
|
}
|
||||||
@@ -53,9 +52,7 @@ void main() async {
|
|||||||
'uploadedAt': uploadedAt,
|
'uploadedAt': uploadedAt,
|
||||||
'downloadUrl': downloadUrl,
|
'downloadUrl': downloadUrl,
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
||||||
// Essayer de deviner la location depuis le nom du fichier
|
// Essayer de deviner la location depuis le nom du fichier
|
||||||
final parts = fileName.split('_');
|
final parts = fileName.split('_');
|
||||||
if (parts.length >= 2) {
|
if (parts.length >= 2) {
|
||||||
@@ -73,7 +70,6 @@ void main() async {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Analyser les doublons
|
// Analyser les doublons
|
||||||
@@ -89,14 +85,9 @@ void main() async {
|
|||||||
for (int i = 0; i < images.length; i++) {
|
for (int i = 0; i < images.length; i++) {
|
||||||
final image = images[i];
|
final image = images[i];
|
||||||
}
|
}
|
||||||
} else {
|
} else {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (totalDuplicates > 0) {}
|
||||||
if (totalDuplicates > 0) {
|
} catch (e) {}
|
||||||
}
|
|
||||||
|
|
||||||
} catch (e) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ void main() {
|
|||||||
|
|
||||||
// Scénario 1: Premier chargement (aucune image existante)
|
// Scénario 1: Premier chargement (aucune image existante)
|
||||||
print('=== Scénario 1: Premier chargement ===');
|
print('=== Scénario 1: Premier chargement ===');
|
||||||
String? existingImage = null; // Aucune image dans le Storage
|
String? existingImage; // Aucune image dans le Storage
|
||||||
|
|
||||||
if (existingImage == null) {
|
if (existingImage == null) {
|
||||||
print('✓ Aucune image existante trouvée');
|
print('✓ Aucune image existante trouvée');
|
||||||
@@ -30,7 +30,8 @@ void main() {
|
|||||||
|
|
||||||
// Scénario 3: Différente destination
|
// Scénario 3: Différente destination
|
||||||
print('\n=== Scénario 3: Destination différente ===');
|
print('\n=== Scénario 3: Destination différente ===');
|
||||||
String? differentLocationImage = null; // Pas d'image pour cette nouvelle destination
|
String?
|
||||||
|
differentLocationImage; // Pas d'image pour cette nouvelle destination
|
||||||
|
|
||||||
if (differentLocationImage == null) {
|
if (differentLocationImage == null) {
|
||||||
print('✓ Nouvelle destination, aucune image existante');
|
print('✓ Nouvelle destination, aucune image existante');
|
||||||
@@ -52,9 +53,15 @@ void main() {
|
|||||||
final testCases = [
|
final testCases = [
|
||||||
{'input': 'Paris, France', 'expected': 'paris_france'},
|
{'input': 'Paris, France', 'expected': 'paris_france'},
|
||||||
{'input': 'New York City', 'expected': 'new_york_city'},
|
{'input': 'New York City', 'expected': 'new_york_city'},
|
||||||
{'input': 'São Paulo', 'expected': 's_o_paulo'}, // Caractères spéciaux remplacés
|
{
|
||||||
|
'input': 'São Paulo',
|
||||||
|
'expected': 's_o_paulo',
|
||||||
|
}, // Caractères spéciaux remplacés
|
||||||
{'input': 'Londres, Royaume-Uni', 'expected': 'londres_royaume_uni'},
|
{'input': 'Londres, Royaume-Uni', 'expected': 'londres_royaume_uni'},
|
||||||
{'input': 'Tokyo (東京)', 'expected': 'tokyo'}, // Caractères non-latins supprimés
|
{
|
||||||
|
'input': 'Tokyo (東京)',
|
||||||
|
'expected': 'tokyo',
|
||||||
|
}, // Caractères non-latins supprimés
|
||||||
];
|
];
|
||||||
|
|
||||||
for (final testCase in testCases) {
|
for (final testCase in testCases) {
|
||||||
@@ -68,17 +75,17 @@ void main() {
|
|||||||
// Simulation des bénéfices de performance
|
// Simulation des bénéfices de performance
|
||||||
|
|
||||||
final oldSystem = {
|
final oldSystem = {
|
||||||
'apiCalls': 4, // 4 appels à chaque chargement
|
'apiCalls': 4, // 4 appels à chaque chargement
|
||||||
'storageWrites': 4, // 4 écritures dans le Storage
|
'storageWrites': 4, // 4 écritures dans le Storage
|
||||||
'storageReads': 0, // Pas de vérification existante
|
'storageReads': 0, // Pas de vérification existante
|
||||||
'dataUsage': '4.8 MB', // 4 images × 1.2 MB chacune
|
'dataUsage': '4.8 MB', // 4 images × 1.2 MB chacune
|
||||||
};
|
};
|
||||||
|
|
||||||
final newSystem = {
|
final newSystem = {
|
||||||
'apiCalls': 2, // Seulement pour les nouvelles destinations
|
'apiCalls': 2, // Seulement pour les nouvelles destinations
|
||||||
'storageWrites': 2, // Seulement pour les nouvelles images
|
'storageWrites': 2, // Seulement pour les nouvelles images
|
||||||
'storageReads': 2, // Vérifications d'existence
|
'storageReads': 2, // Vérifications d'existence
|
||||||
'dataUsage': '2.4 MB', // Seulement 2 images nécessaires
|
'dataUsage': '2.4 MB', // Seulement 2 images nécessaires
|
||||||
};
|
};
|
||||||
|
|
||||||
print('=== Comparaison de performance ===');
|
print('=== Comparaison de performance ===');
|
||||||
|
|||||||
@@ -30,8 +30,10 @@ void main() {
|
|||||||
final height = photo['height'] as int;
|
final height = photo['height'] as int;
|
||||||
final ratio = width / height;
|
final ratio = width / height;
|
||||||
final resolution = width * height;
|
final resolution = width * height;
|
||||||
print('${photo['photo_reference']}: ${width}x${height} '
|
print(
|
||||||
'(ratio: ${ratio.toStringAsFixed(2)}, résolution: $resolution)');
|
'${photo['photo_reference']}: ${width}x$height '
|
||||||
|
'(ratio: ${ratio.toStringAsFixed(2)}, résolution: $resolution)',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -44,7 +46,10 @@ void main() {
|
|||||||
expect(searchTerms.any((term) => term.contains('Notre-Dame')), true);
|
expect(searchTerms.any((term) => term.contains('Notre-Dame')), true);
|
||||||
|
|
||||||
// Vérifier que les termes génériques sont aussi présents
|
// Vérifier que les termes génériques sont aussi présents
|
||||||
expect(searchTerms.any((term) => term.contains('attractions touristiques')), true);
|
expect(
|
||||||
|
searchTerms.any((term) => term.contains('attractions touristiques')),
|
||||||
|
true,
|
||||||
|
);
|
||||||
expect(searchTerms.any((term) => term.contains('landmarks')), true);
|
expect(searchTerms.any((term) => term.contains('landmarks')), true);
|
||||||
|
|
||||||
print('Termes de recherche pour Paris:');
|
print('Termes de recherche pour Paris:');
|
||||||
@@ -72,7 +77,10 @@ void main() {
|
|||||||
|
|
||||||
// Devrait au moins avoir des termes génériques
|
// Devrait au moins avoir des termes génériques
|
||||||
expect(searchTerms.isNotEmpty, true);
|
expect(searchTerms.isNotEmpty, true);
|
||||||
expect(searchTerms.any((term) => term.contains('attractions touristiques')), true);
|
expect(
|
||||||
|
searchTerms.any((term) => term.contains('attractions touristiques')),
|
||||||
|
true,
|
||||||
|
);
|
||||||
expect(searchTerms.any((term) => term.contains('landmarks')), true);
|
expect(searchTerms.any((term) => term.contains('landmarks')), true);
|
||||||
|
|
||||||
// Le terme original devrait être en dernier
|
// Le terme original devrait être en dernier
|
||||||
|
|||||||
Reference in New Issue
Block a user