import 'package:appwrite/appwrite.dart'; import 'package:appwrite/models.dart' as models; import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; import 'package:intl/intl.dart'; import '../../utils/extensions/static_helper.dart'; import '../../data/repository/location_repository.dart'; import '../../data/repository/appwrite_repository.dart'; import '../login/login_view.dart'; import '../tanklist/tanklist_view.dart'; class TankController extends GetxController { final _dataBox = GetStorage('MyUserStorage'); //AppWrite API-REST get Data final AppwriteRepository _authRepository = AppwriteRepository(); // GEOLOCATING Services final LocationRepository _locationRepository = LocationRepository(); // Rx-Variablen für die UI, um auf Änderungen zu reagieren final circleAvatarUserChar = 'A'.obs; final userNameToDisplay = 'Test User'.obs; final Rx currentPosition = Rx(null); final Rx isLoading = false.obs; final Rx errorMessage = Rx(null); //final rxOrtString = '?'.obs; final rxSessionIdString = '?'.obs; final rxSummePreisString = '0.00'.obs; // TextEditingController für die Formulareingaben final formKeyTank = GlobalKey(); bool isFormValid = false; DateTime? _selectedDateTime; final dateController = TextEditingController(); final f = DateFormat('yyyy-MM-dd'); final kilometerStandEdittingController = TextEditingController(); final mengeController = TextEditingController(); final pricePerLiterController = TextEditingController(); final ortController = TextEditingController(); final FocusNode firstFocusNode = FocusNode(); // Deklariere den FocusNode final isEditMode = false.obs; String documentId = ''; // Methode für das ausgewählte Datum Future selectDateTime(BuildContext context) async { // 1. Datum auswählen final DateTime? pickedDate = await showDatePicker( context: context, initialDate: _selectedDateTime ?? DateTime.now(), firstDate: DateTime(2000), lastDate: DateTime(2101), ); _selectedDateTime = pickedDate; if (_selectedDateTime != null) { dateController.text = _selectedDateTime!.toIso8601String().substring( 0, 10, ); } } /// Methode zum Abrufen des Standorts. Future fetchCurrentLocation() async { isLoading.value = true; errorMessage.value = null; try { final Position position = await _locationRepository.getCurrentPosition(); currentPosition.value = position; final double latitude = position.latitude; final double longitude = position.longitude; // Hier kannst du die Logik hinzufügen, um den Standort zu verwenden, z.B. // den Standort in der UI anzuzeigen oder an einen Server zu senden. var map = {'lat': latitude, 'lng': longitude}; var loc = await _locationRepository.getNearbyLocation(map); ortController.text = loc; // Print Standortinformationen in der Konsole print('Nearby Location: $loc'); print('Current Position: Latitude: $latitude, Longitude: $longitude'); } catch (e) { // Hier fängst du die Fehler aus dem Repository auf errorMessage.value = e.toString(); } finally { isLoading.value = false; } update(); } void clearTextEditingController() { formKeyTank.currentState!.reset(); // Den Fokus wieder auf das erste Feld legen FocusScope.of(Get.context!).requestFocus(firstFocusNode); // TextEditingController zurücksetzen _selectedDateTime = null; // Datum zurücksetzen dateController.clear(); kilometerStandEdittingController.clear(); mengeController.clear(); pricePerLiterController.clear(); ortController.clear(); } String? validateKilometerStand(String? value) { if (value == null || value.isEmpty) { return 'Bitte Kilometerstand eingeben'; } if (!GetUtils.isNum(value)) { return 'Bitte geben Sie eine gültige Zahl ein'; } return null; } String? validateMenge(String? value) { if (value == null || value.isEmpty) { return 'Bitte Menge eingeben'; } if (!GetUtils.isNum(value)) { return 'Bitte geben Sie eine gültige Zahl ein'; } return null; } String? validatePricePerLiter(String? value) { if (value == null || value.isEmpty) { return 'Bitte Preis pro Liter eingeben'; } if (!GetUtils.isNum(value)) { return 'Bitte geben Sie eine gültige Zahl ein'; } return null; } String? validateOrt(String? value) { if (value == null || value.isEmpty) { return 'Bitte Ort eingeben...'; } return null; } //Go to Login Page void logoutSessionAndGoToLoginPage() async { // Handle logout logic here print('Logout session and go to login page'); // Clear GetStorage session ID StaticHelper.removeFromStorage(); print('Session ID removed from GetStorage'); await _authRepository.logout(); Get.offAndToNamed(LoginPage.namedRoute); StaticHelper.getMySnackeBar( 'Logout', 'Sie wurden abgemeldet!', Colors.blue); } @override void onInit() { super.onInit(); handleInputOrUpdate(); } void handleInputOrUpdate() { var mapFromArguments = Get.arguments as Map?; if (mapFromArguments != null && mapFromArguments['from'] != null) { isEditMode.value = mapFromArguments['from'] == 'Input' ? true : false; } //bei true ein insert bei false ein update if (isEditMode.value) { fetchCurrentLocation(); } else { // Im Editiermodus, keine Standortabfrage durchführen print('Im Editiermodus, keine Standortabfrage durchführen'); // Den Fokus auf das erste Eingabefeld setzen FocusScope.of(Get.context!).requestFocus(firstFocusNode); print('TankController is in Edit Mode'); if (mapFromArguments != null && mapFromArguments['data'] != null) { var dataMap = mapFromArguments['data'] as Map; print('Data Map for Edit Mode: $dataMap'); // Setze die documentId für spätere Updates documentId = dataMap['\$id'] ?? ''; // Setze die Werte in die TextEditingController dateController.text = dataMap['date'] ?? ''; kilometerStandEdittingController.text = dataMap['odometer'] ?? ''; mengeController.text = dataMap['liters'] ?? ''; pricePerLiterController.text = dataMap['pricePerLiter'] ?? ''; ortController.text = dataMap['location'] ?? ''; // Berechne den Gesamtpreis updateSumPrice(); } } } @override void onReady() async { super.onReady(); if (_dataBox.hasData('sessionId')) { rxSessionIdString(_dataBox.read('sessionId').toString()); } await getCurrentLoggedinUser(); FocusScope.of(Get.context!).requestFocus(firstFocusNode); print('TankController is ready'); } Future getCurrentLoggedinUser() async { await _authRepository.getCurrentUser.then((models.User user) { // Hier kannst du den Benutzernamen und das Avatar-Zeichen setzen userNameToDisplay.value = user.name; circleAvatarUserChar.value = user.name.substring(0, 1).toUpperCase(); }).catchError((error) { print('Fehler beim Abrufen des Benutzers: $error'); }); } @override void onClose() { dateController.dispose(); kilometerStandEdittingController.dispose(); mengeController.dispose(); pricePerLiterController.dispose(); ortController.dispose(); firstFocusNode.dispose(); // Dispose den FocusNode } void updateSumPrice() { final double menge = double.tryParse(mengeController.text) ?? 0.0; final double pricePerLiter = double.tryParse(pricePerLiterController.text) ?? 0.0; final double sumPrice = menge * pricePerLiter; rxSummePreisString.value = sumPrice.toStringAsFixed( 2, ); // Formatieren auf 2 Dezimalstellen } void saveTankstopp() async { bool isErrorBySaving = false; String messageToUser = ''; isFormValid = formKeyTank.currentState!.validate(); if (!isFormValid) { print('Formular ist ungültig'); messageToUser = 'Bitte überprüfen Sie Ihre Eingaben.'; Get.snackbar( 'Fehler', messageToUser, snackPosition: SnackPosition.BOTTOM, duration: const Duration(seconds: 2), ); return; } else { print('Formular ist gültig'); formKeyTank.currentState!.save(); try { //false update a tank stop if (isEditMode.value == false) { await _authRepository.updateTankStop(documentId, { 'userId': _dataBox.read('userId'), 'date': f.format(DateTime.parse(dateController.text)), 'odometer': kilometerStandEdittingController.text, 'liters': mengeController.text, 'pricePerLiter': pricePerLiterController.text, 'location': ortController.text, }).then((models.Document document) { print('Tankstopp erfolgreich aktualisiert: ${document.data}'); messageToUser = 'Tankstopp erfolgreich aktualisiert!'; isErrorBySaving = false; }) // Handle specific Appwrite exceptions .catchError((error) { isErrorBySaving = true; if (error is AppwriteException) { // Handle specific Appwrite exceptions messageToUser = 'Appwrite Fehler: ${error.message}'; print('Appwrite Fehler: ${error.message}'); } else { // Handle other types of errors messageToUser = 'Allgemeiner Fehler: $error'; print('Allgemeiner Fehler: $error'); } print('Fehler bei der speicherung: $error'); }); } else { //true creating a tank stop await _authRepository.createTankStop({ 'userId': _dataBox.read('userId'), 'date': f.format(DateTime.parse(dateController.text)), 'odometer': kilometerStandEdittingController.text, 'liters': mengeController.text, 'pricePerLiter': pricePerLiterController.text, 'location': ortController.text, }).then((models.Document document) { print('Tankstopp erfolgreich gespeichert: ${document.data}'); messageToUser = 'Tankstopp erfolgreich gespeichert!'; isErrorBySaving = false; }) // Handle specific Appwrite exceptions .catchError((error) { isErrorBySaving = true; if (error is AppwriteException) { // Handle specific Appwrite exceptions messageToUser = 'Appwrite Fehler: ${error.message}'; print('Appwrite Fehler: ${error.message}'); } else { // Handle other types of errors messageToUser = 'Allgemeiner Fehler: $error'; print('Allgemeiner Fehler: $error'); } print('Fehler bei der speicherung: $error'); }); // bei true ein insert } } // Handle any other exceptions that might occur catch (e) { isErrorBySaving = true; messageToUser = 'Fehler beim Speichern des Tankstopps: $e'; print('Fehler beim speichern: $e'); } if (!isErrorBySaving) { clearTextEditingController(); } // Handle button press logic here String title = isErrorBySaving ? 'Fehler' : 'Erfolg'; Get.snackbar( title, messageToUser, backgroundColor: isErrorBySaving ? Colors.red : Colors.green, snackPosition: SnackPosition.BOTTOM, duration: const Duration(seconds: 4), ); goToTankStopsView(); } } goToTankStopsView() async { clearTextEditingController(); await Get.offAndToNamed(TanklistPage.namedRoute); } }