diff --git a/KkuMulKum.xcodeproj/project.pbxproj b/KkuMulKum.xcodeproj/project.pbxproj index 37a780bb..37959011 100644 --- a/KkuMulKum.xcodeproj/project.pbxproj +++ b/KkuMulKum.xcodeproj/project.pbxproj @@ -111,6 +111,7 @@ DD3F9DD22C485753008E1FF7 /* UtilService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3F9DD12C485753008E1FF7 /* UtilService.swift */; }; DD3F9DD42C4858A3008E1FF7 /* UtilTargetType.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3F9DD32C4858A3008E1FF7 /* UtilTargetType.swift */; }; DD3F9DD62C4988E2008E1FF7 /* RegisterMeetingsResponseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3F9DD52C4988E2008E1FF7 /* RegisterMeetingsResponseModel.swift */; }; + DD3F9DD82C49C25D008E1FF7 /* PagePromiseServiceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3F9DD72C49C25D008E1FF7 /* PagePromiseServiceType.swift */; }; DD41BEFA2C41D4160095A068 /* TardyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD41BEF92C41D4160095A068 /* TardyView.swift */; }; DD41BEFC2C41D54D0095A068 /* TardyPenaltyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD41BEFB2C41D54D0095A068 /* TardyPenaltyView.swift */; }; DD41BEFF2C41DAA40095A068 /* TardyEmptyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD41BEFE2C41DAA40095A068 /* TardyEmptyView.swift */; }; @@ -304,6 +305,7 @@ DD3F9DD12C485753008E1FF7 /* UtilService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UtilService.swift; sourceTree = ""; }; DD3F9DD32C4858A3008E1FF7 /* UtilTargetType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UtilTargetType.swift; sourceTree = ""; }; DD3F9DD52C4988E2008E1FF7 /* RegisterMeetingsResponseModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegisterMeetingsResponseModel.swift; sourceTree = ""; }; + DD3F9DD72C49C25D008E1FF7 /* PagePromiseServiceType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PagePromiseServiceType.swift; sourceTree = ""; }; DD41BEF92C41D4160095A068 /* TardyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TardyView.swift; sourceTree = ""; }; DD41BEFB2C41D54D0095A068 /* TardyPenaltyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TardyPenaltyView.swift; sourceTree = ""; }; DD41BEFE2C41DAA40095A068 /* TardyEmptyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TardyEmptyView.swift; sourceTree = ""; }; @@ -764,6 +766,7 @@ DD39768D2C41CA0700E2A4C4 /* PagePromise */ = { isa = PBXGroup; children = ( + DD3F9DD92C49CF05008E1FF7 /* Service */, DD39768E2C41CABE00E2A4C4 /* ViewController */, DD39768F2C41CAC700E2A4C4 /* ViewModel */, DD3976902C41CACF00E2A4C4 /* View */, @@ -855,6 +858,14 @@ path = ServiceType; sourceTree = ""; }; + DD3F9DD92C49CF05008E1FF7 /* Service */ = { + isa = PBXGroup; + children = ( + DD3F9DD72C49C25D008E1FF7 /* PagePromiseServiceType.swift */, + ); + path = Service; + sourceTree = ""; + }; DD41BEFD2C41D85F0095A068 /* View */ = { isa = PBXGroup; children = ( @@ -1766,6 +1777,7 @@ DD3F9DD02C48571A008E1FF7 /* MeetingListServiceType.swift in Sources */, A39F2B212C499CE5008DA5F5 /* SetReadyStatusInfoServiceType.swift in Sources */, DE6D4D132C3F14D80005584B /* MeetingMemberCell.swift in Sources */, + DD3F9DD82C49C25D008E1FF7 /* PagePromiseServiceType.swift in Sources */, DDAF1C932C3D6E3D008A37D3 /* PagePromiseViewController.swift in Sources */, 789D73BE2C47FE0F00C7077D /* AuthInterceptor.swift in Sources */, 789D73B32C47CC6D00C7077D /* LocalNotificationManager.swift in Sources */, diff --git a/KkuMulKum/Source/AddPromise/ViewController/AddPromiseCompleteViewController.swift b/KkuMulKum/Source/AddPromise/ViewController/AddPromiseCompleteViewController.swift index 51edbcae..293662ff 100644 --- a/KkuMulKum/Source/AddPromise/ViewController/AddPromiseCompleteViewController.swift +++ b/KkuMulKum/Source/AddPromise/ViewController/AddPromiseCompleteViewController.swift @@ -69,7 +69,8 @@ final class AddPromiseCompleteViewController: BaseViewController { rootViewController.navigationController?.pushViewController( PagePromiseViewController( promiseViewModel: PagePromiseViewModel( - promiseID: self.promiseID + promiseID: self.promiseID, + service: PromiseService() ) ), animated: true diff --git a/KkuMulKum/Source/Home/ViewController/HomeViewController.swift b/KkuMulKum/Source/Home/ViewController/HomeViewController.swift index 97231eb7..7e707733 100644 --- a/KkuMulKum/Source/Home/ViewController/HomeViewController.swift +++ b/KkuMulKum/Source/Home/ViewController/HomeViewController.swift @@ -128,7 +128,8 @@ extension HomeViewController: UICollectionViewDelegateFlowLayout { ) { let pagePromiseViewController = PagePromiseViewController( promiseViewModel: PagePromiseViewModel( - promiseID: viewModel.upcomingPromiseList.value?.data?.promises[indexPath.item].promiseID ?? 0 + promiseID: viewModel.upcomingPromiseList.value?.data?.promises[indexPath.item].promiseID ?? 0, + service: PromiseService() ) ) @@ -390,7 +391,8 @@ private extension HomeViewController { func todayButtonDidTap(_ sender: UIButton) { let viewController = PagePromiseViewController( promiseViewModel: PagePromiseViewModel( - promiseID: viewModel.nearestPromise.value?.data?.promiseID ?? 0 + promiseID: viewModel.nearestPromise.value?.data?.promiseID ?? 0, + service: PromiseService() ) ) diff --git a/KkuMulKum/Source/MeetingInfo/ViewController/MeetingInfoViewController.swift b/KkuMulKum/Source/MeetingInfo/ViewController/MeetingInfoViewController.swift index 492d1ac9..2f16a191 100644 --- a/KkuMulKum/Source/MeetingInfo/ViewController/MeetingInfoViewController.swift +++ b/KkuMulKum/Source/MeetingInfo/ViewController/MeetingInfoViewController.swift @@ -75,7 +75,8 @@ extension MeetingInfoViewController: UICollectionViewDelegate { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let pagePromiseViewController = PagePromiseViewController( promiseViewModel: PagePromiseViewModel( - promiseID: viewModel.meetingPromises[indexPath.item].promiseID + promiseID: viewModel.meetingPromises[indexPath.item].promiseID, + service: PromiseService() ) ) diff --git a/KkuMulKum/Source/Promise/PagePromise/Service/PagePromiseServiceType.swift b/KkuMulKum/Source/Promise/PagePromise/Service/PagePromiseServiceType.swift new file mode 100644 index 00000000..1b9ab2ee --- /dev/null +++ b/KkuMulKum/Source/Promise/PagePromise/Service/PagePromiseServiceType.swift @@ -0,0 +1,22 @@ +// +// PagePromiseServiceType.swift +// KkuMulKum +// +// Created by YOUJIM on 7/19/24. +// + +import Foundation + +protocol PagePromiseServiceType { + func fetchPromiseInfo(with promiseId: Int) async throws -> ResponseBodyDTO? +} + +extension PromiseService: PagePromiseServiceType { + func fetchPromiseInfo(with promiseId: Int) async throws -> ResponseBodyDTO? { + return try await request( + with: .fetchPromiseInfo( + promiseID: promiseId + ) + ) + } +} diff --git a/KkuMulKum/Source/Promise/PagePromise/ViewController/PagePromiseViewController.swift b/KkuMulKum/Source/Promise/PagePromise/ViewController/PagePromiseViewController.swift index 75db9340..feac4d2d 100644 --- a/KkuMulKum/Source/Promise/PagePromise/ViewController/PagePromiseViewController.swift +++ b/KkuMulKum/Source/Promise/PagePromise/ViewController/PagePromiseViewController.swift @@ -14,11 +14,16 @@ class PagePromiseViewController: BaseViewController { private let promiseViewModel: PagePromiseViewModel - // TODO: 서버 연결 시 데이터 바인딩 필요 private var promiseViewControllerList: [BaseViewController] = [] private let promiseInfoViewController: PromiseInfoViewController + + private let promiseInfoViewModel: PromiseInfoViewModel + private let readyStatusViewController: ReadyStatusViewController + + private let readyStatusViewModel: ReadyStatusViewModel + private let tardyViewController: TardyViewController private lazy var promiseSegmentedControl = PagePromiseSegmentedControl( @@ -30,53 +35,36 @@ class PagePromiseViewController: BaseViewController { navigationOrientation: .vertical ) - override func viewDidLoad() { - super.viewDidLoad() - - setupNavigationBarBackButton() - } - - // MARK: - LifeCycle - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - - navigationController?.isNavigationBarHidden = false - - } - - override func viewWillDisappear(_ animated: Bool) { - super.viewWillDisappear(animated) - - navigationController?.isNavigationBarHidden = true - } - - // MARK: Initialize + // MARK: Initializer init(promiseViewModel: PagePromiseViewModel) { self.promiseViewModel = promiseViewModel - // TODO: 네트워크 통신 필요 + promiseViewModel.fetchPromiseInfo(promiseID: promiseViewModel.promiseID) + + promiseInfoViewModel = PromiseInfoViewModel( + promiseID: promiseViewModel.promiseID, + promiseInfoService: PromiseService() + ) promiseInfoViewController = PromiseInfoViewController( - promiseInfoViewModel: PromiseInfoViewModel( - promiseInfoService: MockPromiseInfoService(), - promiseID: promiseViewModel.promiseID.value - ) + promiseInfoViewModel: promiseInfoViewModel + ) + + readyStatusViewModel = ReadyStatusViewModel( + readyStatusService: MockReadyStatusService(), + promiseID: promiseViewModel.promiseID ) readyStatusViewController = ReadyStatusViewController( - readyStatusViewModel: ReadyStatusViewModel( - readyStatusService: PromiseService(), - promiseID: promiseViewModel.promiseID.value - ) + readyStatusViewModel: readyStatusViewModel ) tardyViewController = TardyViewController( tardyViewModel: TardyViewModel( tardyService: MockTardyService(), - promiseID: promiseViewModel.promiseID.value + promiseID: promiseViewModel.promiseID ) ) @@ -94,6 +82,30 @@ class PagePromiseViewController: BaseViewController { } + // MARK: - LifeCycle + + override func viewDidLoad() { + super.viewDidLoad() + + setupNavigationBarBackButton() + setupBindings() + } + + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + navigationController?.isNavigationBarHidden = false + + } + + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + + navigationController?.isNavigationBarHidden = true + } + + // MARK: - Setup override func setupView() { @@ -148,7 +160,6 @@ class PagePromiseViewController: BaseViewController { } override func setupDelegate() { - promisePageViewController.delegate = self promisePageViewController.dataSource = self } } @@ -186,14 +197,6 @@ extension PagePromiseViewController { } - -// MARK: - UIPageViewControllerDelegate - -extension PagePromiseViewController: UIPageViewControllerDelegate { - -} - - // MARK: - UIPageViewControllerDataSource extension PagePromiseViewController: UIPageViewControllerDataSource { @@ -211,3 +214,16 @@ extension PagePromiseViewController: UIPageViewControllerDataSource { return nil } } + +private extension PagePromiseViewController { + func setupBindings() { + promiseViewModel.promiseInfo.bind { [weak self] model in + guard let model else { return } + DispatchQueue.main.async { + self?.setupNavigationBarTitle(with: model.promiseName) + self?.promiseInfoViewModel.promiseInfo.value = model + self?.readyStatusViewModel.promiseName.value = model.promiseName + } + } + } +} diff --git a/KkuMulKum/Source/Promise/PagePromise/ViewModel/PagePromiseViewModel.swift b/KkuMulKum/Source/Promise/PagePromise/ViewModel/PagePromiseViewModel.swift index 219f9b08..f4d31cb0 100644 --- a/KkuMulKum/Source/Promise/PagePromise/ViewModel/PagePromiseViewModel.swift +++ b/KkuMulKum/Source/Promise/PagePromise/ViewModel/PagePromiseViewModel.swift @@ -12,16 +12,20 @@ class PagePromiseViewModel { // MARK: Property + + private let service: PagePromiseServiceType - var currentPage = ObservablePattern(0) - var promiseID: ObservablePattern + let promiseID: Int + let currentPage = ObservablePattern(0) + let promiseInfo = ObservablePattern(nil) let promiseName: String = "Test" // MARK: Initialize - init(promiseID: Int) { - self.promiseID = ObservablePattern(promiseID) + init(promiseID: Int, service: PagePromiseServiceType) { + self.service = service + self.promiseID = promiseID } } @@ -33,7 +37,19 @@ extension PagePromiseViewModel { currentPage.value = index } - func promiseIDDidChanged(id: Int) { - promiseID.value = id + func fetchPromiseInfo(promiseID: Int) { + Task { + do { + let result = try await service.fetchPromiseInfo(with: promiseID) + + guard let success = result?.success, + success == true + else { + return + } + + promiseInfo.value = result?.data + } + } } } diff --git a/KkuMulKum/Source/Promise/PromiseInfo/Cell/ParticipantCollectionViewCell.swift b/KkuMulKum/Source/Promise/PromiseInfo/Cell/ParticipantCollectionViewCell.swift index 95b4c364..028d03b0 100644 --- a/KkuMulKum/Source/Promise/PromiseInfo/Cell/ParticipantCollectionViewCell.swift +++ b/KkuMulKum/Source/Promise/PromiseInfo/Cell/ParticipantCollectionViewCell.swift @@ -12,7 +12,7 @@ import SnapKit class ParticipantCollectionViewCell: BaseCollectionViewCell { - // MARK: Property + // MARK: - Property let profileImageView: UIImageView = UIImageView().then { $0.backgroundColor = .gray1 diff --git a/KkuMulKum/Source/Promise/PromiseInfo/View/PromiseInfoView.swift b/KkuMulKum/Source/Promise/PromiseInfo/View/PromiseInfoView.swift index 64fb7149..fbc90420 100644 --- a/KkuMulKum/Source/Promise/PromiseInfo/View/PromiseInfoView.swift +++ b/KkuMulKum/Source/Promise/PromiseInfo/View/PromiseInfoView.swift @@ -12,7 +12,7 @@ class PromiseInfoView: BaseView { // MARK: Property - private let participantNumberLabel: UILabel = UILabel().then { + let participantNumberLabel: UILabel = UILabel().then { $0.setText("약속 참여 인원 n명", style: .body01) $0.setHighlightText("n명", style: .body01, color: .maincolor) } @@ -57,7 +57,7 @@ class PromiseInfoView: BaseView { $0.setText("위치", style: .caption01, color: .maincolor) } - private let locationContentLabel: UILabel = UILabel().then { + let locationContentLabel: UILabel = UILabel().then { $0.setText("sss역 s번 출구", style: .body04, color: .gray7) } @@ -69,7 +69,7 @@ class PromiseInfoView: BaseView { $0.setText("약속시간", style: .caption01, color: .maincolor) } - private let timeContentLabel: UILabel = UILabel().then { + let timeContentLabel: UILabel = UILabel().then { $0.setText("mm월 dd일 hh:mm", style: .body04, color: .gray7) } @@ -81,7 +81,7 @@ class PromiseInfoView: BaseView { $0.setText("준비레벨", style: .caption01, color: .maincolor) } - private let readyLevelContentLabel: UILabel = UILabel().then { + let readyLevelContentLabel: UILabel = UILabel().then { $0.setText("LV n. sss", style: .body04, color: .gray7) } @@ -93,7 +93,7 @@ class PromiseInfoView: BaseView { $0.setText("벌칙", style: .caption01, color: .maincolor) } - private let penaltyLevelContentLabel: UILabel = UILabel().then { + let penaltyLevelContentLabel: UILabel = UILabel().then { $0.setText("ssss하기", style: .body04, color: .gray7) } diff --git a/KkuMulKum/Source/Promise/PromiseInfo/ViewController/PromiseInfoViewController.swift b/KkuMulKum/Source/Promise/PromiseInfo/ViewController/PromiseInfoViewController.swift index 4607d923..f12ccc23 100644 --- a/KkuMulKum/Source/Promise/PromiseInfo/ViewController/PromiseInfoViewController.swift +++ b/KkuMulKum/Source/Promise/PromiseInfo/ViewController/PromiseInfoViewController.swift @@ -7,6 +7,8 @@ import UIKit +import Kingfisher + class PromiseInfoViewController: BaseViewController { @@ -15,9 +17,6 @@ class PromiseInfoViewController: BaseViewController { private let promiseInfoViewModel: PromiseInfoViewModel private let promiseInfoView: PromiseInfoView = PromiseInfoView() - - // MARK: - Setup - init(promiseInfoViewModel: PromiseInfoViewModel) { self.promiseInfoViewModel = promiseInfoViewModel @@ -28,19 +27,15 @@ class PromiseInfoViewController: BaseViewController { fatalError("init(coder:) has not been implemented") } - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - - // TODO: 서버 통신하고 데이터 바인딩 + override func loadView() { + view = promiseInfoView } - override func setupView() { - view.addSubview(promiseInfoView) - self.navigationController?.navigationBar.shadowImage = nil + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) - promiseInfoView.snp.makeConstraints { - $0.edges.equalToSuperview() - } + setupBinding() + promiseInfoViewModel.fetchPromiseParticipantList() } override func setupDelegate() { @@ -50,6 +45,57 @@ class PromiseInfoViewController: BaseViewController { } +// MARK: - Extension + +extension PromiseInfoViewController { + func setupBinding() { + promiseInfoViewModel.promiseInfo.bind(with: self) { owner, info in + owner.promiseInfoView.timeContentLabel.setText( + info?.time ?? "설정되지 않음", + style: .body04, + color: .gray7 + ) + + owner.promiseInfoView.readyLevelContentLabel.setText( + info?.dressUpLevel ?? "설정되지 않음", + style: .body04, + color: .gray7 + ) + + owner.promiseInfoView.locationContentLabel.setText( + info?.address ?? "설정되지 않음", + style: .body04, + color: .gray7 + ) + + owner.promiseInfoView.penaltyLevelContentLabel.setText( + info?.penalty ?? "설정되지 않음", + style: .body04, + color: .gray7 + ) + } + + promiseInfoViewModel.participantsInfo.bind(with: self) { + owner, + participantsInfo in + DispatchQueue.main.async { + owner.promiseInfoView.participantNumberLabel.setText( + "약속 참여 인원 \(participantsInfo?.count ?? 0)명", + style: .body01 + ) + owner.promiseInfoView.participantNumberLabel.setHighlightText( + "\(participantsInfo?.count ?? 0)명", + style: .body01, + color: .maincolor + ) + + owner.promiseInfoView.participantCollectionView.reloadData() + } + } + } +} + + // MARK: - UICollectionViewDataSource extension PromiseInfoViewController: UICollectionViewDataSource { @@ -57,8 +103,7 @@ extension PromiseInfoViewController: UICollectionViewDataSource { _ collectionView: UICollectionView, numberOfItemsInSection section: Int ) -> Int { - // TODO: 데이터 바인딩 필요 - return 10 + return ((promiseInfoViewModel.participantsInfo.value?.count ?? 0) + 1) } } @@ -75,12 +120,27 @@ extension PromiseInfoViewController: UICollectionViewDelegateFlowLayout { for: indexPath) as? ParticipantCollectionViewCell else { return UICollectionViewCell() } - // TODO: 데이터 바인딩 필요 - if indexPath.row == 0 { cell.profileImageView.image = .imgEmptyCell cell.profileImageView.contentMode = .scaleAspectFill + cell.userNameLabel.isHidden = true + + return cell + } + + guard let info = promiseInfoViewModel.participantsInfo.value?[indexPath.row - 1] else { + return cell + } + + cell.userNameLabel.setText(info.name, style: .caption02, color: .gray6) + + guard let image = URL(string: info.profileImageURL ?? "") else { + cell.profileImageView.image = .imgProfile + + return cell } + + cell.profileImageView.kf.setImage(with: image) return cell } diff --git a/KkuMulKum/Source/Promise/PromiseInfo/ViewModel/PromiseInfoViewModel.swift b/KkuMulKum/Source/Promise/PromiseInfo/ViewModel/PromiseInfoViewModel.swift index 42034201..a6a826f8 100644 --- a/KkuMulKum/Source/Promise/PromiseInfo/ViewModel/PromiseInfoViewModel.swift +++ b/KkuMulKum/Source/Promise/PromiseInfo/ViewModel/PromiseInfoViewModel.swift @@ -8,11 +8,36 @@ import Foundation class PromiseInfoViewModel { - var promiseID: ObservablePattern - var promiseInfoService: PromiseInfoServiceType - init(promiseInfoService: PromiseInfoServiceType, promiseID: Int) { + let promiseID: Int + + let participantsInfo = ObservablePattern<[Participant]?>(nil) + let promiseInfo = ObservablePattern(nil) + + /// 굳이 서비스 하나 더 만들 필요 없을 것 같아서 같은 API 사용하는 ReadyStatusServiceType 가져옴 + private let promiseInfoService: ReadyStatusServiceType + + init(promiseID: Int, promiseInfoService: ReadyStatusServiceType) { + self.promiseID = promiseID self.promiseInfoService = promiseInfoService - self.promiseID = ObservablePattern(promiseID) + } +} + +extension PromiseInfoViewModel { + func fetchPromiseParticipantList() { + Task { + do { + + let responseBody = try await promiseInfoService.fetchPromiseParticipantList(with: promiseID) + + guard let success = responseBody?.success, success == true else { + return + } + + participantsInfo.value = responseBody?.data?.participants + } catch { + print(">>>>> \(error.localizedDescription) : \(#function)") + } + } } } diff --git a/KkuMulKum/Source/Promise/ReadyStatus/View/ReadyStatusButton.swift b/KkuMulKum/Source/Promise/ReadyStatus/View/ReadyStatusButton.swift index 911de64b..f56c9041 100644 --- a/KkuMulKum/Source/Promise/ReadyStatus/View/ReadyStatusButton.swift +++ b/KkuMulKum/Source/Promise/ReadyStatus/View/ReadyStatusButton.swift @@ -7,7 +7,7 @@ import UIKit -enum ReadyStatus { +enum ReadyProgressStatus { case none case ready case move @@ -15,7 +15,7 @@ enum ReadyStatus { } class ReadyStatusButton: UIButton { - init(title: String, readyStatus: ReadyStatus) { + init(title: String, readyStatus: ReadyProgressStatus) { super.init(frame: .zero) setupButton(title, readyStatus) @@ -23,7 +23,7 @@ class ReadyStatusButton: UIButton { override init(frame: CGRect) { super.init(frame: frame) - } +} required init?(coder: NSCoder) { super.init(coder: coder) @@ -33,7 +33,7 @@ class ReadyStatusButton: UIButton { extension ReadyStatusButton { func setupButton( _ title: String, - _ readyStatus: ReadyStatus + _ readyStatus: ReadyProgressStatus ) { switch readyStatus { case .none: diff --git a/KkuMulKum/Source/Promise/ReadyStatus/ViewController/ReadyStatusViewController.swift b/KkuMulKum/Source/Promise/ReadyStatus/ViewController/ReadyStatusViewController.swift index 8d1aeda2..8cb34e4e 100644 --- a/KkuMulKum/Source/Promise/ReadyStatus/ViewController/ReadyStatusViewController.swift +++ b/KkuMulKum/Source/Promise/ReadyStatus/ViewController/ReadyStatusViewController.swift @@ -40,11 +40,8 @@ class ReadyStatusViewController: BaseViewController { super.viewWillAppear(animated) // TODO: 서버 통신해서 - readyStatusViewModel.isReadyInfoEntered.bind { [weak self] flag in - DispatchQueue.main.async { - self?.updateReadyInfoView(flag: flag) - } - } + readyStatusViewModel.fetchMyReadyStatus() + readyStatusViewModel.fetchPromiseParticipantList() } override func setupDelegate() { @@ -79,31 +76,37 @@ class ReadyStatusViewController: BaseViewController { @objc func readyStartButtonDidTapped() { // TODO: 늦었을 때 꾸물거릴 시간이 없어요 팝업 뜨도록 설정 - readyStatusViewModel.myReadyStatus.value = .ready + readyStatusViewModel.myReadyProgressStatus.value = .ready rootView.myReadyStatusProgressView.readyStartButton.isEnabled.toggle() } @objc func moveStartButtonDidTapped() { // TODO: 늦었을 때 꾸물거릴 시간이 없어요 팝업 뜨도록 설정 - readyStatusViewModel.myReadyStatus.value = .move + readyStatusViewModel.myReadyProgressStatus.value = .move rootView.myReadyStatusProgressView.moveStartButton.isEnabled.toggle() } @objc func arrivalButtonDidTapped() { - readyStatusViewModel.myReadyStatus.value = .done + readyStatusViewModel.myReadyProgressStatus.value = .done rootView.myReadyStatusProgressView.arrivalButton.isEnabled.toggle() } /// 눌렀을 때 준비 정보 입력하기 화면으로 넘어가도록 설정 @objc func enterReadyButtonDidTapped() { - // TODO: 유진이가 promiseID, promiseTime 를 전달하면 됩니다. + // TODO: 유진이가 promiseID, promiseName, promiseTime 를 전달하면 됩니다. + + guard !readyStatusViewModel.promiseName.value.isEmpty else { return } + + guard let readyStatusInfo = readyStatusViewModel.myReadyStatus.value else { return } + let setReadyInfoViewController = SetReadyInfoViewController( viewModel: SetReadyInfoViewModel( - promiseID: 1, - promiseTime: "", + promiseID: readyStatusViewModel.promiseID, + promiseTime: readyStatusInfo.promiseTime, + promiseName: readyStatusViewModel.promiseName.value, service: PromiseService() ) ) @@ -168,21 +171,18 @@ private extension ReadyStatusViewController { func setupBinding() { readyStatusViewModel.isReadyInfoEntered.bind(with: self) { owner, status in DispatchQueue.main.async { - owner.readyStatusViewModel.isReadyInfoEntered.value = status owner.updateReadyInfoView(flag: status) } } - readyStatusViewModel.myReadyStatus.bind(with: self) { owner, status in + readyStatusViewModel.myReadyProgressStatus.bind(with: self) { owner, status in DispatchQueue.main.async { - owner.readyStatusViewModel.myReadyStatus.value = status owner.updateReadyStartButton(status: status) } } readyStatusViewModel.participantInfos.bind(with: self) { owner, participants in DispatchQueue.main.async { - owner.readyStatusViewModel.participantInfos.value = participants owner.rootView.ourReadyStatusCollectionView.reloadData() } } @@ -206,7 +206,7 @@ private extension ReadyStatusViewController { rootView.popUpImageView.isHidden = !isLate } - func updateReadyStartButton(status: ReadyStatus) { + func updateReadyStartButton(status: ReadyProgressStatus) { switch status { case .none: rootView.myReadyStatusProgressView.readyStartButton.setupButton( diff --git a/KkuMulKum/Source/Promise/ReadyStatus/ViewModel/ReadyStatusViewModel.swift b/KkuMulKum/Source/Promise/ReadyStatus/ViewModel/ReadyStatusViewModel.swift index 56f26ba4..5aa7714e 100644 --- a/KkuMulKum/Source/Promise/ReadyStatus/ViewModel/ReadyStatusViewModel.swift +++ b/KkuMulKum/Source/Promise/ReadyStatus/ViewModel/ReadyStatusViewModel.swift @@ -8,23 +8,33 @@ import Foundation class ReadyStatusViewModel { - // 서비스 객체 - var readyStatusService: ReadyStatusServiceType - // 서버 통신을 위한 promiseID - var promiseID: ObservablePattern + let promiseID: Int + + /// 단순히 값을 전달만 하기 위한 코드 + /// 준비 현황 입력하기 버튼을 눌렀을 때 + /// promiseName.value.isEmpty로 분기처리 1차 (실패 시 버튼 입력 안되게) + /// bind를 사용하라는 말이 아님 + let promiseName = ObservablePattern("") // 준비 정보가 입력되었는지 여부 - var isReadyInfoEntered = ObservablePattern(false) + let isReadyInfoEntered = ObservablePattern(false) - // 현재 준비 상태 - var myReadyStatus = ObservablePattern(.none) + /// 나의 준비현황이 담긴 정보 + /// 설령 데이터가 없다하더라도 약속 시간은 담겨있음. + let myReadyStatus = ObservablePattern(nil) + + // 현재 준비 상태에 대한 버튼 처리 + let myReadyProgressStatus = ObservablePattern(.none) // 꾸물거림 여부 - var isLate = ObservablePattern(false) + let isLate = ObservablePattern(false) // 우리들의 준비 현황 스택 뷰에 들어갈 정보들 - var participantInfos = ObservablePattern<[Participant]>([]) + let participantInfos = ObservablePattern<[Participant]>([]) + + // 서비스 객체 + private let readyStatusService: ReadyStatusServiceType // 현재 시간 받아오기 위한 dateFormatter 구헌 private let dateFormatter = DateFormatter().then { @@ -36,7 +46,7 @@ class ReadyStatusViewModel { // 초기화 init(readyStatusService: ReadyStatusServiceType, promiseID: Int) { self.readyStatusService = readyStatusService - self.promiseID = ObservablePattern(promiseID) + self.promiseID = promiseID } // 우리들의 준비 현황 변동되었을 때 @@ -51,3 +61,41 @@ class ReadyStatusViewModel { return currentTimeString } } + +extension ReadyStatusViewModel { + func fetchMyReadyStatus() { + Task { + do { + let responseBody = try await readyStatusService.fetchMyReadyStatus(with: promiseID) + + guard let success = responseBody?.success, + success == true + else { + return + } + myReadyStatus.value = responseBody?.data + } catch { + print(">>>>> \(error.localizedDescription) : \(#function)") + } + } + } + + func fetchPromiseParticipantList() { + Task { + do { + let responseBody = try await readyStatusService.fetchPromiseParticipantList( + with: promiseID + ) + + guard let success = responseBody?.success, + success == true, + let participants = responseBody?.data?.participants + else { + participantInfos.value = [] + return + } + participantInfos.value = participants + } + } + } +} diff --git a/KkuMulKum/Source/Promise/ReadyStatus/ViewModel/SetReadyInfoViewModel.swift b/KkuMulKum/Source/Promise/ReadyStatus/ViewModel/SetReadyInfoViewModel.swift index d1fb8bcd..bd4ce9b5 100644 --- a/KkuMulKum/Source/Promise/ReadyStatus/ViewModel/SetReadyInfoViewModel.swift +++ b/KkuMulKum/Source/Promise/ReadyStatus/ViewModel/SetReadyInfoViewModel.swift @@ -9,6 +9,7 @@ import Foundation final class SetReadyInfoViewModel { let promiseID: Int + let promiseName: String let promiseTime: String let isValid = ObservablePattern(false) @@ -29,9 +30,11 @@ final class SetReadyInfoViewModel { init( promiseID: Int, promiseTime: String, + promiseName: String, service: SetReadyStatusInfoServiceType ) { self.promiseID = promiseID + self.promiseName = promiseName self.promiseTime = promiseTime self.service = service }