콘텐츠 전체보기

- 카테고리 추가
This commit is contained in:
Yu Sung 2024-02-07 15:09:48 +09:00
parent 638d00ffc3
commit 62904d96b1
7 changed files with 196 additions and 10 deletions

View File

@ -0,0 +1,45 @@
//
// CategoryApi.swift
// SodaLive
//
// Created by klaus on 2/7/24.
//
import Foundation
import Moya
enum CategoryApi {
case getCategoryList(creatorId: Int)
}
extension CategoryApi: TargetType {
var baseURL: URL {
return URL(string: BASE_URL)!
}
var path: String {
switch self {
case .getCategoryList:
return "/category"
}
}
var method: Moya.Method {
switch self {
case .getCategoryList:
return .get
}
}
var task: Moya.Task {
switch self {
case .getCategoryList(let creatorId):
let parameters = ["creatorId": creatorId] as [String : Any]
return .requestParameters(parameters: parameters, encoding: URLEncoding.queryString)
}
}
var headers: [String : String]? {
return ["Authorization": "Bearer \(UserDefaults.string(forKey: UserDefaultsKey.token))"]
}
}

View File

@ -0,0 +1,59 @@
//
// ContentListCategoryView.swift
// SodaLive
//
// Created by klaus on 2/7/24.
//
import SwiftUI
struct ContentListCategoryView: View {
let categoryList: [GetCategoryListResponse]
let selectCategory: (Int) -> Void
@Binding var selectedCategory: String
var body: some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 8) {
ForEach(0..<categoryList.count, id: \.self) { index in
let category = categoryList[index]
Text(category.category)
.font(.custom(Font.medium.rawValue, size: 14.7))
.foregroundColor(Color(hex: selectedCategory == category.category ? "3bb9f1" : "777777"))
.padding(.horizontal, 13.3)
.padding(.vertical, 9.3)
.border(
Color(hex: selectedCategory == category.category ? "3bb9f1" : "eeeeee"),
width: 0.5
)
.cornerRadius(16.7)
.overlay(
RoundedRectangle(cornerRadius: CGFloat(16.7))
.stroke(lineWidth: 0.5)
.foregroundColor(Color(hex: selectedCategory == category.category ? "3bb9f1" : "eeeeee"))
)
.onTapGesture {
if selectedCategory != category.category {
selectedCategory = category.category
selectCategory(category.categoryId)
}
}
}
}
}
}
}
#Preview {
ContentListCategoryView(
categoryList: [
GetCategoryListResponse(categoryId: 0, category: "전체"),
GetCategoryListResponse(categoryId: 1, category: "test"),
GetCategoryListResponse(categoryId: 0, category: "test2")
],
selectCategory: { _ in },
selectedCategory: .constant("전체")
)
}

View File

@ -0,0 +1,13 @@
//
// GetCategoryListResponse.swift
// SodaLive
//
// Created by klaus on 2/7/24.
//
import Foundation
struct GetCategoryListResponse: Decodable {
let categoryId: Int
let category: String
}

View File

@ -9,7 +9,7 @@ import Foundation
import Moya
enum ContentApi {
case getAudioContentList(userId: Int, page: Int, size: Int, sort: ContentListViewModel.Sort)
case getAudioContentList(userId: Int, categoryId: Int, page: Int, size: Int, sort: ContentListViewModel.Sort)
case getAudioContentDetail(audioContentId: Int)
case likeContent(request: PutAudioContentLikeRequest)
case registerComment(request: RegisterAudioContentCommentRequest)
@ -152,9 +152,10 @@ extension ContentApi: TargetType {
var task: Moya.Task {
switch self {
case .getAudioContentList(let userId, let page, let size, let sort):
case .getAudioContentList(let userId, let categoryId, let page, let size, let sort):
let parameters = [
"creator-id": userId,
"category-id": categoryId,
"page": page - 1,
"size": size,
"sort-type": sort

View File

@ -35,6 +35,15 @@ struct ContentListView: View {
.frame(height: 50)
.background(Color.black)
if !viewModel.categoryList.isEmpty {
ContentListCategoryView(
categoryList: viewModel.categoryList,
selectCategory: { viewModel.selectCategory(categoryId: $0) },
selectedCategory: $viewModel.selectedCategory
)
.padding(.horizontal, 13.3)
}
if userId == UserDefaults.int(forKey: .userId) {
Text("새로운 콘텐츠 등록하기")
.font(.custom(Font.bold.rawValue, size: 15))
@ -132,12 +141,14 @@ struct ContentListView: View {
}
}
}
.padding(.horizontal, 13.3)
}
}
.padding(.top, 13.3)
}
.onAppear {
viewModel.userId = userId
viewModel.getCategoryList()
viewModel.getAudioContentList()
}
.popup(isPresented: $viewModel.isShowPopup, type: .toast, position: .bottom, autohideIn: 2) {

View File

@ -21,6 +21,7 @@ final class ContentListViewModel: ObservableObject {
@Published var isShowPopup = false
@Published var isLoading = false
@Published var categoryList: [GetCategoryListResponse] = []
@Published var audioContentList: [GetAudioContentListItem] = []
@Published var totalCount = 0
@Published var sort = Sort.NEWEST {
@ -32,18 +33,20 @@ final class ContentListViewModel: ObservableObject {
}
@Published var scrollToTop = false
@Published var selectedCategory: String = "전체"
var userId = 0
var page = 1
var isLast = false
private let pageSize = 10
private var categoryId = 0
func getAudioContentList() {
if (!isLast && !isLoading) {
isLoading = true
repository
.getAudioContentList(userId: userId, page: page, size: pageSize, sort: sort)
.getAudioContentList(userId: userId, categoryId: categoryId, page: page, size: pageSize, sort: sort)
.sink { result in
switch result {
case .finished:
@ -64,11 +67,11 @@ final class ContentListViewModel: ObservableObject {
self.scrollToTop.toggle()
}
if !data.items.isEmpty {
page += 1
self.totalCount = data.totalCount
self.audioContentList.append(contentsOf: data.items)
} else {
page += 1
self.totalCount = data.totalCount
self.audioContentList.append(contentsOf: data.items)
if data.items.isEmpty {
isLast = true
}
} else {
@ -90,4 +93,53 @@ final class ContentListViewModel: ObservableObject {
.store(in: &subscription)
}
}
func getCategoryList() {
repository.getCategoryList(creatorId: userId)
.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<[GetCategoryListResponse]>.self, from: responseData)
if let data = decoded.data, decoded.success {
categoryList.removeAll()
if !data.isEmpty {
categoryList.append(GetCategoryListResponse(categoryId: 0, category: "전체"))
categoryList.append(contentsOf: data)
}
} else {
if let message = decoded.message {
self.errorMessage = message
} else {
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
}
self.isShowPopup = true
}
} catch {
print(error)
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
self.isShowPopup = true
}
}
.store(in: &subscription)
}
func selectCategory(categoryId: Int) {
self.categoryId = categoryId
page = 1
isLast = false
getAudioContentList()
}
}

View File

@ -12,9 +12,10 @@ import Moya
final class ContentRepository {
private let api = MoyaProvider<ContentApi>()
private let categoryApi = MoyaProvider<CategoryApi>()
func getAudioContentList(userId: Int, page: Int, size: Int, sort: ContentListViewModel.Sort) -> AnyPublisher<Response, MoyaError> {
return api.requestPublisher(.getAudioContentList(userId: userId, page: page, size: size, sort: sort))
func getAudioContentList(userId: Int, categoryId: Int, page: Int, size: Int, sort: ContentListViewModel.Sort) -> AnyPublisher<Response, MoyaError> {
return api.requestPublisher(.getAudioContentList(userId: userId, categoryId: categoryId, page: page, size: size, sort: sort))
}
func getAudioContentDetail(audioContentId: Int) -> AnyPublisher<Response, MoyaError> {
@ -120,4 +121,8 @@ final class ContentRepository {
func unpinContent(contentId: Int) -> AnyPublisher<Response, MoyaError> {
return api.requestPublisher(.unpinContent(contentId: contentId))
}
func getCategoryList(creatorId: Int) -> AnyPublisher<Response, MoyaError> {
return categoryApi.requestPublisher(.getCategoryList(creatorId: creatorId))
}
}