stacked bar graph, edit / remove transaction & budget page base

This commit is contained in:
2024-02-06 23:58:29 +01:00
parent 3abee9ff6f
commit 3610c466d2
25 changed files with 483 additions and 180 deletions

View File

@@ -4,6 +4,7 @@ class AutocompleteInput extends StatelessWidget {
final List<String> options;
final String hintText;
final String? errorText;
final String? initialValue;
final ValueChanged<String>? onChanged;
const AutocompleteInput({
@@ -11,12 +12,14 @@ class AutocompleteInput extends StatelessWidget {
required this.options,
required this.hintText,
required this.errorText,
required this.initialValue,
required this.onChanged,
});
@override
Widget build(BuildContext context) {
return RawAutocomplete<String>(
initialValue: TextEditingValue(text: initialValue ?? ''),
optionsBuilder: (TextEditingValue textEditingValue) => options.where((String option) =>option.contains(textEditingValue.text.toLowerCase())),
fieldViewBuilder: (
BuildContext context,

View File

@@ -1,40 +1,60 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:tunas/domains/account/account_bloc.dart';
import 'package:tunas/pages/transactions/widgets/transaction_add_form.dart';
import 'package:tunas/pages/transactions/widgets/transaction_form.dart';
import 'package:tunas/repositories/account/models/transaction.dart';
class TransactionAddDialog extends StatelessWidget {
const TransactionAddDialog({super.key});
static void show(BuildContext context) => showDialog(
context: context,
barrierDismissible: false,
useRootNavigator: false,
builder: (_) => BlocProvider.value(
value: BlocProvider.of<AccountBloc>(context),
child: const TransactionAddDialog()
)
);
static void show(BuildContext context, Transaction? transaction) {
context.read<AccountBloc>().add(TransactionSetCurrent(transaction));
showDialog(
context: context,
barrierDismissible: false,
useRootNavigator: false,
builder: (_) => BlocProvider.value(
value: BlocProvider.of<AccountBloc>(context),
child: const TransactionAddDialog()
)
);
}
static void hide(BuildContext context) => Navigator.pop(context);
_computeActions(BuildContext context, Transaction? currentTransaction) {
final actions = [
IconButton(
onPressed: () => TransactionAddDialog.hide(context),
icon: const Icon(Icons.close)
),
IconButton(
onPressed: () => context.read<AccountBloc>().add(const TransactionAdd()),
icon: const Icon(Icons.save)
),
];
if (currentTransaction != null) {
actions.add(IconButton(
onPressed: () => context.read<AccountBloc>().add(const TransactionDeleteCurrent()),
icon: const Icon(Icons.delete)
));
}
return actions;
}
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text('Add transaction'),
actions: [
TextButton(
onPressed: () => TransactionAddDialog.hide(context),
child: Text('Close')
),
TextButton(
onPressed: () => context.read<AccountBloc>().add(TransactionAdd()),
child: Text('Add')
),
],
content: SizedBox(
height: 400,
child: TransactionAddForm(),
return BlocBuilder<AccountBloc, AccountState>(
buildWhen: (previous, current) => previous.currentTransaction != current.currentTransaction,
builder: (context, state) => AlertDialog(
title: Text(state.currentTransaction == null ? 'Add Transaction' : 'Edit Transaction'),
actions: _computeActions(context, state.currentTransaction),
content: const SizedBox(
height: 400,
child: TransactionForm(),
)
)
);
}

View File

@@ -5,8 +5,9 @@ import 'package:tunas/domains/account/account_bloc.dart';
import 'autocomplete_input.dart';
class TransactionAddForm extends StatelessWidget {
const TransactionAddForm({super.key});
class TransactionForm extends StatelessWidget {
const TransactionForm({super.key});
@override
Widget build(BuildContext context) {
@@ -61,6 +62,7 @@ class _TransactionCategoryInput extends StatelessWidget {
child: AutocompleteInput(
options: state.categories,
hintText: 'Category',
initialValue: state.transactionCategory.value,
errorText: state.transactionCategory.isNotValid ? state.transactionCategory.error?.message : null,
onChanged: (value) => context.read<AccountBloc>().add(TransactionCategoryChange(value)),
),
@@ -98,6 +100,7 @@ class _TransactionAccountInput extends StatelessWidget {
child: AutocompleteInput(
options: state.accountsTotals.keys.toList(),
hintText: 'Account',
initialValue: state.transactionAccount.value,
errorText: state.transactionAccount.isNotValid ? state.transactionAccount.error?.message : null,
onChanged: (value) => context.read<AccountBloc>().add(TransactionAccountChange(value)),
),

View File

@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:tunas/pages/transactions/widgets/transaction_add_dialog.dart';
import 'package:tunas/repositories/account/models/transaction.dart';
class TransactionLine extends StatelessWidget {
@@ -10,54 +11,57 @@ class TransactionLine extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MergeSemantics(
child: Container(
padding: const EdgeInsets.symmetric(vertical: 9, horizontal: 10),
margin: const EdgeInsets.symmetric(vertical: 2, horizontal: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
width: 100,
child: Text(DateFormat('dd-MM-yyyy', 'fr_FR').format(transaction.date))
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
transaction.category,
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 18)
),
Text(transaction.description),
],
return InkWell(
onTap: () => TransactionAddDialog.show(context, transaction),
child: MergeSemantics(
child: Container(
padding: const EdgeInsets.symmetric(vertical: 9, horizontal: 10),
margin: const EdgeInsets.symmetric(vertical: 2, horizontal: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
width: 100,
child: Text(DateFormat('dd-MM-yyyy', 'fr_FR').format(transaction.date))
),
),
SizedBox(
width: 100,
child: Text(transaction.account),
),
SizedBox(
width: 120,
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
NumberFormat(transaction.value > 0 ? '+#######.00 €' : '#######.00 €', 'fr_FR').format(transaction.value),
style: TextStyle(
color: transaction.value > 0 ? Colors.green : Colors.red
)
),
Text(
NumberFormat('#######.00 €', 'fr_FR').format(subTotal),
style: TextStyle(
color: subTotal > 0 ? Colors.green : Colors.red
)
),
],
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
transaction.category,
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 18)
),
Text(transaction.description),
],
),
),
)
],
SizedBox(
width: 100,
child: Text(transaction.account),
),
SizedBox(
width: 120,
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
NumberFormat(transaction.value > 0 ? '+#######.00 €' : '#######.00 €', 'fr_FR').format(transaction.value),
style: TextStyle(
color: transaction.value > 0 ? Colors.green : Colors.red
)
),
Text(
NumberFormat('#######.00 €', 'fr_FR').format(subTotal),
style: TextStyle(
color: subTotal > 0 ? Colors.green : Colors.red
)
),
],
),
)
],
)
)
)
);

View File

@@ -22,12 +22,11 @@ class TransactionsActions extends StatelessWidget {
fontSize: 35,
),
),
ElevatedButton.icon(
onPressed: () => TransactionAddDialog.show(context),
IconButton(
onPressed: () => TransactionAddDialog.show(context, null),
icon: const Icon(
Icons.add
),
label: const Text('Add'),
)
),
],
)