Add budgets

This commit is contained in:
2025-05-04 19:26:11 +02:00
parent 5cc0bba09a
commit eced6e6a6d
23 changed files with 3211 additions and 1507 deletions

View File

@@ -4,6 +4,7 @@ import 'package:bloc/bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:okane/database/collections/account.dart';
import 'package:okane/database/collections/beneficiary.dart';
import 'package:okane/database/collections/budget.dart';
import 'package:okane/database/collections/expense_category.dart';
import 'package:okane/database/collections/recurrent.dart';
import 'package:okane/database/collections/template.dart';
@@ -25,6 +26,8 @@ abstract class CoreState with _$CoreState {
@Default([]) List<TransactionTemplate> transactionTemplates,
@Default([]) List<Beneficiary> beneficiaries,
@Default([]) List<ExpenseCategory> expenseCategories,
@Default([]) List<Budget> budgets,
@Default(null) Budget? activeBudget,
}) = _CoreState;
}
@@ -37,6 +40,7 @@ class CoreCubit extends Cubit<CoreState> {
StreamSubscription<void>? _transactionsStreamSubscription;
StreamSubscription<void>? _beneficiariesStreamSubscription;
StreamSubscription<void>? _expenseCategoryStreamSubscription;
StreamSubscription<void>? _budgetsStreamSubscription;
void setupAccountStream() {
_accountsStreamSubscription?.cancel();
@@ -94,6 +98,12 @@ class CoreCubit extends Cubit<CoreState> {
) async {
emit(state.copyWith(expenseCategories: await getExpenseCategories()));
});
_budgetsStreamSubscription?.cancel();
_budgetsStreamSubscription = watchBudgets(activeAccount!).listen((
_,
) async {
emit(state.copyWith(budgets: await getBudgets(activeAccount!)));
});
}
Future<void> init() async {
@@ -108,6 +118,7 @@ class CoreCubit extends Cubit<CoreState> {
transactionTemplates: await getTransactionTemplates(account),
recurringTransactions: await getRecurringTransactions(account),
expenseCategories: await getExpenseCategories(),
budgets: await getBudgets(account),
),
);
@@ -132,6 +143,9 @@ class CoreCubit extends Cubit<CoreState> {
beneficiaries: await getBeneficiaries(),
transactionTemplates: await getTransactionTemplates(account),
recurringTransactions: await getRecurringTransactions(account),
budgets: await getBudgets(account),
activeBudget: null,
activeTransaction: null,
),
);
setupStreams(account);
@@ -145,6 +159,10 @@ class CoreCubit extends Cubit<CoreState> {
emit(state.copyWith(accounts: accounts));
}
void setActiveBudget(Budget? budget) {
emit(state.copyWith(activeBudget: budget));
}
Account? get activeAccount =>
state.activeAccountIndex == null
? null

View File

@@ -12,8 +12,7 @@ part of 'core.dart';
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models',
);
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
/// @nodoc
mixin _$CoreState {
@@ -29,6 +28,8 @@ mixin _$CoreState {
List<Beneficiary> get beneficiaries => throw _privateConstructorUsedError;
List<ExpenseCategory> get expenseCategories =>
throw _privateConstructorUsedError;
List<Budget> get budgets => throw _privateConstructorUsedError;
Budget? get activeBudget => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$CoreStateCopyWith<CoreState> get copyWith =>
@@ -40,17 +41,18 @@ abstract class $CoreStateCopyWith<$Res> {
factory $CoreStateCopyWith(CoreState value, $Res Function(CoreState) then) =
_$CoreStateCopyWithImpl<$Res, CoreState>;
@useResult
$Res call({
OkanePage activePage,
int? activeAccountIndex,
Transaction? activeTransaction,
List<Account> accounts,
List<RecurringTransaction> recurringTransactions,
List<Transaction> transactions,
List<TransactionTemplate> transactionTemplates,
List<Beneficiary> beneficiaries,
List<ExpenseCategory> expenseCategories,
});
$Res call(
{OkanePage activePage,
int? activeAccountIndex,
Transaction? activeTransaction,
List<Account> accounts,
List<RecurringTransaction> recurringTransactions,
List<Transaction> transactions,
List<TransactionTemplate> transactionTemplates,
List<Beneficiary> beneficiaries,
List<ExpenseCategory> expenseCategories,
List<Budget> budgets,
Budget? activeBudget});
}
/// @nodoc
@@ -75,57 +77,55 @@ class _$CoreStateCopyWithImpl<$Res, $Val extends CoreState>
Object? transactionTemplates = null,
Object? beneficiaries = null,
Object? expenseCategories = null,
Object? budgets = null,
Object? activeBudget = freezed,
}) {
return _then(
_value.copyWith(
activePage:
null == activePage
? _value.activePage
: activePage // ignore: cast_nullable_to_non_nullable
as OkanePage,
activeAccountIndex:
freezed == activeAccountIndex
? _value.activeAccountIndex
: activeAccountIndex // ignore: cast_nullable_to_non_nullable
as int?,
activeTransaction:
freezed == activeTransaction
? _value.activeTransaction
: activeTransaction // ignore: cast_nullable_to_non_nullable
as Transaction?,
accounts:
null == accounts
? _value.accounts
: accounts // ignore: cast_nullable_to_non_nullable
as List<Account>,
recurringTransactions:
null == recurringTransactions
? _value.recurringTransactions
: recurringTransactions // ignore: cast_nullable_to_non_nullable
as List<RecurringTransaction>,
transactions:
null == transactions
? _value.transactions
: transactions // ignore: cast_nullable_to_non_nullable
as List<Transaction>,
transactionTemplates:
null == transactionTemplates
? _value.transactionTemplates
: transactionTemplates // ignore: cast_nullable_to_non_nullable
as List<TransactionTemplate>,
beneficiaries:
null == beneficiaries
? _value.beneficiaries
: beneficiaries // ignore: cast_nullable_to_non_nullable
as List<Beneficiary>,
expenseCategories:
null == expenseCategories
? _value.expenseCategories
: expenseCategories // ignore: cast_nullable_to_non_nullable
as List<ExpenseCategory>,
)
as $Val,
);
return _then(_value.copyWith(
activePage: null == activePage
? _value.activePage
: activePage // ignore: cast_nullable_to_non_nullable
as OkanePage,
activeAccountIndex: freezed == activeAccountIndex
? _value.activeAccountIndex
: activeAccountIndex // ignore: cast_nullable_to_non_nullable
as int?,
activeTransaction: freezed == activeTransaction
? _value.activeTransaction
: activeTransaction // ignore: cast_nullable_to_non_nullable
as Transaction?,
accounts: null == accounts
? _value.accounts
: accounts // ignore: cast_nullable_to_non_nullable
as List<Account>,
recurringTransactions: null == recurringTransactions
? _value.recurringTransactions
: recurringTransactions // ignore: cast_nullable_to_non_nullable
as List<RecurringTransaction>,
transactions: null == transactions
? _value.transactions
: transactions // ignore: cast_nullable_to_non_nullable
as List<Transaction>,
transactionTemplates: null == transactionTemplates
? _value.transactionTemplates
: transactionTemplates // ignore: cast_nullable_to_non_nullable
as List<TransactionTemplate>,
beneficiaries: null == beneficiaries
? _value.beneficiaries
: beneficiaries // ignore: cast_nullable_to_non_nullable
as List<Beneficiary>,
expenseCategories: null == expenseCategories
? _value.expenseCategories
: expenseCategories // ignore: cast_nullable_to_non_nullable
as List<ExpenseCategory>,
budgets: null == budgets
? _value.budgets
: budgets // ignore: cast_nullable_to_non_nullable
as List<Budget>,
activeBudget: freezed == activeBudget
? _value.activeBudget
: activeBudget // ignore: cast_nullable_to_non_nullable
as Budget?,
) as $Val);
}
}
@@ -133,22 +133,22 @@ class _$CoreStateCopyWithImpl<$Res, $Val extends CoreState>
abstract class _$$CoreStateImplCopyWith<$Res>
implements $CoreStateCopyWith<$Res> {
factory _$$CoreStateImplCopyWith(
_$CoreStateImpl value,
$Res Function(_$CoreStateImpl) then,
) = __$$CoreStateImplCopyWithImpl<$Res>;
_$CoreStateImpl value, $Res Function(_$CoreStateImpl) then) =
__$$CoreStateImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({
OkanePage activePage,
int? activeAccountIndex,
Transaction? activeTransaction,
List<Account> accounts,
List<RecurringTransaction> recurringTransactions,
List<Transaction> transactions,
List<TransactionTemplate> transactionTemplates,
List<Beneficiary> beneficiaries,
List<ExpenseCategory> expenseCategories,
});
$Res call(
{OkanePage activePage,
int? activeAccountIndex,
Transaction? activeTransaction,
List<Account> accounts,
List<RecurringTransaction> recurringTransactions,
List<Transaction> transactions,
List<TransactionTemplate> transactionTemplates,
List<Beneficiary> beneficiaries,
List<ExpenseCategory> expenseCategories,
List<Budget> budgets,
Budget? activeBudget});
}
/// @nodoc
@@ -156,9 +156,8 @@ class __$$CoreStateImplCopyWithImpl<$Res>
extends _$CoreStateCopyWithImpl<$Res, _$CoreStateImpl>
implements _$$CoreStateImplCopyWith<$Res> {
__$$CoreStateImplCopyWithImpl(
_$CoreStateImpl _value,
$Res Function(_$CoreStateImpl) _then,
) : super(_value, _then);
_$CoreStateImpl _value, $Res Function(_$CoreStateImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
@@ -172,78 +171,80 @@ class __$$CoreStateImplCopyWithImpl<$Res>
Object? transactionTemplates = null,
Object? beneficiaries = null,
Object? expenseCategories = null,
Object? budgets = null,
Object? activeBudget = freezed,
}) {
return _then(
_$CoreStateImpl(
activePage:
null == activePage
? _value.activePage
: activePage // ignore: cast_nullable_to_non_nullable
as OkanePage,
activeAccountIndex:
freezed == activeAccountIndex
? _value.activeAccountIndex
: activeAccountIndex // ignore: cast_nullable_to_non_nullable
as int?,
activeTransaction:
freezed == activeTransaction
? _value.activeTransaction
: activeTransaction // ignore: cast_nullable_to_non_nullable
as Transaction?,
accounts:
null == accounts
? _value._accounts
: accounts // ignore: cast_nullable_to_non_nullable
as List<Account>,
recurringTransactions:
null == recurringTransactions
? _value._recurringTransactions
: recurringTransactions // ignore: cast_nullable_to_non_nullable
as List<RecurringTransaction>,
transactions:
null == transactions
? _value._transactions
: transactions // ignore: cast_nullable_to_non_nullable
as List<Transaction>,
transactionTemplates:
null == transactionTemplates
? _value._transactionTemplates
: transactionTemplates // ignore: cast_nullable_to_non_nullable
as List<TransactionTemplate>,
beneficiaries:
null == beneficiaries
? _value._beneficiaries
: beneficiaries // ignore: cast_nullable_to_non_nullable
as List<Beneficiary>,
expenseCategories:
null == expenseCategories
? _value._expenseCategories
: expenseCategories // ignore: cast_nullable_to_non_nullable
as List<ExpenseCategory>,
),
);
return _then(_$CoreStateImpl(
activePage: null == activePage
? _value.activePage
: activePage // ignore: cast_nullable_to_non_nullable
as OkanePage,
activeAccountIndex: freezed == activeAccountIndex
? _value.activeAccountIndex
: activeAccountIndex // ignore: cast_nullable_to_non_nullable
as int?,
activeTransaction: freezed == activeTransaction
? _value.activeTransaction
: activeTransaction // ignore: cast_nullable_to_non_nullable
as Transaction?,
accounts: null == accounts
? _value._accounts
: accounts // ignore: cast_nullable_to_non_nullable
as List<Account>,
recurringTransactions: null == recurringTransactions
? _value._recurringTransactions
: recurringTransactions // ignore: cast_nullable_to_non_nullable
as List<RecurringTransaction>,
transactions: null == transactions
? _value._transactions
: transactions // ignore: cast_nullable_to_non_nullable
as List<Transaction>,
transactionTemplates: null == transactionTemplates
? _value._transactionTemplates
: transactionTemplates // ignore: cast_nullable_to_non_nullable
as List<TransactionTemplate>,
beneficiaries: null == beneficiaries
? _value._beneficiaries
: beneficiaries // ignore: cast_nullable_to_non_nullable
as List<Beneficiary>,
expenseCategories: null == expenseCategories
? _value._expenseCategories
: expenseCategories // ignore: cast_nullable_to_non_nullable
as List<ExpenseCategory>,
budgets: null == budgets
? _value._budgets
: budgets // ignore: cast_nullable_to_non_nullable
as List<Budget>,
activeBudget: freezed == activeBudget
? _value.activeBudget
: activeBudget // ignore: cast_nullable_to_non_nullable
as Budget?,
));
}
}
/// @nodoc
class _$CoreStateImpl implements _CoreState {
const _$CoreStateImpl({
this.activePage = OkanePage.accounts,
this.activeAccountIndex,
this.activeTransaction = null,
final List<Account> accounts = const [],
final List<RecurringTransaction> recurringTransactions = const [],
final List<Transaction> transactions = const [],
final List<TransactionTemplate> transactionTemplates = const [],
final List<Beneficiary> beneficiaries = const [],
final List<ExpenseCategory> expenseCategories = const [],
}) : _accounts = accounts,
_recurringTransactions = recurringTransactions,
_transactions = transactions,
_transactionTemplates = transactionTemplates,
_beneficiaries = beneficiaries,
_expenseCategories = expenseCategories;
const _$CoreStateImpl(
{this.activePage = OkanePage.accounts,
this.activeAccountIndex,
this.activeTransaction = null,
final List<Account> accounts = const [],
final List<RecurringTransaction> recurringTransactions = const [],
final List<Transaction> transactions = const [],
final List<TransactionTemplate> transactionTemplates = const [],
final List<Beneficiary> beneficiaries = const [],
final List<ExpenseCategory> expenseCategories = const [],
final List<Budget> budgets = const [],
this.activeBudget = null})
: _accounts = accounts,
_recurringTransactions = recurringTransactions,
_transactions = transactions,
_transactionTemplates = transactionTemplates,
_beneficiaries = beneficiaries,
_expenseCategories = expenseCategories,
_budgets = budgets;
@override
@JsonKey()
@@ -310,9 +311,22 @@ class _$CoreStateImpl implements _CoreState {
return EqualUnmodifiableListView(_expenseCategories);
}
final List<Budget> _budgets;
@override
@JsonKey()
List<Budget> get budgets {
if (_budgets is EqualUnmodifiableListView) return _budgets;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_budgets);
}
@override
@JsonKey()
final Budget? activeBudget;
@override
String toString() {
return 'CoreState(activePage: $activePage, activeAccountIndex: $activeAccountIndex, activeTransaction: $activeTransaction, accounts: $accounts, recurringTransactions: $recurringTransactions, transactions: $transactions, transactionTemplates: $transactionTemplates, beneficiaries: $beneficiaries, expenseCategories: $expenseCategories)';
return 'CoreState(activePage: $activePage, activeAccountIndex: $activeAccountIndex, activeTransaction: $activeTransaction, accounts: $accounts, recurringTransactions: $recurringTransactions, transactions: $transactions, transactionTemplates: $transactionTemplates, beneficiaries: $beneficiaries, expenseCategories: $expenseCategories, budgets: $budgets, activeBudget: $activeBudget)';
}
@override
@@ -327,41 +341,35 @@ class _$CoreStateImpl implements _CoreState {
(identical(other.activeTransaction, activeTransaction) ||
other.activeTransaction == activeTransaction) &&
const DeepCollectionEquality().equals(other._accounts, _accounts) &&
const DeepCollectionEquality().equals(
other._recurringTransactions,
_recurringTransactions,
) &&
const DeepCollectionEquality().equals(
other._transactions,
_transactions,
) &&
const DeepCollectionEquality().equals(
other._transactionTemplates,
_transactionTemplates,
) &&
const DeepCollectionEquality().equals(
other._beneficiaries,
_beneficiaries,
) &&
const DeepCollectionEquality().equals(
other._expenseCategories,
_expenseCategories,
));
const DeepCollectionEquality()
.equals(other._recurringTransactions, _recurringTransactions) &&
const DeepCollectionEquality()
.equals(other._transactions, _transactions) &&
const DeepCollectionEquality()
.equals(other._transactionTemplates, _transactionTemplates) &&
const DeepCollectionEquality()
.equals(other._beneficiaries, _beneficiaries) &&
const DeepCollectionEquality()
.equals(other._expenseCategories, _expenseCategories) &&
const DeepCollectionEquality().equals(other._budgets, _budgets) &&
(identical(other.activeBudget, activeBudget) ||
other.activeBudget == activeBudget));
}
@override
int get hashCode => Object.hash(
runtimeType,
activePage,
activeAccountIndex,
activeTransaction,
const DeepCollectionEquality().hash(_accounts),
const DeepCollectionEquality().hash(_recurringTransactions),
const DeepCollectionEquality().hash(_transactions),
const DeepCollectionEquality().hash(_transactionTemplates),
const DeepCollectionEquality().hash(_beneficiaries),
const DeepCollectionEquality().hash(_expenseCategories),
);
runtimeType,
activePage,
activeAccountIndex,
activeTransaction,
const DeepCollectionEquality().hash(_accounts),
const DeepCollectionEquality().hash(_recurringTransactions),
const DeepCollectionEquality().hash(_transactions),
const DeepCollectionEquality().hash(_transactionTemplates),
const DeepCollectionEquality().hash(_beneficiaries),
const DeepCollectionEquality().hash(_expenseCategories),
const DeepCollectionEquality().hash(_budgets),
activeBudget);
@JsonKey(ignore: true)
@override
@@ -371,17 +379,18 @@ class _$CoreStateImpl implements _CoreState {
}
abstract class _CoreState implements CoreState {
const factory _CoreState({
final OkanePage activePage,
final int? activeAccountIndex,
final Transaction? activeTransaction,
final List<Account> accounts,
final List<RecurringTransaction> recurringTransactions,
final List<Transaction> transactions,
final List<TransactionTemplate> transactionTemplates,
final List<Beneficiary> beneficiaries,
final List<ExpenseCategory> expenseCategories,
}) = _$CoreStateImpl;
const factory _CoreState(
{final OkanePage activePage,
final int? activeAccountIndex,
final Transaction? activeTransaction,
final List<Account> accounts,
final List<RecurringTransaction> recurringTransactions,
final List<Transaction> transactions,
final List<TransactionTemplate> transactionTemplates,
final List<Beneficiary> beneficiaries,
final List<ExpenseCategory> expenseCategories,
final List<Budget> budgets,
final Budget? activeBudget}) = _$CoreStateImpl;
@override
OkanePage get activePage;
@@ -402,6 +411,10 @@ abstract class _CoreState implements CoreState {
@override
List<ExpenseCategory> get expenseCategories;
@override
List<Budget> get budgets;
@override
Budget? get activeBudget;
@override
@JsonKey(ignore: true)
_$$CoreStateImplCopyWith<_$CoreStateImpl> get copyWith =>
throw _privateConstructorUsedError;