From 77422c5144d8efec3770d77955b679662e4340db Mon Sep 17 00:00:00 2001 From: Elvis Date: Fri, 14 Jun 2024 15:57:06 +0200 Subject: [PATCH] Add CreditCardDetailsController --- Vanilla/Vanilla.xcodeproj/project.pbxproj | 4 ++ .../Vanilla/CreditCardDetailsController.swift | 60 +++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 Vanilla/Vanilla/CreditCardDetailsController.swift diff --git a/Vanilla/Vanilla.xcodeproj/project.pbxproj b/Vanilla/Vanilla.xcodeproj/project.pbxproj index 15fab84..66b840a 100644 --- a/Vanilla/Vanilla.xcodeproj/project.pbxproj +++ b/Vanilla/Vanilla.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 282B13122C1BE91F00FB13F1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 282B13112C1BE91F00FB13F1 /* Assets.xcassets */; }; 282B13152C1BE91F00FB13F1 /* Base in Resources */ = {isa = PBXBuildFile; fileRef = 282B13142C1BE91F00FB13F1 /* Base */; }; 2867CE842C1BE96E004C821F /* FormTextField in Frameworks */ = {isa = PBXBuildFile; productRef = 2867CE832C1BE96E004C821F /* FormTextField */; }; + 28EE88A72C1C83A7000EBFCF /* CreditCardDetailsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28EE88A62C1C83A7000EBFCF /* CreditCardDetailsController.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -21,6 +22,7 @@ 282B13112C1BE91F00FB13F1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 282B13142C1BE91F00FB13F1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 282B13162C1BE91F00FB13F1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 28EE88A62C1C83A7000EBFCF /* CreditCardDetailsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreditCardDetailsController.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -60,6 +62,7 @@ 282B13112C1BE91F00FB13F1 /* Assets.xcassets */, 282B13132C1BE91F00FB13F1 /* LaunchScreen.storyboard */, 282B13162C1BE91F00FB13F1 /* Info.plist */, + 28EE88A62C1C83A7000EBFCF /* CreditCardDetailsController.swift */, ); path = Vanilla; sourceTree = ""; @@ -145,6 +148,7 @@ buildActionMask = 2147483647; files = ( 282B130D2C1BE91E00FB13F1 /* ViewController.swift in Sources */, + 28EE88A72C1C83A7000EBFCF /* CreditCardDetailsController.swift in Sources */, 282B13092C1BE91E00FB13F1 /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Vanilla/Vanilla/CreditCardDetailsController.swift b/Vanilla/Vanilla/CreditCardDetailsController.swift new file mode 100644 index 0000000..8c763e6 --- /dev/null +++ b/Vanilla/Vanilla/CreditCardDetailsController.swift @@ -0,0 +1,60 @@ +import UIKit +import FormTextField + +class CreditCardDetailsController: UIViewController { + lazy var inputValidator: InputValidator = { + var validation = Validation() + validation.maximumLength = "1234 5678 1234 5678".count + validation.minimumLength = "1234 5678 1234 5678".count + let characterSet = NSMutableCharacterSet.decimalDigit() + characterSet.addCharacters(in: " ") + validation.characterSet = characterSet as CharacterSet + let inputValidator = InputValidator(validation: validation) + return inputValidator + }() + + let formatter = CardNumberFormatter() + + lazy var creditCardNumberTextField: UITextField = { + let textField = UITextField(frame: .zero) + textField.translatesAutoresizingMaskIntoConstraints = false + textField.backgroundColor = .secondarySystemBackground + textField.textColor = .label + textField.autocapitalizationType = .none + textField.autocorrectionType = .no + textField.keyboardType = .numberPad + textField.textContentType = .creditCardNumber + textField.placeholder = "Credit card number" + textField.delegate = self + textField.addTarget(self, action: #selector(textFieldDidUpdate(_:)), for: .editingChanged) + textField.clearButtonMode = .whileEditing + return textField + }() + + override func viewDidLoad() { + super.viewDidLoad() + view.addSubview(creditCardNumberTextField) + view.backgroundColor = .systemBackground + + NSLayoutConstraint.activate([ + creditCardNumberTextField.centerYAnchor.constraint(equalTo: view.centerYAnchor), + creditCardNumberTextField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 12), + creditCardNumberTextField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -12), + ]) + } + + @objc func textFieldDidUpdate(_ textField: UITextField) { + let creditCardNumber = creditCardNumberTextField.text ?? "" + textField.text = formatter.formatString(creditCardNumber, reverse: reverse) + creditCardNumberTextField.backgroundColor = self.inputValidator.validateString(creditCardNumber) ? .systemMint : .secondarySystemBackground + } + + var reverse = false +} + +extension CreditCardDetailsController: UITextFieldDelegate { + public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { + reverse = string.isEmpty + return self.inputValidator.validateReplacementString(string, fullString: textField.text, inRange: range) + } +}