diff --git a/app/src/main/java/com/kickstarter/features/pledgeredemption/ui/PledgeRedemptionActivity.kt b/app/src/main/java/com/kickstarter/features/pledgeredemption/ui/PledgeRedemptionActivity.kt index b80947cfc0..c739ad5138 100644 --- a/app/src/main/java/com/kickstarter/features/pledgeredemption/ui/PledgeRedemptionActivity.kt +++ b/app/src/main/java/com/kickstarter/features/pledgeredemption/ui/PledgeRedemptionActivity.kt @@ -5,6 +5,7 @@ import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.viewModels import com.kickstarter.features.pledgeredemption.viewmodels.PledgeRedemptionViewModel +import com.kickstarter.libs.featureflag.FlagKey import com.kickstarter.libs.utils.extensions.getEnvironment import com.kickstarter.libs.utils.extensions.isDarkModeEnabled import com.kickstarter.mock.factories.RewardFactory @@ -35,6 +36,7 @@ class PledgeRedemptionActivity : ComponentActivity() { val shippingAmount = backing.shippingAmount().toDouble() val totalAmount = backing.amount() val bonus = backing.bonusAmount() + val pledgeReason = PledgeReason.PLEDGE backing.reward()?.let { lists.add(it) } backing.addOns()?.map { lists.add(it) } @@ -42,7 +44,12 @@ class PledgeRedemptionActivity : ComponentActivity() { val darModeEnabled = this.isDarkModeEnabled(env = requireNotNull(env)) KickstarterApp(useDarkTheme = darModeEnabled) { CheckoutScreen( - rewardsList = lists.map { Pair(it.title() ?: "", it.pledgeAmount().toString()) }, + rewardsList = lists.map { + Pair( + it.title() ?: "", + it.pledgeAmount().toString() + ) + }, environment = env, shippingAmount = shippingAmount, selectedReward = RewardFactory.rewardWithShipping(), @@ -52,12 +59,14 @@ class PledgeRedemptionActivity : ComponentActivity() { storedCards = emptyList(), project = project, email = "example@example.com", - pledgeReason = PledgeReason.PLEDGE, + pledgeReason = pledgeReason, rewardsHaveShippables = true, onPledgeCtaClicked = { }, newPaymentMethodClicked = { }, onDisclaimerItemClicked = {}, - onAccountabilityLinkClicked = {} + onAccountabilityLinkClicked = {}, + isPlotEnabled = env.featureFlagClient() + ?.getBoolean(FlagKey.ANDROID_PLEDGE_OVER_TIME) ?: false, ) } } diff --git a/app/src/main/java/com/kickstarter/ui/activities/compose/projectpage/CheckoutScreen.kt b/app/src/main/java/com/kickstarter/ui/activities/compose/projectpage/CheckoutScreen.kt index 4ffda7dac3..f1c3ddd4ad 100644 --- a/app/src/main/java/com/kickstarter/ui/activities/compose/projectpage/CheckoutScreen.kt +++ b/app/src/main/java/com/kickstarter/ui/activities/compose/projectpage/CheckoutScreen.kt @@ -1,5 +1,6 @@ package com.kickstarter.ui.activities.compose.projectpage +import CollectionPlan import android.content.res.Configuration import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -121,11 +122,55 @@ fun CheckoutScreenPreview() { newPaymentMethodClicked = { }, onDisclaimerItemClicked = {}, onAccountabilityLinkClicked = {}, - onChangedPaymentMethod = {} + onChangedPaymentMethod = {}, + isPlotEnabled = false ) } } +@Composable +@Preview(name = "Light", uiMode = Configuration.UI_MODE_NIGHT_NO) +@Preview(name = "Dark", uiMode = Configuration.UI_MODE_NIGHT_YES) +fun CheckoutScreenisPlotEnabledPreview() { + KSTheme { + CheckoutScreen( + rewardsList = (1..6).map { + Pair("Cool Item $it", "$20") + }, + environment = Environment.Builder().build(), + shippingAmount = 4.0, + selectedReward = RewardFactory.rewardWithShipping(), + currentShippingRule = ShippingRule.builder().build(), + totalAmount = 60.0, + totalBonusSupport = 5.0, + storedCards = listOf( + StoredCardFactory.visa(), StoredCardFactory.discoverCard(), StoredCardFactory.visa() + ), + project = + Project.builder() + .currency("USD") + .currentCurrency("USD") + .state(Project.STATE_LIVE) + .availableCardTypes( + listOf( + CreditCardTypes.AMEX.rawValue(), + CreditCardTypes.MASTERCARD.rawValue(), + CreditCardTypes.VISA.rawValue() + ) + ) + .build(), + email = "example@example.com", + pledgeReason = PledgeReason.PLEDGE, + rewardsHaveShippables = true, + onPledgeCtaClicked = { }, + newPaymentMethodClicked = { }, + onDisclaimerItemClicked = {}, + onAccountabilityLinkClicked = {}, + onChangedPaymentMethod = {}, + isPlotEnabled = true + ) + } +} @Composable fun CheckoutScreen( storedCards: List = listOf(), @@ -148,7 +193,7 @@ fun CheckoutScreen( onDisclaimerItemClicked: (disclaimerItem: DisclaimerItems) -> Unit, onAccountabilityLinkClicked: () -> Unit, onChangedPaymentMethod: (StoredCard?) -> Unit = {}, - plotSelected: Boolean = false, + isPlotEnabled: Boolean ) { val selectedOption = remember { mutableStateOf( @@ -328,8 +373,33 @@ fun CheckoutScreen( style = typography.title3Bold, color = colors.kds_black, ) + Spacer(modifier = Modifier.height(dimensions.paddingMediumSmall)) + if (isPlotEnabled) { + Text( + modifier = Modifier.padding( + start = dimensions.paddingMediumLarge, + end = dimensions.paddingMediumLarge + ), + text = stringResource(id = R.string.fpo_collection_plan), + style = typography.headline, + color = colors.kds_black, + ) + Spacer(modifier = Modifier.height(dimensions.paddingMediumSmall)) + CollectionPlan(isEligible = true) + Spacer(modifier = Modifier.height(dimensions.paddingMediumSmall)) + Text( + modifier = Modifier.padding( + start = dimensions.paddingMediumLarge, + end = dimensions.paddingMediumLarge + ), + text = stringResource(id = R.string.fpo_payment), + style = typography.headline, + color = colors.kds_black, + ) + Spacer(modifier = Modifier.height(dimensions.paddingMediumSmall)) + } storedCards.forEachIndexed { index, card -> val isAvailable = project.acceptedCardType(card.type()) || card.isFromPaymentSheet() @@ -495,7 +565,7 @@ fun CheckoutScreen( totalBonusSupport = totalBonusSupportString, deliveryDateString = deliveryDateString, rewardsHaveShippables = rewardsHaveShippables, - disclaimerText = if (plotSelected) plotDisclaimerText else disclaimerText, + disclaimerText = if (isPlotEnabled) plotDisclaimerText else disclaimerText, plotSelected = false ) } else { @@ -506,7 +576,7 @@ fun CheckoutScreen( initialBonusSupport = initialBonusSupportString, totalBonusSupport = totalAmountString, shippingAmount = shippingAmount, - disclaimerText = if (plotSelected) plotDisclaimerText else disclaimerText, + disclaimerText = if (isPlotEnabled) plotDisclaimerText else disclaimerText, plotSelected = false ) } diff --git a/app/src/main/java/com/kickstarter/ui/activities/compose/projectpage/ProjectPledgeButtonAndFragmentContainer.kt b/app/src/main/java/com/kickstarter/ui/activities/compose/projectpage/ProjectPledgeButtonAndFragmentContainer.kt index e2f992aeeb..ba006a537c 100644 --- a/app/src/main/java/com/kickstarter/ui/activities/compose/projectpage/ProjectPledgeButtonAndFragmentContainer.kt +++ b/app/src/main/java/com/kickstarter/ui/activities/compose/projectpage/ProjectPledgeButtonAndFragmentContainer.kt @@ -291,7 +291,8 @@ fun ProjectPledgeButtonAndFragmentContainer( newPaymentMethodClicked = onAddPaymentMethodClicked, isLoading = isLoading, onDisclaimerItemClicked = onDisclaimerItemClicked, - onAccountabilityLinkClicked = onAccountabilityLinkClicked + onAccountabilityLinkClicked = onAccountabilityLinkClicked, + isPlotEnabled = false, ) } } diff --git a/app/src/main/java/com/kickstarter/ui/fragments/CrowdfundCheckoutFragment.kt b/app/src/main/java/com/kickstarter/ui/fragments/CrowdfundCheckoutFragment.kt index e4ad4c6d28..e63adf9858 100644 --- a/app/src/main/java/com/kickstarter/ui/fragments/CrowdfundCheckoutFragment.kt +++ b/app/src/main/java/com/kickstarter/ui/fragments/CrowdfundCheckoutFragment.kt @@ -11,6 +11,7 @@ import androidx.fragment.app.viewModels import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.kickstarter.R import com.kickstarter.databinding.FragmentCrowdfundCheckoutBinding +import com.kickstarter.libs.featureflag.FlagKey import com.kickstarter.libs.utils.RewardUtils import com.kickstarter.libs.utils.extensions.getEnvironment import com.kickstarter.libs.utils.extensions.getPaymentSheetConfiguration @@ -44,7 +45,11 @@ class CrowdfundCheckoutFragment : Fragment() { private lateinit var flowController: PaymentSheet.FlowController - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { super.onCreateView(inflater, container, savedInstanceState) binding = FragmentCrowdfundCheckoutBinding.inflate(inflater, container, false) @@ -58,7 +63,11 @@ class CrowdfundCheckoutFragment : Fragment() { viewModel.provideErrorAction { message -> activity?.runOnUiThread { - showErrorToast(context, this, message ?: getString(R.string.general_error_something_wrong)) + showErrorToast( + context, + this, + message ?: getString(R.string.general_error_something_wrong) + ) } } @@ -70,9 +79,10 @@ class CrowdfundCheckoutFragment : Fragment() { useDarkTheme = true ) { - val checkoutStates = viewModel.crowdfundCheckoutUIState.collectAsStateWithLifecycle( - initialValue = CheckoutUIState() - ).value + val checkoutStates = + viewModel.crowdfundCheckoutUIState.collectAsStateWithLifecycle( + initialValue = CheckoutUIState() + ).value val rwList = checkoutStates.selectedRewards val email = checkoutStates.userEmail @@ -88,10 +98,12 @@ class CrowdfundCheckoutFragment : Fragment() { val project = pledgeData?.projectData()?.project() ?: Project.builder().build() val selectedRw = pledgeData?.reward() ?: Reward.builder().build() - val checkoutSuccess = viewModel.checkoutResultState.collectAsStateWithLifecycle().value + val checkoutSuccess = + viewModel.checkoutResultState.collectAsStateWithLifecycle().value val id = checkoutSuccess.first?.id() ?: -1 - val paymentSheetPresenter = viewModel.presentPaymentSheetStates.collectAsStateWithLifecycle().value + val paymentSheetPresenter = + viewModel.presentPaymentSheetStates.collectAsStateWithLifecycle().value val setUpIntent = paymentSheetPresenter.setupClientId configurePaymentSheet(paymentSheetPresenter.setupClientId) @@ -104,7 +116,9 @@ class CrowdfundCheckoutFragment : Fragment() { LaunchedEffect(id) { if (id > 0) { if (pledgeReason == PledgeReason.PLEDGE) - (activity as PledgeDelegate?)?.pledgeSuccessfullyCreated(checkoutSuccess) + (activity as PledgeDelegate?)?.pledgeSuccessfullyCreated( + checkoutSuccess + ) if (pledgeReason == PledgeReason.UPDATE_PAYMENT) (activity as PledgeDelegate?)?.pledgePaymentSuccessfullyUpdated() if (pledgeReason == PledgeReason.UPDATE_REWARD || pledgeReason == PledgeReason.UPDATE_PLEDGE || pledgeReason == PledgeReason.FIX_PLEDGE) @@ -140,7 +154,9 @@ class CrowdfundCheckoutFragment : Fragment() { onAccountabilityLinkClicked = {}, onChangedPaymentMethod = { paymentMethodSelected -> viewModel.userChangedPaymentMethodSelected(paymentMethodSelected) - } + }, + isPlotEnabled = environment.featureFlagClient() + ?.getBoolean(FlagKey.ANDROID_PLEDGE_OVER_TIME) ?: false && pledgeReason == PledgeReason.PLEDGE, ) } } @@ -207,16 +223,19 @@ class CrowdfundCheckoutFragment : Fragment() { } } } + is PaymentSheetResult.Failed -> { binding?.composeView?.let { view -> context?.let { - val errorMessage = paymentSheetResult.error.localizedMessage ?: getString(R.string.general_error_something_wrong) + val errorMessage = paymentSheetResult.error.localizedMessage + ?: getString(R.string.general_error_something_wrong) activity?.runOnUiThread { showErrorToast(it, view, errorMessage) } } } } + is PaymentSheetResult.Completed -> { } } diff --git a/app/src/main/java/com/kickstarter/ui/views/compose/checkout/CollectionPlan.kt b/app/src/main/java/com/kickstarter/ui/views/compose/checkout/CollectionPlan.kt index a59ac463de..fb820530c2 100644 --- a/app/src/main/java/com/kickstarter/ui/views/compose/checkout/CollectionPlan.kt +++ b/app/src/main/java/com/kickstarter/ui/views/compose/checkout/CollectionPlan.kt @@ -104,7 +104,7 @@ fun CollectionPlan( ) { var selectedOption by remember { mutableStateOf(initialSelectedOption) } - Column(modifier = Modifier.fillMaxWidth()) { + Column(modifier = Modifier.padding(start = dimensions.paddingMedium, end = dimensions.paddingMedium)) { PledgeOption( optionText = stringResource(id = R.string.fpo_pledge_in_full), selected = selectedOption == CollectionOptions.PLEDGE_IN_FULL.name, @@ -144,7 +144,7 @@ fun PledgeOption( .clip(RoundedCornerShape(dimensions.radiusSmall)) .background(colors.kds_white) .clickable(enabled = isSelectable, onClick = onSelect) - .padding(end = dimensions.paddingSmall, bottom = dimensions.paddingSmall) + .padding(bottom = dimensions.paddingSmall, end = dimensions.paddingMedium) .semantics { this.selected = selected } .then( if (!isSelectable) Modifier.padding(