diff --git a/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj b/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj index 84b46861..a0f0103a 100644 --- a/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj +++ b/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj @@ -21,6 +21,7 @@ CE0C23742966D62A00B45063 /* PagedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0C23732966D62A00B45063 /* PagedView.swift */; }; CE0C23772966D64D00B45063 /* PageCVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0C23762966D64D00B45063 /* PageCVC.swift */; }; CE0C23792966D6AF00B45063 /* ViewPager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0C23782966D6AF00B45063 /* ViewPager.swift */; }; + A3BC2F432966A93100198261 /* CourseDetailVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3BC2F422966A93100198261 /* CourseDetailVC.swift */; }; CE0D9FD329648DA300CEB5CD /* CustomAlertVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0D9FD229648DA300CEB5CD /* CustomAlertVC.swift */; }; CE146770296568DC00DCEA1B /* RunTrackingVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE14676F296568DC00DCEA1B /* RunTrackingVC.swift */; }; CE14677829658C7200DCEA1B /* Stopwatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE14677729658C7200DCEA1B /* Stopwatch.swift */; }; @@ -129,6 +130,7 @@ A3BC2F3C296468E500198261 /* UploadedCourseInfoModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UploadedCourseInfoModel.swift; sourceTree = ""; }; A3BC2F3E2964706100198261 /* UploadedCourseInfoCVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UploadedCourseInfoCVC.swift; sourceTree = ""; }; A3BC2F4029667A0D00198261 /* NicknameEditorVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NicknameEditorVC.swift; sourceTree = ""; }; + A3BC2F422966A93100198261 /* CourseDetailVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseDetailVC.swift; sourceTree = ""; }; CE0C23732966D62A00B45063 /* PagedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PagedView.swift; sourceTree = ""; }; CE0C23762966D64D00B45063 /* PageCVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageCVC.swift; sourceTree = ""; }; CE0C23782966D6AF00B45063 /* ViewPager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewPager.swift; sourceTree = ""; }; @@ -505,6 +507,7 @@ isa = PBXGroup; children = ( CEEC6B462961C5BB00D00E1E /* .gitkeep */, + A3BC2F422966A93100198261 /* CourseDetailVC.swift */, ); path = VC; sourceTree = ""; @@ -1032,6 +1035,7 @@ CEEC6B492961C5E200D00E1E /* SplashVC.swift in Sources */, CE6655D0295D85FF00C64E12 /* CancelBag.swift in Sources */, DA20D83F296696A000F1581F /* MapModel.swift in Sources */, + A3BC2F432966A93100198261 /* CourseDetailVC.swift in Sources */, A3BC2F3D296468E500198261 /* UploadedCourseInfoModel.swift in Sources */, DA20D8502966C0D500F1581F /* MapCollectionViewController.swift in Sources */, CE6655DC295D873500C64E12 /* UIButton+.swift in Sources */, diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseDetail/VC/CourseDetailVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseDetail/VC/CourseDetailVC.swift new file mode 100644 index 00000000..e3e6c9ed --- /dev/null +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDetail/VC/CourseDetailVC.swift @@ -0,0 +1,231 @@ +// +// CourseDetailVC.swift +// Runnect-iOS +// +// Created by 몽이 누나 on 2023/01/05. +// + +import UIKit +import SnapKit +import Then + +final class CourseDetailVC: UIViewController { + + // MARK: - UI Components + private lazy var navibar = CustomNavigationBar(self, type: .titleWithLeftButton) + private lazy var middleScorollView = UIScrollView().then { + $0.isScrollEnabled = true + $0.showsVerticalScrollIndicator = false + } + private let bottomView = UIView() + private let firstHorizontalDivideLine = UIView() + private let secondHorizontalDivideLine = UIView() + private let thirdHorizontalDivideLine = UIView() + + private lazy var likeButton = UIButton(type: .custom).then { + $0.setImage(ImageLiterals.icHeart, for: .normal) + $0.setImage(ImageLiterals.icHeartFill, for: .selected) + $0.tintColor = .g2 + $0.backgroundColor = .w1 + } + + private lazy var startButton = CustomButton(title: "시작하기").then { + $0.addTarget(self, action: #selector(pushToCountDownVC), for: .touchUpInside) + } + + private let mapImage = UIImageView() + private let profileImage = UIImageView().then { + $0.image = ImageLiterals.imgStampC3 + $0.layer.cornerRadius = 20 + $0.layer.borderWidth = 1 + $0.layer.borderColor = UIColor.m3.cgColor + } + + private let profileNameLabel = UILabel().then { + $0.text = "말랑콩떡" + $0.textColor = .g1 + $0.font = .h5 + } + + private let runningLevelLabel = UILabel().then { + $0.text = "Lv. 3" + $0.textColor = .m1 + $0.font = .b5 + } + + private let courseTitleLabel = UILabel().then { + $0.text = "잠실 석촌호수 한 바퀴 러닝" + $0.textColor = .g1 + $0.font = .h4 + } + + private let courseDistanceLabel = CourseDetailInfoView(title: "거리", description: "2.3km") + + private let courseDepartureLabel = CourseDetailInfoView(title: "출발지", description: "패스트파이브 을지로점") + + private lazy var courseDetailStackView = UIStackView(arrangedSubviews: [courseDistanceLabel, courseDepartureLabel]).then { + $0.axis = .vertical + $0.spacing = 6 + $0.distribution = .fillEqually + } + + private lazy var courseExplanationTextView = UITextView().then { + $0.text = "석촌 호수 한 바퀴 뛰는 코스에요! 평탄한 길과 느린 페이스, 난이도 하 코스입니다! 롯데월드 야경 감상 하면서 뛰기에 좋은 야간 코스에요! 석촌 호수 한 바퀴 뛰는 코스에요! 평탄한 길과 느린 페이스, 난이도 하 코스입니다! 롯데월드 야경 감상 하면서 뛰기에 좋은" + $0.isEditable = false + let paragraphStyle = NSMutableParagraphStyle() + paragraphStyle.lineSpacing = 10 + let attributedString = NSMutableAttributedString(string: $0.text, attributes: [.font: UIFont.b3, .foregroundColor: UIColor.g1]) + attributedString.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: attributedString.length)) + $0.attributedText = attributedString + $0.isScrollEnabled = false + $0.sizeToFit() + } + + // MARK: - View Life Cycle + + override func viewDidLoad() { + super.viewDidLoad() + setNavigationBar() + setUI() + setLayout() + setAddTarget() + } +} + +// MARK: - @objc Function + +extension CourseDetailVC { + @objc func likeButtonDidTap(_ sender: UIButton) { + sender.isSelected.toggle() + } + + @objc private func pushToCountDownVC() { + let countDownVC = CountDownVC() + countDownVC.setData(locations: [], distance: "1.0", pathImage: UIImage()) + self.navigationController?.pushViewController(countDownVC, animated: true) + } +} + +// MARK: - Method + +extension CourseDetailVC { + private func setAddTarget() { + likeButton.addTarget(self, action: #selector(likeButtonDidTap), for: .touchUpInside) + } +} + +extension CourseDetailVC { + + // MARK: - Layout Helpers + private func setNavigationBar() { + view.addSubview(navibar) + + navibar.snp.makeConstraints { make in + make.top.leading.trailing.equalTo(view.safeAreaLayoutGuide) + make.height.equalTo(48) + } + } + + private func setUI() { + view.backgroundColor = .w1 + bottomView.backgroundColor = .w1 + middleScorollView.backgroundColor = .w1 + mapImage.backgroundColor = .g3 + firstHorizontalDivideLine.backgroundColor = .g3 + secondHorizontalDivideLine.backgroundColor = .g5 + thirdHorizontalDivideLine.backgroundColor = .g3 + } + + private func setLayout() { + view.addSubviews(middleScorollView, thirdHorizontalDivideLine, bottomView) + + bottomView.snp.makeConstraints { make in + make.bottom.leading.trailing.equalToSuperview() + make.height.equalTo(84) + } + + thirdHorizontalDivideLine.snp.makeConstraints { make in + make.bottom.equalTo(bottomView.snp.top) + make.leading.trailing.equalTo(view.safeAreaLayoutGuide) + make.height.equalTo(0.5) + } + + bottomView.addSubviews(likeButton, startButton) + + likeButton.snp.makeConstraints { make in + make.top.equalToSuperview().offset(18) + make.leading.equalToSuperview().offset(26) + make.width.equalTo(24) + make.height.equalTo(22) + } + + startButton.snp.makeConstraints { make in + make.leading.equalTo(likeButton.snp.trailing).offset(20) + make.top.equalToSuperview().offset(10) + make.trailing.equalToSuperview().inset(16) + make.height.equalTo(40) + } + + setMiddleScrollView() + } + + private func setMiddleScrollView() { + middleScorollView.snp.makeConstraints { make in + make.top.equalTo(navibar.snp.bottom) + make.leading.trailing.equalTo(view.safeAreaLayoutGuide) + make.bottom.equalTo(thirdHorizontalDivideLine.snp.top) + } + + middleScorollView.addSubviews(mapImage, profileImage, profileNameLabel, runningLevelLabel, firstHorizontalDivideLine, courseTitleLabel, courseDetailStackView, secondHorizontalDivideLine, courseExplanationTextView) + + mapImage.snp.makeConstraints { make in + make.top.equalToSuperview() + make.leading.trailing.equalTo(view.safeAreaLayoutGuide) + make.height.equalTo(middleScorollView.snp.width).multipliedBy(0.7) + } + + profileImage.snp.makeConstraints { make in + make.top.equalTo(mapImage.snp.bottom).offset(14) + make.leading.equalToSuperview().offset(14) + make.width.height.equalTo(34) + } + + profileNameLabel.snp.makeConstraints { make in + make.centerY.equalTo(profileImage.snp.centerY) + make.leading.equalTo(profileImage.snp.trailing).offset(12) + } + + runningLevelLabel.snp.makeConstraints { make in + make.bottom.equalTo(profileNameLabel.snp.bottom) + make.trailing.equalTo(view.safeAreaLayoutGuide).inset(31) + } + + firstHorizontalDivideLine.snp.makeConstraints { make in + make.top.equalTo(mapImage.snp.bottom).offset(62) + make.leading.trailing.equalTo(view.safeAreaLayoutGuide).inset(14) + make.height.equalTo(0.5) + } + + courseTitleLabel.snp.makeConstraints { make in + make.top.equalTo(firstHorizontalDivideLine.snp.bottom).offset(16) + make.leading.equalTo(view.safeAreaLayoutGuide).offset(16) + } + + courseDetailStackView.snp.makeConstraints { make in + make.top.equalTo(courseTitleLabel.snp.bottom).offset(19) + make.leading.trailing.equalToSuperview().inset(16) + } + + secondHorizontalDivideLine.snp.makeConstraints { make in + make.top.equalTo(courseDetailStackView.snp.bottom).offset(27) + make.leading.trailing.equalTo(view.safeAreaLayoutGuide) + make.height.equalTo(8) + } + + courseExplanationTextView.snp.makeConstraints { make in + make.top.equalTo(secondHorizontalDivideLine.snp.bottom).offset(17) + make.leading.trailing.equalTo(view.safeAreaLayoutGuide).inset(16) + make.bottom.equalToSuperview().inset(20) + } + } +} diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift index 4664066d..cb33f09f 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift @@ -58,7 +58,9 @@ extension CourseStorageVC { scrapCourseListView.cellDidTapped.sink { [weak self] index in guard let self = self else { return } - print(index) + let courseDetailVC = CourseDetailVC() + courseDetailVC.hidesBottomBarWhenPushed = true + self.navigationController?.pushViewController(courseDetailVC, animated: true) }.store(in: cancelBag) } } diff --git a/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/InfoVC/UploadedCourseInfoVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/InfoVC/UploadedCourseInfoVC.swift index 5e88188c..854aacf2 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/InfoVC/UploadedCourseInfoVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/InfoVC/UploadedCourseInfoVC.swift @@ -27,7 +27,7 @@ final class UploadedCourseInfoVC: UIViewController { // MARK: - Constants - final let uploadedCourseInset: UIEdgeInsets = UIEdgeInsets(top: 16, left: 16, bottom: 0, right: 16) + final let uploadedCourseInset: UIEdgeInsets = UIEdgeInsets(top: 16, left: 16, bottom: 25, right: 16) final let uploadedCourseLineSpacing: CGFloat = 20 final let uploadedCourseItemSpacing: CGFloat = 10 final let uplodaedCourseCellHeight: CGFloat = 124 @@ -84,7 +84,7 @@ extension UploadedCourseInfoVC { UploadedCourseInfoCollectionView.snp.makeConstraints { make in make.top.equalTo(navibar.snp.bottom) make.leading.trailing.equalTo(view.safeAreaLayoutGuide) - make.bottom.equalToSuperview() + make.bottom.equalTo(view.safeAreaLayoutGuide) } }