Files
flutter_tank_web_app/lib/controller/edit_controller.dart

223 lines
6.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_tank_web_app/services/geolocation_service.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<void> _requestLocationIQ() async {
var geolocationService = GeolocationService();
var locationIQService = LocationIQService();
isLoadingLocation.value = true;
try {
await geolocationService.getCurrentLocation();
if (geolocationService.hasLocation) {
print(
'Aktuelle Position: ${geolocationService.latitude}, ${geolocationService.longitude}',
);
await locationIQService.fetchLocationIQ(
geolocationService.latitude,
geolocationService.longitude,
);
currentLocationIQ = locationIQService.locationIQ;
locationController.text =
currentLocationIQ?.address?.shortAddress ?? '';
} else {
throw Exception('Standort nicht verfügbar');
}
} 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<void> 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<void> 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);
}
}