import 'package:fforte/other/db_helper.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:geolocator/geolocator.dart'; 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 // ! completely new page class Karte extends StatefulWidget { final TextEditingController beiOrtC; final TextEditingController ortInfoC; final Position currentPosition; final Function(Position) onPositionChange; const Karte( {super.key, required this.currentPosition, required this.onPositionChange, required this.beiOrtC, required this.ortInfoC}); @override KarteState createState() => KarteState(); } class KarteState extends State { List markers = []; LatLng? selectedPosition; Position? updatedPosition; bool saveVisible = false; @override void initState() { super.initState(); markers = [ Marker( point: LatLng(widget.currentPosition.latitude, widget.currentPosition.longitude), child: const Icon( Icons.location_on, color: Colors.red, )) ]; } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.map), actions: [ Visibility( visible: saveVisible, child: Row( children: [ Text(AppLocalizations.of(context)!.saveMap), TextButton( onPressed: () async { List placemarks = await placemarkFromCoordinates( selectedPosition!.latitude, selectedPosition!.longitude); // print(placemarks); if (selectedPosition != null) { setState(() { widget.beiOrtC.text = placemarks.first.locality!; widget.ortInfoC.text = placemarks.first.street!; updatedPosition = Position( longitude: selectedPosition!.longitude, latitude: selectedPosition!.latitude, timestamp: DateTime.now(), accuracy: 0.0, altitude: 0.0, altitudeAccuracy: 0.0, heading: 0.0, headingAccuracy: 0.0, speed: 0.0, speedAccuracy: 0.0); widget.onPositionChange(updatedPosition!); }); } // ignore: use_build_context_synchronously Navigator.pop(context); }, child: const Icon(Icons.save), ), ], ), ), ], ), body: FlutterMap( mapController: MapController(), options: MapOptions( interactionOptions: const InteractionOptions( flags: InteractiveFlag.pinchZoom | InteractiveFlag.drag | InteractiveFlag.pinchMove), initialCenter: LatLng(widget.currentPosition.latitude, widget.currentPosition.longitude), initialZoom: 16.0, onTap: _handleTap, ), children: [ TileLayer( urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', userAgentPackageName: 'com.example.app', ), MarkerLayer(markers: markers), ]), ); } _handleTap(TapPosition position, LatLng latlng) { setState(() { markers.clear(); markers.add( Marker( width: 80.0, height: 80.0, point: latlng, child: const Icon( Icons.location_on, color: Colors.red, ), ), ); selectedPosition = latlng; saveVisible = true; }); ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text( "${AppLocalizations.of(context)!.markerSet}\n${selectedPosition!.latitude}\n${selectedPosition!.longitude}"))); } } // // // // // // // // // // // // // // // // 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 { final Function(String) onStatusChanged; final String initialStatus; const Status( {super.key, required this.onStatusChanged, this.initialStatus = 'Aktiv'}); @override State createState() => _StatusState(); } class _StatusState extends State { String? _selectedStatus; @override void initState() { super.initState(); _selectedStatus = widget.initialStatus; } @override Widget build(BuildContext context) { return Column( children: [ ListTile( visualDensity: const VisualDensity(vertical: -4), title: Text(AppLocalizations.of(context)!.aktiv), leading: Radio( value: 'aktiv', groupValue: _selectedStatus, onChanged: (value) { setState(() { _selectedStatus = value; widget.onStatusChanged(value!); }); }, ), ), ListTile( visualDensity: const VisualDensity(vertical: -4), title: Text(AppLocalizations.of(context)!.inaktiv), leading: Radio( value: 'inaktiv', groupValue: _selectedStatus, onChanged: (value) { setState(() { _selectedStatus = value; widget.onStatusChanged(value!); }); }, ), ), ], ); } } // STTyp class STTyp extends StatefulWidget { final Function(String) onSTTypChanged; final String initialSTTyp; const STTyp( {super.key, required this.onSTTypChanged, this.initialSTTyp = 'opportunistisch'}); @override State createState() => _STTypState(); } class _STTypState extends State { String? _selectedSTTyp; @override void initState() { super.initState(); _selectedSTTyp = widget.initialSTTyp; } @override Widget build(BuildContext context) { return Column( children: [ ListTile( visualDensity: const VisualDensity(vertical: -4), title: Text(AppLocalizations.of(context)!.opportunistisch), leading: Radio( value: 'opportunistisch', groupValue: _selectedSTTyp, onChanged: (value) { setState(() { _selectedSTTyp = value; widget.onSTTypChanged(value!); }); }, ), ), ListTile( visualDensity: const VisualDensity(vertical: -4), title: Text(AppLocalizations.of(context)!.systematisch), leading: Radio( value: 'systematisch', groupValue: _selectedSTTyp, onChanged: (value) { setState(() { _selectedSTTyp = value; widget.onSTTypChanged(value!); }); }, ), ), ], ); } } // platzung class Platzung extends StatefulWidget { final Function(String) onPlatzungChanged; final String? initialPlatzung; const Platzung({ super.key, required this.onPlatzungChanged, this.initialPlatzung, }); @override State createState() => _PlatzungState(); } class _PlatzungState extends State { String? _selectedPlatzung; @override void initState() { super.initState(); if (widget.initialPlatzung != "") { _selectedPlatzung = widget.initialPlatzung; } } @override Widget build(BuildContext context) { return Column( children: [ ListTile( visualDensity: const VisualDensity(vertical: -4), title: Text(AppLocalizations.of(context)!.kirrung), leading: Radio( value: 'Kirrung', groupValue: _selectedPlatzung, onChanged: (value) { setState(() { _selectedPlatzung = value; widget.onPlatzungChanged(value!); }); }, ), ), ListTile( visualDensity: const VisualDensity(vertical: -4), title: Text(AppLocalizations.of(context)!.wasserstelle), leading: Radio( value: 'Wasserstelle', groupValue: _selectedPlatzung, onChanged: (value) { setState(() { _selectedPlatzung = value; widget.onPlatzungChanged(value!); }); }, ), ), ListTile( visualDensity: const VisualDensity(vertical: -4), title: Text(AppLocalizations.of(context)!.wald), leading: Radio( value: 'Wald', groupValue: _selectedPlatzung, onChanged: (value) { setState(() { _selectedPlatzung = value; widget.onPlatzungChanged(value!); }); }, ), ), ListTile( visualDensity: const VisualDensity(vertical: -4), title: Text(AppLocalizations.of(context)!.wildwechsel), leading: Radio( value: 'Wildwechsel', groupValue: _selectedPlatzung, onChanged: (value) { setState(() { _selectedPlatzung = value; widget.onPlatzungChanged(value!); }); }, ), ), ListTile( visualDensity: const VisualDensity(vertical: -4), title: Text(AppLocalizations.of(context)!.wegstrasse), leading: Radio( value: 'Weg/Straße', groupValue: _selectedPlatzung, onChanged: (value) { setState(() { _selectedPlatzung = value; widget.onPlatzungChanged(value!); }); }, ), ), ListTile( visualDensity: const VisualDensity(vertical: -4), title: Text(AppLocalizations.of(context)!.hofgarten), leading: Radio( value: 'Hof/Garten', groupValue: _selectedPlatzung, onChanged: (value) { setState(() { _selectedPlatzung = value; widget.onPlatzungChanged(value!); }); }, ), ), ListTile( visualDensity: const VisualDensity(vertical: -4), title: Text(AppLocalizations.of(context)!.wiesefeld), leading: Radio( value: 'Wiese/Feld/Offenfläche', groupValue: _selectedPlatzung, onChanged: (value) { setState(() { _selectedPlatzung = value; widget.onPlatzungChanged(value!); }); }, ), ), ], ); } } // FotoFilm class FotoFilm extends StatefulWidget { final Function(String) onFotoFilmChanged; final String initialFotoFilm; const FotoFilm( {super.key, required this.onFotoFilmChanged, this.initialFotoFilm = 'foto'}); @override State createState() => _FotoFilmState(); } class _FotoFilmState extends State { String? _selectedFotoFilm; @override void initState() { super.initState(); _selectedFotoFilm = widget.initialFotoFilm; } @override Widget build(BuildContext context) { return Column( children: [ ListTile( visualDensity: const VisualDensity(vertical: -4), title: Text(AppLocalizations.of(context)!.foto), leading: Radio( value: 'Foto', groupValue: _selectedFotoFilm, onChanged: (value) { setState(() { _selectedFotoFilm = value; widget.onFotoFilmChanged(value!); }); }, ), ), ListTile( visualDensity: const VisualDensity(vertical: -4), title: Text(AppLocalizations.of(context)!.film), leading: Radio( value: 'Film', groupValue: _selectedFotoFilm, onChanged: (value) { setState(() { _selectedFotoFilm = value; widget.onFotoFilmChanged(value!); }); }, ), ), ], ); } } // MEZ class MEZ extends StatefulWidget { final Function(String) onMEZChanged; final String initialMEZ; const MEZ( {super.key, required this.onMEZChanged, this.initialMEZ = 'sommerzeit'}); @override State createState() => _MEZState(); } class _MEZState extends State { String? _selectedMEZ; @override void initState() { super.initState(); _selectedMEZ = widget.initialMEZ; } @override Widget build(BuildContext context) { return Column( children: [ ListTile( visualDensity: const VisualDensity(vertical: -4), title: Text(AppLocalizations.of(context)!.sommerzeit), leading: Radio( value: 'Sommerzeit', groupValue: _selectedMEZ, onChanged: (value) { setState(() { _selectedMEZ = value; widget.onMEZChanged(value!); }); }, ), ), ListTile( visualDensity: const VisualDensity(vertical: -4), title: Text(AppLocalizations.of(context)!.winterzeit), leading: Radio( value: 'Winterzeit', groupValue: _selectedMEZ, onChanged: (value) { setState(() { _selectedMEZ = value; widget.onMEZChanged(value!); }); }, ), ), ], ); } } // KontDat class KontDat extends StatefulWidget { final DateTime? initKontDat; final Function(DateTime) onDateChanged; const KontDat( {super.key, required this.initKontDat, required this.onDateChanged}); @override State createState() => _KontDatState(); } class _KontDatState extends State { DateTime? kontDat; @override void initState() { super.initState(); kontDat = widget.initKontDat; } @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(() { kontDat = date; }); widget.onDateChanged(date); }, child: Text(AppLocalizations.of(context)!.pickkontdat)), ), const SizedBox( width: 10, ), Text( '${kontDat?.day}. ${kontDat?.month}. ${kontDat?.year}', ), ]), ], ); } Future pickDate() async { final date = await showDatePicker( context: context, initialDate: kontDat ?? DateTime.now(), firstDate: DateTime(2000), lastDate: DateTime(5000)); return date; } } // AbbauDat class AbbauDat extends StatefulWidget { final DateTime? initAbbauDat; final Function(DateTime) onDateChanged; const AbbauDat({super.key, required this.initAbbauDat, required this.onDateChanged}); @override State createState() => _AbbauDatState(); } class _AbbauDatState extends State { DateTime? abbauDat; @override void initState() { super.initState(); abbauDat = widget.initAbbauDat; } @override Widget build(BuildContext context) { return Row( children: [ Column(children: [ SizedBox( width: 140, child: ElevatedButton( onPressed: () async { final date = await pickDate(); if (date == null) return; setState(() => abbauDat = date); widget.onDateChanged(date); }, child: Text(AppLocalizations.of(context)!.pickabbaudat)), ), Row( children: [ const SizedBox( width: 10, ), Builder(builder: (context) { if (abbauDat != null) { return Text( '${abbauDat?.day}. ${abbauDat?.month}. ${abbauDat?.year}'); } else { return Text(AppLocalizations.of(context)!.nichts); } }), const SizedBox( width: 10, ), ElevatedButton( onPressed: () { setState(() { abbauDat = null; }); }, child: const Text("X")) ]), ], ) ], ); } Future pickDate() async { final date = await showDatePicker( context: context, initialDate: DateTime.now(), firstDate: DateTime(2000), lastDate: DateTime(5000)); if (date == null) return null; return date; } }