diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..a89b377 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,25 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "tunas", + "request": "launch", + "type": "dart" + }, + { + "name": "tunas (profile mode)", + "request": "launch", + "type": "dart", + "flutterMode": "profile" + }, + { + "name": "tunas (release mode)", + "request": "launch", + "type": "dart", + "flutterMode": "release" + } + ] +} \ No newline at end of file diff --git a/lib/domains/account/account_bloc.dart b/lib/domains/account/account_bloc.dart index f626d04..0fd7316 100644 --- a/lib/domains/account/account_bloc.dart +++ b/lib/domains/account/account_bloc.dart @@ -202,7 +202,11 @@ class AccountBloc extends Bloc { accountFound.color = accountToSave.color; accountFound.saving = accountToSave.saving; } catch (e) { - accounts.add(accountToSave); + if (accounts.isEmpty) { + accounts = [accountToSave]; + } else { + accounts.add(accountToSave); + } } await _metadataRepository.saveAccounts(accounts); diff --git a/lib/pages/budgets/budgets_page.dart b/lib/pages/budgets/budgets_page.dart index 210ec6c..5ec38d2 100644 --- a/lib/pages/budgets/budgets_page.dart +++ b/lib/pages/budgets/budgets_page.dart @@ -7,19 +7,19 @@ class BudgetsPage extends StatelessWidget { @override Widget build(BuildContext context) { + MediaQueryData mediaQuery = MediaQuery.of(context); return Center( child: Container( constraints: const BoxConstraints( maxWidth: 1000 ), - padding: const EdgeInsets.symmetric(vertical: 9, horizontal: 10), - margin: const EdgeInsets.symmetric(vertical: 2, horizontal: 10), - child: const Column( - children: [ + child: ListView( + padding: mediaQuery.padding.copyWith(left: 10.0, right: 10.0, bottom: 100.0), + children: const [ BudgetsActions(), MonthDistribution() - ], - ) + ] + ), ) ); } diff --git a/lib/pages/data/data_page.dart b/lib/pages/data/data_page.dart index 35db0ff..ddd8cdd 100644 --- a/lib/pages/data/data_page.dart +++ b/lib/pages/data/data_page.dart @@ -8,34 +8,27 @@ class DataPage extends StatelessWidget { @override Widget build(BuildContext context) { + MediaQueryData mediaQuery = MediaQuery.of(context); return Center( child: Container( constraints: const BoxConstraints( maxWidth: 1000 ), - padding: const EdgeInsets.symmetric(vertical: 9, horizontal: 10), - margin: const EdgeInsets.symmetric(vertical: 2, horizontal: 10), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( + child: ListView( + padding: mediaQuery.padding.copyWith(left: 10.0, right: 10.0, bottom: 100.0), + children: const [ + Text( 'Settings', style: TextStyle( fontWeight: FontWeight.w900, fontSize: 35, ), ), - Expanded( - child: ListView( - children: const [ - ImportSettings(), - AccountSettings(), - CategoriesSettings(), - ] - ) - ), + ImportSettings(), + AccountSettings(), + CategoriesSettings(), ] - ) + ), ) ); } diff --git a/lib/pages/stats/stats_page.dart b/lib/pages/stats/stats_page.dart index 0c806bc..2de8075 100644 --- a/lib/pages/stats/stats_page.dart +++ b/lib/pages/stats/stats_page.dart @@ -110,6 +110,7 @@ class StatsPage extends StatelessWidget { @override Widget build(BuildContext context) { + MediaQueryData mediaQuery = MediaQuery.of(context); bool smallVerticalScreen = MediaQuery.sizeOf(context).width < 800; return BlocProvider( create: (context) => ChartBloc( @@ -118,6 +119,7 @@ class StatsPage extends StatelessWidget { ), child: BlocBuilder( builder: (context, state) => ListView( + padding: mediaQuery.padding.copyWith(bottom: 100.0), children: [ smallVerticalScreen ? _smallScreenHeader(state) : _largeScreenHeader(state), SizedBox( diff --git a/lib/pages/stats/widgets/monthly_categories_total_chart.dart b/lib/pages/stats/widgets/monthly_categories_total_chart.dart index db31c39..d90f7a5 100644 --- a/lib/pages/stats/widgets/monthly_categories_total_chart.dart +++ b/lib/pages/stats/widgets/monthly_categories_total_chart.dart @@ -26,7 +26,7 @@ class MonthlyCategoriesTotalChart extends StatelessWidget { ); } - List _computeBarGroups(double barsSpace, double barsWidth, Map categoriesColors) { + List _computeBarGroups(double barsSpace, double barsWidth, Map categoriesColors, bool smallVerticalScreen) { var a = categoriesMonthlyTotals.entries .map((entry) { return BarChartGroupData( @@ -36,7 +36,7 @@ class MonthlyCategoriesTotalChart extends StatelessWidget { _computeStack(barsWidth, entry.value.positives, categoriesColors), _computeStack(barsWidth, entry.value.negatives, categoriesColors), ], - showingTooltipIndicators: [0, 1] + showingTooltipIndicators: smallVerticalScreen ? [] : [0, 1] ); }) .toList(); @@ -66,6 +66,7 @@ class MonthlyCategoriesTotalChart extends StatelessWidget { @override Widget build(BuildContext context) { + bool smallVerticalScreen = MediaQuery.sizeOf(context).width < 800; return BlocBuilder( builder: (context, state) => AspectRatio( aspectRatio: 1.66, @@ -77,7 +78,7 @@ class MonthlyCategoriesTotalChart extends StatelessWidget { return BarChart( BarChartData( maxY: _computeMaxValue(), - barGroups: _computeBarGroups(barsSpace, barsWidth, state.categoriesColors), + barGroups: _computeBarGroups(barsSpace, barsWidth, state.categoriesColors, smallVerticalScreen), titlesData: FlTitlesData( topTitles: const AxisTitles( sideTitles: SideTitles(showTitles: false) diff --git a/lib/pages/transactions/transactions_page.dart b/lib/pages/transactions/transactions_page.dart index 9e14964..86d225b 100644 --- a/lib/pages/transactions/transactions_page.dart +++ b/lib/pages/transactions/transactions_page.dart @@ -8,11 +8,13 @@ class TransactionsPage extends StatelessWidget { @override Widget build(BuildContext context) { + MediaQueryData mediaQuery = MediaQuery.of(context); return Center( - child: ConstrainedBox( + child: Container( constraints: const BoxConstraints( maxWidth: 1000 ), + padding: mediaQuery.padding, child: const Column( children: [ TransactionsActions(), diff --git a/lib/pages/transactions/widgets/transaction_line.dart b/lib/pages/transactions/widgets/transaction_line.dart index 19dd076..2d457c0 100644 --- a/lib/pages/transactions/widgets/transaction_line.dart +++ b/lib/pages/transactions/widgets/transaction_line.dart @@ -9,8 +9,121 @@ class TransactionLine extends StatelessWidget { const TransactionLine({super.key, required this.transaction, required this.subTotal}); + List _largeScreenLayout(BuildContext context) { + return [ + SizedBox( + width: 100, + child: Text( + DateFormat('dd/MM/yyyy', 'fr_FR').format(transaction.date), + style: const TextStyle( + fontWeight: FontWeight.w300, + fontSize: 15 + ) + ) + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + transaction.category, + style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 18) + ), + Text( + transaction.description, + style: const TextStyle(fontWeight: FontWeight.w300, fontSize: 15) + ), + ], + ), + ), + 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 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.error + ) + ), + Text( + NumberFormat('#######.00 €', 'fr_FR').format(subTotal), + style: TextStyle( + fontWeight: FontWeight.w300, + fontSize: 15, + color: subTotal > 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.error + ) + ), + ], + ), + ) + ]; + } + + List _smallScreenLayout(BuildContext context) { + return [ + SizedBox( + width: 100, + child: Text( + DateFormat('dd/MM/yyyy', 'fr_FR').format(transaction.date), + style: const TextStyle( + fontWeight: FontWeight.w300, + fontSize: 15 + ) + ) + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + transaction.category, + style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 18) + ), + Text( + transaction.description, + style: const TextStyle(fontWeight: FontWeight.w300, fontSize: 15) + ), + Text( + transaction.account, + style: const TextStyle(fontWeight: FontWeight.w300, fontSize: 15) + ), + ], + ), + ), + 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 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.error + ) + ), + Text( + NumberFormat('#######.00 €', 'fr_FR').format(subTotal), + style: TextStyle( + fontWeight: FontWeight.w300, + fontSize: 15, + color: subTotal > 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.error + ) + ), + ], + ), + ) + ]; + } + @override Widget build(BuildContext context) { + bool smallVerticalScreen = MediaQuery.sizeOf(context).width < 800; return InkWell( onTap: () => TransactionAddDialog.show(context, transaction), child: MergeSemantics( @@ -19,48 +132,7 @@ class TransactionLine extends StatelessWidget { 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), - ], - ), - ), - 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 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.error - ) - ), - Text( - NumberFormat('#######.00 €', 'fr_FR').format(subTotal), - style: TextStyle( - color: subTotal > 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.error - ) - ), - ], - ), - ) - ], + children: smallVerticalScreen ? _smallScreenLayout(context) : _largeScreenLayout(context), ) ) ) diff --git a/lib/pages/transactions/widgets/transactions_actions.dart b/lib/pages/transactions/widgets/transactions_actions.dart index ac07abc..8c0252e 100644 --- a/lib/pages/transactions/widgets/transactions_actions.dart +++ b/lib/pages/transactions/widgets/transactions_actions.dart @@ -23,7 +23,7 @@ class TransactionsActions extends StatelessWidget { ), FilledButton.icon( onPressed: () => TransactionAddDialog.show(context, null), - label: const Text('Add transaction'), + label: const Text('Add'), icon: const Icon( Icons.add ) diff --git a/lib/pages/transactions/widgets/transactions_header.dart b/lib/pages/transactions/widgets/transactions_header.dart index bf5ac01..43f4a0e 100644 --- a/lib/pages/transactions/widgets/transactions_header.dart +++ b/lib/pages/transactions/widgets/transactions_header.dart @@ -3,39 +3,66 @@ import 'package:flutter/material.dart'; class TransactionsHeader extends StatelessWidget { const TransactionsHeader({super.key}); + List _largeScreenLayout() { + return const [ + SizedBox( + width: 100, + child: Text('Date') + ), + Expanded( + child: Text('Description') + ), + SizedBox( + width: 100, + child: Text('Account'), + ), + SizedBox( + width: 120, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text('Amount'), + Text('SubTotal'), + ], + ), + ) + ]; + } + + List _smallScreenLayout() { + return const [ + SizedBox( + width: 100, + child: Text('Date') + ), + Expanded( + child: Text('Description') + ), + SizedBox( + width: 120, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text('Amount'), + Text('SubTotal'), + ], + ), + ) + ]; + } + @override Widget build(BuildContext context) { + bool smallVerticalScreen = MediaQuery.sizeOf(context).width < 800; return Container( padding: const EdgeInsets.symmetric(vertical: 9, horizontal: 10), margin: const EdgeInsets.symmetric(vertical: 2, horizontal: 10), decoration: const BoxDecoration( border: Border(bottom: BorderSide(color: Colors.black)) ), - child: const Row( + child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - SizedBox( - width: 100, - child: Text('Date') - ), - Expanded( - child: Text('Description') - ), - SizedBox( - width: 100, - child: Text('Account'), - ), - SizedBox( - width: 120, - child: Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text('Amount'), - Text('SubTotal'), - ], - ), - ) - ], + children: smallVerticalScreen ? _smallScreenLayout() : _largeScreenLayout(), ), ); }