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:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'ItemMenu.dart';
|
import 'ItemMenu.dart';
|
||||||
import 'Camera.dart';
|
import 'Camera.dart';
|
||||||
import 'package:http/http.dart' as http;
|
|
||||||
import 'package:flutter/material.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:camera/camera.dart';
|
||||||
|
import 'package:mapbox_gl/mapbox_gl.dart'; // Add this import
|
||||||
import '../variable/globals.dart' as globals;
|
import '../variable/globals.dart' as globals;
|
||||||
|
|
||||||
// app starting point
|
|
||||||
void main() {
|
void main() {
|
||||||
initializeDateFormatting("fr_FR", null).then((_) => runApp(const MyApp()));
|
initializeDateFormatting("fr_FR", null).then((_) => runApp(const MyApp()));
|
||||||
}
|
}
|
||||||
@ -28,7 +29,6 @@ class MyApp extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// homepage class
|
|
||||||
class ListItemMenu extends StatefulWidget {
|
class ListItemMenu extends StatefulWidget {
|
||||||
const ListItemMenu({super.key});
|
const ListItemMenu({super.key});
|
||||||
|
|
||||||
@ -36,14 +36,15 @@ class ListItemMenu extends StatefulWidget {
|
|||||||
State<ListItemMenu> createState() => _MyHomePageState();
|
State<ListItemMenu> createState() => _MyHomePageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
// homepage state
|
|
||||||
class _MyHomePageState extends State<ListItemMenu> {
|
class _MyHomePageState extends State<ListItemMenu> {
|
||||||
Future<List<Events>> postsFuture = getPosts();
|
Future<List<Events>> postsFuture = getPosts();
|
||||||
List<Events> filteredPosts = [];
|
List<Events> filteredPosts = [];
|
||||||
String geographicalZone = '';
|
String geographicalZone = '';
|
||||||
String query = '';
|
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 {
|
static Future<List<Events>> getPosts() async {
|
||||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
var accessToken = prefs.getString("access_token") ?? "";
|
var accessToken = prefs.getString("access_token") ?? "";
|
||||||
@ -60,45 +61,77 @@ class _MyHomePageState extends State<ListItemMenu> {
|
|||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Events>> searchPosts(String query) async {
|
Future<void> searchSuggestions(String input) async {
|
||||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
await dotenv.load(fileName: ".env"); // Load .env file
|
||||||
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> popCamera() async {
|
final mapboxAccessToken = dotenv.env['MAPBOX_ACCESS_TOKEN'] ?? '';
|
||||||
await availableCameras().then((value) => Navigator.push(context,
|
final url =
|
||||||
MaterialPageRoute(builder: (_) => Camera(camera: value.first))));
|
'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() {
|
Padding _buildGeographicalZoneSearchField() {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: TextField(
|
child: Column(
|
||||||
decoration: InputDecoration(
|
children: [
|
||||||
labelText: 'Search by geographical zone',
|
TextField(
|
||||||
border: OutlineInputBorder(),
|
controller: inputGeo,
|
||||||
),
|
decoration: InputDecoration(
|
||||||
onChanged: (value) {
|
labelText: 'Search by geographical zone',
|
||||||
setState(() {
|
border: OutlineInputBorder(),
|
||||||
geographicalZone = value; // Update geographical zone
|
),
|
||||||
});
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@ -120,7 +153,6 @@ class _MyHomePageState extends State<ListItemMenu> {
|
|||||||
),
|
),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
// New Search Bar for Geographical Zone
|
|
||||||
_buildGeographicalZoneSearchField(),
|
_buildGeographicalZoneSearchField(),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: FutureBuilder<List<Events>>(
|
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) {
|
Widget buildPosts(List<Events> posts) {
|
||||||
return ListView.separated(
|
return ListView.separated(
|
||||||
itemCount: posts.length,
|
itemCount: posts.length,
|
||||||
|
@ -1,6 +1,14 @@
|
|||||||
# Generated by pub
|
# Generated by pub
|
||||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||||
packages:
|
packages:
|
||||||
|
archive:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: archive
|
||||||
|
sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.6.1"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -89,6 +97,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.4+2"
|
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:
|
cupertino_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -248,6 +264,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.2"
|
version: "4.0.2"
|
||||||
|
image:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: image
|
||||||
|
sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.3.0"
|
||||||
image_picker:
|
image_picker:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -320,6 +344,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.19.0"
|
version: "0.19.0"
|
||||||
|
js:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: js
|
||||||
|
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.6.7"
|
||||||
json_annotation:
|
json_annotation:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -360,6 +392,38 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
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:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -448,6 +512,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.0"
|
version: "2.3.0"
|
||||||
|
petitparser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: petitparser
|
||||||
|
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.0.2"
|
||||||
platform:
|
platform:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -629,6 +701,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.4"
|
version: "1.0.4"
|
||||||
|
xml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: xml
|
||||||
|
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.5.0"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.4.0 <4.0.0"
|
dart: ">=3.4.0 <4.0.0"
|
||||||
flutter: ">=3.22.0"
|
flutter: ">=3.22.0"
|
||||||
|
@ -46,6 +46,7 @@ dependencies:
|
|||||||
image_picker: ^1.1.2
|
image_picker: ^1.1.2
|
||||||
date_format_field: ^0.1.0
|
date_format_field: ^0.1.0
|
||||||
textfield_tags: ^3.0.1
|
textfield_tags: ^3.0.1
|
||||||
|
mapbox_gl: ^0.16.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user