diff --git a/CMC/Sources/Data/Repositories/Auth/FakeAuthRepository.swift b/CMC/Sources/Data/Repositories/Auth/FakeAuthRepository.swift index 72f2844..c79d51c 100644 --- a/CMC/Sources/Data/Repositories/Auth/FakeAuthRepository.swift +++ b/CMC/Sources/Data/Repositories/Auth/FakeAuthRepository.swift @@ -58,4 +58,24 @@ final class FakeAuthRepository: AuthRepository { ) return Single.just(fakeSendCertifyCodeDTO) } + + func confirmCertifyCode(body: ConfirmCertifyCodeBody) -> Single { + let fakeConfirmCertifyCodeDTO = ConfirmCertifyCodeDTO( + isSuccess: true, + code: "200", + message: "성공", + result: "인증번호가 발송되었습니다." + ) + return Single.just(fakeConfirmCertifyCodeDTO) + } + + func reSettingPassword(body: ResettingPasswordBody) -> Single { + let fakeResettingPasswordDTO = ResettingPasswordDTO( + isSuccess: true, + code: "200", + message: "성공", + result: "인증번호가 발송되었습니다." + ) + return Single.just(fakeResettingPasswordDTO) + } } diff --git a/CMC/Sources/Domain/Usecases/Auth/AuthUsecase.swift b/CMC/Sources/Domain/Usecases/Auth/AuthUsecase.swift index 9959cfa..67f5c19 100644 --- a/CMC/Sources/Domain/Usecases/Auth/AuthUsecase.swift +++ b/CMC/Sources/Domain/Usecases/Auth/AuthUsecase.swift @@ -13,6 +13,7 @@ protocol AuthUsecase { func signUp(body: SignUpBody) -> Single func signIn(body: SignInBody) -> Single func emailDup(query: EmailDupQuery) -> Single + func sendCertifyCode(query: SendCertifyCodeQuery) -> Single func confirmCertifyCode(body: ConfirmCertifyCodeBody) -> Single func reSettingPassword(body: ResettingPasswordBody) -> Single } diff --git a/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/ConfirmCertifyCode/ConfirmCertifyCodeView.swift b/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/ConfirmCertifyCode/ConfirmCertifyCodeView.swift index f9002a6..5b5c47b 100644 --- a/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/ConfirmCertifyCode/ConfirmCertifyCodeView.swift +++ b/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/ConfirmCertifyCode/ConfirmCertifyCodeView.swift @@ -51,6 +51,16 @@ final class ConfirmCertifyCodeView: BaseView { return textField }() + private lazy var confirmCertifyCodeButton: CMCButton = { + let button = CMCButton( + isRound: false, + iconTitle: nil, + type: .login(.disabled), + title: "인증번호 확인" + ) + button.translatesAutoresizingMaskIntoConstraints = false + return button + }() // MARK: - Properties private var viewModel: ConfirmCertifyCodeViewModel @@ -79,6 +89,7 @@ final class ConfirmCertifyCodeView: BaseView { addSubview(titleLabel) addSubview(subTitle) addSubview(certifyCodeTextField) + addSubview(confirmCertifyCodeButton) } override func setConstraint() { @@ -100,6 +111,11 @@ final class ConfirmCertifyCodeView: BaseView { $0.height.equalTo(74) } + confirmCertifyCodeButton.snp.makeConstraints{ confirmCertifyCodeButton in + confirmCertifyCodeButton.leading.trailing.equalToSuperview().inset(20) + confirmCertifyCodeButton.bottom.equalTo(self.keyboardLayoutGuide.snp.top).offset(-20) + confirmCertifyCodeButton.height.equalTo(56) + } } override func bind() { @@ -116,19 +132,39 @@ final class ConfirmCertifyCodeView: BaseView { .disposed(by: disposeBag) + parentViewModel.timerStart + .withUnretained(self) + .subscribe(onNext: { owner, _ in + owner.certifyCodeTextField.resetTimer() + }) + .disposed(by: disposeBag) + let input = ConfirmCertifyCodeViewModel.Input( - nowPage: parentViewModel.nowPage.asObservable(), + email: parentViewModel.email.asObservable(), certifiedCode: certifyCodeTextField.rx.text.orEmpty.asObservable(), reSendButtonTapped: certifyCodeTextField.accessoryCMCButton.rx.tap.asObservable() ) let output = viewModel.transform(input: input) - output.startTimer - .withUnretained(self) - .subscribe(onNext: { owner, isStart in - if isStart { - owner.certifyCodeTextField.resetTimer() + output.sendCertifyResult + .observe(on: MainScheduler.instance) + .subscribe(onNext: { [weak self] isSuccessed in + guard let ss = self else { return } + if isSuccessed { + ss.parentViewModel.nowPage.accept(2) + ss.parentViewModel.timerStart.accept(()) + CMCBottomSheetManager.shared.showBottomSheet( + title: "인증번호를 전송했어요", + body: "3분 내 인증번호를 입력해주세요 :)", + buttonTitle: "확인" + ) + } else { + CMCBottomSheetManager.shared.showBottomSheet( + title: "존재하지 않는 계정이에요", + body: "아이디 찾기는 운영진에게 문의해주세요 :)", + buttonTitle: "확인" + ) } }) .disposed(by: disposeBag) 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 43454ea..b8cc14f 100644 --- a/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/ConfirmCertifyCode/ConfirmCertifyCodeViewModel.swift +++ b/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/ConfirmCertifyCode/ConfirmCertifyCodeViewModel.swift @@ -16,20 +16,19 @@ import RxSwift final class ConfirmCertifyCodeViewModel: ViewModelType { struct Input { - let nowPage: Observable + let email: Observable let certifiedCode: Observable let reSendButtonTapped: Observable } struct Output { - let startTimer: Observable + let sendCertifyResult: Observable let nextAvailable: Observable } var disposeBag: DisposeBag = DisposeBag() private let usecase: AuthUsecase - private let startTimer = BehaviorRelay(value: false) private let nextAvailable = BehaviorRelay(value: false) init( @@ -41,15 +40,6 @@ final class ConfirmCertifyCodeViewModel: ViewModelType { func transform(input: Input) -> Output { - input.nowPage - .withUnretained(self) - .subscribe(onNext: { owner, page in - if page == 2 { - owner.startTimer.accept(true) - } - }) - .disposed(by: disposeBag) - input.certifiedCode .withUnretained(self) .subscribe(onNext: { owner, code in @@ -57,8 +47,24 @@ final class ConfirmCertifyCodeViewModel: ViewModelType { }) .disposed(by: disposeBag) + + let sendCertifyResult = input.reSendButtonTapped + .withLatestFrom(input.email) + .withUnretained(self) + .flatMapLatest { owner, email -> Observable in + let query = SendCertifyCodeQuery(email: email) + return owner.usecase.sendCertifyCode(query: query) + .asObservable() + .map { _ in true} + .catch { _ in + return .just(false) + } + } + .share() + + return Output( - startTimer: startTimer.asObservable(), + sendCertifyResult: sendCertifyResult, nextAvailable: nextAvailable.asObservable() ) diff --git a/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/SendCertifyCode/SendCertifyCodeView.swift b/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/SendCertifyCode/SendCertifyCodeView.swift index 1373503..2b6fae1 100644 --- a/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/SendCertifyCode/SendCertifyCodeView.swift +++ b/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordScrollPages/SendCertifyCode/SendCertifyCodeView.swift @@ -131,6 +131,10 @@ final class SendCertifyCodeView: BaseView { }) .disposed(by: disposeBag) + self.emailTextField.rx.text.orEmpty + .bind(to: parentViewModel.email) + .disposed(by: disposeBag) + let input = SendCertifyCodeViewModel.Input( email: emailTextField.rx.text.orEmpty.asObservable(), receiveCertifyTapped: receiveCertiftyButton.rx.tap.asObservable() @@ -153,6 +157,7 @@ final class SendCertifyCodeView: BaseView { guard let ss = self else { return } if isSuccessed { ss.parentViewModel.nowPage.accept(2) + ss.parentViewModel.timerStart.accept(()) CMCBottomSheetManager.shared.showBottomSheet( title: "인증번호를 전송했어요", body: "3분 내 인증번호를 입력해주세요 :)", diff --git a/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordViewModel.swift b/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordViewModel.swift index fcb9bed..665955e 100644 --- a/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordViewModel.swift +++ b/CMC/Sources/Presenter/Auth/SignIn/FindPassword/FindPasswordViewModel.swift @@ -34,6 +34,7 @@ class FindPasswordViewModel: ViewModelType{ let email = BehaviorRelay(value: "") let nowPage = BehaviorRelay(value: 1) + let timerStart = PublishRelay() // MARK: - Initializers init( diff --git a/DesignSystem/Sources/CMCTextField+Timer.swift b/DesignSystem/Sources/CMCTextField+Timer.swift index aff0a0e..c4f2079 100644 --- a/DesignSystem/Sources/CMCTextField+Timer.swift +++ b/DesignSystem/Sources/CMCTextField+Timer.swift @@ -219,6 +219,7 @@ public final class CMCTextField_Timer: UIView { } public func resetTimer() { + timerDisposeBag = DisposeBag() // 타이머 구독 해제 timerCountRelay.accept(180) // 초기 시간을 180초로 설정 startTimer() // 타이머 다시 시작 }