1
import 'dart:math';
2
3
import 'package:auto_size_text/auto_size_text.dart';
4
+import 'package:cake_wallet/entities/fiat_currency.dart';
5
import 'package:cake_wallet/generated/i18n.dart';
6
import 'package:cake_wallet/src/widgets/cake_image_widget.dart';
7
import 'package:cake_wallet/themes/utils/custom_theme_colors.dart';
8
import 'package:cw_core/crypto_currency.dart';
9
+import 'package:flutter/cupertino.dart';
10
import 'package:flutter/material.dart';
11
12
class SavingsCard extends StatelessWidget {
13
final bool isDarkTheme;
14
final bool isEnabled;
15
+ final bool isLoading;
16
final String interestRate;
17
final String savingsBalance;
18
+ final String? fiatSavingsBalance;
19
+ final FiatCurrency? fiatCurrency;
20
final CryptoCurrency currency;
21
final VoidCallback onAddSavingsPressed;
22
final VoidCallback onRemoveSavingsPressed;
23
final VoidCallback onApproveSavingsPressed;
24
+ final VoidCallback onTooltipPressed;
25
26
const SavingsCard({
27
super.key,
32
required this.onAddSavingsPressed,
33
required this.onRemoveSavingsPressed,
34
required this.onApproveSavingsPressed,
35
+ required this.onTooltipPressed,
36
this.isEnabled = true,
37
+ this.isLoading = false,
38
+ this.fiatSavingsBalance,
39
+ this.fiatCurrency,
40
});
41
42
@override
43
Widget build(BuildContext context) => Container(
34
- margin: const EdgeInsets.all(15),
35
- decoration: BoxDecoration(
36
- borderRadius: BorderRadius.circular(15),
37
- gradient: LinearGradient(
38
- colors: [
39
- isDarkTheme
40
- ? CustomThemeColors.cardGradientColorPrimaryDark
41
- : CustomThemeColors.cardGradientColorPrimaryLight,
42
- isDarkTheme
43
- ? CustomThemeColors.cardGradientColorSecondaryDark
44
- : CustomThemeColors.cardGradientColorSecondaryLight,
45
- ],
46
- begin: Alignment.topCenter,
47
- end: Alignment.bottomCenter,
44
+ margin: const EdgeInsets.all(15),
45
+ decoration: BoxDecoration(
46
+ borderRadius: BorderRadius.circular(15),
47
+ color: Theme.of(context).colorScheme.surfaceContainerLowest,
48
),
49
- ),
50
- child: Container(
51
- padding: const EdgeInsets.all(20),
52
- child: Column(
53
- children: [
54
- getAssetBalanceRow(context,
55
- title: S.of(context).deuro_savings_balance,
56
- subtitle: savingsBalance,
57
- currency: currency),
58
- Padding(
59
- padding: const EdgeInsets.symmetric(vertical: 10),
60
- child: Row(
61
- children: [
62
- Expanded(
63
- child: Text(
64
- 'Current APR',
65
- style: Theme.of(context).textTheme.bodyMedium?.copyWith(
66
- color:
67
- Theme.of(context).colorScheme.onSurfaceVariant,
68
- fontWeight: FontWeight.w500,
69
- ),
70
- softWrap: true,
71
- ),
72
- ),
73
- Text(
74
- interestRate,
49
+ child: Column(children: [
50
+ Padding(
51
+ padding: const EdgeInsets.only(top: 10, bottom: 10, left: 20, right: 20),
52
+ child: Row(
53
+ children: [
54
+ Expanded(
55
+ child: Text(
56
+ 'Current APR', // ToDo: Localize
57
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
58
color: Theme.of(context).colorScheme.onSurfaceVariant,
59
fontWeight: FontWeight.w500,
60
),
61
softWrap: true,
62
),
63
+ ),
64
+ Text(
65
+ interestRate,
66
+ style: Theme.of(context).textTheme.bodyMedium?.copyWith(
67
+ color: Theme.of(context).colorScheme.onSurfaceVariant,
68
+ fontWeight: FontWeight.w800,
69
+ ),
70
+ softWrap: true,
71
+ ),
72
+ ],
73
+ ),
74
+ ),
75
+ Container(
76
+ decoration: BoxDecoration(
77
+ borderRadius: BorderRadius.circular(15),
78
+ gradient: LinearGradient(
79
+ colors: [
80
+ isDarkTheme
81
+ ? CustomThemeColors.cardGradientColorPrimaryDark
82
+ : CustomThemeColors.cardGradientColorPrimaryLight,
83
+ isDarkTheme
84
+ ? CustomThemeColors.cardGradientColorSecondaryDark
85
+ : CustomThemeColors.cardGradientColorSecondaryLight,
86
],
87
+ begin: Alignment.topCenter,
88
+ end: Alignment.bottomCenter,
89
),
90
),
84
- Row(
85
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
86
- children: isEnabled
87
- ? [
88
- Expanded(
89
- child: getButton(
90
- context,
91
- label: S.of(context).deuro_savings_add,
92
- imagePath: 'assets/images/received.png',
93
- onPressed: onAddSavingsPressed,
94
- backgroundColor:
95
- Theme.of(context).colorScheme.primary,
96
- color: Theme.of(context).colorScheme.onPrimary,
97
- ),
98
- ),
99
- SizedBox(width: 12),
100
- Expanded(
101
- child: getButton(
102
- context,
103
- label: S.of(context).deuro_savings_remove,
104
- imagePath: 'assets/images/upload.png',
105
- onPressed: onRemoveSavingsPressed,
106
- backgroundColor:
107
- Theme.of(context).colorScheme.surface,
108
- color: Theme.of(context)
109
- .colorScheme
110
- .onSecondaryContainer,
111
- ),
91
+ padding: const EdgeInsets.all(20),
92
+ child: Column(
93
+ children: [
94
+ Padding(
95
+ padding: const EdgeInsets.only(bottom: 20),
96
+ child: getAssetBalanceRow(
97
+ context,
98
+ title: S.of(context).deuro_savings_balance,
99
+ amount: savingsBalance,
100
+ fiatAmount: fiatSavingsBalance,
101
+ currency: currency,
102
+ fiatCurrency: fiatCurrency,
103
+ hideSymbol: false,
104
+ onTooltipPressed: onTooltipPressed,
105
+ ),
106
+ ),
107
+ isLoading
108
+ ? CupertinoActivityIndicator(color: Theme.of(context).colorScheme.onSurface)
109
+ : Row(
110
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
111
+ children: isEnabled
112
+ ? [
113
+ Expanded(
114
+ child: getButton(
115
+ context,
116
+ label: S.of(context).deuro_savings_add,
117
+ imagePath: 'assets/images/received.png',
118
+ onPressed: onAddSavingsPressed,
119
+ backgroundColor: Theme.of(context).colorScheme.primary,
120
+ color: Theme.of(context).colorScheme.onPrimary,
121
+ ),
122
+ ),
123
+ SizedBox(width: 12),
124
+ Expanded(
125
+ child: getButton(
126
+ context,
127
+ label: S.of(context).deuro_savings_remove,
128
+ imagePath: 'assets/images/upload.png',
129
+ onPressed: onRemoveSavingsPressed,
130
+ backgroundColor: Theme.of(context).colorScheme.surface,
131
+ color: Theme.of(context).colorScheme.onSecondaryContainer,
132
+ ),
133
+ ),
134
+ ]
135
+ : [
136
+ Expanded(
137
+ child: getButton(
138
+ context,
139
+ label: S.of(context).deuro_savings_approve_app,
140
+ onPressed: onApproveSavingsPressed,
141
+ backgroundColor: Theme.of(context).colorScheme.primary,
142
+ color: Theme.of(context).colorScheme.onPrimary,
143
+ icon: Icons.check,
144
+ ),
145
+ )
146
+ ],
147
),
113
- ]
114
- : [
115
- Expanded(
116
- child: getButton(
117
- context,
118
- label: S.of(context).deuro_savings_set_approval,
119
- onPressed: onApproveSavingsPressed,
120
- backgroundColor:
121
- Theme.of(context).colorScheme.primary,
122
- color: Theme.of(context).colorScheme.onPrimary,
123
- ),
124
- )
125
- ],
148
+ ],
149
),
127
- ],
128
- ),
129
- ));
150
+ ),
151
+ ]),
152
+ );
153
154
static Widget getButton(
155
BuildContext context, {
156
required String label,
134
- String? imagePath,
157
required VoidCallback onPressed,
158
required Color backgroundColor,
159
required Color color,
138
- }) =>
139
- Semantics(
140
- label: label,
141
- child: OutlinedButton(
142
- onPressed: onPressed,
143
- style: OutlinedButton.styleFrom(
144
- backgroundColor: backgroundColor,
145
- side: BorderSide(
146
- color: Theme.of(context).colorScheme.outlineVariant.withAlpha(0),
147
- width: 0,
148
- ),
149
- shape:
150
- RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
160
+ String? imagePath,
161
+ IconData? icon,
162
+ bool enabled = true,
163
+ double iconSize = 24,
164
+ }) {
165
+ backgroundColor = enabled ? backgroundColor : backgroundColor.withAlpha(130);
166
+ color = enabled ? color : color.withAlpha(130);
167
+
168
+ return Semantics(
169
+ label: label,
170
+ child: OutlinedButton(
171
+ onPressed: enabled ? onPressed : null,
172
+ style: OutlinedButton.styleFrom(
173
+ backgroundColor: backgroundColor,
174
+ side: BorderSide(
175
+ color: Theme.of(context).colorScheme.outlineVariant.withAlpha(0),
176
+ width: 0,
177
),
152
- child: Container(
153
- padding: const EdgeInsets.symmetric(vertical: 12),
154
- child: Row(
155
- mainAxisAlignment: MainAxisAlignment.center,
156
- children: [
157
- if (imagePath != null) ...[
158
- Image.asset(
159
- imagePath,
160
- height: 30,
161
- width: 30,
162
- color: color,
163
- ),
164
- const SizedBox(width: 8),
165
- ],
166
- Text(
167
- label,
168
- style: Theme.of(context).textTheme.bodyMedium?.copyWith(
169
- color: color,
170
- fontWeight: FontWeight.w700,
171
- ),
172
- ),
178
+ shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
179
+ ),
180
+ child: Container(
181
+ padding: const EdgeInsets.symmetric(vertical: 12),
182
+ child: Row(
183
+ mainAxisAlignment: MainAxisAlignment.center,
184
+ children: [
185
+ if (imagePath != null) ...[
186
+ Image.asset(imagePath, height: iconSize, width: iconSize, color: color),
187
+ const SizedBox(width: 8),
188
],
174
- ),
189
+ if (icon != null) ...[
190
+ Icon(icon, size: iconSize, color: color),
191
+ const SizedBox(width: 8),
192
+ ],
193
+ Text(
194
+ label,
195
+ style: Theme.of(context).textTheme.bodyMedium?.copyWith(
196
+ color: color,
197
+ fontWeight: FontWeight.w700,
198
+ ),
199
+ ),
200
+ ],
201
),
202
),
177
- );
203
+ ),
204
+ );
205
+ }
206
207
static Widget getAssetBalanceRow(
208
BuildContext context, {
209
required String title,
182
- required String subtitle,
210
+ required String amount,
211
required CryptoCurrency currency,
212
bool hideSymbol = true,
213
+ VoidCallback? onTooltipPressed,
214
+ FiatCurrency? fiatCurrency,
215
+ String? fiatAmount,
216
}) =>
217
Row(
218
mainAxisAlignment: MainAxisAlignment.spaceBetween,
221
Column(
222
crossAxisAlignment: CrossAxisAlignment.start,
223
children: [
193
- Text(
194
- title,
195
- style: Theme.of(context).textTheme.bodySmall?.copyWith(
196
- color: Theme.of(context).colorScheme.onSurfaceVariant,
197
- height: 1,
224
+ Row(
225
+ children: [
226
+ Text(
227
+ title,
228
+ style: Theme.of(context).textTheme.bodySmall?.copyWith(
229
+ color: Theme.of(context).colorScheme.onSurfaceVariant,
230
+ height: 1,
231
+ ),
232
+ ),
233
+ if (onTooltipPressed != null)
234
+ Padding(
235
+ padding: EdgeInsets.only(left: 4),
236
+ child: InkWell(
237
+ onTap: onTooltipPressed,
238
+ child: Icon(
239
+ CupertinoIcons.question_circle,
240
+ size: 13,
241
+ color: Theme.of(context).colorScheme.onSurfaceVariant,
242
+ ),
243
+ ),
244
),
245
+ ],
246
),
247
SizedBox(height: 6),
248
AutoSizeText(
202
- subtitle,
249
+ amount,
250
style: Theme.of(context).textTheme.titleLarge?.copyWith(
251
color: Theme.of(context).colorScheme.onSurface,
252
fontWeight: FontWeight.w900,
256
maxLines: 1,
257
textAlign: TextAlign.start,
258
),
259
+ if (fiatCurrency != null)
260
+ AutoSizeText(
261
+ "${fiatCurrency.title} $fiatAmount",
262
+ style: Theme.of(context).textTheme.titleLarge?.copyWith(
263
+ color: Theme.of(context).colorScheme.onSurfaceVariant,
264
+ fontWeight: FontWeight.w500,
265
+ fontSize: 16,
266
+ height: 1.5,
267
+ ),
268
+ maxLines: 1,
269
+ textAlign: TextAlign.start,
270
+ ),
271
],
272
),
273
SizedBox(
215
- //width: min(MediaQuery.of(context).size.width * 0.2, 100),
274
child: Center(
275
child: Column(
276
children: [
283
width: 30.0,
284
child: Center(
285
child: Text(
228
- currency.title
229
- .substring(0, min(currency.title.length, 2)),
230
- style:
231
- Theme.of(context).textTheme.bodySmall?.copyWith(
232
- fontSize: 11,
233
- color: Theme.of(context)
234
- .colorScheme
235
- .onSurfaceVariant,
236
- ),
286
+ currency.title.substring(0, min(currency.title.length, 2)),
287
+ style: Theme.of(context).textTheme.bodySmall?.copyWith(
288
+ fontSize: 11,
289
+ color: Theme.of(context).colorScheme.onSurfaceVariant,
290
+ ),
291
),
292
),
293
decoration: BoxDecoration(
297
),
298
),
299
if (!hideSymbol) ...[
246
- const SizedBox(height: 10),
300
+ const SizedBox(height: 3),
301
Text(
302
currency.title,
303
style: Theme.of(context).textTheme.bodyMedium?.copyWith(