diff --git a/Segno/Segno.xcodeproj/project.pbxproj b/Segno/Segno.xcodeproj/project.pbxproj index 0cc55df..264962d 100644 --- a/Segno/Segno.xcodeproj/project.pbxproj +++ b/Segno/Segno.xcodeproj/project.pbxproj @@ -84,6 +84,9 @@ 9825F41D29377ACF005F2163 /* SettingsRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9825F41C29377ACF005F2163 /* SettingsRepository.swift */; }; 982A2A472924AE74006F6ACD /* UserDefaultsKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 982A2A462924AE74006F6ACD /* UserDefaultsKey.swift */; }; 982A3699292C905300FDC6CF /* DiaryDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 982A3698292C905300FDC6CF /* DiaryDetailViewController.swift */; }; + 982A4FBF2941F1CA005AEB1D /* NewDiaryDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 982A4FBE2941F1CA005AEB1D /* NewDiaryDetail.swift */; }; + 982A4FC12941F481005AEB1D /* NewDiaryPostEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 982A4FC02941F481005AEB1D /* NewDiaryPostEndpoint.swift */; }; + 982A4FC32941F580005AEB1D /* NewDiaryDetailDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 982A4FC22941F580005AEB1D /* NewDiaryDetailDTO.swift */; }; 982B3B7F292E68FB0077A44B /* DiaryDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 982B3B7E292E68FB0077A44B /* DiaryDetailViewModel.swift */; }; 9838443E29387C0A00BCCEE2 /* ChangeNicknameEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9838443D29387C0A00BCCEE2 /* ChangeNicknameEndpoint.swift */; }; 983AE9D22934F041006547BD /* NicknameCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 983AE9D12934F041006547BD /* NicknameCell.swift */; }; @@ -186,6 +189,9 @@ 9825F41C29377ACF005F2163 /* SettingsRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsRepository.swift; sourceTree = ""; }; 982A2A462924AE74006F6ACD /* UserDefaultsKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsKey.swift; sourceTree = ""; }; 982A3698292C905300FDC6CF /* DiaryDetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiaryDetailViewController.swift; sourceTree = ""; }; + 982A4FBE2941F1CA005AEB1D /* NewDiaryDetail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewDiaryDetail.swift; sourceTree = ""; }; + 982A4FC02941F481005AEB1D /* NewDiaryPostEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewDiaryPostEndpoint.swift; sourceTree = ""; }; + 982A4FC22941F580005AEB1D /* NewDiaryDetailDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewDiaryDetailDTO.swift; sourceTree = ""; }; 982B3B7E292E68FB0077A44B /* DiaryDetailViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiaryDetailViewModel.swift; sourceTree = ""; }; 9838443D29387C0A00BCCEE2 /* ChangeNicknameEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChangeNicknameEndpoint.swift; sourceTree = ""; }; 983AE9D12934F041006547BD /* NicknameCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NicknameCell.swift; sourceTree = ""; }; @@ -302,6 +308,7 @@ children = ( 4FEBFAAA291CF30E00E78139 /* DiaryListItem.swift */, 4FEBFAAC291CF62E00E78139 /* DiaryDetail.swift */, + 982A4FBE2941F1CA005AEB1D /* NewDiaryDetail.swift */, 4FEBFAAE291CF9F300E78139 /* MusicInfo.swift */, 4F6F74B0292C9BF3007E7AC1 /* UserInfo.swift */, 98FDF8A0292F56580083FA05 /* Location.swift */, @@ -466,6 +473,7 @@ 4FA324252923600C00DB04D5 /* DiaryListDTO.swift */, 4F4E0D73292521D0005ABA8F /* UserInfoDTO.swift */, 7940FB2E292E063100276EFC /* DiaryDetailDTO.swift */, + 982A4FC22941F580005AEB1D /* NewDiaryDetailDTO.swift */, 4F4E0D7A29252526005ABA8F /* TokenDTO.swift */, 66A8CF6A2937947A00C17F84 /* UserDetailDTO.swift */, 791529DB29332CF2005A8DDB /* ImageDTO.swift */, @@ -480,6 +488,7 @@ 4FA3242A2923646F00DB04D5 /* DiaryListItemEndpoint.swift */, 7940FB30292E065100276EFC /* DiaryDetailEndpoint.swift */, 791529DF293344E8005A8DDB /* DiaryPostEndpoint.swift */, + 982A4FC02941F481005AEB1D /* NewDiaryPostEndpoint.swift */, 79767E63293E2A1200E489DD /* DiaryDeleteEndpoint.swift */, 4F4E0D7529252236005ABA8F /* LoginEndpoint.swift */, 66A8CF6C29379A9900C17F84 /* UserDetailEndpoint.swift */, @@ -633,6 +642,7 @@ 9825F41D29377ACF005F2163 /* SettingsRepository.swift in Sources */, 66F0D7EE2925FF8B0074872E /* DiaryCell.swift in Sources */, 79767E64293E2A1200E489DD /* DiaryDeleteEndpoint.swift in Sources */, + 982A4FC32941F580005AEB1D /* NewDiaryDetailDTO.swift in Sources */, 4F307A482938832900FA36A0 /* MusicSession.swift in Sources */, 4F9A00202922337F007D9057 /* LoginViewController.swift in Sources */, 982A2A472924AE74006F6ACD /* UserDefaultsKey.swift in Sources */, @@ -648,6 +658,7 @@ 98003E0E293F20F6009FBC35 /* DarkModeManager.swift in Sources */, 66A8CF692937945300C17F84 /* UserDetailUseCase.swift in Sources */, 988414AE2922235B007C9132 /* LocalUtilityRepository.swift in Sources */, + 982A4FC12941F481005AEB1D /* NewDiaryPostEndpoint.swift in Sources */, 66A8CF612935F44100C17F84 /* MyPageViewModel.swift in Sources */, 98138D4D2940F53F00D2CEDF /* LocationUseCase.swift in Sources */, 988414D929235345007C9132 /* DiaryCollectionViewModel.swift in Sources */, @@ -707,6 +718,7 @@ 4F4E0D7629252236005ABA8F /* LoginEndpoint.swift in Sources */, 791529D82932F364005A8DDB /* DiaryEditUseCase.swift in Sources */, 4FA324262923600C00DB04D5 /* DiaryListDTO.swift in Sources */, + 982A4FBF2941F1CA005AEB1D /* NewDiaryDetail.swift in Sources */, 666E6F87291CF4B400CECD4B /* DiaryCoordinator.swift in Sources */, 4F31777F291BE4710019BDFC /* SceneDelegate.swift in Sources */, 4F307A4629387C1100FA36A0 /* ShazamSession.swift in Sources */, diff --git a/Segno/Segno/Data/Network/Endpoints/NewDiaryPostEndpoint.swift b/Segno/Segno/Data/Network/Endpoints/NewDiaryPostEndpoint.swift new file mode 100644 index 0000000..06ea84a --- /dev/null +++ b/Segno/Segno/Data/Network/Endpoints/NewDiaryPostEndpoint.swift @@ -0,0 +1,31 @@ +// +// NewDiaryPostEndpoint.swift +// Segno +// +// Created by YOONJONG on 2022/12/08. +// + +import Foundation + +enum NewDiaryPostEndpoint: Endpoint { + case item(NewDiaryDetail) + + var baseURL: URL? { + return URL(string: BaseURL.urlString) + } + + var httpMethod: HTTPMethod { + return .POST + } + + var path: String { + return "diary" + } + + var parameters: HTTPRequestParameter? { + switch self { + case .item(let diary): + return HTTPRequestParameter.body(diary) + } + } +} diff --git a/Segno/Segno/Data/Network/NetworkManager.swift b/Segno/Segno/Data/Network/NetworkManager.swift index d5ff632..a7ca020 100644 --- a/Segno/Segno/Data/Network/NetworkManager.swift +++ b/Segno/Segno/Data/Network/NetworkManager.swift @@ -53,6 +53,7 @@ struct NetworkManager { observer(.success(data)) } else { // TODO: 서버에서 설정하는 에러 코드에 따라 에러 메시지 다르게 설정 + print(httpResponse.statusCode) observer(.failure(NetworkError.invalidNetworkStatusCode)) } } diff --git a/Segno/Segno/Data/Repository/DTO/NewDiaryDetailDTO.swift b/Segno/Segno/Data/Repository/DTO/NewDiaryDetailDTO.swift new file mode 100644 index 0000000..b4c7879 --- /dev/null +++ b/Segno/Segno/Data/Repository/DTO/NewDiaryDetailDTO.swift @@ -0,0 +1,26 @@ +// +// NewDiaryDetailDTO.swift +// Segno +// +// Created by YOONJONG on 2022/12/08. +// + +struct NewDiaryDetailDTO: Decodable { + let token: String + let title: String + let tags: [String] + let imagePath: String + let bodyText: String? + let musicInfo: MusicInfo? + let location: Location? + + init(title: String, tags: [String], imagePath: String, bodyText: String?, musicInfo: MusicInfo?, location: Location?, token: String) { + self.title = title + self.tags = tags + self.imagePath = imagePath + self.bodyText = bodyText + self.musicInfo = musicInfo + self.location = location + self.token = token + } +} diff --git a/Segno/Segno/Data/Repository/DiaryRepository.swift b/Segno/Segno/Data/Repository/DiaryRepository.swift index 8d54ebf..294ae2c 100644 --- a/Segno/Segno/Data/Repository/DiaryRepository.swift +++ b/Segno/Segno/Data/Repository/DiaryRepository.swift @@ -12,7 +12,7 @@ import RxSwift protocol DiaryRepository { func getDiaryListItem() -> Single func getDiary(id: String) -> Single - func postDiary(_ diary: DiaryDetail, image: Data) -> Single + func postDiary(_ newDiary: NewDiaryDetail) -> Single func deleteDiary(id: String) -> Single } @@ -25,7 +25,7 @@ final class DiaryRepositoryImpl: DiaryRepository { let diaryListItemDTO = try JSONDecoder().decode(DiaryListDTO.self, from: $0) return diaryListItemDTO } -// + // // TODO: 추후에 NetworkManager로 변경 // return Single.create { observer -> Disposable in // let dto = DiaryListDTO.example @@ -51,31 +51,12 @@ final class DiaryRepositoryImpl: DiaryRepository { // } } - func postDiary(_ diary: DiaryDetail, image: Data) -> Single { - // Dummy endpoint + func postDiary(_ newDiary: NewDiaryDetail) -> Single { + let newDiaryDetailEndpoint = NewDiaryPostEndpoint.item(newDiary) + print("========= repository -> ", newDiary) - let imageEndpoint = ImageEndpoint.item(image) - - let single = NetworkManager.shared.call(imageEndpoint) - .compactMap { - // image 전송 후 이름 받아오기 - let imageDTO = try JSONDecoder().decode(ImageDTO.self, from: $0) - return imageDTO.filename - }.map { imagePath in - // diary에 imagePath넣어 전달 - return DiaryDetail(diary, imagePath: imagePath) - }.flatMap { diaryDetail in - // diary를 다시 서버에 전달 - // TODO: - token 넣어야됩니당 - let testDiaryDetail = DiaryDetail(diaryDetail, token: "0KjV78s0YPKbrlVP3QeAwUJcjohs2h2ysdWDLWg") - - let diaryDetailEndpoint = DiaryPostEndpoint.item(testDiaryDetail) - - return NetworkManager.shared.call(diaryDetailEndpoint) - .map { try JSONDecoder().decode(DiaryDetailDTO.self, from: $0) } - .asObservable() - .asMaybe() - } + let single = NetworkManager.shared.call(newDiaryDetailEndpoint) + .map { try JSONDecoder().decode(NewDiaryDetailDTO.self, from: $0) } .asObservable() .asSingle() diff --git a/Segno/Segno/Data/Repository/LocationRepository.swift b/Segno/Segno/Data/Repository/LocationRepository.swift index 9eb7382..25b1784 100644 --- a/Segno/Segno/Data/Repository/LocationRepository.swift +++ b/Segno/Segno/Data/Repository/LocationRepository.swift @@ -67,8 +67,6 @@ extension LocationRepositoryImpl: CLLocationManagerDelegate { func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { debugPrint("didUpdateLocations") if let cllocation = locations.first { - print("위도 : \(cllocation.coordinate.latitude)") - print("경도 : \(cllocation.coordinate.longitude)") let location = Location(latitude: cllocation.coordinate.latitude, longitude: cllocation.coordinate.longitude) getAddress(location: cllocation) locationSubject.onNext(location) diff --git a/Segno/Segno/Domain/UseCase/DiaryEditUseCase.swift b/Segno/Segno/Domain/UseCase/DiaryEditUseCase.swift index 350a68c..b170530 100644 --- a/Segno/Segno/Domain/UseCase/DiaryEditUseCase.swift +++ b/Segno/Segno/Domain/UseCase/DiaryEditUseCase.swift @@ -9,27 +9,30 @@ import Foundation import RxSwift protocol DiaryEditUseCase { - func postDiary(_ diary: DiaryDetail, image: Data) -> Single + func postDiary(_ newDiary: NewDiaryDetail) -> Single } final class DiaryEditUseCaseImpl: DiaryEditUseCase { - let repository: DiaryRepository + let diaryRepository: DiaryRepository + let imageRepository: ImageRepository private let disposeBag = DisposeBag() - init(repository: DiaryRepository = DiaryRepositoryImpl()) { - self.repository = repository + init(diaryRepository: DiaryRepository = DiaryRepositoryImpl(), + imageRepository: ImageRepository = ImageRepositoryImpl()) { + self.diaryRepository = diaryRepository + self.imageRepository = imageRepository } - func postDiary(_ diary: DiaryDetail, image: Data) -> Single { - return repository.postDiary(diary, image: image).map { dto in - DiaryDetail( - identifier: dto.id, + func postDiary(_ newDiary: NewDiaryDetail) -> Single { + return diaryRepository.postDiary(newDiary).map { dto in + NewDiaryDetail( title: dto.title, tags: dto.tags, imagePath: dto.imagePath, bodyText: dto.bodyText, musicInfo: dto.musicInfo, - location: dto.location + location: dto.location, + token: "A1lmMjb2pgNWg6ZzAaPYgMcqRv/8BOyO4U/ui6i/Ic4=" ) } } diff --git a/Segno/Segno/Entity/NewDiaryDetail.swift b/Segno/Segno/Entity/NewDiaryDetail.swift new file mode 100644 index 0000000..4d3cae5 --- /dev/null +++ b/Segno/Segno/Entity/NewDiaryDetail.swift @@ -0,0 +1,26 @@ +// +// NewDiaryDetail.swift +// Segno +// +// Created by YOONJONG on 2022/12/08. +// + +struct NewDiaryDetail: Encodable { + let title: String + let tags: [String] + let imagePath: String + let bodyText: String? + let musicInfo: MusicInfo? + let location: Location? + let token: String + + init(title: String, tags: [String], imagePath: String, bodyText: String?, musicInfo: MusicInfo?, location: Location?, token: String) { + self.title = title + self.tags = tags + self.imagePath = imagePath + self.bodyText = bodyText + self.musicInfo = musicInfo + self.location = location + self.token = token + } +} diff --git a/Segno/Segno/Presentation/ViewController/DiaryEditViewController.swift b/Segno/Segno/Presentation/ViewController/DiaryEditViewController.swift index 2f0da0a..43c8c72 100644 --- a/Segno/Segno/Presentation/ViewController/DiaryEditViewController.swift +++ b/Segno/Segno/Presentation/ViewController/DiaryEditViewController.swift @@ -469,8 +469,10 @@ extension DiaryEditViewController { dateFormatter.locale = Locale(identifier: "ko_KR") title = dateFormatter.string(from: Date()) } - guard let bodyText = bodyTextView.text else { return } - + var bodyText: String? + if bodyTextView.text == Metric.bodyPlaceholder || bodyTextView.text.isEmpty { + bodyText = nil + } viewModel.saveDiary(title: title, body: bodyText, tags: tags, imageData: imageData) } } diff --git a/Segno/Segno/Presentation/ViewModel/DiaryEditViewModel.swift b/Segno/Segno/Presentation/ViewModel/DiaryEditViewModel.swift index a73f6ef..997e047 100644 --- a/Segno/Segno/Presentation/ViewModel/DiaryEditViewModel.swift +++ b/Segno/Segno/Presentation/ViewModel/DiaryEditViewModel.swift @@ -17,6 +17,7 @@ final class DiaryEditViewModel { var diaryDetail: DiaryDetail? // 에딧 화면에 들어갈 여러 요소들 + let diaryEditUseCase: DiaryEditUseCase let diaryDetailUseCase: DiaryDetailUseCase let searchMusicUseCase: SearchMusicUseCase let locationUseCase: LocationUseCase @@ -26,10 +27,12 @@ final class DiaryEditViewModel { var isReceivingLocation = BehaviorSubject(value: false) var musicInfo = BehaviorSubject(value: nil) - init(diaryDetailUseCase: DiaryDetailUseCase = DiaryDetailUseCaseImpl(), + init(diaryEditUseCase: DiaryEditUseCase = DiaryEditUseCaseImpl(), + diaryDetailUseCase: DiaryDetailUseCase = DiaryDetailUseCaseImpl(), searchMusicUseCase: SearchMusicUseCase = SearchMusicUseCaseImpl(), locationUseCase: LocationUseCase = LocationUseCaseImpl(), imageUseCase: ImageUseCase = ImageUseCaseImpl()) { + self.diaryEditUseCase = diaryEditUseCase self.diaryDetailUseCase = diaryDetailUseCase self.searchMusicUseCase = searchMusicUseCase self.locationUseCase = locationUseCase @@ -89,31 +92,50 @@ final class DiaryEditViewModel { searchMusicUseCase.stopSearching() } - func toggleLocation() { guard let value = try? isReceivingLocation.value() else { return } isReceivingLocation.onNext(!value) } - func saveDiary(title: String, body: String, tags: [String], imageData: Data) { + func saveDiary(title: String, body: String?, tags: [String], imageData: Data) { imageUseCase.uploadImage(data: imageData) .subscribe(onSuccess: { [weak self] imageInfo in guard let imageName = imageInfo.filename else { return } - debugPrint(imageName) - guard let location = try? self?.locationSubject.value() else { return } - guard let musicInfoResult = try? self?.musicInfo.value() else { return } - switch musicInfoResult { - case .success(let musicInfo): - debugPrint(musicInfo) - self?.saveDiary(title: title, body: body, tags: tags, imageName: imageName, musicInfo: musicInfo, location: location) - case .failure(let error): - debugPrint(error) - } + debugPrint("이미지 이름 : ", imageName) + self?.saveDiary(title: title, body: body, tags: tags, imageName: imageName) }) .disposed(by: disposeBag) } - func saveDiary(title: String, body: String, tags: [String], imageName: String, musicInfo: MusicInfo, location: Location) { - debugPrint("저장할 프로퍼티 : \(title), \(body), \(tags), \(imageName), \(musicInfo), \(location)") + func saveDiary(title: String, body: String?, tags: [String], imageName: String) { + let location = try? locationSubject.value() + var newDiary: NewDiaryDetail + // music data가 있는 경우 + if let musicInfoResult = try? musicInfo.value(), + let musicInfo = try? musicInfoResult.get() { + newDiary = NewDiaryDetail(title: title, + tags: tags, + imagePath: imageName, + bodyText: body, + musicInfo: musicInfo, + location: location, + token: "A1lmMjb2pgNWg6ZzAaPYgMcqRv/8BOyO4U/ui6i/Ic4=") + } + // music data가 없는 경우 + else { + newDiary = NewDiaryDetail(title: title, + tags: tags, + imagePath: imageName, + bodyText: body, + musicInfo: nil, + location: location, + token: "A1lmMjb2pgNWg6ZzAaPYgMcqRv/8BOyO4U/ui6i/Ic4=") + } + + diaryEditUseCase.postDiary(newDiary) + .subscribe(onSuccess: { newDiaryDetail in + debugPrint("전송 성공, 결과 : ", newDiaryDetail) + }) + .disposed(by: disposeBag) } }