Skip to content

Commit

Permalink
[NT-1329, NT-1330] Bonus Support UI (#1233)
Browse files Browse the repository at this point in the history
* Add bonus support to pledge view

* Update snapshots
  • Loading branch information
justinswart authored Jun 23, 2020
1 parent dbdabde commit 04fe7cb
Show file tree
Hide file tree
Showing 155 changed files with 498 additions and 301 deletions.
2 changes: 1 addition & 1 deletion Kickstarter-iOS/Views/AmountInputView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ private let labelStyle: LabelStyle = { (label: UILabel) in
private let textFieldStyle: TextFieldStyle = { (textField: UITextField) in
textField
|> \.adjustsFontForContentSizeCategory .~ true
|> \.font .~ UIFont.ksr_title1()
|> \.font .~ UIFont.ksr_title1().monospaced
|> \.keyboardType .~ UIKeyboardType.decimalPad
}

Expand Down
66 changes: 49 additions & 17 deletions Kickstarter-iOS/Views/Controllers/PledgeAmountViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ final class PledgeAmountViewController: UIViewController {

private lazy var adaptableStackView: UIStackView = { UIStackView(frame: .zero) }()
private lazy var amountInputView: AmountInputView = { AmountInputView(frame: .zero) }()
private lazy var amountInputStackView: UIStackView = { UIStackView(frame: .zero) }()
private lazy var maxPledgeAmountErrorLabel: UILabel = { UILabel(frame: .zero) }()
private lazy var minPledgeAmountLabel: UILabel = { UILabel(frame: .zero) }()
private lazy var plusSignLabel: UILabel = { UILabel(frame: .zero) }()
private lazy var titleLabel: UILabel = { UILabel(frame: .zero) }()
private lazy var titlesStackView: UIStackView = { UIStackView(frame: .zero) }()
private lazy var subtitleLabel: UILabel = { UILabel(frame: .zero) }()
private lazy var rootStackView: UIStackView = { UIStackView(frame: .zero) }()
private lazy var horizontalSpacer: UIView = { UIView(frame: .zero) }()
private lazy var stepper: UIStepper = { UIStepper(frame: .zero) }()
Expand All @@ -33,22 +36,36 @@ final class PledgeAmountViewController: UIViewController {
super.viewDidLoad()

_ = self
|> \.accessibilityElements .~ [self.titleLabel, self.stepper, self.amountInputView]
|> \.accessibilityElements .~ [
self.titleLabel,
self.subtitleLabel,
self.stepper,
self.amountInputView
]

_ = (self.rootStackView, self.view)
|> ksr_addSubviewToParent()
|> ksr_constrainViewToEdgesInParent()

_ = ([self.titleLabel, self.subtitleLabel], self.titlesStackView)
|> ksr_addArrangedSubviewsToStackView()

_ = ([
self.titleLabel,
self.minPledgeAmountLabel,
self.titlesStackView,
self.adaptableStackView,
self.maxPledgeAmountErrorLabel,
self.verticalSpacer
], self.rootStackView)
|> ksr_addArrangedSubviewsToStackView()

_ = ([self.stepper, self.horizontalSpacer, self.amountInputView], self.adaptableStackView)
_ = ([self.plusSignLabel, self.amountInputView], self.amountInputStackView)
|> ksr_addArrangedSubviewsToStackView()

_ = ([
self.stepper,
self.horizontalSpacer,
self.amountInputStackView
], self.adaptableStackView)
|> ksr_addArrangedSubviewsToStackView()

self.amountInputView.textField.delegate = self
Expand Down Expand Up @@ -86,24 +103,34 @@ final class PledgeAmountViewController: UIViewController {
|> adaptableStackViewStyle(isAccessibilityCategory)
|> \.spacing .~ Styles.grid(3)

_ = self.titlesStackView
|> \.axis .~ .vertical
|> \.spacing .~ Styles.grid(1)

_ = self.amountInputStackView
|> \.alignment .~ .center
|> \.spacing .~ Styles.grid(1)

_ = self.horizontalSpacer
|> \.isHidden .~ isAccessibilityCategory

_ = self.titleLabel
|> checkoutBackgroundStyle
_ = self.titleLabel
|> checkoutTitleLabelStyle
|> \.text %~ { _ in Strings.Your_pledge_amount() }
|> checkoutBackgroundStyle

_ = self.plusSignLabel
|> \.text .~ "+"
|> \.textColor .~ UIColor.ksr_dark_grey_400

_ = self.subtitleLabel
|> subtitleLabelStyle

_ = self.rootStackView
|> checkoutStackViewStyle

_ = self.stepper
|> stepperStyle

_ = self.minPledgeAmountLabel
|> minPledgeAmountLabelStyle

_ = self.maxPledgeAmountErrorLabel
|> maxPledgeAmountErrorLabelStyle
}
Expand All @@ -121,11 +148,12 @@ final class PledgeAmountViewController: UIViewController {
self.amountInputView.textField.rac.textColor = self.viewModel.outputs.textFieldTextColor
self.maxPledgeAmountErrorLabel.rac.hidden = self.viewModel.outputs.maxPledgeAmountErrorLabelIsHidden
self.maxPledgeAmountErrorLabel.rac.text = self.viewModel.outputs.maxPledgeAmountErrorLabelText
self.minPledgeAmountLabel.rac.hidden = self.viewModel.outputs.minPledgeAmountLabelIsHidden
self.minPledgeAmountLabel.rac.text = self.viewModel.outputs.minPledgeAmountLabelText
self.plusSignLabel.rac.hidden = self.viewModel.outputs.plusSignLabelHidden
self.stepper.rac.maximumValue = self.viewModel.outputs.stepperMaxValue
self.stepper.rac.minimumValue = self.viewModel.outputs.stepperMinValue
self.stepper.rac.value = self.viewModel.outputs.stepperValue
self.subtitleLabel.rac.hidden = self.viewModel.outputs.subTitleLabelHidden
self.titleLabel.rac.text = self.viewModel.outputs.titleLabelText

self.viewModel.outputs.generateSelectionFeedback
.observeForUI()
Expand All @@ -150,8 +178,8 @@ final class PledgeAmountViewController: UIViewController {

// MARK: - Configuration

func configureWith(value: (project: Project, reward: Reward)) {
self.viewModel.inputs.configureWith(project: value.project, reward: value.reward)
func configureWith(value: PledgeAmountViewConfigData) {
self.viewModel.inputs.configureWith(data: value)
}

// MARK: - Actions
Expand Down Expand Up @@ -212,11 +240,15 @@ private func stepperStyle(_ stepper: UIStepper) -> UIStepper {
<> UIStepper.lens.incrementImage(for: .highlighted) .~ image(named: "stepper-increment-highlighted")
}

private let minPledgeAmountLabelStyle: LabelStyle = { label in
private let subtitleLabelStyle: LabelStyle = { label in
label
|> \.font .~ UIFont.ksr_caption1()
|> \.font .~ UIFont.ksr_footnote()
|> \.numberOfLines .~ 0
|> \.textColor .~ UIColor.ksr_text_navy_600
|> \.text .~ localizedString(
key: "A_little_extra_to_help_bring_this_project_to_life",
defaultValue: "A little extra to help bring this project to life."
)
}

private let maxPledgeAmountErrorLabelStyle: LabelStyle = { label in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ final class PledgeAmountViewControllerTests: TestCase {
let (parent, _) = traitControllers(device: device, orientation: .portrait, child: controller)
parent.view.frame.size.height = regularHeight

controller.configureWith(value: (project: .template, reward: .template))
controller.configureWith(value: (project: .template, reward: .template, 0))

FBSnapshotVerifyView(parent.view, identifier: "device_\(device)")
}
Expand All @@ -40,7 +40,7 @@ final class PledgeAmountViewControllerTests: TestCase {
let (parent, _) = traitControllers(child: controller, additionalTraits: additionalTraits)
parent.view.frame.size.height = expandedHeight

controller.configureWith(value: (project: .template, reward: .template))
controller.configureWith(value: (project: .template, reward: .template, 0))

FBSnapshotVerifyView(
parent.view, identifier: "trait_\(additionalTraits.preferredContentSizeCategory.rawValue)"
Expand All @@ -57,7 +57,7 @@ final class PledgeAmountViewControllerTests: TestCase {
let (parent, _) = traitControllers(device: device, orientation: .portrait, child: controller)
parent.view.frame.size.height = regularHeight

controller.configureWith(value: (project: project, reward: .template))
controller.configureWith(value: (project: project, reward: .template, 0))

FBSnapshotVerifyView(parent.view, identifier: "device_\(device)")
}
Expand All @@ -72,7 +72,7 @@ final class PledgeAmountViewControllerTests: TestCase {
let (parent, _) = traitControllers(device: device, orientation: .portrait, child: controller)
parent.view.frame.size.height = regularHeight

controller.configureWith(value: (project: .template, reward: reward))
controller.configureWith(value: (project: .template, reward: reward, 0))
controller.stepperValueChanged(UIStepper(frame: .zero) |> \.value .~ 0)
controller.textFieldDidChange(UITextField(frame: .zero) |> \.text .~ "0")

Expand All @@ -95,7 +95,7 @@ final class PledgeAmountViewControllerTests: TestCase {
let (parent, _) = traitControllers(device: device, orientation: .portrait, child: controller)
parent.view.frame.size.height = regularHeight

controller.configureWith(value: (project: .template, reward: .template))
controller.configureWith(value: (project: .template, reward: .template, 0))
controller.stepperValueChanged(stepper)
controller.textFieldDidChange(textField)

Expand All @@ -108,33 +108,14 @@ final class PledgeAmountViewControllerTests: TestCase {
|> Reward.lens.minimum .~ 10

let stepper = UIStepper(frame: .zero)
|> \.value .~ 5
|> \.value .~ 0

[Device.phone4_7inch, Device.pad].forEach { device in
let controller = PledgeAmountViewController.instantiate()
let (parent, _) = traitControllers(device: device, orientation: .portrait, child: controller)
parent.view.frame.size.height = regularHeight

controller.configureWith(value: (project: .template, reward: reward))
controller.stepperValueChanged(stepper)

FBSnapshotVerifyView(parent.view, identifier: "device_\(device)")
}
}

func testView_TextColorIsRedWhenBellowMinimumPledgeAmount() {
let reward = Reward.template
|> Reward.lens.minimum .~ 10

let stepper = UIStepper(frame: .zero)
|> \.value .~ 5

[Device.phone4_7inch, Device.pad].forEach { device in
let controller = PledgeAmountViewController.instantiate()
let (parent, _) = traitControllers(device: device, orientation: .portrait, child: controller)
parent.view.frame.size.height = regularHeight

controller.configureWith(value: (project: .template, reward: reward))
controller.configureWith(value: (project: .template, reward: reward, 0))
controller.stepperValueChanged(stepper)

FBSnapshotVerifyView(parent.view, identifier: "device_\(device)")
Expand All @@ -154,7 +135,7 @@ final class PledgeAmountViewControllerTests: TestCase {
let (parent, _) = traitControllers(device: device, orientation: .portrait, child: controller)
parent.view.frame.size.height = regularHeight

controller.configureWith(value: (project: project, reward: .template))
controller.configureWith(value: (project: project, reward: .template, 0))
controller.stepperValueChanged(stepper)

FBSnapshotVerifyView(parent.view, identifier: "device_\(device)")
Expand All @@ -174,7 +155,7 @@ final class PledgeAmountViewControllerTests: TestCase {
let (parent, _) = traitControllers(device: device, orientation: .portrait, child: controller)
parent.view.frame.size.height = regularHeight

controller.configureWith(value: (project: project, reward: .template))
controller.configureWith(value: (project: project, reward: .template, 0))
controller.stepperValueChanged(stepper)

FBSnapshotVerifyView(parent.view, identifier: "device_\(device)")
Expand Down
9 changes: 7 additions & 2 deletions Kickstarter-iOS/Views/Controllers/PledgeViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ final class PledgeViewController: UIViewController,
}()

private lazy var inputsSectionViews = {
[self.pledgeAmountViewController.view, self.shippingLocationViewController.view]
[self.shippingLocationViewController.view, self.pledgeAmountViewController.view]
}()

fileprivate lazy var keyboardDimissingTapGestureRecognizer: UITapGestureRecognizer = {
Expand Down Expand Up @@ -288,10 +288,15 @@ final class PledgeViewController: UIViewController,
self.viewModel.outputs.configureWithData
.observeForUI()
.observeValues { [weak self] data in
self?.pledgeAmountViewController.configureWith(value: data)
self?.shippingLocationViewController.configureWith(value: data)
}

self.viewModel.outputs.configurePledgeAmountViewWithData
.observeForUI()
.observeValues { [weak self] data in
self?.pledgeAmountViewController.configureWith(value: data)
}

self.viewModel.outputs.configureExpandableRewardsHeaderWithData
.observeForUI()
.observeValues { [weak self] data in
Expand Down
9 changes: 9 additions & 0 deletions Library/Backing+PledgeAmount.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,13 @@ extension Backing {
subtractingShippingAmount: self.shippingAmount.flatMap(Double.init)
)
}

/// Returns the bonus support amount subtracting the reward minimum from the total pledge amount
public var bonusSupportAmount: Double {
guard let reward = self.reward else { return 0 }

let bonusSupportAmount = Decimal(self.pledgeAmount) - Decimal(reward.minimum)

return (bonusSupportAmount as NSDecimalNumber).doubleValue
}
}
Loading

0 comments on commit 04fe7cb

Please sign in to comment.