import SwiftUI struct MainHomeActiveCreatorSection: View { let items: [HomeActiveCreatorItem] let onTapLive: (Int) -> Void let onTapContent: (Int) -> Void let onTapCommunityPost: (Int) -> Void init( items: [HomeActiveCreatorItem], onTapLive: @escaping (Int) -> Void = { _ in }, onTapContent: @escaping (Int) -> Void = { _ in }, onTapCommunityPost: @escaping (Int) -> Void = { _ in } ) { self.items = items self.onTapLive = onTapLive self.onTapContent = onTapContent self.onTapCommunityPost = onTapCommunityPost } var body: some View { if !items.isEmpty { VStack(alignment: .leading, spacing: SodaSpacing.s14) { SectionTitle(title: I18n.HomeRecommendation.activeCreatorSectionTitle) ScrollView(.horizontal, showsIndicators: false) { LazyHStack(alignment: .center, spacing: SodaSpacing.s8) { ForEach(items, id: \.self) { item in MainHomeActiveCreatorItemView(item: item) { handleTap(item) } } } .padding(.horizontal, SodaSpacing.s14) } } } } private func handleTap(_ item: HomeActiveCreatorItem) { guard let targetId = item.targetId else { return } switch item.activityType { case .live: onTapLive(targetId) case .audio: onTapContent(targetId) case .community: onTapCommunityPost(targetId) case .unknown: break } } } private struct MainHomeActiveCreatorItemView: View { let item: HomeActiveCreatorItem let action: () -> Void var body: some View { Button(action: action) { HStack(alignment: .center, spacing: SodaSpacing.s8) { DownsampledKFImage(url: URL(string: item.creatorProfileImage), size: CGSize(width: 52, height: 52)) .background(Color.gray800) .clipShape(Circle()) .frame(width: 52, height: 52) VStack(alignment: .leading, spacing: SodaSpacing.s6) { Text(item.creatorNickname) .appFont(.heading4) .foregroundColor(.white) .lineLimit(1) .truncationMode(.tail) .frame(width: 147, alignment: .leading) HStack(alignment: .center, spacing: SodaSpacing.s8) { if !item.activityType.title.isEmpty { Text(item.activityType.title) .appFont(.body5) .foregroundColor(Color.gray100) .padding(.horizontal, SodaSpacing.s4) .padding(.vertical, 2) .background(Color.gray700) .clipShape(RoundedRectangle(cornerRadius: SodaSpacing.s4, style: .continuous)) } Text(item.relativeActivityAtText()) .appFont(.body4) .foregroundColor(Color.gray500) .lineLimit(1) } } .frame(width: 159, alignment: .leading) } .padding(SodaSpacing.s12) .background(Color.gray900) .clipShape(Capsule()) } .buttonStyle(.plain) } } private extension HomeActiveCreatorItem { func relativeActivityAtText(now: Date = Date()) -> String { guard let activityDate = DateParser.parse(activityAt) else { return activityAt } let interval = max(0, now.timeIntervalSince(activityDate)) let calendar = Calendar.current let yearMonth = calendar.dateComponents([.year, .month], from: activityDate, to: now) if let years = yearMonth.year, years >= 1 { return I18n.Time.yearsAgo(years) } if let months = yearMonth.month, months >= 1 { return I18n.Time.monthsAgo(months) } if interval < 60 { return I18n.Time.justNow } if interval < 3600 { return I18n.Time.minutesAgo(max(1, Int(interval / 60))) } if interval < 86_400 { return I18n.Time.hoursAgo(max(1, Int(interval / 3600))) } return I18n.Time.daysAgo(max(1, Int(interval / 86_400))) } } struct MainHomeActiveCreatorSection_Previews: PreviewProvider { private static let previewImageUrl = "https://picsum.photos/500/500" static var previews: some View { MainHomeActiveCreatorSection( items: [ HomeActiveCreatorItem( creatorNickname: "크리에이터이름", creatorProfileImage: previewImageUrl, activityType: .live, activityAt: "2026-06-29T06:39:00Z", targetId: 1 ), HomeActiveCreatorItem( creatorNickname: "크리에이터이름", creatorProfileImage: previewImageUrl, activityType: .audio, activityAt: "2026-06-29T06:39:00Z", targetId: 2 ) ] ) .padding(.vertical, SodaSpacing.s20) .background(Color.black) .previewLayout(.sizeThatFits) } }