From 3b5a0b7d25124fd8e6ee79e7cd92ad156291ea1d Mon Sep 17 00:00:00 2001 From: Lee SeJin Date: Sat, 6 Apr 2024 00:49:51 +0900 Subject: [PATCH] =?UTF-8?q?[Feat]=20#360=20-=20=ED=8C=8C=ED=8A=B8=20?= =?UTF-8?q?=EB=82=B4=20=EB=9E=AD=ED=82=B9=20API=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Repository/RankingRepository.swift | 9 ++++++ .../RankingRepositoryInterface.swift | 1 + .../Sources/UseCase/RankingUseCase.swift | 11 +++++++ .../StampFeature/Interface/Sources/Part.swift | 29 +++++++++++++++++++ .../Sources/StampFeatureBuildable.swift | 1 + .../StampFeatureViewControllable.swift | 25 +++++++++------- .../Coordinator/RankingCoordinator.swift | 13 ++++----- .../Cells/PartRankingListCVC.swift | 10 ++++--- .../RankingScene/VC/PartRankingVC.swift | 11 +++---- .../Sources/RankingScene/VC/RankingVC.swift | 10 +++++-- .../ViewModel/RankingViewModel.swift | 8 +++-- .../Networks/Sources/API/RankAPI.swift | 3 ++ .../Sources/Service/RankService.swift | 5 ++++ 13 files changed, 106 insertions(+), 30 deletions(-) create mode 100644 SOPT-iOS/Projects/Features/StampFeature/Interface/Sources/Part.swift diff --git a/SOPT-iOS/Projects/Data/Sources/Repository/RankingRepository.swift b/SOPT-iOS/Projects/Data/Sources/Repository/RankingRepository.swift index 4040da0a..aa126153 100644 --- a/SOPT-iOS/Projects/Data/Sources/Repository/RankingRepository.swift +++ b/SOPT-iOS/Projects/Data/Sources/Repository/RankingRepository.swift @@ -39,4 +39,13 @@ extension RankingRepository: RankingRepositoryInterface { $0.map { $0.toDomain() } }.eraseToAnyPublisher() } + + public func fetchRankingListInPart(part: String) -> AnyPublisher<[RankingModel], Error> { + return self.rankService + .fetchRankingListInPart(part: part) + .map { + $0.map { $0.toDomain() } + } + .eraseToAnyPublisher() + } } diff --git a/SOPT-iOS/Projects/Domain/Sources/RepositoryInterface/RankingRepositoryInterface.swift b/SOPT-iOS/Projects/Domain/Sources/RepositoryInterface/RankingRepositoryInterface.swift index c44b3c4d..18e849ff 100644 --- a/SOPT-iOS/Projects/Domain/Sources/RepositoryInterface/RankingRepositoryInterface.swift +++ b/SOPT-iOS/Projects/Domain/Sources/RepositoryInterface/RankingRepositoryInterface.swift @@ -11,4 +11,5 @@ import Combine public protocol RankingRepositoryInterface { func fetchRankingListModel(isCurrentGeneration: Bool) -> AnyPublisher<[RankingModel], Error> func fetchPartRanking() -> AnyPublisher<[Domain.PartRankingModel], Error> + func fetchRankingListInPart(part: String) -> AnyPublisher<[RankingModel], Error> } diff --git a/SOPT-iOS/Projects/Domain/Sources/UseCase/RankingUseCase.swift b/SOPT-iOS/Projects/Domain/Sources/UseCase/RankingUseCase.swift index 0946b2aa..c8d3b7ec 100644 --- a/SOPT-iOS/Projects/Domain/Sources/UseCase/RankingUseCase.swift +++ b/SOPT-iOS/Projects/Domain/Sources/UseCase/RankingUseCase.swift @@ -12,6 +12,7 @@ import Core public protocol RankingUseCase { func fetchRankingList(isCurrentGeneration: Bool) + func fetchRankingList(part: String) func findMyRanking() func fetchPartRanking() @@ -61,6 +62,16 @@ extension DefaultRankingUseCase: RankingUseCase { }.store(in: cancelBag) } + public func fetchRankingList(part: String) { + self.repository + .fetchRankingListInPart(part: part) + .sink { completion in + print(completion) + } receiveValue: { [weak self] rankingModels in + self?.rankingListModelFetched.send(rankingModels) + }.store(in: cancelBag) + } + public func findMyRanking() { let myRankingIndex = self.findMyRankingIndex(model: rankingListModelFetched.value) diff --git a/SOPT-iOS/Projects/Features/StampFeature/Interface/Sources/Part.swift b/SOPT-iOS/Projects/Features/StampFeature/Interface/Sources/Part.swift new file mode 100644 index 00000000..56a9a414 --- /dev/null +++ b/SOPT-iOS/Projects/Features/StampFeature/Interface/Sources/Part.swift @@ -0,0 +1,29 @@ +// +// Part.swift +// StampFeatureInterface +// +// Created by Aiden.lee on 2024/04/06. +// Copyright © 2024 SOPT-iOS. All rights reserved. +// + +import Foundation + +public enum Part: String, CaseIterable { + case plan = "기획" + case design = "디자인" + case web = "웹" + case ios = "아요" + case android = "안드" + case server = "서버" + + public func uppercasedName() -> String { + switch self { + case .plan: return "PLAN" + case .design: return "DESIGN" + case .web: return "WEB" + case .ios: return "IOS" + case .android: return "ANDROID" + case .server: return "SERVER" + } + } +} diff --git a/SOPT-iOS/Projects/Features/StampFeature/Interface/Sources/StampFeatureBuildable.swift b/SOPT-iOS/Projects/Features/StampFeature/Interface/Sources/StampFeatureBuildable.swift index a151fdf1..8848820d 100644 --- a/SOPT-iOS/Projects/Features/StampFeature/Interface/Sources/StampFeatureBuildable.swift +++ b/SOPT-iOS/Projects/Features/StampFeature/Interface/Sources/StampFeatureBuildable.swift @@ -14,6 +14,7 @@ public enum RankingViewType { case all case currentGeneration(info: UsersActiveGenerationStatusViewResponse) case partRanking + case individualRankingInPart(part: Part) } public protocol StampFeatureViewBuildable { diff --git a/SOPT-iOS/Projects/Features/StampFeature/Interface/Sources/StampFeatureViewControllable.swift b/SOPT-iOS/Projects/Features/StampFeature/Interface/Sources/StampFeatureViewControllable.swift index 90939227..d652bffd 100644 --- a/SOPT-iOS/Projects/Features/StampFeature/Interface/Sources/StampFeatureViewControllable.swift +++ b/SOPT-iOS/Projects/Features/StampFeature/Interface/Sources/StampFeatureViewControllable.swift @@ -12,22 +12,27 @@ import Domain public protocol MissionListViewControllable: ViewControllable & MissionListCoordinatable { } public protocol MissionListCoordinatable { - var onSwiped: (() -> Void)? { get set } - var onNaviBackTap: (() -> Void)? { get set } - var onPartRankingButtonTap: ((RankingViewType) -> Void)? { get set } - var onCurrentGenerationRankingButtonTap: ((RankingViewType) -> Void)? { get set } - var onGuideTap: (() -> Void)? { get set } - var onCellTap: ((MissionListModel, _ username: String?) -> Void)? { get set } + var onSwiped: (() -> Void)? { get set } + var onNaviBackTap: (() -> Void)? { get set } + var onPartRankingButtonTap: ((RankingViewType) -> Void)? { get set } + var onCurrentGenerationRankingButtonTap: ((RankingViewType) -> Void)? { get set } + var onGuideTap: (() -> Void)? { get set } + var onCellTap: ((MissionListModel, _ username: String?) -> Void)? { get set } } public protocol ListDetailViewControllable: ViewControllable & ListDetailCoordinatable { } public protocol ListDetailCoordinatable { - var onComplete: ((StarViewLevel, (() -> Void)?) -> Void)? { get set } + var onComplete: ((StarViewLevel, (() -> Void)?) -> Void)? { get set } } public protocol MissionCompletedViewControllable: ViewControllable { } public protocol RankingViewControllable: ViewControllable & RankingCoordinatable { } public protocol RankingCoordinatable { - var onCellTap: ((_ username: String, _ sentence: String) -> Void)? { get set } - var onNaviBackTap: (() -> Void)? { get set } + var onCellTap: ((_ username: String, _ sentence: String) -> Void)? { get set } + var onNaviBackTap: (() -> Void)? { get set } } -public protocol PartRankingViewControllable: ViewControllable & RankingCoordinatable { } + +public protocol PartRankingCoordinatable { + var onCellTap: ((_ part: Part) -> Void)? { get set } + var onNaviBackTap: (() -> Void)? { get set } +} +public protocol PartRankingViewControllable: ViewControllable & PartRankingCoordinatable { } public protocol StampGuideViewControllable: ViewControllable { } diff --git a/SOPT-iOS/Projects/Features/StampFeature/Sources/Coordinator/RankingCoordinator.swift b/SOPT-iOS/Projects/Features/StampFeature/Sources/Coordinator/RankingCoordinator.swift index 48a845c0..a5f4e26c 100644 --- a/SOPT-iOS/Projects/Features/StampFeature/Sources/Coordinator/RankingCoordinator.swift +++ b/SOPT-iOS/Projects/Features/StampFeature/Sources/Coordinator/RankingCoordinator.swift @@ -32,22 +32,21 @@ final class RankingCoordinator: DefaultCoordinator { public override func start() { switch rankingViewType { - case .all, .currentGeneration: - showRanking() + case .all, .currentGeneration, .individualRankingInPart: + showRanking(rankingViewType: rankingViewType) case .partRanking: showPartRanking() } } - private func showRanking() { - var ranking = factory.makeRankingVC(rankingViewType: self.rankingViewType) + private func showRanking(rankingViewType: RankingViewType) { + var ranking = factory.makeRankingVC(rankingViewType: rankingViewType) ranking.onCellTap = { [weak self] (username, sentence) in self?.showOtherMissionList(username, sentence) } ranking.onNaviBackTap = { [weak self] in self?.router.popModule() - self?.finishFlow?() } router.push(ranking) } @@ -55,8 +54,8 @@ final class RankingCoordinator: DefaultCoordinator { private func showPartRanking() { var ranking = factory.makePartRankingVC(rankingViewType: self.rankingViewType) - ranking.onCellTap = { [weak self] (username, sentence) in - self?.showOtherMissionList(username, sentence) + ranking.onCellTap = { [weak self] part in + self?.showRanking(rankingViewType: .individualRankingInPart(part: part)) } ranking.onNaviBackTap = { [weak self] in self?.router.popModule() diff --git a/SOPT-iOS/Projects/Features/StampFeature/Sources/RankingScene/Cells/PartRankingListCVC.swift b/SOPT-iOS/Projects/Features/StampFeature/Sources/RankingScene/Cells/PartRankingListCVC.swift index e18d4989..38ac42d4 100644 --- a/SOPT-iOS/Projects/Features/StampFeature/Sources/RankingScene/Cells/PartRankingListCVC.swift +++ b/SOPT-iOS/Projects/Features/StampFeature/Sources/RankingScene/Cells/PartRankingListCVC.swift @@ -20,6 +20,7 @@ final class PartRankingListCVC: UICollectionViewCell, UICollectionViewRegisterab // MARK: - Properties static var isFromNib: Bool = false + var model: PartRankingModel? // MARK: - UI Components @@ -95,10 +96,11 @@ extension PartRankingListCVC { extension PartRankingListCVC { - public func setData(rank: Int, partName: String, score: Int) { - rankLabel.text = String(rank) - partNameLabel.text = partName - scoreLabel.text = "\(score)점" + public func setData(model: PartRankingModel) { + self.model = model + rankLabel.text = String(model.rank) + partNameLabel.text = model.part + scoreLabel.text = "\(model.points)점" scoreLabel.partFontChange(targetString: "점", font: DSKitFontFamily.Pretendard.medium.font(size: 12)) setDefaultRanking() diff --git a/SOPT-iOS/Projects/Features/StampFeature/Sources/RankingScene/VC/PartRankingVC.swift b/SOPT-iOS/Projects/Features/StampFeature/Sources/RankingScene/VC/PartRankingVC.swift index 346c807b..a9fa6810 100644 --- a/SOPT-iOS/Projects/Features/StampFeature/Sources/RankingScene/VC/PartRankingVC.swift +++ b/SOPT-iOS/Projects/Features/StampFeature/Sources/RankingScene/VC/PartRankingVC.swift @@ -30,7 +30,7 @@ public class PartRankingVC: UIViewController, PartRankingViewControllable { // MARK: - RankingCoordinatable - public var onCellTap: ((String, String) -> Void)? + public var onCellTap: ((Part) -> Void)? public var onNaviBackTap: (() -> Void)? // MARK: - UI Components @@ -159,7 +159,7 @@ extension PartRankingVC { case .list: guard let rankingListCell = collectionView.dequeueReusableCell(withReuseIdentifier: PartRankingListCVC.className, for: indexPath) as? PartRankingListCVC, let model = itemIdentifier as? PartRankingModel else { return UICollectionViewCell() } - rankingListCell.setData(rank: model.rank, partName: model.part, score: model.points) + rankingListCell.setData(model: model) return rankingListCell } @@ -186,8 +186,9 @@ extension PartRankingVC: UICollectionViewDelegate { public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { guard indexPath.section >= 1 else { return } - guard let tappedCell = collectionView.cellForItem(at: indexPath) as? RankingListTappable, - let item = tappedCell.getModelItem() else { return } - self.onCellTap?(item.username, item.sentence) + guard let tappedCell = collectionView.cellForItem(at: indexPath) as? PartRankingListCVC, + let model = tappedCell.model else { return } + guard let part = Part(rawValue: model.part) else { return } + self.onCellTap?(part) } } diff --git a/SOPT-iOS/Projects/Features/StampFeature/Sources/RankingScene/VC/RankingVC.swift b/SOPT-iOS/Projects/Features/StampFeature/Sources/RankingScene/VC/RankingVC.swift index 675f3851..1581313f 100644 --- a/SOPT-iOS/Projects/Features/StampFeature/Sources/RankingScene/VC/RankingVC.swift +++ b/SOPT-iOS/Projects/Features/StampFeature/Sources/RankingScene/VC/RankingVC.swift @@ -17,6 +17,7 @@ import SnapKit import Then import StampFeatureInterface +import BaseFeatureDependency public class RankingVC: UIViewController, RankingViewControllable { @@ -73,10 +74,15 @@ public class RankingVC: UIViewController, RankingViewControllable { super.init(nibName: nil, bundle: nil) - guard case .currentGeneration(let info) = rankingViewType else { return } - + if case .currentGeneration(let info) = rankingViewType { let navigationTitle = String(describing: info.currentGeneration) + "기 랭킹" self.naviBar.setTitle(navigationTitle) + } + + if case .individualRankingInPart(let part) = rankingViewType { + let navigationTitle = String(describing: part.rawValue) + " 랭킹" + self.naviBar.setTitle(navigationTitle) + } } required init?(coder: NSCoder) { diff --git a/SOPT-iOS/Projects/Features/StampFeature/Sources/RankingScene/ViewModel/RankingViewModel.swift b/SOPT-iOS/Projects/Features/StampFeature/Sources/RankingScene/ViewModel/RankingViewModel.swift index 11b25fac..3158c251 100644 --- a/SOPT-iOS/Projects/Features/StampFeature/Sources/RankingScene/ViewModel/RankingViewModel.swift +++ b/SOPT-iOS/Projects/Features/StampFeature/Sources/RankingScene/ViewModel/RankingViewModel.swift @@ -55,8 +55,12 @@ extension RankingViewModel { .withUnretained(self) .sink { owner, _ in switch self.rankingViewType { - case .all: owner.useCase.fetchRankingList(isCurrentGeneration: false) - case .currentGeneration: owner.useCase.fetchRankingList(isCurrentGeneration: true) + case .all: + owner.useCase.fetchRankingList(isCurrentGeneration: false) + case .currentGeneration: + owner.useCase.fetchRankingList(isCurrentGeneration: true) + case .individualRankingInPart(let part): + owner.useCase.fetchRankingList(part: part.uppercasedName()) default: return } diff --git a/SOPT-iOS/Projects/Modules/Networks/Sources/API/RankAPI.swift b/SOPT-iOS/Projects/Modules/Networks/Sources/API/RankAPI.swift index 01e98edd..10644249 100644 --- a/SOPT-iOS/Projects/Modules/Networks/Sources/API/RankAPI.swift +++ b/SOPT-iOS/Projects/Modules/Networks/Sources/API/RankAPI.swift @@ -16,6 +16,7 @@ public enum RankAPI { case currentRank case rankDetail(userName: String) case rankPart + case currentRankInPart(partName: String) } extension RankAPI: BaseAPI { @@ -42,6 +43,8 @@ extension RankAPI: BaseAPI { return "/detail" case .rankPart: return "/part" + case .currentRankInPart(let partName): + return "/current/part/\(partName)" } } diff --git a/SOPT-iOS/Projects/Modules/Networks/Sources/Service/RankService.swift b/SOPT-iOS/Projects/Modules/Networks/Sources/Service/RankService.swift index b3f70b91..fdb0b9e7 100644 --- a/SOPT-iOS/Projects/Modules/Networks/Sources/Service/RankService.swift +++ b/SOPT-iOS/Projects/Modules/Networks/Sources/Service/RankService.swift @@ -18,6 +18,7 @@ public protocol RankService { func fetchRankingList(isCurrentGeneration: Bool) -> AnyPublisher<[RankingEntity], Error> func fetchRankDetail(userName: String) -> AnyPublisher func fetchPartRanking() -> AnyPublisher<[PartRankingEntity], Error> + func fetchRankingListInPart(part: String) -> AnyPublisher<[RankingEntity], Error> } extension DefaultRankService: RankService { @@ -32,4 +33,8 @@ extension DefaultRankService: RankService { public func fetchPartRanking() -> AnyPublisher<[PartRankingEntity], Error> { requestObjectInCombine(.rankPart) } + + public func fetchRankingListInPart(part: String) -> AnyPublisher<[RankingEntity], Error> { + requestObjectInCombine(.currentRankInPart(partName: part)) + } }