diff --git a/project/Projects/Data/ConcreteRepository/RecruitmentPost/DefaultRecruitmentPostRepository.swift b/project/Projects/Data/ConcreteRepository/RecruitmentPost/DefaultRecruitmentPostRepository.swift index f76bcfd8..6625c5e4 100644 --- a/project/Projects/Data/ConcreteRepository/RecruitmentPost/DefaultRecruitmentPostRepository.swift +++ b/project/Projects/Data/ConcreteRepository/RecruitmentPost/DefaultRecruitmentPostRepository.swift @@ -114,37 +114,23 @@ public class DefaultRecruitmentPostRepository: RecruitmentPostRepository { api: .getOnGoingNativePostListForWorker(nextPageId: nextPageId, requestCnt: String(requestCnt)), with: .withToken ) - .map(RecruitmentPostListForWorkerDTO.self) - .catch({ error in - if let moyaError = error as? MoyaError, case .objectMapping(let error, _) = moyaError { - #if DEBUG - print("앱용 공고 전체조회 에러:", error.localizedDescription) - #endif - } - return .error(error) - }) - .map { dto in - dto.toEntity() - } + .mapToEntity(RecruitmentPostListForWorkerDTO.self) } - public func getFavoritePostListForWorker(nextPageId: String?, requestCnt: Int) -> RxSwift.Single { + public func getNativeFavoritePostListForWorker() -> RxSwift.Single<[RecruitmentPostForWorkerRepresentable]> { recruitmentPostService.request( - api: .getFavoritePostListForWorker(nextPageId: nextPageId, requestCnt: String(requestCnt)), + api: .getNativeFavoritePost, with: .withToken ) - .map(RecruitmentPostListForWorkerDTO.self) - .catch({ error in - if let moyaError = error as? MoyaError, case .objectMapping(let error, _) = moyaError { - #if DEBUG - print("즐겨찾기한 공고 전체조회 에러:",error.localizedDescription) - #endif - } - return .error(error) - }) - .map { dto in - dto.toEntity() - } + .mapToEntity(FavoriteRecruitmentPostListForWorkerDTO.self) + } + + public func getWorknetFavoritePostListForWorker() -> RxSwift.Single<[RecruitmentPostForWorkerRepresentable]> { + crawlingPostService.request( + api: .getWorknetFavoritePost, + with: .withToken + ) + .mapToEntity(FavoriteRecruitmentPostListForWorkerDTO.self) } public func getAppliedPostListForWorker(nextPageId: String?, requestCnt: Int) -> RxSwift.Single { @@ -152,18 +138,7 @@ public class DefaultRecruitmentPostRepository: RecruitmentPostRepository { api: .getAppliedPostListForWorker(nextPageId: nextPageId, requestCnt: String(requestCnt)), with: .withToken ) - .map(RecruitmentPostListForWorkerDTO.self) - .catch({ error in - if let moyaError = error as? MoyaError, case .objectMapping(let error, _) = moyaError { - #if DEBUG - print("지원한 공고 전체조회 에러:", error.localizedDescription) - #endif - } - return .error(error) - }) - .map { dto in - dto.toEntity() - } + .mapToEntity(RecruitmentPostListForWorkerDTO.self) } public func getWorknetPostListForWorker(nextPageId: String?, requestCnt: Int) -> RxSwift.Single { @@ -172,19 +147,7 @@ public class DefaultRecruitmentPostRepository: RecruitmentPostRepository { api: .getPostList(nextPageId: nextPageId, requestCnt: requestCnt), with: .withToken ) - .map(RecruitmentPostListForWorkerDTO.self) - .catch({ error in - if let moyaError = error as? MoyaError, case .objectMapping(let error, _) = moyaError { - #if DEBUG - print("지원한 공고 전체조회 에러:", error.localizedDescription) - #endif - } - return .error(error) - }) - .map { dto in - dto.toEntity() - } - + .mapToEntity(RecruitmentPostListForWorkerDTO.self) } public func applyToPost(postId: String, method: ApplyType) -> Single { diff --git a/project/Projects/Data/DataSource/API/CrawlingPostAPI.swift b/project/Projects/Data/DataSource/API/CrawlingPostAPI.swift index 0dc267c4..c5d01545 100644 --- a/project/Projects/Data/DataSource/API/CrawlingPostAPI.swift +++ b/project/Projects/Data/DataSource/API/CrawlingPostAPI.swift @@ -13,6 +13,7 @@ public enum CrawlingPostAPI { case getPostList(nextPageId: String?, requestCnt: Int) case getDetail(postId: String) + case getWorknetFavoritePost } extension CrawlingPostAPI: BaseAPI { @@ -22,18 +23,22 @@ extension CrawlingPostAPI: BaseAPI { public var path: String { switch self { - case .getPostList(let nextPageId, let requestCnt): + case .getPostList: "" case .getDetail(let postId): "/\(postId)" + case .getWorknetFavoritePost: + "/my/favorites" } } public var method: Moya.Method { switch self { - case .getPostList(let nextPageId, let requestCnt): + case .getPostList: .get - case .getDetail(let postId): + case .getDetail: + .get + case .getWorknetFavoritePost: .get } } diff --git a/project/Projects/Data/DataSource/API/RcruitmentPostAPI.swift b/project/Projects/Data/DataSource/API/RcruitmentPostAPI.swift index b5d6164e..48cf8c5e 100644 --- a/project/Projects/Data/DataSource/API/RcruitmentPostAPI.swift +++ b/project/Projects/Data/DataSource/API/RcruitmentPostAPI.swift @@ -31,8 +31,10 @@ public enum RcruitmentPostAPI { // Worker case getOnGoingNativePostListForWorker(nextPageId: String?, requestCnt: String) - case getFavoritePostListForWorker(nextPageId: String?, requestCnt: String) case getAppliedPostListForWorker(nextPageId: String?, requestCnt: String) + + // Favorite posts + case getNativeFavoritePost case addFavoritePost(id: String, jobPostingType: RecruitmentPostType) case removeFavoritePost(id: String) } @@ -73,11 +75,12 @@ extension RcruitmentPostAPI: BaseAPI { case .getOnGoingNativePostListForWorker: "" - case .getFavoritePostListForWorker: - "/my/favorites" case .getAppliedPostListForWorker: "/carer/my/applied" + + case .getNativeFavoritePost: + "/my/favorites" case .addFavoritePost(let id, _): "/\(id)/favorites" case .removeFavoritePost(let id): @@ -115,11 +118,11 @@ extension RcruitmentPostAPI: BaseAPI { case .getOnGoingNativePostListForWorker: .get - case .getFavoritePostListForWorker: - .get case .getAppliedPostListForWorker: .get + case .getNativeFavoritePost: + .get case .addFavoritePost: .post case .removeFavoritePost: @@ -135,11 +138,6 @@ extension RcruitmentPostAPI: BaseAPI { params["next"] = nextPageId } params["limit"] = requestCnt - case .getFavoritePostListForWorker(let nextPageId, let requestCnt): - if let nextPageId { - params["next"] = nextPageId - } - params["limit"] = requestCnt case .getAppliedPostListForWorker(let nextPageId, let requestCnt): if let nextPageId { params["next"] = nextPageId @@ -156,7 +154,6 @@ extension RcruitmentPostAPI: BaseAPI { var parameterEncoding: ParameterEncoding { switch self { case .getOnGoingNativePostListForWorker, - .getFavoritePostListForWorker, .getAppliedPostListForWorker: return URLEncoding.queryString default: @@ -167,7 +164,6 @@ extension RcruitmentPostAPI: BaseAPI { public var task: Moya.Task { switch self { case .getOnGoingNativePostListForWorker, - .getFavoritePostListForWorker, .getAppliedPostListForWorker: .requestParameters(parameters: bodyParameters ?? [:], encoding: parameterEncoding) case .registerPost(let bodyData): diff --git a/project/Projects/Data/DataSource/DTO/RecruitmentPost/RecuritmentPostListForWorkerDTO.swift b/project/Projects/Data/DataSource/DTO/RecruitmentPost/RecuritmentPostListForWorkerDTO.swift index ed2c3de5..b34ef0c7 100644 --- a/project/Projects/Data/DataSource/DTO/RecruitmentPost/RecuritmentPostListForWorkerDTO.swift +++ b/project/Projects/Data/DataSource/DTO/RecruitmentPost/RecuritmentPostListForWorkerDTO.swift @@ -13,7 +13,7 @@ public protocol EntityRepresentable: Codable { func toEntity() -> Entity } -public struct RecruitmentPostListForWorkerDTO: Codable where T.Entity: RecruitmentPostForWorkerRepresentable { +public struct RecruitmentPostListForWorkerDTO: EntityRepresentable where T.Entity: RecruitmentPostForWorkerRepresentable { public let items: [T] public let next: String? @@ -29,6 +29,18 @@ public struct RecruitmentPostListForWorkerDTO: Codable w } } +public struct FavoriteRecruitmentPostListForWorkerDTO: EntityRepresentable where T.Entity: RecruitmentPostForWorkerRepresentable { + + public let favoriteJobPostings: [T] + + public func toEntity() -> [RecruitmentPostForWorkerRepresentable] { + + favoriteJobPostings.map { dto in + dto.toEntity() + } + } +} + // MARK: Worknet post의 카드 정보 public struct WorkNetRecruitmentPostForWorkerDTO: EntityRepresentable { @@ -41,6 +53,7 @@ public struct WorkNetRecruitmentPostForWorkerDTO: EntityRepresentable { public let applyDeadline: String public let isFavorite: Bool public let jobPostingType: RecruitmentPostType + public let createdAt: String? public func toEntity() -> WorknetRecruitmentPostVO { @@ -49,6 +62,12 @@ public struct WorkNetRecruitmentPostForWorkerDTO: EntityRepresentable { let deadlineDate = dateFormatter.date(from: self.applyDeadline)! + let iso8601Formatter = ISO8601DateFormatter() + var createdDate: Date? + if let createdAt { + createdDate = iso8601Formatter.date(from: createdAt) + } + return .init( id: id, title: title, @@ -58,7 +77,8 @@ public struct WorkNetRecruitmentPostForWorkerDTO: EntityRepresentable { payInfo: payInfo, applyDeadline: deadlineDate, isFavorite: isFavorite, - postType: jobPostingType + postType: jobPostingType, + beFavoritedTime: createdDate ) } } @@ -84,6 +104,7 @@ public struct NativeRecruitmentPostForWorkerDTO: EntityRepresentable { public let applyTime: String? public let isFavorite: Bool public let jobPostingType: RecruitmentPostType + public let createdAt: String? public func toEntity() -> NativeRecruitmentPostForWorkerVO { @@ -97,6 +118,12 @@ public struct NativeRecruitmentPostForWorkerDTO: EntityRepresentable { let deadlineDate = self.applyDeadline != nil ? dateFormatter.date(from: self.applyDeadline!) : nil let applyDate = self.applyTime != nil ? dateFormatter.date(from: self.applyDeadline!) : nil + let iso8601Formatter = ISO8601DateFormatter() + var createdDate: Date? + if let createdAt { + createdDate = iso8601Formatter.date(from: createdAt) + } + return .init( postId: id, workDays: workDayList, @@ -115,7 +142,8 @@ public struct NativeRecruitmentPostForWorkerDTO: EntityRepresentable { distanceFromWorkPlace: distance, applyTime: applyDate, isFavorite: isFavorite, - postType: jobPostingType + postType: jobPostingType, + beFavoritedTime: createdDate ) } } diff --git a/project/Projects/Data/DataSource/Util/Extension/Single+Extension.swift b/project/Projects/Data/DataSource/Util/Extension/Single+Extension.swift index 34030e83..252f8d9b 100644 --- a/project/Projects/Data/DataSource/Util/Extension/Single+Extension.swift +++ b/project/Projects/Data/DataSource/Util/Extension/Single+Extension.swift @@ -15,9 +15,17 @@ public extension PrimitiveSequence where Trait == SingleTrait, Element == Respon func mapToEntity(_ type: T.Type) -> Single { map(T.self) - .map { dto in - dto.toEntity() - } + .catch({ error in + if let moyaError = error as? MoyaError, case .objectMapping(let error, _) = moyaError { + #if DEBUG + print("[디코딩에러] \(String(describing: T.self))") + #endif + } + return .error(error) + }) + .map { dto in + dto.toEntity() + } } } diff --git a/project/Projects/Domain/ConcreteUseCase/RecruitmentPost/DefualtRecruitmentPostUseCase.swift b/project/Projects/Domain/ConcreteUseCase/RecruitmentPost/DefualtRecruitmentPostUseCase.swift index d293a6d8..58969877 100644 --- a/project/Projects/Domain/ConcreteUseCase/RecruitmentPost/DefualtRecruitmentPostUseCase.swift +++ b/project/Projects/Domain/ConcreteUseCase/RecruitmentPost/DefualtRecruitmentPostUseCase.swift @@ -125,30 +125,18 @@ public class DefaultRecruitmentPostUseCase: RecruitmentPostUseCase { return convert(task: stream) } - public func getFavoritePostListForWorker(request: PostPagingRequestForWorker, postCount: Int) -> RxSwift.Single> { + public func getFavoritePostListForWorker() -> RxSwift.Single> { - let stream: Single! + let nativeList = repository.getNativeFavoritePostListForWorker() + let worknetList = repository.getWorknetFavoritePostListForWorker() - switch request { - case .initial: - stream = repository.getFavoritePostListForWorker( - nextPageId: nil, - requestCnt: postCount - ) - case .paging(let source, let nextPageId): - switch source { - case .native: - stream = repository.getFavoritePostListForWorker( - nextPageId: nextPageId, - requestCnt: postCount - ) - case .thirdParty: - // TODO: ‼️ ‼️워크넷 가져오기 미구현 - fatalError() + let task = Single + .zip(nativeList, worknetList) + .map { (native, worknet) in + native + worknet } - } - return convert(task: stream) + return convert(task: task) } public func getAppliedPostListForWorker(request: PostPagingRequestForWorker, postCount: Int) -> RxSwift.Single> { diff --git a/project/Projects/Domain/Entity/VO/Post/List/NativeRecruitmentPostForWorkerVO.swift b/project/Projects/Domain/Entity/VO/Post/List/NativeRecruitmentPostForWorkerVO.swift index 513d3cc0..b771c191 100644 --- a/project/Projects/Domain/Entity/VO/Post/List/NativeRecruitmentPostForWorkerVO.swift +++ b/project/Projects/Domain/Entity/VO/Post/List/NativeRecruitmentPostForWorkerVO.swift @@ -9,7 +9,9 @@ import Foundation public struct NativeRecruitmentPostForWorkerVO: RecruitmentPostForWorkerRepresentable { + // protocol required public var postType: RecruitmentPostType + public var beFavoritedTime: Date? public let postId: String @@ -34,6 +36,7 @@ public struct NativeRecruitmentPostForWorkerVO: RecruitmentPostForWorkerRepresen public let applyTime: Date? public let isFavorite: Bool + public init( postId: String, workDays: [WorkDay], @@ -52,7 +55,8 @@ public struct NativeRecruitmentPostForWorkerVO: RecruitmentPostForWorkerRepresen distanceFromWorkPlace: Int, applyTime: Date?, isFavorite: Bool, - postType: RecruitmentPostType + postType: RecruitmentPostType, + beFavoritedTime: Date? ) { self.postId = postId self.workDays = workDays @@ -72,6 +76,7 @@ public struct NativeRecruitmentPostForWorkerVO: RecruitmentPostForWorkerRepresen self.applyTime = applyTime self.isFavorite = isFavorite self.postType = postType + self.beFavoritedTime = beFavoritedTime } public static let mock = NativeRecruitmentPostForWorkerVO( @@ -92,6 +97,7 @@ public struct NativeRecruitmentPostForWorkerVO: RecruitmentPostForWorkerRepresen distanceFromWorkPlace: 2500, applyTime: Date(), isFavorite: true, - postType: .native + postType: .native, + beFavoritedTime: Calendar.current.date(byAdding: .day, value: 7, to: Date()) ) } diff --git a/project/Projects/Domain/Entity/VO/Post/List/RecruitmentPostListForWorkerVO.swift b/project/Projects/Domain/Entity/VO/Post/List/RecruitmentPostListForWorkerVO.swift index f02632c1..87186311 100644 --- a/project/Projects/Domain/Entity/VO/Post/List/RecruitmentPostListForWorkerVO.swift +++ b/project/Projects/Domain/Entity/VO/Post/List/RecruitmentPostListForWorkerVO.swift @@ -19,7 +19,7 @@ public struct RecruitmentPostListForWorkerVO { self.fetchedPostCount = fetchedPostCount } } - public protocol RecruitmentPostForWorkerRepresentable { var postType: RecruitmentPostType { get } + var beFavoritedTime: Date? { get } } diff --git a/project/Projects/Domain/Entity/VO/Post/List/WorknetRecruitmentPostForWorkerVO.swift b/project/Projects/Domain/Entity/VO/Post/List/WorknetRecruitmentPostForWorkerVO.swift index fd6c0562..2a69386f 100644 --- a/project/Projects/Domain/Entity/VO/Post/List/WorknetRecruitmentPostForWorkerVO.swift +++ b/project/Projects/Domain/Entity/VO/Post/List/WorknetRecruitmentPostForWorkerVO.swift @@ -9,7 +9,9 @@ import Foundation public struct WorknetRecruitmentPostVO: RecruitmentPostForWorkerRepresentable { - public let postType: RecruitmentPostType + // protocol required + public var postType: RecruitmentPostType + public var beFavoritedTime: Date? public let id: String public let title: String @@ -29,7 +31,8 @@ public struct WorknetRecruitmentPostVO: RecruitmentPostForWorkerRepresentable { payInfo: String, applyDeadline: Date, isFavorite: Bool, - postType: RecruitmentPostType + postType: RecruitmentPostType, + beFavoritedTime: Date? = nil ) { self.id = id self.title = title @@ -40,5 +43,6 @@ public struct WorknetRecruitmentPostVO: RecruitmentPostForWorkerRepresentable { self.applyDeadline = applyDeadline self.isFavorite = isFavorite self.postType = postType + self.beFavoritedTime = beFavoritedTime } } diff --git a/project/Projects/Domain/RepositoryInterface/RecruitmentPost/RecruitmentPostRepository.swift b/project/Projects/Domain/RepositoryInterface/RecruitmentPost/RecruitmentPostRepository.swift index bee72ff8..e920fd7c 100644 --- a/project/Projects/Domain/RepositoryInterface/RecruitmentPost/RecruitmentPostRepository.swift +++ b/project/Projects/Domain/RepositoryInterface/RecruitmentPost/RecruitmentPostRepository.swift @@ -52,8 +52,11 @@ public protocol RecruitmentPostRepository: RepositoryBase { /// 요양보호사가 확인하는 케어밋 자체 공고정보를 가져옵니다. func getNativePostListForWorker(nextPageId: String?, requestCnt: Int) -> Single - /// 요양보호사가 확인하는 케어밋 자체 공고정보를 가져옵니다. - func getFavoritePostListForWorker(nextPageId: String?, requestCnt: Int) -> Single + /// 요양보호사가 즐겨찾는 케어밋 자체 공고정보를 가져옵니다. + func getNativeFavoritePostListForWorker() -> Single<[RecruitmentPostForWorkerRepresentable]> + + /// 요양보호사가 즐겨찾는 워크넷 공고정보를 가져옵니다. + func getWorknetFavoritePostListForWorker() -> Single<[RecruitmentPostForWorkerRepresentable]> /// 요양보호사가 확인하는 케어밋 자체 공고정보를 가져옵니다. func getAppliedPostListForWorker(nextPageId: String?, requestCnt: Int) -> Single diff --git a/project/Projects/Domain/UseCaseInterface/RecruitmentPost/RecruitmentPostUseCase.swift b/project/Projects/Domain/UseCaseInterface/RecruitmentPost/RecruitmentPostUseCase.swift index 3d4c778b..a1689a7a 100644 --- a/project/Projects/Domain/UseCaseInterface/RecruitmentPost/RecruitmentPostUseCase.swift +++ b/project/Projects/Domain/UseCaseInterface/RecruitmentPost/RecruitmentPostUseCase.swift @@ -56,7 +56,7 @@ public protocol RecruitmentPostUseCase: UseCaseBase { func getPostListForWorker(request: PostPagingRequestForWorker, postCount: Int) -> Single> /// 요양보호사가 즐겨찾기한 공고리스트를 호출합니다. - func getFavoritePostListForWorker(request: PostPagingRequestForWorker, postCount: Int) -> Single> + func getFavoritePostListForWorker() -> Single> /// 요양보호사가 지원한 공고리스트를 호출합니다. func getAppliedPostListForWorker(request: PostPagingRequestForWorker, postCount: Int) -> Single> diff --git a/project/Projects/Presentation/Feature/Worker/Sources/ViewModel/RecruitmentPost/StarredPostBoardVM.swift b/project/Projects/Presentation/Feature/Worker/Sources/ViewModel/RecruitmentPost/StarredPostBoardVM.swift index ff3546d2..756f7041 100644 --- a/project/Projects/Presentation/Feature/Worker/Sources/ViewModel/RecruitmentPost/StarredPostBoardVM.swift +++ b/project/Projects/Presentation/Feature/Worker/Sources/ViewModel/RecruitmentPost/StarredPostBoardVM.swift @@ -29,102 +29,53 @@ public class StarredPostBoardVM: BaseViewModel, WorkerAppliablePostBoardVMable { public weak var coordinator: WorkerRecruitmentBoardCoordinatable? public let recruitmentPostUseCase: RecruitmentPostUseCase - // Paging - /// 값이 nil이라면 요청을 보내지 않습니다. - var nextPagingRequest: PostPagingRequestForWorker? - /// 가장최신의 데이터를 홀드, 다음 요청시 해당데이터에 새로운 데이터를 더해서 방출 - private let currentPostVO: BehaviorRelay<[RecruitmentPostForWorkerRepresentable]> = .init(value: []) - public init(coordinator: WorkerRecruitmentBoardCoordinatable, recruitmentPostUseCase: RecruitmentPostUseCase) { self.coordinator = coordinator self.recruitmentPostUseCase = recruitmentPostUseCase - self.nextPagingRequest = .initial super.init() - var loadingStartObservables: [Observable] = [] - var loadingEndObservables: [Observable] = [] - // MARK: 공고리스트 처음부터 요청하기 - let initialRequest = requestInitialPageRequest - .flatMap { [weak self, recruitmentPostUseCase] request in + let initialRequestResult = requestInitialPageRequest + .flatMap { [weak self, recruitmentPostUseCase] _ in - self?.currentPostVO.accept([]) - self?.nextPagingRequest = .initial + self?.showLoading.onNext(()) return recruitmentPostUseCase - .getFavoritePostListForWorker( - request: .initial, - postCount: 10 - ) + .getFavoritePostListForWorker() } .share() - // 로딩 시작 - loadingStartObservables.append(initialRequest.map { _ in }) - - // MARK: 공고리스트 페이징 요청 - let pagingRequest = requestNextPage - .compactMap { [weak self] _ in - // 요청이 없는 경우 요청을 보내지 않는다. - // ThirdPatry에서도 불러올 데이터가 없는 경우입니다. - self?.nextPagingRequest - } - .flatMap { [recruitmentPostUseCase] request in - recruitmentPostUseCase - .getFavoritePostListForWorker( - request: request, - postCount: 10 - ) - } - - let postPageReqeustResult = Observable - .merge(initialRequest, pagingRequest) - .share() - - // 로딩 종료 - loadingEndObservables.append(postPageReqeustResult.map { _ in }) + initialRequestResult + .subscribe(onNext: { [weak self] _ in + guard let self else { return } + dismissLoading.onNext(()) + }) + .disposed(by: disposeBag) - let requestPostListSuccess = postPageReqeustResult.compactMap { $0.value } - let requestPostListFailure = postPageReqeustResult.compactMap { $0.error } + let initialRequestSuccess = initialRequestResult.compactMap { $0.value } + let initialRequestFailure = initialRequestResult.compactMap { $0.error } - postBoardData = Observable - .zip( - currentPostVO, - requestPostListSuccess - ) - .compactMap { [weak self] (prevPostList, fetchedData) -> BoardRefreshResult? in - - guard let self else { return nil } - - let isRefreshed: Bool = self.nextPagingRequest == .initial - - // TODO: ‼️ ‼️ 즐겨찾기 공고의 경우 서버에서 아직 워크넷 공고를 처리하는 방법을 정하지 못했음으로 추후에 수정할 예정입니다. + postBoardData = initialRequestSuccess + .map({ list in - if let next = fetchedData.nextPageId { - // 지원 공고의 경우 써드파티에서 불러올 데이터가 없다. - self.nextPagingRequest = .paging( - source: .native, - nextPageId: next - ) - } else { - self.nextPagingRequest = nil + let sortedList = list.sorted { lhs, rhs in + guard let lhsDate = lhs.beFavoritedTime, let rhsDate = rhs.beFavoritedTime else { + return false + } + + // 최신값을 배열의 앞쪽(화면의 상단)에 노출 + + return lhsDate > rhsDate } - // 화면에 표시할 전체리스트 도출 - let fetchedPosts = fetchedData.posts - var mergedPosts = currentPostVO.value - mergedPosts.append(contentsOf: fetchedPosts) - - // 최근값 업데이트 - self.currentPostVO.accept(mergedPosts) - - return (isRefreshed, mergedPosts) - } + return (true, sortedList) + }) .asDriver(onErrorDriveWith: .never()) // MARK: 지원하기 let applyRequest: PublishRelay = .init() + self.idleAlertVM = applyButtonClicked .map { (postId: String, postTitle: String) in DefaultIdleAlertVM( @@ -136,20 +87,18 @@ public class StarredPostBoardVM: BaseViewModel, WorkerAppliablePostBoardVMable { } } .asDriver(onErrorDriveWith: .never()) - - // 로딩 시작 - loadingStartObservables.append(applyRequest.map { _ in }) let applyRequestResult = applyRequest - .flatMap { [recruitmentPostUseCase] postId in + .flatMap { [weak self, recruitmentPostUseCase] postId in + + self?.showLoading.onNext(()) + // 리스트화면에서는 앱내 지원만 지원합니다. - recruitmentPostUseCase + return recruitmentPostUseCase .applyToPost(postId: postId, method: .app) } .share() - // 로딩 종료 - loadingEndObservables.append(applyRequestResult.map { _ in }) let applyRequestFailure = applyRequestResult.compactMap { $0.error } @@ -161,7 +110,7 @@ public class StarredPostBoardVM: BaseViewModel, WorkerAppliablePostBoardVMable { ) } - let requestPostListFailureAlert = requestPostListFailure + let requestPostListFailureAlert = initialRequestFailure .map { error in DefaultAlertContentVO( title: "즐겨찾기한 공고 불러오기 오류", @@ -171,19 +120,22 @@ public class StarredPostBoardVM: BaseViewModel, WorkerAppliablePostBoardVMable { Observable .merge(applyRequestFailureAlert, requestPostListFailureAlert) - .subscribe(self.alert) - .disposed(by: disposeBag) - - // MARK: 로딩 - Observable - .merge(loadingStartObservables) - .subscribe(self.showLoading) + .subscribe(onNext: { [weak self] alertVO in + guard let self else { return } + alert.onNext(alertVO) + }) .disposed(by: disposeBag) + // MARK: 로딩 종료 Observable - .merge(loadingEndObservables) - .delay(.milliseconds(300), scheduler: MainScheduler.instance) - .subscribe(self.dismissLoading) + .merge( + initialRequestResult.map({ _ in }), + applyRequestResult.map({ _ in }) + ) + .subscribe(onNext: { [weak self] _ in + guard let self else { return } + dismissLoading.onNext(()) + }) .disposed(by: disposeBag) } }