diff --git a/SwiftUIBasics.xcodeproj/xcuserdata/trumann.xcuserdatad/xcschemes/xcschememanagement.plist b/SwiftUIBasics.xcodeproj/xcuserdata/trumann.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..27cd9e4 --- /dev/null +++ b/SwiftUIBasics.xcodeproj/xcuserdata/trumann.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..3809ecf 100644 --- a/SwiftUIBasics/Views/SignUpView.swift +++ b/SwiftUIBasics/Views/SignUpView.swift @@ -16,9 +16,21 @@ class SignUpViewModel: ObservableObject { // outputs @Published var isValidUsernameLength: Bool = false + @Published var isValidPasswordLength: Bool = false + @Published var isValidPasswordUpperCase: Bool = false + + @Published var isValidPasswordLowerCase: Bool = false + + @Published var isValidPasswordHasNumber: Bool = false + + @Published var isValidPasswordHasSpecialCharacter: Bool = false + + + @Published var isValidPasswordMatch: Bool = false + @Published var isValid: Bool = false private var cancelableSet: Set = [] @@ -27,7 +39,12 @@ class SignUpViewModel: ObservableObject { $username .receive(on: RunLoop.main) .map { username in - return username.count >= 4 + let pattern = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}" + if let _ = username.range(of: pattern, options: .regularExpression) { + return true + } else { + return false + } } .assign(to: \.isValidUsernameLength, on: self) .store(in: &cancelableSet) @@ -52,6 +69,57 @@ 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 = "[0-9]" + if let _ = password.range(of: pattern, options: .regularExpression) { + return true + } else { + return false + } + } + .assign(to: \.isValidPasswordHasNumber, on: self) + .store(in: &cancelableSet) + + $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: \.isValidPasswordHasSpecialCharacter, on: self) + .store(in: &cancelableSet) + + $passwordConfirm + .receive(on: RunLoop.main) + .map{ + passwordConfirm in + return self.password == passwordConfirm + } + .assign(to: \.isValidPasswordMatch, on: self) + .store(in: &cancelableSet) Publishers.CombineLatest($password, $passwordConfirm) .receive(on: RunLoop.main) @@ -80,15 +148,27 @@ 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: "e-mail", value: $vm.username) + .autocorrectionDisabled() + .textInputAutocapitalization(.never) + .keyboardType(.emailAddress) + + RequirementText(text: "This field should be an email", isValid: vm.isValidUsernameLength) .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: "One special character", isValid: vm.isValidPasswordHasSpecialCharacter) + RequirementText(text: "At least one number", isValid: vm.isValidPasswordHasNumber) + } .padding() + + FormTextField(name: "Confirm Password", value: $vm.passwordConfirm, isSecure: true) RequirementText(text: "Your confirm password should be the same as password", isValid: vm.isValidPasswordMatch) .padding()