From 4d380487c4a51a44ed325c8fe7e743c721a9895f Mon Sep 17 00:00:00 2001 From: Sejin Lee Date: Tue, 10 Jan 2023 18:38:58 +0900 Subject: [PATCH 1/2] =?UTF-8?q?[Feat]=20#69=20-=20=EB=B3=B4=EA=B4=80?= =?UTF-8?q?=ED=95=A8=EC=9A=A9=20=EB=82=B4=EA=B0=80=20=EA=B7=B8=EB=A6=B0=20?= =?UTF-8?q?=EC=BD=94=EC=8A=A4=20API=20=EC=97=B0=EA=B2=B0=EC=9D=84=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20Router=EC=99=80=20Dto=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Runnect-iOS.xcodeproj/project.pbxproj | 20 +++++-- .../Network/Dto/CourseStorageDto/.gitkeep | 0 .../PrivateCourseResponseDto.swift | 32 ++++++++++++ .../CourseStorageRouter.swift | 52 +++++++++++++++++++ .../Router/RunningRouter/RunningRouter.swift | 2 +- 5 files changed, 101 insertions(+), 5 deletions(-) delete mode 100644 Runnect-iOS/Runnect-iOS/Network/Dto/CourseStorageDto/.gitkeep create mode 100644 Runnect-iOS/Runnect-iOS/Network/Dto/CourseStorageDto/ResponseDto/PrivateCourseResponseDto.swift create mode 100644 Runnect-iOS/Runnect-iOS/Network/Router/CourseStorageRouter/CourseStorageRouter.swift diff --git a/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj b/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj index 382e32b7..6f4b7376 100644 --- a/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj +++ b/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj @@ -62,6 +62,7 @@ CE5875A4296015D2005D967E /* Encodable+.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5875A3296015D2005D967E /* Encodable+.swift */; }; CE591E9C296D4F69000FCBB3 /* RunningRecordResonseDto.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE591E9B296D4F69000FCBB3 /* RunningRecordResonseDto.swift */; }; CE591E9E296D5140000FCBB3 /* RunningRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE591E9D296D5140000FCBB3 /* RunningRouter.swift */; }; + CE591EA1296D5EB5000FCBB3 /* PrivateCourseResponseDto.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE591EA0296D5EB5000FCBB3 /* PrivateCourseResponseDto.swift */; }; CE6655BF295D82E200C64E12 /* .gitkeep in Resources */ = {isa = PBXBuildFile; fileRef = CE6655BE295D82E200C64E12 /* .gitkeep */; }; CE6655C8295D849F00C64E12 /* StringLiterals.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6655C7295D849F00C64E12 /* StringLiterals.swift */; }; CE6655CA295D84DD00C64E12 /* UserDefaultKeyList.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6655C9295D84DD00C64E12 /* UserDefaultKeyList.swift */; }; @@ -123,6 +124,7 @@ CEEC6B402961C55000D00E1E /* MyPageVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEEC6B3F2961C55000D00E1E /* MyPageVC.swift */; }; CEEC6B492961C5E200D00E1E /* SplashVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEEC6B482961C5E200D00E1E /* SplashVC.swift */; }; CEEC6B4B2961D89700D00E1E /* CustomNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEEC6B4A2961D89700D00E1E /* CustomNavigationBar.swift */; }; + CEF3CD98296D63B9002723A1 /* CourseStorageRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEF3CD97296D63B9002723A1 /* CourseStorageRouter.swift */; }; DA20D847296697A600F1581F /* MyCourseSelectVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA20D846296697A600F1581F /* MyCourseSelectVC.swift */; }; DA20D849296697B400F1581F /* CourseUploadVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA20D848296697B400F1581F /* CourseUploadVC.swift */; }; DA20D84E2966A9B300F1581F /* CourseSearchVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA20D84D2966A9B300F1581F /* CourseSearchVC.swift */; }; @@ -150,11 +152,9 @@ CE0C23782966D6AF00B45063 /* ViewPager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewPager.swift; sourceTree = ""; }; CE0D9FD229648DA300CEB5CD /* CustomAlertVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomAlertVC.swift; sourceTree = ""; }; CE10063929680C5700FD31FB /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = ""; }; - CE10063B29680C6800FD31FB /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = ""; }; CE10063C29680C7000FD31FB /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = ""; }; CE10063D29680C8100FD31FB /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = ""; }; CE10063E29680C8800FD31FB /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = ""; }; - CE10064129680CA700FD31FB /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = ""; }; CE10064229680CAD00FD31FB /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = ""; }; CE10064329680CB400FD31FB /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = ""; }; CE10064429680CBC00FD31FB /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = ""; }; @@ -204,6 +204,7 @@ CE5875A3296015D2005D967E /* Encodable+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Encodable+.swift"; sourceTree = ""; }; CE591E9B296D4F69000FCBB3 /* RunningRecordResonseDto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunningRecordResonseDto.swift; sourceTree = ""; }; CE591E9D296D5140000FCBB3 /* RunningRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunningRouter.swift; sourceTree = ""; }; + CE591EA0296D5EB5000FCBB3 /* PrivateCourseResponseDto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivateCourseResponseDto.swift; sourceTree = ""; }; CE6655BE295D82E200C64E12 /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = ""; }; CE6655C0295D82F000C64E12 /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = ""; }; CE6655C1295D82F700C64E12 /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = ""; }; @@ -272,6 +273,7 @@ CEEC6B462961C5BB00D00E1E /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = ""; }; CEEC6B482961C5E200D00E1E /* SplashVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashVC.swift; sourceTree = ""; }; CEEC6B4A2961D89700D00E1E /* CustomNavigationBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomNavigationBar.swift; sourceTree = ""; }; + CEF3CD97296D63B9002723A1 /* CourseStorageRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseStorageRouter.swift; sourceTree = ""; }; DA20D846296697A600F1581F /* MyCourseSelectVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyCourseSelectVC.swift; sourceTree = ""; }; DA20D848296697B400F1581F /* CourseUploadVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseUploadVC.swift; sourceTree = ""; }; DA20D84D2966A9B300F1581F /* CourseSearchVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseSearchVC.swift; sourceTree = ""; }; @@ -412,7 +414,7 @@ CE10063629680C1C00FD31FB /* CourseStorageDto */ = { isa = PBXGroup; children = ( - CE10063B29680C6800FD31FB /* .gitkeep */, + CE591E9F296D5E0F000FCBB3 /* ResponseDto */, ); path = CourseStorageDto; sourceTree = ""; @@ -711,7 +713,7 @@ CE40BB27296808290030ABCA /* CourseStorageRouter */ = { isa = PBXGroup; children = ( - CE10064129680CA700FD31FB /* .gitkeep */, + CEF3CD97296D63B9002723A1 /* CourseStorageRouter.swift */, ); path = CourseStorageRouter; sourceTree = ""; @@ -805,6 +807,14 @@ path = ResponseDto; sourceTree = ""; }; + CE591E9F296D5E0F000FCBB3 /* ResponseDto */ = { + isa = PBXGroup; + children = ( + CE591EA0296D5EB5000FCBB3 /* PrivateCourseResponseDto.swift */, + ); + path = ResponseDto; + sourceTree = ""; + }; CE6655A8295D7F7D00C64E12 /* Presentation */ = { isa = PBXGroup; children = ( @@ -1298,10 +1308,12 @@ CE6655F0295D891B00C64E12 /* UITextView+.swift in Sources */, CEC2A6922962BE2900160BF7 /* DepartureSearchVC.swift in Sources */, CE6655EE295D88E600C64E12 /* UITextField+.swift in Sources */, + CEF3CD98296D63B9002723A1 /* CourseStorageRouter.swift in Sources */, CE40BB1C2967E4910030ABCA /* RunningWaitingVC.swift in Sources */, CE6B63D6296731F9003F900F /* ScrapCourseListView.swift in Sources */, CE6655F8295D90CF00C64E12 /* adjusted+.swift in Sources */, CE4545CB295D7AF4003201E1 /* SceneDelegate.swift in Sources */, + CE591EA1296D5EB5000FCBB3 /* PrivateCourseResponseDto.swift in Sources */, A3BC2F3F2964706100198261 /* UploadedCourseInfoCVC.swift in Sources */, CE6655FE295D912300C64E12 /* calculateTopInset.swift in Sources */, CEEC6B492961C5E200D00E1E /* SplashVC.swift in Sources */, diff --git a/Runnect-iOS/Runnect-iOS/Network/Dto/CourseStorageDto/.gitkeep b/Runnect-iOS/Runnect-iOS/Network/Dto/CourseStorageDto/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/Runnect-iOS/Runnect-iOS/Network/Dto/CourseStorageDto/ResponseDto/PrivateCourseResponseDto.swift b/Runnect-iOS/Runnect-iOS/Network/Dto/CourseStorageDto/ResponseDto/PrivateCourseResponseDto.swift new file mode 100644 index 00000000..e4a31dd0 --- /dev/null +++ b/Runnect-iOS/Runnect-iOS/Network/Dto/CourseStorageDto/ResponseDto/PrivateCourseResponseDto.swift @@ -0,0 +1,32 @@ +// +// PrivateCourseResponseDto.swift +// Runnect-iOS +// +// Created by sejin on 2023/01/10. +// + +import Foundation + +// MARK: - PrivateCourseResponseDto + +struct PrivateCourseResponseDto: Codable { + let courses: [PrivateCourse] +} + +// MARK: - PrivateCourse + +struct PrivateCourse: Codable { + let id: Int + let image, createdAt: String + let distance: Float? + let path: [[Double]]? + let departure: PrivateCourseDeparture +} + +// MARK: - PrivateCourseDeparture + +struct PrivateCourseDeparture: Codable { + let region, city: String + let town: String? + let name: String? +} diff --git a/Runnect-iOS/Runnect-iOS/Network/Router/CourseStorageRouter/CourseStorageRouter.swift b/Runnect-iOS/Runnect-iOS/Network/Router/CourseStorageRouter/CourseStorageRouter.swift new file mode 100644 index 00000000..ba7ceb45 --- /dev/null +++ b/Runnect-iOS/Runnect-iOS/Network/Router/CourseStorageRouter/CourseStorageRouter.swift @@ -0,0 +1,52 @@ +// +// CourseStorageRouter.swift +// Runnect-iOS +// +// Created by sejin on 2023/01/10. +// + +import Foundation + +import Moya + +enum CourseStorageRouter { + case getAllPrivateCourse +} + +extension CourseStorageRouter: TargetType { + var baseURL: URL { + guard let url = URL(string: Config.baseURL) else { + fatalError("baseURL could not be configured") + } + + return url + } + + var path: String { + switch self { + case .getAllPrivateCourse: + return "/course/user" + } + } + + var method: Moya.Method { + switch self { + case .getAllPrivateCourse: + return .get + } + } + + var task: Moya.Task { + switch self { + case .getAllPrivateCourse: + return .requestPlain + } + } + + var headers: [String: String]? { + switch self { + case .getAllPrivateCourse: + return Config.headerWithDeviceId + } + } +} diff --git a/Runnect-iOS/Runnect-iOS/Network/Router/RunningRouter/RunningRouter.swift b/Runnect-iOS/Runnect-iOS/Network/Router/RunningRouter/RunningRouter.swift index 409b78bc..a43e73b0 100644 --- a/Runnect-iOS/Runnect-iOS/Network/Router/RunningRouter/RunningRouter.swift +++ b/Runnect-iOS/Runnect-iOS/Network/Router/RunningRouter/RunningRouter.swift @@ -47,7 +47,7 @@ extension RunningRouter: TargetType { } } - var headers: [String : String]? { + var headers: [String: String]? { switch self { case .recordRunning: return Config.headerWithDeviceId From afc853734c4ea3f60108a72e83a9c56f36d6d96b Mon Sep 17 00:00:00 2001 From: Sejin Lee Date: Tue, 10 Jan 2023 18:39:25 +0900 Subject: [PATCH 2/2] =?UTF-8?q?[Feat]=20#69=20-=20=EB=B3=B4=EA=B4=80?= =?UTF-8?q?=ED=95=A8=EC=9D=98=20=EB=82=B4=EA=B0=80=20=EA=B7=B8=EB=A6=B0=20?= =?UTF-8?q?=EC=BD=94=EC=8A=A4=20API=20=EC=97=B0=EA=B2=B0=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Router/CourseStorageRouter/.gitkeep | 0 .../CourseStorage/VC/CourseStorageVC.swift | 50 +++++++++++++++++++ .../Views/CVC/CourseListCVC.swift | 1 + .../PrivateCourseListView.swift | 12 ++++- 4 files changed, 62 insertions(+), 1 deletion(-) delete mode 100644 Runnect-iOS/Runnect-iOS/Network/Router/CourseStorageRouter/.gitkeep diff --git a/Runnect-iOS/Runnect-iOS/Network/Router/CourseStorageRouter/.gitkeep b/Runnect-iOS/Runnect-iOS/Network/Router/CourseStorageRouter/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift index cb33f09f..be78bf7d 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift @@ -8,12 +8,20 @@ import UIKit import Combine +import Moya + final class CourseStorageVC: UIViewController { // MARK: - Properties + private let courseStorageProvider = MoyaProvider( + plugins: [NetworkLoggerPlugin(verbose: true)] + ) + private let cancelBag = CancelBag() + private var privateCourseList = [PrivateCourse]() + // MARK: - UI Components private lazy var naviBar = CustomNavigationBar(self, type: .title).setTitle("보관함") @@ -33,11 +41,21 @@ final class CourseStorageVC: UIViewController { self.setLayout() self.bindUI() } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.getPrivateCourseList() + } } // MARK: - Methods extension CourseStorageVC { + private func setPrivateCourseData(courseList: [PrivateCourse]) { + self.privateCourseList = courseList + self.privateCourseListView.setData(courseList: courseList) + } + private func bindUI() { privateCourseListView.courseDrawButtonTapped.sink { [weak self] in guard let self = self else { return } @@ -86,3 +104,35 @@ extension CourseStorageVC { } } } + +// MARK: - Network + +extension CourseStorageVC { + private func getPrivateCourseList() { + LoadingIndicator.showLoading() + courseStorageProvider.request(.getAllPrivateCourse) { [weak self] response in + guard let self = self else { return } + LoadingIndicator.hideLoading() + switch response { + case .success(let result): + let status = result.statusCode + if 200..<300 ~= status { + do { + let responseDto = try result.map(BaseResponse.self) + guard let data = responseDto.data else { return } + self.setPrivateCourseData(courseList: data.courses) + } catch { + print(error.localizedDescription) + } + } + if status >= 400 { + print("400 error") + self.showNetworkFailureToast() + } + case .failure(let error): + print(error.localizedDescription) + self.showNetworkFailureToast() + } + } + } +} diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CVC/CourseListCVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CVC/CourseListCVC.swift index c8bf26cd..e1248df7 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CVC/CourseListCVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CVC/CourseListCVC.swift @@ -40,6 +40,7 @@ final class CourseListCVC: UICollectionViewCell { $0.backgroundColor = .g3 $0.contentMode = .scaleToFill $0.layer.cornerRadius = 5 + $0.clipsToBounds = true } private let titleLabel = UILabel().then { diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CourseListView/PrivateCourseListView.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CourseListView/PrivateCourseListView.swift index c3448020..1a29f45d 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CourseListView/PrivateCourseListView.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CourseListView/PrivateCourseListView.swift @@ -15,6 +15,8 @@ final class PrivateCourseListView: UIView { var courseDrawButtonTapped = PassthroughSubject() var cellDidTapped = PassthroughSubject() + private var courseList = [PrivateCourse]() + final let collectionViewInset = UIEdgeInsets(top: 28, left: 16, bottom: 28, right: 16) final let itemSpacing: CGFloat = 10 final let lineSpacing: CGFloat = 20 @@ -53,6 +55,11 @@ final class PrivateCourseListView: UIView { // MARK: - Methods extension PrivateCourseListView { + func setData(courseList: [PrivateCourse]) { + self.courseList = courseList + self.courseListCollectionView.reloadData() + } + private func setDelegate() { courseListCollectionView.delegate = self courseListCollectionView.dataSource = self @@ -94,7 +101,7 @@ extension PrivateCourseListView { extension PrivateCourseListView: UICollectionViewDelegate, UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return 15 + return courseList.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { @@ -102,6 +109,9 @@ extension PrivateCourseListView: UICollectionViewDelegate, UICollectionViewDataS for: indexPath) as? CourseListCVC else { return UICollectionViewCell() } cell.setCellType(type: .title) + let model = courseList[indexPath.item] + let cellTitle = "\(model.departure.region) \(model.departure.city)" + cell.setData(imageURL: model.image, title: cellTitle, location: nil, didLike: nil) return cell } }