import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:geolocator/geolocator.dart'; import '../models/locationiq_model.dart'; import '../models/tank_model.dart'; import '../services/appwrite_service.dart'; import '../services/location_iq_service.dart'; import '../pages/home_view.dart'; class EditController extends GetxController { final AppwriteService appwriteService = AppwriteService(); // Form controllers final dateController = TextEditingController(); final odometerController = TextEditingController(); final litersController = TextEditingController(); final pricePerLiterController = TextEditingController(); final locationController = TextEditingController(); // Observable states final isLoading = false.obs; final isNewEntry = true.obs; final calculatedTotal = '0.00'.obs; final isLoadingLocation = false.obs; TankModel? editingTankModel; LocationIQ? currentLocationIQ; @override void onInit() { super.onInit(); // Check if we're editing or creating new if (Get.arguments != null) { editingTankModel = Get.arguments as TankModel; isNewEntry.value = false; _loadExistingData(); } else { isNewEntry.value = true; _setDefaultDate(); _requestLocationIQ(); } // Add listeners for automatic calculation litersController.addListener(_calculateTotal); pricePerLiterController.addListener(_calculateTotal); } void _loadExistingData() { dateController.text = editingTankModel!.szDate; odometerController.text = editingTankModel!.szOdometer; litersController.text = editingTankModel!.szLiters; pricePerLiterController.text = editingTankModel!.szPricePerLiter; locationController.text = editingTankModel!.szLocation; calculatedTotal.value = editingTankModel!.szPriceTotal; } void _setDefaultDate() { final now = DateTime.now(); dateController.text = '${now.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')}'; } Future _requestLocationIQ() async { bool serviceEnabled; LocationPermission permission; try { isLoadingLocation.value = true; // 1. Prüfen, ob Standortdienste aktiviert sind serviceEnabled = await Geolocator.isLocationServiceEnabled(); if (!serviceEnabled) { return Future.error('Standortdienste sind deaktiviert.'); } // 2. Berechtigungen prüfen permission = await Geolocator.checkPermission(); if (permission == LocationPermission.denied) { permission = await Geolocator.requestPermission(); if (permission == LocationPermission.denied) { return Future.error('Berechtigung verweigert.'); } } // 3. Position abrufen Position position = await Geolocator.getCurrentPosition( locationSettings: const LocationSettings( accuracy: LocationAccuracy.high, ), ); // 4. Standort über Backend-Proxy abrufen var lat = position.latitude; var lon = position.longitude; print('📍 Verwende LocationIQ für Geocoding...'); final LocationIQService locationIQService = LocationIQService(); await locationIQService.fetchLocationIQ(lat, lon); currentLocationIQ = locationIQService.locationIQ; locationController.text = currentLocationIQ?.address?.shortAddress ?? ''; } catch (e) { Get.snackbar( "Fehler", "Standort konnte nicht abgerufen werden: $e", snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.red[100], colorText: Colors.red[900], ); print("Fehler beim Abrufen des Standorts: $e"); locationController.text = ''; } finally { isLoadingLocation.value = false; } } void _calculateTotal() { final liters = double.tryParse(litersController.text.replaceAll(',', '.')) ?? 0.0; final pricePerLiter = double.tryParse(pricePerLiterController.text.replaceAll(',', '.')) ?? 0.0; calculatedTotal.value = (liters * pricePerLiter).toStringAsFixed(2); print('$liters L * $pricePerLiter €/L = ${calculatedTotal.value} €'); } Future selectDate(BuildContext context) async { final DateTime? picked = await showDatePicker( context: context, initialDate: DateTime.now(), firstDate: DateTime(2020), lastDate: DateTime.now(), builder: (context, child) { return Theme( data: ThemeData.light().copyWith( colorScheme: ColorScheme.light( primary: Colors.blueGrey[700]!, onPrimary: Colors.white, ), ), child: child!, ); }, ); if (picked != null) { dateController.text = '${picked.year}-${picked.month.toString().padLeft(2, '0')}-${picked.day.toString().padLeft(2, '0')}'; } } Future saveTankEntry() async { if (!_validateForm()) { Get.snackbar( 'Validierungsfehler', 'Bitte füllen Sie alle Pflichtfelder aus', snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.red[100], colorText: Colors.red[900], ); return; } isLoading.value = true; try { final userId = await appwriteService.getCurrentUserId(); if (userId == null) { throw Exception('Benutzer nicht eingeloggt'); } final data = { 'userId': userId, 'date': dateController.text, 'odometer': odometerController.text, 'liters': litersController.text.replaceAll(',', '.'), 'pricePerLiter': pricePerLiterController.text.replaceAll(',', '.'), 'location': locationController.text, }; bool success; if (isNewEntry.value) { success = await appwriteService.createDocumentInCollection(data); } else { success = await appwriteService.updateDocumentInCollection( editingTankModel!.szDocumentId, data, ); } if (success) { Get.snackbar( 'Erfolgreich', isNewEntry.value ? 'Tankeintrag erstellt' : 'Tankeintrag aktualisiert', snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.green[100], colorText: Colors.green[900], ); Get.offAllNamed(HomePage.namedRoute); } else { throw Exception('Speichern fehlgeschlagen'); } } catch (e) { Get.snackbar( 'Fehler', 'Beim Speichern ist ein Fehler aufgetreten: $e', snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.red[100], colorText: Colors.red[900], ); } finally { isLoading.value = false; } } bool _validateForm() { return dateController.text.isNotEmpty && odometerController.text.isNotEmpty && litersController.text.isNotEmpty && pricePerLiterController.text.isNotEmpty; } @override void onClose() { dateController.dispose(); odometerController.dispose(); litersController.dispose(); pricePerLiterController.dispose(); locationController.dispose(); super.onClose(); } void gotToList() { Get.offAllNamed(HomePage.namedRoute); } }