From 8b951f6d9d4a4f5ceeb671e4159a16d044681ff1 Mon Sep 17 00:00:00 2001 From: Niklas Date: Fri, 12 Jan 2024 23:33:27 +0100 Subject: [PATCH] Added Categorie Party page. And added goecoding API --- emma/android/app/src/main/AndroidManifest.xml | 3 +- emma/ios/Runner/Info.plist | 4 + emma/lib/main.dart | 375 +++++++++++++----- emma/macos/Runner/Release.entitlements | 4 + emma/pubspec.lock | 8 + emma/pubspec.yaml | 1 + 6 files changed, 293 insertions(+), 102 deletions(-) diff --git a/emma/android/app/src/main/AndroidManifest.xml b/emma/android/app/src/main/AndroidManifest.xml index 3d285c7..0548da0 100644 --- a/emma/android/app/src/main/AndroidManifest.xml +++ b/emma/android/app/src/main/AndroidManifest.xml @@ -28,6 +28,7 @@ This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> + android:value="2" /> + diff --git a/emma/ios/Runner/Info.plist b/emma/ios/Runner/Info.plist index 593945e..6e69dc2 100644 --- a/emma/ios/Runner/Info.plist +++ b/emma/ios/Runner/Info.plist @@ -47,5 +47,9 @@ UIApplicationSupportsIndirectInputEvents + + com.apple.security.network.client + + diff --git a/emma/lib/main.dart b/emma/lib/main.dart index 1be0f69..c3933eb 100644 --- a/emma/lib/main.dart +++ b/emma/lib/main.dart @@ -1,7 +1,10 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:location/location.dart'; +import 'package:http/http.dart' as http; import 'dart:async'; +import 'dart:convert'; +import 'dart:developer'; void main() => runApp(const MyApp()); const Duration fakeAPIDuration = Duration(milliseconds: 50); @@ -43,8 +46,10 @@ class MyApp extends StatelessWidget { UIData.homeRoute: (BuildContext context) => MyFormPage(title: 'SecondPage'), //title=AbsorbPointer()'Start'), UIData.typeRoute: (BuildContext context) => TypePage(title: 'Type'), - UIData.categorieRoute: (BuildContext context) => - CategoriePage(), //title='Kategorie'), + UIData.categorieFoodRoute: (BuildContext context) => + CategorieFoodPage(), //title='Kategorie'), + UIData.categoriePartyRoute: (BuildContext context) => + CategoriePartyPage(title: 'Kategorie Party'), //UIData.teamRoute: (BuildContext context) =>TeamsPage(), //UIData.planRoute: (BuildContext context) =>PlanPage(), //UIData.quizRoute: (BuildContext context) =>QuizPage(), @@ -57,13 +62,61 @@ class UIData { //routes static const String homeRoute = "/home"; static const String typeRoute = "/teams"; - static const String categorieRoute = "/categorie"; + static const String categorieFoodRoute = "/categoriefood"; + static const String categoriePartyRoute = "/categorieparty"; static const String timeRoute = "/time"; static const String resoultRoute = "/list"; static const String quizRoute = "/quiz"; static const String impressionRoute = "/impression"; } +class Address { + final String display_name; + /*final String house_number; + final String roadName; + final String cityName;*/ + const Address({ + required this.display_name, + /*required this.house_number, + required this.roadName, + required this.cityName,*/ + }); + factory Address.fromJson(Map json) { + return switch (json) { + { + 'display_name': String display_name, + //'house_number': String house_number, + //'road': String roadName, + //'town': String cityName, + } => + Address( + display_name: display_name, + /*house_number: house_number, + roadName: roadName, + cityName: cityName,*/ + ), + _ => throw const FormatException('Failed to load address.'), + }; + } +} + +Future
fetchAddress(LocationData userLocation) async { + final response = await http.get(Uri.parse( + 'https://nominatim.openstreetmap.org/reverse?lat=${userLocation.latitude}&lon=${userLocation.longitude}&format=json')); + + if (response.statusCode == 200) { + // If the server did return a 200 OK response, + // then parse the JSON. + log("Index number is: ${response.body}"); + + return Address.fromJson(jsonDecode(response.body) as Map); + } else { + // If the server did not return a 200 OK response, + // then throw an exception. + throw Exception('Failed to load album'); + } +} + class MyFormPage extends StatefulWidget { const MyFormPage({Key key = const Key('defaultKey'), required this.title}) : super(key: key); @@ -80,6 +133,7 @@ class _MyFormPageState extends State { late bool _serviceEnabled; late PermissionStatus _permissionGranted; + late Future
futureAddress; LocationData? _userLocation; @@ -108,11 +162,13 @@ class _MyFormPageState extends State { final locationData = await location.getLocation(); setState(() { _userLocation = locationData; + futureAddress = fetchAddress(_userLocation!); }); } final _formKey = GlobalKey(); double _currentSliderValue = 1; + @override Widget build(BuildContext context) { return Scaffold( @@ -160,9 +216,17 @@ class _MyFormPageState extends State { _userLocation != null ? Wrap( children: [ - Text('Your latitude: ${_userLocation?.latitude}'), - const SizedBox(width: 10), - Text('Your longtitude: ${_userLocation?.longitude}') + FutureBuilder
( + future: futureAddress, + builder: (context, snapshot) { + if (snapshot.hasData) { + return Text(snapshot.data!.display_name); + } else if (snapshot.hasError) { + return Text('${snapshot.error}'); + } // By default, show a loading spinner. + return const CircularProgressIndicator(); + }, + ), ], ) : const Text(''), @@ -273,7 +337,7 @@ class TypePage extends StatelessWidget { onPressed: () { Navigator.push(context, MaterialPageRoute(builder: (context) { - return CategoriePage(); + return CategorieFoodPage(); })); }, ), @@ -293,7 +357,7 @@ class TypePage extends StatelessWidget { onPressed: () { Navigator.push(context, MaterialPageRoute(builder: (context) { - return CategoriePage(); + return CategoriePartyPage(title: 'Kategorie Party'); })); }, ), @@ -313,7 +377,7 @@ class TypePage extends StatelessWidget { onPressed: () { Navigator.push(context, MaterialPageRoute(builder: (context) { - return CategoriePage(); + return CategorieFoodPage(); })); }, ), @@ -339,7 +403,7 @@ class TypePage extends StatelessWidget { onPressed: () { Navigator.push(context, MaterialPageRoute(builder: (context) { - return CategoriePage(); + return CategorieFoodPage(); })); }, ), @@ -359,7 +423,7 @@ class TypePage extends StatelessWidget { onPressed: () { Navigator.push(context, MaterialPageRoute(builder: (context) { - return CategoriePage(); + return CategorieFoodPage(); })); }, ), @@ -379,7 +443,7 @@ class TypePage extends StatelessWidget { onPressed: () { Navigator.push(context, MaterialPageRoute(builder: (context) { - return CategoriePage(); + return CategorieFoodPage(); })); }, ), @@ -418,7 +482,7 @@ class TypePage extends StatelessWidget { onPressed: () { // Wenn alle Validatoren der Felder des Formulars gültig sind. Navigator.push(context, MaterialPageRoute(builder: (context) { - return CategoriePage(); + return CategorieFoodPage(); })); }, child: const Text('Weiter'), @@ -431,55 +495,21 @@ class TypePage extends StatelessWidget { } } -class TypePage2 extends StatelessWidget { - TypePage2({Key? key, required this.title}) : super(key: key); +class CategoriePartyPage extends StatelessWidget { + CategoriePartyPage({Key? key, required this.title}) : super(key: key); final String title; final List myProducts = - List.generate(100000, (index) => {"id": index, "name": "Product $index"}) + List.generate(10, (index) => {"id": index, "name": "Product $index"}) .toList(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text("Type"), + title: Text(this.title), ), body: Padding( padding: const EdgeInsets.all(8.0), // implement GridView.builder - child: GridView.builder( - gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent( - maxCrossAxisExtent: 200, - childAspectRatio: 3 / 2, - crossAxisSpacing: 20, - mainAxisSpacing: 20), - itemCount: myProducts.length, - itemBuilder: (BuildContext ctx, index) { - return Container( - alignment: Alignment.center, - decoration: BoxDecoration( - color: Colors.amber, - borderRadius: BorderRadius.circular(15)), - child: ElevatedButton( - onPressed: () { - Navigator.pop(context); - }, - child: Text(myProducts[index]["name"]), - ), - ); - }), - ), - ); - } -} - -class CategoriePage extends StatelessWidget { - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text("Kategorie"), - ), - body: Center( child: Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Expanded( @@ -496,13 +526,8 @@ class CategoriePage extends StatelessWidget { borderRadius: BorderRadius.circular(10.0), ), ), - child: Text('Frühstück'), - onPressed: () { - Navigator.push(context, - MaterialPageRoute(builder: (context) { - return CategoriePage(); - })); - }, + child: Text('Elektro'), + onPressed: () {}, ), ), SizedBox( @@ -516,13 +541,8 @@ class CategoriePage extends StatelessWidget { borderRadius: BorderRadius.circular(10.0), ), ), - child: Text('Mittag'), - onPressed: () { - Navigator.push(context, - MaterialPageRoute(builder: (context) { - return CategoriePage(); - })); - }, + child: Text('Hip Hop'), + onPressed: () {}, ), ), SizedBox( @@ -536,13 +556,8 @@ class CategoriePage extends StatelessWidget { borderRadius: BorderRadius.circular(10.0), ), ), - child: Text('Abendessen'), - onPressed: () { - Navigator.push(context, - MaterialPageRoute(builder: (context) { - return CategoriePage(); - })); - }, + child: Text('90s'), + onPressed: () {}, ), ), ], @@ -563,12 +578,7 @@ class CategoriePage extends StatelessWidget { ), ), child: Text('Indisch'), - onPressed: () { - Navigator.push(context, - MaterialPageRoute(builder: (context) { - return CategoriePage(); - })); - }, + onPressed: () {}, ), ), SizedBox( @@ -583,14 +593,190 @@ class CategoriePage extends StatelessWidget { ), ), child: Text('Bayrisch'), + onPressed: () {}, + ), + ), + SizedBox( + height: 100, //height of button + width: (MediaQuery.of(context).size.width - 30) / + 3, //width of button + child: ElevatedButton( + style: ElevatedButton.styleFrom( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + ), + child: Text('Snack'), onPressed: () { Navigator.push(context, MaterialPageRoute(builder: (context) { - return CategoriePage(); + return TimePage(); })); }, ), ), + ], + ), + ), + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.grey, + textStyle: const TextStyle(color: Colors.white)), + onPressed: () { + // reset() setzt alle Felder wieder auf den Initalwert zurück. + }, + child: const Text('Zurücksetzen'), + ), + const SizedBox(width: 25), + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.grey, + textStyle: const TextStyle(color: Colors.white)), + onPressed: () { + // reset() setzt alle Felder wieder auf den Initalwert zurück. + }, + child: const Text('Skip'), + ), + const SizedBox(width: 25), + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + textStyle: const TextStyle(color: Colors.white)), + onPressed: () { + // Wenn alle Validatoren der Felder des Formulars gültig sind. + Navigator.push(context, MaterialPageRoute(builder: (context) { + return TimePage(); + })); + }, + child: const Text('Weiter'), + ) + ], + )), + ]), /*GridView.builder( + gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent( + maxCrossAxisExtent: 200, + childAspectRatio: 3 / 2, + crossAxisSpacing: 20, + mainAxisSpacing: 20), + itemCount: myProducts.length, + itemBuilder: (BuildContext ctx, index) { + return Container( + alignment: Alignment.center, + decoration: BoxDecoration( + color: Colors.amber, + borderRadius: BorderRadius.circular(15)), + child: ElevatedButton( + onPressed: () { + Navigator.pop(context); + }, + child: Text(myProducts[index]["name"]), + ), + ); + }),*/ + ), + ); + } +} + +class CategorieFoodPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text("Kategorie Essen"), + ), + body: Center( + child: + Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [ + Expanded( + child: Row( + children: [ + SizedBox( + height: 100, //height of button + width: (MediaQuery.of(context).size.width - 30) / + 3, //width of button + child: ElevatedButton( + style: ElevatedButton.styleFrom( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + ), + child: Text('Frühstück'), + onPressed: () {}, + ), + ), + SizedBox( + height: 100, //height of button + width: (MediaQuery.of(context).size.width - 30) / + 3, //width of button + child: ElevatedButton( + style: ElevatedButton.styleFrom( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + ), + child: Text('Mittag'), + onPressed: () {}, + ), + ), + SizedBox( + height: 100, //height of button + width: (MediaQuery.of(context).size.width - 30) / + 3, //width of button + child: ElevatedButton( + style: ElevatedButton.styleFrom( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + ), + child: Text('Abendessen'), + onPressed: () {}, + ), + ), + ], + ), + ), + Expanded( + child: Row( + children: [ + SizedBox( + height: 100, //height of button + width: (MediaQuery.of(context).size.width - 30) / + 3, //width of button + child: ElevatedButton( + style: ElevatedButton.styleFrom( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + ), + child: Text('Indisch'), + onPressed: () {}, + ), + ), + SizedBox( + height: 100, //height of button + width: (MediaQuery.of(context).size.width - 30) / + 3, //width of button + child: ElevatedButton( + style: ElevatedButton.styleFrom( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + ), + child: Text('Bayrisch'), + onPressed: () {}, + ), + ), SizedBox( height: 100, //height of button width: (MediaQuery.of(context).size.width - 30) / @@ -661,6 +847,8 @@ class CategoriePage extends StatelessWidget { class TimePage extends StatelessWidget { DateTime selectedDate = DateTime.now(); TimeOfDay selectedTime = TimeOfDay.now(); + + TimePage({super.key}); Future _selectDate(BuildContext context) async { final DateTime? picked = await showDatePicker( context: context, @@ -755,12 +943,7 @@ class TimePage extends StatelessWidget { ), ), child: Text('Morgen'), - onPressed: () { - Navigator.push(context, - MaterialPageRoute(builder: (context) { - return CategoriePage(); - })); - }, + onPressed: () {}, ), ), const SizedBox(width: 15), @@ -776,12 +959,7 @@ class TimePage extends StatelessWidget { ), ), child: Text('Dieses Wochenende'), - onPressed: () { - Navigator.push(context, - MaterialPageRoute(builder: (context) { - return CategoriePage(); - })); - }, + onPressed: () {}, ), ), ], @@ -831,12 +1009,7 @@ class TimePage extends StatelessWidget { ), ), child: Text('+ 1 Std'), - onPressed: () { - Navigator.push(context, - MaterialPageRoute(builder: (context) { - return CategoriePage(); - })); - }, + onPressed: () {}, ), ), const SizedBox(width: 15), @@ -858,10 +1031,10 @@ class TimePage extends StatelessWidget { ), label: Text('Select'), onPressed: () { - Navigator.push(context, - MaterialPageRoute(builder: (context) { - return CategoriePage(); - })); + Future selectedTime = showTimePicker( + initialTime: TimeOfDay.now(), + context: context, + ); }, ), ), diff --git a/emma/macos/Runner/Release.entitlements b/emma/macos/Runner/Release.entitlements index 852fa1a..64564dd 100644 --- a/emma/macos/Runner/Release.entitlements +++ b/emma/macos/Runner/Release.entitlements @@ -4,5 +4,9 @@ com.apple.security.app-sandbox + + com.apple.security.network.client + + diff --git a/emma/pubspec.lock b/emma/pubspec.lock index 1593f86..59c5dc3 100644 --- a/emma/pubspec.lock +++ b/emma/pubspec.lock @@ -80,6 +80,14 @@ packages: description: flutter source: sdk version: "0.0.0" + http: + dependency: "direct main" + description: + name: http + sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139 + url: "https://pub.dev" + source: hosted + version: "1.1.2" http_parser: dependency: transitive description: diff --git a/emma/pubspec.yaml b/emma/pubspec.yaml index af40667..4315e93 100644 --- a/emma/pubspec.yaml +++ b/emma/pubspec.yaml @@ -36,6 +36,7 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 location: ^5.0.3 + http: ^1.1.2 dev_dependencies: flutter_test: