// // CharacterDetailGalleryView.swift // SodaLive // // Created by klaus on 9/1/25. // import SwiftUI struct CharacterDetailGalleryView: View { @StateObject var viewModel = CharacterDetailGalleryViewModel() private let columns = Array(repeating: GridItem(.flexible(), spacing: 2), count: 3) // 갤러리 데이터 private let ownedCount: Int = 104 private let totalCount: Int = 259 // 계산된 속성들 private var ownershipPercentage: Int { guard totalCount > 0 else { return 0 } return Int(round(Double(ownedCount) / Double(totalCount) * 100)) } private var progressBarWidth: CGFloat { let maxWidth: CGFloat = 352 // 전체 진행률 바의 최대 너비 guard totalCount > 0 else { return 0 } let percentage = Double(ownedCount) / Double(totalCount) return maxWidth * percentage } var body: some View { BaseView(isLoading: $viewModel.isLoading) { VStack(spacing: 0) { // 상단 여백 24px Spacer() .frame(height: 24) // 보유 정보 섹션 collectionInfoView() .padding(.horizontal, 24) .padding(.bottom, 8) // 갤러리 그리드 LazyVGrid(columns: columns, spacing: 2) { ForEach(0..<4, id: \.self) { index in galleryImageView(index: index) } } .padding(.horizontal, 0) Spacer() } .background(Color(hex: "#131313")) } } @ViewBuilder private func collectionInfoView() -> some View { VStack(spacing: 8) { // 상단 정보 (계산된 % 보유중, 정보 아이콘, 개수) HStack { Text("\(ownershipPercentage)% 보유중") .font(.custom(Font.preBold.rawValue, size: 18)) .foregroundColor(.white) Spacer() HStack(spacing: 4) { Text("\(ownedCount)") .font(.custom(Font.preRegular.rawValue, size: 16)) .foregroundColor(Color(hex: "#FDD453")) Text("/") .font(.custom(Font.preRegular.rawValue, size: 16)) .foregroundColor(.white) Text("\(totalCount)개") .font(.custom(Font.preRegular.rawValue, size: 16)) .foregroundColor(.white) } } // 진행률 바 GeometryReader { geometry in ZStack(alignment: .leading) { // 배경 바 RoundedRectangle(cornerRadius: 999) .foregroundColor(Color(hex: "#37474F")) .frame(height: 9) // 진행률 바 (계산된 퍼센트) RoundedRectangle(cornerRadius: 999) .fill( LinearGradient( colors: [Color(hex: "#80D8FF"), Color(hex: "#6D5ED7")], startPoint: .leading, endPoint: .trailing ) ) .frame(width: min(progressBarWidth, geometry.size.width), height: 9) } } .frame(height: 9) } } @ViewBuilder private func galleryImageView(index: Int) -> some View { ZStack { // 이미지 AsyncImage(url: URL(string: "https://picsum.photos/400/500")) { image in image .resizable() .aspectRatio(contentMode: .fill) } placeholder: { Rectangle() .fill(Color.gray.opacity(0.3)) } .frame(width: 132, height: 165) .clipped() .cornerRadius(0) // 자물쇠가 있는 이미지들 (index 2, 3) if index >= 2 { // 어두운 오버레이 Rectangle() .fill(Color.black.opacity(0.2)) .frame(width: 132, height: 165) // 자물쇠 아이콘과 코인 정보 VStack(spacing: 8) { // 자물쇠 아이콘 Image("ic_new_lock") .resizable() .scaledToFit() .frame(width: 24) // 코인 정보 배경 HStack(spacing: 4) { Image("ic_can") .resizable() .scaledToFit() .frame(width: 16) Text("20") .font(.custom(Font.preBold.rawValue, size: 16)) .foregroundColor(Color(hex: "#263238")) } .padding(.horizontal, 12) .padding(.vertical, 6) .background(Color(hex: "#B5E7FA")) .cornerRadius(30) .overlay { RoundedRectangle(cornerRadius: 30) .strokeBorder(lineWidth: 1) .foregroundColor(.button) } } } } } } #Preview { CharacterDetailGalleryView() }