refactored some of the credit card
Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
parent
5d9b744077
commit
819aa7a44e
@ -94,7 +94,11 @@ open class InputField: EntryFieldBase {
|
||||
|
||||
/// Value for the textField
|
||||
open override var value: String? {
|
||||
textField.text
|
||||
if fieldType == .creditCard {
|
||||
return creditCardRawNumber
|
||||
} else {
|
||||
return textField.text
|
||||
}
|
||||
}
|
||||
|
||||
var _showError: Bool = false
|
||||
@ -170,21 +174,29 @@ open class InputField: EntryFieldBase {
|
||||
.textPublisher
|
||||
.sink { [weak self] newText in
|
||||
print("textPublisher newText: \(newText)")
|
||||
self?.process(text: newText)
|
||||
self?.validate()
|
||||
self?.sendActions(for: .valueChanged)
|
||||
}.store(in: &subscribers)
|
||||
|
||||
textField
|
||||
.publisher(for: .editingDidBegin)
|
||||
.sink { [weak self] _ in
|
||||
self?.setNeedsUpdate()
|
||||
guard let self else { return }
|
||||
if self.fieldType == .creditCard {
|
||||
self.isCreditCardMasked = false
|
||||
self.textField.text = self.formatCreditCardNumber(self.creditCardRawNumber)
|
||||
}
|
||||
self.setNeedsUpdate()
|
||||
}.store(in: &subscribers)
|
||||
|
||||
textField
|
||||
.publisher(for: .editingDidEnd)
|
||||
.sink { [weak self] _ in
|
||||
self?.validate()
|
||||
guard let self else { return }
|
||||
if self.fieldType == .creditCard {
|
||||
self.isCreditCardMasked = true
|
||||
self.textField.text = self.maskCreditCardNumber(self.creditCardRawNumber)
|
||||
}
|
||||
self.validate()
|
||||
}.store(in: &subscribers)
|
||||
|
||||
stackView.addArrangedSubview(successLabel)
|
||||
@ -328,7 +340,7 @@ open class InputField: EntryFieldBase {
|
||||
rules.append(.init(rule))
|
||||
case .securityCode:
|
||||
minWidth = 88.0
|
||||
|
||||
isSecureTextEntry = true
|
||||
}
|
||||
|
||||
//textField
|
||||
@ -375,6 +387,16 @@ open class InputField: EntryFieldBase {
|
||||
super.updateRules()
|
||||
|
||||
switch fieldType {
|
||||
case .creditCard:
|
||||
if let text = textField.text, text.count > 0 {
|
||||
let rule = CharacterCountRule().copyWith {
|
||||
$0.maxLength = "XXXX XXXX XXXX XXXX".count
|
||||
$0.compareType = .equals
|
||||
$0.errorMessage = "Enter a valid credit card."
|
||||
}
|
||||
rules.append(.init(rule))
|
||||
}
|
||||
|
||||
case .tel:
|
||||
if let text = textField.text, text.count > 0 {
|
||||
let rule = CharacterCountRule().copyWith {
|
||||
@ -473,6 +495,46 @@ open class InputField: EntryFieldBase {
|
||||
return formattedString
|
||||
}
|
||||
|
||||
//---------------------------------------------------
|
||||
// MARK: - Credit Card
|
||||
//---------------------------------------------------
|
||||
private var isCreditCardMasked: Bool = false
|
||||
private var creditCardRawNumber: String = ""
|
||||
private var creditCardMaxLength = 16
|
||||
|
||||
private func formatCreditCardNumber(_ number: String) -> String {
|
||||
// Format the number in the style XXXX XXXX XXXX XXXX
|
||||
var formattedNumber = ""
|
||||
for (index, char) in number.enumerated() {
|
||||
if index != 0 && index % 4 == 0 {
|
||||
formattedNumber.append(" ")
|
||||
}
|
||||
formattedNumber.append(char)
|
||||
}
|
||||
|
||||
return formattedNumber
|
||||
}
|
||||
|
||||
private func updateCardTypeIcon(rawNumber: String) {
|
||||
// let firstFourDigits = String(rawNumber.prefix(4))
|
||||
// if let icon = cardTypeIcons[firstFourDigits] {
|
||||
// cardTypeIconView.image = icon
|
||||
// } else {
|
||||
// cardTypeIconView.image = nil
|
||||
// }
|
||||
}
|
||||
|
||||
private func maskCreditCardNumber(_ number: String) -> String {
|
||||
// Mask the first 12 characters if the length is 16
|
||||
let rawNumber = number.filter { $0.isNumber }
|
||||
guard rawNumber.count == creditCardMaxLength else { return number }
|
||||
let lastFourDigits = rawNumber.suffix(4)
|
||||
let maskedSection = String(repeating: "•", count: 12)
|
||||
let formattedMaskSection = formatCreditCardNumber(maskedSection)
|
||||
return formattedMaskSection + " " + lastFourDigits
|
||||
}
|
||||
|
||||
//---------------------------------------------------
|
||||
// MARK: - Telephone
|
||||
//---------------------------------------------------
|
||||
private func formatUSNumber(_ number: String) -> String {
|
||||
@ -530,31 +592,55 @@ open class InputField: EntryFieldBase {
|
||||
}
|
||||
|
||||
extension InputField: UITextFieldDelegate {
|
||||
public func process(text changedText: String) {
|
||||
var newText: String = changedText
|
||||
switch fieldType {
|
||||
case .date:
|
||||
guard newText.count <= dateFormat.maxLength else { return }
|
||||
let numericText = newText.compactMap { $0.isNumber ? $0 : nil }
|
||||
var formattedText = ""
|
||||
|
||||
for (index, char) in numericText.enumerated() {
|
||||
if (index == 2 || (index == 4 && (dateFormat != .mmyy))) && index < dateFormat.maxLength {
|
||||
formattedText += "/"
|
||||
}
|
||||
formattedText.append(char)
|
||||
}
|
||||
newText = formattedText
|
||||
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
||||
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
|
||||
|
||||
// case text, number, inlineAction, password, creditCard, tel, date, securityCode
|
||||
|
||||
switch fieldType {
|
||||
case .creditCard:
|
||||
let allowedCharacters = CharacterSet.decimalDigits
|
||||
if string.rangeOfCharacter(from: allowedCharacters.inverted) != nil && !string.isEmpty {
|
||||
return false
|
||||
}
|
||||
|
||||
// Get the current text
|
||||
let currentText = textField.text ?? ""
|
||||
|
||||
// Calculate the new text
|
||||
let newText = (currentText as NSString).replacingCharacters(in: range, with: string)
|
||||
|
||||
// Remove any existing formatting
|
||||
let rawNumber = newText.filter { $0.isNumber }
|
||||
|
||||
if rawNumber.count > creditCardMaxLength {
|
||||
return false
|
||||
}
|
||||
|
||||
// Format the number with spaces
|
||||
let formattedNumber = formatCreditCardNumber(rawNumber)
|
||||
|
||||
// Update the icon based on the first four digits
|
||||
updateCardTypeIcon(rawNumber: rawNumber)
|
||||
|
||||
// Set the formatted text
|
||||
textField.text = formattedNumber
|
||||
|
||||
// Calculate the new cursor position
|
||||
if let newPosition = getTelCursorPosition(textField: textField,
|
||||
range: range,
|
||||
replacementString: string,
|
||||
rawNumber: rawNumber,
|
||||
formattedNumber: formattedNumber) {
|
||||
textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
|
||||
}
|
||||
|
||||
// if all passes, then set the number1
|
||||
creditCardRawNumber = rawNumber
|
||||
|
||||
// Prevent the default behavior
|
||||
return false
|
||||
|
||||
case .date:
|
||||
// Allow only numbers and limit the length of text.
|
||||
guard let oldText = textField.text,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user