Skip to content

Commit

Permalink
Merge pull request #247 from OMZigak/feat/#240-promise-detail
Browse files Browse the repository at this point in the history
[feat] 약속 상세 API 연결
  • Loading branch information
hooni0918 authored Jul 19, 2024
2 parents efcd731 + b292e1d commit e983f09
Show file tree
Hide file tree
Showing 10 changed files with 195 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class PagePromiseViewController: BaseViewController {

tardyViewController = TardyViewController(
tardyViewModel: TardyViewModel(
tardyService: MockTardyService(),
tardyService: PromiseService(),
promiseID: promiseViewModel.promiseID
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ class ReadyPlanInfoView: BaseView {

// MARK: Property

private let readyTimeLabel: UILabel = UILabel().then {
let readyTimeLabel: UILabel = UILabel().then {
$0.setText("12시 30분에 준비하고,\n1시에 이동을 시작해야 해요", style: .body03)
$0.setHighlightText("12시 30분", "1시", style: .body03, color: .maincolor)
}

private let requestReadyTimeLabel: UILabel = UILabel().then {
let requestReadyTimeLabel: UILabel = UILabel().then {
$0.setText("준비 소요 시간: 30분", style: .label02, color: .gray8)
}

private let requestMoveTimeLabel: UILabel = UILabel().then {
let requestMoveTimeLabel: UILabel = UILabel().then {
$0.setText("이동 소요 시간: 1시간 30분", style: .label02, color: .gray8)
}

Expand Down Expand Up @@ -69,7 +69,3 @@ class ReadyPlanInfoView: BaseView {
}
}
}

extension ReadyPlanInfoView {
func configure() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ class ReadyStatusViewController: BaseViewController {

@objc
func readyStartButtonDidTapped() {
// TODO: 늦었을 때 꾸물거릴 시간이 없어요 팝업 뜨도록 설정
readyStatusViewModel.myReadyProgressStatus.value = .ready
rootView.myReadyStatusProgressView.readyStartButton.isEnabled.toggle()
}
Expand Down Expand Up @@ -174,9 +173,32 @@ private extension ReadyStatusViewController {
owner.updateReadyInfoView(flag: false)
return
}
// TODO: 시간 계산 로직 필요..

owner.updateReadyInfoView(flag: true)
owner.rootView.readyPlanInfoView.configure()
owner.readyStatusViewModel.calculatePrepareTime()
owner.readyStatusViewModel.convertMinute()
}
}

readyStatusViewModel.moveTime.bind(with: self) { owner, moveTime in
owner.rootView.readyPlanInfoView.requestMoveTimeLabel.setText("이동 소요 시간: \(moveTime)", style: .label02, color: .gray8)
}

readyStatusViewModel.readyTime.bind(with: self) { owner, readyTime in
owner.rootView.readyPlanInfoView.requestReadyTimeLabel.setText("준비 소요 시간: \(readyTime)", style: .label02, color: .gray8)
}

readyStatusViewModel.readyStartTime.bind(with: self) { owner, readyStartTime in
DispatchQueue.main.async {
owner.rootView.readyPlanInfoView.readyTimeLabel.setText("\(readyStartTime)에 준비하고,\n\(owner.readyStatusViewModel.moveStartTime.value)에 이동을 시작해야 해요", style: .body03)
owner.rootView.readyPlanInfoView.readyTimeLabel.setHighlightText(readyStartTime, owner.readyStatusViewModel.moveStartTime.value, style: .body03, color: .maincolor)
}
}

readyStatusViewModel.moveStartTime.bind(with: self) { owner, moveStartTime in
DispatchQueue.main.async {
owner.rootView.readyPlanInfoView.readyTimeLabel.setText("\(owner.readyStatusViewModel.readyStartTime.value)에 준비하고,\n\(moveStartTime)에 이동을 시작해야 해요", style: .body03)
owner.rootView.readyPlanInfoView.readyTimeLabel.setHighlightText(owner.readyStatusViewModel.readyStartTime.value, moveStartTime, style: .body03, color: .maincolor)
}
}

Expand Down Expand Up @@ -217,7 +239,7 @@ private extension ReadyStatusViewController {
}

func updateReadyStartButton(status: ReadyProgressStatus) {
/// 버튼 누를 때 서버 통신하게 설정
// TODO: 버튼 누를 때 서버 통신하게 설정
switch status {
case .none:
rootView.myReadyStatusProgressView.readyStartButton.setupButton(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,22 @@ class ReadyStatusViewModel {
/// bind를 사용하라는 말이 아님
let promiseName = ObservablePattern<String>("")

// 준비 정보가 입력되었는지 여부
// let isReadyInfoEntered = ObservablePattern<Bool>(false)

/// 나의 준비현황이 담긴 정보
/// 설령 데이터가 없다하더라도 약속 시간은 담겨있음.
let myReadyStatus = ObservablePattern<MyReadyStatusModel?>(nil)

// 준비 시작 시간
var readyStartTime = ObservablePattern<String>("")

// 준비 소요 시간
var readyTime = ObservablePattern<String>("")

// 이동 시작 시간
var moveStartTime = ObservablePattern<String>("")

// 이동 소요 시간
var moveTime = ObservablePattern<String>("")

// 현재 준비 상태에 대한 버튼 처리
let myReadyProgressStatus = ObservablePattern<ReadyProgressStatus>(.none)

Expand Down Expand Up @@ -63,6 +72,55 @@ class ReadyStatusViewModel {
}

extension ReadyStatusViewModel {
func convertMinute() {
let preparationHours = (self.myReadyStatus.value?.preparationTime ?? 0) / 60
let preparationMinutes = (self.myReadyStatus.value?.preparationTime ?? 0) % 60

readyTime.value = preparationHours == 0 ? "\(preparationMinutes)" : "\(preparationHours)시간 \(preparationMinutes)"

let travelHours = (self.myReadyStatus.value?.travelTime ?? 0) / 60
let travelMinutes = (self.myReadyStatus.value?.travelTime ?? 0) % 60

moveTime.value = travelHours == 0 ? "\(travelMinutes)" : "\(travelHours)시간 \(travelMinutes)"
}

func calculatePrepareTime() {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
dateFormatter.locale = Locale(identifier: "ko_KR")
dateFormatter.timeZone = TimeZone(identifier: "Asia/Seoul")

let promiseTime = self.myReadyStatus.value?.promiseTime ?? ""
let readyTime = self.myReadyStatus.value?.preparationTime ?? 0
let moveTime = self.myReadyStatus.value?.travelTime ?? 0


guard let promiseDate = dateFormatter.date(from: promiseTime) else {
print("Invalid date format: \(promiseTime)")
return
}

let totalPrepTime = TimeInterval((readyTime + moveTime) * 60)

let timeFormatter = DateFormatter()
timeFormatter.dateFormat = "HH시 mm분"
timeFormatter.timeZone = TimeZone(identifier: "Asia/Seoul")

print("약속 시간: \(timeFormatter.string(from: promiseDate))")
print("준비 시간: \(readyTime)")
print("이동 시간: \(moveTime)")
print("총 준비 시간: \(totalPrepTime / 60)")

let readyStartTime = promiseDate.addingTimeInterval(-TimeInterval(readyTime + moveTime) * 60)
let moveStartTime = promiseDate.addingTimeInterval(-TimeInterval(moveTime) * 60)

self.readyStartTime.value = timeFormatter.string(from: readyStartTime)
print("준비 시작 시간: \(self.readyStartTime.value)")

self.moveStartTime.value = timeFormatter.string(from: moveStartTime)
print("이동 시작 시간: \(self.moveStartTime.value)")
}

func fetchMyReadyStatus() {
Task {
do {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ class TardyCollectionViewCell: BaseCollectionViewCell {

// MARK: Property

private let profileImageView: UIImageView = UIImageView().then {
let profileImageView: UIImageView = UIImageView().then {
$0.image = .imgProfile
$0.contentMode = .scaleAspectFill
$0.layer.cornerRadius = 67 / 2
$0.layer.cornerRadius = Screen.height(67) / 2
$0.clipsToBounds = true
}

Expand Down
2 changes: 2 additions & 0 deletions KkuMulKum/Source/Promise/Tardy/View/TardyEmptyView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class TardyEmptyView: BaseView {

private let emptyContentLabel: UILabel = UILabel().then {
$0.setText("꾸물이들이 도착하길\n기다리는 중이에요", style: .body05, color: .gray3)
}.then {
$0.textAlignment = .center
}


Expand Down
2 changes: 1 addition & 1 deletion KkuMulKum/Source/Promise/Tardy/View/TardyPenaltyView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class TardyPenaltyView: BaseView {
$0.setText("벌칙", style: .caption02, color: .gray8)
}

private let contentLabel: UILabel = UILabel().then {
let contentLabel: UILabel = UILabel().then {
$0.setText("탕후루 릴스 찍기", style: .body03, color: .gray8)
}

Expand Down
6 changes: 3 additions & 3 deletions KkuMulKum/Source/Promise/Tardy/View/TardyView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ class TardyView: BaseView {

// MARK: Property

private let tardyPenaltyView: TardyPenaltyView = TardyPenaltyView().then {
let tardyPenaltyView: TardyPenaltyView = TardyPenaltyView().then {
$0.layer.cornerRadius = 8
}

private let titleLabel: UILabel = UILabel().then {
$0.setText("이번 약속의 지각 꾸물이는?", style: .head01, color: .gray8)
}

private let tardyEmptyView: TardyEmptyView = TardyEmptyView()
let tardyEmptyView: TardyEmptyView = TardyEmptyView()

let tardyCollectionView: UICollectionView = UICollectionView(
frame: .zero,
Expand Down Expand Up @@ -74,7 +74,7 @@ class TardyView: BaseView {
tardyEmptyView.snp.makeConstraints {
$0.top.equalTo(titleLabel.snp.bottom).offset(108)
$0.centerX.equalToSuperview()
$0.height.equalTo(Screen.height(192))
$0.height.equalTo(Screen.height(210))
$0.width.equalTo(Screen.width(112))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ class TardyViewController: BaseViewController {
// MARK: - Setup

override func loadView() {
let state = !tardyViewModel.hasTardy.value && tardyViewModel.isPastDue.value
view = state ? tardyView : arriveView
view = tardyViewModel.isPastDue.value ? arriveView : tardyView
}

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)

// TODO: 서버 통신하고 데이터 바인딩
tardyViewModel.fetchTardyInfo()
tardyViewModel.updatePromiseCompletion()
}

override func viewDidLoad() {
Expand All @@ -50,7 +50,6 @@ class TardyViewController: BaseViewController {
}

override func setupDelegate() {
tardyView.tardyCollectionView.delegate = self
tardyView.tardyCollectionView.dataSource = self
}
}
Expand All @@ -61,34 +60,48 @@ class TardyViewController: BaseViewController {
private extension TardyViewController {
func setupBinding() {
/// 시간이 지나고 지각자가 없을 때 arriveView로 띄워짐
tardyViewModel.hasTardy.bind(with: self) { owner, flag in
let state = !flag && owner.tardyViewModel.isPastDue.value
owner.view = state ? owner.tardyView : owner.arriveView
tardyViewModel.isPastDue.bind(with: self) { owner, isPastDue in
DispatchQueue.main.async {
owner.tardyView.tardyCollectionView.isHidden = !isPastDue
owner.tardyView.tardyEmptyView.isHidden = isPastDue
owner.tardyView.finishMeetingButton.isEnabled = isPastDue
}
}

/// isFinishButtonEnabled에 따라서 버튼 활성화 상태 변경
tardyViewModel.isFinishButtonEnabled.bind(with: self) { owner, flag in
self.tardyView.finishMeetingButton.isEnabled = flag
tardyViewModel.penalty.bind(with: self) {
owner,
penalty in
DispatchQueue.main.async {
owner.tardyView.tardyPenaltyView.contentLabel.setText(
penalty,
style: .body03,
color: .gray8
)
}
}

tardyViewModel.hasTardy.bind(with: self) { owner, hasTardy in
DispatchQueue.main.async {
owner.view = hasTardy && owner.tardyViewModel.isPastDue.value ? owner.arriveView : owner.tardyView
}
}

tardyViewModel.comers.bind(with: self) { owner, comers in
DispatchQueue.main.async {
owner.tardyView.tardyCollectionView.reloadData()
}
}
}
}

// MARK: UICollectionViewDelegate

extension TardyViewController: UICollectionViewDelegate {

}


// MARK: UICollectionViewDataSource

extension TardyViewController: UICollectionViewDataSource {
func collectionView(
_ collectionView: UICollectionView,
numberOfItemsInSection section: Int
) -> Int {
// TODO: 데이터 바인딩
return 10
return tardyViewModel.comers.value?.count ?? 0
}

func collectionView(
Expand All @@ -100,6 +113,18 @@ extension TardyViewController: UICollectionViewDataSource {
for: indexPath
) as? TardyCollectionViewCell else { return UICollectionViewCell() }

guard let data = tardyViewModel.comers.value?[indexPath.row] else { return cell }

cell.nameLabel.setText(data.name, style: .body06, color: .gray6)

guard let image = URL(string: data.profileImageURL) else {
cell.profileImageView.image = .imgProfile

return cell
}

cell.profileImageView.kf.setImage(with: image)

return cell
}
}
Loading

0 comments on commit e983f09

Please sign in to comment.