CW-143 cake pay custom tip amount (#492)

* Add custom tip logic * Fix euro currency

Godwin Asuquo committed Sep 1, 2022 at 19:29 UTC 0931696fa10f8fe706e8743844d114f68b95b343
6 files changed +75 -20
lib/di.dart
+12 -5
@@ -4,9 +4,11 @@ import 'package:cake_wallet/entities/wake_lock.dart';
4 import 'package:cake_wallet/ionia/ionia_anypay.dart';
5 import 'package:cake_wallet/ionia/ionia_category.dart';
6 import 'package:cake_wallet/ionia/ionia_gift_card.dart';
7 +import 'package:cake_wallet/ionia/ionia_tip.dart';
8 import 'package:cake_wallet/src/screens/ionia/cards/ionia_gift_card_detail_page.dart';
9 import 'package:cake_wallet/view_model/ionia/ionia_auth_view_model.dart';
10 import 'package:cake_wallet/view_model/ionia/ionia_buy_card_view_model.dart';
11 +import 'package:cake_wallet/view_model/ionia/ionia_custom_tip_view_model.dart';
12 import 'package:cake_wallet/view_model/ionia/ionia_filter_view_model.dart';
13 import 'package:cake_wallet/ionia/ionia_service.dart';
14 import 'package:cake_wallet/ionia/ionia_api.dart';
@@ -731,16 +733,21 @@ Future setup(
733 ioniaService: getIt.get<IoniaService>(),
734 giftCard: giftCard);
735 });
734 -
736 +
737 + getIt.registerFactoryParam<IoniaCustomTipViewModel, List, void>((List args, _) {
738 + final amount = args[0] as double;
739 + final merchant = args[1] as IoniaMerchant;
740 + final tip = args[2] as IoniaTip;
741 +
742 + return IoniaCustomTipViewModel(amount: amount, tip: tip, ioniaMerchant: merchant);
743 + });
744 +
745 getIt.registerFactoryParam<IoniaGiftCardDetailPage, IoniaGiftCard, void>((IoniaGiftCard giftCard, _) {
746 return IoniaGiftCardDetailPage(getIt.get<IoniaGiftCardDetailsViewModel>(param1: giftCard));
747 });
748
749 getIt.registerFactoryParam<IoniaCustomTipPage, List, void>((List args, _) {
740 - final amount = args.first as String;
741 - final merchant = args.last as IoniaMerchant;
742 -
743 - return IoniaCustomTipPage(getIt.get<IoniaMerchPurchaseViewModel>(param1: amount, param2: merchant));
750 + return IoniaCustomTipPage(getIt.get<IoniaCustomTipViewModel>(param1: args));
751 });
752
753 getIt.registerFactory(() => IoniaManageCardsPage(getIt.get<IoniaGiftCardsListViewModel>()));
lib/ionia/ionia_tip.dart
+2 -1
@@ -1,7 +1,8 @@
1 class IoniaTip {
2 - const IoniaTip({this.originalAmount, this.percentage});
2 + const IoniaTip({this.originalAmount, this.percentage, this.isCustom = false});
3 final double originalAmount;
4 final double percentage;
5 + final bool isCustom;
6 double get additionalAmount => double.parse((originalAmount * percentage / 100).toStringAsFixed(2));
7
8 static const tipList = [
lib/src/screens/ionia/cards/ionia_buy_card_detail_page.dart
+20 -5
@@ -156,7 +156,7 @@ class IoniaBuyGiftCardDetailPage extends BasePage {
156 ),
157 ),
158 Padding(
159 - padding: const EdgeInsets.all(24.0),
159 + padding: const EdgeInsets.fromLTRB(24.0, 24.0, 0, 24.0),
160 child: Column(
161 crossAxisAlignment: CrossAxisAlignment.start,
162 children: [
@@ -174,6 +174,8 @@ class IoniaBuyGiftCardDetailPage extends BasePage {
174 selectedTip: ioniaPurchaseViewModel.selectedTip.percentage,
175 tipsList: ioniaPurchaseViewModel.tips,
176 onSelect: (value) => ioniaPurchaseViewModel.addTip(value),
177 + amount: ioniaPurchaseViewModel.amount,
178 + merchant: ioniaPurchaseViewModel.ioniaMerchant,
179 ),
180 )
181 ],
@@ -372,13 +374,19 @@ class TipButtonGroup extends StatelessWidget {
374 @required this.selectedTip,
375 @required this.onSelect,
376 @required this.tipsList,
377 + @required this.amount,
378 + @required this.merchant,
379 }) : super(key: key);
380
381 final Function(IoniaTip) onSelect;
382 final double selectedTip;
383 final List<IoniaTip> tipsList;
384 + final double amount;
385 + final IoniaMerchant merchant;
386
387 bool _isSelected(double value) => selectedTip == value;
388 + Set<double> get filter => tipsList.map((e) => e.percentage).toSet();
389 + bool get _isCustomSelected => !filter.contains(selectedTip);
390
391 @override
392 Widget build(BuildContext context) {
@@ -392,10 +400,17 @@ class TipButtonGroup extends StatelessWidget {
400 return Padding(
401 padding: EdgeInsets.only(right: 5),
402 child: TipButton(
395 - isSelected: _isSelected(tip.percentage),
396 - onTap: () => onSelect(tip),
397 - caption: '${tip.percentage.toStringAsFixed(0)}%',
398 - subTitle: '\$${tip.additionalAmount.toStringAsFixed(2)}',
403 + isSelected: tip.isCustom ? _isCustomSelected : _isSelected(tip.percentage),
404 + onTap: () async {
405 + IoniaTip ioniaTip = tip;
406 + if(tip.isCustom){
407 + final customTip = await Navigator.pushNamed(context, Routes.ioniaCustomTipPage, arguments: [amount, merchant, tip]) as IoniaTip;
408 + ioniaTip = customTip ?? tip;
409 + }
410 + onSelect(ioniaTip);
411 + },
412 + caption: tip.isCustom ? S.of(context).custom : '${tip.percentage.toStringAsFixed(0)}%',
413 + subTitle: tip.isCustom ? null : '\$${tip.additionalAmount.toStringAsFixed(2)}',
414 ));
415 }));
416 }
lib/src/screens/ionia/cards/ionia_custom_tip_page.dart
+9 -9
@@ -6,7 +6,7 @@ import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
6 import 'package:cake_wallet/src/widgets/primary_button.dart';
7 import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
8 import 'package:cake_wallet/themes/theme_base.dart';
9 -import 'package:cake_wallet/view_model/ionia/ionia_purchase_merch_view_model.dart';
9 +import 'package:cake_wallet/view_model/ionia/ionia_custom_tip_view_model.dart';
10 import 'package:flutter/material.dart';
11 import 'package:flutter/services.dart';
12 import 'package:flutter_mobx/flutter_mobx.dart';
@@ -15,15 +15,15 @@ import 'package:cake_wallet/generated/i18n.dart';
15
16 class IoniaCustomTipPage extends BasePage {
17 IoniaCustomTipPage(
18 - this.ioniaPurchaseViewModel,
18 + this.customTipViewModel,
19 ) : _amountFieldFocus = FocusNode(),
20 _amountController = TextEditingController() {
21 _amountController.addListener(() {
22 - // ioniaPurchaseViewModel.onTipChanged(_amountController.text);
22 + customTipViewModel.onTipChanged(_amountController.text);
23 });
24 }
25
26 - final IoniaMerchPurchaseViewModel ioniaPurchaseViewModel;
26 + final IoniaCustomTipViewModel customTipViewModel;
27
28
29 @override
@@ -46,7 +46,7 @@ class IoniaCustomTipPage extends BasePage {
46 @override
47 Widget body(BuildContext context) {
48 final _width = MediaQuery.of(context).size.width;
49 - final merchant = ioniaPurchaseViewModel.ioniaMerchant;
49 + final merchant = customTipViewModel.ioniaMerchant;
50 return KeyboardActions(
51 disableScroll: true,
52 config: KeyboardActionsConfig(
@@ -116,7 +116,7 @@ class IoniaCustomTipPage extends BasePage {
116 ),
117 SizedBox(height: 8),
118 Observer(builder: (_) {
119 - if (ioniaPurchaseViewModel.percentage == 0.0) {
119 + if (customTipViewModel.percentage == 0.0) {
120 return SizedBox.shrink();
121 }
122
@@ -129,8 +129,8 @@ class IoniaCustomTipPage extends BasePage {
129 ),
130 children: [
131 TextSpan(text: ' ${S.of(context).is_percentage} '),
132 - TextSpan(text: '${ioniaPurchaseViewModel.percentage}%'),
133 - TextSpan(text: ' ${S.of(context).percentageOf(ioniaPurchaseViewModel.amount.toString())} '),
132 + TextSpan(text: '${customTipViewModel.percentage.toStringAsFixed(2)}%'),
133 + TextSpan(text: ' ${S.of(context).percentageOf(customTipViewModel.amount.toStringAsFixed(2))} '),
134 ],
135 ),
136 );
@@ -159,7 +159,7 @@ class IoniaCustomTipPage extends BasePage {
159 padding: EdgeInsets.only(bottom: 12),
160 child: PrimaryButton(
161 onPressed: () {
162 - Navigator.of(context).pop(_amountController.text);
162 + Navigator.of(context).pop(customTipViewModel.customTip);
163 },
164 text: S.of(context).add_tip,
165 color: Theme.of(context).accentTextTheme.body2.color,
lib/view_model/ionia/ionia_custom_tip_view_model.dart new
+31
@@ -0,0 +1,31 @@
1 +import 'package:cake_wallet/ionia/ionia_merchant.dart';
2 +import 'package:cake_wallet/ionia/ionia_tip.dart';
3 +import 'package:mobx/mobx.dart';
4 +
5 +part 'ionia_custom_tip_view_model.g.dart';
6 +
7 +class IoniaCustomTipViewModel = IoniaCustomTipViewModelBase with _$IoniaCustomTipViewModel;
8 +
9 +abstract class IoniaCustomTipViewModelBase with Store {
10 + IoniaCustomTipViewModelBase({this.amount, this.tip, this.ioniaMerchant}){
11 + customTip = tip;
12 + percentage = 0;
13 + }
14 + final IoniaMerchant ioniaMerchant;
15 + final double amount;
16 + final IoniaTip tip;
17 +
18 + @observable
19 + IoniaTip customTip;
20 +
21 + @observable
22 + double percentage;
23 +
24 + @action
25 + void onTipChanged(String value){
26 +
27 + final _amount = value.isEmpty ? 0 : double.parse(value.replaceAll(',', '.'));
28 + percentage = _amount/amount * 100;
29 + customTip = IoniaTip(percentage: percentage, originalAmount: amount);
30 + }
31 +}
\ No newline at end of file
lib/view_model/ionia/ionia_purchase_merch_view_model.dart
+1
@@ -25,6 +25,7 @@ abstract class IoniaMerchPurchaseViewModelBase with Store {
25 IoniaTip(percentage: 15, originalAmount: amount),
26 IoniaTip(percentage: 18, originalAmount: amount),
27 IoniaTip(percentage: 20, originalAmount: amount),
28 + IoniaTip(percentage: 0, originalAmount: amount, isCustom: true),
29 ];
30 selectedTip = tips.first;
31 }