From e4f1f8610726f2a9f6eeb4b077bd8bd732ccb75f Mon Sep 17 00:00:00 2001 From: Florian Schindler <florianschndlr@gmail.com> Date: Tue, 27 Jun 2023 12:46:24 +0200 Subject: [PATCH] Create edit_transaction_view.dart --- .../frontend/views/edit_transaction_view.dart | 254 ++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 trackeroo/lib/frontend/views/edit_transaction_view.dart diff --git a/trackeroo/lib/frontend/views/edit_transaction_view.dart b/trackeroo/lib/frontend/views/edit_transaction_view.dart new file mode 100644 index 0000000..5683e8c --- /dev/null +++ b/trackeroo/lib/frontend/views/edit_transaction_view.dart @@ -0,0 +1,254 @@ +import 'package:flutter/material.dart'; +import 'package:trackeroo/logic/models/category.dart'; +import 'package:trackeroo/logic/models/transaction.dart'; +import 'package:trackeroo/logic/services/categories_controller.dart'; +import 'package:trackeroo/logic/services/locator.dart'; +import 'package:trackeroo/logic/services/transactions_controller.dart'; + +enum Timespan { none, daily, weekly, monthly, yearly } + +class EditTransactionView extends StatefulWidget { + const EditTransactionView({super.key, this.transaction}); + + final Transaction? transaction; + + @override + State<EditTransactionView> createState() => _EditTransactionViewState(); +} + +class _EditTransactionViewState extends State<EditTransactionView> { + + final TextEditingController _titleController = TextEditingController(); + final TextEditingController _amountController = TextEditingController(); + String categoryId = ''; + DateTime dueDate = DateTime.now(); + bool transExists = false; + bool isExpense = true; + bool isScheduled = false; + Timespan selectedTimespan = Timespan.none; + + @override + void initState() { + transExists = widget.transaction != null; + if(transExists) { + _titleController.text = widget.transaction!.title; + isExpense = widget.transaction!.amount.isNegative; + _amountController.text = widget.transaction!.amount.abs().toString(); + categoryId = widget.transaction!.categoryId; + dueDate = widget.transaction!.dueDate; + } + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(transExists ? 'Edit Transaction': 'Create Transaction'), + elevation: 0.0, + scrolledUnderElevation: 0.0, + actions: [ + IconButton( + onPressed: () async => { + if(await saveChanges()) Navigator.pop(context), + }, + padding: const EdgeInsets.all(12.0), + icon: const Icon(Icons.check_rounded) + ), + const SizedBox(width: 16.0) + ], + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(30.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[ + TextField( + controller: _titleController, + decoration: const InputDecoration( + border: InputBorder.none, + hintText: 'Title', + hintStyle: TextStyle( + fontWeight: FontWeight.normal + ) + ), + ), + const SizedBox(height: 50.0), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + IconButton( + onPressed: () => setState(() { + isExpense = !isExpense; + }), + icon: Icon(isExpense ? Icons.remove_rounded : Icons.add_rounded) + ), + SizedBox( + width: 200.0, + child: TextField( + controller: _amountController, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + contentPadding: EdgeInsets.only(left: 10.0, bottom: 7.0), + enabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: 'Amount', + hintStyle: TextStyle( + fontWeight: FontWeight.w300 + ), + ), + style: const TextStyle( + fontSize: 40.0, + fontWeight: FontWeight.w300 + ), + ) + ), + const SizedBox(width: 10.0), + ], + ), + const SizedBox(height: 50.0), + SizedBox( + width: double.infinity, + child: DropdownButton( + hint: const Text('Kategorie'), + isExpanded: true, + borderRadius: const BorderRadius.all(Radius.circular(10.0)), + underline: const SizedBox(), + style: TextStyle( + fontSize: 16.0, + fontWeight: FontWeight.normal, + color: Theme.of(context).colorScheme.onSurface + ), + items: [ + DropdownMenuItem( + value: '', + child: Text( + 'Kategorie', + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface.withAlpha(150) + ) + ), + ), + for(Category cat in locator.get<CategoriesController>().categories.values) DropdownMenuItem( + value: cat.id, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Icon(IconData(cat.iconCodePoint, fontFamily: cat.iconFontFamily)), + const SizedBox(width: 20.0), + Text(cat.title) + ], + ), + Container( + height: 15.0, + width: 15.0, + decoration: BoxDecoration( + color: Color(cat.colorValue), + shape: BoxShape.circle + ), + ) + ], + ) + ) + ], + value: categoryId, + onChanged: (value) { + setState(() { + categoryId = value.toString(); + }); + } + ), + ), + Theme( + data: Theme.of(context).copyWith( + splashColor: Colors.transparent, + highlightColor: Colors.transparent, + hoverColor: Colors.transparent + ), + child: CheckboxListTile( + title: const Text('Scheduled payment'), + contentPadding: const EdgeInsets.all(0.0), + value: isScheduled, + onChanged: (value) => setState(() { + isScheduled = !isScheduled; + }) + ), + ), + AbsorbPointer( + absorbing: !isScheduled, + child: Opacity( + opacity: !isScheduled ? 0.5 : 1, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + FilterChip( + onSelected: (value) => setState(() { + selectedTimespan = Timespan.daily; + }), + label: const Text('Daily'), + selected: selectedTimespan == Timespan.daily, + showCheckmark: false + ), + FilterChip( + onSelected: (value) => setState(() { + selectedTimespan = Timespan.weekly; + }), + label: const Text('Weekly'), + selected: selectedTimespan == Timespan.weekly, + showCheckmark: false + ), + FilterChip( + onSelected: (value) => setState(() { + selectedTimespan = Timespan.monthly; + }), + label: const Text('Montly'), + selected: selectedTimespan == Timespan.monthly, + showCheckmark: false + ), + FilterChip( + onSelected: (value) => setState(() { + selectedTimespan = Timespan.yearly; + }), + label: const Text('Yearly'), + selected: selectedTimespan == Timespan.yearly, + showCheckmark: false + ) + ], + ), + ], + ), + ), + ), + Text(categoryId) + ] + ) + ) + ), + ); + } + + Future<bool> saveChanges() async { + if(transExists) { + widget.transaction!.title = _titleController.text; + widget.transaction!.amount = isExpense ? -double.parse(_amountController.text) : double.parse(_amountController.text); + widget.transaction!.categoryId = categoryId; + return await locator.get<TransactionsController>().updateTransaction(widget.transaction!); + } else { + Transaction newTransaction = Transaction( + title: _titleController.text, + amount: isExpense ? -double.parse(_amountController.text) : double.parse(_amountController.text), + categoryId: categoryId, + dueDate: dueDate + ); + return await locator.get<TransactionsController>().saveTransaction(newTransaction); + } + } +} -- GitLab