diff --git a/KkuMulKum.xcodeproj/project.pbxproj b/KkuMulKum.xcodeproj/project.pbxproj index ce5f4079..31b47e41 100644 --- a/KkuMulKum.xcodeproj/project.pbxproj +++ b/KkuMulKum.xcodeproj/project.pbxproj @@ -67,6 +67,11 @@ DD3072242C3C0EB200416D9F /* MyPromiseReadyInfoRequestModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3072232C3C0EB200416D9F /* MyPromiseReadyInfoRequestModel.swift */; }; DD3072262C3C0F0B00416D9F /* PromiseLateInfoResponseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3072252C3C0F0B00416D9F /* PromiseLateInfoResponseModel.swift */; }; DD3072282C3C104D00416D9F /* ArrivalCompletionResponseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3072272C3C104D00416D9F /* ArrivalCompletionResponseModel.swift */; }; + DD931B6B2C3D9EBB00526452 /* ReadyStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD931B6A2C3D9EBB00526452 /* ReadyStatusView.swift */; }; + DD931B6E2C3DA27F00526452 /* ParticipantCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD931B6D2C3DA27F00526452 /* ParticipantCollectionViewCell.swift */; }; + DD931B722C3DA92700526452 /* EnterReadyInfoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD931B712C3DA92700526452 /* EnterReadyInfoButtonView.swift */; }; + DD931B742C3DAB9A00526452 /* ReadyPlanInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD931B732C3DAB9A00526452 /* ReadyPlanInfoView.swift */; }; + DD931B762C3DC16100526452 /* PromiseInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD931B752C3DC16100526452 /* PromiseInfoView.swift */; }; DDA2EE732C385EB9007C6059 /* MainTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA2EE722C385EB9007C6059 /* MainTabBarController.swift */; }; DDA2EE752C385FB1007C6059 /* HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA2EE742C385FB1007C6059 /* HomeViewController.swift */; }; DDA2EE772C385FC3007C6059 /* GroupListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA2EE762C385FC3007C6059 /* GroupListViewController.swift */; }; @@ -147,6 +152,11 @@ DD3072232C3C0EB200416D9F /* MyPromiseReadyInfoRequestModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPromiseReadyInfoRequestModel.swift; sourceTree = ""; }; DD3072252C3C0F0B00416D9F /* PromiseLateInfoResponseModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromiseLateInfoResponseModel.swift; sourceTree = ""; }; DD3072272C3C104D00416D9F /* ArrivalCompletionResponseModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrivalCompletionResponseModel.swift; sourceTree = ""; }; + DD931B6A2C3D9EBB00526452 /* ReadyStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadyStatusView.swift; sourceTree = ""; }; + DD931B6D2C3DA27F00526452 /* ParticipantCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParticipantCollectionViewCell.swift; sourceTree = ""; }; + DD931B712C3DA92700526452 /* EnterReadyInfoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnterReadyInfoButtonView.swift; sourceTree = ""; }; + DD931B732C3DAB9A00526452 /* ReadyPlanInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadyPlanInfoView.swift; sourceTree = ""; }; + DD931B752C3DC16100526452 /* PromiseInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromiseInfoView.swift; sourceTree = ""; }; DDA2EE722C385EB9007C6059 /* MainTabBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTabBarController.swift; sourceTree = ""; }; DDA2EE742C385FB1007C6059 /* HomeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewController.swift; sourceTree = ""; }; DDA2EE762C385FC3007C6059 /* GroupListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupListViewController.swift; sourceTree = ""; }; @@ -314,6 +324,45 @@ path = Login; sourceTree = ""; }; + DD931B672C3D9D9C00526452 /* ViewController */ = { + isa = PBXGroup; + children = ( + DDAF1C8D2C3D6E3D008A37D3 /* PromiseViewController.swift */, + DDAF1C8C2C3D6E3D008A37D3 /* PromiseInfoViewController.swift */, + DDAF1C882C3D6E3D008A37D3 /* ReadyStatusViewController.swift */, + DDAF1C8B2C3D6E3D008A37D3 /* TardyViewController.swift */, + ); + path = ViewController; + sourceTree = ""; + }; + DD931B682C3D9DAD00526452 /* View */ = { + isa = PBXGroup; + children = ( + DDAF1C892C3D6E3D008A37D3 /* PromiseSegmentedControl.swift */, + DD931B752C3DC16100526452 /* PromiseInfoView.swift */, + DD931B6A2C3D9EBB00526452 /* ReadyStatusView.swift */, + DD931B712C3DA92700526452 /* EnterReadyInfoButtonView.swift */, + DD931B732C3DAB9A00526452 /* ReadyPlanInfoView.swift */, + ); + path = View; + sourceTree = ""; + }; + DD931B692C3D9DC800526452 /* ViewModel */ = { + isa = PBXGroup; + children = ( + DDAF1C8A2C3D6E3D008A37D3 /* PromiseViewModel.swift */, + ); + path = ViewModel; + sourceTree = ""; + }; + DD931B6C2C3DA24C00526452 /* Cell */ = { + isa = PBXGroup; + children = ( + DD931B6D2C3DA27F00526452 /* ParticipantCollectionViewCell.swift */, + ); + path = Cell; + sourceTree = ""; + }; DDA2EE7B2C386078007C6059 /* Home */ = { isa = PBXGroup; children = ( @@ -357,12 +406,10 @@ DDAF1C872C3D6E3D008A37D3 /* Promise */ = { isa = PBXGroup; children = ( - DDAF1C882C3D6E3D008A37D3 /* ReadyStatusViewController.swift */, - DDAF1C892C3D6E3D008A37D3 /* PromiseSegmentedControl.swift */, - DDAF1C8A2C3D6E3D008A37D3 /* PromiseViewModel.swift */, - DDAF1C8B2C3D6E3D008A37D3 /* TardyViewController.swift */, - DDAF1C8C2C3D6E3D008A37D3 /* PromiseInfoViewController.swift */, - DDAF1C8D2C3D6E3D008A37D3 /* PromiseViewController.swift */, + DD931B672C3D9D9C00526452 /* ViewController */, + DD931B682C3D9DAD00526452 /* View */, + DD931B692C3D9DC800526452 /* ViewModel */, + DD931B6C2C3DA24C00526452 /* Cell */, ); path = Promise; sourceTree = ""; @@ -726,12 +773,14 @@ DED5DBEC2C345210006ECE7E /* BaseViewController.swift in Sources */, DD30721A2C3C011600416D9F /* AddPromiseRequestModel.swift in Sources */, DD30721E2C3C0CC800416D9F /* PromiseInfoResponseModel.swift in Sources */, + DD931B722C3DA92700526452 /* EnterReadyInfoButtonView.swift in Sources */, A3FB18512C3BF531001483E5 /* RegisterMeetingsResponseModel.swift in Sources */, 789AD4B32C3C0093002E2688 /* SocialLoginResponseModel.swift in Sources */, DE9E188B2C3BC92500DB76B4 /* EmptyModel.swift in Sources */, DDA2EE732C385EB9007C6059 /* MainTabBarController.swift in Sources */, A3FB184D2C3BF45F001483E5 /* MakeMeetingsRequestModel.swift in Sources */, DEBA03312C3C2972002ED8F2 /* ViewController.swift in Sources */, + DD931B742C3DAB9A00526452 /* ReadyPlanInfoView.swift in Sources */, 789873342C3D1A7B00435E96 /* LoginView.swift in Sources */, A3FB18592C3BF77D001483E5 /* MeetingInfoResponseModel.swift in Sources */, DE9E18842C3BA84500DB76B4 /* CustomTextField.swift in Sources */, @@ -769,8 +818,11 @@ DDAF1C8F2C3D6E3D008A37D3 /* PromiseSegmentedControl.swift in Sources */, DE32D1D22C3BF703006848DF /* LoginUserResponseModel.swift in Sources */, DE9E18892C3BC91000DB76B4 /* ResponseBodyDTO.swift in Sources */, + DD931B6B2C3D9EBB00526452 /* ReadyStatusView.swift in Sources */, DD3072202C3C0D4500416D9F /* MyReadyStatusResponseModel.swift in Sources */, DD3072282C3C104D00416D9F /* ArrivalCompletionResponseModel.swift in Sources */, + DD931B6E2C3DA27F00526452 /* ParticipantCollectionViewCell.swift in Sources */, + DD931B762C3DC16100526452 /* PromiseInfoView.swift in Sources */, DD3072242C3C0EB200416D9F /* MyPromiseReadyInfoRequestModel.swift in Sources */, 789873332C3D1A7B00435E96 /* LoginViewModel.swift in Sources */, DED5DBEE2C34529A006ECE7E /* BaseView.swift in Sources */, diff --git a/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/Contents.json b/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/Contents.json index 62fea975..165fd2cc 100644 --- a/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/Contents.json +++ b/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/Contents.json @@ -1,17 +1,17 @@ { "images" : [ { - "filename" : "profileBasic.png", + "filename" : "ic_profilebasic.png", "idiom" : "universal", "scale" : "1x" }, { - "filename" : "profileBasic@2x.png", + "filename" : "ic_profilebasic@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "profileBasic@3x.png", + "filename" : "ic_profilebasic@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/ic_profilebasic.png b/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/ic_profilebasic.png new file mode 100644 index 00000000..085ccad5 Binary files /dev/null and b/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/ic_profilebasic.png differ diff --git a/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/ic_profilebasic@2x.png b/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/ic_profilebasic@2x.png new file mode 100644 index 00000000..906c465e Binary files /dev/null and b/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/ic_profilebasic@2x.png differ diff --git a/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/ic_profilebasic@3x.png b/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/ic_profilebasic@3x.png new file mode 100644 index 00000000..b3221088 Binary files /dev/null and b/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/ic_profilebasic@3x.png differ diff --git a/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/profileBasic.png b/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/profileBasic.png deleted file mode 100644 index 53565b46..00000000 Binary files a/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/profileBasic.png and /dev/null differ diff --git a/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/profileBasic@2x.png b/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/profileBasic@2x.png deleted file mode 100644 index 1327b409..00000000 Binary files a/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/profileBasic@2x.png and /dev/null differ diff --git a/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/profileBasic@3x.png b/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/profileBasic@3x.png deleted file mode 100644 index 475b2c21..00000000 Binary files a/KkuMulKum/Resource/Assets.xcassets/Image/img_profile.imageset/profileBasic@3x.png and /dev/null differ diff --git a/KkuMulKum/Resource/Color.xcassets/gray0.colorset/Contents.json b/KkuMulKum/Resource/Color.xcassets/gray0.colorset/Contents.json new file mode 100644 index 00000000..e1ce072f --- /dev/null +++ b/KkuMulKum/Resource/Color.xcassets/gray0.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xF7", + "green" : "0xF7", + "red" : "0xF7" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xF7", + "green" : "0xF7", + "red" : "0xF7" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/KkuMulKum/Source/Promise/Cell/ParticipantCollectionViewCell.swift b/KkuMulKum/Source/Promise/Cell/ParticipantCollectionViewCell.swift new file mode 100644 index 00000000..3d6489a3 --- /dev/null +++ b/KkuMulKum/Source/Promise/Cell/ParticipantCollectionViewCell.swift @@ -0,0 +1,39 @@ +// +// ParticipantCollectionViewCell.swift +// KkuMulKum +// +// Created by YOUJIM on 7/10/24. +// + +import UIKit + +import SnapKit + +class ParticipantCollectionViewCell: BaseCollectionViewCell { + private lazy var profileImageView: UIImageView = UIImageView().then { + $0.image = .imgProfile + $0.contentMode = .scaleAspectFit + } + + private let userNameLabel: UILabel = UILabel().then { + $0.setText("userName", style: .caption02, color: .gray6) + } + + override func setupView() { + contentView.addSubviews(profileImageView, userNameLabel) + } + + override func setupAutoLayout() { + profileImageView.snp.makeConstraints { + $0.height.equalTo(Screen.height(68)) + $0.width.equalTo(profileImageView.snp.height) + $0.top.centerX.equalToSuperview() + } + + userNameLabel.snp.makeConstraints { + $0.top.equalTo(profileImageView.snp.bottom).offset(6) + $0.centerX.equalTo(profileImageView) + $0.bottom.equalToSuperview() + } + } +} diff --git a/KkuMulKum/Source/Promise/PromiseInfoViewController.swift b/KkuMulKum/Source/Promise/PromiseInfoViewController.swift deleted file mode 100644 index 8dd2847c..00000000 --- a/KkuMulKum/Source/Promise/PromiseInfoViewController.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// PromiseInfoViewController.swift -// KkuMulKum -// -// Created by YOUJIM on 7/9/24. -// - -import UIKit - -class PromiseInfoViewController: BaseViewController { - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - } - - - /* - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ - -} diff --git a/KkuMulKum/Source/Promise/PromiseViewController.swift b/KkuMulKum/Source/Promise/PromiseViewController.swift deleted file mode 100644 index c2b35fce..00000000 --- a/KkuMulKum/Source/Promise/PromiseViewController.swift +++ /dev/null @@ -1,70 +0,0 @@ -// -// PromiseViewController.swift -// KkuMulKum -// -// Created by YOUJIM on 7/9/24. -// - -import UIKit - -class PromiseViewController: BaseViewController { - private let promiseViewModel = PromiseViewModel() - - private lazy var promiseSegmentedControl = PromiseSegmentedControl(items: ["약속 정보", - "준비 현황", - "지각 꾸물이"]) - - private let promisePageViewController = UIPageViewController(transitionStyle: .scroll, - navigationOrientation: .horizontal) - - override func viewDidLoad() { - super.viewDidLoad() - } - - override func setupView() { - view.backgroundColor = .white - self.navigationItem.title = "기말고사 모각작" - - view.addSubview(promiseSegmentedControl) - addChild(promisePageViewController) - - promiseSegmentedControl.snp.makeConstraints { - $0.top.equalToSuperview() - $0.leading.trailing.equalToSuperview().inset(-6) - $0.height.equalTo(52) - } - - promisePageViewController.view.snp.makeConstraints { - $0.top.equalTo(promiseSegmentedControl.snp.bottom) - $0.horizontalEdges.bottom.equalToSuperview() - } - - promisePageViewController.didMove(toParent: self) - } - - override func setupAction() { - promiseSegmentedControl.addTarget(self, action: #selector(didSegmentedControlIndexUpdated), for: .valueChanged) - } - - override func setupDelegate() { - promisePageViewController.delegate = self - promisePageViewController.dataSource = self - } - - @objc private func didSegmentedControlIndexUpdated() { - promiseSegmentedControl.selectedUnderLineView.snp.updateConstraints { - $0.leading.equalToSuperview().offset((promiseSegmentedControl.bounds.width / CGFloat(promiseSegmentedControl.numberOfSegments)) * CGFloat(promiseSegmentedControl.selectedSegmentIndex)) - } - } -} - - -extension BaseViewController: UIPageViewControllerDelegate, UIPageViewControllerDataSource { - func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { - return UIViewController() - } - - func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { - return UIViewController() - } -} diff --git a/KkuMulKum/Source/Promise/PromiseViewModel.swift b/KkuMulKum/Source/Promise/PromiseViewModel.swift deleted file mode 100644 index 3d4950e6..00000000 --- a/KkuMulKum/Source/Promise/PromiseViewModel.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// PromiseViewModel.swift -// KkuMulKum -// -// Created by YOUJIM on 7/9/24. -// - -import Foundation - - -class PromiseViewModel { - let promiseViewControllerList = [PromiseInfoViewController(), - ReadyStatusViewController(), - TardyViewController()] -} diff --git a/KkuMulKum/Source/Promise/ReadyStatusViewController.swift b/KkuMulKum/Source/Promise/ReadyStatusViewController.swift deleted file mode 100644 index a576adb3..00000000 --- a/KkuMulKum/Source/Promise/ReadyStatusViewController.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// ReadyStatusViewController.swift -// KkuMulKum -// -// Created by YOUJIM on 7/9/24. -// - -import UIKit - -class ReadyStatusViewController: BaseViewController { - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - } - - - /* - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ - -} diff --git a/KkuMulKum/Source/Promise/TardyViewController.swift b/KkuMulKum/Source/Promise/TardyViewController.swift deleted file mode 100644 index 8e0ea951..00000000 --- a/KkuMulKum/Source/Promise/TardyViewController.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// TardyViewController.swift -// KkuMulKum -// -// Created by YOUJIM on 7/9/24. -// - -import UIKit - -class TardyViewController: BaseViewController { - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - } - - - /* - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ - -} diff --git a/KkuMulKum/Source/Promise/View/EnterReadyInfoButtonView.swift b/KkuMulKum/Source/Promise/View/EnterReadyInfoButtonView.swift new file mode 100644 index 00000000..46c21e86 --- /dev/null +++ b/KkuMulKum/Source/Promise/View/EnterReadyInfoButtonView.swift @@ -0,0 +1,49 @@ +// +// EnterReadyInfoButtonView.swift +// KkuMulKum +// +// Created by YOUJIM on 7/10/24. +// + +import UIKit + +class EnterReadyInfoButtonView: BaseView { + private let descriptionLabel: UILabel = UILabel().then { + $0.setText("준비 정보 입력하기", style: .body03) + } + + private let chevronButton: UIButton = UIButton().then { + $0.setImage(.iconRight, for: .normal) + $0.contentMode = .scaleAspectFill + } + + override func setupView() { + backgroundColor = .white + addSubviews(descriptionLabel, chevronButton) + } + + override func setupAutoLayout() { + descriptionLabel.snp.makeConstraints { + $0.centerY.equalToSuperview() + $0.leading.equalToSuperview().offset(20) + } + + chevronButton.snp.makeConstraints { + $0.trailing.equalToSuperview().inset(17) + $0.centerY.equalToSuperview() + } + } + + + // TODO: 빼야됨 + + private func setupAction() { + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTapped)) + + self.addGestureRecognizer(tapGesture) + } + + @objc private func didTapped() { + + } +} diff --git a/KkuMulKum/Source/Promise/View/PromiseInfoView.swift b/KkuMulKum/Source/Promise/View/PromiseInfoView.swift new file mode 100644 index 00000000..9fce12d2 --- /dev/null +++ b/KkuMulKum/Source/Promise/View/PromiseInfoView.swift @@ -0,0 +1,215 @@ +// +// PromiseInfoView.swift +// KkuMulKum +// +// Created by YOUJIM on 7/10/24. +// + +import UIKit + +class PromiseInfoView: BaseView { + private let participantNumberLabel: UILabel = UILabel().then { + $0.setText("약속 참여 인원 n명", style: .body01) + $0.setHighlightText("n명", style: .body01, color: .maincolor) + } + + private let chevronButton: UIButton = UIButton().then { + $0.setImage(.iconRight.withTintColor(.gray4), for: .normal) + $0.contentMode = .scaleAspectFill + } + + let participantCollectionView: UICollectionView = UICollectionView( + frame: .zero, + collectionViewLayout: UICollectionViewFlowLayout().then { + $0.scrollDirection = .horizontal + $0.minimumInteritemSpacing = 12 + $0.estimatedItemSize = .init(width: Screen.width(68), height: Screen.height(88)) + }).then { + $0.showsHorizontalScrollIndicator = false + $0.contentInset = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 0) + $0.register( + ParticipantCollectionViewCell.self, + forCellWithReuseIdentifier: ParticipantCollectionViewCell.reuseIdentifier + ) + } + + private let backgroundView: UIView = UIView().then { + $0.backgroundColor = .gray0 + $0.layer.cornerRadius = Screen.height(18) + } + + private let promiseInfoLabel: UILabel = UILabel().then { + $0.setText("약속 상세 정보", style: .body01, color: .gray7) + } + + private let promiseInfoBackgroundView: UIView = UIView().then { + $0.backgroundColor = .white + $0.layer.borderColor = UIColor.gray2.cgColor + $0.layer.borderWidth = 1 + $0.layer.cornerRadius = Screen.height(8) + } + + private let locationInfoLabel: UILabel = UILabel().then { + $0.setText("위치", style: .caption01, color: .maincolor) + } + + private let locationContentLabel: UILabel = UILabel().then { + $0.setText("sss역 s번 출구", style: .body04, color: .gray7) + } + + private let locationDivideView: UIView = UIView().then { + $0.backgroundColor = .gray2 + } + + private let timeInfoLabel: UILabel = UILabel().then { + $0.setText("약속시간", style: .caption01, color: .maincolor) + } + + private let timeContentLabel: UILabel = UILabel().then { + $0.setText("mm월 dd일 hh:mm", style: .body04, color: .gray7) + } + + private let timeDivideView: UIView = UIView().then { + $0.backgroundColor = .gray2 + } + + private let readyLevelInfoLabel: UILabel = UILabel().then { + $0.setText("준비레벨", style: .caption01, color: .maincolor) + } + + private let readyLevelContentLabel: UILabel = UILabel().then { + $0.setText("LV n. sss", style: .body04, color: .gray7) + } + + private let readyLevelDivideView: UIView = UIView().then { + $0.backgroundColor = .gray2 + } + + private let penaltyLevelInfoLabel: UILabel = UILabel().then { + $0.setText("벌칙", style: .caption01, color: .maincolor) + } + + private let penaltyLevelContentLabel: UILabel = UILabel().then { + $0.setText("ssss하기", style: .body04, color: .gray7) + } + + override func setupView() { + addSubviews( + participantNumberLabel, + chevronButton, + participantCollectionView, + backgroundView, + promiseInfoLabel, + promiseInfoBackgroundView + ) + + promiseInfoBackgroundView.addSubviews( + locationInfoLabel, + locationContentLabel, + locationDivideView, + timeInfoLabel, + timeContentLabel, + timeDivideView, + readyLevelInfoLabel, + readyLevelContentLabel, + readyLevelDivideView, + penaltyLevelInfoLabel, + penaltyLevelContentLabel + ) + } + + override func setupAutoLayout() { + participantNumberLabel.snp.makeConstraints { + $0.top.equalTo(self.safeAreaLayoutGuide).offset(28) + $0.leading.equalToSuperview().offset(20) + } + + chevronButton.snp.makeConstraints { + $0.centerY.equalTo(participantNumberLabel) + $0.trailing.equalToSuperview().inset(20) + $0.height.equalTo(Screen.height(24)) + $0.width.equalTo(Screen.width(70)) + } + + participantCollectionView.snp.makeConstraints { + $0.top.equalTo(participantNumberLabel.snp.bottom).offset(20) + $0.leading.trailing.equalToSuperview() + $0.height.equalTo(Screen.height(88)) + } + + backgroundView.snp.makeConstraints { + $0.top.equalTo(participantCollectionView.snp.bottom).offset(27) + $0.leading.trailing.equalToSuperview() + $0.bottom.equalToSuperview() + } + + promiseInfoLabel.snp.makeConstraints { + $0.top.equalTo(backgroundView.snp.top).offset(26) + $0.leading.equalToSuperview().offset(20) + } + + promiseInfoBackgroundView.snp.makeConstraints { + $0.top.equalTo(promiseInfoLabel.snp.bottom).offset(20) + $0.leading.trailing.equalToSuperview().inset(20) + } + + locationInfoLabel.snp.makeConstraints { + $0.top.equalToSuperview().offset(14) + $0.leading.equalToSuperview().offset(12) + } + + locationContentLabel.snp.makeConstraints { + $0.top.equalTo(locationInfoLabel.snp.bottom).offset(8) + $0.leading.equalTo(locationInfoLabel) + } + + locationDivideView.snp.makeConstraints { + $0.top.equalTo(locationContentLabel.snp.bottom).offset(16) + $0.leading.trailing.equalToSuperview().inset(12) + $0.height.equalTo(Screen.height(1)) + } + + timeInfoLabel.snp.makeConstraints { + $0.top.equalTo(locationDivideView.snp.top).offset(14) + $0.leading.equalTo(locationDivideView) + } + + timeContentLabel.snp.makeConstraints { + $0.top.equalTo(timeInfoLabel.snp.bottom).offset(8) + $0.leading.equalTo(timeInfoLabel) + } + + timeDivideView.snp.makeConstraints { + $0.top.equalTo(timeContentLabel.snp.bottom).offset(16) + $0.leading.trailing.equalToSuperview().inset(12) + $0.height.equalTo(Screen.height(1)) + } + + readyLevelInfoLabel.snp.makeConstraints { + $0.top.equalTo(timeDivideView.snp.top).offset(14) + $0.leading.equalTo(timeDivideView) + } + + readyLevelContentLabel.snp.makeConstraints { + $0.top.equalTo(readyLevelInfoLabel.snp.bottom).offset(8) + $0.leading.equalTo(readyLevelInfoLabel) + } + + readyLevelDivideView.snp.makeConstraints { + $0.top.equalTo(readyLevelContentLabel.snp.bottom).offset(16) + $0.leading.trailing.equalToSuperview().inset(12) + $0.height.equalTo(Screen.height(1)) + } + + penaltyLevelInfoLabel.snp.makeConstraints { + $0.top.equalTo(readyLevelDivideView.snp.top).offset(14) + $0.leading.equalTo(timeDivideView) + } + + penaltyLevelContentLabel.snp.makeConstraints { + $0.top.equalTo(penaltyLevelInfoLabel.snp.bottom).offset(8) + $0.leading.equalTo(penaltyLevelInfoLabel) + $0.bottom.equalToSuperview().inset(16) + } + } +} diff --git a/KkuMulKum/Source/Promise/PromiseSegmentedControl.swift b/KkuMulKum/Source/Promise/View/PromiseSegmentedControl.swift similarity index 99% rename from KkuMulKum/Source/Promise/PromiseSegmentedControl.swift rename to KkuMulKum/Source/Promise/View/PromiseSegmentedControl.swift index 8c762571..7f387a6a 100644 --- a/KkuMulKum/Source/Promise/PromiseSegmentedControl.swift +++ b/KkuMulKum/Source/Promise/View/PromiseSegmentedControl.swift @@ -26,7 +26,6 @@ class PromiseSegmentedControl: UISegmentedControl { setupTextAttribute() setupBackgroundLineView() setupBackgroundAndDivider() - } required init?(coder: NSCoder) { diff --git a/KkuMulKum/Source/Promise/View/ReadyPlanInfoView.swift b/KkuMulKum/Source/Promise/View/ReadyPlanInfoView.swift new file mode 100644 index 00000000..355010eb --- /dev/null +++ b/KkuMulKum/Source/Promise/View/ReadyPlanInfoView.swift @@ -0,0 +1,15 @@ +// +// ReadyPlanInfoView.swift +// KkuMulKum +// +// Created by YOUJIM on 7/10/24. +// + +import UIKit + +class ReadyPlanInfoView: BaseView { + private let readyTimeLabel: UILabel = UILabel().then { + $0.setText("12시 30분에 준비하고,\n1시에 이동을 시작해야 해요", style: .body03) + $0.setHighlightText("12시 30분", "1시", style: .body03, color: .maincolor) + } +} diff --git a/KkuMulKum/Source/Promise/View/ReadyStatusView.swift b/KkuMulKum/Source/Promise/View/ReadyStatusView.swift new file mode 100644 index 00000000..37ce3d08 --- /dev/null +++ b/KkuMulKum/Source/Promise/View/ReadyStatusView.swift @@ -0,0 +1,18 @@ +// +// ReadyStatusView.swift +// KkuMulKum +// +// Created by YOUJIM on 7/10/24. +// + +import UIKit + +class ReadyStatusView: BaseView { + override init(frame: CGRect) { + super.init(frame: frame) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/KkuMulKum/Source/Promise/ViewController/PromiseInfoViewController.swift b/KkuMulKum/Source/Promise/ViewController/PromiseInfoViewController.swift new file mode 100644 index 00000000..47a430cb --- /dev/null +++ b/KkuMulKum/Source/Promise/ViewController/PromiseInfoViewController.swift @@ -0,0 +1,55 @@ +// +// PromiseInfoViewController.swift +// KkuMulKum +// +// Created by YOUJIM on 7/9/24. +// + +import UIKit + +class PromiseInfoViewController: BaseViewController { + private let promiseInfoView: PromiseInfoView = PromiseInfoView() + + override func viewDidLoad() { + super.viewDidLoad() + } + + override func setupView() { + view.addSubview(promiseInfoView) + self.navigationController?.navigationBar.shadowImage = nil + + promiseInfoView.snp.makeConstraints { + $0.edges.equalToSuperview() + } + } + + override func setupDelegate() { + promiseInfoView.participantCollectionView.delegate = self + promiseInfoView.participantCollectionView.dataSource = self + } +} + + +extension PromiseInfoViewController: UICollectionViewDataSource { + func collectionView( + _ collectionView: UICollectionView, + numberOfItemsInSection section: Int + ) -> Int { + return 10 + } +} + + +extension PromiseInfoViewController: UICollectionViewDelegateFlowLayout { + func collectionView( + _ collectionView: UICollectionView, + cellForItemAt indexPath: IndexPath + ) -> UICollectionViewCell { + guard let cell = collectionView.dequeueReusableCell( + withReuseIdentifier: ParticipantCollectionViewCell.reuseIdentifier, + for: indexPath) as? ParticipantCollectionViewCell + else { return UICollectionViewCell() } + + return cell + } +} diff --git a/KkuMulKum/Source/Promise/ViewController/PromiseViewController.swift b/KkuMulKum/Source/Promise/ViewController/PromiseViewController.swift new file mode 100644 index 00000000..33335cfa --- /dev/null +++ b/KkuMulKum/Source/Promise/ViewController/PromiseViewController.swift @@ -0,0 +1,104 @@ +// +// PromiseViewController.swift +// KkuMulKum +// +// Created by YOUJIM on 7/9/24. +// + +import UIKit + +class PromiseViewController: BaseViewController { + private let promiseViewModel = PromiseViewModel() + + private let promiseViewControllerList: [BaseViewController] = [PromiseInfoViewController(), + ReadyStatusViewController(), + TardyViewController()] + + private lazy var promiseSegmentedControl = PromiseSegmentedControl( + items: ["약속 정보", "준비 현황", "지각 꾸물이"] + ) + + private let promisePageViewController = UIPageViewController( + transitionStyle: .scroll, + navigationOrientation: .vertical + ) + + override func viewDidLoad() { + super.viewDidLoad() + } + + override func setupView() { + view.backgroundColor = .white + self.navigationItem.title = "기말고사 모각작" + + addChild(promisePageViewController) + view.addSubviews( + promiseSegmentedControl, + promisePageViewController.view + ) + + promisePageViewController.setViewControllers( + [promiseViewControllerList[0]], + direction: .forward, + animated: true + ) + + promiseSegmentedControl.snp.makeConstraints { + $0.top.equalTo(view.safeAreaLayoutGuide) + $0.leading.trailing.equalToSuperview().inset(-6) + $0.height.equalTo(61) + } + + promisePageViewController.view.snp.makeConstraints { + $0.top.equalTo(promiseSegmentedControl.snp.bottom) + $0.leading.trailing.bottom.equalToSuperview() + } + } + + override func setupAction() { + promiseSegmentedControl.addTarget( + self, + action: #selector(didSegmentedControlIndexUpdated), + for: .valueChanged + ) + } + + override func setupDelegate() { + promisePageViewController.delegate = self + promisePageViewController.dataSource = self + } + + @objc private func didSegmentedControlIndexUpdated() { + let condition = promiseViewModel.currentPage.value <= promiseSegmentedControl.selectedSegmentIndex + let direction: UIPageViewController.NavigationDirection = condition ? .forward : .reverse + let (width, count, selectedIndex) = ( + promiseSegmentedControl.bounds.width, + promiseSegmentedControl.numberOfSegments, + promiseSegmentedControl.selectedSegmentIndex + ) + + promiseSegmentedControl.selectedUnderLineView.snp.updateConstraints { + $0.leading.equalToSuperview().offset((width / CGFloat(count)) * CGFloat(selectedIndex)) + } + + promiseViewModel.didSegmentIndexChanged(index: promiseSegmentedControl.selectedSegmentIndex) + + promisePageViewController.setViewControllers([ + promiseViewControllerList[promiseViewModel.currentPage.value] + ], direction: direction, animated: false) + } +} + + +extension PromiseViewController: UIPageViewControllerDelegate, UIPageViewControllerDataSource { + func pageViewController( + _ pageViewController: UIPageViewController, + viewControllerAfter viewController: UIViewController + ) -> UIViewController? { + return nil + } + + func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { + return nil + } +} diff --git a/KkuMulKum/Source/Promise/ViewController/ReadyStatusViewController.swift b/KkuMulKum/Source/Promise/ViewController/ReadyStatusViewController.swift new file mode 100644 index 00000000..78876385 --- /dev/null +++ b/KkuMulKum/Source/Promise/ViewController/ReadyStatusViewController.swift @@ -0,0 +1,18 @@ +// +// ReadyStatusViewController.swift +// KkuMulKum +// +// Created by YOUJIM on 7/9/24. +// + +import UIKit + +class ReadyStatusViewController: BaseViewController { + private let readyStatusView: ReadyStatusView = ReadyStatusView() + + override func viewDidLoad() { + super.viewDidLoad() + + view.addSubview(readyStatusView) + } +} diff --git a/KkuMulKum/Source/Promise/ViewController/TardyViewController.swift b/KkuMulKum/Source/Promise/ViewController/TardyViewController.swift new file mode 100644 index 00000000..dfeb5c40 --- /dev/null +++ b/KkuMulKum/Source/Promise/ViewController/TardyViewController.swift @@ -0,0 +1,16 @@ +// +// TardyViewController.swift +// KkuMulKum +// +// Created by YOUJIM on 7/9/24. +// + +import UIKit + +class TardyViewController: BaseViewController { + override func viewDidLoad() { + super.viewDidLoad() + + view.backgroundColor = .green + } +} diff --git a/KkuMulKum/Source/Promise/ViewModel/PromiseViewModel.swift b/KkuMulKum/Source/Promise/ViewModel/PromiseViewModel.swift new file mode 100644 index 00000000..196d2d36 --- /dev/null +++ b/KkuMulKum/Source/Promise/ViewModel/PromiseViewModel.swift @@ -0,0 +1,17 @@ +// +// PromiseViewModel.swift +// KkuMulKum +// +// Created by YOUJIM on 7/9/24. +// + +import Foundation + + +class PromiseViewModel { + var currentPage = ObservablePattern(0) + + func didSegmentIndexChanged(index: Int) { + currentPage.value = index + } +}