Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend UpdateCardViewController to bank accounts and sepa debit #4280

Open
wants to merge 76 commits into
base: master
Choose a base branch
from

Conversation

joyceqin-stripe
Copy link
Collaborator

@joyceqin-stripe joyceqin-stripe commented Nov 18, 2024

Summary

Refactored UpdateCardViewController to UpdatePaymentMethodViewController and extended its functionality to include US bank accounts and SEPA debit. Created an UpdatePaymentMethodViewModel to determine which form should be shown. Conditionally displays "Save" button and "_ details cannot be changed." label.

Motivation

MOBILESDK-2743
MOBILESDK-2662

Testing

https://github.com/user-attachments/assets/49331f2f-1fe7-45bf-91eb-7554c22eecdf
test_UpdatePaymentMethodViewControllerUSBankAccountLightMode@3x
test_UpdatePaymentMethodViewControllerSEPADebitLightMode@3x
test_UpdatePaymentMethodViewControllerLightMode@3x
test_UpdatePaymentMethodViewControllerExpiredCard@3x
test_UpdatePaymentMethodViewControllerRemoveOnlyCard@3x

Changelog

…Sheet. Edit icon shows for all cards regardless of cbc eligibility.
…reorganized code for card details section, and added conditionally rendered label
@joyceqin-stripe joyceqin-stripe marked this pull request as ready for review November 20, 2024 17:37
@joyceqin-stripe joyceqin-stripe requested review from a team as code owners November 20, 2024 17:37
isTestMode: configuration.isTestMode,
cardBrandFilter: savedPaymentMethodsConfiguration.cardBrandFilter)
cardBrandFilter: savedPaymentMethodsConfiguration.cardBrandFilter,
viewModel: UpdatePaymentMethodViewModel(paymentMethod: paymentMethod, canEdit: paymentMethod.isCoBrandedCard && cbcEligible, canRemove: configuration.paymentMethodRemove && (savedPaymentMethods.count > 1 || configuration.allowsRemovalOfLastSavedPaymentMethod)))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's break the view model instantiation into it's own line, it's difficult to read. Same for wherever this is done.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fair, done.

@@ -179,6 +179,24 @@ extension TextFieldElement {
}
}
}

struct LastFourIBANConfiguration: TextFieldElementConfiguration {
let label: String = STPLocalizedString("IBAN", "Label for an IBAN field")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should moved this into where Localized.bank_account lives.

However, I'm not really sure it' makes senes to localize "IBAN", I don't think it'll localize into anything. Can you confirm in the project channel?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the STPLocalizedString part and just have it as a hardcoded String "IBAN" now.

@@ -361,4 +361,23 @@ extension TextFieldElement {
return TextFieldElement.PANConfiguration(cardBrandDropDown: cardBrandDropDown).accessoryView(for: lastFourFormatted, theme: theme)
}
}
struct USBankNumberConfiguration: TextFieldElementConfiguration {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's put this in it's own file, it doesn't belong in the +Card file.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created a new file, TextFieldElement+Card.swift specifically for USBankNumberConfiguration

return stackView
}()

private lazy var sepaDebitSection: UIStackView = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be good to move all the form creation for card, us bank account and sepa into it's own class.

Then it can have a function where you pass it in a view model and it just returns a view.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or inside of the view model.


class UpdatePaymentMethodViewModel {
let paymentMethod: STPPaymentMethod
static let supportedPaymentMethods: [STPPaymentMethodType] = [.card, .USBankAccount, .SEPADebit]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: On the ordering here, let's put all static variables up on their own and not in between more "normal" variables for readability.

class UpdatePaymentMethodViewModel {
    static let supportedPaymentMethods: [STPPaymentMethodType] = [.card, .USBankAccount, .SEPADebit]


    let paymentMethod: STPPaymentMethod
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also does it need to be static? Do we ever reference this property where we don't have an instance of UpdatePaymentMethodViewModel?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's used in VerticalSavedPaymentMethodsViewController and SavedPaymentMethodCollectionView when checking if a payment method should allow editint

public let disallowedCharacters: CharacterSet = .whitespacesAndNewlines
let invalidError = Error.invalid(
localizedDescription: String.Localized.invalid_email
)

init(defaultValue: String? = nil, isOptional: Bool = false) {
public init(defaultValue: String? = nil, isOptional: Bool = false, isEditable: Bool = true) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this need to be public now?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't— I don't remember what led me to add that in. I've reverted that part

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wait actually, I think it was because I was getting inaccessible due to '@_spi' protection level errors

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think we should commit this, but not sure why it's not being ignored.

@@ -0,0 +1,24 @@
{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, let's not commit this.

let isEditable = false

private var lastFourFormatted: String {
"•••• \(lastFour)"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the figma I'm seeing the last four of IBAN in SEPA having a space between the 2 and 3rd digit. Looking at the snapshots that doesn't appear to be the case here.

CleanShot 2024-11-21 at 10 43 24

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remember being told that the IBAN shouldn't have the space between those digits, but I'll verify in the channel

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bella confirmed there shouldn't be a space there.

@@ -0,0 +1,148 @@
//
// PaymentMethodForm.swift
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that this is a standalone class and not a variable nested within the update screen, the name "PaymentMethodForm" seems ambiguous. Maybe "SavedPaymentMethodFormFactory" or something.

case .SEPADebit:
return sepaDebitSection
default:
fatalError("Updating payment method has not been implemented for \(viewModel.paymentMethod.type)")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: This error message doesn't make much sense in the context of this class

Comment on lines 62 to 64
stackView.addArrangedSubview(updateButton)
stackView.addArrangedSubview(removeButton)
stackView.addArrangedSubview(errorLabel)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just add these to the array on line 50?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how to insert footnoteLabel at an index into the stackView array— addArrangedSubview adds to the end of the array. If I add these to the array on line 50, then when I add footnoteLabel, it will show up below the remove button.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never mind, found out that there's insertArrangedSubview(view, at)

@@ -103,7 +103,7 @@ class CircularButton: UIControl {
accessibilityIdentifier = "CircularButton.Remove"
case .edit:
imageView.image = Image.icon_edit.makeImage(template: true)
accessibilityLabel = String.Localized.update_card_brand
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wrong here, sorry! I got this mixed up w/ accessibilityIdentifier! Let's localize this, apologies for the churn on this.

@joyceqin-stripe joyceqin-stripe enabled auto-merge (squash) November 21, 2024 21:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants