fixed a lot of things after i broke everything. Just the card is not implemented again yet

time
This commit is contained in:
Nico
2025-05-12 23:09:28 +02:00
parent 97691f3453
commit 74b4648e73
18 changed files with 599 additions and 479 deletions

View File

@@ -10,7 +10,6 @@ import 'screens/addCam/add_cam_main.dart';
class HomePage extends StatelessWidget {
const HomePage({super.key});
void _sendFile() async {
FilePickerResult? result = await FilePicker.platform.pickFiles();
@@ -29,69 +28,86 @@ class HomePage extends StatelessWidget {
title: Text(AppLocalizations.of(context)!.homePageTitle),
actions: [
PopupMenuButton(
onSelected: (value) {
Navigator.pushNamed(context, value.toString());
},
itemBuilder: (context) => [
PopupMenuItem(
value: '/settings',
child: Text(AppLocalizations.of(context)!.settings),
),
PopupMenuItem(
value: '/introScreen',
child:
Text(AppLocalizations.of(context)!.showloginscreen))
])
onSelected: (value) {
Navigator.pushNamed(context, value.toString());
},
itemBuilder:
(context) => [
PopupMenuItem(
value: '/settings',
child: Text(AppLocalizations.of(context)!.settings),
),
PopupMenuItem(
value: '/introScreen',
child: Text(AppLocalizations.of(context)!.showloginscreen),
),
],
),
],
),
body: Column(
children: [
Image.asset('assets/images/reconix_small.png'),
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(height: 30,),
ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size(250, 40),
padding: const EdgeInsets.fromLTRB(10, 5, 10, 5),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(height: 30),
ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size(250, 40),
padding: const EdgeInsets.fromLTRB(10, 5, 10, 5),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const AddCamMain()));
context,
MaterialPageRoute(
builder: (context) => const AddCamMain(),
),
);
},
child: Text(AppLocalizations.of(context)!.addplace)),
const SizedBox(height: 10,),
ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size(250, 40)
child: Text(AppLocalizations.of(context)!.addplace),
),
const SizedBox(height: 10),
ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size(250, 40),
),
onPressed: () => Navigator.pushNamed(context, '/excursion'),
child: Text(AppLocalizations.of(context)!.excursion)), // Excursion
child: Text(AppLocalizations.of(context)!.excursion),
), // Excursion
const SizedBox(height: 10,),
ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size(250, 40)
),
const SizedBox(height: 10),
ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size(250, 40),
),
onPressed: () => Navigator.pushNamed(context, '/viewCams'),
child: Text(AppLocalizations.of(context)!.viewplaces)),
const SizedBox(height: 10,),
ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size(250, 40)
child: Text(AppLocalizations.of(context)!.viewplaces),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size(250, 40),
),
onPressed: () => Navigator.pushNamed(context, '/viewExcursionen'),
child: Text(AppLocalizations.of(context)!.viewplaces),
),
const SizedBox(height: 10),
ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size(250, 40),
),
onPressed: () {
_sendFile();
},
child: Text(AppLocalizations.of(context)!.sendfile)),
],
)),
child: Text(AppLocalizations.of(context)!.sendfile),
),
],
),
),
],
),
);

View File

@@ -79,6 +79,7 @@
"sendtoserver": "Zum Server senden",
"savemethod": "Speichermethode auswählen",
"viewplaces": "Standorte anzeigen",
"viewExcursionen": "Excursionen anzeigen",
"showloginscreen": "Login-Bildschirm Anzeigen",
"apiaddress": "Api-Adresse",
"benutzername": "Benutzername",

View File

@@ -379,6 +379,11 @@
"description": "View places button"
},
"viewExcursionen": "View Excursionen",
"@viewplaces": {
"description": "View Excursionen button"
},
"showloginscreen": "Show login Screen",
"@showloginscreen": {
"description": "show login screen popup menu item"

View File

@@ -569,12 +569,18 @@ abstract class AppLocalizations {
/// **'Choose safe method'**
String get savemethod;
/// View places button
/// View Excursionen button
///
/// In en, this message translates to:
/// **'View Places'**
String get viewplaces;
/// No description provided for @viewExcursionen.
///
/// In en, this message translates to:
/// **'View Excursionen'**
String get viewExcursionen;
/// show login screen popup menu item
///
/// In en, this message translates to:

View File

@@ -248,6 +248,9 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get viewplaces => 'Standorte anzeigen';
@override
String get viewExcursionen => 'Excursionen anzeigen';
@override
String get showloginscreen => 'Login-Bildschirm Anzeigen';

View File

@@ -248,6 +248,9 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get viewplaces => 'View Places';
@override
String get viewExcursionen => 'View Excursionen';
@override
String get showloginscreen => 'Show login Screen';

View File

@@ -47,7 +47,8 @@ class MyApp extends StatelessWidget {
routes: {
'/home': (context) => const HomePage(),
'/addCamMain': (context) => const AddCamMain(),
'/viewCams': (context) => const ViewCams(dbType: DatabasesEnum.place,),
'/viewCams': (context) => const ViewEntries(dbType: DatabasesEnum.place,),
'/viewExcursionen': (context) => const ViewEntries(dbType: DatabasesEnum.excursion,),
'/introScreen': (context) => const IntroScreen(),
'/settings': (context) => const Settings(),
'/excursion': (context) => const ExcursionMain(),

View File

@@ -7,7 +7,7 @@ import 'package:path/path.dart';
// * Gives the complete functionality for the databases
// ! functions may not be named complete correctly
class ExcursionDBHelper implements IDb{
class ExcursionDBHelper implements IDb {
static Database? _excursionDB;
// checks if the databses are existing and creates them with the initPlaceDatabase function if not
@@ -25,22 +25,26 @@ class ExcursionDBHelper implements IDb{
initDatabases() async {
io.Directory documentsDirectory = await getApplicationCacheDirectory();
String path = join(documentsDirectory.path, 'excursionDB.db');
var excursionDB =
await openDatabase(path, version: 1, onCreate: onCreateDatabases);
var excursionDB = await openDatabase(
path,
version: 1,
onCreate: onCreateDatabases,
);
return excursionDB;
}
// The function that helps
// TODO Change to right cols
@override
onCreateDatabases(Database excursionDB, int version) async {
await excursionDB.execute(
'CREATE TABLE excursion (ID INTEGER PRIMARY KEY AUTOINCREMENT, Datum TEXT, Rudel TEXT, Teilnehmer TEXT, Jahr TEXT, Mjahr TEXT, Monat INTEGER, Saison TEXT, Dauer TEXT, BLjahr TEXT, BLand, TEXT, Lkr TEXT, BeiOrt TEXT, Wetter TEXT, Temperat TEXT, RegenVor TEXT, KmAuto TEXT, KmFuss TEXT, KmRad TEXT, KmTotal TEXT, KmAuProf TEXT, KmFuProz TEXT, KmRaProz TEXT, SpGut TEXT, SpSchlecht TEXT, SpurFund TEXT, SpurLang TEXT, SpurTiere Text, SpSicher TEXT, WelpenSp TEXT, WelpenAnz TEXT, WpSicher TEXT, LosungGes TEXT, LosunAnz TEXT, LosunGen TEXT, UrinAnz TEXT, UrinGen TEXT, OestrAnz TEXT, OestrGen TEXT, HaarAnz TEXT, HaarGen TEXT, LosungKm TEXT, GenetiKm TEXT, Hinweise TEXT, Bemerk TEXT, IntKomm TEXT, BimaNr TEXT, BimaName TEXT, BimaNutzer TEXT, BimaAGV TEXT, FallNum INTEGER, MHund TEXT, MLeine TEXT, LogDat TEXT, HinweiseSonstiges TEXT)');
'CREATE TABLE excursion (ID INTEGER PRIMARY KEY AUTOINCREMENT, LogDat TEXT, Rudel TEXT, Teilnehmer TEXT, Jahr TEXT, Dauer TEXT, MHund INTEGER, MLeine TEXT, BLand TEXT, Lkr TEXT, BeiOrt, TEXT, BimaName TEXT, Wetter TEXT, Temperat TEXT, RegenVor TEXT, KmRad TEXT, KmAuto TEXT, KmFuss TEXT, KmTotal TEXT, KmAuProz TEXT, KmFuProz TEXT, KmRaProz TEXT, SpGut TEXT, SpMittel, SpSchlecht TEXT, SpurFund TEXT, SpurLang TEXT, SpurTiere Text, SpSicher TEXT, WelpenSp TEXT, WelpenAnz TEXT, WpSicher TEXT, LosungGes TEXT, LosungAnz TEXT, LosungGen TEXT, UrinAnz TEXT, UrinGen TEXT, OestrAnz TEXT, OestrGen TEXT, HaarAnz TEXT, HaarGen TEXT, LosungKm TEXT, GenetiKm TEXT, Hinweise TEXT, Bemerk TEXT, IntKomm TEXT, BimaNr TEXT, BimaNutzer TEXT, BimaAGV TEXT, FallNum INTEGER, HinweiseSonstiges TEXT, Sent INTEGER DEFAULT 0)',
);
await excursionDB.execute(
'CREATE TABLE excursionTemplates (ID INTEGER PRIMARY KEY AUTOINCREMENT, Datum TEXT, Rudel TEXT, Teilnehmer TEXT, Jahr TEXT, Mjahr TEXT, Monat INTEGER, Saison TEXT, Dauer TEXT, BLjahr TEXT, BLand, TEXT, Lkr TEXT, BeiOrt TEXT, Wetter TEXT, Temperat TEXT, RegenVor TEXT, KmAuto TEXT, KmFuss TEXT, KmRad TEXT, KmTotal TEXT, KmAuProf TEXT, KmFuProz TEXT, KmRaProz TEXT, SpGut TEXT, SpSchlecht TEXT, SpurFund TEXT, SpurLang TEXT, SpurTiere Text, SpSicher TEXT, WelpenSp TEXT, WelpenAnz TEXT, WpSicher TEXT, LosungGes TEXT, LosunAnz TEXT, LosunGen TEXT, UrinAnz TEXT, UrinGen TEXT, OestrAnz TEXT, OestrGen TEXT, HaarAnz TEXT, HaarGen TEXT, LosungKm TEXT, GenetiKm TEXT, Hinweise TEXT, Bemerk TEXT, IntKomm TEXT, BimaNr TEXT, BimaName TEXT, BimaNutzer TEXT, BimaAGV TEXT, FallNum INTEGER, MHund TEXT, MLeine TEXT, LogDat TEXT, HinweiseSonstiges TEXT)');
'CREATE TABLE excursionTemplates (ID INTEGER PRIMARY KEY AUTOINCREMENT, LogDat TEXT, Rudel TEXT, Teilnehmer TEXT, Jahr TEXT, Dauer TEXT, MHund INTEGER, MLeine TEXT, BLand TEXT, Lkr TEXT, BeiOrt, TEXT, BimaName TEXT, Wetter TEXT, Temperat TEXT, RegenVor TEXT, KmRad TEXT, KmAuto TEXT, KmFuss TEXT, KmTotal TEXT, KmAuProz TEXT, KmFuProz TEXT, KmRaProz TEXT, SpGut TEXT, SpMittel, SpSchlecht TEXT, SpurFund TEXT, SpurLang TEXT, SpurTiere Text, SpSicher TEXT, WelpenSp TEXT, WelpenAnz TEXT, WpSicher TEXT, LosungGes TEXT, LosungAnz TEXT, LosungGen TEXT, UrinAnz TEXT, UrinGen TEXT, OestrAnz TEXT, OestrGen TEXT, HaarAnz TEXT, HaarGen TEXT, LosungKm TEXT, GenetiKm TEXT, Hinweise TEXT, Bemerk TEXT, IntKomm TEXT, BimaNr TEXT, BimaNutzer TEXT, BimaAGV TEXT, FallNum INTEGER, HinweiseSonstiges TEXT)',
);
}
// Function to add a finished entry and return its ID
// Function to add a finished entry and return its ID
@override
Future<int> addMainEntry(Map<String, String> excursion) async {
var excursionDBClient = await dB;
@@ -68,8 +72,12 @@ class ExcursionDBHelper implements IDb{
Future<int> updateMainEntry(Map<String, String> excursion) async {
var excursionDBClient = await dB;
return await excursionDBClient
.update('excursion', excursion, where: "ID = ?", whereArgs: [excursion['ID']]);
return await excursionDBClient.update(
'excursion',
excursion,
where: "ID = ?",
whereArgs: [excursion['ID']],
);
}
// function to update the sent value
@@ -77,8 +85,12 @@ class ExcursionDBHelper implements IDb{
Future<void> updateSent(int id) async {
var excursionDBClient = await dB;
await excursionDBClient.update('excursion', {'Sent': 1},
where: 'ID = ?', whereArgs: [id]);
await excursionDBClient.update(
'excursion',
{'Sent': 1},
where: 'ID = ?',
whereArgs: [id],
);
}
// same thing as before but with templatews
@@ -119,14 +131,24 @@ class ExcursionDBHelper implements IDb{
@override
Future<List<Map<String, dynamic>>> getAllMainEntries() async {
var excursionDBClient = await dB;
return await excursionDBClient.query('excursion');
var erg = await excursionDBClient.query('excursion');
if (erg.isEmpty) {
return [];
} else {
return erg;
}
}
// get the finished templates from db
@override
Future<List<Map<String, dynamic>>> getAllTemplates() async {
var excursionDBClient = await dB;
return await excursionDBClient.query('excursionTemplates');
var erg = await excursionDBClient.query('excursionTemplates');
if (erg.isEmpty) {
return [];
} else {
return erg;
}
}
// deletes all finished entries from the db LOCALLY
@@ -154,7 +176,7 @@ class ExcursionDBHelper implements IDb{
);
}
// delete specific excursion
// delete specific excursion
@override
Future<void> deleteMainEntryById(String id) async {
var excursionDBClient = await dB;

View File

@@ -118,14 +118,24 @@ class PlaceDBHelper implements IDb{
@override
Future<List<Map<String, dynamic>>> getAllMainEntries() async {
var placeDBClient = await dB;
return await placeDBClient.query('place');
var erg = await placeDBClient.query('place');
if (erg.isEmpty) {
return [];
} else {
return erg;
}
}
// get the finished templates from db
@override
Future<List<Map<String, dynamic>>> getAllTemplates() async {
var placeDBClient = await dB;
return await placeDBClient.query('placeTemplates');
var erg = await placeDBClient.query('placeTemplates');
if (erg.isEmpty) {
return [];
} else {
return erg;
}
}
// deletes all finished entries from the db LOCALLY

View File

@@ -598,13 +598,11 @@ class _AddCamMainState extends State<AddCamMain> {
saveTemplate(
getFieldsText(),
DatabasesEnum.place,
widget.isTemplate,
);
setState(() {
currentStep += 1;
});
} else {
// ! always filled out
if (widget.isSent) {
Navigator.pushNamedAndRemoveUntil(
@@ -623,7 +621,6 @@ class _AddCamMainState extends State<AddCamMain> {
AddEntriesDialogHelper.showTemplateDialog(
context,
getFieldsText(),
widget.existingData?.isNotEmpty ?? false,
);
return;
} else if (empty == false) {

View File

@@ -66,7 +66,7 @@ class KarteState extends State<Karte> {
// widget.ortInfoC.text = placemarks.first.street!;
// } catch (e) {
// //
// // TODO Localization
// // !!! Localization
// if (context.mounted) {
// SnackBarHelper.showSnackBarMessage(
// context, "Geocoding error");

View File

@@ -9,81 +9,111 @@ import 'package:fforte/screens/excursion/widgets/spur_gefunden.dart';
import 'package:fforte/screens/excursion/widgets/strecke_u_spurbedingungen.dart';
import 'package:fforte/screens/helper/add_entries_dialog_helper.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:fforte/l10n/app_localizations.dart';
import 'package:flutter/material.dart';
class ExcursionMain extends StatefulWidget {
const ExcursionMain({super.key});
final bool isTemplate;
final bool isSent;
final Map<String, dynamic>? existingData;
const ExcursionMain({
super.key,
this.isTemplate = false,
this.isSent = false,
this.existingData,
});
@override
State<ExcursionMain> createState() => _ExcursionMainState();
}
class _ExcursionMainState extends State<ExcursionMain> {
// all TextEditingController because its easier
int currentStep = 0;
// all TextEditingController because its easier
Map<String, Map<String, dynamic>> rmap = {
// Step 1
"LogDat": {"controller": TextEditingController(), "required": bool},
"Rudel": {"controller": TextEditingController(), "required": bool},
"Teilnehm": {"controller": TextEditingController(), "required": bool},
"Jahr": {"controller": TextEditingController(), "required": bool},
"Dauer": {"controller": TextEditingController(), "required": bool},
"MHund": {"controller": TextEditingController(), "required": bool},
"MLeine": {"controller": TextEditingController(), "required": bool},
"BLand": {"controller": TextEditingController(), "required": bool},
"Lkr": {"controller": TextEditingController(), "required": bool},
"BeiOrt": {"controller": TextEditingController(), "required": bool},
"BimaNr": {"controller": TextEditingController(), "required": bool},
"BimaName": {"controller": TextEditingController(), "required": bool},
"BimaNutzer": {"controller": TextEditingController(), "required": bool},
"BimaAGV": {"controller": TextEditingController(), "required": bool},
"LogDat": {"controller": TextEditingController(), "required": false},
"Rudel": {"controller": TextEditingController(), "required": false},
"Teilnehmer": {"controller": TextEditingController(), "required": false},
"Jahr": {"controller": TextEditingController(), "required": false},
"Dauer": {"controller": TextEditingController(), "required": false},
"MHund": {"controller": TextEditingController(), "required": false},
"MLeine": {"controller": TextEditingController(), "required": false},
"BLand": {"controller": TextEditingController(), "required": false},
"Lkr": {"controller": TextEditingController(), "required": false},
"BeiOrt": {"controller": TextEditingController(), "required": false},
"BimaNr": {"controller": TextEditingController(), "required": false},
"BimaName": {"controller": TextEditingController(), "required": false},
"BimaNutzer": {"controller": TextEditingController(), "required": false},
"BimaAGV": {"controller": TextEditingController(), "required": false},
// Step 2
"Wetter": {"controller": TextEditingController(), "required": bool},
"Temperat": {"controller": TextEditingController(), "required": bool},
"RegenVor": {"controller": TextEditingController(), "required": bool},
"KmAuto": {"controller": TextEditingController(), "required": bool},
"KmFuss": {"controller": TextEditingController(), "required": bool},
"KmRad": {"controller": TextEditingController(), "required": bool},
"KmTotal": {"controller": TextEditingController(), "required": bool},
"KmAuProz": {"controller": TextEditingController(), "required": bool},
"KmFuProz": {"controller": TextEditingController(), "required": bool},
"KmRaProz": {"controller": TextEditingController(), "required": bool},
"Wetter": {"controller": TextEditingController(), "required": false},
"Temperat": {"controller": TextEditingController(), "required": false},
"RegenVor": {"controller": TextEditingController(), "required": false},
"KmAuto": {"controller": TextEditingController(), "required": false},
"KmFuss": {"controller": TextEditingController(), "required": false},
"KmRad": {"controller": TextEditingController(), "required": false},
"KmTotal": {"controller": TextEditingController(), "required": false},
"KmAuProz": {"controller": TextEditingController(), "required": false},
"KmFuProz": {"controller": TextEditingController(), "required": false},
"KmRaProz": {"controller": TextEditingController(), "required": false},
// Spur maybe own step?
"SpGut": {"controller": TextEditingController(), "required": bool},
"SpMittel": {"controller": TextEditingController(), "required": bool},
"SpSchlecht": {"controller": TextEditingController(), "required": bool},
"SpurFund": {"controller": TextEditingController(), "required": bool},
"SpurLang": {"controller": TextEditingController(), "required": bool},
"SpurTiere": {"controller": TextEditingController(), "required": bool},
"SpSicher": {"controller": TextEditingController(), "required": bool},
"WelpenSp": {"controller": TextEditingController(), "required": bool},
"WelpenAnz": {"controller": TextEditingController(), "required": bool},
"WpSicher": {"controller": TextEditingController(), "required": bool},
"SpGut": {"controller": TextEditingController(), "required": false},
"SpMittel": {"controller": TextEditingController(), "required": false},
"SpSchlecht": {"controller": TextEditingController(), "required": false},
"SpurFund": {"controller": TextEditingController(), "required": false},
"SpurLang": {"controller": TextEditingController(), "required": false},
"SpurTiere": {"controller": TextEditingController(), "required": false},
"SpSicher": {"controller": TextEditingController(), "required": false},
"WelpenSp": {"controller": TextEditingController(), "required": false},
"WelpenAnz": {"controller": TextEditingController(), "required": false},
"WpSicher": {"controller": TextEditingController(), "required": false},
"LosungGes": {"controller": TextEditingController(), "required": bool},
"LosungAnz": {"controller": TextEditingController(), "required": bool},
"LosungGen": {"controller": TextEditingController(), "required": bool},
"UrinAnz": {"controller": TextEditingController(), "required": bool},
"UrinGen": {"controller": TextEditingController(), "required": bool},
"OestrAnz": {"controller": TextEditingController(), "required": bool},
"OestrGen": {"controller": TextEditingController(), "required": bool},
"HaarAnz": {"controller": TextEditingController(), "required": bool},
"HaarGen": {"controller": TextEditingController(), "required": bool},
"LosungKm": {"controller": TextEditingController(), "required": bool},
"GenetiKm": {"controller": TextEditingController(), "required": bool},
"Hinweise": {"controller": TextEditingController(), "required": bool},
"LosungGes": {"controller": TextEditingController(), "required": false},
"LosungAnz": {"controller": TextEditingController(), "required": false},
"LosungGen": {"controller": TextEditingController(), "required": false},
"UrinAnz": {"controller": TextEditingController(), "required": false},
"UrinGen": {"controller": TextEditingController(), "required": false},
"OestrAnz": {"controller": TextEditingController(), "required": false},
"OestrGen": {"controller": TextEditingController(), "required": false},
"HaarAnz": {"controller": TextEditingController(), "required": false},
"HaarGen": {"controller": TextEditingController(), "required": false},
"LosungKm": {"controller": TextEditingController(), "required": false},
"GenetiKm": {"controller": TextEditingController(), "required": false},
"Hinweise": {"controller": TextEditingController(), "required": false},
// Step 3
"Bemerk": {"controller": TextEditingController(), "required": bool},
"IntKomm": {"controller": TextEditingController(), "required": bool},
"FallNum": {"controller": TextEditingController(), "required": bool},
"Bemerk": {"controller": TextEditingController(), "required": false},
"IntKomm": {"controller": TextEditingController(), "required": false},
"FallNum": {"controller": TextEditingController(), "required": false},
};
@override
void initState() {
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();
}
Map<String, String> getFieldsText() {
Map<String, String> puff = {};
@@ -94,7 +124,6 @@ class _ExcursionMainState extends State<ExcursionMain> {
return puff;
}
int currentStep = 0;
@override
Widget build(BuildContext context) {
@@ -123,9 +152,9 @@ class _ExcursionMainState extends State<ExcursionMain> {
const SizedBox(height: 10),
// ---------- Participants
VarTextField(
textController: rmap["Teilnehm"]!["controller"]!,
textController: rmap["Teilnehmer"]!["controller"]!,
localization: AppLocalizations.of(context)!.teilnehmer,
dbName: "Teilnehm",
dbName: "Teilnehmer",
required: false,
dbDesignation: DatabasesEnum.excursion,
),
@@ -344,23 +373,40 @@ class _ExcursionMainState extends State<ExcursionMain> {
final isLastStep = currentStep == getSteps().length - 1;
if (!isLastStep) {
saveTemplate(
getFieldsText(),
DatabasesEnum.excursion,
);
setState(() {
currentStep += 1;
});
} else {
if (widget.isSent) {
Navigator.pushNamedAndRemoveUntil(
context,
'/home',
(route) => false,
);
return;
}
bool empty = CheckRequired.checkRequired(rmap);
if (empty) {
await AddEntriesDialogHelper.showTemplateDialog(
// TODO for debugging always true
empty = false;
if (empty == true) {
AddEntriesDialogHelper.showTemplateDialog(
context,
getFieldsText(),
false,
);
} else {
return;
} else if (empty == false) {
await AddEntriesDialogHelper.showSaveOptionsDialog(
context,
getFieldsText(),
false,
DatabasesEnum.excursion
widget.isTemplate,
DatabasesEnum.excursion,
);
}
}

View File

@@ -10,7 +10,7 @@ import 'package:fforte/l10n/app_localizations.dart';
class AddEntriesDialogHelper {
// Function to show the dialog where the user has to choose if he want to safe his values as a template
static Future<void> showTemplateDialog(BuildContext context,
Map<String, String> saveData, bool update) async {
Map<String, String> saveData) async {
return showDialog(
context: context,
barrierDismissible: false,
@@ -25,7 +25,7 @@ class AddEntriesDialogHelper {
child: Text(AppLocalizations.of(context)!.cancel)),
TextButton(
onPressed: () {
saveTemplate(saveData, DatabasesEnum.place, update);
saveTemplate(saveData, DatabasesEnum.place);
Navigator.pushNamedAndRemoveUntil(
context, '/home', (route) => false);
},
@@ -111,7 +111,7 @@ class AddEntriesDialogHelper {
onPressed: () async {
setState(() => isLoading = true);
saveTemplate(
saveData, DatabasesEnum.place, isTemplate);
saveData, DatabasesEnum.place);
Navigator.pushNamedAndRemoveUntil(
context, '/home', (route) => false);
},

View File

@@ -19,12 +19,13 @@ class SaveMainEntryMethod {
placeDB = ExcursionDBHelper();
}
if (isTemplate) placeDB!.deleteTemplateById(entryData["ID"]!);
if (isTemplate) await placeDB!.deleteTemplateById(entryData["ID"]!);
int entryId;
if (isTemplate || entryData["ID"] == "") {
if (entryData["ID"] == "") {
entryData.remove("ID");
entryId = await placeDB!.addMainEntry(entryData);
// await placeDB.deleteTemplateById(entryData["CID"]!);
} else {
entryId = await placeDB!.updateMainEntry(entryData);
}
@@ -33,6 +34,5 @@ class SaveMainEntryMethod {
placeDB.updateSent(entryId); // Update 'Sent' using the correct ID
}
await placeDB.deleteTemplateById(entryData["CID"]!);
}
}

View File

@@ -3,8 +3,7 @@ import 'package:fforte/interfaces/i_db.dart';
import 'package:fforte/methods/excursion_db_helper.dart';
import 'package:fforte/methods/place_db_helper.dart';
void saveTemplate(Map<String, String> templateData, DatabasesEnum dbType,
bool update) async {
void saveTemplate(Map<String, String> templateData, DatabasesEnum dbType,) async {
IDb dbHelper;
if (dbType == DatabasesEnum.place) {
dbHelper = PlaceDBHelper();
@@ -15,11 +14,11 @@ void saveTemplate(Map<String, String> templateData, DatabasesEnum dbType,
}
templateData.remove("Sent");
templateData.remove("ID");
if (update) {
await dbHelper.updateTemplate(templateData);
} else {
if (templateData["ID"]! == "") {
templateData.remove("ID");
await dbHelper.addTemplate(templateData);
} else {
await dbHelper.updateTemplate(templateData);
}
}

View File

@@ -4,7 +4,6 @@ import 'package:fforte/methods/place_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;
@@ -14,22 +13,23 @@ class VarTextField extends StatefulWidget {
final String? otherDefault;
final bool required;
const VarTextField(
{super.key,
const VarTextField({
super.key,
required this.textController,
required this.localization,
required this.dbName,
required this.required,
required this.dbDesignation,
this.defaultValue,
this.otherDefault});
this.otherDefault,
});
@override
State<VarTextField> createState() => _VarTextFieldState();
}
class _VarTextFieldState extends State<VarTextField> {
late Future<List<Map<String, dynamic>>> dbVar;
List<String> dbVar = [];
@override
void initState() {
@@ -43,19 +43,40 @@ class _VarTextFieldState extends State<VarTextField> {
widget.textController.text = widget.otherDefault!;
}
dbVar = _loadData();
_loadData().then((e) => dbVar = e);
}
Future<List<Map<String, dynamic>>> _loadData() async {
Future<List<String>> _loadData() async {
List<Map<String, dynamic>> entries = [];
List<Map<String, dynamic>> templatesEntries = [];
if (widget.dbDesignation == DatabasesEnum.place) {
var entries = await PlaceDBHelper().getAllMainEntries();
var templatesEntries = await PlaceDBHelper().getAllTemplates();
return [...entries, ...templatesEntries];
} else {
var entries = await ExcursionDBHelper().getAllMainEntries();
var templatesEntries = await ExcursionDBHelper().getAllTemplates();
return [...entries, ...templatesEntries];
entries = await PlaceDBHelper().getAllMainEntries();
templatesEntries = await PlaceDBHelper().getAllTemplates();
} else if (widget.dbDesignation == DatabasesEnum.excursion) {
entries = await ExcursionDBHelper().getAllMainEntries();
templatesEntries = await ExcursionDBHelper().getAllTemplates();
}
List<String> erg = [];
for (var element in entries) {
for (var key in element.keys) {
if (key == widget.dbName && element[key].toString() != "") {
erg.add(element[key].toString());
}
}
}
for (var element in templatesEntries) {
for (var key in element.keys) {
if (key == widget.dbName && element[key].toString() != "") {
erg.add(element[key].toString());
}
}
}
return erg;
}
void _loadPref() {
@@ -85,71 +106,53 @@ class _VarTextFieldState extends State<VarTextField> {
},
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,
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<List<Map<String, dynamic>>>(
future: dbVar,
builder: (BuildContext context,
AsyncSnapshot<List<Map<String, dynamic>>> 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<String>(
onSelected: (String value) {
setState(() {
widget.textController.text = value;
});
},
itemBuilder: (BuildContext context) {
return uniqueData
.map((value) => PopupMenuItem<String>(
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();
}
},
child: PopupMenuButton<String>(
onSelected: (String value) {
setState(() {
widget.textController.text = value;
});
},
itemBuilder: (BuildContext context) {
return dbVar.map((String item) {
return PopupMenuItem<String>(value: item, child: Text(item));
}).toList();
},
child: const Icon(Icons.arrow_drop_down),
),
),
),
)
),
],
);
}

View File

@@ -13,51 +13,55 @@ import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:latlong2/latlong.dart';
// * Site that shows all entries in the databases
class ViewCams extends StatefulWidget {
class ViewEntries extends StatefulWidget {
final DatabasesEnum dbType;
const ViewCams({super.key, required this.dbType});
const ViewEntries({super.key, required this.dbType});
@override
State<ViewCams> createState() => _ViewCamsState();
State<ViewEntries> createState() => _ViewEntriesState();
}
class _ViewCamsState extends State<ViewCams> {
class _ViewEntriesState extends State<ViewEntries> {
// var declaration
late Future<List<Map<String, dynamic>>> mainEntries;
late Future<List<Map<String, dynamic>>> templates;
List<Map<String, dynamic>> mainEntries = [];
List<Map<String, dynamic>> templates = [];
late List<Marker> markers;
IDb? db;
// loads the entries
@override
void initState() {
super.initState();
reloadAllEntries();
}
Future<void> reloadAllEntries() async {
IDb? db;
if (widget.dbType == DatabasesEnum.place) {
db = PlaceDBHelper();
} else if (widget.dbType == DatabasesEnum.excursion) {
db = ExcursionDBHelper();
}
reloadAllEntries();
}
mainEntries = await db!.getAllMainEntries();
templates = await db.getAllTemplates();
Future<void> reloadAllEntries() async {
mainEntries = db!.getAllMainEntries();
templates = db!.getAllTemplates();
setState(() {});
}
// The widet tree with taps to differentiate between templates and finished entries
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3,
length: 2,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
tabs: [
Tab(text: AppLocalizations.of(context)!.completed),
Tab(text: AppLocalizations.of(context)!.uncompleted),
Tab(text: AppLocalizations.of(context)!.map),
// Tab(text: AppLocalizations.of(context)!.map),
],
),
title: Text(AppLocalizations.of(context)!.viewplacesappbar),
@@ -65,264 +69,267 @@ class _ViewCamsState extends State<ViewCams> {
body: TabBarView(
children: [
Tab(
child: FutureBuilder<List<Map<String, dynamic>>>(
future: mainEntries,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
List<Map<String, dynamic>> placeList = List.of(
snapshot.data!,
// child: FutureBuilder<List<Map<String, dynamic>>>(
// future: mainEntries,
// builder: (context, snapshot) {
// if (snapshot.connectionState == ConnectionState.waiting) {
// return const CircularProgressIndicator();
// } else if (snapshot.hasError) {
// return Text('Error: ${snapshot.error}');
// } else {
// List<Map<String, dynamic>> placeList = List.of(
// snapshot.data!,
// );
// return
child: Scaffold(
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.delete),
onPressed: () {
ViewEntriesDialogHelper.deleteAllMainEntries(
context,
widget.dbType,
);
return Scaffold(
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.delete),
onPressed: () {
ViewEntriesDialogHelper.deleteAllMainEntries(
context,
widget.dbType,
);
},
),
body: Column(
children: [
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
const SizedBox(width: 10),
Text(
style: const TextStyle(
decoration: TextDecoration.underline,
),
AppLocalizations.of(context)!.placedata,
),
],
),
Row(
children: [
Text(
style: const TextStyle(
decoration: TextDecoration.underline,
),
AppLocalizations.of(context)!.sent,
),
const SizedBox(width: 10),
],
),
],
),
const SizedBox(height: 15),
Expanded(
child: ListView.builder(
itemCount: placeList.length,
itemBuilder: (context, index) {
Map<String, dynamic> place =
snapshot.data![index];
return Slidable(
startActionPane: ActionPane(
motion: const ScrollMotion(),
children: [
SlidableAction(
onPressed: (context) {
DeleteMainEntries.deleteSingle(
widget.dbType,
place['ID'.toString()],
);
setState(() {
reloadAllEntries();
});
},
backgroundColor: Colors.red,
foregroundColor: Colors.white,
icon: Icons.delete,
label:
AppLocalizations.of(
context,
)!.justdelete,
),
],
),
child: ListTile(
title: Text('Standort ${index + 1}'),
subtitle: Text(
'ID: ${place['ID']} DATUM: ${place['Datum']}',
),
trailing: Checkbox(
value: place['Sent'] == 0 ? false : true,
onChanged: null,
),
onTap: () async {
Navigator.push(
context,
MaterialPageRoute(
builder:
(context) => AddCamMain(
isSent:
place['Sent'] == 1
? true
: false,
existingData: place,
),
),
);
},
),
);
},
),
),
],
),
);
}
},
),
),
Tab(
child: FutureBuilder<List<Map<String, dynamic>>>(
future: templates,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
return Scaffold(
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.delete),
onPressed: () {
ViewEntriesDialogHelper.deleteAllTemplates(
context,
widget.dbType,
);
},
),
body: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
Map<String, dynamic> templates =
snapshot.data![index];
return Slidable(
startActionPane: ActionPane(
motion: const ScrollMotion(),
children: [
SlidableAction(
onPressed: (context) {
DeleteTemplates.deleteSingle(
widget.dbType,
templates['ID'].toString(),
);
setState(() {
reloadAllEntries();
});
},
backgroundColor: Colors.red,
foregroundColor: Colors.white,
icon: Icons.delete,
label:
AppLocalizations.of(
context,
)!.justdelete,
),
],
),
child: ListTile(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder:
(context) => AddCamMain(
isTemplate: true,
existingData: templates,
),
),
);
},
title: Text('Place ${index + 1}'),
subtitle: Text(
'ID: ${templates['CID']} DATUM: ${templates['Datum']} RUDEL: ${templates['Rudel']} STATUS: ${templates['Status']}',
),
),
);
},
),
),
],
),
);
}
},
),
),
Tab(
child: FutureBuilder(
future: mainEntries,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
} else if (snapshot.hasError) {
return Text("Error ${snapshot.error}");
} else {
if (snapshot.data != null) {
markers =
snapshot.data!.map((e) {
return Marker(
width: 80.0,
height: 80.0,
point: LatLng(
double.parse(e['DECLAT'].toString()),
double.parse(e['DECLNG'].toString()),
),
child: Column(
children: [
const Icon(
Icons.location_on,
color: Colors.red,
),
Text(
"ID: ${e['ID'].toString()}",
style: const TextStyle(color: Colors.black),
),
],
),
);
}).toList();
}
return FlutterMap(
options: MapOptions(
initialCenter:
markers.isEmpty
? const LatLng(50, 10)
: markers.first.point,
interactionOptions: const InteractionOptions(
flags:
InteractiveFlag.pinchZoom |
InteractiveFlag.drag |
InteractiveFlag.pinchMove,
),
),
},
),
body: Column(
children: [
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
TileLayer(
urlTemplate:
'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
userAgentPackageName: 'com.example.app',
Row(
children: [
const SizedBox(width: 10),
if (widget.dbType == DatabasesEnum.place)
Text(
style: const TextStyle(
decoration: TextDecoration.underline,
),
AppLocalizations.of(context)!.placedata,
),
if (widget.dbType == DatabasesEnum.excursion)
Text(
style: const TextStyle(
decoration: TextDecoration.underline,
),
// TODO localization
AppLocalizations.of(context)!.homePageTitle,
),
],
),
Row(
children: [
Text(
style: const TextStyle(
decoration: TextDecoration.underline,
),
AppLocalizations.of(context)!.sent,
),
const SizedBox(width: 10),
],
),
MarkerLayer(markers: markers),
],
);
}
},
),
const SizedBox(height: 15),
Expanded(
child: ListView.builder(
itemCount: mainEntries.length,
itemBuilder: (context, index) {
return Slidable(
startActionPane: ActionPane(
motion: const ScrollMotion(),
children: [
SlidableAction(
onPressed: (context) {
DeleteMainEntries.deleteSingle(
widget.dbType,
mainEntries[index]['ID'.toString()],
);
setState(() {
reloadAllEntries();
});
},
backgroundColor: Colors.red,
foregroundColor: Colors.white,
icon: Icons.delete,
label:
AppLocalizations.of(context)!.justdelete,
),
],
),
child: ListTile(
title: Text('Standort ${index + 1}'),
subtitle: Text(
'ID: ${mainEntries[index]['ID']} DATUM: ${mainEntries[index]['Datum']}',
),
trailing: Checkbox(
value: mainEntries[index]['Sent'] == 0 ? false : true,
onChanged: null,
),
onTap: () async {
Navigator.push(
context,
MaterialPageRoute(
builder:
(context) => AddCamMain(
isSent:
mainEntries[index]['Sent'] == 1
? true
: false,
existingData: mainEntries[index],
),
),
);
},
),
);
},
),
),
],
),
),
// } // REMOVE
// }, // REMOVE
// ), // REMOVE
),
Tab(
// child: FutureBuilder<List<Map<String, dynamic>>>(
// future: templates,
// builder: (context, snapshot) {
// if (snapshot.connectionState == ConnectionState.waiting) {
// return const CircularProgressIndicator();
// } else if (snapshot.hasError) {
// return Text('Error: ${snapshot.error}');
// } else {
// return Scaffold(
child: Scaffold(
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.delete),
onPressed: () {
ViewEntriesDialogHelper.deleteAllTemplates(
context,
widget.dbType,
);
},
),
body: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: templates.length,
itemBuilder: (context, index) {
return Slidable(
startActionPane: ActionPane(
motion: const ScrollMotion(),
children: [
SlidableAction(
onPressed: (context) {
DeleteTemplates.deleteSingle(
widget.dbType,
templates[index]['ID'].toString(),
);
setState(() {
reloadAllEntries();
});
},
backgroundColor: Colors.red,
foregroundColor: Colors.white,
icon: Icons.delete,
label:
AppLocalizations.of(context)!.justdelete,
),
],
),
child: ListTile(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder:
(context) => AddCamMain(
isTemplate: true,
existingData: templates[index],
),
),
);
},
title: Text('Place ${index + 1}'),
subtitle: Text(
'ID: ${templates[index]['CID']} DATUM: ${templates[index]['Datum']} RUDEL: ${templates[index]['Rudel']} STATUS: ${templates[index]['Status']}',
),
),
);
},
),
),
],
),
),
// } // REMOVE
// }, // REMOVE
// ), // REMOVE
),
// Tab(
// child: FutureBuilder(
// future: mainEntries,
// builder: (context, snapshot) {
// if (snapshot.connectionState == ConnectionState.waiting) {
// return const CircularProgressIndicator();
// } else if (snapshot.hasError) {
// return Text("Error ${snapshot.error}");
// } else {
// if (snapshot.data != null) {
// markers =
// snapshot.data!.map((e) {
// return Marker(
// width: 80.0,
// height: 80.0,
// point: LatLng(
// double.parse(e['DECLAT'].toString()),
// double.parse(e['DECLNG'].toString()),
// ),
// child: Column(
// children: [
// const Icon(
// Icons.location_on,
// color: Colors.red,
// ),
// Text(
// "ID: ${e['ID'].toString()}",
// style: const TextStyle(color: Colors.black),
// ),
// ],
// ),
// );
// }).toList();
// }
// return FlutterMap(
// options: MapOptions(
// initialCenter:
// markers.isEmpty
// ? const LatLng(50, 10)
// : markers.first.point,
// interactionOptions: const InteractionOptions(
// flags:
// InteractiveFlag.pinchZoom |
// InteractiveFlag.drag |
// InteractiveFlag.pinchMove,
// ),
// ),
// children: [
// TileLayer(
// urlTemplate:
// 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
// userAgentPackageName: 'com.example.app',
// ),
// MarkerLayer(markers: markers),
// ],
// );
// } // REMOVE
// }, // REMOVE
// ), // REMOVE
// ),
],
),
),

View File

@@ -80,3 +80,4 @@
9. mai 3h 40min
10.mai 4h 15min
11.mai 1h 15min
12.mai 5h 30min