Skip to content

Commit

Permalink
Managed create account and login btn click
Browse files Browse the repository at this point in the history
  • Loading branch information
cp-nirali-s committed Dec 5, 2024
1 parent a5ba912 commit c9ba99f
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 81 deletions.
20 changes: 10 additions & 10 deletions Splito/Localization/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -314,9 +314,6 @@
},
"Email" : {
"extractionState" : "manual"
},
"Email address" : {

},
"Email sent successfully!" : {
"extractionState" : "manual"
Expand All @@ -341,6 +338,9 @@
},
"Enter the percentage split that's fair for your situation." : {
"extractionState" : "manual"
},
"Enter your email" : {

},
"Enter your email address" : {
"extractionState" : "manual"
Expand All @@ -353,6 +353,9 @@
},
"Enter your note here..." : {
"extractionState" : "manual"
},
"Enter your password" : {

},
"Enter your phone number" : {
"extractionState" : "manual"
Expand Down Expand Up @@ -381,7 +384,7 @@
"First Name" : {
"extractionState" : "manual"
},
"Forgot your password?" : {
"Forgot password?" : {

},
"get back" : {
Expand Down Expand Up @@ -724,6 +727,9 @@
"Sign in with Apple" : {
"extractionState" : "manual"
},
"Sign in with Email" : {
"extractionState" : "manual"
},
"Sign in with Google" : {
"extractionState" : "manual"
},
Expand Down Expand Up @@ -996,12 +1002,6 @@
},
"Your device cannot send email." : {
"extractionState" : "manual"
},
"Your email address" : {

},
"Your password" : {

},
"Your requested data not found." : {
"extractionState" : "manual"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "email_svgrepo.com.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
132 changes: 86 additions & 46 deletions Splito/UI/Login/EmailLogin/EmailLoginView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,47 @@ struct EmailLoginView: View {
AppLogoView(geometry: .constant(proxy))

Group {
LoginTitleView(titleText: "Continue your journey")

VSpacer(16)

LoginSubtitleView(subtitleText: "Sign in to access your account and enjoy all its features.")

VSpacer(24)

EmailFieldView(email: $viewModel.email, focusedField: $focusedField)

VSpacer(16)

PasswordFieldView(password: $viewModel.password, focusedField: $focusedField,
isPasswordVisible: viewModel.isPasswordVisible,
handlePasswordEyeTap: viewModel.handlePasswordEyeTap,
onEditingChanged: viewModel.onEditingChanged(abc:))

VSpacer(8)

HStack {
Spacer()

Button(action: viewModel.onForgotPasswordClick) {
Text("Forgot password?")
.font(.caption1())
.foregroundStyle(disableText)
}
}

Spacer()

PrimaryButton(text: "Sign in", isEnabled: !viewModel.email.isEmpty && !viewModel.password.isEmpty,
PrimaryButton(text: "Login", isEnabled: !viewModel.email.isEmpty && !viewModel.password.isEmpty,
showLoader: viewModel.showLoader, onClick: viewModel.onEmailLoginClick)
.padding(.top, 8)

Button("Forgot your password?") {}
.padding()
.underline()
VSpacer(16)

PrimaryButton(text: "Create account", isEnabled: !viewModel.email.isEmpty && !viewModel.password.isEmpty,
showLoader: viewModel.showCreateAccountLoading, onClick: viewModel.onCreateAccountClick)

VSpacer(40)
}
.padding(.horizontal, 16)
.frame(maxWidth: isIpad ? 600 : nil, alignment: .leading)
Expand All @@ -48,12 +74,15 @@ struct EmailLoginView: View {
}
}
.background(surfaceColor)
.backport.alert(isPresented: $viewModel.showAlert, alertStruct: viewModel.alert)
.alertView.alert(isPresented: $viewModel.showAlert, alertStruct: viewModel.alert)
.ignoresSafeArea(edges: .top)
.toolbar(.hidden, for: .navigationBar)
.overlay(alignment: .topLeading) {
BackButton(onClick: viewModel.handleBackBtnTap)
}
.onTapGesture {
UIApplication.shared.endEditing()
}
}
}

Expand All @@ -63,24 +92,29 @@ private struct EmailFieldView: View {
var focusedField: FocusState<EmailLoginViewModel.EmailLoginField?>.Binding

var body: some View {
Text("Email address")
.font(.subTitle1())
.foregroundStyle(secondaryText)

TextField("Your email address", text: $email)
.autocapitalization(.none)
.keyboardType(.emailAddress)
.padding(16)
.overlay {
RoundedRectangle(cornerRadius: 12)
.stroke(outlineColor, lineWidth: 1)
}
.onSubmit {
focusedField.wrappedValue = .password
}
.focused(focusedField, equals: .email)
.submitLabel(.next)
.padding(.top, 16)
VStack(alignment: .leading, spacing: 8) {
Text("Email")
.font(.body3())
.foregroundStyle(secondaryText)

TextField("Enter your email", text: $email)
.font(.subTitle3())
.foregroundStyle(primaryText)
.tint(primaryColor)
.autocapitalization(.none)
.keyboardType(.emailAddress)
.padding(.vertical, 12)
.padding(.horizontal, 16)
.overlay {
RoundedRectangle(cornerRadius: 12)
.stroke(outlineColor, lineWidth: 1)
}
.onSubmit {
focusedField.wrappedValue = .password
}
.focused(focusedField, equals: .email)
.submitLabel(.next)
}
}
}

Expand All @@ -94,30 +128,36 @@ private struct PasswordFieldView: View {
var onEditingChanged: (Bool) -> Void

var body: some View {
Text("Password")
.font(.subTitle1())
.foregroundStyle(secondaryText)

HStack {
if isPasswordVisible {
TextField("Your password", text: $password, onEditingChanged: onEditingChanged)
} else {
SecureField("Your password", text: $password)
VStack(alignment: .leading, spacing: 8) {
Text("Password")
.font(.body3())
.foregroundStyle(secondaryText)

HStack {
if isPasswordVisible {
TextField("Enter your password", text: $password, onEditingChanged: onEditingChanged)
} else {
SecureField("Enter your password", text: $password)
}
}
.font(.subTitle3())
.foregroundStyle(primaryText)
.tint(primaryColor)
.autocapitalization(.none)
.padding(.vertical, 12)
.padding(.horizontal, 16)
.overlay {
RoundedRectangle(cornerRadius: 12)
.stroke(outlineColor, lineWidth: 1)
}
.overlay(alignment: .trailing) {
Image(systemName: isPasswordVisible ? "eye.fill" : "eye.slash.fill")
.font(.system(size: 14))
.padding()
.onTapGesture(perform: handlePasswordEyeTap)
}
.focused(focusedField, equals: .password)
.submitLabel(.done)
}
.padding(16)
.overlay {
RoundedRectangle(cornerRadius: 12)
.stroke(outlineColor, lineWidth: 1)
}
.overlay(alignment: .trailing) {
Image(systemName: isPasswordVisible ? "eye.fill" : "eye.slash.fill")
.font(.system(size: 14))
.padding()
.onTapGesture(perform: handlePasswordEyeTap)
}
.focused(focusedField, equals: .password) // Bind focus to password field
.submitLabel(.done)
.padding(.top, 16)
}
}
79 changes: 58 additions & 21 deletions Splito/UI/Login/EmailLogin/EmailLoginViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ public class EmailLoginViewModel: BaseViewModel, ObservableObject {
@Inject private var preference: SplitoPreference
@Inject private var userRepository: UserRepository

@Published var isPasswordVisible = false
@Published private(set) var showLoader = false
@Published private(set) var showCreateAccountLoading = false
@Published private(set) var isPasswordVisible = false

@Published var email = ""
@Published var password = ""

Expand All @@ -25,33 +27,48 @@ public class EmailLoginViewModel: BaseViewModel, ObservableObject {
self.router = router
}

func onEmailSignUp() {
FirebaseAuth.Auth.auth().createUser(withEmail: email, password: password) { [weak self] authResult, error in
guard let self = self else { return }
func onCreateAccountClick() {
showCreateAccountLoading = true

FirebaseAuth.Auth.auth().createUser(withEmail: email, password: password) { [weak self] result, error in
guard let self else { return }
showCreateAccountLoading = false
if let error {
LogE("EmailLoginViewModel: Error during sign up: \(error)")
self.alert = .init(message: "Sign-up failed: \(error)")
self.showAlert = true
} else if let authResult {
let user = AppUser(id: authResult.user.uid, firstName: "", lastName: "",
handleFirebaseAuthErrors(error)
} else if let result {
let user = AppUser(id: result.user.uid, firstName: "", lastName: "",
emailId: email, phoneNumber: nil, loginType: .Email)
Task {
await self.storeUser(user: user)
}
LogD("EmailLoginViewModel: \(#function) Logged in User: \(result.user)")
} else {
self.alert = .init(message: "Contact Support")
self.showAlert = true
}
}
}

func onEmailLoginClick() {
FirebaseAuth.Auth.auth().signIn(withEmail: email, password: password) { [weak self] _, error in
guard let self = self else { return }
showLoader = true

FirebaseAuth.Auth.auth().signIn(withEmail: email, password: password) { [weak self] result, error in
guard let self else { return }
showLoader = false
if let error {
LogE("EmailLoginViewModel: Error during login: \(error)")
self.alert = .init(message: "Login failed: \(error)")
self.showAlert = true
handleFirebaseAuthErrors(error)
} else if let result {
let user = AppUser(id: result.user.uid, firstName: "", lastName: "",
emailId: email, phoneNumber: nil, loginType: .Email)
Task {
await self.storeUser(user: user)
}
LogD("EmailLoginViewModel: \(#function) Logged in User: \(result.user)")
} else {
LogD("EmailLoginViewModel: User logged in successfully.")
self.onLoginSuccess()
self.alert = .init(message: "Contact Support")
self.showAlert = true
}
}
}
Expand All @@ -61,7 +78,7 @@ public class EmailLoginViewModel: BaseViewModel, ObservableObject {
let user = try await userRepository.storeUser(user: user)
self.preference.isVerifiedUser = true
self.preference.user = user
self.onLoginSuccess()
self.router.popToRoot()
LogD("EmailLoginViewModel: \(#function) User stored successfully.")
} catch {
LogE("EmailLoginViewModel: \(#function) Failed to store user: \(error).")
Expand All @@ -70,12 +87,8 @@ public class EmailLoginViewModel: BaseViewModel, ObservableObject {
}
}

private func onLoginSuccess() {
// if onLoginSuccess == nil {
// router?.popToRoot()
// } else {
// onLoginSuccess?(otp)
// }
func onForgotPasswordClick() {

}

func handleBackBtnTap() {
Expand All @@ -89,6 +102,30 @@ public class EmailLoginViewModel: BaseViewModel, ObservableObject {
func onEditingChanged(abc: Bool) {

}

private func handleFirebaseAuthErrors(_ error: Error) {
let errorCode = (error as NSError).code

switch FirebaseAuth.AuthErrorCode(rawValue: errorCode) {
case .webContextCancelled:
showAlertFor(message: "Something went wrong! Please try after some time.")
case .tooManyRequests:
showAlertFor(message: "Too many attempts, please try after some time.")
case .invalidEmail:
showAlertFor(title: "Invalid Email", message: "The email address is not valid. Please check and try again.")
case .wrongPassword:
showAlertFor(title: "Incorrect Password", message: "The password you entered is incorrect. Please try again.")
case .userNotFound:
showAlertFor(title: "Account Not Found", message: "No account found with the provided email address. Please sign up.")
case .userDisabled:
showAlertFor(title: "Account Disabled", message: "This account has been disabled. Please contact support.")
case .invalidCredential:
showAlertFor(title: "Incorrect email or password", message: "The email or password you entered is incorrect. Please try again.")
default:
LogE("EmailLoginViewModel: \(#function) Phone login fail with error: \(error).")
showAlertFor(title: "Authentication failed", message: "Apologies, we were not able to complete the authentication process. Please try again later.")
}
}
}

extension EmailLoginViewModel {
Expand Down
2 changes: 2 additions & 0 deletions Splito/UI/Login/LoginView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ private struct LoginOptionsView: View {
LoginOptionsButtonView(systemImage: ("phone.fill", primaryLightText, (12, 12)),
buttonName: "Sign in with Phone Number", bgColor: primaryColor,
buttonTextColor: primaryLightText, showLoader: false, onClick: onPhoneLoginClick)
LoginOptionsButtonView(image: .emailIcon, buttonName: "Sign in with Email", bgColor: primaryColor,
buttonTextColor: primaryLightText, showLoader: false, onClick: onEmailLoginClick)
}
.padding(.horizontal, 16)
.frame(maxWidth: isIpad ? 600 : nil, alignment: .center)
Expand Down
Loading

0 comments on commit c9ba99f

Please sign in to comment.