From 00b86b472875b917a221482377f8346cb46c67f0 Mon Sep 17 00:00:00 2001 From: yeahzxnn Date: Thu, 20 Jun 2024 12:06:48 +0900 Subject: [PATCH 1/4] =?UTF-8?q?fix=20:=20=EC=B5=9C=EA=B7=BC=20=EB=B3=B8=20?= =?UTF-8?q?=EB=89=B4=EC=8A=A4=20=EC=A1=B0=ED=9A=8C=ED=95=98=EA=B8=B0=20API?= =?UTF-8?q?=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/RollTheDice/.DS_Store | Bin 6148 -> 6148 bytes .../RollTheDice.xcodeproj/project.pbxproj | 20 +++ .../View/Debate/ChatList/ChatListView.swift | 26 +++- .../Debate/ChatList/RecentNewsCardView.swift | 121 +++++++++++++++--- .../ChatList/RecentNewsModel/News.swift | 14 ++ .../ChatList/Service/RecentNewsService.swift | 49 +++++++ .../ViewModel/RecentNewsViewModel.swift | 38 ++++++ 7 files changed, 245 insertions(+), 23 deletions(-) create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsModel/News.swift create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/RecentNewsService.swift create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/RecentNewsViewModel.swift diff --git a/iOS/RollTheDice/.DS_Store b/iOS/RollTheDice/.DS_Store index 3e52fcdbeeb138923b6e9766c2a4f1e021649a7e..1c15186344d1bf8f30e95be81449cb90120907f1 100644 GIT binary patch delta 59 zcmZoMXffE}&cw{Dwsi72CcViOOgyY7eG9!`PCm_KIC&Qm&yI"; }; 357699432C09C7B900AD2DA4 /* LoginService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginService.swift; sourceTree = ""; }; 357FC6E92BCE866B00AD8915 /* DetailCardNews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailCardNews.swift; sourceTree = ""; }; + 3586B5552C23D25A006B1458 /* News.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = News.swift; sourceTree = ""; }; + 3586B5572C23D27C006B1458 /* RecentNewsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentNewsService.swift; sourceTree = ""; }; + 3586B5592C23D296006B1458 /* RecentNewsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentNewsViewModel.swift; sourceTree = ""; }; 6C32379E2B7C376D00B699AB /* Bookmarks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bookmarks.swift; sourceTree = ""; }; 6C3237A02B7C377600B699AB /* BookmarkViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkViewModel.swift; sourceTree = ""; }; 6C3237A42B7C37D100B699AB /* BookmarkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkView.swift; sourceTree = ""; }; @@ -224,6 +230,7 @@ isa = PBXGroup; children = ( 3544D73F2C228EFC007DBD18 /* CreateDebateRoomService.swift */, + 3586B5572C23D27C006B1458 /* RecentNewsService.swift */, ); path = Service; sourceTree = ""; @@ -232,6 +239,7 @@ isa = PBXGroup; children = ( 3544D7422C228F54007DBD18 /* CreateDebateRoomViewModel.swift */, + 3586B5592C23D296006B1458 /* RecentNewsViewModel.swift */, ); path = ViewModel; sourceTree = ""; @@ -252,6 +260,14 @@ path = Splah; sourceTree = ""; }; + 3586B5542C23D246006B1458 /* RecentNewsModel */ = { + isa = PBXGroup; + children = ( + 3586B5552C23D25A006B1458 /* News.swift */, + ); + path = RecentNewsModel; + sourceTree = ""; + }; 6C32379D2B7C374E00B699AB /* BookmarkCard */ = { isa = PBXGroup; children = ( @@ -283,6 +299,7 @@ 6C41B8D62BE1048500274FA4 /* ChatList */ = { isa = PBXGroup; children = ( + 3586B5542C23D246006B1458 /* RecentNewsModel */, 3544D7412C228F39007DBD18 /* ViewModel */, 3544D73E2C228EDB007DBD18 /* Service */, 6C41B8D92BE104A800274FA4 /* RecentNewsCardView.swift */, @@ -811,10 +828,12 @@ 6C77048F2B7229B1001B17CB /* NewsListView.swift in Sources */, 357666132BBD54AA002C226A /* SplashView.swift in Sources */, 6C4F7BAD2BDE510900ED01DA /* DailyReportViewModel.swift in Sources */, + 3586B5582C23D27C006B1458 /* RecentNewsService.swift in Sources */, 6C3237A72B7C37E500B699AB /* BookmarksListViewModel.swift in Sources */, 6C454A822B9DAFA3006FD9D0 /* Path.swift in Sources */, 6C94799E2BD3C00C00D5AEEB /* Image.swift in Sources */, 6C454A842B9DAFCB006FD9D0 /* PathType.swift in Sources */, + 3586B55A2C23D296006B1458 /* RecentNewsViewModel.swift in Sources */, 6CF130AF2BAB0C4F00A437B6 /* AuthenticatedView.swift in Sources */, 6C3237B52B7C433D00B699AB /* ChatTypeView.swift in Sources */, 6CF130B22BAB74BA00A437B6 /* NewsService.swift in Sources */, @@ -829,6 +848,7 @@ 6CC673802C233A65009FB30E /* ScoopAPIStatistics.swift in Sources */, 6C7704A12B722CEB001B17CB /* ProfileView.swift in Sources */, 6C4F7BAB2BDE50C600ED01DA /* DailyReportModel.swift in Sources */, + 3586B5562C23D25A006B1458 /* News.swift in Sources */, 6C3237B72B7C434600B699AB /* ChatType.swift in Sources */, 6CE103152BD56CA800498AA4 /* DailyBarChartView.swift in Sources */, 6CE2AC122BD43FB900416A02 /* SignInView.swift in Sources */, diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift index 67ed690b..9fc31f13 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift @@ -10,6 +10,7 @@ import SwiftUI struct ChatListView: View { @EnvironmentObject var pathModel: PathModel + @StateObject private var newsViewModel = RecentNewsViewModel() var body: some View { ZStack { @@ -32,14 +33,27 @@ struct ChatListView: View { .foregroundStyle(.basicWhite) .font(.pretendardBold32) HStack { - RecentNewsCardView() - Spacer() - RecentNewsCardView() - Spacer() - RecentNewsCardView() +// RecentNewsCardView() +// Spacer() +// RecentNewsCardView() +// Spacer() +// RecentNewsCardView() + if newsViewModel.news.isEmpty { + Text("최근 읽은 뉴스를 불러오는 중...") + .onAppear { + print("뷰가 나타남 - 최근 읽은 뉴스 조회 시작") + newsViewModel.fetchViewedHistory() + } + } else { + ForEach(newsViewModel.news.prefix(3), id: \.id) { news in + RecentNewsCardView(news: news) + Spacer() + } + } + } + .padding() } } - } @ViewBuilder var debateChatListView: some View { diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift index 8d5ff093..c707b95f 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift @@ -5,27 +5,116 @@ // Created by Subeen on 4/30/24. // +//import SwiftUI +// +//struct RecentNewsCardView: View { +// @EnvironmentObject var pathModel: PathModel +// @StateObject private var viewModel = CreateDebateRoomViewModel() +// @State private var topic: String = "" +// +// var body: some View { +// HStack { +// titleView +// } +//// .frame(width: 260, height: 244) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// } +// +// var titleView: some View { +// ZStack { +// VStack(alignment: .center, spacing: 20) { +// Text("📌") +// .font(.title) +// Text("내 안경 못 봤어?\" 핸드폰이 알려준다…구글 \'일상 AI\' 공략 [팩플]") +// .multilineTextAlignment(.center) +// .foregroundStyle(.gray07) +// .font(.pretendardBold24) +// .frame(width: 240, height: 96) +// .padding(.horizontal, 10) +// .padding(.vertical, 30) +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 2)) +// .overlay { +// RoundedRectangle(cornerRadius: 2) +// .stroke(Color.gray05, lineWidth: 1.0) +// } +// .shadow(color: .basicBlack.opacity(0.1), radius: 2) +// Button { +// print("버튼 클릭됨 - 주제: \(topic)") +// viewModel.createDebate(topic: topic) +// pathModel.paths.append(.createdebateroom) +// } label: { +// Text("토론 시작하기") +// .foregroundStyle(.basicWhite) +// .font(.pretendardRegular14) +// .padding(.horizontal, 38) +// .padding(.vertical, 10) +// .background(.primary01) +// .clipShape(RoundedRectangle(cornerRadius: 16)) +// } +// } +// +// if let debateID = viewModel.debateID { +// Text("토론방 ID: \(debateID)") +// } +// +// if let errorMessage = viewModel.errorMessage { +// Text("Error: \(errorMessage)") +// .foregroundColor(.red) +// } +// } +// .padding(.horizontal, 20) +// .padding(.top, 24) +// .padding(.bottom, 32) +// .background(.gray02) +// } +//} +// +//#Preview { +// RecentNewsCardView() +//} + import SwiftUI +import Combine struct RecentNewsCardView: View { + let news: News @EnvironmentObject var pathModel: PathModel - @StateObject private var viewModel = CreateDebateRoomViewModel() +// @StateObject private var newsViewModel = RecentNewsViewModel() + @StateObject private var debateRoomViewModel = CreateDebateRoomViewModel() @State private var topic: String = "" - var body: some View { - HStack { - titleView - } -// .frame(width: 260, height: 244) - .clipShape(RoundedRectangle(cornerRadius: 8)) - } +// var body: some View { +// VStack { +// if let news = newsViewModel.news.first { +// HStack { +// titleView(news: news) +// } +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// } else { +// Text("최근 읽은 뉴스를 불러오는 중...") +// .onAppear { +// print("뷰가 나타남 - 최근 읽은 뉴스 조회 시작") +// newsViewModel.fetchViewedHistory() +// } +// } +// } +// } +// + var body: some View { + HStack { + titleView + } + .clipShape(RoundedRectangle(cornerRadius: 8)) + } + - var titleView: some View { + var titleView : some View { ZStack { VStack(alignment: .center, spacing: 20) { Text("📌") .font(.title) - Text("내 안경 못 봤어?\" 핸드폰이 알려준다…구글 \'일상 AI\' 공략 [팩플]") + Text(news.title) .multilineTextAlignment(.center) .foregroundStyle(.gray07) .font(.pretendardBold24) @@ -40,8 +129,9 @@ struct RecentNewsCardView: View { } .shadow(color: .basicBlack.opacity(0.1), radius: 2) Button { - print("버튼 클릭됨 - 주제: \(topic)") - viewModel.createDebate(topic: topic) + print("버튼 클릭됨 - 주제: \(news.title)") + topic = news.title + debateRoomViewModel.createDebate(topic: topic) pathModel.paths.append(.createdebateroom) } label: { Text("토론 시작하기") @@ -54,11 +144,11 @@ struct RecentNewsCardView: View { } } - if let debateID = viewModel.debateID { + if let debateID = debateRoomViewModel.debateID { Text("토론방 ID: \(debateID)") } - if let errorMessage = viewModel.errorMessage { + if let errorMessage = debateRoomViewModel.errorMessage { Text("Error: \(errorMessage)") .foregroundColor(.red) } @@ -70,6 +160,3 @@ struct RecentNewsCardView: View { } } -#Preview { - RecentNewsCardView() -} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsModel/News.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsModel/News.swift new file mode 100644 index 00000000..c2204feb --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsModel/News.swift @@ -0,0 +1,14 @@ +// +// News.swift +// RollTheDice +// +// Created by 신예진 on 6/20/24. +// + +import Foundation + +//MARK : 최근 읽은 뉴스 Model +struct News: Identifiable, Codable { + let id: Int + let title: String +} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/RecentNewsService.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/RecentNewsService.swift new file mode 100644 index 00000000..29c62fc8 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/RecentNewsService.swift @@ -0,0 +1,49 @@ +// +// RecentNewsService.swift +// RollTheDice +// +// Created by 신예진 on 6/20/24. +// + +import Foundation +import Moya + +//MARK : 최근읽은 뉴스 관련 Service +enum RecentNewsService { + case getViewedHistory +} + +extension RecentNewsService: TargetType { + var baseURL: URL { + return URL(string: "http://roll-the-dice.store:8080")! + } + + var path: String { + switch self { + case .getViewedHistory: + return "/news/viewed-history" + } + } + + var method: Moya.Method { + switch self { + case .getViewedHistory: + return .get + } + } + + var task: Task { + return .requestPlain + } + + var headers: [String : String]? { + guard let token = TokenManager.shared.accessToken else { + return nil + } + return ["Authorization": "Bearer \(token)"] + } + + var sampleData: Data { + return Data() + } +} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/RecentNewsViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/RecentNewsViewModel.swift new file mode 100644 index 00000000..dc8879d8 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/RecentNewsViewModel.swift @@ -0,0 +1,38 @@ +// +// RecentNewsViewModel.swift +// RollTheDice +// +// Created by 신예진 on 6/20/24. +// + +import Foundation +import Combine +import Moya +import Combine + +class RecentNewsViewModel: ObservableObject { + @Published var news: [News] = [] + private var cancellables = Set() + private let provider = MoyaProvider() + + func fetchViewedHistory() { + print("최근 읽은 뉴스 조회 요청 시작") + provider.requestPublisher(.getViewedHistory) + .map([News].self) + .receive(on: DispatchQueue.main) + .sink(receiveCompletion: { completion in + switch completion { + case .failure(let error): + print("최근 읽은 뉴스 조회 실패 - 에러: \(error)") + case .finished: + print("최근 읽은 뉴스 조회 완료") + } + }, receiveValue: { [weak self] news in + self?.news = news + for item in news { + print("최근 읽은 뉴스 조회 성공 - 뉴스 id: \(item.id), 뉴스 제목: \(item.title)") + } + }) + .store(in: &cancellables) + } +} From 4b68972fc74797756bab7236f19ca7fdf0dc806f Mon Sep 17 00:00:00 2001 From: yeahzxnn Date: Thu, 20 Jun 2024 12:24:59 +0900 Subject: [PATCH 2/4] =?UTF-8?q?fix=20:=20ChatGPT=EA=B0=80=20=EB=A8=BC?= =?UTF-8?q?=EC=A0=80=20=ED=86=A0=EB=A1=A0=20=EC=8B=9C=EC=9E=91=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EB=A1=9C=EC=A7=81=EC=9C=BC=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/RollTheDice/.DS_Store | Bin 6148 -> 6148 bytes .../RollTheDice/RollTheDiceApp.swift | 14 +- .../Source/View/Debate/ChatGPT/GPTChat.swift | 4 +- .../Debate/ChatGPT/GPTChatListViewModel.swift | 148 +++++++++++++----- .../View/Debate/ChatGPT/GPTChatView.swift | 143 ++++++++++++++++- .../Debate/ChatList/RecentNewsCardView.swift | 25 ++- .../ViewModel/CreateDebateRoomViewModel.swift | 7 +- 7 files changed, 282 insertions(+), 59 deletions(-) diff --git a/iOS/RollTheDice/.DS_Store b/iOS/RollTheDice/.DS_Store index 1c15186344d1bf8f30e95be81449cb90120907f1..5fbc7ec27315c0b366802e04a5fe123046dc29e3 100644 GIT binary patch delta 19 acmZoMXffE}!NjE1Gx;2o-sTFX9#H^73I=)r delta 19 acmZoMXffE}!NjDtbn-bSz0DO&J)!_Y*anXP diff --git a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift index 5009d613..1fdc82da 100644 --- a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift +++ b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift @@ -46,7 +46,7 @@ struct RollTheDiceApp: App { // 각 뷰마다 .navigationBarBackButtonHidden() 설정하기! switch pathType { case .chatView(isAiMode: true) : - GPTChatView() + GPTChatView(topic: "") .navigationBarBackButtonHidden() case .chatView(isAiMode: false): @@ -67,7 +67,7 @@ struct RollTheDiceApp: App { case .webView(let url): WebView(urlToLoad: url) case .createdebateroom: - GPTChatView() + GPTChatView(topic: "") } }) } @@ -81,13 +81,13 @@ struct RollTheDiceApp: App { // NavigationStack(path: $pathModel.paths) { // MainTabView(newsListViewModel: newsListViewModel) // .navigationDestination(for: PathType.self, destination: { pathType in -// +// // // 각 뷰마다 .navigationBarBackButtonHidden() 설정하기! // switch pathType { // case .chatView(isAiMode: true) : // GPTChatView() // .navigationBarBackButtonHidden() -// +// // case .chatView(isAiMode: false): // Text("user") // .navigationBarBackButtonHidden() @@ -106,10 +106,10 @@ struct RollTheDiceApp: App { // } // }) // } -// +// // .environmentObject(pathModel) -// -// +// +// // } else { // AuthenticatedView() // .environmentObject(pathModel) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChat.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChat.swift index 8112a66b..4fd8da8e 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChat.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChat.swift @@ -8,9 +8,10 @@ import Foundation -struct GPTChat: Hashable { +struct GPTChat: Hashable, Identifiable{ var title: String var messages: [Message] + var id: UUID = .init() // id 속성 추가 init( title: String = "", @@ -26,3 +27,4 @@ struct Message: Hashable, Identifiable { var content: String var isUser: Bool } + diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift index 7d94565e..f3119123 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift @@ -10,31 +10,124 @@ import OpenAI import Combine import Moya +//class GPTChatListViewModel: ObservableObject { +// @Published var chatList: [GPTChat] +// private var cancellables = Set() +// private let provider = MoyaProvider() +// +// // OpenAI API 토큰 관리 +// private let openAI: OpenAI +// +//// // TODO: Token Hidden +//// /// token 추가해야 함 +//// let openAI = OpenAI(apiToken: "") +// +// init( +// topic: String, +// chatList: [GPTChat] = [], +//// .init(title: "토론제목", messages: []), +//// ], +// apiToken: String = "" // 깃허브 보안 이슈상으로 제거 +// ) { +//// self.chatList = chatList +// self.chatList = chatList.isEmpty ? [GPTChat(title: topic, messages: [])] : chatList +// self.openAI = OpenAI(apiToken: apiToken) +// } +//} +// +//extension GPTChatListViewModel { +// /// OpenAI +// func sendNewMessage(index: Int, content: String) { +// print("call sendNewMessage func") +// +// let userMessage = Message(content: content, isUser: true) +// self.chatList[index].messages.append(userMessage) +// +// getBotReply(index: index) +// } +// +// func getBotReply(index: Int) { +// print("call getBotReply func") +// +// let messages = self.chatList[index].messages.map { +// Chat(role: $0.isUser ? .user : .system, content: $0.content) +// } +// +// // openAI.chats( +// // query: .init( +// // model: .gpt3_5Turbo, +// // messages: self.chatList[index].messages.map( +// // {Chat(role: .user, content: $0.content)})) +// // ) { result in +// // switch result { +// // case .success(let success): +// // guard let choice = success.choices.first else { +// // return +// // } +// // let message = choice.message.content +// // +// // DispatchQueue.main.async { +// // self.chatList[index].messages.append(.init(content: message ?? "Error", isUser: false)) +// // print("gpt msg: \(self.chatList[index].messages[1])") +// // } +// // +// // case .failure(let failure): +// // print(failure) +// // } +// // } +// openAI.chats( +// query: .init( +// model: .gpt3_5Turbo, +// messages: messages +// ) +// ) { [weak self] result in +// guard let self = self else { return } +// +// switch result { +// case .success(let success): +// guard let choice = success.choices.first else { +// return +// } +// let message = choice.message.content +// +// DispatchQueue.main.async { +// self.chatList[index].messages.append(.init(content: message ?? "Error", isUser: false)) +// print("gpt msg: \(self.chatList[index].messages.last?.content ?? "Error")") +// } +// +// case .failure(let failure): +// print(failure) +// } +// } +// } +//} + class GPTChatListViewModel: ObservableObject { @Published var chatList: [GPTChat] private var cancellables = Set() - private let provider = MoyaProvider() - - // OpenAI API 토큰 관리 - private let openAI: OpenAI - -// // TODO: Token Hidden -// /// token 추가해야 함 -// let openAI = OpenAI(apiToken: "") + private let provider = MoyaProvider() + private let debateprovider = MoyaProvider() + private let openAI: OpenAI + @Published var topic: String = "" init( - chatList: [GPTChat] = [ - .init(title: "토론제목", messages: []), - ], - apiToken: String = "" // TokenManager를 통해 API 토큰을 관리 + topic: String, + chatList: [GPTChat] = [], + apiToken: String = "" ) { - self.chatList = chatList + self.chatList = chatList.isEmpty ? [GPTChat(title: topic, messages: [])] : chatList self.openAI = OpenAI(apiToken: apiToken) + + // CreateDebateRoomService를 통해 주제를 받아와 초기 메시지를 설정 + CreateDebateRoomViewModel().createDebate(topic: topic) { debateTopic in + let initialMessage = Message(content: "안녕하세요! 오늘의 토론 주제는 '\(debateTopic)'입니다. 이 주제에 대해 어떻게 생각하시나요?", isUser: false) + DispatchQueue.main.async { + self.chatList[0].messages.append(initialMessage) + } + } } -} -extension GPTChatListViewModel { - /// OpenAI + func sendNewMessage(index: Int, content: String) { print("call sendNewMessage func") @@ -51,28 +144,6 @@ extension GPTChatListViewModel { Chat(role: $0.isUser ? .user : .system, content: $0.content) } - // openAI.chats( - // query: .init( - // model: .gpt3_5Turbo, - // messages: self.chatList[index].messages.map( - // {Chat(role: .user, content: $0.content)})) - // ) { result in - // switch result { - // case .success(let success): - // guard let choice = success.choices.first else { - // return - // } - // let message = choice.message.content - // - // DispatchQueue.main.async { - // self.chatList[index].messages.append(.init(content: message ?? "Error", isUser: false)) - // print("gpt msg: \(self.chatList[index].messages[1])") - // } - // - // case .failure(let failure): - // print(failure) - // } - // } openAI.chats( query: .init( model: .gpt3_5Turbo, @@ -99,3 +170,4 @@ extension GPTChatListViewModel { } } } + diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift index b2ecf127..9a460661 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift @@ -10,8 +10,16 @@ import SwiftUI struct GPTChatView: View { @EnvironmentObject var pathModel: PathModel - @StateObject var chatListViewModel = GPTChatListViewModel() - @State var selectedChat: GPTChat? = .init(title: "토론제목입니다", messages: [.init(content: "ChatGPT와의 토론!", isUser: false)]) +// @State var selectedChat: GPTChat? = .init(title: "토론제목입니다", messages: [.init(content: "ChatGPT와의 토론!", isUser: false)]) + @State var selectedChat: GPTChat? + @StateObject var chatListViewModel = GPTChatListViewModel(topic: "토론") + @StateObject var createDebateRoomViewModel = CreateDebateRoomViewModel() + + + init(topic: String) { + _chatListViewModel = StateObject(wrappedValue: GPTChatListViewModel(topic: topic)) + _selectedChat = State(initialValue: GPTChat(title: topic, messages: [.init(content: "\(createDebateRoomViewModel.topic) ChatGPT와의 토론!", isUser: false)])) + } var body: some View { ZStack { @@ -84,7 +92,7 @@ struct GPTChatView: View { } private struct TitleCellView: View { - var title: String + var title: String fileprivate var body: some View { HStack { Text(title) @@ -130,6 +138,129 @@ struct GPTChatView: View { -#Preview { - GPTChatView() -} +//#Preview { +// GPTChatView() +//} + +//struct GPTChatView: View { +// +// @EnvironmentObject var pathModel: PathModel +// @State var selectedChat: GPTChat? +// @StateObject var chatListViewModel: GPTChatListViewModel +// @StateObject var createDebateRoomViewModel = CreateDebateRoomViewModel() +// +// init(topic: String) { +// _chatListViewModel = StateObject(wrappedValue: GPTChatListViewModel(topic: topic)) +// _selectedChat = State(initialValue: GPTChat(title: topic, messages: [.init(content: "\(topic)ChatGPT와의 토론!", isUser: false)])) +// } +// +// var body: some View { +// ZStack { +// Color.backgroundDark.ignoresSafeArea(.all) +// VStack { +// CustomNavigationBar(title: selectedChat?.title ?? "", isDisplayLeadingBtn: true, leadingItems: [(Image(.chevronLeft), {pathModel.paths.popLast()})]) +// MessageTitleView(chatListViewModel: chatListViewModel, selectedChat: $selectedChat) +// } +// } +// } +// +// private struct MessageTitleView: View { +// @ObservedObject var chatListViewModel: GPTChatListViewModel +// @Binding var selectedChat: GPTChat? +// @State var string: String = "" +// @State var index: Int? = 0 +// +// fileprivate var body: some View { +// if chatListViewModel.chatList.isEmpty { +// // TODO: 채팅방 생성 뷰 +// } else { +// HStack { +// ScrollView { +// ForEach(chatListViewModel.chatList.indices, id: \.self) { index in +// Button { +// selectedChat = chatListViewModel.chatList[index] +// } label: { +// TitleCellView(title: chatListViewModel.chatList[index].title) +// } +// } +// } +// if selectedChat != nil { +// VStack { +// ScrollView { +// ForEach(selectedChat?.messages ?? []) { message in +// MessageCellView(message: message) +// } +// } +// Divider() +// +// HStack { +// TextField("Message...", text: $string, axis: .vertical) +// .padding(5) +// .background(Color.gray.opacity(0.1)) +// .foregroundStyle(.basicWhite) +// .cornerRadius(15) +// Button { +// if let index = chatListViewModel.chatList.firstIndex(where: { $0.id == selectedChat?.id }) { +// chatListViewModel.sendNewMessage(index: index, content: string) +// string = "" +// print("왜 채팅하기 버튼 안 눌려?") +// } +// } label: { +// Image(systemName: "paperplane") +// } +// } +// .padding() +// } +// } else { +// // TODO: 채팅방 선택 유도 뷰 +// Spacer() +// } +// } +// } +// } +// } +// +// private struct TitleCellView: View { +// var title: String +// fileprivate var body: some View { +// HStack { +// Text(title) +// .multilineTextAlignment(.leading) +// .padding(.horizontal) +// .background(Color.basicBlack) +// .foregroundStyle(.basicWhite) +// .clipShape(RoundedRectangle(cornerRadius: 15)) +// } +// } +// } +// +// private struct MessageCellView: View { +// var message: Message +// +// fileprivate var body: some View { +// Group { +// if message.isUser { +// HStack { +// Spacer() +// Text(message.content) +// .multilineTextAlignment(.leading) +// .padding() +// .background(Color.blue) +// .foregroundStyle(.white) +// .clipShape(RoundedRectangle(cornerRadius: 15)) +// } +// } else { +// HStack { +// Text(message.content) +// .padding() +// .background(Color.orange) +// .foregroundStyle(.white) +// .clipShape(RoundedRectangle(cornerRadius: 15)) +// Spacer() +// } +// } +// } +// } +// } +//} + diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift index c707b95f..b07a3df6 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift @@ -10,8 +10,9 @@ //struct RecentNewsCardView: View { // @EnvironmentObject var pathModel: PathModel // @StateObject private var viewModel = CreateDebateRoomViewModel() +// @StateObject private var newsviewModel = RecentNewsViewModel() // @State private var topic: String = "" -// +// // var body: some View { // HStack { // titleView @@ -19,7 +20,7 @@ //// .frame(width: 260, height: 244) // .clipShape(RoundedRectangle(cornerRadius: 8)) // } -// +// // var titleView: some View { // ZStack { // VStack(alignment: .center, spacing: 20) { @@ -53,11 +54,11 @@ // .clipShape(RoundedRectangle(cornerRadius: 16)) // } // } -// +// // if let debateID = viewModel.debateID { // Text("토론방 ID: \(debateID)") // } -// +// // if let errorMessage = viewModel.errorMessage { // Text("Error: \(errorMessage)") // .foregroundColor(.red) @@ -74,6 +75,13 @@ // RecentNewsCardView() //} +// +// RecentNewsCardView.swift +// RollTheDice +// +// Created by Subeen on 4/30/24. +// + import SwiftUI import Combine @@ -131,8 +139,12 @@ struct RecentNewsCardView: View { Button { print("버튼 클릭됨 - 주제: \(news.title)") topic = news.title - debateRoomViewModel.createDebate(topic: topic) - pathModel.paths.append(.createdebateroom) + debateRoomViewModel.createDebate(topic: topic) { debateTopic in + pathModel.paths.append(.createdebateroom) + print("토론방 생성 완료 - 주제: \(debateTopic)") + + } +// pathModel.paths.append(.createdebateroom) } label: { Text("토론 시작하기") .foregroundStyle(.basicWhite) @@ -160,3 +172,4 @@ struct RecentNewsCardView: View { } } + diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/CreateDebateRoomViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/CreateDebateRoomViewModel.swift index 3b6cfc9b..c19b0ae7 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/CreateDebateRoomViewModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/CreateDebateRoomViewModel.swift @@ -13,9 +13,12 @@ class CreateDebateRoomViewModel: ObservableObject { private let provider = MoyaProvider() @Published var debateID: Int? @Published var errorMessage: String? + @Published var topic: String = "" + - func createDebate(topic: String) { + func createDebate(topic: String, completion: @escaping (String) -> Void) { print("API 호출 시작 - 토론 주제: \(topic)") + self.topic = topic // 토론 주제 저장 provider.request(.createDebate(topic: topic)) { result in switch result { case .success(let response): @@ -26,6 +29,7 @@ class CreateDebateRoomViewModel: ObservableObject { DispatchQueue.main.async { self.debateID = id print("토론방 생성 성공 - ID: \(id)") + completion(topic) // 주제를 반환하여 초기 메시지 설정 } } } catch { @@ -43,3 +47,4 @@ class CreateDebateRoomViewModel: ObservableObject { } } } + From d9840172e76936fa0254facfce028a0a6cc8ca54 Mon Sep 17 00:00:00 2001 From: yeahzxnn Date: Thu, 20 Jun 2024 12:38:28 +0900 Subject: [PATCH 3/4] =?UTF-8?q?fix=20:=20=ED=86=A0=EB=A1=A0=20=EC=A2=85?= =?UTF-8?q?=EB=A3=8C=20API=20=EC=97=B0=EB=8F=99=20=EB=B0=8F=20=ED=86=A0?= =?UTF-8?q?=EB=A1=A0=20=EC=A2=85=EB=A3=8C=20=ED=9B=84=20=ED=86=A0=EB=A1=A0?= =?UTF-8?q?=20=ED=83=AD=20=EB=A9=94=EC=9D=B8=20=ED=99=94=EB=A9=B4=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=8F=8C=EC=95=84=EC=98=A4=EB=8A=94=20=EA=B2=83?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/RollTheDice/.DS_Store | Bin 6148 -> 6148 bytes .../RollTheDice.xcodeproj/project.pbxproj | 16 +++++++ .../RollTheDice/RollTheDiceApp.swift | 4 +- .../Debate/ChatGPT/GPTChatListViewModel.swift | 5 +- .../View/Debate/ChatGPT/GPTChatView.swift | 45 ++++++++++++++++-- .../ChatGPT/Service/EndDebateService.swift | 43 +++++++++++++++++ .../ViewModel/EndDebateViewModel.swift | 26 ++++++++++ .../View/Debate/ChatList/ChatListView.swift | 37 +++++++------- 8 files changed, 150 insertions(+), 26 deletions(-) create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/Service/EndDebateService.swift create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/ViewModel/EndDebateViewModel.swift diff --git a/iOS/RollTheDice/.DS_Store b/iOS/RollTheDice/.DS_Store index 5fbc7ec27315c0b366802e04a5fe123046dc29e3..c839e8159ef3ba5841fdb675867dc10d5936ed32 100644 GIT binary patch delta 57 zcmZoMXffE}!Ng=ceeyXby~!0!Jgf~|hi1K*e45E{@-8HvJ>!JUg3RAoCN{8bX6N|J F4*+8T6;l8J delta 57 zcmZoMXffE}!NjE1Gx;2o-sB1<9@dk-h2AeGpJp>Pjj E0a=R__W%F@ diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 544ebea0..21b33357 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -11,6 +11,8 @@ 3544D7402C228EFC007DBD18 /* CreateDebateRoomService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3544D73F2C228EFC007DBD18 /* CreateDebateRoomService.swift */; }; 3544D7432C228F54007DBD18 /* CreateDebateRoomViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3544D7422C228F54007DBD18 /* CreateDebateRoomViewModel.swift */; }; 3544D7462C229436007DBD18 /* ChatService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3544D7452C229436007DBD18 /* ChatService.swift */; }; + 35710D732C23D9030041ECD2 /* EndDebateViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35710D722C23D9030041ECD2 /* EndDebateViewModel.swift */; }; + 35710D752C23D9350041ECD2 /* EndDebateService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35710D742C23D9350041ECD2 /* EndDebateService.swift */; }; 357666102BBD4BF6002C226A /* ReportListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3576660F2BBD4BF6002C226A /* ReportListView.swift */; }; 357666132BBD54AA002C226A /* SplashView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 357666122BBD54AA002C226A /* SplashView.swift */; }; 3576993A2C09C1EB00AD2DA4 /* KakaoSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 357699392C09C1EB00AD2DA4 /* KakaoSDK */; }; @@ -114,6 +116,8 @@ 3544D73F2C228EFC007DBD18 /* CreateDebateRoomService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateDebateRoomService.swift; sourceTree = ""; }; 3544D7422C228F54007DBD18 /* CreateDebateRoomViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateDebateRoomViewModel.swift; sourceTree = ""; }; 3544D7452C229436007DBD18 /* ChatService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatService.swift; sourceTree = ""; }; + 35710D722C23D9030041ECD2 /* EndDebateViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndDebateViewModel.swift; sourceTree = ""; }; + 35710D742C23D9350041ECD2 /* EndDebateService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndDebateService.swift; sourceTree = ""; }; 3576660F2BBD4BF6002C226A /* ReportListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportListView.swift; sourceTree = ""; }; 357666122BBD54AA002C226A /* SplashView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashView.swift; sourceTree = ""; }; 357699432C09C7B900AD2DA4 /* LoginService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginService.swift; sourceTree = ""; }; @@ -248,10 +252,19 @@ isa = PBXGroup; children = ( 3544D7452C229436007DBD18 /* ChatService.swift */, + 35710D742C23D9350041ECD2 /* EndDebateService.swift */, ); path = Service; sourceTree = ""; }; + 35710D712C23D8F10041ECD2 /* ViewModel */ = { + isa = PBXGroup; + children = ( + 35710D722C23D9030041ECD2 /* EndDebateViewModel.swift */, + ); + path = ViewModel; + sourceTree = ""; + }; 357666112BBD5494002C226A /* Splah */ = { isa = PBXGroup; children = ( @@ -563,6 +576,7 @@ 6CDB29F72BAA06FB0081037B /* ChatGPT */ = { isa = PBXGroup; children = ( + 35710D712C23D8F10041ECD2 /* ViewModel */, 3544D7442C229428007DBD18 /* Service */, 6CDB29F82BAA07350081037B /* GPTChat.swift */, 6CDB29FA2BAA07B10081037B /* GPTChatViewModel.swift */, @@ -806,6 +820,7 @@ 6CF130C92BAB7CC200A437B6 /* BaseTargetType.swift in Sources */, 6C7651492BF5FDB900196536 /* WebView.swift in Sources */, 6CDB29FF2BAA08280081037B /* GPTChatListViewModel.swift in Sources */, + 35710D752C23D9350041ECD2 /* EndDebateService.swift in Sources */, 6CF130AD2BAB0C4400A437B6 /* AuthenticationViewModel.swift in Sources */, 3544D7402C228EFC007DBD18 /* CreateDebateRoomService.swift in Sources */, 6CDB29F92BAA07350081037B /* GPTChat.swift in Sources */, @@ -858,6 +873,7 @@ 6C454A7C2B9DA71C006FD9D0 /* SignUpView.swift in Sources */, 6C41B8DA2BE104A800274FA4 /* RecentNewsCardView.swift in Sources */, 3509091A2C1C1248007D76A1 /* TokenManager.swift in Sources */, + 35710D732C23D9030041ECD2 /* EndDebateViewModel.swift in Sources */, 6CF130C72BAB7B9800A437B6 /* ScoopAPINews.swift in Sources */, 6CC6737E2C233443009FB30E /* StatisticsService.swift in Sources */, 6C7651402BF37F3400196536 /* Log.swift in Sources */, diff --git a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift index 1fdc82da..474be745 100644 --- a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift +++ b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift @@ -46,7 +46,7 @@ struct RollTheDiceApp: App { // 각 뷰마다 .navigationBarBackButtonHidden() 설정하기! switch pathType { case .chatView(isAiMode: true) : - GPTChatView(topic: "") + GPTChatView(topic: "",roomId: 74) .navigationBarBackButtonHidden() case .chatView(isAiMode: false): @@ -67,7 +67,7 @@ struct RollTheDiceApp: App { case .webView(let url): WebView(urlToLoad: url) case .createdebateroom: - GPTChatView(topic: "") + GPTChatView(topic: "",roomId: 74) } }) } diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift index f3119123..c99720f8 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift @@ -107,13 +107,14 @@ class GPTChatListViewModel: ObservableObject { private var cancellables = Set() private let provider = MoyaProvider() private let debateprovider = MoyaProvider() + private let enddebateprovider = MoyaProvider() private let openAI: OpenAI @Published var topic: String = "" init( topic: String, chatList: [GPTChat] = [], - apiToken: String = "" + apiToken: String = "" //깃허브 보안 이슈로 계속 제거해야됨. ) { self.chatList = chatList.isEmpty ? [GPTChat(title: topic, messages: [])] : chatList self.openAI = OpenAI(apiToken: apiToken) @@ -126,7 +127,6 @@ class GPTChatListViewModel: ObservableObject { } } } - func sendNewMessage(index: Int, content: String) { print("call sendNewMessage func") @@ -170,4 +170,3 @@ class GPTChatListViewModel: ObservableObject { } } } - diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift index 9a460661..978e4e4c 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift @@ -13,10 +13,12 @@ struct GPTChatView: View { // @State var selectedChat: GPTChat? = .init(title: "토론제목입니다", messages: [.init(content: "ChatGPT와의 토론!", isUser: false)]) @State var selectedChat: GPTChat? @StateObject var chatListViewModel = GPTChatListViewModel(topic: "토론") - @StateObject var createDebateRoomViewModel = CreateDebateRoomViewModel() + @StateObject var createDebateRoomViewModel = CreateDebateRoomViewModel() + @StateObject private var viewModel = EndDebateViewModel() + var roomId: Int - - init(topic: String) { + init(topic: String, roomId: Int) { + self.roomId = roomId _chatListViewModel = StateObject(wrappedValue: GPTChatListViewModel(topic: topic)) _selectedChat = State(initialValue: GPTChat(title: topic, messages: [.init(content: "\(createDebateRoomViewModel.topic) ChatGPT와의 토론!", isUser: false)])) } @@ -26,7 +28,9 @@ struct GPTChatView: View { Color.backgroundDark.ignoresSafeArea(.all) VStack { CustomNavigationBar(title: selectedChat?.title ?? "", isDisplayLeadingBtn: true, leadingItems: [(Image(.chevronLeft), {pathModel.paths.popLast()})]) - MessageTitleView(chatListViewModel: chatListViewModel, selectedChat: $selectedChat) + + MessageTitleView(chatListViewModel: chatListViewModel, selectedChat: $selectedChat, roomId: roomId) + } } } @@ -37,6 +41,10 @@ struct GPTChatView: View { @Binding var selectedChat: GPTChat? @State var string: String = "" @State var index: Int? = 0 + @StateObject private var viewModel = EndDebateViewModel() + var roomId: Int + @EnvironmentObject var pathModel: PathModel + fileprivate var body: some View { if chatListViewModel.chatList.isEmpty { @@ -60,6 +68,33 @@ struct GPTChatView: View { MessageCellView(message: message) } } + + //MARK : 토론 종료 버튼 + Button(action: { + print("토론종료버튼 눌림!") + viewModel.endDebate(roomId: "\(roomId)") { success in + if success { + print("토론이 종료되었습니다.") +// pathModel.paths.append(.debateSummaryView) + pathModel.paths.popLast() + } else { + print("토론 종료에 실패했습니다.") + } + } + + + }) { + Text("토론종료") + .font(.title3.weight(.semibold)) + .foregroundColor(.white) + .padding() + .background(Color.primary01) + .cornerRadius(15) + .shadow(radius: 4, x: 0, y: 4) + } + .frame(width: 100, height: 30) + .padding(.bottom, 20) + Divider() HStack { @@ -75,6 +110,8 @@ struct GPTChatView: View { string = "" } label: { Image(systemName: "paperplane") + .foregroundColor(.primary01) + } } .padding() diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/Service/EndDebateService.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/Service/EndDebateService.swift new file mode 100644 index 00000000..af1fdf4f --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/Service/EndDebateService.swift @@ -0,0 +1,43 @@ +// +// EndDebateService.swift +// RollTheDice +// +// Created by 신예진 on 6/20/24. +// + +import Foundation +import Moya + +enum EndDebateService { + case endDebate(roomId: String) +} + +extension EndDebateService: TargetType { + var baseURL: URL { + return URL(string: "http://roll-the-dice.store:8080")! + } + + var path: String { + switch self { + case .endDebate(let roomId): + return "/debates/\(roomId)" + } + } + + var method: Moya.Method { + return .patch + } + + var task: Task { + return .requestPlain + } + + var headers: [String : String]? { + guard let token = TokenManager.shared.accessToken else { return nil } + return ["Authorization": "Bearer \(token)"] + } + + var sampleData: Data { + return Data() + } +} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/ViewModel/EndDebateViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/ViewModel/EndDebateViewModel.swift new file mode 100644 index 00000000..a8f42303 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/ViewModel/EndDebateViewModel.swift @@ -0,0 +1,26 @@ +// +// EndDebateViewModel.swift +// RollTheDice +// +// Created by 신예진 on 6/20/24. +// + +import Foundation +import Moya + +class EndDebateViewModel: ObservableObject { + private let provider = MoyaProvider() + + func endDebate(roomId: String, completion: @escaping (Bool) -> Void) { + provider.request(.endDebate(roomId: roomId)) { result in + switch result { + case .success: + print("토론 종료 성공") + completion(true) + case .failure: + print("토론 종료 실패") + completion(false) + } + } + } +} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift index 9fc31f13..19e20b2b 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift @@ -11,7 +11,7 @@ struct ChatListView: View { @EnvironmentObject var pathModel: PathModel @StateObject private var newsViewModel = RecentNewsViewModel() - + var body: some View { ZStack { Color.backgroundDark.ignoresSafeArea(.all) @@ -32,28 +32,30 @@ struct ChatListView: View { Text("최근 본 뉴스") .foregroundStyle(.basicWhite) .font(.pretendardBold32) - HStack { +// HStack { // RecentNewsCardView() // Spacer() // RecentNewsCardView() // Spacer() // RecentNewsCardView() - if newsViewModel.news.isEmpty { - Text("최근 읽은 뉴스를 불러오는 중...") - .onAppear { - print("뷰가 나타남 - 최근 읽은 뉴스 조회 시작") - newsViewModel.fetchViewedHistory() +// } + HStack { + if newsViewModel.news.isEmpty { + Text("최근 읽은 뉴스를 불러오는 중...") + .onAppear { + print("뷰가 나타남 - 최근 읽은 뉴스 조회 시작") + newsViewModel.fetchViewedHistory() + } + } else { + ForEach(newsViewModel.news.prefix(3), id: \.id) { news in + RecentNewsCardView(news: news) + Spacer() } - } else { - ForEach(newsViewModel.news.prefix(3), id: \.id) { news in - RecentNewsCardView(news: news) - Spacer() } } - } - .padding() - } + .padding() } + } @ViewBuilder var debateChatListView: some View { @@ -84,7 +86,8 @@ struct ChatListView: View { Button { pathModel.paths.append(.chatView(isAiMode: true)) } label: { - Image(.chevronRight) + Image(systemName: "quote.bubble") + .background(.gray01) } } .background(.gray01) @@ -219,8 +222,8 @@ struct ChatListView: View { Button { pathModel.paths.append(.debateSummaryView) } label: { - Image(.chevronLeft) -// .background(.gray01) + Image(systemName: "quote.bubble") + .background(.gray01) } .frame(width: 80, height: 80) From 12865a8ab64e37f54c99d0f4721d5b65ba280951 Mon Sep 17 00:00:00 2001 From: yeahzxnn Date: Thu, 20 Jun 2024 12:44:50 +0900 Subject: [PATCH 4/4] =?UTF-8?q?fix=20:=20=EC=B1=84=ED=8C=85=EB=B0=A9=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EB=B6=88=EB=9F=AC=EC=98=A4=EA=B8=B0=20API?= =?UTF-8?q?=20=EC=97=B0=EB=8F=99=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/RollTheDice/.DS_Store | Bin 6148 -> 6148 bytes .../RollTheDice.xcodeproj/project.pbxproj | 44 ++ .../View/Debate/ChatList/ChatListView.swift | 413 ++++++++++-------- .../GetDebateRoomModel/GetDebateRoom.swift | 15 + .../Service/GetDebateRoomService.swift | 50 +++ .../ViewModel/GetDebateRoomViewModel.swift | 34 ++ .../Debate/Summary/DebateSummaryView.swift | 6 +- .../Service/DebateSummaryService.swift | 43 ++ .../ViewModel/DebateSummaryViewModel.swift | 46 ++ 9 files changed, 473 insertions(+), 178 deletions(-) create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/GetDebateRoomModel/GetDebateRoom.swift create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/GetDebateRoomService.swift create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/GetDebateRoomViewModel.swift create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/Service/DebateSummaryService.swift create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/ViewModel/DebateSummaryViewModel.swift diff --git a/iOS/RollTheDice/.DS_Store b/iOS/RollTheDice/.DS_Store index c839e8159ef3ba5841fdb675867dc10d5936ed32..01b0d69344641ec4624617b694b10e558d0d4a82 100644 GIT binary patch delta 57 zcmZoMXffE}!NimuHu)Tr-sB1<9@bRB&Y*XbPcs=#-i5@oXFRZ3kog>Pjj E0YMrRN&o-= delta 57 zcmZoMXffE}!Ng=ceeyXby~!0!Jgf~|hi1K*e45E{@-8HvJ>!JUg3RAoCN{8bX6N|J F4*+8T6;l8J diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 21b33357..d7ffd3e1 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -13,6 +13,11 @@ 3544D7462C229436007DBD18 /* ChatService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3544D7452C229436007DBD18 /* ChatService.swift */; }; 35710D732C23D9030041ECD2 /* EndDebateViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35710D722C23D9030041ECD2 /* EndDebateViewModel.swift */; }; 35710D752C23D9350041ECD2 /* EndDebateService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35710D742C23D9350041ECD2 /* EndDebateService.swift */; }; + 35710D772C23DBEA0041ECD2 /* DebateSummaryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35710D762C23DBEA0041ECD2 /* DebateSummaryViewModel.swift */; }; + 35710D7B2C23DC360041ECD2 /* DebateSummaryService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35710D7A2C23DC360041ECD2 /* DebateSummaryService.swift */; }; + 35710D7D2C23DC6A0041ECD2 /* GetDebateRoomViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35710D7C2C23DC6A0041ECD2 /* GetDebateRoomViewModel.swift */; }; + 35710D7F2C23DC830041ECD2 /* GetDebateRoomService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35710D7E2C23DC830041ECD2 /* GetDebateRoomService.swift */; }; + 35710D822C23DCA40041ECD2 /* GetDebateRoom.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35710D812C23DCA40041ECD2 /* GetDebateRoom.swift */; }; 357666102BBD4BF6002C226A /* ReportListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3576660F2BBD4BF6002C226A /* ReportListView.swift */; }; 357666132BBD54AA002C226A /* SplashView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 357666122BBD54AA002C226A /* SplashView.swift */; }; 3576993A2C09C1EB00AD2DA4 /* KakaoSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 357699392C09C1EB00AD2DA4 /* KakaoSDK */; }; @@ -118,6 +123,11 @@ 3544D7452C229436007DBD18 /* ChatService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatService.swift; sourceTree = ""; }; 35710D722C23D9030041ECD2 /* EndDebateViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndDebateViewModel.swift; sourceTree = ""; }; 35710D742C23D9350041ECD2 /* EndDebateService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndDebateService.swift; sourceTree = ""; }; + 35710D762C23DBEA0041ECD2 /* DebateSummaryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebateSummaryViewModel.swift; sourceTree = ""; }; + 35710D7A2C23DC360041ECD2 /* DebateSummaryService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebateSummaryService.swift; sourceTree = ""; }; + 35710D7C2C23DC6A0041ECD2 /* GetDebateRoomViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetDebateRoomViewModel.swift; sourceTree = ""; }; + 35710D7E2C23DC830041ECD2 /* GetDebateRoomService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetDebateRoomService.swift; sourceTree = ""; }; + 35710D812C23DCA40041ECD2 /* GetDebateRoom.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetDebateRoom.swift; sourceTree = ""; }; 3576660F2BBD4BF6002C226A /* ReportListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportListView.swift; sourceTree = ""; }; 357666122BBD54AA002C226A /* SplashView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashView.swift; sourceTree = ""; }; 357699432C09C7B900AD2DA4 /* LoginService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginService.swift; sourceTree = ""; }; @@ -235,6 +245,7 @@ children = ( 3544D73F2C228EFC007DBD18 /* CreateDebateRoomService.swift */, 3586B5572C23D27C006B1458 /* RecentNewsService.swift */, + 35710D7E2C23DC830041ECD2 /* GetDebateRoomService.swift */, ); path = Service; sourceTree = ""; @@ -244,6 +255,7 @@ children = ( 3544D7422C228F54007DBD18 /* CreateDebateRoomViewModel.swift */, 3586B5592C23D296006B1458 /* RecentNewsViewModel.swift */, + 35710D7C2C23DC6A0041ECD2 /* GetDebateRoomViewModel.swift */, ); path = ViewModel; sourceTree = ""; @@ -265,6 +277,30 @@ path = ViewModel; sourceTree = ""; }; + 35710D782C23DC100041ECD2 /* ViewModel */ = { + isa = PBXGroup; + children = ( + 35710D762C23DBEA0041ECD2 /* DebateSummaryViewModel.swift */, + ); + path = ViewModel; + sourceTree = ""; + }; + 35710D792C23DC250041ECD2 /* Service */ = { + isa = PBXGroup; + children = ( + 35710D7A2C23DC360041ECD2 /* DebateSummaryService.swift */, + ); + path = Service; + sourceTree = ""; + }; + 35710D802C23DC970041ECD2 /* GetDebateRoomModel */ = { + isa = PBXGroup; + children = ( + 35710D812C23DCA40041ECD2 /* GetDebateRoom.swift */, + ); + path = GetDebateRoomModel; + sourceTree = ""; + }; 357666112BBD5494002C226A /* Splah */ = { isa = PBXGroup; children = ( @@ -312,6 +348,7 @@ 6C41B8D62BE1048500274FA4 /* ChatList */ = { isa = PBXGroup; children = ( + 35710D802C23DC970041ECD2 /* GetDebateRoomModel */, 3586B5542C23D246006B1458 /* RecentNewsModel */, 3544D7412C228F39007DBD18 /* ViewModel */, 3544D73E2C228EDB007DBD18 /* Service */, @@ -621,6 +658,8 @@ 6CE103182BD57A1600498AA4 /* Summary */ = { isa = PBXGroup; children = ( + 35710D792C23DC250041ECD2 /* Service */, + 35710D782C23DC100041ECD2 /* ViewModel */, 6CE103192BD57A2500498AA4 /* DebateSummaryView.swift */, ); path = Summary; @@ -813,6 +852,7 @@ 6CE103102BD56A5B00498AA4 /* TypeReportViewModel.swift in Sources */, 6C5B0C8A2C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift in Sources */, 6CF130C52BAB79DE00A437B6 /* ScoopAPI.swift in Sources */, + 35710D822C23DCA40041ECD2 /* GetDebateRoom.swift in Sources */, 6CE103132BD56B1200498AA4 /* DailyReportView.swift in Sources */, 6C454A7A2B9DA67C006FD9D0 /* SignUpViewModel.swift in Sources */, 6CC6737A2C217C4B009FB30E /* ScoopAPILogin.swift in Sources */, @@ -829,6 +869,7 @@ 6C41B8D22BDE696200274FA4 /* NewsType.swift in Sources */, 357666102BBD4BF6002C226A /* ReportListView.swift in Sources */, 6C41B8D42BDE6D2500274FA4 /* TypePieChartView.swift in Sources */, + 35710D772C23DBEA0041ECD2 /* DebateSummaryViewModel.swift in Sources */, 6C3237A12B7C377600B699AB /* BookmarkViewModel.swift in Sources */, 6C7651462BF5B45A00196536 /* DetailNews.swift in Sources */, 6C3237AC2B7C382200B699AB /* NewsList.swift in Sources */, @@ -873,9 +914,12 @@ 6C454A7C2B9DA71C006FD9D0 /* SignUpView.swift in Sources */, 6C41B8DA2BE104A800274FA4 /* RecentNewsCardView.swift in Sources */, 3509091A2C1C1248007D76A1 /* TokenManager.swift in Sources */, + 35710D7D2C23DC6A0041ECD2 /* GetDebateRoomViewModel.swift in Sources */, + 35710D7B2C23DC360041ECD2 /* DebateSummaryService.swift in Sources */, 35710D732C23D9030041ECD2 /* EndDebateViewModel.swift in Sources */, 6CF130C72BAB7B9800A437B6 /* ScoopAPINews.swift in Sources */, 6CC6737E2C233443009FB30E /* StatisticsService.swift in Sources */, + 35710D7F2C23DC830041ECD2 /* GetDebateRoomService.swift in Sources */, 6C7651402BF37F3400196536 /* Log.swift in Sources */, 6CE1031A2BD57A2500498AA4 /* DebateSummaryView.swift in Sources */, 6CE1030C2BD56A4000498AA4 /* TypeReportView.swift in Sources */, diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift index 19e20b2b..17357ea8 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift @@ -11,7 +11,12 @@ struct ChatListView: View { @EnvironmentObject var pathModel: PathModel @StateObject private var newsViewModel = RecentNewsViewModel() - + @StateObject private var viewModel = DebateSummaryViewModel() + @StateObject private var endDebateViewModel = EndDebateViewModel() + @State private var roomId: String = "" // EndDebateViewModel로부터 받아올 roomId + @StateObject private var getdebateroomviewModel = GetDebateRoomViewModel() + + var body: some View { ZStack { Color.backgroundDark.ignoresSafeArea(.all) @@ -32,28 +37,28 @@ struct ChatListView: View { Text("최근 본 뉴스") .foregroundStyle(.basicWhite) .font(.pretendardBold32) -// HStack { -// RecentNewsCardView() -// Spacer() -// RecentNewsCardView() -// Spacer() -// RecentNewsCardView() -// } + // HStack { + // RecentNewsCardView() + // Spacer() + // RecentNewsCardView() + // Spacer() + // RecentNewsCardView() + // } HStack { - if newsViewModel.news.isEmpty { - Text("최근 읽은 뉴스를 불러오는 중...") - .onAppear { - print("뷰가 나타남 - 최근 읽은 뉴스 조회 시작") - newsViewModel.fetchViewedHistory() - } - } else { - ForEach(newsViewModel.news.prefix(3), id: \.id) { news in - RecentNewsCardView(news: news) - Spacer() + if newsViewModel.news.isEmpty { + Text("최근 읽은 뉴스를 불러오는 중...") + .onAppear { + print("뷰가 나타남 - 최근 읽은 뉴스 조회 시작") + newsViewModel.fetchViewedHistory() } + } else { + ForEach(newsViewModel.news.prefix(3), id: \.id) { news in + RecentNewsCardView(news: news) + Spacer() } } - .padding() + } + .padding() } } @@ -63,174 +68,228 @@ struct ChatListView: View { Text("채팅방") .foregroundStyle(.basicWhite) .font(.pretendardBold32) - debateChatCellView - debateChatCellView2 - debateChatCellView3 - debateChatCellView4 - debateChatCellView5 + // debateChatCellView + // debateChatCellView2 + // debateChatCellView3 + // debateChatCellView4 + // debateChatCellView5 + ForEach(getdebateroomviewModel.debates) { debate in + DebateChatCellView(debate: debate) + } + } + .onAppear { + print("채팅방 불러와짐") + getdebateroomviewModel.fetchDebates(page: 5, size: 10) } } - var debateChatCellView: some View { - HStack { - HStack(alignment: .center, spacing: 16) { - Text("🏛️") - .padding(.leading, 26) - .font(.pretendardBold32) - Text("삼성, 갤럭시Z플립6 두뇌 전량 퀄컴칩 탑재하나") - .foregroundStyle(.gray07) - .font(.pretendardBold24) - .padding(.vertical, 24) - - Spacer() + struct DebateChatCellView: View { + let debate: GetDebateRoom + let emojis = ["🏛️", "🔥", "📌", "⭐️", "🧬", "👩🏼‍💻", "🎨", "🎬", "💌", "🔗", "👀"] + + @EnvironmentObject var pathModel: PathModel + + var body: some View { + let randomEmoji = emojis.randomElement() ?? "🏛️" // 이모지가 선택되지 않으면 기본값을 설정합니다. + + HStack { + HStack(alignment: .center, spacing: 16) { +// Text("🏛️") +// .padding(.leading, 26) +// .font(.pretendardBold32) + Text(randomEmoji) + .padding(.leading, 26) + .font(.pretendardBold32) + Text(debate.topic.isEmpty ? "토론을 시작해주세요!" : debate.topic) + .foregroundStyle(.gray07) + .font(.pretendardBold24) + .padding(.vertical, 24) + + Spacer() + Button { + pathModel.paths.append(.chatView(isAiMode: true)) + } label: { + Image(systemName: "chevronRight") + .foregroundColor(.gray01) + } + } + .background(.gray01) + .clipShape(RoundedRectangle(cornerRadius: 8)) + .padding(.trailing, 16) + Button { - pathModel.paths.append(.chatView(isAiMode: true)) + pathModel.paths.append(.debateSummaryView) } label: { - Image(systemName: "quote.bubble") - .background(.gray01) + Image("quote.bubble") + .foregroundColor(.gray01) + } + .frame(width: 80, height: 80) + .background(.gray01) + .clipShape(RoundedRectangle(cornerRadius: 8)) } - .background(.gray01) - .clipShape(RoundedRectangle(cornerRadius: 8)) - .padding(.trailing, 16) - - //TODO: 버튼 영역 수정하기 - Button { - pathModel.paths.append(.debateSummaryView) - } label: { - Image(.chevronLeft) -// .background(.gray01) - - } - .frame(width: 80, height: 80) - .background(.gray01) - .clipShape(RoundedRectangle(cornerRadius: 8)) } } - var debateChatCellView2: some View { - HStack { - HStack(alignment: .center, spacing: 16) { - Text("📱") - .padding(.leading, 26) - .font(.pretendardBold32) - Text("모친 내친 한미약품 형제… 2644억 상속세 마련방안은 `아직`") - .foregroundStyle(.gray07) - .font(.pretendardBold24) - .padding(.vertical, 24) - - Spacer() - Image(.chevronRight) - } - .background(.gray01) - .clipShape(RoundedRectangle(cornerRadius: 8)) - .padding(.trailing, 16) - - //TODO: 버튼 영역 수정하기 - Button { - pathModel.paths.append(.debateSummaryView) - } label: { - Image(.chevronLeft) -// .background(.gray01) - - } - .frame(width: 80, height: 80) - .background(.gray01) - .clipShape(RoundedRectangle(cornerRadius: 8)) - } - } - var debateChatCellView3: some View { - HStack { - HStack(alignment: .center, spacing: 16) { - Text("💌") - .padding(.leading, 26) - .font(.pretendardBold32) - Text("[ET단상]한바탕 휩쓴 방산 해킹 사건, 보안의 다른 \'답\'을 찾아야 할 때") - .foregroundStyle(.gray07) - .font(.pretendardBold24) - .padding(.vertical, 24) - - Spacer() - Image(.chevronRight) - } - .background(.gray01) - .clipShape(RoundedRectangle(cornerRadius: 8)) - .padding(.trailing, 16) - - //TODO: 버튼 영역 수정하기 - Button { - pathModel.paths.append(.debateSummaryView) - } label: { - Image(.chevronLeft) -// .background(.gray01) - - } - .frame(width: 80, height: 80) - .background(.gray01) - .clipShape(RoundedRectangle(cornerRadius: 8)) - } - } - var debateChatCellView4: some View { - HStack { - HStack(alignment: .center, spacing: 16) { - Text("📱") - .padding(.leading, 26) - .font(.pretendardBold32) - Text("삼성, 갤럭시Z플립6 두뇌 전량 퀄컴칩 탑재하나") - .foregroundStyle(.gray07) - .font(.pretendardBold24) - .padding(.vertical, 24) - - Spacer() - Image(.chevronRight) - } - .background(.gray01) - .clipShape(RoundedRectangle(cornerRadius: 8)) - .padding(.trailing, 16) - - //TODO: 버튼 영역 수정하기 - Button { - pathModel.paths.append(.debateSummaryView) - } label: { - Image(.chevronLeft) +// var debateChatCellView: some View { +// HStack { +// HStack(alignment: .center, spacing: 16) { +// Text("🏛️") +// .padding(.leading, 26) +// .font(.pretendardBold32) +// Text("삼성, 갤럭시Z플립6 두뇌 전량 퀄컴칩 탑재하나") +// .foregroundStyle(.gray07) +// .font(.pretendardBold24) +// .padding(.vertical, 24) +// +// Spacer() +// Button { +// pathModel.paths.append(.chatView(isAiMode: true)) +// } label: { +// Image(systemName: "chevronRight") +// .foregroundColor(.gray01) +// } +// } +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// .padding(.trailing, 16) +// +// //TODO: 버튼 영역 수정하기 +// Button { +// pathModel.paths.append(.debateSummaryView) +// } label: { +// Image("quote.bubble") +// .foregroundColor(.gray01) +// +// } +// .frame(width: 80, height: 80) +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// } +// } +// var debateChatCellView2: some View { +// HStack { +// HStack(alignment: .center, spacing: 16) { +// Text("📱") +// .padding(.leading, 26) +// .font(.pretendardBold32) +// Text("모친 내친 한미약품 형제… 2644억 상속세 마련방안은 `아직`") +// .foregroundStyle(.gray07) +// .font(.pretendardBold24) +// .padding(.vertical, 24) +// +// Spacer() +// Image(.chevronRight) +// } +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// .padding(.trailing, 16) +// +// //TODO: 버튼 영역 수정하기 +// Button { +// pathModel.paths.append(.debateSummaryView) +// } label: { +// Image(.chevronLeft) +//// .background(.gray01) +// +// } +// .frame(width: 80, height: 80) +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// } +// } +// var debateChatCellView3: some View { +// HStack { +// HStack(alignment: .center, spacing: 16) { +// Text("💌") +// .padding(.leading, 26) +// .font(.pretendardBold32) +// Text("[ET단상]한바탕 휩쓴 방산 해킹 사건, 보안의 다른 \'답\'을 찾아야 할 때") +// .foregroundStyle(.gray07) +// .font(.pretendardBold24) +// .padding(.vertical, 24) +// +// Spacer() +// Image(.chevronRight) +// } +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// .padding(.trailing, 16) +// +// //TODO: 버튼 영역 수정하기 +// Button { +// pathModel.paths.append(.debateSummaryView) +// } label: { +// Image(.chevronLeft) +//// .background(.gray01) +// +// } +// .frame(width: 80, height: 80) +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// } +// } +// var debateChatCellView4: some View { +// HStack { +// HStack(alignment: .center, spacing: 16) { +// Text("📱") +// .padding(.leading, 26) +// .font(.pretendardBold32) +// Text("삼성, 갤럭시Z플립6 두뇌 전량 퀄컴칩 탑재하나") +// .foregroundStyle(.gray07) +// .font(.pretendardBold24) +// .padding(.vertical, 24) +// +// Spacer() +// Image(.chevronRight) +// } +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// .padding(.trailing, 16) +// +// //TODO: 버튼 영역 수정하기 +// Button { +// pathModel.paths.append(.debateSummaryView) +// } label: { +// Image(.chevronLeft) +//// .background(.gray01) +// +// } +// .frame(width: 80, height: 80) +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// } +// } +// var debateChatCellView5: some View { +// HStack { +// HStack(alignment: .center, spacing: 16) { +// Text("🏛️") +// .padding(.leading, 26) +// .font(.pretendardBold32) +// Text("삼성, 갤럭시Z플립6 두뇌 전량 퀄컴칩 탑재하나") +// .foregroundStyle(.gray07) +// .font(.pretendardBold24) +// .padding(.vertical, 24) +// +// Spacer() +// Image(.chevronRight) +// } +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// .padding(.trailing, 16) +// +// //TODO: 버튼 영역 수정하기 +// Button { +// pathModel.paths.append(.debateSummaryView) +// } label: { +// Image(systemName: "quote.bubble") // .background(.gray01) - - } - .frame(width: 80, height: 80) - .background(.gray01) - .clipShape(RoundedRectangle(cornerRadius: 8)) - } - } - var debateChatCellView5: some View { - HStack { - HStack(alignment: .center, spacing: 16) { - Text("🏛️") - .padding(.leading, 26) - .font(.pretendardBold32) - Text("삼성, 갤럭시Z플립6 두뇌 전량 퀄컴칩 탑재하나") - .foregroundStyle(.gray07) - .font(.pretendardBold24) - .padding(.vertical, 24) - - Spacer() - Image(.chevronRight) - } - .background(.gray01) - .clipShape(RoundedRectangle(cornerRadius: 8)) - .padding(.trailing, 16) - - //TODO: 버튼 영역 수정하기 - Button { - pathModel.paths.append(.debateSummaryView) - } label: { - Image(systemName: "quote.bubble") - .background(.gray01) - - } - .frame(width: 80, height: 80) - .background(.gray01) - .clipShape(RoundedRectangle(cornerRadius: 8)) - } - } +// +// } +// .frame(width: 80, height: 80) +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// } +// } } #Preview { diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/GetDebateRoomModel/GetDebateRoom.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/GetDebateRoomModel/GetDebateRoom.swift new file mode 100644 index 00000000..a24fbd01 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/GetDebateRoomModel/GetDebateRoom.swift @@ -0,0 +1,15 @@ +// +// GetDebateRoom.swift +// RollTheDice +// +// Created by 신예진 on 6/20/24. +// + +import Foundation + + +struct GetDebateRoom: Identifiable, Codable { + let id: Int + let topic: String + let isClosed: Bool? +} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/GetDebateRoomService.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/GetDebateRoomService.swift new file mode 100644 index 00000000..49601d7d --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/GetDebateRoomService.swift @@ -0,0 +1,50 @@ +// +// GetDebateRoomService.swift +// RollTheDice +// +// Created by 신예진 on 6/20/24. +// + +//MARK : 토론방 전체 조회 +import Foundation +import Moya + +enum GetDebateRoomService { + case getDebates(page: Int, size: Int) +} + +extension GetDebateRoomService: TargetType { + var baseURL: URL { + return URL(string: "http://roll-the-dice.store:8080")! + } + + var path: String { + switch self { + case .getDebates: + return "/debates" + } + } + + var method: Moya.Method { + switch self { + case .getDebates: + return .get + } + } + + var task: Task { + switch self { + case let .getDebates(page, size): + return .requestParameters(parameters: ["page": page, "size": size], encoding: URLEncoding.queryString) + } + } + + var headers: [String: String]? { + guard let token = TokenManager.shared.accessToken else { return nil } + return ["Authorization": "Bearer \(token)"] + } + + var sampleData: Data { + return Data() + } +} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/GetDebateRoomViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/GetDebateRoomViewModel.swift new file mode 100644 index 00000000..b003450b --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/GetDebateRoomViewModel.swift @@ -0,0 +1,34 @@ +// +// GetDebateRoomViewModel.swift +// RollTheDice +// +// Created by 신예진 on 6/20/24. +// + +import Foundation +import Combine +import Moya + +class GetDebateRoomViewModel: ObservableObject { + @Published var debates: [GetDebateRoom] = [] + private var cancellables = Set() + private let provider = MoyaProvider() + + func fetchDebates(page: Int, size: Int) { + provider.requestPublisher(.getDebates(page: page, size: size)) + .map(\.data) + .decode(type: [GetDebateRoom].self, decoder: JSONDecoder()) + .sink(receiveCompletion: { completion in + switch completion { + case .failure(let error): + print("Error fetching debates: \(error)") + case .finished: + break + } + }, receiveValue: { [weak self] debates in + self?.debates = debates + print("Fetched debates: \(debates)") // 로그 확인용 + }) + .store(in: &cancellables) + } +} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/DebateSummaryView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/DebateSummaryView.swift index 62319d1e..55ba3742 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/DebateSummaryView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/DebateSummaryView.swift @@ -9,6 +9,9 @@ import SwiftUI struct DebateSummaryView: View { @EnvironmentObject var pathModel: PathModel + @StateObject private var viewModel = DebateSummaryViewModel() + @StateObject private var endDebateViewModel = EndDebateViewModel() + @State private var roomId: String = "" // EndDebateViewModel로부터 받아오는 roomid var body: some View { ZStack { @@ -53,7 +56,7 @@ struct DebateSummaryView: View { } - // TODO: 말풍선 수정하기 + // TODO: 말풍선 수정하기 .overlay { VStack(spacing: 20) { Rectangle() @@ -115,3 +118,4 @@ struct DebateSummaryView: View { #Preview { DebateSummaryView() } + diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/Service/DebateSummaryService.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/Service/DebateSummaryService.swift new file mode 100644 index 00000000..b161bd3d --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/Service/DebateSummaryService.swift @@ -0,0 +1,43 @@ +// +// DebateSummaryService.swift +// RollTheDice +// +// Created by 신예진 on 6/20/24. +// + +import Foundation +import Moya + +enum DebateSummaryService { + case getSummary(roomId: Int) +} + +extension DebateSummaryService: TargetType { + var baseURL: URL { + return URL(string: "http://roll-the-dice.store:8080")! + } + + var path: String { + switch self { + case .getSummary(let roomId): + return "/debates/summary/\(roomId)" + } + } + + var method: Moya.Method { + return .post + } + + var task: Task { + return .requestPlain + } + + var headers: [String : String]? { + guard let token = TokenManager.shared.accessToken else { return nil } + return ["Authorization": "Bearer \(token)"] + } + + var sampleData: Data { + return Data() + } +} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/ViewModel/DebateSummaryViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/ViewModel/DebateSummaryViewModel.swift new file mode 100644 index 00000000..638529c4 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/ViewModel/DebateSummaryViewModel.swift @@ -0,0 +1,46 @@ +// +// DebateSummaryViewModel.swift +// RollTheDice +// +// Created by 신예진 on 6/20/24. +// + +import Foundation +import Combine +import Moya + +class DebateSummaryViewModel: ObservableObject { + @Published var summary: String? + @Published var roomId: Int? + @Published var isLoading: Bool = false + @Published var errorMessage: String? + + private let provider = MoyaProvider() + + func fetchSummary(roomId: Int) { + isLoading = true + provider.request(.getSummary(roomId: roomId)) { result in + self.isLoading = false + switch result { + case .success(let response): + do { + let json = try JSONSerialization.jsonObject(with: response.data, options: []) + if let dict = json as? [String: Any], let summary = dict["summary"] as? String { + self.summary = summary + self.roomId = roomId + print("토론 요약 성공") + } else { + self.errorMessage = "Invalid response format" + print("토론 요약 유효하지 않은 포맷") + } + } catch { + self.errorMessage = "Failed to parse response" + print("토론 요약 reponse 못 받아옴") + } + case .failure(let error): + self.errorMessage = error.localizedDescription + print("토론 요약 오류/실패") + } + } + } +}