diff --git a/SodaLive/Sources/Content/ContentListItemView.swift b/SodaLive/Sources/Content/ContentListItemView.swift index ca78a71..b78107f 100644 --- a/SodaLive/Sources/Content/ContentListItemView.swift +++ b/SodaLive/Sources/Content/ContentListItemView.swift @@ -14,23 +14,23 @@ struct ContentListItemView: View { var body: some View { VStack(spacing: 10) { - HStack(spacing: 0) { + HStack(spacing: 8) { ZStack(alignment: .topLeading) { KFImage(URL(string: item.coverImageUrl)) .cancelOnDisappear(true) - .downsampling(size: CGSize(width: 66.7, height: 66.7)) + .downsampling(size: CGSize(width: 85, height: 85)) .resizable() .scaledToFill() - .frame(width: 66.7, height: 66.7, alignment: .top) + .frame(width: 85, height: 85, alignment: .top) .clipped() - .cornerRadius(5.3) + .cornerRadius(12) } - VStack(alignment: .leading, spacing: 0) { + VStack(alignment: .leading, spacing: 8) { HStack(spacing: 8) { if item.isScheduledToOpen { Text("오픈예정") - .font(.custom(Font.medium.rawValue, size: 8)) + .font(.custom(Font.preMedium.rawValue, size: 11)) .foregroundColor(Color(hex: "3bb9f1")) .padding(2.6) .background(Color(hex: "003851")) @@ -38,14 +38,14 @@ struct ContentListItemView: View { } Text(item.themeStr) - .font(.custom(Font.medium.rawValue, size: 8)) + .font(.custom(Font.preMedium.rawValue, size: 11)) .foregroundColor(Color(hex: "3bac6a")) .padding(2.6) .background(Color(hex: "28312b")) .cornerRadius(2.6) Text(item.duration!) - .font(.custom(Font.medium.rawValue, size: 8)) + .font(.custom(Font.preMedium.rawValue, size: 11)) .foregroundColor(Color(hex: "777777")) .padding(2.6) .background(Color(hex: "222222")) @@ -53,7 +53,7 @@ struct ContentListItemView: View { if item.isPointAvailable { Text("포인트") - .font(.custom(Font.medium.rawValue, size: 8)) + .font(.custom(Font.preMedium.rawValue, size: 11)) .foregroundColor(.white) .padding(2.6) .background(Color(hex: "7849bc")) @@ -68,43 +68,38 @@ struct ContentListItemView: View { } Text(item.title) - .font(.custom(Font.medium.rawValue, size: 12)) - .foregroundColor(Color(hex: "d2d2d2")) + .font(.custom(Font.preMedium.rawValue, size: 18)) + .foregroundColor(.white) .multilineTextAlignment(.leading) - .padding(.top, 8) - .padding(.bottom, 10) - HStack(spacing: 13.3) { + HStack(spacing: 14) { HStack(spacing: 6) { Image("ic_heart_777") .resizable() - .frame(width: 13.3, height: 13.3) + .frame(width: 18, height: 18) Text("\(item.likeCount)") - .font(.custom(Font.medium.rawValue, size: 13.3)) + .font(.custom(Font.preMedium.rawValue, size: 18)) .foregroundColor(Color(hex: "777777")) } HStack(spacing: 6) { Image("ic_message_square_777") .resizable() - .frame(width: 13.3, height: 13.3) + .frame(width: 18, height: 18) Text("\(item.commentCount)") - .font(.custom(Font.medium.rawValue, size: 13.3)) + .font(.custom(Font.preMedium.rawValue, size: 18)) .foregroundColor(Color(hex: "777777")) } } } - .padding(.leading, 10.7) - .padding(.top, 8) - .padding(.bottom, 12) Spacer() if item.isOwned { Text("소장중") - .font(.custom(Font.medium.rawValue, size: 13.3)) + .font(.custom(Font.preMedium.rawValue, size: 14)) .foregroundColor(Color.gray11) .padding(.horizontal, 5.3) .padding(.vertical, 2.7) @@ -112,7 +107,7 @@ struct ContentListItemView: View { .cornerRadius(2.6) } else if item.isRented { Text("대여중") - .font(.custom(Font.medium.rawValue, size: 13.3)) + .font(.custom(Font.preMedium.rawValue, size: 14)) .foregroundColor(Color.white) .padding(.horizontal, 5.3) .padding(.vertical, 2.7) @@ -120,7 +115,7 @@ struct ContentListItemView: View { .cornerRadius(2.6) } else if item.isSoldOut { Text("Sold Out") - .font(.custom(Font.medium.rawValue, size: 13.3)) + .font(.custom(Font.preMedium.rawValue, size: 14)) .foregroundColor(Color.grayd2) .padding(.horizontal, 5.3) .padding(.vertical, 2.7) @@ -136,13 +131,13 @@ struct ContentListItemView: View { .frame(width: 17, height: 17) Text("\(item.price)") - .font(.custom(Font.medium.rawValue, size: 12)) - .foregroundColor(Color(hex: "909090")) + .font(.custom(Font.preMedium.rawValue, size: 14)) + .foregroundColor(.white) } } else { Text("무료") - .font(.custom(Font.medium.rawValue, size: 12)) - .foregroundColor(Color(hex: "909090")) + .font(.custom(Font.preMedium.rawValue, size: 14)) + .foregroundColor(.white) } } diff --git a/SodaLive/Sources/Explorer/Profile/UserProfileContentView.swift b/SodaLive/Sources/Explorer/Profile/UserProfileContentView.swift index 2d858d6..4340ef9 100644 --- a/SodaLive/Sources/Explorer/Profile/UserProfileContentView.swift +++ b/SodaLive/Sources/Explorer/Profile/UserProfileContentView.swift @@ -11,19 +11,28 @@ struct UserProfileContentView: View { let userId: Int let items: [GetAudioContentListItem] + let totalContentCount: Int + let ownedContentCount: Int + + private var progressBarWidth: CGFloat { + let maxWidth: CGFloat = screenSize().width - 48 + guard totalContentCount > 0 else { return 0 } + let percentage = Double(ownedContentCount) / Double(totalContentCount) + return maxWidth * percentage + } var body: some View { VStack(spacing: 21) { HStack(spacing: 0) { Text(userId == UserDefaults.int(forKey: .userId) ? "내 콘텐츠" : "콘텐츠") - .font(.custom(Font.bold.rawValue, size: 18.3)) - .foregroundColor(Color.grayee) + .font(.custom(Font.preBold.rawValue, size: 26)) + .foregroundColor(Color.white) Spacer() Text("전체보기") - .font(.custom(Font.medium.rawValue, size: 12)) - .foregroundColor(Color.graybb) + .font(.custom(Font.preLight.rawValue, size: 14)) + .foregroundColor(Color(hex: "78909C")) .onTapGesture { AppState.shared.setAppStep(step: .contentListAll(userId: userId)) } @@ -31,13 +40,15 @@ struct UserProfileContentView: View { if userId == UserDefaults.int(forKey: .userId) { Text("새로운 콘텐츠 등록하기") - .font(.custom(Font.bold.rawValue, size: 15)) + .font(.custom(Font.bold.rawValue, size: 16)) .foregroundColor(Color.grayee) .padding(.vertical, 17) .frame(maxWidth: .infinity) .background(Color.button) - .cornerRadius(5.3) + .cornerRadius(12) .onTapGesture { AppState.shared.setAppStep(step: .createContent) } + } else { + collectionInfoView() } VStack(spacing: 10.7) { @@ -56,6 +67,56 @@ struct UserProfileContentView: View { } } } + + @ViewBuilder + private func collectionInfoView() -> some View { + VStack(spacing: 8) { + // 상단 정보 (계산된 % 보유중, 정보 아이콘, 개수) + HStack { + Text(ownedContentCount > 0 ? "\(Int(round(Double(ownedContentCount) / Double(totalContentCount) * 100)))% 보유중" : "소장 중인 작품이 없어요!") + .font(.custom(Font.preBold.rawValue, size: 18)) + .foregroundColor(.white) + + Spacer() + + HStack(spacing: 4) { + Text("\(ownedContentCount)") + .font(.custom(Font.preRegular.rawValue, size: 16)) + .foregroundColor(Color(hex: "#FDD453")) + + Text("/") + .font(.custom(Font.preRegular.rawValue, size: 16)) + .foregroundColor(.white) + + Text("\(totalContentCount)개") + .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) + } + } } struct UserProfileContentView_Previews: PreviewProvider { @@ -80,7 +141,9 @@ struct UserProfileContentView_Previews: PreviewProvider { isSoldOut: false, isPointAvailable: true ) - ] + ], + totalContentCount: 0, + ownedContentCount: 0 ) } } diff --git a/SodaLive/Sources/Explorer/Profile/UserProfileView.swift b/SodaLive/Sources/Explorer/Profile/UserProfileView.swift index ea45951..8262b94 100644 --- a/SodaLive/Sources/Explorer/Profile/UserProfileView.swift +++ b/SodaLive/Sources/Explorer/Profile/UserProfileView.swift @@ -203,8 +203,11 @@ struct UserProfileView: View { if creatorProfile.creator.creatorId == UserDefaults.int(forKey: .userId) || creatorProfile.contentList.count > 0 { UserProfileContentView( userId: userId, - items: creatorProfile.contentList + items: creatorProfile.contentList, + totalContentCount: creatorProfile.totalContentCount, + ownedContentCount: creatorProfile.ownedContentCount ) + .padding(.horizontal, 24) } if viewModel.communityPostList.count > 0 {