222 lines
6.5 KiB
Dart
222 lines
6.5 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import '../models/locationiq_model.dart';
|
|
import '../models/tank_model.dart';
|
|
import '../services/appwrite_service.dart';
|
|
import '../services/geolocation_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);
|
|
}
|
|
}
|