search item with geographical search
This commit is contained in:
parent
b796d0206f
commit
3a0f24cc4c
@ -4,13 +4,11 @@ import 'package:flutter_dotenv/flutter_dotenv.dart'; // Import dotenv
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'ItemMenu.dart';
|
import 'ItemMenu.dart';
|
||||||
import 'Camera.dart';
|
import 'SearchDelegate.dart';
|
||||||
import '../classes/events.dart';
|
import '../classes/events.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:intl/date_symbol_data_local.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 'dart:math';
|
||||||
import '../variable/globals.dart' as globals;
|
import '../variable/globals.dart' as globals;
|
||||||
|
|
||||||
@ -230,7 +228,7 @@ class _MyHomePageState extends State<ListItemMenu> {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
showSearch(
|
showSearch(
|
||||||
context: context,
|
context: context,
|
||||||
delegate: SearchDelegateExample(),
|
delegate: SearchDelegateExample(geoQuery: inputGeo.text),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -297,83 +295,3 @@ class _MyHomePageState extends State<ListItemMenu> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SearchDelegateExample extends SearchDelegate {
|
|
||||||
@override
|
|
||||||
List<Widget> 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<List<Events>>(
|
|
||||||
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<List<Events>> searchPosts(String query) async {
|
|
||||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
||||||
var accessToken = prefs.getString("access_token") ?? "";
|
|
||||||
final List<Events> 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
129
covas_mobile/lib/pages/SearchDelegate.dart
Normal file
129
covas_mobile/lib/pages/SearchDelegate.dart
Normal file
@ -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<Widget> 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<List<Events>>(
|
||||||
|
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<List<Events>> searchPosts(String query, String geoQuery) async {
|
||||||
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
|
var accessToken = prefs.getString("access_token") ?? "";
|
||||||
|
final List<Events> 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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user