feat(home): 랭킹 소식 카드를 추가한다

This commit is contained in:
Yu Sung
2026-07-01 15:27:39 +09:00
parent 9ecb663f7b
commit 54d2787be0
4 changed files with 146 additions and 1 deletions

View File

@@ -3127,6 +3127,22 @@ If you block this user, the following features will be restricted.
pick(ko: "최근 소식", en: "Recent news", ja: "最近のニュース")
}
static func rankingMessagePrefix(_ title: String) -> String {
pick(
ko: "\(title)님이 이번 주 랭킹 ",
en: "\(title) reached ",
ja: "\(title)さんが今週のランキング"
)
}
static func rankingRankText(_ rank: Int) -> String {
pick(ko: "\(rank)", en: "No. \(rank)", ja: "\(rank)")
}
static var rankingMessageSuffix: String {
pick(ko: "에 올랐어요!", en: " in this week's ranking!", ja: "に入りました!")
}
static var audioTag: String {
pick(ko: "오디오", en: "Audio", ja: "オーディオ")
}

View File

@@ -0,0 +1,116 @@
import SwiftUI
struct MainHomeFollowingRankingNewsCard: View {
private let imageUrl: String?
private let title: String
private let rank: Int
private let action: () -> Void
init(
creatorRanking: FollowingCreatorRankingNewsResponse,
onTapCreator: @escaping (Int) -> Void = { _ in }
) {
self.imageUrl = creatorRanking.profileImageUrl
self.title = creatorRanking.nickname
self.rank = creatorRanking.rank
self.action = { onTapCreator(creatorRanking.creatorId) }
}
init(
contentRanking: FollowingContentRankingNewsResponse,
onTapContent: @escaping (Int) -> Void = { _ in }
) {
self.imageUrl = contentRanking.contentImageUrl
self.title = contentRanking.title
self.rank = contentRanking.rank
self.action = { onTapContent(contentRanking.contentId) }
}
var body: some View {
Button(action: action) {
HStack(alignment: .center, spacing: SodaSpacing.s14) {
RankingThumbnailView(imageUrl: imageUrl, rank: rank)
rankingMessage
.appFont(size: 16, weight: .medium)
.lineSpacing(0)
.multilineTextAlignment(.leading)
.frame(maxWidth: .infinity, alignment: .leading)
}
.padding(SodaSpacing.s14)
.background(Color.gray900)
.clipShape(RoundedRectangle(cornerRadius: SodaRadius.r14, style: .continuous))
}
.buttonStyle(.plain)
}
private var rankingMessage: Text {
Text(I18n.HomeFollowing.rankingMessagePrefix(title))
.foregroundColor(.white)
+ Text(I18n.HomeFollowing.rankingRankText(rank))
.foregroundColor(Color.soda400)
+ Text(I18n.HomeFollowing.rankingMessageSuffix)
.foregroundColor(.white)
}
}
private struct RankingThumbnailView: View {
let imageUrl: String?
let rank: Int
var body: some View {
ZStack(alignment: .bottomTrailing) {
DownsampledKFImage(url: imageUrl.flatMap(URL.init(string:)), size: CGSize(width: 80, height: 80))
.clipShape(RoundedRectangle(cornerRadius: SodaRadius.r14, style: .continuous))
LinearGradient(
colors: [Color.black.opacity(0), Color.black.opacity(0.5)],
startPoint: .top,
endPoint: .bottom
)
.clipShape(RoundedRectangle(cornerRadius: SodaRadius.r14, style: .continuous))
Text("\(rank)")
.appFont(size: 40, weight: .regular, family: .pattaya)
.foregroundStyle(
LinearGradient(
colors: [.white, Color(hex: "EEEEEE")],
startPoint: .top,
endPoint: .bottom
)
)
.shadow(color: Color.black.opacity(0.48), radius: 2)
.offset(x: 0, y: 24)
}
.frame(width: 80, height: 80)
}
}
struct MainHomeFollowingRankingNewsCard_Previews: PreviewProvider {
private static let previewImageUrl = "https://picsum.photos/500/500"
static var previews: some View {
VStack(spacing: SodaSpacing.s12) {
MainHomeFollowingRankingNewsCard(
creatorRanking: FollowingCreatorRankingNewsResponse(
rank: 2,
creatorId: 1,
nickname: "크리",
profileImageUrl: previewImageUrl
)
)
MainHomeFollowingRankingNewsCard(
contentRanking: FollowingContentRankingNewsResponse(
rank: 4,
contentId: 10,
contentImageUrl: previewImageUrl,
title: "콘텐츠 제목"
)
)
}
.padding(SodaSpacing.s14)
.background(Color.black)
.previewLayout(.sizeThatFits)
}
}