diff --git a/CMC/Sources/App/AppCoordinator.swift b/CMC/Sources/App/AppCoordinator.swift index f8bde88..21c8ad2 100644 --- a/CMC/Sources/App/AppCoordinator.swift +++ b/CMC/Sources/App/AppCoordinator.swift @@ -64,7 +64,7 @@ class AppCoordinator: CoordinatorType { ) ) ) - self.pushViewController(viewController: splashViewController) + self.navigationController.pushViewController(splashViewController, animated: false) } } diff --git a/CMC/Sources/Presenter/Auth/Coordinators/AuthCoordinator.swift b/CMC/Sources/Presenter/Auth/Coordinators/AuthCoordinator.swift index da221f3..0b24187 100644 --- a/CMC/Sources/Presenter/Auth/Coordinators/AuthCoordinator.swift +++ b/CMC/Sources/Presenter/Auth/Coordinators/AuthCoordinator.swift @@ -45,31 +45,34 @@ class AuthCoordinator: CoordinatorType { CMCIndecatorManager.shared.show() switch state{ case .main: - let mainAuthViewController = MainAuthViewController( - viewModel: MainAuthViewModel( - coordinator: self - ) - ) if self.navigationController.viewControllers.contains(where: {$0 is MainAuthViewController}) { - self.navigationController.popViewController(animated: true) - }else { - self.pushViewController(viewController: mainAuthViewController) - CMCIndecatorManager.shared.hide() + self.navigationController.popToRootViewController(animated: true) } + let mainAuthViewController = MainAuthViewController( + viewModel: MainAuthViewModel( + coordinator: self + ) + ) + self.pushViewController(viewController: mainAuthViewController) + CMCIndecatorManager.shared.hide() case .signUp: + if self.navigationController.viewControllers.contains(where: {$0 is SignUpViewController}) { + self.navigationController.popToRootViewController(animated: true) + } let signUpViewController = SignUpViewController( viewModel: SignUpViewModel( - coordinator: self, - authUsecase: DefaultAuthUsecase( - authRepository: DefaultAuthRepository() - ) - ) - ) + coordinator: self, + authUsecase: DefaultAuthUsecase( + authRepository: DefaultAuthRepository() + ) + ) + ) + self.pushViewController(viewController: signUpViewController) + CMCIndecatorManager.shared.hide() + case .signIn: if self.navigationController.viewControllers.contains(where: {$0 is SignInViewController}) { - self.navigationController.popViewController(animated: true) + self.navigationController.popToRootViewController(animated: true) } - self.pushViewController(viewController: signUpViewController) - case .signIn: let signInViewController = SignInViewController( viewModel: SignInViewModel( coordinator: self, @@ -78,9 +81,6 @@ class AuthCoordinator: CoordinatorType { ) ) ) - if self.navigationController.viewControllers.contains(where: {$0 is SignUpViewController}) { - self.navigationController.popViewController(animated: true) - } self.pushViewController(viewController: signInViewController) CMCIndecatorManager.shared.hide() } diff --git a/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/ConfirmCertifyCode/ConfirmCertifyCodeViewModel.swift b/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/ConfirmCertifyCode/ConfirmCertifyCodeViewModel.swift index 9284d06..b2f65a7 100644 --- a/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/ConfirmCertifyCode/ConfirmCertifyCodeViewModel.swift +++ b/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/ConfirmCertifyCode/ConfirmCertifyCodeViewModel.swift @@ -31,13 +31,13 @@ final class ConfirmCertifyCodeViewModel: ViewModelType { var disposeBag: DisposeBag = DisposeBag() private let usecase: AuthUsecase + // MARK: - Initializers init( usecase: AuthUsecase ) { self.usecase = usecase } - func transform(input: Input) -> Output { let resendCertifyCode = input.reSendButtonTapped diff --git a/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/ResettingPassword/ResettingPasswordView.swift b/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/ResettingPassword/ResettingPasswordView.swift index d42d92f..352b797 100644 --- a/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/ResettingPassword/ResettingPasswordView.swift +++ b/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/ResettingPassword/ResettingPasswordView.swift @@ -89,6 +89,19 @@ final class ResettingPasswordView: BaseView { return errorCell }() + + private lazy var reSettingPasswordButton: CMCButton = { + let button = CMCButton( + isRound: false, + iconTitle: nil, + type: .login(.disabled), + title: "비밀번호 변경하기" + ) + button.translatesAutoresizingMaskIntoConstraints = false + return button + }() + + // MARK: - Properties private var viewModel: ResettingPasswordViewModel private var parentViewModel: FindPasswordViewModel @@ -123,12 +136,14 @@ final class ResettingPasswordView: BaseView { mainContentView.addSubview(passwordErrorStackView) mainContentView.addSubview(confirmPasswordTextField) mainContentView.addSubview(passwordCheckErrorCell) + self.addSubview(reSettingPasswordButton) } override func setConstraint() { scrollView.snp.makeConstraints { make in - make.top.leading.trailing.bottom.equalToSuperview() + make.top.leading.trailing.equalToSuperview() + make.bottom.equalTo(reSettingPasswordButton.snp.top) } mainContentView.snp.makeConstraints { make in @@ -166,6 +181,11 @@ final class ResettingPasswordView: BaseView { make.bottom.equalToSuperview().offset(-24) } + reSettingPasswordButton.snp.makeConstraints{ reSettingPasswordButton in + reSettingPasswordButton.leading.trailing.equalToSuperview().inset(20) + reSettingPasswordButton.bottom.equalTo(self.keyboardLayoutGuide.snp.top).offset(-20) + reSettingPasswordButton.height.equalTo(56) + } } override func bind() { @@ -181,7 +201,6 @@ final class ResettingPasswordView: BaseView { }) .disposed(by: disposeBag) - passwordTextField.accessoryState .observe(on: MainScheduler.instance) .withUnretained(self) @@ -199,8 +218,11 @@ final class ResettingPasswordView: BaseView { .disposed(by: disposeBag) let input = ResettingPasswordViewModel.Input( + email: parentViewModel.email.asObservable(), password: passwordTextField.rx.text.orEmpty.asObservable(), - rePassword: confirmPasswordTextField.rx.text.orEmpty.asObservable() + rePassword: confirmPasswordTextField.rx.text.orEmpty.asObservable(), + reSettingPasswordTapped: reSettingPasswordButton.rx.tap.asObservable() + ) let output = viewModel.transform(input: input) @@ -224,6 +246,35 @@ final class ResettingPasswordView: BaseView { }) .disposed(by: disposeBag) + output.reSettingButtonActive + .withUnretained(self) + .subscribe(onNext: { owner, isEnable in + isEnable == true + ? owner.reSettingPasswordButton.rxType.accept(.login(.inactive)) + : owner.reSettingPasswordButton.rxType.accept(.login(.disabled)) + }) + .disposed(by: disposeBag) + + output.reSettingPasswordResult + .observe(on: MainScheduler.instance) + .subscribe(onNext: { [weak self] isSuccessed in + guard let ss = self else { return } + if isSuccessed { + CMCBottomSheetManager.shared.showBottomSheet( + title: "비밀번호가 변경되었습니다\n다시 로그인해주세요 :)", + body: nil, + buttonTitle: "확인" + ) + ss.parentViewModel.coordinator?.userActionState.accept(.main) + } else { + CMCBottomSheetManager.shared.showBottomSheet( + title: "비밀번호 변경에 실패하였습니다.", + body: "다시 시도해주세요 :(", + buttonTitle: "확인" + ) + } + }) + .disposed(by: disposeBag) } } diff --git a/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/ResettingPassword/ResettingPasswordViewModel.swift b/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/ResettingPassword/ResettingPasswordViewModel.swift index 22ea516..6c05927 100644 --- a/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/ResettingPassword/ResettingPasswordViewModel.swift +++ b/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/ResettingPassword/ResettingPasswordViewModel.swift @@ -16,21 +16,27 @@ import UIKit final class ResettingPasswordViewModel: ViewModelType { struct Input { + let email: Observable let password: Observable let rePassword: Observable + let reSettingPasswordTapped: Observable } struct Output { let passwordValidations: [Observable] let passwordConfirmRegex: Observable - let nextAvailable: Observable + let reSettingButtonActive: Observable + let reSettingPasswordResult: Observable } var disposeBag: DisposeBag = DisposeBag() + private let usecase: AuthUsecase // MARK: - Initializers - init() { - + init( + usecase: AuthUsecase + ) { + self.usecase = usecase } func transform(input: Input) -> Output { @@ -49,16 +55,32 @@ final class ResettingPasswordViewModel: ViewModelType { let passwordConfirmRegex = Observable.combineLatest(input.password, input.rePassword) .map { $0 == $1 && !$0.isEmpty} - let nextAvailable = Observable.combineLatest( + let reSettingButtonActive = Observable.combineLatest( passwordRegex, passwordConfirmRegex ) .map { $0 && $1 } + let reSettingPasswordResult = input.reSettingPasswordTapped + .withLatestFrom(Observable.combineLatest(input.email, input.password)) + .withUnretained(self) + .flatMapLatest { owner, result -> Observable in + let (email, password) = result + let body = ResettingPasswordBody(email: email, password: password) + return owner.usecase.reSettingPassword(body: body) + .asObservable() + .map { _ in true} + .catch { _ in + return .just(false) + } + } + .share() + return Output( passwordValidations: passwordValidations, passwordConfirmRegex: passwordConfirmRegex, - nextAvailable: nextAvailable + reSettingButtonActive: reSettingButtonActive, + reSettingPasswordResult: reSettingPasswordResult ) } diff --git a/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordViewController.swift b/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordViewController.swift index 063fbf2..938f255 100644 --- a/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordViewController.swift +++ b/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordViewController.swift @@ -57,7 +57,11 @@ class FindPasswordViewController: BaseViewController { private lazy var resettingPasswordView: ResettingPasswordView = { let view = ResettingPasswordView( - viewModel: ResettingPasswordViewModel(), + viewModel: ResettingPasswordViewModel( + usecase: DefaultAuthUsecase( + authRepository: DefaultAuthRepository() + ) + ), parentViewModel: viewModel ) view.translatesAutoresizingMaskIntoConstraints = false