From ef9209e3accb0526bd5bdcca02e8f6a809307f81 Mon Sep 17 00:00:00 2001 From: Eirado <111468283+Eirado@users.noreply.github.com> Date: Tue, 11 Feb 2025 08:52:07 -0300 Subject: [PATCH 01/22] initial --- .../Lua/LuaErrors/LuaConnectivityError.swift | 29 ++++++ .../Lua/LuaErrors/LuaNetworkError.swift | 34 +++++++ .../Lua/LuaErrors/LuaUserAccountError.swift | 22 +++++ .../LuaHandlers/LuaAlertErrorHandler.swift | 21 ++++ .../Lua/Main/LuaAlertErrorHandlerFabric.swift | 12 +++ .../LuaResetPasswordViewModelFabric.swift | 13 +++ .../ResetPassword/LuaResetPasswordView.swift | 16 +++ .../LuaResetPasswordViewController.swift | 98 +++++-------------- .../LuaResetPasswordViewModel.swift | 61 ++++++++++++ 9 files changed, 231 insertions(+), 75 deletions(-) create mode 100644 CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaConnectivityError.swift create mode 100644 CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaNetworkError.swift create mode 100644 CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaUserAccountError.swift create mode 100644 CleanCodeApp/Modules/Features/Lua/LuaHandlers/LuaAlertErrorHandler.swift create mode 100644 CleanCodeApp/Modules/Features/Lua/Main/LuaAlertErrorHandlerFabric.swift create mode 100644 CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFabric.swift create mode 100644 CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift create mode 100644 CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift diff --git a/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaConnectivityError.swift b/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaConnectivityError.swift new file mode 100644 index 0000000..5e09b66 --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaConnectivityError.swift @@ -0,0 +1,29 @@ +// +// LuaConnecti.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 10/02/25. +// + +import Foundation + +enum LuaConnectivityError: Error { + case noInternetConnection +} + +extension LuaConnectivityError: LocalizedError { + + var errorTitle: String? { + switch self { + case .noInternetConnection: + return "Sem Conexão com a Internet." + } + } + + var errorDescription: String? { + switch self { + case .noInternetConnection: + return "Você não está conectado à internet. Verifique sua conexão e tente novamente." + } + } +} diff --git a/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaNetworkError.swift b/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaNetworkError.swift new file mode 100644 index 0000000..a522faa --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaNetworkError.swift @@ -0,0 +1,34 @@ +// +// LuaNetworkError.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 10/02/25. +// + +import Foundation + +enum LuaNetworkError: Error { + case decodeError + case noData + case invalidURL + case invalidStatusCode + case networkError +} + +extension LuaNetworkError: LocalizedError { + + var errorDescription: String? { + switch self { + case .decodeError: + return "Error during data decoding" + case .noData: + return "Data error" + case .invalidURL: + return "Invalid URL" + case .invalidStatusCode: + return "Invalid status code" + case .networkError: + return "An error has occurred. Please verify your connection." + } + } +} diff --git a/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaUserAccountError.swift b/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaUserAccountError.swift new file mode 100644 index 0000000..1ee1484 --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaUserAccountError.swift @@ -0,0 +1,22 @@ +// +// LuaPasswordRecoveryError.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 10/02/25. +// + +import Foundation + +enum LuaUserAccountError: Error { + case invalidEmail +} + +extension LuaUserAccountError: LocalizedError { + + var errorDescription: String? { + switch self { + case .invalidEmail: + return "O e-mail informado é inválido. Verifique e tente novamente." + } + } +} diff --git a/CleanCodeApp/Modules/Features/Lua/LuaHandlers/LuaAlertErrorHandler.swift b/CleanCodeApp/Modules/Features/Lua/LuaHandlers/LuaAlertErrorHandler.swift new file mode 100644 index 0000000..4da1c63 --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/LuaHandlers/LuaAlertErrorHandler.swift @@ -0,0 +1,21 @@ +// +// LuaAlert.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 11/02/25. +// + +import UIKit + +public protocol LuaAlertErrorHandlerProtocol { + func handle(error: Error, from viewController: UIViewController, alertTitle: String?) +} + +final class LuaAlertErrorHandler: LuaAlertErrorHandlerProtocol { + public func handle(error: Error, from viewController: UIViewController, alertTitle: String?) { + let alertController = UIAlertController(title: alertTitle, message: error.localizedDescription, preferredStyle: .alert) + let action = UIAlertAction(title: "OK", style: .default) + alertController.addAction(action) + viewController.present(alertController, animated: true) + } +} diff --git a/CleanCodeApp/Modules/Features/Lua/Main/LuaAlertErrorHandlerFabric.swift b/CleanCodeApp/Modules/Features/Lua/Main/LuaAlertErrorHandlerFabric.swift new file mode 100644 index 0000000..8ba0738 --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/Main/LuaAlertErrorHandlerFabric.swift @@ -0,0 +1,12 @@ +// +// LuaAlertErrorHandlerFabric.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 11/02/25. +// + +public struct LuaAlertErrorHandlerFabric { + static func makeAlertErrorHandle() -> LuaAlertErrorHandlerProtocol { + return LuaAlertErrorHandler() + } +} diff --git a/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFabric.swift b/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFabric.swift new file mode 100644 index 0000000..6579daf --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFabric.swift @@ -0,0 +1,13 @@ +// +// LuaResetPasswordViewModelFabric.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 11/02/25. +// + +public struct LuaResetPasswordViewModelFabric { + static func makeLuaResetPasswordViewModel() -> LuaResetPasswordViewModel { + let alertErrorHandler = LuaAlertErrorHandlerFabric.makeAlertErrorHandle() + return LuaResetPasswordViewModel(alertHandler: alertErrorHandler) + } +} diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift new file mode 100644 index 0000000..6374e85 --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift @@ -0,0 +1,16 @@ +// +// LuaResetPasswordView.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 11/02/25. +// + +import UIKit + + +class LuaResetPasswordView: UIView { + + +} + + diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift index 9ec9ab6..0c537b7 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift @@ -1,10 +1,5 @@ import UIKit -enum LuaPasswordRecoveryError: Error { - case invalidEmail - case noInternetConnection -} - class LuaResetPasswordViewController: UIViewController { @IBOutlet weak var emailTextField: UITextField! @@ -16,7 +11,7 @@ class LuaResetPasswordViewController: UIViewController { @IBOutlet weak var passwordRecoverySuccessView: UIView! @IBOutlet weak var emailLabel: UILabel! - var emaiInputed: String { + var emailInputted: String { get { guard let emailInput = emailTextField.text?.trimmingCharacters(in: .whitespaces) else { return "" @@ -24,10 +19,14 @@ class LuaResetPasswordViewController: UIViewController { return emailInput } } + var hasRequestedRecovery = false + let viewModel = LuaResetPasswordViewModelFabric.makeLuaResetPasswordViewModel() + override func viewDidLoad() { super.viewDidLoad() + setupView() } @@ -49,70 +48,34 @@ class LuaResetPasswordViewController: UIViewController { return } do { - try validatePasswordRecovery() - let parametersForRecoverPassword = makePasswordResetParams() - sendPasswordResetRequest(parameters: parametersForRecoverPassword) + try validateEmailFormat() + resquestPasswordReset() + self.displayPasswordResetSuccessUI() self.view.endEditing(true) - } catch let error { - showPasswordRecoveryError(error: error as! LuaPasswordRecoveryError) - return + } catch { + displayFormError(textField: emailTextField, label: emailErrorLabel, errorText: LuaUserAccountError.invalidEmail.localizedDescription) } } - func showPasswordRecoveryError(error: LuaPasswordRecoveryError) { - switch error { - case LuaPasswordRecoveryError.invalidEmail: - showFormError(textField: emailTextField, label: emailErrorLabel, errorText: "Verifique o e-mail informado") - case LuaPasswordRecoveryError.noInternetConnection: - Globals.showNoInternetCOnnection(controller: self) - } + func resquestPasswordReset() { + viewModel.startPasswordResetRequest(targetViewController: self, emailInputted: emailInputted) } - func validatePasswordRecovery() throws { - guard validateEmailForm() else { - throw LuaPasswordRecoveryError.invalidEmail + func validateEmailFormat() throws { + guard viewModel.validateEmailFormat(inputedEmail: emailInputted) else { + throw LuaUserAccountError.invalidEmail } - guard ConnectivityManager.shared.isConnected else { - throw LuaPasswordRecoveryError.noInternetConnection - } - } - - func makePasswordResetParams() -> [String : String] { - let passwordResetParameters = [ - "email": emaiInputed - ] - return passwordResetParameters } - func sendPasswordResetRequest(parameters: [String : String]) { - BadNetworkLayer.shared.resetPassword(self, parameters: parameters) { (success) in - if success { - self.showPasswordResetSuccessUI() - return - } - self.showPasswordResetErrorAlert() - } - } - - func showPasswordResetSuccessUI() { + func displayPasswordResetSuccessUI() { self.hasRequestedRecovery = true self.emailTextField.isHidden = true self.emailErrorLabel.isHidden = true self.passwordRecoverySuccessView.isHidden = false - self.emailLabel.text = emaiInputed + self.emailLabel.text = emailInputted self.recoverPasswordButton.setTitle("Voltar", for: .normal) } - func showPasswordResetErrorAlert() { - let alertController = UIAlertController( - title: "Ops..", - message: "Algo de errado aconteceu. Tente novamente mais tarde.", - preferredStyle: .alert) - let action = UIAlertAction(title: "OK", style: .default) - alertController.addAction(action) - self.present(alertController, animated: true) - } - @IBAction func onLoginButtonTapped(_ sender: Any) { dismiss(animated: true) } @@ -138,23 +101,7 @@ class LuaResetPasswordViewController: UIViewController { present(LuaCreateAccountViewController, animated: true) } - - func validateEmailForm() -> Bool { - let isEmailFormatValid = validateEmailFormat() - if isEmailFormatValid { - return true - } - return false - } - - func validateEmailFormat() -> Bool { - let isEmailFormatValid = emaiInputed.contains(".") && - emaiInputed.contains("@") && - emaiInputed.count > 5 - return isEmailFormatValid - } - - func showFormError(textField: UITextField, label: UILabel, errorText: String) { + func displayFormError(textField: UITextField, label: UILabel, errorText: String) { textField.setErrorColor() label.textColor = .red label.text = errorText @@ -221,20 +168,21 @@ extension LuaResetPasswordViewController { extension LuaResetPasswordViewController { func validateExistingEmailInput(){ - if !emaiInputed.isEmpty { - emailTextField.text = emaiInputed + if !emailInputted.isEmpty { + emailTextField.text = emailInputted emailTextField.isEnabled = false } } func updatePasswordRecoveryButtonState() { - let isEnabled = !emaiInputed.isEmpty - recoverPasswordButton.setTitleColor(.white, for: .normal) + let isEnabled = !emailInputted.isEmpty updatePasswordRecoverButtonStatus(newStatus: isEnabled) } func updatePasswordRecoverButtonStatus(newStatus: Bool) { recoverPasswordButton.backgroundColor = newStatus ? .blue : .gray + recoverPasswordButton.setTitleColor(newStatus ? .white: .blue, for: .normal) recoverPasswordButton.isEnabled = newStatus } } + diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift new file mode 100644 index 0000000..7e40ad1 --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift @@ -0,0 +1,61 @@ +// +// Untitled.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 10/02/25. +// + +import UIKit + +class LuaResetPasswordViewModel { + + private let alertHandler: LuaAlertErrorHandlerProtocol + + init(alertHandler: LuaAlertErrorHandlerProtocol) { + self.alertHandler = alertHandler + } + + func startPasswordResetRequest(targetViewController: UIViewController, emailInputted: String) { + do { + try validateConnectivity(emailInputted: emailInputted) + + let passwordParameters = makePasswordResetParams(inputedEmail: emailInputted) + sendPasswordResetRequest(targetViewController: targetViewController, parameters: passwordParameters) + } catch let error as LuaConnectivityError { + alertHandler.handle(error: error, from: targetViewController, alertTitle: error.errorTitle) + } catch { + alertHandler.handle(error: error, from: targetViewController, alertTitle: "Algo de errado aconteceu. Tente novamente mais tarde.") + } + } + + + private func sendPasswordResetRequest(targetViewController: UIViewController, parameters: [String : String]) { + BadNetworkLayer.shared.resetPassword(targetViewController, parameters: parameters) { succes in // need to refactor + if succes { + + } + // show alert + } + } + + private func makePasswordResetParams(inputedEmail: String) -> [String : String] { + let passwordResetParameters = [ + "email": inputedEmail + ] + return passwordResetParameters + } + + private func validateConnectivity(emailInputted: String) throws { + guard ConnectivityManager.shared.isConnected else { + throw LuaConnectivityError.noInternetConnection + } + } + + func validateEmailFormat(inputedEmail: String) -> Bool { + let isEmailFormatValid = inputedEmail.contains(".") && + inputedEmail.contains("@") && + inputedEmail.count > 5 + return isEmailFormatValid + } +} + From 3b9cfc38c1100b7dba5652c0b45288b7fb3fc27c Mon Sep 17 00:00:00 2001 From: Eirado <111468283+Eirado@users.noreply.github.com> Date: Tue, 11 Feb 2025 12:06:23 -0300 Subject: [PATCH 02/22] starting Coordinator --- .../HomeFlow/Home/LuaHomeViewController.swift | 1 + .../LuaResetPasswordViewController.swift | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/CleanCodeApp/Modules/Features/Lua/HomeFlow/Home/LuaHomeViewController.swift b/CleanCodeApp/Modules/Features/Lua/HomeFlow/Home/LuaHomeViewController.swift index 54cc773..69a2da1 100644 --- a/CleanCodeApp/Modules/Features/Lua/HomeFlow/Home/LuaHomeViewController.swift +++ b/CleanCodeApp/Modules/Features/Lua/HomeFlow/Home/LuaHomeViewController.swift @@ -44,4 +44,5 @@ class LuaHomeViewController: UIViewController { } class HomeView: UIView { + } diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift index 0c537b7..6f8655a 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift @@ -186,3 +186,19 @@ extension LuaResetPasswordViewController { } } +class Coordinator { + + + let navigationController: UINavigationController + let viewStack: [UIViewController] = [] + + init(navigationController: UINavigationController) { + self.navigationController = navigationController + } + + func push() { + +// navigationController.pushViewController(<#T##viewController: UIViewController##UIViewController#>, animated: <#T##Bool#>) + } +} + From 3439387e32df6e568abc5fd7027244c7ee9a6c6a Mon Sep 17 00:00:00 2001 From: Eirado <111468283+Eirado@users.noreply.github.com> Date: Tue, 11 Feb 2025 22:05:27 -0300 Subject: [PATCH 03/22] First Coordinator done --- .DS_Store | Bin 6148 -> 6148 bytes CleanCodeApp/AppDelegate/SceneDelegate.swift | 2 +- .../Lua/Coordinator/LuaBasicCoordinator.swift | 37 ++++++++++ ...wift => LuaAlertErrorHandlerFactory.swift} | 2 +- .../Lua/Main/LuaBasicCoordinatorFactory.swift | 14 ++++ .../LuaContactUsViewControllerFactory.swift | 14 ++++ ...uaCreateAccountViewControllerFactory.swift | 14 ++++ ...=> LuaResetPasswordViewModelFactory.swift} | 7 +- .../LuaResetPasswordViewController.swift | 65 ++++++------------ .../LuaResetPasswordViewModel.swift | 22 ++++-- 10 files changed, 124 insertions(+), 53 deletions(-) create mode 100644 CleanCodeApp/Modules/Features/Lua/Coordinator/LuaBasicCoordinator.swift rename CleanCodeApp/Modules/Features/Lua/Main/{LuaAlertErrorHandlerFabric.swift => LuaAlertErrorHandlerFactory.swift} (83%) create mode 100644 CleanCodeApp/Modules/Features/Lua/Main/LuaBasicCoordinatorFactory.swift create mode 100644 CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewControllerFactory.swift create mode 100644 CleanCodeApp/Modules/Features/Lua/Main/LuaCreateAccountViewControllerFactory.swift rename CleanCodeApp/Modules/Features/Lua/Main/{LuaResetPasswordViewModelFabric.swift => LuaResetPasswordViewModelFactory.swift} (51%) diff --git a/.DS_Store b/.DS_Store index 92b50aae85de97f11db3dd046fe95c2a56b69f82..7d7702cfd4ccaa3561b219af4913da410dafc4a3 100644 GIT binary patch delta 287 zcmZoMXfc@J&&awlU^gQxD+2=q&tw56iTb4S;)0}{{3M{j_N0QG%;FLQgKLaT%q*;I z>>TVI+#IpN8TsYGC5a`a#ZHMu(I8$(etu38jGdSimYG@}FCgNapI4HYnU`7w){vQ! z3RDsko|%`DU+$D&nwL@x)*B3w;Naxoj295EcBwWs*HJLCFs;>5sJ1jR&`~fkGpViR z LuaAlertErrorHandlerProtocol { return LuaAlertErrorHandler() } diff --git a/CleanCodeApp/Modules/Features/Lua/Main/LuaBasicCoordinatorFactory.swift b/CleanCodeApp/Modules/Features/Lua/Main/LuaBasicCoordinatorFactory.swift new file mode 100644 index 0000000..319d5ac --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/Main/LuaBasicCoordinatorFactory.swift @@ -0,0 +1,14 @@ +// +// Untitled.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 11/02/25. +// + +import UIKit + +public struct LuaBasicCoordinatorFactory { + static func makeBasicCoordinator() -> LuaCoordinatorProtocol { + return LuaBasicCoordinator() + } +} diff --git a/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewControllerFactory.swift b/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewControllerFactory.swift new file mode 100644 index 0000000..81902b5 --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewControllerFactory.swift @@ -0,0 +1,14 @@ +// +// LuaContactUsViewControllerFactory.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 11/02/25. +// + +import UIKit + +public struct LuaContactUsViewControllerFactory { + static func makeLuaContactUsViewController() -> UIViewController { + return LuaContactUsViewController() + } +} diff --git a/CleanCodeApp/Modules/Features/Lua/Main/LuaCreateAccountViewControllerFactory.swift b/CleanCodeApp/Modules/Features/Lua/Main/LuaCreateAccountViewControllerFactory.swift new file mode 100644 index 0000000..36f2789 --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/Main/LuaCreateAccountViewControllerFactory.swift @@ -0,0 +1,14 @@ +// +// LuaCreateAccountViewControllerFabric.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 11/02/25. +// + +import UIKit + +public struct LuaCreateAccountViewControllerFactory { + static func makeLuaCreateAccountViewController() -> UIViewController { + return LuaCreateAccountViewController() + } +} diff --git a/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFabric.swift b/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFactory.swift similarity index 51% rename from CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFabric.swift rename to CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFactory.swift index 6579daf..f7bbac1 100644 --- a/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFabric.swift +++ b/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFactory.swift @@ -5,9 +5,10 @@ // Created by Gabriel Amaral on 11/02/25. // -public struct LuaResetPasswordViewModelFabric { +public struct LuaResetPasswordViewModelFactory { static func makeLuaResetPasswordViewModel() -> LuaResetPasswordViewModel { - let alertErrorHandler = LuaAlertErrorHandlerFabric.makeAlertErrorHandle() - return LuaResetPasswordViewModel(alertHandler: alertErrorHandler) + let alertErrorHandler = LuaAlertErrorHandlerFactory.makeAlertErrorHandle() + let coordinator = LuaBasicCoordinatorFactory.makeBasicCoordinator() + return LuaResetPasswordViewModel(alertHandler: alertErrorHandler, luaBasicCoordinator: coordinator) } } diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift index 6f8655a..32af2f2 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift @@ -1,6 +1,6 @@ import UIKit -class LuaResetPasswordViewController: UIViewController { +final class LuaResetPasswordViewController: UIViewController { @IBOutlet weak var emailTextField: UITextField! @IBOutlet weak var recoverPasswordButton: UIButton! @@ -11,7 +11,7 @@ class LuaResetPasswordViewController: UIViewController { @IBOutlet weak var passwordRecoverySuccessView: UIView! @IBOutlet weak var emailLabel: UILabel! - var emailInputted: String { + private var emailInputted: String { get { guard let emailInput = emailTextField.text?.trimmingCharacters(in: .whitespaces) else { return "" @@ -20,9 +20,9 @@ class LuaResetPasswordViewController: UIViewController { } } - var hasRequestedRecovery = false + private var hasRequestedRecovery = false - let viewModel = LuaResetPasswordViewModelFabric.makeLuaResetPasswordViewModel() + private let viewModel = LuaResetPasswordViewModelFactory.makeLuaResetPasswordViewModel() override func viewDidLoad() { super.viewDidLoad() @@ -30,7 +30,7 @@ class LuaResetPasswordViewController: UIViewController { setupView() } - open override var preferredStatusBarStyle: UIStatusBarStyle { + public override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent } @@ -42,7 +42,7 @@ class LuaResetPasswordViewController: UIViewController { startPasswordRecoveringProcess() } - func startPasswordRecoveringProcess() { + private func startPasswordRecoveringProcess() { if hasRequestedRecovery { dismiss(animated: true) return @@ -50,24 +50,28 @@ class LuaResetPasswordViewController: UIViewController { do { try validateEmailFormat() resquestPasswordReset() - self.displayPasswordResetSuccessUI() + self.view.endEditing(true) } catch { displayFormError(textField: emailTextField, label: emailErrorLabel, errorText: LuaUserAccountError.invalidEmail.localizedDescription) } } - func resquestPasswordReset() { - viewModel.startPasswordResetRequest(targetViewController: self, emailInputted: emailInputted) + private func resquestPasswordReset() { + viewModel.startPasswordResetRequest(targetViewController: self, emailInputted: emailInputted) { succes in + if succes { + self.displayPasswordResetSuccessUI() + } + } } - func validateEmailFormat() throws { + private func validateEmailFormat() throws { guard viewModel.validateEmailFormat(inputedEmail: emailInputted) else { throw LuaUserAccountError.invalidEmail } } - func displayPasswordResetSuccessUI() { + private func displayPasswordResetSuccessUI() { self.hasRequestedRecovery = true self.emailTextField.isHidden = true self.emailErrorLabel.isHidden = true @@ -81,27 +85,15 @@ class LuaResetPasswordViewController: UIViewController { } @IBAction func onHelpButtonTapped(_ sender: Any) { - presentLuaContactUsViewController() - } - - func presentLuaContactUsViewController() { - let LuaContactUsViewController = LuaContactUsViewController() - LuaContactUsViewController.modalPresentationStyle = .fullScreen - LuaContactUsViewController.modalTransitionStyle = .coverVertical - self.present(LuaContactUsViewController, animated: true, completion: nil) + viewModel.presentLuaContactUSViewController(viewController: self) } + @IBAction func onCreateAccountButtonTapped(_ sender: Any) { - presentLuaCreateAccountViewController() - } - - func presentLuaCreateAccountViewController() { - let LuaCreateAccountViewController = LuaCreateAccountViewController() - LuaCreateAccountViewController.modalPresentationStyle = .fullScreen - present(LuaCreateAccountViewController, animated: true) + viewModel.presentLuaCreateAccountViewController(viewController: self) } - func displayFormError(textField: UITextField, label: UILabel, errorText: String) { + private func displayFormError(textField: UITextField, label: UILabel, errorText: String) { textField.setErrorColor() label.textColor = .red label.text = errorText @@ -109,7 +101,7 @@ class LuaResetPasswordViewController: UIViewController { } // MARK: - Comportamentos de layout -extension LuaResetPasswordViewController { +private extension LuaResetPasswordViewController { func setupView() { setupRecoverPasswordButton() @@ -165,7 +157,7 @@ extension LuaResetPasswordViewController { } } -extension LuaResetPasswordViewController { +private extension LuaResetPasswordViewController { func validateExistingEmailInput(){ if !emailInputted.isEmpty { @@ -186,19 +178,4 @@ extension LuaResetPasswordViewController { } } -class Coordinator { - - - let navigationController: UINavigationController - let viewStack: [UIViewController] = [] - - init(navigationController: UINavigationController) { - self.navigationController = navigationController - } - - func push() { - -// navigationController.pushViewController(<#T##viewController: UIViewController##UIViewController#>, animated: <#T##Bool#>) - } -} diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift index 7e40ad1..57ef3ff 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift @@ -7,28 +7,32 @@ import UIKit -class LuaResetPasswordViewModel { +final class LuaResetPasswordViewModel { private let alertHandler: LuaAlertErrorHandlerProtocol + private var luaBasicCoordinator: LuaCoordinatorProtocol // need to refactor - init(alertHandler: LuaAlertErrorHandlerProtocol) { + init(alertHandler: LuaAlertErrorHandlerProtocol, luaBasicCoordinator: LuaCoordinatorProtocol) { self.alertHandler = alertHandler + self.luaBasicCoordinator = luaBasicCoordinator } - func startPasswordResetRequest(targetViewController: UIViewController, emailInputted: String) { + func startPasswordResetRequest(targetViewController: UIViewController, emailInputted: String, completion: @escaping (Bool) -> Void) { do { try validateConnectivity(emailInputted: emailInputted) let passwordParameters = makePasswordResetParams(inputedEmail: emailInputted) sendPasswordResetRequest(targetViewController: targetViewController, parameters: passwordParameters) + completion(true) } catch let error as LuaConnectivityError { alertHandler.handle(error: error, from: targetViewController, alertTitle: error.errorTitle) + completion(false) } catch { alertHandler.handle(error: error, from: targetViewController, alertTitle: "Algo de errado aconteceu. Tente novamente mais tarde.") + completion(false) } } - private func sendPasswordResetRequest(targetViewController: UIViewController, parameters: [String : String]) { BadNetworkLayer.shared.resetPassword(targetViewController, parameters: parameters) { succes in // need to refactor if succes { @@ -57,5 +61,15 @@ class LuaResetPasswordViewModel { inputedEmail.count > 5 return isEmailFormatValid } + + func presentLuaContactUSViewController(viewController: UIViewController) { + luaBasicCoordinator.viewController = viewController + luaBasicCoordinator.openLuaContactUsScreen() + } + + func presentLuaCreateAccountViewController(viewController: UIViewController) { + luaBasicCoordinator.viewController = viewController + luaBasicCoordinator.openLuaCreateAccountScreen() + } } From 3cea24534547169736bb19c986942504f0a29045 Mon Sep 17 00:00:00 2001 From: Eirado <111468283+Eirado@users.noreply.github.com> Date: Wed, 12 Feb 2025 18:55:18 -0300 Subject: [PATCH 04/22] more POP to viewModel --- .DS_Store | Bin 6148 -> 6148 bytes .../LuaResetPasswordViewModelFactory.swift | 2 +- .../LuaResetPasswordViewModel.swift | 12 +++++++++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.DS_Store b/.DS_Store index 7d7702cfd4ccaa3561b219af4913da410dafc4a3..150ea31ab0d32815df9d5003137bd0c60e428306 100644 GIT binary patch delta 54 zcmZoMXffEJ$;@P#GC7~wXmTtw7psUD^ShXNJO)H!vGdp3lq!=Q%P?*eu8)%CecA<1aq| D(e)6Y diff --git a/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFactory.swift b/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFactory.swift index f7bbac1..4cc3c2b 100644 --- a/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFactory.swift +++ b/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFactory.swift @@ -6,7 +6,7 @@ // public struct LuaResetPasswordViewModelFactory { - static func makeLuaResetPasswordViewModel() -> LuaResetPasswordViewModel { + static func makeLuaResetPasswordViewModel() -> LuaResetPasswordViewModelProtocol { let alertErrorHandler = LuaAlertErrorHandlerFactory.makeAlertErrorHandle() let coordinator = LuaBasicCoordinatorFactory.makeBasicCoordinator() return LuaResetPasswordViewModel(alertHandler: alertErrorHandler, luaBasicCoordinator: coordinator) diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift index 57ef3ff..d070776 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift @@ -7,7 +7,13 @@ import UIKit -final class LuaResetPasswordViewModel { +protocol LuaResetPasswordViewModelProtocol { + func validateEmailFormat(inputedEmail: String) -> Bool + func presentLuaContactUSViewController(viewController: UIViewController) + func presentLuaCreateAccountViewController(viewController: UIViewController) +} + +final class LuaResetPasswordViewModel: LuaResetPasswordViewModelProtocol { private let alertHandler: LuaAlertErrorHandlerProtocol private var luaBasicCoordinator: LuaCoordinatorProtocol // need to refactor @@ -20,7 +26,7 @@ final class LuaResetPasswordViewModel { func startPasswordResetRequest(targetViewController: UIViewController, emailInputted: String, completion: @escaping (Bool) -> Void) { do { try validateConnectivity(emailInputted: emailInputted) - + let passwordParameters = makePasswordResetParams(inputedEmail: emailInputted) sendPasswordResetRequest(targetViewController: targetViewController, parameters: passwordParameters) completion(true) @@ -55,7 +61,7 @@ final class LuaResetPasswordViewModel { } } - func validateEmailFormat(inputedEmail: String) -> Bool { + func validateEmailFormat(inputedEmail: String) -> Bool { let isEmailFormatValid = inputedEmail.contains(".") && inputedEmail.contains("@") && inputedEmail.count > 5 From 3c9417472dbd81bb6912381cc68168581a7af241 Mon Sep 17 00:00:00 2001 From: Eirado <111468283+Eirado@users.noreply.github.com> Date: Wed, 12 Feb 2025 18:57:31 -0300 Subject: [PATCH 05/22] added 1 function to vm protocol --- .DS_Store | Bin 6148 -> 6148 bytes .../LuaResetPasswordViewModel.swift | 1 + 2 files changed, 1 insertion(+) diff --git a/.DS_Store b/.DS_Store index 150ea31ab0d32815df9d5003137bd0c60e428306..475b940e66915e20d65df72e97d27bf61c26aaca 100644 GIT binary patch delta 26 hcmZoMXffEJ#ms0mIiJ~RaxAmo&5xNCMF4H32mAm4 delta 28 jcmZoMXffEJ#mty8IiJ~RaxAkS>q$9#CW*}(m_tMWd}atX diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift index d070776..2c030f1 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift @@ -11,6 +11,7 @@ protocol LuaResetPasswordViewModelProtocol { func validateEmailFormat(inputedEmail: String) -> Bool func presentLuaContactUSViewController(viewController: UIViewController) func presentLuaCreateAccountViewController(viewController: UIViewController) + func startPasswordResetRequest(targetViewController: UIViewController, emailInputted: String, completion: @escaping (Bool) -> Void) } final class LuaResetPasswordViewModel: LuaResetPasswordViewModelProtocol { From a3715673b4074762d090217400ef76bbb881ef5e Mon Sep 17 00:00:00 2001 From: Eirado <111468283+Eirado@users.noreply.github.com> Date: Thu, 13 Feb 2025 19:10:41 -0300 Subject: [PATCH 06/22] Coordinator / alerts refactored --- .DS_Store | Bin 6148 -> 6148 bytes .../Lua/Coordinator/LuaBasicCoordinator.swift | 7 ---- .../Lua/Login/LuaLoginViewController.swift | 6 ++-- .../Lua/LuaErrors/LuaConnectivityError.swift | 29 ---------------- .../Lua/LuaErrors/LuaNetworkError.swift | 16 ++++++++- .../LuaHandlers/LuaAlertErrorHandler.swift | 2 +- .../Main/LuaAlertErrorHandlerFactory.swift | 12 ------- .../Lua/Main/LuaBasicCoordinatorFactory.swift | 14 -------- .../LuaContactUsViewControllerFactory.swift | 5 ++- ...uaCreateAccountViewControllerFactory.swift | 4 ++- ...uaResetPasswordViewControllerFactory.swift | 25 ++++++++++++++ .../LuaResetPasswordViewModelFactory.swift | 4 +-- .../ResetPassword/LuaResetPasswordView.swift | 16 --------- .../LuaResetPasswordViewController.swift | 19 +++++++---- .../LuaResetPasswordViewModel.swift | 32 ++++-------------- 15 files changed, 70 insertions(+), 121 deletions(-) delete mode 100644 CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaConnectivityError.swift delete mode 100644 CleanCodeApp/Modules/Features/Lua/Main/LuaAlertErrorHandlerFactory.swift delete mode 100644 CleanCodeApp/Modules/Features/Lua/Main/LuaBasicCoordinatorFactory.swift create mode 100644 CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewControllerFactory.swift delete mode 100644 CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift diff --git a/.DS_Store b/.DS_Store index 475b940e66915e20d65df72e97d27bf61c26aaca..b30aa9fb0df26839f0af16a86205983165116cdc 100644 GIT binary patch delta 56 zcmZoMXffEJ$;?!iGC7~wXmTtw7h9(D$;_bjlQ#mn^O<=NTnEMjn*}*USvIqC{N)D# D7{L LuaAlertErrorHandlerProtocol { - return LuaAlertErrorHandler() - } -} diff --git a/CleanCodeApp/Modules/Features/Lua/Main/LuaBasicCoordinatorFactory.swift b/CleanCodeApp/Modules/Features/Lua/Main/LuaBasicCoordinatorFactory.swift deleted file mode 100644 index 319d5ac..0000000 --- a/CleanCodeApp/Modules/Features/Lua/Main/LuaBasicCoordinatorFactory.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// Untitled.swift -// CleanCodeApp -// -// Created by Gabriel Amaral on 11/02/25. -// - -import UIKit - -public struct LuaBasicCoordinatorFactory { - static func makeBasicCoordinator() -> LuaCoordinatorProtocol { - return LuaBasicCoordinator() - } -} diff --git a/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewControllerFactory.swift b/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewControllerFactory.swift index 81902b5..2c481ed 100644 --- a/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewControllerFactory.swift +++ b/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewControllerFactory.swift @@ -9,6 +9,9 @@ import UIKit public struct LuaContactUsViewControllerFactory { static func makeLuaContactUsViewController() -> UIViewController { - return LuaContactUsViewController() + let luaContactUsViewController = LuaContactUsViewController() + luaContactUsViewController.modalPresentationStyle = .fullScreen + luaContactUsViewController.modalTransitionStyle = .coverVertical + return luaContactUsViewController } } diff --git a/CleanCodeApp/Modules/Features/Lua/Main/LuaCreateAccountViewControllerFactory.swift b/CleanCodeApp/Modules/Features/Lua/Main/LuaCreateAccountViewControllerFactory.swift index 36f2789..b3f1731 100644 --- a/CleanCodeApp/Modules/Features/Lua/Main/LuaCreateAccountViewControllerFactory.swift +++ b/CleanCodeApp/Modules/Features/Lua/Main/LuaCreateAccountViewControllerFactory.swift @@ -9,6 +9,8 @@ import UIKit public struct LuaCreateAccountViewControllerFactory { static func makeLuaCreateAccountViewController() -> UIViewController { - return LuaCreateAccountViewController() + let luaCreateAccountViewController = LuaCreateAccountViewController() + luaCreateAccountViewController.modalPresentationStyle = .fullScreen + return luaCreateAccountViewController } } diff --git a/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewControllerFactory.swift b/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewControllerFactory.swift new file mode 100644 index 0000000..2f87f65 --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewControllerFactory.swift @@ -0,0 +1,25 @@ +// +// LuaResetPasswordViewControllerFactory.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 13/02/25. +// + +import UIKit + +struct LuaResetPasswordViewControllerFactory { + static func makeLuaResetPasswordViewController() -> UIViewController { + let viewModel = LuaResetPasswordViewModelFactory.makeLuaResetPasswordViewModel() + let coordinator = LuaBasicCoordinator() + let storyboard = UIStoryboard(name: "LuaUser", bundle: nil) + guard let viewController = storyboard.instantiateViewController(withIdentifier: "LuaResetPasswordViewController") as? LuaResetPasswordViewController else { + fatalError("Could not instantiate LuaResetPasswordViewController from LuaUser storyboard") + } + viewController.configure(viewModel: viewModel, coordinator: coordinator) + viewController.modalPresentationStyle = .fullScreen + + coordinator.viewController = viewController + return viewController + } + +} diff --git a/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFactory.swift b/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFactory.swift index 4cc3c2b..4e4e83e 100644 --- a/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFactory.swift +++ b/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFactory.swift @@ -7,8 +7,6 @@ public struct LuaResetPasswordViewModelFactory { static func makeLuaResetPasswordViewModel() -> LuaResetPasswordViewModelProtocol { - let alertErrorHandler = LuaAlertErrorHandlerFactory.makeAlertErrorHandle() - let coordinator = LuaBasicCoordinatorFactory.makeBasicCoordinator() - return LuaResetPasswordViewModel(alertHandler: alertErrorHandler, luaBasicCoordinator: coordinator) + return LuaResetPasswordViewModel() } } diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift deleted file mode 100644 index 6374e85..0000000 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// LuaResetPasswordView.swift -// CleanCodeApp -// -// Created by Gabriel Amaral on 11/02/25. -// - -import UIKit - - -class LuaResetPasswordView: UIView { - - -} - - diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift index 32af2f2..1d4317e 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift @@ -22,7 +22,13 @@ final class LuaResetPasswordViewController: UIViewController { private var hasRequestedRecovery = false - private let viewModel = LuaResetPasswordViewModelFactory.makeLuaResetPasswordViewModel() + private var viewModel: LuaResetPasswordViewModelProtocol? + private var coordinator: LuaCoordinatorProtocol? + + func configure(viewModel: LuaResetPasswordViewModelProtocol, coordinator: LuaCoordinatorProtocol) { + self.viewModel = viewModel + self.coordinator = coordinator + } override func viewDidLoad() { super.viewDidLoad() @@ -58,7 +64,7 @@ final class LuaResetPasswordViewController: UIViewController { } private func resquestPasswordReset() { - viewModel.startPasswordResetRequest(targetViewController: self, emailInputted: emailInputted) { succes in + viewModel!.startPasswordResetRequest(targetViewController: self, emailInputted: emailInputted) { succes in if succes { self.displayPasswordResetSuccessUI() } @@ -66,7 +72,7 @@ final class LuaResetPasswordViewController: UIViewController { } private func validateEmailFormat() throws { - guard viewModel.validateEmailFormat(inputedEmail: emailInputted) else { + guard viewModel!.validateEmailFormat(inputedEmail: emailInputted) else { throw LuaUserAccountError.invalidEmail } } @@ -85,12 +91,12 @@ final class LuaResetPasswordViewController: UIViewController { } @IBAction func onHelpButtonTapped(_ sender: Any) { - viewModel.presentLuaContactUSViewController(viewController: self) + coordinator!.openLuaContactUsScreen() } @IBAction func onCreateAccountButtonTapped(_ sender: Any) { - viewModel.presentLuaCreateAccountViewController(viewController: self) + coordinator!.openLuaCreateAccountScreen() } private func displayFormError(textField: UITextField, label: UILabel, errorText: String) { @@ -160,7 +166,8 @@ private extension LuaResetPasswordViewController { private extension LuaResetPasswordViewController { func validateExistingEmailInput(){ - if !emailInputted.isEmpty { + let emailInputtedIsNotEmpty = !emailInputted.isEmpty + if emailInputtedIsNotEmpty { emailTextField.text = emailInputted emailTextField.isEnabled = false } diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift index 2c030f1..9e00d2e 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift @@ -9,21 +9,11 @@ import UIKit protocol LuaResetPasswordViewModelProtocol { func validateEmailFormat(inputedEmail: String) -> Bool - func presentLuaContactUSViewController(viewController: UIViewController) - func presentLuaCreateAccountViewController(viewController: UIViewController) func startPasswordResetRequest(targetViewController: UIViewController, emailInputted: String, completion: @escaping (Bool) -> Void) } -final class LuaResetPasswordViewModel: LuaResetPasswordViewModelProtocol { - - private let alertHandler: LuaAlertErrorHandlerProtocol - private var luaBasicCoordinator: LuaCoordinatorProtocol // need to refactor - - init(alertHandler: LuaAlertErrorHandlerProtocol, luaBasicCoordinator: LuaCoordinatorProtocol) { - self.alertHandler = alertHandler - self.luaBasicCoordinator = luaBasicCoordinator - } - +final class LuaResetPasswordViewModel: LuaResetPasswordViewModelProtocol, LuaAlertErrorHandlerProtocol { + func startPasswordResetRequest(targetViewController: UIViewController, emailInputted: String, completion: @escaping (Bool) -> Void) { do { try validateConnectivity(emailInputted: emailInputted) @@ -31,11 +21,11 @@ final class LuaResetPasswordViewModel: LuaResetPasswordViewModelProtocol { let passwordParameters = makePasswordResetParams(inputedEmail: emailInputted) sendPasswordResetRequest(targetViewController: targetViewController, parameters: passwordParameters) completion(true) - } catch let error as LuaConnectivityError { - alertHandler.handle(error: error, from: targetViewController, alertTitle: error.errorTitle) + } catch let error as LuaNetworkError { + handle(error: error, from: targetViewController, alertTitle: error.errorTitle) completion(false) } catch { - alertHandler.handle(error: error, from: targetViewController, alertTitle: "Algo de errado aconteceu. Tente novamente mais tarde.") + handle(error: error, from: targetViewController, alertTitle: "Algo de errado aconteceu. Tente novamente mais tarde.") completion(false) } } @@ -58,7 +48,7 @@ final class LuaResetPasswordViewModel: LuaResetPasswordViewModelProtocol { private func validateConnectivity(emailInputted: String) throws { guard ConnectivityManager.shared.isConnected else { - throw LuaConnectivityError.noInternetConnection + throw LuaNetworkError.noInternetConnection } } @@ -68,15 +58,5 @@ final class LuaResetPasswordViewModel: LuaResetPasswordViewModelProtocol { inputedEmail.count > 5 return isEmailFormatValid } - - func presentLuaContactUSViewController(viewController: UIViewController) { - luaBasicCoordinator.viewController = viewController - luaBasicCoordinator.openLuaContactUsScreen() - } - - func presentLuaCreateAccountViewController(viewController: UIViewController) { - luaBasicCoordinator.viewController = viewController - luaBasicCoordinator.openLuaCreateAccountScreen() - } } From 8c9bb40d5deb75bc8e877e81040c7ae64bebfb72 Mon Sep 17 00:00:00 2001 From: Eirado <111468283+Eirado@users.noreply.github.com> Date: Thu, 13 Feb 2025 21:14:01 -0300 Subject: [PATCH 07/22] async await --- .DS_Store | Bin 6148 -> 6148 bytes .../LuaAlertErrorHandler.swift | 0 .../Lua/LuaHelpers/StringExtension.swift | 14 +++++++ .../LuaResetPasswordViewController.swift | 38 ++++++++++-------- .../LuaResetPasswordViewModel.swift | 16 +++----- 5 files changed, 41 insertions(+), 27 deletions(-) rename CleanCodeApp/Modules/Features/Lua/{LuaHandlers => LuaHelpers}/LuaAlertErrorHandler.swift (100%) create mode 100644 CleanCodeApp/Modules/Features/Lua/LuaHelpers/StringExtension.swift diff --git a/.DS_Store b/.DS_Store index b30aa9fb0df26839f0af16a86205983165116cdc..42927ce393b2dbac578e48a35fae8dbbfa4a6516 100644 GIT binary patch delta 54 zcmZoMXffEJ$;>p@ZE`-d(d1ZWE>^*>7d8h^-oR`;c|J1_oae~+V6z~HD9dJcj=%f> D2zCqJ&u8X=^BfruY!>7YW!cQm@s}R} D;_nf3 diff --git a/CleanCodeApp/Modules/Features/Lua/LuaHandlers/LuaAlertErrorHandler.swift b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/LuaAlertErrorHandler.swift similarity index 100% rename from CleanCodeApp/Modules/Features/Lua/LuaHandlers/LuaAlertErrorHandler.swift rename to CleanCodeApp/Modules/Features/Lua/LuaHelpers/LuaAlertErrorHandler.swift diff --git a/CleanCodeApp/Modules/Features/Lua/LuaHelpers/StringExtension.swift b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/StringExtension.swift new file mode 100644 index 0000000..0cb5227 --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/StringExtension.swift @@ -0,0 +1,14 @@ +// +// LuaTextFieldExtension.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 13/02/25. +// + +import UIKit + +extension String { + var isNotEmpty: Bool { + return !self.isEmpty + } +} diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift index 1d4317e..3805145 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift @@ -1,6 +1,6 @@ import UIKit -final class LuaResetPasswordViewController: UIViewController { +final class LuaResetPasswordViewController: UIViewController, LuaAlertErrorHandlerProtocol { @IBOutlet weak var emailTextField: UITextField! @IBOutlet weak var recoverPasswordButton: UIButton! @@ -26,9 +26,9 @@ final class LuaResetPasswordViewController: UIViewController { private var coordinator: LuaCoordinatorProtocol? func configure(viewModel: LuaResetPasswordViewModelProtocol, coordinator: LuaCoordinatorProtocol) { - self.viewModel = viewModel - self.coordinator = coordinator - } + self.viewModel = viewModel + self.coordinator = coordinator + } override func viewDidLoad() { super.viewDidLoad() @@ -45,32 +45,36 @@ final class LuaResetPasswordViewController: UIViewController { } @IBAction func onPasswordRecoveryButtonTapped(_ sender: Any) { - startPasswordRecoveringProcess() + Task { + await startPasswordRecoveringProcess() + } } - private func startPasswordRecoveringProcess() { + private func startPasswordRecoveringProcess() async { if hasRequestedRecovery { dismiss(animated: true) return } do { try validateEmailFormat() - resquestPasswordReset() - + await resquestPasswordReset() self.view.endEditing(true) } catch { displayFormError(textField: emailTextField, label: emailErrorLabel, errorText: LuaUserAccountError.invalidEmail.localizedDescription) } } - private func resquestPasswordReset() { - viewModel!.startPasswordResetRequest(targetViewController: self, emailInputted: emailInputted) { succes in - if succes { - self.displayPasswordResetSuccessUI() - } + private func resquestPasswordReset() async { + do { + try await viewModel!.startPasswordResetRequest(targetViewController: self, emailInputted: emailInputted) + displayPasswordResetSuccessUI() + } catch let error as LuaNetworkError { + handle(error: error, from: self, alertTitle: error.errorTitle) + } catch { + handle(error: error, from: self, alertTitle: "Algo de errado aconteceu. Tente novamente mais tarde.") } } - + private func validateEmailFormat() throws { guard viewModel!.validateEmailFormat(inputedEmail: emailInputted) else { throw LuaUserAccountError.invalidEmail @@ -93,7 +97,7 @@ final class LuaResetPasswordViewController: UIViewController { @IBAction func onHelpButtonTapped(_ sender: Any) { coordinator!.openLuaContactUsScreen() } - + @IBAction func onCreateAccountButtonTapped(_ sender: Any) { coordinator!.openLuaCreateAccountScreen() @@ -166,7 +170,7 @@ private extension LuaResetPasswordViewController { private extension LuaResetPasswordViewController { func validateExistingEmailInput(){ - let emailInputtedIsNotEmpty = !emailInputted.isEmpty + let emailInputtedIsNotEmpty = emailInputted.isNotEmpty if emailInputtedIsNotEmpty { emailTextField.text = emailInputted emailTextField.isEnabled = false @@ -174,7 +178,7 @@ private extension LuaResetPasswordViewController { } func updatePasswordRecoveryButtonState() { - let isEnabled = !emailInputted.isEmpty + let isEnabled = emailInputted.isNotEmpty updatePasswordRecoverButtonStatus(newStatus: isEnabled) } diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift index 9e00d2e..49bb120 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift @@ -9,24 +9,20 @@ import UIKit protocol LuaResetPasswordViewModelProtocol { func validateEmailFormat(inputedEmail: String) -> Bool - func startPasswordResetRequest(targetViewController: UIViewController, emailInputted: String, completion: @escaping (Bool) -> Void) + func startPasswordResetRequest(targetViewController: UIViewController, emailInputted: String) async throws } -final class LuaResetPasswordViewModel: LuaResetPasswordViewModelProtocol, LuaAlertErrorHandlerProtocol { +final class LuaResetPasswordViewModel: LuaResetPasswordViewModelProtocol { - func startPasswordResetRequest(targetViewController: UIViewController, emailInputted: String, completion: @escaping (Bool) -> Void) { + func startPasswordResetRequest(targetViewController: UIViewController, emailInputted: String) async throws { do { try validateConnectivity(emailInputted: emailInputted) - let passwordParameters = makePasswordResetParams(inputedEmail: emailInputted) sendPasswordResetRequest(targetViewController: targetViewController, parameters: passwordParameters) - completion(true) - } catch let error as LuaNetworkError { - handle(error: error, from: targetViewController, alertTitle: error.errorTitle) - completion(false) + } catch _ as LuaNetworkError { + throw LuaNetworkError.noInternetConnection } catch { - handle(error: error, from: targetViewController, alertTitle: "Algo de errado aconteceu. Tente novamente mais tarde.") - completion(false) + throw LuaNetworkError.invalidStatusCode } } From d25b840c6aa32d3ee2880c2596dc3661c2d89ede Mon Sep 17 00:00:00 2001 From: Eirado <111468283+Eirado@users.noreply.github.com> Date: Fri, 14 Feb 2025 02:54:58 -0300 Subject: [PATCH 08/22] view code --- .DS_Store | Bin 6148 -> 6148 bytes .../Lua/Base.lproj/LuaUser.storyboard | 2 +- .../Lua/LuaHelpers/LuaAlertErrorHandler.swift | 4 +- ...tension.swift => LuaStringExtension.swift} | 0 .../Lua/LuaHelpers/LuaUIColorExtensions.swift | 14 + .../ResetPassword/LuaResetPasswordView.swift | 288 ++++++++++++++++++ .../LuaResetPasswordViewController.swift | 154 ++++------ 7 files changed, 361 insertions(+), 101 deletions(-) rename CleanCodeApp/Modules/Features/Lua/LuaHelpers/{StringExtension.swift => LuaStringExtension.swift} (100%) create mode 100644 CleanCodeApp/Modules/Features/Lua/LuaHelpers/LuaUIColorExtensions.swift create mode 100644 CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift diff --git a/.DS_Store b/.DS_Store index 42927ce393b2dbac578e48a35fae8dbbfa4a6516..4395db64ce880a20cdb824a363fbf6af70c78fd1 100644 GIT binary patch delta 54 zcmZoMXffEJ$;`C-|KxmTqsg(%T&#gYyO~-iZ(uf_JfE2d&U0X7+bqZ-#j=^3<0n4= D<+u=t delta 55 zcmZoMXffEJ$;>p@ZE`-d(d1ZWE>^*>7d8h^-oR`;c|J1_oaeyA`e5@%W>J>S>>Pjj E0Uyf~)c^nh diff --git a/CleanCodeApp/Modules/Features/Lua/Base.lproj/LuaUser.storyboard b/CleanCodeApp/Modules/Features/Lua/Base.lproj/LuaUser.storyboard index 009e24f..8c06795 100644 --- a/CleanCodeApp/Modules/Features/Lua/Base.lproj/LuaUser.storyboard +++ b/CleanCodeApp/Modules/Features/Lua/Base.lproj/LuaUser.storyboard @@ -360,7 +360,7 @@ E-mail enviado para: - + diff --git a/CleanCodeApp/Modules/Features/Lua/LuaHelpers/LuaAlertErrorHandler.swift b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/LuaAlertErrorHandler.swift index a3bf05c..c84fb5e 100644 --- a/CleanCodeApp/Modules/Features/Lua/LuaHelpers/LuaAlertErrorHandler.swift +++ b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/LuaAlertErrorHandler.swift @@ -7,11 +7,11 @@ import UIKit -public protocol LuaAlertErrorHandlerProtocol { +public protocol LuaAlertHandlerProtocol { func handle(error: Error, from viewController: UIViewController, alertTitle: String?) } -extension LuaAlertErrorHandlerProtocol { +extension LuaAlertHandlerProtocol { public func handle(error: Error, from viewController: UIViewController, alertTitle: String?) { let alertController = UIAlertController(title: alertTitle, message: error.localizedDescription, preferredStyle: .alert) let action = UIAlertAction(title: "OK", style: .default) diff --git a/CleanCodeApp/Modules/Features/Lua/LuaHelpers/StringExtension.swift b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/LuaStringExtension.swift similarity index 100% rename from CleanCodeApp/Modules/Features/Lua/LuaHelpers/StringExtension.swift rename to CleanCodeApp/Modules/Features/Lua/LuaHelpers/LuaStringExtension.swift diff --git a/CleanCodeApp/Modules/Features/Lua/LuaHelpers/LuaUIColorExtensions.swift b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/LuaUIColorExtensions.swift new file mode 100644 index 0000000..9235019 --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/LuaUIColorExtensions.swift @@ -0,0 +1,14 @@ +// +// LuaUIColorExtension.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 14/02/25. +// + +import UIKit + +extension UIColor { + static var defaultViolet: UIColor { + return UIColor(red: 0.53, green: 0.45, blue: 1.0, alpha: 1.0) + } +} diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift new file mode 100644 index 0000000..d66332d --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift @@ -0,0 +1,288 @@ +import UIKit + +protocol LuaResetPasswordViewProtocol { + func configurePasswordRecoveryButton(target: Any, selector: Selector) + func configureLoginButton(target: Any, selector: Selector) + func configureHelpButton(target: Any, selector: Selector) + func configureCreateAccountButton(target: Any, selector: Selector) + func configureCloseButton(target: Any, selector: Selector) + func configureEmailTextFieldDidBeginEditing(target: Any, selector: Selector) + func configureEmailTextFieldOnEditing(target: Any, selector: Selector) +} + +class LuaResetPasswordView: UIView, LuaResetPasswordViewProtocol { + + // MARK: - UI Components + private lazy var scrollView: UIScrollView = { + let scrollView = UIScrollView() + scrollView.translatesAutoresizingMaskIntoConstraints = false + return scrollView + }() + + private lazy var contentView: UIView = { + let view = UIView() + view.translatesAutoresizingMaskIntoConstraints = false + return view + }() + + private lazy var smokeImageView: UIImageView = { + let imageView = UIImageView() + imageView.image = UIImage(systemName: "smoke.fill") + imageView.contentMode = .scaleAspectFit + imageView.translatesAutoresizingMaskIntoConstraints = false + return imageView + }() + + public lazy var passwordRecoverySuccessView: UIView = { + let view = UIView() + view.backgroundColor = .systemGray6 + view.isHidden = true + view.translatesAutoresizingMaskIntoConstraints = false + return view + }() + + public lazy var successLabel: UILabel = { + let label = UILabel() + label.text = "Se o e-mail informado estiver cadastrado, você receberá em instantes um link de recuperação de senha. E-mail enviado para:" + label.font = UIFont(name: "SourceSansPro-Regular", size: 14) + label.textColor = .lightGray + label.textAlignment = .center + label.numberOfLines = 5 + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() + + private lazy var emailSentLabel: UILabel = { + let label = UILabel() + label.text = "email@email.com" + label.font = UIFont(name: "SourceSansPro-Bold", size: 14) + label.textColor = .white + label.textAlignment = .center + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() + + public lazy var emailLabel: UILabel = { + let label = UILabel() + label.text = "Informe o e-mail associado à sua conta" + label.font = UIFont(name: "SourceSansPro-Regular", size: 12) + label.textColor = .lightGray + label.textAlignment = .center + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() + + public lazy var emailTextField: UITextField = { + let textField = UITextField() + textField.placeholder = "E-mail" + textField.borderStyle = .roundedRect + textField.font = UIFont(name: "SourceSansPro-Regular", size: 12) + textField.textColor = .black + textField.setDefaultColor() + textField.keyboardType = .emailAddress + textField.autocorrectionType = .no + textField.translatesAutoresizingMaskIntoConstraints = false + return textField + }() + + public lazy var passwordRecoveryButton: UIButton = { + let button = UIButton(type: .system) + button.setTitle("RECUPERAR SENHA", for: .normal) + button.titleLabel?.font = UIFont(name: "OpenSans-Bold", size: 15) + button.backgroundColor = UIColor.defaultViolet + button.setTitleColor(.white, for: .normal) + button.layer.cornerRadius = 20 + button.layer.borderWidth = 1 + button.translatesAutoresizingMaskIntoConstraints = false + return button + }() + + private lazy var loginButton: UIButton = { + let button = UIButton(type: .system) + button.setTitle("LOGIN", for: .normal) + button.titleLabel?.font = UIFont(name: "OpenSans-Bold", size: 15) + button.backgroundColor = .clear + button.setTitleColor(UIColor.defaultViolet, for: .normal) + button.backgroundColor = .white + button.layer.cornerRadius = 20 + button.layer.borderWidth = 1 + button.layer.borderColor = UIColor.blue.cgColor + button.translatesAutoresizingMaskIntoConstraints = false + return button + }() + + private lazy var helpButton: UIButton = { + let button = UIButton(type: .system) + button.setTitle("PRECISO DE AJUDA", for: .normal) + button.titleLabel?.font = UIFont(name: "OpenSans-Bold", size: 15) + button.backgroundColor = .clear + button.setTitleColor(UIColor.defaultViolet, for: .normal) + button.backgroundColor = .white + button.layer.cornerRadius = 20 + button.layer.borderWidth = 1 + button.layer.borderColor = UIColor.blue.cgColor + button.translatesAutoresizingMaskIntoConstraints = false + return button + }() + + private lazy var createAccountButton: UIButton = { + let button = UIButton(type: .system) + button.setTitle("CRIAR UMA CONTA", for: .normal) + button.titleLabel?.font = UIFont(name: "OpenSans-Bold", size: 15) + button.backgroundColor = .clear + button.setTitleColor( UIColor.defaultViolet, for: .normal) + button.backgroundColor = .white + button.layer.cornerRadius = 20 + button.layer.borderWidth = 1 + button.layer.borderColor = UIColor.blue.cgColor + button.translatesAutoresizingMaskIntoConstraints = false + return button + }() + + private lazy var closeButton: UIButton = { + let button = UIButton(type: .system) + button.setImage(UIImage(systemName: "xmark.app.fill"), for: .normal) + button.translatesAutoresizingMaskIntoConstraints = false + return button + }() + + public var emailInputted: String { + get { + guard let emailInput = emailTextField.text?.trimmingCharacters(in: .whitespaces) else { + return "" + } + return emailInput + } + } + + // MARK: - Lifecycle + override init(frame: CGRect) { + super.init(frame: frame) + setupView() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: - Setup UI + private func setupView() { + backgroundColor = .systemGray6 + addSubview(scrollView) + scrollView.addSubview(contentView) + addSubviewsToContentView() + addSubviewsTosuccessView() + addConstraintsToUIComponents() + } + + private func addSubviewsToContentView() { + [smokeImageView, passwordRecoverySuccessView, emailLabel, emailTextField, passwordRecoveryButton, loginButton, helpButton, createAccountButton, closeButton].forEach { contentView.addSubview($0) } + } + + private func addSubviewsTosuccessView() { + [successLabel, emailSentLabel].forEach { passwordRecoverySuccessView.addSubview($0) } + } + + private func addConstraintsToUIComponents() { + NSLayoutConstraint.activate([ + scrollView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor), + scrollView.leadingAnchor.constraint(equalTo: leadingAnchor), + scrollView.trailingAnchor.constraint(equalTo: trailingAnchor), + scrollView.bottomAnchor.constraint(equalTo: bottomAnchor), + + contentView.topAnchor.constraint(equalTo: scrollView.topAnchor), + contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor), + contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor), + contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor), + contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor), + + smokeImageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 65), + smokeImageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), + smokeImageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), + smokeImageView.heightAnchor.constraint(equalToConstant: 75), + + passwordRecoverySuccessView.topAnchor.constraint(equalTo: smokeImageView.bottomAnchor, constant: 8), + passwordRecoverySuccessView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), + passwordRecoverySuccessView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), + passwordRecoverySuccessView.heightAnchor.constraint(equalToConstant: 138), + + successLabel.topAnchor.constraint(equalTo: passwordRecoverySuccessView.topAnchor), + successLabel.leadingAnchor.constraint(equalTo: passwordRecoverySuccessView.leadingAnchor), + successLabel.trailingAnchor.constraint(equalTo: passwordRecoverySuccessView.trailingAnchor), + successLabel.heightAnchor.constraint(equalToConstant: 98), + + emailSentLabel.topAnchor.constraint(equalTo: successLabel.bottomAnchor), + emailSentLabel.leadingAnchor.constraint(equalTo: passwordRecoverySuccessView.leadingAnchor), + emailSentLabel.trailingAnchor.constraint(equalTo: passwordRecoverySuccessView.trailingAnchor), + emailSentLabel.bottomAnchor.constraint(equalTo: passwordRecoverySuccessView.bottomAnchor, constant: -10), + + emailLabel.topAnchor.constraint(equalTo: smokeImageView.bottomAnchor, constant: 70), + emailLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), + emailLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), + emailLabel.heightAnchor.constraint(equalToConstant: 20), + + emailTextField.topAnchor.constraint(equalTo: emailLabel.bottomAnchor, constant: 8), + emailTextField.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), + emailTextField.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), + emailTextField.heightAnchor.constraint(equalToConstant: 48), + + passwordRecoveryButton.topAnchor.constraint(equalTo: emailTextField.bottomAnchor, constant: 20), + passwordRecoveryButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), + passwordRecoveryButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), + passwordRecoveryButton.heightAnchor.constraint(equalToConstant: 48), + + loginButton.topAnchor.constraint(equalTo: passwordRecoveryButton.bottomAnchor, constant: 84), + loginButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), + loginButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), + loginButton.heightAnchor.constraint(equalToConstant: 48), + + helpButton.topAnchor.constraint(equalTo: loginButton.bottomAnchor, constant: 20), + helpButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), + helpButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), + helpButton.heightAnchor.constraint(equalToConstant: 48), + + createAccountButton.topAnchor.constraint(equalTo: helpButton.bottomAnchor, constant: 20), + createAccountButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), + createAccountButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), + createAccountButton.heightAnchor.constraint(equalToConstant: 48), + createAccountButton.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -40), + + closeButton.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10), + closeButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -15), + closeButton.widthAnchor.constraint(equalToConstant: 45), + closeButton.heightAnchor.constraint(equalToConstant: 45) + ]) + } + + public func configurePasswordRecoveryButton(target: Any, selector: Selector) { + passwordRecoveryButton.addTarget(target, action: selector, for: .touchUpInside) + } + + public func configureLoginButton(target: Any, selector: Selector) { + loginButton.addTarget(target, action: selector, for: .touchUpInside) + } + + public func configureHelpButton(target: Any, selector: Selector) { + helpButton.addTarget(target, action: selector, for: .touchUpInside) + } + + public func configureCreateAccountButton(target: Any, selector: Selector) { + createAccountButton.addTarget(target, action: selector, for: .touchUpInside) + } + + public func configureCloseButton(target: Any, selector: Selector) { + closeButton.addTarget(target, action: selector, for: .touchUpInside) + } + + public func configureEmailTextFieldDidBeginEditing(target: Any, selector: Selector) { + emailTextField.addTarget(target, action: selector, for: .editingDidBegin) + } + + public func configureEmailTextFieldOnEditing(target: Any, selector: Selector) { + emailTextField.addTarget(target, action: selector, for: .editingChanged) + } + + public func configureEmailTextFieldDidEndEditing(target: Any, selector: Selector) { + emailTextField.addTarget(target, action: selector, for: .editingDidEnd) + } +} diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift index 3805145..164084f 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift @@ -1,55 +1,33 @@ import UIKit -final class LuaResetPasswordViewController: UIViewController, LuaAlertErrorHandlerProtocol { - - @IBOutlet weak var emailTextField: UITextField! - @IBOutlet weak var recoverPasswordButton: UIButton! - @IBOutlet weak var loginButton: UIButton! - @IBOutlet weak var helpButton: UIButton! - @IBOutlet weak var createAccountButton: UIButton! - @IBOutlet weak var emailErrorLabel: UILabel! - @IBOutlet weak var passwordRecoverySuccessView: UIView! - @IBOutlet weak var emailLabel: UILabel! - - private var emailInputted: String { - get { - guard let emailInput = emailTextField.text?.trimmingCharacters(in: .whitespaces) else { - return "" - } - return emailInput - } - } - - private var hasRequestedRecovery = false +final class LuaResetPasswordViewController: UIViewController, LuaAlertHandlerProtocol { + private let luaResetPasswordView = LuaResetPasswordView() private var viewModel: LuaResetPasswordViewModelProtocol? private var coordinator: LuaCoordinatorProtocol? + private var hasRequestedRecovery = false func configure(viewModel: LuaResetPasswordViewModelProtocol, coordinator: LuaCoordinatorProtocol) { self.viewModel = viewModel self.coordinator = coordinator } + override func loadView() { + view = luaResetPasswordView + } + override func viewDidLoad() { super.viewDidLoad() - - setupView() + configureButtons() + configureTextField() + updatePasswordRecoveryButtonState() + validateExistingEmailInput() } public override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent } - @IBAction func closeButtonAction(_ sender: Any) { - dismiss(animated: true) - } - - @IBAction func onPasswordRecoveryButtonTapped(_ sender: Any) { - Task { - await startPasswordRecoveringProcess() - } - } - private func startPasswordRecoveringProcess() async { if hasRequestedRecovery { dismiss(animated: true) @@ -60,13 +38,13 @@ final class LuaResetPasswordViewController: UIViewController, LuaAlertErrorHandl await resquestPasswordReset() self.view.endEditing(true) } catch { - displayFormError(textField: emailTextField, label: emailErrorLabel, errorText: LuaUserAccountError.invalidEmail.localizedDescription) + displayFormError(textField: luaResetPasswordView.emailTextField, label: luaResetPasswordView.successLabel, errorText: LuaUserAccountError.invalidEmail.localizedDescription) } } private func resquestPasswordReset() async { do { - try await viewModel!.startPasswordResetRequest(targetViewController: self, emailInputted: emailInputted) + try await viewModel!.startPasswordResetRequest(targetViewController: self, emailInputted: luaResetPasswordView.emailInputted) displayPasswordResetSuccessUI() } catch let error as LuaNetworkError { handle(error: error, from: self, alertTitle: error.errorTitle) @@ -74,33 +52,20 @@ final class LuaResetPasswordViewController: UIViewController, LuaAlertErrorHandl handle(error: error, from: self, alertTitle: "Algo de errado aconteceu. Tente novamente mais tarde.") } } - + private func validateEmailFormat() throws { - guard viewModel!.validateEmailFormat(inputedEmail: emailInputted) else { + guard viewModel!.validateEmailFormat(inputedEmail: luaResetPasswordView.emailInputted) else { throw LuaUserAccountError.invalidEmail } } private func displayPasswordResetSuccessUI() { self.hasRequestedRecovery = true - self.emailTextField.isHidden = true - self.emailErrorLabel.isHidden = true - self.passwordRecoverySuccessView.isHidden = false - self.emailLabel.text = emailInputted - self.recoverPasswordButton.setTitle("Voltar", for: .normal) - } - - @IBAction func onLoginButtonTapped(_ sender: Any) { - dismiss(animated: true) - } - - @IBAction func onHelpButtonTapped(_ sender: Any) { - coordinator!.openLuaContactUsScreen() - } - - - @IBAction func onCreateAccountButtonTapped(_ sender: Any) { - coordinator!.openLuaCreateAccountScreen() + luaResetPasswordView.emailTextField.isHidden = true + luaResetPasswordView.successLabel.isHidden = true + luaResetPasswordView.passwordRecoverySuccessView.isHidden = false + luaResetPasswordView.emailLabel.text = luaResetPasswordView.emailInputted + luaResetPasswordView.passwordRecoveryButton.setTitle("Voltar", for: .normal) } private func displayFormError(textField: UITextField, label: UILabel, errorText: String) { @@ -113,80 +78,73 @@ final class LuaResetPasswordViewController: UIViewController, LuaAlertErrorHandl // MARK: - Comportamentos de layout private extension LuaResetPasswordViewController { - func setupView() { - setupRecoverPasswordButton() - setupLoginButton() - setupHelpButton() - setupAccountButton() - emailTextField.setDefaultColor() - validateExistingEmailInput() - updatePasswordRecoveryButtonState() + func configureButtons() { + luaResetPasswordView.configureHelpButton(target: self, selector: #selector(onHelpButtonTapped) ) + luaResetPasswordView.configureCloseButton(target: self, selector: #selector(closeButtonTapped)) + luaResetPasswordView.configureLoginButton(target: self, selector: #selector(onLoginButtonTapped)) + luaResetPasswordView.configureCreateAccountButton(target: self, selector: #selector(onCreateAccountButtonTapped)) + luaResetPasswordView.configurePasswordRecoveryButton(target: self, selector: #selector(onPasswordRecoveryButtonTapped)) + } + + func configureTextField() { + luaResetPasswordView.configureEmailTextFieldOnEditing(target: self, selector: #selector(onEmailTextFieldEdit)) + luaResetPasswordView.configureEmailTextFieldDidBeginEditing(target: self, selector: #selector(emailTextFieldDidBeginEditing)) + luaResetPasswordView.configureEmailTextFieldDidEndEditing(target: self, selector: #selector(emailTextFieldDidEndEditing)) + } + + @IBAction func closeButtonTapped(_ sender: Any) { + dismiss(animated: true) } - func setupRecoverPasswordButton() { - recoverPasswordButton.layer.cornerRadius = recoverPasswordButton.bounds.height / 2 - recoverPasswordButton.backgroundColor = .blue - recoverPasswordButton.setTitleColor(.white, for: .normal) + @IBAction func onPasswordRecoveryButtonTapped(_ sender: Any) { + Task { + await startPasswordRecoveringProcess() + } } - func setupLoginButton() { - loginButton.layer.cornerRadius = createAccountButton.frame.height / 2 - loginButton.layer.borderWidth = 1 - loginButton.layer.borderColor = UIColor.blue.cgColor - loginButton.setTitleColor(.blue, for: .normal) - loginButton.backgroundColor = .white + @IBAction func onLoginButtonTapped(_ sender: Any) { + dismiss(animated: true) } - func setupHelpButton() { - helpButton.layer.cornerRadius = createAccountButton.frame.height / 2 - helpButton.layer.borderWidth = 1 - helpButton.layer.borderColor = UIColor.blue.cgColor - helpButton.setTitleColor(.blue, for: .normal) - helpButton.backgroundColor = .white + @IBAction func onHelpButtonTapped(_ sender: Any) { + coordinator!.openLuaContactUsScreen() } - func setupAccountButton() { - createAccountButton.layer.cornerRadius = createAccountButton.frame.height / 2 - createAccountButton.layer.borderWidth = 1 - createAccountButton.layer.borderColor = UIColor.blue.cgColor - createAccountButton.setTitleColor(.blue, for: .normal) - createAccountButton.backgroundColor = .white + @IBAction func onCreateAccountButtonTapped(_ sender: Any) { + coordinator!.openLuaCreateAccountScreen() } @IBAction func emailTextFieldDidBeginEditing(_ sender: Any) { - emailTextField.setEditingColor() + luaResetPasswordView.emailTextField.setEditingColor() } @IBAction func onEmailTextFieldEdit(_ sender: Any) { - emailTextField.setEditingColor() + luaResetPasswordView.emailTextField.setEditingColor() updatePasswordRecoveryButtonState() } @IBAction func emailTextFieldDidEndEditing(_ sender: Any) { - emailTextField.setDefaultColor() + luaResetPasswordView.emailTextField.setDefaultColor() } } private extension LuaResetPasswordViewController { func validateExistingEmailInput(){ - let emailInputtedIsNotEmpty = emailInputted.isNotEmpty - if emailInputtedIsNotEmpty { - emailTextField.text = emailInputted - emailTextField.isEnabled = false + if luaResetPasswordView.emailInputted.isNotEmpty { + luaResetPasswordView.emailTextField.text = luaResetPasswordView.emailInputted + luaResetPasswordView.emailTextField.isEnabled = false } } func updatePasswordRecoveryButtonState() { - let isEnabled = emailInputted.isNotEmpty + let isEnabled = luaResetPasswordView.emailInputted.isNotEmpty updatePasswordRecoverButtonStatus(newStatus: isEnabled) } func updatePasswordRecoverButtonStatus(newStatus: Bool) { - recoverPasswordButton.backgroundColor = newStatus ? .blue : .gray - recoverPasswordButton.setTitleColor(newStatus ? .white: .blue, for: .normal) - recoverPasswordButton.isEnabled = newStatus + luaResetPasswordView.passwordRecoveryButton.backgroundColor = newStatus ? .defaultViolet : .darkGray + luaResetPasswordView.passwordRecoveryButton.setTitleColor(newStatus ? .white: .defaultViolet, for: .normal) + luaResetPasswordView.passwordRecoveryButton.isEnabled = newStatus } } - - From 9953f89c2d9c302de79a76ff7bf3a36fed2faa77 Mon Sep 17 00:00:00 2001 From: Eirado <111468283+Eirado@users.noreply.github.com> Date: Fri, 14 Feb 2025 03:15:57 -0300 Subject: [PATCH 09/22] viewcontroller factory changes --- .DS_Store | Bin 6148 -> 6148 bytes ...uaResetPasswordViewControllerFactory.swift | 8 +---- .../ResetPassword/LuaResetPasswordView.swift | 22 ++++++------- .../LuaResetPasswordViewController.swift | 29 ++++++++++-------- 4 files changed, 29 insertions(+), 30 deletions(-) diff --git a/.DS_Store b/.DS_Store index 4395db64ce880a20cdb824a363fbf6af70c78fd1..e4a4e9b5ea2670ea1dea31b18cd7efdde6406301 100644 GIT binary patch delta 19 acmZoMXffEJ$;@=(*W`R=qs_6*%S8Z4ZU+tk delta 19 acmZoMXffEJ$;`C-|KxmTqs_6*%S8Z45eEhU diff --git a/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewControllerFactory.swift b/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewControllerFactory.swift index 2f87f65..697cd27 100644 --- a/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewControllerFactory.swift +++ b/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewControllerFactory.swift @@ -11,15 +11,9 @@ struct LuaResetPasswordViewControllerFactory { static func makeLuaResetPasswordViewController() -> UIViewController { let viewModel = LuaResetPasswordViewModelFactory.makeLuaResetPasswordViewModel() let coordinator = LuaBasicCoordinator() - let storyboard = UIStoryboard(name: "LuaUser", bundle: nil) - guard let viewController = storyboard.instantiateViewController(withIdentifier: "LuaResetPasswordViewController") as? LuaResetPasswordViewController else { - fatalError("Could not instantiate LuaResetPasswordViewController from LuaUser storyboard") - } - viewController.configure(viewModel: viewModel, coordinator: coordinator) + let viewController = LuaResetPasswordViewController(viewModel: viewModel, coordinator: coordinator) viewController.modalPresentationStyle = .fullScreen - coordinator.viewController = viewController return viewController } - } diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift index d66332d..82a8641 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift @@ -44,7 +44,7 @@ class LuaResetPasswordView: UIView, LuaResetPasswordViewProtocol { public lazy var successLabel: UILabel = { let label = UILabel() label.text = "Se o e-mail informado estiver cadastrado, você receberá em instantes um link de recuperação de senha. E-mail enviado para:" - label.font = UIFont(name: "SourceSansPro-Regular", size: 14) + label.font = .systemFont(ofSize: 14) label.textColor = .lightGray label.textAlignment = .center label.numberOfLines = 5 @@ -52,10 +52,10 @@ class LuaResetPasswordView: UIView, LuaResetPasswordViewProtocol { return label }() - private lazy var emailSentLabel: UILabel = { + public lazy var emailSentLabel: UILabel = { let label = UILabel() label.text = "email@email.com" - label.font = UIFont(name: "SourceSansPro-Bold", size: 14) + label.font = .systemFont(ofSize: 14) label.textColor = .white label.textAlignment = .center label.translatesAutoresizingMaskIntoConstraints = false @@ -65,7 +65,7 @@ class LuaResetPasswordView: UIView, LuaResetPasswordViewProtocol { public lazy var emailLabel: UILabel = { let label = UILabel() label.text = "Informe o e-mail associado à sua conta" - label.font = UIFont(name: "SourceSansPro-Regular", size: 12) + label.font = .systemFont(ofSize: 12) label.textColor = .lightGray label.textAlignment = .center label.translatesAutoresizingMaskIntoConstraints = false @@ -76,7 +76,7 @@ class LuaResetPasswordView: UIView, LuaResetPasswordViewProtocol { let textField = UITextField() textField.placeholder = "E-mail" textField.borderStyle = .roundedRect - textField.font = UIFont(name: "SourceSansPro-Regular", size: 12) + textField.font = .systemFont(ofSize: 12) textField.textColor = .black textField.setDefaultColor() textField.keyboardType = .emailAddress @@ -88,7 +88,7 @@ class LuaResetPasswordView: UIView, LuaResetPasswordViewProtocol { public lazy var passwordRecoveryButton: UIButton = { let button = UIButton(type: .system) button.setTitle("RECUPERAR SENHA", for: .normal) - button.titleLabel?.font = UIFont(name: "OpenSans-Bold", size: 15) + button.titleLabel?.font = .systemFont(ofSize: 15) button.backgroundColor = UIColor.defaultViolet button.setTitleColor(.white, for: .normal) button.layer.cornerRadius = 20 @@ -100,7 +100,7 @@ class LuaResetPasswordView: UIView, LuaResetPasswordViewProtocol { private lazy var loginButton: UIButton = { let button = UIButton(type: .system) button.setTitle("LOGIN", for: .normal) - button.titleLabel?.font = UIFont(name: "OpenSans-Bold", size: 15) + button.titleLabel?.font = .systemFont(ofSize: 15) button.backgroundColor = .clear button.setTitleColor(UIColor.defaultViolet, for: .normal) button.backgroundColor = .white @@ -114,7 +114,7 @@ class LuaResetPasswordView: UIView, LuaResetPasswordViewProtocol { private lazy var helpButton: UIButton = { let button = UIButton(type: .system) button.setTitle("PRECISO DE AJUDA", for: .normal) - button.titleLabel?.font = UIFont(name: "OpenSans-Bold", size: 15) + button.titleLabel?.font = .systemFont(ofSize: 15) button.backgroundColor = .clear button.setTitleColor(UIColor.defaultViolet, for: .normal) button.backgroundColor = .white @@ -128,7 +128,7 @@ class LuaResetPasswordView: UIView, LuaResetPasswordViewProtocol { private lazy var createAccountButton: UIButton = { let button = UIButton(type: .system) button.setTitle("CRIAR UMA CONTA", for: .normal) - button.titleLabel?.font = UIFont(name: "OpenSans-Bold", size: 15) + button.titleLabel?.font = .systemFont(ofSize: 15) button.backgroundColor = .clear button.setTitleColor( UIColor.defaultViolet, for: .normal) button.backgroundColor = .white @@ -176,11 +176,11 @@ class LuaResetPasswordView: UIView, LuaResetPasswordViewProtocol { } private func addSubviewsToContentView() { - [smokeImageView, passwordRecoverySuccessView, emailLabel, emailTextField, passwordRecoveryButton, loginButton, helpButton, createAccountButton, closeButton].forEach { contentView.addSubview($0) } + [smokeImageView, passwordRecoverySuccessView, emailLabel, emailTextField, passwordRecoveryButton, loginButton, helpButton, createAccountButton, closeButton].forEach { contentView.addSubview($0) } } private func addSubviewsTosuccessView() { - [successLabel, emailSentLabel].forEach { passwordRecoverySuccessView.addSubview($0) } + [successLabel, emailSentLabel].forEach { passwordRecoverySuccessView.addSubview($0) } } private func addConstraintsToUIComponents() { diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift index 164084f..19c0fad 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift @@ -3,13 +3,18 @@ import UIKit final class LuaResetPasswordViewController: UIViewController, LuaAlertHandlerProtocol { private let luaResetPasswordView = LuaResetPasswordView() - private var viewModel: LuaResetPasswordViewModelProtocol? - private var coordinator: LuaCoordinatorProtocol? + private var viewModel: LuaResetPasswordViewModelProtocol + private var coordinator: LuaCoordinatorProtocol private var hasRequestedRecovery = false - func configure(viewModel: LuaResetPasswordViewModelProtocol, coordinator: LuaCoordinatorProtocol) { - self.viewModel = viewModel - self.coordinator = coordinator + init(viewModel: LuaResetPasswordViewModelProtocol, coordinator: LuaBasicCoordinator) { + self.viewModel = viewModel + self.coordinator = coordinator + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") } override func loadView() { @@ -38,13 +43,13 @@ final class LuaResetPasswordViewController: UIViewController, LuaAlertHandlerPro await resquestPasswordReset() self.view.endEditing(true) } catch { - displayFormError(textField: luaResetPasswordView.emailTextField, label: luaResetPasswordView.successLabel, errorText: LuaUserAccountError.invalidEmail.localizedDescription) + displayFormError(textField: luaResetPasswordView.emailTextField, label: luaResetPasswordView.emailLabel, errorText: LuaUserAccountError.invalidEmail.localizedDescription) } } private func resquestPasswordReset() async { do { - try await viewModel!.startPasswordResetRequest(targetViewController: self, emailInputted: luaResetPasswordView.emailInputted) + try await viewModel.startPasswordResetRequest(targetViewController: self, emailInputted: luaResetPasswordView.emailInputted) displayPasswordResetSuccessUI() } catch let error as LuaNetworkError { handle(error: error, from: self, alertTitle: error.errorTitle) @@ -54,7 +59,7 @@ final class LuaResetPasswordViewController: UIViewController, LuaAlertHandlerPro } private func validateEmailFormat() throws { - guard viewModel!.validateEmailFormat(inputedEmail: luaResetPasswordView.emailInputted) else { + guard viewModel.validateEmailFormat(inputedEmail: luaResetPasswordView.emailInputted) else { throw LuaUserAccountError.invalidEmail } } @@ -62,9 +67,9 @@ final class LuaResetPasswordViewController: UIViewController, LuaAlertHandlerPro private func displayPasswordResetSuccessUI() { self.hasRequestedRecovery = true luaResetPasswordView.emailTextField.isHidden = true - luaResetPasswordView.successLabel.isHidden = true + luaResetPasswordView.emailLabel.isHidden = true luaResetPasswordView.passwordRecoverySuccessView.isHidden = false - luaResetPasswordView.emailLabel.text = luaResetPasswordView.emailInputted + luaResetPasswordView.emailSentLabel.text = luaResetPasswordView.emailInputted luaResetPasswordView.passwordRecoveryButton.setTitle("Voltar", for: .normal) } @@ -107,11 +112,11 @@ private extension LuaResetPasswordViewController { } @IBAction func onHelpButtonTapped(_ sender: Any) { - coordinator!.openLuaContactUsScreen() + coordinator.openLuaContactUsScreen() } @IBAction func onCreateAccountButtonTapped(_ sender: Any) { - coordinator!.openLuaCreateAccountScreen() + coordinator.openLuaCreateAccountScreen() } @IBAction func emailTextFieldDidBeginEditing(_ sender: Any) { From cc1846a8e619740d9cc9fe7105834904fa740d32 Mon Sep 17 00:00:00 2001 From: Eirado <111468283+Eirado@users.noreply.github.com> Date: Fri, 14 Feb 2025 03:16:14 -0300 Subject: [PATCH 10/22] Update .DS_Store --- .DS_Store | Bin 6148 -> 6148 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/.DS_Store b/.DS_Store index e4a4e9b5ea2670ea1dea31b18cd7efdde6406301..1cbbec3d3d0a58aaa0306c4e481a83025af75ca9 100644 GIT binary patch delta 19 acmZoMXffEJ$;@;hb8 Date: Fri, 14 Feb 2025 12:44:11 -0300 Subject: [PATCH 11/22] UIRefactor --- .DS_Store | Bin 6148 -> 6148 bytes CleanCodeApp/AppDelegate/SceneDelegate.swift | 2 +- .../Lua/ContactsUs/LuaContactUsView.swift | 214 ++++++++++++++++++ .../LuaContactUsViewController.swift | 133 ++--------- .../ResetPassword/LuaResetPasswordView.swift | 4 +- 5 files changed, 230 insertions(+), 123 deletions(-) create mode 100644 CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsView.swift diff --git a/.DS_Store b/.DS_Store index 1cbbec3d3d0a58aaa0306c4e481a83025af75ca9..7ff96106cc45fd2a3fda6da0edde94fa715081be 100644 GIT binary patch delta 19 acmZoMXffEJ$;@=rWpX~V(dJm@ UIViewController { } let storyboard = UIStoryboard(name: "\(userIdentifier)User", bundle: nil) let vc = storyboard.instantiateViewController(withIdentifier: "\(userIdentifier)LoginViewController") - return vc + return LuaContactUsViewController() } enum Users { diff --git a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsView.swift b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsView.swift new file mode 100644 index 0000000..7f7720b --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsView.swift @@ -0,0 +1,214 @@ +import UIKit + +protocol LuaContactUsViewProtocol { + func configurePhoneButton(target: Any, selector: Selector) + func configureEmailButton(target: Any, selector: Selector) + func configureChatButton(target: Any, selector: Selector) + func configureSendMessageButton(target: Any, selector: Selector) + func configureCloseButton(target: Any, selector: Selector) +} + +class LuaContactUsView: UIView, LuaContactUsViewProtocol { + + // MARK: - Lazy UI Components + private lazy var scrollView: UIScrollView = { + let scrollView = UIScrollView() + scrollView.translatesAutoresizingMaskIntoConstraints = false + return scrollView + }() + + private lazy var contentView: UIView = { + let view = UIView() + view.translatesAutoresizingMaskIntoConstraints = false + return view + }() + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.textColor = .black + label.font = UIFont.systemFont(ofSize: 24, weight: .semibold) + label.text = "Escolha o canal para contato" + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() + + private lazy var phoneButton: UIButton = { + let button = UIButton() + button.backgroundColor = .systemGray4 + button.layer.cornerRadius = 10 + let symbolConfiguration = UIImage.SymbolConfiguration(pointSize: 36) + button.setImage(UIImage(systemName: "phone")?.withConfiguration(symbolConfiguration), for: .normal) + button.translatesAutoresizingMaskIntoConstraints = false + return button + }() + + private lazy var emailButton: UIButton = { + let button = UIButton() + button.backgroundColor = .systemGray4 + button.layer.cornerRadius = 10 + let symbolConfiguration = UIImage.SymbolConfiguration(pointSize: 36) + button.setImage(UIImage(systemName: "envelope")?.withConfiguration(symbolConfiguration), for: .normal) + button.translatesAutoresizingMaskIntoConstraints = false + return button + }() + + private lazy var chatButton: UIButton = { + let button = UIButton() + button.backgroundColor = .systemGray4 + button.layer.cornerRadius = 10 + let symbolConfiguration = UIImage.SymbolConfiguration(pointSize: 36) + button.setImage(UIImage(systemName: "message")?.withConfiguration(symbolConfiguration), for: .normal) + button.translatesAutoresizingMaskIntoConstraints = false + return button + }() + + private lazy var messageLabel: UILabel = { + let label = UILabel() + label.textColor = .black + label.font = UIFont.systemFont(ofSize: 16, weight: .semibold) + label.text = "Ou envie uma mensagem" + label.numberOfLines = 2 + label.setContentHuggingPriority(.defaultLow, for: .horizontal) + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() + + public lazy var textView: UITextView = { + let textView = UITextView() + textView.text = "Escreva sua mensagem aqui" + textView.font = .systemFont(ofSize: 10) + textView.backgroundColor = .systemGray5 + textView.layer.cornerRadius = 10 + textView.translatesAutoresizingMaskIntoConstraints = false + return textView + }() + + private lazy var sendMessageButton: UIButton = { + let button = UIButton() + button.backgroundColor = .blue + button.setTitle(" Enviar ", for: .normal) + button.setTitleColor(.white, for: .normal) + button.layer.cornerRadius = 10 + button.setContentHuggingPriority(.required, for: .horizontal) + button.translatesAutoresizingMaskIntoConstraints = false + return button + }() + + private lazy var closeButton: UIButton = { + let button = UIButton() + button.setTitle("Voltar", for: .normal) + button.setTitleColor(.blue, for: .normal) + button.backgroundColor = .clear + button.layer.borderWidth = 1 + button.layer.borderColor = UIColor.blue.cgColor + button.layer.cornerRadius = 10 + button.translatesAutoresizingMaskIntoConstraints = false + return button + }() + + // MARK: - Lifecycle + override init(frame: CGRect) { + super.init(frame: frame) + setupView() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: - Setup UI + private func setupView() { + backgroundColor = .systemGray6 + addSubview(scrollView) + scrollView.addSubview(contentView) + addSubviewsToContentView() + addConstraintToUIElements() + } + + private func addSubviewsToContentView() { + [titleLabel, phoneButton, emailButton, chatButton, messageLabel, textView, sendMessageButton, closeButton ].forEach { contentView.addSubview($0) } + } + + private func addConstraintToUIElements() { + NSLayoutConstraint.activate([ + + scrollView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor), + scrollView.leadingAnchor.constraint(equalTo: leadingAnchor), + scrollView.trailingAnchor.constraint(equalTo: trailingAnchor), + scrollView.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor), + + // ContentView + contentView.topAnchor.constraint(equalTo: scrollView.topAnchor), + contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor), + contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor), + contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor), + contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor), + + // Title Label + titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 20), + titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), + titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), + + // Phone Button + phoneButton.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 30), + phoneButton.widthAnchor.constraint(equalToConstant: 80), + phoneButton.heightAnchor.constraint(equalToConstant: 80), + phoneButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), + + // Email Button + emailButton.centerYAnchor.constraint(equalTo: phoneButton.centerYAnchor), + emailButton.widthAnchor.constraint(equalToConstant: 80), + emailButton.heightAnchor.constraint(equalToConstant: 80), + emailButton.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), + + // Chat Button + chatButton.centerYAnchor.constraint(equalTo: phoneButton.centerYAnchor), + chatButton.widthAnchor.constraint(equalToConstant: 80), + chatButton.heightAnchor.constraint(equalToConstant: 80), + chatButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), + + // Message Label + messageLabel.topAnchor.constraint(equalTo: phoneButton.bottomAnchor, constant: 30), + messageLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), + messageLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), + + // TextView + textView.topAnchor.constraint(equalTo: messageLabel.bottomAnchor, constant: 20), + textView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), + textView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), + textView.heightAnchor.constraint(equalToConstant: 350), + + sendMessageButton.topAnchor.constraint(equalTo: textView.bottomAnchor, constant: 20), + sendMessageButton.heightAnchor.constraint(equalToConstant: 40), + sendMessageButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), + sendMessageButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), + + closeButton.topAnchor.constraint(equalTo: sendMessageButton.bottomAnchor, constant: 20), + closeButton.heightAnchor.constraint(equalToConstant: 40), + closeButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), + closeButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), + closeButton.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -20) + ]) + } + // MARK: - Target configuration + func configurePhoneButton(target: Any, selector: Selector){ + phoneButton.addTarget(target, action: selector, for: .touchUpInside) + } + func configureEmailButton(target: Any, selector: Selector){ + emailButton.addTarget(target, action: selector, for: .touchUpInside) + } + func configureChatButton(target: Any, selector: Selector){ + chatButton.addTarget(target, action: selector, for: .touchUpInside) + } + func configureSendMessageButton(target: Any, selector: Selector){ + sendMessageButton.addTarget(target, action: selector, for: .touchUpInside) + } + func configureCloseButton(target: Any, selector: Selector){ + closeButton.addTarget(target, action: selector, for: .touchUpInside) + } + +} + +//#Preview { +// LuaContactUsView() +//} diff --git a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift index dc5e58f..a4f0d08 100644 --- a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift +++ b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift @@ -9,126 +9,20 @@ import UIKit class LuaContactUsViewController: LoadingInheritageController { var model: ContactUsModel? - let textView = UITextView() - + var luaContactUsView = LuaContactUsView() override func viewDidLoad() { super.viewDidLoad() - - view.backgroundColor = .systemGray6 - let titleLabel = UILabel() - titleLabel.textColor = .black - titleLabel.font = UIFont.systemFont(ofSize: 24, weight: .semibold) - titleLabel.text = "Escolha o canal para contato" - - // Criar botões - let phoneButton = UIButton() - phoneButton.backgroundColor = .systemGray4 - phoneButton.layer.cornerRadius = 10 - phoneButton.addTarget(self, action: #selector(phoneClick), for: .touchUpInside) - let emailButton = UIButton() - emailButton.backgroundColor = .systemGray4 - emailButton.layer.cornerRadius = 10 - emailButton.addTarget(self, action: #selector(emailClick), for: .touchUpInside) - - let chatButton = UIButton() - chatButton.backgroundColor = .systemGray4 - chatButton.layer.cornerRadius = 10 - chatButton.addTarget(self, action: #selector(chatClicked), for: .touchUpInside) - - let messageLabel = UILabel() - messageLabel.textColor = .black - messageLabel.font = UIFont.systemFont(ofSize: 16, weight: .semibold) - messageLabel.text = "Ou envie uma mensagem" - messageLabel.numberOfLines = 2 - messageLabel.setContentHuggingPriority(.defaultLow, for: .horizontal) - - let sendMessageButton = UIButton() - sendMessageButton.backgroundColor = .blue - sendMessageButton.setTitle(" Enviar ", for: .normal) - sendMessageButton.setTitleColor(.white, for: .normal) - sendMessageButton.layer.cornerRadius = 10 - sendMessageButton.setContentHuggingPriority(.required, for: .horizontal) - sendMessageButton.addTarget(self, action: #selector(messageSend), for: .touchUpInside) - - textView.text = "Escreva sua mensagem aqui" - let closeButton = UIButton() - closeButton.setTitle("Voltar", for: .normal) - closeButton.setTitleColor(.blue, for: .normal) - closeButton.backgroundColor = .clear - closeButton.layer.borderWidth = 1 - closeButton.layer.borderColor = UIColor.blue.cgColor - closeButton.layer.cornerRadius = 10 - closeButton.addTarget(self, action: #selector(close), for: .touchUpInside) - - - let symbolConfiguration = UIImage.SymbolConfiguration(pointSize: 36) - phoneButton.setImage(UIImage.init(systemName: "phone")?.withConfiguration(symbolConfiguration), for: .normal) - emailButton.setImage(UIImage.init(systemName: "envelope")?.withConfiguration(symbolConfiguration), for: .normal) - chatButton.setImage(UIImage.init(systemName: "message")?.withConfiguration(symbolConfiguration), for: .normal) - - titleLabel.translatesAutoresizingMaskIntoConstraints = false - phoneButton.translatesAutoresizingMaskIntoConstraints = false - emailButton.translatesAutoresizingMaskIntoConstraints = false - chatButton.translatesAutoresizingMaskIntoConstraints = false - messageLabel.translatesAutoresizingMaskIntoConstraints = false - textView.translatesAutoresizingMaskIntoConstraints = false - sendMessageButton.translatesAutoresizingMaskIntoConstraints = false - closeButton.translatesAutoresizingMaskIntoConstraints = false - - view.addSubview(titleLabel) - view.addSubview(phoneButton) - view.addSubview(emailButton) - view.addSubview(chatButton) - view.addSubview(messageLabel) - view.addSubview(textView) - view.addSubview(sendMessageButton) - view.addSubview(closeButton) - - NSLayoutConstraint.activate([ - - titleLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 30), - titleLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20), - titleLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20), - - phoneButton.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 30), - emailButton.centerYAnchor.constraint(equalTo: phoneButton.centerYAnchor), - chatButton.centerYAnchor.constraint(equalTo: phoneButton.centerYAnchor), - - phoneButton.widthAnchor.constraint(equalToConstant: 80), - phoneButton.heightAnchor.constraint(equalToConstant: 80), - phoneButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20), - - emailButton.widthAnchor.constraint(equalToConstant: 80), - emailButton.heightAnchor.constraint(equalToConstant: 80), - emailButton.centerXAnchor.constraint(equalTo: view.centerXAnchor), - - chatButton.widthAnchor.constraint(equalToConstant: 80), - chatButton.heightAnchor.constraint(equalToConstant: 80), - chatButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20), - - messageLabel.topAnchor.constraint(equalTo: phoneButton.bottomAnchor, constant: 30), - messageLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20), - messageLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20), -// stackView.heightAnchor.constraint(equalToConstant: 30), - - textView.topAnchor.constraint(equalTo: messageLabel.bottomAnchor, constant: 20), - textView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20), - textView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20), - textView.bottomAnchor.constraint(equalTo: sendMessageButton.topAnchor, constant: -30), - - - sendMessageButton.bottomAnchor.constraint(equalTo: closeButton.topAnchor, constant: -20), - sendMessageButton.heightAnchor.constraint(equalToConstant: 40), - sendMessageButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20), - sendMessageButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20), - - closeButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20), - closeButton.heightAnchor.constraint(equalToConstant: 40), - closeButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20), - closeButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20), - ]) - + view = luaContactUsView pegarDados() + configureButtons() + } + + private func configureButtons() { + luaContactUsView.configureChatButton(target: self, selector: #selector(chatClicked)) + luaContactUsView.configureCloseButton(target: self, selector: #selector(close)) + luaContactUsView.configureEmailButton(target: self, selector: #selector(emailClick)) + luaContactUsView.configurePhoneButton(target: self, selector: #selector(phoneClick)) + luaContactUsView.configureSendMessageButton(target: self, selector: #selector(messageSend)) } @objc @@ -147,8 +41,7 @@ class LuaContactUsViewController: LoadingInheritageController { } } - @objc - func chatClicked() { + @objc func chatClicked() { if let phoneNumber = model?.phone, let whatsappURL = URL(string: "whatsapp://send?phone=\(phoneNumber)&text=Oi)") { if UIApplication.shared.canOpenURL(whatsappURL) { UIApplication.shared.open(whatsappURL, options: [:], completionHandler: nil) @@ -194,7 +87,7 @@ class LuaContactUsViewController: LoadingInheritageController { func messageSend() { view.endEditing(true) let email = model?.mail ?? "" - if let message = textView.text, textView.text.count > 0 { + if let message = luaContactUsView.textView.text, luaContactUsView.textView.text.count > 0 { let parameters: [String: String] = [ "email": email, "mensagem": message diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift index 82a8641..ba1d5f9 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift @@ -231,7 +231,7 @@ class LuaResetPasswordView: UIView, LuaResetPasswordViewProtocol { passwordRecoveryButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), passwordRecoveryButton.heightAnchor.constraint(equalToConstant: 48), - loginButton.topAnchor.constraint(equalTo: passwordRecoveryButton.bottomAnchor, constant: 84), + loginButton.topAnchor.constraint(equalTo: passwordRecoveryButton.bottomAnchor, constant: 84), loginButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), loginButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), loginButton.heightAnchor.constraint(equalToConstant: 48), @@ -253,7 +253,7 @@ class LuaResetPasswordView: UIView, LuaResetPasswordViewProtocol { closeButton.heightAnchor.constraint(equalToConstant: 45) ]) } - + // MARK: - Target configuration public func configurePasswordRecoveryButton(target: Any, selector: Selector) { passwordRecoveryButton.addTarget(target, action: selector, for: .touchUpInside) } From 17d29647563c8dc0b3eaf49776a2983824a0a6b4 Mon Sep 17 00:00:00 2001 From: Eirado <111468283+Eirado@users.noreply.github.com> Date: Sat, 15 Feb 2025 11:18:17 -0300 Subject: [PATCH 12/22] external links handled --- .../Lua/ContactsUs/LuaAppURLTarget.swift | 37 ++++ .../Lua/ContactsUs/LuaContactUsView.swift | 2 +- .../LuaContactUsViewController.swift | 160 ++++++++++++------ .../Lua/LuaErrors/LuaPersonalInfoError.swift | 22 +++ .../LuaErrors/LuaUIApplicationURLError.swift | 20 +++ .../{ => Extensions}/LuaStringExtension.swift | 0 .../LuaUIColorExtensions.swift | 0 .../Protocols/ExternarURLProtocol.swift | 35 ++++ .../LuaAlertHandlerProtocol.swift} | 4 +- .../Protocols/UIviewControllerProtocol.swift | 15 ++ .../ResetPassword/LuaResetPasswordView.swift | 4 +- .../LuaResetPasswordViewController.swift | 63 +++---- .../Globals/LoadingInheritageController.swift | 1 - 13 files changed, 275 insertions(+), 88 deletions(-) create mode 100644 CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaAppURLTarget.swift create mode 100644 CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaPersonalInfoError.swift create mode 100644 CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaUIApplicationURLError.swift rename CleanCodeApp/Modules/Features/Lua/LuaHelpers/{ => Extensions}/LuaStringExtension.swift (100%) rename CleanCodeApp/Modules/Features/Lua/LuaHelpers/{ => Extensions}/LuaUIColorExtensions.swift (100%) create mode 100644 CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/ExternarURLProtocol.swift rename CleanCodeApp/Modules/Features/Lua/LuaHelpers/{LuaAlertErrorHandler.swift => Protocols/LuaAlertHandlerProtocol.swift} (63%) create mode 100644 CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/UIviewControllerProtocol.swift diff --git a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaAppURLTarget.swift b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaAppURLTarget.swift new file mode 100644 index 0000000..2dd0143 --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaAppURLTarget.swift @@ -0,0 +1,37 @@ +// +// LuaAppURLTarget.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 15/02/25. +// + +import Foundation + +enum LuaAppURLTarget { + + case phone(String) + case mail(String) + case whatsapp(String) + + var url: URL? { + switch self { + case .phone(let phoneNumer): + return URL(string: "tel://\(phoneNumer)") + + case .mail(let mail): + return URL(string: "mailto:\(mail)") + + case .whatsapp(let whatsappNumber): + return URL(string:"whatsapp://send?phone=\(whatsappNumber)&text=Oi)") + } + } + + var fallBackURL: URL? { + switch self { + case .whatsapp(let whatsappNumber): + return URL(string:"https://apps.apple.com/app/whatsapp-messenger/id310633997") + default: + return nil + } + } +} diff --git a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsView.swift b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsView.swift index 7f7720b..f3aa803 100644 --- a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsView.swift +++ b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsView.swift @@ -76,7 +76,7 @@ class LuaContactUsView: UIView, LuaContactUsViewProtocol { public lazy var textView: UITextView = { let textView = UITextView() textView.text = "Escreva sua mensagem aqui" - textView.font = .systemFont(ofSize: 10) + textView.font = .systemFont(ofSize: 13) textView.backgroundColor = .systemGray5 textView.layer.cornerRadius = 10 textView.translatesAutoresizingMaskIntoConstraints = false diff --git a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift index a4f0d08..8e0dc3c 100644 --- a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift +++ b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift @@ -7,63 +7,27 @@ import UIKit -class LuaContactUsViewController: LoadingInheritageController { +final class LuaContactUsViewController: UIViewController, LuaAlertHandlerProtocol, LuaViewControllerProtocol { var model: ContactUsModel? - var luaContactUsView = LuaContactUsView() + typealias ViewCode = LuaContactUsView + internal let viewCode = LuaContactUsView() + + override func loadView() { + view = viewCode + } + override func viewDidLoad() { super.viewDidLoad() - view = luaContactUsView pegarDados() configureButtons() + hideKeyboardWhenTappedAround() } - - private func configureButtons() { - luaContactUsView.configureChatButton(target: self, selector: #selector(chatClicked)) - luaContactUsView.configureCloseButton(target: self, selector: #selector(close)) - luaContactUsView.configureEmailButton(target: self, selector: #selector(emailClick)) - luaContactUsView.configurePhoneButton(target: self, selector: #selector(phoneClick)) - luaContactUsView.configureSendMessageButton(target: self, selector: #selector(messageSend)) - } - - @objc - func phoneClick() { - if let tel = model?.phone, - let url = URL(string: "tel://\(tel)") { - UIApplication.shared.open(url, options: [:], completionHandler: nil) - } - } - - @objc - func emailClick() { - if let mail = model?.mail, - let url = URL(string: "mailto:\(mail)") { - UIApplication.shared.open(url, options: [:], completionHandler: nil) - } - } - - @objc func chatClicked() { - if let phoneNumber = model?.phone, let whatsappURL = URL(string: "whatsapp://send?phone=\(phoneNumber)&text=Oi)") { - if UIApplication.shared.canOpenURL(whatsappURL) { - UIApplication.shared.open(whatsappURL, options: [:], completionHandler: nil) - } else { - if let appStoreURL = URL(string: "https://apps.apple.com/app/whatsapp-messenger/id310633997") { - UIApplication.shared.open(appStoreURL, options: [:], completionHandler: nil) - } - } - } - } - - @objc - func close() { - dismiss(animated: true) - } - - + func pegarDados() { - showLoadingView() + showLoading() let url = Endpoints.contactUs AF.shared.request(url, method: .get, parameters: nil, headers: nil) { result in - self.removeLoadingView() + self.stopLoading() switch result { case .success(let data): let decoder = JSONDecoder() @@ -87,15 +51,15 @@ class LuaContactUsViewController: LoadingInheritageController { func messageSend() { view.endEditing(true) let email = model?.mail ?? "" - if let message = luaContactUsView.textView.text, luaContactUsView.textView.text.count > 0 { + if let message = viewCode.textView.text, viewCode.textView.text.count > 0 { let parameters: [String: String] = [ "email": email, "mensagem": message ] - showLoadingView() + showLoading() let url = Endpoints.sendMessage AF.shared.request(url, method: .post, parameters: parameters, headers: nil) { result in - self.removeLoadingView() + self.stopLoading() switch result { case .success: Globals.alertMessage(title: "Sucesso..", message: "Sua mensagem foi enviada", targetVC: self) { @@ -108,3 +72,97 @@ class LuaContactUsViewController: LoadingInheritageController { } } } +// MARK: - Comportamentos de layout +private extension LuaContactUsViewController { + func configureButtons() { + viewCode.configureChatButton(target: self, selector: #selector(chatButtonTapped)) + viewCode.configureCloseButton(target: self, selector: #selector(close)) + viewCode.configureEmailButton(target: self, selector: #selector(emailButtonTapped)) + viewCode.configurePhoneButton(target: self, selector: #selector(phoneButtonTapped)) + viewCode.configureSendMessageButton(target: self, selector: #selector(messageSend)) + } + + @objc func phoneButtonTapped() { + do { + try openPhone() + } catch let error as LuaPersonalInfoError { + showAlertError(error: error, from: self, alertTitle: error.errorTitle) + } catch { + showAlertError(error: error, from: self, alertTitle: "Algo de errado aconteceu. Tente novamente mais tarde.") + } + } + + @objc func emailButtonTapped() { + do { + try openMail() + } catch let error as LuaPersonalInfoError { + showAlertError(error: error, from: self, alertTitle: error.errorTitle) + } catch { + showAlertError(error: error, from: self, alertTitle: "Algo de errado aconteceu. Tente novamente mais tarde.") + } + } + + @objc func chatButtonTapped() { + do { + try openWhatsapp() + } catch let error as LuaPersonalInfoError { + showAlertError(error: error, from: self, alertTitle: error.errorTitle) + } catch { + showAlertError(error: error, from: self, alertTitle: "Algo de errado aconteceu. Tente novamente mais tarde.") + } + } + + @objc func close() { + dismiss(animated: true) + } + + func openPhone() throws { + guard let phoneNumer = model?.phone else { + throw LuaPersonalInfoError.invalidPhoneNumber + } + do { + try openExternalApp(appURLTarget: .phone(phoneNumer)) + } + catch let error as LuaUIApplicationURLError { + showAlertError(error: error, from: self, alertTitle: error.errorTitle) + } + } + + func openWhatsapp() throws { + guard let phoneNumer = model?.phone else { + throw LuaPersonalInfoError.invalidPhoneNumber + } + do { + try openExternalApp(appURLTarget: .whatsapp(phoneNumer)) + } + catch let error as LuaUIApplicationURLError { + showAlertError(error: error, from: self, alertTitle: error.errorTitle) + } + } + + func openMail() throws { + guard let mail = model?.mail else { + throw LuaPersonalInfoError.invalidMail + } + do { + try openExternalApp(appURLTarget: .mail(mail)) + } + catch let error as LuaUIApplicationURLError { + showAlertError(error: error, from: self, alertTitle: error.errorTitle) + } + } + + func openExternalApp(appURLTarget: LuaAppURLTarget) throws { + guard let url = appURLTarget.url else { + throw LuaUIApplicationURLError.invalidAppURL + } + if canOpenURL(url) { + openExternalURL(url) + return + } + guard let fallBackURL = appURLTarget.fallBackURL else { + throw LuaUIApplicationURLError.unableToOpenAppURL + } + openExternalURL(fallBackURL) + } +} diff --git a/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaPersonalInfoError.swift b/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaPersonalInfoError.swift new file mode 100644 index 0000000..f58cb45 --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaPersonalInfoError.swift @@ -0,0 +1,22 @@ +// +// LuaPersonalInfoError.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 15/02/25. +// + +public enum LuaPersonalInfoError: Error { + case invalidPhoneNumber + case invalidMail +} + +extension LuaPersonalInfoError { + var errorTitle: String? { + switch self { + case .invalidMail: + return "Email inválido" + case .invalidPhoneNumber: + return "Número de telefone inválido" + } + } +} diff --git a/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaUIApplicationURLError.swift b/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaUIApplicationURLError.swift new file mode 100644 index 0000000..a5a325a --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaUIApplicationURLError.swift @@ -0,0 +1,20 @@ +// +// LuaUIApplicationURLError.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 15/02/25. +// + +public enum LuaUIApplicationURLError: Error { + case unableToOpenAppURL + case invalidAppURL +} + +extension LuaUIApplicationURLError { + var errorTitle: String? { + switch self { + case .invalidAppURL, .unableToOpenAppURL: + return "Error ao abrir link externo" + } + } +} diff --git a/CleanCodeApp/Modules/Features/Lua/LuaHelpers/LuaStringExtension.swift b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Extensions/LuaStringExtension.swift similarity index 100% rename from CleanCodeApp/Modules/Features/Lua/LuaHelpers/LuaStringExtension.swift rename to CleanCodeApp/Modules/Features/Lua/LuaHelpers/Extensions/LuaStringExtension.swift diff --git a/CleanCodeApp/Modules/Features/Lua/LuaHelpers/LuaUIColorExtensions.swift b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Extensions/LuaUIColorExtensions.swift similarity index 100% rename from CleanCodeApp/Modules/Features/Lua/LuaHelpers/LuaUIColorExtensions.swift rename to CleanCodeApp/Modules/Features/Lua/LuaHelpers/Extensions/LuaUIColorExtensions.swift diff --git a/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/ExternarURLProtocol.swift b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/ExternarURLProtocol.swift new file mode 100644 index 0000000..77457c2 --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/ExternarURLProtocol.swift @@ -0,0 +1,35 @@ +// +// ExternarURLProtocol.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 15/02/25. +// + + +import UIKit + +public protocol ExternalURLProtocol { + func openExternalURL( + _ url: URL, + options: [UIApplication.OpenExternalURLOptionsKey: Any], + completionHandler: (@MainActor @Sendable (Bool) -> Void)? + ) + + func canOpenURL(_ url: URL) -> Bool +} + +extension ExternalURLProtocol { + public func openExternalURL( + _ url: URL, + options: [UIApplication.OpenExternalURLOptionsKey: Any] = [:], + completionHandler: (@MainActor @Sendable (Bool) -> Void)? = nil + ) { + UIApplication.shared.open(url, options: options, completionHandler: completionHandler) + } + + public func canOpenURL(_ url: URL) -> Bool { + return UIApplication.shared.canOpenURL(url) + } +} + +extension UIViewController: ExternalURLProtocol { } diff --git a/CleanCodeApp/Modules/Features/Lua/LuaHelpers/LuaAlertErrorHandler.swift b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/LuaAlertHandlerProtocol.swift similarity index 63% rename from CleanCodeApp/Modules/Features/Lua/LuaHelpers/LuaAlertErrorHandler.swift rename to CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/LuaAlertHandlerProtocol.swift index c84fb5e..8572f6f 100644 --- a/CleanCodeApp/Modules/Features/Lua/LuaHelpers/LuaAlertErrorHandler.swift +++ b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/LuaAlertHandlerProtocol.swift @@ -8,11 +8,11 @@ import UIKit public protocol LuaAlertHandlerProtocol { - func handle(error: Error, from viewController: UIViewController, alertTitle: String?) + func showAlertError(error: Error, from viewController: UIViewController, alertTitle: String?, style: UIAlertController.Style?) } extension LuaAlertHandlerProtocol { - public func handle(error: Error, from viewController: UIViewController, alertTitle: String?) { + public func showAlertError(error: Error, from viewController: UIViewController, alertTitle: String?, style: UIAlertController.Style? = nil) { let alertController = UIAlertController(title: alertTitle, message: error.localizedDescription, preferredStyle: .alert) let action = UIAlertAction(title: "OK", style: .default) alertController.addAction(action) diff --git a/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/UIviewControllerProtocol.swift b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/UIviewControllerProtocol.swift new file mode 100644 index 0000000..b79fa44 --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/UIviewControllerProtocol.swift @@ -0,0 +1,15 @@ +// +// UIviewControllerProtocol.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 15/02/25. +// + +import UIKit + +public protocol LuaViewControllerProtocol { + associatedtype ViewCode: UIView + var viewCode: ViewCode { get } + func hideKeyboardWhenTappedAround() +} + diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift index ba1d5f9..110ae7f 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift @@ -166,7 +166,7 @@ class LuaResetPasswordView: UIView, LuaResetPasswordViewProtocol { } // MARK: - Setup UI - private func setupView() { + func setupView() { backgroundColor = .systemGray6 addSubview(scrollView) scrollView.addSubview(contentView) @@ -183,7 +183,7 @@ class LuaResetPasswordView: UIView, LuaResetPasswordViewProtocol { [successLabel, emailSentLabel].forEach { passwordRecoverySuccessView.addSubview($0) } } - private func addConstraintsToUIComponents() { + func addConstraintsToUIComponents() { NSLayoutConstraint.activate([ scrollView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor), scrollView.leadingAnchor.constraint(equalTo: leadingAnchor), diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift index 19c0fad..60f78c9 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift @@ -1,8 +1,9 @@ import UIKit -final class LuaResetPasswordViewController: UIViewController, LuaAlertHandlerProtocol { +final class LuaResetPasswordViewController: UIViewController, LuaAlertHandlerProtocol, LuaViewControllerProtocol { - private let luaResetPasswordView = LuaResetPasswordView() + typealias ViewCode = LuaResetPasswordView + internal let viewCode = LuaResetPasswordView() private var viewModel: LuaResetPasswordViewModelProtocol private var coordinator: LuaCoordinatorProtocol private var hasRequestedRecovery = false @@ -18,7 +19,7 @@ final class LuaResetPasswordViewController: UIViewController, LuaAlertHandlerPro } override func loadView() { - view = luaResetPasswordView + view = viewCode } override func viewDidLoad() { @@ -43,34 +44,34 @@ final class LuaResetPasswordViewController: UIViewController, LuaAlertHandlerPro await resquestPasswordReset() self.view.endEditing(true) } catch { - displayFormError(textField: luaResetPasswordView.emailTextField, label: luaResetPasswordView.emailLabel, errorText: LuaUserAccountError.invalidEmail.localizedDescription) + displayFormError(textField: viewCode.emailTextField, label: viewCode.emailLabel, errorText: LuaUserAccountError.invalidEmail.localizedDescription) } } private func resquestPasswordReset() async { do { - try await viewModel.startPasswordResetRequest(targetViewController: self, emailInputted: luaResetPasswordView.emailInputted) + try await viewModel.startPasswordResetRequest(targetViewController: self, emailInputted: viewCode.emailInputted) displayPasswordResetSuccessUI() } catch let error as LuaNetworkError { - handle(error: error, from: self, alertTitle: error.errorTitle) + showAlertError(error: error, from: self, alertTitle: error.errorTitle) } catch { - handle(error: error, from: self, alertTitle: "Algo de errado aconteceu. Tente novamente mais tarde.") + showAlertError(error: error, from: self, alertTitle: "Algo de errado aconteceu. Tente novamente mais tarde.") } } private func validateEmailFormat() throws { - guard viewModel.validateEmailFormat(inputedEmail: luaResetPasswordView.emailInputted) else { + guard viewModel.validateEmailFormat(inputedEmail: viewCode.emailInputted) else { throw LuaUserAccountError.invalidEmail } } private func displayPasswordResetSuccessUI() { self.hasRequestedRecovery = true - luaResetPasswordView.emailTextField.isHidden = true - luaResetPasswordView.emailLabel.isHidden = true - luaResetPasswordView.passwordRecoverySuccessView.isHidden = false - luaResetPasswordView.emailSentLabel.text = luaResetPasswordView.emailInputted - luaResetPasswordView.passwordRecoveryButton.setTitle("Voltar", for: .normal) + viewCode.emailTextField.isHidden = true + viewCode.emailLabel.isHidden = true + viewCode.passwordRecoverySuccessView.isHidden = false + viewCode.emailSentLabel.text = viewCode.emailInputted + viewCode.passwordRecoveryButton.setTitle("Voltar", for: .normal) } private func displayFormError(textField: UITextField, label: UILabel, errorText: String) { @@ -84,17 +85,17 @@ final class LuaResetPasswordViewController: UIViewController, LuaAlertHandlerPro private extension LuaResetPasswordViewController { func configureButtons() { - luaResetPasswordView.configureHelpButton(target: self, selector: #selector(onHelpButtonTapped) ) - luaResetPasswordView.configureCloseButton(target: self, selector: #selector(closeButtonTapped)) - luaResetPasswordView.configureLoginButton(target: self, selector: #selector(onLoginButtonTapped)) - luaResetPasswordView.configureCreateAccountButton(target: self, selector: #selector(onCreateAccountButtonTapped)) - luaResetPasswordView.configurePasswordRecoveryButton(target: self, selector: #selector(onPasswordRecoveryButtonTapped)) + viewCode.configureHelpButton(target: self, selector: #selector(onHelpButtonTapped) ) + viewCode.configureCloseButton(target: self, selector: #selector(closeButtonTapped)) + viewCode.configureLoginButton(target: self, selector: #selector(onLoginButtonTapped)) + viewCode.configureCreateAccountButton(target: self, selector: #selector(onCreateAccountButtonTapped)) + viewCode.configurePasswordRecoveryButton(target: self, selector: #selector(onPasswordRecoveryButtonTapped)) } func configureTextField() { - luaResetPasswordView.configureEmailTextFieldOnEditing(target: self, selector: #selector(onEmailTextFieldEdit)) - luaResetPasswordView.configureEmailTextFieldDidBeginEditing(target: self, selector: #selector(emailTextFieldDidBeginEditing)) - luaResetPasswordView.configureEmailTextFieldDidEndEditing(target: self, selector: #selector(emailTextFieldDidEndEditing)) + viewCode.configureEmailTextFieldOnEditing(target: self, selector: #selector(onEmailTextFieldEdit)) + viewCode.configureEmailTextFieldDidBeginEditing(target: self, selector: #selector(emailTextFieldDidBeginEditing)) + viewCode.configureEmailTextFieldDidEndEditing(target: self, selector: #selector(emailTextFieldDidEndEditing)) } @IBAction func closeButtonTapped(_ sender: Any) { @@ -120,36 +121,36 @@ private extension LuaResetPasswordViewController { } @IBAction func emailTextFieldDidBeginEditing(_ sender: Any) { - luaResetPasswordView.emailTextField.setEditingColor() + viewCode.emailTextField.setEditingColor() } @IBAction func onEmailTextFieldEdit(_ sender: Any) { - luaResetPasswordView.emailTextField.setEditingColor() + viewCode.emailTextField.setEditingColor() updatePasswordRecoveryButtonState() } @IBAction func emailTextFieldDidEndEditing(_ sender: Any) { - luaResetPasswordView.emailTextField.setDefaultColor() + viewCode.emailTextField.setDefaultColor() } } private extension LuaResetPasswordViewController { func validateExistingEmailInput(){ - if luaResetPasswordView.emailInputted.isNotEmpty { - luaResetPasswordView.emailTextField.text = luaResetPasswordView.emailInputted - luaResetPasswordView.emailTextField.isEnabled = false + if viewCode.emailInputted.isNotEmpty { + viewCode.emailTextField.text = viewCode.emailInputted + viewCode.emailTextField.isEnabled = false } } func updatePasswordRecoveryButtonState() { - let isEnabled = luaResetPasswordView.emailInputted.isNotEmpty + let isEnabled = viewCode.emailInputted.isNotEmpty updatePasswordRecoverButtonStatus(newStatus: isEnabled) } func updatePasswordRecoverButtonStatus(newStatus: Bool) { - luaResetPasswordView.passwordRecoveryButton.backgroundColor = newStatus ? .defaultViolet : .darkGray - luaResetPasswordView.passwordRecoveryButton.setTitleColor(newStatus ? .white: .defaultViolet, for: .normal) - luaResetPasswordView.passwordRecoveryButton.isEnabled = newStatus + viewCode.passwordRecoveryButton.backgroundColor = newStatus ? .defaultViolet : .darkGray + viewCode.passwordRecoveryButton.setTitleColor(newStatus ? .white: .defaultViolet, for: .normal) + viewCode.passwordRecoveryButton.isEnabled = newStatus } } diff --git a/CleanCodeApp/Modules/Utils/Globals/LoadingInheritageController.swift b/CleanCodeApp/Modules/Utils/Globals/LoadingInheritageController.swift index b9b9dd4..048133a 100644 --- a/CleanCodeApp/Modules/Utils/Globals/LoadingInheritageController.swift +++ b/CleanCodeApp/Modules/Utils/Globals/LoadingInheritageController.swift @@ -38,7 +38,6 @@ class LoadingInheritageController: UIViewController { self.loadingView.removeFromSuperview() } } - } From bdc6859c010e74fd5802a5fbf8978a685c4dbd7c Mon Sep 17 00:00:00 2001 From: Eirado <111468283+Eirado@users.noreply.github.com> Date: Sat, 15 Feb 2025 11:38:32 -0300 Subject: [PATCH 13/22] starting network manager --- .../Lua/ContactsUs/LuaAppURLTarget.swift | 4 ++-- .../Lua/ContactsUs/LuaContactUsView.swift | 4 ++-- .../LuaContactUsViewController.swift | 5 ++++- .../Lua/ContactsUs/LuaContactUsViewModel.swift | 11 +++++++++++ .../Lua/LuaNetwork/LuaNetworkManager.swift | 18 ++++++++++++++++++ 5 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewModel.swift create mode 100644 CleanCodeApp/Modules/Features/Lua/LuaNetwork/LuaNetworkManager.swift diff --git a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaAppURLTarget.swift b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaAppURLTarget.swift index 2dd0143..313adc6 100644 --- a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaAppURLTarget.swift +++ b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaAppURLTarget.swift @@ -7,7 +7,7 @@ import Foundation -enum LuaAppURLTarget { +public enum LuaAppURLTarget { case phone(String) case mail(String) @@ -28,7 +28,7 @@ enum LuaAppURLTarget { var fallBackURL: URL? { switch self { - case .whatsapp(let whatsappNumber): + case .whatsapp: return URL(string:"https://apps.apple.com/app/whatsapp-messenger/id310633997") default: return nil diff --git a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsView.swift b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsView.swift index f3aa803..697b0e1 100644 --- a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsView.swift +++ b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsView.swift @@ -1,6 +1,6 @@ import UIKit -protocol LuaContactUsViewProtocol { +public protocol LuaContactUsViewProtocol { func configurePhoneButton(target: Any, selector: Selector) func configureEmailButton(target: Any, selector: Selector) func configureChatButton(target: Any, selector: Selector) @@ -8,7 +8,7 @@ protocol LuaContactUsViewProtocol { func configureCloseButton(target: Any, selector: Selector) } -class LuaContactUsView: UIView, LuaContactUsViewProtocol { +final class LuaContactUsView: UIView, LuaContactUsViewProtocol { // MARK: - Lazy UI Components private lazy var scrollView: UIScrollView = { diff --git a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift index 8e0dc3c..6d8bbd7 100644 --- a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift +++ b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift @@ -7,8 +7,9 @@ import UIKit -final class LuaContactUsViewController: UIViewController, LuaAlertHandlerProtocol, LuaViewControllerProtocol { +final class LuaContactUsViewController: UIViewController, LuaViewControllerProtocol, LuaAlertHandlerProtocol { var model: ContactUsModel? + typealias ViewCode = LuaContactUsView internal let viewCode = LuaContactUsView() @@ -25,7 +26,9 @@ final class LuaContactUsViewController: UIViewController, LuaAlertHandlerProtoco func pegarDados() { showLoading() + let url = Endpoints.contactUs + AF.shared.request(url, method: .get, parameters: nil, headers: nil) { result in self.stopLoading() switch result { diff --git a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewModel.swift b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewModel.swift new file mode 100644 index 0000000..6371425 --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewModel.swift @@ -0,0 +1,11 @@ +// +// LuaContactUsViewModel.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 15/02/25. +// + + +final class LuaContactUsViewModel { + +} diff --git a/CleanCodeApp/Modules/Features/Lua/LuaNetwork/LuaNetworkManager.swift b/CleanCodeApp/Modules/Features/Lua/LuaNetwork/LuaNetworkManager.swift new file mode 100644 index 0000000..5be8f5d --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/LuaNetwork/LuaNetworkManager.swift @@ -0,0 +1,18 @@ +// +// LuaNetworkManager.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 15/02/25. +// + +public enum APITarget { + +} + +private protocol LuaNetworkingProtocol { + func request(_ target: APITarget) async throws -> T +} + +extension LuaNetworkingProtocol { + +} From 910e817487d6e270ba193f1b71fdf76189950d01 Mon Sep 17 00:00:00 2001 From: Eirado <111468283+Eirado@users.noreply.github.com> Date: Mon, 17 Feb 2025 09:06:56 -0300 Subject: [PATCH 14/22] sendMessage request --- .../LuaContactUsViewController.swift | 81 ++++++++---- .../ContactsUs/LuaContactUsViewModel.swift | 22 ++++ .../Lua/LuaErrors/LuaNetworkError.swift | 25 ++-- .../Lua/LuaNetwork/LuaAPITarget.swift | 118 ++++++++++++++++++ .../Lua/LuaNetwork/LuaNetworkManager.swift | 71 ++++++++++- .../LuaResetPasswordViewModel.swift | 2 +- 6 files changed, 269 insertions(+), 50 deletions(-) create mode 100644 CleanCodeApp/Modules/Features/Lua/LuaNetwork/LuaAPITarget.swift diff --git a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift index 6d8bbd7..8ea0bd6 100644 --- a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift +++ b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift @@ -9,22 +9,22 @@ import UIKit final class LuaContactUsViewController: UIViewController, LuaViewControllerProtocol, LuaAlertHandlerProtocol { var model: ContactUsModel? - + typealias ViewCode = LuaContactUsView internal let viewCode = LuaContactUsView() - + private let viewModel = LuaContactUsViewModel() override func loadView() { view = viewCode } override func viewDidLoad() { super.viewDidLoad() - pegarDados() + FetchContactUSData() configureButtons() - hideKeyboardWhenTappedAround() + hideKeyboardWhenTappedAround() } - - func pegarDados() { + + private func FetchContactUSData() { showLoading() let url = Endpoints.contactUs @@ -50,30 +50,55 @@ final class LuaContactUsViewController: UIViewController, LuaViewControllerProto } } - @objc - func messageSend() { + private func startSendMessageProcess() { view.endEditing(true) - let email = model?.mail ?? "" - if let message = viewCode.textView.text, viewCode.textView.text.count > 0 { - let parameters: [String: String] = [ - "email": email, - "mensagem": message - ] + let hasMessage = viewCode.textView.text.isNotEmpty && viewCode.textView.text != "Escreva sua mensagem aqui" + if hasMessage { + + let message = viewCode.textView.text! + let email = model?.mail ?? "" + showLoading() - let url = Endpoints.sendMessage - AF.shared.request(url, method: .post, parameters: parameters, headers: nil) { result in - self.stopLoading() - switch result { - case .success: - Globals.alertMessage(title: "Sucesso..", message: "Sua mensagem foi enviada", targetVC: self) { - self.dismiss(animated: true) - } - case .failure: - Globals.alertMessage(title: "Ops..", message: "Ocorreu algum erro", targetVC: self) - } + + do { + try viewModel.sendMessage(message: message, mail: email) + // need a alert to success + self.dismiss(animated: true) + } catch { + showAlertError(error: error, from: self, alertTitle: "Ocorreu algum erro") } + + stopLoading() + return } + // need a alert to show that user does not wrote a message } + + + // @objc + // func sendMessage() { + // view.endEditing(true) + // let email = model?.mail ?? "" + // if let message = viewCode.textView.text, viewCode.textView.text.count > 0 { + // let parameters: [String: String] = [ + // "email": email, + // "mensagem": message + // ] + // showLoading() + // let url = Endpoints.sendMessage + // AF.shared.request(url, method: .post, parameters: parameters, headers: nil) { result in + // self.stopLoading() + // switch result { + // case .success: + // Globals.alertMessage(title: "Sucesso..", message: "Sua mensagem foi enviada", targetVC: self) { + // self.dismiss(animated: true) + // } + // case .failure: + // Globals.alertMessage(title: "Ops..", message: "Ocorreu algum erro", targetVC: self) + // } + // } + // } + // } } // MARK: - Comportamentos de layout private extension LuaContactUsViewController { @@ -82,7 +107,11 @@ private extension LuaContactUsViewController { viewCode.configureCloseButton(target: self, selector: #selector(close)) viewCode.configureEmailButton(target: self, selector: #selector(emailButtonTapped)) viewCode.configurePhoneButton(target: self, selector: #selector(phoneButtonTapped)) - viewCode.configureSendMessageButton(target: self, selector: #selector(messageSend)) + viewCode.configureSendMessageButton(target: self, selector: #selector(sendMessageButtonTapped)) + } + + @objc func sendMessageButtonTapped() { + startSendMessageProcess() } @objc func phoneButtonTapped() { diff --git a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewModel.swift b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewModel.swift index 6371425..3acdbd4 100644 --- a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewModel.swift +++ b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewModel.swift @@ -8,4 +8,26 @@ final class LuaContactUsViewModel { + private let networkManager = LuaNetworkManager() + + + func sendMessage(message: String, mail: String) throws { + + Task { + do { + let params = makeSendParams(message: message, mail: mail) + let response: [String: String] = try await networkManager.request(.sendContactUsMessage(params)) + } catch { + throw error + } + } + } + + private func makeSendParams(message: String, mail: String) -> [String:String] { + let params: [String: String] = [ + "email": mail, + "mensagem": message + ] + return params + } } diff --git a/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaNetworkError.swift b/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaNetworkError.swift index 6fb3b5f..6cfd72b 100644 --- a/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaNetworkError.swift +++ b/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaNetworkError.swift @@ -8,17 +8,17 @@ import Foundation enum LuaNetworkError: Error { - case decodeError - case noData - case invalidURL - case invalidStatusCode - case networkError + case badRequest // 400 + case unauthorized // 401 + case forbidden // 403 + case notFound // 404 + case serverError // 500 + case unknown case noInternetConnection } extension LuaNetworkError: LocalizedError { - var errorTitle: String? { switch self { case .noInternetConnection: @@ -30,19 +30,10 @@ extension LuaNetworkError: LocalizedError { var errorDescription: String? { switch self { - case .decodeError: - return "Error during data decoding" - case .noData: - return "Data error" - case .invalidURL: - return "Invalid URL" - case .invalidStatusCode: - return "Invalid status code" - case .networkError: - return "An error has occurred. Please verify your connection." case .noInternetConnection: return "Você não está conectado à internet. Verifique sua conexão e tente novamente." + default: + return "" } } - } diff --git a/CleanCodeApp/Modules/Features/Lua/LuaNetwork/LuaAPITarget.swift b/CleanCodeApp/Modules/Features/Lua/LuaNetwork/LuaAPITarget.swift new file mode 100644 index 0000000..4734764 --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/LuaNetwork/LuaAPITarget.swift @@ -0,0 +1,118 @@ +// +// APITarget.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 15/02/25. +// + +import Foundation + +public enum LuaAPIAuthTarget { + case login + case createUser + case resetPassword +} + +public enum LuaAPITarget { + case authTarget(LuaAPIAuthTarget) + case getContactUsData + case sendContactUsMessage([String: Any]) + + private var baseURL: URL! { + switch self { + case .sendContactUsMessage, .getContactUsData: + return URL(string: "www.apiQualquer.com") + case .authTarget(let authTarget): + switch authTarget{ + case .createUser, .login: + return URL(string: "www.aplicandoCleanCode.muito.foda") + case .resetPassword: + return URL(string: "www.aplicandocleancodedemaneirafodastico.com") + } + } + } + + private var path: String { + switch self { + case .getContactUsData: + return "/contactUs" + case .sendContactUsMessage: + return "/sendMessage" + case .authTarget(let authTarget): + switch authTarget{ + case .createUser: + return "/create" + case .login: + return "/login" + case .resetPassword: + return "/resetPassword" + } + } + } + + var method: String { + switch self { + case .getContactUsData: + return "GET" + case .sendContactUsMessage: + return "POST" + default: + return "GET" + } + } + + var parameters: [String: Any] { + switch self { + + case .sendContactUsMessage(let params): + return params + default: + return [:] + } + } + + var headers: [String: String] { + return ["Content-Type": "application/json"] + } + + public var url: URL { + return baseURL.appendingPathComponent(path) + } + + var dummyData: Data { + switch self { + case .authTarget(.login): + let session = Session(id: UUID().uuidString, token: UUID().uuidString) + return try! JSONEncoder().encode(session) + + case .authTarget(.createUser): + let session = Session(id: UUID().uuidString, token: UUID().uuidString) + return try! JSONEncoder().encode(session) + + case .authTarget(.resetPassword): + return Data() + + case .getContactUsData: + let contact = ContactUsModel( + whatsapp: "37998988822", + phone: "08001234567", + mail: "cleanCode@devPass.com" + ) + return try! JSONEncoder().encode(contact) + + case .sendContactUsMessage(let params): + + let email = params["email"] as? String ?? "email_nao_informado" + let mensagem = params["mensagem"] as? String ?? "mensagem_nao_informada" + + let response = [ + "message": "sucesso", + "email": email, + "mensagem": mensagem + ] + + return try! JSONEncoder().encode(response) + } + } +} + diff --git a/CleanCodeApp/Modules/Features/Lua/LuaNetwork/LuaNetworkManager.swift b/CleanCodeApp/Modules/Features/Lua/LuaNetwork/LuaNetworkManager.swift index 5be8f5d..51fa6e4 100644 --- a/CleanCodeApp/Modules/Features/Lua/LuaNetwork/LuaNetworkManager.swift +++ b/CleanCodeApp/Modules/Features/Lua/LuaNetwork/LuaNetworkManager.swift @@ -5,14 +5,73 @@ // Created by Gabriel Amaral on 15/02/25. // -public enum APITarget { - +import Foundation + + + +public protocol LuaNetworkSessionProtocol { + func customDataTaskPublisher(for request: URLRequest) async throws -> (Data, URLResponse) } -private protocol LuaNetworkingProtocol { - func request(_ target: APITarget) async throws -> T +extension URLSession: LuaNetworkSessionProtocol { + public func customDataTaskPublisher(for request: URLRequest) async throws -> (Data, URLResponse) { + let (data, response) = try await self.data(for: request) + return (data, response) + } } -extension LuaNetworkingProtocol { - +private protocol LuaNetworkManagerProtocol { + func request(_ target: LuaAPITarget) async throws -> T +} + +final class LuaNetworkManager: LuaNetworkManagerProtocol { + + private let session: LuaNetworkSessionProtocol + private let useMockData: Bool + + init(session: LuaNetworkSessionProtocol = URLSession.shared, useMockData: Bool = true) { + self.session = session + self.useMockData = useMockData + } + + public func request(_ target: LuaAPITarget) async throws -> T { + + if useMockData { + let data = target.dummyData + let decodedData = try JSONDecoder().decode(T.self, from: data) + return decodedData + } + + var request = URLRequest(url: target.url) + request.httpMethod = target.method + request.allHTTPHeaderFields = target.headers + + if target.method == "POST" { + request.httpBody = try? JSONSerialization.data(withJSONObject: target.parameters, options: .prettyPrinted) + } + + let (data, response) = try await session.customDataTaskPublisher(for: request) + + guard let httpResponse = response as? HTTPURLResponse else { + throw LuaNetworkError.unknown + } + + switch httpResponse.statusCode { + case 200..<300: + let decodedData = try JSONDecoder().decode(T.self, from: data) + return decodedData + case 400: + throw LuaNetworkError.badRequest + case 401: + throw LuaNetworkError.unauthorized + case 403: + throw LuaNetworkError.forbidden + case 404: + throw LuaNetworkError.notFound + case 500: + throw LuaNetworkError.serverError + default: + throw LuaNetworkError.unknown + } + } } diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift index 49bb120..3d7290c 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift @@ -22,7 +22,7 @@ final class LuaResetPasswordViewModel: LuaResetPasswordViewModelProtocol { } catch _ as LuaNetworkError { throw LuaNetworkError.noInternetConnection } catch { - throw LuaNetworkError.invalidStatusCode + throw LuaNetworkError.unknown } } From 4dbabed454555091d60fd3dcb224419e1f856b0e Mon Sep 17 00:00:00 2001 From: Eirado <111468283+Eirado@users.noreply.github.com> Date: Mon, 17 Feb 2025 17:16:15 -0300 Subject: [PATCH 15/22] ContactUs done with Pr fixes --- CleanCodeApp/AppDelegate/SceneDelegate.swift | 2 +- .../Lua/ContactsUs/LuaContactUsView.swift | 130 ++++++++---------- .../LuaContactUsViewController.swift | 130 +++++++----------- .../ContactsUs/LuaContactUsViewModel.swift | 23 +++- .../LuaUIViewControllerExtension.swift | 38 +++++ .../Protocols/LuaAlertHandlerProtocol.swift | 8 ++ .../LuaContactUsViewControllerFactory.swift | 3 +- .../Main/LuaContactUsViewModelFactory.swift | 13 ++ .../LuaResetPasswordViewModelFactory.swift | 3 +- .../ResetPassword/LuaResetPasswordView.swift | 45 ++---- .../LuaResetPasswordViewController.swift | 20 +-- .../LuaResetPasswordViewModel.swift | 19 ++- .../UIViewController+extensions.swift | 4 +- 13 files changed, 223 insertions(+), 215 deletions(-) create mode 100644 CleanCodeApp/Modules/Features/Lua/LuaHelpers/Extensions/LuaUIViewControllerExtension.swift create mode 100644 CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewModelFactory.swift diff --git a/CleanCodeApp/AppDelegate/SceneDelegate.swift b/CleanCodeApp/AppDelegate/SceneDelegate.swift index aca7954..88b5245 100644 --- a/CleanCodeApp/AppDelegate/SceneDelegate.swift +++ b/CleanCodeApp/AppDelegate/SceneDelegate.swift @@ -50,7 +50,7 @@ func getRootViewController(forUser user: Users) -> UIViewController { } let storyboard = UIStoryboard(name: "\(userIdentifier)User", bundle: nil) let vc = storyboard.instantiateViewController(withIdentifier: "\(userIdentifier)LoginViewController") - return LuaContactUsViewController() + return LuaResetPasswordViewControllerFactory.makeLuaResetPasswordViewController() } enum Users { diff --git a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsView.swift b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsView.swift index 697b0e1..8bbeefd 100644 --- a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsView.swift +++ b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsView.swift @@ -1,14 +1,6 @@ import UIKit -public protocol LuaContactUsViewProtocol { - func configurePhoneButton(target: Any, selector: Selector) - func configureEmailButton(target: Any, selector: Selector) - func configureChatButton(target: Any, selector: Selector) - func configureSendMessageButton(target: Any, selector: Selector) - func configureCloseButton(target: Any, selector: Selector) -} - -final class LuaContactUsView: UIView, LuaContactUsViewProtocol { +final class LuaContactUsView: UIView { // MARK: - Lazy UI Components private lazy var scrollView: UIScrollView = { @@ -16,13 +8,13 @@ final class LuaContactUsView: UIView, LuaContactUsViewProtocol { scrollView.translatesAutoresizingMaskIntoConstraints = false return scrollView }() - + private lazy var contentView: UIView = { let view = UIView() view.translatesAutoresizingMaskIntoConstraints = false return view }() - + private lazy var titleLabel: UILabel = { let label = UILabel() label.textColor = .black @@ -31,8 +23,8 @@ final class LuaContactUsView: UIView, LuaContactUsViewProtocol { label.translatesAutoresizingMaskIntoConstraints = false return label }() - - private lazy var phoneButton: UIButton = { + + public lazy var phoneButton: UIButton = { let button = UIButton() button.backgroundColor = .systemGray4 button.layer.cornerRadius = 10 @@ -41,8 +33,8 @@ final class LuaContactUsView: UIView, LuaContactUsViewProtocol { button.translatesAutoresizingMaskIntoConstraints = false return button }() - - private lazy var emailButton: UIButton = { + + public lazy var emailButton: UIButton = { let button = UIButton() button.backgroundColor = .systemGray4 button.layer.cornerRadius = 10 @@ -51,8 +43,8 @@ final class LuaContactUsView: UIView, LuaContactUsViewProtocol { button.translatesAutoresizingMaskIntoConstraints = false return button }() - - private lazy var chatButton: UIButton = { + + public lazy var chatButton: UIButton = { let button = UIButton() button.backgroundColor = .systemGray4 button.layer.cornerRadius = 10 @@ -61,29 +53,8 @@ final class LuaContactUsView: UIView, LuaContactUsViewProtocol { button.translatesAutoresizingMaskIntoConstraints = false return button }() - - private lazy var messageLabel: UILabel = { - let label = UILabel() - label.textColor = .black - label.font = UIFont.systemFont(ofSize: 16, weight: .semibold) - label.text = "Ou envie uma mensagem" - label.numberOfLines = 2 - label.setContentHuggingPriority(.defaultLow, for: .horizontal) - label.translatesAutoresizingMaskIntoConstraints = false - return label - }() - - public lazy var textView: UITextView = { - let textView = UITextView() - textView.text = "Escreva sua mensagem aqui" - textView.font = .systemFont(ofSize: 13) - textView.backgroundColor = .systemGray5 - textView.layer.cornerRadius = 10 - textView.translatesAutoresizingMaskIntoConstraints = false - return textView - }() - - private lazy var sendMessageButton: UIButton = { + + public lazy var sendMessageButton: UIButton = { let button = UIButton() button.backgroundColor = .blue button.setTitle(" Enviar ", for: .normal) @@ -93,8 +64,8 @@ final class LuaContactUsView: UIView, LuaContactUsViewProtocol { button.translatesAutoresizingMaskIntoConstraints = false return button }() - - private lazy var closeButton: UIButton = { + + public lazy var closeButton: UIButton = { let button = UIButton() button.setTitle("Voltar", for: .normal) button.setTitleColor(.blue, for: .normal) @@ -105,7 +76,37 @@ final class LuaContactUsView: UIView, LuaContactUsViewProtocol { button.translatesAutoresizingMaskIntoConstraints = false return button }() - + + public lazy var messageLabel: UILabel = { + let label = UILabel() + label.textColor = .black + label.font = UIFont.systemFont(ofSize: 16, weight: .semibold) + label.text = "Ou envie uma mensagem" + label.numberOfLines = 2 + label.setContentHuggingPriority(.defaultLow, for: .horizontal) + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() + + public lazy var textView: UITextView = { + let textView = UITextView() + textView.text = "Escreva sua mensagem aqui" + textView.font = .systemFont(ofSize: 13) + textView.backgroundColor = .systemGray5 + textView.layer.cornerRadius = 10 + textView.translatesAutoresizingMaskIntoConstraints = false + return textView + }() + + public var textInputted: String { + get { + guard let textInputted = textView.text?.trimmingCharacters(in: .whitespacesAndNewlines) else { + return "" + } + return textInputted + } + } + // MARK: - Lifecycle override init(frame: CGRect) { super.init(frame: frame) @@ -115,7 +116,7 @@ final class LuaContactUsView: UIView, LuaContactUsViewProtocol { required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + // MARK: - Setup UI private func setupView() { backgroundColor = .systemGray6 @@ -131,58 +132,58 @@ final class LuaContactUsView: UIView, LuaContactUsViewProtocol { private func addConstraintToUIElements() { NSLayoutConstraint.activate([ - + scrollView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor), scrollView.leadingAnchor.constraint(equalTo: leadingAnchor), scrollView.trailingAnchor.constraint(equalTo: trailingAnchor), scrollView.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor), - + // ContentView contentView.topAnchor.constraint(equalTo: scrollView.topAnchor), contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor), contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor), contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor), contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor), - + // Title Label titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 20), titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), - + // Phone Button phoneButton.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 30), phoneButton.widthAnchor.constraint(equalToConstant: 80), phoneButton.heightAnchor.constraint(equalToConstant: 80), phoneButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), - + // Email Button emailButton.centerYAnchor.constraint(equalTo: phoneButton.centerYAnchor), emailButton.widthAnchor.constraint(equalToConstant: 80), emailButton.heightAnchor.constraint(equalToConstant: 80), emailButton.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), - + // Chat Button chatButton.centerYAnchor.constraint(equalTo: phoneButton.centerYAnchor), chatButton.widthAnchor.constraint(equalToConstant: 80), chatButton.heightAnchor.constraint(equalToConstant: 80), chatButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), - + // Message Label messageLabel.topAnchor.constraint(equalTo: phoneButton.bottomAnchor, constant: 30), messageLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), messageLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), - + // TextView textView.topAnchor.constraint(equalTo: messageLabel.bottomAnchor, constant: 20), textView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), textView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), textView.heightAnchor.constraint(equalToConstant: 350), - + sendMessageButton.topAnchor.constraint(equalTo: textView.bottomAnchor, constant: 20), sendMessageButton.heightAnchor.constraint(equalToConstant: 40), sendMessageButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), sendMessageButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), - + closeButton.topAnchor.constraint(equalTo: sendMessageButton.bottomAnchor, constant: 20), closeButton.heightAnchor.constraint(equalToConstant: 40), closeButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), @@ -190,25 +191,4 @@ final class LuaContactUsView: UIView, LuaContactUsViewProtocol { closeButton.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -20) ]) } - // MARK: - Target configuration - func configurePhoneButton(target: Any, selector: Selector){ - phoneButton.addTarget(target, action: selector, for: .touchUpInside) - } - func configureEmailButton(target: Any, selector: Selector){ - emailButton.addTarget(target, action: selector, for: .touchUpInside) - } - func configureChatButton(target: Any, selector: Selector){ - chatButton.addTarget(target, action: selector, for: .touchUpInside) - } - func configureSendMessageButton(target: Any, selector: Selector){ - sendMessageButton.addTarget(target, action: selector, for: .touchUpInside) - } - func configureCloseButton(target: Any, selector: Selector){ - closeButton.addTarget(target, action: selector, for: .touchUpInside) - } - } - -//#Preview { -// LuaContactUsView() -//} diff --git a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift index 8ea0bd6..09ac71c 100644 --- a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift +++ b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift @@ -8,106 +8,82 @@ import UIKit final class LuaContactUsViewController: UIViewController, LuaViewControllerProtocol, LuaAlertHandlerProtocol { - var model: ContactUsModel? - typealias ViewCode = LuaContactUsView internal let viewCode = LuaContactUsView() - private let viewModel = LuaContactUsViewModel() + private let viewModel: LuaContactUsViewModel + + init(viewModel: LuaContactUsViewModel) { + self.viewModel = viewModel + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + override func loadView() { view = viewCode } override func viewDidLoad() { super.viewDidLoad() - FetchContactUSData() + FetchContactUsData() configureButtons() hideKeyboardWhenTappedAround() } - private func FetchContactUSData() { - showLoading() - - let url = Endpoints.contactUs - - AF.shared.request(url, method: .get, parameters: nil, headers: nil) { result in - self.stopLoading() - switch result { - case .success(let data): - let decoder = JSONDecoder() - if let returned = try? decoder.decode(ContactUsModel.self, from: data) { - self.model = returned - } else { - Globals.alertMessage(title: "Ops..", message: "Ocorreu algum erro", targetVC: self) { - self.dismiss(animated: true) - } - } - case .failure(let error): - print("error api: \(error.localizedDescription)") - Globals.alertMessage(title: "Ops..", message: "Ocorreu algum erro", targetVC: self) { - self.dismiss(animated: true) - } + private func FetchContactUsData() { + Task { + do { + await luaShowLoading() + try await viewModel.fetchContactUsData() + await luaStopLoading() + } catch { + await luaStopLoading() + showAlertError(error: error, from: self, alertTitle: "Ocorreu algum erro") + self.dismiss(animated: true) } } } private func startSendMessageProcess() { view.endEditing(true) - let hasMessage = viewCode.textView.text.isNotEmpty && viewCode.textView.text != "Escreva sua mensagem aqui" + let hasMessage = viewCode.textInputted.isNotEmpty && viewCode.textInputted != "Escreva sua mensagem aqui" if hasMessage { - - let message = viewCode.textView.text! - let email = model?.mail ?? "" - - showLoading() - + let message = viewCode.textInputted + guard let mail = viewModel.contactUsModel?.mail else { + return + } + sendMessage(message: message, mail: mail) + return + } + showAlert(alertTitle: "Mensagem vazia", message: "Por favor, escreva uma mensagem antes de enviar.", viewController: self) + } + + private func sendMessage(message: String, mail: String) { + Task { do { - try viewModel.sendMessage(message: message, mail: email) - // need a alert to success - self.dismiss(animated: true) + await luaShowLoading() + try await viewModel.sendMessage(message: message, mail: mail) + await luaStopLoading() + showAlert(alertTitle: "Sucesso..", message: "Sua mensagem foi enviada com sucesso.", viewController: self) } catch { - showAlertError(error: error, from: self, alertTitle: "Ocorreu algum erro") + stopLoading() + showAlertError(error: error, from: self, alertTitle: "Erro ao enviar mensagem") } - - stopLoading() - return } - // need a alert to show that user does not wrote a message - } - - - // @objc - // func sendMessage() { - // view.endEditing(true) - // let email = model?.mail ?? "" - // if let message = viewCode.textView.text, viewCode.textView.text.count > 0 { - // let parameters: [String: String] = [ - // "email": email, - // "mensagem": message - // ] - // showLoading() - // let url = Endpoints.sendMessage - // AF.shared.request(url, method: .post, parameters: parameters, headers: nil) { result in - // self.stopLoading() - // switch result { - // case .success: - // Globals.alertMessage(title: "Sucesso..", message: "Sua mensagem foi enviada", targetVC: self) { - // self.dismiss(animated: true) - // } - // case .failure: - // Globals.alertMessage(title: "Ops..", message: "Ocorreu algum erro", targetVC: self) - // } - // } - // } - // } + } } + // MARK: - Comportamentos de layout private extension LuaContactUsViewController { + func configureButtons() { - viewCode.configureChatButton(target: self, selector: #selector(chatButtonTapped)) - viewCode.configureCloseButton(target: self, selector: #selector(close)) - viewCode.configureEmailButton(target: self, selector: #selector(emailButtonTapped)) - viewCode.configurePhoneButton(target: self, selector: #selector(phoneButtonTapped)) - viewCode.configureSendMessageButton(target: self, selector: #selector(sendMessageButtonTapped)) + viewCode.phoneButton.addTarget(self, action: #selector(phoneButtonTapped), for: .touchUpInside) + viewCode.emailButton.addTarget(self, action: #selector(emailButtonTapped), for: .touchUpInside) + viewCode.chatButton.addTarget(self, action: #selector(chatButtonTapped), for: .touchUpInside) + viewCode.sendMessageButton.addTarget(self, action: #selector(sendMessageButtonTapped), for: .touchUpInside) + viewCode.closeButton.addTarget(self, action: #selector(closeButtonTapped), for: .touchUpInside) } @objc func sendMessageButtonTapped() { @@ -144,12 +120,12 @@ private extension LuaContactUsViewController { } } - @objc func close() { + @objc func closeButtonTapped() { dismiss(animated: true) } func openPhone() throws { - guard let phoneNumer = model?.phone else { + guard let phoneNumer = viewModel.contactUsModel?.phone else { throw LuaPersonalInfoError.invalidPhoneNumber } do { @@ -161,7 +137,7 @@ private extension LuaContactUsViewController { } func openWhatsapp() throws { - guard let phoneNumer = model?.phone else { + guard let phoneNumer = viewModel.contactUsModel?.phone else { throw LuaPersonalInfoError.invalidPhoneNumber } do { @@ -173,7 +149,7 @@ private extension LuaContactUsViewController { } func openMail() throws { - guard let mail = model?.mail else { + guard let mail = viewModel.contactUsModel?.mail else { throw LuaPersonalInfoError.invalidMail } do { diff --git a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewModel.swift b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewModel.swift index 3acdbd4..b2ef31f 100644 --- a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewModel.swift +++ b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewModel.swift @@ -8,15 +8,28 @@ final class LuaContactUsViewModel { - private let networkManager = LuaNetworkManager() + private let networkManager: LuaNetworkManager + public var contactUsModel: ContactUsModel? + init(networkManager: LuaNetworkManager) { + self.networkManager = networkManager + } + + func sendMessage(message: String, mail: String) async throws { + do { + let params = makeSendParams(message: message, mail: mail) + let response: [String: String] = try await networkManager.request(.sendContactUsMessage(params)) + print(response) + } catch { + throw error + } + } - func sendMessage(message: String, mail: String) throws { - + func fetchContactUsData() async throws { Task { do { - let params = makeSendParams(message: message, mail: mail) - let response: [String: String] = try await networkManager.request(.sendContactUsMessage(params)) + contactUsModel = try await networkManager.request(.getContactUsData) + print(contactUsModel) } catch { throw error } diff --git a/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Extensions/LuaUIViewControllerExtension.swift b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Extensions/LuaUIViewControllerExtension.swift new file mode 100644 index 0000000..bd00cf9 --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Extensions/LuaUIViewControllerExtension.swift @@ -0,0 +1,38 @@ +// +// LuaUIViewControllerExtension.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 17/02/25. +// + +import UIKit + +extension UIViewController { + + func luaShowLoading() async { + let loadingController = LoadingController() // this is too slow, find other solution later + loadingController.modalPresentationStyle = .fullScreen + loadingController.modalTransitionStyle = .crossDissolve + + await withCheckedContinuation { continuation in + present(loadingController, animated: true) { + print("Loading presentation completed") + continuation.resume() + } + } + } + + func luaStopLoading() async { + guard let presented = presentedViewController as? LoadingController else { + print("No loading controller presented") + return + } + + await withCheckedContinuation { continuation in + presented.dismiss(animated: true) { + print("Loading dismissal completed") + continuation.resume() + } + } + } +} diff --git a/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/LuaAlertHandlerProtocol.swift b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/LuaAlertHandlerProtocol.swift index 8572f6f..95fb0e6 100644 --- a/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/LuaAlertHandlerProtocol.swift +++ b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/LuaAlertHandlerProtocol.swift @@ -8,6 +8,7 @@ import UIKit public protocol LuaAlertHandlerProtocol { + func showAlert(alertTitle: String?, message: String, style: UIAlertController.Style?, viewController: UIViewController) func showAlertError(error: Error, from viewController: UIViewController, alertTitle: String?, style: UIAlertController.Style?) } @@ -18,4 +19,11 @@ extension LuaAlertHandlerProtocol { alertController.addAction(action) viewController.present(alertController, animated: true) } + + public func showAlert(alertTitle: String?, message: String, style: UIAlertController.Style? = .alert, viewController: UIViewController) { + let alertController = UIAlertController(title: alertTitle, message: message, preferredStyle: style!) + let action = UIAlertAction(title: "OK", style: .default) + alertController.addAction(action) + viewController.present(alertController, animated: true) + } } diff --git a/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewControllerFactory.swift b/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewControllerFactory.swift index 2c481ed..ffef1fd 100644 --- a/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewControllerFactory.swift +++ b/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewControllerFactory.swift @@ -9,7 +9,8 @@ import UIKit public struct LuaContactUsViewControllerFactory { static func makeLuaContactUsViewController() -> UIViewController { - let luaContactUsViewController = LuaContactUsViewController() + let viewModel = LuaContactUsViewModelFactory.makeLuaContactUsViewModel() + let luaContactUsViewController = LuaContactUsViewController(viewModel: viewModel) luaContactUsViewController.modalPresentationStyle = .fullScreen luaContactUsViewController.modalTransitionStyle = .coverVertical return luaContactUsViewController diff --git a/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewModelFactory.swift b/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewModelFactory.swift new file mode 100644 index 0000000..b327419 --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewModelFactory.swift @@ -0,0 +1,13 @@ +// +// LuaContactUsViewModelFactory.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 17/02/25. +// + +struct LuaContactUsViewModelFactory { + static func makeLuaContactUsViewModel() -> LuaContactUsViewModel { + let viewModel = LuaContactUsViewModel(networkManager: LuaNetworkManager()) + return viewModel + } +} diff --git a/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFactory.swift b/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFactory.swift index 4e4e83e..b66e53b 100644 --- a/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFactory.swift +++ b/CleanCodeApp/Modules/Features/Lua/Main/LuaResetPasswordViewModelFactory.swift @@ -7,6 +7,7 @@ public struct LuaResetPasswordViewModelFactory { static func makeLuaResetPasswordViewModel() -> LuaResetPasswordViewModelProtocol { - return LuaResetPasswordViewModel() + let viewModel = LuaResetPasswordViewModel(networkManager: LuaNetworkManager()) + return viewModel } } diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift index 110ae7f..173c212 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift @@ -1,16 +1,6 @@ import UIKit -protocol LuaResetPasswordViewProtocol { - func configurePasswordRecoveryButton(target: Any, selector: Selector) - func configureLoginButton(target: Any, selector: Selector) - func configureHelpButton(target: Any, selector: Selector) - func configureCreateAccountButton(target: Any, selector: Selector) - func configureCloseButton(target: Any, selector: Selector) - func configureEmailTextFieldDidBeginEditing(target: Any, selector: Selector) - func configureEmailTextFieldOnEditing(target: Any, selector: Selector) -} - -class LuaResetPasswordView: UIView, LuaResetPasswordViewProtocol { +class LuaResetPasswordView: UIView { // MARK: - UI Components private lazy var scrollView: UIScrollView = { @@ -97,7 +87,7 @@ class LuaResetPasswordView: UIView, LuaResetPasswordViewProtocol { return button }() - private lazy var loginButton: UIButton = { + public lazy var loginButton: UIButton = { let button = UIButton(type: .system) button.setTitle("LOGIN", for: .normal) button.titleLabel?.font = .systemFont(ofSize: 15) @@ -111,7 +101,7 @@ class LuaResetPasswordView: UIView, LuaResetPasswordViewProtocol { return button }() - private lazy var helpButton: UIButton = { + public lazy var helpButton: UIButton = { let button = UIButton(type: .system) button.setTitle("PRECISO DE AJUDA", for: .normal) button.titleLabel?.font = .systemFont(ofSize: 15) @@ -125,7 +115,7 @@ class LuaResetPasswordView: UIView, LuaResetPasswordViewProtocol { return button }() - private lazy var createAccountButton: UIButton = { + public lazy var createAccountButton: UIButton = { let button = UIButton(type: .system) button.setTitle("CRIAR UMA CONTA", for: .normal) button.titleLabel?.font = .systemFont(ofSize: 15) @@ -139,7 +129,7 @@ class LuaResetPasswordView: UIView, LuaResetPasswordViewProtocol { return button }() - private lazy var closeButton: UIButton = { + public lazy var closeButton: UIButton = { let button = UIButton(type: .system) button.setImage(UIImage(systemName: "xmark.app.fill"), for: .normal) button.translatesAutoresizingMaskIntoConstraints = false @@ -255,34 +245,15 @@ class LuaResetPasswordView: UIView, LuaResetPasswordViewProtocol { } // MARK: - Target configuration public func configurePasswordRecoveryButton(target: Any, selector: Selector) { - passwordRecoveryButton.addTarget(target, action: selector, for: .touchUpInside) - } - - public func configureLoginButton(target: Any, selector: Selector) { + loginButton.addTarget(target, action: selector, for: .touchUpInside) - } - - public func configureHelpButton(target: Any, selector: Selector) { helpButton.addTarget(target, action: selector, for: .touchUpInside) - } - - public func configureCreateAccountButton(target: Any, selector: Selector) { createAccountButton.addTarget(target, action: selector, for: .touchUpInside) - } - - public func configureCloseButton(target: Any, selector: Selector) { closeButton.addTarget(target, action: selector, for: .touchUpInside) - } - - public func configureEmailTextFieldDidBeginEditing(target: Any, selector: Selector) { emailTextField.addTarget(target, action: selector, for: .editingDidBegin) - } - - public func configureEmailTextFieldOnEditing(target: Any, selector: Selector) { emailTextField.addTarget(target, action: selector, for: .editingChanged) - } - - public func configureEmailTextFieldDidEndEditing(target: Any, selector: Selector) { emailTextField.addTarget(target, action: selector, for: .editingDidEnd) } + + } diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift index 60f78c9..f19c8ba 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift @@ -4,8 +4,8 @@ final class LuaResetPasswordViewController: UIViewController, LuaAlertHandlerPro typealias ViewCode = LuaResetPasswordView internal let viewCode = LuaResetPasswordView() - private var viewModel: LuaResetPasswordViewModelProtocol - private var coordinator: LuaCoordinatorProtocol + private let viewModel: LuaResetPasswordViewModelProtocol + private let coordinator: LuaCoordinatorProtocol private var hasRequestedRecovery = false init(viewModel: LuaResetPasswordViewModelProtocol, coordinator: LuaBasicCoordinator) { @@ -85,17 +85,17 @@ final class LuaResetPasswordViewController: UIViewController, LuaAlertHandlerPro private extension LuaResetPasswordViewController { func configureButtons() { - viewCode.configureHelpButton(target: self, selector: #selector(onHelpButtonTapped) ) - viewCode.configureCloseButton(target: self, selector: #selector(closeButtonTapped)) - viewCode.configureLoginButton(target: self, selector: #selector(onLoginButtonTapped)) - viewCode.configureCreateAccountButton(target: self, selector: #selector(onCreateAccountButtonTapped)) - viewCode.configurePasswordRecoveryButton(target: self, selector: #selector(onPasswordRecoveryButtonTapped)) + viewCode.loginButton.addTarget(self, action: #selector(onLoginButtonTapped), for: .touchUpInside) + viewCode.helpButton.addTarget(self, action: #selector(onHelpButtonTapped), for: .touchUpInside) + viewCode.createAccountButton.addTarget(self, action: #selector(onCreateAccountButtonTapped), for: .touchUpInside) + viewCode.closeButton.addTarget(self, action: #selector(closeButtonTapped), for: .touchUpInside) + viewCode.passwordRecoveryButton.addTarget(target, action: #selector(onPasswordRecoveryButtonTapped), for: .touchUpInside) } func configureTextField() { - viewCode.configureEmailTextFieldOnEditing(target: self, selector: #selector(onEmailTextFieldEdit)) - viewCode.configureEmailTextFieldDidBeginEditing(target: self, selector: #selector(emailTextFieldDidBeginEditing)) - viewCode.configureEmailTextFieldDidEndEditing(target: self, selector: #selector(emailTextFieldDidEndEditing)) + viewCode.emailTextField.addTarget(self, action: #selector(emailTextFieldDidBeginEditing), for: .editingDidBegin) + viewCode.emailTextField.addTarget(self, action: #selector(onEmailTextFieldEdit), for: .editingChanged) + viewCode.emailTextField.addTarget(self, action: #selector(emailTextFieldDidEndEditing), for: .editingDidEnd) } @IBAction func closeButtonTapped(_ sender: Any) { diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift index 3d7290c..670f984 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift @@ -13,12 +13,18 @@ protocol LuaResetPasswordViewModelProtocol { } final class LuaResetPasswordViewModel: LuaResetPasswordViewModelProtocol { + + private let networkManager: LuaNetworkManager + + init(networkManager: LuaNetworkManager) { + self.networkManager = networkManager + } func startPasswordResetRequest(targetViewController: UIViewController, emailInputted: String) async throws { do { try validateConnectivity(emailInputted: emailInputted) let passwordParameters = makePasswordResetParams(inputedEmail: emailInputted) - sendPasswordResetRequest(targetViewController: targetViewController, parameters: passwordParameters) + try sendPasswordResetRequest(targetViewController: targetViewController, parameters: passwordParameters) } catch _ as LuaNetworkError { throw LuaNetworkError.noInternetConnection } catch { @@ -26,12 +32,13 @@ final class LuaResetPasswordViewModel: LuaResetPasswordViewModelProtocol { } } - private func sendPasswordResetRequest(targetViewController: UIViewController, parameters: [String : String]) { - BadNetworkLayer.shared.resetPassword(targetViewController, parameters: parameters) { succes in // need to refactor - if succes { - + private func sendPasswordResetRequest(targetViewController: UIViewController, parameters: [String : String]) throws { + Task { + do { + let _: Data = try await networkManager.request(.authTarget(.resetPassword)) + } catch { + throw error } - // show alert } } diff --git a/CleanCodeApp/Modules/Utils/Extensions/UIViewController+extensions.swift b/CleanCodeApp/Modules/Utils/Extensions/UIViewController+extensions.swift index 98060f0..0ff9c39 100644 --- a/CleanCodeApp/Modules/Utils/Extensions/UIViewController+extensions.swift +++ b/CleanCodeApp/Modules/Utils/Extensions/UIViewController+extensions.swift @@ -5,12 +5,12 @@ extension UIViewController { let loadingController = LoadingController() loadingController.modalPresentationStyle = .fullScreen loadingController.modalTransitionStyle = .crossDissolve - self.present(loadingController, animated: true) + self.present(loadingController, animated: false) } func stopLoading() { if let presentedController = presentedViewController as? LoadingController { - presentedController.dismiss(animated: true) + presentedController.dismiss(animated: false) } } From 5a9623277c76f2360cfabb759c46b74521589199 Mon Sep 17 00:00:00 2001 From: Eirado <111468283+Eirado@users.noreply.github.com> Date: Mon, 17 Feb 2025 17:38:36 -0300 Subject: [PATCH 16/22] . --- .../Lua/ResetPassword/LuaResetPasswordView.swift | 13 ------------- .../ResetPassword/LuaResetPasswordViewModel.swift | 2 +- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift index 173c212..06c7a5a 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift @@ -243,17 +243,4 @@ class LuaResetPasswordView: UIView { closeButton.heightAnchor.constraint(equalToConstant: 45) ]) } - // MARK: - Target configuration - public func configurePasswordRecoveryButton(target: Any, selector: Selector) { - - loginButton.addTarget(target, action: selector, for: .touchUpInside) - helpButton.addTarget(target, action: selector, for: .touchUpInside) - createAccountButton.addTarget(target, action: selector, for: .touchUpInside) - closeButton.addTarget(target, action: selector, for: .touchUpInside) - emailTextField.addTarget(target, action: selector, for: .editingDidBegin) - emailTextField.addTarget(target, action: selector, for: .editingChanged) - emailTextField.addTarget(target, action: selector, for: .editingDidEnd) - } - - } diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift index 670f984..f458c45 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift @@ -28,7 +28,7 @@ final class LuaResetPasswordViewModel: LuaResetPasswordViewModelProtocol { } catch _ as LuaNetworkError { throw LuaNetworkError.noInternetConnection } catch { - throw LuaNetworkError.unknown + throw error } } From 28784fe8e9a97cbc2941a4fddb8cbfa370e4c904 Mon Sep 17 00:00:00 2001 From: Eirado <111468283+Eirado@users.noreply.github.com> Date: Mon, 17 Feb 2025 20:48:23 -0300 Subject: [PATCH 17/22] viewStacks tests --- .../ResetPassword/LuaResetPasswordView.swift | 65 ++++++++++++------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift index 06c7a5a..03f54fa 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordView.swift @@ -161,20 +161,44 @@ class LuaResetPasswordView: UIView { addSubview(scrollView) scrollView.addSubview(contentView) addSubviewsToContentView() - addSubviewsTosuccessView() addConstraintsToUIComponents() } private func addSubviewsToContentView() { - [smokeImageView, passwordRecoverySuccessView, emailLabel, emailTextField, passwordRecoveryButton, loginButton, helpButton, createAccountButton, closeButton].forEach { contentView.addSubview($0) } + [smokeImageView, passwordRecoverySuccessView, emailLabel, emailTextField, passwordRecoveryButton, closeButton].forEach { contentView.addSubview($0) } } - private func addSubviewsTosuccessView() { - [successLabel, emailSentLabel].forEach { passwordRecoverySuccessView.addSubview($0) } + private func createSuccessContentStack() -> UIStackView { + let successContentStack = UIStackView(arrangedSubviews: [successLabel, emailSentLabel]) + successContentStack.axis = .vertical + successContentStack.spacing = 0 + successContentStack.isLayoutMarginsRelativeArrangement = true + successContentStack.layoutMargins = UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0) + return successContentStack + } + + private func createButtonsStack() -> UIStackView { + let buttonsStack = UIStackView(arrangedSubviews: [loginButton, helpButton, createAccountButton]) + buttonsStack.axis = .vertical + buttonsStack.spacing = 20 + + return buttonsStack } func addConstraintsToUIComponents() { + + let successContentStack = createSuccessContentStack() + + let buttonsStack = createButtonsStack() + + [successContentStack, buttonsStack].forEach { + $0.translatesAutoresizingMaskIntoConstraints = false + } + passwordRecoverySuccessView.addSubview(successContentStack) + contentView.addSubview(buttonsStack) + NSLayoutConstraint.activate([ + scrollView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor), scrollView.leadingAnchor.constraint(equalTo: leadingAnchor), scrollView.trailingAnchor.constraint(equalTo: trailingAnchor), @@ -196,16 +220,16 @@ class LuaResetPasswordView: UIView { passwordRecoverySuccessView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), passwordRecoverySuccessView.heightAnchor.constraint(equalToConstant: 138), - successLabel.topAnchor.constraint(equalTo: passwordRecoverySuccessView.topAnchor), - successLabel.leadingAnchor.constraint(equalTo: passwordRecoverySuccessView.leadingAnchor), - successLabel.trailingAnchor.constraint(equalTo: passwordRecoverySuccessView.trailingAnchor), - successLabel.heightAnchor.constraint(equalToConstant: 98), + // Success Content Stack (replaces individual label constraints) + successContentStack.topAnchor.constraint(equalTo: passwordRecoverySuccessView.topAnchor), + successContentStack.leadingAnchor.constraint(equalTo: passwordRecoverySuccessView.leadingAnchor), + successContentStack.trailingAnchor.constraint(equalTo: passwordRecoverySuccessView.trailingAnchor), + successContentStack.bottomAnchor.constraint(equalTo: passwordRecoverySuccessView.bottomAnchor), - emailSentLabel.topAnchor.constraint(equalTo: successLabel.bottomAnchor), - emailSentLabel.leadingAnchor.constraint(equalTo: passwordRecoverySuccessView.leadingAnchor), - emailSentLabel.trailingAnchor.constraint(equalTo: passwordRecoverySuccessView.trailingAnchor), - emailSentLabel.bottomAnchor.constraint(equalTo: passwordRecoverySuccessView.bottomAnchor, constant: -10), + // Fixed heights + successLabel.heightAnchor.constraint(equalToConstant: 98), + // Rest of the layout (unchanged) emailLabel.topAnchor.constraint(equalTo: smokeImageView.bottomAnchor, constant: 70), emailLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), emailLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), @@ -221,21 +245,14 @@ class LuaResetPasswordView: UIView { passwordRecoveryButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), passwordRecoveryButton.heightAnchor.constraint(equalToConstant: 48), - loginButton.topAnchor.constraint(equalTo: passwordRecoveryButton.bottomAnchor, constant: 84), - loginButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), - loginButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), - loginButton.heightAnchor.constraint(equalToConstant: 48), + buttonsStack.topAnchor.constraint(equalTo: passwordRecoveryButton.bottomAnchor, constant: 84), + buttonsStack.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), + buttonsStack.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), + buttonsStack.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -40), - helpButton.topAnchor.constraint(equalTo: loginButton.bottomAnchor, constant: 20), - helpButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), - helpButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), + loginButton.heightAnchor.constraint(equalToConstant: 48), helpButton.heightAnchor.constraint(equalToConstant: 48), - - createAccountButton.topAnchor.constraint(equalTo: helpButton.bottomAnchor, constant: 20), - createAccountButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), - createAccountButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20), createAccountButton.heightAnchor.constraint(equalToConstant: 48), - createAccountButton.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -40), closeButton.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10), closeButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -15), From 8ab83498a3dd51a54aa59609daddf5b47d10411f Mon Sep 17 00:00:00 2001 From: Eirado <111468283+Eirado@users.noreply.github.com> Date: Mon, 17 Feb 2025 20:59:14 -0300 Subject: [PATCH 18/22] POP LuaContactUsViewModelProtocol --- .../Lua/ContactsUs/LuaContactUsViewController.swift | 4 ++-- .../Lua/ContactsUs/LuaContactUsViewModel.swift | 11 ++++++++--- .../Lua/Main/LuaContactUsViewModelFactory.swift | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift index 09ac71c..4c3fdf6 100644 --- a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift +++ b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift @@ -10,9 +10,9 @@ import UIKit final class LuaContactUsViewController: UIViewController, LuaViewControllerProtocol, LuaAlertHandlerProtocol { typealias ViewCode = LuaContactUsView internal let viewCode = LuaContactUsView() - private let viewModel: LuaContactUsViewModel + private let viewModel: LuaContactUsViewModelProtocol - init(viewModel: LuaContactUsViewModel) { + init(viewModel: LuaContactUsViewModelProtocol) { self.viewModel = viewModel super.init(nibName: nil, bundle: nil) } diff --git a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewModel.swift b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewModel.swift index b2ef31f..3721bb6 100644 --- a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewModel.swift +++ b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewModel.swift @@ -5,8 +5,13 @@ // Created by Gabriel Amaral on 15/02/25. // +protocol LuaContactUsViewModelProtocol { + var contactUsModel: ContactUsModel? { get } + func sendMessage(message: String, mail: String) async throws + func fetchContactUsData() async throws +} -final class LuaContactUsViewModel { +final class LuaContactUsViewModel: LuaContactUsViewModelProtocol { private let networkManager: LuaNetworkManager public var contactUsModel: ContactUsModel? @@ -15,7 +20,7 @@ final class LuaContactUsViewModel { self.networkManager = networkManager } - func sendMessage(message: String, mail: String) async throws { + public func sendMessage(message: String, mail: String) async throws { do { let params = makeSendParams(message: message, mail: mail) let response: [String: String] = try await networkManager.request(.sendContactUsMessage(params)) @@ -25,7 +30,7 @@ final class LuaContactUsViewModel { } } - func fetchContactUsData() async throws { + public func fetchContactUsData() async throws { Task { do { contactUsModel = try await networkManager.request(.getContactUsData) diff --git a/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewModelFactory.swift b/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewModelFactory.swift index b327419..d8092b1 100644 --- a/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewModelFactory.swift +++ b/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewModelFactory.swift @@ -6,7 +6,7 @@ // struct LuaContactUsViewModelFactory { - static func makeLuaContactUsViewModel() -> LuaContactUsViewModel { + static func makeLuaContactUsViewModel() -> LuaContactUsViewModelProtocol { let viewModel = LuaContactUsViewModel(networkManager: LuaNetworkManager()) return viewModel } From b487d468711808815210fbadc8d19f4464c389df Mon Sep 17 00:00:00 2001 From: Eirado <111468283+Eirado@users.noreply.github.com> Date: Mon, 17 Feb 2025 21:19:25 -0300 Subject: [PATCH 19/22] Update SceneDelegate.swift --- CleanCodeApp/AppDelegate/SceneDelegate.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CleanCodeApp/AppDelegate/SceneDelegate.swift b/CleanCodeApp/AppDelegate/SceneDelegate.swift index 88b5245..2fa1cfe 100644 --- a/CleanCodeApp/AppDelegate/SceneDelegate.swift +++ b/CleanCodeApp/AppDelegate/SceneDelegate.swift @@ -50,7 +50,7 @@ func getRootViewController(forUser user: Users) -> UIViewController { } let storyboard = UIStoryboard(name: "\(userIdentifier)User", bundle: nil) let vc = storyboard.instantiateViewController(withIdentifier: "\(userIdentifier)LoginViewController") - return LuaResetPasswordViewControllerFactory.makeLuaResetPasswordViewController() + return vc } enum Users { From 46677a0e3457b3e56c052275f75d40ca0081447f Mon Sep 17 00:00:00 2001 From: Eirado <111468283+Eirado@users.noreply.github.com> Date: Mon, 17 Feb 2025 21:31:05 -0300 Subject: [PATCH 20/22] fix fetch function --- .../Features/Lua/ContactsUs/LuaContactUsViewController.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift index 4c3fdf6..f3e36bc 100644 --- a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift +++ b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift @@ -27,12 +27,12 @@ final class LuaContactUsViewController: UIViewController, LuaViewControllerProto override func viewDidLoad() { super.viewDidLoad() - FetchContactUsData() + fetchContactUsData() configureButtons() hideKeyboardWhenTappedAround() } - private func FetchContactUsData() { + private func fetchContactUsData() { Task { do { await luaShowLoading() From e4e8ddbd4d6e1feba4344d68ce3d62e65108c273 Mon Sep 17 00:00:00 2001 From: Eirado <111468283+Eirado@users.noreply.github.com> Date: Thu, 20 Feb 2025 21:51:21 -0300 Subject: [PATCH 21/22] pr fixes --- .DS_Store | Bin 6148 -> 6148 bytes .../Lua/ContactsUs/LuaContactUsStrings.swift | 18 ++++++++++++++ .../LuaContactUsViewController.swift | 22 +++++++++--------- .../ContactsUs/LuaContactUsViewModel.swift | 10 ++++---- .../Lua/LuaErrors/LuaNetworkError.swift | 1 + .../Protocols/LuaAlertHandlerProtocol.swift | 2 +- .../Lua/LuaNetwork/LuaAPITarget.swift | 2 +- .../LuaContactUsViewControllerFactory.swift | 2 +- .../Main/LuaContactUsViewModelFactory.swift | 13 ----------- .../LuaResetPasswordViewController.swift | 4 ++-- .../LuaResetPasswordViewModel.swift | 16 +++---------- 11 files changed, 44 insertions(+), 46 deletions(-) create mode 100644 CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsStrings.swift delete mode 100644 CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewModelFactory.swift diff --git a/.DS_Store b/.DS_Store index 7ff96106cc45fd2a3fda6da0edde94fa715081be..060e125f9a1e4ad253082a70ac0e6593662f390c 100644 GIT binary patch delta 58 zcmZoMXffEJ!OYBVvSxBVv(e;OW-hh|t5kL~ZkfCh$eqv3gW%dTu@`Lq$SlgTnVsV= FKLA2;6Y&55 delta 57 zcmZoMXffEJ!OYBh)Mau$v(e;OW-hisq1{Za>nCpna_2MiAh`C7Y?}o+q*yj{bNu87 E0RCSQJOBUy diff --git a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsStrings.swift b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsStrings.swift new file mode 100644 index 0000000..5b19c1d --- /dev/null +++ b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsStrings.swift @@ -0,0 +1,18 @@ +// +// LuaContactUsStrings.swift +// CleanCodeApp +// +// Created by Gabriel Amaral on 20/02/25. +// + + +enum LuaContactUsStrings { + static var defaultErrorTitle = "Ocorreu algum erro" + static var defaultErrorDescription = "Algo de errado aconteceu. Tente novamente mais tarde." + static var textFieldDefaultMessage = "Escreva sua mensagem aqui" + static var emptyMessageTitle = "Mensagem vazia" + static var emptyMessageDescription = "Por favor, escreva uma mensagem antes de enviar." + static var sendMessageErrorDescription = "Erro ao enviar mensagem" + static var defaultSuccessTitle = "Sucesso.." + static var defaultSuccessDescription = "Sua mensagem foi enviada com sucesso." +} \ No newline at end of file diff --git a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift index f3e36bc..c00c479 100644 --- a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift +++ b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift @@ -7,7 +7,7 @@ import UIKit -final class LuaContactUsViewController: UIViewController, LuaViewControllerProtocol, LuaAlertHandlerProtocol { +final class LuaContactUsViewController: UIViewController, LuaViewControllerProtocol { typealias ViewCode = LuaContactUsView internal let viewCode = LuaContactUsView() private let viewModel: LuaContactUsViewModelProtocol @@ -40,7 +40,7 @@ final class LuaContactUsViewController: UIViewController, LuaViewControllerProto await luaStopLoading() } catch { await luaStopLoading() - showAlertError(error: error, from: self, alertTitle: "Ocorreu algum erro") + showAlertError(error: error, from: self, alertTitle: LuaContactUsStrings.defaultErrorTitle) self.dismiss(animated: true) } } @@ -48,7 +48,7 @@ final class LuaContactUsViewController: UIViewController, LuaViewControllerProto private func startSendMessageProcess() { view.endEditing(true) - let hasMessage = viewCode.textInputted.isNotEmpty && viewCode.textInputted != "Escreva sua mensagem aqui" + let hasMessage = viewCode.textInputted.isNotEmpty && viewCode.textInputted != LuaContactUsStrings.textFieldDefaultMessage if hasMessage { let message = viewCode.textInputted guard let mail = viewModel.contactUsModel?.mail else { @@ -57,7 +57,7 @@ final class LuaContactUsViewController: UIViewController, LuaViewControllerProto sendMessage(message: message, mail: mail) return } - showAlert(alertTitle: "Mensagem vazia", message: "Por favor, escreva uma mensagem antes de enviar.", viewController: self) + showAlert(alertTitle: LuaContactUsStrings.emptyMessageTitle , message: LuaContactUsStrings.emptyMessageDescription, viewController: self) } private func sendMessage(message: String, mail: String) { @@ -65,12 +65,12 @@ final class LuaContactUsViewController: UIViewController, LuaViewControllerProto do { await luaShowLoading() try await viewModel.sendMessage(message: message, mail: mail) - await luaStopLoading() - showAlert(alertTitle: "Sucesso..", message: "Sua mensagem foi enviada com sucesso.", viewController: self) + showAlert(alertTitle: LuaContactUsStrings.defaultSuccessTitle, message: LuaContactUsStrings.defaultSuccessDescription, viewController: self) } catch { - stopLoading() - showAlertError(error: error, from: self, alertTitle: "Erro ao enviar mensagem") + await luaStopLoading() + showAlertError(error: error, from: self, alertTitle: LuaContactUsStrings.sendMessageErrorDescription) } + await luaStopLoading() } } } @@ -96,7 +96,7 @@ private extension LuaContactUsViewController { } catch let error as LuaPersonalInfoError { showAlertError(error: error, from: self, alertTitle: error.errorTitle) } catch { - showAlertError(error: error, from: self, alertTitle: "Algo de errado aconteceu. Tente novamente mais tarde.") + showAlertError(error: error, from: self, alertTitle: LuaContactUsStrings.defaultErrorDescription) } } @@ -106,7 +106,7 @@ private extension LuaContactUsViewController { } catch let error as LuaPersonalInfoError { showAlertError(error: error, from: self, alertTitle: error.errorTitle) } catch { - showAlertError(error: error, from: self, alertTitle: "Algo de errado aconteceu. Tente novamente mais tarde.") + showAlertError(error: error, from: self, alertTitle: LuaContactUsStrings.defaultErrorDescription) } } @@ -116,7 +116,7 @@ private extension LuaContactUsViewController { } catch let error as LuaPersonalInfoError { showAlertError(error: error, from: self, alertTitle: error.errorTitle) } catch { - showAlertError(error: error, from: self, alertTitle: "Algo de errado aconteceu. Tente novamente mais tarde.") + showAlertError(error: error, from: self, alertTitle: LuaContactUsStrings.defaultErrorDescription) } } diff --git a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewModel.swift b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewModel.swift index 3721bb6..5ff129b 100644 --- a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewModel.swift +++ b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewModel.swift @@ -22,11 +22,12 @@ final class LuaContactUsViewModel: LuaContactUsViewModelProtocol { public func sendMessage(message: String, mail: String) async throws { do { - let params = makeSendParams(message: message, mail: mail) + let params = makeSendMessageParams(message: message, mail: mail) let response: [String: String] = try await networkManager.request(.sendContactUsMessage(params)) print(response) } catch { - throw error + print(error.localizedDescription) + throw LuaNetworkError.anyUnintendedResponse } } @@ -36,12 +37,13 @@ final class LuaContactUsViewModel: LuaContactUsViewModelProtocol { contactUsModel = try await networkManager.request(.getContactUsData) print(contactUsModel) } catch { - throw error + print(error.localizedDescription) + throw LuaNetworkError.anyUnintendedResponse } } } - private func makeSendParams(message: String, mail: String) -> [String:String] { + private func makeSendMessageParams(message: String, mail: String) -> [String:String] { let params: [String: String] = [ "email": mail, "mensagem": message diff --git a/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaNetworkError.swift b/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaNetworkError.swift index 6cfd72b..314ec1d 100644 --- a/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaNetworkError.swift +++ b/CleanCodeApp/Modules/Features/Lua/LuaErrors/LuaNetworkError.swift @@ -15,6 +15,7 @@ enum LuaNetworkError: Error { case serverError // 500 case unknown case noInternetConnection + case anyUnintendedResponse } extension LuaNetworkError: LocalizedError { diff --git a/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/LuaAlertHandlerProtocol.swift b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/LuaAlertHandlerProtocol.swift index 95fb0e6..c7f166a 100644 --- a/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/LuaAlertHandlerProtocol.swift +++ b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/LuaAlertHandlerProtocol.swift @@ -12,7 +12,7 @@ public protocol LuaAlertHandlerProtocol { func showAlertError(error: Error, from viewController: UIViewController, alertTitle: String?, style: UIAlertController.Style?) } -extension LuaAlertHandlerProtocol { +extension UIViewController: LuaAlertHandlerProtocol { public func showAlertError(error: Error, from viewController: UIViewController, alertTitle: String?, style: UIAlertController.Style? = nil) { let alertController = UIAlertController(title: alertTitle, message: error.localizedDescription, preferredStyle: .alert) let action = UIAlertAction(title: "OK", style: .default) diff --git a/CleanCodeApp/Modules/Features/Lua/LuaNetwork/LuaAPITarget.swift b/CleanCodeApp/Modules/Features/Lua/LuaNetwork/LuaAPITarget.swift index 4734764..4167b26 100644 --- a/CleanCodeApp/Modules/Features/Lua/LuaNetwork/LuaAPITarget.swift +++ b/CleanCodeApp/Modules/Features/Lua/LuaNetwork/LuaAPITarget.swift @@ -10,7 +10,7 @@ import Foundation public enum LuaAPIAuthTarget { case login case createUser - case resetPassword + case resetPassword([String:String]) } public enum LuaAPITarget { diff --git a/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewControllerFactory.swift b/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewControllerFactory.swift index ffef1fd..147ce9b 100644 --- a/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewControllerFactory.swift +++ b/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewControllerFactory.swift @@ -9,7 +9,7 @@ import UIKit public struct LuaContactUsViewControllerFactory { static func makeLuaContactUsViewController() -> UIViewController { - let viewModel = LuaContactUsViewModelFactory.makeLuaContactUsViewModel() + let viewModel = LuaContactUsViewModel(networkManager: LuaNetworkManager()) let luaContactUsViewController = LuaContactUsViewController(viewModel: viewModel) luaContactUsViewController.modalPresentationStyle = .fullScreen luaContactUsViewController.modalTransitionStyle = .coverVertical diff --git a/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewModelFactory.swift b/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewModelFactory.swift deleted file mode 100644 index d8092b1..0000000 --- a/CleanCodeApp/Modules/Features/Lua/Main/LuaContactUsViewModelFactory.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// LuaContactUsViewModelFactory.swift -// CleanCodeApp -// -// Created by Gabriel Amaral on 17/02/25. -// - -struct LuaContactUsViewModelFactory { - static func makeLuaContactUsViewModel() -> LuaContactUsViewModelProtocol { - let viewModel = LuaContactUsViewModel(networkManager: LuaNetworkManager()) - return viewModel - } -} diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift index f19c8ba..374a1dc 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift @@ -1,6 +1,6 @@ import UIKit -final class LuaResetPasswordViewController: UIViewController, LuaAlertHandlerProtocol, LuaViewControllerProtocol { +final class LuaResetPasswordViewController: UIViewController, LuaViewControllerProtocol { typealias ViewCode = LuaResetPasswordView internal let viewCode = LuaResetPasswordView() @@ -50,7 +50,7 @@ final class LuaResetPasswordViewController: UIViewController, LuaAlertHandlerPro private func resquestPasswordReset() async { do { - try await viewModel.startPasswordResetRequest(targetViewController: self, emailInputted: viewCode.emailInputted) + try await viewModel.startPasswordReseting(targetViewController: self, emailInputted: viewCode.emailInputted) displayPasswordResetSuccessUI() } catch let error as LuaNetworkError { showAlertError(error: error, from: self, alertTitle: error.errorTitle) diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift index f458c45..0b9ba94 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewModel.swift @@ -9,7 +9,7 @@ import UIKit protocol LuaResetPasswordViewModelProtocol { func validateEmailFormat(inputedEmail: String) -> Bool - func startPasswordResetRequest(targetViewController: UIViewController, emailInputted: String) async throws + func startPasswordReseting(targetViewController: UIViewController, emailInputted: String) async throws } final class LuaResetPasswordViewModel: LuaResetPasswordViewModelProtocol { @@ -20,11 +20,11 @@ final class LuaResetPasswordViewModel: LuaResetPasswordViewModelProtocol { self.networkManager = networkManager } - func startPasswordResetRequest(targetViewController: UIViewController, emailInputted: String) async throws { + func startPasswordReseting(targetViewController: UIViewController, emailInputted: String) async throws { do { try validateConnectivity(emailInputted: emailInputted) let passwordParameters = makePasswordResetParams(inputedEmail: emailInputted) - try sendPasswordResetRequest(targetViewController: targetViewController, parameters: passwordParameters) + let _: Data = try await networkManager.request(.authTarget(.resetPassword(passwordParameters))) } catch _ as LuaNetworkError { throw LuaNetworkError.noInternetConnection } catch { @@ -32,16 +32,6 @@ final class LuaResetPasswordViewModel: LuaResetPasswordViewModelProtocol { } } - private func sendPasswordResetRequest(targetViewController: UIViewController, parameters: [String : String]) throws { - Task { - do { - let _: Data = try await networkManager.request(.authTarget(.resetPassword)) - } catch { - throw error - } - } - } - private func makePasswordResetParams(inputedEmail: String) -> [String : String] { let passwordResetParameters = [ "email": inputedEmail From a2addce83a49d54731526d7550ddb7ec2ebd8f94 Mon Sep 17 00:00:00 2001 From: Eirado <111468283+Eirado@users.noreply.github.com> Date: Mon, 24 Feb 2025 11:02:31 -0300 Subject: [PATCH 22/22] pr fixes 2 --- .DS_Store | Bin 6148 -> 6148 bytes .../LuaContactUsViewController.swift | 28 +++++++++--------- .../Protocols/LuaAlertHandlerProtocol.swift | 27 +++++++++++------ .../LuaResetPasswordViewController.swift | 6 ++-- 4 files changed, 35 insertions(+), 26 deletions(-) diff --git a/.DS_Store b/.DS_Store index 060e125f9a1e4ad253082a70ac0e6593662f390c..bf7fb6f73a72b3cac3937dfdb44d03295e3126d5 100644 GIT binary patch delta 56 zcmZoMXffEJ$;{NpJvpD*XmTtw7n>WSKzii1$s2*(`OG{Bt^?zR&4L`FESuRm{_+C= D(OVFI delta 56 zcmZoMXffEJ$;@Q3W^z8W(d1ZWF181&RCY6NnY7YW!cQm@s}R} DCf*YW diff --git a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift index c00c479..f4b032d 100644 --- a/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift +++ b/CleanCodeApp/Modules/Features/Lua/ContactsUs/LuaContactUsViewController.swift @@ -7,7 +7,7 @@ import UIKit -final class LuaContactUsViewController: UIViewController, LuaViewControllerProtocol { +final class LuaContactUsViewController: UIViewController, LuaViewControllerProtocol, LuaAlertHandlerProtocol { typealias ViewCode = LuaContactUsView internal let viewCode = LuaContactUsView() private let viewModel: LuaContactUsViewModelProtocol @@ -40,7 +40,7 @@ final class LuaContactUsViewController: UIViewController, LuaViewControllerProto await luaStopLoading() } catch { await luaStopLoading() - showAlertError(error: error, from: self, alertTitle: LuaContactUsStrings.defaultErrorTitle) + showAlertError(error: error, alertTitle: LuaContactUsStrings.defaultErrorTitle) self.dismiss(animated: true) } } @@ -57,7 +57,7 @@ final class LuaContactUsViewController: UIViewController, LuaViewControllerProto sendMessage(message: message, mail: mail) return } - showAlert(alertTitle: LuaContactUsStrings.emptyMessageTitle , message: LuaContactUsStrings.emptyMessageDescription, viewController: self) + showAlert(alertTitle: LuaContactUsStrings.emptyMessageTitle , message: LuaContactUsStrings.emptyMessageDescription) } private func sendMessage(message: String, mail: String) { @@ -65,10 +65,10 @@ final class LuaContactUsViewController: UIViewController, LuaViewControllerProto do { await luaShowLoading() try await viewModel.sendMessage(message: message, mail: mail) - showAlert(alertTitle: LuaContactUsStrings.defaultSuccessTitle, message: LuaContactUsStrings.defaultSuccessDescription, viewController: self) + showAlert(alertTitle: LuaContactUsStrings.defaultSuccessTitle, message: LuaContactUsStrings.defaultSuccessDescription) } catch { await luaStopLoading() - showAlertError(error: error, from: self, alertTitle: LuaContactUsStrings.sendMessageErrorDescription) + showAlertError(error: error, alertTitle: LuaContactUsStrings.sendMessageErrorDescription) } await luaStopLoading() } @@ -94,9 +94,9 @@ private extension LuaContactUsViewController { do { try openPhone() } catch let error as LuaPersonalInfoError { - showAlertError(error: error, from: self, alertTitle: error.errorTitle) + showAlertError(error: error, alertTitle: error.errorTitle) } catch { - showAlertError(error: error, from: self, alertTitle: LuaContactUsStrings.defaultErrorDescription) + showAlertError(error: error, alertTitle: LuaContactUsStrings.defaultErrorDescription) } } @@ -104,9 +104,9 @@ private extension LuaContactUsViewController { do { try openMail() } catch let error as LuaPersonalInfoError { - showAlertError(error: error, from: self, alertTitle: error.errorTitle) + showAlertError(error: error, alertTitle: error.errorTitle) } catch { - showAlertError(error: error, from: self, alertTitle: LuaContactUsStrings.defaultErrorDescription) + showAlertError(error: error, alertTitle: LuaContactUsStrings.defaultErrorDescription) } } @@ -114,9 +114,9 @@ private extension LuaContactUsViewController { do { try openWhatsapp() } catch let error as LuaPersonalInfoError { - showAlertError(error: error, from: self, alertTitle: error.errorTitle) + showAlertError(error: error, alertTitle: error.errorTitle) } catch { - showAlertError(error: error, from: self, alertTitle: LuaContactUsStrings.defaultErrorDescription) + showAlertError(error: error, alertTitle: LuaContactUsStrings.defaultErrorDescription) } } @@ -132,7 +132,7 @@ private extension LuaContactUsViewController { try openExternalApp(appURLTarget: .phone(phoneNumer)) } catch let error as LuaUIApplicationURLError { - showAlertError(error: error, from: self, alertTitle: error.errorTitle) + showAlertError(error: error, alertTitle: error.errorTitle) } } @@ -144,7 +144,7 @@ private extension LuaContactUsViewController { try openExternalApp(appURLTarget: .whatsapp(phoneNumer)) } catch let error as LuaUIApplicationURLError { - showAlertError(error: error, from: self, alertTitle: error.errorTitle) + showAlertError(error: error, alertTitle: error.errorTitle) } } @@ -156,7 +156,7 @@ private extension LuaContactUsViewController { try openExternalApp(appURLTarget: .mail(mail)) } catch let error as LuaUIApplicationURLError { - showAlertError(error: error, from: self, alertTitle: error.errorTitle) + showAlertError(error: error, alertTitle: error.errorTitle) } } diff --git a/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/LuaAlertHandlerProtocol.swift b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/LuaAlertHandlerProtocol.swift index c7f166a..4da1b71 100644 --- a/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/LuaAlertHandlerProtocol.swift +++ b/CleanCodeApp/Modules/Features/Lua/LuaHelpers/Protocols/LuaAlertHandlerProtocol.swift @@ -8,22 +8,31 @@ import UIKit public protocol LuaAlertHandlerProtocol { - func showAlert(alertTitle: String?, message: String, style: UIAlertController.Style?, viewController: UIViewController) - func showAlertError(error: Error, from viewController: UIViewController, alertTitle: String?, style: UIAlertController.Style?) + func showAlert(alertTitle: String?, message: String, style: UIAlertController.Style) + func showAlertError(error: Error, alertTitle: String?, style: UIAlertController.Style) } -extension UIViewController: LuaAlertHandlerProtocol { - public func showAlertError(error: Error, from viewController: UIViewController, alertTitle: String?, style: UIAlertController.Style? = nil) { - let alertController = UIAlertController(title: alertTitle, message: error.localizedDescription, preferredStyle: .alert) +extension LuaAlertHandlerProtocol where Self: UIViewController { + + public func showAlertError(error: Error, alertTitle: String? = "Error", style: UIAlertController.Style = .alert) { + let alertController = UIAlertController( + title: alertTitle, + message: error.localizedDescription, + preferredStyle: style + ) let action = UIAlertAction(title: "OK", style: .default) alertController.addAction(action) - viewController.present(alertController, animated: true) + self.present(alertController, animated: true) } - public func showAlert(alertTitle: String?, message: String, style: UIAlertController.Style? = .alert, viewController: UIViewController) { - let alertController = UIAlertController(title: alertTitle, message: message, preferredStyle: style!) + public func showAlert(alertTitle: String?, message: String, style: UIAlertController.Style = .alert) { + let alertController = UIAlertController( + title: alertTitle, + message: message, + preferredStyle: style + ) let action = UIAlertAction(title: "OK", style: .default) alertController.addAction(action) - viewController.present(alertController, animated: true) + self.present(alertController, animated: true) } } diff --git a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift index 374a1dc..fc72516 100644 --- a/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift +++ b/CleanCodeApp/Modules/Features/Lua/ResetPassword/LuaResetPasswordViewController.swift @@ -1,6 +1,6 @@ import UIKit -final class LuaResetPasswordViewController: UIViewController, LuaViewControllerProtocol { +final class LuaResetPasswordViewController: UIViewController, LuaViewControllerProtocol, LuaAlertHandlerProtocol { typealias ViewCode = LuaResetPasswordView internal let viewCode = LuaResetPasswordView() @@ -53,9 +53,9 @@ final class LuaResetPasswordViewController: UIViewController, LuaViewControllerP try await viewModel.startPasswordReseting(targetViewController: self, emailInputted: viewCode.emailInputted) displayPasswordResetSuccessUI() } catch let error as LuaNetworkError { - showAlertError(error: error, from: self, alertTitle: error.errorTitle) + showAlertError(error: error, alertTitle: error.errorTitle) } catch { - showAlertError(error: error, from: self, alertTitle: "Algo de errado aconteceu. Tente novamente mais tarde.") + showAlertError(error: error, alertTitle: "Algo de errado aconteceu. Tente novamente mais tarde.") } }