Skip to content

Commit

Permalink
[Native Checkout] Credit card cell (#766)
Browse files Browse the repository at this point in the history
  • Loading branch information
Scollaco authored and justinswart committed Aug 5, 2019
1 parent e305043 commit 8922547
Show file tree
Hide file tree
Showing 19 changed files with 471 additions and 84 deletions.
1 change: 1 addition & 0 deletions Kickstarter-iOS/Locales/Base.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
"Email_must_be_a_valid_email_address" = "Email must be a valid email address.";
"Email_notifications" = "Email notifications";
"Email_unverified" = "This email address is unverified.";
"Ending_in_last_four" = "Ending in %{last_four}";
"Ending_soon" = "Ending Soon";
"Estimated_delivery" = "Estimated delivery:";
"Estimated_delivery_of" = "Estimated delivery of";
Expand Down
1 change: 1 addition & 0 deletions Kickstarter-iOS/Locales/de.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
"Email_must_be_a_valid_email_address" = "E-Mail-Adresse muss gültig sein.";
"Email_notifications" = "Benachrichtigung per E-Mail";
"Email_unverified" = "Diese E-Mail-Adresse wurde noch nicht verifiziert.";
"Ending_in_last_four" = "Endet auf %{last_four}";
"Ending_soon" = "Endet bald";
"Estimated_delivery" = "Voraussichtliche Lieferung:";
"Estimated_delivery_of" = "Voraussichtliches Lieferdatum";
Expand Down
1 change: 1 addition & 0 deletions Kickstarter-iOS/Locales/es.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
"Email_must_be_a_valid_email_address" = "El correo electrónico debe tener una dirección de correo electrónico válida.";
"Email_notifications" = "Notificaciones por correo electrónico";
"Email_unverified" = "Esta dirección de correo electrónico no está verificada.";
"Ending_in_last_four" = "Número que termina en %{last_four}";
"Ending_soon" = "Finaliza pronto";
"Estimated_delivery" = "Entrega estimada:";
"Estimated_delivery_of" = "Entrega estimada de";
Expand Down
1 change: 1 addition & 0 deletions Kickstarter-iOS/Locales/fr.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
"Email_must_be_a_valid_email_address" = "L'adresse e-mail doit être valide.";
"Email_notifications" = "Notifications par e-mail";
"Email_unverified" = "Adresse e-mail non vérifiée.";
"Ending_in_last_four" = "Finissant par %{last_four}";
"Ending_soon" = "Campagnes bientôt terminées";
"Estimated_delivery" = "Livraison prévue :";
"Estimated_delivery_of" = "Livraison prévue le";
Expand Down
1 change: 1 addition & 0 deletions Kickstarter-iOS/Locales/ja.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
"Email_must_be_a_valid_email_address" = "有効なメールアドレスを入力してください。";
"Email_notifications" = "メール通知設定";
"Email_unverified" = "このメールアドレスは認証されていません。";
"Ending_in_last_four" = "下の桁が%{last_four} の番号";
"Ending_soon" = "終了直前";
"Estimated_delivery" = "配達予定日:";
"Estimated_delivery_of" = "配送予定日";
Expand Down
2 changes: 1 addition & 1 deletion Kickstarter-iOS/Views/Cells/CreditCardCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ internal final class CreditCardCell: UITableViewCell, ValueCell {
super.bindViewModel()

self.cardNumberLabel.rac.accessibilityLabel = self.viewModel.outputs.cardNumberAccessibilityLabel
self.cardNumberLabel.rac.text = self.viewModel.outputs.cardNumberText
self.cardNumberLabel.rac.text = self.viewModel.outputs.cardNumberTextLongStyle
self.expirationDateLabel.rac.text = self.viewModel.outputs.expirationDateText

self.viewModel.outputs.cardImage
Expand Down
182 changes: 182 additions & 0 deletions Kickstarter-iOS/Views/Cells/PledgeCreditCardView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
import KsApi
import Library
import Prelude
import UIKit

private enum Layout {
enum Card {
static let width: CGFloat = 240
}

enum ImageView {
static let width: CGFloat = 64
static let height: CGFloat = 40
}

enum Button {
static let width: CGFloat = 217
}
}

final class PledgeCreditCardView: UIView {
// MARK: - Properties

private let viewModel: CreditCardCellViewModelType = CreditCardCellViewModel()

private let adaptableStackView: UIStackView = { UIStackView(frame: .zero) }()
private let expirationDateLabel: UILabel = { UILabel(frame: .zero) }()
private let imageView: UIImageView = { UIImageView(frame: .zero) }()
private let labelsStackView: UIStackView = { UIStackView(frame: .zero) }()
private let lastFourLabel: UILabel = { UILabel(frame: .zero) }()
private let rootStackView: UIStackView = { UIStackView(frame: .zero) }()
private let selectButton: UIButton = { UIButton(type: .custom) }()

// MARK: - Lifecycle

override init(frame: CGRect) {
super.init(frame: frame)

self.configureSubviews()
self.setupConstraints()
self.bindViewModel()
}

required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

private func configureSubviews() {
_ = self
|> \.accessibilityElements .~ self.subviews

_ = ([self.lastFourLabel, self.expirationDateLabel], self.labelsStackView)
|> ksr_addArrangedSubviewsToStackView()

_ = ([self.imageView, self.labelsStackView], self.adaptableStackView)
|> ksr_addArrangedSubviewsToStackView()

_ = ([self.adaptableStackView, self.selectButton], self.rootStackView)
|> ksr_addArrangedSubviewsToStackView()

_ = (self.rootStackView, self)
|> ksr_addSubviewToParent()
|> ksr_constrainViewToMarginsInParent()
}

private func setupConstraints() {
NSLayoutConstraint.activate([
self.rootStackView.widthAnchor.constraint(equalToConstant: Layout.Card.width),
self.selectButton.heightAnchor.constraint(greaterThanOrEqualToConstant: Styles.minTouchSize.height),
self.imageView.widthAnchor.constraint(equalToConstant: Layout.ImageView.width)
])
}

// MARK: - Styles

override func bindStyles() {
super.bindStyles()

_ = self
|> viewStyle

_ = self.selectButton
|> selectButtonStyle

_ = self.selectButton.titleLabel
?|> selectButtonTitleLabelStyle

_ = self.imageView
|> imageViewStyle

_ = self.lastFourLabel
|> lastFourLabelStyle

_ = self.expirationDateLabel
|> expirationDateLabelStyle

_ = self.labelsStackView
|> labelsStackViewStyle

_ = self.adaptableStackView
|> checkoutAdaptableStackViewStyle(
self.traitCollection.preferredContentSizeCategory.isAccessibilityCategory
)
|> adaptableStackViewStyle

_ = self.rootStackView
|> rootStackViewStyle
}

override func bindViewModel() {
super.bindViewModel()

self.expirationDateLabel.rac.text = self.viewModel.outputs.expirationDateText
self.lastFourLabel.rac.text = self.viewModel.outputs.cardNumberTextShortStyle
self.viewModel.outputs.cardImage
.observeForUI()
.observeValues { [weak self] image in
_ = self?.imageView
?|> \.image .~ image
}
}

func configureWith(value: GraphUserCreditCard.CreditCard) {
self.viewModel.inputs.configureWith(creditCard: value)
}
}

// MARK: - Styles

private let adaptableStackViewStyle: StackViewStyle = { stackView in
stackView
|> \.spacing .~ Styles.grid(2)
}

private let expirationDateLabelStyle: LabelStyle = { label in
label
|> checkoutTitleLabelStyle
|> \.font .~ UIFont.ksr_caption2().bolded
|> \.textColor .~ .ksr_text_dark_grey_500
}

private let imageViewStyle: ImageViewStyle = { imageView in
imageView
|> \.contentMode .~ .scaleAspectFit
}

private let lastFourLabelStyle: LabelStyle = { label in
label
|> checkoutTitleLabelStyle
|> \.font .~ UIFont.ksr_callout().bolded
|> \.textColor .~ .ksr_soft_black
}

private let labelsStackViewStyle: StackViewStyle = { stackView in
stackView
|> \.axis .~ .vertical
|> \.spacing .~ Styles.gridHalf(1)
}

private let rootStackViewStyle: StackViewStyle = { stackView in
stackView
|> checkoutStackViewStyle
|> \.spacing .~ Styles.grid(3)
}

private let selectButtonStyle: ButtonStyle = { button in
button
|> checkoutSmallBlackButtonStyle
|> UIButton.lens.title(for: .normal) %~ { _ in Strings.Select() }
}

private let selectButtonTitleLabelStyle: LabelStyle = { label in
label
|> \.font .~ UIFont.ksr_headline()
}

private let viewStyle: ViewStyle = { view in
view
|> \.backgroundColor .~ .white
|> roundedStyle(cornerRadius: Styles.grid(1))
|> \.layoutMargins .~ UIEdgeInsets(topBottom: Styles.grid(3), leftRight: Styles.grid(2))
}
Loading

0 comments on commit 8922547

Please sign in to comment.