diff --git a/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj b/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj index a2fd75f3..2009a986 100644 --- a/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj +++ b/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj @@ -20,6 +20,7 @@ 712F661D2A7B7BAB00D9539B /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = 712F661C2A7B7BAB00D9539B /* Config.swift */; }; 7136BF8A2AF921A900679364 /* CustomBottomSheetVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7136BF892AF921A900679364 /* CustomBottomSheetVC.swift */; }; 713A98F02B29DD9900189B3C /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 713A98EF2B29DD9900189B3C /* GoogleService-Info.plist */; }; + 715D36E82B2CC64000CAA9D6 /* MyUploadedCourseResponseDto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 715D36E72B2CC64000CAA9D6 /* MyUploadedCourseResponseDto.swift */; }; 717916DA2B13613B009CEF97 /* MarathonListResponseDto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 717916D92B13613B009CEF97 /* MarathonListResponseDto.swift */; }; 71BAD06A2B24CECC0061E31D /* UserProfileDto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71BAD0692B24CECC0061E31D /* UserProfileDto.swift */; }; 71BAD06C2B24D1F70061E31D /* UserProfileVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71BAD06B2B24D1F70061E31D /* UserProfileVC.swift */; }; @@ -190,6 +191,7 @@ 712F661C2A7B7BAB00D9539B /* Config.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Config.swift; sourceTree = ""; }; 7136BF892AF921A900679364 /* CustomBottomSheetVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomBottomSheetVC.swift; sourceTree = ""; }; 713A98EF2B29DD9900189B3C /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; + 715D36E72B2CC64000CAA9D6 /* MyUploadedCourseResponseDto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyUploadedCourseResponseDto.swift; sourceTree = ""; }; 717916D92B13613B009CEF97 /* MarathonListResponseDto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarathonListResponseDto.swift; sourceTree = ""; }; 71BAD0692B24CECC0061E31D /* UserProfileDto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileDto.swift; sourceTree = ""; }; 71BAD06B2B24D1F70061E31D /* UserProfileVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileVC.swift; sourceTree = ""; }; @@ -523,6 +525,7 @@ A3305A96296EF58C000B1A10 /* GoalRewardInfoDto.swift */, CEFA9A2E29FC263700F2D0CF /* UserDeleteResponseDto.swift */, 71BAD0692B24CECC0061E31D /* UserProfileDto.swift */, + 715D36E72B2CC64000CAA9D6 /* MyUploadedCourseResponseDto.swift */, ); path = MyPageDto; sourceTree = ""; @@ -1392,6 +1395,7 @@ buildActionMask = 2147483647; files = ( CE40BB20296805F70030ABCA /* NetworkResult.swift in Sources */, + 715D36E82B2CC64000CAA9D6 /* MyUploadedCourseResponseDto.swift in Sources */, CE55BC11296D4EA600E8CD69 /* RunningRecordRequestDto.swift in Sources */, CE665604295D91B100C64E12 /* makeAlert.swift in Sources */, A3BC2F2F2962C40A00198261 /* UploadedCourseInfoVC.swift in Sources */, diff --git a/Runnect-iOS/Runnect-iOS/Network/Dto/CourseStorageDto/ResponseDto/PrivateCourseNotUploadedResponseDto.swift b/Runnect-iOS/Runnect-iOS/Network/Dto/CourseStorageDto/ResponseDto/PrivateCourseNotUploadedResponseDto.swift index 898a21f0..d90058bc 100644 --- a/Runnect-iOS/Runnect-iOS/Network/Dto/CourseStorageDto/ResponseDto/PrivateCourseNotUploadedResponseDto.swift +++ b/Runnect-iOS/Runnect-iOS/Network/Dto/CourseStorageDto/ResponseDto/PrivateCourseNotUploadedResponseDto.swift @@ -8,5 +8,5 @@ import Foundation struct PrivateCourseNotUploadedResponseDto: Codable { - let privateCourses: [Course] + let courses: [Course] } diff --git a/Runnect-iOS/Runnect-iOS/Network/Dto/MyPageDto/MyUploadedCourseResponseDto.swift b/Runnect-iOS/Runnect-iOS/Network/Dto/MyPageDto/MyUploadedCourseResponseDto.swift new file mode 100644 index 00000000..cf0ae390 --- /dev/null +++ b/Runnect-iOS/Runnect-iOS/Network/Dto/MyPageDto/MyUploadedCourseResponseDto.swift @@ -0,0 +1,19 @@ +// +// MyUploadedCourseResponseDto.swift +// Runnect-iOS +// +// Created by 이명진 on 12/16/23. +// + +import Foundation + +// MARK: - MyUploadedCourseResponseDto +struct MyUploadedCourseResponseDto: Codable { + let user: MyPage + let publicCourses: [PublicCourse] +} + +// MARK: - MyPage +struct MyPage: Codable { + let id: Int +} diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseDetail/VC/CourseDetailVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseDetail/VC/CourseDetailVC.swift index 2ab37a45..7975f74e 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseDetail/VC/CourseDetailVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDetail/VC/CourseDetailVC.swift @@ -601,11 +601,11 @@ extension CourseDetailVC { print("리절트", result) let status = result.statusCode if 200..<300 ~= status { - print("삭제 성공") - DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + delegate?.didRemoveCourse(publicCourseId: courseId) + print("코스 \(courseId) 번 삭제 성공") + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { self.navigationController?.popViewController(animated: true) } - delegate?.didRemoveCourse(publicCourseId: courseId) } if status >= 400 { print("400 error") diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseDiscoveryVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseDiscoveryVC.swift index 9aff9953..f76e0a5c 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseDiscoveryVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseDiscoveryVC.swift @@ -17,6 +17,11 @@ protocol ScrapStateDelegate: AnyObject { // 코스 상세 에서 스크랩 누르면 코스발견에 해당 부분 스크랩 누르는 이벤트 전달 } +protocol UploadSuccessDelegate: AnyObject { + // 코스 업로드시, 코스 발견 피드 새로 고침 + func didUploadSuccess() +} + final class CourseDiscoveryVC: UIViewController { // MARK: - Properties @@ -118,8 +123,8 @@ extension CourseDiscoveryVC { private func setAddTarget() { self.searchButton.addTarget(self, action: #selector(pushToSearchVC), for: .touchUpInside) - self.uploadButton.addTarget(self, action: #selector(pushToDiscoveryVC), for: .touchUpInside) - self.miniUploadButton.addTarget(self, action: #selector(pushToDiscoveryVC), for: .touchUpInside) + self.uploadButton.addTarget(self, action: #selector(pushToCourseSelectVC), for: .touchUpInside) + self.miniUploadButton.addTarget(self, action: #selector(pushToCourseSelectVC), for: .touchUpInside) } private func setCombineEvent() { @@ -137,6 +142,13 @@ extension CourseDiscoveryVC { print("\(indexPath) 부분 스크랩 교체 되었음") } } + + func refresh() { + print("✅ refresh ✅") + pageNo = 1 + self.courseList = [] + self.getCourseData(pageNo: pageNo) + } } // MARK: - @objc Function @@ -147,13 +159,14 @@ extension CourseDiscoveryVC { self.navigationController?.pushViewController(nextVC, animated: true) } - @objc private func pushToDiscoveryVC() { + @objc private func pushToCourseSelectVC() { guard UserManager.shared.userType != .visitor else { self.showToastOnWindow(text: "러넥트에 가입하면 코스를 업로드할 수 있어요.") return } let nextVC = MyCourseSelectVC() + nextVC.delegate = self self.navigationController?.pushViewController(nextVC, animated: true) } } @@ -275,6 +288,7 @@ extension CourseDiscoveryVC: UICollectionViewDelegate, UICollectionViewDataSourc } } + // 최신순, 스크랩순 막 연달아 누르면 앱 터짐.. private func courseListCell(collectionView: UICollectionView, indexPath: IndexPath) -> UICollectionViewCell { guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CourseListCVC.className, for: indexPath) as? CourseListCVC else { return UICollectionViewCell() } cell.setCellType(type: .all) @@ -436,11 +450,26 @@ extension CourseDiscoveryVC: ScrapStateDelegate { } func didRemoveCourse(publicCourseId: Int) { - if let index = courseList.firstIndex(where: { $0.id == publicCourseId }) { - self.courseList.remove(at: index) - self.mapCollectionView.reloadData() - print("didRemoveCourse= 삭제되었음\n") - } +// if let index = courseList.firstIndex(where: { $0.id == publicCourseId }) { +// courseList.remove(at: index) +// self.mapCollectionView.reloadData() +// } + // ⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️ + // 원래 해당하는 데이터(index) 만 가지고, 그 데이터 삭제 후 courseList를 받아야하는데, 삭제가 이미되어버려서 if let index 부분이 안들어옴 + // 왜??? 이미 데이터는 삭제가 되어서 $0.id 랑 publicCourseId 가 같은게 매치가 될 수 없어!!! + // 네트워크 성공하기 전에 didRemoveCourse(publicCourseId:) 를 호출 해야 해당 부분 확인하고 지운다음, 서버측에서 지워야 1페이지부터 시작 안하고 지울 수 있음 + // ⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️ + self.refresh() + } +} + +// MARK: - didUploadCourse + +extension CourseDiscoveryVC: UploadSuccessDelegate { + func didUploadSuccess() { + print("여기서 didUploadSuccess 함수 호출\n MyCourseSelectVC -> CourseDiscoveryVC 이벤트 전달") + self.refresh() + print("코스 발견 피드 새로고침 완료 되었음") } } diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseUploadVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseUploadVC.swift index ab274d81..b655f479 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseUploadVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseUploadVC.swift @@ -19,6 +19,8 @@ class CourseUploadVC: UIViewController { private var courseModel: Course? private let courseTitleMaxLength = 20 + weak var delegate: UploadStateDelegate? + // MARK: - UI Components private lazy var navibar = CustomNavigationBar(self, type: .titleWithLeftButton).setTitle("코스 업로드") @@ -332,7 +334,11 @@ extension CourseUploadVC { case .success(let result): let status = result.statusCode if 200..<300 ~= status { - self.navigationController?.popToRootViewController(animated: true) + delegate?.didUploadCourse() + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + self.navigationController?.popToRootViewController(animated: true) + } + // uploadCourse 업로드 성공하면, 코스발견 CVC 맨 위에 데이터 추가 } if status >= 400 { print("400 error") diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/MyCourseSelectVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/MyCourseSelectVC.swift index def8d8dc..0e4b97c9 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/MyCourseSelectVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/MyCourseSelectVC.swift @@ -10,6 +10,10 @@ import UIKit import Then import Moya +protocol UploadStateDelegate: AnyObject { + func didUploadCourse() +} + class MyCourseSelectVC: UIViewController { // MARK: - Properties @@ -26,6 +30,8 @@ class MyCourseSelectVC: UIViewController { } } + weak var delegate: UploadSuccessDelegate? + // MARK: - UI Components private lazy var navibar = CustomNavigationBar(self, type: .titleWithLeftButton).setTitle("불러오기") @@ -116,11 +122,19 @@ extension MyCourseSelectVC { @objc private func pushToUploadVC() { guard let selectedIndex = self.selectedIndex else { return } let courseUploadVC = CourseUploadVC() + courseUploadVC.delegate = self // 이 부분이 중요합니다. courseUploadVC.setData(courseModel: courseList[selectedIndex]) self.navigationController?.pushViewController(courseUploadVC, animated: true) } } +extension MyCourseSelectVC: UploadStateDelegate { + func didUploadCourse() { + print("여기 한번 거치고\n CourseUploadVC -> MyCourseSelectVC 이벤트 전달\n") + delegate?.didUploadSuccess() + } +} + // MARK: - UI & Layout extension MyCourseSelectVC { @@ -269,7 +283,7 @@ extension MyCourseSelectVC { do { let responseDto = try result.map(BaseResponse.self) guard let data = responseDto.data else { return } - self.setData(courseList: data.privateCourses) + self.setData(courseList: data.courses) } catch { print(error.localizedDescription) } diff --git a/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/InfoVC/UploadedCourseInfoVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/InfoVC/UploadedCourseInfoVC.swift index 7e43cf96..efe99f1c 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/InfoVC/UploadedCourseInfoVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/InfoVC/UploadedCourseInfoVC.swift @@ -340,7 +340,7 @@ extension UploadedCourseInfoVC { let status = result.statusCode if 200..<300 ~= status { do { - let responseDto = try result.map(BaseResponse.self) + let responseDto = try result.map(BaseResponse.self) guard let data = responseDto.data else { return } self.setData(courseList: data.publicCourses) UploadedCourseInfoCollectionView.reloadData()