From 735bc058648c0027bfc1e467d436e00fba6408ac Mon Sep 17 00:00:00 2001 From: Wilberforce Uwadiegwu Date: Sun, 3 Nov 2019 07:26:12 +0100 Subject: [PATCH] Added error messages for payments that's under development. Resolves: #1 --- example/.gitignore | 1 - lib/src/manager/ach_transaction_manager.dart | 17 +++++ .../manager/gh_mm_transaction_manager.dart | 17 +++++ .../manager/mpesa_transaction_manager.dart | 17 +++++ .../manager/ug_mm_transaction_manager.dart | 17 +++++ lib/src/ui/common/otp_widget.dart | 5 +- .../ui/payment/pages/ach_payment_widget.dart | 7 ++ .../ui/payment/pages/base_payment_page.dart | 61 ++++++++++++++- .../pages/gh_mobile_money_payment_widget.dart | 76 ++++++++++--------- .../payment/pages/mpesa_payment_widget.dart | 7 ++ .../pages/ug_mobile_money_payment_widget.dart | 7 ++ lib/src/ui/payment/rave_pay_widget.dart | 69 +++++++++++++---- 12 files changed, 248 insertions(+), 53 deletions(-) create mode 100644 lib/src/manager/ach_transaction_manager.dart create mode 100644 lib/src/manager/gh_mm_transaction_manager.dart create mode 100644 lib/src/manager/mpesa_transaction_manager.dart create mode 100644 lib/src/manager/ug_mm_transaction_manager.dart diff --git a/example/.gitignore b/example/.gitignore index f6c116a..846d567 100644 --- a/example/.gitignore +++ b/example/.gitignore @@ -69,4 +69,3 @@ !**/ios/**/default.perspectivev3 !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages /ios/Flutter/flutter_export_environment.sh -/ios/.symlinks/plugins/rave_flutter/ diff --git a/lib/src/manager/ach_transaction_manager.dart b/lib/src/manager/ach_transaction_manager.dart new file mode 100644 index 0000000..499e17d --- /dev/null +++ b/lib/src/manager/ach_transaction_manager.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:rave_flutter/src/manager/base_transaction_manager.dart'; + +class AchTransactionManager extends BaseTransactionManager { + AchTransactionManager( + {@required BuildContext context, + @required TransactionComplete onTransactionComplete}) + : super( + context: context, + onTransactionComplete: onTransactionComplete, + ); + + @override + charge() { + // TODO: implement charge + } +} diff --git a/lib/src/manager/gh_mm_transaction_manager.dart b/lib/src/manager/gh_mm_transaction_manager.dart new file mode 100644 index 0000000..2f2debe --- /dev/null +++ b/lib/src/manager/gh_mm_transaction_manager.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:rave_flutter/src/manager/base_transaction_manager.dart'; + +class GhMMTransactionManager extends BaseTransactionManager { + GhMMTransactionManager( + {@required BuildContext context, + @required TransactionComplete onTransactionComplete}) + : super( + context: context, + onTransactionComplete: onTransactionComplete, + ); + + @override + charge() { + // TODO: implement charge + } +} diff --git a/lib/src/manager/mpesa_transaction_manager.dart b/lib/src/manager/mpesa_transaction_manager.dart new file mode 100644 index 0000000..88eefc6 --- /dev/null +++ b/lib/src/manager/mpesa_transaction_manager.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:rave_flutter/src/manager/base_transaction_manager.dart'; + +class MpesaTransactionManager extends BaseTransactionManager { + MpesaTransactionManager( + {@required BuildContext context, + @required TransactionComplete onTransactionComplete}) + : super( + context: context, + onTransactionComplete: onTransactionComplete, + ); + + @override + charge() { + // TODO: implement charge + } +} diff --git a/lib/src/manager/ug_mm_transaction_manager.dart b/lib/src/manager/ug_mm_transaction_manager.dart new file mode 100644 index 0000000..d1840d3 --- /dev/null +++ b/lib/src/manager/ug_mm_transaction_manager.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:rave_flutter/src/manager/base_transaction_manager.dart'; + +class UgMMTransactionManager extends BaseTransactionManager { + UgMMTransactionManager( + {@required BuildContext context, + @required TransactionComplete onTransactionComplete}) + : super( + context: context, + onTransactionComplete: onTransactionComplete, + ); + + @override + charge() { + // TODO: implement charge + } +} diff --git a/lib/src/ui/common/otp_widget.dart b/lib/src/ui/common/otp_widget.dart index 0e56f70..74b94e0 100644 --- a/lib/src/ui/common/otp_widget.dart +++ b/lib/src/ui/common/otp_widget.dart @@ -73,7 +73,10 @@ class _OtpWidgetState extends State { color: Colors.white, fontSize: 15), ), - padding: EdgeInsets.symmetric(vertical: 18, horizontal: 20), + padding: EdgeInsets.symmetric( + vertical: 13, + horizontal: 20, + ), onPressed: _validateInputs, ), ) diff --git a/lib/src/ui/payment/pages/ach_payment_widget.dart b/lib/src/ui/payment/pages/ach_payment_widget.dart index d63b1bd..4d11fc3 100644 --- a/lib/src/ui/payment/pages/ach_payment_widget.dart +++ b/lib/src/ui/payment/pages/ach_payment_widget.dart @@ -1,8 +1,12 @@ import 'package:flutter/material.dart'; +import 'package:rave_flutter/src/manager/ach_transaction_manager.dart'; import 'package:rave_flutter/src/ui/fields/phone_number_field.dart'; import 'package:rave_flutter/src/ui/payment/pages/base_payment_page.dart'; class AchPaymentWidget extends BasePaymentPage { + AchPaymentWidget({@required AchTransactionManager manager}) + : super(transactionManager: manager); + @override _AchPaymentWidgetState createState() => _AchPaymentWidgetState(); } @@ -47,4 +51,7 @@ class _AchPaymentWidgetState extends BasePaymentPageState { @override bool showEmailField() => false; + + @override + bool get supported => false; } diff --git a/lib/src/ui/payment/pages/base_payment_page.dart b/lib/src/ui/payment/pages/base_payment_page.dart index 51cd32f..4f93f26 100644 --- a/lib/src/ui/payment/pages/base_payment_page.dart +++ b/lib/src/ui/payment/pages/base_payment_page.dart @@ -24,6 +24,8 @@ abstract class BasePaymentPageState extends State TextEditingController _amountController; TextEditingController _emailController; AnimationController _animationController; + AnimationController _infoAnimationController; + Animation _infoAnimation; var _emailFocusNode = FocusNode(); var _amountFocusNode = FocusNode(); Animation _animation; @@ -33,6 +35,7 @@ abstract class BasePaymentPageState extends State bool _cameWithValidAmount = true; bool _cameWithValidEmail = true; + int _infoAnimationRepetition = 0; @override void initState() { @@ -54,6 +57,14 @@ abstract class BasePaymentPageState extends State parent: Tween(begin: 0, end: 1).animate(_animationController), curve: Curves.fastOutSlowIn); _animationController.forward(); + + if (!supported) { + _infoAnimationController = AnimationController( + vsync: this, duration: Duration(milliseconds: 400)); + _infoAnimation = + Tween(begin: 1.0, end: 1.2).animate(_infoAnimationController); + _infoAnimationController.addStatusListener(_onInfoAnimationChange); + } super.initState(); } @@ -64,6 +75,7 @@ abstract class BasePaymentPageState extends State _animationController.dispose(); _emailFocusNode.dispose(); _amountFocusNode.dispose(); + _infoAnimationController?.dispose(); super.dispose(); } @@ -127,7 +139,7 @@ abstract class BasePaymentPageState extends State child: FlatButton( onPressed: _validateInputs, color: MyColors.buttercup, - padding: EdgeInsets.symmetric(vertical: 12, horizontal: 20), + padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20), child: Row( children: [ Expanded( @@ -150,6 +162,22 @@ abstract class BasePaymentPageState extends State Widget topWidget = buildTopWidget(); + Widget info = supported + ? SizedBox() + : Padding( + padding: EdgeInsets.only(top: 15), + child: ScaleTransition( + scale: _infoAnimation, + child: Text( + "This payment mode is currently under development", + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.redAccent, + ), + ), + ), + ); + return Form( key: formKey, autovalidate: _autoValidate, @@ -157,6 +185,7 @@ abstract class BasePaymentPageState extends State children: amountAndEmailFields ..insert(0, topWidget) ..addAll(buildLocalFields(data)) + ..add(info) ..add(payButton), ), ); @@ -230,7 +259,7 @@ abstract class BasePaymentPageState extends State return Strings.pay; } - return '${Strings.pay} ${initializer.currency.toUpperCase()}${RaveUtils.formatAmount(initializer.amount)}'; + return '${Strings.pay} ${initializer.currency.toUpperCase()} ${RaveUtils.formatAmount(initializer.amount)}'; } _validateInputs() { @@ -246,7 +275,13 @@ abstract class BasePaymentPageState extends State } @mustCallSuper - onFormValidated() => widget.transactionManager.processTransaction(payload); + onFormValidated() { + if (!supported) { + _blinkInfoWidget(); + return; + } + widget.transactionManager.processTransaction(payload); + } void _updateAmount() => setState( () => initializer.amount = double.tryParse(_amountController.text)); @@ -267,5 +302,25 @@ abstract class BasePaymentPageState extends State bool get autoValidate => _autoValidate; + bool get supported => true; + setDataState(ConnectionState state) => _connectionBloc.setState(state); + + _blinkInfoWidget() { + if (_infoAnimationController.isAnimating) return; + _infoAnimationController.forward(); + } + + _onInfoAnimationChange(AnimationStatus status) { + if (status == AnimationStatus.completed) { + _infoAnimationController.reverse(); + } else if (status == AnimationStatus.dismissed) { + if (_infoAnimationRepetition >= 1) { + _infoAnimationRepetition = 0; + } else { + _infoAnimationController.forward(); + _infoAnimationRepetition++; + } + } + } } diff --git a/lib/src/ui/payment/pages/gh_mobile_money_payment_widget.dart b/lib/src/ui/payment/pages/gh_mobile_money_payment_widget.dart index 12e5432..56e8c6a 100644 --- a/lib/src/ui/payment/pages/gh_mobile_money_payment_widget.dart +++ b/lib/src/ui/payment/pages/gh_mobile_money_payment_widget.dart @@ -1,10 +1,14 @@ import 'package:flutter/material.dart'; import 'package:rave_flutter/src/common/strings.dart'; +import 'package:rave_flutter/src/manager/gh_mm_transaction_manager.dart'; import 'package:rave_flutter/src/ui/fields/base_field.dart'; import 'package:rave_flutter/src/ui/fields/phone_number_field.dart'; import 'package:rave_flutter/src/ui/payment/pages/base_payment_page.dart'; class GhMobileMoneyPaymentWidget extends BasePaymentPage { + GhMobileMoneyPaymentWidget({@required GhMMTransactionManager manager}) + : super(transactionManager: manager); + @override _GhMobileMoneyPaymentWidgetState createState() => _GhMobileMoneyPaymentWidgetState(); @@ -28,41 +32,42 @@ class _GhMobileMoneyPaymentWidgetState List buildLocalFields([data]) { return [ DropdownButtonHideUnderline( - child: InputDecorator( - decoration: InputDecoration( - border: OutlineInputBorder(), - isDense: true, - filled: true, - errorText: autoValidate && _selectedNetwork == null - ? 'Select a network' - : null, - fillColor: Colors.grey[50], - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.grey[400].withOpacity(.7), width: .5), - borderRadius: BorderRadius.all(Radius.circular(1.5))), - focusedBorder: OutlineInputBorder( - borderSide: - BorderSide(color: Colors.grey[400].withOpacity(.7), width: 1), - borderRadius: BorderRadius.all(Radius.circular(1.5))), - hintText: 'Select network', - ), - isEmpty: _selectedNetwork == null, - child: new DropdownButton( - value: _selectedNetwork, - isDense: true, - onChanged: (String newValue) { - setState(() => _selectedNetwork = newValue); - payload.network = _selectedNetwork; - }, - items: _networks.map((String value) { - return new DropdownMenuItem( - value: value, - child: new Text(value), - ); - }).toList(), + child: InputDecorator( + decoration: InputDecoration( + border: OutlineInputBorder(), + isDense: true, + filled: true, + errorText: autoValidate && _selectedNetwork == null + ? 'Select a network' + : null, + fillColor: Colors.grey[50], + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.grey[400].withOpacity(.7), width: .5), + borderRadius: BorderRadius.all(Radius.circular(1.5))), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.grey[400].withOpacity(.7), width: 1), + borderRadius: BorderRadius.all(Radius.circular(1.5))), + hintText: 'Select network', + ), + isEmpty: _selectedNetwork == null, + child: new DropdownButton( + value: _selectedNetwork, + isDense: true, + onChanged: (String newValue) { + setState(() => _selectedNetwork = newValue); + payload.network = _selectedNetwork; + }, + items: _networks.map((String value) { + return new DropdownMenuItem( + value: value, + child: new Text(value), + ); + }).toList(), + ), ), - )), + ), PhoneNumberField( focusNode: _phoneFocusNode, textInputAction: isVodaFoneSelected() @@ -103,6 +108,9 @@ class _GhMobileMoneyPaymentWidgetState @override bool showEmailField() => false; + @override + bool get supported => false; + @override Widget buildTopWidget() { if (isVodaFoneSelected()) { diff --git a/lib/src/ui/payment/pages/mpesa_payment_widget.dart b/lib/src/ui/payment/pages/mpesa_payment_widget.dart index 5605847..3281bbf 100644 --- a/lib/src/ui/payment/pages/mpesa_payment_widget.dart +++ b/lib/src/ui/payment/pages/mpesa_payment_widget.dart @@ -1,8 +1,12 @@ import 'package:flutter/material.dart'; +import 'package:rave_flutter/src/manager/mpesa_transaction_manager.dart'; import 'package:rave_flutter/src/ui/fields/phone_number_field.dart'; import 'package:rave_flutter/src/ui/payment/pages/base_payment_page.dart'; class MpesaPaymentWidget extends BasePaymentPage { + MpesaPaymentWidget({@required MpesaTransactionManager manager}) + : super(transactionManager: manager); + @override _MpesaPaymentWidgetState createState() => _MpesaPaymentWidgetState(); } @@ -41,4 +45,7 @@ class _MpesaPaymentWidgetState @override bool showEmailField() => false; + + @override + bool get supported => false; } diff --git a/lib/src/ui/payment/pages/ug_mobile_money_payment_widget.dart b/lib/src/ui/payment/pages/ug_mobile_money_payment_widget.dart index 7fb6909..9661928 100644 --- a/lib/src/ui/payment/pages/ug_mobile_money_payment_widget.dart +++ b/lib/src/ui/payment/pages/ug_mobile_money_payment_widget.dart @@ -1,8 +1,12 @@ import 'package:flutter/material.dart'; +import 'package:rave_flutter/src/manager/ug_mm_transaction_manager.dart'; import 'package:rave_flutter/src/ui/fields/phone_number_field.dart'; import 'package:rave_flutter/src/ui/payment/pages/base_payment_page.dart'; class UgMobileMoneyPaymentWidget extends BasePaymentPage { + UgMobileMoneyPaymentWidget({@required UgMMTransactionManager manager}) + : super(transactionManager: manager); + @override _UgMobileMoneyPaymentWidgetState createState() => _UgMobileMoneyPaymentWidgetState(); @@ -42,4 +46,7 @@ class _UgMobileMoneyPaymentWidgetState @override bool showEmailField() => false; + + @override + bool get supported => false; } diff --git a/lib/src/ui/payment/rave_pay_widget.dart b/lib/src/ui/payment/rave_pay_widget.dart index 929a62f..2cdc53b 100644 --- a/lib/src/ui/payment/rave_pay_widget.dart +++ b/lib/src/ui/payment/rave_pay_widget.dart @@ -7,7 +7,11 @@ import 'package:rave_flutter/src/common/rave_pay_initializer.dart'; import 'package:rave_flutter/src/common/rave_utils.dart'; import 'package:rave_flutter/src/common/strings.dart'; import 'package:rave_flutter/src/manager/account_transaction_manager.dart'; +import 'package:rave_flutter/src/manager/ach_transaction_manager.dart'; import 'package:rave_flutter/src/manager/card_transaction_manager.dart'; +import 'package:rave_flutter/src/manager/gh_mm_transaction_manager.dart'; +import 'package:rave_flutter/src/manager/mpesa_transaction_manager.dart'; +import 'package:rave_flutter/src/manager/ug_mm_transaction_manager.dart'; import 'package:rave_flutter/src/rave_result.dart'; import 'package:rave_flutter/src/repository/repository.dart'; import 'package:rave_flutter/src/ui/base_widget.dart'; @@ -299,32 +303,69 @@ class _RavePayWidgetState extends BaseState if (_initializer.acceptAccountPayments) { if (_initializer.country.toLowerCase() == 'us' && _initializer.currency.toLowerCase() == 'usd') { - items.add(_Item(Strings.ach, 'note', AchPaymentWidget())); - } else { items.add(_Item( - Strings.account, - 'bank', - AccountPaymentWidget( - manager: AccountTransactionManager( - context: context, - onTransactionComplete: _onTransactionComplete), + Strings.ach, + 'note', + AchPaymentWidget( + manager: AchTransactionManager( + context: context, + onTransactionComplete: _onTransactionComplete), + ))); + } else { + items.add( + _Item( + Strings.account, + 'bank', + AccountPaymentWidget( + manager: AccountTransactionManager( + context: context, + onTransactionComplete: _onTransactionComplete), + ), ), - )); + ); } } if (_initializer.acceptMpesaPayments) { - items.add(_Item(Strings.mpesa, 'note', MpesaPaymentWidget())); + items.add( + _Item( + Strings.mpesa, + 'note', + MpesaPaymentWidget( + manager: MpesaTransactionManager( + context: context, + onTransactionComplete: _onTransactionComplete), + ), + ), + ); } if (_initializer.acceptGHMobileMoneyPayments) { - items.add(_Item( - Strings.ghanaMobileMoney, 'note', GhMobileMoneyPaymentWidget())); + items.add( + _Item( + Strings.ghanaMobileMoney, + 'note', + GhMobileMoneyPaymentWidget( + manager: GhMMTransactionManager( + context: context, + onTransactionComplete: _onTransactionComplete), + ), + ), + ); } if (_initializer.acceptUgMobileMoneyPayments) { - items.add(_Item( - Strings.ugandaMobileMoney, 'note', UgMobileMoneyPaymentWidget())); + items.add( + _Item( + Strings.ugandaMobileMoney, + 'note', + UgMobileMoneyPaymentWidget( + manager: UgMMTransactionManager( + context: context, + onTransactionComplete: _onTransactionComplete), + ), + ), + ); } return items; }