// // UserProfileDonationAllView.swift // SodaLive // // Created by klaus on 2023/08/29. // import SwiftUI import Kingfisher struct UserProfileDonationAllView: View { let userId: Int @StateObject var viewModel = UserProfileDonationAllViewModel() var body: some View { BaseView(isLoading: $viewModel.isLoading) { VStack(spacing: 0) { DetailNavigationBar(title: "후원랭킹 전체보기") if userId == UserDefaults.int(forKey: .userId) { VStack(spacing: 10.7) { HStack(spacing: 10) { Spacer() Text("채널에 후원랭킹 활성화") .font(.custom(Font.bold.rawValue, size: 16)) .foregroundColor(Color(hex: "eeeeee")) Image(viewModel.isVisibleDonationRank ? "btn_toggle_on_big" : "btn_toggle_off_big") .resizable() .frame(width: 46.7, height: 27) .onTapGesture { viewModel.toggleVisibleDonationRank() } } HStack(spacing: 0) { Spacer() Text("※ 비활성화하면 채널 내 후원랭킹이 표시되지 않으며,\n라이브 중에도 후원랭킹에 따른 뱃지가 반영되지 않습니다.") .font(.custom(Font.medium.rawValue, size: 12)) .foregroundColor(Color(hex: "555555")) .multilineTextAlignment(.trailing) } } .padding(.top, 13.3) .padding(.horizontal, 13.3) VStack(spacing: 13.3) { HStack(spacing: 0) { Text("오늘") .font(.custom(Font.bold.rawValue, size: 12)) .foregroundColor(Color(hex: "eeeeee")) Spacer() Text("\(viewModel.accumulatedCansToday.comma())") .font(.custom(Font.bold.rawValue, size: 12)) .foregroundColor(Color(hex: "eeeeee")) Text(" 캔") .font(.custom(Font.light.rawValue, size: 12)) .foregroundColor(Color(hex: "eeeeee")) } HStack(spacing: 0) { Text("지난주") .font(.custom(Font.bold.rawValue, size: 12)) .foregroundColor(Color(hex: "eeeeee")) Spacer() Text("\(viewModel.accumulatedCansLastWeek.comma())") .font(.custom(Font.bold.rawValue, size: 12)) .foregroundColor(Color(hex: "eeeeee")) Text(" 캔") .font(.custom(Font.light.rawValue, size: 12)) .foregroundColor(Color(hex: "eeeeee")) } HStack(spacing: 0) { Text("이번 달 어제까지") .font(.custom(Font.bold.rawValue, size: 12)) .foregroundColor(Color(hex: "eeeeee")) Spacer() Text("\(viewModel.accumulatedCansThisMonth.comma())") .font(.custom(Font.bold.rawValue, size: 12)) .foregroundColor(Color(hex: "eeeeee")) Text(" 캔") .font(.custom(Font.light.rawValue, size: 12)) .foregroundColor(Color(hex: "eeeeee")) } } .padding(16.7) .background(Color(hex: "13181b")) .cornerRadius(8) .padding(.top, 13.3) .padding(.horizontal, 13.3) } HStack(alignment: .center, spacing: 0) { Text("전체") .font(.custom(Font.medium.rawValue, size: 14.7)) .foregroundColor(Color(hex: "eeeeee")) Text("\(viewModel.totalCount)") .font(.custom(Font.medium.rawValue, size: 12)) .foregroundColor(Color(hex: "80d8ff")) .padding(.leading, 6.7) Text("개") .font(.custom(Font.medium.rawValue, size: 12)) .foregroundColor(Color(hex: "777777")) Spacer() } .padding(.top, 13.3) .padding(.horizontal, 13.3) Rectangle() .frame(width: screenSize().width - 26.7, height: 1) .foregroundColor(Color(hex: "595959")) .padding(.top, 6.7) ScrollView(.vertical, showsIndicators: false) { LazyVStack(spacing: 0) { ForEach(0..<viewModel.userDonationRanking.count, id: \.self) { index in let item = viewModel.userDonationRanking[index] UserProfileDonationAllItemView( index: index, item: item, withDonationCan: userId == UserDefaults.int(forKey: .userId), itemCount: viewModel.userDonationRanking.count ) .onAppear { if index == viewModel.userDonationRanking.count - 1 { viewModel.getCreatorProfileDonationRanking() } } } } } .padding(.vertical, 16.7) .padding(.horizontal, 13.3) } .onAppear { viewModel.userId = userId viewModel.getCreatorProfileDonationRanking() } .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: "9970ff")) .foregroundColor(Color.white) .multilineTextAlignment(.leading) .cornerRadius(20) .padding(.bottom, 66.7) Spacer() } } } } } struct UserProfileDonationAllItemView: View { let index: Int let item: UserDonationRankingResponse let withDonationCan: Bool let itemCount: Int let rankingCrawns = ["ic_crown_1", "ic_crown_2", "ic_crown_3"] let rankingColors = [ [Color(hex: "ffdc00"), Color(hex: "ffb600")], [Color(hex: "ffffff"), Color(hex: "9f9f9f")], [Color(hex: "e6a77a"), Color(hex: "c67e4a")], [Color(hex: "ffffff").opacity(0), Color(hex: "ffffff").opacity(0)] ] var body: some View { HStack(spacing: 0) { ZStack { KFImage(URL(string: item.profileImage)) .cancelOnDisappear(true) .downsampling(size: CGSize(width: 60, height: 60)) .resizable() .scaledToFill() .frame(width: 60, height: 60, alignment: .top) .clipShape(Circle()) .overlay( Circle() .stroke( AngularGradient(colors: rankingColors[index < 4 ? index : 3], center: .center), lineWidth: 3 ) ) if index < 3 { VStack(alignment: .trailing, spacing: 0) { Spacer() Image(rankingCrawns[index]) .resizable() .frame(width: 25, height: 25) } .frame(width: 63, height: 63, alignment: .trailing) } } .frame(width: 63, height: 63) Text("\(index + 1)") .font(.custom(Font.bold.rawValue, size: 13.3)) .foregroundColor(Color(hex: "eeeeee")) .padding(.leading, 20) .padding(.trailing, 13.3) let nickname = item.nickname.count > 10 ? "\(String(item.nickname.prefix(10)))..." : item.nickname Text(nickname) .font(.custom(Font.medium.rawValue, size: 13.3)) .foregroundColor(Color(hex: "eeeeee")) Spacer() if let donationCan = item.donationCan, donationCan > 0, withDonationCan { Text("\(donationCan) 캔") .font(.custom(Font.medium.rawValue, size: 13.3)) .foregroundColor(Color(hex: "eeeeee")) } } .padding(.horizontal, isTop3Index(index: index) ? 20 : 0) .padding(.top, getTopPadding(index: index)) .padding(.bottom, getBottomPadding(index: index)) .background(Color(hex: "13181b").opacity(isTop3Index(index: index) ? 1 : 0)) .cornerRadius(4.7, corners: cornerRadiusConers(index: index)) .padding(.horizontal, isTop3Index(index: index) ? 0 : 6.7) } private func isTop3Index(index: Int) -> Bool { return index == 0 || index == 1 || index == 2 } private func getTopPadding(index: Int) -> CGFloat { if index == 0 || index == 3 { return 20 } else { return 6.7 } } private func getBottomPadding(index: Int) -> CGFloat { if (index == 0 && itemCount == 1) || (index == 1 && itemCount == 2) || index == 2 { return 20 } else { return 6.7 } } private func cornerRadiusConers(index: Int) -> UIRectCorner { if (index == 0 && itemCount == 1) { return [.topLeft, .topRight, .bottomLeft, .bottomRight] } else if index == 0 { return [.topLeft, .topRight] } else if (index == 1 && itemCount == 2) || index == 2 { return [.bottomLeft, .bottomRight] } else { return [] } } }