mod switch between pages and remove errors

This commit is contained in:
atseirjo 2025-10-28 14:01:34 +01:00
parent 059b4773f4
commit 461b07bf10
6 changed files with 211 additions and 44 deletions

View File

@ -4,7 +4,8 @@ import '../controllers/login_controller.dart';
class LoginBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut<LoginController>(() => LoginController());
// Permanent für bessere Controller-Stabilität
Get.put<LoginController>(LoginController(), permanent: true);
}
}

View File

@ -1,3 +1,4 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:geolocator/geolocator.dart';
import '../../services/geolocation.dart';
@ -47,15 +48,10 @@ class GeolocationController extends GetxController {
} else {
_ptvModel.value = null;
}
// Erfolgs-Snackbar anzeigen
Get.snackbar(
'Position ermittelt',
'Aktuelle Position wurde erfolgreich abgerufen',
snackPosition: SnackPosition.BOTTOM,
);
debugPrint('Position ermittelt: ${_currentPosition.value}');
} else {
_statusText.value = 'Position konnte nicht ermittelt werden';
debugPrint('Fehler beim Abrufen der Position');
// Fehler-Snackbar anzeigen
Get.snackbar(
'Fehler',
@ -172,14 +168,17 @@ class GeolocationController extends GetxController {
_isLoading.value = true;
_statusText.value = 'Berechtigungen werden geprüft...';
LocationPermission permission = await GeolocationService.checkPermission();
LocationPermission permission =
await GeolocationService.checkPermission();
bool serviceEnabled = await GeolocationService.isLocationServiceEnabled();
_statusText.value = 'Service aktiv: $serviceEnabled\n'
_statusText.value =
'Service aktiv: $serviceEnabled\n'
'Berechtigung: ${LocationPermissionHelper.getPermissionStatusText(permission)}';
// Detaillierte Information in Snackbar
String permissionStatus = LocationPermissionHelper.getPermissionStatusText(permission);
String permissionStatus =
LocationPermissionHelper.getPermissionStatusText(permission);
Get.snackbar(
'Berechtigungs-Status',
'Location Service: ${serviceEnabled ? "Aktiv" : "Inaktiv"}\n$permissionStatus',

View File

@ -8,33 +8,76 @@ import '../routes/app_routes.dart';
class InputController extends GetxController {
final GeolocationController geoCtrl = Get.put(GeolocationController());
final LoginController loginCtrl = Get.put(LoginController());
// Lazy-get für LoginController - wird nur erstellt wenn benötigt
LoginController get loginCtrl => Get.find<LoginController>();
final _ptvModel = Rxn<PTVModel>();
final _user = (Get.arguments as user_models.User).obs;
final formKey = GlobalKey<FormState>();
late TextEditingController dateController;
late TextEditingController odometerController;
late TextEditingController litersController;
late TextEditingController pricePerLiterController;
late TextEditingController locationController;
late TextEditingController sumPriceController;
PTVModel? get ptvModel => _ptvModel.value;
user_models.User? get currentUser => _user.value;
// Sichere Getter für Controller-Text
String get safeDate => _isControllerValid(dateController) ? dateController.text : '';
String get safeLocation => _isControllerValid(locationController) ? locationController.text : '';
// Hilfsmethode zur Controller-Validierung
bool _isControllerValid(TextEditingController? controller) {
try {
return controller != null && controller.text.isNotEmpty;
} catch (e) {
return false;
}
}
@override
void onInit() {
_initController();
_getLocation();
super.onInit();
}
void _initController() {
dateController = TextEditingController();
odometerController = TextEditingController();
litersController = TextEditingController();
pricePerLiterController = TextEditingController();
locationController = TextEditingController();
sumPriceController = TextEditingController();
// init Date today to dateController
dateController.text = DateTime.now().toString().split(' ').first;
}
@override
void onReady() {}
@override
void onClose() {
// Dispose aller TextEditingController
dateController.dispose();
odometerController.dispose();
litersController.dispose();
pricePerLiterController.dispose();
locationController.dispose();
sumPriceController.dispose();
geoCtrl.onClose();
loginCtrl.onClose();
// LoginController nicht schließen da er permanent sein könnte
super.onClose();
}
void _getLocation() async {
await geoCtrl.getCurrentPosition().then(
(_) => {_ptvModel.value = geoCtrl.ptvModel},
(_) => {
_ptvModel.value = geoCtrl.ptvModel,
locationController.text = geoCtrl.ptvModel?.locations?.first.formattedAddress ?? '',
},
);
update();
}
@ -43,9 +86,43 @@ class InputController extends GetxController {
//AppNavigation.goToListPage
}
void logout() {
loginCtrl.logout();
//AppNavigation.toLogin();
void logout() async {
// Zeige Loading um weitere Interaktionen zu verhindern
Get.dialog(
const Center(
child: CircularProgressIndicator(),
),
barrierDismissible: false,
);
try {
// Kurze Verzögerung um sicherzustellen dass UI Updates verarbeitet werden
await Future.delayed(const Duration(milliseconds: 100));
// Logout ausführen
await loginCtrl.logout();
// Dialog schließen
if (Get.isDialogOpen == true) {
Get.back();
}
// Navigation nach kurzer Verzögerung
await Future.delayed(const Duration(milliseconds: 100));
AppNavigation.offAllToLogin();
} catch (e) {
// Dialog schließen bei Fehler
if (Get.isDialogOpen == true) {
Get.back();
}
Get.snackbar(
'Fehler',
'Logout fehlgeschlagen: $e',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.red.shade500,
);
}
}
}

View File

@ -24,6 +24,23 @@ class LoginController extends GetxController {
account_models.Account? get account => _account.value;
user_models.User? get logedInUser => _logedInUser.value;
// Sichere Getter für Controller
String get safeEmail => _isControllerValid(mailController) ? mailController.text : '';
String get safePassword => _isControllerValid(passwordController) ? passwordController.text : '';
String get safeName => _isControllerValid(nameController) ? nameController.text : '';
// Hilfsmethode zur Controller-Validierung
bool _isControllerValid(TextEditingController? controller) {
try {
if (controller == null) return false;
// Teste ob der Controller noch verwendbar ist
controller.text;
return true;
} catch (e) {
return false;
}
}
@override
void onInit() {
// Initialisiere TextEditingController
@ -71,6 +88,17 @@ class LoginController extends GetxController {
Future<void> login() async {
logout();
try {
// Sichere Controller-Zugriffe
if (!_isControllerValid(mailController) || !_isControllerValid(passwordController)) {
Get.snackbar(
'Fehler',
'Formular nicht verfügbar. Bitte laden Sie die Seite neu.',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.red.shade500,
);
return;
}
var result = await _account.value!.createEmailPasswordSession(
email: mailController.text,
password: passwordController.text,
@ -107,13 +135,30 @@ class LoginController extends GetxController {
}
clearFields() {
mailController.clear();
passwordController.clear();
nameController.clear();
try {
if (_isControllerValid(mailController)) mailController.clear();
if (_isControllerValid(passwordController)) passwordController.clear();
if (_isControllerValid(nameController)) nameController.clear();
} catch (e) {
// Ignore dispose errors beim Clearing
}
}
Future<void> register() async {
try {
// Sichere Controller-Zugriffe
if (!_isControllerValid(mailController) ||
!_isControllerValid(passwordController) ||
!_isControllerValid(nameController)) {
Get.snackbar(
'Fehler',
'Formular nicht verfügbar. Bitte laden Sie die Seite neu.',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.red.shade500,
);
return;
}
await _account.value!.create(
userId: ID.unique(),
email: mailController.text,
@ -142,15 +187,31 @@ class LoginController extends GetxController {
}
Future<void> logout() async {
try {
await _account.value!.deleteSession(sessionId: 'current');
_logedInUser.value = null;
// Erfolgsmeldung nur wenn noch nicht navigiert wurde
if (Get.currentRoute != '/login') {
Get.snackbar(
'Erfolg',
'Logout erfolgreich',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.red.shade500,
backgroundColor: Colors.green.shade500,
);
}
} catch (e) {
if (Get.currentRoute != '/login') {
Get.snackbar(
'Meldung',
'Keine aktive Sitzung zum Abmelden',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.orange.shade500,
);
}
debugPrint('Logout error: $e');
}
}
@override
void onClose() {

View File

@ -45,7 +45,8 @@ class InputPage extends GetView<InputController> {
children: [
Obx(
() => inputCtrl.ptvModel != null && inputCtrl.currentUser != null
? Text('UserEmail: ${inputCtrl.currentUser!.email}\nName: ${inputCtrl.currentUser!.name}\nFormattedAddress: ${inputCtrl.ptvModel!.locations!.first.formattedAddress}',
? Text(
'DateNow: ${inputCtrl.safeDate}\nUserEmail: ${inputCtrl.currentUser!.email}\nName: ${inputCtrl.currentUser!.name}\nFormattedAddress: ${inputCtrl.safeLocation}',
)
: const Text('Keine Daten gefunden'),
),

View File

@ -18,8 +18,36 @@ class MyFormField extends StatelessWidget {
final TextInputType keyboardType;
final String? Function(String?)? validator;
// Prüft ob Controller noch verwendbar ist
bool _isControllerValid() {
try {
userController.text;
return true;
} catch (e) {
return false;
}
}
@override
Widget build(BuildContext context) {
// Wenn Controller disposed ist, zeige Ersatz-Widget
if (!_isControllerValid()) {
return Container(
height: 56,
decoration: BoxDecoration(
color: fillColor,
borderRadius: BorderRadius.circular(4),
border: Border.all(color: Colors.grey),
),
child: Center(
child: Text(
'$labelText (Controller nicht verfügbar)',
style: TextStyle(color: Colors.grey[600]),
),
),
);
}
return TextFormField(
autovalidateMode: AutovalidateMode.onUserInteraction,
style: const TextStyle(color: Colors.black),