diff --git a/WSSiOS/WSSiOS/Network/Auth/AuthService.swift b/WSSiOS/WSSiOS/Network/Auth/AuthService.swift index 7a67c62ff..f9b405461 100644 --- a/WSSiOS/WSSiOS/Network/Auth/AuthService.swift +++ b/WSSiOS/WSSiOS/Network/Auth/AuthService.swift @@ -10,8 +10,7 @@ import Foundation import RxSwift protocol AuthService { - func loginWithApple(authorizationCode: String, - idToken: String) -> Single + func loginWithApple(appleLoginData: AppleLoginRequest) -> Single func loginWithKakao(_ kakaoAccessToken: String) -> Single func reissueToken() -> Single func postWithdrawId(withdrawData: WithdrawRequest) -> Single @@ -21,8 +20,8 @@ protocol AuthService { final class DefaultAuthService: NSObject, Networking, AuthService { - func loginWithApple(authorizationCode: String, idToken: String) -> RxSwift.Single { - guard let appleLoginBody = try? JSONEncoder().encode(AppleLoginBody(authorizationCode: authorizationCode, idToken: idToken)) else { + func loginWithApple(appleLoginData: AppleLoginRequest) -> RxSwift.Single { + guard let appleLoginBody = try? JSONEncoder().encode(appleLoginData) else { return Single.error(NetworkServiceError.invalidRequestError) } diff --git a/WSSiOS/WSSiOS/Network/Keyword/KeywordService.swift b/WSSiOS/WSSiOS/Network/Keyword/KeywordService.swift index 15fffd35a..d9c926e64 100644 --- a/WSSiOS/WSSiOS/Network/Keyword/KeywordService.swift +++ b/WSSiOS/WSSiOS/Network/Keyword/KeywordService.swift @@ -10,11 +10,11 @@ import Foundation import RxSwift protocol KeywordService { - func searchKeyword(query: String?) -> Single + func searchKeyword(query: String?) -> Single } final class DefaultKeywordService: NSObject, Networking, KeywordService { - func searchKeyword(query: String? = nil) -> RxSwift.Single { + func searchKeyword(query: String? = nil) -> RxSwift.Single { var searchKeywordQueryItems: [URLQueryItem] = [] if let query { @@ -32,7 +32,7 @@ final class DefaultKeywordService: NSObject, Networking, KeywordService { return tokenCheckURLSession.rx.data(request: request) .map { try self.decode(data: $0, - to: SearchKeywordResult.self) } + to: SearchKeywordResponse.self) } .asSingle() } catch { diff --git a/WSSiOS/WSSiOS/Network/NovelReview/NovelReviewService.swift b/WSSiOS/WSSiOS/Network/NovelReview/NovelReviewService.swift index 7f60c6f2c..05e92d7cb 100644 --- a/WSSiOS/WSSiOS/Network/NovelReview/NovelReviewService.swift +++ b/WSSiOS/WSSiOS/Network/NovelReview/NovelReviewService.swift @@ -10,32 +10,14 @@ import Foundation import RxSwift protocol NovelReviewService { - func postNovelReview(novelId: Int, - userNovelRating: Float, - status: String, - startDate: String?, - endDate: String?, - attractivePoints: [String], - keywordIds: [Int]) -> Single - func putNovelReview(novelId: Int, - userNovelRating: Float, - status: String, - startDate: String?, - endDate: String?, - attractivePoints: [String], - keywordIds: [Int]) -> Single - func getNovelReview(novelId: Int) -> Single + func postNovelReview(novelReviewData: PostNovelReviewRequest) -> Single + func putNovelReview(novelId: Int, novelReviewData: PutNovelReviewRequest) -> Single + func getNovelReview(novelId: Int) -> Single } final class DefaultNovelReviewService: NSObject, Networking, NovelReviewService { - func postNovelReview(novelId: Int, - userNovelRating: Float, - status: String, - startDate: String?, - endDate: String?, - attractivePoints: [String], - keywordIds: [Int]) -> Single { - guard let novelReviewContentData = try? JSONEncoder().encode(PostNovelReviewContent(novelId: novelId, userNovelRating: userNovelRating, status: status, startDate: startDate, endDate: endDate, attractivePoints: attractivePoints, keywordIds: keywordIds)) else { + func postNovelReview(novelReviewData: PostNovelReviewRequest) -> Single { + guard let novelReviewContentData = try? JSONEncoder().encode(novelReviewData) else { return Single.error(NetworkServiceError.invalidRequestError) } @@ -55,14 +37,8 @@ final class DefaultNovelReviewService: NSObject, Networking, NovelReviewService } } - func putNovelReview(novelId: Int, - userNovelRating: Float, - status: String, - startDate: String?, - endDate: String?, - attractivePoints: [String], - keywordIds: [Int]) -> Single { - guard let novelReviewContentData = try? JSONEncoder().encode(PutNovelReviewContent(userNovelRating: userNovelRating, status: status, startDate: startDate, endDate: endDate, attractivePoints: attractivePoints, keywordIds: keywordIds)) else { + func putNovelReview(novelId: Int, novelReviewData: PutNovelReviewRequest) -> Single { + guard let novelReviewContentData = try? JSONEncoder().encode(novelReviewData) else { return Single.error(NetworkServiceError.invalidRequestError) } @@ -82,7 +58,7 @@ final class DefaultNovelReviewService: NSObject, Networking, NovelReviewService } } - func getNovelReview(novelId: Int) -> Single { + func getNovelReview(novelId: Int) -> Single { do { let request = try makeHTTPRequest(method: .get, path: URLs.NovelReview.getNovelReview(novelId: novelId), @@ -93,7 +69,7 @@ final class DefaultNovelReviewService: NSObject, Networking, NovelReviewService return tokenCheckURLSession.rx.data(request: request) .map { try self.decode(data: $0, - to: NovelReviewResult.self) } + to: NovelReviewResponse.self) } .asSingle() } catch { diff --git a/WSSiOS/WSSiOS/Source/Data/DTO/AuthResult.swift b/WSSiOS/WSSiOS/Source/Data/DTO/Auth.swift similarity index 91% rename from WSSiOS/WSSiOS/Source/Data/DTO/AuthResult.swift rename to WSSiOS/WSSiOS/Source/Data/DTO/Auth.swift index ca4df25ea..b309a99a6 100644 --- a/WSSiOS/WSSiOS/Source/Data/DTO/AuthResult.swift +++ b/WSSiOS/WSSiOS/Source/Data/DTO/Auth.swift @@ -1,5 +1,5 @@ // -// AuthResult.swift +// Auth.swift // WSSiOS // // Created by Hyowon Jeon on 11/2/24. @@ -7,7 +7,7 @@ import Foundation -struct AppleLoginBody: Codable { +struct AppleLoginRequest: Encodable { let authorizationCode: String let idToken: String } diff --git a/WSSiOS/WSSiOS/Source/Data/DTO/NovelReviewResult.swift b/WSSiOS/WSSiOS/Source/Data/DTO/NovelReviewResponse.swift similarity index 84% rename from WSSiOS/WSSiOS/Source/Data/DTO/NovelReviewResult.swift rename to WSSiOS/WSSiOS/Source/Data/DTO/NovelReviewResponse.swift index 88aa3b9b0..48cda9d3b 100644 --- a/WSSiOS/WSSiOS/Source/Data/DTO/NovelReviewResult.swift +++ b/WSSiOS/WSSiOS/Source/Data/DTO/NovelReviewResponse.swift @@ -7,7 +7,7 @@ import Foundation -struct NovelReviewResult: Codable { +struct NovelReviewResponse: Decodable { let novelTitle: String let status: String? let startDate: String? @@ -17,7 +17,7 @@ struct NovelReviewResult: Codable { let keywords: [KeywordData] } -struct PostNovelReviewContent: Codable { +struct PostNovelReviewRequest: Encodable { let novelId: Int let userNovelRating: Float let status: String @@ -27,7 +27,7 @@ struct PostNovelReviewContent: Codable { let keywordIds: [Int] } -struct PutNovelReviewContent: Codable { +struct PutNovelReviewRequest: Encodable { let userNovelRating: Float let status: String let startDate: String? diff --git a/WSSiOS/WSSiOS/Source/Data/DTO/SearchKeywordResult.swift b/WSSiOS/WSSiOS/Source/Data/DTO/SearchKeywordResponse.swift similarity index 81% rename from WSSiOS/WSSiOS/Source/Data/DTO/SearchKeywordResult.swift rename to WSSiOS/WSSiOS/Source/Data/DTO/SearchKeywordResponse.swift index 7bbafbead..6c7f3c43c 100644 --- a/WSSiOS/WSSiOS/Source/Data/DTO/SearchKeywordResult.swift +++ b/WSSiOS/WSSiOS/Source/Data/DTO/SearchKeywordResponse.swift @@ -1,5 +1,5 @@ // -// SearchKeywordResult.swift +// SearchKeywordResponse.swift // WSSiOS // // Created by Hyowon Jeon on 9/27/24. @@ -7,7 +7,7 @@ import Foundation -struct SearchKeywordResult: Codable { +struct SearchKeywordResponse: Decodable { let categories: [KeywordCategory] } diff --git a/WSSiOS/WSSiOS/Source/Data/Entity/AuthEntity.swift b/WSSiOS/WSSiOS/Source/Data/Entity/AuthEntity.swift new file mode 100644 index 000000000..ba15fc91e --- /dev/null +++ b/WSSiOS/WSSiOS/Source/Data/Entity/AuthEntity.swift @@ -0,0 +1,36 @@ +// +// AuthEntity.swift +// WSSiOS +// +// Created by Hyowon Jeon on 3/23/25. +// + +import Foundation + +struct AppleLoginEntity { + let authorizationCode: Data + let idToken: Data +} + +extension AppleLoginEntity { + func toDTO() -> AppleLoginRequest { + let authorizationCode = String(data: authorizationCode, encoding: String.Encoding.utf8)! + let idToken = String(data: idToken, encoding: String.Encoding.utf8)! + return AppleLoginRequest(authorizationCode: authorizationCode, + idToken: idToken) + } +} + +struct LoginEntity { + let Authorization: String + let refreshToken: String + let isRegister: Bool +} + +extension LoginResponse { + func toEntity() -> LoginEntity { + return LoginEntity(Authorization: self.Authorization, + refreshToken: self.refreshToken, + isRegister: self.isRegister) + } +} diff --git a/WSSiOS/WSSiOS/Source/Data/Entity/NovelReviewEntity.swift b/WSSiOS/WSSiOS/Source/Data/Entity/NovelReviewEntity.swift new file mode 100644 index 000000000..911633a73 --- /dev/null +++ b/WSSiOS/WSSiOS/Source/Data/Entity/NovelReviewEntity.swift @@ -0,0 +1,86 @@ +// +// NovelReviewEntity.swift +// WSSiOS +// +// Created by Hyowon Jeon on 3/23/25. +// + +import Foundation + +struct NovelReviewEntity { + let novelTitle: String + let status: ReadStatus? + let startDate: Date? + let endDate: Date? + let userNovelRating: Float + let attractivePoints: [AttractivePoint?] + let keywords: [KeywordData] +} + +extension NovelReviewResponse { + func toEntity() -> NovelReviewEntity { + let dateFormatter = DateFormatter().then { + $0.dateFormat = "yyyy-MM-dd" + $0.timeZone = TimeZone(identifier: "ko_KR") + } + + let startDate = self.startDate.flatMap { dateFormatter.date(from: $0) } + let endDate = self.endDate.flatMap { dateFormatter.date(from: $0) } + let readStatus = self.status.flatMap { ReadStatus(rawValue: $0) } + let attractivePoints = self.attractivePoints.map { AttractivePoint(rawValue: $0) } + + return NovelReviewEntity(novelTitle: self.novelTitle, + status: readStatus, + startDate: startDate, + endDate: endDate, + userNovelRating: self.userNovelRating, + attractivePoints: attractivePoints, + keywords: self.keywords) + } +} + +struct PostNovelReviewEntity { + let novelId: Int + let userNovelRating: Float + let status: ReadStatus + let startDate: String? + let endDate: String? + let attractivePoints: [AttractivePoint?] + let keywordIds: [Int] +} + +extension PostNovelReviewEntity { + func toDTO() -> PostNovelReviewRequest { + let statusString = self.status.rawValue + let attractivePoints = self.attractivePoints.compactMap { $0?.rawValue } + return PostNovelReviewRequest(novelId: self.novelId, + userNovelRating: self.userNovelRating, + status: statusString, + startDate: self.startDate, + endDate: self.endDate, + attractivePoints: attractivePoints, + keywordIds: self.keywordIds) + } +} + +struct PutNovelReviewEntity { + let userNovelRating: Float + let status: ReadStatus + let startDate: String? + let endDate: String? + let attractivePoints: [AttractivePoint?] + let keywordIds: [Int] +} + +extension PutNovelReviewEntity { + func toDTO() -> PutNovelReviewRequest { + let statusString = self.status.rawValue + let attractivePoints = self.attractivePoints.compactMap { $0?.rawValue } + return PutNovelReviewRequest(userNovelRating: self.userNovelRating, + status: statusString, + startDate: self.startDate, + endDate: self.endDate, + attractivePoints: attractivePoints, + keywordIds: self.keywordIds) + } +} diff --git a/WSSiOS/WSSiOS/Source/Data/Entity/SearchKeywordEntity.swift b/WSSiOS/WSSiOS/Source/Data/Entity/SearchKeywordEntity.swift new file mode 100644 index 000000000..f733ca264 --- /dev/null +++ b/WSSiOS/WSSiOS/Source/Data/Entity/SearchKeywordEntity.swift @@ -0,0 +1,18 @@ +// +// SearchKeywordEntity.swift +// WSSiOS +// +// Created by Hyowon Jeon on 3/23/25. +// + +import Foundation + +struct SearchKeywordEntity { + let categories: [KeywordCategory] +} + +extension SearchKeywordResponse { + func toEntity() -> SearchKeywordEntity { + return SearchKeywordEntity(categories: self.categories) + } +} diff --git a/WSSiOS/WSSiOS/Source/Data/Repository/AuthRepository.swift b/WSSiOS/WSSiOS/Source/Data/Repository/AuthRepository.swift index 08f4f15bb..7e3c87498 100644 --- a/WSSiOS/WSSiOS/Source/Data/Repository/AuthRepository.swift +++ b/WSSiOS/WSSiOS/Source/Data/Repository/AuthRepository.swift @@ -12,8 +12,8 @@ import RxKakaoSDKAuth import RxSwift protocol AuthRepository { - func loginWithApple(authorizationCode: String, idToken: String) -> Observable - func loginWithKakao(_ kakaoAccessToken: OAuthToken) -> Single + func loginWithApple(appleLoginData: AppleLoginEntity) -> Observable + func loginWithKakao(_ kakaoAccessToken: OAuthToken) -> Single func postWithdrawId(withdrawData: WithdrawRequest) -> Observable func postLogout(refreshToken: String, deviceIdentifier: String) -> Observable } @@ -26,13 +26,16 @@ struct DefaultAuthRepository: AuthRepository { self.authService = authService } - func loginWithApple(authorizationCode: String, idToken: String) -> Observable { - return authService.loginWithApple(authorizationCode: authorizationCode, idToken: idToken) + func loginWithApple(appleLoginData: AppleLoginEntity) -> Observable { + let appleLoginDataDTO = appleLoginData.toDTO() + return authService.loginWithApple(appleLoginData: appleLoginDataDTO) + .map { $0.toEntity() } .asObservable() } - func loginWithKakao(_ kakaoAccessToken: OAuthToken) -> Single { + func loginWithKakao(_ kakaoAccessToken: OAuthToken) -> Single { return authService.loginWithKakao(kakaoAccessToken.accessToken) + .map { $0.toEntity() } } func postWithdrawId(withdrawData: WithdrawRequest) -> Observable { diff --git a/WSSiOS/WSSiOS/Source/Data/Repository/KeywordRepository.swift b/WSSiOS/WSSiOS/Source/Data/Repository/KeywordRepository.swift index 73e6c135d..4644d64b8 100644 --- a/WSSiOS/WSSiOS/Source/Data/Repository/KeywordRepository.swift +++ b/WSSiOS/WSSiOS/Source/Data/Repository/KeywordRepository.swift @@ -10,7 +10,7 @@ import Foundation import RxSwift protocol KeywordRepository { - func searchKeyword(query: String?) -> Observable + func searchKeyword(query: String?) -> Observable } struct DefaultKeywordRepository: KeywordRepository { @@ -21,8 +21,9 @@ struct DefaultKeywordRepository: KeywordRepository { self.keywordService = keywordService } - func searchKeyword(query: String?) -> Observable { + func searchKeyword(query: String?) -> Observable { return keywordService.searchKeyword(query: query) + .map{ $0.toEntity() } .asObservable() } } diff --git a/WSSiOS/WSSiOS/Source/Data/Repository/NovelReviewRepository.swift b/WSSiOS/WSSiOS/Source/Data/Repository/NovelReviewRepository.swift index 972104560..6b5664a95 100644 --- a/WSSiOS/WSSiOS/Source/Data/Repository/NovelReviewRepository.swift +++ b/WSSiOS/WSSiOS/Source/Data/Repository/NovelReviewRepository.swift @@ -10,21 +10,9 @@ import Foundation import RxSwift protocol NovelReviewRepository { - func postNovelReview(novelId: Int, - userNovelRating: Float, - status: String, - startDate: String?, - endDate: String?, - attractivePoints: [String], - keywordIds: [Int]) -> Observable - func putNovelReview(novelId: Int, - userNovelRating: Float, - status: String, - startDate: String?, - endDate: String?, - attractivePoints: [String], - keywordIds: [Int]) -> Observable - func getNovelReview(novelId: Int) -> Observable + func postNovelReview(novelReviewData: PostNovelReviewEntity) -> Observable + func putNovelReview(novelId: Int, novelReviewData: PutNovelReviewEntity) -> Observable + func getNovelReview(novelId: Int) -> Observable } struct DefaultNovelReviewRepository: NovelReviewRepository { @@ -34,42 +22,21 @@ struct DefaultNovelReviewRepository: NovelReviewRepository { self.novelReviewService = novelReviewService } - func postNovelReview(novelId: Int, - userNovelRating: Float, - status: String, - startDate: String?, - endDate: String?, - attractivePoints: [String], - keywordIds: [Int]) -> Observable { - return novelReviewService.postNovelReview(novelId: novelId, - userNovelRating: userNovelRating, - status: status, - startDate: startDate, - endDate: endDate, - attractivePoints: attractivePoints, - keywordIds: keywordIds) - .asObservable() + func postNovelReview(novelReviewData: PostNovelReviewEntity) -> Observable { + let novelReviewDataDTO = novelReviewData.toDTO() + return novelReviewService.postNovelReview(novelReviewData: novelReviewDataDTO) + .asObservable() } - func putNovelReview(novelId: Int, - userNovelRating: Float, - status: String, - startDate: String?, - endDate: String?, - attractivePoints: [String], - keywordIds: [Int]) -> Observable { - return novelReviewService.putNovelReview(novelId: novelId, - userNovelRating: userNovelRating, - status: status, - startDate: startDate, - endDate: endDate, - attractivePoints: attractivePoints, - keywordIds: keywordIds) - .asObservable() + func putNovelReview(novelId: Int, novelReviewData: PutNovelReviewEntity) -> Observable { + let novelReviewDataDTO = novelReviewData.toDTO() + return novelReviewService.putNovelReview(novelId: novelId, novelReviewData: novelReviewDataDTO) + .asObservable() } - func getNovelReview(novelId: Int) -> Observable { + func getNovelReview(novelId: Int) -> Observable { return novelReviewService.getNovelReview(novelId: novelId) + .map { $0.toEntity() } .asObservable() } } diff --git a/WSSiOS/WSSiOS/Source/Presentation/FeedEdit/FeedEditViewController/FeedEditViewController.swift b/WSSiOS/WSSiOS/Source/Presentation/FeedEdit/FeedEditViewController/FeedEditViewController.swift index d79c7af29..2217cf69c 100644 --- a/WSSiOS/WSSiOS/Source/Presentation/FeedEdit/FeedEditViewController/FeedEditViewController.swift +++ b/WSSiOS/WSSiOS/Source/Presentation/FeedEdit/FeedEditViewController/FeedEditViewController.swift @@ -19,7 +19,6 @@ final class FeedEditViewController: UIViewController { private let disposeBag = DisposeBag() private let viewDidLoadEvent = PublishRelay() - private let stopEditingEvent = PublishRelay() //MARK: - Components @@ -54,6 +53,7 @@ final class FeedEditViewController: UIViewController { register() delegate() bindViewModel() + bindAction() viewDidLoadEvent.accept(()) @@ -104,7 +104,6 @@ final class FeedEditViewController: UIViewController { return true } .asObservable(), - backButtonDidTap: rootView.backButton.rx.tap, completeButtonDidTap: rootView.completeButton.rx.tap, spoilerButtonDidTap: rootView.feedEditContentView.spoilerButton.rx.tap, categoryCollectionViewItemSelected: rootView.feedEditCategoryView.categoryCollectionView.rx.itemSelected.asObservable(), @@ -114,8 +113,7 @@ final class FeedEditViewController: UIViewController { feedContentViewDidEndEditing: rootView.feedEditContentView.feedTextView.rx.didEndEditing, novelConnectViewDidTap: rootView.feedEditNovelConnectView.rx.tapGesture().when(.recognized).asObservable(), feedNovelConnectedNotification: NotificationCenter.default.rx.notification(Notification.Name("FeedNovelConnected")).asObservable(), - novelRemoveButtonDidTap: rootView.feedEditConnectedNovelView.removeButton.rx.tap, - stopEditButtonDidTap: stopEditingEvent.asObservable() + novelRemoveButtonDidTap: rootView.feedEditConnectedNovelView.removeButton.rx.tap ) let output = self.feedEditViewModel.transform(from: input, disposeBag: self.disposeBag) @@ -143,7 +141,7 @@ final class FeedEditViewController: UIViewController { output.popViewController .subscribe(with: self, onNext: { owner, _ in - owner.navigationController?.popViewController(animated: true) + owner.popToLastViewController() }) .disposed(by: disposeBag) @@ -194,8 +192,11 @@ final class FeedEditViewController: UIViewController { owner.showToast(.novelAlreadyConnected) }) .disposed(by: disposeBag) - - output.showStopEditingAlert + } + + private func bindAction() { + rootView.backButton.rx.tap + .throttle(.seconds(3), latest: false, scheduler: MainScheduler.instance) .flatMapLatest { _ -> Observable in return self.presentToAlertViewController(iconImage: .icModalWarning, titleText: StringLiterals.FeedEdit.Alert.titleText, @@ -206,7 +207,7 @@ final class FeedEditViewController: UIViewController { } .subscribe(with: self, onNext: { owner, buttonType in if buttonType == .left { - owner.stopEditingEvent.accept(()) + owner.popToLastViewController() } }) .disposed(by: disposeBag) diff --git a/WSSiOS/WSSiOS/Source/Presentation/FeedEdit/FeedEditViewController/FeedNovelConnectModalViewController.swift b/WSSiOS/WSSiOS/Source/Presentation/FeedEdit/FeedEditViewController/FeedNovelConnectModalViewController.swift index 1f1319dd6..2de2713a6 100644 --- a/WSSiOS/WSSiOS/Source/Presentation/FeedEdit/FeedEditViewController/FeedNovelConnectModalViewController.swift +++ b/WSSiOS/WSSiOS/Source/Presentation/FeedEdit/FeedEditViewController/FeedNovelConnectModalViewController.swift @@ -42,6 +42,7 @@ final class FeedNovelConnectModalViewController: UIViewController { register() bindViewModel() + bindAction() } override func touchesBegan(_ touches: Set, with event: UIEvent?) { @@ -58,7 +59,6 @@ final class FeedNovelConnectModalViewController: UIViewController { private func bindViewModel() { let input = FeedNovelConnectModalViewModel.Input( - closeButtonDidTap: rootView.closeButton.rx.tap, searchTextUpdated: rootView.feedNovelConnectSearchBarView.titleTextField.rx.text.orEmpty.asObservable(), searchButtonDidTap: rootView.feedNovelConnectSearchBarView.searchButton.rx.tap, searchResultCollectionViewReachedBottom: observeReachedBottom(rootView.feedNovelConnectSearchResultView.searchResultCollectionView), @@ -102,6 +102,14 @@ final class FeedNovelConnectModalViewController: UIViewController { .disposed(by: disposeBag) } + private func bindAction() { + rootView.closeButton.rx.tap + .subscribe(with: self, onNext: { owner, _ in + owner.dismissModalViewController() + }) + .disposed(by: disposeBag) + } + // MARK: - Custom Method private func observeReachedBottom(_ scrollView: UIScrollView) -> Observable { diff --git a/WSSiOS/WSSiOS/Source/Presentation/FeedEdit/FeedEditViewModel/FeedEditViewModel.swift b/WSSiOS/WSSiOS/Source/Presentation/FeedEdit/FeedEditViewModel/FeedEditViewModel.swift index c6b05f938..f6c873fbd 100644 --- a/WSSiOS/WSSiOS/Source/Presentation/FeedEdit/FeedEditViewModel/FeedEditViewModel.swift +++ b/WSSiOS/WSSiOS/Source/Presentation/FeedEdit/FeedEditViewModel/FeedEditViewModel.swift @@ -49,7 +49,6 @@ final class FeedEditViewModel: ViewModelType { private let presentFeedEditNovelConnectModalViewController = PublishRelay() private let connectedNovelTitle = BehaviorRelay(value: nil) private let showAlreadyConnectedToast = PublishRelay() - private let showStopEditingAlert = PublishRelay() //MARK: - Life Cycle @@ -67,7 +66,6 @@ final class FeedEditViewModel: ViewModelType { struct Input { let viewDidLoadEvent: Observable let viewDidTap: Observable - let backButtonDidTap: ControlEvent let completeButtonDidTap: ControlEvent let spoilerButtonDidTap: ControlEvent let categoryCollectionViewItemSelected: Observable @@ -78,7 +76,6 @@ final class FeedEditViewModel: ViewModelType { let novelConnectViewDidTap: Observable let feedNovelConnectedNotification: Observable let novelRemoveButtonDidTap: ControlEvent - let stopEditButtonDidTap: Observable } struct Output { @@ -93,7 +90,6 @@ final class FeedEditViewModel: ViewModelType { let presentFeedEditNovelConnectModalViewController: Observable let connectedNovelTitle: Observable let showAlreadyConnectedToast: Observable - let showStopEditingAlert: Observable } func transform(from input: Input, disposeBag: DisposeBag) -> Output { @@ -126,13 +122,6 @@ final class FeedEditViewModel: ViewModelType { }) .disposed(by: disposeBag) - input.backButtonDidTap - .throttle(.seconds(3), latest: false, scheduler: MainScheduler.instance) - .subscribe(with: self, onNext: { owner, _ in - owner.showStopEditingAlert.accept(()) - }) - .disposed(by: disposeBag) - input.completeButtonDidTap .throttle(.seconds(3), latest: false, scheduler: MainScheduler.instance) .do(onNext: { _ in @@ -239,12 +228,6 @@ final class FeedEditViewModel: ViewModelType { }) .disposed(by: disposeBag) - input.stopEditButtonDidTap - .subscribe(with: self, onNext: { owner, _ in - owner.popViewController.accept(()) - }) - .disposed(by: disposeBag) - return Output(endEditing: endEditing.asObservable(), categoryListData: categoryListData.asObservable(), popViewController: popViewController.asObservable(), @@ -255,8 +238,8 @@ final class FeedEditViewModel: ViewModelType { showPlaceholder: showPlaceholder.asObservable(), presentFeedEditNovelConnectModalViewController: presentFeedEditNovelConnectModalViewController.asObservable(), connectedNovelTitle: connectedNovelTitle.asObservable(), - showAlreadyConnectedToast: showAlreadyConnectedToast.asObservable(), - showStopEditingAlert: showStopEditingAlert.asObservable()) + showAlreadyConnectedToast: showAlreadyConnectedToast.asObservable() + ) } // MARK: - Custom Method diff --git a/WSSiOS/WSSiOS/Source/Presentation/FeedEdit/FeedEditViewModel/FeedNovelConnectModalViewModel.swift b/WSSiOS/WSSiOS/Source/Presentation/FeedEdit/FeedEditViewModel/FeedNovelConnectModalViewModel.swift index 4ba25ac24..73f8c4b8d 100644 --- a/WSSiOS/WSSiOS/Source/Presentation/FeedEdit/FeedEditViewModel/FeedNovelConnectModalViewModel.swift +++ b/WSSiOS/WSSiOS/Source/Presentation/FeedEdit/FeedEditViewModel/FeedNovelConnectModalViewModel.swift @@ -38,7 +38,6 @@ final class FeedNovelConnectModalViewModel: ViewModelType { } struct Input { - let closeButtonDidTap: ControlEvent let searchTextUpdated: Observable let searchButtonDidTap: ControlEvent let searchResultCollectionViewReachedBottom: Observable @@ -57,12 +56,6 @@ final class FeedNovelConnectModalViewModel: ViewModelType { } func transform(from input: Input, disposeBag: DisposeBag) -> Output { - input.closeButtonDidTap - .subscribe(with: self, onNext: { owner, _ in - owner.dismissModalViewController.accept(()) - }) - .disposed(by: disposeBag) - input.searchTextUpdated .subscribe(with: self, onNext: { owner, text in owner.searchText = text diff --git a/WSSiOS/WSSiOS/Source/Presentation/Login/LoginViewModel/LoginViewModel.swift b/WSSiOS/WSSiOS/Source/Presentation/Login/LoginViewModel/LoginViewModel.swift index e3b1d36c5..6cc8ede3b 100644 --- a/WSSiOS/WSSiOS/Source/Presentation/Login/LoginViewModel/LoginViewModel.swift +++ b/WSSiOS/WSSiOS/Source/Presentation/Login/LoginViewModel/LoginViewModel.swift @@ -35,8 +35,7 @@ final class LoginViewModel: NSObject, ViewModelType { private let navigateToHome = PublishRelay() private let navigateToOnboarding = PublishRelay() - private let loginWithApple = PublishRelay<(authorizationCode: String, - idToken: String)>() + private let loginWithApple = PublishRelay() //MARK: - Life Cycle @@ -103,9 +102,8 @@ final class LoginViewModel: NSObject, ViewModelType { // 애플로그인 후 authorizationCode와 idToken을 받아와서 로그인 요청 loginWithApple - .flatMapLatest { authorizationCode, idToken in - self.loginWithApple(authorizationCode: authorizationCode, - idToken: idToken) + .flatMapLatest { loginWithApple in + self.loginWithApple(appleLoginData: loginWithApple) } .subscribe(with: self, onNext: { owner, result in owner.loginSuccess(result: result) @@ -137,7 +135,7 @@ final class LoginViewModel: NSObject, ViewModelType { }) } - private func loginSuccess(result: LoginResponse) { + private func loginSuccess(result: LoginEntity) { UserDefaults.standard.setValue(result.Authorization, forKey: StringLiterals.UserDefault.accessToken) UserDefaults.standard.setValue(result.refreshToken, @@ -154,8 +152,8 @@ final class LoginViewModel: NSObject, ViewModelType { //MARK: - API/Apple - private func loginWithApple(authorizationCode: String, idToken: String) -> Observable { - authRepository.loginWithApple(authorizationCode: authorizationCode, idToken: idToken) + private func loginWithApple(appleLoginData: AppleLoginEntity) -> Observable { + authRepository.loginWithApple(appleLoginData: appleLoginData) .observe(on: MainScheduler.instance) } @@ -221,8 +219,10 @@ extension LoginViewModel: ASAuthorizationControllerDelegate { return } - loginWithApple.accept((authorizationCode: String(data: credential.authorizationCode!, encoding: String.Encoding.utf8)!, - idToken: String(data: credential.identityToken!, encoding: String.Encoding.utf8)!)) + let appleLoginData = AppleLoginEntity(authorizationCode: credential.authorizationCode!, + idToken: credential.identityToken!) + + loginWithApple.accept(appleLoginData) } func authorizationController( diff --git a/WSSiOS/WSSiOS/Source/Presentation/NovelDetail/NovelDetailViewController/NovelDetailViewController.swift b/WSSiOS/WSSiOS/Source/Presentation/NovelDetail/NovelDetailViewController/NovelDetailViewController.swift index c6cd049c7..2698619b8 100644 --- a/WSSiOS/WSSiOS/Source/Presentation/NovelDetail/NovelDetailViewController/NovelDetailViewController.swift +++ b/WSSiOS/WSSiOS/Source/Presentation/NovelDetail/NovelDetailViewController/NovelDetailViewController.swift @@ -442,26 +442,12 @@ final class NovelDetailViewController: UIViewController { }) .disposed(by: disposeBag) - output.showFeedEditedToast - .subscribe(with: self, onNext: { owner, _ in - owner.showToast(.feedEdited) - }) - .disposed(by: disposeBag) - output.showWithdrawalUserToastView .observe(on: MainScheduler.instance) .subscribe(with: self, onNext: { owner, _ in owner.showToast(.unknownUser) }) .disposed(by: disposeBag) - - //MARK: - Bind/NovelReview - - output.showNovelReviewedToast - .subscribe(with: self, onNext: { owner, _ in - owner.showToast(.novelReviewed) - }) - .disposed(by: disposeBag) } //MARK: - Actions @@ -483,6 +469,18 @@ final class NovelDetailViewController: UIViewController { owner.popToLastViewController() }) .disposed(by: disposeBag) + + NotificationCenter.default.rx.notification(Notification.Name("FeedEdited")) + .subscribe(with: self, onNext: { owner, _ in + owner.showToast(.feedEdited) + }) + .disposed(by: disposeBag) + + NotificationCenter.default.rx.notification(Notification.Name("NovelReviewed")) + .subscribe(with: self, onNext: { owner, _ in + owner.showToast(.novelReviewed) + }) + .disposed(by: disposeBag) } private func createViewModelInput() -> NovelDetailViewModel.Input { @@ -542,9 +540,7 @@ final class NovelDetailViewController: UIViewController { novelDetailFeedLikeViewDidTap: novelDetailFeedLikeViewDidTap.asObservable(), reloadNovelDetailFeed: reloadNovelDetailFeed.asObservable(), scrollViewReachedBottom: observeReachedBottom(rootView.scrollView), - createFeedButtonDidTap: rootView.createFeedButton.rx.tap, - feedEditedNotification: NotificationCenter.default.rx.notification(Notification.Name("FeedEdited")).asObservable(), - novelReviewedNotification: NotificationCenter.default.rx.notification(Notification.Name("NovelReviewed")).asObservable() + createFeedButtonDidTap: rootView.createFeedButton.rx.tap ) } diff --git a/WSSiOS/WSSiOS/Source/Presentation/NovelDetail/NovelDetailViewModel/NovelDetailViewModel.swift b/WSSiOS/WSSiOS/Source/Presentation/NovelDetail/NovelDetailViewModel/NovelDetailViewModel.swift index c1adfb065..6d257af3c 100644 --- a/WSSiOS/WSSiOS/Source/Presentation/NovelDetail/NovelDetailViewModel/NovelDetailViewModel.swift +++ b/WSSiOS/WSSiOS/Source/Presentation/NovelDetail/NovelDetailViewModel/NovelDetailViewModel.swift @@ -113,10 +113,6 @@ final class NovelDetailViewModel: ViewModelType { let reloadNovelDetailFeed: Observable let scrollViewReachedBottom: Observable let createFeedButtonDidTap: ControlEvent - let feedEditedNotification: Observable - - // NovelReview - let novelReviewedNotification: Observable } struct Output { @@ -158,11 +154,7 @@ final class NovelDetailViewModel: ViewModelType { let showImproperAlertView: Observable<((Int) -> Observable, Int)> let pushToFeedEditViewController: Observable let showDeleteAlertView: Observable<((Int) -> Observable, Int)> - let showFeedEditedToast: Observable let showWithdrawalUserToastView: Observable - - // NovelReview - let showNovelReviewedToast: Observable } func transform(from input: Input, disposeBag: DisposeBag) -> Output { @@ -483,14 +475,6 @@ final class NovelDetailViewModel: ViewModelType { }) .disposed(by: disposeBag) - let showFeedEditedToast = input.feedEditedNotification - .map { _ in () } - .asObservable() - - let showNovelReviewedToast = input.novelReviewedNotification - .map { _ in () } - .asObservable() - input.novelDetailFeedProfileViewDidTap .subscribe(with: self, onNext: { owner, userId in if userId == -1 { @@ -531,9 +515,7 @@ final class NovelDetailViewModel: ViewModelType { showImproperAlertView: showImproperAlertView.asObservable(), pushToFeedEditViewController: pushToFeedEditViewController.asObservable(), showDeleteAlertView: showDeleteAlertView.asObservable(), - showFeedEditedToast: showFeedEditedToast, - showWithdrawalUserToastView: showWithdrawalUserToastView.asObservable(), - showNovelReviewedToast: showNovelReviewedToast + showWithdrawalUserToastView: showWithdrawalUserToastView.asObservable() ) } diff --git a/WSSiOS/WSSiOS/Source/Presentation/NovelReview/NovelReviewViewController/NovelDateSelectModalViewController.swift b/WSSiOS/WSSiOS/Source/Presentation/NovelReview/NovelReviewViewController/NovelDateSelectModalViewController.swift index f3d4bc667..b2c70af33 100644 --- a/WSSiOS/WSSiOS/Source/Presentation/NovelReview/NovelReviewViewController/NovelDateSelectModalViewController.swift +++ b/WSSiOS/WSSiOS/Source/Presentation/NovelReview/NovelReviewViewController/NovelDateSelectModalViewController.swift @@ -48,18 +48,16 @@ final class NovelDateSelectModalViewController: UIViewController { super.viewDidLoad() bindViewModel() + bindAction() viewDidLoadEvent.accept(()) } - //MARK: - UI - //MARK: - Bind private func bindViewModel() { let input = NovelDateSelectModalViewModel.Input( viewDidLoadEvent: viewDidLoadEvent.asObservable(), - closeButtonDidTap: rootView.closeButton.rx.tap, startDateButonDidTap: rootView.novelDateSelectModalDateButtonView.startDateButton.rx.tap, endDateButonDidTap: rootView.novelDateSelectModalDateButtonView.endDateButton.rx.tap, datePickerDateDidChanged: rootView.novelDateSelectModalDatePickerView.datePicker.rx.date.changed, @@ -105,4 +103,12 @@ final class NovelDateSelectModalViewController: UIViewController { }) .disposed(by: disposeBag) } + + private func bindAction() { + rootView.closeButton.rx.tap + .subscribe(with: self, onNext: { owner, _ in + owner.dismissModalViewController() + }) + .disposed(by: disposeBag) + } } diff --git a/WSSiOS/WSSiOS/Source/Presentation/NovelReview/NovelReviewViewController/NovelReviewViewController.swift b/WSSiOS/WSSiOS/Source/Presentation/NovelReview/NovelReviewViewController/NovelReviewViewController.swift index da1ebe061..6eb4ba7b4 100644 --- a/WSSiOS/WSSiOS/Source/Presentation/NovelReview/NovelReviewViewController/NovelReviewViewController.swift +++ b/WSSiOS/WSSiOS/Source/Presentation/NovelReview/NovelReviewViewController/NovelReviewViewController.swift @@ -19,7 +19,6 @@ final class NovelReviewViewController: UIViewController { private let disposeBag = DisposeBag() private let viewDidLoadEvent = PublishRelay() - private let stopReviewingEvent = PublishRelay() //MARK: - Components @@ -47,6 +46,7 @@ final class NovelReviewViewController: UIViewController { register() delegate() bindViewModel() + bindAction() viewDidLoadEvent.accept(()) } @@ -78,7 +78,6 @@ final class NovelReviewViewController: UIViewController { private func bindViewModel() { let input = NovelReviewViewModel.Input( viewDidLoadEvent: viewDidLoadEvent.asObservable(), - backButtonDidTap: rootView.backButton.rx.tap, completeButtonDidTap: rootView.completeButton.rx.tap, statusCollectionViewItemSelected: rootView.novelReviewStatusView.statusCollectionView.rx.itemSelected.asObservable(), dateLabelTapGesture: rootView.novelReviewStatusView.dateLabel.rx.tapGesture() @@ -110,15 +109,14 @@ final class NovelReviewViewController: UIViewController { selectedKeywordCollectionViewItemSelected: rootView.novelReviewKeywordView.selectedKeywordCollectionView.rx.itemSelected.asObservable(), novelReviewKeywordSelectedNotification: NotificationCenter.default.rx.notification(Notification.Name("NovelReviewKeywordSelected")).asObservable(), novelReviewDateSelectedNotification: NotificationCenter.default.rx.notification(Notification.Name("NovelReviewDateSelected")).asObservable(), - novelReviewDateRemovedNotification: NotificationCenter.default.rx.notification(Notification.Name("NovelReviewDateRemoved")).asObservable(), - stopReviewButtonDidTap: stopReviewingEvent.asObservable() + novelReviewDateRemovedNotification: NotificationCenter.default.rx.notification(Notification.Name("NovelReviewDateRemoved")).asObservable() ) let output = self.novelReviewViewModel.transform(from: input, disposeBag: self.disposeBag) output.popViewController .subscribe(with: self, onNext: { owner, _ in - owner.navigationController?.popViewController(animated: true) + owner.popToLastViewController() }) .disposed(by: disposeBag) @@ -162,7 +160,7 @@ final class NovelReviewViewController: UIViewController { .bind(to: rootView.novelReviewAttractivePointView.attractivePointCollectionView.rx.items(cellIdentifier: NovelReviewAttractivePointCollectionViewCell.cellIdentifier, cellType: NovelReviewAttractivePointCollectionViewCell.self)) { item, element, cell in let indexPath = IndexPath(item: item, section: 0) - if self.novelReviewViewModel.selectedAttractivePointList.contains(element.rawValue) { + if self.novelReviewViewModel.selectedAttractivePointList.contains(element) { self.rootView.novelReviewAttractivePointView.attractivePointCollectionView.selectItem(at: indexPath, animated: false, scrollPosition: []) } else { self.rootView.novelReviewAttractivePointView.attractivePointCollectionView.deselectItem(at: indexPath, animated: false) @@ -195,8 +193,11 @@ final class NovelReviewViewController: UIViewController { owner.rootView.novelReviewKeywordView.updateCollectionViewHeight(height: height) }) .disposed(by: disposeBag) - - output.showStopReviewingAlert + } + + private func bindAction() { + rootView.backButton.rx.tap + .throttle(.seconds(3), latest: false, scheduler: MainScheduler.instance) .flatMapLatest { _ -> Observable in return self.presentToAlertViewController(iconImage: .icModalWarning, titleText: StringLiterals.NovelReview.Alert.titleText, @@ -207,10 +208,11 @@ final class NovelReviewViewController: UIViewController { } .subscribe(with: self, onNext: { owner, buttonType in if buttonType == .left { - owner.stopReviewingEvent.accept(()) + owner.popToLastViewController() } }) .disposed(by: disposeBag) + } } diff --git a/WSSiOS/WSSiOS/Source/Presentation/NovelReview/NovelReviewViewModel/NovelDateSelectModalViewModel.swift b/WSSiOS/WSSiOS/Source/Presentation/NovelReview/NovelReviewViewModel/NovelDateSelectModalViewModel.swift index 97c15effc..975a4d75a 100644 --- a/WSSiOS/WSSiOS/Source/Presentation/NovelReview/NovelReviewViewModel/NovelDateSelectModalViewModel.swift +++ b/WSSiOS/WSSiOS/Source/Presentation/NovelReview/NovelReviewViewModel/NovelDateSelectModalViewModel.swift @@ -30,7 +30,6 @@ final class NovelDateSelectModalViewModel: ViewModelType { struct Input { let viewDidLoadEvent: Observable - let closeButtonDidTap: ControlEvent let startDateButonDidTap: ControlEvent let endDateButonDidTap: ControlEvent let datePickerDateDidChanged: ControlEvent @@ -73,12 +72,6 @@ final class NovelDateSelectModalViewModel: ViewModelType { }) .disposed(by: disposeBag) - input.closeButtonDidTap - .subscribe(onNext: { _ in - output.dismissModalViewController.accept(()) - }) - .disposed(by: disposeBag) - input.startDateButonDidTap .subscribe(with: self, onNext: { owner, _ in owner.isStartDateEditing = true diff --git a/WSSiOS/WSSiOS/Source/Presentation/NovelReview/NovelReviewViewModel/NovelKeywordSelectModalViewModel.swift b/WSSiOS/WSSiOS/Source/Presentation/NovelReview/NovelReviewViewModel/NovelKeywordSelectModalViewModel.swift index 5688d6fbf..04afa247e 100644 --- a/WSSiOS/WSSiOS/Source/Presentation/NovelReview/NovelReviewViewModel/NovelKeywordSelectModalViewModel.swift +++ b/WSSiOS/WSSiOS/Source/Presentation/NovelReview/NovelReviewViewModel/NovelKeywordSelectModalViewModel.swift @@ -237,7 +237,7 @@ final class NovelKeywordSelectModalViewModel: ViewModelType { //MARK: - API - private func searchKeyword(query: String? = nil) -> Observable { + private func searchKeyword(query: String? = nil) -> Observable { keywordRepository.searchKeyword(query: query) .observe(on: MainScheduler.instance) } diff --git a/WSSiOS/WSSiOS/Source/Presentation/NovelReview/NovelReviewViewModel/NovelReviewViewModel.swift b/WSSiOS/WSSiOS/Source/Presentation/NovelReview/NovelReviewViewModel/NovelReviewViewModel.swift index 741b182a8..154d3dfd2 100644 --- a/WSSiOS/WSSiOS/Source/Presentation/NovelReview/NovelReviewViewModel/NovelReviewViewModel.swift +++ b/WSSiOS/WSSiOS/Source/Presentation/NovelReview/NovelReviewViewModel/NovelReviewViewModel.swift @@ -23,10 +23,10 @@ final class NovelReviewViewModel: ViewModelType { let novelTitle: String private var isNovelReviewExist: Bool = false - + private var startDate: Date? private var endDate: Date? - var selectedAttractivePointList: [String] = [] + var selectedAttractivePointList: [AttractivePoint?] = [] private let minStarRating: Float = 0.0 private let maxStarRating: Float = 5.0 @@ -49,7 +49,6 @@ final class NovelReviewViewModel: ViewModelType { private let presentNovelKeywordSelectModalViewController = PublishRelay<[KeywordData]>() let selectedKeywordListData = BehaviorRelay<[KeywordData]>(value: []) private let selectedKeywordCollectionViewHeight = BehaviorRelay(value: 0) - private let showStopReviewingAlert = PublishRelay() //MARK: - Life Cycle @@ -63,7 +62,6 @@ final class NovelReviewViewModel: ViewModelType { struct Input { let viewDidLoadEvent: Observable - let backButtonDidTap: ControlEvent let completeButtonDidTap: ControlEvent let statusCollectionViewItemSelected: Observable let dateLabelTapGesture: Observable @@ -77,7 +75,6 @@ final class NovelReviewViewModel: ViewModelType { let novelReviewKeywordSelectedNotification: Observable let novelReviewDateSelectedNotification: Observable let novelReviewDateRemovedNotification: Observable - let stopReviewButtonDidTap: Observable } struct Output { @@ -92,7 +89,6 @@ final class NovelReviewViewModel: ViewModelType { let presentNovelKeywordSelectModalViewController: Observable<[KeywordData]> let selectedKeywordListData: Observable<[KeywordData]> let selectedKeywordCollectionViewHeight: Observable - let showStopReviewingAlert: Observable } func transform(from input: Input, disposeBag: DisposeBag) -> Output { @@ -102,10 +98,8 @@ final class NovelReviewViewModel: ViewModelType { } .subscribe(with: self, onNext: { owner, data in owner.isNovelReviewExist = data.status != nil || owner.isInterest == true - if data.startDate != nil || data.endDate != nil { - owner.startDate = data.startDate.flatMap { owner.dateFormatter.date(from: $0) } ?? Date() - owner.endDate = data.endDate.flatMap { owner.dateFormatter.date(from: $0) } ?? Date() - } + owner.startDate = data.startDate + owner.endDate = data.endDate owner.startDateEndDateData.accept([owner.startDate, owner.endDate]) owner.starRating.accept(data.userNovelRating) owner.selectedKeywordListData.accept(data.keywords) @@ -117,42 +111,43 @@ final class NovelReviewViewModel: ViewModelType { }) .disposed(by: disposeBag) - input.backButtonDidTap - .throttle(.seconds(3), latest: false, scheduler: MainScheduler.instance) - .subscribe(with: self, onNext: { owner, _ in - owner.showStopReviewingAlert.accept(()) - }) - .disposed(by: disposeBag) - input.completeButtonDidTap .throttle(.seconds(3), latest: false, scheduler: MainScheduler.instance) .flatMapLatest { AmplitudeManager.shared.track(AmplitudeEvent.Novel.rateNovel) - + let startDateString = self.readStatus != .quit ? self.startDate.map { self.dateFormatter.string(from: $0) } : nil let endDateString = self.readStatus != .watching ? self.endDate.map { self.dateFormatter.string(from: $0) } : nil let keywordIdList = self.selectedKeywordListData.value.map { $0.keywordId } if self.isNovelReviewExist { - return self.putNovelReview( - novelId: self.novelId, + let novelReviewData = PutNovelReviewEntity( userNovelRating: self.starRating.value, - status: self.readStatus.rawValue, + status: self.readStatus, startDate: startDateString, endDate: endDateString, attractivePoints: self.selectedAttractivePointList, keywordIds: keywordIdList ) + + return self.putNovelReview( + novelId: self.novelId, + novelReviewData: novelReviewData + ) } else { - return self.postNovelReview( + let novelReviewData = PostNovelReviewEntity( novelId: self.novelId, userNovelRating: self.starRating.value, - status: self.readStatus.rawValue, + status: self.readStatus, startDate: startDateString, endDate: endDateString, attractivePoints: self.selectedAttractivePointList, keywordIds: keywordIdList ) + + return self.postNovelReview( + novelReviewData: novelReviewData + ) } } .subscribe(with: self, onNext: { owner, _ in @@ -173,8 +168,8 @@ final class NovelReviewViewModel: ViewModelType { input.dateLabelTapGesture .subscribe(with: self, onNext: { owner, _ in owner.presentNovelDateSelectModalViewController.accept((owner.readStatus, - owner.startDate, - owner.endDate)) + owner.startDate, + owner.endDate)) }) .disposed(by: disposeBag) @@ -202,14 +197,14 @@ final class NovelReviewViewModel: ViewModelType { if owner.selectedAttractivePointList.count >= owner.attractivePointLimit { owner.isAttractivePointCountOverLimit.accept(indexPath) } else { - owner.selectedAttractivePointList.append(AttractivePoint.allCases[indexPath.item].rawValue) + owner.selectedAttractivePointList.append(AttractivePoint.allCases[indexPath.item]) } }) .disposed(by: disposeBag) input.attractivePointCollectionViewItemDeselected .subscribe(with: self, onNext: { owner, indexPath in - owner.selectedAttractivePointList.removeAll { $0 == AttractivePoint.allCases[indexPath.item].rawValue } + owner.selectedAttractivePointList.removeAll { $0 == AttractivePoint.allCases[indexPath.item] } }) .disposed(by: disposeBag) @@ -257,12 +252,6 @@ final class NovelReviewViewModel: ViewModelType { }) .disposed(by: disposeBag) - input.stopReviewButtonDidTap - .subscribe(with: self, onNext: { owner, _ in - owner.popViewController.accept(()) - }) - .disposed(by: disposeBag) - return Output(popViewController: popViewController.asObservable(), readStatusListData: readStatusListData.asObservable(), readStatusData: readStatusData.asObservable(), @@ -273,47 +262,23 @@ final class NovelReviewViewModel: ViewModelType { isAttractivePointCountOverLimit: isAttractivePointCountOverLimit.asObservable(), presentNovelKeywordSelectModalViewController: presentNovelKeywordSelectModalViewController.asObservable(), selectedKeywordListData: selectedKeywordListData.asObservable(), - selectedKeywordCollectionViewHeight: selectedKeywordCollectionViewHeight.asObservable(), - showStopReviewingAlert: showStopReviewingAlert.asObservable()) + selectedKeywordCollectionViewHeight: selectedKeywordCollectionViewHeight.asObservable() + ) } //MARK: - API - private func postNovelReview(novelId: Int, - userNovelRating: Float, - status: String, - startDate: String?, - endDate: String?, - attractivePoints: [String], - keywordIds: [Int]) -> Observable { - novelReviewRepository.postNovelReview(novelId: novelId, - userNovelRating: userNovelRating, - status: status, - startDate: startDate, - endDate: endDate, - attractivePoints: attractivePoints, - keywordIds: keywordIds) - .observe(on: MainScheduler.instance) + private func postNovelReview(novelReviewData: PostNovelReviewEntity) -> Observable { + novelReviewRepository.postNovelReview(novelReviewData: novelReviewData) + .observe(on: MainScheduler.instance) } - private func putNovelReview(novelId: Int, - userNovelRating: Float, - status: String, - startDate: String?, - endDate: String?, - attractivePoints: [String], - keywordIds: [Int]) -> Observable { - novelReviewRepository.putNovelReview(novelId: novelId, - userNovelRating: userNovelRating, - status: status, - startDate: startDate, - endDate: endDate, - attractivePoints: attractivePoints, - keywordIds: keywordIds) - .observe(on: MainScheduler.instance) + private func putNovelReview(novelId: Int, novelReviewData: PutNovelReviewEntity) -> Observable { + novelReviewRepository.putNovelReview(novelId: novelId, novelReviewData: novelReviewData) + .observe(on: MainScheduler.instance) } - private func getNovelReview(novelId: Int) -> Observable { + private func getNovelReview(novelId: Int) -> Observable { novelReviewRepository.getNovelReview(novelId: novelId) .observe(on: MainScheduler.instance) } diff --git a/WSSiOS/WSSiOS/Source/Presentation/Search/DetailSearch/DetailSearchViewModel/DetailSearchViewModel.swift b/WSSiOS/WSSiOS/Source/Presentation/Search/DetailSearch/DetailSearchViewModel/DetailSearchViewModel.swift index 4914cca57..79b228def 100644 --- a/WSSiOS/WSSiOS/Source/Presentation/Search/DetailSearch/DetailSearchViewModel/DetailSearchViewModel.swift +++ b/WSSiOS/WSSiOS/Source/Presentation/Search/DetailSearch/DetailSearchViewModel/DetailSearchViewModel.swift @@ -392,7 +392,7 @@ final class DetailSearchViewModel: ViewModelType { //MARK: - API - private func searchKeyword(query: String? = nil) -> Observable { + private func searchKeyword(query: String? = nil) -> Observable { keywordRepository.searchKeyword(query: query) .observe(on: MainScheduler.instance) }