diff --git a/common/ui/src/main/java/com/tangem/common/ui/navigationButtons/NavigationButtonsState.kt b/common/ui/src/main/java/com/tangem/common/ui/navigationButtons/NavigationButtonsState.kt index cb7a3743ec..c534f12308 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/navigationButtons/NavigationButtonsState.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/navigationButtons/NavigationButtonsState.kt @@ -19,9 +19,9 @@ sealed class NavigationButtonsState { data class NavigationButton( val textReference: TextReference, @DrawableRes val iconRes: Int? = null, - val isSecondary: Boolean, - val isIconVisible: Boolean, - val showProgress: Boolean, - val isEnabled: Boolean, + val isSecondary: Boolean = false, + val isIconVisible: Boolean = false, + val showProgress: Boolean = false, + val isEnabled: Boolean = true, val onClick: () -> Unit, ) \ No newline at end of file diff --git a/core/ui/src/main/res/drawable/img_card_visa.webp b/core/ui/src/main/res/drawable/img_card_visa.webp new file mode 100644 index 0000000000..bd2804ca99 Binary files /dev/null and b/core/ui/src/main/res/drawable/img_card_visa.webp differ diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/DefaultOnboardingVisaComponent.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/DefaultOnboardingVisaComponent.kt index fe903926b8..67982e4535 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/DefaultOnboardingVisaComponent.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/DefaultOnboardingVisaComponent.kt @@ -16,7 +16,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch @Suppress("UnusedPrivateMember") -class DefaultOnboardingVisaComponent @AssistedInject constructor( +internal class DefaultOnboardingVisaComponent @AssistedInject constructor( @Assisted appComponentContext: AppComponentContext, @Assisted private val params: OnboardingVisaComponent.Params, ) : OnboardingVisaComponent, AppComponentContext by appComponentContext { diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/accesscode/OnboardingVisaAccessCodeComponent.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/accesscode/OnboardingVisaAccessCodeComponent.kt index 2c3e0eb8dd..0a5bb21947 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/accesscode/OnboardingVisaAccessCodeComponent.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/accesscode/OnboardingVisaAccessCodeComponent.kt @@ -9,7 +9,7 @@ import com.tangem.core.ui.decompose.ComposableContentComponent import com.tangem.features.onboarding.v2.visa.impl.child.accesscode.model.OnboardingVisaAccessCodeModel import kotlinx.coroutines.flow.SharedFlow -class OnboardingVisaAccessCodeComponent( +internal class OnboardingVisaAccessCodeComponent( appComponentContext: AppComponentContext, private val params: Params, ) : ComposableContentComponent, AppComponentContext by appComponentContext { diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/accesscode/model/OnboardingVisaAccessCodeModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/accesscode/model/OnboardingVisaAccessCodeModel.kt index 678c620c27..d75af43b85 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/accesscode/model/OnboardingVisaAccessCodeModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/accesscode/model/OnboardingVisaAccessCodeModel.kt @@ -10,7 +10,7 @@ import javax.inject.Inject @Stable @ComponentScoped -class OnboardingVisaAccessCodeModel @Inject constructor( +internal class OnboardingVisaAccessCodeModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val paramsContainer: ParamsContainer, ) : Model() { diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/accesscode/ui/OnboardingVisaAccessCode.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/accesscode/ui/OnboardingVisaAccessCode.kt new file mode 100644 index 0000000000..cf16e457eb --- /dev/null +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/accesscode/ui/OnboardingVisaAccessCode.kt @@ -0,0 +1,167 @@ +package com.tangem.features.onboarding.v2.visa.impl.child.accesscode.ui + +import androidx.compose.animation.AnimatedContent +import androidx.compose.foundation.layout.* +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.text.input.VisualTransformation +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.tangem.common.ui.navigationButtons.NavigationButton +import com.tangem.common.ui.navigationButtons.NavigationPrimaryButton +import com.tangem.core.ui.components.OutlineTextFieldWithIcon +import com.tangem.core.ui.components.SpacerH +import com.tangem.core.ui.components.SpacerH16 +import com.tangem.core.ui.components.SpacerH32 +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.res.TangemAnimations +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.features.onboarding.v2.impl.R +import com.tangem.features.onboarding.v2.visa.impl.child.accesscode.ui.state.OnboardingVisaAccessCodeUM +import kotlinx.coroutines.delay + +@Composable +internal fun OnboardingVisaAccessCode(state: OnboardingVisaAccessCodeUM, modifier: Modifier = Modifier) { + Column( + modifier + .fillMaxSize() + .navigationBarsPadding(), + ) { + AnimatedContent( + modifier = Modifier + .padding(top = 48.dp) + .weight(1f), + targetState = state.step, + transitionSpec = TangemAnimations.AnimatedContent + .slide { initial, target -> initial.ordinal < target.ordinal }, + ) { step -> + Content( + state = state, + reEnterAccessCodeState = step == OnboardingVisaAccessCodeUM.Step.ReEnter, + ) + } + + SpacerH(20.dp) + + NavigationPrimaryButton( + modifier = Modifier + .padding(start = 16.dp, end = 16.dp, bottom = 16.dp) + .imePadding(), + primaryButton = NavigationButton( + textReference = when (state.step) { + OnboardingVisaAccessCodeUM.Step.Enter -> resourceReference(R.string.common_continue) + OnboardingVisaAccessCodeUM.Step.ReEnter -> + resourceReference(R.string.onboarding_create_wallet_button_create_wallet) + }, + onClick = state.onContinue, + iconRes = R.drawable.ic_tangem_24, + isIconVisible = state.step == OnboardingVisaAccessCodeUM.Step.ReEnter, + ), + ) + } +} + +@Suppress("LongMethod") +@Composable +private fun Content( + state: OnboardingVisaAccessCodeUM, + reEnterAccessCodeState: Boolean, + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Text( + modifier = Modifier + .padding(horizontal = 32.dp), + text = if (reEnterAccessCodeState) { + "Re-enter your access code" // TODO + } else { + "Create access code" // TODO + }, + style = TangemTheme.typography.h2, + color = TangemTheme.colors.text.primary1, + textAlign = TextAlign.Center, + ) + + SpacerH16() + + // TODO + Text( + modifier = Modifier + .padding(horizontal = 32.dp), + text = "The access code will be used manage your payment account and protect it from unauthorized access", + style = TangemTheme.typography.body1, + color = TangemTheme.colors.text.secondary, + textAlign = TextAlign.Center, + ) + + SpacerH32() + + val focusRequester = remember { FocusRequester() } + + OutlineTextFieldWithIcon( + modifier = modifier + .padding(horizontal = 16.dp) + .focusRequester(focusRequester) + .fillMaxWidth(), + iconResId = if (state.accessCodeHidden) { + R.drawable.ic_eye_outline_24 + } else { + R.drawable.ic_eye_off_outline_24 + }, + iconColor = TangemTheme.colors.icon.primary1, + onIconClick = state.onAccessCodeHideClick, + value = if (reEnterAccessCodeState) { + state.accessCodeSecond + } else { + state.accessCodeFirst + }, + onValueChange = if (reEnterAccessCodeState) { + state.onAccessCodeSecondChange + } else { + state.onAccessCodeFirstChange + }, + label = stringResource(id = R.string.onboarding_wallet_info_title_third), + isError = state.codesNotMatchError || state.atLeast4CharError, + visualTransformation = if (state.accessCodeHidden) { + PasswordVisualTransformation() + } else { + VisualTransformation.None + }, + caption = when { + state.codesNotMatchError && reEnterAccessCodeState -> + stringResource(R.string.onboarding_access_codes_doesnt_match) + state.atLeast4CharError && !reEnterAccessCodeState -> + stringResource(R.string.onboarding_access_code_too_short) + else -> null + }, + ) + + LaunchedEffect(Unit) { + delay(timeMillis = 200) + focusRequester.requestFocus() + } + } +} + +@Preview(showBackground = true) +@Composable +private fun Preview() { + TangemThemePreview { + OnboardingVisaAccessCode( + state = OnboardingVisaAccessCodeUM(), + ) + } +} \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/accesscode/ui/state/OnboardingVisaAccessCodeUM.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/accesscode/ui/state/OnboardingVisaAccessCodeUM.kt new file mode 100644 index 0000000000..68719daa53 --- /dev/null +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/accesscode/ui/state/OnboardingVisaAccessCodeUM.kt @@ -0,0 +1,20 @@ +package com.tangem.features.onboarding.v2.visa.impl.child.accesscode.ui.state + +import androidx.compose.ui.text.input.TextFieldValue + +data class OnboardingVisaAccessCodeUM( + val step: Step = Step.Enter, + val accessCodeFirst: TextFieldValue = TextFieldValue(""), + val accessCodeSecond: TextFieldValue = TextFieldValue(""), + val codesNotMatchError: Boolean = false, + val atLeast4CharError: Boolean = false, + val accessCodeHidden: Boolean = true, + val onAccessCodeFirstChange: (TextFieldValue) -> Unit = {}, + val onAccessCodeSecondChange: (TextFieldValue) -> Unit = {}, + val onContinue: () -> Unit = {}, + val onAccessCodeHideClick: () -> Unit = {}, +) { + enum class Step { + Enter, ReEnter + } +} \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/welcome/OnboardingVisaWelcomeComponent.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/welcome/OnboardingVisaWelcomeComponent.kt index 8dab8ddac4..0194489e69 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/welcome/OnboardingVisaWelcomeComponent.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/welcome/OnboardingVisaWelcomeComponent.kt @@ -6,8 +6,10 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.features.onboarding.v2.visa.impl.child.welcome.ui.OnboardingVisaWelcome +import com.tangem.features.onboarding.v2.visa.impl.child.welcome.ui.state.OnboardingVisaWelcomeUM -class OnboardingVisaWelcomeComponent( +internal class OnboardingVisaWelcomeComponent( appComponentContext: AppComponentContext, private val params: Params, ) : ComposableContentComponent, AppComponentContext by appComponentContext { @@ -15,9 +17,15 @@ class OnboardingVisaWelcomeComponent( @Composable override fun Content(modifier: Modifier) { BackHandler(onBack = remember(this) { { params.onBack() } }) + + OnboardingVisaWelcome( + modifier = modifier, + state = OnboardingVisaWelcomeUM(), + ) } data class Params( val onBack: () -> Unit, + val startActivation: () -> Unit, ) } \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/welcome/ui/OnboardingVisaWelcome.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/welcome/ui/OnboardingVisaWelcome.kt new file mode 100644 index 0000000000..61c2b6e0d8 --- /dev/null +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/welcome/ui/OnboardingVisaWelcome.kt @@ -0,0 +1,124 @@ +package com.tangem.features.onboarding.v2.visa.impl.child.welcome.ui + +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.layout.* +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import coil.compose.AsyncImage +import com.tangem.core.ui.components.PrimaryButton +import com.tangem.core.ui.components.PrimaryButtonIconEnd +import com.tangem.core.ui.components.SpacerH +import com.tangem.core.ui.components.SpacerH12 +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.features.onboarding.v2.impl.R +import com.tangem.features.onboarding.v2.visa.impl.child.welcome.ui.state.OnboardingVisaWelcomeUM + +@Composable +internal fun OnboardingVisaWelcome(state: OnboardingVisaWelcomeUM, modifier: Modifier = Modifier) { + Column( + modifier = modifier + .fillMaxSize() + .navigationBarsPadding(), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Column( + Modifier + .padding( + top = 20.dp, + bottom = 32.dp, + start = 32.dp, + end = 32.dp, + ) + .fillMaxSize() + .weight(1f), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Artwork() + + SpacerH(50.dp) + + Text( + text = when (state.mode) { + OnboardingVisaWelcomeUM.Mode.Hello -> "Hello, ${state.userName}!" + OnboardingVisaWelcomeUM.Mode.WelcomeBack -> "Welcome back, ${state.userName}!" + }, + style = TangemTheme.typography.h2, + color = TangemTheme.colors.text.primary1, + ) + + SpacerH12() + + Text( + text = when (state.mode) { + OnboardingVisaWelcomeUM.Mode.Hello -> "bla bla bla //TODO" + OnboardingVisaWelcomeUM.Mode.WelcomeBack -> "bla bla bla? //TODO" + }, + style = TangemTheme.typography.body1, + color = TangemTheme.colors.text.secondary, + ) + } + + when (state.mode) { + OnboardingVisaWelcomeUM.Mode.Hello -> { + PrimaryButton( + modifier = Modifier + .padding(start = 16.dp, end = 16.dp, bottom = 16.dp) + .fillMaxWidth(), + text = "Start Activation", + onClick = state.onContinueClick, + ) + } + OnboardingVisaWelcomeUM.Mode.WelcomeBack -> { + PrimaryButtonIconEnd( + modifier = Modifier + .padding(start = 16.dp, end = 16.dp, bottom = 16.dp) + .fillMaxWidth(), + text = "Start Activation", + iconResId = R.drawable.ic_tangem_24, + onClick = state.onContinueClick, + ) + } + } + } +} + +@Composable +fun Artwork(modifier: Modifier = Modifier) { + Box(modifier) { + val circleColor = TangemTheme.colors.background.secondary + + Canvas( + modifier = Modifier + .align(Alignment.Center) + .size(254.dp) + .fillMaxSize(), + ) { + drawCircle( + color = circleColor, + radius = size.width / 2, + center = center, + ) + } + + AsyncImage( + model = R.drawable.img_card_visa, + contentDescription = null, + modifier = Modifier + .align(Alignment.Center) + .size(128.dp), // Adjust the size as needed + ) + } +} + +@Preview(showBackground = true) +@Composable +private fun Preview() { + TangemThemePreview { + OnboardingVisaWelcome(state = OnboardingVisaWelcomeUM()) + } +} \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/welcome/ui/state/OnboardingVisaWelcomeUM.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/welcome/ui/state/OnboardingVisaWelcomeUM.kt new file mode 100644 index 0000000000..9e1f6ba81b --- /dev/null +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/welcome/ui/state/OnboardingVisaWelcomeUM.kt @@ -0,0 +1,11 @@ +package com.tangem.features.onboarding.v2.visa.impl.child.welcome.ui.state + +internal data class OnboardingVisaWelcomeUM( + val mode: Mode = Mode.Hello, + val userName: String = "", + val onContinueClick: () -> Unit = {}, +) { + enum class Mode { + Hello, WelcomeBack + } +} \ No newline at end of file