From 3a0f24cc4c23b1b12feee7a65bc79e00c970bd85 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Tue, 5 Nov 2024 23:29:55 +0100 Subject: [PATCH] search item with geographical search --- covas_mobile/lib/pages/ListItemMenu.dart | 86 +------------- covas_mobile/lib/pages/SearchDelegate.dart | 129 +++++++++++++++++++++ 2 files changed, 131 insertions(+), 84 deletions(-) create mode 100644 covas_mobile/lib/pages/SearchDelegate.dart diff --git a/covas_mobile/lib/pages/ListItemMenu.dart b/covas_mobile/lib/pages/ListItemMenu.dart index 87a974e..145255d 100644 --- a/covas_mobile/lib/pages/ListItemMenu.dart +++ b/covas_mobile/lib/pages/ListItemMenu.dart @@ -4,13 +4,11 @@ import 'package:flutter_dotenv/flutter_dotenv.dart'; // Import dotenv import 'dart:convert'; import 'dart:io'; import 'ItemMenu.dart'; -import 'Camera.dart'; +import 'SearchDelegate.dart'; import '../classes/events.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:intl/intl.dart'; import 'package:intl/date_symbol_data_local.dart'; -import 'package:camera/camera.dart'; -import 'package:mapbox_gl/mapbox_gl.dart'; // Add this import import 'dart:math'; import '../variable/globals.dart' as globals; @@ -230,7 +228,7 @@ class _MyHomePageState extends State { onPressed: () { showSearch( context: context, - delegate: SearchDelegateExample(), + delegate: SearchDelegateExample(geoQuery: inputGeo.text), ); }, ), @@ -297,83 +295,3 @@ class _MyHomePageState extends State { ); } } - -class SearchDelegateExample extends SearchDelegate { - @override - List buildActions(BuildContext context) { - return [ - IconButton( - icon: const Icon(Icons.clear), - onPressed: () { - query = ''; - }, - ), - ]; - } - - @override - Widget buildLeading(BuildContext context) { - return IconButton( - icon: const Icon(Icons.arrow_back), - onPressed: () { - close(context, null); - }, - ); - } - - @override - Widget buildResults(BuildContext context) { - // Perform the search and return the results - return FutureBuilder>( - future: searchPosts(query), - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const Center(child: CircularProgressIndicator()); - } else if (snapshot.hasData) { - final posts = snapshot.data!; - return ListView.builder( - itemCount: posts.length, - itemBuilder: (context, index) { - final post = posts[index]; - return ListTile( - title: Text(post.name!), - subtitle: Text(post.place!), - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (_) => ItemMenu(title: post.id!), - ), - ); - }, - ); - }, - ); - } else { - return const Center(child: Text("No results found")); - } - }, - ); - } - - @override - Widget buildSuggestions(BuildContext context) { - return Container(); // Implement suggestions if needed - } - - Future> searchPosts(String query) async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - var accessToken = prefs.getString("access_token") ?? ""; - final List body = []; - if (accessToken.isNotEmpty) { - var url = Uri.parse("${globals.api}/events/search?item=$query"); - final response = await http.get(url, headers: { - "Content-Type": "application/json", - HttpHeaders.cookieHeader: "access_token=${accessToken}" - }); - final List body = json.decode(utf8.decode(response.bodyBytes)); - return body.map((e) => Events.fromJson(e)).toList(); - } - return body; - } -} diff --git a/covas_mobile/lib/pages/SearchDelegate.dart b/covas_mobile/lib/pages/SearchDelegate.dart new file mode 100644 index 0000000..6c870ea --- /dev/null +++ b/covas_mobile/lib/pages/SearchDelegate.dart @@ -0,0 +1,129 @@ +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; +import 'dart:convert'; +import 'dart:io'; +import 'ItemMenu.dart'; +import '../classes/events.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; // Import dotenv +import 'dart:math'; + +import '../variable/globals.dart' as globals; + +class SearchDelegateExample extends SearchDelegate { + final String geoQuery; + + SearchDelegateExample({ + required this.geoQuery, + }); + + @override + List buildActions(BuildContext context) { + return [ + IconButton( + icon: const Icon(Icons.clear), + onPressed: () { + query = ''; + }, + ), + ]; + } + + @override + Widget buildLeading(BuildContext context) { + return IconButton( + icon: const Icon(Icons.arrow_back), + onPressed: () { + close(context, null); + }, + ); + } + + @override + Widget buildResults(BuildContext context) { + // Perform the search and return the results + return FutureBuilder>( + future: searchPosts(query, geoQuery), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const Center(child: CircularProgressIndicator()); + } else if (snapshot.hasData) { + final posts = snapshot.data!; + return ListView.builder( + itemCount: posts.length, + itemBuilder: (context, index) { + final post = posts[index]; + return ListTile( + title: Text(post.name!), + subtitle: Text(post.place!), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => ItemMenu(title: post.id!), + ), + ); + }, + ); + }, + ); + } else { + return const Center(child: Text("No results found")); + } + }, + ); + } + + @override + Widget buildSuggestions(BuildContext context) { + return Container(); // Implement suggestions if needed + } + + Future> searchPosts(String query, String geoQuery) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + var accessToken = prefs.getString("access_token") ?? ""; + final List body = []; + if (accessToken.isNotEmpty) { + var url = Uri.parse("${globals.api}/events/search?item=$query"); + if (geoQuery.isNotEmpty) { + await dotenv.load( + fileName: ".env"); // Load your .env for the Mapbox access token + final mapboxAccessToken = dotenv.env['MAPBOX_ACCESS_TOKEN'] ?? ''; + final geocodeUrl = Uri.parse( + 'https://api.mapbox.com/geocoding/v5/mapbox.places/$geoQuery.json?access_token=$mapboxAccessToken'); + final geocodeResponse = await http.get(geocodeUrl); + if (geocodeResponse.statusCode == 200) { + final geocodeData = json.decode(geocodeResponse.body); + if (geocodeData['features'].isNotEmpty) { + final coordinates = + geocodeData['features'][0]['geometry']['coordinates']; + final longitude = coordinates[0]; // Longitude + final latitude = coordinates[1]; // Latitude + + // Now use the latitude and longitude to get events within a 50km radius + double radiusInKm = 50; + double latDistance = radiusInKm / 111.0; + double lonDistance = + radiusInKm / (111.0 * cos(latitude * pi / 180)); + + double minLat = latitude - latDistance; + double maxLat = latitude + latDistance; + double minLon = longitude - lonDistance; + double maxLon = longitude + lonDistance; + + // Construct the search URL with the item query and latitude/longitude bounds + url = Uri.parse( + "${globals.api}/events/search?item=$query&min_lat=$minLat&max_lat=$maxLat&min_lon=$minLon&max_lon=$maxLon"); + } + } + } + final response = await http.get(url, headers: { + "Content-Type": "application/json", + HttpHeaders.cookieHeader: "access_token=${accessToken}" + }); + final List body = json.decode(utf8.decode(response.bodyBytes)); + return body.map((e) => Events.fromJson(e)).toList(); + } + return body; + } +}