diff --git a/iOS/Projects/Features/WriteBoard/Sources/Dombain/Entities/Record.swift b/iOS/Projects/Features/WriteBoard/Sources/Dombain/Entities/Record.swift new file mode 100644 index 00000000..d7f896d2 --- /dev/null +++ b/iOS/Projects/Features/WriteBoard/Sources/Dombain/Entities/Record.swift @@ -0,0 +1,53 @@ +// +// Record.swift +// WriteBoardFeature +// +// Created by MaraMincho on 1/11/24. +// Copyright © 2024 kr.codesquad.boostcamp8. All rights reserved. +// + +import Foundation + +/// 기록 목록을 표시하기위해 사용하는 모델입니다. +struct Record: Codable, Hashable { + /// 현재 운동의 날짜를 나타냅니다. + let dateString: String + + /// 현재 운동의 목록을 나타냅니다. + let workoutID: Int + + /// 운동 시작 시간 + /// + /// HH:MM 으로 표시 + let startTime: String + + /// 운동 끝 시간 + /// + /// HH:MM 으로 표시 + let endTime: String + + /// 총 운동한 거리를 "미터"단위로 표시해줍니다. + let distance: Int +} + +extension Record { + var durationTime: String { + guard + let endDate = DateFormatter.HHmmFormatter.date(from: endTime), + let startDate = DateFormatter.HHmmFormatter.date(from: startTime) else { + return "" + } + let timeInterval = endDate.timeIntervalSince(startDate) + let hours = Int(timeInterval / 3600) + let minutes = Int((timeInterval.truncatingRemainder(dividingBy: 3600)) / 60) + return "\(hours):\(minutes)" + } +} + +private extension DateFormatter { + static let HHmmFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateFormat = "HH:mm" + return formatter + }() +} diff --git a/iOS/Projects/Features/WriteBoard/Sources/Presentation/Common/Coordinator/WriteBoardCoordinator.swift b/iOS/Projects/Features/WriteBoard/Sources/Presentation/Common/Coordinator/WriteBoardCoordinator.swift index d133f964..78c67651 100644 --- a/iOS/Projects/Features/WriteBoard/Sources/Presentation/Common/Coordinator/WriteBoardCoordinator.swift +++ b/iOS/Projects/Features/WriteBoard/Sources/Presentation/Common/Coordinator/WriteBoardCoordinator.swift @@ -64,7 +64,12 @@ public final class WriteBoardCoordinator: WriteBoardFeatureCoordinating { containerViewController?.pushViewController(viewController, animated: false) } - public func pushWriteBoardScene() {} + public func pushWriteBoardScene() { + let viewModel = WriteBoardViewModel() + let viewController = WriteBoardViewController(viewModel: viewModel) + + containerViewController?.pushViewController(viewController, animated: true) + } public func didFinishWriteBoard() {} diff --git a/iOS/Projects/Features/WriteBoard/Sources/Presentation/Common/ContainerViewController/ContainerViewController.swift b/iOS/Projects/Features/WriteBoard/Sources/Presentation/ContainerViewController/ContainerViewController.swift similarity index 100% rename from iOS/Projects/Features/WriteBoard/Sources/Presentation/Common/ContainerViewController/ContainerViewController.swift rename to iOS/Projects/Features/WriteBoard/Sources/Presentation/ContainerViewController/ContainerViewController.swift diff --git a/iOS/Projects/Features/WriteBoard/Sources/Presentation/Common/ContainerViewController/ContainerViewModel.swift b/iOS/Projects/Features/WriteBoard/Sources/Presentation/ContainerViewController/ContainerViewModel.swift similarity index 100% rename from iOS/Projects/Features/WriteBoard/Sources/Presentation/Common/ContainerViewController/ContainerViewModel.swift rename to iOS/Projects/Features/WriteBoard/Sources/Presentation/ContainerViewController/ContainerViewModel.swift diff --git a/iOS/Projects/Features/WriteBoard/Sources/Presentation/WirteBoardScene/WriteBoardViewController.swift b/iOS/Projects/Features/WriteBoard/Sources/Presentation/WirteBoardScene/WriteBoardViewController.swift new file mode 100644 index 00000000..fbdaefa4 --- /dev/null +++ b/iOS/Projects/Features/WriteBoard/Sources/Presentation/WirteBoardScene/WriteBoardViewController.swift @@ -0,0 +1,73 @@ +// +// WriteBoardViewController.swift +// WriteBoardFeature +// +// Created by MaraMincho on 1/11/24. +// Copyright © 2024 kr.codesquad.boostcamp8. All rights reserved. +// + +import Combine +import DesignSystem +import UIKit + +// MARK: - WriteBoardViewController + +final class WriteBoardViewController: UIViewController { + // MARK: Properties + + private let viewModel: WriteBoardViewModelRepresentable + + private var subscriptions: Set = [] + + // MARK: UI Components + + private let button: UIButton = .init(configuration: .mainEnabled(title: "test button")) + + // MARK: Initializations + + init(viewModel: WriteBoardViewModelRepresentable) { + self.viewModel = viewModel + super.init(nibName: nil, bundle: nil) + } + + @available(*, unavailable) + required init?(coder _: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: Life Cycles + + override func viewDidLoad() { + super.viewDidLoad() + setup() + } +} + +private extension WriteBoardViewController { + func setup() { + setupStyles() + setupHierarchyAndConstraints() + bind() + } + + func setupHierarchyAndConstraints() { + let safeArea = view.safeAreaLayoutGuide + } + + func setupStyles() { + view.backgroundColor = DesignSystemColor.primaryBackground + } + + func bind() { + let output = viewModel.transform(input: .init()) + output.sink { state in + switch state { + case .idle: + break + } + } + .store(in: &subscriptions) + } + + enum Metrics {} +} diff --git a/iOS/Projects/Features/WriteBoard/Sources/Presentation/WirteBoardScene/WriteBoardViewModel.swift b/iOS/Projects/Features/WriteBoard/Sources/Presentation/WirteBoardScene/WriteBoardViewModel.swift new file mode 100644 index 00000000..d9d13523 --- /dev/null +++ b/iOS/Projects/Features/WriteBoard/Sources/Presentation/WirteBoardScene/WriteBoardViewModel.swift @@ -0,0 +1,48 @@ +// +// WriteBoardViewModel.swift +// WriteBoardFeature +// +// Created by MaraMincho on 1/11/24. +// Copyright © 2024 kr.codesquad.boostcamp8. All rights reserved. +// + +import Combine +import Foundation + +// MARK: - WriteBoardViewModelInput + +public struct WriteBoardViewModelInput {} + +public typealias WriteBoardViewModelOutput = AnyPublisher + +// MARK: - WriteBoardState + +public enum WriteBoardState { + case idle +} + +// MARK: - WriteBoardViewModelRepresentable + +protocol WriteBoardViewModelRepresentable { + func transform(input: WriteBoardViewModelInput) -> WriteBoardViewModelOutput +} + +// MARK: - WriteBoardViewModel + +final class WriteBoardViewModel { + // MARK: - Properties + + private var subscriptions: Set = [] +} + +// MARK: WriteBoardViewModelRepresentable + +extension WriteBoardViewModel: WriteBoardViewModelRepresentable { + public func transform(input _: WriteBoardViewModelInput) -> WriteBoardViewModelOutput { + subscriptions.removeAll() + + let initialState: WriteBoardViewModelOutput = Just(.idle).eraseToAnyPublisher() + + return initialState + } +} diff --git a/iOS/Projects/Features/WriteBoard/Sources/Presentation/WorkoutHistorySelectScene/View/WorkoutHistoryCell.swift b/iOS/Projects/Features/WriteBoard/Sources/Presentation/WorkoutHistorySelectScene/View/WorkoutHistoryCell.swift index 579ba762..8512c84c 100644 --- a/iOS/Projects/Features/WriteBoard/Sources/Presentation/WorkoutHistorySelectScene/View/WorkoutHistoryCell.swift +++ b/iOS/Projects/Features/WriteBoard/Sources/Presentation/WorkoutHistorySelectScene/View/WorkoutHistoryCell.swift @@ -100,8 +100,7 @@ final class WorkoutHistoryCell: UITableViewCell { }() private let workoutImageView: UIImageView = { - let configure: UIImage.SymbolConfiguration = .init(font: .boldSystemFont(ofSize: 35)) - var image = UIImage(systemName: "figure.run", withConfiguration: configure) + var image = UIImage(systemName: "figure.run", withConfiguration: UIImage.configure) let imageView = UIImageView(image: image) imageView.contentMode = .scaleAspectFit @@ -179,3 +178,50 @@ private extension WorkoutHistoryCell { layer.cornerRadius = radius } } + +extension WorkoutHistoryCell { + func configure(_ record: Record) { + workoutImageView.image = record.image + workoutTitleLabel.text = record.name + workoutDistanceLabel.text = record.kmDistance + dateLabel.text = record.dateString + timeLabel.text = record.timeDescription + } +} + +private extension Record { + var timeDescription: String { + return "\(startTime) ~ \(endTime) \(durationTime)" + } + var kmDistance: String { + return String(Double(distance) / 1000) + "km" + } + var name: String { + switch workoutID { + case 1: + return "달리기" + case 2: + return "수영" + case 3: + return "사이클" + default: + return "달리기" + } + } + var image: UIImage? { + switch workoutID { + case 1: + return UIImage(systemName: "figure.run", withConfiguration: UIImage.configure) + case 2: + return UIImage(systemName: "figure.pool.swim", withConfiguration: UIImage.configure) + case 3: + return UIImage(systemName: "figure.outdoor.cycle", withConfiguration: UIImage.configure) + default: + return UIImage(systemName: "figure.run", withConfiguration: UIImage.configure) + } + } +} + +private extension UIImage { + static let configure: UIImage.SymbolConfiguration = .init(font: .boldSystemFont(ofSize: 35)) +} diff --git a/iOS/Projects/Features/WriteBoard/Sources/Presentation/WorkoutHistorySelectScene/View/WorkoutHistorySelectViewController.swift b/iOS/Projects/Features/WriteBoard/Sources/Presentation/WorkoutHistorySelectScene/View/WorkoutHistorySelectViewController.swift index bb4cdd97..e27c6941 100644 --- a/iOS/Projects/Features/WriteBoard/Sources/Presentation/WorkoutHistorySelectScene/View/WorkoutHistorySelectViewController.swift +++ b/iOS/Projects/Features/WriteBoard/Sources/Presentation/WorkoutHistorySelectScene/View/WorkoutHistorySelectViewController.swift @@ -20,7 +20,7 @@ final class WorkoutHistorySelectViewController: UIViewController { private var subscriptions: Set = [] - private var dataSource: UITableViewDiffableDataSource? = nil + private var dataSource: UITableViewDiffableDataSource? = nil // MARK: UI Components @@ -85,11 +85,11 @@ private extension WorkoutHistorySelectViewController { } func setDataSource() { - dataSource = .init(tableView: workoutHistoryTableView) { tableView, _, _ in + dataSource = .init(tableView: workoutHistoryTableView) { tableView, _, itemIdentifier in guard let cell = tableView.dequeueReusableCell(withIdentifier: WorkoutHistoryCell.identifier) as? WorkoutHistoryCell else { return UITableViewCell() } - + cell.configure(itemIdentifier) return cell } guard let dataSource else { return } @@ -104,7 +104,11 @@ private extension WorkoutHistorySelectViewController { return } var snapshot = dataSource.snapshot() - snapshot.appendItems([.init(), .init(), .init()]) + snapshot.appendItems([ + .init(dateString: "11월 9일", workoutID: 2, startTime: "06:00", endTime: "06:30", distance: 500), + .init(dateString: "11월 7일", workoutID: 1, startTime: "06:00", endTime: "07:00", distance: 1500), + .init(dateString: "11월 6일", workoutID: 3, startTime: "06:00", endTime: "06:30", distance: 1000), + ]) dataSource.apply(snapshot) } @@ -136,4 +140,9 @@ extension WorkoutHistorySelectViewController: UITableViewDelegate { func tableView(_: UITableView, estimatedHeightForRowAt _: IndexPath) -> CGFloat { return 80 } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + let item = dataSource?.snapshot().itemIdentifiers[indexPath.row] + + } } diff --git a/iOS/Projects/Features/WriteBoard/Sources/Presentation/WorkoutHistorySelectScene/ViewModel/WorkoutHistorySelectViewModel.swift b/iOS/Projects/Features/WriteBoard/Sources/Presentation/WorkoutHistorySelectScene/ViewModel/WorkoutHistorySelectViewModel.swift index 98cbc6cd..92956160 100644 --- a/iOS/Projects/Features/WriteBoard/Sources/Presentation/WorkoutHistorySelectScene/ViewModel/WorkoutHistorySelectViewModel.swift +++ b/iOS/Projects/Features/WriteBoard/Sources/Presentation/WorkoutHistorySelectScene/ViewModel/WorkoutHistorySelectViewModel.swift @@ -11,7 +11,9 @@ import Foundation // MARK: - SelectWorkoutViewModelInput -public struct SelectWorkoutViewModelInput {} +public struct SelectWorkoutViewModelInput { + let selectCell: AnyPublisher +} public typealias SelectWorkoutViewModelOutput = AnyPublisher @@ -33,13 +35,20 @@ final class WorkoutHistorySelectViewModel { // MARK: - Properties private var subscriptions: Set = [] + weak var writeBoardCoordinator: WriteBoardCoordinator } // MARK: SelectWorkoutViewModelRepresentable extension WorkoutHistorySelectViewModel: SelectWorkoutViewModelRepresentable { - public func transform(input _: SelectWorkoutViewModelInput) -> SelectWorkoutViewModelOutput { + public func transform(input: SelectWorkoutViewModelInput) -> SelectWorkoutViewModelOutput { subscriptions.removeAll() + + input.selectCell + .sink { [weak self] record in + + } + .store(in: &subscriptions) let initialState: SelectWorkoutViewModelOutput = Just(.idle).eraseToAnyPublisher()