From 240cc39b252bb39f6edaf5abb9cb066216a2059b Mon Sep 17 00:00:00 2001 From: gom1n Date: Wed, 31 May 2023 07:25:19 +0900 Subject: [PATCH] =?UTF-8?q?[refactor]=20=EA=B8=B0=EB=A1=9D=ED=83=AD=20&=20?= =?UTF-8?q?=ED=9A=8C=EA=B3=A0=ED=83=AD=20=EC=83=81=EC=86=8D=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- POME.xcodeproj/project.pbxproj | 8 +- .../ViewModel/GoalWithRecordViewModel.swift | 123 ++++++++++++++++++ .../ViewModel/Record/RecordTabViewModel.swift | 2 +- .../ViewModel/Review/ReviewViewModel.swift | 4 - 4 files changed, 128 insertions(+), 9 deletions(-) create mode 100644 POME/Presentation/ViewModel/GoalWithRecordViewModel.swift diff --git a/POME.xcodeproj/project.pbxproj b/POME.xcodeproj/project.pbxproj index 4b83962..0da4159 100644 --- a/POME.xcodeproj/project.pbxproj +++ b/POME.xcodeproj/project.pbxproj @@ -39,7 +39,7 @@ 23431C322A24293500571286 /* DeleteGoalUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23431C312A24293500571286 /* DeleteGoalUseCase.swift */; }; 23431C342A242B1D00571286 /* GetRecordsOfGoalInRecordTabUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23431C332A242B1D00571286 /* GetRecordsOfGoalInRecordTabUseCase.swift */; }; 23431C362A242C8B00571286 /* GetNoSecondEmotionRecordsUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23431C352A242C8B00571286 /* GetNoSecondEmotionRecordsUseCase.swift */; }; - 2343FB032A269F7600820625 /* GoalWithRecordViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2343FB022A269F7600820625 /* GoalWithRecordViewModel.swift */; }; + 2343FB052A26AD7200820625 /* GoalWithRecordViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2343FB042A26AD7200820625 /* GoalWithRecordViewModel.swift */; }; 2345E1C429818848003185E0 /* BaseResponseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2345E1C329818848003185E0 /* BaseResponseModel.swift */; }; 2345E1C829819471003185E0 /* UserRequestModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2345E1C729819471003185E0 /* UserRequestModel.swift */; }; 2345E1CA2981947A003185E0 /* UserResponseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2345E1C92981947A003185E0 /* UserResponseModel.swift */; }; @@ -328,7 +328,7 @@ 23431C312A24293500571286 /* DeleteGoalUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteGoalUseCase.swift; sourceTree = ""; }; 23431C332A242B1D00571286 /* GetRecordsOfGoalInRecordTabUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetRecordsOfGoalInRecordTabUseCase.swift; sourceTree = ""; }; 23431C352A242C8B00571286 /* GetNoSecondEmotionRecordsUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetNoSecondEmotionRecordsUseCase.swift; sourceTree = ""; }; - 2343FB022A269F7600820625 /* GoalWithRecordViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoalWithRecordViewModel.swift; sourceTree = ""; }; + 2343FB042A26AD7200820625 /* GoalWithRecordViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoalWithRecordViewModel.swift; sourceTree = ""; }; 2345E1C329818848003185E0 /* BaseResponseModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseResponseModel.swift; sourceTree = ""; }; 2345E1C729819471003185E0 /* UserRequestModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserRequestModel.swift; sourceTree = ""; }; 2345E1C92981947A003185E0 /* UserResponseModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserResponseModel.swift; sourceTree = ""; }; @@ -1588,7 +1588,7 @@ EE7D35DC29D5A16300D2AD60 /* Authentication */, EE7D35DE29D5A16300D2AD60 /* Review */, EE7D35E029D5A16300D2AD60 /* Goal */, - 2343FB022A269F7600820625 /* GoalWithRecordViewModel.swift */, + 2343FB042A26AD7200820625 /* GoalWithRecordViewModel.swift */, ); path = ViewModel; sourceTree = ""; @@ -2281,7 +2281,7 @@ 2375E4892A20397400843056 /* MyPageViewModel.swift in Sources */, 5724EC84291B29A700DC529B /* EmojiFloatingCollectionViewCell.swift in Sources */, EE38758029D917B900A26AD5 /* TextConverter.swift in Sources */, - 2343FB032A269F7600820625 /* GoalWithRecordViewModel.swift in Sources */, + 2343FB052A26AD7200820625 /* GoalWithRecordViewModel.swift in Sources */, EE7D35EC29D5A16300D2AD60 /* GenerateGoalDateViewModel.swift in Sources */, 57543B7C2951BF5300A409E3 /* CalendarSheetCollectionViewCell.swift in Sources */, 23F57834292D5460002DD28E /* SettingViewController.swift in Sources */, diff --git a/POME/Presentation/ViewModel/GoalWithRecordViewModel.swift b/POME/Presentation/ViewModel/GoalWithRecordViewModel.swift new file mode 100644 index 0000000..f856e2c --- /dev/null +++ b/POME/Presentation/ViewModel/GoalWithRecordViewModel.swift @@ -0,0 +1,123 @@ +// +// GoalWithRecordViewModel.swift +// POME +// +// Created by gomin on 2023/05/31. +// + +import Foundation +import RxSwift +import RxCocoa + +protocol ModifyRecordInterface { + var modifyRecordSubject: PublishSubject { get } + func modifyRecord(_ record: RecordResponseModel, index: Int) +} + +protocol DeleteRecord{ + var deleteRecordSubject: PublishSubject { get } + func deleteRecord(index: Int) +} + +protocol PageableInterface{ + var hasNextPage: Bool { get } +} + +protocol GoalWithRecordViewModelInterface: BaseViewModel, ModifyRecordInterface { + var goals: [GoalResponseModel] { get } + var records: [RecordResponseModel] { get } +} + +class GoalWithRecordViewModel: GoalWithRecordViewModelInterface, DeleteRecord{ + + private let getGoalsUseCase: GetGoalUseCaseInterface + private let deleteRecordUseCase: DeleteRecordUseCaseInterface + + init(getGoalsUseCase: GetGoalUseCaseInterface = GetGoalUseCase(), + deleteRecordUseCase: DeleteRecordUseCaseInterface = DeleteRecordUseCase()){ + self.getGoalsUseCase = getGoalsUseCase + self.deleteRecordUseCase = deleteRecordUseCase + } + + var hasNextPage: Bool = false + var goals = [GoalResponseModel]() + var records = [RecordResponseModel]() + + let changeGoalSelect = PublishSubject() + let reloadTableView = PublishRelay() + let deleteRecordSubject = PublishSubject() + let modifyRecordSubject = PublishSubject() + + var page: Int = 0 + var selectedGoalIndex: Int = 0 + + let disposeBag = DisposeBag() + + struct Input{ + let selectedGoalIndex: Observable + } + + struct Output{} + + @discardableResult + func transform(_ input: Input) -> Output{ + + input.selectedGoalIndex + .subscribe{ [weak self] in + self?.selectedGoalIndex = $0 + self?.initializeStateAndRequestRecord() + }.disposed(by: disposeBag) + + return Output() + } + + func refreshData(){ + getGoalsUseCase.execute() + .subscribe(onNext: { [weak self] goals in + self?.goals = goals.filter{ !$0.isEnd } + self?.initializeStateAndRequestRecord() + }).disposed(by: disposeBag) + } + + func initializeStateAndRequestRecord(){ + hasNextPage = false + page = 0 + canRequestRecord() + } + + private func canRequestRecord(){ + //goal이 존재할 때만 기록 조회 요청 + if goals.isEmpty { + records = [] + reloadTableView.accept(Void()) + } else if selectedGoalIndex >= goals.count { //현재 선택 중인 목표가 삭제되었을 경우, 목표 변경 VC으로 전달 + changeGoalSelect.onNext(Void()) + } else { + requestRecords() + } + } + + func requestRecords(){ + + } + + func requestNextPage(){ + page += 1 + requestRecords() + } + + func deleteRecord(index: Int) { + deleteRecordUseCase.execute(requestValue: DeleteRecordRequestModel(recordId: records[index].id)) + .subscribe{ [weak self] in + if $0 == .success { + self?.records.remove(at: index) + self?.deleteRecordSubject.onNext(index) + } + }.disposed(by: disposeBag) + } + + func modifyRecord(_ record: RecordResponseModel, index: Int){ + records[index] = record + modifyRecordSubject.onNext(index) + } +} diff --git a/POME/Presentation/ViewModel/Record/RecordTabViewModel.swift b/POME/Presentation/ViewModel/Record/RecordTabViewModel.swift index 2076b7f..bf86038 100644 --- a/POME/Presentation/ViewModel/Record/RecordTabViewModel.swift +++ b/POME/Presentation/ViewModel/Record/RecordTabViewModel.swift @@ -26,7 +26,7 @@ protocol NoSecondEmotionRecordViewModelInterface { // var records: [RecordResponseModel] { get } //} -final class RecordTabViewModel: GoalWithRecordViewModel, NoSecondEmotionViewModelInterface { +final class RecordTabViewModel: GoalWithRecordViewModel, NoSecondEmotionRecordViewModelInterface { internal var noSecondEmotionRecords: Int = 0 diff --git a/POME/Presentation/ViewModel/Review/ReviewViewModel.swift b/POME/Presentation/ViewModel/Review/ReviewViewModel.swift index 591c91d..6e8fdd4 100644 --- a/POME/Presentation/ViewModel/Review/ReviewViewModel.swift +++ b/POME/Presentation/ViewModel/Review/ReviewViewModel.swift @@ -82,8 +82,4 @@ final class ReviewViewModel: GoalWithRecordViewModel { }).disposed(by: disposeBag) } - func requestNextPage(){ - page += 1 - requestRecords() - } }