From 44f6d433d1e9c454029f241efb25d6e8d85d3ee5 Mon Sep 17 00:00:00 2001 From: gltron Date: Fri, 9 Feb 2024 01:22:04 +0100 Subject: [PATCH] Improved category with colors --- lib/domains/account/account_bloc.dart | 64 ++++++++++--- lib/domains/category/category_bloc.dart | 3 + lib/domains/category/category_state.dart | 6 +- lib/domains/charts/chart_bloc.dart | 54 ++--------- lib/domains/charts/chart_state.dart | 6 -- lib/pages/data/data_page.dart | 41 ++++---- .../data/widgets/categories_settings.dart | 57 +++++++++++ lib/pages/data/widgets/import_settings.dart | 54 +++++++++++ lib/pages/stats/stats_page.dart | 6 +- lib/pages/stats/widgets/account_counters.dart | 2 +- .../widgets/categories_totals_chart.dart | 95 +++++++++---------- .../monthly_categories_total_chart.dart | 55 ++++++----- .../account/account_repository.dart | 24 +++-- lib/repositories/account/models/category.dart | 6 ++ 14 files changed, 303 insertions(+), 170 deletions(-) create mode 100644 lib/pages/data/widgets/categories_settings.dart create mode 100644 lib/pages/data/widgets/import_settings.dart diff --git a/lib/domains/account/account_bloc.dart b/lib/domains/account/account_bloc.dart index 1523af2..fa5d254 100644 --- a/lib/domains/account/account_bloc.dart +++ b/lib/domains/account/account_bloc.dart @@ -6,12 +6,33 @@ import 'package:equatable/equatable.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:tunas/repositories/account/account_repository.dart'; +import 'package:tunas/repositories/account/models/account.dart'; +import 'package:tunas/repositories/account/models/category.dart'; import 'package:tunas/repositories/account/models/transaction.dart'; import 'package:uuid/uuid.dart'; part 'account_event.dart'; part 'account_state.dart'; +final colors = [ + 'FF74feff', + 'FF64c0ff', + 'FF5873fe', + 'FF4b4cff', + 'FFc0fcfd', + 'FFa7caff', + 'FF8d7efd', + 'FF7f65fe', + 'FFe7ffff', + 'FFd7dafd', + 'FFd8a6ff', + 'FFc065fe', + 'FFffffff', + 'FFffe6fe', + 'FFffbdff', + 'FFff80fe', +]; + class AccountBloc extends Bloc { final AccountRepository _accountRepository; @@ -38,6 +59,7 @@ class AccountBloc extends Bloc { _onAccountImportCSV( AccountImportCSV event, Emitter emit) async { + int colorIndex = 0; FilePickerResult? result = await FilePicker.platform.pickFiles(); final csvPath = result?.files.first.path; @@ -46,19 +68,39 @@ class AccountBloc extends Bloc { final String csvFileContent = await csv.readAsString(); final List> csvList = const CsvToListConverter(fieldDelimiter: '|', eol: '\n').convert(csvFileContent); + final Map categoriesMap = {}; + final transactions = csvList - .map((line) => Transaction( - uuid: const Uuid().v8(), - date: DateTime.parse(line[0]), - category: line[1], - description: line[2], - account: line[3], - value: _universalConvertToDouble(line[4])) - ) - .toList(); - + .map((line) { + + String? categoryLabel = line[1]; + if (categoryLabel == null || categoryLabel == '') { + categoryLabel = 'N/A'; + } + + if (categoriesMap[categoryLabel] == null) { + if (categoryLabel == 'N/A') { + categoriesMap[categoryLabel] = Category(label: 'N/A', color: 'FFFF0000' ); + } else { + String color = colorIndex >= colors.length ? 'FF0000FF' : colors[colorIndex]; + colorIndex++; + categoriesMap[categoryLabel] = Category(label: categoryLabel, color: color ); + } + } + + return Transaction( + uuid: const Uuid().v8(), + date: DateTime.parse(line[0]), + category: categoryLabel, + description: line[2], + account: line[3], + value: _universalConvertToDouble(line[4])); + }) + .toList(); + await _accountRepository.deleteAccount(); - await _accountRepository.saveTransactions(transactions); + final account = Account(transactions: transactions, categories: categoriesMap.values.toList()); + await _accountRepository.saveAccount(account); } } diff --git a/lib/domains/category/category_bloc.dart b/lib/domains/category/category_bloc.dart index 4c971ea..d3db74a 100644 --- a/lib/domains/category/category_bloc.dart +++ b/lib/domains/category/category_bloc.dart @@ -1,3 +1,5 @@ +import 'dart:ui'; + import 'package:equatable/equatable.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:tunas/repositories/account/account_repository.dart'; @@ -22,6 +24,7 @@ class CategoryBloc extends Bloc { ) { emit(state.copyWith( categories: event.categories, + categoriesColors: { for (var category in event.categories) category.label : category.rgbToColor() } )); } } diff --git a/lib/domains/category/category_state.dart b/lib/domains/category/category_state.dart index 9639fc1..9eb461f 100644 --- a/lib/domains/category/category_state.dart +++ b/lib/domains/category/category_state.dart @@ -2,19 +2,23 @@ part of 'category_bloc.dart'; final class CategoryState extends Equatable { final List categories; + final Map categoriesColors; const CategoryState({ this.categories = const [], + this.categoriesColors = const {}, }); CategoryState copyWith({ List? categories, + Map? categoriesColors, }) { return CategoryState( categories: categories ?? this.categories, + categoriesColors: categoriesColors ?? this.categoriesColors, ); } @override - List get props => [categories]; + List get props => [categories, categoriesColors]; } diff --git a/lib/domains/charts/chart_bloc.dart b/lib/domains/charts/chart_bloc.dart index e5ae774..69fab03 100644 --- a/lib/domains/charts/chart_bloc.dart +++ b/lib/domains/charts/chart_bloc.dart @@ -1,8 +1,5 @@ -import 'dart:ui'; - import 'package:equatable/equatable.dart'; import 'package:fl_chart/fl_chart.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:tunas/domains/transaction/models/transaction_line.dart'; import 'package:tunas/domains/charts/models/chart_item.dart'; @@ -12,29 +9,6 @@ import 'package:tunas/repositories/account/models/transaction.dart'; part 'chart_event.dart'; part 'chart_state.dart'; -final colors = [ - Colors.purple.shade300, - Colors.purple.shade500, - Colors.purple.shade700, - Colors.purple.shade900, - Colors.blue.shade300, - Colors.blue.shade500, - Colors.blue.shade700, - Colors.blue.shade900, - Colors.green.shade300, - Colors.green.shade500, - Colors.green.shade700, - Colors.green.shade900, - Colors.yellow.shade300, - Colors.yellow.shade500, - Colors.yellow.shade700, - Colors.yellow.shade900, - Colors.red.shade300, - Colors.red.shade500, - Colors.red.shade700, - Colors.red.shade900, -]; - class ChartBloc extends Bloc { final AccountRepository _accountRepository; @@ -56,13 +30,17 @@ class ChartBloc extends Bloc { } _onNextYear(ChartNextYear event, Emitter emit) { - ChartState localState = state.copyWith(currentYear: state.currentYear + 1); - emit(_computeStateScopedStats(localState)); + if (state.lastDate!.year >= state.currentYear + 1) { + ChartState localState = state.copyWith(currentYear: state.currentYear + 1); + emit(_computeStateScopedStats(localState)); + } } _onPreviousYear(ChartPreviousYear event, Emitter emit) { - ChartState localState = state.copyWith(currentYear: state.currentYear - 1); - emit(_computeStateScopedStats(localState)); + if (state.firstDate!.year <= state.currentYear - 1) { + ChartState localState = state.copyWith(currentYear: state.currentYear - 1); + emit(_computeStateScopedStats(localState)); + } } ChartState _computeStateStats(ChartState state) { @@ -90,11 +68,11 @@ class ChartBloc extends Bloc { transactionsLines.add(transactionLine); monthlyTotals.add(FlSpot(transactionLine.transaction.date.microsecondsSinceEpoch.toDouble(), transactionLine.subTotal)); - if (firstDate.compareTo(transaction.date) < 0) { + if (firstDate.compareTo(transaction.date) > 0) { firstDate = transaction.date; } - if (lastDate.compareTo(transaction.date) > 0) { + if (lastDate.compareTo(transaction.date) < 0) { lastDate = transaction.date; } @@ -122,8 +100,6 @@ class ChartBloc extends Bloc { List scopedCategoriesNegativeTotals = []; Map scopedMonthlyTotals = {}; Map> scopedCategoriesMonthlyTotals = {}; - Map categoriesColors = {}; - int colorIndex = 0; for(var transaction in state.transactions) { double subTotal = globalTotal + transaction.value; @@ -148,15 +124,6 @@ class ChartBloc extends Bloc { continue; } - if (categoriesColors[transaction.category] == null) { - if (colorIndex >= colors.length) { - categoriesColors[transaction.category] = const Color.fromARGB(255, 234, 0, 255); - } else { - categoriesColors[transaction.category] = colors[colorIndex]; - } - colorIndex++; - } - if (transaction.value >= 0) { ChartItem? chartItem = scopedCategoriesPositiveTotals.firstWhere( (item) => item.label == transaction.category, @@ -248,7 +215,6 @@ class ChartBloc extends Bloc { scopedSimplifiedCategoriesNegativeTotalsPercents: scopedSimplifiedCategoriesNegativeTotalsPercents, scopedMonthlyTotals: scopedMonthlyTotals.values.toList(), scopedCategoriesMonthlyTotals: scopedCategoriesMonthlyTotals, - categoriesColors: categoriesColors, ); } } diff --git a/lib/domains/charts/chart_state.dart b/lib/domains/charts/chart_state.dart index 2a9b2e2..78e989e 100644 --- a/lib/domains/charts/chart_state.dart +++ b/lib/domains/charts/chart_state.dart @@ -29,8 +29,6 @@ final class ChartState extends Equatable { final List scopedMonthlyTotals; final Map> scopedCategoriesMonthlyTotals; - final Map categoriesColors; - const ChartState({ this.transactions = const [], this.transactionsLines = const [], @@ -52,7 +50,6 @@ final class ChartState extends Equatable { this.scopedSimplifiedCategoriesNegativeTotalsPercents = const [], this.scopedMonthlyTotals = const [], this.scopedCategoriesMonthlyTotals = const {}, - this.categoriesColors = const {}, }); ChartState copyWith({ @@ -76,7 +73,6 @@ final class ChartState extends Equatable { List? scopedSimplifiedCategoriesNegativeTotalsPercents, List? scopedMonthlyTotals, Map>? scopedCategoriesMonthlyTotals, - Map? categoriesColors, }) { return ChartState( transactions: transactions ?? this.transactions, @@ -99,7 +95,6 @@ final class ChartState extends Equatable { scopedSimplifiedCategoriesNegativeTotalsPercents: scopedSimplifiedCategoriesNegativeTotalsPercents ?? this.scopedSimplifiedCategoriesNegativeTotalsPercents, scopedMonthlyTotals: scopedMonthlyTotals ?? this.scopedMonthlyTotals, scopedCategoriesMonthlyTotals: scopedCategoriesMonthlyTotals ?? this.scopedCategoriesMonthlyTotals, - categoriesColors: categoriesColors ?? this.categoriesColors, ); } @@ -123,7 +118,6 @@ final class ChartState extends Equatable { scopedSimplifiedCategoriesNegativeTotalsPercents, scopedMonthlyTotals, scopedCategoriesMonthlyTotals, - categoriesColors, ]; } diff --git a/lib/pages/data/data_page.dart b/lib/pages/data/data_page.dart index ee04d91..7efa548 100644 --- a/lib/pages/data/data_page.dart +++ b/lib/pages/data/data_page.dart @@ -1,32 +1,33 @@ import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:tunas/domains/account/account_bloc.dart'; +import 'package:tunas/pages/data/widgets/categories_settings.dart'; +import 'package:tunas/pages/data/widgets/import_settings.dart'; class DataPage extends StatelessWidget { const DataPage({super.key}); @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) => Column( + return Container( + padding: const EdgeInsets.symmetric(vertical: 9, horizontal: 10), + margin: const EdgeInsets.symmetric(vertical: 2, horizontal: 10), + child: const Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - FilledButton( - onPressed: () => context.read().add(const AccountImportCSV()), - child: const Text('Import CSV') + Text( + 'Settings', + style: TextStyle( + fontWeight: FontWeight.w900, + fontSize: 35, + ), ), - FilledButton( - onPressed: () => context.read().add(const AccountImportJSON()), - child: const Text('Import JSON') - ), - FilledButton( - onPressed: () => context.read().add(const AccountExportCSV()), - child: const Text('Export CSV') - ), - FilledButton( - onPressed: () => context.read().add(const AccountExportJSON()), - child: const Text('Export JSON') - ), - ], + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ImportSettings(), + CategoriesSettings() + ], + ) + ] ) ); } diff --git a/lib/pages/data/widgets/categories_settings.dart b/lib/pages/data/widgets/categories_settings.dart new file mode 100644 index 0000000..3cb5681 --- /dev/null +++ b/lib/pages/data/widgets/categories_settings.dart @@ -0,0 +1,57 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:tunas/domains/category/category_bloc.dart'; +import 'package:tunas/repositories/account/models/category.dart'; + +class CategoriesSettings extends StatelessWidget { + const CategoriesSettings({super.key}); + + List _computeCategoryList(List categories) { + return categories.map((category) => Row( + children: [ + Container( + height: 10, + width: 10, + color: category.rgbToColor(), + ), + Container(width: 5), + Text(category.label), + ], + )).toList(); + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) => Container( + decoration: BoxDecoration( + color: Colors.blue, + borderRadius: BorderRadius.circular(5), + ), + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15), + margin: const EdgeInsets.all(5), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + "Categories", + style: TextStyle( + fontWeight: FontWeight.w900, + fontSize: 20, + ), + ), + const SizedBox(height: 10), + SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: _computeCategoryList(state.categories), + ), + ), + ], + ) + ), + ); + } +} \ No newline at end of file diff --git a/lib/pages/data/widgets/import_settings.dart b/lib/pages/data/widgets/import_settings.dart new file mode 100644 index 0000000..10ce384 --- /dev/null +++ b/lib/pages/data/widgets/import_settings.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:tunas/domains/account/account_bloc.dart'; + +class ImportSettings extends StatelessWidget { + const ImportSettings({super.key}); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) => Container( + decoration: BoxDecoration( + color: Colors.blue, + borderRadius: BorderRadius.circular(5) + ), + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15), + margin: const EdgeInsets.all(5), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + "Import", + style: TextStyle( + fontWeight: FontWeight.w900, + fontSize: 20, + ), + ), + const SizedBox(height: 10), + FilledButton( + onPressed: () => context.read().add(const AccountImportCSV()), + child: const Text('Import CSV') + ), + const SizedBox(height: 5), + FilledButton( + onPressed: () => context.read().add(const AccountImportJSON()), + child: const Text('Import JSON') + ), + const SizedBox(height: 5), + FilledButton( + onPressed: () => context.read().add(const AccountExportCSV()), + child: const Text('Export CSV') + ), + const SizedBox(height: 5), + FilledButton( + onPressed: () => context.read().add(const AccountExportJSON()), + child: const Text('Export JSON') + ), + ], + ), + ) + ); + } +} \ No newline at end of file diff --git a/lib/pages/stats/stats_page.dart b/lib/pages/stats/stats_page.dart index ffa689b..26762e6 100644 --- a/lib/pages/stats/stats_page.dart +++ b/lib/pages/stats/stats_page.dart @@ -45,15 +45,15 @@ class StatsPage extends StatelessWidget { ), SizedBox( height: 500, - child: MonthlyCategoriesTotalChart(categoriesMonthlyTotals: state.scopedCategoriesMonthlyTotals, categoriesColors: state.categoriesColors) + child: MonthlyCategoriesTotalChart(categoriesMonthlyTotals: state.scopedCategoriesMonthlyTotals) ), SizedBox( height: 450, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - CategoriesTotalsChart(categoriesTotals: state.scopedCategoriesPositiveTotals, categoriesTotalsPercents: state.scopedCategoriesPositiveTotalsPercents, categoriesColors: state.categoriesColors), - CategoriesTotalsChart(categoriesTotals: state.scopedCategoriesNegativeTotals, categoriesTotalsPercents: state.scopedSimplifiedCategoriesNegativeTotalsPercents, categoriesColors: state.categoriesColors), + CategoriesTotalsChart(categoriesTotals: state.scopedCategoriesPositiveTotals, categoriesTotalsPercents: state.scopedSimplifiedCategoriesPositiveTotalsPercents), + CategoriesTotalsChart(categoriesTotals: state.scopedCategoriesNegativeTotals, categoriesTotalsPercents: state.scopedSimplifiedCategoriesNegativeTotalsPercents), ], ) ), diff --git a/lib/pages/stats/widgets/account_counters.dart b/lib/pages/stats/widgets/account_counters.dart index fe96c41..a9f7b85 100644 --- a/lib/pages/stats/widgets/account_counters.dart +++ b/lib/pages/stats/widgets/account_counters.dart @@ -10,7 +10,7 @@ class AccountCounter extends StatelessWidget { return accountsTotals.entries.toList().map((entry) => Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text("${entry.key}:"), + Text(entry.key), Text( NumberFormat('#######.00 €', 'fr_FR').format(entry.value), style: TextStyle( diff --git a/lib/pages/stats/widgets/categories_totals_chart.dart b/lib/pages/stats/widgets/categories_totals_chart.dart index f0d495d..d6fd54e 100644 --- a/lib/pages/stats/widgets/categories_totals_chart.dart +++ b/lib/pages/stats/widgets/categories_totals_chart.dart @@ -1,21 +1,22 @@ import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:intl/intl.dart'; +import 'package:tunas/domains/category/category_bloc.dart'; import 'package:tunas/domains/charts/models/chart_item.dart'; class CategoriesTotalsChart extends StatelessWidget { final List categoriesTotals; final List categoriesTotalsPercents; - final Map categoriesColors; - const CategoriesTotalsChart({super.key, required this.categoriesTotals, required this.categoriesTotalsPercents, required this.categoriesColors}); + const CategoriesTotalsChart({super.key, required this.categoriesTotals, required this.categoriesTotalsPercents}); - List _convertDataForChart() { + List _convertDataForChart(Map categoriesColors) { return categoriesTotalsPercents .map((item) => PieChartSectionData( value: item.value, - title: item.label, + title: NumberFormat("#0 %").format(item.value / 100), titleStyle: const TextStyle( fontSize: 15, fontWeight: FontWeight.w300 @@ -28,7 +29,7 @@ class CategoriesTotalsChart extends StatelessWidget { .toList(); } - List _computeLegend() { + List _computeLegend(Map categoriesColors) { return categoriesTotals .map((item) => Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -56,55 +57,49 @@ class CategoriesTotalsChart extends StatelessWidget { @override Widget build(BuildContext context) { - return Container( - height: 320, - width: 560, - padding: const EdgeInsets.all(10), - margin: const EdgeInsets.all(20), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(5), - color: Colors.blue - ), - child: Expanded( - child: AspectRatio( - aspectRatio: 1.3, - child: Row( - children: [ - Expanded( - child: AspectRatio( - aspectRatio: 1, - child: PieChart( - PieChartData( - sections: _convertDataForChart(), - borderData: FlBorderData( - show: false - ), - centerSpaceRadius: 0, - sectionsSpace: 2 - ) + return BlocBuilder( + builder: (context, state) => Container( + height: 320, + width: 560, + padding: const EdgeInsets.all(10), + margin: const EdgeInsets.all(20), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + color: Colors.blue + ), + child: Row( + children: [ + Expanded( + child: PieChart( + PieChartData( + sections: _convertDataForChart(state.categoriesColors), + borderData: FlBorderData( + show: false ), + centerSpaceRadius: 0, + sectionsSpace: 2 ) ), - Container( - height: 300, - width: 250, - padding: const EdgeInsets.all(10), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(5), - color: Colors.blueGrey - ), - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: _computeLegend(), - ), - ) + ), + Container( + height: 300, + width: 250, + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + color: Colors.blueGrey ), - ], - ), - ) + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: _computeLegend(state.categoriesColors), + ), + ) + ), + ], + ), ) ); } diff --git a/lib/pages/stats/widgets/monthly_categories_total_chart.dart b/lib/pages/stats/widgets/monthly_categories_total_chart.dart index 4bf5d13..0df4ae1 100644 --- a/lib/pages/stats/widgets/monthly_categories_total_chart.dart +++ b/lib/pages/stats/widgets/monthly_categories_total_chart.dart @@ -1,13 +1,14 @@ import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:tunas/domains/category/category_bloc.dart'; class MonthlyCategoriesTotalChart extends StatelessWidget { final Map> categoriesMonthlyTotals; - final Map categoriesColors; - const MonthlyCategoriesTotalChart({super.key, required this.categoriesMonthlyTotals, required this.categoriesColors}); + const MonthlyCategoriesTotalChart({super.key, required this.categoriesMonthlyTotals}); - BarChartRodData _computeStack(double barsWidth, MapEntry> entry) { + BarChartRodData _computeStack(double barsWidth, MapEntry> entry, Map categoriesColors) { var subcounter = 0.0; var a = entry.value.entries.map((subEntry) => BarChartRodStackItem(subcounter, subcounter += subEntry.value, categoriesColors[subEntry.key] ?? Colors.red)).toList(); return BarChartRodData( @@ -19,13 +20,13 @@ class MonthlyCategoriesTotalChart extends StatelessWidget { ); } - List _computeBarGroups(double barsSpace, double barsWidth) { + List _computeBarGroups(double barsSpace, double barsWidth, Map categoriesColors) { var a = categoriesMonthlyTotals.entries .map((entry) { return BarChartGroupData( x: entry.key, barsSpace: barsSpace, - barRods: [_computeStack(barsWidth, entry)] + barRods: [_computeStack(barsWidth, entry, categoriesColors)] ); }) .toList(); @@ -55,31 +56,33 @@ class MonthlyCategoriesTotalChart extends StatelessWidget { @override Widget build(BuildContext context) { - return AspectRatio( - aspectRatio: 1.66, - child: LayoutBuilder( - builder: (context, constraints) { - final barsSpace = 4.0 * constraints.maxWidth / 100; - final barsWidth = 8.0 * constraints.maxWidth / 130; + return BlocBuilder( + builder: (context, state) => AspectRatio( + aspectRatio: 1.66, + child: LayoutBuilder( + builder: (context, constraints) { + final barsSpace = 4.0 * constraints.maxWidth / 100; + final barsWidth = 8.0 * constraints.maxWidth / 130; - return BarChart( - BarChartData( - maxY: _computeMaxValue(), - barGroups: _computeBarGroups(barsSpace, barsWidth), - titlesData: FlTitlesData( - topTitles: const AxisTitles( - sideTitles: SideTitles(showTitles: false) - ), - bottomTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - getTitlesWidget: _computeBottomTitles + return BarChart( + BarChartData( + maxY: _computeMaxValue(), + barGroups: _computeBarGroups(barsSpace, barsWidth, state.categoriesColors), + titlesData: FlTitlesData( + topTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false) + ), + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + getTitlesWidget: _computeBottomTitles + ) ) ) ) - ) - ); - }, + ); + }, + ) ) ); } diff --git a/lib/repositories/account/account_repository.dart b/lib/repositories/account/account_repository.dart index 229d8fa..ad54b37 100644 --- a/lib/repositories/account/account_repository.dart +++ b/lib/repositories/account/account_repository.dart @@ -9,6 +9,7 @@ import 'package:tunas/repositories/account/models/transaction.dart'; class AccountRepository { String accountFile = 'tunas_main_account.json'; + Account? currentAccount; final StorageClient _storageClient; @@ -49,20 +50,27 @@ class AccountRepository { saveAccount(Account account) async { await _storageClient.save(accountFile, jsonEncode(account.toJson())); + _broadcastAccountData(account); } saveTransactions(List transactions) async { - final account = Account(transactions: transactions); - await saveAccount(account); - _transactionsController.add(account.transactions); - _categoriesController.add(account.categories); - _budgetController.add(account.budgets); + Account? account = currentAccount; + if (account == null) { + throw Error(); + } else {account.transactions = transactions; + await saveAccount(account); + } } deleteAccount() async { await _storageClient.delete(accountFile); - _transactionsController.add(const []); - _categoriesController.add(const []); - _budgetController.add(const []); + _broadcastAccountData(Account()); + } + + _broadcastAccountData(Account account) { + currentAccount = account; + _transactionsController.add(account.transactions); + _categoriesController.add(account.categories); + _budgetController.add(account.budgets); } } diff --git a/lib/repositories/account/models/category.dart b/lib/repositories/account/models/category.dart index 7360d29..de1c2e4 100644 --- a/lib/repositories/account/models/category.dart +++ b/lib/repositories/account/models/category.dart @@ -1,3 +1,5 @@ +import 'dart:ui'; + class Category { String label; String color; @@ -18,4 +20,8 @@ class Category { 'label': label, 'color': color, }; + + Color rgbToColor() { + return Color(int.parse(color.toUpperCase().replaceAll("#", ""), radix: 16)); + } }