-
Notifications
You must be signed in to change notification settings - Fork 10
Feature/main/tratar classe #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
7bff2b2
b5f68eb
d2cc78c
3220523
9126b63
79d1e52
741e65e
9b1a159
1c1c0be
83a17a6
42bbb44
1d6851e
08b4c35
0dea448
b193e27
cee5e06
476f786
0bf8a44
2ce712a
872a360
1d2281a
9abd3eb
41bd2d4
408899f
4e367a1
6da5370
484695d
b7f7fd8
219b317
e709c2d
fdad58b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| // | ||
| // RioAlertHelper.swift | ||
| // CleanCode | ||
| // | ||
| // Created by thaisa on 17/02/25. | ||
| // | ||
|
|
||
| import Foundation | ||
| import UIKit | ||
|
|
||
| class RioAlertHelper { | ||
|
|
||
| static func showErrorAlert(on viewController: UIViewController, message: String) { | ||
| let alert = UIAlertController(title: "Ops...", message: message, preferredStyle: .alert) | ||
| alert.addAction(UIAlertAction(title: "OK", style: .default)) | ||
| viewController.present(alert, animated: true) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| // | ||
| // RioCommonErrors.swift | ||
| // CleanCode | ||
| // | ||
| // Created by thaisa on 17/02/25. | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| enum RioCommonErrors: Error { | ||
| case noInternet | ||
| case invalidEmail | ||
|
|
||
| var alertDescription: String { | ||
| switch self { | ||
| case .noInternet: | ||
| return "Você não tem conexão no momento." | ||
| case .invalidEmail: | ||
| return "O e-mail informado é inválido." | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| // | ||
| // RioResetPasswordService.swift | ||
| // CleanCode | ||
| // | ||
| // Created by thaisa on 17/02/25. | ||
| // | ||
|
|
||
| import Foundation | ||
| import UIKit | ||
|
|
||
| class RioResetPasswordService { | ||
|
|
||
| func resetPassword(email: String, completion: @escaping (Bool) -> Void) { | ||
| let parameters = ["email": email] | ||
|
|
||
| if let topController = UIApplication.shared.windows.first?.rootViewController { | ||
| BadNetworkLayer.shared.resetPassword(topController, parameters: parameters) { success in | ||
| completion(success) | ||
| } | ||
| } else { | ||
| completion(false) | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| // | ||
| // RioResetPasswordViewConfigurator.swift | ||
| // CleanCode | ||
| // | ||
| // Created by thaisa on 17/02/25. | ||
| // | ||
|
|
||
| import Foundation | ||
| import UIKit | ||
|
|
||
| class RioResetPasswordViewConfigurator { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nao interessante performar operações da viewController fora dela (com exceção do coordinator)
|
||
|
|
||
| func setupView(for viewController: RioResetPasswordViewController) { | ||
| setupButtons(for: viewController) | ||
| setupTextField(for: viewController) | ||
| setupEmail(for: viewController) | ||
| updateRecoverPasswordButtonState(for: viewController) | ||
| viewController.viewSuccess.isHidden = true | ||
| } | ||
|
|
||
| private func setupButtons(for vc: RioResetPasswordViewController) { | ||
| styleButton(vc.recoverPasswordButton, backgroundColor: .blue, titleColor: .white, borderWidth: 0) | ||
| styleButton(vc.loginButton, backgroundColor: .white, titleColor: .blue, borderWidth: 1) | ||
| styleButton(vc.helpButton, backgroundColor: .white, titleColor: .blue, borderWidth: 1) | ||
| styleButton(vc.createAccountButton, backgroundColor: .white, titleColor: .blue, borderWidth: 1) | ||
| } | ||
|
|
||
| private func styleButton(_ button: UIButton, backgroundColor: UIColor, titleColor: UIColor, borderWidth: CGFloat) { | ||
| button.layer.cornerRadius = button.bounds.height / 2 | ||
| button.layer.borderWidth = borderWidth | ||
| button.layer.borderColor = UIColor.blue.cgColor | ||
| button.setTitleColor(titleColor, for: .normal) | ||
| button.backgroundColor = backgroundColor | ||
| } | ||
|
|
||
| private func setupTextField(for vc: RioResetPasswordViewController) { | ||
| vc.emailTextfield.setDefaultColor() | ||
| } | ||
|
|
||
| private func setupEmail(for vc: RioResetPasswordViewController) { | ||
| guard !vc.email.isEmpty else { return } | ||
| vc.emailTextfield.text = vc.email | ||
| vc.emailTextfield.isEnabled = false | ||
| } | ||
|
|
||
| func updateRecoverPasswordButtonState(for vc: RioResetPasswordViewController) { | ||
| let isValid = !(vc.emailTextfield.text?.isEmpty ?? true) | ||
| vc.recoverPasswordButton.backgroundColor = isValid ? .blue : .gray | ||
| vc.recoverPasswordButton.setTitleColor(.white, for: .normal) | ||
| vc.recoverPasswordButton.isEnabled = isValid | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,21 +1,12 @@ | ||
| import UIKit | ||
|
|
||
| enum RioCommonErrors: Error { | ||
| case noInternet | ||
| case invalidEmail | ||
|
|
||
| var alertDescription: String { | ||
| switch self { | ||
| case .noInternet: | ||
| return "Você não tem conexão no momento." | ||
| case .invalidEmail: | ||
| return "O e-mail informado é inválido." | ||
| } | ||
| } | ||
| protocol RioResetPasswordViewModelDelegate: AnyObject { | ||
| func didResetPasswordSuccess(email: String) | ||
| func didFailWithError(_ error: RioCommonErrors) | ||
| } | ||
|
|
||
| class RioResetPasswordViewController: UIViewController { | ||
|
|
||
| @IBOutlet weak var emailTextfield: UITextField! | ||
| @IBOutlet weak var recoverPasswordButton: UIButton! | ||
| @IBOutlet weak var loginButton: UIButton! | ||
|
|
@@ -27,88 +18,32 @@ class RioResetPasswordViewController: UIViewController { | |
| @IBOutlet weak var emailLabel: UILabel! | ||
|
|
||
| var email = "" | ||
| var recoveryEmail = false | ||
|
|
||
| private var recoveryEmail = false | ||
| private let viewModel = RioResetPasswordViewModel() | ||
| private let viewConfigurator = RioResetPasswordViewConfigurator() | ||
|
|
||
| override func viewDidLoad() { | ||
| super.viewDidLoad() | ||
| setupView() | ||
| viewModel.delegate = self | ||
| viewConfigurator.setupView(for: self) | ||
| } | ||
|
|
||
| open override var preferredStatusBarStyle: UIStatusBarStyle { | ||
| return .lightContent | ||
| } | ||
|
|
||
| @IBAction func closeButtonAction(_ sender: Any) { | ||
| dismiss(animated: true) | ||
| } | ||
|
|
||
| @IBAction func recoverPasswordButton(_ sender: Any) { | ||
| if recoveryEmail { | ||
| dismiss(animated: true) | ||
| return | ||
| } | ||
|
|
||
| attemptPasswordReset() | ||
| } | ||
|
|
||
| // MARK: - Nova função de reset de senha com tratamento de erro | ||
|
|
||
| private func attemptPasswordReset() { | ||
| do { | ||
| try validateForm() | ||
| try validateInternetConnection() | ||
|
|
||
| let emailUser = emailTextfield.text!.trimmingCharacters(in: .whitespaces) | ||
| resetPassword(email: emailUser) | ||
| } catch let error as RioCommonErrors { | ||
| showErrorAlert(message: error.alertDescription) | ||
| } catch { | ||
| showErrorAlert(message: "Ocorreu um erro inesperado. Tente novamente.") | ||
| } | ||
| } | ||
|
|
||
| // MARK: - Validações | ||
|
|
||
| private func validateInternetConnection() throws { | ||
| guard ConnectivityManager.shared.isConnected else { | ||
| throw RioCommonErrors.noInternet | ||
| } else { | ||
| guard let emailUser = emailTextfield.text?.trimmingCharacters(in: .whitespaces) else { return } | ||
| viewModel.attemptPasswordReset(email: emailUser) | ||
| } | ||
| } | ||
|
|
||
| // MARK: - Reset de Senha | ||
|
|
||
| private func resetPassword(email: String) { | ||
| let parameters = ["email": email] | ||
|
|
||
| BadNetworkLayer.shared.resetPassword(self, parameters: parameters) { success in | ||
| success ? self.handleSuccess(email: email) : self.showErrorAlert(message: "Algo de errado aconteceu. Tente novamente mais tarde.") | ||
| } | ||
| } | ||
|
|
||
| private func handleSuccess(email: String) { | ||
| recoveryEmail = true | ||
| emailTextfield.isHidden = true | ||
| textLabel.isHidden = true | ||
| viewSuccess.isHidden = false | ||
| emailLabel.text = email | ||
| updateRecoverPasswordButton() | ||
| } | ||
|
|
||
| private func updateRecoverPasswordButton() { | ||
| recoverPasswordButton.titleLabel?.text = "REENVIAR E-MAIL" | ||
| recoverPasswordButton.setTitle("Voltar", for: .normal) | ||
| } | ||
|
|
||
| private func showErrorAlert(message: String) { | ||
| let alert = UIAlertController( | ||
| title: "Ops..", | ||
| message: message, | ||
| preferredStyle: .alert | ||
| ) | ||
| alert.addAction(UIAlertAction(title: "OK", style: .default)) | ||
| present(alert, animated: true) | ||
| } | ||
|
|
||
|
|
||
| @IBAction func loginButton(_ sender: Any) { | ||
| dismiss(animated: true) | ||
|
|
@@ -118,7 +53,7 @@ class RioResetPasswordViewController: UIViewController { | |
| let vc = RioContactUsViewController() | ||
| vc.modalPresentationStyle = .fullScreen | ||
| vc.modalTransitionStyle = .coverVertical | ||
| self.present(vc, animated: true, completion: nil) | ||
| present(vc, animated: true) | ||
| } | ||
|
|
||
| @IBAction func createAccountButton(_ sender: Any) { | ||
|
|
@@ -127,82 +62,36 @@ class RioResetPasswordViewController: UIViewController { | |
| present(newVc, animated: true) | ||
| } | ||
|
|
||
| func validateForm() throws { | ||
| guard let email = emailTextfield.text, !isEmailFormatInvalid(email) else { | ||
| throw RioCommonErrors.invalidEmail | ||
| } | ||
| } | ||
|
|
||
| func isEmailFormatInvalid(_ email: String) -> Bool { | ||
| return email.isEmpty || | ||
| !email.contains(".") || | ||
| !email.contains("@") || | ||
| email.count <= 5 | ||
| } | ||
| } | ||
|
|
||
| // MARK: - Comportamentos de layout | ||
| extension RioResetPasswordViewController { | ||
|
|
||
| func setupView() { | ||
| setupButtons() | ||
| setupTextField() | ||
| setupEmail() | ||
| updateRecoverPasswordButtonState() | ||
| } | ||
|
|
||
| // MARK: - Configuração dos Botões | ||
|
|
||
| private func setupButtons() { | ||
| styleButton(recoverPasswordButton, backgroundColor: .blue, titleColor: .white, borderWidth: 0) | ||
| styleButton(loginButton, backgroundColor: .white, titleColor: .blue, borderWidth: 1) | ||
| styleButton(helpButton, backgroundColor: .white, titleColor: .blue, borderWidth: 1) | ||
| styleButton(createAccountButton, backgroundColor: .white, titleColor: .blue, borderWidth: 1) | ||
| } | ||
|
|
||
| private func styleButton(_ button: UIButton, backgroundColor: UIColor, titleColor: UIColor, borderWidth: CGFloat) { | ||
| button.layer.cornerRadius = button.bounds.height / 2 | ||
| button.layer.borderWidth = borderWidth | ||
| button.layer.borderColor = UIColor.blue.cgColor | ||
| button.setTitleColor(titleColor, for: .normal) | ||
| button.backgroundColor = backgroundColor | ||
| } | ||
|
|
||
| // MARK: - Configuração do Campo de Texto | ||
|
|
||
| private func setupTextField() { | ||
| emailTextfield.setDefaultColor() | ||
| } | ||
|
|
||
| // MARK: - Configuração do E-mail | ||
|
|
||
| private func setupEmail() { | ||
| guard !email.isEmpty else { return } | ||
| emailTextfield.text = email | ||
| emailTextfield.isEnabled = false | ||
| } | ||
|
|
||
| @IBAction func emailBeginEditing(_ sender: Any) { | ||
| emailTextfield.setEditingColor() | ||
| } | ||
|
|
||
| @IBAction func emailEditing(_ sender: Any) { | ||
| emailTextfield.setEditingColor() | ||
| updateRecoverPasswordButtonState() | ||
| viewConfigurator.updateRecoverPasswordButtonState(for: self) | ||
| } | ||
|
|
||
| @IBAction func emailEndEditing(_ sender: Any) { | ||
| emailTextfield.setDefaultColor() | ||
| } | ||
| } | ||
|
|
||
| extension RioResetPasswordViewController { | ||
| extension RioResetPasswordViewController: RioResetPasswordViewModelDelegate { | ||
|
|
||
| func didResetPasswordSuccess(email: String) { | ||
| recoveryEmail = true | ||
| emailTextfield.isHidden = true | ||
| textLabel.isHidden = true | ||
| viewSuccess.isHidden = false | ||
| emailLabel.text = email | ||
| updateRecoverPasswordButtonTitleForSuccess() | ||
| } | ||
|
|
||
| func didFailWithError(_ error: RioCommonErrors) { | ||
| RioAlertHelper.showErrorAlert(on: self, message: error.alertDescription) | ||
| } | ||
|
|
||
| func updateRecoverPasswordButtonState() { | ||
| let isValid = !(emailTextfield.text?.isEmpty ?? true) | ||
| recoverPasswordButton.backgroundColor = isValid ? .blue : .gray | ||
| recoverPasswordButton.setTitleColor(.white, for: .normal) | ||
| recoverPasswordButton.isEnabled = isValid | ||
| private func updateRecoverPasswordButtonTitleForSuccess() { | ||
| recoverPasswordButton.setTitle("Voltar", for: .normal) | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. n tem necessidade de uma funcao com 1 linha |
||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
futuramente vou sugerir para usar composição para essa funcao (aula de LI)
mas por enquanto sugiro apenas usar enum ao inves de classe
já que nao tem necessidade de instanciar esse objeto