From 0ecafa39fc0d3e01f06e37aa0b4059a7497af86a Mon Sep 17 00:00:00 2001
From: Florian <74116125+florianschndlr@users.noreply.github.com>
Date: Thu, 29 Jun 2023 15:16:32 +0200
Subject: [PATCH] home page improvements

---
 .../utils/onboarding/category_chip.dart       | 23 +++++
 .../frontend/views/edit_transaction_view.dart |  4 +-
 trackeroo/lib/frontend/views/home_view.dart   | 87 ++++++++++++++++---
 .../services/transactions_controller.dart     | 14 +--
 4 files changed, 108 insertions(+), 20 deletions(-)
 create mode 100644 trackeroo/lib/frontend/utils/onboarding/category_chip.dart

diff --git a/trackeroo/lib/frontend/utils/onboarding/category_chip.dart b/trackeroo/lib/frontend/utils/onboarding/category_chip.dart
new file mode 100644
index 0000000..3ffa517
--- /dev/null
+++ b/trackeroo/lib/frontend/utils/onboarding/category_chip.dart
@@ -0,0 +1,23 @@
+import 'package:flutter/material.dart';
+import 'package:trackeroo/logic/models/category.dart';
+
+class CategoryChip extends StatelessWidget {
+  const CategoryChip({Key? key, required this.category}) : super(key: key);
+
+  final Category category;
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.only(right: 5.0),
+      child: ActionChip(
+        avatar: Icon(
+          IconData(category.iconCodePoint, fontFamily: category.iconFontFamily),
+          color: Color(category.colorValue),
+        ),
+        label: Text(category.title),
+        onPressed: () => {},
+      ),
+    );
+  }
+}
\ No newline at end of file
diff --git a/trackeroo/lib/frontend/views/edit_transaction_view.dart b/trackeroo/lib/frontend/views/edit_transaction_view.dart
index 5683e8c..20fc6cd 100644
--- a/trackeroo/lib/frontend/views/edit_transaction_view.dart
+++ b/trackeroo/lib/frontend/views/edit_transaction_view.dart
@@ -23,6 +23,7 @@ class _EditTransactionViewState extends State<EditTransactionView> {
   String categoryId = '';
   DateTime dueDate = DateTime.now();
   bool transExists = false;
+  double oldAmount = 0.0;
   bool isExpense = true;
   bool isScheduled = false;
   Timespan selectedTimespan = Timespan.none;
@@ -31,6 +32,7 @@ class _EditTransactionViewState extends State<EditTransactionView> {
   void initState() {
     transExists = widget.transaction != null;
     if(transExists) {
+      oldAmount = widget.transaction!.amount;
       _titleController.text = widget.transaction!.title;
       isExpense = widget.transaction!.amount.isNegative;
       _amountController.text = widget.transaction!.amount.abs().toString();
@@ -240,7 +242,7 @@ class _EditTransactionViewState extends State<EditTransactionView> {
       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!);
+      return await locator.get<TransactionsController>().updateTransaction(oldAmount, widget.transaction!);
     } else {
       Transaction newTransaction = Transaction(
         title: _titleController.text,
diff --git a/trackeroo/lib/frontend/views/home_view.dart b/trackeroo/lib/frontend/views/home_view.dart
index ce71ad1..a9fe58b 100644
--- a/trackeroo/lib/frontend/views/home_view.dart
+++ b/trackeroo/lib/frontend/views/home_view.dart
@@ -1,6 +1,7 @@
 import 'package:flutter/material.dart';
 import 'package:fl_chart/fl_chart.dart';
 import 'package:hive_flutter/hive_flutter.dart';
+import 'package:trackeroo/frontend/utils/onboarding/category_chip.dart';
 import 'package:trackeroo/frontend/utils/transaction_listtile.dart';
 import 'package:trackeroo/frontend/views/onboarding_view.dart';
 import 'package:trackeroo/logic/models/category.dart';
@@ -19,11 +20,9 @@ class HomeView extends StatefulWidget {
 }
 
 class _HomeViewState extends State<HomeView> {
-  Transaction trn = Transaction(title: "Bus Ticket VVS", amount: -5.32, categoryId: 'food_and_groceries', dueDate: DateTime.now());
-  Transaction trp = Transaction(title: "Gehalt", amount: 1300, categoryId: 'leisure_and_entertainment', dueDate: DateTime.now());
-
   Timespan timespanView = Timespan.monthly;
   TransactionsController transContr = locator.get<TransactionsController>();
+  List<Category> inChartShownCats = [];
 
   @override
   Widget build(BuildContext context) {
@@ -84,7 +83,7 @@ class _HomeViewState extends State<HomeView> {
                         width: 50.0,
                         child: PieChart(
                           PieChartData(
-                            centerSpaceRadius: 0,
+                            centerSpaceRadius: 30.0,
                             sections: transContr.transactionsList.isNotEmpty ? buildPieChartSectionList(context) : null,
                           ),
                           swapAnimationDuration: const Duration(milliseconds: 500),
@@ -106,6 +105,15 @@ class _HomeViewState extends State<HomeView> {
                     ),
                   ],
                 ),
+                const SizedBox(height: 15.0),
+                AbsorbPointer(
+                  absorbing: true,
+                  child: Wrap(
+                    children: [
+                      for(Category cat in inChartShownCats) CategoryChip(category: cat)
+                    ],
+                  ),
+                ),
                 const SizedBox(height: 10.0),
                 Row(
                   mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -191,6 +199,7 @@ class _HomeViewState extends State<HomeView> {
 
   List<PieChartSectionData> buildPieChartSectionList(BuildContext context) {
     List<PieChartSectionData> sectionList = [];
+    inChartShownCats.clear();
 
     int elapsedDays = transContr.transactionsList.last.createdAt.difference(DateTime.now()).inDays;
     if(elapsedDays <= 0) elapsedDays = 1;
@@ -218,25 +227,79 @@ class _HomeViewState extends State<HomeView> {
         avg = categorySum;
       }
 
-      bool meetsThreshold = (categorySum / transContr.balance) > 0.2;
+      bool meetsThreshold = (categorySum.abs() / transContr.balance.abs()) > 0.06;
 
       if(!meetsThreshold) {
         other += avg;
       }
 
       if(!avg.isNaN && meetsThreshold) {
+        inChartShownCats.add(cat);
         sectionList.add(PieChartSectionData(
-          value: double.parse(avg.toStringAsFixed(2)),
+          value: double.parse(avg.toStringAsFixed(2)).abs(),
+          showTitle: true,
+          title: avg.toStringAsFixed(2),
           color: Color(cat.colorValue),
-          radius: 100.0
+          radius: 70.0,
+          badgeWidget: Container(
+            height: 40.0,
+            width: 40.0,
+            decoration: BoxDecoration(
+              color: Theme.of(context).colorScheme.surface,
+              shape: BoxShape.circle,
+            ),
+            child: Center(
+              child: Icon(
+                IconData(
+                  cat.iconCodePoint,
+                  fontFamily: cat.iconFontFamily,
+                ),
+                color: Color(cat.colorValue),
+              )
+            )
+          ),
+          titlePositionPercentageOffset: .4,
+          titleStyle: TextStyle(
+            color: Theme.of(context).colorScheme.onSurface
+          ),
+          badgePositionPercentageOffset: 1.1
         ));
       }
     }
-    sectionList.add(PieChartSectionData(
-      value: double.parse(other.toStringAsFixed(2)),
-      color: Colors.grey,
-      radius: 100.0
-    ));
+    if (other.abs() > 0) {
+      inChartShownCats.add(Category(
+        id: 'other',
+        title: 'Other',
+        iconCodePoint: Icons.category_rounded.codePoint,
+        colorValue: Colors.grey.value
+      ));
+      sectionList.add(PieChartSectionData(
+        value: double.parse(other.toStringAsFixed(2)).abs(),
+        showTitle: true,
+        title: other.toStringAsFixed(2),
+        color: Colors.grey,
+        radius: 70.0,
+        badgeWidget: Container(
+          height: 40.0,
+          width: 40.0,
+          decoration: BoxDecoration(
+            color: Theme.of(context).colorScheme.surface,
+            shape: BoxShape.circle
+          ),
+          child: const Center(
+            child: Icon(
+              Icons.category_rounded,
+              color: Colors.grey,
+            )
+          )
+        ),
+        titlePositionPercentageOffset: .4,
+        titleStyle: TextStyle(
+          color: Theme.of(context).colorScheme.onSurface
+        ),
+        badgePositionPercentageOffset: 1.1
+      ));
+}
     return sectionList;
   }
 }
diff --git a/trackeroo/lib/logic/services/transactions_controller.dart b/trackeroo/lib/logic/services/transactions_controller.dart
index 5f631a8..3b365c1 100644
--- a/trackeroo/lib/logic/services/transactions_controller.dart
+++ b/trackeroo/lib/logic/services/transactions_controller.dart
@@ -19,21 +19,21 @@ class TransactionsController extends ChangeNotifier {
       locator.get<CategoriesController>().categories[transaction.categoryId]?.spendings += transaction.amount;
       int id = UniqueKey().hashCode;
       transaction.id = id;
-      await transactionsBox.put(transaction.id, transaction);
-      transactionsList = transactionsBox.values.toList();
       balance += transaction.amount;
       if(transaction.amount.isNegative) {
         expenses += transaction.amount;
       } else {
         income += transaction.amount;
       }
+      await transactionsBox.put(transaction.id, transaction);
+      transactionsList = transactionsBox.values.toList();
     } catch (e) {
       return false;
     }
     return true;
   }
 
-  Future<bool> updateTransaction(Transaction transaction) async {
+  Future<bool> updateTransaction(double oldAmount, Transaction transaction) async {
     try {
       await transactionsBox.put(transaction.id, transaction);
       transactionsList = transactionsBox.values.toList();
@@ -46,14 +46,14 @@ class TransactionsController extends ChangeNotifier {
   Future<bool> deleteTransaction(Transaction transaction) async {
     try {
       lastDeletedTransaction = transaction;
-      await transactionsBox.delete(transaction.id);
-      transactionsList = transactionsBox.values.toList();
       balance -= transaction.amount;
       if(transaction.amount.isNegative) {
         expenses -= transaction.amount;
       } else {
         income -= transaction.amount;
       }
+      await transactionsBox.delete(transaction.id);
+      transactionsList = transactionsBox.values.toList();
     } catch (e) {
       return false;
     }
@@ -62,8 +62,6 @@ class TransactionsController extends ChangeNotifier {
 
   Future<bool> undoLastDeletion() async {
     try {
-      await transactionsBox.put(lastDeletedTransaction.id, lastDeletedTransaction);
-      transactionsList = transactionsBox.values.toList();
       balance += lastDeletedTransaction.amount;
 
       if(lastDeletedTransaction.amount.isNegative) {
@@ -71,6 +69,8 @@ class TransactionsController extends ChangeNotifier {
       } else {
         income += lastDeletedTransaction.amount;
       }
+      await transactionsBox.put(lastDeletedTransaction.id, lastDeletedTransaction);
+      transactionsList = transactionsBox.values.toList();
     } catch (e) {
       return false;
     }
-- 
GitLab