diff --git a/Runnect-iOS/Podfile.lock b/Runnect-iOS/Podfile.lock index 327732e9..49d75367 100644 --- a/Runnect-iOS/Podfile.lock +++ b/Runnect-iOS/Podfile.lock @@ -118,4 +118,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: a1846e0d9fa164fc8d0a63bb343a6b7ba18187b9 -COCOAPODS: 1.12.1 +COCOAPODS: 1.14.3 diff --git a/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj b/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj index a2fd75f3..1665cf01 100644 --- a/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj +++ b/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj @@ -21,6 +21,7 @@ 7136BF8A2AF921A900679364 /* CustomBottomSheetVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7136BF892AF921A900679364 /* CustomBottomSheetVC.swift */; }; 713A98F02B29DD9900189B3C /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 713A98EF2B29DD9900189B3C /* GoogleService-Info.plist */; }; 717916DA2B13613B009CEF97 /* MarathonListResponseDto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 717916D92B13613B009CEF97 /* MarathonListResponseDto.swift */; }; + 71802C5C2B3364C2008DBCEE /* CourseDetailScrapCountDto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71802C5B2B3364C2008DBCEE /* CourseDetailScrapCountDto.swift */; }; 71BAD06A2B24CECC0061E31D /* UserProfileDto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71BAD0692B24CECC0061E31D /* UserProfileDto.swift */; }; 71BAD06C2B24D1F70061E31D /* UserProfileVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71BAD06B2B24D1F70061E31D /* UserProfileVC.swift */; }; 71F7804E2B0893B600B53253 /* MarathonTitleCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71F7804D2B0893B600B53253 /* MarathonTitleCollectionViewCell.swift */; }; @@ -191,6 +192,7 @@ 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 = ""; }; 717916D92B13613B009CEF97 /* MarathonListResponseDto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarathonListResponseDto.swift; sourceTree = ""; }; + 71802C5B2B3364C2008DBCEE /* CourseDetailScrapCountDto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseDetailScrapCountDto.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 = ""; }; 71F7804D2B0893B600B53253 /* MarathonTitleCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarathonTitleCollectionViewCell.swift; sourceTree = ""; }; @@ -868,6 +870,7 @@ isa = PBXGroup; children = ( CE4942AC296FCD2300736701 /* UploadedCourseDetailResponseDto.swift */, + 71802C5B2B3364C2008DBCEE /* CourseDetailScrapCountDto.swift */, ); path = ResponseDto; sourceTree = ""; @@ -1538,6 +1541,7 @@ CEB8416E2962C45300BF8080 /* LocationSearchResultTVC.swift in Sources */, CE102C4829DB1D6B00E23E69 /* GetNewTokenResponseDto.swift in Sources */, CE6655CA295D84DD00C64E12 /* UserDefaultKeyList.swift in Sources */, + 71802C5C2B3364C2008DBCEE /* CourseDetailScrapCountDto.swift in Sources */, 712F661D2A7B7BAB00D9539B /* Config.swift in Sources */, 23EE06CB2AC2AF3E00CB3FF8 /* KakaoAddressSearchingResponseDto.swift in Sources */, CE6655F2295D894D00C64E12 /* UIView+.swift in Sources */, diff --git a/Runnect-iOS/Runnect-iOS/Network/Dto/CourseDetailDto/ResponseDto/CourseDetailScrapCountDto.swift b/Runnect-iOS/Runnect-iOS/Network/Dto/CourseDetailDto/ResponseDto/CourseDetailScrapCountDto.swift new file mode 100644 index 00000000..25950623 --- /dev/null +++ b/Runnect-iOS/Runnect-iOS/Network/Dto/CourseDetailDto/ResponseDto/CourseDetailScrapCountDto.swift @@ -0,0 +1,13 @@ +// +// CourseDetailScrapCountDto.swift +// Runnect-iOS +// +// Created by 이명진 on 12/21/23. +// + +import Foundation + + +struct CourseDetailScrapCountDto: Codable { + let scrapCount: 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..9bad78c5 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseDetail/VC/CourseDetailVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDetail/VC/CourseDetailVC.swift @@ -23,16 +23,14 @@ final class CourseDetailVC: UIViewController { // MARK: - Properties - weak var delegate: ScrapStateDelegate? + weak var delegate: ScrapStateDelegate? // 코스 발견 스크랩 이벤트 + weak var marathonDelegate: MarathonScrapStateDelegate? // 마라톤 스크랩 이벤트 private let scrapProvider = Providers.scrapProvider - - private let PublicCourseProvider = Providers.publicCourseProvider - + private let publicCourseProvider = Providers.publicCourseProvider private let courseProvider = Providers.courseProvider private var courseModel: Course? - private var uploadedCourseDetailModel: UploadedCourseDetailResponseDto? private var courseId: Int? @@ -167,12 +165,9 @@ extension CourseDetailVC { guard let publicCourseId = publicCourseId else { return } scrapCourse(scrapTF: !sender.isSelected) - delegate?.didUpdateScrapState(publicCourseId: publicCourseId, isScrapped: !sender.isSelected) /// UI Update 부분 + delegate?.didUpdateScrapState(publicCourseId: publicCourseId, isScrapped: !sender.isSelected) /// 코스 발견 UI Update 부분 + marathonDelegate?.didUpdateMarathonScrapState(publicCourseId: publicCourseId, isScrapped: !sender.isSelected) // 마라톤 코스 UI Update 부분 - /// 누른상태(true)에서 누르면 스크랩 취소(false) 하는 이벤트, 즉 -1 - let toggle = sender.isSelected ? -1 : 1 - self.scrapCount += toggle - self.scrapCountLabel.text = "\(self.scrapCount)" /// print("CourseDetailVC 스크랩 탭🔥publicCourseId=\(publicCourseId), isScrapped은 \(!sender.isSelected) 요렇게 변경 ") } @@ -509,7 +504,7 @@ extension CourseDetailVC { private func getUploadedCourseDetail() { guard let publicCourseId = self.publicCourseId else { return } LoadingIndicator.showLoading() - PublicCourseProvider.request(.getUploadedCourseDetail(publicCourseId: publicCourseId)) { [weak self] response in + publicCourseProvider.request(.getUploadedCourseDetail(publicCourseId: publicCourseId)) { [weak self] response in guard let self = self else { return } LoadingIndicator.hideLoading() switch response { @@ -575,7 +570,15 @@ extension CourseDetailVC { case .success(let result): let status = result.statusCode if 200..<300 ~= status { - self.likeButton.isSelected.toggle() + do { + let responseDto = try result.map(BaseResponse.self) + guard let data = responseDto.data else { return } + self.likeButton.isSelected.toggle() + self.scrapCount = data.scrapCount + self.scrapCountLabel.text = "\(self.scrapCount)" + } catch { + print(error.localizedDescription) + } } if status >= 400 { print("400 error") diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/MarathonMapCollectionViewCell.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/MarathonMapCollectionViewCell.swift index cb43eb5a..e67307e3 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/MarathonMapCollectionViewCell.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/MarathonMapCollectionViewCell.swift @@ -8,6 +8,10 @@ import UIKit import Combine +protocol MarathonScrapStateDelegate: AnyObject { + func didUpdateMarathonScrapState(publicCourseId: Int, isScrapped: Bool) +} + class CourseSelectionPublisher { static let shared = CourseSelectionPublisher() @@ -68,6 +72,15 @@ extension MarathonMapCollectionViewCell { marathonCollectionView.register(CourseListCVC.self, forCellWithReuseIdentifier: CourseListCVC.className) } + + private func marathonReloadCellForCourse(publicCourseId: Int) { + print("✅ 2. \(publicCourseId)번 부분이 교체가 되는가") + if let index = marathonCourseList.firstIndex(where: { $0.id == publicCourseId }) { + let indexPath = IndexPath(item: index, section: 0) + marathonCollectionView.reloadItems(at: [indexPath]) + print("✅ 3. \(indexPath) 마라톤 부분 스크랩 교체 되었음 \n reloadItems까지는 작동은 했음 여기서 안되면 코드가 잘 못 된것.") + } + } } // MARK: - Layout Helpers @@ -146,10 +159,22 @@ extension MarathonMapCollectionViewCell: CourseListCVCDeleagte { let publicCourseId = self.marathonCourseList[index].id self.scrapCourse(publicCourseId: publicCourseId, scrapTF: wantsTolike) + print("마라톤에 들어온 index = \(index)") } } +extension MarathonMapCollectionViewCell: MarathonScrapStateDelegate { + func didUpdateMarathonScrapState(publicCourseId: Int, isScrapped: Bool) { + print("✅ 1. 마라톤 델리게이트 들어오는가 🫶🏻") + if let index = marathonCourseList.firstIndex(where: { $0.id == publicCourseId }) { + marathonCourseList[index].scrap = isScrapped + marathonReloadCellForCourse(publicCourseId: publicCourseId) + print("✅ 4. ‼️MarathonMapCollectionViewCell에서 작업 완료") + } + } +} + // MARK: - NetWork extension MarathonMapCollectionViewCell { 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..874b132f 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseDiscoveryVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseDiscoveryVC.swift @@ -339,6 +339,7 @@ extension CourseDiscoveryVC: UICollectionViewDelegateFlowLayout { if let marathonCell = mapCollectionView.cellForItem(at: IndexPath(item: 0, section: Section.marathonCourseList)) as? MarathonMapCollectionViewCell { let marathonCourseList = marathonCell.marathonCourseList let courseDetailVC = CourseDetailVC() + courseDetailVC.marathonDelegate = marathonCell let courseModel = marathonCourseList[indexPath.item] courseDetailVC.setCourseId(courseId: courseModel.courseId, publicCourseId: courseModel.id) courseDetailVC.hidesBottomBarWhenPushed = true