Start migration to sqlite using drift
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import 'package:drift/drift.dart' show Value;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:okane/database/collections/budget.dart';
|
||||
import 'package:okane/database/database.dart';
|
||||
import 'package:okane/database/sqlite.dart';
|
||||
import 'package:okane/i18n/strings.g.dart';
|
||||
import 'package:okane/ui/state/core.dart';
|
||||
|
||||
@@ -52,14 +52,17 @@ class AddBudgetState extends State<AddBudgetPopup> {
|
||||
}
|
||||
|
||||
final bloc = GetIt.I.get<CoreCubit>();
|
||||
final budget =
|
||||
Budget()
|
||||
..name = _budgetNameEditController.text
|
||||
..period = BudgetPeriod.month
|
||||
..includeOtherSpendings = false
|
||||
..income = double.parse(_budgetIncomeEditController.text)
|
||||
..account.value = bloc.activeAccount!;
|
||||
await upsertBudget(budget);
|
||||
await GetIt.I.get<OkaneDatabase>().budgetsDao.upsertBudget(
|
||||
BudgetsCompanion(
|
||||
name: Value(_budgetNameEditController.text),
|
||||
period: Value(BudgetPeriod.month),
|
||||
includeOtherSpendings: Value(false),
|
||||
income: Value(
|
||||
double.parse(_budgetIncomeEditController.text),
|
||||
),
|
||||
accountId: Value(bloc.activeAccount!.id),
|
||||
),
|
||||
);
|
||||
widget.onDone();
|
||||
},
|
||||
child: Text(t.modals.add),
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
import 'package:drift/drift.dart' show Value;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:okane/database/collections/budget.dart';
|
||||
import 'package:okane/database/collections/expense_category.dart';
|
||||
import 'package:okane/database/database.dart';
|
||||
import 'package:okane/database/sqlite.dart';
|
||||
import 'package:okane/i18n/strings.g.dart';
|
||||
import 'package:okane/ui/state/core.dart';
|
||||
import 'package:okane/ui/utils.dart';
|
||||
import 'package:okane/ui/widgets/add_expense_category.dart';
|
||||
|
||||
class AddBudgetItemPopup extends StatefulWidget {
|
||||
final VoidCallback onDone;
|
||||
final Budget budget;
|
||||
final BudgetsDto budget;
|
||||
|
||||
const AddBudgetItemPopup({
|
||||
super.key,
|
||||
@@ -74,26 +72,24 @@ class AddBudgetItemState extends State<AddBudgetItemPopup> {
|
||||
_expenseCategory == null) {
|
||||
return;
|
||||
}
|
||||
if (widget.budget.items
|
||||
if (widget.budget.budgetItems
|
||||
.where(
|
||||
(i) =>
|
||||
i.expenseCategory.value!.name ==
|
||||
_expenseCategory!.name,
|
||||
i.expenseCategory.name == _expenseCategory!.name,
|
||||
)
|
||||
.firstOrNull !=
|
||||
null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final item =
|
||||
BudgetItem()
|
||||
..expenseCategory.value = _expenseCategory
|
||||
..amount = double.parse(
|
||||
_budgetItemAmountEditController.text,
|
||||
);
|
||||
await upsertBudgetItem(item);
|
||||
widget.budget.items.add(item);
|
||||
await upsertBudget(widget.budget);
|
||||
await GetIt.I.get<OkaneDatabase>().budgetsDao.upsertBudgetItem(
|
||||
BudgetItemsCompanion(
|
||||
expenseCategoryId: Value(_expenseCategory!.id),
|
||||
amount: Value(
|
||||
double.parse(_budgetItemAmountEditController.text),
|
||||
),
|
||||
),
|
||||
);
|
||||
widget.onDone();
|
||||
},
|
||||
child: Text(t.modals.add),
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:okane/database/collections/budget.dart';
|
||||
import 'package:okane/database/database.dart';
|
||||
import 'package:okane/database/sqlite.dart';
|
||||
import 'package:okane/i18n/strings.g.dart';
|
||||
import 'package:okane/ui/pages/budgets/add_budget_item.dart';
|
||||
import 'package:okane/ui/state/core.dart';
|
||||
@@ -56,7 +55,7 @@ class BudgetDetailsPage extends StatelessWidget {
|
||||
return Text(t.pages.budgets.details.noBudgetSelected);
|
||||
}
|
||||
|
||||
if (state.activeBudget!.items.isEmpty) {
|
||||
if (state.activeBudget!.budgetItems.isEmpty) {
|
||||
return Row(
|
||||
children: [
|
||||
Text(t.pages.budgets.details.noBudgetItems),
|
||||
@@ -73,14 +72,15 @@ class BudgetDetailsPage extends StatelessWidget {
|
||||
|
||||
final bloc = GetIt.I.get<CoreCubit>();
|
||||
final today = DateTime.now();
|
||||
final db = GetIt.I.get<OkaneDatabase>();
|
||||
return FutureBuilder(
|
||||
future: getTransactionsInTimeframe(
|
||||
future: db.transactionsDao.getTransactionsInTimeframe(
|
||||
bloc.activeAccount!,
|
||||
today,
|
||||
TransactionQueryDateOption.thisMonth,
|
||||
),
|
||||
builder: (context, snapshot) {
|
||||
final daysLeft = switch (state.activeBudget!.period) {
|
||||
final daysLeft = switch (state.activeBudget!.budget.period) {
|
||||
BudgetPeriod.month =>
|
||||
monthEnding(today).difference(today).inDays,
|
||||
};
|
||||
@@ -95,16 +95,17 @@ class BudgetDetailsPage extends StatelessWidget {
|
||||
),
|
||||
ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: state.activeBudget!.items.length,
|
||||
itemCount: state.activeBudget!.budgetItems.length,
|
||||
itemBuilder: (context, index) {
|
||||
final item = state.activeBudget!.items.elementAt(
|
||||
index,
|
||||
);
|
||||
final amount = formatCurrency(item.amount);
|
||||
final item = state.activeBudget!.budgetItems
|
||||
.elementAt(index);
|
||||
final amount = formatCurrency(item.item.amount);
|
||||
return ListTile(
|
||||
title: Text(
|
||||
t.pages.budgets.details.items.title(
|
||||
name: item.expenseCategory.value!.name,
|
||||
// TODO
|
||||
name: "lol",
|
||||
//name: item.expenseCategory.value!.name,
|
||||
amount: amount,
|
||||
),
|
||||
),
|
||||
@@ -119,26 +120,28 @@ class BudgetDetailsPage extends StatelessWidget {
|
||||
}
|
||||
|
||||
final categories =
|
||||
state.activeBudget!.items
|
||||
.map((i) => i.expenseCategory.value!.name)
|
||||
state.activeBudget!.budgetItems
|
||||
// TODO
|
||||
//.map((i) => i.expenseCategory.value!.name)
|
||||
.map((i) => "lol")
|
||||
.toList();
|
||||
final spending = <String, double>{};
|
||||
for (final t in snapshot.data!) {
|
||||
String categoryName;
|
||||
if (!categories.contains(t.expenseCategory.value?.name)) {
|
||||
if (!state.activeBudget!.includeOtherSpendings) {
|
||||
if (!categories.contains(t.expenseCategory?.name)) {
|
||||
if (!state.activeBudget!.budget.includeOtherSpendings) {
|
||||
continue;
|
||||
}
|
||||
|
||||
categoryName = "Other";
|
||||
} else {
|
||||
categoryName = t.expenseCategory.value!.name;
|
||||
categoryName = t.expenseCategory!.name;
|
||||
}
|
||||
|
||||
spending.update(
|
||||
categoryName,
|
||||
(value) => value + t.amount,
|
||||
ifAbsent: () => t.amount,
|
||||
(value) => value + t.transaction.amount,
|
||||
ifAbsent: () => t.transaction.amount,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -146,8 +149,8 @@ class BudgetDetailsPage extends StatelessWidget {
|
||||
spending.isEmpty
|
||||
? 0
|
||||
: spending.values.reduce((acc, val) => acc + val);
|
||||
final budgetTotal = state.activeBudget!.items
|
||||
.map((i) => i.amount)
|
||||
final budgetTotal = state.activeBudget!.budgetItems
|
||||
.map((i) => i.item.amount)
|
||||
.reduce((acc, val) => acc + val);
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@@ -268,13 +271,13 @@ class BudgetDetailsPage extends StatelessWidget {
|
||||
fallbackText: "",
|
||||
valueConverter: formatCurrency,
|
||||
items:
|
||||
state.activeBudget!.items
|
||||
state.activeBudget!.budgetItems
|
||||
.map(
|
||||
(i) => (
|
||||
title: i.expenseCategory.value!.name,
|
||||
value: i.amount,
|
||||
title: i.expenseCategory.name,
|
||||
value: i.item.amount,
|
||||
color: colorHash(
|
||||
i.expenseCategory.value!.name,
|
||||
i.expenseCategory.name,
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -339,18 +342,16 @@ class BudgetDetailsPage extends StatelessWidget {
|
||||
padding: EdgeInsets.all(8),
|
||||
child: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: state.activeBudget!.items.length,
|
||||
itemCount: state.activeBudget!.budgetItems.length,
|
||||
itemBuilder: (context, index) {
|
||||
final item = state.activeBudget!.items.elementAt(
|
||||
index,
|
||||
);
|
||||
final amount = formatCurrency(item.amount);
|
||||
final spent =
|
||||
spending[item.expenseCategory.value!.name];
|
||||
final item = state.activeBudget!.budgetItems
|
||||
.elementAt(index);
|
||||
final amount = formatCurrency(item.item.amount);
|
||||
final spent = spending[item.expenseCategory.name];
|
||||
final left =
|
||||
spent == null
|
||||
? item.amount
|
||||
: item.amount + spent;
|
||||
? item.item.amount
|
||||
: item.item.amount + spent;
|
||||
final subtitleText =
|
||||
left < 0
|
||||
? t.pages.budgets.details.items.over(
|
||||
@@ -361,7 +362,7 @@ class BudgetDetailsPage extends StatelessWidget {
|
||||
);
|
||||
return ListTile(
|
||||
title: Text(
|
||||
"${item.expenseCategory.value!.name} ($amount)",
|
||||
"${item.expenseCategory.name} ($amount)",
|
||||
),
|
||||
subtitle: Text(
|
||||
subtitleText,
|
||||
|
||||
@@ -28,7 +28,7 @@ class BudgetListPage extends StatelessWidget {
|
||||
itemCount: state.budgets.length,
|
||||
itemBuilder:
|
||||
(context, index) => ListTile(
|
||||
title: Text(state.budgets[index].name),
|
||||
title: Text(state.budgets[index].budget.name),
|
||||
selected: state.budgets[index] == state.activeBudget,
|
||||
trailing: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:okane/database/collections/budget.dart';
|
||||
import 'package:okane/database/database.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:okane/database/sqlite.dart';
|
||||
import 'package:okane/i18n/strings.g.dart';
|
||||
|
||||
class EditBudgetPopup extends StatefulWidget {
|
||||
final Budget budget;
|
||||
final BudgetsDto budget;
|
||||
|
||||
final VoidCallback onDone;
|
||||
|
||||
@@ -27,8 +27,8 @@ class EditBudgetState extends State<EditBudgetPopup> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_budgetNameEditController.text = widget.budget.name;
|
||||
_includeOtherSpendings = widget.budget.includeOtherSpendings;
|
||||
_budgetNameEditController.text = widget.budget.budget.name;
|
||||
_includeOtherSpendings = widget.budget.budget.includeOtherSpendings;
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -61,17 +61,22 @@ class EditBudgetState extends State<EditBudgetPopup> {
|
||||
if (_budgetNameEditController.text.isEmpty) {
|
||||
return;
|
||||
}
|
||||
if (_budgetNameEditController.text == widget.budget.name &&
|
||||
if (_budgetNameEditController.text ==
|
||||
widget.budget.budget.name &&
|
||||
_includeOtherSpendings ==
|
||||
widget.budget.includeOtherSpendings) {
|
||||
widget.budget.budget.includeOtherSpendings) {
|
||||
widget.onDone();
|
||||
return;
|
||||
}
|
||||
|
||||
widget.budget
|
||||
..name = _budgetNameEditController.text
|
||||
..includeOtherSpendings = _includeOtherSpendings;
|
||||
await upsertBudget(widget.budget);
|
||||
await GetIt.I.get<OkaneDatabase>().budgetsDao.upsertBudget(
|
||||
widget.budget.budget
|
||||
.copyWith(
|
||||
name: _budgetNameEditController.text,
|
||||
includeOtherSpendings: _includeOtherSpendings,
|
||||
)
|
||||
.toCompanion(false),
|
||||
);
|
||||
widget.onDone();
|
||||
},
|
||||
child: Text(t.modals.save),
|
||||
|
||||
Reference in New Issue
Block a user