diff --git a/lib/custom_widgets/account_modal.dart b/lib/custom_widgets/account_modal.dart index 7d0f440..cd470f5 100644 --- a/lib/custom_widgets/account_modal.dart +++ b/lib/custom_widgets/account_modal.dart @@ -2,18 +2,22 @@ import 'dart:ui'; import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../constants/functions.dart'; +import '../providers/currency_provider.dart'; import 'line_chart.dart'; -class AccountDialog extends StatelessWidget with Functions { +class AccountDialog extends ConsumerWidget with Functions { final String accountName; final num amount; const AccountDialog({super.key, required this.accountName, required this.amount}); @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { + final currencyState = ref.watch(currencyStateNotifier); + return SingleChildScrollView( child: Column( children: [ @@ -108,7 +112,7 @@ class AccountDialog extends StatelessWidget with Functions { TextSpan( text: "-285,99", style: Theme.of(context).textTheme.labelSmall), TextSpan( - text: "€", + text: currencyState.selectedCurrency.symbol, style: Theme.of(context) .textTheme .headlineSmall @@ -154,7 +158,7 @@ class AccountDialog extends StatelessWidget with Functions { text: "-280,00", style: Theme.of(context).textTheme.labelSmall), TextSpan( - text: "€", + text: currencyState.selectedCurrency.symbol, style: Theme.of(context).textTheme.headlineSmall?.apply( fontFeatures: [const FontFeature.subscripts()], ), @@ -228,7 +232,7 @@ class AccountDialog extends StatelessWidget with Functions { style: Theme.of(context).textTheme.labelSmall, ), TextSpan( - text: "€", + text: currencyState.selectedCurrency.symbol, style: Theme.of(context).textTheme.headlineSmall?.apply( fontFeatures: [const FontFeature.subscripts()], ), @@ -303,7 +307,7 @@ class AccountDialog extends StatelessWidget with Functions { style: Theme.of(context).textTheme.labelSmall, ), TextSpan( - text: "€", + text: currencyState.selectedCurrency.symbol, style: Theme.of(context).textTheme.headlineSmall?.apply( fontFeatures: [const FontFeature.subscripts()], ), diff --git a/lib/custom_widgets/accounts_sum.dart b/lib/custom_widgets/accounts_sum.dart index 819679f..4189e41 100644 --- a/lib/custom_widgets/accounts_sum.dart +++ b/lib/custom_widgets/accounts_sum.dart @@ -7,6 +7,7 @@ import '../model/bank_account.dart'; import '../constants/functions.dart'; import '../constants/style.dart'; import '../../../providers/accounts_provider.dart'; +import '../providers/currency_provider.dart'; /// This class shows account summaries in the dashboard class AccountsSum extends ConsumerWidget with Functions { @@ -19,8 +20,9 @@ class AccountsSum extends ConsumerWidget with Functions { @override Widget build(BuildContext context, WidgetRef ref) { + final currencyState = ref.watch(currencyStateNotifier); + return Container( - width: 160.0, margin: const EdgeInsets.fromLTRB(0, 4, 16, 6), decoration: BoxDecoration( color: white, @@ -40,7 +42,8 @@ class AccountsSum extends ConsumerWidget with Functions { await ref .read(accountsProvider.notifier) .selectedAccount(account) - .whenComplete(() => Navigator.of(context).pushNamed('/account')); + .whenComplete( + () => Navigator.of(context).pushNamed('/account')); }, child: Container( padding: const EdgeInsets.fromLTRB(12, 8, 12, 8), @@ -67,7 +70,10 @@ class AccountsSum extends ConsumerWidget with Functions { children: [ Text( account.name, - style: Theme.of(context).textTheme.bodyLarge!.copyWith(color: darkBlue7), + style: Theme.of(context) + .textTheme + .bodyLarge! + .copyWith(color: darkBlue7), ), RichText( text: TextSpan( @@ -80,8 +86,9 @@ class AccountsSum extends ConsumerWidget with Functions { .copyWith(color: darkBlue7), ), TextSpan( - text: "€", - style: Theme.of(context).textTheme.bodyMedium?.apply( + text: currencyState.selectedCurrency.symbol, + style: + Theme.of(context).textTheme.bodySmall?.apply( fontFeatures: [const FontFeature.subscripts()], ).copyWith(color: darkBlue7), ), diff --git a/lib/custom_widgets/budget_circular_indicator.dart b/lib/custom_widgets/budget_circular_indicator.dart index 0c36847..f872eb1 100644 --- a/lib/custom_widgets/budget_circular_indicator.dart +++ b/lib/custom_widgets/budget_circular_indicator.dart @@ -1,11 +1,13 @@ import 'dart:ui'; import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:percent_indicator/circular_percent_indicator.dart'; import '../constants/functions.dart'; +import '../providers/currency_provider.dart'; /// This class shows account summaries in dashboard -class BudgetCircularIndicator extends StatelessWidget with Functions { +class BudgetCircularIndicator extends ConsumerWidget with Functions { final String title; final num amount; final double perc; @@ -20,7 +22,9 @@ class BudgetCircularIndicator extends StatelessWidget with Functions { }); @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { + final currencyState = ref.watch(currencyStateNotifier); + return Column( children: [ CircularPercentIndicator( @@ -43,7 +47,7 @@ class BudgetCircularIndicator extends StatelessWidget with Functions { .copyWith(color: Theme.of(context).colorScheme.primary), ), TextSpan( - text: "€", + text: currencyState.selectedCurrency.symbol, style: Theme.of(context) .textTheme .labelMedium! diff --git a/lib/custom_widgets/transactions_list.dart b/lib/custom_widgets/transactions_list.dart index 8f10004..e0b0b90 100644 --- a/lib/custom_widgets/transactions_list.dart +++ b/lib/custom_widgets/transactions_list.dart @@ -5,6 +5,7 @@ import '../constants/constants.dart'; import '../constants/functions.dart'; import '../constants/style.dart'; import '../model/transaction.dart'; +import '../providers/currency_provider.dart'; import '../providers/transactions_provider.dart'; import '../utils/date_helper.dart'; import 'default_container.dart'; @@ -99,7 +100,7 @@ class _TransactionsListState extends State with Functions { } } -class TransactionTitle extends StatelessWidget with Functions { +class TransactionTitle extends ConsumerWidget with Functions { final DateTime date; final num total; final bool first; @@ -112,7 +113,8 @@ class TransactionTitle extends StatelessWidget with Functions { }); @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { + final currencyState = ref.watch(currencyStateNotifier); final color = total < 0 ? red : (total > 0 ? green : blue3); return Padding( padding: EdgeInsets.only(top: first ? 0 : 24), @@ -136,7 +138,7 @@ class TransactionTitle extends StatelessWidget with Functions { style: Theme.of(context).textTheme.bodyLarge!.copyWith(color: color), ), TextSpan( - text: "€", + text: currencyState.selectedCurrency.symbol, style: Theme.of(context) .textTheme .labelMedium! @@ -163,6 +165,8 @@ class TransactionRow extends ConsumerWidget with Functions { @override Widget build(BuildContext context, WidgetRef ref) { + final currencyState = ref.watch(currencyStateNotifier); + return Column( children: [ Material( @@ -233,7 +237,7 @@ class TransactionRow extends ConsumerWidget with Functions { .copyWith(color: typeToColor(transaction.type)), ), TextSpan( - text: "€", + text: currencyState.selectedCurrency.symbol, style: Theme.of(context) .textTheme .labelSmall! diff --git a/lib/model/currency.dart b/lib/model/currency.dart index 7eb9c87..6a49af9 100644 --- a/lib/model/currency.dart +++ b/lib/model/currency.dart @@ -62,14 +62,37 @@ class Currency extends BaseEntity { }; } -class BudgetMethods extends SossoldiDatabase { +class CurrencyMethods extends SossoldiDatabase { + Future getSelectedCurrency() async { + final db = await database; + + final maps = await db.query( + currencyTable, + columns: CurrencyFields.allFields, + where: '${CurrencyFields.mainCurrency} = ?', + whereArgs: [1], + ); + + if (maps.isNotEmpty) { + return Currency.fromJson(maps.first); + } else { + //fallback + return const Currency( + id: 2, + symbol: '\$', + code: 'USD', + name: "United States Dollar", + mainCurrency: true + ); + } + } + Future insert(Currency item) async { final db = await database; final id = await db.insert(currencyTable, item.toJson()); return item.copy(id: id); } - Future selectById(int id) async { final db = await database; @@ -100,7 +123,6 @@ class BudgetMethods extends SossoldiDatabase { Future updateItem(Currency item) async { final db = await database; - // You can use `rawUpdate` to write the query in SQL return db.update( currencyTable, item.toJson(), @@ -119,4 +141,11 @@ class BudgetMethods extends SossoldiDatabase { whereArgs: [id]); } + void changeMainCurrency(int id) async { + final db = await database; + + db.rawUpdate("UPDATE currency SET mainCurrency = 0"); + db.rawUpdate("UPDATE currency SET mainCurrency = 1 WHERE id = $id"); + } + } \ No newline at end of file diff --git a/lib/pages/accounts/add_account.dart b/lib/pages/accounts/add_account.dart index 09da007..6c5248e 100644 --- a/lib/pages/accounts/add_account.dart +++ b/lib/pages/accounts/add_account.dart @@ -6,6 +6,7 @@ import '../../providers/accounts_provider.dart'; import '../../constants/constants.dart'; import '../../constants/functions.dart'; import '../../constants/style.dart'; +import '../../providers/currency_provider.dart'; final showAccountIconsProvider = StateProvider.autoDispose((ref) => false); @@ -42,6 +43,7 @@ class _AddAccountState extends ConsumerState with Functions { final showAccountIcons = ref.watch(showAccountIconsProvider); final accountMainSwitch = ref.watch(accountMainSwitchProvider); final countNetWorth = ref.watch(countNetWorthSwitchProvider); + final currencyState = ref.watch(currencyStateNotifier); return Scaffold( backgroundColor: Theme.of(context).colorScheme.background, @@ -255,7 +257,7 @@ class _AddAccountState extends ConsumerState with Functions { controller: startingValueController, decoration: InputDecoration( hintText: "Initial balance", - suffixText: "€", + suffixText: currencyState.selectedCurrency.symbol, hintStyle: Theme.of(context) .textTheme .titleLarge! diff --git a/lib/pages/add_page/widgets/amount_section.dart b/lib/pages/add_page/widgets/amount_section.dart index 8bfe9b2..2c743fe 100644 --- a/lib/pages/add_page/widgets/amount_section.dart +++ b/lib/pages/add_page/widgets/amount_section.dart @@ -4,6 +4,7 @@ import "package:flutter_riverpod/flutter_riverpod.dart"; import '../../../constants/functions.dart'; import "../../../constants/style.dart"; import '../../../model/transaction.dart'; +import '../../../providers/currency_provider.dart'; import '../../../providers/transactions_provider.dart'; import 'account_selector.dart'; import 'type_tab.dart'; @@ -42,6 +43,7 @@ class _AmountSectionState extends ConsumerState with Functions { Widget build(BuildContext context) { final trsncTypeList = ref.watch(transactionTypeList); final selectedType = ref.watch(transactionTypeProvider); + final currencyState = ref.watch(currencyStateNotifier); return Container( color: Theme.of(context).colorScheme.surface, @@ -274,7 +276,7 @@ class _AmountSectionState extends ConsumerState with Functions { hintText: "0", border: InputBorder.none, prefixText: ' ', // set to center the amount - suffixText: '€', + suffixText: currencyState.selectedCurrency.symbol, suffixStyle: Theme.of(context) .textTheme .headlineMedium! diff --git a/lib/pages/general_options/general_settings.dart b/lib/pages/general_options/general_settings.dart index 2644110..353daaa 100644 --- a/lib/pages/general_options/general_settings.dart +++ b/lib/pages/general_options/general_settings.dart @@ -3,13 +3,17 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:intl/intl.dart'; import '../../constants/style.dart'; +import '../../model/currency.dart'; +import '../../providers/currency_provider.dart'; import '../../providers/theme_provider.dart'; +import 'widgets/currency_selector.dart'; class GeneralSettingsPage extends ConsumerStatefulWidget { const GeneralSettingsPage({super.key}); @override - ConsumerState createState() => _GeneralSettingsPageState(); + ConsumerState createState() => + _GeneralSettingsPageState(); } class _GeneralSettingsPageState extends ConsumerState { @@ -25,17 +29,13 @@ class _GeneralSettingsPageState extends ConsumerState { ["🇩🇪", "Deutsch"] ]; - List> currencies = [ - ["£", "British Pound"], - ["€", "Euro"], - ["\$", "US Dollar"], - ["CHF", "Swiss Franc"], - ["¥", "Yuan"], - ]; + Future> currencyList = CurrencyMethods().selectAll(); @override Widget build(BuildContext context) { final appThemeState = ref.watch(appThemeStateNotifier); + final currencyState = ref.watch(currencyStateNotifier); + return Scaffold( appBar: AppBar( leading: IconButton( @@ -58,10 +58,8 @@ class _GeneralSettingsPageState extends ConsumerState { Row( children: [ Text("Appearance", - style: Theme.of(context) - .textTheme - .titleLarge! - .copyWith(color: Theme.of(context).colorScheme.primary)), + style: Theme.of(context).textTheme.titleLarge!.copyWith( + color: Theme.of(context).colorScheme.primary)), const Spacer(), CircleAvatar( radius: 30.0, @@ -71,13 +69,19 @@ class _GeneralSettingsPageState extends ConsumerState { onPressed: () { // Toggle dark mode using the provider if (appThemeState.isDarkModeEnabled) { - ref.read(appThemeStateNotifier.notifier).setLightTheme(); + ref + .read(appThemeStateNotifier.notifier) + .setLightTheme(); } else { - ref.read(appThemeStateNotifier.notifier).setDarkTheme(); + ref + .read(appThemeStateNotifier.notifier) + .setDarkTheme(); } }, icon: Icon( - appThemeState.isDarkModeEnabled ? Icons.dark_mode : Icons.light_mode, + appThemeState.isDarkModeEnabled + ? Icons.dark_mode + : Icons.light_mode, size: 25.0, color: Theme.of(context).colorScheme.background, ), @@ -88,23 +92,24 @@ class _GeneralSettingsPageState extends ConsumerState { Row( children: [ Text("Currency", - style: Theme.of(context) - .textTheme - .titleLarge! - .copyWith(color: Theme.of(context).colorScheme.primary)), + style: Theme.of(context).textTheme.titleLarge!.copyWith( + color: Theme.of(context).colorScheme.primary)), const Spacer(), GestureDetector( onTap: () { - selectCurrency(); + setState(() { + CurrencySelectorDialog.selectCurrencyDialog(context, currencyState, currencyList); + }); }, child: CircleAvatar( radius: 30.0, backgroundColor: blue5, child: Center( child: Text( - NumberFormat().simpleCurrencySymbol(selectedCurrency), + currencyState.selectedCurrency.symbol, style: TextStyle( - color: Theme.of(context).colorScheme.background, fontSize: 25), + color: Theme.of(context).colorScheme.background, + fontSize: 25), )))), ], ), @@ -168,45 +173,4 @@ class _GeneralSettingsPageState extends ConsumerState { }), ))); } - - selectCurrency() { - showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text('Select a currency', - style: Theme.of(context) - .textTheme - .titleLarge! - .copyWith(color: Theme.of(context).colorScheme.primary)), - content: SizedBox( - height: 220, - width: 220, - child: ListView.builder( - itemCount: currencies.length, - physics: const BouncingScrollPhysics(), - shrinkWrap: true, - itemBuilder: (BuildContext context, int index) { - return GestureDetector( - onTap: () { - setState(() { - selectedCurrency = currencies.elementAt(index)[0]; - }); - Navigator.pop(context); - }, - child: ListTile( - leading: CircleAvatar( - radius: 22, - backgroundColor: blue5, - child: Text(currencies.elementAt(index)[0], - style: TextStyle( - color: Theme.of(context).colorScheme.background, fontSize: 20)), - ), - title: Text( - currencies.elementAt(index)[1], - textAlign: TextAlign.center, - ), - )); - }), - ))); - } } diff --git a/lib/pages/general_options/widgets/currency_selector.dart b/lib/pages/general_options/widgets/currency_selector.dart new file mode 100644 index 0000000..838ec39 --- /dev/null +++ b/lib/pages/general_options/widgets/currency_selector.dart @@ -0,0 +1,77 @@ +import 'package:flutter/material.dart'; + +import '../../../constants/style.dart'; +import '../../../model/currency.dart'; +import '../../../providers/currency_provider.dart'; + +class CurrencySelectorDialog { + static void selectCurrencyDialog(BuildContext context, CurrencyState state, + Future> currencies) { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text('Select a currency', + style: Theme.of(context) + .textTheme + .titleLarge! + .copyWith(color: Theme.of(context).colorScheme.primary)), + content: SizedBox( + height: 300, + width: 220, + child: SingleChildScrollView( + child: FutureBuilder( + future: currencies, + builder: (context, snapshot) { + if (snapshot.hasData && + snapshot.data != null && + snapshot.connectionState == ConnectionState.done) { + return ListView.builder( + itemCount: snapshot.data!.length, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (BuildContext context, int i) { + return GestureDetector( + onTap: () { + state.setSelectedCurrency( + snapshot.data![i]); + Navigator.pop(context); + }, + child: ListTile( + leading: CircleAvatar( + radius: 22, + backgroundColor: + state.selectedCurrency.code == + snapshot.data![i].code + ? blue5 + : grey1, + child: Text(snapshot.data![i].symbol, + style: TextStyle( + color: Theme.of(context) + .colorScheme + .background, + fontSize: 20)), + ), + title: Text( + snapshot.data![i].name, + textAlign: TextAlign.center, + ), + )); + }); + } else if (snapshot.hasError) { + return Text( + 'Something went wrong: ${snapshot.error}'); + } else { + if (snapshot.connectionState == + ConnectionState.waiting) { + return Transform.scale( + scale: 0.5, + child: const CircularProgressIndicator(), + ); + } else { + return const Text("Search for a transaction"); + } + } + }), + )))); + } +} diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart index 2c3739c..5a0418c 100644 --- a/lib/pages/home_page.dart +++ b/lib/pages/home_page.dart @@ -9,6 +9,7 @@ import '../custom_widgets/line_chart.dart'; import '../custom_widgets/transactions_list.dart'; import '../model/bank_account.dart'; import '../providers/accounts_provider.dart'; +import '../providers/currency_provider.dart'; import '../providers/dashboard_provider.dart'; import '../providers/transactions_provider.dart'; @@ -24,6 +25,8 @@ class _HomePageState extends ConsumerState with Functions { Widget build(BuildContext context) { final accountList = ref.watch(accountsProvider); final lastTransactions = ref.watch(lastTransactionsProvider); + final currencyState = ref.watch(currencyStateNotifier); + return Container( color: Theme.of(context).colorScheme.tertiary, child: ListView( @@ -35,6 +38,7 @@ class _HomePageState extends ConsumerState with Functions { final total = income + expense; final currentMonthList = ref.watch(currentMonthListProvider); final lastMonthList = ref.watch(lastMonthListProvider); + return Column( children: [ const SizedBox(height: 24), @@ -62,7 +66,7 @@ class _HomePageState extends ConsumerState with Functions { ?.copyWith(color: Theme.of(context).colorScheme.primary), ), TextSpan( - text: "€", + text: currencyState.selectedCurrency.symbol, style: Theme.of(context) .textTheme .bodyLarge @@ -92,7 +96,7 @@ class _HomePageState extends ConsumerState with Functions { ?.copyWith(color: green), ), TextSpan( - text: "€", + text: currencyState.selectedCurrency.symbol, style: Theme.of(context) .textTheme .labelLarge @@ -122,7 +126,7 @@ class _HomePageState extends ConsumerState with Functions { ?.copyWith(color: red), ), TextSpan( - text: "€", + text: currencyState.selectedCurrency.symbol, style: Theme.of(context) .textTheme .labelLarge diff --git a/lib/pages/planning_page/widget/budget_card.dart b/lib/pages/planning_page/widget/budget_card.dart index 9c541f4..deefb0c 100644 --- a/lib/pages/planning_page/widget/budget_card.dart +++ b/lib/pages/planning_page/widget/budget_card.dart @@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../constants/style.dart'; import '../../../model/budget.dart'; import '../../../providers/budgets_provider.dart'; +import '../../../providers/currency_provider.dart'; import 'budget_pie_chart.dart'; class BudgetCard extends ConsumerStatefulWidget { @@ -17,6 +18,7 @@ class _BudgetCardState extends ConsumerState { @override Widget build(BuildContext context) { final budgets = ref.watch(budgetsProvider); + final currencyState = ref.watch(currencyStateNotifier); return Container( decoration: BoxDecoration( color: Theme.of(context).colorScheme.surface, @@ -52,7 +54,7 @@ class _BudgetCardState extends ConsumerState { ), const Spacer(), Text( - "$spent/${budget.amountLimit}€", + "$spent/${budget.amountLimit}${currencyState.selectedCurrency.symbol}", style: const TextStyle(fontWeight: FontWeight.normal), ), ], diff --git a/lib/pages/planning_page/widget/budget_pie_chart.dart b/lib/pages/planning_page/widget/budget_pie_chart.dart index b060e72..9e60063 100644 --- a/lib/pages/planning_page/widget/budget_pie_chart.dart +++ b/lib/pages/planning_page/widget/budget_pie_chart.dart @@ -1,9 +1,11 @@ import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../model/budget.dart'; +import '../../../providers/currency_provider.dart'; -class BudgetPieChart extends StatefulWidget { +class BudgetPieChart extends ConsumerStatefulWidget { BudgetPieChart({super.key, required this.budgets}); final List budgets; @@ -12,11 +14,12 @@ class BudgetPieChart extends StatefulWidget { BudgetPieChartState createState() => BudgetPieChartState(); } -class BudgetPieChartState extends State { +class BudgetPieChartState extends ConsumerState { double totalBudget = 0; @override Widget build(BuildContext context) { + final currencyState = ref.watch(currencyStateNotifier); totalBudget = 0; for (Budget budget in widget.budgets) { totalBudget += budget.amountLimit; @@ -34,7 +37,7 @@ class BudgetPieChartState extends State { ), Column( children: [ - Text("${totalBudget.round()}€", style: const TextStyle(fontSize: 25)), + Text("${totalBudget.round()}${currencyState.selectedCurrency.symbol}", style: const TextStyle(fontSize: 25)), const SizedBox(height: 5), const Text("PLANNED", style: TextStyle(fontWeight: FontWeight.normal)) ], diff --git a/lib/pages/statistics_page.dart b/lib/pages/statistics_page.dart index 58879de..5479041 100644 --- a/lib/pages/statistics_page.dart +++ b/lib/pages/statistics_page.dart @@ -9,6 +9,7 @@ import '../custom_widgets/line_chart.dart'; import '../custom_widgets/transaction_type_button.dart'; import '../model/bank_account.dart'; import '../providers/accounts_provider.dart'; +import '../providers/currency_provider.dart'; import '../providers/statistics_provider.dart'; class StatsPage extends ConsumerStatefulWidget { @@ -23,6 +24,7 @@ class _StatsPageState extends ConsumerState with Functions { Widget build(BuildContext context) { final currentYearMonthlyTransactions = ref.watch(currentYearMontlyTransactionsProvider); final accountList = ref.watch(accountsProvider); + final currencyState = ref.watch(currencyStateNotifier); return ListView( children: [ @@ -67,7 +69,7 @@ class _StatsPageState extends ConsumerState with Functions { ?.copyWith(color: blue4), ), TextSpan( - text: "€", + text: currencyState.selectedCurrency.symbol, style: Theme.of(context) .textTheme .labelLarge @@ -156,7 +158,7 @@ class _StatsPageState extends ConsumerState with Functions { ), Expanded( child: Text( - "${numToCurrency(account.total)}€", + "${numToCurrency(account.total)}${currencyState.selectedCurrency.symbol}", textAlign: TextAlign.right, style: Theme.of(context).textTheme.bodySmall?.copyWith(color: blue1), ), diff --git a/lib/pages/transactions_page/widgets/account_list_tile.dart b/lib/pages/transactions_page/widgets/account_list_tile.dart index fa453a4..af2e910 100644 --- a/lib/pages/transactions_page/widgets/account_list_tile.dart +++ b/lib/pages/transactions_page/widgets/account_list_tile.dart @@ -2,6 +2,7 @@ import "package:flutter/material.dart"; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../constants/style.dart'; +import '../../../providers/currency_provider.dart'; import 'accounts_tab.dart'; class AccountListTile extends ConsumerWidget { @@ -29,6 +30,7 @@ class AccountListTile extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final selectedAccountIndex = ref.watch(selectedAccountIndexProvider); + final currencyState = ref.watch(currencyStateNotifier); return Column( mainAxisSize: MainAxisSize.min, children: [ @@ -75,7 +77,7 @@ class AccountListTile extends ConsumerWidget { style: Theme.of(context).textTheme.titleMedium, ), Text( - "${amount.toStringAsFixed(2)} €", + "${amount.toStringAsFixed(2)} ${currencyState.selectedCurrency.symbol}", style: Theme.of(context) .textTheme .bodyLarge @@ -135,7 +137,7 @@ class AccountListTile extends ConsumerWidget { } } -class TransactionRow extends StatelessWidget { +class TransactionRow extends ConsumerWidget { const TransactionRow({ super.key, required this.transaction, @@ -144,7 +146,8 @@ class TransactionRow extends StatelessWidget { final Map transaction; @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { + final currencyState = ref.watch(currencyStateNotifier); return Container( padding: const EdgeInsets.symmetric( horizontal: 8.0, @@ -165,7 +168,7 @@ class TransactionRow extends StatelessWidget { style: Theme.of(context).textTheme.titleMedium, ), Text( - "${transaction['amount'].toStringAsFixed(2)} €", + "${transaction['amount'].toStringAsFixed(2)} ${currencyState.selectedCurrency.symbol}", style: Theme.of(context) .textTheme .bodyLarge diff --git a/lib/pages/transactions_page/widgets/accounts_pie_chart.dart b/lib/pages/transactions_page/widgets/accounts_pie_chart.dart index eb5b0e2..414b1d7 100644 --- a/lib/pages/transactions_page/widgets/accounts_pie_chart.dart +++ b/lib/pages/transactions_page/widgets/accounts_pie_chart.dart @@ -6,6 +6,7 @@ import '../../../constants/constants.dart'; import '../../../constants/functions.dart'; import '../../../constants/style.dart'; import '../../../model/bank_account.dart'; +import '../../../providers/currency_provider.dart'; import 'accounts_tab.dart'; class AccountsPieChart extends ConsumerWidget with Functions { @@ -23,6 +24,7 @@ class AccountsPieChart extends ConsumerWidget with Functions { @override Widget build(BuildContext context, WidgetRef ref) { final selectedAccountIndex = ref.watch(selectedAccountIndexProvider); + final currencyState = ref.watch(currencyStateNotifier); return SizedBox( height: 200, child: Stack( @@ -68,8 +70,8 @@ class AccountsPieChart extends ConsumerWidget with Functions { : const SizedBox(), Text( (selectedAccountIndex != -1) - ? "${amounts[accounts[selectedAccountIndex].id]!.toStringAsFixed(2)} €" - : "${total.toStringAsFixed(2)} €", + ? "${amounts[accounts[selectedAccountIndex].id]!.toStringAsFixed(2)} ${currencyState.selectedCurrency.symbol}" + : "${total.toStringAsFixed(2)} ${currencyState.selectedCurrency.symbol}", style: Theme.of(context).textTheme.headlineLarge?.copyWith( color: ((selectedAccountIndex != -1 && amounts[accounts[selectedAccountIndex].id]! > 0) || diff --git a/lib/pages/transactions_page/widgets/categories_pie_chart.dart b/lib/pages/transactions_page/widgets/categories_pie_chart.dart index 8d17102..b140b81 100644 --- a/lib/pages/transactions_page/widgets/categories_pie_chart.dart +++ b/lib/pages/transactions_page/widgets/categories_pie_chart.dart @@ -6,6 +6,7 @@ import '../../../constants/constants.dart'; import '../../../constants/functions.dart'; import '../../../constants/style.dart'; import '../../../model/category_transaction.dart'; +import '../../../providers/currency_provider.dart'; import 'categories_tab.dart'; class CategoriesPieChart extends ConsumerWidget with Functions { @@ -25,6 +26,7 @@ class CategoriesPieChart extends ConsumerWidget with Functions { final selectedCategoryIndex = ref.watch(selectedCategoryIndexProvider); final selectedCategory = (selectedCategoryIndex >= 0) ? categories[selectedCategoryIndex] : null; + final currencyState = ref.watch(currencyStateNotifier); return SizedBox( height: 200, child: Stack( @@ -69,8 +71,8 @@ class CategoriesPieChart extends ConsumerWidget with Functions { : const SizedBox(), Text( (selectedCategory != null) - ? "${amounts[selectedCategory.id]!.toStringAsFixed(2)} €" - : "${total.toStringAsFixed(2)} €", + ? "${amounts[selectedCategory.id]!.toStringAsFixed(2)} ${currencyState.selectedCurrency.symbol}" + : "${total.toStringAsFixed(2)} ${currencyState.selectedCurrency.symbol}", style: Theme.of(context).textTheme.headlineLarge?.copyWith( color: ((selectedCategory != null && amounts[selectedCategory.id]! > 0) || (selectedCategory == null && total > 0)) diff --git a/lib/pages/transactions_page/widgets/category_list_tile.dart b/lib/pages/transactions_page/widgets/category_list_tile.dart index 85ab855..64e8ab2 100644 --- a/lib/pages/transactions_page/widgets/category_list_tile.dart +++ b/lib/pages/transactions_page/widgets/category_list_tile.dart @@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../constants/constants.dart'; import '../../../constants/style.dart'; import '../../../model/category_transaction.dart'; +import '../../../providers/currency_provider.dart'; import 'categories_tab.dart'; class CategoryListTile extends ConsumerWidget { @@ -25,6 +26,7 @@ class CategoryListTile extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final selectedCategoryIndex = ref.watch(selectedCategoryIndexProvider); + final currencyState = ref.watch(currencyStateNotifier); final nTransactions = transactions.length; return Column( mainAxisSize: MainAxisSize.min, @@ -72,7 +74,7 @@ class CategoryListTile extends ConsumerWidget { style: Theme.of(context).textTheme.titleMedium, ), Text( - "${amount.toStringAsFixed(2)} €", + "${amount.toStringAsFixed(2)} ${currencyState.selectedCurrency.symbol}", style: Theme.of(context) .textTheme .bodyLarge @@ -142,6 +144,7 @@ class TransactionRow extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { + final currencyState = ref.watch(currencyStateNotifier); return Container( padding: const EdgeInsets.symmetric( horizontal: 8.0, @@ -162,7 +165,7 @@ class TransactionRow extends ConsumerWidget { style: Theme.of(context).textTheme.titleMedium, ), Text( - "${transaction['amount'].toStringAsFixed(2)} €", + "${transaction['amount'].toStringAsFixed(2)} ${currencyState.selectedCurrency.symbol}", style: Theme.of(context) .textTheme .bodyLarge diff --git a/lib/pages/transactions_page/widgets/custom_sliver_delegate.dart b/lib/pages/transactions_page/widgets/custom_sliver_delegate.dart index 5d527f0..2e31c7e 100644 --- a/lib/pages/transactions_page/widgets/custom_sliver_delegate.dart +++ b/lib/pages/transactions_page/widgets/custom_sliver_delegate.dart @@ -6,6 +6,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../constants/functions.dart'; import '../../../constants/style.dart'; +import '../../../providers/currency_provider.dart'; import '../../../providers/transactions_provider.dart'; import '../../../utils/formatted_date_range.dart'; import 'month_selector.dart'; @@ -142,6 +143,7 @@ class CollapsedWidget extends StatelessWidget with Functions { final totalAmount = ref.watch(totalAmountProvider); final startDate = ref.watch(filterDateStartProvider); final endDate = ref.watch(filterDateEndProvider); + final currencyState = ref.watch(currencyStateNotifier); return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -175,7 +177,7 @@ class CollapsedWidget extends StatelessWidget with Functions { .copyWith(color: totalAmount >= 0 ? green : red), ), TextSpan( - text: "€", + text: currencyState.selectedCurrency.symbol, style: Theme.of(context) .textTheme .labelLarge! diff --git a/lib/pages/transactions_page/widgets/month_selector.dart b/lib/pages/transactions_page/widgets/month_selector.dart index 1a440f1..0894b6d 100644 --- a/lib/pages/transactions_page/widgets/month_selector.dart +++ b/lib/pages/transactions_page/widgets/month_selector.dart @@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../constants/functions.dart'; import '../../../constants/style.dart'; +import '../../../providers/currency_provider.dart'; import '../../../providers/transactions_provider.dart'; import '../../../utils/formatted_date_range.dart'; @@ -18,6 +19,7 @@ class MonthSelector extends ConsumerWidget with Functions { final totalAmount = ref.watch(totalAmountProvider); final startDate = ref.watch(filterDateStartProvider); final endDate = ref.watch(filterDateEndProvider); + final currencyState = ref.watch(currencyStateNotifier); return GestureDetector( onTap: () async { // pick range of dates @@ -89,7 +91,7 @@ class MonthSelector extends ConsumerWidget with Functions { .copyWith(color: totalAmount >= 0 ? green : red), ), TextSpan( - text: "€", + text: currencyState.selectedCurrency.symbol, style: Theme.of(context) .textTheme .labelLarge! diff --git a/lib/providers/currency_provider.dart b/lib/providers/currency_provider.dart new file mode 100644 index 0000000..6601e45 --- /dev/null +++ b/lib/providers/currency_provider.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../model/currency.dart'; + +final currencyStateNotifier = ChangeNotifierProvider( + (ref) => CurrencyState(), +); + +class CurrencyState extends ChangeNotifier { + //Initial currency selected + Currency selectedCurrency = const Currency( + id: 2, + symbol: '\$', + code: 'USD', + name: "United States Dollar", + mainCurrency: true + ); + + CurrencyState() { + _initializeState(); + } + + Future _initializeState() async { + selectedCurrency = await CurrencyMethods().getSelectedCurrency(); + notifyListeners(); + } + + void setSelectedCurrency(Currency currency) { + selectedCurrency = currency; + CurrencyMethods().changeMainCurrency(currency.id!); + notifyListeners(); + } +} diff --git a/test/widget/accounts_sum_test.dart b/test/widget/accounts_sum_test.dart index 231b87d..7da3ff9 100644 --- a/test/widget/accounts_sum_test.dart +++ b/test/widget/accounts_sum_test.dart @@ -1,3 +1,4 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:sqflite/sqflite.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; @@ -31,7 +32,7 @@ void main() { await tester.pumpWidget(MaterialApp( home: Material( - child: AccountsSum(account: randomBankAccount), + child: ProviderScope(child:AccountsSum(account: randomBankAccount)), ), )); @@ -44,7 +45,7 @@ void main() { } else { final accountSum = snapshot.data ?? 0; // TODO need to test total amount with some transactions too - expect(find.text("${accountSum.toStringAsFixed(2).replaceAll('.', ',')}€", findRichText: true), findsOneWidget); + expect(find.text("${accountSum.toStringAsFixed(2).replaceAll('.', ',')}", findRichText: true), findsOneWidget); return const Text('Ok!'); } }