1
votes

I have a credit card number input and I am trying to add an image of the credit card brand next to the text field based on the number the user entered. whether that may be visa, master card, etc.

I have created a struct for the credit cards:

struct CreditCard: Identifiable, Codable {
    var id: String = UUID().uuidString
    var type: String
    var prefix: [Int]
    var length: Int
}

and I have added the credit card data locally:

let cardTypes: [CreditCard] = [
    CreditCard(type: "American Express", prefix: [34, 37], length: 15),
    CreditCard(type: "Visa", prefix: [4], length: 16),
    CreditCard(type: "Master Card", prefix: [51, 52, 53, 54], length: 16),
    CreditCard(type: "Discover", prefix: [6011], length: 16),
    CreditCard(type: "JCB", prefix: [3, 2131, 1800], length: 15)
]

I have imported the data into my view using the following:

var creditCards: [CreditCard] = cardTypes

So for instance, I'd like to display an image saved in my assets folder with the name "Master Card" only when the first numbers in the text input are 51, 52, 53 or 54.

I am using a swiftui textfield

Any help is appreciated, thank you!

1
I guess if you can determine card type, you can determine image easily.Are you able to determine card type? User will be selecting 1 card type to use right, from above objects? - Tushar Sharma

1 Answers

1
votes

Here is a solution for SwiftUI.

Add your logo in the Asset folder. Then store the name of the Image inside your CreditCard model like this

struct CreditCard: Identifiable, Codable {
    var id: String = UUID().uuidString
    var type: String
    var prefix: [Int]
    var length: Int
    var imageName: String
}

Here I created sample data for two credit cards with their imageName.

let cardTypes: [CreditCard] = [
    CreditCard(type: "Visa", prefix: [4], length: 16, imageName: "visa"),
    CreditCard(type: "Master Card", prefix: [51, 52, 53, 54], length: 16, imageName: "mastercard")
]

And then use ProxyBinding to check the typed text and set the image.

struct ContentView: View {
    @State var string: String = ""
    var creditCards: [CreditCard] = cardTypes
    
    @State var imageName: String = ""
    
    var body: some View {
        HStack(spacing: 8) {
            
            if imageName != "" {
                Image(imageName)
                    .resizable()
                    .frame(width: 32, height: 25)
            } else {
                Rectangle()
                    .foregroundColor(.gray)
                    .frame(width: 32, height: 25)
            }
            
            TextField("Card Number", text: Binding<String>( get: {
                return string
            }, set: {
                string = $0
                
                let trimmedText = string.trimmingCharacters(in: .whitespaces)
                
                guard string.count >= 1,
                      trimmedText != "" else {
                    imageName = ""
                    return
                }
                
                for card in creditCards {
                    for prefix in card.prefix {
                        if trimmedText.hasPrefix(String(prefix)) {
                            imageName = card.imageName
                            return
                        }
                    }
                }
                
                imageName = ""
            }))
        }
        .padding(.horizontal, 16)
    }
}