CXTDT-565105 - InputField - Date - Typeover text not working.

Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
Matt Bruce 2024-06-06 16:18:32 -05:00
parent 8a686314f5
commit f7ded23857
2 changed files with 125 additions and 11 deletions

View File

@ -10,6 +10,18 @@ import UIKit
extension InputField {
public class DateRule: Rule, Withable {
public var dateFormat: DateFormat?
public var errorMessage: String = "Enter a valid date"
private let dateFormatter = DateFormatter()
public func isValid(value: String?) -> Bool {
guard let value, let dateFormat, !value.isEmpty else { return true }
dateFormatter.dateFormat = dateFormat.formatString
return dateFormatter.date(from: value) != nil
}
}
public enum DateFormat: String, CaseIterable {
case mmyy
case mmddyy
@ -46,6 +58,102 @@ extension InputField {
case .mmddyyyy: [2,4]
}
}
public func isValid(_ date: String) -> Bool {
let allowedCharacters = CharacterSet(charactersIn: "0123456789/")
// Check if the input contains only allowed characters
if date.rangeOfCharacter(from: allowedCharacters.inverted) != nil || date.isEmpty {
return false
}
let components = date.split(separator: "/")
func isMonth(_ month: String) -> Bool {
switch month.count {
case 1:
guard let month = Int(month), (0...1).contains(month) else { return false }
return true
case 2:
guard let month = Int(month), (1...12).contains(month) else { return false }
return true
default:
return false
}
}
func isDay(_ day: String) -> Bool {
switch day.count {
case 1:
guard let day = Int(day),(1...3).contains(day) else { return false }
return true
case 2:
guard let day = Int(day), (1...31).contains(day) else { return false }
return true
default:
return false
}
}
func isYear(_ year: String, max: Int) -> Bool {
guard year.count <= max else {
return false
}
return true
}
switch self {
case .mmyy:
if components.count > 2 {
return false
}
// Validate month part
if components.count > 0, let monthPart = components.first {
if !isMonth(String(monthPart)) {
return false
}
}
// Validate year part
if components.count > 1, let yearPart = components.last {
if !isYear(String(yearPart), max: 2) {
return false
}
}
case .mmddyy, .mmddyyyy:
if components.count > 3 {
return false
}
// Validate month part
if components.count > 0, let monthPart = components.first {
if !isMonth(String(monthPart)) {
return false
}
}
// Validate day part
if components.count > 1 {
let dayPart = components[1]
if !isDay(String(dayPart)) {
return false
}
}
// Validate year part
if components.count > 2, let yearPart = components.last {
if !isYear(String(yearPart), max: self == .mmddyy ? 2 : 4) {
return false
}
}
}
return true
}
}
class DateHandler: FieldTypeHandler {
@ -58,16 +166,15 @@ extension InputField {
override func updateView(_ inputField: InputField) {
minWidth = 114.0
placeholderText = inputField.dateFormat.placeholderText
//placeholderText = inputField.dateFormat.placeholderText
inputField.textField.formatText = inputField.dateFormat.placeholderText
super.updateView(inputField)
}
override func appendRules(_ inputField: InputField) {
if let text = inputField.textField.text, text.count > 0 {
let rule = CharacterCountRule().copyWith {
$0.maxLength = inputField.dateFormat.maxLength
$0.compareType = .equals
let rule = DateRule().copyWith {
$0.dateFormat = inputField.dateFormat
$0.errorMessage = "Enter a valid date."
}
inputField.rules.append(.init(rule))
@ -86,9 +193,13 @@ extension InputField {
if newText.count > inputField.dateFormat.maxLength {
return false
}
if newText.count <= inputField.dateFormat.maxLength {
textField.text = String.format(newText, indices: inputField.dateFormat.separatorIndices, with: "/")
let rawNumber = newText.filter { $0.isNumber }
let formatted = String.format(rawNumber, indices: inputField.dateFormat.separatorIndices, with: "/")
if inputField.dateFormat.isValid(formatted) || formatted.isEmpty {
textField.text = formatted
}
return false
} else {
return true

View File

@ -190,9 +190,11 @@ open class InputField: EntryFieldBase {
successLabel.textColorConfiguration = primaryColorConfiguration.eraseToAnyColorable()
backgroundColorConfiguration.setSurfaceColors(VDSColor.feedbackSuccessBackgroundOnlight, VDSColor.feedbackSuccessBackgroundOndark, forState: .success)
borderColorConfiguration.setSurfaceColors(VDSColor.feedbackSuccessOnlight, VDSColor.feedbackSuccessOndark, forState: .success)
backgroundColorConfiguration.setSurfaceColors(VDSColor.feedbackSuccessBackgroundOnlight, VDSColor.feedbackSuccessBackgroundOndark, forState: [.success, .focused])
borderColorConfiguration.setSurfaceColors(VDSColor.feedbackSuccessOnlight, VDSColor.feedbackSuccessOndark, forState: .success)
textField.textColorConfiguration = textFieldTextColorConfiguration
}
open override func getFieldContainer() -> UIView {
@ -221,9 +223,9 @@ open class InputField: EntryFieldBase {
super.updateView()
textField.surface = surface
textField.isEnabled = isEnabled
textField.isUserInteractionEnabled = isEnabled && !isReadOnly
textField.textColor = textFieldTextColorConfiguration.getColor(self)
}
open override func updateAccessibility() {
@ -248,7 +250,7 @@ open class InputField: EntryFieldBase {
statusIcon.name = .checkmarkAlt
statusIcon.color = iconColorConfiguration.getColor(self)
statusIcon.surface = surface
statusIcon.isHidden = !isEnabled
statusIcon.isHidden = !isEnabled || state.contains(.focused)
} else {
successLabel.isHidden = true
}
@ -303,6 +305,7 @@ extension InputField: UITextFieldDelegate {
public func textFieldDidBeginEditing(_ textField: UITextField) {
fieldType.handler().textFieldDidBeginEditing(self, textField: textField)
updateContainerView()
updateErrorLabel()
}
public func textFieldDidEndEditing(_ textField: UITextField) {