diff --git a/README.md b/README.md new file mode 100644 index 0000000..461d381 --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# fforte + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/lib/#main.dart# b/lib/#main.dart# index fe5cdff..66fbc74 100644 --- a/lib/#main.dart# +++ b/lib/#main.dart# @@ -1,4 +1,5 @@ -import 'package:fforte/screens/addCam/add_cam_main.dart~'; +import 'package:fforte/screens/Excursion/excursion_main.dart'; +import 'package:fforte/screens/addCam/add_cam_main.dart'; import 'package:fforte/screens/intro_screen.dart'; import 'package:fforte/screens/settings.dart'; import 'package:fforte/screens/viewCam/view_cams.dart'; @@ -15,14 +16,14 @@ import 'l10n/l10n.dart'; runApp(const MyApp()); } */ - void main() async { WidgetsFlutterBinding.ensureInitialized(); SharedPreferences prefs = await SharedPreferences.getInstance(); bool isFirstLaunch = prefs.getBool('isFirstLaunch') ?? true; await prefs.setString('kTage1', "28"); await prefs.setString('kTage2', "48"); - await prefs.setString('apiAddress', 'http://192.168.1.106/www.dbb-wolf.de/data/app24.php'); + await prefs.setString( + 'apiAddress', 'http://192.168.1.106/www.dbb-wolf.de/data/app24.php'); runApp(MyApp(isFirstLaunch: isFirstLaunch)); } @@ -30,14 +31,11 @@ class MyApp extends StatelessWidget { final bool isFirstLaunch; const MyApp({super.key, required this.isFirstLaunch}); - - @override Widget build(BuildContext context) { return MaterialApp( title: 'FFOrte', - theme: - FlexThemeData.light(scheme: FlexScheme.gold, useMaterial3: true), + theme: FlexThemeData.light(scheme: FlexScheme.gold, useMaterial3: true), darkTheme: FlexThemeData.dark(scheme: FlexScheme.greenM3, useMaterial3: true), themeMode: ThemeMode.system, @@ -55,7 +53,7 @@ class MyApp extends StatelessWidget { '/viewCams': (context) => const ViewCams(), '/introScreen': (context) => const IntroScreen(), '/settings': (context) => const Settings(), - '/excursion': (context) => const Settings(), + '/excursion': (context) => const ExcursionMain(), }, ); } diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 7531e28..8d83a49 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -101,5 +101,6 @@ "back": "Zurück", "loading": "Lädt", "test": "Test", - "notest": "Kein Test" + "notest": "Kein Test", + "dateandtime": "Datum und Zeit" } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 715fda8..8391d8f 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -494,10 +494,13 @@ "description": "no test" }, - "excursion": "Excursion", "@excursion": { "description": "no test" + }, + "dateandtime": "Date and Time", + "@dateandtime": { + "description": "date and time step header" } } \ No newline at end of file diff --git a/lib/methods/db_helper.dart b/lib/methods/db_helper.dart index d8a056e..727bb65 100644 --- a/lib/methods/db_helper.dart +++ b/lib/methods/db_helper.dart @@ -33,6 +33,9 @@ class DBHelper { 'CREATE TABLE place (ID INTEGER PRIMARY KEY AUTOINCREMENT, CID TEXT, Standort TEXT, Rudel TEXT, Datum DATE, Adresse1 TEXT, Adresse2 TEXT, Adresse3 TEXT, BLand TEXT, Lkr TEXT, BeiOrt TEXT, OrtInfo TEXT, Status TEXT, FFTyp TEXT, FotoFilm TEXT, MEZ TEXT, Platzung TEXT, KSchloNr TEXT, KontDat DATE, Betreuung TEXT, AbbauDat DATE, Auftrag TEXT, KontAbsp TEXT, SonstBem TEXT, FKontakt1 TEXT, FKontakt2 TEXT, FKontakt3 TEXT, KTage1 INTEGER, KTage2 INTEGER, ProtoAm DATE, IntKomm TEXT, DECLNG DECIMALS(4,8), DECLAT DECIMALS(4,8), Sent INTEGER DEFAULT 0)'); await placeDB.execute( 'CREATE TABLE templates (ID INTEGER PRIMARY KEY AUTOINCREMENT, CID TEXT, Standort TEXT, Rudel TEXT, Datum DATE, Adresse1 TEXT, Adresse2 TEXT, Adresse3 TEXT, BLand TEXT, Lkr TEXT, BeiOrt TEXT, OrtInfo TEXT, Status TEXT, FFTyp TEXT, FotoFilm TEXT, MEZ TEXT, Platzung TEXT, KSchloNr TEXT, KontDat DATE, Betreuung TEXT, AbbauDat DATE, Auftrag TEXT, KontAbsp TEXT, SonstBem TEXT, FKontakt1 TEXT, FKontakt2 TEXT, FKontakt3 TEXT, KTage1 INTEGER, KTage2 INTEGER, ProtoAm DATE, IntKomm TEXT, DECLNG DECIMALS(4,8), DECLAT DECIMALS(4,8))'); + await placeDB.execute( + 'CREATE TABLE excursion (ID INTEGER PRIMARY KEY AUTOINCREMENT)' + ); } // Function to add a finished entry and return its ID diff --git a/lib/screens/Excursion/excursion_main.dart b/lib/screens/Excursion/excursion_main.dart index 6ef2e0a..953667c 100644 --- a/lib/screens/Excursion/excursion_main.dart +++ b/lib/screens/Excursion/excursion_main.dart @@ -1,4 +1,5 @@ import 'package:animations/animations.dart'; +import 'package:fforte/screens/sharedWidgets/datum.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -14,15 +15,22 @@ class _ExcursionMainState extends State { Widget build(BuildContext context) { List getSteps() => [ Step( - title: const Text("step1"), - content: const Column( + title: Text(AppLocalizations.of(context)!.dateandtime), + content: Column( children: [ - Text("data"), + Datum(initDatum: DateTime.now(), + onDateChanged: (date) { + + }), + const SizedBox(height: 10,) ], )), const Step(title: Text("step2"), content: Text("data")) ]; + + + int currentStep = 0; return Scaffold( diff --git a/lib/screens/addCam/add_cam_main.dart b/lib/screens/addCam/add_cam_main.dart index 3631612..7302217 100644 --- a/lib/screens/addCam/add_cam_main.dart +++ b/lib/screens/addCam/add_cam_main.dart @@ -4,6 +4,8 @@ import 'dart:io'; import 'package:fforte/screens/addCam/cam_widgets.dart'; import 'package:fforte/methods/db_helper.dart'; import 'package:fforte/methods/http_request.dart'; +import 'package:fforte/screens/sharedWidgets/datum.dart'; +import 'package:fforte/screens/sharedWidgets/var_text_field.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; diff --git a/lib/screens/addCam/cam_widgets.dart b/lib/screens/addCam/cam_widgets.dart index 7c4d97e..66637a0 100644 --- a/lib/screens/addCam/cam_widgets.dart +++ b/lib/screens/addCam/cam_widgets.dart @@ -8,150 +8,6 @@ import 'package:latlong2/latlong.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:geocoding/geocoding.dart'; -// * Collection of All widgets displayed in the add_cam section - -class VarTextField extends StatefulWidget { - final TextEditingController textController; - final String localization; - final String dbName; - final String? defaultValue; - final String? otherDefault; - final bool required; - - const VarTextField( - {super.key, - required this.textController, - required this.localization, - required this.dbName, - required this.required, - this.defaultValue, - this.otherDefault}); - - @override - State createState() => _VarTextFieldState(); -} - -class _VarTextFieldState extends State { - late Future>> dbVar; - - @override - void initState() { - super.initState(); - - if (widget.textController.text == "" && widget.defaultValue != null) { - _loadPref(); - } - - if (widget.otherDefault != null) { - widget.textController.text = widget.otherDefault!; - } - - dbVar = _loadData(); - } - - Future>> _loadData() async { - var places = await DBHelper().getPlace(); - var templates = await DBHelper().getTemplates(); - return [...places, ...templates]; - } - - void _loadPref() { - Future.delayed(Duration.zero, () async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - String bLand = prefs.getString(widget.defaultValue!) ?? ""; - setState(() { - widget.textController.text = bLand; - }); - }); - } - - @override - Widget build(BuildContext context) { - return Row( - children: [ - Expanded( - flex: 5, - child: TextField( - controller: widget.textController, - keyboardType: TextInputType.multiline, - maxLines: null, - onChanged: (value) { - setState(() { - widget.textController.text = value; - }); - }, - decoration: InputDecoration( - hintText: widget.localization, - enabledBorder: widget.required - ? (widget.textController.text.isEmpty - ? const UnderlineInputBorder( - borderSide: BorderSide(color: Colors.red)) - : const UnderlineInputBorder( - borderSide: BorderSide(color: Colors.green))) - : const UnderlineInputBorder( - borderSide: BorderSide(color: Colors.grey)), - focusedBorder: widget.required - ? (widget.textController.text.isEmpty - ? const UnderlineInputBorder( - borderSide: BorderSide(color: Colors.red)) - : const UnderlineInputBorder( - borderSide: BorderSide(color: Colors.green))) - : const UnderlineInputBorder( - borderSide: BorderSide(color: Colors.grey))), - )), - const Expanded( - child: SizedBox( - width: 15, - ), - ), - Expanded( - flex: 1, - child: Align( - alignment: Alignment.bottomLeft, - child: FutureBuilder>>( - future: dbVar, - builder: (BuildContext context, - AsyncSnapshot>> snapshot) { - if (snapshot.hasData) { - // Filtern der Daten, um sicherzustellen, dass keine 'null' Werte für den Schlüssel dbName vorhanden sind - var filteredData = snapshot.data! - .where((item) => - item[widget.dbName] != null && - item[widget.dbName] != "") - .toList(); - - var uniqueData = { ...filteredData.map((e) => e[widget.dbName].toString())}; - - return PopupMenuButton( - onSelected: (String value) { - setState(() { - widget.textController.text = value; - }); - }, - itemBuilder: (BuildContext context) { - return uniqueData - .map((value) => PopupMenuItem( - value: value, - child: Text(value), - )) - .toList(); - }, - child: const Icon(Icons.arrow_drop_down), - ); - } else if (snapshot.hasError) { - return Text('Fehler: ${snapshot.error}'); - } else { - return const CircularProgressIndicator(); - } - }, - ), - ), - ) - ], - ); - } -} - // Karte @@ -286,82 +142,6 @@ class KarteState extends State { } } -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// - -// Datum == Datum der Aufstellung -// datum is the variable where the chosen date is stored - -class Datum extends StatefulWidget { - final DateTime? initDatum; - final Function(DateTime) onDateChanged; - - const Datum({super.key, required this.initDatum, required this.onDateChanged}); - - @override - State createState() => _DatumState(); -} - -class _DatumState extends State { - DateTime? datum; - - @override - void initState() { - super.initState(); - datum = widget.initDatum; - } - - @override - Widget build(BuildContext context) { - return Row( - children: [ - Row(children: [ - SizedBox( - width: 140, - child: ElevatedButton( - onPressed: () async { - final date = await pickDate(); - if (date == null) return; - setState(() => datum = date); - widget.onDateChanged(date); - }, - child: Text(AppLocalizations.of(context)!.pickDate)), - ), - const SizedBox( - width: 10, - ), - Text( - '${datum?.day}. ${datum?.month}. ${datum?.year}', - ), - ]), - ], - ); - } - - Future pickDate() async { - final date = await showDatePicker( - context: context, - initialDate: datum!, - firstDate: DateTime(2000), - lastDate: DateTime(5000)); - - return date; - } -} - // Status class Status extends StatefulWidget { diff --git a/lib/screens/sharedWidgets/datum.dart b/lib/screens/sharedWidgets/datum.dart new file mode 100644 index 0000000..5f964f6 --- /dev/null +++ b/lib/screens/sharedWidgets/datum.dart @@ -0,0 +1,60 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + + +class Datum extends StatefulWidget { + final DateTime? initDatum; + final Function(DateTime) onDateChanged; + + const Datum({super.key, required this.initDatum, required this.onDateChanged}); + + @override + State createState() => _DatumState(); +} + +class _DatumState extends State { + DateTime? datum; + + @override + void initState() { + super.initState(); + datum = widget.initDatum; + } + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Row(children: [ + SizedBox( + width: 140, + child: ElevatedButton( + onPressed: () async { + final date = await pickDate(); + if (date == null) return; + setState(() => datum = date); + widget.onDateChanged(date); + }, + child: Text(AppLocalizations.of(context)!.pickDate)), + ), + const SizedBox( + width: 10, + ), + Text( + '${datum?.day}. ${datum?.month}. ${datum?.year}', + ), + ]), + ], + ); + } + + Future pickDate() async { + final date = await showDatePicker( + context: context, + initialDate: datum!, + firstDate: DateTime(2000), + lastDate: DateTime(5000)); + + return date; + } +} diff --git a/lib/screens/sharedWidgets/var_text_field.dart b/lib/screens/sharedWidgets/var_text_field.dart new file mode 100644 index 0000000..1d6c5bc --- /dev/null +++ b/lib/screens/sharedWidgets/var_text_field.dart @@ -0,0 +1,146 @@ +import 'package:fforte/methods/db_helper.dart'; +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + + +class VarTextField extends StatefulWidget { + final TextEditingController textController; + final String localization; + final String dbName; + final String? defaultValue; + final String? otherDefault; + final bool required; + + const VarTextField( + {super.key, + required this.textController, + required this.localization, + required this.dbName, + required this.required, + this.defaultValue, + this.otherDefault}); + + @override + State createState() => _VarTextFieldState(); +} + +class _VarTextFieldState extends State { + late Future>> dbVar; + + @override + void initState() { + super.initState(); + + if (widget.textController.text == "" && widget.defaultValue != null) { + _loadPref(); + } + + if (widget.otherDefault != null) { + widget.textController.text = widget.otherDefault!; + } + + dbVar = _loadData(); + } + + Future>> _loadData() async { + var places = await DBHelper().getPlace(); + var templates = await DBHelper().getTemplates(); + return [...places, ...templates]; + } + + void _loadPref() { + Future.delayed(Duration.zero, () async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + String bLand = prefs.getString(widget.defaultValue!) ?? ""; + setState(() { + widget.textController.text = bLand; + }); + }); + } + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Expanded( + flex: 5, + child: TextField( + controller: widget.textController, + keyboardType: TextInputType.multiline, + maxLines: null, + onChanged: (value) { + setState(() { + widget.textController.text = value; + }); + }, + decoration: InputDecoration( + hintText: widget.localization, + enabledBorder: widget.required + ? (widget.textController.text.isEmpty + ? const UnderlineInputBorder( + borderSide: BorderSide(color: Colors.red)) + : const UnderlineInputBorder( + borderSide: BorderSide(color: Colors.green))) + : const UnderlineInputBorder( + borderSide: BorderSide(color: Colors.grey)), + focusedBorder: widget.required + ? (widget.textController.text.isEmpty + ? const UnderlineInputBorder( + borderSide: BorderSide(color: Colors.red)) + : const UnderlineInputBorder( + borderSide: BorderSide(color: Colors.green))) + : const UnderlineInputBorder( + borderSide: BorderSide(color: Colors.grey))), + )), + const Expanded( + child: SizedBox( + width: 15, + ), + ), + Expanded( + flex: 1, + child: Align( + alignment: Alignment.bottomLeft, + child: FutureBuilder>>( + future: dbVar, + builder: (BuildContext context, + AsyncSnapshot>> snapshot) { + if (snapshot.hasData) { + // Filtern der Daten, um sicherzustellen, dass keine 'null' Werte für den Schlüssel dbName vorhanden sind + var filteredData = snapshot.data! + .where((item) => + item[widget.dbName] != null && + item[widget.dbName] != "") + .toList(); + + var uniqueData = { ...filteredData.map((e) => e[widget.dbName].toString())}; + + return PopupMenuButton( + onSelected: (String value) { + setState(() { + widget.textController.text = value; + }); + }, + itemBuilder: (BuildContext context) { + return uniqueData + .map((value) => PopupMenuItem( + value: value, + child: Text(value), + )) + .toList(); + }, + child: const Icon(Icons.arrow_drop_down), + ); + } else if (snapshot.hasError) { + return Text('Fehler: ${snapshot.error}'); + } else { + return const CircularProgressIndicator(); + } + }, + ), + ), + ) + ], + ); + } +}