Files
fforte/lib/screens/addCam/add_cam_main.dart
Nico ecafe2df02 added sent and id column again for add_cam_main
id checks if entry already exists. sent says if the entry is already
sent to the db
2025-05-12 18:18:36 +02:00

653 lines
23 KiB
Dart

import 'package:fforte/enums/databases.dart';
import 'package:fforte/screens/helper/add_entries_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 = {
"ID": {"controller": TextEditingController(), "required": false},
// 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},
"Sent": {"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
if (widget.existingData?.isNotEmpty ?? false) {
for (var key in widget.existingData!.keys) {
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);
// TODO for debugging always true
empty = false;
if (empty == true) {
AddEntriesDialogHelper.showTemplateDialog(
context,
getFieldsText(),
widget.existingData?.isNotEmpty ?? false,
);
return;
} else if (empty == false) {
await AddEntriesDialogHelper.showSaveOptionsDialog(
context,
getFieldsText(),
widget.isTemplate,
DatabasesEnum.place,
);
}
}
},
onStepCancel: () {
if (currentStep == 0) {
Navigator.pop(context);
} else {
setState(() {
currentStep -= 1;
});
}
},
),
),
);
}
}