Add a loan feature

This commit is contained in:
2025-05-12 21:02:51 +02:00
parent e0fba11f25
commit c5aa165424
15 changed files with 1383 additions and 5 deletions

View File

@@ -5,6 +5,7 @@ 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/loan.dart';
import 'package:okane/database/collections/recurrent.dart';
import 'package:okane/database/collections/template.dart';
import 'package:okane/database/collections/transaction.dart';
@@ -27,6 +28,8 @@ abstract class CoreState with _$CoreState {
@Default([]) List<ExpenseCategory> expenseCategories,
@Default([]) List<Budget> budgets,
@Default(null) Budget? activeBudget,
@Default([]) List<Loan> loans,
@Default(null) Loan? activeLoan,
@Default(false) bool isDeletingAccount,
}) = _CoreState;
}
@@ -41,6 +44,7 @@ class CoreCubit extends Cubit<CoreState> {
StreamSubscription<void>? _beneficiariesStreamSubscription;
StreamSubscription<void>? _expenseCategoryStreamSubscription;
StreamSubscription<void>? _budgetsStreamSubscription;
StreamSubscription<void>? _loanStreamSubscription;
void setupAccountStream() {
_accountsStreamSubscription?.cancel();
@@ -115,6 +119,10 @@ class CoreCubit extends Cubit<CoreState> {
) async {
emit(state.copyWith(budgets: await db.getBudgets(activeAccount!)));
});
_loanStreamSubscription?.cancel();
_loanStreamSubscription = db.watchLoans().listen((_) async {
emit(state.copyWith(loans: await db.getLoans()));
});
}
void cancelStreams() {
@@ -125,6 +133,7 @@ class CoreCubit extends Cubit<CoreState> {
_expenseCategoryStreamSubscription?.cancel();
_transactionsStreamSubscription?.cancel();
_transactionTemplatesStreamSubcription?.cancel();
_loanStreamSubscription?.cancel();
}
Future<void> init() async {
@@ -140,6 +149,7 @@ class CoreCubit extends Cubit<CoreState> {
recurringTransactions: await db.getRecurringTransactions(account),
expenseCategories: await db.getExpenseCategories(),
budgets: await db.getBudgets(account),
loans: await db.getLoans(),
),
);
@@ -167,6 +177,7 @@ class CoreCubit extends Cubit<CoreState> {
budgets: await db.getBudgets(account),
activeBudget: null,
activeTransaction: null,
activeLoan: null,
),
);
setupStreams(account);
@@ -199,6 +210,10 @@ class CoreCubit extends Cubit<CoreState> {
await init();
}
void setActiveLoan(Loan loan) {
emit(state.copyWith(activeLoan: loan));
}
Account? get activeAccount =>
state.activeAccountIndex == null
? null

View File

@@ -31,6 +31,8 @@ mixin _$CoreState {
throw _privateConstructorUsedError;
List<Budget> get budgets => throw _privateConstructorUsedError;
Budget? get activeBudget => throw _privateConstructorUsedError;
List<Loan> get loans => throw _privateConstructorUsedError;
Loan? get activeLoan => throw _privateConstructorUsedError;
bool get isDeletingAccount => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
@@ -55,6 +57,8 @@ abstract class $CoreStateCopyWith<$Res> {
List<ExpenseCategory> expenseCategories,
List<Budget> budgets,
Budget? activeBudget,
List<Loan> loans,
Loan? activeLoan,
bool isDeletingAccount,
});
}
@@ -83,6 +87,8 @@ class _$CoreStateCopyWithImpl<$Res, $Val extends CoreState>
Object? expenseCategories = null,
Object? budgets = null,
Object? activeBudget = freezed,
Object? loans = null,
Object? activeLoan = freezed,
Object? isDeletingAccount = null,
}) {
return _then(
@@ -142,6 +148,16 @@ class _$CoreStateCopyWithImpl<$Res, $Val extends CoreState>
? _value.activeBudget
: activeBudget // ignore: cast_nullable_to_non_nullable
as Budget?,
loans:
null == loans
? _value.loans
: loans // ignore: cast_nullable_to_non_nullable
as List<Loan>,
activeLoan:
freezed == activeLoan
? _value.activeLoan
: activeLoan // ignore: cast_nullable_to_non_nullable
as Loan?,
isDeletingAccount:
null == isDeletingAccount
? _value.isDeletingAccount
@@ -174,6 +190,8 @@ abstract class _$$CoreStateImplCopyWith<$Res>
List<ExpenseCategory> expenseCategories,
List<Budget> budgets,
Budget? activeBudget,
List<Loan> loans,
Loan? activeLoan,
bool isDeletingAccount,
});
}
@@ -201,6 +219,8 @@ class __$$CoreStateImplCopyWithImpl<$Res>
Object? expenseCategories = null,
Object? budgets = null,
Object? activeBudget = freezed,
Object? loans = null,
Object? activeLoan = freezed,
Object? isDeletingAccount = null,
}) {
return _then(
@@ -260,6 +280,16 @@ class __$$CoreStateImplCopyWithImpl<$Res>
? _value.activeBudget
: activeBudget // ignore: cast_nullable_to_non_nullable
as Budget?,
loans:
null == loans
? _value._loans
: loans // ignore: cast_nullable_to_non_nullable
as List<Loan>,
activeLoan:
freezed == activeLoan
? _value.activeLoan
: activeLoan // ignore: cast_nullable_to_non_nullable
as Loan?,
isDeletingAccount:
null == isDeletingAccount
? _value.isDeletingAccount
@@ -285,6 +315,8 @@ class _$CoreStateImpl implements _CoreState {
final List<ExpenseCategory> expenseCategories = const [],
final List<Budget> budgets = const [],
this.activeBudget = null,
final List<Loan> loans = const [],
this.activeLoan = null,
this.isDeletingAccount = false,
}) : _accounts = accounts,
_recurringTransactions = recurringTransactions,
@@ -292,7 +324,8 @@ class _$CoreStateImpl implements _CoreState {
_transactionTemplates = transactionTemplates,
_beneficiaries = beneficiaries,
_expenseCategories = expenseCategories,
_budgets = budgets;
_budgets = budgets,
_loans = loans;
@override
@JsonKey()
@@ -371,13 +404,25 @@ class _$CoreStateImpl implements _CoreState {
@override
@JsonKey()
final Budget? activeBudget;
final List<Loan> _loans;
@override
@JsonKey()
List<Loan> get loans {
if (_loans is EqualUnmodifiableListView) return _loans;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_loans);
}
@override
@JsonKey()
final Loan? activeLoan;
@override
@JsonKey()
final bool isDeletingAccount;
@override
String toString() {
return 'CoreState(activePage: $activePage, activeAccountIndex: $activeAccountIndex, activeTransaction: $activeTransaction, accounts: $accounts, recurringTransactions: $recurringTransactions, transactions: $transactions, transactionTemplates: $transactionTemplates, beneficiaries: $beneficiaries, expenseCategories: $expenseCategories, budgets: $budgets, activeBudget: $activeBudget, isDeletingAccount: $isDeletingAccount)';
return 'CoreState(activePage: $activePage, activeAccountIndex: $activeAccountIndex, activeTransaction: $activeTransaction, accounts: $accounts, recurringTransactions: $recurringTransactions, transactions: $transactions, transactionTemplates: $transactionTemplates, beneficiaries: $beneficiaries, expenseCategories: $expenseCategories, budgets: $budgets, activeBudget: $activeBudget, loans: $loans, activeLoan: $activeLoan, isDeletingAccount: $isDeletingAccount)';
}
@override
@@ -415,6 +460,9 @@ class _$CoreStateImpl implements _CoreState {
const DeepCollectionEquality().equals(other._budgets, _budgets) &&
(identical(other.activeBudget, activeBudget) ||
other.activeBudget == activeBudget) &&
const DeepCollectionEquality().equals(other._loans, _loans) &&
(identical(other.activeLoan, activeLoan) ||
other.activeLoan == activeLoan) &&
(identical(other.isDeletingAccount, isDeletingAccount) ||
other.isDeletingAccount == isDeletingAccount));
}
@@ -433,6 +481,8 @@ class _$CoreStateImpl implements _CoreState {
const DeepCollectionEquality().hash(_expenseCategories),
const DeepCollectionEquality().hash(_budgets),
activeBudget,
const DeepCollectionEquality().hash(_loans),
activeLoan,
isDeletingAccount,
);
@@ -456,6 +506,8 @@ abstract class _CoreState implements CoreState {
final List<ExpenseCategory> expenseCategories,
final List<Budget> budgets,
final Budget? activeBudget,
final List<Loan> loans,
final Loan? activeLoan,
final bool isDeletingAccount,
}) = _$CoreStateImpl;
@@ -482,6 +534,10 @@ abstract class _CoreState implements CoreState {
@override
Budget? get activeBudget;
@override
List<Loan> get loans;
@override
Loan? get activeLoan;
@override
bool get isDeletingAccount;
@override
@JsonKey(ignore: true)