-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ Feat: #40 - 비밀번호 찾기 전체 UI제작 (API 연결 제외)
- Loading branch information
Showing
7 changed files
with
548 additions
and
25 deletions.
There are no files selected for viewing
151 changes: 151 additions & 0 deletions
151
...gnIn/FindPassword/FindPasswordScrollPages/ConfirmCertifyCode/ConfirmCertifyCodeView.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
// | ||
// ConfirmCertifyCodeView.swift | ||
// CMC | ||
// | ||
// Created by Siri on 11/15/23. | ||
// Copyright © 2023 com.softsquared.cmc. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
import RxCocoa | ||
import RxGesture | ||
import RxSwift | ||
|
||
import DesignSystem | ||
import SnapKit | ||
|
||
import UIKit | ||
|
||
final class ConfirmCertifyCodeView: BaseView { | ||
|
||
// MARK: - UI | ||
|
||
private lazy var titleLabel: UILabel = { | ||
let label = UILabel() | ||
label.text = "비밀번호 재설정" | ||
label.font = DesignSystemFontFamily.Pretendard.bold.font(size: 26) | ||
label.textColor = DesignSystemAsset.gray50.color | ||
label.translatesAutoresizingMaskIntoConstraints = false | ||
return label | ||
}() | ||
|
||
private lazy var subTitle: UILabel = { | ||
let label = UILabel() | ||
label.text = "이메일로 인증번호를 전송했어요\n인증번호를 입력해주세요!" | ||
label.font = DesignSystemFontFamily.Pretendard.medium.font(size: 14) | ||
label.numberOfLines = 2 | ||
label.textColor = DesignSystemAsset.gray500.color | ||
label.translatesAutoresizingMaskIntoConstraints = false | ||
return label | ||
}() | ||
|
||
private lazy var certifyCodeTextField: CMCTextField_Timer = { | ||
let textField = CMCTextField_Timer( | ||
placeHolder: "인증번호를 입력해주세요", | ||
textFieldSubTitle: "인증번호", | ||
buttonTitle: "재요청", | ||
keyboardType: .numberPad | ||
) | ||
textField.translatesAutoresizingMaskIntoConstraints = false | ||
return textField | ||
}() | ||
|
||
|
||
// MARK: - Properties | ||
private var viewModel: ConfirmCertifyCodeViewModel | ||
private var parentViewModel: FindPasswordViewModel | ||
|
||
// MARK: - Initializers | ||
init( | ||
viewModel: ConfirmCertifyCodeViewModel, | ||
parentViewModel: FindPasswordViewModel | ||
) { | ||
self.viewModel = viewModel | ||
self.parentViewModel = parentViewModel | ||
super.init(frame: .zero) | ||
self.backgroundColor = CMCAsset.background.color | ||
} | ||
|
||
|
||
required init?(coder: NSCoder) { | ||
fatalError("init(coder:) has not been implemented") | ||
} | ||
|
||
// MARK: - LifeCycle | ||
// MARK: - Methods | ||
|
||
override func setAddSubView() { | ||
addSubview(titleLabel) | ||
addSubview(subTitle) | ||
addSubview(certifyCodeTextField) | ||
} | ||
|
||
override func setConstraint() { | ||
|
||
titleLabel.snp.makeConstraints{ titleLabel in | ||
titleLabel.top.equalToSuperview().offset(30) | ||
titleLabel.leading.equalToSuperview().offset(24) | ||
} | ||
|
||
subTitle.snp.makeConstraints { | ||
$0.top.equalTo(titleLabel.snp.bottom).offset(24) | ||
$0.leading.equalToSuperview().offset(24) | ||
} | ||
|
||
certifyCodeTextField.snp.makeConstraints { | ||
$0.top.equalTo(subTitle.snp.bottom).offset(30) | ||
$0.leading.equalToSuperview().offset(24) | ||
$0.trailing.equalToSuperview().offset(-24) | ||
$0.height.equalTo(74) | ||
} | ||
|
||
} | ||
|
||
override func bind() { | ||
|
||
self.rx.tapGesture() | ||
.when(.recognized) | ||
.withUnretained(self) | ||
.subscribe(onNext: { owner, gesture in | ||
let location = gesture.location(in: owner) | ||
if !owner.isPointInsideTextField(location) { | ||
owner.endEditing(true) | ||
} | ||
}) | ||
.disposed(by: disposeBag) | ||
|
||
|
||
let input = ConfirmCertifyCodeViewModel.Input( | ||
nowPage: parentViewModel.pageAppeared.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() | ||
} | ||
}) | ||
.disposed(by: disposeBag) | ||
|
||
output.nextAvailable | ||
.withUnretained(self) | ||
.subscribe(onNext: { owner, isAvailable in | ||
owner.parentViewModel.readyForNextButton.accept(isAvailable) | ||
}) | ||
.disposed(by: disposeBag) | ||
} | ||
} | ||
|
||
extension ConfirmCertifyCodeView { | ||
fileprivate func isPointInsideTextField(_ point: CGPoint) -> Bool { | ||
// 모든 텍스트 필드를 순회하면서 탭된 위치가 텍스트 필드 내부인지 확인합니다. | ||
let textFields = [certifyCodeTextField] | ||
return textFields.contains(where: { $0.frame.contains(point) }) | ||
} | ||
} |
68 changes: 68 additions & 0 deletions
68
...FindPassword/FindPasswordScrollPages/ConfirmCertifyCode/ConfirmCertifyCodeViewModel.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// | ||
// ConfirmCertifyCodeViewModel.swift | ||
// CMC | ||
// | ||
// Created by Siri on 11/15/23. | ||
// Copyright © 2023 com.softsquared.cmc. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
import UIKit | ||
|
||
import RxCocoa | ||
import RxSwift | ||
|
||
|
||
final class ConfirmCertifyCodeViewModel: ViewModelType { | ||
|
||
struct Input { | ||
let nowPage: Observable<Int> | ||
let certifiedCode: Observable<String> | ||
let reSendButtonTapped: Observable<Void> | ||
} | ||
|
||
struct Output { | ||
let startTimer: Observable<Bool> | ||
let nextAvailable: Observable<Bool> | ||
} | ||
|
||
var disposeBag: DisposeBag = DisposeBag() | ||
private let usecase: AuthUsecase | ||
|
||
private let startTimer = BehaviorRelay<Bool>(value: false) | ||
private let nextAvailable = BehaviorRelay<Bool>(value: false) | ||
|
||
init( | ||
usecase: AuthUsecase | ||
) { | ||
self.usecase = usecase | ||
} | ||
|
||
|
||
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 | ||
code.count >= 6 ? owner.nextAvailable.accept(true) : owner.nextAvailable.accept(false) | ||
}) | ||
.disposed(by: disposeBag) | ||
|
||
return Output( | ||
startTimer: startTimer.asObservable(), | ||
nextAvailable: nextAvailable.asObservable() | ||
) | ||
|
||
} | ||
|
||
|
||
} |
Oops, something went wrong.