Skip to content

Commit

Permalink
[MBL-1607] Add Estimated Shipping View to Late Pledge Checkout (#2133)
Browse files Browse the repository at this point in the history
* add estimated shipping view to late pledge checkout

* basic cleanup

* add snapshot tests

* fix view model test

* formatting

* fix spacing and width of rewards table

* remove unnecessary logged in/logged out check in tests

* cleanup view spacing

* fix snapshots

* delete old snapshots

* more snapshot updates

* Re-record screenshots

---------

Co-authored-by: Ingerid Fosli <i.fosli@kickstarter.com>
  • Loading branch information
scottkicks and ifosli authored Aug 28, 2024
1 parent eaacccb commit 4decc8f
Show file tree
Hide file tree
Showing 64 changed files with 562 additions and 148 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ final class NoShippingConfirmDetailsViewController: UIViewController, MessageBan

private var sessionStartedObserver: Any?

private let viewModel: ConfirmDetailsViewModelType = ConfirmDetailsViewModel()
private let viewModel: NoShippingConfirmDetailsViewModelType = NoShippingConfirmDetailsViewModel()

// MARK: - Lifecycle

Expand Down Expand Up @@ -309,20 +309,6 @@ extension NoShippingConfirmDetailsViewController: PledgeAmountViewControllerDele
}
}

// MARK: - PledgeShippingLocationViewControllerDelegate

extension NoShippingConfirmDetailsViewController: PledgeShippingLocationViewControllerDelegate {
func pledgeShippingLocationViewController(
_: PledgeShippingLocationViewController,
didSelect shippingRule: ShippingRule
) {
self.viewModel.inputs.shippingRuleSelected(shippingRule)
}

func pledgeShippingLocationViewControllerLayoutDidUpdate(_: PledgeShippingLocationViewController) {}
func pledgeShippingLocationViewControllerFailedToLoad(_: PledgeShippingLocationViewController) {}
}

// MARK: - ConfirmDetailsContinueCTAViewDelegate

extension NoShippingConfirmDetailsViewController: ConfirmDetailsContinueCTAViewDelegate {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ final class NoShippingPledgeViewController: UIViewController,
|> \.translatesAutoresizingMaskIntoConstraints .~ false
}()

private lazy var estimatedShippingStackView: UIStackView = {
UIStackView(frame: .zero)
|> \.translatesAutoresizingMaskIntoConstraints .~ false
}()

private var sessionStartedObserver: Any?
private let viewModel: NoShippingPledgeViewModelType = NoShippingPledgeViewModel()

Expand Down Expand Up @@ -143,31 +148,27 @@ final class NoShippingPledgeViewController: UIViewController,
// MARK: - Configuration

private func configureChildViewControllers() {
_ = (self.rootScrollView, self.view)
|> ksr_addSubviewToParent()
self.view.addSubview(self.rootScrollView)
self.view.addSubview(self.pledgeCTAContainerView)

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

_ = (self.pledgeCTAContainerView, self.view)
|> ksr_addSubviewToParent()

let childViewControllers = [
self.pledgeRewardsSummaryViewController,
self.paymentMethodsViewController
]

let arrangedInsetSubviews = [
[self.titleLabel],
self.paymentMethodsSectionViews,
self.confirmationSectionViews,
[self.pledgeRewardsSummaryViewController.view]
self.confirmationSectionViews
]
.flatMap { $0 }
.compact()

_ = ([self.titleLabel, self.rootInsetStackView], self.rootStackView)
|> ksr_addArrangedSubviewsToStackView()
self.rootStackView.addArrangedSubview(self.rootInsetStackView)

arrangedInsetSubviews.forEach { view in
self.rootInsetStackView.addArrangedSubview(view)
Expand All @@ -178,26 +179,24 @@ final class NoShippingPledgeViewController: UIViewController,
viewController.didMove(toParent: self)
}

self.rootStackView.addArrangedSubview(self.pledgeRewardsSummaryViewController.view)

self.rootStackView.addArrangedSubview(self.estimatedShippingStackView)

self.titleLabel.setContentCompressionResistancePriority(.required, for: .vertical)
self.titleLabel.setContentHuggingPriority(.required, for: .vertical)
}

private func setupConstraints() {
NSLayoutConstraint.activate([
self.rootScrollView.topAnchor.constraint(
equalTo: self.view.safeAreaLayoutGuide.topAnchor,
constant: Styles.grid(1)
),
self.rootScrollView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
self.rootScrollView.leftAnchor.constraint(equalTo: self.view.leftAnchor),
self.rootScrollView.rightAnchor.constraint(equalTo: self.view.rightAnchor),
self.rootScrollView.bottomAnchor.constraint(
equalTo: self.pledgeCTAContainerView.topAnchor,
constant: -Styles.grid(3)
),
self.rootScrollView.bottomAnchor.constraint(equalTo: self.pledgeCTAContainerView.topAnchor),
self.pledgeCTAContainerView.leftAnchor.constraint(equalTo: self.view.leftAnchor),
self.pledgeCTAContainerView.rightAnchor.constraint(equalTo: self.view.rightAnchor),
self.pledgeCTAContainerView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
self.rootStackView.widthAnchor.constraint(equalTo: self.view.widthAnchor)
self.rootStackView.widthAnchor.constraint(equalTo: self.rootScrollView.widthAnchor)
])
}

Expand All @@ -206,26 +205,21 @@ final class NoShippingPledgeViewController: UIViewController,
override func bindStyles() {
super.bindStyles()

_ = self.view
|> checkoutBackgroundStyle
self.view.backgroundColor = UIColor.ksr_support_100

_ = self.titleLabel
|> titleLabelStyle
titleLabelStyle(self.titleLabel)

_ = self.pledgeDisclaimerView
|> pledgeDisclaimerViewStyle
rootScrollViewStyle(self.rootScrollView)

_ = self.rootScrollView
|> rootScrollViewStyle
rootStackViewStyle(self.rootStackView)

_ = self.rootStackView
|> rootStackViewStyle
rootInsetStackViewStyle(self.rootInsetStackView)

_ = self.rootInsetStackView
|> rootInsetStackViewStyle
rootInsetStackViewStyle(self.estimatedShippingStackView)

_ = self.paymentMethodsViewController.view
|> roundedStyle(cornerRadius: Layout.Style.cornerRadius)
roundedStyle(self.paymentMethodsViewController.view, cornerRadius: Layout.Style.cornerRadius)

roundedViewStyle(self.pledgeDisclaimerView, cornerRadius: Layout.Style.cornerRadius)
}

// MARK: - View model
Expand Down Expand Up @@ -282,7 +276,7 @@ final class NoShippingPledgeViewController: UIViewController,
.observeForUI()
.observeValues { [weak self] strings in
let (estimatedShippingText, estimatedConversionText) = strings
self?.configureEstimatedShippingView(with: (estimatedShippingText, estimatedConversionText))
self?.configureEstimatedShippingView(estimatedShippingText, estimatedConversionText)
}

self.viewModel.outputs.estimatedShippingViewHidden
Expand Down Expand Up @@ -440,20 +434,22 @@ final class NoShippingPledgeViewController: UIViewController,
self.pledgeDisclaimerView.configure(with: ("icon-not-a-store", attributedText))
}

private func configureEstimatedShippingView(with strings: (String, String)) {
let (estimatedCost, aboutConversion) = strings
private func configureEstimatedShippingView(_ estimatedCost: String, _ aboutConversion: String) {
let estimatedShippingView = EstimatedShippingCheckoutView(
estimatedCost: estimatedCost,
aboutConversion: aboutConversion
)

self.estimatedShippingViewContainer.rootView = estimatedShippingView
self.estimatedShippingViewContainer.view.translatesAutoresizingMaskIntoConstraints = false
self.estimatedShippingViewContainer.view.clipsToBounds = true
self.estimatedShippingViewContainer.view.layer.masksToBounds = true
self.estimatedShippingViewContainer.view.layer.cornerRadius = Layout.Style.cornerRadius

self.rootInsetStackView.addArrangedSubview(self.estimatedShippingViewContainer.view)
self.rootInsetStackView.layoutIfNeeded()
self.estimatedShippingStackView.addArrangedSubview(self.estimatedShippingViewContainer.view)
self.estimatedShippingViewContainer.didMove(toParent: self)

self.estimatedShippingStackView.layoutIfNeeded()
}

private func goToLoginSignup(with intent: LoginIntent, project: Project, reward: Reward) {
Expand Down Expand Up @@ -598,38 +594,39 @@ extension NoShippingPledgeViewController: PledgeDisclaimerViewDelegate {

// MARK: - Styles

private let pledgeDisclaimerViewStyle: ViewStyle = { view in
view
|> roundedStyle(cornerRadius: Layout.Style.cornerRadius)
private func roundedViewStyle(_ view: UIView, cornerRadius: CGFloat) {
view.clipsToBounds = true
view.layer.masksToBounds = true
view.layer.cornerRadius = cornerRadius
}

private let rootScrollViewStyle: ScrollStyle = { scrollView in
scrollView
|> \.showsVerticalScrollIndicator .~ false
|> \.alwaysBounceVertical .~ true
private func rootScrollViewStyle(_ scrollView: UIScrollView) {
scrollView.showsVerticalScrollIndicator = false
scrollView.alwaysBounceVertical = true
}

private let rootStackViewStyle: StackViewStyle = { stackView in
stackView
|> \.axis .~ NSLayoutConstraint.Axis.vertical
|> \.spacing .~ Styles.grid(4)
|> \.isLayoutMarginsRelativeArrangement .~ true
|> \.layoutMargins .~ UIEdgeInsets(
topBottom: 0,
leftRight: Layout.Margin.leftRight
)
private func rootStackViewStyle(_ stackView: UIStackView) {
stackView.axis = NSLayoutConstraint.Axis.vertical
stackView.spacing = Styles.grid(2)
stackView.isLayoutMarginsRelativeArrangement = true
stackView.layoutMargins = UIEdgeInsets(
topBottom: ConfirmDetailsLayout.Margin.topBottom,
leftRight: 0
)
}

private let rootInsetStackViewStyle: StackViewStyle = { stackView in
stackView
|> \.axis .~ NSLayoutConstraint.Axis.vertical
|> \.spacing .~ Styles.grid(4)
|> \.isLayoutMarginsRelativeArrangement .~ true
private func rootInsetStackViewStyle(_ stackView: UIStackView) {
stackView.axis = NSLayoutConstraint.Axis.vertical
stackView.spacing = Styles.grid(4)
stackView.isLayoutMarginsRelativeArrangement = true
stackView.layoutMargins = UIEdgeInsets(
topBottom: ConfirmDetailsLayout.Margin.topBottom,
leftRight: ConfirmDetailsLayout.Margin.leftRight
)
}

public func titleLabelStyle(_ label: UILabel) {
label.numberOfLines = 1
label.textColor = UIColor.ksr_support_700
label.font = UIFont.ksr_title2().bolded
label.layoutMargins = UIEdgeInsets(topBottom: Layout.Margin.topBottom, leftRight: Styles.grid(3))
}
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ final class NoShippingPledgeViewControllerTests: TestCase {
RemoteConfigFeature.noShippingAtCheckout.rawValue: true
]

orthogonalCombos(Language.allLanguages, [Device.phone4_7inch, Device.pad], [nil, User.template])
.forEach { language, device, currentUser in
orthogonalCombos(Language.allLanguages, [Device.phone4_7inch, Device.pad])
.forEach { language, device in
withEnvironment(language: language, remoteConfigClient: mockConfigClient) {
let controller = NoShippingPledgeViewController.instantiate()
let data = PledgeViewData(
Expand All @@ -155,16 +155,12 @@ final class NoShippingPledgeViewControllerTests: TestCase {

self.scheduler.advance(by: .seconds(1))

let loggedIn = currentUser != nil
let loggedInString = loggedIn ? "LoggedIn" : "LoggedOut"
if loggedIn { parent.view.frame.size.height = 1_200 }

self.allowLayoutPass()

assertSnapshot(
matching: parent.view,
as: .image(perceptualPrecision: 0.98),
named: "lang_\(language)_device_\(device)_\(loggedInString)"
named: "lang_\(language)_device_\(device)"
)
}
}
Expand Down Expand Up @@ -242,24 +238,20 @@ final class NoShippingPledgeViewControllerTests: TestCase {
RemoteConfigFeature.noShippingAtCheckout.rawValue: true
]

orthogonalCombos(Language.allLanguages, [Device.phone4_7inch, Device.pad], [nil, User.template])
.forEach { language, device, currentUser in
orthogonalCombos(Language.allLanguages, [Device.phone4_7inch, Device.pad])
.forEach { language, device in
withEnvironment(language: language, remoteConfigClient: mockConfigClient) {
let controller = NoShippingPledgeViewController.instantiate()
controller.configure(with: data)
let (parent, _) = traitControllers(device: device, orientation: .portrait, child: controller)
self.scheduler.advance(by: .seconds(1))

let loggedIn = currentUser != nil
let loggedInString = loggedIn ? "LoggedIn" : "LoggedOut"
if loggedIn { parent.view.frame.size.height = 1_200 }

self.allowLayoutPass()

assertSnapshot(
matching: parent.view,
as: .image(perceptualPrecision: 0.98),
named: "lang_\(language)_device_\(device)_\(loggedInString)"
named: "lang_\(language)_device_\(device)"
)
}
}
Expand Down
Loading

0 comments on commit 4decc8f

Please sign in to comment.