Skip to content

Commit

Permalink
PAY-1521: Pledge Screen show localReceiptLocation UI (#1617)
Browse files Browse the repository at this point in the history
  • Loading branch information
Arkariang authored Apr 28, 2022
1 parent f22a70b commit 9bbd295
Show file tree
Hide file tree
Showing 9 changed files with 483 additions and 4 deletions.
15 changes: 15 additions & 0 deletions app/src/main/java/com/kickstarter/ui/fragments/PledgeFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import com.kickstarter.ui.itemdecorations.RewardCardItemDecoration
import com.kickstarter.viewmodels.PledgeFragmentViewModel
import com.stripe.android.ApiResultCallback
import com.stripe.android.SetupIntentResult
import rx.android.schedulers.AndroidSchedulers

@RequiresFragmentViewModel(PledgeFragmentViewModel.ViewModel::class)
class PledgeFragment :
Expand Down Expand Up @@ -550,6 +551,20 @@ class PledgeFragment :
binding?.pledgeSectionRewardSummary?.pledgeHeaderTitleNoReward ?.text = it
}

this.viewModel.outputs.localPickUpIsGone()
.compose(bindToLifecycle())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
this.binding?.pledgeSectionPickupLocation?.localPickupContainer?.setGone(it)
}

this.viewModel.outputs.localPickUpName()
.compose(bindToLifecycle())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
this.binding?.pledgeSectionPickupLocation?.localPickupLocationName?.text = it
}

binding?.pledgeSectionPledgeAmount?. pledgeAmount?.setOnTouchListener { _, _ ->
binding?.pledgeSectionPledgeAmount?. pledgeAmount?.post {
binding?.pledgeRoot?.let { pledgeRoot ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import com.kickstarter.databinding.ItemAddOnBinding
import com.kickstarter.libs.rx.transformers.Transformers.observeForUI
import com.kickstarter.libs.utils.RewardViewUtils
import com.kickstarter.libs.utils.ViewUtils
import com.kickstarter.libs.utils.extensions.setGone
import com.kickstarter.models.Reward
import com.kickstarter.ui.adapters.RewardItemsAdapter
import com.kickstarter.ui.data.ProjectData
import com.kickstarter.viewmodels.AddOnViewHolderViewModel
import rx.android.schedulers.AndroidSchedulers

class AddOnViewHolder(private val binding: ItemAddOnBinding) : KSViewHolder(binding.root) {

Expand Down Expand Up @@ -89,6 +91,20 @@ class AddOnViewHolder(private val binding: ItemAddOnBinding) : KSViewHolder(bind
.compose(bindToLifecycle())
.compose(observeForUI())
.subscribe { binding.titleContainer.addOnTitleTextView.text = RewardViewUtils.styleTitleForAddOns(context(), it.first, it.second) }

this.viewModel.outputs.localPickUpIsGone()
.compose(bindToLifecycle())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
binding.rewardItemLocalPickupContainer.localPickupGroup.setGone(it)
}

this.viewModel.outputs.localPickUpName()
.compose(bindToLifecycle())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
binding.rewardItemLocalPickupContainer.localPickupLocation.text = it
}
}

override fun bindData(data: Any?) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import com.kickstarter.libs.ActivityViewModel
import com.kickstarter.libs.Environment
import com.kickstarter.libs.KSCurrency
import com.kickstarter.libs.models.Country
import com.kickstarter.libs.models.OptimizelyFeature
import com.kickstarter.libs.utils.ObjectUtils
import com.kickstarter.libs.utils.RewardUtils
import com.kickstarter.libs.utils.extensions.negate
import com.kickstarter.models.Project
Expand Down Expand Up @@ -62,6 +64,12 @@ interface AddOnViewHolderViewModel {

/** Emits a pait with the add on title and the quantity in order to build the stylized title */
fun titleForAddOn(): Observable<Pair<String, Int>>

/** Emits a boolean that determines if the local PickUp section should be hidden **/
fun localPickUpIsGone(): Observable<Boolean>

/** Emits the String with the Local Pickup Displayable name **/
fun localPickUpName(): Observable<String>
}

/**
Expand All @@ -86,6 +94,9 @@ interface AddOnViewHolderViewModel {
private val titleForReward = BehaviorSubject.create<String?>()
private val titleForAddOn = BehaviorSubject.create<Pair<String, Int>>()
private val titleIsGone = BehaviorSubject.create<Boolean>()
private val localPickUpIsGone = BehaviorSubject.create<Boolean>()
private val localPickUpName = BehaviorSubject.create<String>()
private val optimizely = environment.optimizely()

val inputs: Inputs = this
val outputs: Outputs = this
Expand Down Expand Up @@ -156,6 +167,26 @@ interface AddOnViewHolderViewModel {
.map { reward -> parametersForTitle(reward) }
.compose(bindToLifecycle())
.subscribe(this.titleForAddOn)

reward
.filter { !RewardUtils.isShippable(it) }
.map {
RewardUtils.isLocalPickup(it) && optimizely.isFeatureEnabled(
OptimizelyFeature.Key.ANDROID_LOCAL_PICKUP
)
}
.compose(bindToLifecycle())
.subscribe {
this.localPickUpIsGone.onNext(!it)
}

reward
.filter { !RewardUtils.isShippable(it) }
.filter { RewardUtils.isLocalPickup(it) }
.map { it.localReceiptLocation()?.displayableName() }
.filter { ObjectUtils.isNotNull(it) }
.compose(bindToLifecycle())
.subscribe(this.localPickUpName)
}

private fun getCurrency(it: Pair<Project, Reward>) =
Expand Down Expand Up @@ -198,5 +229,9 @@ interface AddOnViewHolderViewModel {
override fun titleForReward(): Observable<String?> = this.titleForReward

override fun titleForAddOn(): Observable<Pair<String, Int>> = this.titleForAddOn

override fun localPickUpIsGone(): Observable<Boolean> = localPickUpIsGone

override fun localPickUpName(): Observable<String> = localPickUpName
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.kickstarter.libs.FragmentViewModel
import com.kickstarter.libs.NumberOptions
import com.kickstarter.libs.models.Country
import com.kickstarter.libs.models.OptimizelyExperiment
import com.kickstarter.libs.models.OptimizelyFeature
import com.kickstarter.libs.rx.transformers.Transformers.combineLatestPair
import com.kickstarter.libs.rx.transformers.Transformers.errors
import com.kickstarter.libs.rx.transformers.Transformers.ignoreValues
Expand Down Expand Up @@ -323,6 +324,12 @@ interface PledgeFragmentViewModel {
fun changeCheckoutRiskMessageBottomSheetStatus(): Observable<Boolean>

fun changePledgeSectionAccountabilityFragmentVisiablity(): Observable<Boolean>

/** Emits a boolean that determines if the local PickUp section should be hidden **/
fun localPickUpIsGone(): Observable<Boolean>

/** Emits the String with the Local Pickup Displayable name **/
fun localPickUpName(): Observable<String>
}

class ViewModel(@NonNull val environment: Environment) : FragmentViewModel<PledgeFragment>(environment), Inputs, Outputs {
Expand Down Expand Up @@ -442,6 +449,9 @@ interface PledgeFragmentViewModel {

private var riskConfirmationFlag = BehaviorSubject.create(false)

private val localPickUpIsGone = BehaviorSubject.create<Boolean>()
private val localPickUpName = BehaviorSubject.create<String>()

val inputs: Inputs = this
val outputs: Outputs = this

Expand Down Expand Up @@ -623,6 +633,26 @@ interface PledgeFragmentViewModel {
.compose(bindToLifecycle())
.subscribe(this.rewardTitle)

this.selectedReward
.filter { !RewardUtils.isShippable(it) }
.map {
RewardUtils.isLocalPickup(it) && optimizely.isFeatureEnabled(
OptimizelyFeature.Key.ANDROID_LOCAL_PICKUP
)
}
.compose(bindToLifecycle())
.subscribe {
this.localPickUpIsGone.onNext(!it)
}

this.selectedReward
.filter { !RewardUtils.isShippable(it) }
.filter { RewardUtils.isLocalPickup(it) }
.map { it.localReceiptLocation()?.displayableName() }
.filter { ObjectUtils.isNotNull(it) }
.compose(bindToLifecycle())
.subscribe(this.localPickUpName)

this.selectedReward
.map { it.estimatedDeliveryOn() }
.filter { ObjectUtils.isNotNull(it) }
Expand Down Expand Up @@ -858,7 +888,7 @@ interface PledgeFragmentViewModel {
.distinctUntilChanged()

val isDigitalRw = this.selectedReward
.filter { RewardUtils.isDigital(it) }
.filter { RewardUtils.isDigital(it) || RewardUtils.isLocalPickup(it) }
.distinctUntilChanged()

// - Calculate total for Reward || Rewards + AddOns with Shipping location
Expand All @@ -874,13 +904,13 @@ interface PledgeFragmentViewModel {
.compose<Pair<Reward, String>>(combineLatestPair(this.pledgeInput.startWith("")))
.map { if (it.second.isNotEmpty()) NumberUtils.parse(it.second) else it.first.minimum() }

// - Calculate total for DigitalRewards || DigitalReward + DigitalAddOns
val totalDigital = Observable.combineLatest(isDigitalRw, pledgeAmountHeader, this.bonusAmount, pledgeReason) { _, pledgeAmount, bonusAmount, pReason ->
// - Calculate total for DigitalRewards || DigitalReward + DigitalAddOns || LocalPickup
val totalNoShipping = Observable.combineLatest(isDigitalRw, pledgeAmountHeader, this.bonusAmount, pledgeReason) { _, pledgeAmount, bonusAmount, pReason ->
return@combineLatest getAmountDigital(pledgeAmount, NumberUtils.parse(bonusAmount), pReason)
}
.distinctUntilChanged()

val total = Observable.merge(totalWShipping, totalNR, totalDigital)
val total = Observable.merge(totalWShipping, totalNR, totalNoShipping)

total
.compose<Pair<Double, Project>>(combineLatestPair(project))
Expand Down Expand Up @@ -1953,5 +1983,13 @@ interface PledgeFragmentViewModel {
@NonNull
override fun changePledgeSectionAccountabilityFragmentVisiablity(): Observable<Boolean> =
this.changePledgeSectionAccountabilityFragmentVisiablity

@NonNull
override fun localPickUpIsGone(): Observable<Boolean> =
localPickUpIsGone

@Override
override fun localPickUpName(): Observable<String> =
localPickUpName
}
}
3 changes: 3 additions & 0 deletions app/src/main/res/layout/fragment_pledge.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
android:paddingStart="@dimen/activity_vertical_margin"
android:paddingEnd="@dimen/activity_vertical_margin">

<include
android:id="@+id/pledge_section_pickup_location"
layout="@layout/fragment_pledge_section_local_pickup" />
<include
android:id="@+id/pledge_section_shipping"
layout="@layout/fragment_pledge_section_shipping" />
Expand Down
43 changes: 43 additions & 0 deletions app/src/main/res/layout/fragment_pledge_section_local_pickup.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/local_pickup_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/grid_2"
android:focusable="true"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="gone"
tools:visibility="visible"
tools:showIn="@layout/fragment_pledge">

<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/local_pickup_label_static"
style="@style/CalloutPrimaryMedium"
android:textColor="@color/kds_support_700"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/FPO_reward_location"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/local_pickup_location_name"
style="@style/CalloutPrimary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/grid_1"
android:layout_marginEnd="@dimen/grid_3"
android:ellipsize="end"
android:enabled="false"
android:hint="@string/Shipping"
android:maxLines="1"
android:textColor="@color/kds_support_400"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/local_pickup_label_static"
tools:text="Los Angeles, CA" />
</androidx.constraintlayout.widget.ConstraintLayout>
1 change: 1 addition & 0 deletions app/src/main/res/layout/item_add_on.xml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
tools:text="@string/Pledge_any_amount_to_help_bring_this_project_to_life" />

<include
android:id="@+id/reward_item_local_pickup_container"
layout="@layout/reward_item_local_pickup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import androidx.annotation.NonNull
import com.kickstarter.KSRobolectricTestCase
import com.kickstarter.R
import com.kickstarter.libs.Environment
import com.kickstarter.libs.models.OptimizelyFeature
import com.kickstarter.mock.MockExperimentsClientType
import com.kickstarter.mock.factories.ProjectDataFactory
import com.kickstarter.mock.factories.ProjectFactory
import com.kickstarter.mock.factories.RewardFactory
Expand All @@ -25,6 +27,8 @@ class AddOnViewHolderViewModelTest : KSRobolectricTestCase() {
private val titleForReward = TestSubscriber.create<String>()
private val titleForNoReward = TestSubscriber.create<Int>()
private val titleForAddOn = TestSubscriber.create<Pair<String, Int>>()
private val localPickUpIsGone = TestSubscriber.create<Boolean>()
private val localPickUpName = TestSubscriber.create<String>()

private fun setUpEnvironment(@NonNull environment: Environment) {
this.vm = AddOnViewHolderViewModel.ViewModel(environment)
Expand All @@ -38,6 +42,8 @@ class AddOnViewHolderViewModelTest : KSRobolectricTestCase() {
this.vm.outputs.titleForNoReward().subscribe(this.titleForNoReward)
this.vm.outputs.titleForReward().subscribe(this.titleForReward)
this.vm.outputs.titleForAddOn().subscribe(this.titleForAddOn)
this.vm.outputs.localPickUpIsGone().subscribe(this.localPickUpIsGone)
this.vm.outputs.localPickUpName().subscribe(this.localPickUpName)
}

@Test
Expand Down Expand Up @@ -106,4 +112,64 @@ class AddOnViewHolderViewModelTest : KSRobolectricTestCase() {
this.conversionIsGone.assertValue(true)
this.conversion.assertValue("$50")
}

@Test
fun testReward_LocalReceiptGroup_Visible_FF_On() {
val env = environment()
.toBuilder()
.optimizely(getMockOptimizelyFFOn())
.build()
setUpEnvironment(env)

val project = ProjectFactory.project()
val reward = RewardFactory.localReceiptLocation()
this.vm.inputs.configureWith(ProjectDataFactory.project(project), reward)

this.localPickUpName.assertValue(reward.localReceiptLocation()?.displayableName())
this.localPickUpIsGone.assertValue(false)
}

@Test
fun testReward_LocalReceiptGroup_Visible_FF_On_When_RewardNotLocal() {
val env = environment()
.toBuilder()
.optimizely(getMockOptimizelyFFOn())
.build()
setUpEnvironment(env)

val project = ProjectFactory.project()
val reward = RewardFactory.rewardWithShipping()
this.vm.inputs.configureWith(ProjectDataFactory.project(project), reward)

this.localPickUpName.assertNoValues()
this.localPickUpIsGone.assertNoValues()
}

@Test
fun testReward_LocalReceipt_Group_Not_Visible_FF_Off() {
val env = environment()
.toBuilder()
.optimizely(getMockOptimizelyFFOff())
.build()
setUpEnvironment(env)

val project = ProjectFactory.project()
val reward = RewardFactory.localReceiptLocation()
this.vm.inputs.configureWith(ProjectDataFactory.project(project), reward)

this.localPickUpName.assertValue(reward.localReceiptLocation()?.displayableName())
this.localPickUpIsGone.assertValue(true)
}

private fun getMockOptimizelyFFOn() = object : MockExperimentsClientType() {
override fun isFeatureEnabled(key: OptimizelyFeature.Key): Boolean {
return true
}
}

private fun getMockOptimizelyFFOff() = object : MockExperimentsClientType() {
override fun isFeatureEnabled(key: OptimizelyFeature.Key): Boolean {
return false
}
}
}
Loading

0 comments on commit 9bbd295

Please sign in to comment.