add latitude and longitude

This commit is contained in:
Valentin CZERYBA 2024-11-07 23:10:03 +01:00
parent b22458021b
commit 44a0691e31
3 changed files with 240 additions and 174 deletions

View File

@ -85,11 +85,14 @@ class DisplayPictureScreenState extends State<DisplayPictureScreen>
}
Future<void> searchEvents(String json, String imagePath) async {
print(json);
print(json.replaceAll("'''json", '').replaceAll("'''", ""));
SharedPreferences prefs = await SharedPreferences.getInstance();
Map<String, dynamic> jsonData = jsonDecode(json);
Map<String, dynamic> jsonData =
jsonDecode(json.replaceAll("```json", '').replaceAll("```", ""));
print("json : ${jsonData}");
var name = jsonData["name"];
print("name : ${name}");
var place = jsonData["place"];
var accessToken = prefs.getString("access_token") ?? "";
@ -132,7 +135,7 @@ class DisplayPictureScreenState extends State<DisplayPictureScreen>
gemini
.textAndImage(
text:
"Peux-tu donner le nom, la date avec l'année actuelle ou d'une année future proche et le lieu de l'évènement sous format JSON avec les valeurs suivantes : name, address, city, zip_code, country, description, tags (tableau sans espace), organizers (tableau), start_date et end_date sous le format en YYYY-MM-DD HH:mm:ssZ, et sans la présence du mot json dans la chaîne de caractère",
"Peux-tu donner le nom, la date avec l'année actuelle ou d'une année future proche et le lieu de l'évènement sous format JSON (sans le caratère json au début de la chaine de caractère) avec les valeurs suivantes : name, place, description, tags (tableau sans espace), organizers (tableau), start_date et end_date sous le format en YYYY-MM-DD HH:mm:ssZ",
images: [file.readAsBytesSync()],
modelName: "models/gemini-1.5-pro-latest")
.then((value) => searchEvents(

View File

@ -13,6 +13,8 @@ import 'dart:math';
import 'package:geolocator/geolocator.dart';
import '../variable/globals.dart' as globals;
import 'package:permission_handler/permission_handler.dart';
import "Camera.dart";
import 'package:camera/camera.dart';
void main() {
initializeDateFormatting("fr_FR", null).then((_) => runApp(const MyApp()));
@ -356,6 +358,11 @@ class _MyHomePageState extends State<ListItemMenu> {
);
}
Future<void> popCamera() async {
await availableCameras().then((value) => Navigator.push(context,
MaterialPageRoute(builder: (_) => Camera(camera: value.first))));
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -397,6 +404,12 @@ class _MyHomePageState extends State<ListItemMenu> {
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: popCamera,
backgroundColor: Colors.blue,
tooltip: 'Recherche',
child: const Icon(Icons.photo_camera, color: Colors.white),
),
);
}
@ -433,7 +446,8 @@ class _MyHomePageState extends State<ListItemMenu> {
},
);
},
separatorBuilder: (context, index) => Divider(),
);
separatorBuilder: (context, index) {
return Divider();
});
}
}

View File

@ -44,20 +44,21 @@ class UpdateeventImage extends StatefulWidget {
class _UpdateeventImageState extends State<UpdateeventImage>
with ShowErrorDialog, ShowEventDialog {
TextEditingController inputName = TextEditingController();
TextEditingController inputAddress = TextEditingController();
TextEditingController inputZipCode = TextEditingController();
TextEditingController inputCity = TextEditingController();
TextEditingController inputCountry = TextEditingController();
TextEditingController inputDate = TextEditingController();
TextEditingController inputDesc = TextEditingController();
TextEditingController inputGeo = TextEditingController();
TextEditingController startDatepicker = TextEditingController();
TextEditingController startTimepicker = TextEditingController();
TextEditingController endDatepicker = TextEditingController();
TextEditingController endTimepicker = TextEditingController();
final _stringTagController = StringTagController();
List<Map<String, dynamic>> suggestions = [];
String geographicalZone = "";
List<String> initialTags = [];
final _stringOrgaController = StringTagController();
@ -128,10 +129,7 @@ class _UpdateeventImageState extends State<UpdateeventImage>
Future<void> _updateEvent(BuildContext context) async {
var url = Uri.parse("${globals.api}/token");
var name = inputName.text;
var place = inputAddress.text;
var city = inputCity.text;
var country = inputCountry.text;
var zipCode = inputZipCode.text;
var place = inputGeo.text;
var description = inputDesc.text;
List<String> tags = List<String>.from(_stringTagController.getTags as List);
List<String> organizers =
@ -150,6 +148,19 @@ class _UpdateeventImageState extends State<UpdateeventImage>
if (accessToken.isNotEmpty) {
try {
await dotenv.load();
final mapboxAccessToken = dotenv.env['MAPBOX_ACCESS_TOKEN'] ?? '';
final url =
'https://api.mapbox.com/geocoding/v5/mapbox.places/${place}.json?access_token=${mapboxAccessToken}&proximity=ip';
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
final data = json.decode(response.body);
if (data['features'].isNotEmpty) {
final coordinates = data['features'][0]['geometry']['coordinates'];
final longitude = coordinates[0]; // Longitude
final latitude = coordinates[1]; // Latitude
final params = {
'expiration': '15552000',
'key': dotenv.env["IMGBB_API_KEY"],
@ -180,7 +191,8 @@ class _UpdateeventImageState extends State<UpdateeventImage>
var responsePut = await http.put(urlPut,
headers: {
HttpHeaders.cookieHeader: 'access_token=${accessToken}',
HttpHeaders.acceptHeader: 'application/json, text/plain, */*',
HttpHeaders.acceptHeader:
'application/json, text/plain, */*',
HttpHeaders.contentTypeHeader: 'application/json'
},
body: jsonEncode({
@ -188,12 +200,9 @@ class _UpdateeventImageState extends State<UpdateeventImage>
'place': place,
'start_date': startDate,
'end_date': endDate,
'zip_code': zipCode,
'country': country,
'city': city,
'organizers': organizers,
'latitude': '0.0',
'longitude': '0.0',
'latitude': latitude,
'longitude': longitude,
'description': description,
"imgUrl": imgUrl,
"tags": tags
@ -246,6 +255,12 @@ class _UpdateeventImageState extends State<UpdateeventImage>
} else {
print("imgbb error : ${status}");
}
} else {
showErrorDialog(context, "Aucune donnée geographique");
}
} else {
showErrorDialog(context, "Mapbox non accessible");
}
} catch (e) {
showErrorDialog(context, "${e}");
}
@ -255,11 +270,9 @@ class _UpdateeventImageState extends State<UpdateeventImage>
}
void start() async {
print("events : ${widget.events}");
inputName.text = convertNulltoEmptyString(widget.events["name"]);
inputCity.text = convertNulltoEmptyString(widget.events["city"]);
inputAddress.text = convertNulltoEmptyString(widget.events["address"]);
inputZipCode.text = convertNulltoEmptyString(widget.events["zip_code"]);
inputCountry.text = convertNulltoEmptyString(widget.events["country"]);
inputGeo.text = convertNulltoEmptyString(widget.events["place"]);
inputDesc.text = convertNulltoEmptyString(widget.events["description"]);
DateTime pickedStartDate =
@ -286,6 +299,93 @@ class _UpdateeventImageState extends State<UpdateeventImage>
return value!.isEmpty ? 'Champ requis' : null;
}
Future<void> searchSuggestions(String input) async {
await dotenv.load(fileName: ".env"); // Load .env file
final mapboxAccessToken = dotenv.env['MAPBOX_ACCESS_TOKEN'] ?? '';
final url =
'https://api.mapbox.com/geocoding/v5/mapbox.places/${input}.json?access_token=${mapboxAccessToken}&proximity=ip';
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) => {
'place_name': feature['place_name'],
'geometry': feature[
'geometry'], // Include geometry for latitude/longitude
})
.toList();
});
} else {
throw Exception('Failed to load suggestions');
}
}
Padding _buildGeographicalZoneSearchField() {
return Padding(
padding:
const EdgeInsets.only(left: 15.0, right: 15.0, top: 15, bottom: 0),
child: Column(
children: [
TextField(
controller: inputGeo,
decoration: InputDecoration(
labelText: 'Lieu',
border: OutlineInputBorder(),
suffixIcon: IconButton(
icon: const Icon(Icons.clear),
onPressed: () {
setState(() {
inputGeo.clear(); // Clear the text field
geographicalZone = ''; // Reset the geographical zone state
suggestions.clear(); // Optionally clear suggestions
});
},
),
),
onChanged: (value) {
setState(() {
geographicalZone = value;
searchSuggestions(value);
});
},
),
if (suggestions.isNotEmpty)
Container(
height: 200,
decoration: BoxDecoration(
border: Border.all(color: Colors.blue),
borderRadius: BorderRadius.circular(8),
),
child: ListView.builder(
shrinkWrap: true,
itemCount: suggestions.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(suggestions[index]['place_name']),
onTap: () async {
final latitude =
suggestions[index]['geometry']['coordinates'][1];
final longitude =
suggestions[index]['geometry']['coordinates'][0];
setState(() {
geographicalZone = suggestions[index]['place_name'];
inputGeo.text = geographicalZone;
suggestions.clear();
});
},
);
},
),
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -323,58 +423,7 @@ class _UpdateeventImageState extends State<UpdateeventImage>
hintText: 'Modifier le nom de l\'évènement'),
),
),
Padding(
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 15, bottom: 0),
//padding: EdgeInsets.symmetric(horizontal: 15),
child: TextFormField(
controller: inputAddress,
validator: (value) => _validateField(value),
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Adresse',
hintText: 'Entrer une adresse'),
),
),
Padding(
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 15, bottom: 0),
//padding: EdgeInsets.symmetric(horizontal: 15),
child: TextFormField(
controller: inputZipCode,
validator: (value) => _validateField(value),
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Code postal',
hintText: 'Entrer un code postal'),
),
),
Padding(
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 15, bottom: 0),
//padding: EdgeInsets.symmetric(horizontal: 15),
child: TextFormField(
controller: inputCity,
validator: (value) => _validateField(value),
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Ville',
hintText: 'Entrer une ville'),
),
),
Padding(
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 15, bottom: 0),
//padding: EdgeInsets.symmetric(horizontal: 15),
child: TextFormField(
controller: inputCountry,
validator: (value) => _validateField(value),
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Pays',
hintText: 'Entrer un pays'),
),
),
_buildGeographicalZoneSearchField(),
Padding(
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 15, bottom: 0),