fix issue with custom redeem amount remaining
Godwin Asuquo committed
Dec 7, 2022 at 18:12 UTC
0203f686c555581308c6bf25c05622606782d56f
6 files changed
+156
-122
lib/di.dart
+2
-1
@@ -760,7 +760,8 @@ Future setup(
760
return IoniaMoreOptionsPage(giftCard);
761
});
762
763
- getIt.registerFactoryParam<IoniaCustomRedeemViewModel, IoniaGiftCard, void>((IoniaGiftCard giftCard, _) => IoniaCustomRedeemViewModel(giftCard));
763
+ getIt.registerFactoryParam<IoniaCustomRedeemViewModel, IoniaGiftCard, void>((IoniaGiftCard giftCard, _)
764
+ => IoniaCustomRedeemViewModel(giftCard: giftCard, ioniaService: getIt.get<IoniaService>()));
765
766
getIt.registerFactoryParam<IoniaCustomRedeemPage, List, void>((List args, _){
767
final giftCard = args.first as IoniaGiftCard;
lib/src/screens/ionia/cards/ionia_custom_redeem_page.dart
+40
-29
@@ -1,3 +1,4 @@
1
+import 'package:cake_wallet/core/execution_state.dart';
2
import 'package:cake_wallet/src/screens/base_page.dart';
3
import 'package:cake_wallet/src/screens/ionia/widgets/card_item.dart';
4
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
@@ -18,12 +19,11 @@ class IoniaCustomRedeemPage extends BasePage {
19
) : _amountFieldFocus = FocusNode(),
20
_amountController = TextEditingController() {
21
_amountController.addListener(() {
21
- ioniaCustomRedeemViewModel.updateAmount(_amountController.text);
22
+ ioniaCustomRedeemViewModel.updateAmount(_amountController.text);
23
});
24
}
25
26
final IoniaCustomRedeemViewModel ioniaCustomRedeemViewModel;
26
-
27
28
@override
29
String get title => S.current.custom_redeem_amount;
@@ -50,7 +50,7 @@ class IoniaCustomRedeemPage extends BasePage {
50
disableScroll: true,
51
config: KeyboardActionsConfig(
52
keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
53
- keyboardBarColor: Theme.of(context).accentTextTheme!.bodyText1!.backgroundColor!,
53
+ keyboardBarColor: Theme.of(context).accentTextTheme.bodyText1!.backgroundColor!,
54
nextFocus: false,
55
actions: [
56
KeyboardActionsItem(
@@ -67,10 +67,11 @@ class IoniaCustomRedeemPage extends BasePage {
67
Container(
68
padding: EdgeInsets.symmetric(horizontal: 25),
69
decoration: BoxDecoration(
70
- borderRadius: BorderRadius.only(bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
70
+ borderRadius: BorderRadius.only(
71
+ bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
72
gradient: LinearGradient(colors: [
72
- Theme.of(context).primaryTextTheme!.subtitle1!.color!,
73
- Theme.of(context).primaryTextTheme!.subtitle1!.decorationColor!,
73
+ Theme.of(context).primaryTextTheme.subtitle1!.color!,
74
+ Theme.of(context).primaryTextTheme.subtitle1!.decorationColor!,
75
], begin: Alignment.topLeft, end: Alignment.bottomRight),
76
),
77
child: Column(
@@ -85,11 +86,11 @@ class IoniaCustomRedeemPage extends BasePage {
86
inputFormatters: [FilteringTextInputFormatter.deny(RegExp('[\-|\ ]'))],
87
hintText: '1000',
88
placeholderTextStyle: TextStyle(
88
- color: Theme.of(context).primaryTextTheme!.headline5!.color!,
89
+ color: Theme.of(context).primaryTextTheme.headline5!.color!,
90
fontWeight: FontWeight.w500,
91
fontSize: 36,
92
),
92
- borderColor: Theme.of(context).primaryTextTheme!.headline5!.color!,
93
+ borderColor: Theme.of(context).primaryTextTheme.headline5!.color!,
94
textColor: Colors.white,
95
textStyle: TextStyle(
96
color: Colors.white,
@@ -114,14 +115,17 @@ class IoniaCustomRedeemPage extends BasePage {
115
),
116
),
117
SizedBox(height: 8),
117
- Observer(builder: (_)=>
118
- !ioniaCustomRedeemViewModel.disableRedeem ?
119
- Center(
120
- child: Text('\$${giftCard.remainingAmount} - \$${ioniaCustomRedeemViewModel.amount} = \$${ioniaCustomRedeemViewModel.formattedRemaining} ${S.of(context).remaining}',
121
- style: TextStyle(
122
- color: Theme.of(context).primaryTextTheme!.headline5!.color!,
123
- ),),
124
- ) : SizedBox.shrink(),
118
+ Observer(
119
+ builder: (_) => !ioniaCustomRedeemViewModel.disableRedeem
120
+ ? Center(
121
+ child: Text(
122
+ '\$${giftCard.remainingAmount} - \$${ioniaCustomRedeemViewModel.amount} = \$${ioniaCustomRedeemViewModel.formattedRemaining} ${S.of(context).remaining}',
123
+ style: TextStyle(
124
+ color: Theme.of(context).primaryTextTheme.headline5!.color!,
125
+ ),
126
+ ),
127
+ )
128
+ : SizedBox.shrink(),
129
),
130
SizedBox(height: 24),
131
],
@@ -131,30 +135,37 @@ class IoniaCustomRedeemPage extends BasePage {
135
padding: const EdgeInsets.all(24.0),
136
child: CardItem(
137
title: giftCard.legalName,
134
- backgroundColor: Theme.of(context).accentTextTheme!.headline1!.backgroundColor!.withOpacity(0.1),
138
+ backgroundColor: Theme.of(context)
139
+ .accentTextTheme
140
+ .headline1!
141
+ .backgroundColor!
142
+ .withOpacity(0.1),
143
discount: giftCard.remainingAmount,
144
isAmount: true,
145
discountBackground: AssetImage('assets/images/red_badge_discount.png'),
138
- titleColor: Theme.of(context).accentTextTheme!.headline1!.backgroundColor!,
146
+ titleColor: Theme.of(context).accentTextTheme.headline1!.backgroundColor!,
147
subtitleColor: Theme.of(context).hintColor,
148
subTitle: S.of(context).online,
149
logoUrl: giftCard.logoUrl,
150
),
143
- ),
151
+ ),
152
],
153
),
154
bottomSection: Column(
155
children: [
148
- Padding(
149
- padding: EdgeInsets.only(bottom: 12),
150
- child: PrimaryButton(
151
- onPressed: () {
152
- Navigator.of(context).pop([ioniaCustomRedeemViewModel.remaining.toString(), ioniaCustomRedeemViewModel.amount.toString()]);
153
- },
154
- isDisabled: ioniaCustomRedeemViewModel.disableRedeem,
155
- text: S.of(context).add_custom_redemption,
156
- color: Theme.of(context).accentTextTheme!.bodyText1!.color!,
157
- textColor: Colors.white,
156
+ Observer(
157
+ builder: (_) => Padding(
158
+ padding: EdgeInsets.only(bottom: 12),
159
+ child: LoadingPrimaryButton(
160
+ isLoading: ioniaCustomRedeemViewModel.redeemState is IsExecutingState,
161
+ isDisabled: ioniaCustomRedeemViewModel.disableRedeem,
162
+ text: S.of(context).add_custom_redemption,
163
+ color: Theme.of(context).accentTextTheme.bodyText1!.color!,
164
+ textColor: Colors.white,
165
+ onPressed: () => ioniaCustomRedeemViewModel.addCustomRedeem().then((value) {
166
+ Navigator.of(context).pop(ioniaCustomRedeemViewModel.remaining.toString());
167
+ }),
168
+ ),
169
),
170
),
171
SizedBox(height: 30),
lib/src/screens/ionia/cards/ionia_gift_card_detail_page.dart
+35
-35
@@ -32,7 +32,7 @@ class IoniaGiftCardDetailPage extends BasePage {
32
33
final _backButton = Icon(
34
Icons.arrow_back_ios,
35
- color: Theme.of(context).primaryTextTheme!.headline6!.color!,
35
+ color: Theme.of(context).primaryTextTheme.headline6!.color!,
36
size: 16,
37
);
38
return Padding(
@@ -43,7 +43,7 @@ class IoniaGiftCardDetailPage extends BasePage {
43
child: ButtonTheme(
44
minWidth: double.minPositive,
45
child: TextButton(
46
- // FIX-ME: Style
46
+ // FIX-ME: Style
47
//highlightColor: Colors.transparent,
48
//splashColor: Colors.transparent,
49
//padding: EdgeInsets.all(0),
@@ -61,7 +61,8 @@ class IoniaGiftCardDetailPage extends BasePage {
61
Widget middle(BuildContext context) {
62
return Text(
63
viewModel.giftCard.legalName,
64
- style: textMediumSemiBold(color: Theme.of(context).accentTextTheme!.headline1!.backgroundColor!),
64
+ style:
65
+ textMediumSemiBold(color: Theme.of(context).accentTextTheme.headline1!.backgroundColor!),
66
);
67
}
68
@@ -102,20 +103,21 @@ class IoniaGiftCardDetailPage extends BasePage {
103
title: S.of(context).gift_card_number,
104
subTitle: viewModel.giftCard.cardNumber,
105
),
105
- if (viewModel.giftCard.cardPin?.isNotEmpty ?? false)
106
- ...[Divider(height: 30),
106
+ if (viewModel.giftCard.cardPin.isNotEmpty) ...[
107
+ Divider(height: 30),
108
buildIoniaTile(
109
context,
110
title: S.of(context).pin_number,
111
subTitle: viewModel.giftCard.cardPin,
111
- )],
112
+ )
113
+ ],
114
Divider(height: 30),
113
- Observer(builder: (_) =>
114
- buildIoniaTile(
115
- context,
116
- title: S.of(context).amount,
117
- subTitle: viewModel.remainingAmount.toStringAsFixed(2) ?? '0.00',
118
- )),
115
+ Observer(
116
+ builder: (_) => buildIoniaTile(
117
+ context,
118
+ title: S.of(context).amount,
119
+ subTitle: viewModel.remainingAmount.toStringAsFixed(2),
120
+ )),
121
Divider(height: 50),
122
TextIconButton(
123
label: S.of(context).how_to_use_card,
@@ -131,24 +133,23 @@ class IoniaGiftCardDetailPage extends BasePage {
133
return Column(
134
children: [
135
PrimaryButton(
134
- onPressed: () async {
135
- final amount = await Navigator.of(context)
136
- .pushNamed(Routes.ioniaMoreOptionsPage, arguments: [viewModel.giftCard]) as List<String>?;
137
- if (amount != null) {
138
- viewModel.updateRemaining( balance: double.parse(amount.first), customAmount: double.parse(amount.last));
139
- }
140
- },
141
- text: S.of(context).more_options,
142
- color: Theme.of(context).accentTextTheme.caption!.color!,
143
- textColor: Theme.of(context).primaryTextTheme.headline6!.color!,
136
+ onPressed: () async {
137
+ await Navigator.of(context).pushNamed(
138
+ Routes.ioniaMoreOptionsPage,
139
+ arguments: [viewModel.giftCard]) as String?;
140
+ viewModel.refeshCard();
141
+ },
142
+ text: S.of(context).more_options,
143
+ color: Theme.of(context).accentTextTheme.caption!.color!,
144
+ textColor: Theme.of(context).primaryTextTheme.headline6!.color!,
145
),
146
SizedBox(height: 12),
147
LoadingPrimaryButton(
148
isLoading: viewModel.redeemState is IsExecutingState,
149
onPressed: () => viewModel.redeem().then(
150
(_) {
150
- Navigator.of(context)
151
- .pushNamedAndRemoveUntil(Routes.ioniaManageCardsPage, (route) => route.isFirst);
151
+ Navigator.of(context).pushNamedAndRemoveUntil(
152
+ Routes.ioniaManageCardsPage, (route) => route.isFirst);
153
},
154
),
155
text: S.of(context).mark_as_redeemed,
@@ -168,12 +169,11 @@ class IoniaGiftCardDetailPage extends BasePage {
169
170
Widget buildIoniaTile(BuildContext context, {required String title, required String subTitle}) {
171
return IoniaTile(
171
- title: title,
172
- subTitle: subTitle,
173
- onTap: () {
174
- Clipboard.setData(ClipboardData(text: subTitle));
175
- showBar<void>(context,
176
- S.of(context).transaction_details_copied(title));
172
+ title: title,
173
+ subTitle: subTitle,
174
+ onTap: () {
175
+ Clipboard.setData(ClipboardData(text: subTitle));
176
+ showBar<void>(context, S.of(context).transaction_details_copied(title));
177
});
178
}
179
@@ -184,10 +184,10 @@ class IoniaGiftCardDetailPage extends BasePage {
184
showPopUp<void>(
185
context: context,
186
builder: (BuildContext context) {
187
- return IoniaAlertModal(
187
+ return IoniaAlertModal(
188
title: S.of(context).how_to_use_card,
189
content: Column(
190
- crossAxisAlignment: CrossAxisAlignment.start,
190
+ crossAxisAlignment: CrossAxisAlignment.start,
191
children: viewModel.giftCard.instructions
192
.map((instruction) {
193
return [
@@ -196,13 +196,13 @@ class IoniaGiftCardDetailPage extends BasePage {
196
child: Text(
197
instruction.header,
198
style: textLargeSemiBold(
199
- color: Theme.of(context).textTheme!.headline3!.color!,
199
+ color: Theme.of(context).textTheme.headline3!.color!,
200
),
201
)),
202
Text(
203
instruction.body,
204
style: textMedium(
205
- color: Theme.of(context).textTheme!.headline3!.color!,
205
+ color: Theme.of(context).textTheme.headline3!.color!,
206
),
207
)
208
];
@@ -210,7 +210,7 @@ class IoniaGiftCardDetailPage extends BasePage {
210
.expand((e) => e)
211
.toList()),
212
actionTitle: S.of(context).send_got_it,
213
- );
213
+ );
214
});
215
}
216
}
lib/src/screens/ionia/cards/ionia_more_options_page.dart
+36
-31
@@ -5,7 +5,6 @@ import 'package:cake_wallet/generated/i18n.dart';
5
import 'package:cake_wallet/typography.dart';
6
import 'package:flutter/material.dart';
7
8
-
8
class IoniaMoreOptionsPage extends BasePage {
9
IoniaMoreOptionsPage(this.giftCard);
10
@@ -16,7 +15,7 @@ class IoniaMoreOptionsPage extends BasePage {
15
return Text(
16
S.current.more_options,
17
style: textMediumSemiBold(
19
- color: Theme.of(context).accentTextTheme!.headline1!.backgroundColor!,
18
+ color: Theme.of(context).accentTextTheme.headline1!.backgroundColor!,
19
),
20
);
21
}
@@ -27,40 +26,46 @@ class IoniaMoreOptionsPage extends BasePage {
26
padding: const EdgeInsets.all(16.0),
27
child: Column(
28
crossAxisAlignment: CrossAxisAlignment.stretch,
30
- children: [
31
- SizedBox(height: 10,),
32
- Center(child: Text(S.of(context).choose_from_available_options, style: textMedium(
33
- color: Theme.of(context).primaryTextTheme!.headline6!.color!,
34
- ),)),
35
- SizedBox(height: 40,),
36
- InkWell(
37
- onTap: () async {
38
- final amounts = await Navigator.of(context).pushNamed(Routes.ioniaCustomRedeemPage, arguments: [giftCard]) as List<String>;
39
- if(amounts.first.isNotEmpty){
40
- Navigator.pop(context, amounts);
41
- }
42
- },
43
- child: _GradiantContainer(
44
- content: Padding(
45
- padding: const EdgeInsets.only(top: 24, left: 20, right: 24, bottom: 50),
46
- child: Text(
47
- S.of(context).custom_redeem_amount,
48
- style: textXLargeSemiBold(),
49
- ),
50
- ),
51
- ),
52
- )
53
- ],
54
- ),
29
+ children: [
30
+ SizedBox(
31
+ height: 10,
32
+ ),
33
+ Center(
34
+ child: Text(
35
+ S.of(context).choose_from_available_options,
36
+ style: textMedium(
37
+ color: Theme.of(context).primaryTextTheme.headline6!.color!,
38
+ ),
39
+ )),
40
+ SizedBox(
41
+ height: 40,
42
+ ),
43
+ InkWell(
44
+ onTap: () async {
45
+ final amount = await Navigator.of(context)
46
+ .pushNamed(Routes.ioniaCustomRedeemPage, arguments: [giftCard]) as String?;
47
+ if (amount != null && amount.isNotEmpty) {
48
+ Navigator.pop(context);
49
+ }
50
+ },
51
+ child: _GradiantContainer(
52
+ content: Padding(
53
+ padding: const EdgeInsets.only(top: 24, left: 20, right: 24, bottom: 50),
54
+ child: Text(
55
+ S.of(context).custom_redeem_amount,
56
+ style: textXLargeSemiBold(),
57
+ ),
58
+ ),
59
+ ),
60
+ )
61
+ ],
62
+ ),
63
);
64
}
65
}
66
67
class _GradiantContainer extends StatelessWidget {
60
- const _GradiantContainer({
61
- Key? key,
62
- required this.content
63
- }) : super(key: key);
68
+ const _GradiantContainer({Key? key, required this.content}) : super(key: key);
69
70
final Widget content;
71
lib/view_model/ionia/ionia_custom_redeem_view_model.dart
+29
-7
@@ -1,29 +1,51 @@
1
+import 'package:cake_wallet/core/execution_state.dart';
2
import 'package:cake_wallet/ionia/ionia_gift_card.dart';
3
+import 'package:cake_wallet/ionia/ionia_service.dart';
4
import 'package:mobx/mobx.dart';
5
part 'ionia_custom_redeem_view_model.g.dart';
6
+
7
class IoniaCustomRedeemViewModel = IoniaCustomRedeemViewModelBase with _$IoniaCustomRedeemViewModel;
8
9
abstract class IoniaCustomRedeemViewModelBase with Store {
7
- IoniaCustomRedeemViewModelBase(this.giftCard)
8
- : amount = 0;
10
+ IoniaCustomRedeemViewModelBase({
11
+ required this.giftCard,
12
+ required this.ioniaService,
13
+ }) : amount = 0,
14
+ redeemState = InitialExecutionState();
15
16
final IoniaGiftCard giftCard;
17
18
+ final IoniaService ioniaService;
19
+
20
+ @observable
21
+ ExecutionState redeemState;
22
+
23
@observable
24
double amount;
25
26
@computed
16
- double get remaining => amount <= giftCard.remainingAmount ? giftCard.remainingAmount - amount : 0;
27
+ double get remaining =>
28
+ amount <= giftCard.remainingAmount ? giftCard.remainingAmount - amount : 0;
29
30
@computed
19
- String get formattedRemaining => remaining.toStringAsFixed(2);
31
+ String get formattedRemaining => remaining.toStringAsFixed(2);
32
33
@computed
34
bool get disableRedeem => amount > giftCard.remainingAmount;
35
36
@action
25
- void updateAmount(String text){
26
- amount = text.isEmpty ? 0 : (double.parse(text.replaceAll(',', '.')) ?? 0);
37
+ void updateAmount(String text) {
38
+ amount = text.isEmpty ? 0 : (double.parse(text.replaceAll(',', '.')));
39
}
40
29
-}
\ No newline at end of file
41
+ @action
42
+ Future<void> addCustomRedeem() async {
43
+ try {
44
+ redeemState = IsExecutingState();
45
+ await ioniaService.redeem(giftCardId: giftCard.id, amount: amount);
46
+ redeemState = ExecutedSuccessfullyState();
47
+ } catch (e) {
48
+ redeemState = FailureState(e.toString());
49
+ }
50
+ }
51
+}
lib/view_model/ionia/ionia_gift_card_details_view_model.dart
+14
-19
@@ -6,30 +6,25 @@ import 'package:device_display_brightness/device_display_brightness.dart';
6
7
part 'ionia_gift_card_details_view_model.g.dart';
8
9
-class IoniaGiftCardDetailsViewModel = IoniaGiftCardDetailsViewModelBase with _$IoniaGiftCardDetailsViewModel;
9
+class IoniaGiftCardDetailsViewModel = IoniaGiftCardDetailsViewModelBase
10
+ with _$IoniaGiftCardDetailsViewModel;
11
12
abstract class IoniaGiftCardDetailsViewModelBase with Store {
12
-
13
- IoniaGiftCardDetailsViewModelBase({
14
- required this.ioniaService,
15
- required this.giftCard})
16
- : redeemState = InitialExecutionState(),
17
- remainingAmount = giftCard.remainingAmount,
18
- adjustedAmount = 0,
19
- brightness = 0;
13
+ IoniaGiftCardDetailsViewModelBase({required this.ioniaService, required this.giftCard})
14
+ : redeemState = InitialExecutionState(),
15
+ remainingAmount = giftCard.remainingAmount,
16
+ brightness = 0;
17
18
final IoniaService ioniaService;
22
-
19
+
20
double brightness;
24
-
21
+
22
@observable
23
IoniaGiftCard giftCard;
24
25
@observable
26
double remainingAmount;
27
31
- double adjustedAmount;
32
-
28
@observable
29
ExecutionState redeemState;
30
@@ -38,22 +33,22 @@ abstract class IoniaGiftCardDetailsViewModelBase with Store {
33
giftCard.remainingAmount = remainingAmount;
34
try {
35
redeemState = IsExecutingState();
41
- await ioniaService.redeem(giftCardId: giftCard.id, amount : adjustedAmount > 0 ? adjustedAmount : giftCard.remainingAmount);
36
+ await ioniaService.redeem(giftCardId: giftCard.id, amount: giftCard.remainingAmount);
37
giftCard = await ioniaService.getGiftCard(id: giftCard.id);
38
redeemState = ExecutedSuccessfullyState();
44
- } catch(e) {
39
+ } catch (e) {
40
redeemState = FailureState(e.toString());
41
}
42
}
43
44
@action
50
- void updateRemaining({required double balance, required double customAmount}) {
51
- remainingAmount = balance;
52
- adjustedAmount = customAmount;
45
+ Future<void> refeshCard() async {
46
+ giftCard = await ioniaService.getGiftCard(id: giftCard.id);
47
+ remainingAmount = giftCard.remainingAmount;
48
}
49
50
void increaseBrightness() async {
51
brightness = await DeviceDisplayBrightness.getBrightness();
52
await DeviceDisplayBrightness.setBrightness(1.0);
53
}
59
-}
\ No newline at end of file
54
+}