Skip to content

Commit

Permalink
Handled validation and refactor code
Browse files Browse the repository at this point in the history
  • Loading branch information
cp-nirali-s committed Dec 5, 2024
1 parent 5a42f12 commit 9ba8788
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 71 deletions.
9 changes: 9 additions & 0 deletions Splito/Localization/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,9 @@
},
"Enter mobile number" : {
"extractionState" : "manual"
},
"Enter note" : {

},
"Enter the invite code" : {
"extractionState" : "manual"
Expand Down Expand Up @@ -540,6 +543,9 @@
},
"not involved" : {

},
"Note" : {

},
"Note:" : {

Expand Down Expand Up @@ -627,6 +633,9 @@
},
"Reach out to your friends to get the code of the group they created." : {

},
"Reason" : {

},
"Reauthenticate" : {
"extractionState" : "manual"
Expand Down
53 changes: 25 additions & 28 deletions Splito/UI/Login/EmailLogin/EmailLoginView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,7 @@ struct EmailLoginView: View {

VSpacer(16)

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

PasswordFieldView(password: $viewModel.password, focusedField: $focusedField)
VSpacer(8)

HStack {
Expand All @@ -54,13 +50,13 @@ struct EmailLoginView: View {
Spacer()

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

VSpacer(16)

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

VSpacer(40)
}
Expand Down Expand Up @@ -123,41 +119,42 @@ private struct PasswordFieldView: View {
@Binding var password: String
var focusedField: FocusState<EmailLoginViewModel.EmailLoginField?>.Binding

let isPasswordVisible: Bool
var handlePasswordEyeTap: () -> Void
var onEditingChanged: (Bool) -> Void
@State private var isSecured: Bool = true

var body: some View {
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)
ZStack(alignment: .trailing) {
Group {
if isSecured {
SecureField("Enter your password", text: $password)
} else {
TextField("Enter your password", text: $password)
}
}
.font(.subTitle3())
.foregroundStyle(primaryText)
.tint(primaryColor)
.autocapitalization(.none)
.focused(focusedField, equals: .password)
.submitLabel(.done)

Button {
isSecured.toggle()
} label: {
Image(systemName: self.isSecured ? "eye.slash" : "eye")
.accentColor(.gray)
}
}
.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)
}
}
}
83 changes: 40 additions & 43 deletions Splito/UI/Login/EmailLogin/EmailLoginViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ public class EmailLoginViewModel: BaseViewModel, ObservableObject {
@Inject private var preference: SplitoPreference
@Inject private var userRepository: UserRepository

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

@Published var email = ""
@Published var password = ""
Expand All @@ -27,52 +26,57 @@ public class EmailLoginViewModel: BaseViewModel, ObservableObject {
self.router = router
}

// MARK: - User Actions
func onCreateAccountClick() {
showCreateAccountLoading = true
guard validateEmailAndPassword() else { return }

isSignupInProgress = 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)")
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
}
isSignupInProgress = false
self.handleAuthResponse(result: result, error: error, isLogin: false)
}
}

func onEmailLoginClick() {
showLoader = true
guard validateEmailAndPassword() else { return }

isLoginInProgress = 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)")
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
}
isLoginInProgress = false
self.handleAuthResponse(result: result, error: error, isLogin: true)
}
}

private func handleAuthResponse(result: AuthDataResult?, error: Error?, isLogin: Bool) {
if let error {
LogE("EmailLoginViewModel: \(#function) Error during \(isLogin ? "login" : "sign up"): \(error)")
handleFirebaseAuthErrors(error)
} else if let result {
let user = AppUser(id: result.user.uid, firstName: "", lastName: "",
emailId: email, phoneNumber: nil, loginType: .Email)
Task { await storeUser(user: user) }
LogD("EmailLoginViewModel: \(#function) User \(isLogin ? "logged in" : "signed up") successfully.")
} else {
self.alert = .init(message: "Contact Support")
self.showAlert = true
}
}

private func validateEmailAndPassword() -> Bool {
if !email.isValidEmail {
showAlertFor(title: "Error", message: "Please enter a valid email address.")
return false
}
if password.count < 4 {
showAlertFor(title: "Error", message: "Password must be at least 4 characters long.")
return false
}

return true
}

private func storeUser(user: AppUser) async {
do {
let user = try await userRepository.storeUser(user: user)
Expand All @@ -95,14 +99,7 @@ public class EmailLoginViewModel: BaseViewModel, ObservableObject {
router.pop()
}

func handlePasswordEyeTap() {
isPasswordVisible.toggle() // Toggle password visibility
}

func onEditingChanged(abc: Bool) {

}

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

Expand Down

0 comments on commit 9ba8788

Please sign in to comment.