From b0c4afe1f34cdd0e3103fe594c2ea7d0667e391a Mon Sep 17 00:00:00 2001 From: Konstantin Kollar Date: Sat, 3 Sep 2022 21:36:18 +0200 Subject: [PATCH] Locations screen and add locations form --- .../locations/add_location_form.dart | 143 ++++++++++++++++++ lib/components/main_menu.dart | 9 ++ lib/screens/locations.dart | 36 +++++ lib/screens/main_weather_view.dart | 1 + 4 files changed, 189 insertions(+) create mode 100644 lib/components/locations/add_location_form.dart create mode 100644 lib/screens/locations.dart diff --git a/lib/components/locations/add_location_form.dart b/lib/components/locations/add_location_form.dart new file mode 100644 index 0000000..8858972 --- /dev/null +++ b/lib/components/locations/add_location_form.dart @@ -0,0 +1,143 @@ +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class AddLocationsForm extends StatefulWidget { + final SharedPreferences prefs; + + const AddLocationsForm(this.prefs, {Key? key}) : super(key: key); + + @override + AddLocationsFormState createState() => AddLocationsFormState(); +} + +class AddLocationsFormState extends State { + final _formKey = GlobalKey(); + final locationFormController = TextEditingController(); + String? newLocationName; + double? newLatitude; + double? newLongitude; + late List savedLocations; + + @override + void initState() { + super.initState(); + savedLocations = widget.prefs.getStringList('savedLocations') ?? []; + } + + @override + void dispose() { + locationFormController.dispose(); + super.dispose(); + } + + void _submitLocation() { + if (_formKey.currentState!.validate()) { + _formKey.currentState!.save(); + _saveLocationToPrefs(newLocationName!, newLatitude!, newLongitude!); + _formKey.currentState!.reset(); + newLocationName = null; + newLatitude = null; + newLongitude = null; + } + } + + void _saveLocationToPrefs(String name, double lat, double lon) { + savedLocations.add(name); + widget.prefs.setStringList('savedLocations', savedLocations); + widget.prefs.setDouble("$name-lat", lat); + widget.prefs.setDouble("$name-lon", lon); + } + + @override + Widget build(BuildContext context) { + return Form( + key: _formKey, + child: Column(children: [ + Flexible( + flex: 4, + child: TextFormField( + //Location Name + onSaved: (input) { + newLocationName = input; + }, + controller: locationFormController, + validator: ((value) { + if (value == null || value.isEmpty) { + return "Please enter a name for the new location"; + } + if (savedLocations.contains(value)) { + return "Location name already in use"; + } + return null; + }), + decoration: const InputDecoration( + border: UnderlineInputBorder(), labelText: "Location Name"), + )), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Flexible( + flex: 1, + child: TextFormField( + //Latitude + validator: ((value) { + if (value == null || value.isEmpty) { + return "Please enter a value"; + } + try { + double.parse(value); + } catch (e) { + return "Please enter a number"; + } + return null; + }), + onSaved: (input) { + newLatitude = double.parse(input!); + }, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + border: UnderlineInputBorder(), labelText: "Latitude"), + )), + const SizedBox(width: 10), + Flexible( + flex: 1, + child: TextFormField( + //Longitude + validator: ((value) { + if (value == null || value.isEmpty) { + return "Please enter a value"; + } + try { + double.parse(value); + } catch (e) { + return "Please enter a number"; + } + return null; + }), + onSaved: (input) { + newLongitude = double.parse(input!); + }, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + border: UnderlineInputBorder(), labelText: "Longitude"), + )), + const SizedBox(width: 10), + Flexible( + flex: 2, + child: ElevatedButton( + onPressed: () { + _submitLocation(); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: const [ + Icon(Icons.add), + SizedBox(width: 5), + Text("Add Location") + ], + ))) + ], + ) + ])); + } +} diff --git a/lib/components/main_menu.dart b/lib/components/main_menu.dart index 0457549..35272af 100644 --- a/lib/components/main_menu.dart +++ b/lib/components/main_menu.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:wetter/screens/locations.dart'; import 'package:wetter/screens/settings.dart'; class NavBar extends StatelessWidget { @@ -23,6 +24,14 @@ class NavBar extends StatelessWidget { MaterialPageRoute(builder: (context) => const Settings())); }, ), + ListTile( + leading: const Icon(Icons.public), + title: const Text("Locations"), + onTap: (() { + Navigator.push(context, + MaterialPageRoute(builder: (context) => const Locations())); + }), + ) ], ), ); diff --git a/lib/screens/locations.dart b/lib/screens/locations.dart new file mode 100644 index 0000000..380821c --- /dev/null +++ b/lib/screens/locations.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:wetter/components/locations/add_location_form.dart'; + +class Locations extends StatefulWidget { + const Locations({super.key}); + + @override + State createState() => _LocationsState(); +} + +class _LocationsState extends State { + late final SharedPreferences? prefs; + + @override + void initState() { + SharedPreferences.getInstance().then((value) => prefs = value); + super.initState(); + } + + Future initializePreferences() async { + prefs = await SharedPreferences.getInstance(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Locations'), + ), + body: Padding( + padding: const EdgeInsets.all(20), + child: AddLocationsForm(prefs!), + )); + } +} diff --git a/lib/screens/main_weather_view.dart b/lib/screens/main_weather_view.dart index e94efd3..e456bf5 100644 --- a/lib/screens/main_weather_view.dart +++ b/lib/screens/main_weather_view.dart @@ -41,6 +41,7 @@ class _MainWeatherViewState extends State @override Widget build(BuildContext context) { + super.build(context); return RefreshIndicator( onRefresh: () { return Future(() {