import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:uuid/uuid.dart'; import '../helper/input_validators.dart'; import '../helper/abfall_berechnung.dart'; import '../models/bauteil_model.dart'; import '../models/kauf_filament_model.dart'; import '../helper/storage_keys.dart'; import '../models/abfall_model.dart'; import '../services/get_storage_services.dart'; class AbfallController extends GetxController { final storage = Get.find(); final abfaelle = [].obs; final datumZeit = DateTime.now().obs; final editingId = RxnString(); final isSaving = false.obs; final message = RxnString(); final hasError = false.obs; final formKey = GlobalKey(); final scrollController = ScrollController(); final kilopreisController = TextEditingController(); final gewichtController = TextEditingController(); final kostenController = TextEditingController(); double get summeAbfall => abfaelle.fold(0, (sum, entry) => sum + entry.gewichtGramm); double get summeKosten => abfaelle.fold(0, (sum, entry) => sum + entry.kosten); @override void onInit() { super.onInit(); loadAbfaelle(); } void loadAbfaelle() { final entries = storage .getModelList(StorageKeys.abfaelle) .map(AbfallModel.fromJson) .toList(); final filamente = storage .getModelList(StorageKeys.filamente) .map(KaufFilamentModel.fromJson) .toList(); for (final bauteil in storage .getModelList(StorageKeys.bauteile) .map(BauteilModel.fromJson)) { if (bauteil.abfallGramm <= 0) continue; final kosten = bauteil.abfallKosten ?? AbfallBerechnung.kosten(bauteil, filamente); entries.add( AbfallModel( abfallId: 'bauteil:${bauteil.bauteilId}', bauteilId: bauteil.bauteilId, bauteilName: bauteil.name, datumZeit: bauteil.erstelltAm, gewichtGramm: bauteil.abfallGramm, kosten: kosten ?? 0, kostenUnbekannt: kosten == null, kostenNachtraeglich: bauteil.abfallKosten == null && kosten != null, ), ); } entries.sort((a, b) => b.datumZeit.compareTo(a.datumZeit)); abfaelle.assignAll(entries); } void berechneKosten(String _) { final kilopreis = InputValidators.number(kilopreisController.text); final gewicht = InputValidators.number(gewichtController.text); if (kilopreis == null || !kilopreis.isFinite || kilopreis < 0 || gewicht == null || !gewicht.isFinite || gewicht <= 0) { return; } final kosten = gewicht / 1000 * kilopreis; if (!kosten.isFinite) return; kostenController.text = kosten.toStringAsFixed(2).replaceAll('.', ','); } void setDatum(DateTime date) { final current = datumZeit.value; datumZeit.value = DateTime( date.year, date.month, date.day, current.hour, current.minute, ); } void setUhrzeit(TimeOfDay time) { final current = datumZeit.value; datumZeit.value = DateTime( current.year, current.month, current.day, time.hour, time.minute, ); } Future _commit(List entries) async { await storage.saveModelList( StorageKeys.abfaelle, entries.map((entry) => entry.toJson()).toList(), ); loadAbfaelle(); } Future saveAbfall() async { if (isSaving.value) return; message.value = null; if (!(formKey.currentState?.validate() ?? false)) return; isSaving.value = true; try { final entries = storage .getModelList(StorageKeys.abfaelle) .map(AbfallModel.fromJson) .toList(); final id = editingId.value; if (id != null && !entries.any((entry) => entry.abfallId == id)) { throw StateError('Eintrag nicht gefunden'); } final entry = AbfallModel( abfallId: id ?? const Uuid().v4(), datumZeit: datumZeit.value, gewichtGramm: InputValidators.number(gewichtController.text)!, kosten: InputValidators.number(kostenController.text)!, ); await _commit([ ...entries.where((item) => item.abfallId != entry.abfallId), entry, ]); resetForm(); hasError.value = false; message.value = 'Abfall gespeichert.'; } catch (_) { hasError.value = true; message.value = 'Speichern fehlgeschlagen. Bitte erneut versuchen.'; } finally { isSaving.value = false; } } Future editAbfall(AbfallModel entry) async { if (isSaving.value || entry.ausBauteil) return; message.value = null; editingId.value = entry.abfallId; datumZeit.value = entry.datumZeit; gewichtController.text = entry.gewichtGramm.toString().replaceAll('.', ','); kostenController.text = entry.kosten.toString().replaceAll('.', ','); if (scrollController.hasClients) { await scrollController.animateTo( 0, duration: const Duration(milliseconds: 300), curve: Curves.easeOutCubic, ); } } Future deleteAbfall(String id) async { if (isSaving.value || abfaelle.any((item) => item.abfallId == id && item.ausBauteil)) { return; } isSaving.value = true; try { final entries = storage .getModelList(StorageKeys.abfaelle) .map(AbfallModel.fromJson) .where((entry) => entry.abfallId != id) .toList(); await _commit(entries); if (editingId.value == id) resetForm(); hasError.value = false; message.value = 'Abfall gelöscht.'; } catch (_) { hasError.value = true; message.value = 'Löschen fehlgeschlagen. Bitte erneut versuchen.'; } finally { isSaving.value = false; } } void resetForm() { final kilopreis = kilopreisController.text; formKey.currentState?.reset(); kilopreisController.text = kilopreis; editingId.value = null; datumZeit.value = DateTime.now(); gewichtController.clear(); kostenController.clear(); message.value = null; hasError.value = false; } @override void onClose() { scrollController.dispose(); kilopreisController.dispose(); gewichtController.dispose(); kostenController.dispose(); super.onClose(); } }