Files
fforte/lib/screens/addCam/add_cam_main.dart
Nico d96d7b2f5d migrated localization
update l10n.yaml
2025-05-10 23:28:56 +02:00

761 lines
26 KiB
Dart

import 'package:fforte/enums/databases.dart';
import 'package:fforte/screens/helper/dialog_helper.dart';
import 'package:fforte/screens/helper/snack_bar_helper.dart';
import 'package:fforte/screens/addCam/exceptions/location_disabled_exception.dart';
import 'package:fforte/screens/addCam/exceptions/location_forbidden_exception.dart';
import 'package:fforte/screens/addCam/services/geolocator_service.dart';
import 'package:fforte/screens/sharedMethods/check_required.dart';
import 'package:fforte/screens/sharedMethods/save_template.dart';
import 'package:fforte/screens/sharedWidgets/datum.dart';
import 'package:fforte/screens/sharedWidgets/var_text_field.dart';
import 'package:flutter/material.dart';
import 'package:fforte/l10n/app_localizations.dart';
import 'package:geolocator/geolocator.dart';
import 'package:latlong2/latlong.dart';
import 'package:animations/animations.dart';
import 'widgets/abbau_dat.dart';
import 'widgets/karte.dart';
import 'widgets/kont_dat.dart';
import 'widgets/mez.dart';
import 'widgets/platzung.dart';
import 'widgets/status.dart';
class AddCamMain extends StatefulWidget {
final bool isTemplate;
final bool isFinished;
final bool isSent;
final Map<String, dynamic>? existingData;
const AddCamMain(
{super.key,
this.isTemplate = false,
this.existingData,
this.isFinished = false,
this.isSent = false});
@override
State<AddCamMain> createState() => _AddCamMainState();
}
class _AddCamMainState extends State<AddCamMain> {
// var declaration
int currentStep = 0;
String selectedStatus = 'aktiv';
String selectedFotoFilm = 'Foto';
String selectedMEZ = 'Sommerzeit';
String selectedPlatzung = '';
Position currentPosition = Position(
longitude: 10.0,
latitude: 51.0,
timestamp: DateTime.now(),
accuracy: 0.0,
altitude: 0.0,
heading: 0.0,
speed: 0.0,
speedAccuracy: 0.0,
altitudeAccuracy: 0.0,
headingAccuracy: 0.0);
DateTime? abbauDat;
DateTime datum = DateTime.now();
DateTime? kontDat = DateTime.now();
DateTime? protoAm = DateTime.now();
Map<String, Map<String, dynamic>> rmap = {
// Step 1
"Standort": {
"controller": TextEditingController(),
"required": true,
},
"Status": {
"controller": TextEditingController(),
"required": true,
},
"Betreuung": {
"controller": TextEditingController(),
"required": false,
},
"CID": {
"controller": TextEditingController(),
"required": true,
},
"FFTyp": {
"controller": TextEditingController(),
"required": true,
},
"MEZ": {
"controller": TextEditingController(),
"required": true,
},
"KSchloNr": {
"controller": TextEditingController(),
"required": false,
},
"Rudel": {
"controller": TextEditingController(),
"required": true,
},
// Step 2
"DECLNG": {
"controller": TextEditingController(),
"required": false,
},
"DECLAT": {
"controller": TextEditingController(),
"required": false,
},
"BLand": {
"controller": TextEditingController(),
"required": true,
},
"Lkr": {
"controller": TextEditingController(),
"required": true,
},
"BeiOrt": {
"controller": TextEditingController(),
"required": true,
},
"OrtInfo": {
"controller": TextEditingController(),
"required": false,
},
"Platzung": {
"controller": TextEditingController(),
"required": true,
},
// Step 3
"Datum": {
"controller": TextEditingController(),
"required": false,
},
"KontDat": {
"controller": TextEditingController(),
"required": false,
},
"KTage1": {
"controller": TextEditingController(),
"required": true,
},
"KTage2": {
"controller": TextEditingController(),
"required": true,
},
"AbbauDat": {
"controller": TextEditingController(),
"required": false,
},
"Auftrag": {
"controller": TextEditingController(),
"required": false,
},
"KontAbsp": {
"controller": TextEditingController(),
"required": false,
},
"SonstBem": {
"controller": TextEditingController(),
"required": false,
},
// Step 4
"Adresse1": {
"controller": TextEditingController(),
"required": true,
},
"Adresse2": {
"controller": TextEditingController(),
"required": false,
},
"Adresse3": {
"controller": TextEditingController(),
"required": false,
},
"FKontakt1": {
"controller": TextEditingController(),
"required": false,
},
"FKontakt2": {
"controller": TextEditingController(),
"required": false,
},
"FKontakt3": {
"controller": TextEditingController(),
"required": false,
},
"IntKomm": {
"controller": TextEditingController(),
"required": false,
},
// Gone?
"ProtoAm": {
"controller": TextEditingController(),
"required": false,
},
"FotoFilm": {
"controller": TextEditingController(),
"required": false,
},
};
Map<String, String> getFieldsText() {
Map<String, String> puff = {};
for (var itemKey in rmap.keys) {
puff[itemKey] = rmap[itemKey]!["controller"]!.text;
}
return puff;
}
@override
void initState() {
// updates the currentPosition var after the _determine position has finished. Means user view updates with his live location
GeolocatorService.deteterminePosition()
.then((result) => currentPosition = result)
.catchError((error) {
if (error is LocationDisabledException) {
if (mounted) {
SnackBarHelper.showSnackBarMessage(
context, AppLocalizations.of(context)!.locationDisabled);
}
} else if (error is LocationForbiddenException) {
if (mounted) {
SnackBarHelper.showSnackBarMessage(
context, AppLocalizations.of(context)!.locationForbidden);
}
}
return currentPosition;
});
// select initial werte
rmap["MEZ"]!["controller"]!.text = selectedMEZ;
rmap["Status"]!["controller"]!.text = selectedStatus;
// If a template is edited this fills in the existing values
var firstRun = true;
if (widget.existingData?.isNotEmpty ?? false) {
for (var key in widget.existingData!.keys) {
if (firstRun) {
firstRun = false;
continue;
}
rmap[key]!["controller"]!.text =
widget.existingData?[key].toString() ?? "";
}
}
super.initState();
}
@override
void dispose() {
for (String key in rmap.keys) {
rmap[key]!["controller"].dispose();
}
super.dispose();
}
// The widget tree which gets the shown widget from the ./cam_widgets.dart file
// The names of the widgets should be self-explaining
@override
Widget build(BuildContext context) {
// List with the steps. The steps itself will be "shown" later
List<Step> getSteps() => [
// First step
Step(
title: Text(AppLocalizations.of(context)!.firststep),
content: Column(
children: [
Align(
alignment: Alignment.bottomLeft,
child: VarTextField(
required: true,
dbName: "Standort",
textController: rmap["Standort"]!["controller"]!,
// textController: betreuungC,
localization: AppLocalizations.of(context)!.altstort,
dbDesignation: DatabasesEnum.place,
),
),
const SizedBox(
height: 5,
),
// --------------------
Align(
alignment: Alignment.bottomLeft,
child: Row(
children: [
Text(AppLocalizations.of(context)!.status),
const Text(
'*',
style: TextStyle(color: Colors.red),
),
],
)),
Status(
initialStatus: selectedStatus,
onStatusChanged: (status) {
setState(() {
rmap["Status"]!["controller"]!.text = status;
});
},
),
// --------------------
VarTextField(
textController: rmap["Betreuung"]!["controller"]!,
localization: AppLocalizations.of(context)!.betreuung,
dbName: "Betreuung",
required: false,
dbDesignation: DatabasesEnum.place,
),
const SizedBox(
height: 20,
),
// --------------------
VarTextField(
textController: rmap["CID"]!["controller"],
localization: AppLocalizations.of(context)!.camLink,
dbName: "CID",
required: true,
dbDesignation: DatabasesEnum.place,
),
// --------------------
VarTextField(
textController: rmap["FFTyp"]!["controller"],
localization: AppLocalizations.of(context)!.fftyp,
dbName: "FFTyp",
required: true,
dbDesignation: DatabasesEnum.place,
),
const SizedBox(
height: 15,
),
// --------------------
Align(
alignment: Alignment.bottomLeft,
child: Row(
children: [
Text(AppLocalizations.of(context)!.zeiteinstellung),
const Text(
'*',
style: TextStyle(color: Colors.red),
)
],
)),
MEZ(
initialMEZ: selectedMEZ,
onMEZChanged: (mez) {
setState(() {
selectedMEZ = mez;
rmap["MEZ"]!["controller"]!.text = mez;
});
},
),
const SizedBox(
height: 15,
),
// --------------------
VarTextField(
textController: rmap["KSchloNr"]!["controller"],
localization: AppLocalizations.of(context)!.kschlonr,
dbName: "KSchloNr",
required: false,
dbDesignation: DatabasesEnum.place,
),
const SizedBox(
height: 5,
),
// --------------------
VarTextField(
textController: rmap["Rudel"]!["controller"],
localization: AppLocalizations.of(context)!.rudel,
dbName: "Rudel",
required: true,
dbDesignation: DatabasesEnum.place,
),
const SizedBox(
height: 15,
),
],
)),
// Second step
Step(
title: Text(AppLocalizations.of(context)!.secondstep),
content: Column(
children: [
Row(
children: [
Column(
children: [
Text(currentPosition.latitude.toString()),
Text(currentPosition.longitude.toString()),
],
),
const SizedBox(
width: 15,
),
ElevatedButton(
onPressed: () async {
final result = await Navigator.of(context)
.push<LatLng>(
MaterialPageRoute(builder: (context) {
return Karte(
ortInfoC: rmap["OrtInfo"]!["controller"],
beiOrtC: rmap["BeiOrt"]!["controller"],
currentPosition: currentPosition,
decLatC: rmap["DECLAT"]!["controller"],
decLngC: rmap["DECLNG"]!["controller"],
);
}));
if (result != null) {
setState(() {
currentPosition = Position(
latitude: result.latitude,
longitude: result.longitude,
timestamp: DateTime.now(),
accuracy: 0.0,
altitude: 0.0,
altitudeAccuracy: 0.0,
heading: 0.0,
headingAccuracy: 0.0,
speed: 0.0,
speedAccuracy: 0.0,
);
});
}
},
child: Text(AppLocalizations.of(context)!.openMap)),
],
),
// --------------------
VarTextField(
textController: rmap["BLand"]!["controller"]!,
localization: AppLocalizations.of(context)!.bland,
dbName: "BLand",
required: true,
dbDesignation: DatabasesEnum.place,
defaultValue: "bLand",
),
// --------------------
VarTextField(
textController: rmap["Lkr"]!["controller"]!,
localization: AppLocalizations.of(context)!.lkr,
dbName: "Lkr",
required: true,
dbDesignation: DatabasesEnum.place,
),
// --------------------
VarTextField(
textController: rmap["BeiOrt"]!["controller"]!,
localization: AppLocalizations.of(context)!.beiort,
dbName: "BeiOrt",
required: true,
dbDesignation: DatabasesEnum.place,
),
// --------------------
VarTextField(
textController: rmap["OrtInfo"]!["controller"]!,
localization: AppLocalizations.of(context)!.ortinfo,
dbName: "OrtInfo",
required: false,
dbDesignation: DatabasesEnum.place,
),
const SizedBox(
height: 15,
),
// --------------------
Align(
alignment: Alignment.bottomLeft,
child: Row(
children: [
Text(AppLocalizations.of(context)!.platzung),
const Text(
'*',
style: TextStyle(color: Colors.red),
)
],
)),
Platzung(
initialPlatzung: selectedPlatzung,
onPlatzungChanged: (platzung) {
setState(() {
selectedPlatzung = platzung;
rmap["Platzung"]!["controller"]!.text = platzung;
});
},
),
],
)),
// Third step
Step(
title: Text(AppLocalizations.of(context)!.thirdstep),
content: Column(
children: [
Datum(
initDatum: datum,
onDateChanged: (value) {
datum = value;
rmap["Datum"]!["controller"]!.text =
value.toString().split(" ").first;
},
name: AppLocalizations.of(context)!.pickDate,
),
// --------------------
KontDat(
initKontDat: kontDat,
onDateChanged: (value) {
setState(() {
kontDat = value;
rmap["KontDat"]!["controller"]!.text =
value.toString().split(" ").first;
});
},
),
const SizedBox(
height: 20,
),
// --------------------
Align(
alignment: Alignment.bottomLeft,
child: Row(
children: [
Text(AppLocalizations.of(context)!.ktage),
const Text(
'*',
style: TextStyle(color: Colors.red),
),
],
),
),
Row(
children: [
Expanded(
child: Text(AppLocalizations.of(context)!.ktage1)),
const SizedBox(
width: 15,
),
Expanded(
flex: 4,
child: VarTextField(
otherDefault: "24",
textController: rmap["KTage1"]!["controller"]!,
localization: AppLocalizations.of(context)!.ktage1,
dbName: "KTage1",
required: true,
dbDesignation: DatabasesEnum.place,
))
],
),
Row(
children: [
Expanded(
child: Text(AppLocalizations.of(context)!.ktage2)),
const SizedBox(
width: 15,
),
Expanded(
flex: 4,
child: VarTextField(
otherDefault: "48",
textController: rmap["KTage2"]!["controller"]!,
localization: AppLocalizations.of(context)!.ktage2,
dbName: "KTage2",
required: true,
dbDesignation: DatabasesEnum.place,
))
],
),
const SizedBox(
height: 20,
),
// --------------------
Row(
children: [
AbbauDat(
initAbbauDat: abbauDat,
onDateChanged: (value) {
abbauDat = value;
rmap["AbbauDat"]!["controller"]!.text =
value.toString().split(" ").first;
},
),
],
),
const SizedBox(
height: 20,
),
// --------------------
VarTextField(
textController: rmap["Auftrag"]!["controller"]!,
localization: AppLocalizations.of(context)!.auftrag,
dbName: "Auftrag",
required: false,
dbDesignation: DatabasesEnum.place,
),
// --------------------
VarTextField(
textController: rmap["KontAbsp"]!["controller"]!,
localization: AppLocalizations.of(context)!.kontabsp,
dbName: "KontAbsp",
required: false,
dbDesignation: DatabasesEnum.place,
),
// --------------------
VarTextField(
textController: rmap["SonstBem"]!["controller"]!,
localization:
AppLocalizations.of(context)!.sonstbemerkungen,
dbName: "SonstBem",
dbDesignation: DatabasesEnum.place,
required: false),
],
)),
// Fourth step
Step(
title: Text(AppLocalizations.of(context)!.fourthstep),
content: Column(
children: [
VarTextField(
textController: rmap["Adresse1"]!["controller"]!,
localization: AppLocalizations.of(context)!.adresse1,
dbName: "Adresse1",
dbDesignation: DatabasesEnum.place,
required: true,
defaultValue: "addresse1",
),
// --------------------
VarTextField(
textController: rmap["Adresse2"]!["controller"]!,
localization: AppLocalizations.of(context)!.adresse2,
dbName: "Adresse2",
required: false,
dbDesignation: DatabasesEnum.place,
),
// --------------------
VarTextField(
textController: rmap["Adresse3"]!["controller"]!,
localization: AppLocalizations.of(context)!.adresse3,
dbName: "Adresse3",
required: false,
dbDesignation: DatabasesEnum.place,
),
const SizedBox(
height: 15,
),
// --------------------
VarTextField(
textController: rmap["FKontakt1"]!["controller"]!,
localization: AppLocalizations.of(context)!.fkontakt1,
dbName: "FKontakt1",
required: false,
dbDesignation: DatabasesEnum.place,
),
// --------------------
VarTextField(
textController: rmap["FKontakt2"]!["controller"]!,
localization: AppLocalizations.of(context)!.fkontakt2,
dbName: "FKontakt2",
required: false,
dbDesignation: DatabasesEnum.place,
),
// --------------------
VarTextField(
textController: rmap["FKontakt3"]!["controller"]!,
localization: AppLocalizations.of(context)!.fkontakt3,
dbName: "FKontakt3",
required: false,
dbDesignation: DatabasesEnum.place,
),
// --------------------
VarTextField(
textController: rmap["IntKomm"]!["controller"]!,
localization: AppLocalizations.of(context)!.intkomm,
dbName: "IntKomm",
required: false,
dbDesignation: DatabasesEnum.place,
),
],
))
];
// Here the site is built with the steps from above
return Scaffold(
appBar: AppBar(title: Text(AppLocalizations.of(context)!.addplace)),
body: PageTransitionSwitcher(
duration: const Duration(milliseconds: 800),
transitionBuilder: (Widget child, Animation<double> animation,
Animation<double> secondaryAnimation) {
return SharedAxisTransition(
animation: animation,
secondaryAnimation: secondaryAnimation,
transitionType: SharedAxisTransitionType.vertical,
child: child,
);
},
child: Stepper(
key: ValueKey<int>(currentStep),
type: StepperType.vertical,
steps: getSteps(),
// Functions that handle the navigation through the steps
currentStep: currentStep,
onStepTapped: (value) {
setState(() {
currentStep = value;
});
},
onStepContinue: () async {
final isLastStep = currentStep == getSteps().length - 1;
if (!isLastStep) {
saveTemplate(
getFieldsText(), DatabasesEnum.place, widget.isTemplate);
setState(() {
currentStep += 1;
});
} else {
// ! always filled out
if (widget.isSent) {
Navigator.pushNamedAndRemoveUntil(
context, '/home', (route) => false);
return;
}
bool empty = CheckRequired.checkRequired(rmap);
if (empty == true) {
DialogHelper.showTemplateDialog(context, getFieldsText(),
widget.existingData?.isNotEmpty ?? false);
return;
} else if (empty == false) {
await DialogHelper.showSaveOptionsDialog(
context, getFieldsText(), widget.isTemplate);
}
}
},
onStepCancel: () {
if (currentStep == 0) {
Navigator.pop(context);
} else {
setState(() {
currentStep -= 1;
});
}
},
),
),
);
}
}