// // ContentListView.swift // SodaLive // // Created by klaus on 2023/08/20. // import SwiftUI struct ContentListView: View { let userId: Int @StateObject var viewModel = ContentListViewModel() var body: some View { NavigationView { BaseView(isLoading: $viewModel.isLoading) { VStack(spacing: 0) { HStack(spacing: 0) { Button { AppState.shared.back() } label: { Image("ic_back") .resizable() .frame(width: 20, height: 20) Text("콘텐츠 전체보기") .font(.custom(Font.bold.rawValue, size: 18.3)) .foregroundColor(Color(hex: "eeeeee")) } Spacer() } .padding(.horizontal, 13.3) .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)) .foregroundColor(Color(hex: "eeeeee")) .padding(.vertical, 17) .frame(maxWidth: .infinity) .background(Color(hex: "3bb9f1")) .cornerRadius(5.3) .padding(.top, 13.3) .padding(.horizontal, 13.3) .onTapGesture { AppState.shared.setAppStep(step: .createContent) } } 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) ScrollViewReader { reader in ScrollView(.vertical, showsIndicators: false) { LazyVStack(spacing: 10.7) { ScrollerToTop(reader: reader, scrollOnChange: $viewModel.scrollToTop) ForEach(0..<viewModel.audioContentList.count, id: \.self) { index in let audioContent = viewModel.audioContentList[index] NavigationLink { ContentDetailView(contentId: audioContent.contentId) } label: { ContentListItemView(item: audioContent) .contentShape(Rectangle()) .onAppear { if index == viewModel.audioContentList.count - 1 { viewModel.getAudioContentList() } } } } } .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) { HStack { Spacer() Text(viewModel.errorMessage) .padding(.vertical, 13.3) .frame(width: screenSize().width - 66.7, alignment: .center) .font(.custom(Font.medium.rawValue, size: 12)) .background(Color(hex: "3bb9f1")) .foregroundColor(Color.white) .multilineTextAlignment(.leading) .cornerRadius(20) .padding(.bottom, 66.7) Spacer() } } } } } } struct ScrollerToTop: View { let reader: ScrollViewProxy @Binding var scrollOnChange: Bool var body: some View { EmptyView() .id("topScrollPoint") .onChange(of: scrollOnChange) { _ in withAnimation { reader.scrollTo("topScrollPoint", anchor: .bottom) } } } }