server things

This commit is contained in:
nico
2024-05-15 19:59:10 +02:00
parent 3528e2ee6c
commit 1656ffb00c
7 changed files with 200 additions and 145 deletions

View File

@@ -15,13 +15,15 @@ import 'package:shared_preferences/shared_preferences.dart';
class AddCamMain extends StatefulWidget { class AddCamMain extends StatefulWidget {
final bool isTemplate; final bool isTemplate;
final bool isFinished; final bool isFinished;
final bool isSent;
final Map<String, dynamic>? existingData; final Map<String, dynamic>? existingData;
const AddCamMain( const AddCamMain(
{super.key, {super.key,
this.isTemplate = false, this.isTemplate = false,
this.existingData, this.existingData,
this.isFinished = false}); this.isFinished = false,
this.isSent = false});
@override @override
State<AddCamMain> createState() => _AddCamMainState(); State<AddCamMain> createState() => _AddCamMainState();
@@ -121,9 +123,6 @@ class _AddCamMainState extends State<AddCamMain> {
// determine live position with checks for denied permission and turned off location service // determine live position with checks for denied permission and turned off location service
Future<Position> _deteterminePosition() async { Future<Position> _deteterminePosition() async {
bool locationEnabled; bool locationEnabled;
LocationPermission permissionGiven; LocationPermission permissionGiven;
@@ -182,10 +181,10 @@ class _AddCamMainState extends State<AddCamMain> {
selectedPlatzung = widget.existingData!['Platzung'] ?? ""; selectedPlatzung = widget.existingData!['Platzung'] ?? "";
kSchloNrC.text = widget.existingData!['KSchloNr'] ?? ""; kSchloNrC.text = widget.existingData!['KSchloNr'] ?? "";
datum = DateTime.parse(widget.existingData!['Datum']); datum = DateTime.parse(widget.existingData!['Datum']);
kontDat = widget.existingData!['KontDat'] == null kontDat = widget.existingData!['KontDat'] == ""
? null ? null
: DateTime.parse(widget.existingData!['KontDat']); : DateTime.parse(widget.existingData!['KontDat']);
abbauDat = widget.existingData!['AbbauDat'] == null abbauDat = widget.existingData!['AbbauDat'] == ""
? null ? null
: DateTime.parse(widget.existingData!['AbbauDat']); : DateTime.parse(widget.existingData!['AbbauDat']);
auftragC.text = widget.existingData!['Auftrag'] ?? ""; auftragC.text = widget.existingData!['Auftrag'] ?? "";
@@ -235,114 +234,155 @@ class _AddCamMainState extends State<AddCamMain> {
} }
Future<dynamic> _showServerErrorDialog() { Future<dynamic> _showServerErrorDialog() {
bool isLoading = false;
return showDialog( return showDialog(
context: context, context: context,
builder: (context) { builder: (context) {
return AlertDialog( return StatefulBuilder(
title: Text(AppLocalizations.of(context)!.servererrortitle), builder: (BuildContext context, StateSetter setState) {
actions: [ return AlertDialog(
TextButton( title: Text(AppLocalizations.of(context)!.servererrortitle),
onPressed: () async { content: isLoading
int errorCode = _httpRequest(); ? const SizedBox(
height: 100,
child: Center(child: CircularProgressIndicator()))
: null,
actions: [
if (!isLoading)
TextButton(
onPressed: () async {
setState(() => isLoading = true);
int errorCode = await _httpRequest();
setState(() => isLoading = false);
if (errorCode != 201) { if (errorCode != 201 && context.mounted) {
Navigator.pop(context); _showServerErrorDialog();
_showServerErrorDialog(); } else {
} if (context.mounted) Navigator.pop(context);
}, saveData(true);
child: Text(AppLocalizations.of(context)!.sendagain)), _showSuccessDialog();
TextButton( }
onPressed: () { },
Navigator.pop(context); child: Text(AppLocalizations.of(context)!.sendagain)),
}, if (!isLoading)
child: Text(AppLocalizations.of(context)!.cancel)) TextButton(
], onPressed: () {
Navigator.pop(context);
},
child: Text(AppLocalizations.of(context)!.cancel))
],
);
},
); );
}); });
} }
Future<void> showSaveOptionsDialog() async { Future<void> showSaveOptionsDialog() async {
bool isLoading = false;
return showDialog( return showDialog(
context: context, context: context,
barrierDismissible:
false, // Verhindert das Schließen des Dialogs durch den Benutzer
builder: (BuildContext context) { builder: (BuildContext context) {
return AlertDialog( return StatefulBuilder(
title: Text(AppLocalizations.of(context)!.savemethod), builder: (context, setState) {
actions: [ return AlertDialog(
TextButton( title: isLoading
onPressed: () async { ? Text(AppLocalizations.of(context)!.loading)
saveTemplate(); : Text(AppLocalizations.of(context)!.savemethod),
Navigator.pushNamedAndRemoveUntil( content: isLoading
context, ? const SizedBox(
'/home', height: 100,
(route) => false); child: Center(child: CircularProgressIndicator()))
}, : null,
child: Text(AppLocalizations.of(context)!.template)), actions: [
TextButton( if (!isLoading)
onPressed: () async { TextButton(
int errorCode = _httpRequest(); onPressed: () async {
setState(() => isLoading = true);
saveTemplate();
Navigator.pushNamedAndRemoveUntil(
context, '/home', (route) => false);
},
child: Text(AppLocalizations.of(context)!.template)),
if (!isLoading)
TextButton(
onPressed: () async {
setState(() => isLoading = true);
int errorCode = await _httpRequest();
setState(() => isLoading = false);
if (errorCode != 201) { if (errorCode != 201 || !context.mounted) {
saveData(); saveData();
_showServerErrorDialog(); _showServerErrorDialog();
} else { } else {
saveData(); saveData(true);
return showDialog( _showSuccessDialog();
context: context, }
builder: (context) { },
return AlertDialog( child:
title: Text( Text(AppLocalizations.of(context)!.sendtoserver)),
AppLocalizations.of(context)!.successful), if (!isLoading)
actions: [ TextButton(
TextButton( onPressed: () async {
onPressed: () { setState(() => isLoading = true);
Navigator.pop(context); saveData();
}, saveFile();
child: Text( setState(() => isLoading = false);
AppLocalizations.of(context)!.back)), },
TextButton( child: Text(AppLocalizations.of(context)!.saveasfile)),
onPressed: () { if (!isLoading)
Navigator.pushNamedAndRemoveUntil( TextButton(
context, '/home', (route) => false); onPressed: () {
}, saveData();
child: Text(AppLocalizations.of(context)! Navigator.pushNamedAndRemoveUntil(
.continueB)) context, '/home', (route) => false);
], },
); child: Text(AppLocalizations.of(context)!.justsave)),
}); if (!isLoading)
} TextButton(
}, onPressed: () {
child: Text(AppLocalizations.of(context)!.sendtoserver)), Navigator.pop(context);
TextButton( },
onPressed: () async { child: Text(AppLocalizations.of(context)!.cancel)),
saveData(); ],
saveFile(); );
}, },
child: Text(AppLocalizations.of(context)!.saveasfile)), );
TextButton( });
onPressed: () { }
saveData();
Navigator.pushNamedAndRemoveUntil( Future<void> _showSuccessDialog() async {
context, return showDialog(
'/home', context: context,
(route) => false); builder: (context) {
}, return AlertDialog(
child: Text(AppLocalizations.of(context)!.justsave)), title: Text(AppLocalizations.of(context)!.successful),
TextButton( actions: [
/* TextButton(
onPressed: () { onPressed: () {
Navigator.pop(context); Navigator.pop(context);
}, },
child: Text(AppLocalizations.of(context)!.cancel)), child: Text(AppLocalizations.of(context)!.back)), */
TextButton(
onPressed: () {
Navigator.pushNamedAndRemoveUntil(
context, '/home', (route) => false);
},
child: Text(AppLocalizations.of(context)!.continueB))
], ],
); );
}); });
} }
int _httpRequest() { Future<int> _httpRequest() async {
Map<String, dynamic> place = getPlace(); Map<String, dynamic> place = getPlace();
Methods method = Methods(); HttpRequest method = HttpRequest();
method.httpRequest(jsonEncode(place)); await method.httpRequest(jsonEncode(place));
return method.errorCode; return method.errorCode;
} }
@@ -366,21 +406,19 @@ class _AddCamMainState extends State<AddCamMain> {
await file.writeAsString(jsonPlace); await file.writeAsString(jsonPlace);
} catch (e) { } catch (e) {
if (mounted) { if (mounted) {
Navigator.pop(context); Navigator.pop(context);
ScaffoldMessenger.of(context).showSnackBar(SnackBar( ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(AppLocalizations.of(context)!.savefilefailed))); } content: Text(AppLocalizations.of(context)!.savefilefailed)));
}
return; return;
} }
if (mounted) { if (mounted) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Datei gespeichert in $selectedDirectory'))); SnackBar(content: Text('Datei gespeichert in $selectedDirectory')));
} }
if (mounted) { if (mounted) {
Navigator.pushNamedAndRemoveUntil( Navigator.pushNamedAndRemoveUntil(context, '/home', (route) => false);
context,
'/home',
(route) => false);
} }
} }
@@ -432,12 +470,16 @@ class _AddCamMainState extends State<AddCamMain> {
// If the user has filled all needed values this function will be called to safe them in the database // If the user has filled all needed values this function will be called to safe them in the database
// * also creates a json string to send it to the server later // * also creates a json string to send it to the server later
void saveData() async { void saveData([bool sent = false]) async {
var placeDB = DBHelper(); var placeDB = DBHelper();
Map<String, dynamic> place = getPlace(); Map<String, dynamic> place = getPlace();
await placeDB.addPlace(place); // Get the ID of the newly added or updated place
int newPlaceId = await placeDB.addPlace(place);
if (sent == true) {
placeDB.updateSent(newPlaceId); // Update 'Sent' using the correct ID
}
if (widget.isTemplate) { if (widget.isTemplate) {
await placeDB.deleteTemplate(cid.text); await placeDB.deleteTemplate(cid.text);
@@ -721,7 +763,7 @@ class _AddCamMainState extends State<AddCamMain> {
onDateChanged: (value) { onDateChanged: (value) {
abbauDat = value; abbauDat = value;
}, },
), ),
], ],
), ),
const SizedBox( const SizedBox(
@@ -832,7 +874,9 @@ class _AddCamMainState extends State<AddCamMain> {
List<String> emptyFields = validateData(); List<String> emptyFields = validateData();
// ! always filled out // ! always filled out
empty = false; empty = false;
if (empty == true) { if (widget.isSent) {
Navigator.pushNamedAndRemoveUntil(context, '/home', (route) => false);
} else if (empty == true) {
showTemplateDialog(emptyFields); showTemplateDialog(emptyFields);
return; return;
} else if (empty == false) { } else if (empty == false) {

View File

@@ -18,7 +18,7 @@ class HomePage extends StatelessWidget {
File file = File(result.files.single.path!); File file = File(result.files.single.path!);
String content = await file.readAsString(); String content = await file.readAsString();
Methods().httpRequest(content); HttpRequest().httpRequest(content);
} }
} }

View File

@@ -97,5 +97,6 @@
"servererrortitle": "Serverfehler", "servererrortitle": "Serverfehler",
"sendagain": "Nochmal senden", "sendagain": "Nochmal senden",
"successful": "Erfolgreich", "successful": "Erfolgreich",
"back": "Zurück" "back": "Zurück",
"loading": "Lädt"
} }

View File

@@ -472,6 +472,11 @@
"back": "Back", "back": "Back",
"@back": { "@back": {
"description": "back alert dialog option" "description": "back alert dialog option"
},
"loading": "Loading",
"@loading": {
"description": "just Loading"
} }
} }

View File

@@ -5,24 +5,23 @@ import 'package:dio/dio.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
class Methods { class HttpRequest {
int? _errorCode; int? _errorCode;
int get errorCode => _errorCode ?? 0; int get errorCode => _errorCode ?? 0;
Methods(); Future<void> httpRequest(String httpData) async {
void httpRequest(String httpData) async {
// print(jsonEncode(place)); // print(jsonEncode(place));
final dio = Dio(); final dio = Dio();
final SharedPreferences prefs = await SharedPreferences.getInstance(); final SharedPreferences prefs = await SharedPreferences.getInstance();
dio.options.responseType = ResponseType.plain; dio.options
..connectTimeout = const Duration(seconds: 5)
..receiveTimeout = const Duration(seconds: 5)
..responseType = ResponseType.plain;
Response response = Response(requestOptions: RequestOptions(path: ''), statusCode: 400); Response response = Response(requestOptions: RequestOptions(path: ''), statusCode: 400);
try { try {

View File

@@ -35,50 +35,42 @@ class DBHelper {
'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))'); '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))');
} }
// Function to add a finished entrie // Function to add a finished entry and return its ID
Future<void> addPlace(Map<String, dynamic> place) async { Future<int> addPlace(Map<String, dynamic> place) async {
var placeDBClient = await placeDB; var placeDBClient = await placeDB;
// gets an camid if it already exists
final existingID = await placeDBClient.query( final existingID = await placeDBClient.query(
'place', 'place',
where: 'ID = ?', where: 'ID = ?',
whereArgs: [place['ID']], whereArgs: [place['ID']],
); );
// checks if the camid var from before is empty to avoid double entries
if (existingID.isNotEmpty) { if (existingID.isNotEmpty) {
updatePlace(place); updatePlace(place);
return; return existingID.first['ID'] as int; // Return existing ID
} }
// inserts the entrie in the database int id = await placeDBClient.insert(
await placeDBClient.insert(
'place', 'place',
place, place,
//conflictAlgorithm: ConflictAlgorithm.replace,
// replaces the entrie with the new onw if a unique value exists and conflicts
// conflictAlgorithm: ConflictAlgorithm.replace,
); );
return id; // Return the ID of the newly inserted entry
} }
Future<void> updatePlace(Map<String, dynamic> place) async { Future<void> updatePlace(Map<String, dynamic> place) async {
var placeDBClient = await placeDB; var placeDBClient = await placeDB;
await placeDBClient.update( await placeDBClient
'place', .update('place', place, where: "ID = ?", whereArgs: [place['ID']]);
place,
where: "ID = ?",
whereArgs: [place['ID']]
);
} }
// function to update the sent value // function to update the sent value
Future<void> updateSent() async { Future<void> updateSent(int id) async {
var placeDBClient = await placeDB; var placeDBClient = await placeDB;
placeDBClient.update('place', true as Map<String, Object?>, await placeDBClient.update('place', {'Sent': 1},
where: 'ID = ?', whereArgs: ['ID']); where: 'ID = ?', whereArgs: [id]);
} }
// same thing as before but with templatews // same thing as before but with templatews

View File

@@ -112,8 +112,12 @@ class _ViewCamsState extends State<ViewCams> {
appBar: AppBar( appBar: AppBar(
bottom: TabBar(tabs: [ bottom: TabBar(tabs: [
Tab(text: AppLocalizations.of(context)!.completed), Tab(text: AppLocalizations.of(context)!.completed),
Tab(text: AppLocalizations.of(context)!.uncompleted,), Tab(
Tab(text: AppLocalizations.of(context)!.map,), text: AppLocalizations.of(context)!.uncompleted,
),
Tab(
text: AppLocalizations.of(context)!.map,
),
]), ]),
title: Text(AppLocalizations.of(context)!.viewplacesappbar)), title: Text(AppLocalizations.of(context)!.viewplacesappbar)),
body: TabBarView( body: TabBarView(
@@ -201,13 +205,14 @@ class _ViewCamsState extends State<ViewCams> {
onChanged: null, onChanged: null,
), ),
onTap: () async { onTap: () async {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => AddCamMain( builder: (context) => AddCamMain(
isFinished: true, isSent: place['Sent'] == 1 ? true : false,
existingData: place, isFinished: true,
))); existingData: place,
)));
}, },
), ),
); );
@@ -277,17 +282,26 @@ class _ViewCamsState extends State<ViewCams> {
return Marker( return Marker(
width: 80.0, width: 80.0,
height: 80.0, height: 80.0,
point: LatLng(double.parse(e['DECLAT'].toString()), double.parse(e['DECLNG'].toString())), point: LatLng(double.parse(e['DECLAT'].toString()),
double.parse(e['DECLNG'].toString())),
child: Column( child: Column(
children: [ children: [
const Icon(Icons.location_on, color: Colors.red,), const Icon(
Text("ID: ${e['ID'].toString()}", style: const TextStyle(color: Colors.black),) Icons.location_on,
color: Colors.red,
),
Text(
"ID: ${e['ID'].toString()}",
style: const TextStyle(color: Colors.black),
)
], ],
)); ));
}).toList(); }).toList();
return FlutterMap( return FlutterMap(
options: MapOptions( options: MapOptions(
initialCenter: markers.isEmpty ? const LatLng(50, 10) : markers.first.point, initialCenter: markers.isEmpty
? const LatLng(50, 10)
: markers.first.point,
interactionOptions: const InteractionOptions( interactionOptions: const InteractionOptions(
flags: InteractiveFlag.pinchZoom | flags: InteractiveFlag.pinchZoom |
InteractiveFlag.drag | InteractiveFlag.drag |