import SwiftUI struct MainHomeFollowingNewsSection: View { let recentNews: [FollowingNewsResponse] let onTapCreator: (Int) -> Void let onTapContent: (Int) -> Void init( recentNews: [FollowingNewsResponse], onTapCreator: @escaping (Int) -> Void = { _ in }, onTapContent: @escaping (Int) -> Void = { _ in } ) { self.recentNews = recentNews self.onTapCreator = onTapCreator self.onTapContent = onTapContent } var body: some View { if !recentNews.isEmpty { VStack(alignment: .leading, spacing: SodaSpacing.s14) { SectionTitle(title: I18n.HomeFollowing.recentNewsTitle) VStack(alignment: .leading, spacing: SodaSpacing.s8) { ForEach(recentNews) { news in newsItemView(news) } } .padding(.horizontal, SodaSpacing.s14) } } } @ViewBuilder private func newsItemView(_ news: FollowingNewsResponse) -> some View { switch news.type { case .creatorRanking: if let creatorRanking = news.creatorRanking { MainHomeFollowingRankingNewsCard( creatorRanking: creatorRanking, onTapCreator: onTapCreator ) } case .contentRanking: if let contentRanking = news.contentRanking { MainHomeFollowingRankingNewsCard( contentRanking: contentRanking, onTapContent: onTapContent ) } case .communityPost: if let communityPost = news.communityPost { CommunityPostCard( postId: communityPost.postId, creatorNickname: communityPost.creatorNickname, creatorProfileImageUrl: communityPost.creatorProfileImage, content: communityPost.content, imageUrl: communityPost.imageUrl, audioUrl: nil, price: 0, existOrdered: true, createdAt: communityPost.relativeCreatedAtText(), isLike: false, likeCount: communityPost.likeCount, commentCount: communityPost.commentCount ) } case .audioContent: if let audioContent = news.audioContent { MainHomeFollowingContentNewsCard( content: audioContent, visibleFromAtUtc: news.visibleFromAtUtc, variant: .audio, onTapContent: onTapContent ) } case .photoContent: if let photoContent = news.photoContent { MainHomeFollowingContentNewsCard( content: photoContent, visibleFromAtUtc: news.visibleFromAtUtc, variant: .photo, onTapContent: onTapContent ) } case .unknown: EmptyView() } } } private extension FollowingCommunityPostNewsResponse { func relativeCreatedAtText(now: Date = Date()) -> String { DateParser.relativeTimeText(fromUTC: createdAt, fallback: createdAt, now: now) } } struct MainHomeFollowingNewsSection_Previews: PreviewProvider { private static let previewImageUrl = "https://picsum.photos/500/500" static var previews: some View { ScrollView(.vertical) { MainHomeFollowingNewsSection( recentNews: [ FollowingNewsResponse( newsId: "creator-ranking", type: .creatorRanking, visibleFromAtUtc: "2026-07-01T00:00:00Z", creatorRanking: FollowingCreatorRankingNewsResponse( rank: 2, creatorId: 1, nickname: "크리에이터", profileImageUrl: previewImageUrl ), audioContent: nil, photoContent: nil, contentRanking: nil, communityPost: nil ), FollowingNewsResponse( newsId: "community-post", type: .communityPost, visibleFromAtUtc: "2026-07-01T00:00:00Z", creatorRanking: nil, audioContent: nil, photoContent: nil, contentRanking: nil, communityPost: FollowingCommunityPostNewsResponse( postId: 10, creatorProfileImage: previewImageUrl, creatorNickname: "크리에이터", imageUrl: previewImageUrl, content: "팔로잉 크리에이터의 커뮤니티 게시글입니다.", createdAt: "2026-07-01T00:00:00Z", likeCount: 5, commentCount: 2 ) ), FollowingNewsResponse( newsId: "audio-content", type: .audioContent, visibleFromAtUtc: "2026-07-01T00:02:00Z", creatorRanking: nil, audioContent: FollowingContentNewsResponse( contentId: 20, contentImageUrl: previewImageUrl, title: "오디오 콘텐츠 이름", creatorProfileImageUrl: previewImageUrl, creatorNickname: "크리에이터이름" ), photoContent: nil, contentRanking: nil, communityPost: nil ), FollowingNewsResponse( newsId: "photo-content", type: .photoContent, visibleFromAtUtc: "2026-07-01T00:03:00Z", creatorRanking: nil, audioContent: nil, photoContent: FollowingContentNewsResponse( contentId: 21, contentImageUrl: previewImageUrl, title: "화보 콘텐츠 이름", creatorProfileImageUrl: previewImageUrl, creatorNickname: "크리에이터이름" ), contentRanking: nil, communityPost: nil ) ] ) .padding(.vertical, SodaSpacing.s20) .background(Color.black) .previewLayout(.sizeThatFits) } } }