diff --git a/KkuMulKum.xcodeproj/project.pbxproj b/KkuMulKum.xcodeproj/project.pbxproj index 4afdfbd8..ce5f4079 100644 --- a/KkuMulKum.xcodeproj/project.pbxproj +++ b/KkuMulKum.xcodeproj/project.pbxproj @@ -75,6 +75,12 @@ DDAF1C7E2C3D5B86008A37D3 /* RxRelay in Frameworks */ = {isa = PBXBuildFile; productRef = DDAF1C7D2C3D5B86008A37D3 /* RxRelay */; }; DDAF1C812C3D5BD5008A37D3 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = DDAF1C802C3D5BD5008A37D3 /* Kingfisher */; }; DDAF1C842C3D5D19008A37D3 /* ViewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF1C832C3D5D19008A37D3 /* ViewModelType.swift */; }; + DDAF1C8E2C3D6E3D008A37D3 /* ReadyStatusViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF1C882C3D6E3D008A37D3 /* ReadyStatusViewController.swift */; }; + DDAF1C8F2C3D6E3D008A37D3 /* PromiseSegmentedControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF1C892C3D6E3D008A37D3 /* PromiseSegmentedControl.swift */; }; + DDAF1C902C3D6E3D008A37D3 /* PromiseViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF1C8A2C3D6E3D008A37D3 /* PromiseViewModel.swift */; }; + DDAF1C912C3D6E3D008A37D3 /* TardyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF1C8B2C3D6E3D008A37D3 /* TardyViewController.swift */; }; + DDAF1C922C3D6E3D008A37D3 /* PromiseInfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF1C8C2C3D6E3D008A37D3 /* PromiseInfoViewController.swift */; }; + DDAF1C932C3D6E3D008A37D3 /* PromiseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF1C8D2C3D6E3D008A37D3 /* PromiseViewController.swift */; }; DE254AA52C31131600A4015E /* Color.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DE254AA42C31131600A4015E /* Color.xcassets */; }; DE254AA82C3118EA00A4015E /* UIView+.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE254AA72C3118EA00A4015E /* UIView+.swift */; }; DE254AAA2C31190E00A4015E /* UIStackView+.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE254AA92C31190E00A4015E /* UIStackView+.swift */; }; @@ -146,6 +152,12 @@ DDA2EE762C385FC3007C6059 /* GroupListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupListViewController.swift; sourceTree = ""; }; DDA2EE782C385FCF007C6059 /* MyPageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageViewController.swift; sourceTree = ""; }; DDAF1C832C3D5D19008A37D3 /* ViewModelType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewModelType.swift; sourceTree = ""; }; + DDAF1C882C3D6E3D008A37D3 /* ReadyStatusViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReadyStatusViewController.swift; sourceTree = ""; }; + DDAF1C892C3D6E3D008A37D3 /* PromiseSegmentedControl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PromiseSegmentedControl.swift; sourceTree = ""; }; + DDAF1C8A2C3D6E3D008A37D3 /* PromiseViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PromiseViewModel.swift; sourceTree = ""; }; + DDAF1C8B2C3D6E3D008A37D3 /* TardyViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TardyViewController.swift; sourceTree = ""; }; + DDAF1C8C2C3D6E3D008A37D3 /* PromiseInfoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PromiseInfoViewController.swift; sourceTree = ""; }; + DDAF1C8D2C3D6E3D008A37D3 /* PromiseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PromiseViewController.swift; sourceTree = ""; }; DE254AA42C31131600A4015E /* Color.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Color.xcassets; sourceTree = ""; }; DE254AA72C3118EA00A4015E /* UIView+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+.swift"; sourceTree = ""; }; DE254AA92C31190E00A4015E /* UIStackView+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIStackView+.swift"; sourceTree = ""; }; @@ -342,6 +354,19 @@ path = Protocol; sourceTree = ""; }; + DDAF1C872C3D6E3D008A37D3 /* Promise */ = { + isa = PBXGroup; + children = ( + DDAF1C882C3D6E3D008A37D3 /* ReadyStatusViewController.swift */, + DDAF1C892C3D6E3D008A37D3 /* PromiseSegmentedControl.swift */, + DDAF1C8A2C3D6E3D008A37D3 /* PromiseViewModel.swift */, + DDAF1C8B2C3D6E3D008A37D3 /* TardyViewController.swift */, + DDAF1C8C2C3D6E3D008A37D3 /* PromiseInfoViewController.swift */, + DDAF1C8D2C3D6E3D008A37D3 /* PromiseViewController.swift */, + ); + path = Promise; + sourceTree = ""; + }; DE254AA12C31106700A4015E /* Application */ = { isa = PBXGroup; children = ( @@ -359,6 +384,7 @@ DDA2EE7C2C38607F007C6059 /* GroupList */, DDA2EE7D2C386087007C6059 /* MyPage */, DD865B652C3920F600C351A2 /* Onboarding */, + DDAF1C872C3D6E3D008A37D3 /* Promise */, ); path = Source; sourceTree = ""; @@ -695,6 +721,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + DDAF1C8E2C3D6E3D008A37D3 /* ReadyStatusViewController.swift in Sources */, DED5DBF22C34534A006ECE7E /* BaseCollectionReusableView.swift in Sources */, DED5DBEC2C345210006ECE7E /* BaseViewController.swift in Sources */, DD30721A2C3C011600416D9F /* AddPromiseRequestModel.swift in Sources */, @@ -712,11 +739,15 @@ DE254AAC2C31192400A4015E /* UILabel+.swift in Sources */, DE254AB72C3119D000A4015E /* ReuseIdentifiable.swift in Sources */, DDA2EE752C385FB1007C6059 /* HomeViewController.swift in Sources */, + DDAF1C922C3D6E3D008A37D3 /* PromiseInfoViewController.swift in Sources */, DE254AB42C31199B00A4015E /* UITextField+.swift in Sources */, + DDAF1C912C3D6E3D008A37D3 /* TardyViewController.swift in Sources */, DE8248002C36E857000601BC /* ObservablePattern.swift in Sources */, + DDAF1C902C3D6E3D008A37D3 /* PromiseViewModel.swift in Sources */, DE254AAA2C31190E00A4015E /* UIStackView+.swift in Sources */, DED5DBF02C345317006ECE7E /* BaseCollectionViewCell.swift in Sources */, DE32D1D42C3BFB56006848DF /* UpdateProfileNameModel.swift in Sources */, + DDAF1C932C3D6E3D008A37D3 /* PromiseViewController.swift in Sources */, DE9E18922C3BCC9D00DB76B4 /* SocialLoginRequestModel.swift in Sources */, DE254AA82C3118EA00A4015E /* UIView+.swift in Sources */, DE254AAE2C31193600A4015E /* UIFont+.swift in Sources */, @@ -735,6 +766,7 @@ A3FB185B2C3BF7DF001483E5 /* MeetingMembersResponseModel.swift in Sources */, DD3072222C3C0DA300416D9F /* PromiseParticipantListResponseModel.swift in Sources */, 789873322C3D1A7B00435E96 /* LoginViewController.swift in Sources */, + DDAF1C8F2C3D6E3D008A37D3 /* PromiseSegmentedControl.swift in Sources */, DE32D1D22C3BF703006848DF /* LoginUserResponseModel.swift in Sources */, DE9E18892C3BC91000DB76B4 /* ResponseBodyDTO.swift in Sources */, DD3072202C3C0D4500416D9F /* MyReadyStatusResponseModel.swift in Sources */, diff --git a/KkuMulKum/Application/AppDelegate.swift b/KkuMulKum/Application/AppDelegate.swift index 6998762c..00e72fe0 100644 --- a/KkuMulKum/Application/AppDelegate.swift +++ b/KkuMulKum/Application/AppDelegate.swift @@ -4,13 +4,14 @@ // // Created by 이지훈 on 6/24/24. // + import UIKit + import KakaoSDKCommon import KakaoSDKAuth @main class AppDelegate: UIResponder, UIApplicationDelegate { - func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? diff --git a/KkuMulKum/Application/SceneDelegate.swift b/KkuMulKum/Application/SceneDelegate.swift index 3cdd1ef4..11d514e9 100644 --- a/KkuMulKum/Application/SceneDelegate.swift +++ b/KkuMulKum/Application/SceneDelegate.swift @@ -18,27 +18,25 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { ) { guard let windowScene = (scene as? UIWindowScene) else { return } self.window = UIWindow(windowScene: windowScene) - let navigationController = UINavigationController(rootViewController: LoginViewController()) - self.window?.rootViewController = navigationController + self.window?.rootViewController = MainTabBarController() self.window?.makeKeyAndVisible() } func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { - if let url = URLContexts.first?.url { - if (AuthApi.isKakaoTalkLoginUrl(url)) { - _ = AuthController.handleOpenUrl(url: url) - } - } - } - + if let url = URLContexts.first?.url { + if (AuthApi.isKakaoTalkLoginUrl(url)) { + _ = AuthController.handleOpenUrl(url: url) + } + } + } + func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { - if (AuthApi.isKakaoTalkLoginUrl(url)) { - return AuthController.handleOpenUrl(url: url) - } - return false - } + if (AuthApi.isKakaoTalkLoginUrl(url)) { + return AuthController.handleOpenUrl(url: url) + } + return false + } - func sceneDidDisconnect(_ scene: UIScene) {} func sceneDidBecomeActive(_ scene: UIScene) {} func sceneWillResignActive(_ scene: UIScene) {} diff --git a/KkuMulKum/Source/Core/MainTabBarController.swift b/KkuMulKum/Source/Core/MainTabBarController.swift index 5f587199..beffd260 100644 --- a/KkuMulKum/Source/Core/MainTabBarController.swift +++ b/KkuMulKum/Source/Core/MainTabBarController.swift @@ -41,11 +41,27 @@ final class MainTabBarController: UITabBarController { tabBar.unselectedItemTintColor = .gray2 tabBar.tintColor = .maincolor + tabBar.backgroundColor = .white + + let homeNavigationController = UINavigationController(rootViewController: homeViewController).then { + $0.navigationBar.topItem?.backButtonDisplayMode = .minimal + $0.navigationBar.tintColor = .black + } + + let groupListNavigationController = UINavigationController(rootViewController: groupListViewController).then { + $0.navigationBar.topItem?.backButtonDisplayMode = .minimal + $0.navigationBar.tintColor = .black + } + + let myPageViewNavigationController = UINavigationController(rootViewController: myPageViewController).then { + $0.navigationBar.topItem?.backButtonDisplayMode = .minimal + $0.navigationBar.tintColor = .black + } setViewControllers([ - UINavigationController(rootViewController: homeViewController), - UINavigationController(rootViewController: groupListViewController), - UINavigationController(rootViewController: myPageViewController) + homeNavigationController, + groupListNavigationController, + myPageViewNavigationController ], animated: true) } } diff --git a/KkuMulKum/Source/GroupList/GroupListViewController.swift b/KkuMulKum/Source/GroupList/GroupListViewController.swift index 027d6c5a..b6e04122 100644 --- a/KkuMulKum/Source/GroupList/GroupListViewController.swift +++ b/KkuMulKum/Source/GroupList/GroupListViewController.swift @@ -7,23 +7,29 @@ import UIKit +import SnapKit + class GroupListViewController: BaseViewController { + private lazy var button: CustomButton = CustomButton(title: "모임 추가하기", isEnabled: true).then { + $0.addTarget(self, action: #selector(didAddScheduleButtonTapped), for: .touchUpInside) + } override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white + + view.addSubview(button) + + button.snp.makeConstraints { + $0.top.equalToSuperview().offset(206) + $0.leading.trailing.equalToSuperview().inset(20) + } } - - /* - // 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. + @objc private func didAddScheduleButtonTapped() { + let scheduleViewController = PromiseViewController() + + self.navigationController?.pushViewController(scheduleViewController, animated: true) } - */ - } diff --git a/KkuMulKum/Source/Promise/PromiseInfoViewController.swift b/KkuMulKum/Source/Promise/PromiseInfoViewController.swift new file mode 100644 index 00000000..8dd2847c --- /dev/null +++ b/KkuMulKum/Source/Promise/PromiseInfoViewController.swift @@ -0,0 +1,29 @@ +// +// 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/PromiseSegmentedControl.swift b/KkuMulKum/Source/Promise/PromiseSegmentedControl.swift new file mode 100644 index 00000000..8c762571 --- /dev/null +++ b/KkuMulKum/Source/Promise/PromiseSegmentedControl.swift @@ -0,0 +1,81 @@ +// +// PromiseSegmentedControl.swift +// KkuMulKum +// +// Created by YOUJIM on 7/9/24. +// + +import UIKit + +import SnapKit + +class PromiseSegmentedControl: UISegmentedControl { + private let backgroundLineView: UIView = UIView().then { + $0.backgroundColor = .gray2 + } + + let selectedUnderLineView: UIView = UIView().then { + $0.backgroundColor = .black + $0.layer.cornerRadius = 1 + } + + override init(items: [Any]?) { + super.init(items: items) + + setupSegment() + setupTextAttribute() + setupBackgroundLineView() + setupBackgroundAndDivider() + + } + + required init?(coder: NSCoder) { + fatalError() + } + + private func setupSegment() { + [ + backgroundLineView, + selectedUnderLineView + ].forEach { addSubview($0) } + + self.selectedSegmentIndex = 0 + } + + private func setupBackgroundAndDivider() { + self.setBackgroundImage(UIImage(), for: .normal, barMetrics: .default) + self.setBackgroundImage(UIImage(), for: .selected, barMetrics: .default) + self.setBackgroundImage(UIImage(), for: .highlighted, barMetrics: .default) + + self.setDividerImage( + UIImage(), + forLeftSegmentState: .selected, + rightSegmentState: .normal, + barMetrics: .default + ) + } + + private func setupTextAttribute() { + setTitleTextAttributes([ + NSAttributedString.Key.foregroundColor: UIColor.gray3, + NSAttributedString.Key.font: UIFont.pretendard(.body05) + ], for: .normal) + setTitleTextAttributes([ + NSAttributedString.Key.foregroundColor: UIColor.black, + NSAttributedString.Key.font: UIFont.pretendard(.body05) + ], for: .selected) + } + + private func setupBackgroundLineView() { + backgroundLineView.snp.makeConstraints { + $0.bottom.leading.trailing.equalToSuperview() + $0.height.equalTo(2) + } + + selectedUnderLineView.snp.makeConstraints { + $0.bottom.leading.equalToSuperview() + $0.width.equalToSuperview().dividedBy(numberOfSegments) + $0.height.equalTo(backgroundLineView) + } + } +} diff --git a/KkuMulKum/Source/Promise/PromiseViewController.swift b/KkuMulKum/Source/Promise/PromiseViewController.swift new file mode 100644 index 00000000..c2b35fce --- /dev/null +++ b/KkuMulKum/Source/Promise/PromiseViewController.swift @@ -0,0 +1,70 @@ +// +// 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 new file mode 100644 index 00000000..3d4950e6 --- /dev/null +++ b/KkuMulKum/Source/Promise/PromiseViewModel.swift @@ -0,0 +1,15 @@ +// +// 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 new file mode 100644 index 00000000..a576adb3 --- /dev/null +++ b/KkuMulKum/Source/Promise/ReadyStatusViewController.swift @@ -0,0 +1,29 @@ +// +// 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 new file mode 100644 index 00000000..8e0ea951 --- /dev/null +++ b/KkuMulKum/Source/Promise/TardyViewController.swift @@ -0,0 +1,29 @@ +// +// 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. + } + */ + +}