add searchbar with mapbox and suggesstionbar
This commit is contained in:
parent
576d045cd8
commit
3a350e33cc
@ -1,17 +1,18 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:flutter_dotenv/flutter_dotenv.dart'; // Import dotenv
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'ItemMenu.dart';
|
||||
import 'Camera.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:flutter/material.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 '../variable/globals.dart' as globals;
|
||||
|
||||
// app starting point
|
||||
void main() {
|
||||
initializeDateFormatting("fr_FR", null).then((_) => runApp(const MyApp()));
|
||||
}
|
||||
@ -28,7 +29,6 @@ class MyApp extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
// homepage class
|
||||
class ListItemMenu extends StatefulWidget {
|
||||
const ListItemMenu({super.key});
|
||||
|
||||
@ -36,14 +36,15 @@ class ListItemMenu extends StatefulWidget {
|
||||
State<ListItemMenu> createState() => _MyHomePageState();
|
||||
}
|
||||
|
||||
// homepage state
|
||||
class _MyHomePageState extends State<ListItemMenu> {
|
||||
Future<List<Events>> postsFuture = getPosts();
|
||||
List<Events> filteredPosts = [];
|
||||
String geographicalZone = '';
|
||||
String query = '';
|
||||
List<String> suggestions = []; // Store suggestions
|
||||
TextEditingController inputGeo = TextEditingController();
|
||||
|
||||
// function to fetch data from api and return future list of posts
|
||||
// Fetching events from API
|
||||
static Future<List<Events>> getPosts() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
var accessToken = prefs.getString("access_token") ?? "";
|
||||
@ -60,45 +61,77 @@ class _MyHomePageState extends State<ListItemMenu> {
|
||||
return body;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
Future<void> searchSuggestions(String input) async {
|
||||
await dotenv.load(fileName: ".env"); // Load .env file
|
||||
|
||||
Future<void> popCamera() async {
|
||||
await availableCameras().then((value) => Navigator.push(context,
|
||||
MaterialPageRoute(builder: (_) => Camera(camera: value.first))));
|
||||
final mapboxAccessToken = dotenv.env['MAPBOX_ACCESS_TOKEN'] ?? '';
|
||||
final url =
|
||||
'https://api.mapbox.com/geocoding/v5/mapbox.places/${input}.json?access_token=${mapboxAccessToken}&proximity=ip'; // Replace with your Mapbox token
|
||||
final response = await http.get(Uri.parse(url));
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final data = json.decode(response.body);
|
||||
setState(() {
|
||||
suggestions = (data['features'] as List)
|
||||
.map((feature) =>
|
||||
feature['place_name'] as String) // Cast to String explicitly
|
||||
.toList();
|
||||
});
|
||||
} else {
|
||||
throw Exception('Failed to load suggestions');
|
||||
}
|
||||
}
|
||||
|
||||
Padding _buildGeographicalZoneSearchField() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: TextField(
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Search by geographical zone',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
geographicalZone = value; // Update geographical zone
|
||||
});
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
TextField(
|
||||
controller: inputGeo,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Search by geographical zone',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
geographicalZone = value;
|
||||
searchSuggestions(value);
|
||||
});
|
||||
},
|
||||
),
|
||||
if (suggestions.isNotEmpty)
|
||||
Container(
|
||||
height: 200,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.blue), // Add a border color
|
||||
borderRadius:
|
||||
BorderRadius.circular(8), // Optional: rounded corners
|
||||
),
|
||||
child: ListView.builder(
|
||||
shrinkWrap:
|
||||
true, // Ensure the list takes only the required space
|
||||
|
||||
itemCount: suggestions.length,
|
||||
itemBuilder: (context, index) {
|
||||
return ListTile(
|
||||
title: Text(suggestions[index]),
|
||||
onTap: () {
|
||||
setState(() {
|
||||
geographicalZone = suggestions[index];
|
||||
inputGeo.text = suggestions[index];
|
||||
suggestions.clear();
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// build function
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@ -120,7 +153,6 @@ class _MyHomePageState extends State<ListItemMenu> {
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
// New Search Bar for Geographical Zone
|
||||
_buildGeographicalZoneSearchField(),
|
||||
Expanded(
|
||||
child: FutureBuilder<List<Events>>(
|
||||
@ -144,7 +176,7 @@ class _MyHomePageState extends State<ListItemMenu> {
|
||||
);
|
||||
}
|
||||
|
||||
// function to display fetched data on screen
|
||||
// Function to display fetched data on screen
|
||||
Widget buildPosts(List<Events> posts) {
|
||||
return ListView.separated(
|
||||
itemCount: posts.length,
|
||||
|
@ -1,6 +1,14 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: archive
|
||||
sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.6.1"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -89,6 +97,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.4+2"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.6"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -248,6 +264,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.2"
|
||||
image:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image
|
||||
sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.3.0"
|
||||
image_picker:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -320,6 +344,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.19.0"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.7"
|
||||
json_annotation:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -360,6 +392,38 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
mapbox_gl:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: mapbox_gl
|
||||
sha256: d78907338ff232e3cf6c1d6dba45e6a8814069496fd352e49bb1967d498f09af
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.16.0"
|
||||
mapbox_gl_dart:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mapbox_gl_dart
|
||||
sha256: de6d03718e5eb05c9eb1ddaae7f0383b28acb5afa16405e1deed7ff04dd34f3d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.1"
|
||||
mapbox_gl_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mapbox_gl_platform_interface
|
||||
sha256: b7c1490b022e650afd20412bdf8ae45a1897118b7ce6049ef6c42df09193d4b2
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.16.0"
|
||||
mapbox_gl_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mapbox_gl_web
|
||||
sha256: e77113bf95a4f321ff44938232517e0f2725aae991f0b283af1afaa7e7a58aca
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.16.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -448,6 +512,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: petitparser
|
||||
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.2"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -629,6 +701,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
xml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xml
|
||||
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.5.0"
|
||||
sdks:
|
||||
dart: ">=3.4.0 <4.0.0"
|
||||
flutter: ">=3.22.0"
|
||||
|
@ -46,6 +46,7 @@ dependencies:
|
||||
image_picker: ^1.1.2
|
||||
date_format_field: ^0.1.0
|
||||
textfield_tags: ^3.0.1
|
||||
mapbox_gl: ^0.16.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Loading…
x
Reference in New Issue
Block a user