From 557490868955523a188004ab6a106319a8ddfcf5 Mon Sep 17 00:00:00 2001 From: Tere Date: Fri, 12 Jan 2024 20:07:54 -0600 Subject: [PATCH] Ejercicio SignUpView --- .../UserInterfaceState.xcuserstate | Bin 0 -> 22026 bytes .../Views/Components/FormTextField.swift | 5 +- SwiftUIBasics/Views/SignUpView.swift | 91 ++++++++++++++---- 3 files changed, 78 insertions(+), 18 deletions(-) create mode 100644 SwiftUIBasics.xcodeproj/project.xcworkspace/xcuserdata/diplomado.xcuserdatad/UserInterfaceState.xcuserstate diff --git a/SwiftUIBasics.xcodeproj/project.xcworkspace/xcuserdata/diplomado.xcuserdatad/UserInterfaceState.xcuserstate b/SwiftUIBasics.xcodeproj/project.xcworkspace/xcuserdata/diplomado.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..f53fbab70349e6e2ea7814d7cbd23b0116be6e9d GIT binary patch literal 22026 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 literal 0 HcmV?d00001 diff --git a/SwiftUIBasics/Views/Components/FormTextField.swift b/SwiftUIBasics/Views/Components/FormTextField.swift index cdd161c..ed9b007 100644 --- a/SwiftUIBasics/Views/Components/FormTextField.swift +++ b/SwiftUIBasics/Views/Components/FormTextField.swift @@ -5,12 +5,14 @@ // Created by Diplomado on 09/12/23. // + import SwiftUI struct FormTextField: View { var name = "" @Binding var value: String var isSecure = false + var fieldType: UIKeyboardType = .default var body: some View { VStack { @@ -20,6 +22,7 @@ struct FormTextField: View { .padding(.horizontal) } else { TextField(name, text: $value) + .keyboardType(fieldType) .font(.system(size: 20, weight: .semibold, design: .rounded)) .padding(.horizontal) } @@ -33,7 +36,7 @@ struct FormTextField: View { #Preview { VStack(spacing: 20) { - FormTextField(name: "Email", value: .constant(""), isSecure: false) + FormTextField(name: "Email", value: .constant(""), isSecure: false, fieldType: .emailAddress) FormTextField(name: "Password", value: .constant(""), isSecure: true) } } diff --git a/SwiftUIBasics/Views/SignUpView.swift b/SwiftUIBasics/Views/SignUpView.swift index 6cef5d9..5aeecbb 100644 --- a/SwiftUIBasics/Views/SignUpView.swift +++ b/SwiftUIBasics/Views/SignUpView.swift @@ -2,34 +2,41 @@ // SignUpView.swift // SwiftUIBasics // -// Created by Diplomado on 09/12/23. +// Created by Tere DurĂ¡n on 09/12/23. // import SwiftUI import Combine class SignUpViewModel: ObservableObject { - // inputs - @Published var username: String = "" + // Inputs + @Published var email: String = "" @Published var password: String = "" @Published var passwordConfirm: String = "" - - // outputs - @Published var isValidUsernameLength: Bool = false + + // Outputs + @Published var isValidEmail: Bool = false + @Published var isValidPassword: Bool = false @Published var isValidPasswordLength: Bool = false @Published var isValidPasswordUpperCase: Bool = false + @Published var isValidPasswordLowerCase: Bool = false + @Published var isValidPasswordCase: Bool = false + @Published var passwordContainsSymbol: Bool = false + @Published var passwordContainsNumber: Bool = false @Published var isValidPasswordMatch: Bool = false @Published var isValid: Bool = false private var cancelableSet: Set = [] init() { - $username + $email .receive(on: RunLoop.main) - .map { username in - return username.count >= 4 + .map { email in + let pattern = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}" + let emailFormat = NSPredicate(format:"SELF MATCHES %@", pattern) + return emailFormat.evaluate(with: email) } - .assign(to: \.isValidUsernameLength, on: self) + .assign(to: \.isValidEmail, on: self) .store(in: &cancelableSet) $password @@ -52,6 +59,46 @@ class SignUpViewModel: ObservableObject { } .assign(to: \.isValidPasswordUpperCase, on: self) .store(in: &cancelableSet) + + $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) + + $password + .receive(on: RunLoop.main) + .map { password in + let pattern = /\W+/ + let symbols = Regex(pattern) + if password.contains(symbols) { + return true + } else { + return false + } + } + .assign(to: \.passwordContainsSymbol, on: self) + .store(in: &cancelableSet) + + $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: \.passwordContainsNumber, on: self) + .store(in: &cancelableSet) Publishers.CombineLatest($password, $passwordConfirm) .receive(on: RunLoop.main) @@ -60,8 +107,16 @@ class SignUpViewModel: ObservableObject { } .assign(to: \.isValidPasswordMatch, on: self) .store(in: &cancelableSet) + + Publishers.CombineLatest4($isValidPasswordUpperCase, $isValidPasswordLowerCase, $passwordContainsSymbol, $passwordContainsNumber) + .receive(on: RunLoop.main) + .map { (uppercase, lowercase, symbol, number) in + return uppercase && lowercase && symbol && number + } + .assign(to: \.isValidPasswordCase, on: self) + .store(in: &cancelableSet) - Publishers.CombineLatest4($isValidUsernameLength, $isValidPasswordLength, $isValidPasswordUpperCase, $isValidPasswordMatch) + Publishers.CombineLatest4($isValidEmail, $isValidPasswordLength, $isValidPasswordCase, $isValidPasswordMatch) .map { (a, b, c, d) in return a && b && c && d } @@ -80,13 +135,16 @@ 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: "Email", value: $vm.email, fieldType: .emailAddress) + RequirementText(text: "A valid email format", isValid: vm.isValidEmail) .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: "At least one uppercase letter", isValid: vm.isValidPasswordUpperCase) + RequirementText(text: "At lest one lowercase letter", isValid: vm.isValidPasswordLowerCase) + RequirementText(text: "At least one symbol", isValid: vm.passwordContainsSymbol) + RequirementText(text: "At least one digit", isValid: vm.passwordContainsNumber) } .padding() FormTextField(name: "Confirm Password", value: $vm.passwordConfirm, isSecure: true) @@ -95,7 +153,6 @@ struct SignUpView: View { .padding(.bottom, 50) Button(action: { print("Doing") - // Proceed to the next screen }) { Text("Sign Up") .font(.system(.body, design: .rounded)) @@ -104,7 +161,6 @@ struct SignUpView: View { .padding() .frame(minWidth: 0, maxWidth: .infinity) .background(vm.isValid ? .maryBlue :.turquoise) - // .background(LinearGradient(gradient: Gradient(colors: [.turquoise, .maryBlue]), startPoint: .leading, endPoint: .trailing)) .cornerRadius(10) .padding(.horizontal) } @@ -115,7 +171,6 @@ struct SignUpView: View { .font(.system(.body, design: .rounded)) .bold() Button(action: { - // Proceed to Sign in screen }) { Text("Sign in") .font(.system(.body, design: .rounded)) @@ -132,3 +187,5 @@ struct SignUpView: View { #Preview { SignUpView() } + +