Skip to content

Commit 81572b3

Browse files
authored
Merge pull request #70 from lsj8706/feat/#69-보관함-내가그린코스-API
[Feat] #69 - 보관함 내가 그린 코스 API 연결
2 parents 9f28dcc + afc8537 commit 81572b3

File tree

9 files changed

+163
-6
lines changed

9 files changed

+163
-6
lines changed

Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
CE5875A4296015D2005D967E /* Encodable+.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5875A3296015D2005D967E /* Encodable+.swift */; };
6363
CE591E9C296D4F69000FCBB3 /* RunningRecordResonseDto.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE591E9B296D4F69000FCBB3 /* RunningRecordResonseDto.swift */; };
6464
CE591E9E296D5140000FCBB3 /* RunningRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE591E9D296D5140000FCBB3 /* RunningRouter.swift */; };
65+
CE591EA1296D5EB5000FCBB3 /* PrivateCourseResponseDto.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE591EA0296D5EB5000FCBB3 /* PrivateCourseResponseDto.swift */; };
6566
CE6655BF295D82E200C64E12 /* .gitkeep in Resources */ = {isa = PBXBuildFile; fileRef = CE6655BE295D82E200C64E12 /* .gitkeep */; };
6667
CE6655C8295D849F00C64E12 /* StringLiterals.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6655C7295D849F00C64E12 /* StringLiterals.swift */; };
6768
CE6655CA295D84DD00C64E12 /* UserDefaultKeyList.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6655C9295D84DD00C64E12 /* UserDefaultKeyList.swift */; };
@@ -123,6 +124,7 @@
123124
CEEC6B402961C55000D00E1E /* MyPageVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEEC6B3F2961C55000D00E1E /* MyPageVC.swift */; };
124125
CEEC6B492961C5E200D00E1E /* SplashVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEEC6B482961C5E200D00E1E /* SplashVC.swift */; };
125126
CEEC6B4B2961D89700D00E1E /* CustomNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEEC6B4A2961D89700D00E1E /* CustomNavigationBar.swift */; };
127+
CEF3CD98296D63B9002723A1 /* CourseStorageRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEF3CD97296D63B9002723A1 /* CourseStorageRouter.swift */; };
126128
DA20D847296697A600F1581F /* MyCourseSelectVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA20D846296697A600F1581F /* MyCourseSelectVC.swift */; };
127129
DA20D849296697B400F1581F /* CourseUploadVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA20D848296697B400F1581F /* CourseUploadVC.swift */; };
128130
DA20D84E2966A9B300F1581F /* CourseSearchVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA20D84D2966A9B300F1581F /* CourseSearchVC.swift */; };
@@ -150,11 +152,9 @@
150152
CE0C23782966D6AF00B45063 /* ViewPager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewPager.swift; sourceTree = "<group>"; };
151153
CE0D9FD229648DA300CEB5CD /* CustomAlertVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomAlertVC.swift; sourceTree = "<group>"; };
152154
CE10063929680C5700FD31FB /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
153-
CE10063B29680C6800FD31FB /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
154155
CE10063C29680C7000FD31FB /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
155156
CE10063D29680C8100FD31FB /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
156157
CE10063E29680C8800FD31FB /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
157-
CE10064129680CA700FD31FB /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
158158
CE10064229680CAD00FD31FB /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
159159
CE10064329680CB400FD31FB /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
160160
CE10064429680CBC00FD31FB /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
@@ -204,6 +204,7 @@
204204
CE5875A3296015D2005D967E /* Encodable+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Encodable+.swift"; sourceTree = "<group>"; };
205205
CE591E9B296D4F69000FCBB3 /* RunningRecordResonseDto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunningRecordResonseDto.swift; sourceTree = "<group>"; };
206206
CE591E9D296D5140000FCBB3 /* RunningRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunningRouter.swift; sourceTree = "<group>"; };
207+
CE591EA0296D5EB5000FCBB3 /* PrivateCourseResponseDto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivateCourseResponseDto.swift; sourceTree = "<group>"; };
207208
CE6655BE295D82E200C64E12 /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
208209
CE6655C0295D82F000C64E12 /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
209210
CE6655C1295D82F700C64E12 /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
@@ -272,6 +273,7 @@
272273
CEEC6B462961C5BB00D00E1E /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
273274
CEEC6B482961C5E200D00E1E /* SplashVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashVC.swift; sourceTree = "<group>"; };
274275
CEEC6B4A2961D89700D00E1E /* CustomNavigationBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomNavigationBar.swift; sourceTree = "<group>"; };
276+
CEF3CD97296D63B9002723A1 /* CourseStorageRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseStorageRouter.swift; sourceTree = "<group>"; };
275277
DA20D846296697A600F1581F /* MyCourseSelectVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyCourseSelectVC.swift; sourceTree = "<group>"; };
276278
DA20D848296697B400F1581F /* CourseUploadVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseUploadVC.swift; sourceTree = "<group>"; };
277279
DA20D84D2966A9B300F1581F /* CourseSearchVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseSearchVC.swift; sourceTree = "<group>"; };
@@ -412,7 +414,7 @@
412414
CE10063629680C1C00FD31FB /* CourseStorageDto */ = {
413415
isa = PBXGroup;
414416
children = (
415-
CE10063B29680C6800FD31FB /* .gitkeep */,
417+
CE591E9F296D5E0F000FCBB3 /* ResponseDto */,
416418
);
417419
path = CourseStorageDto;
418420
sourceTree = "<group>";
@@ -711,7 +713,7 @@
711713
CE40BB27296808290030ABCA /* CourseStorageRouter */ = {
712714
isa = PBXGroup;
713715
children = (
714-
CE10064129680CA700FD31FB /* .gitkeep */,
716+
CEF3CD97296D63B9002723A1 /* CourseStorageRouter.swift */,
715717
);
716718
path = CourseStorageRouter;
717719
sourceTree = "<group>";
@@ -805,6 +807,14 @@
805807
path = ResponseDto;
806808
sourceTree = "<group>";
807809
};
810+
CE591E9F296D5E0F000FCBB3 /* ResponseDto */ = {
811+
isa = PBXGroup;
812+
children = (
813+
CE591EA0296D5EB5000FCBB3 /* PrivateCourseResponseDto.swift */,
814+
);
815+
path = ResponseDto;
816+
sourceTree = "<group>";
817+
};
808818
CE6655A8295D7F7D00C64E12 /* Presentation */ = {
809819
isa = PBXGroup;
810820
children = (
@@ -1298,10 +1308,12 @@
12981308
CE6655F0295D891B00C64E12 /* UITextView+.swift in Sources */,
12991309
CEC2A6922962BE2900160BF7 /* DepartureSearchVC.swift in Sources */,
13001310
CE6655EE295D88E600C64E12 /* UITextField+.swift in Sources */,
1311+
CEF3CD98296D63B9002723A1 /* CourseStorageRouter.swift in Sources */,
13011312
CE40BB1C2967E4910030ABCA /* RunningWaitingVC.swift in Sources */,
13021313
CE6B63D6296731F9003F900F /* ScrapCourseListView.swift in Sources */,
13031314
CE6655F8295D90CF00C64E12 /* adjusted+.swift in Sources */,
13041315
CE4545CB295D7AF4003201E1 /* SceneDelegate.swift in Sources */,
1316+
CE591EA1296D5EB5000FCBB3 /* PrivateCourseResponseDto.swift in Sources */,
13051317
A3BC2F3F2964706100198261 /* UploadedCourseInfoCVC.swift in Sources */,
13061318
CE6655FE295D912300C64E12 /* calculateTopInset.swift in Sources */,
13071319
CEEC6B492961C5E200D00E1E /* SplashVC.swift in Sources */,

Runnect-iOS/Runnect-iOS/Network/Dto/CourseStorageDto/.gitkeep

Whitespace-only changes.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//
2+
// PrivateCourseResponseDto.swift
3+
// Runnect-iOS
4+
//
5+
// Created by sejin on 2023/01/10.
6+
//
7+
8+
import Foundation
9+
10+
// MARK: - PrivateCourseResponseDto
11+
12+
struct PrivateCourseResponseDto: Codable {
13+
let courses: [PrivateCourse]
14+
}
15+
16+
// MARK: - PrivateCourse
17+
18+
struct PrivateCourse: Codable {
19+
let id: Int
20+
let image, createdAt: String
21+
let distance: Float?
22+
let path: [[Double]]?
23+
let departure: PrivateCourseDeparture
24+
}
25+
26+
// MARK: - PrivateCourseDeparture
27+
28+
struct PrivateCourseDeparture: Codable {
29+
let region, city: String
30+
let town: String?
31+
let name: String?
32+
}

Runnect-iOS/Runnect-iOS/Network/Router/CourseStorageRouter/.gitkeep

Whitespace-only changes.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//
2+
// CourseStorageRouter.swift
3+
// Runnect-iOS
4+
//
5+
// Created by sejin on 2023/01/10.
6+
//
7+
8+
import Foundation
9+
10+
import Moya
11+
12+
enum CourseStorageRouter {
13+
case getAllPrivateCourse
14+
}
15+
16+
extension CourseStorageRouter: TargetType {
17+
var baseURL: URL {
18+
guard let url = URL(string: Config.baseURL) else {
19+
fatalError("baseURL could not be configured")
20+
}
21+
22+
return url
23+
}
24+
25+
var path: String {
26+
switch self {
27+
case .getAllPrivateCourse:
28+
return "/course/user"
29+
}
30+
}
31+
32+
var method: Moya.Method {
33+
switch self {
34+
case .getAllPrivateCourse:
35+
return .get
36+
}
37+
}
38+
39+
var task: Moya.Task {
40+
switch self {
41+
case .getAllPrivateCourse:
42+
return .requestPlain
43+
}
44+
}
45+
46+
var headers: [String: String]? {
47+
switch self {
48+
case .getAllPrivateCourse:
49+
return Config.headerWithDeviceId
50+
}
51+
}
52+
}

Runnect-iOS/Runnect-iOS/Network/Router/RunningRouter/RunningRouter.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ extension RunningRouter: TargetType {
4747
}
4848
}
4949

50-
var headers: [String : String]? {
50+
var headers: [String: String]? {
5151
switch self {
5252
case .recordRunning:
5353
return Config.headerWithDeviceId

Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,20 @@
88
import UIKit
99
import Combine
1010

11+
import Moya
12+
1113
final class CourseStorageVC: UIViewController {
1214

1315
// MARK: - Properties
1416

17+
private let courseStorageProvider = MoyaProvider<CourseStorageRouter>(
18+
plugins: [NetworkLoggerPlugin(verbose: true)]
19+
)
20+
1521
private let cancelBag = CancelBag()
1622

23+
private var privateCourseList = [PrivateCourse]()
24+
1725
// MARK: - UI Components
1826

1927
private lazy var naviBar = CustomNavigationBar(self, type: .title).setTitle("보관함")
@@ -33,11 +41,21 @@ final class CourseStorageVC: UIViewController {
3341
self.setLayout()
3442
self.bindUI()
3543
}
44+
45+
override func viewWillAppear(_ animated: Bool) {
46+
super.viewWillAppear(animated)
47+
self.getPrivateCourseList()
48+
}
3649
}
3750

3851
// MARK: - Methods
3952

4053
extension CourseStorageVC {
54+
private func setPrivateCourseData(courseList: [PrivateCourse]) {
55+
self.privateCourseList = courseList
56+
self.privateCourseListView.setData(courseList: courseList)
57+
}
58+
4159
private func bindUI() {
4260
privateCourseListView.courseDrawButtonTapped.sink { [weak self] in
4361
guard let self = self else { return }
@@ -86,3 +104,35 @@ extension CourseStorageVC {
86104
}
87105
}
88106
}
107+
108+
// MARK: - Network
109+
110+
extension CourseStorageVC {
111+
private func getPrivateCourseList() {
112+
LoadingIndicator.showLoading()
113+
courseStorageProvider.request(.getAllPrivateCourse) { [weak self] response in
114+
guard let self = self else { return }
115+
LoadingIndicator.hideLoading()
116+
switch response {
117+
case .success(let result):
118+
let status = result.statusCode
119+
if 200..<300 ~= status {
120+
do {
121+
let responseDto = try result.map(BaseResponse<PrivateCourseResponseDto>.self)
122+
guard let data = responseDto.data else { return }
123+
self.setPrivateCourseData(courseList: data.courses)
124+
} catch {
125+
print(error.localizedDescription)
126+
}
127+
}
128+
if status >= 400 {
129+
print("400 error")
130+
self.showNetworkFailureToast()
131+
}
132+
case .failure(let error):
133+
print(error.localizedDescription)
134+
self.showNetworkFailureToast()
135+
}
136+
}
137+
}
138+
}

Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CVC/CourseListCVC.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ final class CourseListCVC: UICollectionViewCell {
4040
$0.backgroundColor = .g3
4141
$0.contentMode = .scaleToFill
4242
$0.layer.cornerRadius = 5
43+
$0.clipsToBounds = true
4344
}
4445

4546
private let titleLabel = UILabel().then {

Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CourseListView/PrivateCourseListView.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ final class PrivateCourseListView: UIView {
1515
var courseDrawButtonTapped = PassthroughSubject<Void, Never>()
1616
var cellDidTapped = PassthroughSubject<Int, Never>()
1717

18+
private var courseList = [PrivateCourse]()
19+
1820
final let collectionViewInset = UIEdgeInsets(top: 28, left: 16, bottom: 28, right: 16)
1921
final let itemSpacing: CGFloat = 10
2022
final let lineSpacing: CGFloat = 20
@@ -53,6 +55,11 @@ final class PrivateCourseListView: UIView {
5355
// MARK: - Methods
5456

5557
extension PrivateCourseListView {
58+
func setData(courseList: [PrivateCourse]) {
59+
self.courseList = courseList
60+
self.courseListCollectionView.reloadData()
61+
}
62+
5663
private func setDelegate() {
5764
courseListCollectionView.delegate = self
5865
courseListCollectionView.dataSource = self
@@ -94,14 +101,17 @@ extension PrivateCourseListView {
94101

95102
extension PrivateCourseListView: UICollectionViewDelegate, UICollectionViewDataSource {
96103
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
97-
return 15
104+
return courseList.count
98105
}
99106

100107
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
101108
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CourseListCVC.className,
102109
for: indexPath)
103110
as? CourseListCVC else { return UICollectionViewCell() }
104111
cell.setCellType(type: .title)
112+
let model = courseList[indexPath.item]
113+
let cellTitle = "\(model.departure.region) \(model.departure.city)"
114+
cell.setData(imageURL: model.image, title: cellTitle, location: nil, didLike: nil)
105115
return cell
106116
}
107117
}

0 commit comments

Comments
 (0)