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

* Add custom tip logic

* Fix euro currency
This commit is contained in:
Godwin Asuquo 2022-09-01 19:29:58 +03:00 committed by GitHub
parent a745319ffa
commit 0931696fa1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 75 additions and 20 deletions

View file

@ -4,9 +4,11 @@ import 'package:cake_wallet/entities/wake_lock.dart';
import 'package:cake_wallet/ionia/ionia_anypay.dart'; import 'package:cake_wallet/ionia/ionia_anypay.dart';
import 'package:cake_wallet/ionia/ionia_category.dart'; import 'package:cake_wallet/ionia/ionia_category.dart';
import 'package:cake_wallet/ionia/ionia_gift_card.dart'; import 'package:cake_wallet/ionia/ionia_gift_card.dart';
import 'package:cake_wallet/ionia/ionia_tip.dart';
import 'package:cake_wallet/src/screens/ionia/cards/ionia_gift_card_detail_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_gift_card_detail_page.dart';
import 'package:cake_wallet/view_model/ionia/ionia_auth_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_auth_view_model.dart';
import 'package:cake_wallet/view_model/ionia/ionia_buy_card_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_buy_card_view_model.dart';
import 'package:cake_wallet/view_model/ionia/ionia_custom_tip_view_model.dart';
import 'package:cake_wallet/view_model/ionia/ionia_filter_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_filter_view_model.dart';
import 'package:cake_wallet/ionia/ionia_service.dart'; import 'package:cake_wallet/ionia/ionia_service.dart';
import 'package:cake_wallet/ionia/ionia_api.dart'; import 'package:cake_wallet/ionia/ionia_api.dart';
@ -731,16 +733,21 @@ Future setup(
ioniaService: getIt.get<IoniaService>(), ioniaService: getIt.get<IoniaService>(),
giftCard: giftCard); giftCard: giftCard);
}); });
getIt.registerFactoryParam<IoniaCustomTipViewModel, List, void>((List args, _) {
final amount = args[0] as double;
final merchant = args[1] as IoniaMerchant;
final tip = args[2] as IoniaTip;
return IoniaCustomTipViewModel(amount: amount, tip: tip, ioniaMerchant: merchant);
});
getIt.registerFactoryParam<IoniaGiftCardDetailPage, IoniaGiftCard, void>((IoniaGiftCard giftCard, _) { getIt.registerFactoryParam<IoniaGiftCardDetailPage, IoniaGiftCard, void>((IoniaGiftCard giftCard, _) {
return IoniaGiftCardDetailPage(getIt.get<IoniaGiftCardDetailsViewModel>(param1: giftCard)); return IoniaGiftCardDetailPage(getIt.get<IoniaGiftCardDetailsViewModel>(param1: giftCard));
}); });
getIt.registerFactoryParam<IoniaCustomTipPage, List, void>((List args, _) { getIt.registerFactoryParam<IoniaCustomTipPage, List, void>((List args, _) {
final amount = args.first as String; return IoniaCustomTipPage(getIt.get<IoniaCustomTipViewModel>(param1: args));
final merchant = args.last as IoniaMerchant;
return IoniaCustomTipPage(getIt.get<IoniaMerchPurchaseViewModel>(param1: amount, param2: merchant));
}); });
getIt.registerFactory(() => IoniaManageCardsPage(getIt.get<IoniaGiftCardsListViewModel>())); getIt.registerFactory(() => IoniaManageCardsPage(getIt.get<IoniaGiftCardsListViewModel>()));

View file

@ -1,7 +1,8 @@
class IoniaTip { class IoniaTip {
const IoniaTip({this.originalAmount, this.percentage}); const IoniaTip({this.originalAmount, this.percentage, this.isCustom = false});
final double originalAmount; final double originalAmount;
final double percentage; final double percentage;
final bool isCustom;
double get additionalAmount => double.parse((originalAmount * percentage / 100).toStringAsFixed(2)); double get additionalAmount => double.parse((originalAmount * percentage / 100).toStringAsFixed(2));
static const tipList = [ static const tipList = [

View file

@ -156,7 +156,7 @@ class IoniaBuyGiftCardDetailPage extends BasePage {
), ),
), ),
Padding( Padding(
padding: const EdgeInsets.all(24.0), padding: const EdgeInsets.fromLTRB(24.0, 24.0, 0, 24.0),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -174,6 +174,8 @@ class IoniaBuyGiftCardDetailPage extends BasePage {
selectedTip: ioniaPurchaseViewModel.selectedTip.percentage, selectedTip: ioniaPurchaseViewModel.selectedTip.percentage,
tipsList: ioniaPurchaseViewModel.tips, tipsList: ioniaPurchaseViewModel.tips,
onSelect: (value) => ioniaPurchaseViewModel.addTip(value), onSelect: (value) => ioniaPurchaseViewModel.addTip(value),
amount: ioniaPurchaseViewModel.amount,
merchant: ioniaPurchaseViewModel.ioniaMerchant,
), ),
) )
], ],
@ -372,13 +374,19 @@ class TipButtonGroup extends StatelessWidget {
@required this.selectedTip, @required this.selectedTip,
@required this.onSelect, @required this.onSelect,
@required this.tipsList, @required this.tipsList,
@required this.amount,
@required this.merchant,
}) : super(key: key); }) : super(key: key);
final Function(IoniaTip) onSelect; final Function(IoniaTip) onSelect;
final double selectedTip; final double selectedTip;
final List<IoniaTip> tipsList; final List<IoniaTip> tipsList;
final double amount;
final IoniaMerchant merchant;
bool _isSelected(double value) => selectedTip == value; bool _isSelected(double value) => selectedTip == value;
Set<double> get filter => tipsList.map((e) => e.percentage).toSet();
bool get _isCustomSelected => !filter.contains(selectedTip);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -392,10 +400,17 @@ class TipButtonGroup extends StatelessWidget {
return Padding( return Padding(
padding: EdgeInsets.only(right: 5), padding: EdgeInsets.only(right: 5),
child: TipButton( child: TipButton(
isSelected: _isSelected(tip.percentage), isSelected: tip.isCustom ? _isCustomSelected : _isSelected(tip.percentage),
onTap: () => onSelect(tip), onTap: () async {
caption: '${tip.percentage.toStringAsFixed(0)}%', IoniaTip ioniaTip = tip;
subTitle: '\$${tip.additionalAmount.toStringAsFixed(2)}', if(tip.isCustom){
final customTip = await Navigator.pushNamed(context, Routes.ioniaCustomTipPage, arguments: [amount, merchant, tip]) as IoniaTip;
ioniaTip = customTip ?? tip;
}
onSelect(ioniaTip);
},
caption: tip.isCustom ? S.of(context).custom : '${tip.percentage.toStringAsFixed(0)}%',
subTitle: tip.isCustom ? null : '\$${tip.additionalAmount.toStringAsFixed(2)}',
)); ));
})); }));
} }

View file

@ -6,7 +6,7 @@ import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/themes/theme_base.dart';
import 'package:cake_wallet/view_model/ionia/ionia_purchase_merch_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_custom_tip_view_model.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter_mobx/flutter_mobx.dart';
@ -15,15 +15,15 @@ import 'package:cake_wallet/generated/i18n.dart';
class IoniaCustomTipPage extends BasePage { class IoniaCustomTipPage extends BasePage {
IoniaCustomTipPage( IoniaCustomTipPage(
this.ioniaPurchaseViewModel, this.customTipViewModel,
) : _amountFieldFocus = FocusNode(), ) : _amountFieldFocus = FocusNode(),
_amountController = TextEditingController() { _amountController = TextEditingController() {
_amountController.addListener(() { _amountController.addListener(() {
// ioniaPurchaseViewModel.onTipChanged(_amountController.text); customTipViewModel.onTipChanged(_amountController.text);
}); });
} }
final IoniaMerchPurchaseViewModel ioniaPurchaseViewModel; final IoniaCustomTipViewModel customTipViewModel;
@override @override
@ -46,7 +46,7 @@ class IoniaCustomTipPage extends BasePage {
@override @override
Widget body(BuildContext context) { Widget body(BuildContext context) {
final _width = MediaQuery.of(context).size.width; final _width = MediaQuery.of(context).size.width;
final merchant = ioniaPurchaseViewModel.ioniaMerchant; final merchant = customTipViewModel.ioniaMerchant;
return KeyboardActions( return KeyboardActions(
disableScroll: true, disableScroll: true,
config: KeyboardActionsConfig( config: KeyboardActionsConfig(
@ -116,7 +116,7 @@ class IoniaCustomTipPage extends BasePage {
), ),
SizedBox(height: 8), SizedBox(height: 8),
Observer(builder: (_) { Observer(builder: (_) {
if (ioniaPurchaseViewModel.percentage == 0.0) { if (customTipViewModel.percentage == 0.0) {
return SizedBox.shrink(); return SizedBox.shrink();
} }
@ -129,8 +129,8 @@ class IoniaCustomTipPage extends BasePage {
), ),
children: [ children: [
TextSpan(text: ' ${S.of(context).is_percentage} '), TextSpan(text: ' ${S.of(context).is_percentage} '),
TextSpan(text: '${ioniaPurchaseViewModel.percentage}%'), TextSpan(text: '${customTipViewModel.percentage.toStringAsFixed(2)}%'),
TextSpan(text: ' ${S.of(context).percentageOf(ioniaPurchaseViewModel.amount.toString())} '), TextSpan(text: ' ${S.of(context).percentageOf(customTipViewModel.amount.toStringAsFixed(2))} '),
], ],
), ),
); );
@ -159,7 +159,7 @@ class IoniaCustomTipPage extends BasePage {
padding: EdgeInsets.only(bottom: 12), padding: EdgeInsets.only(bottom: 12),
child: PrimaryButton( child: PrimaryButton(
onPressed: () { onPressed: () {
Navigator.of(context).pop(_amountController.text); Navigator.of(context).pop(customTipViewModel.customTip);
}, },
text: S.of(context).add_tip, text: S.of(context).add_tip,
color: Theme.of(context).accentTextTheme.body2.color, color: Theme.of(context).accentTextTheme.body2.color,

View file

@ -0,0 +1,31 @@
import 'package:cake_wallet/ionia/ionia_merchant.dart';
import 'package:cake_wallet/ionia/ionia_tip.dart';
import 'package:mobx/mobx.dart';
part 'ionia_custom_tip_view_model.g.dart';
class IoniaCustomTipViewModel = IoniaCustomTipViewModelBase with _$IoniaCustomTipViewModel;
abstract class IoniaCustomTipViewModelBase with Store {
IoniaCustomTipViewModelBase({this.amount, this.tip, this.ioniaMerchant}){
customTip = tip;
percentage = 0;
}
final IoniaMerchant ioniaMerchant;
final double amount;
final IoniaTip tip;
@observable
IoniaTip customTip;
@observable
double percentage;
@action
void onTipChanged(String value){
final _amount = value.isEmpty ? 0 : double.parse(value.replaceAll(',', '.'));
percentage = _amount/amount * 100;
customTip = IoniaTip(percentage: percentage, originalAmount: amount);
}
}

View file

@ -25,6 +25,7 @@ abstract class IoniaMerchPurchaseViewModelBase with Store {
IoniaTip(percentage: 15, originalAmount: amount), IoniaTip(percentage: 15, originalAmount: amount),
IoniaTip(percentage: 18, originalAmount: amount), IoniaTip(percentage: 18, originalAmount: amount),
IoniaTip(percentage: 20, originalAmount: amount), IoniaTip(percentage: 20, originalAmount: amount),
IoniaTip(percentage: 0, originalAmount: amount, isCustom: true),
]; ];
selectedTip = tips.first; selectedTip = tips.first;
} }