Skip to content

Commit 233d79f

Browse files
author
himanshu goyal
committed
search landmark
1 parent 6d3b0b7 commit 233d79f

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import 'dart:convert';
2+
import 'package:http/http.dart' as http;
3+
4+
class GeoapifyService {
5+
static const String _apiKey = '1e810532f9934cd3a0d964b4caabd5d0';
6+
static const String _baseUrl =
7+
'https://api.geoapify.com/v1/geocode/autocomplete';
8+
9+
Future<List<String>> getLocationSuggestions(String query) async {
10+
final url = Uri.parse("$_baseUrl?text=$query&limit=5&apiKey=$_apiKey");
11+
12+
if (query.isEmpty) {
13+
return [];
14+
}
15+
16+
final response = await http.get(url);
17+
if (response.statusCode == 200) {
18+
final data = jsonDecode(response.body);
19+
List suggestions = data['features'];
20+
21+
return suggestions
22+
.map<String>((item) => item['properties']['formatted'] as String)
23+
.toList();
24+
} else {
25+
throw Exception("Failed to fetch location suggestions");
26+
}
27+
}
28+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import 'package:beacon/presentation/hike/services/geoapify_service.dart';
2+
import 'package:flutter/material.dart';
3+
import 'package:flutter_typeahead/flutter_typeahead.dart';
4+
5+
class LocationSearchWidget extends StatelessWidget {
6+
final GeoapifyService geoapifyService = GeoapifyService();
7+
8+
@override
9+
Widget build(BuildContext context) {
10+
return Container(
11+
margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
12+
child: TypeAheadField<String>(
13+
suggestionsCallback: (pattern) async {
14+
return await geoapifyService.getLocationSuggestions(pattern);
15+
},
16+
builder: (context, controller, focusNode) {
17+
return Container(
18+
decoration: BoxDecoration(
19+
color: Colors.white, borderRadius: BorderRadius.circular(20)),
20+
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
21+
child: TextFormField(
22+
controller: controller,
23+
focusNode: focusNode,
24+
cursorColor: Colors.deepPurpleAccent.withAlpha(120),
25+
decoration: InputDecoration(
26+
isDense: true,
27+
contentPadding: EdgeInsets.symmetric(vertical: 12),
28+
border: InputBorder.none,
29+
focusedBorder: InputBorder.none,
30+
enabledBorder: InputBorder.none,
31+
errorBorder: OutlineInputBorder(
32+
borderRadius: BorderRadius.circular(14),
33+
borderSide: BorderSide(color: Colors.red),
34+
),
35+
hintText: 'Search for a place',
36+
hintStyle: TextStyle(fontSize: 15, color: Colors.grey[600]),
37+
prefixIcon: Icon(
38+
Icons.search,
39+
size: 20,
40+
color: Colors.deepPurpleAccent.withAlpha(120),
41+
),
42+
suffixIcon: IconButton(
43+
icon: Icon(Icons.clear, color: Colors.grey),
44+
onPressed: () {
45+
controller.clear();
46+
focusNode.unfocus();
47+
// remove keyboard
48+
},
49+
)),
50+
style: TextStyle(
51+
color: Colors.black,
52+
fontSize: 14,
53+
),
54+
),
55+
);
56+
},
57+
itemBuilder: (context, suggestion) {
58+
return ListTile(
59+
title: Text(suggestion),
60+
leading: Icon(Icons.location_on, color: Colors.blue),
61+
);
62+
},
63+
onSelected: (suggestion) {
64+
ScaffoldMessenger.of(context).showSnackBar(
65+
SnackBar(content: Text('You selected: $suggestion')),
66+
);
67+
},
68+
hideOnEmpty: true,
69+
decorationBuilder: (context, child) {
70+
return Container(
71+
decoration: BoxDecoration(
72+
color: Colors.white,
73+
borderRadius: BorderRadius.circular(8.0),
74+
boxShadow: [
75+
BoxShadow(
76+
color: Colors.grey.withOpacity(0.2),
77+
spreadRadius: 2,
78+
blurRadius: 5,
79+
offset: Offset(0, 3), // changes position of shadow
80+
),
81+
],
82+
),
83+
child: child,
84+
);
85+
},
86+
),
87+
);
88+
}
89+
}

0 commit comments

Comments
 (0)