import 'dart:async'; import 'package:drift/drift.dart'; import 'package:flutter/material.dart'; import '../Entities/drift_database.dart'; import '../Entities/time_frame_enum.dart'; import '../Pages/Dialog/dialog_action.dart'; import '../Pages/Dialog/dialog_input_field.dart'; import '../Pages/Dialog/dialog_input_field_select_item.dart'; import '../Pages/Dialog/dialog_input_field_type_enum.dart'; import '../Pages/Dialog/dialog_type_enum.dart'; import '../Pages/Dialog/dynamic_dialog.dart'; import '../Repositories/recurring_transacation_repository.dart'; import 'account_controller.dart'; /// Steuert die Interaktion mit den wiederkehrenden Transaktionen class RecurringTransactionController { /// Gibt die aktuell gültige Instanz der Klasse zurück factory RecurringTransactionController() => _instance; /// Erstellt eine neue Instanz dieser Klasse RecurringTransactionController._internal() { _newRecurringTransactionDialog = DynamicDialog( title: 'Neue wiederkehrende Transaktion erstellen', icon: Icons.repeat, inputFields: [ const DialogInputField(id: 'name', label: 'Name', autoFocus: true), const DialogInputField( id: 'startDate', label: 'Anfangsdatum', keyboardType: TextInputType.datetime, inputType: DialogInputFieldTypeEnum.date, ), DialogInputField( id: 'timeFrame', label: 'Zeitraum', inputType: DialogInputFieldTypeEnum.select, selectItems: TimeFrameEnum.values .map( (final value) => DialogInputFieldSelectItem( id: value.index, value: value.name, ), ) .toList(), ), const DialogInputField( id: 'amount', label: 'Betrag €', keyboardType: TextInputType.number, ), ], actions: [ DialogAction(label: 'Abbruch'), DialogAction( label: 'Speichern', isPrimary: true, onPressed: _saveNewRecurringTransaction, ), ], ); _errorRecurringTransactionValueEmptyDialog = DynamicDialog( title: 'Fehler!', icon: Icons.error, content: const Text('Es wurden nicht alle Werte eingetragen!'), dialogType: DialogTypeEnum.error, ); _recurringTransactionCreatedDialog = DynamicDialog( title: 'Wiederkehrende Transaktion erstellt!', icon: Icons.check_circle, content: const Text( 'Die wiederkehrende Transaktion wurde erfolgreich erstellt!', ), dialogType: DialogTypeEnum.success, ); _selectedAccount = _accountController.selected.value; _accountController.selected.addListener(() { _selectedAccount = _accountController.selected.value; unawaited(updateRecurringTransactions()); }); unawaited(updateRecurringTransactions()); } static final RecurringTransactionController _instance = RecurringTransactionController._internal(); final RecurringTransactionRepository _recurringTransactionRepository = RecurringTransactionRepository(); final AccountController _accountController = AccountController(); DynamicDialog? _newRecurringTransactionDialog; DynamicDialog? _errorRecurringTransactionValueEmptyDialog; DynamicDialog? _recurringTransactionCreatedDialog; final ValueNotifier> _recurringTransactions = ValueNotifier>([]); /// Stellt die Liste der wiederkehrenden Transaktionen dar ValueNotifier> get recurringTransactions { if (_recurringTransactions.value == []) { unawaited(updateRecurringTransactions()); } return _recurringTransactions; } set recurringTransactions( final List recurringTransactions, ) { _recurringTransactions.value = recurringTransactions; } Account? _selectedAccount; /// Aktualisiert die gespeicherten wiederkehrenden Transaktionen /// in der internen Liste. Future updateRecurringTransactions() async { if (_selectedAccount != null) { final List recurringTransactions = await _recurringTransactionRepository.findBy( account: _selectedAccount, orderBy: 'nameAsc', ); _recurringTransactions.value = recurringTransactions; } } /// Startet den Prozess, um eine neue wiederkehrende Transaktion anzulegen void newRecurringTransactionHandler() { unawaited(_newRecurringTransactionDialog?.show()); } /// Startet den Prozess, um eine wiederkehrende Transaktion zu bearbeiten Future editRecurringTransactionHandler( final int recurringTransactionId, ) async { final RecurringTransaction? recurringTransaction = await _recurringTransactionRepository.find(recurringTransactionId); if (recurringTransaction != null) { final editRecurringTransactionDialog = DynamicDialog( title: '${recurringTransaction.name} bearbeiten', icon: Icons.edit, inputFields: [ DialogInputField( id: 'name', label: 'Name', autoFocus: true, initialValue: recurringTransaction.name, ), DialogInputField( id: 'startDate', label: 'Anfangsdatum', keyboardType: TextInputType.datetime, inputType: DialogInputFieldTypeEnum.date, initialValue: recurringTransaction.startDate, ), DialogInputField( id: 'timeFrame', label: 'Zeitraum', inputType: DialogInputFieldTypeEnum.select, selectItems: TimeFrameEnum.values .map( (final value) => DialogInputFieldSelectItem( id: value.index, value: value.name, ), ) .toList(), initialValue: recurringTransaction.timeFrame, ), DialogInputField( id: 'amount', label: 'Betrag €', keyboardType: TextInputType.number, initialValue: recurringTransaction.amount.toString(), ), ], actions: [ DialogAction(label: 'Abbruch'), DialogAction( label: 'Bearbeiten', isPrimary: true, onPressed: _editRecurringTransaction, ), ], hiddenValues: {'recurringTransaction': recurringTransaction}, ); unawaited(editRecurringTransactionDialog.show()); } } /// Startet den Prozess, um eine wiederkehrende Transaktion zu löschen Future deleteRecurringTransactionHandler( final int recurringTransactionId, ) async { final RecurringTransaction? recurringTransaction = await _recurringTransactionRepository.find(recurringTransactionId); if (recurringTransaction != null) { final deleteRecurringTransactionDialog = DynamicDialog( dialogType: DialogTypeEnum.error, title: '${recurringTransaction.name} löschen', content: Text( 'Willst du ${recurringTransaction.name} wirklich löschen?', ), icon: Icons.delete_forever, actions: [ DialogAction(label: 'Abbruch', isPrimary: true), DialogAction( label: 'Löschen', onPressed: _deleteRecurringTransaction, ), ], hiddenValues: {'recurringTransaction': recurringTransaction}, ); unawaited(deleteRecurringTransactionDialog.show()); } } Future _saveNewRecurringTransaction( final Map values, ) async { if (values['name'] == null || values['name'] == '' || values['startDate'] == null || values['startDate'] == '' || values['timeFrame'] == null || values['timeFrame'] == '' || values['amount'] == null || values['amount'] == '' || _selectedAccount == null) { await _errorRecurringTransactionValueEmptyDialog?.show(); } else { final DialogInputFieldSelectItem timeFrame = values['timeFrame']; values['timeFrame'] = TimeFrameEnum.values[timeFrame.id]; final String amount = values['amount']; values['amount'] = double.tryParse(amount); if (values['amount'] == null || values['amount'] == 0) { await _errorRecurringTransactionValueEmptyDialog?.show(); } else { final recurringTransaction = RecurringTransactionsCompanion( name: Value(values['name']), startDate: Value(values['startDate']), timeFrame: Value(values['timeFrame']), amount: Value(values['amount']), accountId: Value(_selectedAccount!.id), ); await _recurringTransactionRepository.add(recurringTransaction); await _recurringTransactionCreatedDialog?.show(); await updateRecurringTransactions(); } } } Future _editRecurringTransaction( final Map values, ) async { if (values['recurringTransaction'] != null && values['recurringTransaction'] != null && values['startDate'] != null && values['startDate'] != '' && values['timeFrame'] != null && values['timeFrame'] != '' && values['amount'] != null && values['amount'] != '') { final DialogInputFieldSelectItem timeFrame = values['timeFrame']; values['timeFrame'] = TimeFrameEnum.values[timeFrame.id]; final String amount = values['amount']; values['amount'] = double.tryParse(amount); if (values['amount'] != null && values['amount'] != 0) { final RecurringTransaction recurringTransaction = values['recurringTransaction']; final rtc = RecurringTransactionsCompanion( id: Value(recurringTransaction.id), name: Value(values['name']), startDate: Value(values['startDate']), timeFrame: Value(values['timeFrame']), amount: Value(values['amount']), accountId: Value(recurringTransaction.accountId), ); await _recurringTransactionRepository.update(rtc); await updateRecurringTransactions(); } } } Future _deleteRecurringTransaction( final Map values, ) async { if (values['recurringTransaction'] != null) { final RecurringTransaction recurringTransaction = values['recurringTransaction']; await _recurringTransactionRepository.remove(recurringTransaction); await updateRecurringTransactions(); } } }