Move down to only 1 abstract data type with a nully Frequency. Should aid in making the Expense page usable for all 3 data type.
This commit is contained in:
parent
992195b9a0
commit
be66f52cbf
@ -9,7 +9,7 @@ import 'package:sqflite/sqflite.dart';
|
||||
|
||||
// Local
|
||||
import '/models/expense.dart';
|
||||
import '/models/tracked_type_recurring.dart';
|
||||
import '/models/tracked_item.dart';
|
||||
|
||||
// Leaned on this example:
|
||||
// https://learnflutterwithme.com/sqlite
|
||||
@ -77,7 +77,7 @@ class DatabaseHelper {
|
||||
return expenseList;
|
||||
}
|
||||
|
||||
Future<int> addExpense(RecurringTrackedType expense) async {
|
||||
Future<int> addExpense(TrackedItem expense) async {
|
||||
Database db = await instance.db;
|
||||
return await db.insert(
|
||||
"expense",
|
||||
@ -94,7 +94,7 @@ class DatabaseHelper {
|
||||
);
|
||||
}
|
||||
|
||||
Future<int> updateExpense(RecurringTrackedType expense) async {
|
||||
Future<int> updateExpense(TrackedItem expense) async {
|
||||
Database db = await instance.db;
|
||||
return await db.update(
|
||||
"expense",
|
||||
|
@ -1,6 +1,7 @@
|
||||
import '/models/tracked_type.dart';
|
||||
// Local
|
||||
import '/models/tracked_item.dart';
|
||||
|
||||
class Asset extends TrackedType {
|
||||
class Asset extends TrackedItem {
|
||||
static String amountText = "Amount";
|
||||
|
||||
Asset({
|
||||
|
@ -29,7 +29,7 @@ class DatabaseBackup {
|
||||
'id': e.id,
|
||||
'name': e.name,
|
||||
'cost': e.amount,
|
||||
'frequency': e.frequency.title,
|
||||
'frequency': e.frequency!.title,
|
||||
'description': e.description,
|
||||
},
|
||||
],
|
||||
@ -39,7 +39,7 @@ class DatabaseBackup {
|
||||
'id': i.id,
|
||||
'name': i.name,
|
||||
'revenue': i.amount,
|
||||
'frequency': i.frequency.title,
|
||||
'frequency': i.frequency!.title,
|
||||
'description': i.description,
|
||||
},
|
||||
],
|
||||
|
@ -1,8 +1,8 @@
|
||||
// Local
|
||||
import '/models/tracked_type_recurring.dart';
|
||||
import '/models/tracked_item.dart';
|
||||
import '/models/frequency.dart';
|
||||
|
||||
class Expense extends RecurringTrackedType {
|
||||
class Expense extends TrackedItem {
|
||||
static String amountText = "Cost";
|
||||
|
||||
Expense({
|
||||
@ -29,7 +29,7 @@ class Expense extends RecurringTrackedType {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'cost': amount,
|
||||
'frequency': frequency.title,
|
||||
'frequency': frequency!.title,
|
||||
'description': description,
|
||||
};
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
// Local
|
||||
import '/models/tracked_type_recurring.dart';
|
||||
import '/models/tracked_item.dart';
|
||||
import '/models/frequency.dart';
|
||||
|
||||
class Income extends RecurringTrackedType {
|
||||
class Income extends TrackedItem {
|
||||
static String amountText = "Revenue";
|
||||
|
||||
Income({
|
||||
@ -29,7 +29,7 @@ class Income extends RecurringTrackedType {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'revenue': amount,
|
||||
'frequency': frequency.title,
|
||||
'frequency': frequency!.title,
|
||||
'description': description,
|
||||
};
|
||||
}
|
||||
|
49
lib/models/tracked_item.dart
Normal file
49
lib/models/tracked_item.dart
Normal file
@ -0,0 +1,49 @@
|
||||
// Local
|
||||
import '/models/frequency.dart';
|
||||
|
||||
abstract class TrackedItem {
|
||||
int? id;
|
||||
String name;
|
||||
double amount;
|
||||
Frequency? frequency;
|
||||
String description;
|
||||
|
||||
TrackedItem({
|
||||
this.id,
|
||||
required this.name,
|
||||
required this.amount,
|
||||
this.frequency,
|
||||
required this.description,
|
||||
});
|
||||
|
||||
static String amountText = "Amount";
|
||||
String getAmountText() => amountText;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
|
||||
double calcComparableAmountYearly() {
|
||||
return frequency == null ? 0 : amount * frequency!.timesPerYear;
|
||||
}
|
||||
|
||||
double calcComparableAmountDaily() {
|
||||
return frequency == null ? 0 : amount / frequency!.numDays;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return frequency == null ? {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'amount': amount,
|
||||
'description': description,
|
||||
} : {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'amount': amount,
|
||||
'frequency': frequency!.title,
|
||||
'description': description,
|
||||
};
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
abstract class TrackedType {
|
||||
int? id;
|
||||
String name;
|
||||
double amount;
|
||||
String description;
|
||||
|
||||
TrackedType({
|
||||
this.id,
|
||||
required this.name,
|
||||
required this.amount,
|
||||
required this.description,
|
||||
});
|
||||
|
||||
static String amountText = "Amount";
|
||||
String getAmountText() => amountText;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'amount': amount,
|
||||
'description': description,
|
||||
};
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
// Local
|
||||
import '/models/tracked_type.dart';
|
||||
import '/models/frequency.dart';
|
||||
|
||||
abstract class RecurringTrackedType extends TrackedType {
|
||||
Frequency frequency;
|
||||
|
||||
RecurringTrackedType({
|
||||
super.id,
|
||||
required super.name,
|
||||
required super.amount,
|
||||
required this.frequency,
|
||||
required super.description,
|
||||
});
|
||||
|
||||
double calcComparableAmountYearly() {
|
||||
return amount * frequency.timesPerYear;
|
||||
}
|
||||
|
||||
double calcComparableAmountDaily() {
|
||||
return amount / frequency.numDays;
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'amount': amount,
|
||||
'frequency': frequency.title,
|
||||
'description': description,
|
||||
};
|
||||
}
|
||||
}
|
@ -2,8 +2,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
// Local
|
||||
import '/models/tracked_type.dart';
|
||||
import '/models/tracked_type_recurring.dart';
|
||||
import '/models/tracked_item.dart';
|
||||
import '/models/expense.dart';
|
||||
import '/models/frequency.dart';
|
||||
import '/db.dart';
|
||||
@ -28,10 +27,10 @@ class _ExpensePageState extends State<ExpensePage> {
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return FutureBuilder<List<RecurringTrackedType>>(
|
||||
return FutureBuilder<List<TrackedItem>>(
|
||||
future: DatabaseHelper.instance.getExpenses(),
|
||||
builder: (BuildContext context,
|
||||
AsyncSnapshot<List<RecurringTrackedType>> snapshot) {
|
||||
AsyncSnapshot<List<TrackedItem>> snapshot) {
|
||||
if (!snapshot.hasData) {
|
||||
return Text('Loading...');
|
||||
}
|
||||
@ -49,58 +48,67 @@ class _ExpensePageState extends State<ExpensePage> {
|
||||
itemCount: snapshot.data!.length,
|
||||
itemBuilder: (_, index) {
|
||||
//List<Expense> expenses = snapshot.data!;
|
||||
final RecurringTrackedType curr = snapshot.data![index];
|
||||
final TrackedItem curr = snapshot.data![index];
|
||||
|
||||
final itemKey = Key(curr.id!.toString());
|
||||
final String itemTitle = curr.name;
|
||||
|
||||
final String itemAmount;
|
||||
// TODO: How can we do RecurringTrackedType vs TrackedType here
|
||||
// if the Widgets are expecting RecurringTrackedType, but we
|
||||
// need to be using Frequency? Change to only have one abstract
|
||||
// class and make it nully again? Hmmm...
|
||||
//if (curr is RecurringTrackedType && curr.frequency != null) {
|
||||
if (curr.frequency != null) {
|
||||
itemAmount =
|
||||
"${curr.amount.toStringAsFixed(2)} ${curr.frequency.title}";
|
||||
/*} else {
|
||||
"${curr.amount.toStringAsFixed(2)} ${curr.frequency!.title}";
|
||||
} else {
|
||||
itemAmount = curr.amount.toStringAsFixed(2);
|
||||
}*/
|
||||
}
|
||||
final String itemDescription = curr.description;
|
||||
|
||||
final double itemDayAmount =
|
||||
curr.calcComparableAmountDaily();
|
||||
final String estimateSymbolDaily = curr.frequency.numDays
|
||||
final double itemDayAmount, itemMonthAmount, itemYearAmount;
|
||||
final String estimateSymbolDaily,
|
||||
estimateSymbolMonthly,
|
||||
estimateSymbolYearly;
|
||||
|
||||
if (curr.frequency != null) {
|
||||
itemDayAmount = curr.calcComparableAmountDaily();
|
||||
estimateSymbolDaily = curr.frequency!.numDays
|
||||
.toStringAsFixed(2)
|
||||
.endsWith(".00") &&
|
||||
itemDayAmount.toStringAsFixed(3).endsWith("0")
|
||||
? ""
|
||||
: "~";
|
||||
|
||||
final double itemMonthAmount =
|
||||
itemMonthAmount =
|
||||
(curr.calcComparableAmountYearly() / 12);
|
||||
final String estimateSymbolMonthly = curr
|
||||
.frequency.timesPerYear
|
||||
estimateSymbolMonthly = curr.frequency!.timesPerYear
|
||||
.toStringAsFixed(2)
|
||||
.endsWith(".00") &&
|
||||
itemMonthAmount.toStringAsFixed(3).endsWith("0")
|
||||
? ""
|
||||
: "~";
|
||||
|
||||
final double itemYearAmount =
|
||||
curr.calcComparableAmountYearly();
|
||||
final String estimateSymbolYearly = curr
|
||||
.frequency.timesPerYear
|
||||
itemYearAmount = curr.calcComparableAmountYearly();
|
||||
estimateSymbolYearly = curr.frequency!.timesPerYear
|
||||
.toStringAsFixed(2)
|
||||
.endsWith(".00") &&
|
||||
itemYearAmount.toStringAsFixed(3).endsWith("0")
|
||||
? ""
|
||||
: "~";
|
||||
|
||||
final String itemTopText =
|
||||
"$estimateSymbolDaily${itemDayAmount.toStringAsFixed(2)} ${Frequency.daily.title}";
|
||||
final String itemMiddleText =
|
||||
"$estimateSymbolMonthly${itemMonthAmount.toStringAsFixed(2)} ${Frequency.monthly.title}";
|
||||
final String itemBottomText =
|
||||
"$estimateSymbolYearly${itemYearAmount.toStringAsFixed(2)} ${Frequency.yearly.title}";
|
||||
} else {
|
||||
itemDayAmount = -1;
|
||||
estimateSymbolDaily = "";
|
||||
itemMonthAmount = curr.amount;
|
||||
estimateSymbolMonthly = "";
|
||||
itemYearAmount = -1;
|
||||
estimateSymbolYearly = "";
|
||||
}
|
||||
final String itemTopText = itemDayAmount < 0
|
||||
? ""
|
||||
: "$estimateSymbolDaily${itemDayAmount.toStringAsFixed(2)} ${Frequency.daily.title}";
|
||||
final String itemMiddleText = itemMonthAmount < 0
|
||||
? ""
|
||||
: "$estimateSymbolMonthly${itemMonthAmount.toStringAsFixed(2)} ${Frequency.monthly.title}";
|
||||
final String itemBottomText = itemYearAmount < 0
|
||||
? ""
|
||||
: "$estimateSymbolYearly${itemYearAmount.toStringAsFixed(2)} ${Frequency.yearly.title}";
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
@ -138,7 +146,7 @@ class _ExpensePageState extends State<ExpensePage> {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (_) => AlertDialog(
|
||||
content: RecurringTrackedTypeInputDialog(
|
||||
content: TrackedItemInputDialog(
|
||||
notifyParent: refresh,
|
||||
entry: curr,
|
||||
amountText: curr.getAmountText(),
|
||||
@ -218,12 +226,12 @@ class _ExpensePageState extends State<ExpensePage> {
|
||||
}
|
||||
}
|
||||
|
||||
class RecurringTrackedTypeInputDialog extends StatefulWidget {
|
||||
class TrackedItemInputDialog extends StatefulWidget {
|
||||
final Function() notifyParent;
|
||||
final RecurringTrackedType? entry;
|
||||
final TrackedItem? entry;
|
||||
final String? amountText;
|
||||
|
||||
const RecurringTrackedTypeInputDialog({
|
||||
const TrackedItemInputDialog({
|
||||
super.key,
|
||||
required this.notifyParent,
|
||||
this.entry,
|
||||
@ -231,12 +239,12 @@ class RecurringTrackedTypeInputDialog extends StatefulWidget {
|
||||
});
|
||||
|
||||
@override
|
||||
State<RecurringTrackedTypeInputDialog> createState() =>
|
||||
_RecurringTrackedTypeInputDialogState();
|
||||
State<TrackedItemInputDialog> createState() =>
|
||||
_TrackedItemInputDialogState();
|
||||
}
|
||||
|
||||
class _RecurringTrackedTypeInputDialogState
|
||||
extends State<RecurringTrackedTypeInputDialog> {
|
||||
class _TrackedItemInputDialogState
|
||||
extends State<TrackedItemInputDialog> {
|
||||
final _expenseFormKey = GlobalKey<FormState>();
|
||||
|
||||
int? _id;
|
||||
@ -251,12 +259,12 @@ class _RecurringTrackedTypeInputDialogState
|
||||
_id = widget.entry!.id;
|
||||
_name = widget.entry!.name;
|
||||
_amount = widget.entry!.amount;
|
||||
_freq = widget.entry!.frequency;
|
||||
widget.entry!.frequency == null ? null : _freq = widget.entry!.frequency!;
|
||||
_desc = widget.entry!.description;
|
||||
}
|
||||
|
||||
String amountText =
|
||||
widget.amountText != null ? widget.amountText! : TrackedType.amountText;
|
||||
widget.amountText != null ? widget.amountText! : TrackedItem.amountText;
|
||||
|
||||
return Column(
|
||||
// prevent AlertDialog from taking full vertical height.
|
||||
|
@ -33,7 +33,7 @@ class _HomePageState extends State<HomePage> {
|
||||
switch (pageSelected) {
|
||||
case 0:
|
||||
page = ExpensePage();
|
||||
dialog = RecurringTrackedTypeInputDialog(
|
||||
dialog = TrackedItemInputDialog(
|
||||
notifyParent: refresh,
|
||||
);
|
||||
case 1:
|
||||
|
@ -2,8 +2,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
// Local
|
||||
import 'package:flutter_expense_tracker/db.dart';
|
||||
import 'package:flutter_expense_tracker/models/tracked_type_recurring.dart';
|
||||
import '/db.dart';
|
||||
import '/models/tracked_item.dart';
|
||||
|
||||
/// TODO:
|
||||
/// - Expenses (total number, totals by day / month / year)
|
||||
@ -57,22 +57,22 @@ class SummaryCardForTotals extends StatelessWidget {
|
||||
required this.summaryTypeLabel,
|
||||
});
|
||||
|
||||
final Future<List<RecurringTrackedType>> list;
|
||||
final Future<List<TrackedItem>> list;
|
||||
final String summaryTypeLabel;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder<List<RecurringTrackedType>>(
|
||||
return FutureBuilder<List<TrackedItem>>(
|
||||
future: list,
|
||||
builder: (
|
||||
BuildContext context,
|
||||
AsyncSnapshot<List<RecurringTrackedType>> snapshot,
|
||||
AsyncSnapshot<List<TrackedItem>> snapshot,
|
||||
) {
|
||||
if (!snapshot.hasData) {
|
||||
return Text('Loading $summaryTypeLabel Section...');
|
||||
}
|
||||
double dailyTotal = 0, monthlyTotal = 0, yearlyTotal = 0;
|
||||
for (RecurringTrackedType e in snapshot.data!) {
|
||||
for (TrackedItem e in snapshot.data!) {
|
||||
dailyTotal += e.calcComparableAmountDaily();
|
||||
monthlyTotal += e.calcComparableAmountYearly() / 12;
|
||||
yearlyTotal += e.calcComparableAmountYearly();
|
||||
|
Loading…
x
Reference in New Issue
Block a user