diff --git a/KkuMulKum/Source/Promise/EditPromise/ViewController/ChooseContentViewController.swift b/KkuMulKum/Source/Promise/EditPromise/ViewController/ChooseContentViewController.swift index fde71bbf..a11b161f 100644 --- a/KkuMulKum/Source/Promise/EditPromise/ViewController/ChooseContentViewController.swift +++ b/KkuMulKum/Source/Promise/EditPromise/ViewController/ChooseContentViewController.swift @@ -54,7 +54,22 @@ class ChooseContentViewController: BaseViewController { rootView.confirmButton.setTitle("수정하기", style: .body03, color: .white) for button in self.rootView.levelButtons { - button.isSelected = (button.titleLabel?.text == viewModel.dressUpLevel?.value) + let levels = ["LV1", "LV2", "LV3", "LV4", "FREE"] + + if var dressUpLevel = button.titleLabel?.text { + if dressUpLevel.contains("마음대로 입고 오기") { + dressUpLevel = "FREE" + } + else { + if let matched = levels.first(where: { + level in dressUpLevel.replacingOccurrences(of: " ", with: "").contains(level) + }) { + dressUpLevel = matched + } + } + + button.isSelected = (dressUpLevel == viewModel.dressUpLevel?.value) + } } for button in self.rootView.penaltyButtons { diff --git a/KkuMulKum/Source/Promise/EditPromise/ViewController/ChooseMemberViewController.swift b/KkuMulKum/Source/Promise/EditPromise/ViewController/ChooseMemberViewController.swift index 92c5fc92..2b6d0d5e 100644 --- a/KkuMulKum/Source/Promise/EditPromise/ViewController/ChooseMemberViewController.swift +++ b/KkuMulKum/Source/Promise/EditPromise/ViewController/ChooseMemberViewController.swift @@ -76,7 +76,8 @@ class ChooseMemberViewController: BaseViewController { private extension ChooseMemberViewController { func setupBinding() { viewModel.participantList?.bindOnMain(with: self, { owner, members in - self.rootView.memberListView.reloadData() + owner.rootView.emptyContentView.isHidden = !members.isEmpty + owner.rootView.memberListView.reloadData() }) } diff --git a/KkuMulKum/Source/Promise/PagePromise/ViewController/PromiseViewController.swift b/KkuMulKum/Source/Promise/PagePromise/ViewController/PromiseViewController.swift index 66761ff5..cb888c15 100644 --- a/KkuMulKum/Source/Promise/PagePromise/ViewController/PromiseViewController.swift +++ b/KkuMulKum/Source/Promise/PagePromise/ViewController/PromiseViewController.swift @@ -151,7 +151,6 @@ private extension PromiseViewController { viewModel.promiseInfo.bindOnMain(with: self) { owner, info in owner.setupNavigationBarTitle(with: info?.promiseName ?? "", isBorderHidden: true) - owner.promiseInfoViewController.rootView.editButton.isHidden = !(info?.isParticipant ?? false) owner.setupPromiseEditButton(isHidden: !(info?.isParticipant ?? false)) owner.promiseInfoViewController.setupContent() diff --git a/KkuMulKum/Source/Promise/PromiseInfo/ViewController/PromiseInfoViewController.swift b/KkuMulKum/Source/Promise/PromiseInfo/ViewController/PromiseInfoViewController.swift index 5adb6013..55f1dcae 100644 --- a/KkuMulKum/Source/Promise/PromiseInfo/ViewController/PromiseInfoViewController.swift +++ b/KkuMulKum/Source/Promise/PromiseInfo/ViewController/PromiseInfoViewController.swift @@ -53,6 +53,10 @@ class PromiseInfoViewController: BaseViewController { override func setupView() { view.backgroundColor = .gray0 + + if let isParticipant = viewModel.promiseInfo.value?.isParticipant { + rootView.editButton.isHidden = isParticipant + } } override func setupDelegate() { @@ -71,24 +75,42 @@ class PromiseInfoViewController: BaseViewController { extension PromiseInfoViewController { @objc func editButtonDidTap() { - let viewController = EditPromiseViewController( - viewModel: EditPromiseViewModel( - promiseID: viewModel.promiseID, - promiseName: viewModel.promiseInfo.value?.promiseName, - placeName: viewModel.promiseInfo.value?.placeName, - time: viewModel.promiseInfo.value?.time, - dressUpLevel: viewModel.promiseInfo.value?.dressUpLevel, - penalty: viewModel.promiseInfo.value?.penalty, - service: PromiseService() + if var dressUpLevel = viewModel.promiseInfo.value?.dressUpLevel { + let levels = ["LV1", "LV2", "LV3", "LV4", "FREE"] + + if dressUpLevel.contains("마음대로 입고 오기") { + dressUpLevel = "FREE" + } + else { + if let matched = levels.first(where: { + level in dressUpLevel.replacingOccurrences(of: " ", with: "").contains(level) + }) { + dressUpLevel = matched + } + } + + let viewController = EditPromiseViewController( + viewModel: EditPromiseViewModel( + promiseID: viewModel.promiseID, + promiseName: viewModel.promiseInfo.value?.promiseName, + placeName: viewModel.promiseInfo.value?.placeName, + xCoordinate: viewModel.promiseInfo.value?.x, + yCoordinate: viewModel.promiseInfo.value?.y, + address: viewModel.promiseInfo.value?.address, + roadAddress: viewModel.promiseInfo.value?.roadAddress, + time: viewModel.promiseInfo.value?.time, + dressUpLevel: dressUpLevel, + penalty: viewModel.promiseInfo.value?.penalty, + service: PromiseService() + ) ) - ) - - navigationController?.pushViewController(viewController, animated: true) + + navigationController?.pushViewController(viewController, animated: true) + } } func setupBinding() { viewModel.isPastDue.bindOnMain(with: self) { owner, isPastDue in - owner.rootView.editButton.isHidden = isPastDue } diff --git a/KkuMulKum/Source/Promise/ReadyStatus/View/ReadyStatusView.swift b/KkuMulKum/Source/Promise/ReadyStatus/View/ReadyStatusView.swift index 4d6b25a0..682a5e5c 100644 --- a/KkuMulKum/Source/Promise/ReadyStatus/View/ReadyStatusView.swift +++ b/KkuMulKum/Source/Promise/ReadyStatus/View/ReadyStatusView.swift @@ -31,6 +31,7 @@ class ReadyStatusView: BaseView { let popUpImageView: UIImageView = UIImageView(image: .imgTextPopup).then { $0.contentMode = .scaleAspectFit + $0.isHidden = true } let ourReadyStatusCollectionView: UICollectionView = UICollectionView( diff --git a/KkuMulKum/Source/Promise/ReadyStatus/ViewController/ReadyStatusViewController.swift b/KkuMulKum/Source/Promise/ReadyStatus/ViewController/ReadyStatusViewController.swift index 4bd24f04..6f0b9e8c 100644 --- a/KkuMulKum/Source/Promise/ReadyStatus/ViewController/ReadyStatusViewController.swift +++ b/KkuMulKum/Source/Promise/ReadyStatus/ViewController/ReadyStatusViewController.swift @@ -45,6 +45,7 @@ class ReadyStatusViewController: BaseViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) + viewModel.fetchPromiseInfo() viewModel.fetchMyReadyStatus() viewModel.fetchPromiseParticipantList() } @@ -97,48 +98,47 @@ class ReadyStatusViewController: BaseViewController { extension ReadyStatusViewController { func setupBinding() { viewModel.promiseInfo.bindOnMain(with: self) { owner, model in - owner.rootView.myReadyStatusProgressView.isUserInteractionEnabled = (model?.isParticipant ?? false) + guard let isParticipant = model?.isParticipant else { return } + + owner.rootView.enterReadyButtonView.isUserInteractionEnabled = isParticipant + + if !isParticipant { + owner.updateReadyInfoView(flag: false) + owner.rootView.myReadyStatusProgressView.readyStartButton.setupButton("준비 시작", .none) + } } - viewModel.myReadyStatus.bind(with: self) { - owner, - model in - DispatchQueue.main.async { - guard let model else { - owner.updateReadyInfoView(flag: false) - return - } - - /// 준비 시간을 계산해 UI에 표시 - owner.viewModel.calculateDuration() - owner.viewModel.calculateStartTime() - - /// myReadyStatus의 바인딩 부분에 조건을 통해 myReadyProgressStatus 값을 업데이트 - if model.preparationStartAt == nil { - owner.viewModel.myReadyProgressStatus.value = .none - } - else if model.departureAt == nil { - owner.viewModel.myReadyProgressStatus.value = .ready - } - else if model.arrivalAt == nil { - owner.viewModel.myReadyProgressStatus.value = .move - } - else { - owner.viewModel.myReadyProgressStatus.value = .done - } - - /// 준비하기 버튼과 준비 정보 화면 중 어떤 걸 표시할지 결정 - if model.preparationTime == nil { - owner.updateReadyInfoView(flag: false) - return - } - - owner.updateReadyInfoView(flag: true) + + viewModel.myReadyStatus.bindOnMain(with: self) { owner, model in + guard let status = model else { return } + + /// 준비 시간을 계산해 UI에 표시 + owner.viewModel.calculateDuration() + owner.viewModel.calculateStartTime() + + /// myReadyStatus의 바인딩 부분에 조건을 통해 myReadyProgressStatus 값을 업데이트 + if status.preparationStartAt == nil { + owner.viewModel.myReadyProgressStatus.value = .none + } + else if status.departureAt == nil { + owner.viewModel.myReadyProgressStatus.value = .ready + } + else if status.arrivalAt == nil { + owner.viewModel.myReadyProgressStatus.value = .move } + else { + owner.viewModel.myReadyProgressStatus.value = .done + } + + /// 준비하기 버튼과 준비 정보 화면 중 어떤 걸 표시할지 결정 + if status.preparationTime == nil { + owner.updateReadyInfoView(flag: false) + return + } + + owner.updateReadyInfoView(flag: true) } - viewModel.moveDuration.bind(with: self) { - owner, - moveTime in + viewModel.moveDuration.bind(with: self) { owner, moveTime in owner.rootView.readyPlanInfoView.requestMoveTimeLabel.setText( "이동 소요 시간: \(moveTime)", style: .label02, @@ -173,9 +173,7 @@ extension ReadyStatusViewController { } } - viewModel.moveStartTime.bind(with: self) { - owner, - moveStartTime in + viewModel.moveStartTime.bind(with: self) { owner, moveStartTime in DispatchQueue.main.async { owner.rootView.readyPlanInfoView.readyTimeLabel.setText( "\(owner.viewModel.readyStartTime.value)에 준비하고,\n\(moveStartTime)에 이동을 시작해야 해요", @@ -192,6 +190,7 @@ extension ReadyStatusViewController { viewModel.myReadyProgressStatus.bindOnMain(with: self) { owner, status in owner.updateReadyStartButton() + owner.rootView.ourReadyStatusCollectionView.reloadData() } viewModel.participantsInfo.bindOnMain(with: self) { owner, participants in @@ -205,7 +204,7 @@ extension ReadyStatusViewController { } viewModel.isLate.bindOnMain(with: self) { owner, status in - self.updatePopUpImageView() + owner.updatePopUpImageView() } } @@ -418,20 +417,23 @@ extension ReadyStatusViewController { @objc func readyStartButtonDidTap() { - viewModel.fetchPromiseParticipantList() - viewModel.updatePreparationStatus() + viewModel.updatePreparationStatus { [weak self] in + self?.viewModel.fetchPromiseParticipantList() + } } @objc func moveStartButtonDidTap() { - viewModel.fetchPromiseParticipantList() - viewModel.updateDepartureStatus() + viewModel.updateDepartureStatus { [weak self] in + self?.viewModel.fetchPromiseParticipantList() + } } @objc func arrivalButtonDidTap() { - viewModel.fetchPromiseParticipantList() - viewModel.updateArrivalStatus() + viewModel.updateArrivalStatus { [weak self] in + self?.viewModel.fetchPromiseParticipantList() + } } @objc @@ -512,14 +514,18 @@ extension ReadyStatusViewController: UICollectionViewDataSource { } switch viewModel.participantsInfo.value?[indexPath.row].state { - case "도착": - cell.readyStatusButton.setupButton("도착", .done) - case "이동중": - cell.readyStatusButton.setupButton("이동중", .move) + case "꾸물중": + cell.readyStatusButton.setupButton("꾸물중", .none) case "준비중": cell.readyStatusButton.setupButton("준비중", .ready) - default: - cell.readyStatusButton.setupButton("꾸물중", .none) + case "이동중": + cell.readyStatusButton.setupButton("이동중", .move) + case "도착": + cell.readyStatusButton.setupButton("도착", .done) + case .none: + return cell + case .some(_): + return cell } return cell diff --git a/KkuMulKum/Source/Promise/Tardy/View/ArriveView.swift b/KkuMulKum/Source/Promise/Tardy/View/ArriveView.swift index 2a1230d0..919e3daf 100644 --- a/KkuMulKum/Source/Promise/Tardy/View/ArriveView.swift +++ b/KkuMulKum/Source/Promise/Tardy/View/ArriveView.swift @@ -55,12 +55,12 @@ class ArriveView: BaseView { } mainTitleLabel.snp.makeConstraints { - $0.top.equalTo(giftImageView.snp.bottom).offset(36) + $0.top.equalTo(giftImageView.snp.bottom).offset(30) $0.centerX.equalToSuperview() } subTitleLabel.snp.makeConstraints { - $0.top.equalTo(mainTitleLabel.snp.bottom).offset(17) + $0.top.equalTo(mainTitleLabel.snp.bottom).offset(4) $0.centerX.equalToSuperview() } diff --git a/KkuMulKum/Source/Promise/Tardy/ViewController/TardyViewController.swift b/KkuMulKum/Source/Promise/Tardy/ViewController/TardyViewController.swift index dba12081..653212a1 100644 --- a/KkuMulKum/Source/Promise/Tardy/ViewController/TardyViewController.swift +++ b/KkuMulKum/Source/Promise/Tardy/ViewController/TardyViewController.swift @@ -29,10 +29,6 @@ class TardyViewController: BaseViewController { fatalError("init(coder:) has not been implemented") } - override func loadView() { - view = viewModel.isPastDue.value ? arriveView : tardyView - } - override func viewDidLoad() { super.viewDidLoad() @@ -41,11 +37,23 @@ class TardyViewController: BaseViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) + + viewModel.fetchTardyInfo() } // MARK: - Setup + override func setupView() { + view.addSubviews(arriveView, tardyView) + + [arriveView, tardyView].forEach { + $0.snp.makeConstraints { + $0.edges.equalToSuperview() + } + } + } + override func setupDelegate() { tardyView.tardyCollectionView.dataSource = self } @@ -58,8 +66,6 @@ private extension TardyViewController { func setupBinding() { /// 시간이 지나고 지각자가 없을 때 arriveView로 띄워짐 viewModel.isPastDue.bindOnMain(with: self) { owner, isPastDue in - owner.tardyView.tardyCollectionView.isHidden = !isPastDue - owner.tardyView.tardyEmptyView.isHidden = isPastDue owner.tardyView.finishMeetingButton.isEnabled = (isPastDue && (owner.viewModel.promiseInfo.value?.isParticipant ?? false)) } @@ -71,10 +77,14 @@ private extension TardyViewController { ) } - viewModel.hasTardy.bind(with: self) { owner, hasTardy in - DispatchQueue.main.async { - owner.view = hasTardy && owner.viewModel.isPastDue.value ? owner.arriveView : owner.tardyView - } + viewModel.hasTardy.bindOnMain(with: self) { owner, hasTardy in + let isPastDue = owner.viewModel.isPastDue.value + let arriveHideFlag = !(isPastDue && !hasTardy) + + owner.arriveView.isHidden = arriveHideFlag + owner.tardyView.isHidden = !arriveHideFlag + owner.tardyView.tardyCollectionView.isHidden = !isPastDue + owner.tardyView.tardyEmptyView.isHidden = isPastDue } viewModel.comers.bind(with: self) { owner, comers in diff --git a/KkuMulKum/Source/Promise/ViewModel/PromiseViewModel.swift b/KkuMulKum/Source/Promise/ViewModel/PromiseViewModel.swift index 3c5c7073..3d79fa08 100644 --- a/KkuMulKum/Source/Promise/ViewModel/PromiseViewModel.swift +++ b/KkuMulKum/Source/Promise/ViewModel/PromiseViewModel.swift @@ -265,7 +265,7 @@ extension PromiseViewModel { } /// 준비 시작 업데이트 API 구현 함수 - func updatePreparationStatus() { + func updatePreparationStatus(completion: @escaping () -> Void) { Task { do { let responseBody = try await service.updatePreparationStatus( @@ -281,12 +281,14 @@ extension PromiseViewModel { myReadyProgressStatus.value = .ready self.checkLate(tappedButton: .ready) + + completion() } } } /// 이동 시작 업데이트 API 구현 함수 - func updateDepartureStatus() { + func updateDepartureStatus(completion: @escaping () -> Void) { Task { do { let responseBody = try await service.updateDepartureStatus( @@ -302,12 +304,14 @@ extension PromiseViewModel { myReadyProgressStatus.value = .move self.checkLate(tappedButton: .move) + + completion() } } } /// 도착 완료 업데이트 API 구현 함수 - func updateArrivalStatus() { + func updateArrivalStatus(completion: @escaping () -> Void) { Task { do { let responseBody = try await service.updateArrivalStatus( @@ -321,6 +325,8 @@ extension PromiseViewModel { } myReadyProgressStatus.value = .done + + completion() } } } @@ -342,7 +348,7 @@ extension PromiseViewModel { return } - hasTardy.value = data.lateComers.isEmpty + hasTardy.value = !(data.lateComers.isEmpty) isPastDue.value = data.isPastDue penalty.value = data.penalty comers.value = data.lateComers