Fix the template page
This commit is contained in:
parent
60bfd9481f
commit
058291fa80
@ -145,22 +145,25 @@ Stream<void> watchTransactionTemplates(Account account) {
|
|||||||
.transactionTemplates
|
.transactionTemplates
|
||||||
.filter()
|
.filter()
|
||||||
.account((q) => q.idEqualTo(account.id))
|
.account((q) => q.idEqualTo(account.id))
|
||||||
.recurringEqualTo(false)
|
|
||||||
.watchLazy(fireImmediately: true);
|
.watchLazy(fireImmediately: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<TransactionTemplate>> getTransactionTemplates(Account? account) {
|
Future<List<TransactionTemplate>> getTransactionTemplates(
|
||||||
|
Account? account,
|
||||||
|
) async {
|
||||||
if (account == null) {
|
if (account == null) {
|
||||||
return Future.value([]);
|
return Future.value([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetIt.I
|
final a =
|
||||||
|
await GetIt.I
|
||||||
.get<Isar>()
|
.get<Isar>()
|
||||||
.transactionTemplates
|
.transactionTemplates
|
||||||
.filter()
|
.filter()
|
||||||
.account((q) => q.idEqualTo(account.id))
|
.account((q) => q.idEqualTo(account.id))
|
||||||
.recurringEqualTo(false)
|
|
||||||
.findAll();
|
.findAll();
|
||||||
|
|
||||||
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<void> watchTransactions(Account account) {
|
Stream<void> watchTransactions(Account account) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
|
import 'package:grouped_list/grouped_list.dart';
|
||||||
import 'package:okane/ui/state/core.dart';
|
import 'package:okane/ui/state/core.dart';
|
||||||
import 'package:okane/ui/utils.dart';
|
import 'package:okane/ui/utils.dart';
|
||||||
import 'package:okane/ui/widgets/add_template.dart';
|
import 'package:okane/ui/widgets/add_template.dart';
|
||||||
@ -18,29 +19,45 @@ class TemplateListState extends State<TemplateListPage> {
|
|||||||
return BlocBuilder<CoreCubit, CoreState>(
|
return BlocBuilder<CoreCubit, CoreState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final account = GetIt.I.get<CoreCubit>().activeAccount;
|
final account = GetIt.I.get<CoreCubit>().activeAccount;
|
||||||
|
final nonRecurringTemplates =
|
||||||
|
state.transactionTemplates.where((t) => !t.recurring).toList();
|
||||||
return Stack(
|
return Stack(
|
||||||
children: [
|
children: [
|
||||||
Column(
|
CustomScrollView(
|
||||||
children: [
|
slivers: [
|
||||||
Padding(
|
SliverToBoxAdapter(child: Text("Non-recurring")),
|
||||||
|
SliverList.builder(
|
||||||
|
itemCount: nonRecurringTemplates.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final template = nonRecurringTemplates[index];
|
||||||
|
return ListTile(title: Text(template.name));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SliverToBoxAdapter(child: Text("Recurring")),
|
||||||
|
SliverList.builder(
|
||||||
|
itemCount: state.recurringTransactions.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final template = state.recurringTransactions[index];
|
||||||
|
return ListTile(title: Text(template.template.value!.name));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
/*Padding(
|
||||||
padding: EdgeInsets.only(top: 16),
|
padding: EdgeInsets.only(top: 16),
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
itemCount: state.recurringTransactions.length,
|
itemCount: state.recurringTransactions.length,
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
itemBuilder:
|
itemBuilder: (ctx, idx) {
|
||||||
(ctx, idx) => ListTile(
|
print(idx);
|
||||||
|
return ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
state
|
state.recurringTransactions[idx].template.value!.name,
|
||||||
.recurringTransactions[idx]
|
|
||||||
.template
|
|
||||||
.value!
|
|
||||||
.name,
|
|
||||||
),
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),*/
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Positioned(
|
Positioned(
|
||||||
right: 16,
|
right: 16,
|
||||||
bottom: 16,
|
bottom: 16,
|
||||||
|
@ -186,7 +186,9 @@ class TransactionDetailsPage extends StatelessWidget {
|
|||||||
state.activeTransaction!.amount > 0
|
state.activeTransaction!.amount > 0
|
||||||
? Icon(Icons.add)
|
? Icon(Icons.add)
|
||||||
: Icon(Icons.remove),
|
: Icon(Icons.remove),
|
||||||
Text(formatCurrency(state.activeTransaction!.amount)),
|
Text(
|
||||||
|
formatCurrency(state.activeTransaction!.amount),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -76,6 +76,7 @@ class CoreCubit extends Cubit<CoreState> {
|
|||||||
_transactionTemplatesStreamSubcription = watchTransactionTemplates(
|
_transactionTemplatesStreamSubcription = watchTransactionTemplates(
|
||||||
activeAccount!,
|
activeAccount!,
|
||||||
).listen((_) async {
|
).listen((_) async {
|
||||||
|
print("UPDATE");
|
||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
transactionTemplates: await getTransactionTemplates(activeAccount!),
|
transactionTemplates: await getTransactionTemplates(activeAccount!),
|
||||||
|
@ -64,9 +64,7 @@ Future<TransactionTemplate?> selectTransactionTemplate(BuildContext context) {
|
|||||||
itemCount: state.transactionTemplates.length,
|
itemCount: state.transactionTemplates.length,
|
||||||
itemBuilder:
|
itemBuilder:
|
||||||
(context, index) => ListTile(
|
(context, index) => ListTile(
|
||||||
title: Text(
|
title: Text(state.transactionTemplates[index].name),
|
||||||
state.transactionTemplates[index].name,
|
|
||||||
),
|
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(
|
Navigator.of(
|
||||||
context,
|
context,
|
||||||
|
@ -4,6 +4,7 @@ import 'package:get_it/get_it.dart';
|
|||||||
import 'package:okane/database/collections/account.dart';
|
import 'package:okane/database/collections/account.dart';
|
||||||
import 'package:okane/database/collections/beneficiary.dart';
|
import 'package:okane/database/collections/beneficiary.dart';
|
||||||
import 'package:okane/database/collections/expense_category.dart';
|
import 'package:okane/database/collections/expense_category.dart';
|
||||||
|
import 'package:okane/database/collections/recurrent.dart';
|
||||||
import 'package:okane/database/collections/template.dart';
|
import 'package:okane/database/collections/template.dart';
|
||||||
import 'package:okane/database/database.dart';
|
import 'package:okane/database/database.dart';
|
||||||
import 'package:okane/ui/state/core.dart';
|
import 'package:okane/ui/state/core.dart';
|
||||||
@ -12,6 +13,8 @@ import 'package:okane/ui/utils.dart';
|
|||||||
import 'package:okane/ui/widgets/add_expense_category.dart';
|
import 'package:okane/ui/widgets/add_expense_category.dart';
|
||||||
import 'package:searchfield/searchfield.dart';
|
import 'package:searchfield/searchfield.dart';
|
||||||
|
|
||||||
|
enum Period { days, weeks, months, years }
|
||||||
|
|
||||||
class AddTransactionTemplateWidget extends StatefulWidget {
|
class AddTransactionTemplateWidget extends StatefulWidget {
|
||||||
final VoidCallback onAdd;
|
final VoidCallback onAdd;
|
||||||
|
|
||||||
@ -41,6 +44,11 @@ class _AddTransactionTemplateWidgetState
|
|||||||
|
|
||||||
ExpenseCategory? _expenseCategory;
|
ExpenseCategory? _expenseCategory;
|
||||||
|
|
||||||
|
bool _isRecurring = false;
|
||||||
|
|
||||||
|
Period _selectedPeriod = Period.weeks;
|
||||||
|
int _periodSize = 1;
|
||||||
|
|
||||||
String getBeneficiaryName(Beneficiary item) {
|
String getBeneficiaryName(Beneficiary item) {
|
||||||
return switch (item.type) {
|
return switch (item.type) {
|
||||||
BeneficiaryType.account => "${item.name} (Account)",
|
BeneficiaryType.account => "${item.name} (Account)",
|
||||||
@ -51,6 +59,7 @@ class _AddTransactionTemplateWidgetState
|
|||||||
Future<void> _submit(BuildContext context) async {
|
Future<void> _submit(BuildContext context) async {
|
||||||
final beneficiaryName = _beneficiaryTextController.text;
|
final beneficiaryName = _beneficiaryTextController.text;
|
||||||
if (_selectedBeneficiary == null && beneficiaryName.isEmpty) {
|
if (_selectedBeneficiary == null && beneficiaryName.isEmpty) {
|
||||||
|
print("No beneficiary");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_templateNameController.text.isEmpty) {
|
if (_templateNameController.text.isEmpty) {
|
||||||
@ -103,15 +112,31 @@ class _AddTransactionTemplateWidgetState
|
|||||||
TransactionDirection.receive => 1,
|
TransactionDirection.receive => 1,
|
||||||
};
|
};
|
||||||
final amount = factor * double.parse(_amountTextController.text).abs();
|
final amount = factor * double.parse(_amountTextController.text).abs();
|
||||||
final transaction =
|
final template =
|
||||||
TransactionTemplate()
|
TransactionTemplate()
|
||||||
..name = _templateNameController.text
|
..name = _templateNameController.text
|
||||||
..account.value = widget.activeAccountItem
|
..account.value = widget.activeAccountItem
|
||||||
..beneficiary.value = beneficiary
|
..beneficiary.value = beneficiary
|
||||||
..expenseCategory.value = _expenseCategory
|
..expenseCategory.value = _expenseCategory
|
||||||
..recurring = false
|
..recurring = _isRecurring
|
||||||
..amount = amount;
|
..amount = amount;
|
||||||
await upsertTransactionTemplate(transaction);
|
await upsertTransactionTemplate(template);
|
||||||
|
|
||||||
|
if (_isRecurring) {
|
||||||
|
final days = switch (_selectedPeriod) {
|
||||||
|
Period.days => _periodSize,
|
||||||
|
Period.weeks => _periodSize * 7,
|
||||||
|
Period.months => _periodSize * 31,
|
||||||
|
Period.years => _periodSize * 365,
|
||||||
|
};
|
||||||
|
final recurringTransaction =
|
||||||
|
RecurringTransaction()
|
||||||
|
..account.value = widget.activeAccountItem
|
||||||
|
..template.value = template
|
||||||
|
..lastExecution = null
|
||||||
|
..days = days;
|
||||||
|
await upsertRecurringTransaction(recurringTransaction);
|
||||||
|
}
|
||||||
widget.onAdd();
|
widget.onAdd();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,6 +252,91 @@ class _AddTransactionTemplateWidgetState
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text("Is recurring"),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(left: 16),
|
||||||
|
child: Switch(
|
||||||
|
value: _isRecurring,
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
_isRecurring = value;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(left: 16, right: 16, top: 16),
|
||||||
|
child: SegmentedButton<Period>(
|
||||||
|
segments: [
|
||||||
|
ButtonSegment(value: Period.days, label: Text("Days")),
|
||||||
|
ButtonSegment(value: Period.weeks, label: Text("Weeks")),
|
||||||
|
ButtonSegment(value: Period.months, label: Text("Months")),
|
||||||
|
ButtonSegment(value: Period.years, label: Text("Years")),
|
||||||
|
],
|
||||||
|
selected: <Period>{_selectedPeriod},
|
||||||
|
multiSelectionEnabled: false,
|
||||||
|
onSelectionChanged:
|
||||||
|
_isRecurring
|
||||||
|
? (selection) {
|
||||||
|
setState(() => _selectedPeriod = selection.first);
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.remove),
|
||||||
|
onPressed:
|
||||||
|
_isRecurring
|
||||||
|
? () {
|
||||||
|
if (_periodSize <= 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_periodSize--;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
width: 100,
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
switch (_selectedPeriod) {
|
||||||
|
Period.days => "$_periodSize days",
|
||||||
|
Period.weeks => "$_periodSize weeks",
|
||||||
|
Period.months => "$_periodSize months",
|
||||||
|
Period.years => "$_periodSize years",
|
||||||
|
},
|
||||||
|
style: TextStyle(
|
||||||
|
color: _isRecurring ? Colors.black : Colors.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.add),
|
||||||
|
onPressed:
|
||||||
|
_isRecurring
|
||||||
|
? () {
|
||||||
|
setState(() {
|
||||||
|
_periodSize++;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: OutlinedButton(
|
child: OutlinedButton(
|
||||||
|
Loading…
Reference in New Issue
Block a user