diff --git a/covas_mobile/lib/pages/ListItemMenu.dart b/covas_mobile/lib/pages/ListItemMenu.dart index 0e17203..1391715 100644 --- a/covas_mobile/lib/pages/ListItemMenu.dart +++ b/covas_mobile/lib/pages/ListItemMenu.dart @@ -42,8 +42,10 @@ class _MyHomePageState extends State { Future> postsFuture = getPosts(); List filteredPosts = []; String geographicalZone = ''; + String itemName = ''; String query = ''; List> suggestions = []; + List> suggestionsItem = []; TextEditingController inputGeo = TextEditingController(); TextEditingController startDatepicker = TextEditingController(); TextEditingController endDatepicker = TextEditingController(); @@ -51,6 +53,7 @@ class _MyHomePageState extends State { bool showDateFields = false; // State to toggle date fields bool showArrow = true; + bool showInputSearch = true; // Fetching events from API static Future> getPosts() async { PermissionStatus status = await Permission.location.status; @@ -260,6 +263,7 @@ class _MyHomePageState extends State { .toList(); if (suggestions.isNotEmpty) { showArrow = false; + showInputSearch = false; } }); } else { @@ -267,64 +271,94 @@ class _MyHomePageState extends State { } } + Future getUrlForEvents() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + double latitude = prefs.getDouble("city_lat") ?? 0.0; + double longitude = prefs.getDouble("city_long") ?? 0.0; + String stringParameter = ""; + String endpoint = "events"; + if ((latitude != 0.0) && (longitude != 0.0)) { + // Calculate the boundaries + 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; + endpoint = "events/search"; + + stringParameter = "min_lat=$minLat&max_lat=$maxLat" + "&min_lon=$minLon&max_lon=$maxLon"; + } + DateTime currentDate = DateTime.now(); + String dateParameter = "current_datetime=${currentDate.toString()}"; + if (startDatepicker.text.isNotEmpty) { + var date = DateTime.parse(formatDate(startDatepicker.text)); + dateParameter = "date_event=" + date.toString(); + endpoint = "events/search"; + } + if (endDatepicker.text.isNotEmpty) { + var date = DateTime.parse(formatDate(endDatepicker.text)); + dateParameter = "date_event=" + date.toString(); + endpoint = "events/search"; + } + if ((startDatepicker.text.isNotEmpty) && (endDatepicker.text.isNotEmpty)) { + var startDate = DateTime.parse(formatDate(startDatepicker.text)); + var endDate = DateTime.parse(formatDate(endDatepicker.text)); + dateParameter = "&start_date=" + + startDate.toString() + + "&end_date=" + + endDate.toString(); + endpoint = "events/search"; + } + + if (inputItem.text.isNotEmpty) { + stringParameter = stringParameter + "&item=${inputItem.text}"; + endpoint = "events/search"; + } + if (stringParameter.isNotEmpty) { + stringParameter = "$stringParameter&$dateParameter"; + } else { + stringParameter = dateParameter; + } + return Uri.parse("${globals.api}/${endpoint}?${stringParameter}"); + } + + Future searchSuggestionsByItem(String input) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + var accessToken = prefs.getString("access_token") ?? ""; + + if (accessToken.isNotEmpty) { + var url = await getUrlForEvents(); + final response = await http.get(url, headers: { + "Content-Type": "application/json", + HttpHeaders.cookieHeader: "access_token=$accessToken" + }); + + if (response.statusCode == 200) { + final data = json.decode(utf8.decode(response.bodyBytes)); + setState(() { + suggestionsItem = (data as List) + .map((feature) => {'name': feature['name']}) + .toList(); + if (suggestionsItem.isNotEmpty) { + showDateFields = false; + showArrow = false; + } + }); + print("status code : ${response.statusCode}"); + } + } + } + Future fetchPostsByLocation() async { SharedPreferences prefs = await SharedPreferences.getInstance(); var accessToken = prefs.getString("access_token") ?? ""; if (accessToken.isNotEmpty) { - double latitude = prefs.getDouble("city_lat") ?? 0.0; - double longitude = prefs.getDouble("city_long") ?? 0.0; - String stringParameter = ""; - String endpoint = "events"; - if ((latitude != 0.0) && (longitude != 0.0)) { - // Calculate the boundaries - 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; - endpoint = "events/search"; - - stringParameter = "min_lat=$minLat&max_lat=$maxLat" - "&min_lon=$minLon&max_lon=$maxLon"; - } - DateTime currentDate = DateTime.now(); - String dateParameter = "current_datetime=${currentDate.toString()}"; - if (startDatepicker.text.isNotEmpty) { - var date = DateTime.parse(formatDate(startDatepicker.text)); - dateParameter = "date_event=" + date.toString(); - endpoint = "events/search"; - } - if (endDatepicker.text.isNotEmpty) { - var date = DateTime.parse(formatDate(endDatepicker.text)); - dateParameter = "date_event=" + date.toString(); - endpoint = "events/search"; - } - if ((startDatepicker.text.isNotEmpty) && - (endDatepicker.text.isNotEmpty)) { - var startDate = DateTime.parse(formatDate(startDatepicker.text)); - var endDate = DateTime.parse(formatDate(endDatepicker.text)); - dateParameter = "&start_date=" + - startDate.toString() + - "&end_date=" + - endDate.toString(); - endpoint = "events/search"; - } - - if (inputItem.text.isNotEmpty) { - stringParameter = stringParameter + "&item=${inputItem.text}"; - endpoint = "events/search"; - } - if (stringParameter.isNotEmpty) { - stringParameter = "$stringParameter&$dateParameter"; - } else { - stringParameter = dateParameter; - } - print("stringParameter : ${stringParameter}"); - var url = Uri.parse("${globals.api}/${endpoint}?${stringParameter}"); + var url = await getUrlForEvents(); final response = await http.get(url, headers: { "Content-Type": "application/json", HttpHeaders.cookieHeader: "access_token=$accessToken" @@ -421,7 +455,8 @@ class _MyHomePageState extends State { inputGeo.clear(); // Clear the text field geographicalZone = ''; // Reset the geographical zone state suggestions.clear(); - showArrow = true; // Optionally clear suggestions + showArrow = true; + showInputSearch = true; // Optionally clear suggestions /// Clear the filtered posts }); fetchPostsByLocation(); @@ -443,6 +478,7 @@ class _MyHomePageState extends State { geographicalZone = ''; // Reset the geographical zone state suggestions.clear(); // Optionally clear suggestions showArrow = true; + showInputSearch = true; /// Clear the filted posts }); @@ -474,6 +510,7 @@ class _MyHomePageState extends State { inputGeo.text = geographicalZone; suggestions.clear(); showArrow = true; + showInputSearch = true; }); SharedPreferences prefs = await SharedPreferences.getInstance(); @@ -496,24 +533,70 @@ class _MyHomePageState extends State { child: Column( children: [ TextField( - controller: inputItem, - decoration: InputDecoration( - labelText: 'Search by item', - border: OutlineInputBorder(), - suffixIcon: IconButton( - icon: const Icon(Icons.clear), - onPressed: () { + controller: inputItem, + decoration: InputDecoration( + labelText: 'Search by item', + border: OutlineInputBorder(), + suffixIcon: IconButton( + icon: const Icon(Icons.clear), + onPressed: () { + setState(() { + inputItem.clear(); + itemName = ''; // Reset the geographical zone state + suggestionsItem.clear(); + showDateFields = true; + showArrow = true; + }); + fetchPostsByLocation(); + }, + ), + ), + onChanged: (value) { + if (value.isNotEmpty) { setState(() { - inputItem.clear(); + itemName = value; + searchSuggestionsByItem(value); + }); + } else { + setState(() { + inputItem.clear(); // Clear the text field + itemName = ''; // Reset the geographical zone state + suggestionsItem.clear(); + showDateFields = true; + showArrow = true; // Optionally clear suggestions + + /// Clear the filted posts }); fetchPostsByLocation(); + } + }), + if (suggestionsItem.isNotEmpty) + Container( + height: 200, + decoration: BoxDecoration( + border: Border.all(color: Colors.blue), + borderRadius: BorderRadius.circular(8), + ), + child: ListView.builder( + shrinkWrap: true, + itemCount: suggestionsItem.length, + itemBuilder: (context, index) { + return ListTile( + title: Text(suggestionsItem[index]['name']), + onTap: () async { + setState(() { + itemName = suggestionsItem[index]['name']; + inputItem.text = itemName; + suggestionsItem.clear(); + showDateFields = true; + showArrow = true; + }); + await fetchPostsByLocation(); + }, + ); }, ), ), - onSubmitted: (value) { - fetchPostsByLocation(); - }, - ), ], ), ); @@ -534,7 +617,7 @@ class _MyHomePageState extends State { ), body: Column( children: [ - if (showArrow) _buildItemZoneSearchField(), + if (showInputSearch) _buildItemZoneSearchField(), if ((showDateFields) && (showArrow)) Row( mainAxisAlignment: MainAxisAlignment.spaceBetween,