From 658cff20eb8da08ac4df5d1819394cda776537f3 Mon Sep 17 00:00:00 2001 From: Yu Sung Date: Wed, 27 Sep 2023 21:16:39 +0900 Subject: [PATCH] =?UTF-8?q?=ED=81=90=EB=A0=88=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=EB=B3=B4=EA=B8=B0=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SodaLive/Sources/App/AppStep.swift | 2 + SodaLive/Sources/Content/ContentApi.swift | 15 ++- .../Sources/Content/ContentRepository.swift | 4 + .../Curation/ContentCurationView.swift | 105 ++++++++++++++++++ .../Curation/ContentCurationViewModel.swift | 95 ++++++++++++++++ .../Curation/GetCurationContentResponse.swift | 11 ++ .../Main/ContentMainCurationItemView.swift | 8 +- .../Main/ContentMainCurationView.swift | 3 +- .../Main/GetAudioContentMainResponse.swift | 1 + SodaLive/Sources/ContentView.swift | 3 + 10 files changed, 243 insertions(+), 4 deletions(-) create mode 100644 SodaLive/Sources/Content/Curation/ContentCurationView.swift create mode 100644 SodaLive/Sources/Content/Curation/ContentCurationViewModel.swift create mode 100644 SodaLive/Sources/Content/Curation/GetCurationContentResponse.swift diff --git a/SodaLive/Sources/App/AppStep.swift b/SodaLive/Sources/App/AppStep.swift index e9579ca..46bc904 100644 --- a/SodaLive/Sources/App/AppStep.swift +++ b/SodaLive/Sources/App/AppStep.swift @@ -109,4 +109,6 @@ enum AppStep { case orderListAll case newContentAll + + case curationAll(title: String, curationId: Int) } diff --git a/SodaLive/Sources/Content/ContentApi.swift b/SodaLive/Sources/Content/ContentApi.swift index a4d6d47..d7b14de 100644 --- a/SodaLive/Sources/Content/ContentApi.swift +++ b/SodaLive/Sources/Content/ContentApi.swift @@ -28,6 +28,7 @@ enum ContentApi { case modifyComment(request: ModifyCommentRequest) case getNewContentThemeList case getNewContentAllOfTheme(theme: String, page: Int, size: Int) + case getAudioContentListByCurationId(curationId: Int, page: Int, size: Int, sort: ContentCurationViewModel.Sort) } extension ContentApi: TargetType { @@ -93,12 +94,15 @@ extension ContentApi: TargetType { case .getNewContentAllOfTheme: return "/audio-content/main/new/all" + + case .getAudioContentListByCurationId(let curationId, _, _, _): + return "/audio-content/curation/\(curationId)" } } var method: Moya.Method { switch self { - case .getAudioContentList, .getAudioContentDetail, .getOrderList, .getAudioContentThemeList, .getAudioContentCommentList, .getAudioContentCommentReplyList, .getMain, .getNewContentOfTheme, .getNewContentThemeList, .getNewContentAllOfTheme: + case .getAudioContentList, .getAudioContentDetail, .getOrderList, .getAudioContentThemeList, .getAudioContentCommentList, .getAudioContentCommentReplyList, .getMain, .getNewContentOfTheme, .getNewContentThemeList, .getNewContentAllOfTheme, .getAudioContentListByCurationId: return .get case .likeContent, .modifyAudioContent, .modifyComment: @@ -199,6 +203,15 @@ extension ContentApi: TargetType { "size": size ] as [String : Any] + return .requestParameters(parameters: parameters, encoding: URLEncoding.queryString) + + case .getAudioContentListByCurationId(_, let page, let size, let sort): + let parameters = [ + "page": page - 1, + "size": size, + "sort-type": sort + ] as [String : Any] + return .requestParameters(parameters: parameters, encoding: URLEncoding.queryString) } } diff --git a/SodaLive/Sources/Content/ContentRepository.swift b/SodaLive/Sources/Content/ContentRepository.swift index ee0615a..45989b9 100644 --- a/SodaLive/Sources/Content/ContentRepository.swift +++ b/SodaLive/Sources/Content/ContentRepository.swift @@ -88,4 +88,8 @@ final class ContentRepository { func getNewContentAllOfTheme(theme: String, page: Int, size: Int) -> AnyPublisher { return api.requestPublisher(.getNewContentAllOfTheme(theme: theme, page: page, size: size)) } + + func getAudioContentListByCurationId(curationId: Int, page: Int, size: Int, sort: ContentCurationViewModel.Sort) -> AnyPublisher { + return api.requestPublisher(.getAudioContentListByCurationId(curationId: curationId, page: page, size: size, sort: sort)) + } } diff --git a/SodaLive/Sources/Content/Curation/ContentCurationView.swift b/SodaLive/Sources/Content/Curation/ContentCurationView.swift new file mode 100644 index 0000000..5bb4e00 --- /dev/null +++ b/SodaLive/Sources/Content/Curation/ContentCurationView.swift @@ -0,0 +1,105 @@ +// +// ContentCurationView.swift +// SodaLive +// +// Created by klaus on 2023/09/27. +// + +import SwiftUI + +struct ContentCurationView: View { + + @StateObject var viewModel = ContentCurationViewModel() + + let title: String + let curationId: Int + + let columns = [ + GridItem(.flexible()), + GridItem(.flexible()) + ] + + var body: some View { + BaseView(isLoading: $viewModel.isLoading) { + VStack(spacing: 0) { + DetailNavigationBar(title: title) + + HStack(spacing: 13.3) { + Spacer() + + Text("최신순") + .font(.custom(Font.medium.rawValue, size: 13.3)) + .foregroundColor( + Color(hex: "e2e2e2") + .opacity(viewModel.sort == .NEWEST ? 1 : 0.5) + ) + .onTapGesture { + if viewModel.sort != .NEWEST { + viewModel.sort = .NEWEST + } + } + + Text("높은 가격순") + .font(.custom(Font.medium.rawValue, size: 13.3)) + .foregroundColor( + Color(hex: "e2e2e2") + .opacity(viewModel.sort == .PRICE_HIGH ? 1 : 0.5) + ) + .onTapGesture { + if viewModel.sort != .PRICE_HIGH { + viewModel.sort = .PRICE_HIGH + } + } + + Text("낮은 가격순") + .font(.custom(Font.medium.rawValue, size: 13.3)) + .foregroundColor( + Color(hex: "e2e2e2") + .opacity(viewModel.sort == .PRICE_LOW ? 1 : 0.5) + ) + .onTapGesture { + if viewModel.sort != .PRICE_LOW { + viewModel.sort = .PRICE_LOW + } + } + } + .padding(.vertical, 13.3) + .padding(.horizontal, 20) + .background(Color(hex: "161616")) + .padding(.top, 13.3) + + HStack(spacing: 0) { + Text("전체") + .font(.custom(Font.medium.rawValue, size: 13.3)) + .foregroundColor(Color(hex: "e2e2e2")) + + Text("\(viewModel.totalCount)") + .font(.custom(Font.medium.rawValue, size: 13.3)) + .foregroundColor(Color(hex: "ff5c49")) + .padding(.leading, 8) + + Text("개") + .font(.custom(Font.medium.rawValue, size: 13.3)) + .foregroundColor(Color(hex: "e2e2e2")) + .padding(.leading, 2) + + Spacer() + } + .padding(.vertical, 13.3) + .padding(.horizontal, 20) + + ScrollView(.vertical, showsIndicators: false) { + LazyVGrid(columns: columns, spacing: 13.3) { + ForEach(0..() + + @Published var errorMessage = "" + @Published var isShowPopup = false + @Published var isLoading = false + + @Published var totalCount = 0 + @Published var sort = Sort.NEWEST { + didSet { + page = 1 + isLast = false + getContentList() + } + } + + @Published var contentList: [GetAudioContentMainItem] = [] + + var curationId = 0 + var page = 1 + var isLast = false + private let pageSize = 10 + + func getContentList() { + if (!isLast && !isLoading) { + isLoading = true + + repository.getAudioContentListByCurationId( + curationId: curationId, + page: page, + size: pageSize, + sort: sort + ) + .sink { result in + switch result { + case .finished: + DEBUG_LOG("finish") + case .failure(let error): + ERROR_LOG(error.localizedDescription) + } + } receiveValue: { [unowned self] response in + let responseData = response.data + + do { + let jsonDecoder = JSONDecoder() + let decoded = try jsonDecoder.decode(ApiResponse.self, from: responseData) + + if let data = decoded.data, decoded.success { + if page == 1 { + self.contentList.removeAll() + } + + if !data.items.isEmpty { + page += 1 + self.totalCount = data.totalCount + self.contentList.append(contentsOf: data.items) + } else { + isLast = true + } + } else { + if let message = decoded.message { + self.errorMessage = message + } else { + self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." + } + + self.isShowPopup = true + } + } catch { + self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." + self.isShowPopup = true + } + + self.isLoading = false + } + .store(in: &subscription) + } + } +} diff --git a/SodaLive/Sources/Content/Curation/GetCurationContentResponse.swift b/SodaLive/Sources/Content/Curation/GetCurationContentResponse.swift new file mode 100644 index 0000000..a9f8812 --- /dev/null +++ b/SodaLive/Sources/Content/Curation/GetCurationContentResponse.swift @@ -0,0 +1,11 @@ +// +// GetCurationContentResponse.swift +// SodaLive +// +// Created by klaus on 2023/09/27. +// + +struct GetCurationContentResponse: Decodable { + let totalCount: Int + let items: [GetAudioContentMainItem] +} diff --git a/SodaLive/Sources/Content/Main/ContentMainCurationItemView.swift b/SodaLive/Sources/Content/Main/ContentMainCurationItemView.swift index 8458a21..2b8cedc 100644 --- a/SodaLive/Sources/Content/Main/ContentMainCurationItemView.swift +++ b/SodaLive/Sources/Content/Main/ContentMainCurationItemView.swift @@ -24,7 +24,13 @@ struct ContentMainCurationItemView: View { .resizable() .frame(width: 20, height: 20) .onTapGesture { - + AppState.shared + .setAppStep( + step: .curationAll( + title: item.title, + curationId: item.curationId + ) + ) } } diff --git a/SodaLive/Sources/Content/Main/ContentMainCurationView.swift b/SodaLive/Sources/Content/Main/ContentMainCurationView.swift index e329215..96137eb 100644 --- a/SodaLive/Sources/Content/Main/ContentMainCurationView.swift +++ b/SodaLive/Sources/Content/Main/ContentMainCurationView.swift @@ -14,8 +14,7 @@ struct ContentMainCurationView: View { var body: some View { LazyVStack(spacing: 40) { ForEach(0..