1
+ @file:OptIn(ExperimentalFoundationApi ::class )
2
+
1
3
package com.woocommerce.android.ui.payments.hub.depositsummary
2
4
3
5
import android.content.res.Configuration
4
6
import androidx.compose.animation.AnimatedVisibility
5
7
import androidx.compose.animation.core.animateDpAsState
6
8
import androidx.compose.animation.core.animateFloatAsState
9
+ import androidx.compose.foundation.ExperimentalFoundationApi
7
10
import androidx.compose.foundation.background
8
11
import androidx.compose.foundation.clickable
9
12
import androidx.compose.foundation.interaction.MutableInteractionSource
@@ -16,11 +19,18 @@ import androidx.compose.foundation.layout.Spacer
16
19
import androidx.compose.foundation.layout.fillMaxWidth
17
20
import androidx.compose.foundation.layout.padding
18
21
import androidx.compose.foundation.layout.size
22
+ import androidx.compose.foundation.pager.HorizontalPager
23
+ import androidx.compose.foundation.pager.PagerState
24
+ import androidx.compose.foundation.pager.rememberPagerState
19
25
import androidx.compose.foundation.shape.RoundedCornerShape
20
26
import androidx.compose.material.Divider
21
27
import androidx.compose.material.Icon
22
28
import androidx.compose.material.IconButton
23
29
import androidx.compose.material.MaterialTheme
30
+ import androidx.compose.material.Tab
31
+ import androidx.compose.material.TabRow
32
+ import androidx.compose.material.TabRowDefaults
33
+ import androidx.compose.material.TabRowDefaults.tabIndicatorOffset
24
34
import androidx.compose.material.Text
25
35
import androidx.compose.material.icons.Icons
26
36
import androidx.compose.material.icons.filled.KeyboardArrowDown
@@ -75,126 +85,164 @@ fun PaymentsHubDepositSummaryView(
75
85
isPreview : Boolean = LocalInspectionMode .current,
76
86
) {
77
87
var isExpanded by rememberSaveable { mutableStateOf(false ) }
78
- val chevronRotation by animateFloatAsState(
79
- if (isExpanded) 180f else 0f , label = " chevronRotation"
80
- )
81
88
82
- val topRowIS = remember { MutableInteractionSource () }
83
- val topRowCoroutineScope = rememberCoroutineScope()
89
+ val pageCount = overview.infoPerCurrency.size
84
90
85
91
Column (
86
92
modifier = Modifier
87
93
.fillMaxWidth()
88
94
.background(colorResource(id = R .color.color_surface))
89
95
) {
90
- Row (
91
- modifier = Modifier
92
- .fillMaxWidth()
93
- .clickable(
94
- interactionSource = topRowIS,
95
- indication = null
96
- ) {
97
- val press = PressInteraction .Press (Offset .Zero )
98
- topRowCoroutineScope.launch {
99
- topRowIS.emit(press)
100
- topRowIS.emit(PressInteraction .Release (press))
101
- }
102
- isExpanded = ! isExpanded
103
- }
104
- .padding(
105
- start = dimensionResource(id = R .dimen.major_100),
106
- end = dimensionResource(id = R .dimen.major_100),
107
- top = dimensionResource(id = R .dimen.major_150),
108
- bottom = dimensionResource(id = R .dimen.major_100)
109
- )
96
+ val pagerState = rememberPagerState()
97
+ val currencies = overview.infoPerCurrency.keys.toList()
98
+ val selectedCurrencyInfo = overview.infoPerCurrency[currencies[pagerState.currentPage]] ? : return @Column
99
+
100
+ AnimatedVisibility (
101
+ visible = (isExpanded || isPreview) && pageCount > 1 ,
102
+ modifier = Modifier .fillMaxWidth(),
110
103
) {
111
- Column (
112
- modifier = Modifier .weight(1f )
113
- ) {
114
- Text (
115
- style = MaterialTheme .typography.body2,
116
- text = stringResource(id = R .string.card_reader_hub_deposit_summary_available_funds),
117
- color = colorResource(id = R .color.color_on_surface)
118
- )
119
- Text (
120
- style = MaterialTheme .typography.h6,
121
- fontWeight = FontWeight (700 ),
122
- text = overview.infoPerCurrency[overview.defaultCurrency]?.availableFunds.toString(),
123
- color = colorResource(id = R .color.color_on_surface)
124
- )
125
- }
104
+ CurrenciesTabs (
105
+ currencies = currencies.map { it.uppercase() }.toList(),
106
+ pagerState = pagerState
107
+ )
108
+ }
126
109
110
+ HorizontalPager (
111
+ pageCount = pageCount,
112
+ state = pagerState
113
+ ) {
127
114
Column (
128
- modifier = Modifier .weight(1f )
115
+ modifier = Modifier
116
+ .fillMaxWidth()
117
+ .background(colorResource(id = R .color.color_surface))
129
118
) {
130
- Text (
131
- style = MaterialTheme .typography.body2,
132
- text = stringResource(id = R .string.card_reader_hub_deposit_summary_pending_funds),
133
- color = colorResource(id = R .color.color_on_surface)
134
- )
135
- Text (
136
- style = MaterialTheme .typography.h6,
137
- fontWeight = FontWeight (700 ),
138
- text = overview.infoPerCurrency[overview.defaultCurrency]?.pendingFunds.toString(),
139
- color = colorResource(id = R .color.color_on_surface)
140
- )
141
- Text (
142
- style = MaterialTheme .typography.caption,
143
- text = StringUtils .getQuantityString(
144
- context = LocalContext .current,
145
- quantity = overview.infoPerCurrency[overview.defaultCurrency]?.pendingBalanceDepositsCount ? : 0 ,
146
- default = R .string.card_reader_hub_deposit_summary_pending_deposits_plural,
147
- one = R .string.card_reader_hub_deposit_summary_pending_deposits_one,
148
- ),
149
- color = colorResource(id = R .color.color_surface_variant)
150
- )
151
- }
119
+ FundsOverview (selectedCurrencyInfo, isExpanded) { isExpanded = ! isExpanded }
152
120
153
- Column (
154
- modifier = Modifier .weight(.3f ),
155
- horizontalAlignment = Alignment .End ,
156
- verticalArrangement = Arrangement .Center ,
157
- ) {
158
- IconButton (
159
- onClick = { isExpanded = ! isExpanded },
160
- interactionSource = topRowIS,
121
+ AnimatedVisibility (
122
+ visible = isExpanded || isPreview,
123
+ modifier = Modifier .fillMaxWidth(),
161
124
) {
162
- Icon (
163
- modifier = Modifier .rotate(chevronRotation),
164
- imageVector = Icons .Filled .KeyboardArrowDown ,
165
- contentDescription =
166
- stringResource(R .string.card_reader_hub_deposit_summary_collapse_expand_content_description),
167
- tint = MaterialTheme .colors.primary,
125
+ DepositsInfo (
126
+ nextDeposit = selectedCurrencyInfo.nextDeposit,
127
+ lastDeposit = selectedCurrencyInfo.lastDeposit,
168
128
)
169
129
}
170
130
}
171
131
}
132
+ }
133
+ }
172
134
173
- val dividerPaddingAnimation by animateDpAsState(
174
- if (isExpanded) dimensionResource(id = R .dimen.major_100) else dimensionResource(id = R .dimen.minor_00),
175
- label = " dividerPaddingAnimation"
176
- )
177
-
178
- Divider (
179
- modifier = Modifier
180
- .fillMaxWidth()
181
- .padding(horizontal = dividerPaddingAnimation)
182
- )
135
+ @Composable
136
+ private fun FundsOverview (
137
+ currencyInfo : PaymentsHubDepositSummaryState .Info ,
138
+ isExpanded : Boolean ,
139
+ onExpandCollapseClick : () -> Unit ,
140
+ ) {
141
+ val chevronRotation by animateFloatAsState(
142
+ if (isExpanded) 180f else 0f , label = " chevronRotation"
143
+ )
144
+ val topRowIS = remember { MutableInteractionSource () }
145
+ val topRowCoroutineScope = rememberCoroutineScope()
146
+ Row (
147
+ modifier = Modifier
148
+ .fillMaxWidth()
149
+ .clickable(
150
+ interactionSource = topRowIS,
151
+ indication = null
152
+ ) {
153
+ val press = PressInteraction .Press (Offset .Zero )
154
+ topRowCoroutineScope.launch {
155
+ topRowIS.emit(press)
156
+ topRowIS.emit(PressInteraction .Release (press))
157
+ }
158
+ onExpandCollapseClick()
159
+ }
160
+ .padding(
161
+ start = dimensionResource(id = R .dimen.major_100),
162
+ end = dimensionResource(id = R .dimen.major_100),
163
+ top = dimensionResource(id = R .dimen.major_150),
164
+ bottom = dimensionResource(id = R .dimen.major_100)
165
+ )
166
+ ) {
167
+ Column (
168
+ modifier = Modifier .weight(1f )
169
+ ) {
170
+ Text (
171
+ style = MaterialTheme .typography.body2,
172
+ text = stringResource(id = R .string.card_reader_hub_deposit_summary_available_funds),
173
+ color = colorResource(id = R .color.color_on_surface)
174
+ )
175
+ Text (
176
+ style = MaterialTheme .typography.h6,
177
+ fontWeight = FontWeight .Bold ,
178
+ text = currencyInfo.availableFunds,
179
+ color = colorResource(id = R .color.color_on_surface)
180
+ )
181
+ }
183
182
184
- AnimatedVisibility (
185
- visible = isExpanded || isPreview,
186
- modifier = Modifier .fillMaxWidth(),
183
+ Column (
184
+ modifier = Modifier .weight(1f )
187
185
) {
188
- AdditionInfo (
189
- nextDeposit = overview.infoPerCurrency[overview.defaultCurrency]?.nextDeposit,
190
- lastDeposit = overview.infoPerCurrency[overview.defaultCurrency]?.lastDeposit,
186
+ Text (
187
+ style = MaterialTheme .typography.body2,
188
+ text = stringResource(id = R .string.card_reader_hub_deposit_summary_pending_funds),
189
+ color = colorResource(id = R .color.color_on_surface)
190
+ )
191
+ Text (
192
+ style = MaterialTheme .typography.h6,
193
+ fontWeight = FontWeight .Bold ,
194
+ text = currencyInfo.pendingFunds,
195
+ color = colorResource(id = R .color.color_on_surface)
196
+ )
197
+ Text (
198
+ style = MaterialTheme .typography.caption,
199
+ text = StringUtils .getQuantityString(
200
+ context = LocalContext .current,
201
+ quantity = currencyInfo.pendingBalanceDepositsCount,
202
+ default = R .string.card_reader_hub_deposit_summary_pending_deposits_plural,
203
+ one = R .string.card_reader_hub_deposit_summary_pending_deposits_one,
204
+ ),
205
+ color = colorResource(id = R .color.color_surface_variant)
191
206
)
192
207
}
208
+
209
+ Column (
210
+ modifier = Modifier .weight(.3f ),
211
+ horizontalAlignment = Alignment .End ,
212
+ verticalArrangement = Arrangement .Center ,
213
+ ) {
214
+ IconButton (
215
+ onClick = { onExpandCollapseClick() },
216
+ interactionSource = topRowIS,
217
+ ) {
218
+ Icon (
219
+ modifier = Modifier .rotate(chevronRotation),
220
+ imageVector = Icons .Filled .KeyboardArrowDown ,
221
+ contentDescription =
222
+ stringResource(R .string.card_reader_hub_deposit_summary_collapse_expand_content_description),
223
+ tint = MaterialTheme .colors.primary,
224
+ )
225
+ }
226
+ }
193
227
}
228
+ val dividerPaddingAnimation by animateDpAsState(
229
+ targetValue = if (isExpanded) {
230
+ dimensionResource(id = R .dimen.major_100)
231
+ } else {
232
+ dimensionResource(id = R .dimen.minor_00)
233
+ },
234
+ label = " dividerPaddingAnimation"
235
+ )
236
+
237
+ Divider (
238
+ modifier = Modifier
239
+ .fillMaxWidth()
240
+ .padding(horizontal = dividerPaddingAnimation)
241
+ )
194
242
}
195
243
196
244
@Composable
197
- private fun AdditionInfo (
245
+ private fun DepositsInfo (
198
246
nextDeposit : PaymentsHubDepositSummaryState .Deposit ? ,
199
247
lastDeposit : PaymentsHubDepositSummaryState .Deposit ? ,
200
248
) {
@@ -383,6 +431,52 @@ private fun Deposit(
383
431
}
384
432
}
385
433
434
+ @Composable
435
+ private fun CurrenciesTabs (
436
+ currencies : List <String >,
437
+ pagerState : PagerState ,
438
+ ) {
439
+ val scope = rememberCoroutineScope()
440
+ TabRow (
441
+ modifier = Modifier .fillMaxWidth(),
442
+ selectedTabIndex = pagerState.currentPage,
443
+ backgroundColor = colorResource(id = R .color.color_surface),
444
+ indicator = { tabPositions ->
445
+ TabRowDefaults .Indicator (
446
+ modifier = Modifier
447
+ .tabIndicatorOffset(tabPositions[pagerState.currentPage])
448
+ .padding(horizontal = 16 .dp),
449
+ height = 4 .dp,
450
+ color = colorResource(id = R .color.color_primary)
451
+ )
452
+ }
453
+ ) {
454
+ currencies.forEachIndexed { index, title ->
455
+ Tab (
456
+ selected = pagerState.currentPage == index,
457
+ onClick = {
458
+ scope.launch {
459
+ pagerState.animateScrollToPage(index)
460
+ }
461
+ },
462
+ text = {
463
+ val isSelected = pagerState.currentPage == index
464
+ Text (
465
+ style = MaterialTheme .typography.body1,
466
+ text = title,
467
+ fontWeight = if (isSelected) FontWeight .SemiBold else FontWeight .Normal ,
468
+ color = if (isSelected) {
469
+ colorResource(id = R .color.color_primary)
470
+ } else {
471
+ colorResource(id = R .color.color_on_surface_disabled)
472
+ }
473
+ )
474
+ },
475
+ )
476
+ }
477
+ }
478
+ }
479
+
386
480
@Composable
387
481
private fun DepositStatus (
388
482
text : Int ,
@@ -448,6 +542,22 @@ fun PaymentsHubDepositSummaryViewPreview() {
448
542
status = PaymentsHubDepositSummaryState .Deposit .Status .PAID ,
449
543
date = " 13 Oct 2023"
450
544
)
545
+ ),
546
+ " RUB" to PaymentsHubDepositSummaryState .Info (
547
+ availableFunds = " 100$" ,
548
+ pendingFunds = " 200$" ,
549
+ pendingBalanceDepositsCount = 1 ,
550
+ fundsAvailableInDays = PaymentsHubDepositSummaryState .Info .Interval .Days (1 ),
551
+ nextDeposit = PaymentsHubDepositSummaryState .Deposit (
552
+ amount = " 100$" ,
553
+ status = PaymentsHubDepositSummaryState .Deposit .Status .ESTIMATED ,
554
+ date = " 13 Oct 2023"
555
+ ),
556
+ lastDeposit = PaymentsHubDepositSummaryState .Deposit (
557
+ amount = " 100$" ,
558
+ status = PaymentsHubDepositSummaryState .Deposit .Status .PAID ,
559
+ date = " 13 Oct 2023"
560
+ )
451
561
)
452
562
)
453
563
)
0 commit comments