diff --git a/SwiftUIBasics.xcodeproj/project.xcworkspace/xcuserdata/romark17.xcuserdatad/UserInterfaceState.xcuserstate b/SwiftUIBasics.xcodeproj/project.xcworkspace/xcuserdata/romark17.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..c35cf2a Binary files /dev/null and b/SwiftUIBasics.xcodeproj/project.xcworkspace/xcuserdata/romark17.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/SwiftUIBasics.xcodeproj/xcuserdata/romark17.xcuserdatad/xcschemes/xcschememanagement.plist b/SwiftUIBasics.xcodeproj/xcuserdata/romark17.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..27cd9e4 --- /dev/null +++ b/SwiftUIBasics.xcodeproj/xcuserdata/romark17.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + SwiftUIBasics.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/SwiftUIBasics/Views/SignUpView.swift b/SwiftUIBasics/Views/SignUpView.swift index 6cef5d9..d4fc6db 100644 --- a/SwiftUIBasics/Views/SignUpView.swift +++ b/SwiftUIBasics/Views/SignUpView.swift @@ -1,16 +1,11 @@ -// -// SignUpView.swift -// SwiftUIBasics -// -// Created by Diplomado on 09/12/23. -// - import SwiftUI import Combine class SignUpViewModel: ObservableObject { // inputs @Published var username: String = "" + @Published var mail: String = "" + @Published var password: String = "" @Published var passwordConfirm: String = "" @@ -18,20 +13,41 @@ class SignUpViewModel: ObservableObject { @Published var isValidUsernameLength: Bool = false @Published var isValidPasswordLength: Bool = false @Published var isValidPasswordUpperCase: Bool = false + + @Published var isValidMail: Bool = false + + @Published var isValidPasswordLowerCase: Bool = false + @Published var isValidPasswordHasASymbol: Bool = false + @Published var isValidPasswordHasANumber: Bool = false + + + + @Published var isValidPasswordMatch: Bool = false @Published var isValid: Bool = false private var cancelableSet: Set = [] init() { - $username +// $username +// .receive(on: RunLoop.main) +// .map { username in +// return username.count >= 4 +// } +// .assign(to: \.isValidUsernameLength, on: self) +// .store(in: &cancelableSet) + + $mail .receive(on: RunLoop.main) - .map { username in - return username.count >= 4 + .map { mail in + let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}" + let emailPred = NSPredicate(format:"SELF MATCHES %@", emailRegEx) + return emailPred.evaluate(with: mail) } - .assign(to: \.isValidUsernameLength, on: self) + .assign(to: \.isValidMail, on: self) .store(in: &cancelableSet) + $password .receive(on: RunLoop.main) .map { password in @@ -40,10 +56,11 @@ class SignUpViewModel: ObservableObject { .assign(to: \.isValidPasswordLength, on: self) .store(in: &cancelableSet) + // isValidPasswordUpperCase $password .receive(on: RunLoop.main) .map { password in - let pattern = "[A-Z]" + let pattern = "[A-Z]+" if let _ = password.range(of: pattern, options: .regularExpression) { return true } else { @@ -52,6 +69,50 @@ class SignUpViewModel: ObservableObject { } .assign(to: \.isValidPasswordUpperCase, on: self) .store(in: &cancelableSet) + + // isValidPasswordLowerCase + $password + .receive(on: RunLoop.main) + .map { password in + let pattern = "[a-z]" + if let _ = password.range(of: pattern, options: .regularExpression) { + return true + } else { + return false + } + } + .assign(to: \.isValidPasswordLowerCase, on: self) + .store(in: &cancelableSet) + + // isValidPasswordHasASymbol + $password + .receive(on: RunLoop.main) + .map { password in + let pattern = "[!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>\\/?]" + if let _ = password.range(of: pattern, options: .regularExpression) { + return true + } else { + return false + } + } + .assign(to: \.isValidPasswordHasASymbol, on: self) + .store(in: &cancelableSet) + + // isValidPasswordHasANumber + $password + .receive(on: RunLoop.main) + .map { password in + let pattern = "[0-9]+" + if let _ = password.range(of: pattern, options: .regularExpression) { + return true + } else { + return false + } + } + .assign(to: \.isValidPasswordHasANumber, on: self) + .store(in: &cancelableSet) + + Publishers.CombineLatest($password, $passwordConfirm) .receive(on: RunLoop.main) @@ -80,13 +141,26 @@ struct SignUpView: View { .bold() .foregroundStyle(.maryBlue) .padding(.bottom, 30) - FormTextField(name: "Username", value: $vm.username) - RequirementText(text: "A minimum of 4 characters", isValid: vm.isValidUsernameLength) + +// FormTextField(name: "Username", value: $vm.username) +// RequirementText(text: "A minimum of 4 characters", isValid: vm.isValidUsernameLength) +// .padding() + + FormTextField(name: "Mail", value: $vm.mail) + .keyboardType(.emailAddress) + + + RequirementText(text: "Must be a valid mail", isValid: vm.isValidMail) .padding() + FormTextField(name: "Password", value: $vm.password, isSecure: true) VStack { RequirementText(text: "A minimum of 8 characters", isValid: vm.isValidPasswordLength) RequirementText(text: "One uppercase letter", isValid: vm.isValidPasswordUpperCase) + RequirementText(text: "One lowercase letter", isValid: vm.isValidPasswordLowerCase) + RequirementText(text: "At least one symbol", isValid: vm.isValidPasswordHasASymbol) + RequirementText(text: "At least one number", isValid: vm.isValidPasswordHasANumber) + } .padding() FormTextField(name: "Confirm Password", value: $vm.passwordConfirm, isSecure: true) @@ -132,3 +206,4 @@ struct SignUpView: View { #Preview { SignUpView() } +