diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 5b19f4c6fd..75603cdf2e 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -1612,6 +1612,7 @@ Withdraw unavailable now You can\'t initiate swap or new withdrawal till the current one is finished Withdrawal in progress + Card settings Change PIN-code Come back to the app if you forget it. I understand that I will completely lose access to my Tangem Pay Card and all funds on it without the possibility of recovery diff --git a/features/tangempay/details/api/src/main/kotlin/com/tangem/features/tangempay/components/TangemPayCardPageComponent.kt b/features/tangempay/details/api/src/main/kotlin/com/tangem/features/tangempay/components/TangemPayCardPageComponent.kt new file mode 100644 index 0000000000..9ec8ddecd1 --- /dev/null +++ b/features/tangempay/details/api/src/main/kotlin/com/tangem/features/tangempay/components/TangemPayCardPageComponent.kt @@ -0,0 +1,14 @@ +package com.tangem.features.tangempay.components + +import com.tangem.core.decompose.factory.ComponentFactory +import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.domain.models.wallet.UserWalletId +import com.tangem.domain.pay.TangemPayDetailsConfig + +interface TangemPayCardPageComponent : ComposableContentComponent { + data class Params( + val userWalletId: UserWalletId, + val config: TangemPayDetailsConfig, + ) + interface Factory : ComponentFactory +} \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/DefaultTangemPayCardPageComponent.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/DefaultTangemPayCardPageComponent.kt new file mode 100644 index 0000000000..a69dbe675f --- /dev/null +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/DefaultTangemPayCardPageComponent.kt @@ -0,0 +1,96 @@ +package com.tangem.features.tangempay.components + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import com.arkivanov.decompose.ComponentContext +import com.arkivanov.decompose.extensions.compose.stack.Children +import com.arkivanov.decompose.extensions.compose.stack.animation.stackAnimation +import com.arkivanov.decompose.extensions.compose.subscribeAsState +import com.arkivanov.decompose.router.stack.StackNavigation +import com.arkivanov.decompose.router.stack.childStack +import com.arkivanov.decompose.router.stack.pop +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.decompose.context.childByContext +import com.tangem.core.decompose.navigation.inner.InnerRouter +import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.features.tangempay.navigation.TangemPayDetailsInnerRoute +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject + +internal class DefaultTangemPayCardPageComponent @AssistedInject constructor( + @Assisted private val appComponentContext: AppComponentContext, + @Assisted private val params: TangemPayCardPageComponent.Params, +) : AppComponentContext by appComponentContext, TangemPayCardPageComponent { + + private val stackNavigation = StackNavigation() + + private val innerRouter = InnerRouter( + stackNavigation = stackNavigation, + popCallback = { onChildBack() }, + ) + + private val childStack = childStack( + key = "tangemPayCardPageInnerStack", + source = stackNavigation, + serializer = TangemPayDetailsInnerRoute.serializer(), + initialConfiguration = TangemPayDetailsInnerRoute.Details, + childFactory = ::screenChild, + ) + + @Suppress("ReusedModifierInstance") + @Composable + override fun Content(modifier: Modifier) { + val childStack by childStack.subscribeAsState() + Children( + stack = childStack, + animation = stackAnimation(), + ) { child -> + child.instance.Content(modifier = modifier) + } + } + + private fun screenChild( + config: TangemPayDetailsInnerRoute, + componentContext: ComponentContext, + ): ComposableContentComponent = when (config) { + TangemPayDetailsInnerRoute.Details -> TangemPayCardPageScreenComponent( + appComponentContext = childByContext(componentContext = componentContext, router = innerRouter), + params = params, + ) + TangemPayDetailsInnerRoute.ChangePIN -> TangemPayChangePinComponent( + appComponentContext = childByContext(componentContext = componentContext, router = innerRouter), + params = TangemPayDetailsContainerComponent.Params( + userWalletId = params.userWalletId, + config = params.config, + ), + ) + TangemPayDetailsInnerRoute.ChangePINSuccess -> TangemPayChangePinSuccessComponent( + appComponentContext = childByContext(componentContext = componentContext, router = innerRouter), + ) + TangemPayDetailsInnerRoute.AddToWallet -> TangemPayAddToWalletComponent( + appComponentContext = childByContext(componentContext = componentContext, router = innerRouter), + params = TangemPayDetailsContainerComponent.Params( + userWalletId = params.userWalletId, + config = params.config, + ), + ) + } + + private fun onChildBack() { + if (childStack.value.backStack.isEmpty()) { + router.pop() + } else { + stackNavigation.pop() + } + } + + @AssistedFactory + interface Factory : TangemPayCardPageComponent.Factory { + override fun create( + context: AppComponentContext, + params: TangemPayCardPageComponent.Params, + ): DefaultTangemPayCardPageComponent + } +} \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/TangemPayCardPageScreenComponent.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/TangemPayCardPageScreenComponent.kt new file mode 100644 index 0000000000..975ce82cf3 --- /dev/null +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/TangemPayCardPageScreenComponent.kt @@ -0,0 +1,80 @@ +package com.tangem.features.tangempay.components + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.arkivanov.decompose.ComponentContext +import com.arkivanov.decompose.extensions.compose.subscribeAsState +import com.arkivanov.decompose.router.slot.childSlot +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.decompose.context.child +import com.tangem.core.decompose.context.childByContext +import com.tangem.core.decompose.model.getOrCreateModel +import com.tangem.core.ui.components.NavigationBar3ButtonsScrim +import com.tangem.core.ui.decompose.ComposableBottomSheetComponent +import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.features.tangempay.components.cardDetails.DefaultTangemPayCardDetailsBlockComponent +import com.tangem.features.tangempay.components.cardDetails.TangemPayCardDetailsBlockComponent +import com.tangem.features.tangempay.entity.TangemPayDetailsNavigation +import com.tangem.features.tangempay.model.TangemPayCardPageModel +import com.tangem.features.tangempay.ui.TangemPayCardPageScreen + +internal class TangemPayCardPageScreenComponent( + private val appComponentContext: AppComponentContext, + private val params: TangemPayCardPageComponent.Params, +) : AppComponentContext by appComponentContext, ComposableContentComponent { + + private val model: TangemPayCardPageModel = getOrCreateModel(params = params) + + private val containerParams = TangemPayDetailsContainerComponent.Params( + userWalletId = params.userWalletId, + config = params.config, + ) + + private val cardDetailsBlockComponent = DefaultTangemPayCardDetailsBlockComponent( + appComponentContext = child("cardDetailsBlockComponent"), + params = TangemPayCardDetailsBlockComponent.Params(params = containerParams), + ) + + private val bottomSheetSlot = childSlot( + source = model.bottomSheetNavigation, + serializer = TangemPayDetailsNavigation.serializer(), + handleBackButton = false, + childFactory = ::bottomSheetChild, + ) + + @Composable + override fun Content(modifier: Modifier) { + val state by model.uiState.collectAsStateWithLifecycle() + val cardDetailsState by cardDetailsBlockComponent.state.collectAsStateWithLifecycle() + val bottomSheet by bottomSheetSlot.subscribeAsState() + + NavigationBar3ButtonsScrim() + TangemPayCardPageScreen( + state = state, + cardDetailsBlockComponent = cardDetailsBlockComponent, + cardDetailsState = cardDetailsState, + modifier = modifier, + ) + bottomSheet.child?.instance?.BottomSheet() + } + + private fun bottomSheetChild( + navigation: TangemPayDetailsNavigation, + componentContext: ComponentContext, + ): ComposableBottomSheetComponent { + val context = childByContext(componentContext) + return when (navigation) { + is TangemPayDetailsNavigation.ViewPinCode -> TangemPayViewPinComponent( + appComponentContext = context, + params = TangemPayViewPinComponent.Params( + walletId = navigation.userWalletId, + cardId = navigation.cardId, + listener = model, + ), + ) + else -> error("Unsupported bottom sheet navigation: $navigation") + } + } +} \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/di/TangemPayDetailsFeatureModule.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/di/TangemPayDetailsFeatureModule.kt index de293a174d..df71114f7c 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/di/TangemPayDetailsFeatureModule.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/di/TangemPayDetailsFeatureModule.kt @@ -1,6 +1,8 @@ package com.tangem.features.tangempay.di +import com.tangem.features.tangempay.components.DefaultTangemPayCardPageComponent import com.tangem.features.tangempay.components.DefaultTangemPayDetailsContainerComponent +import com.tangem.features.tangempay.components.TangemPayCardPageComponent import com.tangem.features.tangempay.components.TangemPayDetailsContainerComponent import com.tangem.features.tangempay.model.listener.CardDetailsEventListener import com.tangem.features.tangempay.model.listener.DefaultCardDetailsEventListener @@ -20,6 +22,12 @@ internal interface TangemPayDetailsFeatureModule { factory: DefaultTangemPayDetailsContainerComponent.Factory, ): TangemPayDetailsContainerComponent.Factory + @Binds + @Singleton + fun bindTangemPayCardPageComponentFactory( + factory: DefaultTangemPayCardPageComponent.Factory, + ): TangemPayCardPageComponent.Factory + @Binds @Singleton fun bindCardDetailsEventListener(impl: DefaultCardDetailsEventListener): CardDetailsEventListener diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/di/TangemPayModelModule.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/di/TangemPayModelModule.kt index 2150e54279..d533bce2b9 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/di/TangemPayModelModule.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/di/TangemPayModelModule.kt @@ -5,6 +5,7 @@ import com.tangem.core.decompose.model.Model import com.tangem.features.tangempay.model.TangemPayAddFundsModel import com.tangem.features.tangempay.model.TangemPayAddToWalletModel import com.tangem.features.tangempay.model.TangemPayCardDetailsBlockModel +import com.tangem.features.tangempay.model.TangemPayCardPageModel import com.tangem.features.tangempay.model.TangemPayChangePinModel import com.tangem.features.tangempay.model.TangemPayDetailsModel import com.tangem.features.tangempay.model.TangemPayTxHistoryDetailsModel @@ -59,4 +60,9 @@ internal interface TangemPayModelModule { @IntoMap @ClassKey(TangemPayViewPinModel::class) fun bindTangemPayViewPinModel(model: TangemPayViewPinModel): Model + + @Binds + @IntoMap + @ClassKey(TangemPayCardPageModel::class) + fun bindTangemPayCardPageModel(model: TangemPayCardPageModel): Model } \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayCardPageUM.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayCardPageUM.kt new file mode 100644 index 0000000000..8a16bf6d94 --- /dev/null +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayCardPageUM.kt @@ -0,0 +1,39 @@ +package com.tangem.features.tangempay.entity + +import androidx.compose.runtime.Immutable +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf + +@Immutable +internal data class TangemPayCardPageUM( + val addToWalletBlockState: AddToWalletBlockState? = null, + val settings: ImmutableList = persistentListOf( + TangemPayCardPageSetting.ChangePIN, + TangemPayCardPageSetting.FreezeCard, + ), + val onBackClick: () -> Unit, + val onSettingClick: (TangemPayCardPageSetting) -> Unit, +) { + companion object { + fun stub( + addToWalletBlockState: AddToWalletBlockState? = AddToWalletBlockState(onClick = {}, onClickClose = {}), + settings: ImmutableList = persistentListOf( + TangemPayCardPageSetting.ChangePIN, + TangemPayCardPageSetting.FreezeCard, + TangemPayCardPageSetting.ReplaceCard, + ), + ) = TangemPayCardPageUM( + addToWalletBlockState = addToWalletBlockState, + settings = settings, + onBackClick = {}, + onSettingClick = {}, + ) + } +} + +@Immutable +internal sealed class TangemPayCardPageSetting { + data object ChangePIN : TangemPayCardPageSetting() + data object FreezeCard : TangemPayCardPageSetting() + data object ReplaceCard : TangemPayCardPageSetting() +} \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayCardPageModel.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayCardPageModel.kt new file mode 100644 index 0000000000..b08ca54fbb --- /dev/null +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayCardPageModel.kt @@ -0,0 +1,177 @@ +package com.tangem.features.tangempay.model + +import androidx.compose.runtime.Stable +import com.arkivanov.decompose.router.slot.SlotNavigation +import com.arkivanov.decompose.router.slot.activate +import com.arkivanov.decompose.router.slot.dismiss +import com.tangem.core.decompose.di.ModelScoped +import com.tangem.core.decompose.model.Model +import com.tangem.core.decompose.model.ParamsContainer +import com.tangem.core.decompose.navigation.Router +import com.tangem.core.decompose.ui.UiMessageSender +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.message.SnackbarMessage +import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository +import com.tangem.domain.visa.model.TangemPayCardFrozenState +import com.tangem.features.tangempay.components.TangemPayCardPageComponent +import com.tangem.features.tangempay.components.ViewPinListener +import com.tangem.features.tangempay.details.impl.R +import com.tangem.features.tangempay.entity.AddToWalletBlockState +import com.tangem.features.tangempay.entity.TangemPayCardPageSetting +import com.tangem.features.tangempay.entity.TangemPayCardPageUM +import com.tangem.features.tangempay.entity.TangemPayDetailsNavigation +import com.tangem.features.tangempay.navigation.TangemPayDetailsInnerRoute +import com.tangem.features.tangempay.utils.TangemPayMessagesFactory +import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import com.tangem.utils.coroutines.JobHolder +import com.tangem.utils.coroutines.saveIn +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import javax.inject.Inject + +@Stable +@ModelScoped +internal class TangemPayCardPageModel @Inject constructor( + paramsContainer: ParamsContainer, + override val dispatchers: CoroutineDispatcherProvider, + private val router: Router, + private val cardDetailsRepository: TangemPayCardDetailsRepository, + private val uiMessageSender: UiMessageSender, +) : Model(), ViewPinListener { + + private val params: TangemPayCardPageComponent.Params = paramsContainer.require() + + private var currentFrozenState: TangemPayCardFrozenState = params.config.cardFrozenState + + private val addToWalletBannerJobHolder = JobHolder() + + val uiState: StateFlow + field = MutableStateFlow( + TangemPayCardPageUM( + onBackClick = router::pop, + onSettingClick = ::onSettingClick, + ), + ) + + val bottomSheetNavigation: SlotNavigation = SlotNavigation() + + init { + fetchAddToWalletBanner() + subscribeToCardFrozenState() + } + + private fun onSettingClick(setting: TangemPayCardPageSetting) = when (setting) { + TangemPayCardPageSetting.ChangePIN -> onClickChangePIN() + TangemPayCardPageSetting.FreezeCard -> onClickFreezeOrUnfreezeCard() + TangemPayCardPageSetting.ReplaceCard -> Unit // TODO v_rodionov #[REDACTED_TASK_KEY] + } + + private fun onClickChangePIN() { + if (!params.config.isPinSet) { + router.push(TangemPayDetailsInnerRoute.ChangePIN) + } else { + bottomSheetNavigation.activate( + TangemPayDetailsNavigation.ViewPinCode( + userWalletId = params.userWalletId, + cardId = params.config.cardId, + ), + ) + } + } + + private fun onClickFreezeOrUnfreezeCard() { + when (currentFrozenState) { + TangemPayCardFrozenState.Frozen -> uiMessageSender.send( + TangemPayMessagesFactory.createUnfreezeCardMessage(onUnfreezeClicked = ::unfreezeCard), + ) + else -> uiMessageSender.send( + TangemPayMessagesFactory.createFreezeCardMessage(onFreezeClicked = ::freezeCard), + ) + } + } + + private fun freezeCard() { + modelScope.launch { + cardDetailsRepository.freezeCard( + userWalletId = params.userWalletId, + cardId = params.config.cardId, + ).onLeft { + val message = SnackbarMessage(resourceReference(R.string.tangem_pay_freeze_card_failed)) + uiMessageSender.send(message) + }.onRight { state -> + val message = if (state == TangemPayCardFrozenState.Frozen) { + SnackbarMessage(resourceReference(R.string.tangem_pay_freeze_card_success)) + } else { + SnackbarMessage(resourceReference(R.string.tangem_pay_freeze_card_failed)) + } + uiMessageSender.send(message) + } + } + } + + private fun unfreezeCard() { + modelScope.launch { + cardDetailsRepository.unfreezeCard( + userWalletId = params.userWalletId, + cardId = params.config.cardId, + ).onLeft { + val message = SnackbarMessage(resourceReference(R.string.tangem_pay_unfreeze_card_failed)) + uiMessageSender.send(message) + }.onRight { state -> + val message = if (state == TangemPayCardFrozenState.Unfrozen) { + SnackbarMessage(resourceReference(R.string.tangem_pay_unfreeze_card_success)) + } else { + SnackbarMessage(resourceReference(R.string.tangem_pay_unfreeze_card_failed)) + } + uiMessageSender.send(message) + } + } + } + + private fun subscribeToCardFrozenState() { + cardDetailsRepository + .cardFrozenState(params.config.cardId) + .onEach { state -> currentFrozenState = state } + .launchIn(modelScope) + } + + private fun fetchAddToWalletBanner() { + modelScope.launch { + val isDone = cardDetailsRepository.isAddToWalletDone(params.userWalletId).getOrNull() == true + if (!isDone) { + uiState.update { state -> + state.copy( + addToWalletBlockState = AddToWalletBlockState( + onClick = ::onClickAddToWallet, + onClickClose = ::onClickCloseBanner, + ), + ) + } + } + }.saveIn(addToWalletBannerJobHolder) + } + + private fun onClickAddToWallet() { + router.push(TangemPayDetailsInnerRoute.AddToWallet) + } + + private fun onClickCloseBanner() { + modelScope.launch { + cardDetailsRepository.setAddToWalletAsDone(params.userWalletId) + uiState.update { it.copy(addToWalletBlockState = null) } + }.saveIn(addToWalletBannerJobHolder) + } + + override fun onClickChangePin() { + bottomSheetNavigation.dismiss() + router.push(TangemPayDetailsInnerRoute.ChangePIN) + } + + override fun onDismissViewPin() { + bottomSheetNavigation.dismiss() + } +} \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardPageScreen.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardPageScreen.kt new file mode 100644 index 0000000000..20a8d78463 --- /dev/null +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayCardPageScreen.kt @@ -0,0 +1,182 @@ +package com.tangem.features.tangempay.ui + +import android.content.res.Configuration +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.exclude +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.navigationBars +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.foundation.layout.systemBars +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material3.Scaffold +import androidx.compose.material3.ScaffoldDefaults +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.util.fastForEach +import com.tangem.core.ui.components.appbar.AppBarWithBackButton +import com.tangem.core.ui.extensions.stringResourceSafe +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.domain.visa.model.TangemPayCardFrozenState +import com.tangem.features.tangempay.components.cardDetails.PreviewTangemPayCardDetailsBlockComponent +import com.tangem.features.tangempay.components.cardDetails.TangemPayCardDetailsBlockComponent +import com.tangem.features.tangempay.details.impl.R +import com.tangem.features.tangempay.entity.TangemPayCardDetailsUM +import com.tangem.features.tangempay.entity.TangemPayCardPageSetting +import com.tangem.features.tangempay.entity.TangemPayCardPageUM +import kotlinx.collections.immutable.ImmutableList + +@Composable +internal fun TangemPayCardPageScreen( + state: TangemPayCardPageUM, + cardDetailsBlockComponent: TangemPayCardDetailsBlockComponent, + cardDetailsState: TangemPayCardDetailsUM, + modifier: Modifier = Modifier, +) { + Scaffold( + modifier = modifier, + topBar = { + AppBarWithBackButton( + modifier = Modifier.statusBarsPadding(), + onBackClick = state.onBackClick, + ) + }, + contentWindowInsets = ScaffoldDefaults.contentWindowInsets.exclude(WindowInsets.navigationBars), + containerColor = TangemTheme.colors.background.secondary, + ) { scaffoldPaddings -> + val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() } + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(scaffoldPaddings), + contentPadding = PaddingValues( + start = TangemTheme.dimens.spacing16, + end = TangemTheme.dimens.spacing16, + bottom = TangemTheme.dimens.spacing16 + bottomBarHeight, + ), + verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing16), + ) { + item(key = "Card") { + cardDetailsBlockComponent.CardDetailsBlockContent( + modifier = Modifier.padding(top = TangemTheme.dimens.spacing8), + state = cardDetailsState, + ) + } + if (state.addToWalletBlockState != null) { + item(key = "GooglePay") { + TangemPayAddToWalletBlock( + state = state.addToWalletBlockState, + ) + } + } + item(key = "Settings") { + TangemPayCardPageSettingsBlock( + settings = state.settings, + onSettingClick = state.onSettingClick, + ) + } + } + } +} + +@Composable +private fun TangemPayCardPageSettingsBlock( + settings: ImmutableList, + onSettingClick: (TangemPayCardPageSetting) -> Unit, + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier + .fillMaxWidth() + .background( + color = TangemTheme.colors.background.primary, + shape = TangemTheme.shapes.roundedCornersMedium, + ), + ) { + Text( + modifier = Modifier.padding( + start = TangemTheme.dimens.spacing12, + top = TangemTheme.dimens.spacing12, + bottom = TangemTheme.dimens.spacing4, + ), + text = stringResourceSafe(R.string.tangempay_card_page_settings_title), + style = TangemTheme.typography.subtitle2, + color = TangemTheme.colors.text.tertiary, + ) + settings.fastForEach { item -> + TangemPayCardPageSettingRow( + item = item, + onClick = { onSettingClick(item) }, + ) + } + } +} + +@Composable +private fun TangemPayCardPageSettingRow( + item: TangemPayCardPageSetting, + onClick: () -> Unit, + modifier: Modifier = Modifier, +) { + Box( + modifier = modifier + .fillMaxWidth() + .clickable(onClick = onClick) + .padding(TangemTheme.dimens.spacing12), + contentAlignment = Alignment.CenterStart, + ) { + Text( + text = stringResourceSafe(item.titleRes), + style = TangemTheme.typography.subtitle1, + color = TangemTheme.colors.text.primary1, + ) + } +} + +private val TangemPayCardPageSetting.titleRes + get() = when (this) { + TangemPayCardPageSetting.ChangePIN -> R.string.tangempay_card_details_change_pin + TangemPayCardPageSetting.FreezeCard -> R.string.tangempay_card_details_freeze_card + TangemPayCardPageSetting.ReplaceCard -> R.string.common_error // TODO v_rodionov #[REDACTED_TASK_KEY] + } + +@Preview +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun preview() = TangemThemePreview { + TangemPayCardPageScreen( + state = TangemPayCardPageUM.stub(), + cardDetailsBlockComponent = PreviewTangemPayCardDetailsBlockComponent( + TangemPayCardDetailsUM( + number = "•••• •••• •••• 1245", + numberShort = "··1245", + expiry = "••/••", + cvv = "•••", + onCopy = { _, _ -> }, + onClick = {}, + cardFrozenState = TangemPayCardFrozenState.Unfrozen, + ), + ), + cardDetailsState = TangemPayCardDetailsUM( + number = "•••• •••• •••• 1245", + numberShort = "··1245", + expiry = "••/••", + cvv = "•••", + onCopy = { _, _ -> }, + onClick = {}, + cardFrozenState = TangemPayCardFrozenState.Unfrozen, + ), + ) +} \ No newline at end of file