diff --git a/DaeHyun/MovieListApp/MovieListApp.xcodeproj/project.xcworkspace/xcuserdata/daehyunlee.xcuserdatad/UserInterfaceState.xcuserstate b/DaeHyun/MovieListApp/MovieListApp.xcodeproj/project.xcworkspace/xcuserdata/daehyunlee.xcuserdatad/UserInterfaceState.xcuserstate index f1977aa..59eccf2 100644 Binary files a/DaeHyun/MovieListApp/MovieListApp.xcodeproj/project.xcworkspace/xcuserdata/daehyunlee.xcuserdatad/UserInterfaceState.xcuserstate and b/DaeHyun/MovieListApp/MovieListApp.xcodeproj/project.xcworkspace/xcuserdata/daehyunlee.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/DaeHyun/ToDoListApp/ToDoListApp.xcodeproj/project.pbxproj b/DaeHyun/ToDoListApp/ToDoListApp.xcodeproj/project.pbxproj index 6a6cb57..a271de2 100644 --- a/DaeHyun/ToDoListApp/ToDoListApp.xcodeproj/project.pbxproj +++ b/DaeHyun/ToDoListApp/ToDoListApp.xcodeproj/project.pbxproj @@ -7,7 +7,7 @@ objects = { /* Begin PBXBuildFile section */ - A63437172B14F31000A717C2 /* Task.swift in Sources */ = {isa = PBXBuildFile; fileRef = A63437162B14F31000A717C2 /* Task.swift */; }; + A63437172B14F31000A717C2 /* Todo.swift in Sources */ = {isa = PBXBuildFile; fileRef = A63437162B14F31000A717C2 /* Todo.swift */; }; A634371A2B17275000A717C2 /* CombineMoya in Frameworks */ = {isa = PBXBuildFile; productRef = A63437192B17275000A717C2 /* CombineMoya */; }; A634371C2B17275000A717C2 /* Moya in Frameworks */ = {isa = PBXBuildFile; productRef = A634371B2B17275000A717C2 /* Moya */; }; A634371E2B17275000A717C2 /* ReactiveMoya in Frameworks */ = {isa = PBXBuildFile; productRef = A634371D2B17275000A717C2 /* ReactiveMoya */; }; @@ -16,6 +16,9 @@ A63437262B1755FA00A717C2 /* TodoResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = A63437252B1755FA00A717C2 /* TodoResponseDTO.swift */; }; A63437282B17945300A717C2 /* Date+.swift in Sources */ = {isa = PBXBuildFile; fileRef = A63437272B17945300A717C2 /* Date+.swift */; }; A634372A2B17A41400A717C2 /* TodoRequestDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = A63437292B17A41400A717C2 /* TodoRequestDTO.swift */; }; + A6AB519C2B328BEF00C94A7F /* TaskDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AB519B2B328BEF00C94A7F /* TaskDetailViewController.swift */; }; + A6AB519E2B32D4E500C94A7F /* MoyaProvider+.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AB519D2B32D4E500C94A7F /* MoyaProvider+.swift */; }; + A6AB51A02B32F4B500C94A7F /* LoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AB519F2B32F4B500C94A7F /* LoginViewController.swift */; }; A6B2AFFE2AFB96A80070A772 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6B2AFFD2AFB96A80070A772 /* AppDelegate.swift */; }; A6B2B0002AFB96A80070A772 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6B2AFFF2AFB96A80070A772 /* SceneDelegate.swift */; }; A6B2B0072AFB96A90070A772 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A6B2B0062AFB96A90070A772 /* Assets.xcassets */; }; @@ -31,11 +34,14 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - A63437162B14F31000A717C2 /* Task.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Task.swift; sourceTree = ""; }; + A63437162B14F31000A717C2 /* Todo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Todo.swift; sourceTree = ""; }; A63437212B17276C00A717C2 /* TodoAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoAPI.swift; sourceTree = ""; }; A63437252B1755FA00A717C2 /* TodoResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoResponseDTO.swift; sourceTree = ""; }; A63437272B17945300A717C2 /* Date+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+.swift"; sourceTree = ""; }; A63437292B17A41400A717C2 /* TodoRequestDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoRequestDTO.swift; sourceTree = ""; }; + A6AB519B2B328BEF00C94A7F /* TaskDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskDetailViewController.swift; sourceTree = ""; }; + A6AB519D2B32D4E500C94A7F /* MoyaProvider+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MoyaProvider+.swift"; sourceTree = ""; }; + A6AB519F2B32F4B500C94A7F /* LoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewController.swift; sourceTree = ""; }; A6B2AFFA2AFB96A80070A772 /* ToDoListApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ToDoListApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; A6B2AFFD2AFB96A80070A772 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; A6B2AFFF2AFB96A80070A772 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -121,6 +127,8 @@ A6B2B0112AFBA0860070A772 /* MainTabBarController.swift */, A6B2B0132AFBA0B90070A772 /* TaskViewController.swift */, A6B2B0152AFBA0D00070A772 /* SettingViewController.swift */, + A6AB519B2B328BEF00C94A7F /* TaskDetailViewController.swift */, + A6AB519F2B32F4B500C94A7F /* LoginViewController.swift */, ); path = VCs; sourceTree = ""; @@ -139,6 +147,7 @@ children = ( A63437272B17945300A717C2 /* Date+.swift */, A6B2B0212B02A3B50070A772 /* UILabel+.swift */, + A6AB519D2B32D4E500C94A7F /* MoyaProvider+.swift */, ); path = Classes; sourceTree = ""; @@ -147,7 +156,7 @@ isa = PBXGroup; children = ( A6E1A2FB2B0F1D170014D9A3 /* TaskManager.swift */, - A63437162B14F31000A717C2 /* Task.swift */, + A63437162B14F31000A717C2 /* Todo.swift */, A63437212B17276C00A717C2 /* TodoAPI.swift */, A63437252B1755FA00A717C2 /* TodoResponseDTO.swift */, A63437292B17A41400A717C2 /* TodoRequestDTO.swift */, @@ -242,11 +251,14 @@ A6E1A2FC2B0F1D170014D9A3 /* TaskManager.swift in Sources */, A6B2AFFE2AFB96A80070A772 /* AppDelegate.swift in Sources */, A634372A2B17A41400A717C2 /* TodoRequestDTO.swift in Sources */, - A63437172B14F31000A717C2 /* Task.swift in Sources */, + A63437172B14F31000A717C2 /* Todo.swift in Sources */, A6B2B0142AFBA0B90070A772 /* TaskViewController.swift in Sources */, A6B2B0122AFBA0860070A772 /* MainTabBarController.swift in Sources */, + A6AB519C2B328BEF00C94A7F /* TaskDetailViewController.swift in Sources */, + A6AB519E2B32D4E500C94A7F /* MoyaProvider+.swift in Sources */, A6B2B0222B02A3B50070A772 /* UILabel+.swift in Sources */, A63437222B17276C00A717C2 /* TodoAPI.swift in Sources */, + A6AB51A02B32F4B500C94A7F /* LoginViewController.swift in Sources */, A63437282B17945300A717C2 /* Date+.swift in Sources */, A6B2B0002AFB96A80070A772 /* SceneDelegate.swift in Sources */, A6B2B0162AFBA0D00070A772 /* SettingViewController.swift in Sources */, @@ -317,7 +329,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.4; + IPHONEOS_DEPLOYMENT_TARGET = 17.2; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -371,7 +383,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.4; + IPHONEOS_DEPLOYMENT_TARGET = 17.2; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; @@ -388,6 +400,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 39R4Y76837; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = ToDoListApp/Info.plist; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; @@ -415,6 +428,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 39R4Y76837; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = ToDoListApp/Info.plist; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; diff --git a/DaeHyun/ToDoListApp/ToDoListApp.xcodeproj/project.xcworkspace/xcuserdata/daehyunlee.xcuserdatad/UserInterfaceState.xcuserstate b/DaeHyun/ToDoListApp/ToDoListApp.xcodeproj/project.xcworkspace/xcuserdata/daehyunlee.xcuserdatad/UserInterfaceState.xcuserstate index a95830b..594b373 100644 Binary files a/DaeHyun/ToDoListApp/ToDoListApp.xcodeproj/project.xcworkspace/xcuserdata/daehyunlee.xcuserdatad/UserInterfaceState.xcuserstate and b/DaeHyun/ToDoListApp/ToDoListApp.xcodeproj/project.xcworkspace/xcuserdata/daehyunlee.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/DaeHyun/ToDoListApp/ToDoListApp.xcodeproj/xcuserdata/daehyunlee.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/DaeHyun/ToDoListApp/ToDoListApp.xcodeproj/xcuserdata/daehyunlee.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index 5f48cbd..6cd0a0d 100644 --- a/DaeHyun/ToDoListApp/ToDoListApp.xcodeproj/xcuserdata/daehyunlee.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/DaeHyun/ToDoListApp/ToDoListApp.xcodeproj/xcuserdata/daehyunlee.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -3,70 +3,4 @@ uuid = "68523EC1-307B-4CF1-BC37-E1E64052650B" type = "1" version = "2.0"> - - - - - - - - - - - - - - - - diff --git a/DaeHyun/ToDoListApp/ToDoListApp.xcodeproj/xcuserdata/daehyunlee.xcuserdatad/xcschemes/xcschememanagement.plist b/DaeHyun/ToDoListApp/ToDoListApp.xcodeproj/xcuserdata/daehyunlee.xcuserdatad/xcschemes/xcschememanagement.plist index c41395d..7270543 100644 --- a/DaeHyun/ToDoListApp/ToDoListApp.xcodeproj/xcuserdata/daehyunlee.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/DaeHyun/ToDoListApp/ToDoListApp.xcodeproj/xcuserdata/daehyunlee.xcuserdatad/xcschemes/xcschememanagement.plist @@ -91,7 +91,7 @@ ToDoListApp.xcscheme_^#shared#^_ orderHint - 1 + 0 diff --git a/DaeHyun/ToDoListApp/ToDoListApp/Resources/SceneDelegate.swift b/DaeHyun/ToDoListApp/ToDoListApp/Resources/SceneDelegate.swift index f9454ca..bf9d25a 100644 --- a/DaeHyun/ToDoListApp/ToDoListApp/Resources/SceneDelegate.swift +++ b/DaeHyun/ToDoListApp/ToDoListApp/Resources/SceneDelegate.swift @@ -17,11 +17,25 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). guard let windowScene = (scene as? UIWindowScene) else { return } window = UIWindow(windowScene: windowScene) - let viewController = MainTabBarController() +// let viewController = MainTabBarController() + let viewController = LoginViewController() viewController.view.backgroundColor = .systemBackground window?.rootViewController = viewController window?.makeKeyAndVisible() } + + func changeRootVC(_ vc: UIViewController, animated: Bool) { + guard let window = self.window else { return } + window.rootViewController = vc + + UIView.transition( + with: window, + duration: 0.2, + options: [.transitionCrossDissolve], + animations: nil, + completion: nil + ) + } func sceneDidDisconnect(_ scene: UIScene) { // Called as the scene is being released by the system. diff --git a/DaeHyun/ToDoListApp/ToDoListApp/Sources/Cells/TaskTableViewCell.swift b/DaeHyun/ToDoListApp/ToDoListApp/Sources/Cells/TaskTableViewCell.swift index 74d7df0..279267f 100644 --- a/DaeHyun/ToDoListApp/ToDoListApp/Sources/Cells/TaskTableViewCell.swift +++ b/DaeHyun/ToDoListApp/ToDoListApp/Sources/Cells/TaskTableViewCell.swift @@ -69,7 +69,7 @@ final class TaskTableViewCell: UITableViewCell { return button }() - func setupUI(task: Task) { + func setupUI(task: Todo) { self.taskLabel.text = task.name self.isTaskComplete = task.isCompleted } diff --git a/DaeHyun/ToDoListApp/ToDoListApp/Sources/Classes/MoyaProvider+.swift b/DaeHyun/ToDoListApp/ToDoListApp/Sources/Classes/MoyaProvider+.swift new file mode 100644 index 0000000..4a6e94b --- /dev/null +++ b/DaeHyun/ToDoListApp/ToDoListApp/Sources/Classes/MoyaProvider+.swift @@ -0,0 +1,18 @@ +// +// MoyaProvider+.swift +// ToDoListApp +// +// Created by 이대현 on 12/20/23. +// + +import Moya + +extension MoyaProvider { + func request(_ target: Target) async -> Result { + await withCheckedContinuation { continuation in + self.request(target) { result in + continuation.resume(returning: result) + } + } + } +} diff --git a/DaeHyun/ToDoListApp/ToDoListApp/Sources/Models/TaskManager.swift b/DaeHyun/ToDoListApp/ToDoListApp/Sources/Models/TaskManager.swift index c9d8715..36920c0 100644 --- a/DaeHyun/ToDoListApp/ToDoListApp/Sources/Models/TaskManager.swift +++ b/DaeHyun/ToDoListApp/ToDoListApp/Sources/Models/TaskManager.swift @@ -8,25 +8,25 @@ import Foundation class TaskManager { - var todayTaskData: [Task] = [] - var upcomingTaskData: [Task] = [] + var todayTaskData: [Todo] = [] + var upcomingTaskData: [Todo] = [] static let shared: TaskManager = TaskManager() private init(){} - func fetchTaskData(key: String) -> [Task]? { + func fetchTaskData(key: String) -> [Todo]? { if let taskData = UserDefaults.standard.object(forKey: key) as? Data{ let decoder = JSONDecoder() - if let tasks = try? decoder.decode([Task].self, from: taskData) { + if let tasks = try? decoder.decode([Todo].self, from: taskData) { return tasks } } return nil } - func saveTaskData(data: [Task], key: String) { + func saveTaskData(data: [Todo], key: String) { let encoder = JSONEncoder() if let encoded = try? encoder.encode(data) { UserDefaults.standard.setValue(encoded, forKey: key) diff --git a/DaeHyun/ToDoListApp/ToDoListApp/Sources/Models/Task.swift b/DaeHyun/ToDoListApp/ToDoListApp/Sources/Models/Todo.swift similarity index 55% rename from DaeHyun/ToDoListApp/ToDoListApp/Sources/Models/Task.swift rename to DaeHyun/ToDoListApp/ToDoListApp/Sources/Models/Todo.swift index 352059b..6b188d5 100644 --- a/DaeHyun/ToDoListApp/ToDoListApp/Sources/Models/Task.swift +++ b/DaeHyun/ToDoListApp/ToDoListApp/Sources/Models/Todo.swift @@ -1,5 +1,5 @@ // -// Task.swift +// Todo.swift // ToDoListApp // // Created by 이대현 on 2023/11/14. @@ -7,21 +7,29 @@ import Foundation -enum TaskSection: Int { +enum TodoSection: Int { case Today case Upcoming } -struct Task: Hashable, Codable { +struct Todo: Hashable, Codable { let id: String let name: String var isCompleted: Bool var deadLine: Date - init(id: String, name: String, isCompleted: Bool, deadLine: Date) { + var content: String + + init(id: String, + name: String, + isCompleted: Bool, + deadLine: Date, + content: String = "" + ) { self.id = id self.name = name self.isCompleted = isCompleted self.deadLine = deadLine + self.content = content } } diff --git a/DaeHyun/ToDoListApp/ToDoListApp/Sources/Models/TodoAPI.swift b/DaeHyun/ToDoListApp/ToDoListApp/Sources/Models/TodoAPI.swift index d4c99a5..49ac1f9 100644 --- a/DaeHyun/ToDoListApp/ToDoListApp/Sources/Models/TodoAPI.swift +++ b/DaeHyun/ToDoListApp/ToDoListApp/Sources/Models/TodoAPI.swift @@ -9,11 +9,16 @@ import Foundation import Moya let USERID = 1 // 해당 id에 해당하는 유저의 todolist 불러옴 + enum TodoAPI { - case getList + // Todo 정보 API + case getDetail(_ id: Int) + case updateTodo(_ id: Int, _ params: TodoRequestDTO) case createTodo(_ params: TodoRequestDTO) case updateCheck(_ id: Int, _ completed: Bool) case deleteTodo(_ id: Int) + // 유저 정보 API + case getList } extension TodoAPI: TargetType { @@ -30,18 +35,20 @@ extension TodoAPI: TargetType { return "/todos/\(USERID)" case .updateCheck(_, _): return "/todos/check" - case .deleteTodo(let id): + case .deleteTodo(let id), + .getDetail(let id), + .updateTodo(let id, _): return "/todos/\(id)" } } var method: Moya.Method { switch self { - case .getList: + case .getList, .getDetail(_): return .get case .createTodo(_): return .post - case .updateCheck(_, _): + case .updateCheck(_, _), .updateTodo(_, _): return .put case .deleteTodo(_): return .delete @@ -62,6 +69,10 @@ extension TodoAPI: TargetType { return .requestParameters(parameters: params, encoding: URLEncoding.queryString) case .deleteTodo(_): return .requestPlain + case .getDetail(_): + return .requestPlain + case .updateTodo(_, let params): + return .requestJSONEncodable(params) } } diff --git a/DaeHyun/ToDoListApp/ToDoListApp/Sources/Models/TodoResponseDTO.swift b/DaeHyun/ToDoListApp/ToDoListApp/Sources/Models/TodoResponseDTO.swift index ca79b0e..d36b4ce 100644 --- a/DaeHyun/ToDoListApp/ToDoListApp/Sources/Models/TodoResponseDTO.swift +++ b/DaeHyun/ToDoListApp/ToDoListApp/Sources/Models/TodoResponseDTO.swift @@ -12,12 +12,14 @@ struct TodoResponseDTO: Decodable { var title: String var isCompleted: Bool var deadLine: String + var content: String - func toTask() -> Task { - return Task(id: String(self.id), + func toTodo() -> Todo { + return Todo(id: String(self.id), name: self.title, isCompleted: self.isCompleted, - deadLine: self.deadLineDate + deadLine: self.deadLineDate, + content: self.content ) } diff --git a/DaeHyun/ToDoListApp/ToDoListApp/Sources/VCs/LoginViewController.swift b/DaeHyun/ToDoListApp/ToDoListApp/Sources/VCs/LoginViewController.swift new file mode 100644 index 0000000..21c9d21 --- /dev/null +++ b/DaeHyun/ToDoListApp/ToDoListApp/Sources/VCs/LoginViewController.swift @@ -0,0 +1,148 @@ +// +// LoginViewController.swift +// ToDoListApp +// +// Created by 이대현 on 12/20/23. +// + +import Moya +import SnapKit +import UIKit + +class LoginViewController: UIViewController { + private lazy var titleImageView: UIImageView = { + let imageView = UIImageView() + imageView.image = UIImage(systemName: "list.clipboard") + imageView.tintColor = .red + imageView.snp.makeConstraints { make in + make.width.height.equalTo(50) + } + return imageView + + }() + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.text = "앱센터 To-Do 리스트" + label.font = .systemFont(ofSize: 30, weight: .bold) + return label + }() + + private lazy var titleStackView: UIStackView = { + let stackView = UIStackView(arrangedSubviews: [titleImageView, titleLabel]) + stackView.axis = .horizontal + stackView.alignment = .center + stackView.spacing = 10 + stackView.isLayoutMarginsRelativeArrangement = true + stackView.directionalLayoutMargins = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 20) + return stackView + }() + + private lazy var idLabel: UILabel = { + let label = UILabel() + label.text = "아이디" + return label + }() + + private lazy var idTextField: UITextField = { + let textField = UITextField() + textField.borderStyle = .roundedRect + return textField + }() + + private lazy var passwordLabel: UILabel = { + let label = UILabel() + label.text = "비밀번호" + return label + }() + + private lazy var passwordTextField: UITextField = { + let textField = UITextField() + textField.borderStyle = .roundedRect + return textField + }() + + private lazy var statusLabel: UILabel = { + let label = UILabel() + label.text = "status" + return label + }() + + private lazy var loginButton: UIButton = { + var config = UIButton.Configuration.filled() + config.baseBackgroundColor = .red + config.baseForegroundColor = .black + config.title = "로그인" + + let button = UIButton(configuration: config) + button.addAction(UIAction { [weak self] _ in + self?.moveToMain() + + + }, for: .touchUpInside) + return button + }() + + private func checkLogin() { + + } + + private func moveToMain() { + let tabBarVC = MainTabBarController() + tabBarVC.view.backgroundColor = .systemBackground + (UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate)?.changeRootVC(tabBarVC, animated: true) + } + + + override func viewDidLoad() { + super.viewDidLoad() + + layout() + } + + private func layout() { + self.view.addSubview(titleStackView) + titleStackView.snp.makeConstraints { make in + make.top.equalTo(view.safeAreaLayoutGuide).offset(150) + make.centerX.equalTo(view.safeAreaLayoutGuide) + } + + self.view.addSubview(idLabel) + idLabel.snp.makeConstraints { make in + make.top.equalTo(titleStackView.snp.bottom).offset(50) + make.left.equalTo(view.safeAreaLayoutGuide).offset(30) + make.right.equalTo(view.safeAreaLayoutGuide).offset(-30) + } + + self.view.addSubview(idTextField) + idTextField.snp.makeConstraints { make in + make.top.equalTo(idLabel.snp.bottom).offset(30) + make.left.right.equalTo(idLabel) + } + + self.view.addSubview(passwordLabel) + passwordLabel.snp.makeConstraints { make in + make.top.equalTo(idTextField.snp.bottom).offset(30) + make.left.right.equalTo(idTextField) + } + + self.view.addSubview(passwordTextField) + passwordTextField.snp.makeConstraints { make in + make.top.equalTo(passwordLabel.snp.bottom).offset(30) + make.left.right.equalTo(passwordLabel) + } + + self.view.addSubview(statusLabel) + statusLabel.snp.makeConstraints { make in + make.top.equalTo(passwordTextField.snp.bottom).offset(30) + make.left.right.equalTo(passwordTextField) + } + + self.view.addSubview(loginButton) + loginButton.snp.makeConstraints { make in + make.top.equalTo(statusLabel.snp.bottom).offset(30) + make.left.right.equalTo(statusLabel) + make.height.equalTo(50) + } + } +} diff --git a/DaeHyun/ToDoListApp/ToDoListApp/Sources/VCs/MainTabBarController.swift b/DaeHyun/ToDoListApp/ToDoListApp/Sources/VCs/MainTabBarController.swift index b9af38e..c33dd7c 100644 --- a/DaeHyun/ToDoListApp/ToDoListApp/Sources/VCs/MainTabBarController.swift +++ b/DaeHyun/ToDoListApp/ToDoListApp/Sources/VCs/MainTabBarController.swift @@ -8,7 +8,7 @@ import UIKit class MainTabBarController: UITabBarController { - let taskVC = TaskViewController() + let taskVC = UINavigationController(rootViewController: TaskViewController()) let settingVC = SettingViewController() override func viewDidLoad() { diff --git a/DaeHyun/ToDoListApp/ToDoListApp/Sources/VCs/TaskDetailViewController.swift b/DaeHyun/ToDoListApp/ToDoListApp/Sources/VCs/TaskDetailViewController.swift new file mode 100644 index 0000000..2cf73bc --- /dev/null +++ b/DaeHyun/ToDoListApp/ToDoListApp/Sources/VCs/TaskDetailViewController.swift @@ -0,0 +1,175 @@ +// +// TaskDetailViewController.swift +// ToDoListApp +// +// Created by 이대현 on 12/20/23. +// + +import Moya +import SnapKit +import UIKit + +class TaskDetailViewController: UIViewController { + var todoID: Int? = nil + // 서버 통신을 위한 provider + let provider = MoyaProvider() + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.text = "제목" + return label + }() + + private lazy var titleTextField: UITextField = { + let textField = UITextField() + textField.borderStyle = .roundedRect + textField.text = "titletitle" + return textField + }() + + private lazy var descriptionLabel: UILabel = { + let label = UILabel() + label.text = "내용" + return label + }() + + private lazy var descriptionTextView: UITextView = { + let textView = UITextView() + textView.layer.borderColor = UIColor.lightGray.cgColor + textView.layer.borderWidth = 1 + textView.font = .systemFont(ofSize: 16) + textView.text = "description" + return textView + }() + + private lazy var deadlineLabel: UILabel = { + let label = UILabel() + label.text = "마감일" + return label + }() + + private lazy var deadlineDatePicker: UIDatePicker = { + let datePicker = UIDatePicker() + datePicker.datePickerMode = .date + datePicker.preferredDatePickerStyle = .compact + datePicker.locale = Locale(identifier: "ko-KR") + return datePicker + }() + + private lazy var updateButton: UIButton = { + var config = UIButton.Configuration.filled() + config.baseBackgroundColor = .red + config.baseForegroundColor = .black + config.title = "수정하기" + + let button = UIButton(configuration: config) + button.addAction(UIAction { [weak self] _ in + if let self = self, + let id = self.todoID, + let title = self.titleTextField.text, + let content = self.descriptionTextView.text { + let deadline = self.deadlineDatePicker.date + + // todo server api + let todoRequest = TodoRequestDTO( + content: content, + deadLine: deadline.toString, + title: title + ) + provider.request(.updateTodo(id, todoRequest)) { [weak self] result in + switch result { + case let .success(response): + print(String(data: response.data, encoding: .utf8)) + self?.backToTodoListView() + case let .failure(error): + print(error.localizedDescription) + } + } + + } + }, for: .touchUpInside) + return button + }() + + override func viewDidLoad() { + super.viewDidLoad() + layout() + } + + private func layout() { + self.view.backgroundColor = .systemBackground + + self.view.addSubview(titleLabel) + titleLabel.snp.makeConstraints { make in + make.left.equalTo(view.safeAreaLayoutGuide).offset(30) + make.top.equalTo(view.safeAreaLayoutGuide).offset(20) + make.right.equalTo(view.safeAreaLayoutGuide).offset(-30) + } + + self.view.addSubview(titleTextField) + titleTextField.snp.makeConstraints { make in + make.left.right.equalTo(titleLabel) + make.top.equalTo(titleLabel.snp.bottom ).offset(20) + } + + self.view.addSubview(descriptionLabel) + descriptionLabel.snp.makeConstraints { make in + make.left.right.equalTo(titleTextField) + make.top.equalTo(titleTextField.snp.bottom ).offset(20) + } + + self.view.addSubview(descriptionTextView) + descriptionTextView.snp.makeConstraints { make in + make.left.right.equalTo(descriptionLabel) + make.top.equalTo(descriptionLabel.snp.bottom ).offset(20) + make.height.equalTo(150) + } + + self.view.addSubview(deadlineLabel) + deadlineLabel.snp.makeConstraints { make in + make.left.right.equalTo(descriptionTextView) + make.top.equalTo(descriptionTextView.snp.bottom ).offset(20) + } + + self.view.addSubview(deadlineDatePicker) + deadlineDatePicker.snp.makeConstraints { make in + make.left.equalTo(deadlineLabel) + make.top.equalTo(deadlineLabel.snp.bottom).offset(20) + } + + self.view.addSubview(updateButton) + updateButton.snp.makeConstraints { make in + make.left.right.equalTo(deadlineLabel) + make.top.equalTo(deadlineDatePicker.snp.bottom).offset(20) + make.height.equalTo(50) + } + } + + // MARK: - 초기 세팅 + func setupUI(id: Int) { + self.todoID = id + + _Concurrency.Task { + let result = await provider.request(.getDetail(id)) + switch result { + case let .success(response): + print(String(data: response.data, encoding: .utf8)) + if let result = try? response.map(TodoResponseDTO.self) { + let todoData = result.toTodo() + // 여기서 UI 세팅 + DispatchQueue.main.async { + self.titleTextField.text = todoData.name + self.descriptionTextView.text = todoData.content + self.deadlineDatePicker.date = todoData.deadLine + } + } + case let .failure(error): + print(error.localizedDescription) + } + } + } + + func backToTodoListView() { + self.navigationController?.popViewController(animated: true) + } +} diff --git a/DaeHyun/ToDoListApp/ToDoListApp/Sources/VCs/TaskViewController.swift b/DaeHyun/ToDoListApp/ToDoListApp/Sources/VCs/TaskViewController.swift index 65f445e..96fe379 100644 --- a/DaeHyun/ToDoListApp/ToDoListApp/Sources/VCs/TaskViewController.swift +++ b/DaeHyun/ToDoListApp/ToDoListApp/Sources/VCs/TaskViewController.swift @@ -51,7 +51,7 @@ class TaskViewController: UIViewController { button.addAction(UIAction { [weak self] _ in if let self = self, let content = self.taskTextField.text { - let section: TaskSection + let section: TodoSection if self.todayButton.isSelected { section = .Today } else { @@ -75,23 +75,24 @@ class TaskViewController: UIViewController { return stackView }() - var todayTaskData: [Task] = [] + var todayTaskData: [Todo] = [] - var upcomingTaskData: [Task] = [] + var upcomingTaskData: [Todo] = [] // 서버 통신을 위한 provider let provider = MoyaProvider() // fetch mode let fetchMode: FetchMode = .server - private lazy var taskTableViewDiffableDataSource: UITableViewDiffableDataSource = { - let diffableDataSource = UITableViewDiffableDataSource( + private lazy var taskTableViewDiffableDataSource: UITableViewDiffableDataSource = { + let diffableDataSource = UITableViewDiffableDataSource( tableView: taskTableView ) { tableView, _, task -> UITableViewCell? in guard let cell = tableView.dequeueReusableCell(withIdentifier: TaskTableViewCell.identifier) as? TaskTableViewCell else { return UITableViewCell() } + cell.selectionStyle = .none cell.delegate = self cell.setupUI(task: task) return cell @@ -99,11 +100,15 @@ class TaskViewController: UIViewController { return diffableDataSource }() - private lazy var taskTableViewSnapShot = NSDiffableDataSourceSnapshot() + private lazy var taskTableViewSnapShot = NSDiffableDataSourceSnapshot() override func viewDidLoad() { super.viewDidLoad() layout() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) fetchTaskData(at: .server) loadTableView() } @@ -129,10 +134,10 @@ class TaskViewController: UIViewController { // 섹션 분류 후 보여줌 // 과거 deadline의 todo도 today에 들어가긴 합니다 self.todayTaskData = result - .map { $0.toTask() } + .map { $0.toTodo() } .filter { $0.deadLine.isToday } self.upcomingTaskData = result - .map { $0.toTask() } + .map { $0.toTodo() } .filter { !$0.deadLine.isToday } self.loadTableView() } @@ -144,7 +149,7 @@ class TaskViewController: UIViewController { } private func appendTaskData(title: String, - at section: TaskSection, + at section: TodoSection, mode: FetchMode = .coredata) { // deadline // today -> 그 날의 23시 59분, upcoming -> 다음 날 @@ -153,7 +158,7 @@ class TaskViewController: UIViewController { switch mode { case .coredata: // 코어데이터 저장 - let task = Task( + let task = Todo( id: UUID().uuidString, name: title, isCompleted: false, @@ -170,7 +175,7 @@ class TaskViewController: UIViewController { case .server: // 서버 api 활용 let requestBody = TodoRequestDTO( - content: title, + content: title, // content도 일단 title로 설정 deadLine: deadLine.toString, title: title ) @@ -179,8 +184,7 @@ class TaskViewController: UIViewController { case let .success(response): print(String(data: response.data, encoding: .utf8)) if let result = try? response.map(TodoResponseDTO.self) { - print("result: ", result) - let task = Task(id: String(result.id), + let task = Todo(id: String(result.id), name: result.title, isCompleted: result.isCompleted, deadLine: result.deadLineDate) @@ -221,14 +225,14 @@ class TaskViewController: UIViewController { } private func loadTableView() { - taskTableViewSnapShot = NSDiffableDataSourceSnapshot() + taskTableViewSnapShot = NSDiffableDataSourceSnapshot() taskTableViewSnapShot.appendSections([.Today, .Upcoming]) populateSnapshot(data: todayTaskData, to: .Today) populateSnapshot(data: upcomingTaskData, to: .Upcoming) taskTableViewDiffableDataSource.apply(taskTableViewSnapShot) } - private func populateSnapshot(data: [Task], to section: TaskSection) { + private func populateSnapshot(data: [Todo], to section: TodoSection) { taskTableViewSnapShot.appendItems(data, toSection: section) } @@ -238,7 +242,6 @@ class TaskViewController: UIViewController { self.view.addSubview(appendStackView) appendStackView.snp.makeConstraints { make in make.left.right.bottom.equalTo(view.safeAreaLayoutGuide) - make.height.equalTo(70) } self.view.addSubview(taskTableView) @@ -254,7 +257,7 @@ extension TaskViewController: UITableViewDelegate { guard let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: TaskHeaderView.identifier) as? TaskHeaderView else { return UIView() } - if section == TaskSection.Today.rawValue { + if section == TodoSection.Today.rawValue { headerView.setTitle("Today") } else { headerView.setTitle("Upcoming") @@ -265,12 +268,28 @@ extension TaskViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { return 80 } + + // MARK: - TaskDetailViewController 화면전환 + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + print("select row") + var task: Todo + if indexPath.section == 0 { + task = todayTaskData[indexPath.row] + } else { + task = upcomingTaskData[indexPath.row] + } + if let id = Int(task.id) { + let vc = TaskDetailViewController() + vc.setupUI(id: id) + self.navigationController?.pushViewController(vc, animated: true) + } + } } extension TaskViewController: TaskTableViewCellDelegate { func setIsComplete(forCell cell: TaskTableViewCell, _ isComplete: Bool) { if let indexPath = taskTableView.indexPath(for: cell) { - var task: Task + var task: Todo if indexPath.section == 0 { task = todayTaskData[indexPath.row] } else { @@ -286,7 +305,7 @@ extension TaskViewController: TaskTableViewCellDelegate { func removeTask(forCell cell: TaskTableViewCell) { if let indexPath = taskTableView.indexPath(for: cell) { - let task: Task + let task: Todo if indexPath.section == 0 { task = todayTaskData.remove(at: indexPath.row) } else {