From 2cb017c3eb539efabda295207b1a0a704ac714e1 Mon Sep 17 00:00:00 2001 From: 00yhsp <00yhsp@naver.com> Date: Mon, 19 Feb 2024 01:17:31 +0900 Subject: [PATCH] =?UTF-8?q?[#73]=20=EB=B3=B4=EA=B3=A0=EC=84=9C=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20=EA=B5=AC=ED=98=84=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Spon-us.xcodeproj/project.pbxproj | 6 + .../Model/Portfolio/MakeReportViewModel.swift | 40 +++ .../Portfolio/PortfolioOfferViewModel.swift | 80 +++++- Spon-us/SponusAPI.swift | 138 +++++++--- Spon-us/View/Portfolio/Portfolio.swift | 250 +++++------------- 5 files changed, 286 insertions(+), 228 deletions(-) create mode 100644 Spon-us/Model/Portfolio/MakeReportViewModel.swift diff --git a/Spon-us.xcodeproj/project.pbxproj b/Spon-us.xcodeproj/project.pbxproj index 463ffb8..56dc35b 100644 --- a/Spon-us.xcodeproj/project.pbxproj +++ b/Spon-us.xcodeproj/project.pbxproj @@ -125,6 +125,8 @@ DF498F2C2B7CDDB200ADE078 /* MyAnnouncementsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF498F2B2B7CDDB200ADE078 /* MyAnnouncementsViewModel.swift */; }; DF498F2E2B7DF4F600ADE078 /* LogoutModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF498F2D2B7DF4F500ADE078 /* LogoutModel.swift */; }; DF498F302B7DF50200ADE078 /* LogoutViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF498F2F2B7DF50200ADE078 /* LogoutViewModel.swift */; }; + DF5AB1522B81ED890061F421 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = DF5AB1512B81ED880061F421 /* GoogleService-Info.plist */; }; + DF5AB1542B8228CC0061F421 /* MakeReportViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF5AB1532B8228CC0061F421 /* MakeReportViewModel.swift */; }; DF5B7E922B7FA430001C009C /* PortfolioOfferViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF5B7E912B7FA430001C009C /* PortfolioOfferViewModel.swift */; }; DF5B7E942B808DF1001C009C /* EditAnnouncementViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF5B7E932B808DF0001C009C /* EditAnnouncementViewModel.swift */; }; DF5B7E962B809257001C009C /* EditAnnouncementModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF5B7E952B809257001C009C /* EditAnnouncementModel.swift */; }; @@ -230,6 +232,8 @@ DF498F2B2B7CDDB200ADE078 /* MyAnnouncementsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAnnouncementsViewModel.swift; sourceTree = ""; }; DF498F2D2B7DF4F500ADE078 /* LogoutModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogoutModel.swift; sourceTree = ""; }; DF498F2F2B7DF50200ADE078 /* LogoutViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogoutViewModel.swift; sourceTree = ""; }; + DF5AB1512B81ED880061F421 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "../../../Downloads/GoogleService-Info.plist"; sourceTree = ""; }; + DF5AB1532B8228CC0061F421 /* MakeReportViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MakeReportViewModel.swift; sourceTree = ""; }; DF5B7E912B7FA430001C009C /* PortfolioOfferViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PortfolioOfferViewModel.swift; sourceTree = ""; }; DF5B7E932B808DF0001C009C /* EditAnnouncementViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditAnnouncementViewModel.swift; sourceTree = ""; }; DF5B7E952B809257001C009C /* EditAnnouncementModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditAnnouncementModel.swift; sourceTree = ""; }; @@ -643,6 +647,7 @@ DF5B7E912B7FA430001C009C /* PortfolioOfferViewModel.swift */, DF5B7E932B808DF0001C009C /* EditAnnouncementViewModel.swift */, DF5B7E952B809257001C009C /* EditAnnouncementModel.swift */, + DF5AB1532B8228CC0061F421 /* MakeReportViewModel.swift */, ); path = Portfolio; sourceTree = ""; @@ -811,6 +816,7 @@ DFB22ED92B767003007903DF /* JoinViewModel.swift in Sources */, 100A1E302B71637A00AAC1E8 /* MyProfileView.swift in Sources */, 3BFC8D1F2B5597C9000D6006 /* ProfileView.swift in Sources */, + DF5AB1542B8228CC0061F421 /* MakeReportViewModel.swift in Sources */, 10025B372B7B802F00DCCC5A /* ProposalModel.swift in Sources */, 3B36F09C2B6FEBA00000ACFB /* ChargerInfoViewTest.swift in Sources */, DF90A5BE2B6E39A600BC54D0 /* RegisterPWView.swift in Sources */, diff --git a/Spon-us/Model/Portfolio/MakeReportViewModel.swift b/Spon-us/Model/Portfolio/MakeReportViewModel.swift new file mode 100644 index 0000000..c574fe9 --- /dev/null +++ b/Spon-us/Model/Portfolio/MakeReportViewModel.swift @@ -0,0 +1,40 @@ +// +// MakeReportViewModel.swift +// Spon-us +// +// Created by 박현수 on 2/18/24. +// + +import Foundation +import Moya + +struct PostReportResponse: Codable { + let statusCode: String + let message: String + let content: PostReportContent +} + +// 'content' 필드 내용을 담을 구조체 +struct PostReportContent: Codable { + let id: Int + let writerId: Int + let title: String + let content: String +} + +struct RequestParams: Codable { + let title: String + let content: String + let proposeId: Int +} + +struct PatchProposeReportBody: Codable { + let isReported: Bool + let reportId: Int? +} + +class MakeReportViewModel: ObservableObject { + @Published var filename = "" + + +} diff --git a/Spon-us/Model/Portfolio/PortfolioOfferViewModel.swift b/Spon-us/Model/Portfolio/PortfolioOfferViewModel.swift index 1276000..85dbb49 100644 --- a/Spon-us/Model/Portfolio/PortfolioOfferViewModel.swift +++ b/Spon-us/Model/Portfolio/PortfolioOfferViewModel.swift @@ -80,8 +80,9 @@ class PortfolioOfferViewModel: ObservableObject { myProposes.append(prop) } } -// myProposes = Array(Set(myProposes)) -// myProposes.sort { $0.createdDate > $1.createdDate } + + myProposes = Array(Set(myProposes)) + myProposes.sort {$0.proposeId > $1.proposeId} // for content in myProposes { // if content.status == "SUSPENDED" || content.status == "COMPLETED" { // @@ -96,6 +97,7 @@ class PortfolioOfferViewModel: ObservableObject { case let .success(response): if response.statusCode == 200 { do { + print("stopoffer") let responseBody = try JSONDecoder().decode(ChangeAnnouncementStatusModel400.self, from: response.data) print(responseBody) completion(true) @@ -162,4 +164,78 @@ class PortfolioOfferViewModel: ObservableObject { } } } + + func completeOffer(proposeId: Int, completion: @escaping (Bool) -> Void) { + provider.request(.patchChangeOfferStatus(proposeID: proposeId, status: "COMPLETED")) { result in + switch result { + case let .success(response): + if response.statusCode == 200 { + do { + print("여기") + let responseBody = try JSONDecoder().decode(ChangeAnnouncementStatusModel400.self, from: response.data) + print(responseBody) + completion(true) + } + catch { + print("200 successError") + completion(false) + } + } + else { + do { + print(response.statusCode) + let responseBody = try JSONDecoder().decode(ChangeAnnouncementStatusModel400.self, from: response.data) + print(responseBody) + completion(false) + } + catch { + print("40x successError") + completion(false) + } + } + case let .failure(response): + print(response.errorDescription) + if let moyaError = response as? MoyaError, let response = moyaError.response { + if let responseBody = String(data: response.data, encoding: .utf8) { + print("실패 응답 본문: \(responseBody)") + } + } + print("failureError") + completion(false) + } + } + } + + func cancelCompleteOffer(proposeId: Int, status: String, completion: @escaping (Bool) -> Void) { + provider.request(.patchChangeOfferStatus(proposeID: proposeId, status: status)) { result in + switch result { + case let .success(response): + if response.statusCode == 200 { + do { + let responseBody = try JSONDecoder().decode(ChangeAnnouncementStatusModel400.self, from: response.data) + print(responseBody) + completion(true) + } + catch { + print("200 successError") + completion(false) + } + } + else { + do { + let responseBody = try JSONDecoder().decode(ChangeAnnouncementStatusModel400.self, from: response.data) + print(responseBody) + completion(false) + } + catch { + print("40x successError") + completion(false) + } + } + case .failure(_): + print("failureError") + completion(false) + } + } + } } diff --git a/Spon-us/SponusAPI.swift b/Spon-us/SponusAPI.swift index e40fe22..e3cee80 100644 --- a/Spon-us/SponusAPI.swift +++ b/Spon-us/SponusAPI.swift @@ -37,6 +37,8 @@ enum SponusAPI { case patchPullUp(announcementID: Int) //MARK: 알림 case getNotification + case postReport(title: String, content: String, proposeID: Int, images: [UIImage], attatchments: [URL]) + case patchProposeReportId(proposeId: Int, reportId: Int) } extension SponusAPI: TargetType { @@ -84,7 +86,7 @@ extension SponusAPI: TargetType { return "/api/v1/announcements/\(announcementId)" case .patchModifyAnnouncement(let announcementId, _, _, _, _): return "/api/v1/announcements/\(announcementId)" - //MARK: 검색 + //MARK: 검색 case .searchOrganization(keyword: let keyword): return "/api/v1/organizations" case .searchAnnouncement(keyword: let keyword): @@ -95,6 +97,10 @@ extension SponusAPI: TargetType { return "/api/v1/announcements/\(announcementID)/pullUp" case .getNotification: return "/api/v1/organizations/notifications" + case .postReport: + return "/api/v1/reports" + case .patchProposeReportId(let proposeId, _): + return "/api/v1/proposes/\(proposeId)" } } @@ -111,7 +117,7 @@ extension SponusAPI: TargetType { case .getAnnouncement(announcementId: let announcementId): return .get case .propose(title: let title, content: let content, announcementId: let announcementId, attachments: let attachments): - return .post + return .post case .postLogin: return .post case .getLogout: @@ -138,7 +144,6 @@ extension SponusAPI: TargetType { return .delete case .patchModifyAnnouncement: return .patch - //MARK: 검색 case .searchOrganization(keyword: let keyword): return .get case .searchAnnouncement(keyword: let keyword): @@ -149,6 +154,10 @@ extension SponusAPI: TargetType { return .patch case .getNotification: return .get + case .postReport: + return .post + case .patchProposeReportId: + return .patch } } @@ -168,21 +177,21 @@ extension SponusAPI: TargetType { ] return try! JSONSerialization.data(withJSONObject: response, options: .prettyPrinted) case .postAnnouncement(title: let title, type: let type, category: let category, content: let content, images: let images): - let sampleResponse: [String: Any] = [ - "statusCode": "string", - "message": "string", - "content": [ - "id": 0, - "writerId": 0, - "title": "string", - "type": "SPONSORSHIP", - "category": "IDEA", - "content": "string", - "status": "OPENED", - "viewCount": 0 - ] + let sampleResponse: [String: Any] = [ + "statusCode": "string", + "message": "string", + "content": [ + "id": 0, + "writerId": 0, + "title": "string", + "type": "SPONSORSHIP", + "category": "IDEA", + "content": "string", + "status": "OPENED", + "viewCount": 0 ] - return try! JSONSerialization.data(withJSONObject: sampleResponse, options: .prettyPrinted) + ] + return try! JSONSerialization.data(withJSONObject: sampleResponse, options: .prettyPrinted) case .getCategory(category: let category, type: let type): return Data() case .getAnnouncement(announcementId: let announcementId): @@ -233,6 +242,10 @@ extension SponusAPI: TargetType { return Data() case .getNotification: return Data() + case .postReport: + return Data() + case .patchProposeReportId: + return Data() } } @@ -258,24 +271,24 @@ extension SponusAPI: TargetType { } case .postAnnouncement(title: let title, type: let type, category: let category, content: let content, images: let images): let requestParams = [ - "title": title, - "type": type, - "category": category, - "content": content - ] - let requestJSON = try? JSONEncoder().encode(requestParams) - - let imageMultipartData = images.enumerated().map { (index, image) -> MultipartFormData in - let imageData = image.jpegData(compressionQuality: 0.7) ?? Data() - return MultipartFormData(provider: .data(imageData), name: "images", fileName: "image\(index).jpg", mimeType: "image/jpeg") - } - var multipartData = [MultipartFormData]() - if let requestData = requestJSON { - multipartData.append(MultipartFormData(provider: .data(requestData), name: "request")) - } - multipartData.append(contentsOf: imageMultipartData) - - return .uploadMultipart(multipartData) + "title": title, + "type": type, + "category": category, + "content": content + ] + let requestJSON = try? JSONEncoder().encode(requestParams) + + let imageMultipartData = images.enumerated().map { (index, image) -> MultipartFormData in + let imageData = image.jpegData(compressionQuality: 0.7) ?? Data() + return MultipartFormData(provider: .data(imageData), name: "images", fileName: "image\(index).jpg", mimeType: "image/jpeg") + } + var multipartData = [MultipartFormData]() + if let requestData = requestJSON { + multipartData.append(MultipartFormData(provider: .data(requestData), name: "request")) + } + multipartData.append(contentsOf: imageMultipartData) + + return .uploadMultipart(multipartData) case .getCategory(category: let category, type: let type): var parameters: [String: Any] = [:] if let category = category { @@ -345,7 +358,7 @@ extension SponusAPI: TargetType { "content" : content ] return .requestJSONEncodable(requestBody) - //MARK: 검색 + //MARK: 검색 case .searchOrganization(keyword: let keyword): return .requestParameters(parameters: ["search": keyword], encoding: URLEncoding.queryString) case .searchAnnouncement(keyword: let keyword): @@ -356,6 +369,39 @@ extension SponusAPI: TargetType { return .requestPlain case .getNotification: return .requestPlain + case .postReport(let title, let content, let proposeID, let images, let attatchments): + let requestParams = RequestParams(title: title, content: content, proposeId: proposeID) + let requestJSON = try? JSONEncoder().encode(requestParams) + let imageMultipartData = images.enumerated().map { (index, image) -> MultipartFormData in + let imageData = image.jpegData(compressionQuality: 0.7) ?? Data() + return MultipartFormData(provider: .data(imageData), name: "images", fileName: "image\(index).jpg", mimeType: "image/jpeg") + } + let test = images.enumerated().map { (index, image) -> MultipartFormData in + let imageData = image.jpegData(compressionQuality: 0.7) ?? Data() + return MultipartFormData(provider: .data(imageData), name: "attatchments", fileName: "image\(index).jpg", mimeType: "image/jpeg") + } + let filename = attatchments[0].lastPathComponent + + let pdfMultipartData = attatchments.enumerated().map { (index, pdf) -> MultipartFormData in + let pdfData = try! Data(contentsOf: attatchments[0]) + print(attatchments[0]) + return MultipartFormData(provider: .data(pdfData), name: "attachments", fileName: attatchments[0].lastPathComponent, mimeType: "application/pdf") + } + var multipartData = [MultipartFormData]() + if let requestData = requestJSON { + multipartData.append(MultipartFormData(provider: .data(requestData), name: "request")) + } + multipartData.append(contentsOf: imageMultipartData) + multipartData.append(contentsOf: pdfMultipartData) + return .uploadMultipart(multipartData) + case .patchProposeReportId(_, let reportId): + let requestBody = PatchProposeReportBody(isReported: true, reportId: reportId) + let requestJSON = try? JSONEncoder().encode(requestBody) + var multipartData = [MultipartFormData]() + if let requestData = requestJSON { + multipartData.append(MultipartFormData(provider: .data(requestData), name: "request")) + } + return .uploadMultipart(multipartData) } } @@ -377,11 +423,11 @@ extension SponusAPI: TargetType { return ["Authorization": "Bearer \(loadAccessToken(userID: UserDefaults.standard.string(forKey: "loginAccount") ?? "loadAccessToken Error"))"] case .getOrganization: return ["Authorization": "Bearer \(loadAccessToken(userID: UserDefaults.standard.string(forKey: "loginAccount") ?? "loadAccessToken Error"))"] - /* - case .postLike: - return ["Content-Type": "application/json", - "Accept": "application/json", - "atk": KeychainSwift().get("accessToken") ?? ""] */ + /* + case .postLike: + return ["Content-Type": "application/json", + "Accept": "application/json", + "atk": KeychainSwift().get("accessToken") ?? ""] */ case .postAnnouncement(title: let title, type: let type, category: let category, content: let content, images: let images): return ["Authorization": "Bearer \(loadAccessToken(userID: UserDefaults.standard.string(forKey: "loginAccount") ?? "loadAccessToken Error"))"] case .getCategory(category: let category, type: let type): @@ -414,12 +460,16 @@ extension SponusAPI: TargetType { return ["Authorization": "Bearer \(loadAccessToken(userID: UserDefaults.standard.string(forKey: "loginAccount") ?? "loadAccessToken Error"))"] case .getNotification: return ["Authorization": "Bearer \(loadAccessToken(userID: UserDefaults.standard.string(forKey: "loginAccount") ?? "loadAccessToken Error"))"] + case .postReport: + return ["Authorization": "Bearer \(loadAccessToken(userID: UserDefaults.standard.string(forKey: "loginAccount") ?? "loadAccessToken Error"))"] + case .patchProposeReportId: + return ["Authorization": "Bearer \(loadAccessToken(userID: UserDefaults.standard.string(forKey: "loginAccount") ?? "loadAccessToken Error"))"] } } } extension SponusAPI { - var validationType: ValidationType { - return .successCodes - } + var validationType: ValidationType { + return .successCodes + } } diff --git a/Spon-us/View/Portfolio/Portfolio.swift b/Spon-us/View/Portfolio/Portfolio.swift index 4e8b1cf..4878900 100644 --- a/Spon-us/View/Portfolio/Portfolio.swift +++ b/Spon-us/View/Portfolio/Portfolio.swift @@ -10,6 +10,7 @@ import SwiftUI import PopupView import UniformTypeIdentifiers import MobileCoreServices +import Moya // 버튼 탭 애니메이션 X struct CustomButtonStyle: ButtonStyle { @@ -143,8 +144,12 @@ struct Portfolio: View { Text("협업이 완료되었습니다").font(.Body03).foregroundStyle(.sponusPrimary).padding(.leading, 32) Spacer() Button { - showingCoworkCompletedPopup = false - showingCoworkCompletedCancelPopup = true + portfolioOfferViewModel.cancelCompleteOffer(proposeId: currentProgressingID, status: currentProgressingStatus) { success in + if success { + showingCoworkCompletedPopup = false + showingCoworkCompletedCancelPopup = true + } + } } label: { Text("취소").font(.Body04).foregroundStyle(.sponusGrey700).padding(.trailing, 32) } @@ -364,7 +369,7 @@ struct Portfolio: View { VStack { ForEach(portfolioOfferViewModel.myProposes, id: \.proposeId) { cell in - if cell.status != "SUSPENDED" && cell.announcementSummary.status == "OPENED" { + if cell.status != "SUSPENDED" && cell.status != "COMPLETED" { NavigationLink( destination: MyNoticeDetailView(rootIsActive: $rootIsActive), // destination: DetailView(post: dummy), @@ -419,7 +424,12 @@ struct Portfolio: View { Spacer() Button { currentProgressingID = cell.proposeId - showingCoworkCompletedPopup = true + currentProgressingStatus = cell.status + portfolioOfferViewModel.completeOffer(proposeId: currentProgressingID) { success in + if success { + showingCoworkCompletedPopup = true + } + } } label: { Text("협업 완료") .font(.Caption01) @@ -429,8 +439,6 @@ struct Portfolio: View { } } Divider().backgroundStyle(.sponusGrey200).padding(.top, 16) - }.onAppear() { - print(cell.title) } } ) @@ -457,7 +465,14 @@ struct Portfolio: View { .autohideIn(3) } .popup(isPresented: $showingCoworkCompletedPopup) { - createCoworkCompletedToastMessage() + createCoworkCompletedToastMessage().onDisappear() { + portfolioOfferViewModel.offerContents.removeAll() + portfolioOfferViewModel.getOffers() { success in + if success { + portfolioOfferViewModel.getProposes() + } + } + } } customize: { $0.type(.floater(verticalPadding: 16)) .position(.bottom) @@ -484,7 +499,14 @@ struct Portfolio: View { .autohideIn(2) } .popup(isPresented: $showingCoworkCompletedCancelPopup) { - createCoworkCompletedCancelToastMessage() + createCoworkCompletedCancelToastMessage().onDisappear() { + portfolioOfferViewModel.offerContents.removeAll() + portfolioOfferViewModel.getOffers() { success in + if success { + portfolioOfferViewModel.getProposes() + } + } + } } customize: { $0.type(.floater(verticalPadding: 16)) .position(.bottom) @@ -493,8 +515,6 @@ struct Portfolio: View { .closeOnTapOutside(true) .autohideIn(2) } - - } @@ -511,10 +531,9 @@ struct Portfolio: View { ScrollView { VStack { ForEach(portfolioOfferViewModel.myProposes, id: \.proposeId) { cell in - if (cell.status == "SUSPENDED" || cell.announcementSummary.status == "CLOSED") { + if (cell.status == "SUSPENDED" || cell.status == "COMPLETED" || cell.announcementSummary.status == "CLOSED") { NavigationLink( destination: MyNoticeDetailView(rootIsActive: $rootIsActive), - // destination: DetailView(post: dummy), label: { VStack(alignment:.leading, spacing: 0) { HStack(spacing: 0) { @@ -597,108 +616,19 @@ struct Portfolio: View { } } - // if ($progressStatus.isCompleted.wrappedValue == true) { - // ScrollView { - // VStack { - // ForEach(dummyData) { dummy in - // if (dummy.postProgressStatus == .completed) { - // NavigationLink( - // destination: MyNoticeDetailView(rootIsActive: $rootIsActive), - // // destination: DetailView(post: dummy), - // label: { - // VStack(alignment:.leading, spacing: 0) { - // HStack(spacing: 0) { - // (dummy.thumbNail ?? Image(.icCancel)) - // .resizable().frame(width: 158, height: 158) - // .border(.sponusGrey100) - // - // VStack(alignment: .leading, spacing: 5) { - // switch dummy.postCategory { - // case .sponsorship: - // Text("협찬").font(.Caption02).foregroundStyle(.sponusGrey700) - // case .linkedproject: - // Text("연계프로젝트").font(.Caption02).foregroundStyle(.sponusGrey700) - // case nil: - // Text("nil").font(.Caption02).foregroundStyle(.sponusGrey700) - // } - // Text(dummy.postTitle ?? "nil").font(.Body07).foregroundStyle(.sponusBlack).multilineTextAlignment(.leading).padding(.bottom, 16) - // - // HStack(spacing: 6) { - // (dummy.companyImage ?? Image(.icCancel)).resizable().aspectRatio(contentMode: .fill).frame(width:24, height:24).clipShape(Circle()) - // Text("with \(dummy.companyName ?? "nil")").font(.English16).foregroundStyle(.sponusGrey700) - // }.padding(.bottom) - // - // }.padding(.leading, 20) - // }.padding(.top, 32).padding(.bottom, 24) - // VStack(spacing: 0) { - // switch dummy.completedReportStatus { - // case .reportNotSubmitted: - // Button { - // currentMakeReportID = dummy.id - // activeNavLinkToMakeReport = true - // } label: { - // Text("보고서 작성하기") - // .font(.Caption01) - // .frame(height: 40) - // .frame(maxWidth: .infinity) - // .foregroundStyle(.sponusRed) - // .border(.sponusRed) - // } - // case .unsuccessfulTermination: - // Text("협업이 중단된 공고입니다") - // .font(.Caption01) - // .frame(height: 40) - // .frame(maxWidth: .infinity) - // .foregroundStyle(.sponusGrey700) - // .border(.sponusGrey100) - // case .reportSubmitted: - // Button { - // currentReportID = dummy.id - // activeNavLinkToReport = true - // } label: { - // Text("보고서 보러가기") - // .font(.Caption01) - // .frame(height: 40) - // .frame(maxWidth: .infinity) - // .foregroundStyle(.sponusPrimary) - // .border(.sponusPrimary) - // } - // case nil: - // Text("nil") - // .font(.Caption01) - // .frame(height: 40) - // .foregroundStyle(.sponusRed) - // .border(.sponusRed) - // } - // } - // Divider().backgroundStyle(.sponusGrey200).padding(.top, 16) - // }.frame(maxWidth: .infinity, maxHeight: .infinity) - // } - // ) - // } - // } - // } - // }.scrollIndicators(.hidden) - // } }.padding() .navigationTitle("포트폴리오").font(.Body01) .navigationBarTitleDisplayMode(.inline) .navigationBarBackButtonHidden(true) .navigationBarItems(leading: CustomBackButton()) .navigationDestination(isPresented: $activeNavLinkToEdit) { - // if let index = dummyData.firstIndex(where: { $0.id == currentConfirmationDialogID }) { - // ModifyView(post: dummyData[index]) - // } EditAnnouncementView(announcementID: currentDialogID, popup: .constant(false)) } .navigationDestination(isPresented: $activeNavLinkToMakeReport) { - MakeReportView(rootIsActive: self.$rootIsActive) + MakeReportView(rootIsActive: self.$rootIsActive, proposeID: currentMakeReportID) } .navigationDestination(isPresented: $activeNavLinkToReport) { ReportView(popToRootView: self.$rootIsActive) - // if let index = dummyData.firstIndex(where: { $0.id == currentReportID }) { - // ReportView() - // } } .toolbar(.hidden, for: .tabBar) .onAppear() { @@ -715,7 +645,9 @@ struct Portfolio: View { struct MakeReportView: View { + @StateObject var makeReportViewModel = MakeReportViewModel() @Binding var rootIsActive: Bool + @State var proposeID: Int @State private var postTitle = "" @State private var selectedImages: [UIImage] = [] @State private var postSelectedCategory = "" @@ -742,6 +674,8 @@ struct MakeReportView: View { @Environment(\.presentationMode) var presentationMode + let provider = MoyaProvider(plugins: [NetworkLoggerPlugin()]) + func createPopup() -> some View { HStack { Text("작성이 완료되었습니다").font(.Body03).foregroundStyle(.sponusPrimary) @@ -874,13 +808,7 @@ struct MakeReportView: View { Image(fileButton1Text == "파일 선택" ? .icUpload : .icCancel).resizable().frame(width: 24, height: 24) }.fileImporter( isPresented: $isDocumentPicker1Presented, - allowedContentTypes: [UTType.pdf, - UTType.doc, - UTType.docx, - UTType.hwp, - UTType.hwpx, - UTType.ppt, - UTType.pptx], + allowedContentTypes: [UTType.pdf], allowsMultipleSelection: false, onCompletion: { result in do { @@ -893,76 +821,8 @@ struct MakeReportView: View { ) .padding(.trailing, 20) }.padding(.vertical, 16).border(.sponusGrey100) - HStack { - Text(fileButton2Text).font(.Body10).foregroundStyle(fileButton2Text == "파일 선택" ? .sponusGrey700 : .sponusBlack).padding(.leading, 20) - Spacer() - Button { - if (fileButton2Text != "파일 선택") { - fileButton2Text = "파일 선택" - } - else { - isDocumentPicker2Presented.toggle() - } - selectedURLsFile2 = [] - } - label: { - Image(fileButton2Text == "파일 선택" ? .icUpload : .icCancel).resizable().frame(width: 24, height: 24) - }.fileImporter( - isPresented: $isDocumentPicker2Presented, - allowedContentTypes: [UTType.pdf, - UTType.doc, - UTType.docx, - UTType.hwp, - UTType.hwpx, - UTType.ppt, - UTType.pptx], - allowsMultipleSelection: false, - onCompletion: { result in - do { - selectedURLsFile2 = try result.get() - fileButton2Text = selectedURLsFile2[0].lastPathComponent - } catch { - print(error.localizedDescription) - } - } - ).padding(.trailing, 20) - }.padding(.vertical, 16).border(.sponusGrey100) - HStack { - Text(fileButton3Text).font(.Body10).foregroundStyle(fileButton3Text == "파일 선택" ? .sponusGrey700 : .sponusBlack).padding(.leading, 20) - Spacer() - Button { - if (fileButton3Text != "파일 선택") { - fileButton3Text = "파일 선택" - } - else { - isDocumentPicker3Presented.toggle() - } - selectedURLsFile3 = [] - } - label: { - Image(fileButton3Text == "파일 선택" ? .icUpload : .icCancel).resizable().frame(width: 24, height: 24) - }.fileImporter( - isPresented: $isDocumentPicker3Presented, - allowedContentTypes: [UTType.pdf, - UTType.doc, - UTType.docx, - UTType.hwp, - UTType.hwpx, - UTType.ppt, - UTType.pptx], - allowsMultipleSelection: false, - onCompletion: { result in - do { - selectedURLsFile3 = try result.get() - fileButton3Text = selectedURLsFile3[0].lastPathComponent - } catch { - print(error.localizedDescription) - } - } - ).padding(.trailing, 20) - }.padding(.vertical, 16).border(.sponusGrey100) - Text("상세 내용이 적힌 파일을 첨부해 주세요\n(MS Word, MS PowerPoint, HWP, PDF)") + Text("상세 내용이 적힌 PDF 파일을 첨부해 주세요") .font(.Caption02) .foregroundStyle(.sponusGrey600) .padding(.bottom, 16) @@ -1022,7 +882,36 @@ struct MakeReportView: View { }.popup(isPresented: $showingPopup) { createPopup().onDisappear(){ - self.presentationMode.wrappedValue.dismiss() + provider.request(.postReport(title: postTitle, content: postDetail, proposeID: proposeID, images: selectedImages, attatchments: selectedURLsFile1)) { result in + let innerProposeID = proposeID + switch result { + case let .success(response): + do { + let responseBody = try response.map(PostReportResponse.self) + print("report success") + print(responseBody) + presentationMode.wrappedValue.dismiss() + } catch { + print("postreport parse error") + } + + case let .failure(response): + if let responsee = response.response { + // 실패한 요청의 응답 본문이 있는 경우 + if let responseBody = String(data: responsee.data, encoding: .utf8) { + print("Response body: \(responseBody)") + } else { + print("Failed to decode response body.") + } + } else { + print("No response body.") + } + print(response.localizedDescription) + print(response.errorDescription) + print("postreport error") + } + } + } } customize: { $0.type(.floater(verticalPadding: 16)) @@ -1157,10 +1046,7 @@ struct ReportPreviewView: View { .padding(.horizontal, 20) } .padding(.bottom, 20) - } - - }.navigationTitle("미리보기").font(.Body01) .navigationBarTitleDisplayMode(.inline) .navigationBarBackButtonHidden(true)