Skip to content

Commit

Permalink
[#166] refactor: answerViwModel data binding
Browse files Browse the repository at this point in the history
  • Loading branch information
akrudal committed Dec 6, 2023
1 parent 3133e7e commit 958488f
Show file tree
Hide file tree
Showing 12 changed files with 359 additions and 66 deletions.
4 changes: 4 additions & 0 deletions TellingMe/tellingMe.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@
3AEED26329C99F1500D02F3F /* HeadlineLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AEED26229C99F1500D02F3F /* HeadlineLabel.swift */; };
3AEED26529C99F7D00D02F3F /* BodyLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AEED26429C99F7D00D02F3F /* BodyLabel.swift */; };
3AEED26729C99F8800D02F3F /* CaptionLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AEED26629C99F8800D02F3F /* CaptionLabel.swift */; };
3AF19F1B2B20783900AFAE70 /* MModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AF19F1A2B20783900AFAE70 /* MModalView.swift */; };
3AF324B02ABDE9A600995DBE /* OtherFeedbackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AF324AF2ABDE9A600995DBE /* OtherFeedbackView.swift */; };
3AF324B32ABF5B8C00995DBE /* QuestionFeedbackDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AF324B22ABF5B8C00995DBE /* QuestionFeedbackDTO.swift */; };
3AF324B72ABF5BB200995DBE /* QuestionFeedbackAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AF324B62ABF5BB200995DBE /* QuestionFeedbackAPI.swift */; };
Expand Down Expand Up @@ -561,6 +562,7 @@
3AEED26229C99F1500D02F3F /* HeadlineLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineLabel.swift; sourceTree = "<group>"; };
3AEED26429C99F7D00D02F3F /* BodyLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BodyLabel.swift; sourceTree = "<group>"; };
3AEED26629C99F8800D02F3F /* CaptionLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CaptionLabel.swift; sourceTree = "<group>"; };
3AF19F1A2B20783900AFAE70 /* MModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MModalView.swift; sourceTree = "<group>"; };
3AF324AF2ABDE9A600995DBE /* OtherFeedbackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OtherFeedbackView.swift; sourceTree = "<group>"; };
3AF324B22ABF5B8C00995DBE /* QuestionFeedbackDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuestionFeedbackDTO.swift; sourceTree = "<group>"; };
3AF324B62ABF5BB200995DBE /* QuestionFeedbackAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuestionFeedbackAPI.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1819,6 +1821,7 @@
children = (
3AFA371F2A1A5AB0008A5657 /* Modal.storyboard */,
3A1E403A2A1A611800F1F109 /* ModalViewController.swift */,
3AF19F1A2B20783900AFAE70 /* MModalView.swift */,
);
path = modal;
sourceTree = "<group>";
Expand Down Expand Up @@ -2516,6 +2519,7 @@
3A9F319F2AF13BCA004B3416 /* SpecialQuestionView.swift in Sources */,
3A3739C92A13E4F900739543 /* SettingViewModel.swift in Sources */,
3A8FAACB2ACC297D008C8CA3 /* SignUpModel.swift in Sources */,
3AF19F1B2B20783900AFAE70 /* MModalView.swift in Sources */,
58BB76EB2AD80AFA004AF4BE /* Products.swift in Sources */,
3A320F582A73E57E0098E8C9 /* CommunicationList.swift in Sources */,
3AC9D53829D58D8E006A2566 /* DropDownTableViewCell.swift in Sources */,
Expand Down
25 changes: 9 additions & 16 deletions TellingMe/tellingMe/data/answer/API/AnswerAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -134,22 +134,6 @@ struct AnswerAPI: Networkable {
}
}

// static func getAnswerWithId(query: Int) -> Observable<GetAnswerRespose> {
// return Observable.create { observer in
// try makeAuthorizedProvider().requestO(.getAnswerWithId(query: query), dtoType: GetAnswerRespose.self) { result in
// switch result {
// case .success(let response):
// observer.onNext(response)
// observer.onCompleted()
// case .failure(let error):
// observer.onError(APIError.other(error))
// }
// }
//
// return Disposables.create()
// }
// }

static func getAnswerWithId(query: Int) -> Observable<GetAnswerRespose> {
do {
let provider = try makeAuthorizedProvider()
Expand Down Expand Up @@ -182,6 +166,15 @@ struct AnswerAPI: Networkable {
completion(.failure(APIError.other(error)))
}
}

static func registerAnswer(request: RegisterAnswerRequest) -> Observable<Void> {
do {
let provider = try makeAuthorizedProvider()
return provider.request(target: .registerAnswer(request: request))
} catch {
return Observable.error(error)
}
}

static func getAnswerRecord(query: String, completion: @escaping(Result<AnswerRecordResponse?, APIError>) -> Void) {
do {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ extension HeaderViewWithEmotionView {

extension HeaderViewWithEmotionView {
func configure(data: AnswerForAlarmModel) {
guard let emotion = Emotions(intValue: data.emotion) else { return }
let emotion = Emotions(intValue: data.emotion)
emotionImageView.image = UIImage(named: emotion.rawValue)
emotionTitleLabel.text = emotion.stringValue
questionTitleLabel.text = data.question
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,18 @@ final class AnswerBottomView: BBaseView {
private let publicSwitch = UISwitch()
private let registerButton = UIButton()

var countTextObservable: Binder<String?> {
return countTextLabel.rx.text
}

var registerButtonTapObservable: Observable<Void> {
return registerButton.rx.tap.asObservable()
}

var togglePublicSwitch: ControlProperty<Bool> {
return publicSwitch.rx.isOn
}

override init(frame: CGRect) {
super.init(frame: frame)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,19 @@ final class SelectEmotionView: BBaseView {
private let contentView = UIView()
private let titleLabel = UILabel()
private let emotionLabel = UILabel()
let emotionCollectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
private let emotionCollectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
private let buttonStackView = UIStackView()
private let cancelButton = TeritaryTextButton()
private let confirmButton = SecondaryTextButton()

var collectionViewRx: Reactive<UICollectionView> {
return emotionCollectionView.rx
}

var confirmTapObservable: Observable<Void> {
return confirmButton.rx.tap.asObservable()
}

init(viewModel: AnswerViewModel, frame: CGRect) {
self.viewModel = viewModel
super.init(frame: frame)
Expand All @@ -48,13 +56,22 @@ final class SelectEmotionView: BBaseView {
self.selectEmotion(indexPath: indexPath)
})
.disposed(by: disposeBag)

Observable.just(viewModel.emotionList)
.bind(to: emotionCollectionView.rx.items(cellIdentifier: EmotionCollectionViewCell.id, cellType: EmotionCollectionViewCell.self)) { (row, emotion, cell) in
cell.setAlpha()
cell.setCell(with: emotion.rawValue)
}
.disposed(by: disposeBag)
}

override func setStyles() {
backgroundColor = .AlphaBlackColor

contentView.do {
$0.backgroundColor = .Side100
$0.layer.cornerRadius = 28
$0.setTopCornerRadius()
}

titleLabel.do {
Expand All @@ -69,6 +86,13 @@ final class SelectEmotionView: BBaseView {
$0.text = AnswerStrings.emotionPlaceHolder.stringValue
}

emotionCollectionView.rx.itemSelected
.bind(onNext: { [weak self] indexPath in
guard let self else { return }
self.viewModel.inputs.selectEmotion(indexPath: indexPath)
})
.disposed(by: disposeBag)

emotionCollectionView.do {
$0.backgroundColor = .Side100
$0.register(EmotionCollectionViewCell.self, forCellWithReuseIdentifier: EmotionCollectionViewCell.id)
Expand Down Expand Up @@ -134,7 +158,7 @@ extension SelectEmotionView {
if let cell = emotionCollectionView.cellForItem(at: indexPath) as? EmotionCollectionViewCell {
cell.setOrigin()
}
self.emotionLabel.text = viewModel.emotionList[indexPath.row].stringValue
self.emotionLabel.text = viewModel.emotionList[indexPath.row - 1].stringValue
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class AAnswerViewController: BaseViewController {
private let answerBottomView = AnswerBottomView()
private let emotionView = EmotionView()
private let emotionSheetView: SelectEmotionView
private let backModal = MModalView()

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
emotionSheetView = SelectEmotionView(viewModel: viewModel, frame: .zero)
Expand All @@ -38,46 +39,104 @@ class AAnswerViewController: BaseViewController {

}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
self.view.endEditing(true)
}

override func bindViewModel() {
backHeaderView.backButtonTapObservable
.bind(onNext: {
self.navigationController?.popViewController(animated: true)
.bind(onNext: { [weak self] _ in
guard let self else { return }
showBackModal()
})
.disposed(by: disposeBag)

backHeaderView.rightButtonTapObservable
.bind(onNext: {
.bind(onNext: { [weak self] _ in
guard let self else { return }
self.toggleQuestion()
})
.disposed(by: disposeBag)

answerBottomView.registerButtonTapObservable
.bind(onNext: {
self.showEmotionSheetView()
backModal.leftButtonTapObservable
.subscribe(onNext: { [weak self] _ in
guard let self else { return }
backModal.isHidden = true
})
.disposed(by: disposeBag)

backModal.rightButtonTapObservable
.subscribe(onNext: { [weak self] _ in
guard let self else { return }
self.navigationController?.popViewController(animated: true)
})
.disposed(by: disposeBag)

emotionSheetView.emotionCollectionView.rx.setDelegate(self)
answerBottomView.registerButtonTapObservable
.bind(to: viewModel.inputs.completeButtonTapped)
.disposed(by: disposeBag)

emotionSheetView.emotionCollectionView.rx.itemSelected
.bind(onNext: { [weak self] indexPath in
guard let self = self else { return }
self.viewModel.inputs.selectEmotion(indexPath: indexPath)
})
answerBottomView.togglePublicSwitch
.bind(to: viewModel.inputs.toggleSwitch)
.disposed(by: disposeBag)

emotionSheetView.collectionViewRx.setDelegate(self)
.disposed(by: disposeBag)

emotionSheetView.confirmTapObservable
.bind(to: viewModel.inputs.registerButtonTapped)
.disposed(by: disposeBag)

answerTextView.textViewRxText
.orEmpty
.bind(to: viewModel.inputs.inputText)
.disposed(by: disposeBag)

viewModel.outputs.questionSubject
.bind(onNext: { question in
.bind(onNext: { [weak self] question in
guard let self else { return }
self.questionView.setQuestion(data: question)
})
.disposed(by: disposeBag)

Observable.just(viewModel.emotionList)
.bind(to: emotionSheetView.emotionCollectionView.rx.items(cellIdentifier: EmotionCollectionViewCell.id, cellType: EmotionCollectionViewCell.self)) { (row, emotion, cell) in
cell.setAlpha()
cell.setCell(with: emotion.rawValue)
}
viewModel.outputs.showEmotionSubject
.bind(onNext: { [weak self] _ in
guard let self else { return }
self.view.endEditing(true)
self.showEmotionSheetView()
})
.disposed(by: disposeBag)

viewModel.outputs.toastSubject
.bind(onNext: { [weak self] message in
guard let self else { return }
self.view.endEditing(true)
self.showToast(message: message)
})
.disposed(by: disposeBag)

viewModel.outputs.countTextRelay
.bind(to: answerBottomView.countTextObservable)
.disposed(by: disposeBag)

viewModel.outputs.inputTextRelay
.bind(to: answerTextView.textViewRxText)
.disposed(by: disposeBag)

viewModel.outputs.selectedEmotionIndexSubject
.bind(onNext: { [weak self] indexPath in
guard let self else { return }
self.emotionView.isHidden = false
self.emotionView.setEmotion(emotion: Emotions(intValue: indexPath.row + 1))
})
.disposed(by: disposeBag)

viewModel.outputs.successRegisterSubject
.bind(onNext: { [weak self] _ in
guard let self else { return }
self.navigationController?.popViewController(animated: true)
})
.disposed(by: disposeBag)
}

Expand All @@ -86,6 +145,16 @@ class AAnswerViewController: BaseViewController {
$0.setRightButton(image: UIImage(systemName: "chevron.down")!)
}

backModal.do {
$0.isHidden = true
$0.setModalTitle(title: "작성을 취소하고 나가시겠어요?", subTitle: "작성한 답변은 초기화돼요")
$0.setModalButton(leftButtonTitle: "아니요", rightButtonTitle: "나갈래요")
}

emotionView.do {
$0.isHidden = true
}

seperateLine.do {
$0.backgroundColor = .Side300
}
Expand All @@ -97,14 +166,19 @@ class AAnswerViewController: BaseViewController {

override func setLayout() {
view.addSubviews(backHeaderView, questionView, seperateLine,
answerTextView, answerBottomView, emotionSheetView)
answerTextView, answerBottomView, emotionSheetView,
backModal)
backHeaderView.addSubview(emotionView)

backHeaderView.snp.makeConstraints {
$0.horizontalEdges.top.equalTo(view.safeAreaLayoutGuide)
$0.height.equalTo(77)
}

backModal.snp.makeConstraints {
$0.edges.equalToSuperview()
}

emotionView.snp.makeConstraints {
$0.centerX.equalToSuperview()
$0.height.equalTo(44)
Expand All @@ -130,7 +204,7 @@ class AAnswerViewController: BaseViewController {

answerBottomView.snp.makeConstraints {
$0.top.equalTo(answerTextView.snp.bottom)
$0.bottom.equalTo(view.keyboardLayoutGuide).inset(34)
$0.bottom.equalTo(view.keyboardLayoutGuide.snp.top)
$0.horizontalEdges.equalToSuperview()
$0.height.equalTo(72)
}
Expand Down Expand Up @@ -180,6 +254,11 @@ extension AAnswerViewController {
emotionSheetView.showOpenAnimation()
}

private func showBackModal() {
backModal.isHidden = false
backModal.showOpenAnimation()
}

private func setPremium() {
backHeaderView.do {
$0.setRightSecondButton(image: UIImage(named: "Switch"))
Expand Down
Loading

0 comments on commit 958488f

Please sign in to comment.