From 075c8581edaa3448f070d95c23f8bb5a9acbe5ae Mon Sep 17 00:00:00 2001 From: yeonwoo Date: Wed, 11 Jan 2023 12:01:14 +0900 Subject: [PATCH] =?UTF-8?q?[Feat]=20#76=20-=20CourseSearchAPI=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Runnect-iOS.xcodeproj/project.pbxproj | 17 +++-- .../CourseDiscoveryRouter.swift | 1 - .../CourseSearchingRouter.swift | 51 +++++++++++++++ .../Views/VC/CourseSearchVC.swift | 63 +++++++++++++++++-- 4 files changed, 121 insertions(+), 11 deletions(-) create mode 100644 Runnect-iOS/Runnect-iOS/Network/Router/CourseDiscoveryRouter/CourseSearchingRouter.swift diff --git a/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj b/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj index 776fde5a..727e68be 100644 --- a/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj +++ b/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj @@ -130,6 +130,7 @@ 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 */; }; + DA97A02F296DC3300086760E /* CourseSearchingRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA97A02E296DC3300086760E /* CourseSearchingRouter.swift */; }; DAD5A3D8296C6D9600C8166B /* AdImageCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAD5A3D7296C6D9600C8166B /* AdImageCollectionViewCell.swift */; }; DAD5A3DA296C6DA500C8166B /* TitleCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAD5A3D9296C6DA500C8166B /* TitleCollectionViewCell.swift */; }; DAD5A3DC296C6DB800C8166B /* MapCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAD5A3DB296C6DB800C8166B /* MapCollectionViewCell.swift */; }; @@ -158,13 +159,8 @@ 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 = ""; }; - CE10063F29680C9800FD31FB /* .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 = ""; }; CE10064D29680D2500FD31FB /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = ""; }; @@ -286,6 +282,7 @@ 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 = ""; }; + DA97A02E296DC3300086760E /* CourseSearchingRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseSearchingRouter.swift; sourceTree = ""; }; DAD5A3D7296C6D9600C8166B /* AdImageCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdImageCollectionViewCell.swift; sourceTree = ""; }; DAD5A3D9296C6DA500C8166B /* TitleCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleCollectionViewCell.swift; sourceTree = ""; }; DAD5A3DB296C6DB800C8166B /* MapCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapCollectionViewCell.swift; sourceTree = ""; }; @@ -418,6 +415,7 @@ CE10063529680C0F00FD31FB /* CourseDiscoveryDto */ = { isa = PBXGroup; children = ( + DA97A029296DC2020086760E /* RequestDto */, DAD5A3E0296D4C2A00C8166B /* ResponseDto */, ); path = CourseDiscoveryDto; @@ -734,6 +732,7 @@ isa = PBXGroup; children = ( DAD5A3E3296D526D00C8166B /* CourseDiscoveryRouter.swift */, + DA97A02E296DC3300086760E /* CourseSearchingRouter.swift */, ); path = CourseDiscoveryRouter; sourceTree = ""; @@ -1133,6 +1132,13 @@ path = VC; sourceTree = ""; }; + DA97A029296DC2020086760E /* RequestDto */ = { + isa = PBXGroup; + children = ( + ); + path = RequestDto; + sourceTree = ""; + }; DAD5A3E0296D4C2A00C8166B /* ResponseDto */ = { isa = PBXGroup; children = ( @@ -1316,6 +1322,7 @@ DAD5A3E4296D526D00C8166B /* CourseDiscoveryRouter.swift in Sources */, CEEC6B3E2961C53700D00E1E /* CourseDiscoveryVC.swift in Sources */, CE6655E0295D87D200C64E12 /* UIDevice+.swift in Sources */, + DA97A02F296DC3300086760E /* CourseSearchingRouter.swift in Sources */, CE40BB242968068E0030ABCA /* Config.swift in Sources */, CE17F0382961BF8B00E1DED0 /* FontLiterals.swift in Sources */, CE6655E8295D889600C64E12 /* UISwitch+.swift in Sources */, diff --git a/Runnect-iOS/Runnect-iOS/Network/Router/CourseDiscoveryRouter/CourseDiscoveryRouter.swift b/Runnect-iOS/Runnect-iOS/Network/Router/CourseDiscoveryRouter/CourseDiscoveryRouter.swift index 8d09ed2d..7992ab49 100644 --- a/Runnect-iOS/Runnect-iOS/Network/Router/CourseDiscoveryRouter/CourseDiscoveryRouter.swift +++ b/Runnect-iOS/Runnect-iOS/Network/Router/CourseDiscoveryRouter/CourseDiscoveryRouter.swift @@ -18,7 +18,6 @@ extension pickedMapListRouter: TargetType { guard let url = URL(string: Config.baseURL) else { fatalError("baseURL could not be configured") } - return url } diff --git a/Runnect-iOS/Runnect-iOS/Network/Router/CourseDiscoveryRouter/CourseSearchingRouter.swift b/Runnect-iOS/Runnect-iOS/Network/Router/CourseDiscoveryRouter/CourseSearchingRouter.swift new file mode 100644 index 00000000..da06fafa --- /dev/null +++ b/Runnect-iOS/Runnect-iOS/Network/Router/CourseDiscoveryRouter/CourseSearchingRouter.swift @@ -0,0 +1,51 @@ +// +// CourseSearchingRouter.swift +// Runnect-iOS +// +// Created by YEONOO on 2023/01/11. +// + +import Foundation + +import Moya + +enum CourseSearchingRouter { + case getCourseData(keyword: String) +} + +extension CourseSearchingRouter: 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 .getCourseData: + return "/public-course/search" + } + } + + var method: Moya.Method { + switch self { + case .getCourseData: + return .get + } + } + + var task: Moya.Task { + switch self { + case .getCourseData(let keyword): + return .requestParameters(parameters: ["keyword": keyword], encoding: URLEncoding.default) + } + } + + var headers: [String: String]? { + switch self { + case .getCourseData: + return Config.headerWithDeviceId + } + } +} diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseSearchVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseSearchVC.swift index d7879563..96e0dc3c 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseSearchVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseSearchVC.swift @@ -9,9 +9,17 @@ import UIKit import Then import SnapKit +import Moya final class CourseSearchVC: UIViewController { + // MARK: - Properties + + private let CourseSearchingRouter = MoyaProvider( + plugins: [NetworkLoggerPlugin(verbose: true)]) + + private var courseList = [PublicCourse]() + // MARK: - UI Components private lazy var naviBar = CustomNavigationBar(self, type: .search).setTextFieldPlaceholder(placeholder: "지역과 키워드 위주로 검색해보세요").showKeyboard() @@ -62,7 +70,7 @@ final class CourseSearchVC: UIViewController { setDelegate() layout() setTabBar() - + } } // MARK: - Methods @@ -70,6 +78,7 @@ final class CourseSearchVC: UIViewController { extension CourseSearchVC { private func setDelegate() { + self.naviBar.delegate = self self.mapCollectionView.delegate = self self.mapCollectionView.dataSource = self } @@ -79,7 +88,11 @@ extension CourseSearchVC { } private func setTabBar() { - self.tabBarController?.tabBar.isHidden = true + self.tabBarController?.tabBar.isHidden = true + } + private func setData(data: [PublicCourse]) { + self.courseList = data + mapCollectionView.reloadData() } } @@ -116,14 +129,17 @@ extension CourseSearchVC { extension CourseSearchVC: UICollectionViewDelegate, UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return 15 - } - + return courseList.count + } + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CourseListCVC.className, for: indexPath) as? CourseListCVC else { return UICollectionViewCell() } cell.setCellType(type: .all) + let model = self.courseList[indexPath.item] + let location = "\(model.departure.region) \(model.departure.city)" + cell.setData(imageURL: model.image, title: model.title, location: location, didLike: model.scarp) return cell } } @@ -153,3 +169,40 @@ extension CourseSearchVC: UICollectionViewDelegateFlowLayout { self.naviBar.hideKeyboard() } } +// MARK: - CustomNavigationBarDelegate + +extension CourseSearchVC: CustomNavigationBarDelegate { + func searchButtonDidTap(text: String) { + searchCourseWithKeyword(keyword: text) + } +} +// MARK: - Network + +extension CourseSearchVC { + private func searchCourseWithKeyword(keyword: String) { + LoadingIndicator.showLoading() + CourseSearchingRouter.request(.getCourseData(keyword: keyword)) { response in + 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.setData(data: data.publicCourses) + } catch { + print(error.localizedDescription) + } + } + if status >= 400 { + print("400 error") + self.showNetworkFailureToast() + } + case .failure(let error): + print(error.localizedDescription) + self.showNetworkFailureToast() + } + } + } +}