From 305f9e7f10a317ee47131625672135abf90b6230 Mon Sep 17 00:00:00 2001 From: realhsb Date: Tue, 18 Jun 2024 16:41:59 +0900 Subject: [PATCH 01/61] chore: Bookmark -> Bookmarks --- .../RollTheDice.xcodeproj/project.pbxproj | 16 ++-- .../RollTheDice/RollTheDiceApp.swift | 2 +- .../View/Bookmark/BookmarkCard/Bookmark.swift | 31 -------- .../BookmarkCard/BookmarkListViewModel.swift | 30 ------- .../Bookmark/BookmarkCard/Bookmarks.swift | 46 +++++++++++ .../BookmarkCard/BookmarksListViewModel.swift | 78 +++++++++++++++++++ 6 files changed, 133 insertions(+), 70 deletions(-) delete mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/Bookmark.swift delete mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkListViewModel.swift create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/Bookmarks.swift create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 43967286..92249e2e 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -18,10 +18,10 @@ 357699442C09C7B900AD2DA4 /* AuthAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 357699432C09C7B900AD2DA4 /* AuthAPI.swift */; }; 357FC6EA2BCE866B00AD8915 /* DetailCardNews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 357FC6E92BCE866B00AD8915 /* DetailCardNews.swift */; }; 35C71BF22B79F39900F777D1 /* ExyteChat in Frameworks */ = {isa = PBXBuildFile; productRef = 35C71BF12B79F39900F777D1 /* ExyteChat */; }; - 6C32379F2B7C376D00B699AB /* Bookmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C32379E2B7C376D00B699AB /* Bookmark.swift */; }; + 6C32379F2B7C376D00B699AB /* Bookmarks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C32379E2B7C376D00B699AB /* Bookmarks.swift */; }; 6C3237A12B7C377600B699AB /* BookmarkViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3237A02B7C377600B699AB /* BookmarkViewModel.swift */; }; 6C3237A52B7C37D100B699AB /* BookmarkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3237A42B7C37D100B699AB /* BookmarkView.swift */; }; - 6C3237A72B7C37E500B699AB /* BookmarkListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3237A62B7C37E500B699AB /* BookmarkListViewModel.swift */; }; + 6C3237A72B7C37E500B699AB /* BookmarksListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3237A62B7C37E500B699AB /* BookmarksListViewModel.swift */; }; 6C3237AA2B7C381500B699AB /* NewsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3237A92B7C381500B699AB /* NewsView.swift */; }; 6C3237AC2B7C382200B699AB /* NewsList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3237AB2B7C382200B699AB /* NewsList.swift */; }; 6C3237AE2B7C382E00B699AB /* DetailNewsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3237AD2B7C382E00B699AB /* DetailNewsViewModel.swift */; }; @@ -103,10 +103,10 @@ 357666122BBD54AA002C226A /* SplashView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashView.swift; sourceTree = ""; }; 357699432C09C7B900AD2DA4 /* AuthAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthAPI.swift; sourceTree = ""; }; 357FC6E92BCE866B00AD8915 /* DetailCardNews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailCardNews.swift; sourceTree = ""; }; - 6C32379E2B7C376D00B699AB /* Bookmark.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bookmark.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 = ""; }; - 6C3237A62B7C37E500B699AB /* BookmarkListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkListViewModel.swift; sourceTree = ""; }; + 6C3237A62B7C37E500B699AB /* BookmarksListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksListViewModel.swift; sourceTree = ""; }; 6C3237A92B7C381500B699AB /* NewsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewsView.swift; sourceTree = ""; }; 6C3237AB2B7C382200B699AB /* NewsList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewsList.swift; sourceTree = ""; }; 6C3237AD2B7C382E00B699AB /* DetailNewsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailNewsViewModel.swift; sourceTree = ""; }; @@ -213,10 +213,10 @@ 6C32379D2B7C374E00B699AB /* BookmarkCard */ = { isa = PBXGroup; children = ( - 6C32379E2B7C376D00B699AB /* Bookmark.swift */, + 6C32379E2B7C376D00B699AB /* Bookmarks.swift */, + 6C3237A62B7C37E500B699AB /* BookmarksListViewModel.swift */, 6C3237A02B7C377600B699AB /* BookmarkViewModel.swift */, 6C3237A42B7C37D100B699AB /* BookmarkView.swift */, - 6C3237A62B7C37E500B699AB /* BookmarkListViewModel.swift */, ); path = BookmarkCard; sourceTree = ""; @@ -754,7 +754,7 @@ 6C77048F2B7229B1001B17CB /* NewsListView.swift in Sources */, 357666132BBD54AA002C226A /* SplashView.swift in Sources */, 6C4F7BAD2BDE510900ED01DA /* DailyReportViewModel.swift in Sources */, - 6C3237A72B7C37E500B699AB /* BookmarkListViewModel.swift in Sources */, + 6C3237A72B7C37E500B699AB /* BookmarksListViewModel.swift in Sources */, 6C454A822B9DAFA3006FD9D0 /* Path.swift in Sources */, 6C94799E2BD3C00C00D5AEEB /* Image.swift in Sources */, 6C454A842B9DAFCB006FD9D0 /* PathType.swift in Sources */, @@ -766,7 +766,7 @@ 6CA901962BA2EC0100E20259 /* Font.swift in Sources */, 6CF130C22BAB786600A437B6 /* APIHeaderManager.swift in Sources */, 6CDB29FB2BAA07B10081037B /* GPTChatViewModel.swift in Sources */, - 6C32379F2B7C376D00B699AB /* Bookmark.swift in Sources */, + 6C32379F2B7C376D00B699AB /* Bookmarks.swift in Sources */, 6C454A7E2B9DAA3F006FD9D0 /* SignUpFinishView.swift in Sources */, 6C7704A12B722CEB001B17CB /* ProfileView.swift in Sources */, 6C4F7BAB2BDE50C600ED01DA /* DailyReportModel.swift in Sources */, diff --git a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift index 3e61f628..42aaece7 100644 --- a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift +++ b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift @@ -20,7 +20,7 @@ struct RollTheDiceApp: App { var signUpViewModel = SignUpViewModel() var newsListViewModel = NewsListViewModel() - @StateObject var bookmarkListViewModel = BookmarkListViewModel() + @StateObject var bookmarkListViewModel = BookmarksListViewModel() init() { KakaoSDK.initSDK(appKey: "ff09b3d83873ed4e320f0d6bc90759d6") diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/Bookmark.swift b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/Bookmark.swift deleted file mode 100644 index 39455078..00000000 --- a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/Bookmark.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// Bookmark.swift -// RollTheDice -// -// Created by Subeen on 2/12/24. -// - -import Foundation - -struct Bookmark: Hashable { - var id: UUID = UUID() - var title: String - var date: String - var image: String - var content: String - var isBookmarked: Bool - - init( - title: String = "", - date: String = "", - image: String = "", - content: String = "", - isBookmarked: Bool = false - ) { - self.title = title - self.date = date - self.image = image - self.content = content - self.isBookmarked = isBookmarked - } -} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkListViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkListViewModel.swift deleted file mode 100644 index 8d2a5731..00000000 --- a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkListViewModel.swift +++ /dev/null @@ -1,30 +0,0 @@ -// -// BookmarkListViewModel.swift -// RollTheDice -// -// Created by Subeen on 2/12/24. -// - -import Foundation - -public class BookmarkListViewModel: ObservableObject { - @Published var bookmarkList: [Bookmark] - - init( - bookmarkList: [Bookmark] = [ - .init(title: "2024년 ‘소셜 미디어 다이어트’를 위해 바꿔볼 것", date: "2023년12월3일", image: "exampleNews", content: "2024년으로 접어든지 한 달이 넘었다. 하지만 올 해가 어떻게 흘러갈지 예측하기는 쉽지 않다. 한 가지 확실한 것은 정치적으로 매우 중요한 해라는 점이다. 미국과 러시아, 우크라이나, 방글라데시, 인도, 대만, 한국, 남아프리카공화국, 유럽의회, 영국에서 선거가 치러질 예정이다.", isBookmarked: false), - .init(title: "앤스로픽 최신 AI 모델 '클로드3' 출시", date: "2023년3월13일", image: "https://imgnews.pstatic.net/image/014/2024/03/05/0005151141_001_20240305101610000.jpg?type=w647", content: "오픈AI의 대항마 앤스로픽이 생성형 인공지능(AI) 최신 모델 '클로드'(Claude)3를 선보이면서 생성형 AI 주도권을 잡기 위한 경쟁이 다시 뜨거워지고 있다. 앤스로픽은 지난 한 해 동안 구글과 세일즈포스, 아마존 등에서 총 73억 달러(약 9조7309억 원)를 투자받고 '클로드3'를 내놨는데 오픈AI의 챗GPT-4를 능가한다고 도발했다.", isBookmarked: true), - .init(title: "SK C&C, 외부 전문가 대거 영입… “신성장 동력 강화”", date: "2023년2월13일", image: "https://imgnews.pstatic.net/image/366/2024/03/05/0000975131_001_20240305093504301.jpg?type=w647", content: "SK C&C는 국내외 신성장 동력 강화를 위해 인공지능(AI)·클라우드·디지털 팩토리·ESG(환경·사회·지배구조) 등 4대 성장 사업과 디지털 컨설팅 중심으로 외부 전문가를 대거 영입해 전진 배치했다고 5일 밝혔다.", isBookmarked: false), - .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), - - .init(title: "이종호 과기장관 5년 뒤 구축될 바이오파운드리에 산학연 역량 모아야", date: "2023년3월13일", image: "https://imgnews.pstatic.net/image/003/2024/03/05/NISI20231030_0001398722_web_20231030141808_20240305103108748.jpg?type=w647", content: "정부가 내년부터 합성생물학의 필수 인프라인 '국가 바이오파운드리' 구축에 본격 나서는 가운데 이종호 과학기술정보통신부 장관이 한국생명공학연구원에서 운영 중인 사전연구용 시설을 찾아 구체적인 인프라 구축 계획 등을 점검했다.이 장관은 5일 합성생물학 육성을 위해 바이오파운드리 연구현장을 방문하고, 산·학·연 전문가들을 만났다. 이번 방문은 지난해 미국, 영국과의 정상회담 시 논의됐던 첨단바이오 협력을 위한 후속조치의 일환으로 추진됐다.", isBookmarked: false), - .init(title: "SW산업 육성에 7308억 예산투자, SaaS 등 육성", date: "2023년3월13일", image: "https://imgnews.pstatic.net/image/008/2024/03/05/0005007507_001_20240305135301539.jpg?type=w647", content: "SW(소프트웨어) 산업의 SaaS(서비스형 소프트웨어) 전환 등 SW산업 육성을 위해 정부 예산 7308억원이 투자된다. 강도현 과학기술정보통신부 제2차관은 5일 오전 서울 을지로 더존비즈온 을지사옥에서 열린 'AI(인공지능) 일상화, SW도 이제 서비스형 SW'라는 주제로 열린 현장 간담회에서 정부도 대한민국 SW산업의 미래가 SaaS에 있다고 생각하고 올해 'SaaS 혁신펀드'를 새롭게 조성하는 등 SaaS 육성 및 기존 SW 기업의 SaaS 전환을 위해 다양한 지원을 추진 중이라며 이같이 밝혔다.", isBookmarked: false), - .init(title: "파수, 기업용 AI ‘엔터프라이즈 LLM’ 출시", date: "2023년3월13일", image: "https://imgnews.pstatic.net/image/018/2024/03/05/0005685566_001_20240305103201036.jpg?type=w647", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), - .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), - .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), - .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), - ] - ) { - self.bookmarkList = bookmarkList - } -} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/Bookmarks.swift b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/Bookmarks.swift new file mode 100644 index 00000000..13e6518b --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/Bookmarks.swift @@ -0,0 +1,46 @@ +// +// Bookmark.swift +// RollTheDice +// +// Created by Subeen on 2/12/24. +// + +import Foundation + + +// MARK: - Bookmark +struct Bookmarks: Codable, Identifiable { + let id = UUID().uuidString + let newsId: Int + let title, thumbnailURL, postDate: String? + let isBookmarked: Bool? + + enum CodingKeys: String, CodingKey { + case newsId = "id" + case title, thumbnailURL, postDate, isBookmarked + } +} + + +//struct Bookmarks: Hashable { +// var id: UUID = UUID() +// var title: String +// var date: String +// var image: String +// var content: String +// var isBookmarked: Bool +// +// init( +// title: String = "", +// date: String = "", +// image: String = "", +// content: String = "", +// isBookmarked: Bool = false +// ) { +// self.title = title +// self.date = date +// self.image = image +// self.content = content +// self.isBookmarked = isBookmarked +// } +//} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift new file mode 100644 index 00000000..fc069789 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift @@ -0,0 +1,78 @@ +// +// BookmarkListViewModel.swift +// RollTheDice +// +// Created by Subeen on 2/12/24. +// + +import Foundation +import Combine +import CombineMoya +import Moya +import SwiftUI + +@Observable class BookmarksListViewModel{ + var bookmarksList: [Bookmarks]? + var bookmarksCancellable: AnyCancellable? + + let provider = MoyaProvider(plugins: [MoyaLoggingPlugin()]) + + func bookmarksToViewModel(_ list: [Bookmarks]) { + self.bookmarksList = list + } +} + +extension BookmarksListViewModel { + public func getAllBookmarksData(page: Int, size: Int) { + let accessToken = "5Gu45OmOoZnvANl-qfZv-xHv_2eSweVeAAAAAQopyNkAAAGQFbGnJSn2EFsnJsRZ" + + if let cancellable = bookmarksCancellable { + cancellable.cancel() + } + + bookmarksCancellable = provider.requestWithProgressPublisher( + .allBookmarks( + page: page, + size: size, + accessToken: accessToken + ) + + ) + .compactMap { $0.response?.data } + .receive(on: DispatchQueue.main) + .decode(type: [Bookmarks].self, decoder: JSONDecoder()) + .sink(receiveCompletion: { result in + switch result { + case .finished: + print("all bookmarks 조회 성공") + case .failure(let error): + Log.network("network error", error.localizedDescription) + } + }, receiveValue: { [weak self] response in + self?.bookmarksToViewModel(response) + print(response) + }) + } +} + +//public class BookmarksListViewModel: ObservableObject { +// @Published var bookmarkList: [Bookmarks] +// +// init( +// bookmarkList: [Bookmarks] = [ +// .init(title: "2024년 ‘소셜 미디어 다이어트’를 위해 바꿔볼 것", date: "2023년12월3일", image: "exampleNews", content: "2024년으로 접어든지 한 달이 넘었다. 하지만 올 해가 어떻게 흘러갈지 예측하기는 쉽지 않다. 한 가지 확실한 것은 정치적으로 매우 중요한 해라는 점이다. 미국과 러시아, 우크라이나, 방글라데시, 인도, 대만, 한국, 남아프리카공화국, 유럽의회, 영국에서 선거가 치러질 예정이다.", isBookmarked: false), +// .init(title: "앤스로픽 최신 AI 모델 '클로드3' 출시", date: "2023년3월13일", image: "https://imgnews.pstatic.net/image/014/2024/03/05/0005151141_001_20240305101610000.jpg?type=w647", content: "오픈AI의 대항마 앤스로픽이 생성형 인공지능(AI) 최신 모델 '클로드'(Claude)3를 선보이면서 생성형 AI 주도권을 잡기 위한 경쟁이 다시 뜨거워지고 있다. 앤스로픽은 지난 한 해 동안 구글과 세일즈포스, 아마존 등에서 총 73억 달러(약 9조7309억 원)를 투자받고 '클로드3'를 내놨는데 오픈AI의 챗GPT-4를 능가한다고 도발했다.", isBookmarked: true), +// .init(title: "SK C&C, 외부 전문가 대거 영입… “신성장 동력 강화”", date: "2023년2월13일", image: "https://imgnews.pstatic.net/image/366/2024/03/05/0000975131_001_20240305093504301.jpg?type=w647", content: "SK C&C는 국내외 신성장 동력 강화를 위해 인공지능(AI)·클라우드·디지털 팩토리·ESG(환경·사회·지배구조) 등 4대 성장 사업과 디지털 컨설팅 중심으로 외부 전문가를 대거 영입해 전진 배치했다고 5일 밝혔다.", isBookmarked: false), +// .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), +// +// .init(title: "이종호 과기장관 5년 뒤 구축될 바이오파운드리에 산학연 역량 모아야", date: "2023년3월13일", image: "https://imgnews.pstatic.net/image/003/2024/03/05/NISI20231030_0001398722_web_20231030141808_20240305103108748.jpg?type=w647", content: "정부가 내년부터 합성생물학의 필수 인프라인 '국가 바이오파운드리' 구축에 본격 나서는 가운데 이종호 과학기술정보통신부 장관이 한국생명공학연구원에서 운영 중인 사전연구용 시설을 찾아 구체적인 인프라 구축 계획 등을 점검했다.이 장관은 5일 합성생물학 육성을 위해 바이오파운드리 연구현장을 방문하고, 산·학·연 전문가들을 만났다. 이번 방문은 지난해 미국, 영국과의 정상회담 시 논의됐던 첨단바이오 협력을 위한 후속조치의 일환으로 추진됐다.", isBookmarked: false), +// .init(title: "SW산업 육성에 7308억 예산투자, SaaS 등 육성", date: "2023년3월13일", image: "https://imgnews.pstatic.net/image/008/2024/03/05/0005007507_001_20240305135301539.jpg?type=w647", content: "SW(소프트웨어) 산업의 SaaS(서비스형 소프트웨어) 전환 등 SW산업 육성을 위해 정부 예산 7308억원이 투자된다. 강도현 과학기술정보통신부 제2차관은 5일 오전 서울 을지로 더존비즈온 을지사옥에서 열린 'AI(인공지능) 일상화, SW도 이제 서비스형 SW'라는 주제로 열린 현장 간담회에서 정부도 대한민국 SW산업의 미래가 SaaS에 있다고 생각하고 올해 'SaaS 혁신펀드'를 새롭게 조성하는 등 SaaS 육성 및 기존 SW 기업의 SaaS 전환을 위해 다양한 지원을 추진 중이라며 이같이 밝혔다.", isBookmarked: false), +// .init(title: "파수, 기업용 AI ‘엔터프라이즈 LLM’ 출시", date: "2023년3월13일", image: "https://imgnews.pstatic.net/image/018/2024/03/05/0005685566_001_20240305103201036.jpg?type=w647", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), +// .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), +// .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), +// .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), +// ] +// ) { +// self.bookmarkList = bookmarkList +// } +//} From 8a92c41d07811e5b6189a328753665fe8b92e8b9 Mon Sep 17 00:00:00 2001 From: realhsb Date: Tue, 18 Jun 2024 16:42:19 +0900 Subject: [PATCH 02/61] feat: Bookmark API --- .../RollTheDice.xcodeproj/project.pbxproj | 4 ++++ .../Source/Domain/ScoopAPI/ScoopAPIBookmarks.swift | 12 ++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPIBookmarks.swift diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 92249e2e..107c522a 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -41,6 +41,7 @@ 6C454A882B9DB6C2006FD9D0 /* CustomNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C454A872B9DB6C2006FD9D0 /* CustomNavigationBar.swift */; }; 6C4F7BAB2BDE50C600ED01DA /* DailyReportModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4F7BAA2BDE50C600ED01DA /* DailyReportModel.swift */; }; 6C4F7BAD2BDE510900ED01DA /* DailyReportViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4F7BAC2BDE510900ED01DA /* DailyReportViewModel.swift */; }; + 6C5B0C8A2C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C5B0C892C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift */; }; 6C7651382BF37E7200196536 /* MoyaLoggingPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C7651372BF37E7200196536 /* MoyaLoggingPlugin.swift */; }; 6C76513C2BF37ED300196536 /* Extension+Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C76513B2BF37ED300196536 /* Extension+Log.swift */; }; 6C76513E2BF37F1E00196536 /* Extension+OSLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C76513D2BF37F1E00196536 /* Extension+OSLog.swift */; }; @@ -126,6 +127,7 @@ 6C454A872B9DB6C2006FD9D0 /* CustomNavigationBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomNavigationBar.swift; sourceTree = ""; }; 6C4F7BAA2BDE50C600ED01DA /* DailyReportModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyReportModel.swift; sourceTree = ""; }; 6C4F7BAC2BDE510900ED01DA /* DailyReportViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyReportViewModel.swift; sourceTree = ""; }; + 6C5B0C892C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScoopAPIBookmarks.swift; sourceTree = ""; }; 6C7651372BF37E7200196536 /* MoyaLoggingPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoyaLoggingPlugin.swift; sourceTree = ""; }; 6C76513B2BF37ED300196536 /* Extension+Log.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extension+Log.swift"; sourceTree = ""; }; 6C76513D2BF37F1E00196536 /* Extension+OSLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extension+OSLog.swift"; sourceTree = ""; }; @@ -619,6 +621,7 @@ children = ( 6CF130C42BAB79DE00A437B6 /* ScoopAPI.swift */, 6CF130C62BAB7B9800A437B6 /* ScoopAPINews.swift */, + 6C5B0C892C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift */, ); path = ScoopAPI; sourceTree = ""; @@ -728,6 +731,7 @@ 357699442C09C7B900AD2DA4 /* AuthAPI.swift in Sources */, 6C76513C2BF37ED300196536 /* Extension+Log.swift in Sources */, 6CE103102BD56A5B00498AA4 /* TypeReportViewModel.swift in Sources */, + 6C5B0C8A2C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift in Sources */, 6CF130C52BAB79DE00A437B6 /* ScoopAPI.swift in Sources */, 6CE103132BD56B1200498AA4 /* DailyReportView.swift in Sources */, 6C454A7A2B9DA67C006FD9D0 /* SignUpViewModel.swift in Sources */, diff --git a/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPIBookmarks.swift b/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPIBookmarks.swift new file mode 100644 index 00000000..1905043d --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPIBookmarks.swift @@ -0,0 +1,12 @@ +// +// ScoopAPIBookmark.swift +// RollTheDice +// +// Created by Subeen on 6/14/24. +// + +import Foundation + +public enum ScoopAPIBookmarks { + public static let bookmarks = String("/bookmarks") +} From 7141ef7484ba906857df80c5896f054bf0cac11f Mon Sep 17 00:00:00 2001 From: realhsb Date: Tue, 18 Jun 2024 16:42:49 +0900 Subject: [PATCH 03/61] feat: Bookmarks Service --- .../RollTheDice.xcodeproj/project.pbxproj | 4 + .../Domain/Service/BookmarksService.swift | 81 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 iOS/RollTheDice/RollTheDice/Source/Domain/Service/BookmarksService.swift diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 107c522a..6a886cd3 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -42,6 +42,7 @@ 6C4F7BAB2BDE50C600ED01DA /* DailyReportModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4F7BAA2BDE50C600ED01DA /* DailyReportModel.swift */; }; 6C4F7BAD2BDE510900ED01DA /* DailyReportViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4F7BAC2BDE510900ED01DA /* DailyReportViewModel.swift */; }; 6C5B0C8A2C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C5B0C892C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift */; }; + 6C5B0C8C2C1C32C000A0D5F4 /* BookmarksService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C5B0C8B2C1C32C000A0D5F4 /* BookmarksService.swift */; }; 6C7651382BF37E7200196536 /* MoyaLoggingPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C7651372BF37E7200196536 /* MoyaLoggingPlugin.swift */; }; 6C76513C2BF37ED300196536 /* Extension+Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C76513B2BF37ED300196536 /* Extension+Log.swift */; }; 6C76513E2BF37F1E00196536 /* Extension+OSLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C76513D2BF37F1E00196536 /* Extension+OSLog.swift */; }; @@ -128,6 +129,7 @@ 6C4F7BAA2BDE50C600ED01DA /* DailyReportModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyReportModel.swift; sourceTree = ""; }; 6C4F7BAC2BDE510900ED01DA /* DailyReportViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyReportViewModel.swift; sourceTree = ""; }; 6C5B0C892C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScoopAPIBookmarks.swift; sourceTree = ""; }; + 6C5B0C8B2C1C32C000A0D5F4 /* BookmarksService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksService.swift; sourceTree = ""; }; 6C7651372BF37E7200196536 /* MoyaLoggingPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoyaLoggingPlugin.swift; sourceTree = ""; }; 6C76513B2BF37ED300196536 /* Extension+Log.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extension+Log.swift"; sourceTree = ""; }; 6C76513D2BF37F1E00196536 /* Extension+OSLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extension+OSLog.swift"; sourceTree = ""; }; @@ -594,6 +596,7 @@ children = ( 6C7651432BF381B000196536 /* Log */, 6CF130B12BAB74BA00A437B6 /* NewsService.swift */, + 6C5B0C8B2C1C32C000A0D5F4 /* BookmarksService.swift */, ); path = Service; sourceTree = ""; @@ -769,6 +772,7 @@ 6C454A782B9DA657006FD9D0 /* SignUpQuestionView.swift in Sources */, 6CA901962BA2EC0100E20259 /* Font.swift in Sources */, 6CF130C22BAB786600A437B6 /* APIHeaderManager.swift in Sources */, + 6C5B0C8C2C1C32C000A0D5F4 /* BookmarksService.swift in Sources */, 6CDB29FB2BAA07B10081037B /* GPTChatViewModel.swift in Sources */, 6C32379F2B7C376D00B699AB /* Bookmarks.swift in Sources */, 6C454A7E2B9DAA3F006FD9D0 /* SignUpFinishView.swift in Sources */, diff --git a/iOS/RollTheDice/RollTheDice/Source/Domain/Service/BookmarksService.swift b/iOS/RollTheDice/RollTheDice/Source/Domain/Service/BookmarksService.swift new file mode 100644 index 00000000..926408bc --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/Domain/Service/BookmarksService.swift @@ -0,0 +1,81 @@ +// +// BookmarksService.swift +// RollTheDice +// +// Created by Subeen on 6/14/24. +// + +import Foundation +import Moya + +enum BookmarksService { + case bookmarksIsChecked(newsId: Int, accessToken: String) ///뉴스 북마크 여부 조회 + case saveBookmarks(newsId: Int, accessToken: String) ///북마크 저장 + case deleteBookmarks(newsId: Int, accessToken: String) ///북마크 삭제 + case allBookmarks(page: Int, size: Int, accessToken: String) ///북마크 전체 조회/ +} + +extension BookmarksService: BaseTargetType { + + var baseURL: URL { + return URL(string: ScoopAPI.baseURL)! + } + + var path: String { + switch self { + case .bookmarksIsChecked(let newsId, _), + .saveBookmarks(let newsId, _), + .deleteBookmarks(let newsId, _) + : + return "\(ScoopAPIBookmarks.bookmarks)/\(newsId)" + + case .allBookmarks: + return ScoopAPIBookmarks.bookmarks + } + } + + var method: Moya.Method { + switch self { + case .bookmarksIsChecked: + return .get + case .saveBookmarks: + return .post + case .deleteBookmarks: + return .delete + case .allBookmarks: + return .get + } + } + + var task: Moya.Task { + switch self { + case .bookmarksIsChecked(let newsId, _), + .saveBookmarks(let newsId, _), + .deleteBookmarks(let newsId, _): + let parameters : [String : Any] = [:] + return .requestParameters(parameters: parameters, encoding: URLEncoding.default) + + case .allBookmarks(let page, let size, _): + let parameters : [String : Any] = [ + "page" : page, + "size" : size, + ] + return .requestParameters(parameters: parameters, + encoding: URLEncoding.queryString) + } + } + + var headers: [String : String]? { + let accessToken: String + switch self { + case .bookmarksIsChecked(_, let accessToken), + .saveBookmarks(_, let accessToken), + .deleteBookmarks(_, let accessToken), + .allBookmarks(_, _, let accessToken): + return [ + "Authorization": "Bearer \(accessToken)", + "X-Content-Type_Options" : "nosniff" + ] + } + } +} From e9b2248949b8511e93ae52b49b78d5fdac7d99e7 Mon Sep 17 00:00:00 2001 From: realhsb Date: Tue, 18 Jun 2024 16:46:36 +0900 Subject: [PATCH 04/61] =?UTF-8?q?chore:=20Macro=20=EC=A0=81=EC=9A=A9=20?= =?UTF-8?q?=ED=9B=84=20@StateObject=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift index 42aaece7..17bfa543 100644 --- a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift +++ b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift @@ -20,7 +20,7 @@ struct RollTheDiceApp: App { var signUpViewModel = SignUpViewModel() var newsListViewModel = NewsListViewModel() - @StateObject var bookmarkListViewModel = BookmarksListViewModel() + var bookmarkListViewModel = BookmarksListViewModel() init() { KakaoSDK.initSDK(appKey: "ff09b3d83873ed4e320f0d6bc90759d6") From b5a7f594a9591ab917caab88924004e8d2eec4d0 Mon Sep 17 00:00:00 2001 From: realhsb Date: Tue, 18 Jun 2024 16:47:06 +0900 Subject: [PATCH 05/61] =?UTF-8?q?chore:=20NewsList=20=EB=B7=B0=20spacing?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RollTheDice/Source/View/News/NewsCard/NewsListView.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsListView.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsListView.swift index faf04761..d95bb351 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsListView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsListView.swift @@ -28,12 +28,11 @@ struct NewsListView: View { private struct NewsListContentView: View { var newsList: [NewsList] - fileprivate var body: some View { GeometryReader { proxy in ScrollView(.horizontal, showsIndicators: false) { - LazyHStack(spacing: -234567876455) { + LazyHStack { ForEach(newsList) { news in NewsView(news: news) From 67e45ef82091d7b646d4fce2d27d13e2a37edefc Mon Sep 17 00:00:00 2001 From: realhsb Date: Tue, 18 Jun 2024 16:47:31 +0900 Subject: [PATCH 06/61] =?UTF-8?q?feat:=20=EB=B6=81=EB=A7=88=ED=81=AC?= =?UTF-8?q?=EB=B7=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Bookmark/BookmarkCard/BookmarkView.swift | 26 ++++++++++++------- .../View/Bookmark/BookmarkListView.swift | 15 +++++++---- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkView.swift index c62ed345..ea1086b4 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkView.swift @@ -7,17 +7,20 @@ import SwiftUI +//let id = UUID().uuidString +//let newsId: Int +//let title, thumbnailURL, postDate: String +//let isBookmarked: Bool + struct BookmarkView: View { - - @State var bookmark: Bookmark - + @State var bookmark: Bookmarks var body: some View { ZStack { Color.gray07.ignoresSafeArea(.all) VStack(alignment: .leading, spacing: 0) { - Text(bookmark.title) + Text(bookmark.title ?? "네트워크 통신 중") .font(.system(size: 24, weight: .bold)) .foregroundStyle(.basicWhite) .multilineTextAlignment(.leading) @@ -26,7 +29,7 @@ struct BookmarkView: View { Spacer() HStack { - AsyncImage(url: URL(string: bookmark.image)) { image in + AsyncImage(url: URL(string: bookmark.thumbnailURL ?? "")) { image in image .resizable() .scaledToFill() @@ -54,7 +57,8 @@ struct BookmarkView: View { .overlay { Button { // TODO: 북마크 설정 / 해제 - bookmark.isBookmarked.toggle() +// bookmark.isBookmarked.toggle() + } label: { Image(systemName: "bookmark.fill") @@ -62,7 +66,7 @@ struct BookmarkView: View { .frame(width: 40, height: 65) // .fixedSize() - .foregroundStyle(bookmark.isBookmarked ? .primary01 : .gray01) + .foregroundStyle(bookmark.isBookmarked ?? true ? .primary01 : .gray01) } .offset(x: 110, y: -130) @@ -70,6 +74,8 @@ struct BookmarkView: View { } } -#Preview { - BookmarkView(bookmark: .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false)) -} +//#Preview { +// BookmarkView(bookmark: .init(newsId: 0, title: "NHN, 작년 영업익 555억원...전년비 42% ↑", thumbnailURL: <#T##String#>, postDate: <#T##String#>, isBookmarked: <#T##Bool#>)) +// +// BookmarkView(bookmark: .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false)) +//} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkListView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkListView.swift index ad0be59d..ae4c8175 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkListView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkListView.swift @@ -8,8 +8,10 @@ import SwiftUI struct BookmarkListView: View { + @EnvironmentObject var pathModel: PathModel - @StateObject var bookmarkListViewModel : BookmarkListViewModel + var bookmarkListViewModel : BookmarksListViewModel + var bookmarkPage: Int? @State var selectedIndex: Int = 0 var columns: [GridItem] = [ GridItem(), GridItem()] @@ -39,16 +41,19 @@ struct BookmarkListView: View { Spacer() } } + .task { + bookmarkListViewModel.getAllBookmarksData(page: 0, size: 10) + } .navigationBarBackButtonHidden() } + @ViewBuilder var bookmarkListView: some View { - ScrollViewReader { value in ScrollView(.horizontal, showsIndicators: false) { LazyHGrid(rows: columns, spacing: 10) { - ForEach(bookmarkListViewModel.bookmarkList, id: \.self) { bookmark in + ForEach(bookmarkListViewModel.bookmarksList ?? []) { bookmark in BookmarkView(bookmark: bookmark) // .onTapGesture { // withAnimation { @@ -89,6 +94,6 @@ struct BookmarkListView: View { } #Preview { - BookmarkListView(bookmarkListViewModel: BookmarkListViewModel()) - .environmentObject(BookmarkListViewModel()) + BookmarkListView(bookmarkListViewModel: BookmarksListViewModel()) + .environmentObject(PathModel()) } From 82c53dbad12d0861cc4f580433b44ab219b0a7b2 Mon Sep 17 00:00:00 2001 From: realhsb Date: Tue, 18 Jun 2024 17:18:26 +0900 Subject: [PATCH 07/61] =?UTF-8?q?chore:=20News=20=ED=8F=B4=EB=8D=94=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RollTheDice.xcodeproj/project.pbxproj | 32 +++++++++---------- .../DetailNewsCard/DetailCardNews.swift | 0 .../DetailNews.swift | 0 .../DetailNewsViewModel.swift | 0 .../{NewsCard => NewsList}/NewsList.swift | 0 .../{NewsCard => NewsList}/NewsListView.swift | 0 .../NewsListViewModel.swift | 0 .../{NewsCard => NewsList}/NewsView.swift | 0 .../News/{NewsCard => }/WebView/WebView.swift | 0 9 files changed, 16 insertions(+), 16 deletions(-) rename iOS/RollTheDice/RollTheDice/Source/View/News/{NewsCard => }/DetailNewsCard/DetailCardNews.swift (100%) rename iOS/RollTheDice/RollTheDice/Source/View/News/{NewsCard => DetailNewsCard}/DetailNews.swift (100%) rename iOS/RollTheDice/RollTheDice/Source/View/News/{NewsCard => DetailNewsCard}/DetailNewsViewModel.swift (100%) rename iOS/RollTheDice/RollTheDice/Source/View/News/{NewsCard => NewsList}/NewsList.swift (100%) rename iOS/RollTheDice/RollTheDice/Source/View/News/{NewsCard => NewsList}/NewsListView.swift (100%) rename iOS/RollTheDice/RollTheDice/Source/View/News/{NewsCard => NewsList}/NewsListViewModel.swift (100%) rename iOS/RollTheDice/RollTheDice/Source/View/News/{NewsCard => NewsList}/NewsView.swift (100%) rename iOS/RollTheDice/RollTheDice/Source/View/News/{NewsCard => }/WebView/WebView.swift (100%) diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 6a886cd3..714e0466 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -225,21 +225,6 @@ path = BookmarkCard; sourceTree = ""; }; - 6C3237A82B7C380200B699AB /* NewsCard */ = { - isa = PBXGroup; - children = ( - 6C7651472BF5FDB100196536 /* WebView */, - 6C94799F2BD3CC0400D5AEEB /* DetailNewsCard */, - 6C77048E2B7229B1001B17CB /* NewsListView.swift */, - 6C3237B12B7C385000B699AB /* NewsListViewModel.swift */, - 6C3237A92B7C381500B699AB /* NewsView.swift */, - 6C3237AD2B7C382E00B699AB /* DetailNewsViewModel.swift */, - 6C3237AB2B7C382200B699AB /* NewsList.swift */, - 6C7651452BF5B45A00196536 /* DetailNews.swift */, - ); - path = NewsCard; - sourceTree = ""; - }; 6C3237B32B7C433000B699AB /* ChatType */ = { isa = PBXGroup; children = ( @@ -392,7 +377,9 @@ 6C77048D2B7229A3001B17CB /* News */ = { isa = PBXGroup; children = ( - 6C3237A82B7C380200B699AB /* NewsCard */, + 6CC673782C217999009FB30E /* NewsList */, + 6C7651472BF5FDB100196536 /* WebView */, + 6C94799F2BD3CC0400D5AEEB /* DetailNewsCard */, ); path = News; sourceTree = ""; @@ -436,6 +423,8 @@ 6C94799F2BD3CC0400D5AEEB /* DetailNewsCard */ = { isa = PBXGroup; children = ( + 6C3237AD2B7C382E00B699AB /* DetailNewsViewModel.swift */, + 6C7651452BF5B45A00196536 /* DetailNews.swift */, 357FC6E92BCE866B00AD8915 /* DetailCardNews.swift */, ); path = DetailNewsCard; @@ -503,6 +492,17 @@ path = "Preview Content"; sourceTree = ""; }; + 6CC673782C217999009FB30E /* NewsList */ = { + isa = PBXGroup; + children = ( + 6C3237A92B7C381500B699AB /* NewsView.swift */, + 6C77048E2B7229B1001B17CB /* NewsListView.swift */, + 6C3237B12B7C385000B699AB /* NewsListViewModel.swift */, + 6C3237AB2B7C382200B699AB /* NewsList.swift */, + ); + path = NewsList; + sourceTree = ""; + }; 6CDB29F72BAA06FB0081037B /* ChatGPT */ = { isa = PBXGroup; children = ( diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/DetailNewsCard/DetailCardNews.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/DetailNewsCard/DetailCardNews.swift similarity index 100% rename from iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/DetailNewsCard/DetailCardNews.swift rename to iOS/RollTheDice/RollTheDice/Source/View/News/DetailNewsCard/DetailCardNews.swift diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/DetailNews.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/DetailNewsCard/DetailNews.swift similarity index 100% rename from iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/DetailNews.swift rename to iOS/RollTheDice/RollTheDice/Source/View/News/DetailNewsCard/DetailNews.swift diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/DetailNewsViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/DetailNewsCard/DetailNewsViewModel.swift similarity index 100% rename from iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/DetailNewsViewModel.swift rename to iOS/RollTheDice/RollTheDice/Source/View/News/DetailNewsCard/DetailNewsViewModel.swift diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsList.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsList.swift similarity index 100% rename from iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsList.swift rename to iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsList.swift diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsListView.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsListView.swift similarity index 100% rename from iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsListView.swift rename to iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsListView.swift diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsListViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsListViewModel.swift similarity index 100% rename from iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsListViewModel.swift rename to iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsListViewModel.swift diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsView.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsView.swift similarity index 100% rename from iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsView.swift rename to iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsView.swift diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/WebView/WebView.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/WebView/WebView.swift similarity index 100% rename from iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/WebView/WebView.swift rename to iOS/RollTheDice/RollTheDice/Source/View/News/WebView/WebView.swift From 93999e1dbce5d3f265c466903b2dafcc05357675 Mon Sep 17 00:00:00 2001 From: realhsb Date: Wed, 19 Jun 2024 03:35:07 +0900 Subject: [PATCH 08/61] =?UTF-8?q?feat:=20AuthAPI=20->=20LoginService=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RollTheDice.xcodeproj/project.pbxproj | 5 +- .../Source/Domain/Service/LoginService.swift | 56 +++++++++++++++++++ .../Source/View/Authentication/AuthAPI.swift | 54 ------------------ 3 files changed, 59 insertions(+), 56 deletions(-) create mode 100644 iOS/RollTheDice/RollTheDice/Source/Domain/Service/LoginService.swift delete mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthAPI.swift diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 714e0466..c6aa52ca 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -103,7 +103,7 @@ 350909192C1C1248007D76A1 /* TokenManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenManager.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 /* AuthAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthAPI.swift; sourceTree = ""; }; + 357699432C09C7B900AD2DA4 /* LoginService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginService.swift; sourceTree = ""; }; 357FC6E92BCE866B00AD8915 /* DetailCardNews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailCardNews.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 = ""; }; @@ -731,13 +731,14 @@ files = ( 6C454A882B9DB6C2006FD9D0 /* CustomNavigationBar.swift in Sources */, 6CF130BF2BAB783300A437B6 /* APIConstants.swift in Sources */, - 357699442C09C7B900AD2DA4 /* AuthAPI.swift in Sources */, + 357699442C09C7B900AD2DA4 /* LoginService.swift in Sources */, 6C76513C2BF37ED300196536 /* Extension+Log.swift in Sources */, 6CE103102BD56A5B00498AA4 /* TypeReportViewModel.swift in Sources */, 6C5B0C8A2C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift in Sources */, 6CF130C52BAB79DE00A437B6 /* ScoopAPI.swift in Sources */, 6CE103132BD56B1200498AA4 /* DailyReportView.swift in Sources */, 6C454A7A2B9DA67C006FD9D0 /* SignUpViewModel.swift in Sources */, + 6CC6737A2C217C4B009FB30E /* ScoopAPILogin.swift in Sources */, 6C3237AA2B7C381500B699AB /* NewsView.swift in Sources */, 6CF130C92BAB7CC200A437B6 /* BaseTargetType.swift in Sources */, 6C7651492BF5FDB900196536 /* WebView.swift in Sources */, diff --git a/iOS/RollTheDice/RollTheDice/Source/Domain/Service/LoginService.swift b/iOS/RollTheDice/RollTheDice/Source/Domain/Service/LoginService.swift new file mode 100644 index 00000000..7b1b2ef7 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/Domain/Service/LoginService.swift @@ -0,0 +1,56 @@ +// +// AuthAPI.swift +// RollTheDice +// +// Created by 신예진 on 5/31/24. +// + +import Foundation +import Moya + +enum LoginService { + case login(token: String, socialType: String) +} + +//struct LoginService { +// static let provider = MoyaProvider() +//} + +extension LoginService: BaseTargetType { + + var baseURL: URL { + return URL(string: ScoopAPI.baseURL)! + } + + var path: String { + switch self { + case .login: + return ScoopAPILogin.login + } + } + + var method: Moya.Method { + switch self { + case .login: + return .post + } + } + + var task: Task { + switch self { + case .login(let token, let socialType): + let parameters : [String : Any] = [ + "token" : token, + "socialType" : socialType, + ] + + return .requestParameters(parameters: parameters, encoding: URLEncoding.queryString) + } + } + + var headers: [String: String]? { + return [ + "X-Content-Type_Options" : "nosniff" + ] + } +} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthAPI.swift b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthAPI.swift deleted file mode 100644 index 54af7c2c..00000000 --- a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthAPI.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// AuthAPI.swift -// RollTheDice -// -// Created by 신예진 on 5/31/24. -// - -import Foundation -import Moya - -struct AuthProvider { - static let provider = MoyaProvider() -} - -enum AuthTarget: TargetType { - case login(token: String) - - var baseURL: URL { - return URL(string: "http://ec2-13-124-191-244.ap-northeast-2.compute.amazonaws.com:8080")! - } - - var path: String { - switch self { - case .login: - return "/login" - } - } - - var method: Moya.Method { - switch self { - case .login: - return .post - } - } - - var task: Task { - switch self { - case .login(let token): - return .requestParameters(parameters: ["accessToken": token], encoding: JSONEncoding.default) - } - } - -// var headers: [String: String]? { -// return ["Content-Type": "application/json"] -// } - - var headers: [String: String]? { - var headers = [String: String]() - if let token = TokenManager.shared.accessToken { - headers["Authorization"] = "Bearer \(token)" - } - return headers - } -} From f0fc24f0482de06bb9b9f8f58b9e91e4bd9447ff Mon Sep 17 00:00:00 2001 From: realhsb Date: Wed, 19 Jun 2024 03:37:27 +0900 Subject: [PATCH 09/61] =?UTF-8?q?feat:=20baseURL=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RollTheDice/Source/Domain/API/APIHeaderManager.swift | 4 ++-- .../RollTheDice/Source/Domain/ScoopAPI/ScoopAPI.swift | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/Domain/API/APIHeaderManager.swift b/iOS/RollTheDice/RollTheDice/Source/Domain/API/APIHeaderManager.swift index 81c204d8..cc337cd0 100644 --- a/iOS/RollTheDice/RollTheDice/Source/Domain/API/APIHeaderManager.swift +++ b/iOS/RollTheDice/RollTheDice/Source/Domain/API/APIHeaderManager.swift @@ -12,8 +12,8 @@ public class APIHeaderManager { static let shared = APIHeaderManager() let contentType: String = "application/json" - let scoopHost: String = "ec2-13-124-191-244.ap-northeast-2.compute.amazonaws.com:8080" +// let scoopHost: String = "ec2-13-124-191-244.ap-northeast-2.compute.amazonaws.com:8080" + let scoopHost: String = "roll-the-dice.store:8080" } - // http://ec2-13-124-191-244.ap-northeast-2.compute.amazonaws.com:8080/swagger-ui/index.html diff --git a/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPI.swift b/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPI.swift index 0784adf7..966bd589 100644 --- a/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPI.swift +++ b/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPI.swift @@ -8,5 +8,6 @@ import Foundation enum ScoopAPI { - static let baseURL = "http://ec2-13-124-191-244.ap-northeast-2.compute.amazonaws.com:8080" +// static let baseURL = "http://ec2-13-124-191-244.ap-northeast-2.compute.amazonaws.com:8080" + static let baseURL = "http://roll-the-dice.store:8080" } From 1c20dffed0846a3da9f8b8332933b79f4fcd4d9c Mon Sep 17 00:00:00 2001 From: realhsb Date: Wed, 19 Jun 2024 03:38:39 +0900 Subject: [PATCH 10/61] =?UTF-8?q?feat:=20Auth=20(=EC=84=9C=EB=B2=84=20?= =?UTF-8?q?=ED=86=A0=ED=81=B0=20response)=20=EB=AA=A8=EB=8D=B8=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RollTheDice.xcodeproj/project.pbxproj | 7 +++++-- .../Source/View/Authentication/Auth.swift | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index c6aa52ca..7e9dacb6 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -15,7 +15,7 @@ 3576993E2C09C1EB00AD2DA4 /* KakaoSDKCert in Frameworks */ = {isa = PBXBuildFile; productRef = 3576993D2C09C1EB00AD2DA4 /* KakaoSDKCert */; }; 357699402C09C1EB00AD2DA4 /* KakaoSDKCertCore in Frameworks */ = {isa = PBXBuildFile; productRef = 3576993F2C09C1EB00AD2DA4 /* KakaoSDKCertCore */; }; 357699422C09C1EB00AD2DA4 /* KakaoSDKCommon in Frameworks */ = {isa = PBXBuildFile; productRef = 357699412C09C1EB00AD2DA4 /* KakaoSDKCommon */; }; - 357699442C09C7B900AD2DA4 /* AuthAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 357699432C09C7B900AD2DA4 /* AuthAPI.swift */; }; + 357699442C09C7B900AD2DA4 /* LoginService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 357699432C09C7B900AD2DA4 /* LoginService.swift */; }; 357FC6EA2BCE866B00AD8915 /* DetailCardNews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 357FC6E92BCE866B00AD8915 /* DetailCardNews.swift */; }; 35C71BF22B79F39900F777D1 /* ExyteChat in Frameworks */ = {isa = PBXBuildFile; productRef = 35C71BF12B79F39900F777D1 /* ExyteChat */; }; 6C32379F2B7C376D00B699AB /* Bookmarks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C32379E2B7C376D00B699AB /* Bookmarks.swift */; }; @@ -64,6 +64,7 @@ 6CC4DDC92B5574670080E7E8 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC4DDC82B5574670080E7E8 /* ContentView.swift */; }; 6CC4DDCB2B5574690080E7E8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6CC4DDCA2B5574690080E7E8 /* Assets.xcassets */; }; 6CC4DDCE2B5574690080E7E8 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6CC4DDCD2B5574690080E7E8 /* Preview Assets.xcassets */; }; + 6CC6737C2C21BA5B009FB30E /* Auth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC6737B2C21BA5B009FB30E /* Auth.swift */; }; 6CDB29C92BA97C550081037B /* Pretendard-Black.otf in Resources */ = {isa = PBXBuildFile; fileRef = 6CDB29C02BA97C550081037B /* Pretendard-Black.otf */; }; 6CDB29CA2BA97C550081037B /* Pretendard-ExtraBold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 6CDB29C12BA97C550081037B /* Pretendard-ExtraBold.otf */; }; 6CDB29CB2BA97C550081037B /* Pretendard-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 6CDB29C22BA97C550081037B /* Pretendard-Regular.otf */; }; @@ -152,6 +153,7 @@ 6CC4DDC82B5574670080E7E8 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 6CC4DDCA2B5574690080E7E8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 6CC4DDCD2B5574690080E7E8 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 6CC6737B2C21BA5B009FB30E /* Auth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Auth.swift; sourceTree = ""; }; 6CDB29BF2BA9735C0081037B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 6CDB29C02BA97C550081037B /* Pretendard-Black.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Black.otf"; sourceTree = ""; }; 6CDB29C12BA97C550081037B /* Pretendard-ExtraBold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-ExtraBold.otf"; sourceTree = ""; }; @@ -575,7 +577,7 @@ children = ( 6CF130AC2BAB0C4400A437B6 /* AuthenticationViewModel.swift */, 6CF130AE2BAB0C4F00A437B6 /* AuthenticatedView.swift */, - 357699432C09C7B900AD2DA4 /* AuthAPI.swift */, + 6CC6737B2C21BA5B009FB30E /* Auth.swift */, ); path = Authentication; sourceTree = ""; @@ -755,6 +757,7 @@ 6C3237AC2B7C382200B699AB /* NewsList.swift in Sources */, 6CE1030E2BD56A5200498AA4 /* TypeReportModel.swift in Sources */, 6C76513E2BF37F1E00196536 /* Extension+OSLog.swift in Sources */, + 6CC6737C2C21BA5B009FB30E /* Auth.swift in Sources */, 357FC6EA2BCE866B00AD8915 /* DetailCardNews.swift in Sources */, 6CC4DDC92B5574670080E7E8 /* ContentView.swift in Sources */, 6C3237A52B7C37D100B699AB /* BookmarkView.swift in Sources */, diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift new file mode 100644 index 00000000..00c267c9 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift @@ -0,0 +1,18 @@ +// +// Auth.swift +// RollTheDice +// +// Created by Subeen on 6/18/24. +// + +import Foundation + +struct AuthModel { + let Authorization: String? + let AuthorizationRefresh: String? + + enum CodingKeys: String, CodingKey { + case Authorization + case AuthorizationRefresh = "Authorization-refresh" + } +} From 34027cd9f33723875c09bb5583436dfce9d020ef Mon Sep 17 00:00:00 2001 From: realhsb Date: Wed, 19 Jun 2024 03:39:23 +0900 Subject: [PATCH 11/61] =?UTF-8?q?feat:=20login=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RollTheDice.xcodeproj/project.pbxproj | 4 ++++ .../Source/Domain/ScoopAPI/ScoopAPILogin.swift | 12 ++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPILogin.swift diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 7e9dacb6..64081947 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -64,6 +64,7 @@ 6CC4DDC92B5574670080E7E8 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC4DDC82B5574670080E7E8 /* ContentView.swift */; }; 6CC4DDCB2B5574690080E7E8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6CC4DDCA2B5574690080E7E8 /* Assets.xcassets */; }; 6CC4DDCE2B5574690080E7E8 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6CC4DDCD2B5574690080E7E8 /* Preview Assets.xcassets */; }; + 6CC6737A2C217C4B009FB30E /* ScoopAPILogin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC673792C217C4B009FB30E /* ScoopAPILogin.swift */; }; 6CC6737C2C21BA5B009FB30E /* Auth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC6737B2C21BA5B009FB30E /* Auth.swift */; }; 6CDB29C92BA97C550081037B /* Pretendard-Black.otf in Resources */ = {isa = PBXBuildFile; fileRef = 6CDB29C02BA97C550081037B /* Pretendard-Black.otf */; }; 6CDB29CA2BA97C550081037B /* Pretendard-ExtraBold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 6CDB29C12BA97C550081037B /* Pretendard-ExtraBold.otf */; }; @@ -153,6 +154,7 @@ 6CC4DDC82B5574670080E7E8 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 6CC4DDCA2B5574690080E7E8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 6CC4DDCD2B5574690080E7E8 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 6CC673792C217C4B009FB30E /* ScoopAPILogin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScoopAPILogin.swift; sourceTree = ""; }; 6CC6737B2C21BA5B009FB30E /* Auth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Auth.swift; sourceTree = ""; }; 6CDB29BF2BA9735C0081037B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 6CDB29C02BA97C550081037B /* Pretendard-Black.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Black.otf"; sourceTree = ""; }; @@ -599,6 +601,7 @@ 6C7651432BF381B000196536 /* Log */, 6CF130B12BAB74BA00A437B6 /* NewsService.swift */, 6C5B0C8B2C1C32C000A0D5F4 /* BookmarksService.swift */, + 357699432C09C7B900AD2DA4 /* LoginService.swift */, ); path = Service; sourceTree = ""; @@ -627,6 +630,7 @@ 6CF130C42BAB79DE00A437B6 /* ScoopAPI.swift */, 6CF130C62BAB7B9800A437B6 /* ScoopAPINews.swift */, 6C5B0C892C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift */, + 6CC673792C217C4B009FB30E /* ScoopAPILogin.swift */, ); path = ScoopAPI; sourceTree = ""; diff --git a/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPILogin.swift b/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPILogin.swift new file mode 100644 index 00000000..0aa1c3ba --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPILogin.swift @@ -0,0 +1,12 @@ +// +// ScoopAPILogin.swift +// RollTheDice +// +// Created by Subeen on 6/18/24. +// + +import Foundation + +public enum ScoopAPILogin { + public static let login = String("/login") +} From b078e145de9681fda86579acc1ef74d0b5a6274b Mon Sep 17 00:00:00 2001 From: realhsb Date: Wed, 19 Jun 2024 03:39:41 +0900 Subject: [PATCH 12/61] =?UTF-8?q?chore:=20AuthVM=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AuthenticationViewModel.swift | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticationViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticationViewModel.swift index 521d3965..fcec3dc1 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticationViewModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticationViewModel.swift @@ -8,6 +8,7 @@ import Foundation import KakaoSDKAuth import KakaoSDKUser +import Moya enum AuthenticationState { @@ -20,9 +21,13 @@ enum AuthenticationState { // 로그인 상태에 따라 화면 분기처리 var authenticationState: AuthenticationState = .unauthenticated var isLoading = false + + let provider = MoyaProvider() } extension AuthenticationViewModel { + + func loginWithKakao() { if (UserApi.isKakaoTalkLoginAvailable()) { UserApi.shared.loginWithKakaoTalk { (oauthToken, error) in @@ -34,10 +39,14 @@ extension AuthenticationViewModel { UserApi.shared.me { (user, error) in if let error = error { print("Kakao user info error: \(error)") + self.authenticationState = .unauthenticated } else { // 사용자 정보 처리 - self.authenticationState = .authenticated +// self.authenticationState = .authenticated + self.loginToBackend(with: oauthToken!.accessToken, socialType: "KAKAO") + + } } } @@ -50,14 +59,19 @@ extension AuthenticationViewModel { } extension AuthenticationViewModel { - func loginToBackend(with token: String) { - AuthProvider.provider.request(.login(token: token)) { result in + func loginToBackend(with token: String, socialType: String) { + self.provider.request(.login(token: token, socialType: socialType)) { result in switch result { case .success(let response): + + do { let json = try response.mapJSON() print("Login response: \(json)") - self.authenticationState = .completedSignUp +// self.authenticationState = .completedSignUp + + TokenManager.shared.accessToken = token + } catch { print("Login error: \(error)") self.authenticationState = .unauthenticated From 3b452128b8ea2561a90de4f972c5b939ef05147a Mon Sep 17 00:00:00 2001 From: realhsb Date: Wed, 19 Jun 2024 05:05:44 +0900 Subject: [PATCH 13/61] =?UTF-8?q?chore:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Authentication/AuthenticatedView.swift | 39 +------------------ 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticatedView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticatedView.swift index 72eb4ff6..759b8bd8 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticatedView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticatedView.swift @@ -122,45 +122,8 @@ struct AuthenticatedView: View { .frame(height: 50) } -// Button { -// if (UserApi.isKakaoTalkLoginAvailable()) { -// UserApi.shared.loginWithKakaoTalk {(oauthToken, error) in -// print(oauthToken) -// print(error) -// } -// } else { -// UserApi.shared.loginWithKakaoAccount {(oauthToken, error) in -// print(oauthToken) -// print(error) -// } -// } -// -// } label: { -// Image(.kakaoSignInBtn01) -// .resizable() -// .aspectRatio(contentMode: .fit) -// .frame(height: 50) -// } Button { - if UserApi.isKakaoTalkLoginAvailable() { - UserApi.shared.loginWithKakaoTalk { (oauthToken, error) in - if let error = error { - print("Kakao Login Error: \(error)") - } else if let oauthToken = oauthToken { - print("Kakao Login Success: \(oauthToken)") - TokenManager.shared.accessToken = oauthToken.accessToken - authViewModel.authenticationState = .completedSignUp } - } - } else { - UserApi.shared.loginWithKakaoAccount { (oauthToken, error) in - if let error = error { - print("Kakao Login Error: \(error)") - } else if let oauthToken = oauthToken { - print("Kakao Login Success: \(oauthToken)") - TokenManager.shared.accessToken = oauthToken.accessToken - authViewModel.authenticationState = .completedSignUp } - } - } + authViewModel.loginWithKakao() } label: { Image(.kakaoSignInBtn01) .resizable() From 2ee803c717f54ffac531f64cebc841a395a2b019 Mon Sep 17 00:00:00 2001 From: realhsb Date: Wed, 19 Jun 2024 05:06:45 +0900 Subject: [PATCH 14/61] =?UTF-8?q?chore:=20auth=20=EB=AA=A8=EB=8D=B8=20?= =?UTF-8?q?=EB=B3=80=EC=88=98=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Source/View/Authentication/Auth.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift index 00c267c9..8fb26bff 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift @@ -7,12 +7,12 @@ import Foundation -struct AuthModel { - let Authorization: String? - let AuthorizationRefresh: String? +struct AuthModel: Codable { + let accessToken: String? + let refreshToken: String? - enum CodingKeys: String, CodingKey { - case Authorization - case AuthorizationRefresh = "Authorization-refresh" - } +// enum CodingKeys: String, CodingKey { +// case Authorization +// case AuthorizationRefresh = "Authorization-refresh" +// } } From fbca176f5ad60aeb964053334e7693231c061651 Mon Sep 17 00:00:00 2001 From: realhsb Date: Wed, 19 Jun 2024 05:07:31 +0900 Subject: [PATCH 15/61] =?UTF-8?q?feat:=20auth=20request=20=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RollTheDice/Source/View/Authentication/Auth.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift index 8fb26bff..61d65c61 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift @@ -16,3 +16,8 @@ struct AuthModel: Codable { // case AuthorizationRefresh = "Authorization-refresh" // } } + +struct AuthRequestModel: Codable { + let token: String? + let socialType: String? +} From 6f74dce9b69a8d6ee78cc4bf2c027392d0cd3f6f Mon Sep 17 00:00:00 2001 From: realhsb Date: Wed, 19 Jun 2024 05:07:56 +0900 Subject: [PATCH 16/61] =?UTF-8?q?chore:=20auth=20request=20=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Source/Domain/Service/LoginService.swift | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/Domain/Service/LoginService.swift b/iOS/RollTheDice/RollTheDice/Source/Domain/Service/LoginService.swift index 7b1b2ef7..5a82988d 100644 --- a/iOS/RollTheDice/RollTheDice/Source/Domain/Service/LoginService.swift +++ b/iOS/RollTheDice/RollTheDice/Source/Domain/Service/LoginService.swift @@ -9,7 +9,7 @@ import Foundation import Moya enum LoginService { - case login(token: String, socialType: String) + case login(request: AuthRequestModel) } //struct LoginService { @@ -36,15 +36,15 @@ extension LoginService: BaseTargetType { } } - var task: Task { + var task: Moya.Task { switch self { - case .login(let token, let socialType): - let parameters : [String : Any] = [ - "token" : token, - "socialType" : socialType, - ] - - return .requestParameters(parameters: parameters, encoding: URLEncoding.queryString) + case .login(let request): +// let parameters : [String : Any] = [ +// "token" : token, +// "socialType" : socialType, +// ] +// return .requestParameters(parameters: parameters, encoding: URLEncoding.queryString) + return .requestJSONEncodable(request) } } From 2e2914d4ee0f1ed3c9aebb0efc9ee10475d79e50 Mon Sep 17 00:00:00 2001 From: realhsb Date: Wed, 19 Jun 2024 05:08:26 +0900 Subject: [PATCH 17/61] =?UTF-8?q?chore:=20auth=20VM=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AuthenticationViewModel.swift | 80 ++++++++++++++----- 1 file changed, 58 insertions(+), 22 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticationViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticationViewModel.swift index fcec3dc1..89cfa146 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticationViewModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticationViewModel.swift @@ -9,6 +9,8 @@ import Foundation import KakaoSDKAuth import KakaoSDKUser import Moya +import Combine +import CombineMoya enum AuthenticationState { @@ -22,13 +24,24 @@ enum AuthenticationState { var authenticationState: AuthenticationState = .unauthenticated var isLoading = false - let provider = MoyaProvider() + + + var authModel: AuthModel? + var authCancellable: AnyCancellable? + + let provider = MoyaProvider(plugins: [MoyaLoggingPlugin()]) + + func authModelToViewModel(_ list: AuthModel) { + self.authModel = list + } } extension AuthenticationViewModel { func loginWithKakao() { + + print("loginWithKakao") if (UserApi.isKakaoTalkLoginAvailable()) { UserApi.shared.loginWithKakaoTalk { (oauthToken, error) in if let error = error { @@ -44,43 +57,66 @@ extension AuthenticationViewModel { } else { // 사용자 정보 처리 // self.authenticationState = .authenticated - self.loginToBackend(with: oauthToken!.accessToken, socialType: "KAKAO") - + // oauthToken 카카오에서 발급한 accessToken +// self.loginToBackend(with: oauthToken!.accessToken, socialType: "KAKAO") + let authRequest = AuthRequestModel(token: oauthToken!.accessToken, socialType: "KAKAO") + self.loginToBackend(authRequest: authRequest) } } } } } else { // Kakao 계정으로 로그인할 수 없는 경우 처리 - self.authenticationState = .unauthenticated + UserApi.shared.loginWithKakaoAccount { (oauthToken, error) in + if let error = error { + print("Kakao Login Error: \(error)") + self.authenticationState = .unauthenticated + } else if let oauthToken = oauthToken { + print("Kakao Login Success: \(oauthToken)") + self.authenticationState = .authenticated + + let authRequest = AuthRequestModel(token: oauthToken.accessToken, socialType: "KAKAO") + self.loginToBackend(authRequest: authRequest) + + } + } + } } } extension AuthenticationViewModel { - func loginToBackend(with token: String, socialType: String) { - self.provider.request(.login(token: token, socialType: socialType)) { result in + + func loginToBackend(authRequest: AuthRequestModel) { + print("loginToBackend \(authRequest.token)") + + if let cancellable = authCancellable { + cancellable.cancel() + } + + authCancellable = provider.requestWithProgressPublisher( + .login(request: authRequest) + ) + .compactMap { $0.response?.data } + .receive(on: DispatchQueue.main) + .decode(type: AuthModel.self, decoder: JSONDecoder()) + .sink(receiveCompletion: { result in switch result { - case .success(let response): - + case .finished: + print("서버 토큰 발급 연결 성공") - do { - let json = try response.mapJSON() - print("Login response: \(json)") -// self.authenticationState = .completedSignUp - - TokenManager.shared.accessToken = token - - } catch { - print("Login error: \(error)") - self.authenticationState = .unauthenticated - } + // TODO: 여기 지워야 함. 로그인 -> 회원가입 -> 메인 절차 + self.authenticationState = .completedSignUp case .failure(let error): - print("Login error: \(error)") - self.authenticationState = .unauthenticated + Log.network("network error 서버 토큰 발급 연결 실패", error.localizedDescription) } - } + }, receiveValue: { [weak self] response in + self?.authModelToViewModel(response) + print("서버 토큰 : \(response.accessToken)") + + TokenManager.shared.accessToken = response.accessToken + }) } } From ad8fc2dedd45f1f0a26b0f18c4ae0ffb18302c32 Mon Sep 17 00:00:00 2001 From: yeahzxnn Date: Wed, 19 Jun 2024 13:13:56 +0900 Subject: [PATCH 18/61] =?UTF-8?q?fix=20&=20feat=20:=20=ED=86=A0=EB=A1=A0?= =?UTF-8?q?=EB=B0=A9=20=EC=83=9D=EC=84=B1=20API=20=EC=97=B0=EB=8F=99=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 | 32 ++++++++++- .../RollTheDice/RollTheDiceApp.swift | 2 + .../Source/Model/Path/PathType.swift | 2 + .../Debate/ChatList/RecentNewsCardView.swift | 17 +++++- .../Service/CreateDebateRoomService.swift | 50 ++++++++++++++++++ .../ViewModel/CreateDebateRoomViewModel.swift | 45 ++++++++++++++++ 7 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/CreateDebateRoomService.swift create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/CreateDebateRoomViewModel.swift diff --git a/iOS/RollTheDice/.DS_Store b/iOS/RollTheDice/.DS_Store index 0ed7ed287d10ca2ba122648fa0235e0d173b019d..301a5825fd4fa17371c375e78153dfbe265e7e66 100644 GIT binary patch delta 61 zcmZoMXffE}&cw|4(tGkbCcViOOgwDS57Sq<3r;@6WH5ObGS`-g$zZb}^EZ}>4Q!j) IIsWnk0F(0+{r~^~ delta 61 zcmZoMXffE}&cw{j>OT1#liuVCCLT7^784atzR72p3?}bF=Grnb2W%E({>Cz~fo(H8 H$6tN`3K0=M diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 64081947..20e34247 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -8,6 +8,8 @@ /* Begin PBXBuildFile section */ 3509091A2C1C1248007D76A1 /* TokenManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 350909192C1C1248007D76A1 /* TokenManager.swift */; }; + 3544D7402C228EFC007DBD18 /* CreateDebateRoomService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3544D73F2C228EFC007DBD18 /* CreateDebateRoomService.swift */; }; + 3544D7432C228F54007DBD18 /* CreateDebateRoomViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3544D7422C228F54007DBD18 /* CreateDebateRoomViewModel.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 */; }; @@ -103,6 +105,8 @@ /* Begin PBXFileReference section */ 350909192C1C1248007D76A1 /* TokenManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenManager.swift; sourceTree = ""; }; + 3544D73F2C228EFC007DBD18 /* CreateDebateRoomService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateDebateRoomService.swift; sourceTree = ""; }; + 3544D7422C228F54007DBD18 /* CreateDebateRoomViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateDebateRoomViewModel.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 = ""; }; @@ -210,6 +214,22 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 3544D73E2C228EDB007DBD18 /* Service */ = { + isa = PBXGroup; + children = ( + 3544D73F2C228EFC007DBD18 /* CreateDebateRoomService.swift */, + ); + path = Service; + sourceTree = ""; + }; + 3544D7412C228F39007DBD18 /* ViewModel */ = { + isa = PBXGroup; + children = ( + 3544D7422C228F54007DBD18 /* CreateDebateRoomViewModel.swift */, + ); + path = ViewModel; + sourceTree = ""; + }; 357666112BBD5494002C226A /* Splah */ = { isa = PBXGroup; children = ( @@ -249,6 +269,8 @@ 6C41B8D62BE1048500274FA4 /* ChatList */ = { isa = PBXGroup; children = ( + 3544D7412C228F39007DBD18 /* ViewModel */, + 3544D73E2C228EDB007DBD18 /* Service */, 6C41B8D92BE104A800274FA4 /* RecentNewsCardView.swift */, 6C41B8DB2BE1095800274FA4 /* ChatListView.swift */, ); @@ -750,6 +772,7 @@ 6C7651492BF5FDB900196536 /* WebView.swift in Sources */, 6CDB29FF2BAA08280081037B /* GPTChatListViewModel.swift in Sources */, 6CF130AD2BAB0C4400A437B6 /* AuthenticationViewModel.swift in Sources */, + 3544D7402C228EFC007DBD18 /* CreateDebateRoomService.swift in Sources */, 6CDB29F92BAA07350081037B /* GPTChat.swift in Sources */, 6C41B8DC2BE1095800274FA4 /* ChatListView.swift in Sources */, 6CDB29FD2BAA07FD0081037B /* GPTChatView.swift in Sources */, @@ -763,6 +786,7 @@ 6C76513E2BF37F1E00196536 /* Extension+OSLog.swift in Sources */, 6CC6737C2C21BA5B009FB30E /* Auth.swift in Sources */, 357FC6EA2BCE866B00AD8915 /* DetailCardNews.swift in Sources */, + 3544D7432C228F54007DBD18 /* CreateDebateRoomViewModel.swift in Sources */, 6CC4DDC92B5574670080E7E8 /* ContentView.swift in Sources */, 6C3237A52B7C37D100B699AB /* BookmarkView.swift in Sources */, 6C3237AE2B7C382E00B699AB /* DetailNewsViewModel.swift in Sources */, @@ -932,10 +956,11 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"RollTheDice/Preview Content\""; - DEVELOPMENT_TEAM = 4YH4UGRTMH; + DEVELOPMENT_TEAM = NTXM48C3F8; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = RollTheDice/Resources/Support/Info.plist; @@ -951,6 +976,7 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = jinjihan.RollTheDice; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -962,10 +988,11 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"RollTheDice/Preview Content\""; - DEVELOPMENT_TEAM = 4YH4UGRTMH; + DEVELOPMENT_TEAM = NTXM48C3F8; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = RollTheDice/Resources/Support/Info.plist; @@ -981,6 +1008,7 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = jinjihan.RollTheDice; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift index 17bfa543..3ea1b27f 100644 --- a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift +++ b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift @@ -66,6 +66,8 @@ struct RollTheDiceApp: App { DebateSummaryView() case .webView(let url): WebView(urlToLoad: url) + case .createdebateroom: + GPTChatView() } }) } diff --git a/iOS/RollTheDice/RollTheDice/Source/Model/Path/PathType.swift b/iOS/RollTheDice/RollTheDice/Source/Model/Path/PathType.swift index 30f880a2..806b0279 100644 --- a/iOS/RollTheDice/RollTheDice/Source/Model/Path/PathType.swift +++ b/iOS/RollTheDice/RollTheDice/Source/Model/Path/PathType.swift @@ -20,4 +20,6 @@ enum PathType: Hashable { case mypageView // 마이페이지뷰 case webView(url: String) + + case createdebateroom //토론방 생성 } diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift index 9fa0b186..8d5ff093 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift @@ -8,6 +8,10 @@ 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 @@ -36,7 +40,9 @@ struct RecentNewsCardView: View { } .shadow(color: .basicBlack.opacity(0.1), radius: 2) Button { - + print("버튼 클릭됨 - 주제: \(topic)") + viewModel.createDebate(topic: topic) + pathModel.paths.append(.createdebateroom) } label: { Text("토론 시작하기") .foregroundStyle(.basicWhite) @@ -47,6 +53,15 @@ struct RecentNewsCardView: View { .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) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/CreateDebateRoomService.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/CreateDebateRoomService.swift new file mode 100644 index 00000000..bd80ce2f --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/CreateDebateRoomService.swift @@ -0,0 +1,50 @@ +// +// CreateDebateRoomService.swift +// RollTheDice +// +// Created by 신예진 on 6/19/24. +// + +import Foundation +import Moya + +enum CreateDebateRoomService { + case createDebate(topic: String) +} + +extension CreateDebateRoomService: TargetType { + var baseURL: URL { + return URL(string: "http://roll-the-dice.store:8080")! + } + + var path: String { + switch self { + case .createDebate: + return "/debates" + } + } + + var method: Moya.Method { + switch self { + case .createDebate: + return .post + } + } + + var task: Task { + switch self { + case .createDebate(let topic): + let parameters: [String: Any] = ["topic": topic] + return .requestParameters(parameters: parameters, encoding: JSONEncoding.default) + } + } + + 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/CreateDebateRoomViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/CreateDebateRoomViewModel.swift new file mode 100644 index 00000000..3b6cfc9b --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/CreateDebateRoomViewModel.swift @@ -0,0 +1,45 @@ +// +// CreateDebateRoomViewModel.swift +// RollTheDice +// +// Created by 신예진 on 6/19/24. +// + +import Foundation +import Moya +import Combine + +class CreateDebateRoomViewModel: ObservableObject { + private let provider = MoyaProvider() + @Published var debateID: Int? + @Published var errorMessage: String? + + func createDebate(topic: String) { + print("API 호출 시작 - 토론 주제: \(topic)") + provider.request(.createDebate(topic: topic)) { result in + switch result { + case .success(let response): + print("API 호출 성공 - 응답 코드: \(response.statusCode)") + do { + let json = try JSONSerialization.jsonObject(with: response.data, options: []) as? [String: Any] + if let id = json?["id"] as? Int { + DispatchQueue.main.async { + self.debateID = id + print("토론방 생성 성공 - ID: \(id)") + } + } + } catch { + DispatchQueue.main.async { + self.errorMessage = "Failed to parse response" + print("응답 파싱 중 에러: \(error.localizedDescription)") + } + } + case .failure(let error): + DispatchQueue.main.async { + self.errorMessage = error.localizedDescription + print("API 호출 실패 - 에러: \(error.localizedDescription)") + } + } + } + } +} From 8bec2ded8dd22d378f5871e934f13fc02dea5353 Mon Sep 17 00:00:00 2001 From: yeahzxnn Date: Wed, 19 Jun 2024 13:32:31 +0900 Subject: [PATCH 19/61] =?UTF-8?q?fix=20&=20feat=20:=20ChatGPT=EC=99=80?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=EA=B0=84=EC=9D=98=20=ED=86=A0=EB=A1=A0=20API?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84=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 | 12 ++++ .../Debate/ChatGPT/GPTChatListViewModel.swift | 55 +++++++++++++++--- .../View/Debate/ChatGPT/GPTChatView.swift | 2 +- .../Debate/ChatGPT/Service/ChatService.swift | 45 ++++++++++++++ 5 files changed, 104 insertions(+), 10 deletions(-) create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/Service/ChatService.swift diff --git a/iOS/RollTheDice/.DS_Store b/iOS/RollTheDice/.DS_Store index 301a5825fd4fa17371c375e78153dfbe265e7e66..3e52fcdbeeb138923b6e9766c2a4f1e021649a7e 100644 GIT binary patch delta 58 zcmZoMXffE}&cw{b+dcUlliuVCCLY$@9Ib4x$)}kNC+|Yy*)t|=7G(a$GO>YeGdss$ FegGRW614yT delta 58 zcmZoMXffE}&cw|4(tGkbCcViOOgya757Sqvmo;~mWd5)o7p-3 G@&f>9gA~{R diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 20e34247..9d4f2cfb 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 3509091A2C1C1248007D76A1 /* TokenManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 350909192C1C1248007D76A1 /* TokenManager.swift */; }; 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 */; }; 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 */; }; @@ -107,6 +108,7 @@ 350909192C1C1248007D76A1 /* TokenManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenManager.swift; sourceTree = ""; }; 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 = ""; }; 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 = ""; }; @@ -230,6 +232,14 @@ path = ViewModel; sourceTree = ""; }; + 3544D7442C229428007DBD18 /* Service */ = { + isa = PBXGroup; + children = ( + 3544D7452C229436007DBD18 /* ChatService.swift */, + ); + path = Service; + sourceTree = ""; + }; 357666112BBD5494002C226A /* Splah */ = { isa = PBXGroup; children = ( @@ -532,6 +542,7 @@ 6CDB29F72BAA06FB0081037B /* ChatGPT */ = { isa = PBXGroup; children = ( + 3544D7442C229428007DBD18 /* Service */, 6CDB29F82BAA07350081037B /* GPTChat.swift */, 6CDB29FA2BAA07B10081037B /* GPTChatViewModel.swift */, 6CDB29FC2BAA07FD0081037B /* GPTChatView.swift */, @@ -760,6 +771,7 @@ 6C454A882B9DB6C2006FD9D0 /* CustomNavigationBar.swift in Sources */, 6CF130BF2BAB783300A437B6 /* APIConstants.swift in Sources */, 357699442C09C7B900AD2DA4 /* LoginService.swift in Sources */, + 3544D7462C229436007DBD18 /* ChatService.swift in Sources */, 6C76513C2BF37ED300196536 /* Extension+Log.swift in Sources */, 6CE103102BD56A5B00498AA4 /* TypeReportViewModel.swift in Sources */, 6C5B0C8A2C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift in Sources */, diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift index db009df2..7d94565e 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift @@ -7,20 +7,29 @@ import Foundation import OpenAI +import Combine +import Moya class GPTChatListViewModel: ObservableObject { @Published var chatList: [GPTChat] + private var cancellables = Set() + private let provider = MoyaProvider() - // TODO: Token Hidden - /// token 추가해야 함 - let openAI = OpenAI(apiToken: "") + // OpenAI API 토큰 관리 + private let openAI: OpenAI + +// // TODO: Token Hidden +// /// token 추가해야 함 +// let openAI = OpenAI(apiToken: "") init( chatList: [GPTChat] = [ - .init(title: "111111111", messages: []), - ] + .init(title: "토론제목", messages: []), + ], + apiToken: String = "" // TokenManager를 통해 API 토큰을 관리 ) { self.chatList = chatList + self.openAI = OpenAI(apiToken: apiToken) } } @@ -38,12 +47,40 @@ extension GPTChatListViewModel { 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: self.chatList[index].messages.map( - {Chat(role: .user, content: $0.content)})) - ) { result in + 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 { @@ -53,7 +90,7 @@ extension GPTChatListViewModel { DispatchQueue.main.async { self.chatList[index].messages.append(.init(content: message ?? "Error", isUser: false)) - print("gpt msg: \(self.chatList[index].messages[1])") + print("gpt msg: \(self.chatList[index].messages.last?.content ?? "Error")") } case .failure(let failure): diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift index 4fd938b0..b2ecf127 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift @@ -11,7 +11,7 @@ struct GPTChatView: View { @EnvironmentObject var pathModel: PathModel @StateObject var chatListViewModel = GPTChatListViewModel() - @State var selectedChat: GPTChat? = .init(title: "hi", messages: [.init(content: "안녕하세요", isUser: false)]) + @State var selectedChat: GPTChat? = .init(title: "토론제목입니다", messages: [.init(content: "ChatGPT와의 토론!", isUser: false)]) var body: some View { ZStack { diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/Service/ChatService.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/Service/ChatService.swift new file mode 100644 index 00000000..2b14f250 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/Service/ChatService.swift @@ -0,0 +1,45 @@ +// +// ChatService.swift +// RollTheDice +// +// Created by 신예진 on 6/19/24. +// + +import Foundation +import Moya + +enum ChatService { + case sendMessageToAI(roomId: Int, message: String) + case sendMessageToHuman(roomId: Int, message: String) +} + +extension ChatService: TargetType { + var baseURL: URL { + return URL(string: "http://roll-the-dice.store:8080")! + } + + var path: String { + switch self { + case .sendMessageToAI(let roomId, _): + return "/debates/\(roomId)/ai" + case .sendMessageToHuman(let roomId, _): + return "/debates/\(roomId)/human" + } + } + + var method: Moya.Method { + return .post + } + + var task: Task { + switch self { + case .sendMessageToAI(_, let message), .sendMessageToHuman(_, let message): + return .requestParameters(parameters: ["message": message], encoding: JSONEncoding.default) + } + } + + var headers: [String: String]? { + guard let token = TokenManager.shared.accessToken else { return nil } + return ["Authorization": "Bearer \(token)"] + } +} From fb88f3219d76ebb57bde23aeb5830bc6cfefdbca Mon Sep 17 00:00:00 2001 From: yeahzxnn Date: Wed, 19 Jun 2024 16:22:58 +0900 Subject: [PATCH 20/61] =?UTF-8?q?feat=20:=20=EC=B5=9C=EA=B7=BC=20=EB=B3=B8?= =?UTF-8?q?=20=EB=89=B4=EC=8A=A4=20API=20=EC=97=B0=EB=8F=99=ED=95=98?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Source/View/Debate/ChatList/Model/News.swift | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Model/News.swift diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Model/News.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Model/News.swift new file mode 100644 index 00000000..aa9f64f6 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Model/News.swift @@ -0,0 +1,8 @@ +// +// News.swift +// RollTheDice +// +// Created by 신예진 on 6/19/24. +// + +import Foundation From 330776f901e4ec80e4897cf7c2bbe206712ec1dc Mon Sep 17 00:00:00 2001 From: yeahzxnn Date: Wed, 19 Jun 2024 19:10:06 +0900 Subject: [PATCH 21/61] =?UTF-8?q?feat=20:=20=EC=B5=9C=EA=B7=BC=20=EC=9D=BD?= =?UTF-8?q?=EC=9D=80=20=EB=89=B4=EC=8A=A4=20=EC=A1=B0=ED=9A=8C=20API=20?= =?UTF-8?q?=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 | 20 +++ .../View/Debate/ChatList/ChatListView.swift | 30 +++- .../Debate/ChatList/RecentNewsCardView.swift | 130 +++++++++++++++--- .../ChatList/RecentNewsModel/News.swift | 14 ++ .../ChatList/Service/RecentNewsService.swift | 49 +++++++ .../ViewModel/RecentNewsViewModel.swift | 38 +++++ 7 files changed, 257 insertions(+), 24 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..4e131fbb4e9617b0fc37a7d0b96e248999f2f84b 100644 GIT binary patch delta 57 zcmZoMXffE}!NjybZ}K@Ny~!0!JghIzetw!i`81Q^YeGdss$ FegGyk614yT diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 9d4f2cfb..dfd76995 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -20,6 +20,9 @@ 357699422C09C1EB00AD2DA4 /* KakaoSDKCommon in Frameworks */ = {isa = PBXBuildFile; productRef = 357699412C09C1EB00AD2DA4 /* KakaoSDKCommon */; }; 357699442C09C7B900AD2DA4 /* LoginService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 357699432C09C7B900AD2DA4 /* LoginService.swift */; }; 357FC6EA2BCE866B00AD8915 /* DetailCardNews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 357FC6E92BCE866B00AD8915 /* DetailCardNews.swift */; }; + 3586B53C2C22DF41006B1458 /* News.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B53B2C22DF41006B1458 /* News.swift */; }; + 3586B53E2C22DF67006B1458 /* RecentNewsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B53D2C22DF67006B1458 /* RecentNewsService.swift */; }; + 3586B5402C22DFCB006B1458 /* RecentNewsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B53F2C22DFCB006B1458 /* RecentNewsViewModel.swift */; }; 35C71BF22B79F39900F777D1 /* ExyteChat in Frameworks */ = {isa = PBXBuildFile; productRef = 35C71BF12B79F39900F777D1 /* ExyteChat */; }; 6C32379F2B7C376D00B699AB /* Bookmarks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C32379E2B7C376D00B699AB /* Bookmarks.swift */; }; 6C3237A12B7C377600B699AB /* BookmarkViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3237A02B7C377600B699AB /* BookmarkViewModel.swift */; }; @@ -113,6 +116,9 @@ 357666122BBD54AA002C226A /* SplashView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashView.swift; sourceTree = ""; }; 357699432C09C7B900AD2DA4 /* LoginService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginService.swift; sourceTree = ""; }; 357FC6E92BCE866B00AD8915 /* DetailCardNews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailCardNews.swift; sourceTree = ""; }; + 3586B53B2C22DF41006B1458 /* News.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = News.swift; sourceTree = ""; }; + 3586B53D2C22DF67006B1458 /* RecentNewsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentNewsService.swift; sourceTree = ""; }; + 3586B53F2C22DFCB006B1458 /* 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 = ""; }; @@ -220,6 +226,7 @@ isa = PBXGroup; children = ( 3544D73F2C228EFC007DBD18 /* CreateDebateRoomService.swift */, + 3586B53D2C22DF67006B1458 /* RecentNewsService.swift */, ); path = Service; sourceTree = ""; @@ -228,6 +235,7 @@ isa = PBXGroup; children = ( 3544D7422C228F54007DBD18 /* CreateDebateRoomViewModel.swift */, + 3586B53F2C22DFCB006B1458 /* RecentNewsViewModel.swift */, ); path = ViewModel; sourceTree = ""; @@ -248,6 +256,14 @@ path = Splah; sourceTree = ""; }; + 3586B5392C22DF03006B1458 /* RecentNewsModel */ = { + isa = PBXGroup; + children = ( + 3586B53B2C22DF41006B1458 /* News.swift */, + ); + path = RecentNewsModel; + sourceTree = ""; + }; 6C32379D2B7C374E00B699AB /* BookmarkCard */ = { isa = PBXGroup; children = ( @@ -279,6 +295,7 @@ 6C41B8D62BE1048500274FA4 /* ChatList */ = { isa = PBXGroup; children = ( + 3586B5392C22DF03006B1458 /* RecentNewsModel */, 3544D7412C228F39007DBD18 /* ViewModel */, 3544D73E2C228EDB007DBD18 /* Service */, 6C41B8D92BE104A800274FA4 /* RecentNewsCardView.swift */, @@ -785,6 +802,7 @@ 6CDB29FF2BAA08280081037B /* GPTChatListViewModel.swift in Sources */, 6CF130AD2BAB0C4400A437B6 /* AuthenticationViewModel.swift in Sources */, 3544D7402C228EFC007DBD18 /* CreateDebateRoomService.swift in Sources */, + 3586B53E2C22DF67006B1458 /* RecentNewsService.swift in Sources */, 6CDB29F92BAA07350081037B /* GPTChat.swift in Sources */, 6C41B8DC2BE1095800274FA4 /* ChatListView.swift in Sources */, 6CDB29FD2BAA07FD0081037B /* GPTChatView.swift in Sources */, @@ -801,6 +819,7 @@ 3544D7432C228F54007DBD18 /* CreateDebateRoomViewModel.swift in Sources */, 6CC4DDC92B5574670080E7E8 /* ContentView.swift in Sources */, 6C3237A52B7C37D100B699AB /* BookmarkView.swift in Sources */, + 3586B53C2C22DF41006B1458 /* News.swift in Sources */, 6C3237AE2B7C382E00B699AB /* DetailNewsViewModel.swift in Sources */, 6C77048F2B7229B1001B17CB /* NewsListView.swift in Sources */, 357666132BBD54AA002C226A /* SplashView.swift in Sources */, @@ -829,6 +848,7 @@ 6C77048C2B722686001B17CB /* MainTabView.swift in Sources */, 6C7704992B722A20001B17CB /* MainTabViewModel.swift in Sources */, 6C454A7C2B9DA71C006FD9D0 /* SignUpView.swift in Sources */, + 3586B5402C22DFCB006B1458 /* RecentNewsViewModel.swift in Sources */, 6C41B8DA2BE104A800274FA4 /* RecentNewsCardView.swift in Sources */, 3509091A2C1C1248007D76A1 /* TokenManager.swift in Sources */, 6CF130C72BAB7B9800A437B6 /* ScoopAPINews.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..98da2c9d 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift @@ -10,7 +10,8 @@ import SwiftUI struct ChatListView: View { @EnvironmentObject var pathModel: PathModel - + @StateObject private var newsViewModel = RecentNewsViewModel() + var body: some View { ZStack { Color.backgroundDark.ignoresSafeArea(.all) @@ -31,13 +32,28 @@ struct ChatListView: View { Text("최근 본 뉴스") .foregroundStyle(.basicWhite) .font(.pretendardBold32) +// HStack { +// RecentNewsCardView() +// Spacer() +// RecentNewsCardView() +// Spacer() +// RecentNewsCardView() +// } HStack { - 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() } } diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift index 8d5ff093..6af4af87 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift @@ -5,27 +5,124 @@ // Created by Subeen on 4/30/24. // +//import SwiftUI +// +//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 +// } +//// .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() +//} + +// +// RecentNewsCardView.swift +// RollTheDice +// +// Created by Subeen on 4/30/24. +// + 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 +137,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 +152,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 +168,4 @@ 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..6a24e219 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsModel/News.swift @@ -0,0 +1,14 @@ +// +// News.swift +// RollTheDice +// +// Created by 신예진 on 6/19/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..f2fed705 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/RecentNewsService.swift @@ -0,0 +1,49 @@ +// +// RecentNewsService.swift +// RollTheDice +// +// Created by 신예진 on 6/19/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..0f10153e --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/RecentNewsViewModel.swift @@ -0,0 +1,38 @@ +// +// RecentNewsViewModel.swift +// RollTheDice +// +// Created by 신예진 on 6/19/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 f69c2b5962bb79c3ef325ad2bfcd686cc05592cb Mon Sep 17 00:00:00 2001 From: yeahzxnn Date: Wed, 19 Jun 2024 20:28:15 +0900 Subject: [PATCH 22/61] =?UTF-8?q?fix=20:=20ChatGPT=EA=B0=80=20=EC=B1=84?= =?UTF-8?q?=ED=8C=85=20=EC=8B=9C=EC=9E=91=ED=95=98=EB=8A=94=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= 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 | 4 +- .../Source/View/Debate/ChatGPT/GPTChat.swift | 3 +- .../Debate/ChatGPT/GPTChatListViewModel.swift | 147 +++++++++++++----- .../View/Debate/ChatGPT/GPTChatView.swift | 140 ++++++++++++++++- .../Debate/ChatList/RecentNewsCardView.swift | 8 +- .../ViewModel/CreateDebateRoomViewModel.swift | 6 +- 7 files changed, 259 insertions(+), 49 deletions(-) diff --git a/iOS/RollTheDice/.DS_Store b/iOS/RollTheDice/.DS_Store index 4e131fbb4e9617b0fc37a7d0b96e248999f2f84b..87ed28ab873c1c074a10d71527c4db1760a32cc6 100644 GIT binary patch delta 18 ZcmZoMXffE}$;9|`@;N5G%@s^Nq5wi02E70P delta 18 ZcmZoMXffE}$;6m9`5cqp<_e}BQ2;!x1~LEu diff --git a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift index 3ea1b27f..eb3444a7 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: "") } }) } diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChat.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChat.swift index 8112a66b..7e06327d 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 = "", diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift index 7d94565e..e9e85638 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, diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift index b2ecf127..b52ffa1a 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 { @@ -130,6 +138,128 @@ 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 6af4af87..74175404 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift @@ -139,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) 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..41ef52a7 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 { From fbfb1ebe9991a6cbec456f604f35d28a7c43f82b Mon Sep 17 00:00:00 2001 From: yeahzxnn Date: Thu, 20 Jun 2024 00:44:49 +0900 Subject: [PATCH 23/61] =?UTF-8?q?feat:=20=ED=86=A0=EB=A1=A0=20=EC=A2=85?= =?UTF-8?q?=EB=A3=8C=20API=20=EC=97=B0=EA=B2=B0=20=EB=B0=8F=20=ED=86=A0?= =?UTF-8?q?=EB=A1=A0=20=EC=9A=94=EC=95=BD=20=ED=99=94=EB=A9=B4=20=EB=84=98?= =?UTF-8?q?=EC=96=B4=EA=B0=80=EA=B8=B0=20=EA=B5=AC=ED=98=84?= 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 +++++++- .../RollTheDice/RollTheDiceApp.swift | 4 +- .../Source/Model/Path/PathType.swift | 1 + .../View/Debate/ChatGPT/GPTChatView.swift | 44 ++++++++++++++++-- .../ChatGPT/Service/EndDebateService.swift | 43 +++++++++++++++++ .../ViewModel/EndDebateViewModel.swift | 26 +++++++++++ .../GPTChatListViewModel.swift | 4 +- .../{ => ViewModel}/GPTChatViewModel.swift | 0 9 files changed, 132 insertions(+), 10 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 rename iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/{ => ViewModel}/GPTChatListViewModel.swift (97%) rename iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/{ => ViewModel}/GPTChatViewModel.swift (100%) diff --git a/iOS/RollTheDice/.DS_Store b/iOS/RollTheDice/.DS_Store index 87ed28ab873c1c074a10d71527c4db1760a32cc6..1f34c3f3dc394c9ea6c001fafa3d612c16c6d457 100644 GIT binary patch delta 58 zcmZoMXffE}&cw{jBR=^YliuVCCLUISnU@`=O+L+JIC&Qm&z>=1vmo;~mWd5)o7p-3 G@&f=SViR=$ delta 56 zcmZoMXffE}&cw{L|L5d$OnQ?mn0Q!Up8fnZfAVQ2!^yjlc=nqGnZL12Y+&Ea&heKY E0IIeZ{{R30 diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index dfd76995..1e58b14f 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -23,6 +23,8 @@ 3586B53C2C22DF41006B1458 /* News.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B53B2C22DF41006B1458 /* News.swift */; }; 3586B53E2C22DF67006B1458 /* RecentNewsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B53D2C22DF67006B1458 /* RecentNewsService.swift */; }; 3586B5402C22DFCB006B1458 /* RecentNewsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B53F2C22DFCB006B1458 /* RecentNewsViewModel.swift */; }; + 3586B5422C232C00006B1458 /* EndDebateService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B5412C232C00006B1458 /* EndDebateService.swift */; }; + 3586B5452C232C7C006B1458 /* EndDebateViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B5442C232C7C006B1458 /* EndDebateViewModel.swift */; }; 35C71BF22B79F39900F777D1 /* ExyteChat in Frameworks */ = {isa = PBXBuildFile; productRef = 35C71BF12B79F39900F777D1 /* ExyteChat */; }; 6C32379F2B7C376D00B699AB /* Bookmarks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C32379E2B7C376D00B699AB /* Bookmarks.swift */; }; 6C3237A12B7C377600B699AB /* BookmarkViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3237A02B7C377600B699AB /* BookmarkViewModel.swift */; }; @@ -119,6 +121,8 @@ 3586B53B2C22DF41006B1458 /* News.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = News.swift; sourceTree = ""; }; 3586B53D2C22DF67006B1458 /* RecentNewsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentNewsService.swift; sourceTree = ""; }; 3586B53F2C22DFCB006B1458 /* RecentNewsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentNewsViewModel.swift; sourceTree = ""; }; + 3586B5412C232C00006B1458 /* EndDebateService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndDebateService.swift; sourceTree = ""; }; + 3586B5442C232C7C006B1458 /* EndDebateViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndDebateViewModel.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 = ""; }; @@ -244,6 +248,7 @@ isa = PBXGroup; children = ( 3544D7452C229436007DBD18 /* ChatService.swift */, + 3586B5412C232C00006B1458 /* EndDebateService.swift */, ); path = Service; sourceTree = ""; @@ -264,6 +269,16 @@ path = RecentNewsModel; sourceTree = ""; }; + 3586B5432C232C44006B1458 /* ViewModel */ = { + isa = PBXGroup; + children = ( + 3586B5442C232C7C006B1458 /* EndDebateViewModel.swift */, + 6CDB29FA2BAA07B10081037B /* GPTChatViewModel.swift */, + 6CDB29FE2BAA08280081037B /* GPTChatListViewModel.swift */, + ); + path = ViewModel; + sourceTree = ""; + }; 6C32379D2B7C374E00B699AB /* BookmarkCard */ = { isa = PBXGroup; children = ( @@ -559,11 +574,10 @@ 6CDB29F72BAA06FB0081037B /* ChatGPT */ = { isa = PBXGroup; children = ( + 3586B5432C232C44006B1458 /* ViewModel */, 3544D7442C229428007DBD18 /* Service */, 6CDB29F82BAA07350081037B /* GPTChat.swift */, - 6CDB29FA2BAA07B10081037B /* GPTChatViewModel.swift */, 6CDB29FC2BAA07FD0081037B /* GPTChatView.swift */, - 6CDB29FE2BAA08280081037B /* GPTChatListViewModel.swift */, ); path = ChatGPT; sourceTree = ""; @@ -829,6 +843,7 @@ 6C94799E2BD3C00C00D5AEEB /* Image.swift in Sources */, 6C454A842B9DAFCB006FD9D0 /* PathType.swift in Sources */, 6CF130AF2BAB0C4F00A437B6 /* AuthenticatedView.swift in Sources */, + 3586B5422C232C00006B1458 /* EndDebateService.swift in Sources */, 6C3237B52B7C433D00B699AB /* ChatTypeView.swift in Sources */, 6CF130B22BAB74BA00A437B6 /* NewsService.swift in Sources */, 6C3237B22B7C385000B699AB /* NewsListViewModel.swift in Sources */, @@ -850,6 +865,7 @@ 6C454A7C2B9DA71C006FD9D0 /* SignUpView.swift in Sources */, 3586B5402C22DFCB006B1458 /* RecentNewsViewModel.swift in Sources */, 6C41B8DA2BE104A800274FA4 /* RecentNewsCardView.swift in Sources */, + 3586B5452C232C7C006B1458 /* EndDebateViewModel.swift in Sources */, 3509091A2C1C1248007D76A1 /* TokenManager.swift in Sources */, 6CF130C72BAB7B9800A437B6 /* ScoopAPINews.swift in Sources */, 6C7651402BF37F3400196536 /* Log.swift in Sources */, diff --git a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift index eb3444a7..20a0cb74 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/Model/Path/PathType.swift b/iOS/RollTheDice/RollTheDice/Source/Model/Path/PathType.swift index 806b0279..b464d017 100644 --- a/iOS/RollTheDice/RollTheDice/Source/Model/Path/PathType.swift +++ b/iOS/RollTheDice/RollTheDice/Source/Model/Path/PathType.swift @@ -22,4 +22,5 @@ enum PathType: Hashable { case webView(url: String) case createdebateroom //토론방 생성 + } diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift index b52ffa1a..5dd45488 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,32 @@ struct GPTChatView: View { MessageCellView(message: message) } } + + //MARK : 토론 종료 버튼 + Button(action: { + print("토론종료버튼 눌림!") + viewModel.endDebate(roomId: "\(roomId)") { success in + if success { + print("토론이 종료되었습니다.") + pathModel.paths.append(.debateSummaryView) + } 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 +109,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/ChatGPT/GPTChatListViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/ViewModel/GPTChatListViewModel.swift similarity index 97% rename from iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift rename to iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/ViewModel/GPTChatListViewModel.swift index e9e85638..a723228a 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/ViewModel/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") diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/ViewModel/GPTChatViewModel.swift similarity index 100% rename from iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatViewModel.swift rename to iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/ViewModel/GPTChatViewModel.swift From 8b3e2a903f6ff80e14dcd8c83868e582d07bda91 Mon Sep 17 00:00:00 2001 From: yeahzxnn Date: Thu, 20 Jun 2024 02:57:01 +0900 Subject: [PATCH 24/61] =?UTF-8?q?fix=20:=20=ED=86=A0=EB=A1=A0=20=EC=A2=85?= =?UTF-8?q?=EB=A3=8C=20=ED=9B=84=20=EB=8B=A4=EC=8B=9C=20=EC=9D=B4=EC=A0=84?= =?UTF-8?q?=ED=99=94=EB=A9=B4=EC=9C=BC=EB=A1=9C=20=EB=8F=8C=EC=95=84?= =?UTF-8?q?=EC=98=A4=EB=8A=94=20=EA=B2=83=EC=9C=BC=EB=A1=9C=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=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 .../View/Debate/ChatGPT/GPTChatView.swift | 4 +++- .../View/Debate/ChatList/ChatListView.swift | 7 ++++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/iOS/RollTheDice/.DS_Store b/iOS/RollTheDice/.DS_Store index 1f34c3f3dc394c9ea6c001fafa3d612c16c6d457..bd6aa60bff8ecb7d6bce98f5b7d174c576a2b551 100644 GIT binary patch delta 19 acmZoMXffE}!NerkH2EBp-sTFX9#H^5lLl7+ delta 19 acmZoMXffE}!NkNPKKUGz-sTFX9#H^1E(PZR diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift index 5dd45488..296769b9 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift @@ -75,7 +75,9 @@ struct GPTChatView: View { viewModel.endDebate(roomId: "\(roomId)") { success in if success { print("토론이 종료되었습니다.") - pathModel.paths.append(.debateSummaryView) +// pathModel.paths.append(.debateSummaryView) + pathModel.paths.popLast() + } else { print("토론 종료에 실패했습니다.") } diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift index 98da2c9d..19e20b2b 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift @@ -86,7 +86,8 @@ struct ChatListView: View { Button { pathModel.paths.append(.chatView(isAiMode: true)) } label: { - Image(.chevronRight) + Image(systemName: "quote.bubble") + .background(.gray01) } } .background(.gray01) @@ -221,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 e168c180869717bb08dd406784aeee5e9d008947 Mon Sep 17 00:00:00 2001 From: realhsb Date: Thu, 20 Jun 2024 07:31:47 +0900 Subject: [PATCH 25/61] =?UTF-8?q?feat:=20=ED=86=B5=EA=B3=84=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RollTheDice.xcodeproj/project.pbxproj | 4 ++++ .../Domain/ScoopAPI/ScoopAPIStatistics.swift | 15 +++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPIStatistics.swift diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 9d4f2cfb..16413fc7 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -69,6 +69,7 @@ 6CC4DDCE2B5574690080E7E8 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6CC4DDCD2B5574690080E7E8 /* Preview Assets.xcassets */; }; 6CC6737A2C217C4B009FB30E /* ScoopAPILogin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC673792C217C4B009FB30E /* ScoopAPILogin.swift */; }; 6CC6737C2C21BA5B009FB30E /* Auth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC6737B2C21BA5B009FB30E /* Auth.swift */; }; + 6CC673802C233A65009FB30E /* ScoopAPIStatistics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC6737F2C233A65009FB30E /* ScoopAPIStatistics.swift */; }; 6CDB29C92BA97C550081037B /* Pretendard-Black.otf in Resources */ = {isa = PBXBuildFile; fileRef = 6CDB29C02BA97C550081037B /* Pretendard-Black.otf */; }; 6CDB29CA2BA97C550081037B /* Pretendard-ExtraBold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 6CDB29C12BA97C550081037B /* Pretendard-ExtraBold.otf */; }; 6CDB29CB2BA97C550081037B /* Pretendard-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 6CDB29C22BA97C550081037B /* Pretendard-Regular.otf */; }; @@ -162,6 +163,7 @@ 6CC4DDCD2B5574690080E7E8 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 6CC673792C217C4B009FB30E /* ScoopAPILogin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScoopAPILogin.swift; sourceTree = ""; }; 6CC6737B2C21BA5B009FB30E /* Auth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Auth.swift; sourceTree = ""; }; + 6CC6737F2C233A65009FB30E /* ScoopAPIStatistics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScoopAPIStatistics.swift; sourceTree = ""; }; 6CDB29BF2BA9735C0081037B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 6CDB29C02BA97C550081037B /* Pretendard-Black.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Black.otf"; sourceTree = ""; }; 6CDB29C12BA97C550081037B /* Pretendard-ExtraBold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-ExtraBold.otf"; sourceTree = ""; }; @@ -664,6 +666,7 @@ 6CF130C62BAB7B9800A437B6 /* ScoopAPINews.swift */, 6C5B0C892C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift */, 6CC673792C217C4B009FB30E /* ScoopAPILogin.swift */, + 6CC6737F2C233A65009FB30E /* ScoopAPIStatistics.swift */, ); path = ScoopAPI; sourceTree = ""; @@ -820,6 +823,7 @@ 6CDB29FB2BAA07B10081037B /* GPTChatViewModel.swift in Sources */, 6C32379F2B7C376D00B699AB /* Bookmarks.swift in Sources */, 6C454A7E2B9DAA3F006FD9D0 /* SignUpFinishView.swift in Sources */, + 6CC673802C233A65009FB30E /* ScoopAPIStatistics.swift in Sources */, 6C7704A12B722CEB001B17CB /* ProfileView.swift in Sources */, 6C4F7BAB2BDE50C600ED01DA /* DailyReportModel.swift in Sources */, 6C3237B72B7C434600B699AB /* ChatType.swift in Sources */, diff --git a/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPIStatistics.swift b/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPIStatistics.swift new file mode 100644 index 00000000..22424bdf --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPIStatistics.swift @@ -0,0 +1,15 @@ +// +// ScoopAPIStatistics.swift +// RollTheDice +// +// Created by Subeen on 6/20/24. +// + +import Foundation + +public enum ScoopAPIStatistics { +// public static let statistics = String("/statistics") + public static let statisticsPerDates = String("/statistics/per-dates") + public static let statisticsCategories = String("/statistics/categories") + +} From 2b41196a04740fc531d68257d60bce15bc483587 Mon Sep 17 00:00:00 2001 From: realhsb Date: Thu, 20 Jun 2024 07:32:37 +0900 Subject: [PATCH 26/61] =?UTF-8?q?chore:=20Daily=20Report=20(=EC=9D=BC?= =?UTF-8?q?=EB=B3=84=20=EC=A1=B0=ED=9A=8C=EC=88=98=20=EC=A1=B0=ED=9A=8C)?= =?UTF-8?q?=20Model=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../View/Report/Daily/DailyReportModel.swift | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Report/Daily/DailyReportModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Report/Daily/DailyReportModel.swift index 9a5051cc..10a34175 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Report/Daily/DailyReportModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Report/Daily/DailyReportModel.swift @@ -8,24 +8,25 @@ import Foundation import SwiftUI -struct DailyReportList: Hashable { - var reportList: [DailyReport] -} +//struct DailyReportList: Codable { +// var reportList: [DailyReport] +//} -struct DailyReport: Hashable, Identifiable { - let id = UUID() - let dateStr: String // DateFormatter로 변환 - let views: Int +struct DailyReport: Codable, Identifiable { + + let id = UUID().uuidString + let views: Int? + let dateTime: String? var date: Date { // TODO: Format Style 사용해서 String -> Date 생성하기 // let strategy = Date.ParseStrategy(format: "\(month: .twoDigits)년 \(month: .twoDigits)월 \(day: .defaultDigits)", timeZone: TimeZone(abbreviation: "CDT")!) let dateFormatter = DateFormatter() - dateFormatter.dateFormat = "yyyy년 MM월 dd일" + dateFormatter.dateFormat = "yyyy-MM-dd" - let convertedDate = dateFormatter.date(from: dateStr)! + let convertedDate = dateFormatter.date(from: dateTime ?? "0000-00-00") - return convertedDate + return convertedDate! } } From c2a16b12704b629f1e6e34c8aea5615941177476 Mon Sep 17 00:00:00 2001 From: realhsb Date: Thu, 20 Jun 2024 07:32:57 +0900 Subject: [PATCH 27/61] =?UTF-8?q?chore:=20Daily=20Report=20(=EC=9D=BC?= =?UTF-8?q?=EB=B3=84=20=EC=A1=B0=ED=9A=8C=EC=88=98=20=EC=A1=B0=ED=9A=8C)?= =?UTF-8?q?=20View=20&=20ViewModel=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../View/Report/Daily/DailyBarChartView.swift | 13 ++-- .../Report/Daily/DailyReportViewModel.swift | 62 ++++++++++++++----- 2 files changed, 53 insertions(+), 22 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Report/Daily/DailyBarChartView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Report/Daily/DailyBarChartView.swift index 8f026af7..2b02f12c 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Report/Daily/DailyBarChartView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Report/Daily/DailyBarChartView.swift @@ -11,7 +11,7 @@ import Charts struct DailyBarChartView: View { - @StateObject var dailyViewModel: DailyReportViewModel + var dailyViewModel: DailyReportViewModel @State var selectedDay: Date? @State var selectedView: Int? @@ -21,9 +21,9 @@ struct DailyBarChartView: View { var selectedValue: (date: Date, views: Int)? { if let selectedDay { - for preview in dailyViewModel.dailyReportList.reportList { + for preview in dailyViewModel.dailyReportList ?? [] { if preview.date.formatted(date: .long, time: .omitted) == selectedDay.formatted(date: .long, time: .omitted) { - return (selectedDay, preview.views) + return (selectedDay, preview.views!) } } } @@ -57,10 +57,10 @@ struct DailyBarChartView: View { Chart{ - ForEach(dailyViewModel.dailyReportList.reportList) { day in + ForEach(dailyViewModel.dailyReportList ?? []) { day in BarMark( x: .value("Day", day.date, unit: .weekdayOrdinal), - y: .value("Views", day.views) + y: .value("Views", day.views ?? 0) ) .cornerRadius(8) @@ -100,6 +100,9 @@ struct DailyBarChartView: View { } .chartYAxis(.hidden) .chartXSelection(value: $selectedDay) + .task { + dailyViewModel.getDailyViews() + } } } diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Report/Daily/DailyReportViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Report/Daily/DailyReportViewModel.swift index 344ca3bb..b9aa5374 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Report/Daily/DailyReportViewModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Report/Daily/DailyReportViewModel.swift @@ -6,34 +6,62 @@ // import Foundation +import Combine +import CombineMoya +import Moya +import SwiftUI -class DailyReportViewModel: ObservableObject{ - @Published var dailyReportList: DailyReportList +@Observable class DailyReportViewModel { + var dailyReportList: [DailyReport]? /// 일주일 평균 조회수 var averageView: String { var aver = 0.0 - for daily in dailyReportList.reportList { - aver += Double(daily.views) + for daily in dailyReportList ?? [] { + aver += Double(daily.views ?? 0) } return String(format: "%.1f", aver / 7) } - init( - dailyReportList: DailyReportList = .init( - reportList: - [.init(dateStr: "2024년 1월 1일", views: 32), - .init(dateStr: "2024년 1월 2일", views: 2), - .init(dateStr: "2024년 1월 3일", views: 300), - .init(dateStr: "2024년 1월 4일", views: 999), - .init(dateStr: "2024년 1월 5일", views: 12), - .init(dateStr: "2024년 1월 6일", views: 1), - .init(dateStr: "2024년 1월 7일", views: 99), - ] + var dailyCancellable: AnyCancellable? + + let provider = MoyaProvider(plugins: [MoyaLoggingPlugin()]) + + func dailyToViewModel(_ list: [DailyReport]) { + self.dailyReportList = list + } +} + +extension DailyReportViewModel { + + public func getDailyViews() { + guard let accessToken = TokenManager.shared.accessToken else { + print("Access token 사용 불가능...") + return + } + + if let cancellable = dailyCancellable { + cancellable.cancel() + } + + dailyCancellable = provider.requestWithProgressPublisher( + .recentSevenPerDate(accessToken: accessToken) ) - ) { - self.dailyReportList = dailyReportList + .compactMap { $0.response?.data } + .receive(on: DispatchQueue.main) + .decode(type: [DailyReport].self, decoder: JSONDecoder()) + .sink(receiveCompletion: { result in + switch result { + case .finished: + print("daily report 조회성공") + case .failure(let error): + Log.network("daily report network error", error.localizedDescription) + } + }, receiveValue: { [weak self] response in + self?.dailyToViewModel(response) + print(response) + }) } } From e2b1c8b4e0763bfa3470b93adddfa1b43021eb09 Mon Sep 17 00:00:00 2001 From: realhsb Date: Thu, 20 Jun 2024 07:33:26 +0900 Subject: [PATCH 28/61] feat: Statistics Service --- .../RollTheDice.xcodeproj/project.pbxproj | 4 ++ .../Domain/Service/StatisticsService.swift | 63 +++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 iOS/RollTheDice/RollTheDice/Source/Domain/Service/StatisticsService.swift diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 16413fc7..04a94122 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -69,6 +69,7 @@ 6CC4DDCE2B5574690080E7E8 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6CC4DDCD2B5574690080E7E8 /* Preview Assets.xcassets */; }; 6CC6737A2C217C4B009FB30E /* ScoopAPILogin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC673792C217C4B009FB30E /* ScoopAPILogin.swift */; }; 6CC6737C2C21BA5B009FB30E /* Auth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC6737B2C21BA5B009FB30E /* Auth.swift */; }; + 6CC6737E2C233443009FB30E /* StatisticsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC6737D2C233443009FB30E /* StatisticsService.swift */; }; 6CC673802C233A65009FB30E /* ScoopAPIStatistics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC6737F2C233A65009FB30E /* ScoopAPIStatistics.swift */; }; 6CDB29C92BA97C550081037B /* Pretendard-Black.otf in Resources */ = {isa = PBXBuildFile; fileRef = 6CDB29C02BA97C550081037B /* Pretendard-Black.otf */; }; 6CDB29CA2BA97C550081037B /* Pretendard-ExtraBold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 6CDB29C12BA97C550081037B /* Pretendard-ExtraBold.otf */; }; @@ -163,6 +164,7 @@ 6CC4DDCD2B5574690080E7E8 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 6CC673792C217C4B009FB30E /* ScoopAPILogin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScoopAPILogin.swift; sourceTree = ""; }; 6CC6737B2C21BA5B009FB30E /* Auth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Auth.swift; sourceTree = ""; }; + 6CC6737D2C233443009FB30E /* StatisticsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatisticsService.swift; sourceTree = ""; }; 6CC6737F2C233A65009FB30E /* ScoopAPIStatistics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScoopAPIStatistics.swift; sourceTree = ""; }; 6CDB29BF2BA9735C0081037B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 6CDB29C02BA97C550081037B /* Pretendard-Black.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Black.otf"; sourceTree = ""; }; @@ -637,6 +639,7 @@ 6CF130B12BAB74BA00A437B6 /* NewsService.swift */, 6C5B0C8B2C1C32C000A0D5F4 /* BookmarksService.swift */, 357699432C09C7B900AD2DA4 /* LoginService.swift */, + 6CC6737D2C233443009FB30E /* StatisticsService.swift */, ); path = Service; sourceTree = ""; @@ -836,6 +839,7 @@ 6C41B8DA2BE104A800274FA4 /* RecentNewsCardView.swift in Sources */, 3509091A2C1C1248007D76A1 /* TokenManager.swift in Sources */, 6CF130C72BAB7B9800A437B6 /* ScoopAPINews.swift in Sources */, + 6CC6737E2C233443009FB30E /* StatisticsService.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/Domain/Service/StatisticsService.swift b/iOS/RollTheDice/RollTheDice/Source/Domain/Service/StatisticsService.swift new file mode 100644 index 00000000..9e1ece6d --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/Domain/Service/StatisticsService.swift @@ -0,0 +1,63 @@ +// +// StatisticsService.swift +// RollTheDice +// +// Created by Subeen on 6/20/24. +// + +import Foundation +import Moya + +enum StatisticsService { + case recentSevenPerDate(accessToken: String) /// 최근 일주일 날짜별 뉴스 조회수 조회 + case statisticsCategory(accessToken: String) +} + +extension StatisticsService: BaseTargetType { + var baseURL: URL { + return URL(string: ScoopAPI.baseURL)! + } + + var path: String { + switch self { + case .recentSevenPerDate(let accessToken): + return ScoopAPIStatistics.statisticsPerDates + + case .statisticsCategory(let accessToken): + return ScoopAPIStatistics.statisticsCategories + } + } + + var method: Moya.Method { + switch self { + case .recentSevenPerDate, + .statisticsCategory: + return .get + + } + } + + var task: Moya.Task { + switch self { + case .recentSevenPerDate(_), + .statisticsCategory(_): + + let parameters : [String : Any] = [ : ] + return .requestPlain + } + } + + var headers: [String : String]? { + let accessToken: String + + switch self { + case .recentSevenPerDate(let accessTokenValue), + .statisticsCategory(let accessTokenValue): + accessToken = accessTokenValue + return [ + "Authorization": "Bearer \(accessToken)", + "X-Content-Type_Options" : "nosniff" + ] + } + } +} From ee8349b0bf4b4cf7702c2595a6e5c170a7fb33ad Mon Sep 17 00:00:00 2001 From: realhsb Date: Thu, 20 Jun 2024 08:30:58 +0900 Subject: [PATCH 29/61] =?UTF-8?q?feat:=20Type=20Report=20Model=20(?= =?UTF-8?q?=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=EB=B3=84=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=EC=88=98)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../View/Report/Type/TypeReportModel.swift | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Report/Type/TypeReportModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Report/Type/TypeReportModel.swift index 1c35be6e..2c8c56a1 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Report/Type/TypeReportModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Report/Type/TypeReportModel.swift @@ -7,19 +7,9 @@ import Foundation -struct TypeReportList: Hashable { - var reportList: [TypeReport] -} - -struct TypeReport: Hashable, Identifiable { - var id = UUID() - var newsType: NewsType - var view: Int - - // case politics // 정치 - // case economy // 경제 - // case society // 사회 - // case living // 생활/문화 - // case world // 세계 - // case science // IT/과학 +struct TypeReport: Codable, Identifiable { + + let id = UUID().uuidString + let category: NewsType? + let views: Int? } From ae15c2f2597279cee4c308f1c5c99c672b10fd9d Mon Sep 17 00:00:00 2001 From: realhsb Date: Thu, 20 Jun 2024 08:31:10 +0900 Subject: [PATCH 30/61] =?UTF-8?q?feat:=20Type=20Report=20View=20&=20ViewMo?= =?UTF-8?q?del=20(=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=EB=B3=84=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=EC=88=98)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../View/Report/Type/TypePieChartView.swift | 11 +-- .../Report/Type/TypeReportViewModel.swift | 69 ++++++++++++++----- 2 files changed, 58 insertions(+), 22 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Report/Type/TypePieChartView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Report/Type/TypePieChartView.swift index bbd26054..f27b7243 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Report/Type/TypePieChartView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Report/Type/TypePieChartView.swift @@ -10,23 +10,23 @@ import Charts struct TypePieChartView: View { - @StateObject var reportViewModel: TypeReportViewModel + var reportViewModel: TypeReportViewModel var isPreview: Bool = false var mostViewed: NewsType { - return reportViewModel.sortedList.first!.newsType + return reportViewModel.sortedList.first?.category ?? .economy } var body: some View { Chart(reportViewModel.sortedList) { report in SectorMark( - angle: .value("Views", report.view), + angle: .value("Views", report.views ?? 0), innerRadius: .ratio(0.7), angularInset: 2.0 ) .cornerRadius(8) - .foregroundStyle(report.newsType.color.gradient) + .foregroundStyle(report.category?.color.gradient ?? Color.primary01.gradient) } /// pie chart의 가운데 문구 .chartBackground { chartProxy in @@ -47,6 +47,9 @@ struct TypePieChartView: View { } } .padding(100) + .task { + reportViewModel.getTypeReport() + } } } diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Report/Type/TypeReportViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Report/Type/TypeReportViewModel.swift index d23bce97..fcc6bfde 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Report/Type/TypeReportViewModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Report/Type/TypeReportViewModel.swift @@ -6,28 +6,61 @@ // import Foundation +import Combine +import CombineMoya +import Moya +import SwiftUI -class TypeReportViewModel: ObservableObject { +@Observable class TypeReportViewModel { - @Published var reportList: TypeReportList + var typeReportList: [TypeReport]? + + // 비율이 낮은 순으로 정렬 (파이 차트에서 반시계방향으로 그래프 차지) + var sortedList: [TypeReport] { + if let reportList = typeReportList { + return reportList.sorted { ($0.views ?? 0) < ($1.views ?? 0) } + } else { + return [] + } + } - init( - reportList: TypeReportList = .init( - reportList: [ - .init(newsType: .economy, view: 10), - .init(newsType: .living, view: 20), - .init(newsType: .politics, view: 30), - .init(newsType: .science, view: 5), - .init(newsType: .society, view: 5), - .init(newsType: .world, view: 30) - ] - ) - ) { - self.reportList = reportList + var typeCancellable: AnyCancellable? + + let provider = MoyaProvider(plugins: [MoyaLoggingPlugin()]) + + func typeToViewModel(_ list: [TypeReport]) { + self.typeReportList = list } +} + +extension TypeReportViewModel { - // 비율이 낮은 순으로 정렬 (파이 차트에서 반시계방향으로 그래프 차지) - var sortedList: [TypeReport] { - return reportList.reportList.sorted { $0.view > $1.view } + public func getTypeReport() { + guard let accessToken = TokenManager.shared.accessToken else { + print("Access token 사용 불가능...") + return + } + + if let cancellable = typeCancellable { + cancellable.cancel() + } + + typeCancellable = provider.requestWithProgressPublisher( + .statisticsCategory(accessToken: accessToken) + ) + .compactMap { $0.response?.data } + .receive(on: DispatchQueue.main) + .decode(type: [TypeReport].self, decoder: JSONDecoder()) + .sink(receiveCompletion: { result in + switch result { + case .finished: + print("type report 조회성공") + case .failure(let error): + Log.network("type report network error", error.localizedDescription) + } + }, receiveValue: { [weak self] response in + self?.typeToViewModel(response) + print(response) + }) } } From 7abdbc66ab56c72fd4cc3615f095b60239775773 Mon Sep 17 00:00:00 2001 From: realhsb Date: Thu, 20 Jun 2024 08:31:21 +0900 Subject: [PATCH 31/61] =?UTF-8?q?chore:=20NewsType=20enum=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 --- .../RollTheDice/Source/Model/Report/NewsType.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/Model/Report/NewsType.swift b/iOS/RollTheDice/RollTheDice/Source/Model/Report/NewsType.swift index 99deabbe..ac4c22df 100644 --- a/iOS/RollTheDice/RollTheDice/Source/Model/Report/NewsType.swift +++ b/iOS/RollTheDice/RollTheDice/Source/Model/Report/NewsType.swift @@ -8,13 +8,13 @@ import Foundation import SwiftUI -enum NewsType { - case politics // 정치 - case economy // 경제 - case society // 사회 - case living // 생활/문화 - case world // 세계 - case science // IT/과학 +enum NewsType: String, Codable { + case politics = "정치" // 정치 + case economy = "경제" // 경제 + case society = "사회" // 사회 + case living = "생활/문화" // 생활/문화 + case world = "세계" // 세계 + case science = "IT/과학" // IT/과학 var desciption: String { switch self { From 73b1ee02477831c1cb6831db72d10ea4184d4bcf Mon Sep 17 00:00:00 2001 From: realhsb Date: Thu, 20 Jun 2024 08:31:37 +0900 Subject: [PATCH 32/61] =?UTF-8?q?chore:=20Statistics=20Service=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 --- .../RollTheDice/Source/Domain/Service/StatisticsService.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/Domain/Service/StatisticsService.swift b/iOS/RollTheDice/RollTheDice/Source/Domain/Service/StatisticsService.swift index 9e1ece6d..9ff4993b 100644 --- a/iOS/RollTheDice/RollTheDice/Source/Domain/Service/StatisticsService.swift +++ b/iOS/RollTheDice/RollTheDice/Source/Domain/Service/StatisticsService.swift @@ -10,7 +10,7 @@ import Moya enum StatisticsService { case recentSevenPerDate(accessToken: String) /// 최근 일주일 날짜별 뉴스 조회수 조회 - case statisticsCategory(accessToken: String) + case statisticsCategory(accessToken: String) /// 카테고리별 조회수 조회 } extension StatisticsService: BaseTargetType { From 93509c52c0fc924be64e5605cefdb90b74443cd4 Mon Sep 17 00:00:00 2001 From: realhsb Date: Thu, 20 Jun 2024 08:35:38 +0900 Subject: [PATCH 33/61] =?UTF-8?q?chore:=20Bookmark=20api=20Token=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../View/Bookmark/BookmarkCard/BookmarksListViewModel.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift index fc069789..f9342a31 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift @@ -24,7 +24,10 @@ import SwiftUI extension BookmarksListViewModel { public func getAllBookmarksData(page: Int, size: Int) { - let accessToken = "5Gu45OmOoZnvANl-qfZv-xHv_2eSweVeAAAAAQopyNkAAAGQFbGnJSn2EFsnJsRZ" + guard let accessToken = TokenManager.shared.accessToken else { + print("Access token 사용 불가능...") + return + } if let cancellable = bookmarksCancellable { cancellable.cancel() From 7ecaf7661d5ee2381ebbcaf8f7e0394046fbd840 Mon Sep 17 00:00:00 2001 From: realhsb Date: Thu, 20 Jun 2024 08:53:00 +0900 Subject: [PATCH 34/61] =?UTF-8?q?chore:=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../News/NewsList/NewsListViewModel.swift | 20 --------- .../Source/View/News/NewsList/NewsView.swift | 43 +------------------ .../View/Report/Type/TypePieChartView.swift | 1 - 3 files changed, 2 insertions(+), 62 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsListViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsListViewModel.swift index 2b9cbfbb..6948b661 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsListViewModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsListViewModel.swift @@ -60,7 +60,6 @@ extension NewsListViewModel { print("news 조회 성공") break case .failure(let error): -// print(error.localizedDescription) Log.network("network error", error.localizedDescription) } }, receiveValue: { [weak self] response in @@ -70,22 +69,3 @@ extension NewsListViewModel { }) } } - - -//public class NewsListViewModel: ObservableObject { -// // News = [NewsModel] -// @Published var newsList: [News] = [] -//// var currentPage = 0 -// -// init( -// newsList: [News] = [ -// -// .init(title: "네이버, 사우디 'LEAP 2024'서 AI·로봇 등 자사 기술력 뽐낸다", postDate: "2023년3월3일", image: "https://imgnews.pstatic.net/image/008/2024/03/05/0005007355_001_20240305100101016.jpg?type=w647", content: "네이버(NAVER)는 사우디아라비아에서 지난 4일부터 7일까지 열리는 글로벌 IT전시회 LEAP 2024에서 AI(인공지능), 클라우드, 로봇 등 자사 핵심 기술을 선보이고, 글로벌 업체들과 비즈니스 협력을 강화한다고 5일 밝혔다.", isBookmarked: false), -// .init(title: "앤스로픽 최신 AI 모델 '클로드3' 출시", postDate: "2023년3월13일", image: "https://imgnews.pstatic.net/image/014/2024/03/05/0005151141_001_20240305101610000.jpg?type=w647", content: "오픈AI의 대항마 앤스로픽이 생성형 인공지능(AI) 최신 모델 '클로드'(Claude)3를 선보이면서 생성형 AI 주도권을 잡기 위한 경쟁이 다시 뜨거워지고 있다. 앤스로픽은 지난 한 해 동안 구글과 세일즈포스, 아마존 등에서 총 73억 달러(약 9조7309억 원)를 투자받고 '클로드3'를 내놨는데 오픈AI의 챗GPT-4를 능가한다고 도발했다.", isBookmarked: true), -// .init(title: "SK C&C, 외부 전문가 대거 영입… “신성장 동력 강화”", postDate: "2023년2월13일", image: "https://imgnews.pstatic.net/image/366/2024/03/05/0000975131_001_20240305093504301.jpg?type=w647", content: "SK C&C는 국내외 신성장 동력 강화를 위해 인공지능(AI)·클라우드·디지털 팩토리·ESG(환경·사회·지배구조) 등 4대 성장 사업과 디지털 컨설팅 중심으로 외부 전문가를 대거 영입해 전진 배치했다고 5일 밝혔다.", isBookmarked: false), -// .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", postDate: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), -// ] -// ) { -// self.newsList = newsList -// } -//} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsView.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsView.swift index 81e81d9d..7e7731cf 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsView.swift @@ -43,46 +43,13 @@ struct NewsView: View { .frame(width: 322, height: 160) .clipShape(RoundedRectangle(cornerRadius: 8)) .shadow(color: .black.opacity(0.25), radius: 2, x: 0, y: 0) -// case .empty: -// Image(.exampleNews) -// .resizable() -// .aspectRatio(contentMode: .fill) -// .frame(width: 322, height: 160) -// .clipShape(RoundedRectangle(cornerRadius: 8)) -// .shadow(color: .black.opacity(0.25), radius: 2, x: 0, y: 0) -// case .failure(_): -// Image(.exampleNews) -// .resizable() -// .aspectRatio(contentMode: .fill) -// .frame(width: 322, height: 160) -// .clipShape(RoundedRectangle(cornerRadius: 8)) -// .shadow(color: .black.opacity(0.25), radius: 2, x: 0, y: 0) + @unknown default: Text(""); } } - - -// if isVisibleView { -// Button { -// let newsId:Int = news.newsId -// print("!!!!!!!!!!! newsID : \(news.newsId)") -// pathModel.paths.append(.detailNewsView(newsId: newsId)) -// } label: { -// Text("더보기") -// .font(.pretendardBold14) -// .foregroundStyle(.gray01) -// .padding(.horizontal, 30) -// .padding(.vertical, 13) -// .background(.primary01) -// .clipShape( -// RoundedRectangle(cornerRadius: 16) -// ) -// .shadow(color: .basicBlack.opacity(0.25), radius: 2, x: 0, y: 0) -// -// } -// } + Button { let newsId:Int = news.newsId print("!!!!!!!!!!! newsID : \(news.newsId)") @@ -134,9 +101,3 @@ struct NewsView: View { NewsView(news: .init(newsId: 1, title: "1분기 선방한 dddddddd韓게임사들…엔씨만 울었다", content: "내용내용ㄴㅇㅇㅇ", thumbnailUrl: "", postDate: "2222-22-22", isBookmarked: true)) .environmentObject(PathModel()) } -//#Preview(traits: .sizeThatFitsLayout) { -// NewsView(news: .init(title: "NHN, 작년 영업익 555억원...전년비 42%", postDate: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false)) -// .previewInterfaceOrientation(.landscapeLeft) -// .previewLayout(.sizeThatFits) -// .colorScheme(.dark) -//} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Report/Type/TypePieChartView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Report/Type/TypePieChartView.swift index f27b7243..7a2e0399 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Report/Type/TypePieChartView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Report/Type/TypePieChartView.swift @@ -28,7 +28,6 @@ struct TypePieChartView: View { .cornerRadius(8) .foregroundStyle(report.category?.color.gradient ?? Color.primary01.gradient) } - /// pie chart의 가운데 문구 .chartBackground { chartProxy in GeometryReader { geometry in let frame = geometry[chartProxy.plotFrame!] From 003da6c76ccbb48d9ca156d34770390e7b8827c9 Mon Sep 17 00:00:00 2001 From: realhsb Date: Thu, 20 Jun 2024 08:53:24 +0900 Subject: [PATCH 35/61] =?UTF-8?q?chore:=20Bookmark=20Service=EC=9D=98=20ta?= =?UTF-8?q?sk=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Source/Domain/Service/BookmarksService.swift | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/Domain/Service/BookmarksService.swift b/iOS/RollTheDice/RollTheDice/Source/Domain/Service/BookmarksService.swift index 926408bc..1d24ede8 100644 --- a/iOS/RollTheDice/RollTheDice/Source/Domain/Service/BookmarksService.swift +++ b/iOS/RollTheDice/RollTheDice/Source/Domain/Service/BookmarksService.swift @@ -12,7 +12,7 @@ enum BookmarksService { case bookmarksIsChecked(newsId: Int, accessToken: String) ///뉴스 북마크 여부 조회 case saveBookmarks(newsId: Int, accessToken: String) ///북마크 저장 case deleteBookmarks(newsId: Int, accessToken: String) ///북마크 삭제 - case allBookmarks(page: Int, size: Int, accessToken: String) ///북마크 전체 조회/ + case allBookmarks(page: Int, size: Int, accessToken: String) ///북마크 전체 조회 } extension BookmarksService: BaseTargetType { @@ -49,12 +49,14 @@ extension BookmarksService: BaseTargetType { var task: Moya.Task { switch self { - case .bookmarksIsChecked(let newsId, _), - .saveBookmarks(let newsId, _), - .deleteBookmarks(let newsId, _): + case .bookmarksIsChecked(_, _), + .deleteBookmarks(_, _): let parameters : [String : Any] = [:] return .requestParameters(parameters: parameters, encoding: URLEncoding.default) + case .saveBookmarks(_, _): + return .requestPlain + case .allBookmarks(let page, let size, _): let parameters : [String : Any] = [ "page" : page, From d009b63a9d3caacebaf4e78c627ec1ef4587db7a Mon Sep 17 00:00:00 2001 From: realhsb Date: Thu, 20 Jun 2024 09:17:40 +0900 Subject: [PATCH 36/61] =?UTF-8?q?feat:=20NewsListView=EC=97=90=20Bookmarks?= =?UTF-8?q?ListViewModel=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Source/View/News/NewsList/NewsListView.swift | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsListView.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsListView.swift index d95bb351..45dd6652 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsListView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsListView.swift @@ -10,6 +10,7 @@ import SwiftUI struct NewsListView: View { var newsListViewModel: NewsListViewModel + var bookmarksViewModel: BookmarksListViewModel var newsId: Int? @State var selectedIndex: Int = 0 @@ -18,7 +19,7 @@ struct NewsListView: View { ZStack { Color.backgroundDark.ignoresSafeArea(.all) - NewsListContentView(newsList: newsListViewModel.newsList ?? []) + NewsListContentView(newsList: newsListViewModel.newsList ?? [], bookmarksViewModel: bookmarksViewModel) } .task { newsListViewModel.getAllNewsData(page: 0, size: 10) @@ -27,6 +28,7 @@ struct NewsListView: View { private struct NewsListContentView: View { var newsList: [NewsList] + var bookmarksViewModel: BookmarksListViewModel fileprivate var body: some View { @@ -35,7 +37,7 @@ struct NewsListView: View { LazyHStack { ForEach(newsList) { news in - NewsView(news: news) + NewsView(news: news, bookmarksViewModel: bookmarksViewModel) .frame(width: proxy.size.width) .scrollTransition(.interactive, axis: .horizontal) { effect, phase in effect @@ -69,6 +71,6 @@ struct NewsListView: View { } #Preview { - NewsListView(newsListViewModel: NewsListViewModel()) + NewsListView(newsListViewModel: NewsListViewModel(), bookmarksViewModel: BookmarksListViewModel()) .previewInterfaceOrientation(.landscapeLeft) } From 64498015678c39d29555ba7f23268e6214ed9383 Mon Sep 17 00:00:00 2001 From: realhsb Date: Thu, 20 Jun 2024 09:17:50 +0900 Subject: [PATCH 37/61] =?UTF-8?q?chore:=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Source/View/News/NewsList/NewsView.swift | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsView.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsView.swift index 7e7731cf..341cd109 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsView.swift @@ -10,12 +10,9 @@ import SwiftUI struct NewsView: View { @EnvironmentObject var pathModel : PathModel - -// var newsListViewModel: NewsListViewModel + var news: NewsList -// var isVisibleView: Bool = true -// var cardWidth: Double = 0.0 -// var cardHeight: Double = 0.0 + var bookmarksViewModel: BookmarksListViewModel var body: some View { VStack(alignment: .center, spacing: 20) { @@ -52,7 +49,6 @@ struct NewsView: View { Button { let newsId:Int = news.newsId - print("!!!!!!!!!!! newsID : \(news.newsId)") pathModel.paths.append(.detailNewsView(newsId: newsId)) } label: { Text("더보기") @@ -74,7 +70,6 @@ struct NewsView: View { .padding(.top, 50) .frame(width: 380) .background( -// LinearGradient(colors: isVisibleView ? [.basicWhite, .primaryLight01] : [.basicWhite], startPoint: .top, endPoint: .bottom) LinearGradient(colors: [.basicWhite, .primaryLight01], startPoint: .top, endPoint: .bottom) ) .clipShape(RoundedRectangle(cornerRadius: 12)) @@ -84,9 +79,13 @@ struct NewsView: View { HStack { Spacer() Button { - + if news.isBookmarked ?? false { + + } else { + + } } label: { - Image(.bookmarkfill) + Image(news.isBookmarked ?? false ? .bookmarkfill : .bookmarkunfill) .shadow(color: .gray06, radius: 2) } .offset(CGSize(width: -20, height: -10)) @@ -98,6 +97,6 @@ struct NewsView: View { } #Preview { - NewsView(news: .init(newsId: 1, title: "1분기 선방한 dddddddd韓게임사들…엔씨만 울었다", content: "내용내용ㄴㅇㅇㅇ", thumbnailUrl: "", postDate: "2222-22-22", isBookmarked: true)) + NewsView(news: .init(newsId: 1, title: "1분기 선방한 dddddddd韓게임사들…엔씨만 울었다", content: "내용내용ㄴㅇㅇㅇ", thumbnailUrl: "", postDate: "2222-22-22", isBookmarked: true), bookmarksViewModel: BookmarksListViewModel()) .environmentObject(PathModel()) } From 85f03cd58c948a9117ccf9d75ab1cb7a570d06b3 Mon Sep 17 00:00:00 2001 From: realhsb Date: Thu, 20 Jun 2024 09:18:14 +0900 Subject: [PATCH 38/61] =?UTF-8?q?feat:=20=EB=B6=81=EB=A7=88=ED=81=AC=20?= =?UTF-8?q?=EC=97=AC=EB=B6=80=20=ED=99=95=EC=9D=B8=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EB=B0=8F=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BookmarkCard/BookmarksListViewModel.swift | 74 +++++++++++++------ 1 file changed, 52 insertions(+), 22 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift index f9342a31..0e87e989 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift @@ -23,6 +23,8 @@ import SwiftUI } extension BookmarksListViewModel { + + /// 북마크 전체 조회 public func getAllBookmarksData(page: Int, size: Int) { guard let accessToken = TokenManager.shared.accessToken else { print("Access token 사용 불가능...") @@ -56,26 +58,54 @@ extension BookmarksListViewModel { print(response) }) } -} + + /// 뉴스 북마크 여부 조회 + public func isBookmark(newsId: Int) -> Bool { -//public class BookmarksListViewModel: ObservableObject { -// @Published var bookmarkList: [Bookmarks] -// -// init( -// bookmarkList: [Bookmarks] = [ -// .init(title: "2024년 ‘소셜 미디어 다이어트’를 위해 바꿔볼 것", date: "2023년12월3일", image: "exampleNews", content: "2024년으로 접어든지 한 달이 넘었다. 하지만 올 해가 어떻게 흘러갈지 예측하기는 쉽지 않다. 한 가지 확실한 것은 정치적으로 매우 중요한 해라는 점이다. 미국과 러시아, 우크라이나, 방글라데시, 인도, 대만, 한국, 남아프리카공화국, 유럽의회, 영국에서 선거가 치러질 예정이다.", isBookmarked: false), -// .init(title: "앤스로픽 최신 AI 모델 '클로드3' 출시", date: "2023년3월13일", image: "https://imgnews.pstatic.net/image/014/2024/03/05/0005151141_001_20240305101610000.jpg?type=w647", content: "오픈AI의 대항마 앤스로픽이 생성형 인공지능(AI) 최신 모델 '클로드'(Claude)3를 선보이면서 생성형 AI 주도권을 잡기 위한 경쟁이 다시 뜨거워지고 있다. 앤스로픽은 지난 한 해 동안 구글과 세일즈포스, 아마존 등에서 총 73억 달러(약 9조7309억 원)를 투자받고 '클로드3'를 내놨는데 오픈AI의 챗GPT-4를 능가한다고 도발했다.", isBookmarked: true), -// .init(title: "SK C&C, 외부 전문가 대거 영입… “신성장 동력 강화”", date: "2023년2월13일", image: "https://imgnews.pstatic.net/image/366/2024/03/05/0000975131_001_20240305093504301.jpg?type=w647", content: "SK C&C는 국내외 신성장 동력 강화를 위해 인공지능(AI)·클라우드·디지털 팩토리·ESG(환경·사회·지배구조) 등 4대 성장 사업과 디지털 컨설팅 중심으로 외부 전문가를 대거 영입해 전진 배치했다고 5일 밝혔다.", isBookmarked: false), -// .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), -// -// .init(title: "이종호 과기장관 5년 뒤 구축될 바이오파운드리에 산학연 역량 모아야", date: "2023년3월13일", image: "https://imgnews.pstatic.net/image/003/2024/03/05/NISI20231030_0001398722_web_20231030141808_20240305103108748.jpg?type=w647", content: "정부가 내년부터 합성생물학의 필수 인프라인 '국가 바이오파운드리' 구축에 본격 나서는 가운데 이종호 과학기술정보통신부 장관이 한국생명공학연구원에서 운영 중인 사전연구용 시설을 찾아 구체적인 인프라 구축 계획 등을 점검했다.이 장관은 5일 합성생물학 육성을 위해 바이오파운드리 연구현장을 방문하고, 산·학·연 전문가들을 만났다. 이번 방문은 지난해 미국, 영국과의 정상회담 시 논의됐던 첨단바이오 협력을 위한 후속조치의 일환으로 추진됐다.", isBookmarked: false), -// .init(title: "SW산업 육성에 7308억 예산투자, SaaS 등 육성", date: "2023년3월13일", image: "https://imgnews.pstatic.net/image/008/2024/03/05/0005007507_001_20240305135301539.jpg?type=w647", content: "SW(소프트웨어) 산업의 SaaS(서비스형 소프트웨어) 전환 등 SW산업 육성을 위해 정부 예산 7308억원이 투자된다. 강도현 과학기술정보통신부 제2차관은 5일 오전 서울 을지로 더존비즈온 을지사옥에서 열린 'AI(인공지능) 일상화, SW도 이제 서비스형 SW'라는 주제로 열린 현장 간담회에서 정부도 대한민국 SW산업의 미래가 SaaS에 있다고 생각하고 올해 'SaaS 혁신펀드'를 새롭게 조성하는 등 SaaS 육성 및 기존 SW 기업의 SaaS 전환을 위해 다양한 지원을 추진 중이라며 이같이 밝혔다.", isBookmarked: false), -// .init(title: "파수, 기업용 AI ‘엔터프라이즈 LLM’ 출시", date: "2023년3월13일", image: "https://imgnews.pstatic.net/image/018/2024/03/05/0005685566_001_20240305103201036.jpg?type=w647", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), -// .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), -// .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), -// .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), -// ] -// ) { -// self.bookmarkList = bookmarkList -// } -//} + var isBookmarked: Bool = false + + guard let accessToken = TokenManager.shared.accessToken else { + print("Access token 사용 불가능...") + return isBookmarked + } + + if let cancellable = bookmarksCancellable { + cancellable.cancel() + } + + bookmarksCancellable = provider.requestWithProgressPublisher( + .saveBookmarks( + newsId: newsId, + accessToken: accessToken + ) + ) + .compactMap { $0.response?.data } + .receive(on: DispatchQueue.main) + .decode(type: Bookmarks.self, decoder: JSONDecoder()) + .sink(receiveCompletion: { result in + switch result { + case .finished: + print("bookmark 여부 확인 성공") + case .failure(let error): + Log.network("network error bookmark 여부 확인 실패", error.localizedDescription) + } + }, receiveValue: { [weak self] response in + print(response) + + if response.isBookmarked ?? false { + isBookmarked = true + } else { + isBookmarked = false + } + }) + + return isBookmarked + } + + /// 북마크 저장 + + + /// 북마크 삭제 + + +} From 3ec8334a7b3d3c62eb7c46674fdba1a3d3973aef Mon Sep 17 00:00:00 2001 From: realhsb Date: Thu, 20 Jun 2024 09:18:27 +0900 Subject: [PATCH 39/61] =?UTF-8?q?chore:=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Bookmark/BookmarkCard/BookmarkView.swift | 6 ----- .../View/Bookmark/BookmarkListView.swift | 24 ------------------- 2 files changed, 30 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkView.swift index ea1086b4..24389491 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkView.swift @@ -73,9 +73,3 @@ struct BookmarkView: View { } } } - -//#Preview { -// BookmarkView(bookmark: .init(newsId: 0, title: "NHN, 작년 영업익 555억원...전년비 42% ↑", thumbnailURL: <#T##String#>, postDate: <#T##String#>, isBookmarked: <#T##Bool#>)) -// -// BookmarkView(bookmark: .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false)) -//} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkListView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkListView.swift index ae4c8175..d7bb4c80 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkListView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkListView.swift @@ -67,30 +67,6 @@ struct BookmarkListView: View { } } } - -// private struct BookmarkListContentView: View { -// @StateObject var bookmarkListViewModel: BookmarkListViewModel -// var columns: [GridItem] = [ GridItem(), GridItem()] -// -// fileprivate var body: some View { -// ScrollViewReader { value in -// ScrollView(.horizontal, showsIndicators: false) { -// LazyHGrid(rows: columns, spacing: 10) { -// ForEach(bookmarkListViewModel.bookmarkList, id: \.self) { bookmark in -// BookmarkView(bookmark: bookmark) -//// .onTapGesture { -//// withAnimation { -//// selectedIndex = index -//// value.scrollTo(index) -//// } -//// } -// } -// } -// .padding(.vertical, 90) -// } -// } -// } -// } } #Preview { From 3b019167822b37cd2b629bb82904a268c708f3bb Mon Sep 17 00:00:00 2001 From: realhsb Date: Thu, 20 Jun 2024 09:42:38 +0900 Subject: [PATCH 40/61] =?UTF-8?q?feat:=20=EB=B6=81=EB=A7=88=ED=81=AC=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BookmarkCard/BookmarksListViewModel.swift | 39 ++++++++++++++++++- .../Source/View/News/NewsList/NewsView.swift | 4 +- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift index 0e87e989..3b91e22e 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift @@ -103,7 +103,44 @@ extension BookmarksListViewModel { } /// 북마크 저장 - + public func saveBookmark(newsId: Int) { + print("saveBookmark \(newsId)") + + guard let accessToken = TokenManager.shared.accessToken else { + print("Access token 사용 불가능...") + return + } + + if let cancellable = bookmarksCancellable { + cancellable.cancel() + } + + bookmarksCancellable = provider.requestWithProgressPublisher( + .saveBookmarks( + newsId: newsId, + accessToken: accessToken + ) + ) +// .compactMap { $0.response?.data } + .receive(on: DispatchQueue.main) +// .decode(type: Bookmarks.self, decoder: JSONDecoder()) + .sink(receiveCompletion: { result in + switch result { + case .finished: + print("bookmark 여부 확인 성공") + case .failure(let error): + Log.network("network error bookmark 여부 확인 실패", error.localizedDescription) + } + }, receiveValue: { [weak self] response in + print(response) + if response.response?.statusCode == 201 { + print("북마크 저장 성공") + } else { + print("북마크 저장 실패") + } + }) + + } /// 북마크 삭제 diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsView.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsView.swift index 341cd109..0ff8875c 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsView.swift @@ -79,10 +79,12 @@ struct NewsView: View { HStack { Spacer() Button { + print("북마크 버튼눌림") + print(news.isBookmarked) if news.isBookmarked ?? false { } else { - + bookmarksViewModel.saveBookmark(newsId: news.newsId) } } label: { Image(news.isBookmarked ?? false ? .bookmarkfill : .bookmarkunfill) From 4667af84235abb9dd2c7cf4276b342ab72af114e Mon Sep 17 00:00:00 2001 From: realhsb Date: Thu, 20 Jun 2024 09:42:54 +0900 Subject: [PATCH 41/61] =?UTF-8?q?chore:=20BookmarksViewModel=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift | 2 +- .../RollTheDice/Source/View/MainTab/MainTabView.swift | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift index 3ea1b27f..5009d613 100644 --- a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift +++ b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift @@ -40,7 +40,7 @@ struct RollTheDiceApp: App { .environmentObject(signUpViewModel) case .completedSignUp: NavigationStack(path: $pathModel.paths) { - MainTabView(newsListViewModel: newsListViewModel) + MainTabView(newsListViewModel: newsListViewModel, bookmarksListViewModel: bookmarkListViewModel) .navigationDestination(for: PathType.self, destination: { pathType in // 각 뷰마다 .navigationBarBackButtonHidden() 설정하기! diff --git a/iOS/RollTheDice/RollTheDice/Source/View/MainTab/MainTabView.swift b/iOS/RollTheDice/RollTheDice/Source/View/MainTab/MainTabView.swift index 242bc53b..491633c9 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/MainTab/MainTabView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/MainTab/MainTabView.swift @@ -11,6 +11,7 @@ struct MainTabView: View { @EnvironmentObject private var pathModel: PathModel var newsListViewModel: NewsListViewModel + var bookmarksListViewModel: BookmarksListViewModel @EnvironmentObject var authViewModel: AuthenticationViewModel @@ -37,7 +38,7 @@ struct MainTabView: View { } .tag(0) - NewsListView(newsListViewModel: newsListViewModel) + NewsListView(newsListViewModel: newsListViewModel, bookmarksViewModel: bookmarksListViewModel) .tabItem { Image(systemName: "square.3.layers.3d.down.left") } @@ -59,7 +60,7 @@ struct MainTabView: View { } #Preview { - MainTabView(newsListViewModel: NewsListViewModel()) + MainTabView(newsListViewModel: NewsListViewModel(), bookmarksListViewModel: BookmarksListViewModel()) .environmentObject(PathModel()) // .environmentObject(NewsListViewModel()) } From 0c5d6007b623acc7e36af89c6fc918fa163561d9 Mon Sep 17 00:00:00 2001 From: realhsb Date: Thu, 20 Jun 2024 10:12:23 +0900 Subject: [PATCH 42/61] =?UTF-8?q?feat:=20=EB=B6=81=EB=A7=88=ED=81=AC=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BookmarkCard/BookmarksListViewModel.swift | 43 +++++++++++++++++-- .../Source/View/News/NewsList/NewsView.swift | 2 +- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift index 3b91e22e..f31a3395 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift @@ -127,22 +127,57 @@ extension BookmarksListViewModel { .sink(receiveCompletion: { result in switch result { case .finished: - print("bookmark 여부 확인 성공") + print("bookmarks 저장") case .failure(let error): Log.network("network error bookmark 여부 확인 실패", error.localizedDescription) } }, receiveValue: { [weak self] response in print(response) if response.response?.statusCode == 201 { - print("북마크 저장 성공") + print("bookmarks 저장 성공") } else { - print("북마크 저장 실패") + print("bookmarks 저장 실패") } }) } /// 북마크 삭제 - + public func deleteBookmark(newsId: Int) { + print("saveBookmark \(newsId)") + + guard let accessToken = TokenManager.shared.accessToken else { + print("Access token 사용 불가능...") + return + } + + if let cancellable = bookmarksCancellable { + cancellable.cancel() + } + + bookmarksCancellable = provider.requestWithProgressPublisher( + .deleteBookmarks( + newsId: newsId, + accessToken: accessToken + ) + ) + .receive(on: DispatchQueue.main) + .sink(receiveCompletion: { result in + switch result { + case .finished: + print("bookmarks 삭제") + case .failure(let error): + Log.network("network error bookmark 여부 확인 실패", error.localizedDescription) + } + }, receiveValue: { [weak self] response in + print(response) + if response.response?.statusCode == 204 { + print("bookmarks 삭제 성공") + } else { + print("bookmarks 삭제 실패") + } + }) + + } } diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsView.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsView.swift index 0ff8875c..d346735d 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsView.swift @@ -82,7 +82,7 @@ struct NewsView: View { print("북마크 버튼눌림") print(news.isBookmarked) if news.isBookmarked ?? false { - + bookmarksViewModel.deleteBookmark(newsId: news.newsId) } else { bookmarksViewModel.saveBookmark(newsId: news.newsId) } From 1110c4a75caafac5474563561bfbebbf810622be Mon Sep 17 00:00:00 2001 From: realhsb Date: Thu, 20 Jun 2024 10:12:34 +0900 Subject: [PATCH 43/61] =?UTF-8?q?chore:=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Source/View/Bookmark/BookmarkCard/BookmarkView.swift | 5 ----- 1 file changed, 5 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkView.swift index 24389491..f6ddfdd7 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkView.swift @@ -7,11 +7,6 @@ import SwiftUI -//let id = UUID().uuidString -//let newsId: Int -//let title, thumbnailURL, postDate: String -//let isBookmarked: Bool - struct BookmarkView: View { @State var bookmark: Bookmarks var body: some View { From 0f82def58238753299b00676d6685aafe5b7811d Mon Sep 17 00:00:00 2001 From: yeahzxnn Date: Thu, 20 Jun 2024 10:43:39 +0900 Subject: [PATCH 44/61] =?UTF-8?q?feat:=20=EC=B1=84=ED=8C=85=EB=B0=A9=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8CAPI=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 | 3 + .../Service/DebateSummaryService.swift | 43 ++ .../ViewModel/DebateSummaryViewModel.swift | 46 ++ 9 files changed, 471 insertions(+), 177 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 bd6aa60bff8ecb7d6bce98f5b7d174c576a2b551..f7a638416b1c4e4dc2eb9c750107977c6833eaf8 100644 GIT binary patch delta 57 zcmZoMXffE}!Nim}aq>APy~!0!Jgo6so!{M_e45E{@-8HvJ>!PWg3RAoCN{8bX6N|J F4*-0g7A*h( delta 57 zcmZoMXffE}!NerkH2EBp-sB1<9#(;wmmQ`}KFwq}c^4ATo-tvwAoDkti4AO<**X65 F0{}Q~6XE~> diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 1e58b14f..509e4a56 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -25,6 +25,11 @@ 3586B5402C22DFCB006B1458 /* RecentNewsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B53F2C22DFCB006B1458 /* RecentNewsViewModel.swift */; }; 3586B5422C232C00006B1458 /* EndDebateService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B5412C232C00006B1458 /* EndDebateService.swift */; }; 3586B5452C232C7C006B1458 /* EndDebateViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B5442C232C7C006B1458 /* EndDebateViewModel.swift */; }; + 3586B5492C2356F2006B1458 /* DebateSummaryService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B5482C2356F2006B1458 /* DebateSummaryService.swift */; }; + 3586B54C2C235731006B1458 /* DebateSummaryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B54B2C235731006B1458 /* DebateSummaryViewModel.swift */; }; + 3586B54F2C23B767006B1458 /* GetDebateRoom.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B54E2C23B767006B1458 /* GetDebateRoom.swift */; }; + 3586B5512C23B79F006B1458 /* GetDebateRoomService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B5502C23B79F006B1458 /* GetDebateRoomService.swift */; }; + 3586B5532C23B7DC006B1458 /* GetDebateRoomViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B5522C23B7DC006B1458 /* GetDebateRoomViewModel.swift */; }; 35C71BF22B79F39900F777D1 /* ExyteChat in Frameworks */ = {isa = PBXBuildFile; productRef = 35C71BF12B79F39900F777D1 /* ExyteChat */; }; 6C32379F2B7C376D00B699AB /* Bookmarks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C32379E2B7C376D00B699AB /* Bookmarks.swift */; }; 6C3237A12B7C377600B699AB /* BookmarkViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3237A02B7C377600B699AB /* BookmarkViewModel.swift */; }; @@ -123,6 +128,11 @@ 3586B53F2C22DFCB006B1458 /* RecentNewsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentNewsViewModel.swift; sourceTree = ""; }; 3586B5412C232C00006B1458 /* EndDebateService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndDebateService.swift; sourceTree = ""; }; 3586B5442C232C7C006B1458 /* EndDebateViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndDebateViewModel.swift; sourceTree = ""; }; + 3586B5482C2356F2006B1458 /* DebateSummaryService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebateSummaryService.swift; sourceTree = ""; }; + 3586B54B2C235731006B1458 /* DebateSummaryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebateSummaryViewModel.swift; sourceTree = ""; }; + 3586B54E2C23B767006B1458 /* GetDebateRoom.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetDebateRoom.swift; sourceTree = ""; }; + 3586B5502C23B79F006B1458 /* GetDebateRoomService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetDebateRoomService.swift; sourceTree = ""; }; + 3586B5522C23B7DC006B1458 /* GetDebateRoomViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetDebateRoomViewModel.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 = ""; }; @@ -231,6 +241,7 @@ children = ( 3544D73F2C228EFC007DBD18 /* CreateDebateRoomService.swift */, 3586B53D2C22DF67006B1458 /* RecentNewsService.swift */, + 3586B5502C23B79F006B1458 /* GetDebateRoomService.swift */, ); path = Service; sourceTree = ""; @@ -240,6 +251,7 @@ children = ( 3544D7422C228F54007DBD18 /* CreateDebateRoomViewModel.swift */, 3586B53F2C22DFCB006B1458 /* RecentNewsViewModel.swift */, + 3586B5522C23B7DC006B1458 /* GetDebateRoomViewModel.swift */, ); path = ViewModel; sourceTree = ""; @@ -279,6 +291,30 @@ path = ViewModel; sourceTree = ""; }; + 3586B5472C2356E1006B1458 /* Service */ = { + isa = PBXGroup; + children = ( + 3586B5482C2356F2006B1458 /* DebateSummaryService.swift */, + ); + path = Service; + sourceTree = ""; + }; + 3586B54A2C23571D006B1458 /* ViewModel */ = { + isa = PBXGroup; + children = ( + 3586B54B2C235731006B1458 /* DebateSummaryViewModel.swift */, + ); + path = ViewModel; + sourceTree = ""; + }; + 3586B54D2C23B748006B1458 /* GetDebateRoomModel */ = { + isa = PBXGroup; + children = ( + 3586B54E2C23B767006B1458 /* GetDebateRoom.swift */, + ); + path = GetDebateRoomModel; + sourceTree = ""; + }; 6C32379D2B7C374E00B699AB /* BookmarkCard */ = { isa = PBXGroup; children = ( @@ -310,6 +346,7 @@ 6C41B8D62BE1048500274FA4 /* ChatList */ = { isa = PBXGroup; children = ( + 3586B54D2C23B748006B1458 /* GetDebateRoomModel */, 3586B5392C22DF03006B1458 /* RecentNewsModel */, 3544D7412C228F39007DBD18 /* ViewModel */, 3544D73E2C228EDB007DBD18 /* Service */, @@ -617,6 +654,8 @@ 6CE103182BD57A1600498AA4 /* Summary */ = { isa = PBXGroup; children = ( + 3586B54A2C23571D006B1458 /* ViewModel */, + 3586B5472C2356E1006B1458 /* Service */, 6CE103192BD57A2500498AA4 /* DebateSummaryView.swift */, ); path = Summary; @@ -836,11 +875,13 @@ 3586B53C2C22DF41006B1458 /* News.swift in Sources */, 6C3237AE2B7C382E00B699AB /* DetailNewsViewModel.swift in Sources */, 6C77048F2B7229B1001B17CB /* NewsListView.swift in Sources */, + 3586B54C2C235731006B1458 /* DebateSummaryViewModel.swift in Sources */, 357666132BBD54AA002C226A /* SplashView.swift in Sources */, 6C4F7BAD2BDE510900ED01DA /* DailyReportViewModel.swift in Sources */, 6C3237A72B7C37E500B699AB /* BookmarksListViewModel.swift in Sources */, 6C454A822B9DAFA3006FD9D0 /* Path.swift in Sources */, 6C94799E2BD3C00C00D5AEEB /* Image.swift in Sources */, + 3586B5512C23B79F006B1458 /* GetDebateRoomService.swift in Sources */, 6C454A842B9DAFCB006FD9D0 /* PathType.swift in Sources */, 6CF130AF2BAB0C4F00A437B6 /* AuthenticatedView.swift in Sources */, 3586B5422C232C00006B1458 /* EndDebateService.swift in Sources */, @@ -852,6 +893,7 @@ 6CF130C22BAB786600A437B6 /* APIHeaderManager.swift in Sources */, 6C5B0C8C2C1C32C000A0D5F4 /* BookmarksService.swift in Sources */, 6CDB29FB2BAA07B10081037B /* GPTChatViewModel.swift in Sources */, + 3586B5492C2356F2006B1458 /* DebateSummaryService.swift in Sources */, 6C32379F2B7C376D00B699AB /* Bookmarks.swift in Sources */, 6C454A7E2B9DAA3F006FD9D0 /* SignUpFinishView.swift in Sources */, 6C7704A12B722CEB001B17CB /* ProfileView.swift in Sources */, @@ -865,8 +907,10 @@ 6C454A7C2B9DA71C006FD9D0 /* SignUpView.swift in Sources */, 3586B5402C22DFCB006B1458 /* RecentNewsViewModel.swift in Sources */, 6C41B8DA2BE104A800274FA4 /* RecentNewsCardView.swift in Sources */, + 3586B5532C23B7DC006B1458 /* GetDebateRoomViewModel.swift in Sources */, 3586B5452C232C7C006B1458 /* EndDebateViewModel.swift in Sources */, 3509091A2C1C1248007D76A1 /* TokenManager.swift in Sources */, + 3586B54F2C23B767006B1458 /* GetDebateRoom.swift in Sources */, 6CF130C72BAB7B9800A437B6 /* ScoopAPINews.swift in Sources */, 6C7651402BF37F3400196536 /* Log.swift in Sources */, 6CE1031A2BD57A2500498AA4 /* DebateSummaryView.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..846f529d 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..ae34da56 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 { 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("토론 요약 오류/실패") + } + } + } +} From 00b86b472875b917a221482377f8346cb46c67f0 Mon Sep 17 00:00:00 2001 From: yeahzxnn Date: Thu, 20 Jun 2024 12:06:48 +0900 Subject: [PATCH 45/61] =?UTF-8?q?fix=20:=20=EC=B5=9C=EA=B7=BC=20=EB=B3=B8?= =?UTF-8?q?=20=EB=89=B4=EC=8A=A4=20=EC=A1=B0=ED=9A=8C=ED=95=98=EA=B8=B0=20?= =?UTF-8?q?API=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 46/61] =?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 47/61] =?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 48/61] =?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("토론 요약 오류/실패") + } + } + } +} From 2a702cb292ad257dbc4a321844e45ece354f00e3 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Sun, 30 Jun 2024 15:10:43 +0900 Subject: [PATCH 49/61] feat: success response --- .../global/common/response/SuccessCode.java | 19 +++++++++++++++++++ .../common/response/SuccessResponse.java | 18 ++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java create mode 100644 backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessResponse.java diff --git a/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java b/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java new file mode 100644 index 00000000..e7911554 --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java @@ -0,0 +1,19 @@ +package com.rollthedice.backend.global.common.response; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum SuccessCode { + // bookmark + GET_ALL_BOOKMARK_SUCCESS(200, "북마크 전체 조회를 성공했습니다."), + GET_IS_BOOKMARKED_SUCCESS(200, "뉴스가 북마크 여부 조회를 성공했습니다."), + CREATE_BOOKMARK_SUCCESS(201, "북마크 저장에 성공했습니다."), + DELETE_BOOKMARK_SUCCESS(204, "북마크 삭제에 성공했습니다."), + + ; + + private final int status; + private final String message; +} diff --git a/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessResponse.java b/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessResponse.java new file mode 100644 index 00000000..803b9ac9 --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessResponse.java @@ -0,0 +1,18 @@ +package com.rollthedice.backend.global.common.response; + +public record SuccessResponse( + int status, + String message, + T data +) { + + private static final String NOTHING = ""; + + public static SuccessResponse of(SuccessCode code) { + return new SuccessResponse<>(code.getStatus(), code.getMessage(), NOTHING); + } + + public static SuccessResponse of(SuccessCode code, T data) { + return new SuccessResponse<>(code.getStatus(), code.getMessage(), data); + } +} From 330873729e94b16eefb5400f45dd4eff057ce39f Mon Sep 17 00:00:00 2001 From: yeonjy Date: Sun, 30 Jun 2024 15:11:11 +0900 Subject: [PATCH 50/61] refactor: directory config -> common --- .../backend/global/{config => common}/BaseTimeEntity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename backend/core/src/main/java/com/rollthedice/backend/global/{config => common}/BaseTimeEntity.java (93%) diff --git a/backend/core/src/main/java/com/rollthedice/backend/global/config/BaseTimeEntity.java b/backend/core/src/main/java/com/rollthedice/backend/global/common/BaseTimeEntity.java similarity index 93% rename from backend/core/src/main/java/com/rollthedice/backend/global/config/BaseTimeEntity.java rename to backend/core/src/main/java/com/rollthedice/backend/global/common/BaseTimeEntity.java index 5aff4ca7..fce2d4d0 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/global/config/BaseTimeEntity.java +++ b/backend/core/src/main/java/com/rollthedice/backend/global/common/BaseTimeEntity.java @@ -1,4 +1,4 @@ -package com.rollthedice.backend.global.config; +package com.rollthedice.backend.global.common; import jakarta.persistence.Column; import jakarta.persistence.EntityListeners; From 7f5720476ca7d3dd4205c73b19a6bb0fdd76922b Mon Sep 17 00:00:00 2001 From: yeonjy Date: Sun, 30 Jun 2024 15:12:01 +0900 Subject: [PATCH 51/61] =?UTF-8?q?feat:=20BookmarkApi=EC=97=90=20success=20?= =?UTF-8?q?response=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/bookmark/api/BookmarkApi.java | 9 +++++---- .../bookmark/api/BookmarkController.java | 19 +++++++++++++------ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/bookmark/api/BookmarkApi.java b/backend/core/src/main/java/com/rollthedice/backend/domain/bookmark/api/BookmarkApi.java index d9673019..e8afb307 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/bookmark/api/BookmarkApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/bookmark/api/BookmarkApi.java @@ -2,6 +2,7 @@ import com.rollthedice.backend.domain.bookmark.dto.response.BookmarkResponse; import com.rollthedice.backend.domain.news.dto.response.NewsResponse; +import com.rollthedice.backend.global.common.response.SuccessResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; @@ -22,7 +23,7 @@ public interface BookmarkApi { responseCode = "200", description = "OK" ) - List getAllBookmarkedNews( + SuccessResponse> getAllBookmarkedNews( Pageable pageable ); @@ -36,7 +37,7 @@ List getAllBookmarkedNews( responseCode = "200", description = "OK" ) - BookmarkResponse getIsBookmarked( + SuccessResponse getIsBookmarked( @Parameter(in = ParameterIn.PATH, description = "뉴스 ID", required = true) Long newsId ); @@ -52,7 +53,7 @@ BookmarkResponse getIsBookmarked( responseCode = "201", description = "Created" ) - void saveBookmark( + SuccessResponse saveBookmark( @Parameter(in = ParameterIn.PATH, description = "뉴스 ID", required = true) Long newsId ); @@ -67,7 +68,7 @@ void saveBookmark( responseCode = "204", description = "No Content" ) - void deleteBookmark( + SuccessResponse deleteBookmark( @Parameter(in = ParameterIn.PATH, description = "뉴스 ID", required = true) Long newsId ); diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/bookmark/api/BookmarkController.java b/backend/core/src/main/java/com/rollthedice/backend/domain/bookmark/api/BookmarkController.java index 23dd1b85..d9556f93 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/bookmark/api/BookmarkController.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/bookmark/api/BookmarkController.java @@ -3,6 +3,7 @@ import com.rollthedice.backend.domain.bookmark.dto.response.BookmarkResponse; import com.rollthedice.backend.domain.bookmark.service.BookmarkService; import com.rollthedice.backend.domain.news.dto.response.NewsResponse; +import com.rollthedice.backend.global.common.response.SuccessResponse; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; @@ -10,6 +11,8 @@ import java.util.List; +import static com.rollthedice.backend.global.common.response.SuccessCode.*; + @RestController @RequiredArgsConstructor @RequestMapping("bookmarks") @@ -19,28 +22,32 @@ public class BookmarkController implements BookmarkApi { @ResponseStatus(HttpStatus.OK) @GetMapping("") @Override - public List getAllBookmarkedNews(final Pageable pageable) { - return bookmarkService.getAllBookmarkedNews(pageable); + public SuccessResponse> getAllBookmarkedNews(final Pageable pageable) { + List response = bookmarkService.getAllBookmarkedNews(pageable); + return SuccessResponse.of(GET_ALL_BOOKMARK_SUCCESS, response); } @ResponseStatus(HttpStatus.OK) @GetMapping("/{newsId}") @Override - public BookmarkResponse getIsBookmarked(@PathVariable final Long newsId) { - return bookmarkService.getIsBookmarked(newsId); + public SuccessResponse getIsBookmarked(@PathVariable final Long newsId) { + BookmarkResponse response = bookmarkService.getIsBookmarked(newsId); + return SuccessResponse.of(GET_IS_BOOKMARKED_SUCCESS, response); } @ResponseStatus(HttpStatus.CREATED) @PostMapping("/{newsId}") @Override - public void saveBookmark(@PathVariable final Long newsId) { + public SuccessResponse saveBookmark(@PathVariable final Long newsId) { bookmarkService.saveBookmark(newsId); + return SuccessResponse.of(CREATE_BOOKMARK_SUCCESS); } @ResponseStatus(HttpStatus.NO_CONTENT) @DeleteMapping("/{newsId}") @Override - public void deleteBookmark(@PathVariable final Long newsId) { + public SuccessResponse deleteBookmark(@PathVariable final Long newsId) { bookmarkService.deleteBookmark(newsId); + return SuccessResponse.of(DELETE_BOOKMARK_SUCCESS); } } From b43489d4de194dd529ead19d5fe8f9158fd78ae6 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Sun, 30 Jun 2024 15:13:28 +0900 Subject: [PATCH 52/61] =?UTF-8?q?refactor:=20BaseTimeEntity=20directory=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rollthedice/backend/domain/bookmark/entity/Bookmark.java | 2 +- .../backend/domain/debate/entity/DebateMessage.java | 4 +--- .../rollthedice/backend/domain/debate/entity/DebateRoom.java | 2 +- .../com/rollthedice/backend/domain/member/entity/Member.java | 2 +- .../java/com/rollthedice/backend/domain/news/entity/News.java | 2 +- .../rollthedice/backend/domain/readNews/entity/ReadNews.java | 2 +- 6 files changed, 6 insertions(+), 8 deletions(-) diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/bookmark/entity/Bookmark.java b/backend/core/src/main/java/com/rollthedice/backend/domain/bookmark/entity/Bookmark.java index 6af1d02f..f3cb925a 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/bookmark/entity/Bookmark.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/bookmark/entity/Bookmark.java @@ -2,7 +2,7 @@ import com.rollthedice.backend.domain.member.entity.Member; import com.rollthedice.backend.domain.news.entity.News; -import com.rollthedice.backend.global.config.BaseTimeEntity; +import com.rollthedice.backend.global.common.BaseTimeEntity; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/entity/DebateMessage.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/entity/DebateMessage.java index 91221c01..162926df 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/entity/DebateMessage.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/entity/DebateMessage.java @@ -1,7 +1,6 @@ package com.rollthedice.backend.domain.debate.entity; -import com.rollthedice.backend.domain.member.entity.Member; -import com.rollthedice.backend.global.config.BaseTimeEntity; +import com.rollthedice.backend.global.common.BaseTimeEntity; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; @@ -31,5 +30,4 @@ public DebateMessage(String message, SenderType senderType, DebateRoom debateRoo this.senderType = senderType; this.debateRoom = debateRoom; } - } diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/entity/DebateRoom.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/entity/DebateRoom.java index 566463e4..8ffeb0f4 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/entity/DebateRoom.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/entity/DebateRoom.java @@ -1,7 +1,7 @@ package com.rollthedice.backend.domain.debate.entity; import com.rollthedice.backend.domain.member.entity.Member; -import com.rollthedice.backend.global.config.BaseTimeEntity; +import com.rollthedice.backend.global.common.BaseTimeEntity; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/member/entity/Member.java b/backend/core/src/main/java/com/rollthedice/backend/domain/member/entity/Member.java index 6395057d..390f7490 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/member/entity/Member.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/member/entity/Member.java @@ -1,7 +1,7 @@ package com.rollthedice.backend.domain.member.entity; import com.rollthedice.backend.domain.member.dto.MemberServiceDto; -import com.rollthedice.backend.global.config.BaseTimeEntity; +import com.rollthedice.backend.global.common.BaseTimeEntity; import jakarta.persistence.*; import lombok.*; diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/news/entity/News.java b/backend/core/src/main/java/com/rollthedice/backend/domain/news/entity/News.java index c96859cd..eba53bfe 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/news/entity/News.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/news/entity/News.java @@ -1,6 +1,6 @@ package com.rollthedice.backend.domain.news.entity; -import com.rollthedice.backend.global.config.BaseTimeEntity; +import com.rollthedice.backend.global.common.BaseTimeEntity; import jakarta.persistence.*; import lombok.*; import lombok.extern.slf4j.Slf4j; diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/readNews/entity/ReadNews.java b/backend/core/src/main/java/com/rollthedice/backend/domain/readNews/entity/ReadNews.java index 012fb466..2d6f23be 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/readNews/entity/ReadNews.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/readNews/entity/ReadNews.java @@ -2,7 +2,7 @@ import com.rollthedice.backend.domain.member.entity.Member; import com.rollthedice.backend.domain.news.entity.News; -import com.rollthedice.backend.global.config.BaseTimeEntity; +import com.rollthedice.backend.global.common.BaseTimeEntity; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; From dc2bca4172d542c0a5c4392a9e86a0767600011d Mon Sep 17 00:00:00 2001 From: yeonjy Date: Sun, 30 Jun 2024 18:17:14 +0900 Subject: [PATCH 53/61] =?UTF-8?q?feat:=20Debate=20API=20=EC=97=90=20Succes?= =?UTF-8?q?s=20Response=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/debate/api/DebateApi.java | 19 ++++---- .../domain/debate/api/DebateController.java | 44 ++++++++++++------- .../global/common/response/SuccessCode.java | 10 +++++ 3 files changed, 48 insertions(+), 25 deletions(-) diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/api/DebateApi.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/api/DebateApi.java index f70a4d3b..b61ada20 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/api/DebateApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/api/DebateApi.java @@ -6,6 +6,7 @@ import com.rollthedice.backend.domain.debate.dto.response.DebateRoomResponse; import com.rollthedice.backend.domain.debate.dto.response.DebateRoomSaveResponse; import com.rollthedice.backend.domain.debate.dto.response.DebateSummaryResponse; +import com.rollthedice.backend.global.common.response.SuccessResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; @@ -30,7 +31,7 @@ public interface DebateApi { responseCode = "201", description = "Created" ) - DebateRoomSaveResponse saveDebateRoom(@RequestBody DebateRoomRequest request); + SuccessResponse saveDebateRoom(@RequestBody DebateRoomRequest request); @Operation( summary = "토론방 전체 조회", @@ -42,7 +43,7 @@ public interface DebateApi { responseCode = "200", description = "요청에 성공하였습니다." ) - List getDebateRooms(Pageable pageable); + SuccessResponse> getDebateRooms(Pageable pageable); @Operation( summary = "토론방 삭제", @@ -54,7 +55,7 @@ public interface DebateApi { responseCode = "204", description = "토론방 삭제에 성공하였으며, 응답값은 없습니다." ) - void deleteDebateRoom(@Parameter(in = ParameterIn.PATH, description = "토론방 ID", required = true) + SuccessResponse deleteDebateRoom(@Parameter(in = ParameterIn.PATH, description = "토론방 ID", required = true) Long roomId ); @@ -68,7 +69,7 @@ void deleteDebateRoom(@Parameter(in = ParameterIn.PATH, description = "토론방 responseCode = "201", description = "Created" ) - void saveHumanDebateMessage( + SuccessResponse saveHumanDebateMessage( @Parameter(in = ParameterIn.PATH, description = "토론방 ID", required = true) Long roomId, @@ -85,7 +86,7 @@ void saveHumanDebateMessage( responseCode = "201", description = "Created" ) - void saveAIDebateMessage( + SuccessResponse saveAIDebateMessage( @Parameter(in = ParameterIn.PATH, description = "토론방 ID", required = true) Long roomId, @@ -108,7 +109,7 @@ void saveAIDebateMessage( description = "토론방을 찾지 못했습니다." ) }) - void finishDebate( + SuccessResponse finishDebate( @Parameter(in = ParameterIn.PATH, description = "토론방 ID", required = true) Long roomId ); @@ -123,7 +124,7 @@ void finishDebate( responseCode = "200", description = "요청에 성공하였습니다." ) - List getDebateMessages( + SuccessResponse> getDebateMessages( @Parameter(in = ParameterIn.PATH, description = "토론방 ID", required = true) Long roomId ); @@ -144,7 +145,7 @@ List getDebateMessages( description = "토론방을 찾지 못했습니다." ) }) - DebateSummaryResponse summarizeDebate( + SuccessResponse summarizeDebate( @Parameter(in = ParameterIn.PATH, description = "토론방 ID", required = true) Long roomId ); @@ -165,7 +166,7 @@ DebateSummaryResponse summarizeDebate( description = "토론방을 찾지 못했습니다." ) }) - DebateSummaryResponse getSummarizedDebate( + SuccessResponse getSummarizedDebate( @Parameter(in = ParameterIn.PATH, description = "토론방 ID", required = true) Long roomId ); diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/api/DebateController.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/api/DebateController.java index 9c5863aa..e43c256e 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/api/DebateController.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/api/DebateController.java @@ -8,6 +8,7 @@ import com.rollthedice.backend.domain.debate.dto.response.DebateSummaryResponse; import com.rollthedice.backend.domain.debate.service.DebateMessageService; import com.rollthedice.backend.domain.debate.service.DebateRoomService; +import com.rollthedice.backend.global.common.response.SuccessResponse; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; @@ -16,6 +17,8 @@ import java.util.List; +import static com.rollthedice.backend.global.common.response.SuccessCode.*; + @RestController @RequiredArgsConstructor @RequestMapping("debates") @@ -26,62 +29,71 @@ public class DebateController implements DebateApi { @ResponseStatus(HttpStatus.CREATED) @PostMapping("") @Override - public DebateRoomSaveResponse saveDebateRoom(@RequestBody @Valid final DebateRoomRequest request) { - return debateRoomService.saveDebateRoom(request); + public SuccessResponse saveDebateRoom(@RequestBody @Valid final DebateRoomRequest request) { + DebateRoomSaveResponse response = debateRoomService.saveDebateRoom(request); + return SuccessResponse.of(CREATE_DEBATE_ROOM_SUCCESS, response); } @ResponseStatus(HttpStatus.OK) @GetMapping("") @Override - public List getDebateRooms(final Pageable pageable) { - return debateRoomService.getDebateRooms(pageable); + public SuccessResponse> getDebateRooms(final Pageable pageable) { + List response = debateRoomService.getDebateRooms(pageable); + return SuccessResponse.of(GET_ALL_DEBATE_ROOM_SUCCESS, response); } @ResponseStatus(HttpStatus.NO_CONTENT) @DeleteMapping("/{roomId}") @Override - public void deleteDebateRoom(@PathVariable final Long roomId) { + public SuccessResponse deleteDebateRoom(@PathVariable final Long roomId) { debateRoomService.deleteDebateRoom(roomId); + return SuccessResponse.of(DELETE_DEBATE_ROOM_SUCCESS); } @ResponseStatus(HttpStatus.CREATED) @PostMapping("/{roomId}/human") @Override - public void saveHumanDebateMessage(@PathVariable final Long roomId, @RequestBody final DebateMessageRequest request) { + public SuccessResponse saveHumanDebateMessage(@PathVariable final Long roomId, @RequestBody final DebateMessageRequest request) { debateMessageService.saveHumanDebateMessage(roomId, request); + return SuccessResponse.of(CREATE_HUMAN_DEBATE_MESSAGE_SUCCESS); } @ResponseStatus(HttpStatus.CREATED) @PostMapping("/{roomId}/ai") @Override - public void saveAIDebateMessage(@PathVariable final Long roomId, @RequestBody final DebateMessageRequest request) { + public SuccessResponse saveAIDebateMessage(@PathVariable final Long roomId, @RequestBody final DebateMessageRequest request) { debateMessageService.saveAIDebateMessage(roomId, request); + return SuccessResponse.of(CREATE_AI_DEBATE_MESSAGE_SUCCESS); } @ResponseStatus(HttpStatus.NO_CONTENT) @PatchMapping("/{roomId}") - public void finishDebate(@PathVariable final Long roomId) { + public SuccessResponse finishDebate(@PathVariable final Long roomId) { debateRoomService.closeDebate(roomId); + return SuccessResponse.of(UPDATE_DEBATE_ROOM_IS_CLOSED_SUCCESS); } - @ResponseStatus(HttpStatus.CREATED) + @ResponseStatus(HttpStatus.OK) @GetMapping("/{roomId}") @Override - public List getDebateMessages(@PathVariable final Long roomId) { - return debateMessageService.getDebateMessages(roomId); + public SuccessResponse> getDebateMessages(@PathVariable final Long roomId) { + List response = debateMessageService.getDebateMessages(roomId); + return SuccessResponse.of(GET_DEBATE_MESSAGES_SUCCESS, response); } - @ResponseStatus(HttpStatus.OK) + @ResponseStatus(HttpStatus.CREATED) @PostMapping("/summary/{roomId}") @Override - public DebateSummaryResponse summarizeDebate(@PathVariable final Long roomId) { - return debateRoomService.summaryDebate(roomId); + public SuccessResponse summarizeDebate(@PathVariable final Long roomId) { + DebateSummaryResponse response = debateRoomService.summaryDebate(roomId); + return SuccessResponse.of(CREATE_DEBATE_SUMMARY_SUCCESS, response); } @ResponseStatus(HttpStatus.OK) @GetMapping("/summary/{roomId}") @Override - public DebateSummaryResponse getSummarizedDebate(@PathVariable final Long roomId) { - return debateRoomService.getSummarizedDebate(roomId); + public SuccessResponse getSummarizedDebate(@PathVariable final Long roomId) { + DebateSummaryResponse response = debateRoomService.getSummarizedDebate(roomId); + return SuccessResponse.of(GET_DEBATE_MESSAGES_SUCCESS, response); } } diff --git a/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java b/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java index e7911554..ac21abd5 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java +++ b/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java @@ -12,6 +12,16 @@ public enum SuccessCode { CREATE_BOOKMARK_SUCCESS(201, "북마크 저장에 성공했습니다."), DELETE_BOOKMARK_SUCCESS(204, "북마크 삭제에 성공했습니다."), + // debate + CREATE_DEBATE_ROOM_SUCCESS(201, "토론방 생성에 성공했습니다."), + GET_ALL_DEBATE_ROOM_SUCCESS(200, "토론방 전체 조회에 성공했습니다"), + DELETE_DEBATE_ROOM_SUCCESS(204, "토론방 삭제에 성공했습니다."), + CREATE_HUMAN_DEBATE_MESSAGE_SUCCESS(201, "사용자가 보낸 토론 메세지 저장에 성공했습니다."), + CREATE_AI_DEBATE_MESSAGE_SUCCESS(201, "AI가 보낸 토론 메세지 저장에 성공했습니다."), + UPDATE_DEBATE_ROOM_IS_CLOSED_SUCCESS(204, "토론 종료에 성공했습니다."), + GET_DEBATE_MESSAGES_SUCCESS(200, "토론 메세지 조회에 성공했습니다."), + CREATE_DEBATE_SUMMARY_SUCCESS(201, "토론 요약에 성공했습니다."), + GET_DEBATE_SUMMARY_SUCCESS(200, "토론 요약 조회에 성공했습니다."), ; private final int status; From cebd6bfd96e79844ef1adfcdb701fda36c00f5b3 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Sun, 30 Jun 2024 18:20:00 +0900 Subject: [PATCH 54/61] =?UTF-8?q?feat:=20Member=20API=EC=97=90=20Success?= =?UTF-8?q?=20Response=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/member/api/MemberApi.java | 3 ++- .../backend/domain/member/api/MemberController.java | 12 ++++++------ .../backend/global/common/response/SuccessCode.java | 4 ++++ 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/member/api/MemberApi.java b/backend/core/src/main/java/com/rollthedice/backend/domain/member/api/MemberApi.java index 3f87ce34..273ade92 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/member/api/MemberApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/member/api/MemberApi.java @@ -1,6 +1,7 @@ package com.rollthedice.backend.domain.member.api; import com.rollthedice.backend.domain.member.dto.response.MemberResponse; +import com.rollthedice.backend.global.common.response.SuccessResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; @@ -16,5 +17,5 @@ public interface MemberApi { responseCode = "200", description = "OK" ) - MemberResponse getMemberInfo(); + SuccessResponse getMemberInfo(); } diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/member/api/MemberController.java b/backend/core/src/main/java/com/rollthedice/backend/domain/member/api/MemberController.java index 63411b19..d625e588 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/member/api/MemberController.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/member/api/MemberController.java @@ -1,15 +1,14 @@ package com.rollthedice.backend.domain.member.api; -import com.rollthedice.backend.domain.member.dto.MemberServiceDto; -import com.rollthedice.backend.domain.member.dto.MemberUpdateDto; import com.rollthedice.backend.domain.member.dto.response.MemberResponse; import com.rollthedice.backend.domain.member.service.MemberService; -import com.rollthedice.backend.global.annotation.LoginMemberEmail; +import com.rollthedice.backend.global.common.response.SuccessResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import static com.rollthedice.backend.global.common.response.SuccessCode.GET_MEMBER_INFO_SUCCESS; + @RestController @RequiredArgsConstructor @RequestMapping("members") @@ -19,7 +18,8 @@ public class MemberController implements MemberApi{ @ResponseStatus(HttpStatus.OK) @GetMapping("") @Override - public MemberResponse getMemberInfo() { - return memberService.getMemberInfo(); + public SuccessResponse getMemberInfo() { + MemberResponse response = memberService.getMemberInfo(); + return SuccessResponse.of(GET_MEMBER_INFO_SUCCESS, response); } } diff --git a/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java b/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java index ac21abd5..d7f5105d 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java +++ b/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java @@ -22,6 +22,10 @@ public enum SuccessCode { GET_DEBATE_MESSAGES_SUCCESS(200, "토론 메세지 조회에 성공했습니다."), CREATE_DEBATE_SUMMARY_SUCCESS(201, "토론 요약에 성공했습니다."), GET_DEBATE_SUMMARY_SUCCESS(200, "토론 요약 조회에 성공했습니다."), + + // member + GET_MEMBER_INFO_SUCCESS(200, "사용자 정보 조회에 성공했습니다."), + ; private final int status; From 107726b61776a4dffa0f326aaa39941e3231ec67 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Sun, 30 Jun 2024 18:23:34 +0900 Subject: [PATCH 55/61] =?UTF-8?q?feat:=20News=20API=EC=97=90=20Success=20R?= =?UTF-8?q?esponse=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/news/api/NewsApi.java | 5 +++-- .../backend/domain/news/api/NewsController.java | 14 ++++++++++---- .../global/common/response/SuccessCode.java | 4 ++++ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsApi.java b/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsApi.java index a152eebc..5cc4c906 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsApi.java @@ -3,6 +3,7 @@ import com.rollthedice.backend.domain.news.dto.response.NewsDetailResponse; import com.rollthedice.backend.domain.news.dto.response.NewsResponse; import com.rollthedice.backend.domain.news.dto.response.ReadNewsResponse; +import com.rollthedice.backend.global.common.response.SuccessResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; @@ -24,7 +25,7 @@ public interface NewsApi { responseCode = "200", description = "요청에 성공하였습니다." ) - List getNews(Pageable pageable); + SuccessResponse> getNews(Pageable pageable); @Operation( summary = "요약 뉴스 상세 조회", @@ -42,7 +43,7 @@ public interface NewsApi { description = "뉴스를 찾지 못했습니다." ) }) - NewsDetailResponse getDetailNews( + SuccessResponse getDetailNews( @Parameter(in = ParameterIn.PATH, description = "뉴스 ID", required = true) Long newsId ); diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsController.java b/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsController.java index 84407564..977d1922 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsController.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsController.java @@ -3,6 +3,7 @@ import com.rollthedice.backend.domain.news.dto.response.NewsDetailResponse; import com.rollthedice.backend.domain.news.dto.response.NewsResponse; import com.rollthedice.backend.domain.news.service.NewsService; +import com.rollthedice.backend.global.common.response.SuccessResponse; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; @@ -10,6 +11,9 @@ import java.util.List; +import static com.rollthedice.backend.global.common.response.SuccessCode.GET_ALL_NEWS_SUCCESS; +import static com.rollthedice.backend.global.common.response.SuccessCode.GET_DETAIL_NEWS_SUCCESS; + @RestController @RequiredArgsConstructor @RequestMapping("news") @@ -19,14 +23,16 @@ public class NewsController implements NewsApi { @ResponseStatus(HttpStatus.OK) @GetMapping("") @Override - public List getNews(final Pageable pageable) { - return newsService.getNews(pageable); + public SuccessResponse> getNews(final Pageable pageable) { + List response = newsService.getNews(pageable); + return SuccessResponse.of(GET_ALL_NEWS_SUCCESS, response); } @ResponseStatus(HttpStatus.OK) @GetMapping("/{newsId}") @Override - public NewsDetailResponse getDetailNews(final @PathVariable Long newsId) { - return newsService.getDetailNews(newsId); + public SuccessResponse getDetailNews(final @PathVariable Long newsId) { + NewsDetailResponse response = newsService.getDetailNews(newsId); + return SuccessResponse.of(GET_DETAIL_NEWS_SUCCESS, response); } } diff --git a/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java b/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java index d7f5105d..d7cae1cb 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java +++ b/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java @@ -26,6 +26,10 @@ public enum SuccessCode { // member GET_MEMBER_INFO_SUCCESS(200, "사용자 정보 조회에 성공했습니다."), + // news + GET_ALL_NEWS_SUCCESS(200, "전체 뉴스 조회에 성공했습니다."), + GET_DETAIL_NEWS_SUCCESS(200, "요약 뉴스 상세 조회에 성공했습니다."), + ; private final int status; From d94fb91a3ed38b9dfb03342fa7b5fb472a1faeb7 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Sun, 30 Jun 2024 18:26:40 +0900 Subject: [PATCH 56/61] =?UTF-8?q?feat:=20ReadNews=20API=EC=97=90=20Success?= =?UTF-8?q?=20Response=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/readNews/api/ReadNewsApi.java | 3 ++- .../backend/domain/readNews/api/ReadNewsController.java | 8 ++++++-- .../backend/global/common/response/SuccessCode.java | 3 +++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/readNews/api/ReadNewsApi.java b/backend/core/src/main/java/com/rollthedice/backend/domain/readNews/api/ReadNewsApi.java index 59aff96e..d8e86ce0 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/readNews/api/ReadNewsApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/readNews/api/ReadNewsApi.java @@ -1,6 +1,7 @@ package com.rollthedice.backend.domain.readNews.api; import com.rollthedice.backend.domain.news.dto.response.ReadNewsResponse; +import com.rollthedice.backend.global.common.response.SuccessResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; @@ -18,5 +19,5 @@ public interface ReadNewsApi { responseCode = "200", description = "요청에 성공하였습니다." ) - List getReadNews(); + SuccessResponse> getReadNews(); } diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/readNews/api/ReadNewsController.java b/backend/core/src/main/java/com/rollthedice/backend/domain/readNews/api/ReadNewsController.java index e32da2b7..67d02ed2 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/readNews/api/ReadNewsController.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/readNews/api/ReadNewsController.java @@ -2,6 +2,7 @@ import com.rollthedice.backend.domain.news.dto.response.ReadNewsResponse; import com.rollthedice.backend.domain.readNews.service.ReadNewsService; +import com.rollthedice.backend.global.common.response.SuccessResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; @@ -11,6 +12,8 @@ import java.util.List; +import static com.rollthedice.backend.global.common.response.SuccessCode.GET_RECENT_READ_NEWS_SUCCESS; + @RestController @RequiredArgsConstructor @RequestMapping("read-news") @@ -21,7 +24,8 @@ public class ReadNewsController implements ReadNewsApi { @ResponseStatus(HttpStatus.OK) @GetMapping("/viewed-history") @Override - public List getReadNews() { - return readNewsService.getReadNews(); + public SuccessResponse> getReadNews() { + List response = readNewsService.getReadNews(); + return SuccessResponse.of(GET_RECENT_READ_NEWS_SUCCESS, response); } } diff --git a/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java b/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java index d7cae1cb..d22af479 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java +++ b/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java @@ -30,6 +30,9 @@ public enum SuccessCode { GET_ALL_NEWS_SUCCESS(200, "전체 뉴스 조회에 성공했습니다."), GET_DETAIL_NEWS_SUCCESS(200, "요약 뉴스 상세 조회에 성공했습니다."), + // read news + GET_RECENT_READ_NEWS_SUCCESS(200, "최근 읽은 뉴스 조회에 성공했습니다."), + ; private final int status; From e33a25e2dc4c6cf754b6dee8ea66e644283ae018 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Sun, 30 Jun 2024 18:32:22 +0900 Subject: [PATCH 57/61] =?UTF-8?q?feat:=20Statistics=20API=EC=97=90=20Succe?= =?UTF-8?q?ss=20Response=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/statistics/api/StatisticsApi.java | 5 +++-- .../statistics/api/StatisticsController.java | 14 ++++++++++---- .../global/common/response/SuccessCode.java | 3 +++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsApi.java b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsApi.java index 6866c2bb..04993f4b 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsApi.java @@ -2,6 +2,7 @@ import com.rollthedice.backend.domain.statistics.dto.response.CategoryStatisticsResponse; import com.rollthedice.backend.domain.statistics.dto.response.DateViewStatisticsResponse; +import com.rollthedice.backend.global.common.response.SuccessResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; @@ -19,7 +20,7 @@ public interface StatisticsApi { responseCode = "200", description = "요청에 성공하였습니다." ) - List getViewsOfDates(); + SuccessResponse> getViewsOfDates(); @Operation( summary = "카테고리별 조회수 조회", @@ -31,5 +32,5 @@ public interface StatisticsApi { responseCode = "200", description = "요청에 성공하였습니다." ) - List getCategoryStatistics(); + SuccessResponse> getCategoryStatistics(); } diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsController.java b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsController.java index 8dc19f3d..14634964 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsController.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsController.java @@ -3,6 +3,7 @@ import com.rollthedice.backend.domain.statistics.dto.response.CategoryStatisticsResponse; import com.rollthedice.backend.domain.statistics.dto.response.DateViewStatisticsResponse; import com.rollthedice.backend.domain.statistics.service.StatisticsService; +import com.rollthedice.backend.global.common.response.SuccessResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; @@ -12,6 +13,9 @@ import java.util.List; +import static com.rollthedice.backend.global.common.response.SuccessCode.GET_CATEGORY_VIEWS_SUCCESS; +import static com.rollthedice.backend.global.common.response.SuccessCode.GET_VIEWS_OF_DATE_SUCCESS; + @RestController @RequiredArgsConstructor @RequestMapping("statistics") @@ -21,14 +25,16 @@ public class StatisticsController implements StatisticsApi { @ResponseStatus(HttpStatus.OK) @GetMapping("/per-dates") @Override - public List getViewsOfDates() { - return statisticsService.getViewsOfDates(); + public SuccessResponse> getViewsOfDates() { + List response = statisticsService.getViewsOfDates(); + return SuccessResponse.of(GET_VIEWS_OF_DATE_SUCCESS, response); } @ResponseStatus(HttpStatus.OK) @GetMapping("/categories") @Override - public List getCategoryStatistics() { - return statisticsService.getCategoryStatistics(); + public SuccessResponse> getCategoryStatistics() { + List response = statisticsService.getCategoryStatistics(); + return SuccessResponse.of(GET_CATEGORY_VIEWS_SUCCESS, response); } } diff --git a/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java b/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java index d22af479..dfb73283 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java +++ b/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java @@ -33,6 +33,9 @@ public enum SuccessCode { // read news GET_RECENT_READ_NEWS_SUCCESS(200, "최근 읽은 뉴스 조회에 성공했습니다."), + // statistics + GET_VIEWS_OF_DATE_SUCCESS(200, "최근 일주일 날짜별 뉴스 조회수 조회에 성공했습니다."), + GET_CATEGORY_VIEWS_SUCCESS(200, "카테고리별 조회수 조회에 성공했습니다."), ; private final int status; From 7c4567db107763a4368b927a6f33e5755b83fba0 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Sun, 30 Jun 2024 18:39:53 +0900 Subject: [PATCH 58/61] =?UTF-8?q?feat:=20Auth=20API=EC=97=90=20Success=20R?= =?UTF-8?q?esponse=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/common/response/SuccessCode.java | 4 ++++ .../backend/global/oauth2/api/AuthApi.java | 11 ++++++----- .../backend/global/oauth2/api/AuthController.java | 15 ++++++++++----- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java b/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java index dfb73283..0adb906f 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java +++ b/backend/core/src/main/java/com/rollthedice/backend/global/common/response/SuccessCode.java @@ -36,6 +36,10 @@ public enum SuccessCode { // statistics GET_VIEWS_OF_DATE_SUCCESS(200, "최근 일주일 날짜별 뉴스 조회수 조회에 성공했습니다."), GET_CATEGORY_VIEWS_SUCCESS(200, "카테고리별 조회수 조회에 성공했습니다."), + + // auth + GET_SOCIAL_LOGIN_SUCCESS(201, "소셜 로그인에 성공했습니다."), + UPDATE_NICKNAME_SUCCESS(204, "닉네임 입력에 성공했습니다.") ; private final int status; diff --git a/backend/core/src/main/java/com/rollthedice/backend/global/oauth2/api/AuthApi.java b/backend/core/src/main/java/com/rollthedice/backend/global/oauth2/api/AuthApi.java index b8528389..042de62c 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/global/oauth2/api/AuthApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/global/oauth2/api/AuthApi.java @@ -1,6 +1,7 @@ package com.rollthedice.backend.global.oauth2.api; import com.rollthedice.backend.domain.member.dto.MemberUpdateDto; +import com.rollthedice.backend.global.common.response.SuccessResponse; import com.rollthedice.backend.global.oauth2.dto.LoginRequest; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -18,10 +19,10 @@ public interface AuthApi { tags = {"인증"} ) @ApiResponse( - responseCode = "201", - description = "Created" + responseCode = "200", + description = "소셜 로그인에 성공했습니다." ) - ResponseEntity login( + SuccessResponse login( @RequestBody LoginRequest request, HttpServletResponse response ); @@ -34,9 +35,9 @@ ResponseEntity login( ) @ApiResponse( responseCode = "201", - description = "Created" + description = "닉네임 입력에 성공했습니다." ) - ResponseEntity updateMember( + SuccessResponse updateMember( String email, @RequestBody MemberUpdateDto memberUpdateDto ); diff --git a/backend/core/src/main/java/com/rollthedice/backend/global/oauth2/api/AuthController.java b/backend/core/src/main/java/com/rollthedice/backend/global/oauth2/api/AuthController.java index dad5b0f7..27ba7e0a 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/global/oauth2/api/AuthController.java +++ b/backend/core/src/main/java/com/rollthedice/backend/global/oauth2/api/AuthController.java @@ -3,6 +3,7 @@ import com.rollthedice.backend.domain.member.dto.MemberUpdateDto; import com.rollthedice.backend.domain.member.service.MemberService; import com.rollthedice.backend.global.annotation.LoginMemberEmail; +import com.rollthedice.backend.global.common.response.SuccessResponse; import com.rollthedice.backend.global.oauth2.dto.LoginRequest; import com.rollthedice.backend.global.oauth2.service.AuthService; import jakarta.servlet.http.HttpServletResponse; @@ -12,8 +13,12 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; +import static com.rollthedice.backend.global.common.response.SuccessCode.GET_SOCIAL_LOGIN_SUCCESS; +import static com.rollthedice.backend.global.common.response.SuccessCode.UPDATE_NICKNAME_SUCCESS; + @Slf4j @RestController @RequiredArgsConstructor @@ -21,20 +26,20 @@ public class AuthController implements AuthApi { private final AuthService authService; private final MemberService memberService; + @ResponseStatus(HttpStatus.OK) @PostMapping("/login") @Override - public ResponseEntity login(@RequestBody LoginRequest request, HttpServletResponse response) { + public SuccessResponse login(@RequestBody LoginRequest request, HttpServletResponse response) { authService.authenticateOrRegisterUser(request, response); - return new ResponseEntity<>(HttpStatus.OK); + return SuccessResponse.of(GET_SOCIAL_LOGIN_SUCCESS); } @PostMapping("/oauth2/sign-up") @Override - public ResponseEntity updateMember(@LoginMemberEmail String email, + public SuccessResponse updateMember(@LoginMemberEmail String email, @RequestBody MemberUpdateDto memberUpdateDto) { memberService.update(memberUpdateDto); - - return ResponseEntity.status(HttpStatus.OK).build(); + return SuccessResponse.of(UPDATE_NICKNAME_SUCCESS); } } \ No newline at end of file From 86c8b0a3db945427e2b88e1c7bc2c877258b54e8 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Sun, 30 Jun 2024 18:45:09 +0900 Subject: [PATCH 59/61] =?UTF-8?q?feat:=20success=20message=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 --- .../domain/bookmark/api/BookmarkApi.java | 8 ++++---- .../backend/domain/debate/api/DebateApi.java | 18 +++++++++--------- .../backend/domain/member/api/MemberApi.java | 2 +- .../backend/domain/news/api/NewsApi.java | 4 ++-- .../domain/readNews/api/ReadNewsApi.java | 2 +- .../domain/statistics/api/StatisticsApi.java | 4 ++-- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/bookmark/api/BookmarkApi.java b/backend/core/src/main/java/com/rollthedice/backend/domain/bookmark/api/BookmarkApi.java index e8afb307..7eff090b 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/bookmark/api/BookmarkApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/bookmark/api/BookmarkApi.java @@ -21,7 +21,7 @@ public interface BookmarkApi { ) @ApiResponse( responseCode = "200", - description = "OK" + description = "북마크 전체 조회를 성공했습니다." ) SuccessResponse> getAllBookmarkedNews( Pageable pageable @@ -35,7 +35,7 @@ SuccessResponse> getAllBookmarkedNews( ) @ApiResponse( responseCode = "200", - description = "OK" + description = "뉴스가 북마크 여부 조회를 성공했습니다." ) SuccessResponse getIsBookmarked( @Parameter(in = ParameterIn.PATH, description = "뉴스 ID", required = true) @@ -51,7 +51,7 @@ SuccessResponse getIsBookmarked( ) @ApiResponse( responseCode = "201", - description = "Created" + description = "북마크 저장에 성공했습니다." ) SuccessResponse saveBookmark( @Parameter(in = ParameterIn.PATH, description = "뉴스 ID", required = true) @@ -66,7 +66,7 @@ SuccessResponse saveBookmark( ) @ApiResponse( responseCode = "204", - description = "No Content" + description = "북마크 삭제에 성공했습니다." ) SuccessResponse deleteBookmark( @Parameter(in = ParameterIn.PATH, description = "뉴스 ID", required = true) diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/api/DebateApi.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/api/DebateApi.java index b61ada20..f1093280 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/api/DebateApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/api/DebateApi.java @@ -29,7 +29,7 @@ public interface DebateApi { ) @ApiResponse( responseCode = "201", - description = "Created" + description = "토론방 생성에 성공했습니다." ) SuccessResponse saveDebateRoom(@RequestBody DebateRoomRequest request); @@ -41,7 +41,7 @@ public interface DebateApi { ) @ApiResponse( responseCode = "200", - description = "요청에 성공하였습니다." + description = "토론방 전체 조회에 성공했습니다" ) SuccessResponse> getDebateRooms(Pageable pageable); @@ -53,7 +53,7 @@ public interface DebateApi { ) @ApiResponse( responseCode = "204", - description = "토론방 삭제에 성공하였으며, 응답값은 없습니다." + description = "토론방 삭제에 성공했습니다." ) SuccessResponse deleteDebateRoom(@Parameter(in = ParameterIn.PATH, description = "토론방 ID", required = true) Long roomId @@ -67,7 +67,7 @@ SuccessResponse deleteDebateRoom(@Parameter(in = ParameterIn.PATH, descr ) @ApiResponse( responseCode = "201", - description = "Created" + description = "사용자가 보낸 토론 메세지 저장에 성공했습니다." ) SuccessResponse saveHumanDebateMessage( @Parameter(in = ParameterIn.PATH, description = "토론방 ID", required = true) @@ -84,7 +84,7 @@ SuccessResponse saveHumanDebateMessage( ) @ApiResponse( responseCode = "201", - description = "Created" + description = "AI가 보낸 토론 메세지 저장에 성공했습니다." ) SuccessResponse saveAIDebateMessage( @Parameter(in = ParameterIn.PATH, description = "토론방 ID", required = true) @@ -102,7 +102,7 @@ SuccessResponse saveAIDebateMessage( @ApiResponses(value = { @ApiResponse( responseCode = "204", - description = "요청에 성공하였으며 응답값은 없습니다." + description = "토론 종료에 성공했습니다." ), @ApiResponse( responseCode = "404", @@ -122,7 +122,7 @@ SuccessResponse finishDebate( ) @ApiResponse( responseCode = "200", - description = "요청에 성공하였습니다." + description = "토론 메세지 조회에 성공했습니다." ) SuccessResponse> getDebateMessages( @Parameter(in = ParameterIn.PATH, description = "토론방 ID", required = true) @@ -138,7 +138,7 @@ SuccessResponse> getDebateMessages( @ApiResponses(value = { @ApiResponse( responseCode = "201", - description = "토론 요약이 성공하였습니다." + description = "토론 요약에 성공했습니다." ), @ApiResponse( responseCode = "404", @@ -159,7 +159,7 @@ SuccessResponse summarizeDebate( @ApiResponses(value = { @ApiResponse( responseCode = "200", - description = "요청에 성공하였습니다." + description = "토론 요약 조회에 성공했습니다." ), @ApiResponse( responseCode = "404", diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/member/api/MemberApi.java b/backend/core/src/main/java/com/rollthedice/backend/domain/member/api/MemberApi.java index 273ade92..fcb8ad10 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/member/api/MemberApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/member/api/MemberApi.java @@ -15,7 +15,7 @@ public interface MemberApi { ) @ApiResponse( responseCode = "200", - description = "OK" + description = "사용자 정보 조회에 성공했습니다." ) SuccessResponse getMemberInfo(); } diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsApi.java b/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsApi.java index 5cc4c906..78b8356b 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsApi.java @@ -23,7 +23,7 @@ public interface NewsApi { ) @ApiResponse( responseCode = "200", - description = "요청에 성공하였습니다." + description = "전체 뉴스 조회에 성공했습니다." ) SuccessResponse> getNews(Pageable pageable); @@ -36,7 +36,7 @@ public interface NewsApi { @ApiResponses(value = { @ApiResponse( responseCode = "200", - description = "요청에 성공하였습니다." + description = "요약 뉴스 상세 조회에 성공했습니다." ), @ApiResponse( responseCode = "404", diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/readNews/api/ReadNewsApi.java b/backend/core/src/main/java/com/rollthedice/backend/domain/readNews/api/ReadNewsApi.java index d8e86ce0..d52f7065 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/readNews/api/ReadNewsApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/readNews/api/ReadNewsApi.java @@ -17,7 +17,7 @@ public interface ReadNewsApi { ) @ApiResponse( responseCode = "200", - description = "요청에 성공하였습니다." + description = "최근 읽은 뉴스 조회에 성공했습니다." ) SuccessResponse> getReadNews(); } diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsApi.java b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsApi.java index 04993f4b..80066ddc 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsApi.java @@ -18,7 +18,7 @@ public interface StatisticsApi { ) @ApiResponse( responseCode = "200", - description = "요청에 성공하였습니다." + description = "최근 일주일 날짜별 뉴스 조회수 조회에 성공했습니다." ) SuccessResponse> getViewsOfDates(); @@ -30,7 +30,7 @@ public interface StatisticsApi { ) @ApiResponse( responseCode = "200", - description = "요청에 성공하였습니다." + description = "카테고리별 조회수 조회에 성공했습니다." ) SuccessResponse> getCategoryStatistics(); } From 79686b88da94784dc97fe3feae241b9f26b01c62 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Sun, 30 Jun 2024 18:51:09 +0900 Subject: [PATCH 60/61] refactor: swagger tags -> @Tag --- .../domain/bookmark/api/BookmarkApi.java | 14 ++++----- .../backend/domain/debate/api/DebateApi.java | 31 +++++++------------ .../backend/domain/member/api/MemberApi.java | 5 +-- .../backend/domain/news/api/NewsApi.java | 8 ++--- .../domain/readNews/api/ReadNewsApi.java | 5 +-- .../domain/statistics/api/StatisticsApi.java | 8 ++--- .../backend/global/oauth2/api/AuthApi.java | 8 ++--- 7 files changed, 35 insertions(+), 44 deletions(-) diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/bookmark/api/BookmarkApi.java b/backend/core/src/main/java/com/rollthedice/backend/domain/bookmark/api/BookmarkApi.java index 7eff090b..3b0e9760 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/bookmark/api/BookmarkApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/bookmark/api/BookmarkApi.java @@ -8,16 +8,17 @@ import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.data.domain.Pageable; import java.util.List; +@Tag(name = "Bookmark") public interface BookmarkApi { @Operation( summary = "북마크 전체 조회", description = "회원이 북마크한 뉴스를 페이지로 나누어 조회합니다.", - security = {@SecurityRequirement(name = "access_token")}, - tags = {"북마크"} + security = {@SecurityRequirement(name = "access_token")} ) @ApiResponse( responseCode = "200", @@ -30,8 +31,7 @@ SuccessResponse> getAllBookmarkedNews( @Operation( summary = "뉴스 북마크 여부 조회", description = "로그인한 회원이 해당 뉴스를 북마크 했는지 여부를 조회합니다.", - security = {@SecurityRequirement(name = "access_token")}, - tags = {"북마크"} + security = {@SecurityRequirement(name = "access_token")} ) @ApiResponse( responseCode = "200", @@ -46,8 +46,7 @@ SuccessResponse getIsBookmarked( @Operation( summary = "북마크 저장", description = "뉴스에 대하여 북마크로 저장합니다.", - security = {@SecurityRequirement(name = "access_token")}, - tags = {"북마크"} + security = {@SecurityRequirement(name = "access_token")} ) @ApiResponse( responseCode = "201", @@ -61,8 +60,7 @@ SuccessResponse saveBookmark( @Operation( summary = "북마크 삭제", description = "저장된 북마크를 해제합니다.", - security = {@SecurityRequirement(name = "access_token")}, - tags = {"북마크"} + security = {@SecurityRequirement(name = "access_token")} ) @ApiResponse( responseCode = "204", diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/api/DebateApi.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/api/DebateApi.java index f1093280..8c808f47 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/api/DebateApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/api/DebateApi.java @@ -13,19 +13,19 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.data.domain.Pageable; import org.springframework.web.bind.annotation.RequestBody; import java.util.List; - +@Tag(name = "Debate") public interface DebateApi { @Operation( summary = "토론방 생성", description = "주제가 선택된 토론방을 생성합니다.", - security = {@SecurityRequirement(name = "access_token")}, - tags = {"토론방"} + security = {@SecurityRequirement(name = "access_token")} ) @ApiResponse( responseCode = "201", @@ -36,8 +36,7 @@ public interface DebateApi { @Operation( summary = "토론방 전체 조회", description = "회원의 토론방을 페이지로 나누어 조회합니다.", - security = {@SecurityRequirement(name = "access_token")}, - tags = {"토론방"} + security = {@SecurityRequirement(name = "access_token")} ) @ApiResponse( responseCode = "200", @@ -48,8 +47,7 @@ public interface DebateApi { @Operation( summary = "토론방 삭제", description = "토론방을 삭제합니다.", - security = {@SecurityRequirement(name = "access_token")}, - tags = {"토론방"} + security = {@SecurityRequirement(name = "access_token")} ) @ApiResponse( responseCode = "204", @@ -62,8 +60,7 @@ SuccessResponse deleteDebateRoom(@Parameter(in = ParameterIn.PATH, descr @Operation( summary = "[인간] 토론 메세지 저장", description = "사용자가 보낸 토론 메세지를 저장합니다.", - security = {@SecurityRequirement(name = "access_token")}, - tags = {"토론 메세지"} + security = {@SecurityRequirement(name = "access_token")} ) @ApiResponse( responseCode = "201", @@ -79,8 +76,7 @@ SuccessResponse saveHumanDebateMessage( @Operation( summary = "[AI] 토론 메세지 저장", description = "ChatGPT OPENAI가 보낸 토론 메세지를 저장합니다.", - security = {@SecurityRequirement(name = "access_token")}, - tags = {"토론 메세지"} + security = {@SecurityRequirement(name = "access_token")} ) @ApiResponse( responseCode = "201", @@ -96,8 +92,7 @@ SuccessResponse saveAIDebateMessage( @Operation( summary = "토론 종료", description = "토론을 종료합니다.", - security = {@SecurityRequirement(name = "access_token")}, - tags = {"토론방"} + security = {@SecurityRequirement(name = "access_token")} ) @ApiResponses(value = { @ApiResponse( @@ -117,8 +112,7 @@ SuccessResponse finishDebate( @Operation( summary = "토론 메세지 조회", description = "토론방의 토론 메세지 이력을 조회합니다.", - security = {@SecurityRequirement(name = "access_token")}, - tags = {"토론 메세지"} + security = {@SecurityRequirement(name = "access_token")} ) @ApiResponse( responseCode = "200", @@ -132,8 +126,7 @@ SuccessResponse> getDebateMessages( @Operation( summary = "토론 요약", description = "토론방의 토론 메세지들을 요약합니다.", - security = {@SecurityRequirement(name = "access_token")}, - tags = {"토론방"} + security = {@SecurityRequirement(name = "access_token")} ) @ApiResponses(value = { @ApiResponse( @@ -153,8 +146,7 @@ SuccessResponse summarizeDebate( @Operation( summary = "토론 요약 조회", description = "토론 요약 내용을 조회합니다.", - security = {@SecurityRequirement(name = "access_token")}, - tags = {"토론방"} + security = {@SecurityRequirement(name = "access_token")} ) @ApiResponses(value = { @ApiResponse( @@ -170,5 +162,4 @@ SuccessResponse getSummarizedDebate( @Parameter(in = ParameterIn.PATH, description = "토론방 ID", required = true) Long roomId ); - } diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/member/api/MemberApi.java b/backend/core/src/main/java/com/rollthedice/backend/domain/member/api/MemberApi.java index fcb8ad10..3ebcc3ee 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/member/api/MemberApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/member/api/MemberApi.java @@ -5,13 +5,14 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +@Tag(name = "Member") public interface MemberApi { @Operation( summary = "회원 정보 조회", description = "회원 정보를 조회합니다.", - security = {@SecurityRequirement(name = "access_token")}, - tags = {"member"} + security = {@SecurityRequirement(name = "access_token")} ) @ApiResponse( responseCode = "200", diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsApi.java b/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsApi.java index 78b8356b..ccc2d8c8 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsApi.java @@ -10,16 +10,17 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.data.domain.Pageable; import java.util.List; +@Tag(name = "Tag") public interface NewsApi { @Operation( summary = "요약 뉴스 전체 조회", description = "요약 뉴스를 페이지로 나누어 조회합니다.", - security = {@SecurityRequirement(name = "access_token")}, - tags = {"news"} + security = {@SecurityRequirement(name = "access_token")} ) @ApiResponse( responseCode = "200", @@ -30,8 +31,7 @@ public interface NewsApi { @Operation( summary = "요약 뉴스 상세 조회", description = "하나의 요약 뉴스를 상세 조회합니다.", - security = {@SecurityRequirement(name = "access_token")}, - tags = {"news"} + security = {@SecurityRequirement(name = "access_token")} ) @ApiResponses(value = { @ApiResponse( diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/readNews/api/ReadNewsApi.java b/backend/core/src/main/java/com/rollthedice/backend/domain/readNews/api/ReadNewsApi.java index d52f7065..6279d7e8 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/readNews/api/ReadNewsApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/readNews/api/ReadNewsApi.java @@ -5,15 +5,16 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; import java.util.List; +@Tag(name = "Read News") public interface ReadNewsApi { @Operation( summary = "최근 읽은 뉴스 조회", description = "가장 최근에 읽은 3개의 뉴스를 조회합니다.", - security = {@SecurityRequirement(name = "access_token")}, - tags = {"news"} + security = {@SecurityRequirement(name = "access_token")} ) @ApiResponse( responseCode = "200", diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsApi.java b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsApi.java index 80066ddc..be7e86e7 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsApi.java @@ -6,15 +6,16 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; import java.util.List; +@Tag(name = "Statistics") public interface StatisticsApi { @Operation( summary = "최근 일주일 날짜별 뉴스 조회수 조회", description = "최근 일주일간 날짜별로 뉴스 조회수를 조회합니다.", - security = {@SecurityRequirement(name = "access_token")}, - tags = {"통계"} + security = {@SecurityRequirement(name = "access_token")} ) @ApiResponse( responseCode = "200", @@ -25,8 +26,7 @@ public interface StatisticsApi { @Operation( summary = "카테고리별 조회수 조회", description = "카테고리별 조회수를 조회합니다.", - security = {@SecurityRequirement(name = "access_token")}, - tags = {"통계"} + security = {@SecurityRequirement(name = "access_token")} ) @ApiResponse( responseCode = "200", diff --git a/backend/core/src/main/java/com/rollthedice/backend/global/oauth2/api/AuthApi.java b/backend/core/src/main/java/com/rollthedice/backend/global/oauth2/api/AuthApi.java index 042de62c..c9cabee7 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/global/oauth2/api/AuthApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/global/oauth2/api/AuthApi.java @@ -6,17 +6,18 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestBody; +@Tag(name = "Auth") public interface AuthApi { @Operation( summary = "소셜 로그인", description = "소셜 로그인을 합니다. 회원가입이 되어있지 않은 회원일 경우, 회원가입이 진행됩니다.", - security = {@SecurityRequirement(name = "access_token")}, - tags = {"인증"} + security = {@SecurityRequirement(name = "access_token")} ) @ApiResponse( responseCode = "200", @@ -30,8 +31,7 @@ SuccessResponse login( @Operation( summary = "닉네임 입력", description = "닉네임을 입력합니다. 해당 로직이 진행되어야 회원가입이 완료됩니다.", - security = {@SecurityRequirement(name = "access_token")}, - tags = {"인증"} + security = {@SecurityRequirement(name = "access_token")} ) @ApiResponse( responseCode = "201", From 43f02088d6de5c504b09e9f7e483cd21e5e296e0 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Sun, 30 Jun 2024 18:51:37 +0900 Subject: [PATCH 61/61] =?UTF-8?q?refactor:=20=ED=95=84=EC=9A=94=EC=97=86?= =?UTF-8?q?=EB=8A=94=20log=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/debate/service/ClovaSummary.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/service/ClovaSummary.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/service/ClovaSummary.java index 6f1b71d7..c4a2f3c9 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/service/ClovaSummary.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/service/ClovaSummary.java @@ -36,15 +36,12 @@ public class ClovaSummary { private String CLIENT_ID; public String summaryDebate(String messages) { - log.info("요약할 메세지: {}" ,messages); try { URL url = new URL(API_URL); HttpURLConnection connection = createRequestHeader(url); createRequestBody(connection, messages); - log.info("정상1"); StringBuilder response = getResponse(connection); - log.info("정상2"); return parseResponse(response); } catch (Exception e) { e.printStackTrace();