diff --git a/lib/constants.dart b/lib/constants.dart index a6d1026c3..cacc9d176 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -53,6 +53,11 @@ const String kFacebookUrl = 'https://www.facebook.com/invoiceninja'; const String kYouTubeUrl = 'https://www.youtube.com/channel/UCXAHcBvhW05PDtWYIq7WDFA/videos'; +const String kYodleeCoverageUrl = + 'https://www.yodlee.com/open-banking/data-connections'; +const String kNordigenCoverageUrl = + 'https://gocardless.com/bank-account-data/coverage'; + const String kTaskExtensionUrl = 'https://chromewebstore.google.com/detail/invoice-ninja-tasks/dlfcbfdpemfnjbjlladogijcchfmmaaf'; const String kTaskExtensionYouTubeUrl = diff --git a/lib/data/models/bank_account_model.dart b/lib/data/models/bank_account_model.dart index 0b4e663e7..590b32781 100644 --- a/lib/data/models/bank_account_model.dart +++ b/lib/data/models/bank_account_model.dart @@ -53,6 +53,9 @@ class BankAccountFields { abstract class BankAccountEntity extends Object with BaseEntity implements Built { + static const String INTEGRATION_TYPE_YODLEE = 'yodlee'; + static const String INTEGRATION_TYPE_NORDIGEN = 'nordigen'; + factory BankAccountEntity({String? id, AppState? state}) { return _$BankAccountEntity._( id: id ?? BaseEntity.nextId, diff --git a/lib/ui/app/forms/learn_more.dart b/lib/ui/app/forms/learn_more.dart index 24a807e7c..8f24a94a1 100644 --- a/lib/ui/app/forms/learn_more.dart +++ b/lib/ui/app/forms/learn_more.dart @@ -12,11 +12,13 @@ class LearnMoreUrl extends StatelessWidget { required this.child, required this.url, this.label, + this.isVertical = false, }); final Widget child; final String url; final String? label; + final bool isVertical; @override Widget build(BuildContext context) { @@ -26,26 +28,43 @@ class LearnMoreUrl extends StatelessWidget { return child; } - return Row( - children: [ - Expanded( - flex: 2, - child: child, - ), - SizedBox( - width: 10, - ), - Expanded( - child: TextButton( + if (isVertical) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + child, + SizedBox(height: 8), + OutlinedButton( child: Text( label ?? localization!.learnMore, maxLines: 4, ), onPressed: () => launchUrl(Uri.parse(url)), ), - ), - ], - ); + ], + ); + } else { + return Row( + children: [ + Expanded( + flex: 2, + child: child, + ), + SizedBox( + width: 10, + ), + Expanded( + child: TextButton( + child: Text( + label ?? localization!.learnMore, + maxLines: 4, + ), + onPressed: () => launchUrl(Uri.parse(url)), + ), + ), + ], + ); + } } } diff --git a/lib/ui/bank_account/bank_account_screen.dart b/lib/ui/bank_account/bank_account_screen.dart index 29a021235..51b3345ae 100644 --- a/lib/ui/bank_account/bank_account_screen.dart +++ b/lib/ui/bank_account/bank_account_screen.dart @@ -11,6 +11,7 @@ import 'package:invoiceninja_flutter/redux/bank_account/bank_account_actions.dar import 'package:invoiceninja_flutter/redux/settings/settings_actions.dart'; import 'package:invoiceninja_flutter/ui/app/app_bottom_bar.dart'; import 'package:invoiceninja_flutter/ui/app/buttons/elevated_button.dart'; +import 'package:invoiceninja_flutter/ui/app/forms/learn_more.dart'; import 'package:invoiceninja_flutter/ui/app/help_text.dart'; import 'package:invoiceninja_flutter/ui/app/list_scaffold.dart'; import 'package:invoiceninja_flutter/ui/app/list_filter.dart'; @@ -19,6 +20,7 @@ import 'package:invoiceninja_flutter/ui/bank_account/bank_account_presenter.dart import 'package:invoiceninja_flutter/utils/dialogs.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/localization.dart'; +import 'package:invoiceninja_flutter/utils/platforms.dart'; import 'package:url_launcher/url_launcher.dart'; import 'bank_account_screen_vm.dart'; @@ -34,6 +36,91 @@ class BankAccountScreen extends StatelessWidget { final BankAccountScreenVM viewModel; void connectAccounts(BuildContext context) { + final localization = AppLocalization.of(context)!; + String integrationType = BankAccountEntity.INTEGRATION_TYPE_NORDIGEN; + + if (isHosted(context)) { + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: Text(localization.selectProvider), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: Text(localization.close.toUpperCase())) + ], + content: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text('Envestnet - Yodlee'), + Text( + localization.supportedRegions + + ': USA, Australia, UK & India', + style: Theme.of(context).textTheme.bodySmall), + Row( + children: [ + Expanded( + child: AppButton( + label: localization.learnMore.toUpperCase(), + onPressed: () => + launchUrl(Uri.parse(kYodleeCoverageUrl)), + iconData: Icons.info_outline, + ), + ), + SizedBox(width: kTableColumnGap), + Expanded( + child: AppButton( + label: localization.connect.toUpperCase(), + onPressed: () => _connectAccounts( + context, + BankAccountEntity.INTEGRATION_TYPE_YODLEE, + ), + iconData: Icons.link, + ), + ), + ], + ), + SizedBox(height: 30), + Text('GoCardless - Nordigen'), + Text(localization.supportedRegions + ': Europe & UK', + style: Theme.of(context).textTheme.bodySmall), + Row( + children: [ + Expanded( + child: AppButton( + label: localization.learnMore.toUpperCase(), + onPressed: () => + launchUrl(Uri.parse(kNordigenCoverageUrl)), + iconData: Icons.info_outline, + ), + ), + SizedBox(width: kTableColumnGap), + Expanded( + child: AppButton( + label: localization.connect.toUpperCase(), + onPressed: () => _connectAccounts( + context, + BankAccountEntity.INTEGRATION_TYPE_NORDIGEN, + ), + iconData: Icons.link, + ), + ), + ], + ), + ], + ), + ), + ); + }, + ); + } else { + _connectAccounts(context, integrationType); + } + } + + void _connectAccounts(BuildContext context, String integrationType) { final store = StoreProvider.of(context); final state = store.state; final webClient = WebClient(); @@ -41,7 +128,6 @@ class BankAccountScreen extends StatelessWidget { final url = '${credentials.url}/one_time_token'; store.dispatch(StartSaving()); - webClient .post(url, credentials.token, data: jsonEncode({ diff --git a/lib/utils/i18n.dart b/lib/utils/i18n.dart index a78c38ab8..c6b7b0656 100644 --- a/lib/utils/i18n.dart +++ b/lib/utils/i18n.dart @@ -18,6 +18,8 @@ mixin LocalizationsProvider on LocaleCodeAware { static final Map> _localizedValues = { 'en': { // STARTER: lang key - do not remove comment + 'supported_regions': 'Supported Regions', + 'select_provider': 'Select Provider', 'payment_type_credit': 'Payment Type Credit', 'payment_type_debit': 'Payment Type Debit', 'send_emails_to': 'Send Emails To', @@ -111466,6 +111468,14 @@ mixin LocalizationsProvider on LocaleCodeAware { _localizedValues[localeCode]!['send_emails_to'] ?? _localizedValues['en']!['send_emails_to']!; + String get selectProvider => + _localizedValues[localeCode]!['select_provider'] ?? + _localizedValues['en']!['select_provider']!; + + String get supportedRegions => + _localizedValues[localeCode]!['supported_regions'] ?? + _localizedValues['en']!['supported_regions']!; + // STARTER: lang field - do not remove comment String lookup(String? key) {