diff --git a/POME.xcodeproj/project.pbxproj b/POME.xcodeproj/project.pbxproj index 11bf8641..27b05fee 100644 --- a/POME.xcodeproj/project.pbxproj +++ b/POME.xcodeproj/project.pbxproj @@ -44,6 +44,11 @@ 2367FC57292BDBC0006ED970 /* ProgressBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2367FC56292BDBC0006ED970 /* ProgressBarView.swift */; }; 2367FC59292BDC96006ED970 /* GoalTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2367FC58292BDC96006ED970 /* GoalTableViewCell.swift */; }; 2367FC5C292BECB8006ED970 /* ImagePopUpViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2367FC5B292BECB8006ED970 /* ImagePopUpViewController.swift */; }; + 2375E4892A20397400843056 /* MyPageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2375E4882A20397400843056 /* MyPageViewModel.swift */; }; + 2375E48C2A20401B00843056 /* GetFinishedGoalsUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2375E48B2A20401B00843056 /* GetFinishedGoalsUseCase.swift */; }; + 2375E48E2A20409300843056 /* GetMarshmallowsUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2375E48D2A20409200843056 /* GetMarshmallowsUseCase.swift */; }; + 2375E4902A2040FC00843056 /* MarshmallowRepositoryInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2375E48F2A2040FC00843056 /* MarshmallowRepositoryInterface.swift */; }; + 2375E4922A20415B00843056 /* MarshmallowRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2375E4912A20415B00843056 /* MarshmallowRepository.swift */; }; 23808775291B3ACF00072763 /* RegisterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23808774291B3ACF00072763 /* RegisterViewController.swift */; }; 23808777291B404A00072763 /* UITextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23808776291B404A00072763 /* UITextField.swift */; }; 2380877B291B445100072763 /* DefaultButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2380877A291B445100072763 /* DefaultButton.swift */; }; @@ -315,6 +320,11 @@ 2367FC56292BDBC0006ED970 /* ProgressBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressBarView.swift; sourceTree = ""; }; 2367FC58292BDC96006ED970 /* GoalTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoalTableViewCell.swift; sourceTree = ""; }; 2367FC5B292BECB8006ED970 /* ImagePopUpViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePopUpViewController.swift; sourceTree = ""; }; + 2375E4882A20397400843056 /* MyPageViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageViewModel.swift; sourceTree = ""; }; + 2375E48B2A20401B00843056 /* GetFinishedGoalsUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetFinishedGoalsUseCase.swift; sourceTree = ""; }; + 2375E48D2A20409200843056 /* GetMarshmallowsUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetMarshmallowsUseCase.swift; sourceTree = ""; }; + 2375E48F2A2040FC00843056 /* MarshmallowRepositoryInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarshmallowRepositoryInterface.swift; sourceTree = ""; }; + 2375E4912A20415B00843056 /* MarshmallowRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarshmallowRepository.swift; sourceTree = ""; }; 23808774291B3ACF00072763 /* RegisterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegisterViewController.swift; sourceTree = ""; }; 23808776291B404A00072763 /* UITextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITextField.swift; sourceTree = ""; }; 2380877A291B445100072763 /* DefaultButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultButton.swift; sourceTree = ""; }; @@ -695,6 +705,23 @@ path = PopUp; sourceTree = ""; }; + 2375E4872A20396600843056 /* MyPage */ = { + isa = PBXGroup; + children = ( + 2375E4882A20397400843056 /* MyPageViewModel.swift */, + ); + path = MyPage; + sourceTree = ""; + }; + 2375E48A2A20400E00843056 /* MyPage */ = { + isa = PBXGroup; + children = ( + 2375E48B2A20401B00843056 /* GetFinishedGoalsUseCase.swift */, + 2375E48D2A20409200843056 /* GetMarshmallowsUseCase.swift */, + ); + path = MyPage; + sourceTree = ""; + }; 23808773291B3ABE00072763 /* Register */ = { isa = PBXGroup; children = ( @@ -1247,6 +1274,7 @@ EEC28CBD29D30CA70075CD4C /* GoalRepositoryInterface.swift */, EEC28CBF29D30CE20075CD4C /* FriendRepositoryInterface.swift */, EEC28CC129D30CEF0075CD4C /* RecordRepositoryInterface.swift */, + 2375E48F2A2040FC00843056 /* MarshmallowRepositoryInterface.swift */, ); path = RepositoryInterface; sourceTree = ""; @@ -1254,6 +1282,7 @@ 57C4818129670D7F008731D9 /* UseCase */ = { isa = PBXGroup; children = ( + 2375E48A2A20400E00843056 /* MyPage */, 57397FBA296E77B60088B5F4 /* Record */, 57C481D8296ABCA2008731D9 /* Goal */, EE4CEA4A2A00AADC002BF87E /* Friend */, @@ -1502,6 +1531,7 @@ EE7D35D229D5A16300D2AD60 /* ViewModel */ = { isa = PBXGroup; children = ( + 2375E4872A20396600843056 /* MyPage */, EE7D35D329D5A16300D2AD60 /* Friend */, EE7D35D529D5A16300D2AD60 /* Record */, EE7D35DC29D5A16300D2AD60 /* Register */, @@ -1570,6 +1600,7 @@ EEC28CB729D30C6A0075CD4C /* GoalRepository.swift */, EEC28CB929D30C740075CD4C /* RecordRepository.swift */, EEC28CBB29D30C8C0075CD4C /* FriendRepository.swift */, + 2375E4912A20415B00843056 /* MarshmallowRepository.swift */, ); path = Repository; sourceTree = ""; @@ -2058,6 +2089,7 @@ 232C1C8A2990CCEA0087B81A /* DeleteUserViewController.swift in Sources */, 5724EBE729100C8500DC529B /* AppDelegate.swift in Sources */, EE9505D1298799DB00077B28 /* PageableResponseModel.swift in Sources */, + 2375E4902A2040FC00843056 /* MarshmallowRepositoryInterface.swift in Sources */, 5724EC702918CFA100DC529B /* BaseTableViewCell.swift in Sources */, 23F364D7291B7BB4009232B4 /* FriendSearchView.swift in Sources */, 5724EC6229177BF000DC529B /* TabBarItem.swift in Sources */, @@ -2097,6 +2129,7 @@ EEC5CAF629B0AC6500FF4C26 /* AuthService.swift in Sources */, 2345E1C429818848003185E0 /* BaseResponseModel.swift in Sources */, EE42F93D2A166BB000AFDD03 /* RecordObserver.swift in Sources */, + 2375E4922A20415B00843056 /* MarshmallowRepository.swift in Sources */, EE168C8F2990C8670020D5CE /* EndDateCalendarSheetViewController.swift in Sources */, 5724EC6C2918CEE200DC529B /* FriendCollectionViewCell.swift in Sources */, 2308C5BB29B385500046A76C /* LinkToAppStore.swift in Sources */, @@ -2151,6 +2184,7 @@ EE44601F2983D1EB00B1A311 /* GoalCategoryResponseModel.swift in Sources */, EE39696529DAAF3D003F655F /* FriendReactionSheetViewController.swift in Sources */, 232B2BE1292B861F00FFDF8B /* TermDetailViewController.swift in Sources */, + 2375E48E2A20409300843056 /* GetMarshmallowsUseCase.swift in Sources */, 23ADE48F292D33C1003002D9 /* NotificationViewController.swift in Sources */, 57CCA787292B0A4B007E22D1 /* ReviewView.swift in Sources */, EE635F4C29D1D11400573F66 /* ObservableBinding.swift in Sources */, @@ -2179,7 +2213,9 @@ EE98F0EC2981024D007BFCCD /* PageableModel.swift in Sources */, EE635F4229D1CD1C00573F66 /* GenerateRecordViewController.swift in Sources */, 57C481DD296ABCDB008731D9 /* Goal.swift in Sources */, + 2375E48C2A20401B00843056 /* GetFinishedGoalsUseCase.swift in Sources */, 23061233292B48FA00662007 /* GoEmotionBannerTableViewCell.swift in Sources */, + 2375E4892A20397400843056 /* MyPageViewModel.swift in Sources */, 5724EC84291B29A700DC529B /* EmojiFloatingCollectionViewCell.swift in Sources */, EE38758029D917B900A26AD5 /* TextConverter.swift in Sources */, EE7D35EC29D5A16300D2AD60 /* GenerateGoalDateViewModel.swift in Sources */, diff --git a/POME/Data/Repository/GoalRepository.swift b/POME/Data/Repository/GoalRepository.swift index b4b420c4..3e0d4c37 100644 --- a/POME/Data/Repository/GoalRepository.swift +++ b/POME/Data/Repository/GoalRepository.swift @@ -48,4 +48,19 @@ class GoalRepository: GoalRepositoryInterface{ func deleteGoal() { } + + func getFinishedGoals() -> Observable<[GoalResponseModel]> { + let observable = Observable<[GoalResponseModel]>.create { observer -> Disposable in + let requestReference: () = GoalService.shared.getFinishedGoals { response in + switch response { + case .success(let data): + observer.onNext(data.content) + default: + break + } + } + return Disposables.create(with: { requestReference }) + } + return observable + } } diff --git a/POME/Data/Repository/MarshmallowRepository.swift b/POME/Data/Repository/MarshmallowRepository.swift new file mode 100644 index 00000000..f3e64bfb --- /dev/null +++ b/POME/Data/Repository/MarshmallowRepository.swift @@ -0,0 +1,27 @@ +// +// MarshmallowRepository.swift +// POME +// +// Created by gomin on 2023/05/26. +// + +import Foundation +import RxSwift + +class MarshmallowRepository: MarshmallowRepositoryInterface{ + + func getMarshmallows() -> Observable { + let observable = Observable.create { observer -> Disposable in + let requestReference: () = UserService.shared.getMarshmallow { response in + switch response { + case .success(let data): + observer.onNext(data) + default: + break + } + } + return Disposables.create(with: { requestReference }) + } + return observable + } +} diff --git a/POME/Domain/RepositoryInterface/GoalRepositoryInterface.swift b/POME/Domain/RepositoryInterface/GoalRepositoryInterface.swift index 6dd03edd..2b67229c 100644 --- a/POME/Domain/RepositoryInterface/GoalRepositoryInterface.swift +++ b/POME/Domain/RepositoryInterface/GoalRepositoryInterface.swift @@ -12,4 +12,5 @@ protocol GoalRepositoryInterface{ func getGoals() -> Observable<[GoalResponseModel]> func generateGoal(requestValue: GenerateGoalRequestModel) -> Observable func deleteGoal() + func getFinishedGoals() -> Observable<[GoalResponseModel]> } diff --git a/POME/Domain/RepositoryInterface/MarshmallowRepositoryInterface.swift b/POME/Domain/RepositoryInterface/MarshmallowRepositoryInterface.swift new file mode 100644 index 00000000..167896ea --- /dev/null +++ b/POME/Domain/RepositoryInterface/MarshmallowRepositoryInterface.swift @@ -0,0 +1,13 @@ +// +// MarshmallowRepositoryInterface.swift +// POME +// +// Created by gomin on 2023/05/26. +// + +import Foundation +import RxSwift + +protocol MarshmallowRepositoryInterface{ + func getMarshmallows() -> Observable +} diff --git a/POME/Domain/UseCase/MyPage/GetFinishedGoalsUseCase.swift b/POME/Domain/UseCase/MyPage/GetFinishedGoalsUseCase.swift new file mode 100644 index 00000000..74f2d7d3 --- /dev/null +++ b/POME/Domain/UseCase/MyPage/GetFinishedGoalsUseCase.swift @@ -0,0 +1,32 @@ +// +// GetFinishedGoalsUseCase.swift +// POME +// +// Created by gomin on 2023/05/26. +// + +import Foundation +import RxSwift + +protocol GetFinishedGoalsUseCaseInterface { + func execute() -> Observable<[GoalResponseModel]> +} + +final class GetFinishedGoalsUseCase: GetFinishedGoalsUseCaseInterface { + + private let goalRepository: GoalRepositoryInterface + + init(goalRepository: GoalRepositoryInterface = GoalRepository()) { + self.goalRepository = goalRepository + } + + func execute() -> Observable<[GoalResponseModel]>{ +// let finishedGoalsCount = goalRepository.getFinishedGoals() +// .map { [self] in +// $0.count +// } + return goalRepository.getFinishedGoals() + } +} + + diff --git a/POME/Domain/UseCase/MyPage/GetMarshmallowsUseCase.swift b/POME/Domain/UseCase/MyPage/GetMarshmallowsUseCase.swift new file mode 100644 index 00000000..b9079b1f --- /dev/null +++ b/POME/Domain/UseCase/MyPage/GetMarshmallowsUseCase.swift @@ -0,0 +1,28 @@ +// +// GetMarshmallowsUseCase.swift +// POME +// +// Created by gomin on 2023/05/26. +// + +import Foundation +import RxSwift + +protocol GetMarshmallowsUseCaseInterface { + func execute() -> Observable +} + +final class GetMarshmallowsUseCase: GetMarshmallowsUseCaseInterface { + + private let marshmallowRepository: MarshmallowRepositoryInterface + + init(marshmallowRepository: MarshmallowRepositoryInterface = MarshmallowRepository()) { + self.marshmallowRepository = marshmallowRepository + } + + func execute() -> Observable{ + return marshmallowRepository.getMarshmallows() + } +} + + diff --git a/POME/Global/Source/TabBar/TabBarController.swift b/POME/Global/Source/TabBar/TabBarController.swift index 40bb655f..ab55210a 100644 --- a/POME/Global/Source/TabBar/TabBarController.swift +++ b/POME/Global/Source/TabBar/TabBarController.swift @@ -57,7 +57,7 @@ class TabBarController: UITabBarController { let tabs = [UINavigationController(rootViewController: recordViewController), UINavigationController(rootViewController: ReviewViewController(btnImage: UIImage())), UINavigationController(rootViewController: FriendViewController()), - UINavigationController(rootViewController: MyPageViewController(btnImage: Image.setting))] + UINavigationController(rootViewController: MyPageViewController())] TabBarItem.allCases.forEach { tabs[$0.rawValue].tabBarItem = $0.asTabBarItem() diff --git a/POME/Presentation/Cells/MyPage/MypageGoalsTableViewCell.swift b/POME/Presentation/Cells/MyPage/MypageGoalsTableViewCell.swift index f743cf38..d8e04c3a 100644 --- a/POME/Presentation/Cells/MyPage/MypageGoalsTableViewCell.swift +++ b/POME/Presentation/Cells/MyPage/MypageGoalsTableViewCell.swift @@ -84,7 +84,7 @@ class MypageGoalsTableViewCell: BaseTableViewCell { make.trailing.equalToSuperview().offset(-14) } } - func setUpData(_ count: Int) { + func bindingData(_ count: Int) { self.subTitleLabel.text = "다시 보고 싶은 지난 목표가 \(count)건 있어요" } } diff --git a/POME/Presentation/ViewControllers/MyPage/MyPageViewController.swift b/POME/Presentation/ViewControllers/MyPage/MyPageViewController.swift index 5ceabd4e..696349e1 100644 --- a/POME/Presentation/ViewControllers/MyPage/MyPageViewController.swift +++ b/POME/Presentation/ViewControllers/MyPage/MyPageViewController.swift @@ -6,54 +6,93 @@ // import UIKit +import Foundation +import RxSwift +import RxCocoa -class MyPageViewController: BaseTabViewController { - var mypageTableView: UITableView! - var completedGoalCount = 0 +final class MyPageViewController: BaseTabViewController { + private let viewModel: any MyPageViewModelInterface + + // MARK: Init + init(viewModel: any MyPageViewModelInterface = MyPageViewModel()){ + self.viewModel = viewModel + super.init(btnImage: Image.setting) + } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } - // MARK: Marshmallow - var recordLevel: Int = -1 - var emotionLevel: Int = -1 - var growthLevel: Int = -1 - var honestLevel: Int = -1 + // MARK: Properties + var mypageTableView: UITableView! + + // MARK: Life Cycle override func viewDidLoad() { super.viewDidLoad() } - override func viewDidAppear(_ animated: Bool) { - getFinishedGoalCounts() - getMarshmallow() - } override func style() { super.style() - setTableView() - mypageTableView.delegate = self - mypageTableView.dataSource = self } override func layout() { super.layout() + setTableView() + self.view.addSubview(mypageTableView) mypageTableView.snp.makeConstraints { make in make.leading.trailing.bottom.equalToSuperview() make.top.equalTo(super.navigationView.snp.bottom) } } + + override func initialize() { +// setTableView() + setTableViewDelegate() + } + override func topBtnDidClicked() { self.navigationController?.pushViewController(SettingViewController(), animated: true) } - func setTableView() { + + override func bind() { + guard let viewModel = viewModel as? MyPageViewModel else { return } + + let input = MyPageViewModel.Input() + let output = viewModel.transform(input) + + output.goals + .subscribe(onNext: { [self] + let cell = self.mypageTableView.cellForRow(at: [0,1]) as? MypageGoalsTableViewCell + cell?.bindingData($0) +// mypageTableView.reloadData() + }).disposed(by: disposeBag) + + output.marshmallows + .subscribe(onNext: { [self] in + mypageTableView.reloadData() + }).disposed(by: disposeBag) + + } + + // MARK: Methods + + private func setTableViewDelegate() { + mypageTableView.delegate = self + mypageTableView.dataSource = self + } + + private func setTableView() { mypageTableView = UITableView().then{ // 프로필 - $0.register(MypageProfileTableViewCell.self, forCellReuseIdentifier: "MypageProfileTableViewCell") + $0.register(cellType: MypageProfileTableViewCell.self) // 목표 보관함 가기 - $0.register(MypageGoalsTableViewCell.self, forCellReuseIdentifier: "MypageGoalsTableViewCell") + $0.register(cellType: MypageGoalsTableViewCell.self) // 마시멜로 모아보기 - $0.register(MypageMarshmallowTableViewCell.self, forCellReuseIdentifier: "MypageMarshmallowTableViewCell") + $0.register(cellType: MypageMarshmallowTableViewCell.self) $0.rowHeight = UITableView.automaticDimension $0.estimatedRowHeight = UITableView.automaticDimension @@ -65,11 +104,12 @@ class MyPageViewController: BaseTabViewController { $0.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) } } - // MARK: - Actions + // MARK: Actions @objc func marshmallowToolTopDidTap(tapGestureRecognizer: UITapGestureRecognizer) { LinkManager(self, .marshmallowToolTip) } } + // MARK: - TableView delegate extension MyPageViewController: UITableViewDelegate, UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { @@ -78,27 +118,9 @@ extension MyPageViewController: UITableViewDelegate, UITableViewDataSource { func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let tag = indexPath.row switch tag { - case 0: - guard let cell = tableView.dequeueReusableCell(withIdentifier: "MypageProfileTableViewCell", for: indexPath) as? MypageProfileTableViewCell else { return UITableViewCell() } - cell.setUpData() - cell.selectionStyle = .none - return cell - case 1: - guard let cell = tableView.dequeueReusableCell(withIdentifier: "MypageGoalsTableViewCell", for: indexPath) as? MypageGoalsTableViewCell else { return UITableViewCell() } - cell.setUpData(self.completedGoalCount) - cell.selectionStyle = .none - return cell - default: - guard let cell = tableView.dequeueReusableCell(withIdentifier: "MypageMarshmallowTableViewCell", for: indexPath) as? MypageMarshmallowTableViewCell else { return UITableViewCell() } - cell.marshmallowCollectionView.delegate = self - cell.marshmallowCollectionView.dataSource = self - cell.marshmallowCollectionView.reloadData() - cell.selectionStyle = .none - - let tapGesture = UITapGestureRecognizer(target: self, action: #selector(marshmallowToolTopDidTap(tapGestureRecognizer:))) - cell.marshmallowToolTipLabel.addGestureRecognizer(tapGesture) - - return cell + case 0: return getProfileCell(indexPath: indexPath) + case 1: return getFinishedGoalsCell(indexPath: indexPath) + default: return getMarshmallowsCell(indexPath: indexPath) } } @@ -107,12 +129,35 @@ extension MyPageViewController: UITableViewDelegate, UITableViewDataSource { } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let tag = indexPath.row - if tag == 1 { - self.navigationController?.pushViewController(CompletedGoalsViewController(), animated: true) + tag == 1 ? + self.navigationController?.pushViewController(CompletedGoalsViewController(), animated: true) + : tableView.deselectRow(at: indexPath, animated: true) + } + + // MARK: Setup TableView Cell + private func getProfileCell(indexPath: IndexPath) -> BaseTableViewCell{ + mypageTableView.dequeueReusableCell(for: indexPath, cellType: MypageProfileTableViewCell.self).then{ + $0.setUpData() + $0.selectionStyle = .none } - - tableView.deselectRow(at: indexPath, animated: true) } + private func getFinishedGoalsCell(indexPath: IndexPath) -> BaseTableViewCell{ + mypageTableView.dequeueReusableCell(for: indexPath, cellType: MypageGoalsTableViewCell.self).then{ + $0.bindingData(viewModel.finishedGoals.count) + $0.selectionStyle = .none + } + } + private func getMarshmallowsCell(indexPath: IndexPath) -> BaseTableViewCell{ + mypageTableView.dequeueReusableCell(for: indexPath, cellType: MypageMarshmallowTableViewCell.self).then{ + $0.marshmallowCollectionView.delegate = self + $0.marshmallowCollectionView.dataSource = self + $0.marshmallowCollectionView.reloadData() + + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(marshmallowToolTopDidTap(tapGestureRecognizer:))) + $0.marshmallowToolTipLabel.addGestureRecognizer(tapGesture) + } + } + } //MARK: - CollectionView Delegate extension MyPageViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout{ @@ -122,18 +167,17 @@ extension MyPageViewController: UICollectionViewDelegate, UICollectionViewDataSo } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MarshmallowCollectionViewCell.cellIdentifier, for: indexPath) - as? MarshmallowCollectionViewCell else { fatalError() } + let cell = collectionView.dequeueReusableCell(for: indexPath, cellType: MarshmallowCollectionViewCell.self) let tag = indexPath.row switch tag { case 0: - cell.setUpMarshmallow(.record, self.recordLevel) + cell.setUpMarshmallow(.record, viewModel.marshmallows.recordMarshmelloLv) case 1: - cell.setUpMarshmallow(.emotion, self.emotionLevel) + cell.setUpMarshmallow(.emotion, viewModel.marshmallows.emotionMarshmelloLv) case 2: - cell.setUpMarshmallow(.growth, self.growthLevel) + cell.setUpMarshmallow(.growth, viewModel.marshmallows.growthMarshmelloLv) default: - cell.setUpMarshmallow(.honest, self.honestLevel) + cell.setUpMarshmallow(.honest, viewModel.marshmallows.honestMarshmelloLv) } return cell @@ -145,39 +189,3 @@ extension MyPageViewController: UICollectionViewDelegate, UICollectionViewDataSo } } -//MARK: - API -extension MyPageViewController { - private func getFinishedGoalCounts(){ - GoalService.shared.getFinishedGoals { result in - switch result{ - case .success(let data): - self.completedGoalCount = data.content.count - self.mypageTableView.reloadData() - break - default: - print(result) - break - } - } - } - private func getMarshmallow() { - UserService.shared.getMarshmallow { result in - switch result{ - case .success(let data): - self.recordLevel = data.recordMarshmelloLv - self.emotionLevel = data.emotionMarshmelloLv - self.growthLevel = data.growthMarshmelloLv - self.honestLevel = data.honestMarshmelloLv - - self.mypageTableView.reloadData() - break - default: - print(result) - NetworkAlert.show(in: self){ [weak self] in - self?.getMarshmallow() - } - break - } - } - } -} diff --git a/POME/Presentation/ViewControllers/Record/RecordViewController.swift b/POME/Presentation/ViewControllers/Record/RecordViewController.swift index e1cc6b77..3a4dcae2 100644 --- a/POME/Presentation/ViewControllers/Record/RecordViewController.swift +++ b/POME/Presentation/ViewControllers/Record/RecordViewController.swift @@ -69,7 +69,9 @@ class RecordViewController: BaseTabViewController { override func initialize() { super.initialize() - recordView.writeButton.addTarget(self, action: #selector(writeButtonDidTap), for: .touchUpInside) + recordView.writeButton.rx.tap + .bind {self.writeButtonDidTap()} + .disposed(by: disposeBag) } override func bind() { @@ -90,43 +92,27 @@ class RecordViewController: BaseTabViewController { self.getNoSecondEmotionRecords(id: self.goalContent[self.categorySelectedIdx].id) }.disposed(by: disposeBag) } + // MARK: - Actions // 알림 페이지 연결 제거 override func topBtnDidClicked() { // self.navigationController?.pushViewController(NotificationViewController(), animated: true) } @objc func writeButtonDidTap() { - if self.goalContent.isEmpty { - let sheet = RecordBottomSheetViewController(Image.flagMint, "지금은 씀씀이를 기록할 수 없어요", "나만의 소비 목표를 설정하고\n기록을 시작해보세요!").show(in: self) - } else { - let goal = goalContent[categorySelectedIdx] - let vc = GenerateRecordViewController(goal: goal) - self.navigationController?.pushViewController(vc, animated: true) - } + goalContent.isEmpty ? showNoGoalContentsWarning() : moveToGenerateRecord() } + @objc func finishGoalButtonDidTap(_ sender: GoalTapGesture) { /* 7일이전 기록 있을 때 -> 아직 돌아보지 않은 기록이 있어요 바텀시트 띄우고 & 종료 페이지 진입 불가 7일 이전 기록은 없으나 2차감정 기록을 하지 않았을 때 -> 아직 돌아보지 않은 기록이 있어요 바텀시트 띄우기 & 종료 페이지 진입 불가 모든 감정기록 완료했을 때 -> 종료페이지 진입 */ - - if !self.recordsOfGoal.isEmpty || !self.noSecondEmotionRecords.isEmpty { - showNoSecondEmotionWarning() - } else { - let vc = AllRecordsViewController(self) - vc.goalContent = sender.data - self.navigationController?.pushViewController(vc, animated: true) - } + let isSecondEmotionNeeded = !self.recordsOfGoal.isEmpty || !self.noSecondEmotionRecords.isEmpty + isSecondEmotionNeeded ? showNoSecondEmotionWarning() : moveToAllRecords(sender) } @objc func addGoalButtonDidTap() { - print("goal count: ", self.goalContent.count) - if self.goalContent.count < 10 { - let vc = GenerateGoalDateViewController() - self.navigationController?.pushViewController(vc, animated: true) - } else { - cannotAddGoalWarning() - } + goalContent.count < 10 ? moveToGenerateGoalDate() : cannotAddGoalWarning() } @objc func alertGoalMenuButtonDidTap(_ sender: GoalTapGesture) { @@ -151,7 +137,7 @@ class RecordViewController: BaseTabViewController { // self.recordView.recordTableView.reloadRows(at: [sender.data], with: .automatic) // } - // MARK: - Warning Sheets + // MARK: Warning Sheets func showNoSecondEmotionWarning() { let sheet = RecordBottomSheetViewController(Image.penPink, "아직 돌아보지 않은 기록이 있어요!", @@ -163,6 +149,24 @@ class RecordViewController: BaseTabViewController { func cannotAddGoalWarning() { let sheet = RecordBottomSheetViewController(Image.ten, "목표는 10개를 넘을 수 없어요", "포미는 사용자가 무리하지 않고 즐겁게 목표를\n달성할 수 있도록 응원하고 있어요!").show(in: self) } + func showNoGoalContentsWarning() { + let sheet = RecordBottomSheetViewController(Image.flagMint, "지금은 씀씀이를 기록할 수 없어요", "나만의 소비 목표를 설정하고\n기록을 시작해보세요!").show(in: self) + } + // MARK: Move to other pages + func moveToGenerateRecord() { + let goal = goalContent[categorySelectedIdx] + let vc = GenerateRecordViewController(goal: goal) + self.navigationController?.pushViewController(vc, animated: true) + } + func moveToAllRecords(_ sender: GoalTapGesture) { + let vc = AllRecordsViewController(self) + vc.goalContent = sender.data + self.navigationController?.pushViewController(vc, animated: true) + } + func moveToGenerateGoalDate() { + let vc = GenerateGoalDateViewController() + self.navigationController?.pushViewController(vc, animated: true) + } } //MARK: - CollectionView Delegate @@ -241,7 +245,7 @@ extension RecordViewController: UITableViewDelegate, UITableViewDataSource { let tag = indexPath.row switch tag { case 0: - guard let cell = tableView.dequeueReusableCell(withIdentifier: "GoalCategoryTableViewCell", for: indexPath) as? GoalCategoryTableViewCell else { return UITableViewCell() } + let cell = tableView.dequeueReusableCell(for: indexPath, cellType: GoalCategoryTableViewCell.self) cell.selectionStyle = .none cell.goalCollectionView.delegate = self @@ -253,7 +257,7 @@ extension RecordViewController: UITableViewDelegate, UITableViewDataSource { return cell case 1: - guard let cell = tableView.dequeueReusableCell(withIdentifier: "GoalTableViewCell", for: indexPath) as? GoalTableViewCell else { return UITableViewCell() } + let cell = tableView.dequeueReusableCell(for: indexPath, cellType: GoalTableViewCell.self) if !self.goalContent.isEmpty { cell.setUpData(self.goalContent[self.categorySelectedIdx]) @@ -288,7 +292,7 @@ extension RecordViewController: UITableViewDelegate, UITableViewDataSource { return cell case 2: - guard let cell = tableView.dequeueReusableCell(withIdentifier: "GoEmotionBannerTableViewCell", for: indexPath) as? GoEmotionBannerTableViewCell else { return UITableViewCell() } + let cell = tableView.dequeueReusableCell(for: indexPath, cellType: GoEmotionBannerTableViewCell.self) cell.setUpCount(self.noSecondEmotionRecords.count ?? 0) cell.selectionStyle = .none return cell diff --git a/POME/Presentation/ViewModel/MyPage/MyPageViewModel.swift b/POME/Presentation/ViewModel/MyPage/MyPageViewModel.swift new file mode 100644 index 00000000..cdb3f5b8 --- /dev/null +++ b/POME/Presentation/ViewModel/MyPage/MyPageViewModel.swift @@ -0,0 +1,68 @@ +// +// MyPageViewModel.swift +// POME +// +// Created by gomin on 2023/05/26. +// + +import Foundation +import RxSwift +import RxCocoa + +protocol MyPageViewModelInterface: BaseViewModel{ + + var finishedGoals: [GoalResponseModel] { get } + var marshmallows: MarshmallowResponseModel { get } + +} + +class MyPageViewModel: MyPageViewModelInterface{ + + var finishedGoals = [GoalResponseModel]() + var marshmallows = MarshmallowResponseModel(emotionMarshmelloLv: 0, growthMarshmelloLv: 0, honestMarshmelloLv: 0, recordMarshmelloLv: 0) + + private let getFinishedGoalsUseCase: GetFinishedGoalsUseCaseInterface + private let getMarshmallowsUseCase: GetMarshmallowsUseCaseInterface + + init(getFinishedGoalsUseCase: GetFinishedGoalsUseCaseInterface = GetFinishedGoalsUseCase(), + getMarshmallowsUseCase: GetMarshmallowsUseCaseInterface = GetMarshmallowsUseCase()) { + self.getFinishedGoalsUseCase = getFinishedGoalsUseCase + self.getMarshmallowsUseCase = getMarshmallowsUseCase + } + + private let disposeBag = DisposeBag() + + struct Input{ + + } + + struct Output{ + let goals: Observable + let marshmallows: Observable + } + + func transform(_ input: Input) -> Output { + let finishedGoalsResponse = self.getFinishedGoalsUseCase.execute() + let marshmallowResponse = self.getMarshmallowsUseCase.execute() + + let finishedGoalsTableView = finishedGoalsResponse + .do{ + self.finishedGoals = $0 + }.map{ + $0.count + } + + let marshmallowTableView = marshmallowResponse + .do{ + self.marshmallows = $0 + }.map{ _ in + () + } + + + return Output( + goals: finishedGoalsTableView, + marshmallows: marshmallowTableView + ) + } +}