import SwiftUI struct CreatorChannelCurrentLiveSection: View { let currentLive: CreatorChannelLiveResponse? let onTapLive: (Int) -> Void init( currentLive: CreatorChannelLiveResponse?, onTapLive: @escaping (Int) -> Void = { _ in } ) { self.currentLive = currentLive self.onTapLive = onTapLive } var body: some View { if let currentLive { CreatorChannelCurrentLiveCard(live: currentLive) { onTapLive(currentLive.liveId) } .padding(.horizontal, SodaSpacing.s20) } } } private struct CreatorChannelCurrentLiveCard: View { let live: CreatorChannelLiveResponse let action: () -> Void var body: some View { Button(action: action) { HStack(alignment: .center, spacing: 0) { VStack(alignment: .leading, spacing: SodaSpacing.s4) { HStack(alignment: .center, spacing: SodaSpacing.s8) { LiveTagView() Text(live.relativeStartedAtText()) .appFont(size: 14, weight: .regular) .foregroundColor(Color.gray700) .lineLimit(1) .fixedSize(horizontal: true, vertical: false) } Text(live.title) .appFont(size: 18, weight: .bold) .foregroundColor(.black) .lineLimit(1) .truncationMode(.tail) } .frame(width: 262, alignment: .leading) Spacer(minLength: 0) priceBadge .frame(height: 78) .layoutPriority(1) } .padding(.leading, SodaSpacing.s24) .padding(.trailing, SodaSpacing.s14) .frame(maxWidth: .infinity, minHeight: 78, alignment: .leading) .background(cardBackground) .clipShape(Capsule()) } .buttonStyle(.plain) } private var cardBackground: LinearGradient { LinearGradient( colors: [Color(hex: "00FBE2"), Color(hex: "62CFFF")], startPoint: .leading, endPoint: .trailing ) } private var priceBadge: some View { ZStack { HStack(spacing: 2) { Image("ic_bar_cash") .resizable() .scaledToFit() Text(live.priceText) .appFont(size: 14, weight: .regular) .foregroundColor(.white) .lineLimit(1) .fixedSize(horizontal: true, vertical: false) } .padding(.horizontal, SodaSpacing.s6) .padding(.vertical, SodaSpacing.s4) .background(Color.black.opacity(0.4)) .clipShape(Capsule()) } } } private struct LiveTagView: View { var body: some View { HStack(alignment: .center, spacing: SodaSpacing.s4) { Circle() .fill(Color.red400) .frame(width: 8, height: 8) Text(I18n.HomeFollowing.liveTag) .appFont(size: 12, weight: .regular) .foregroundColor(.white) .lineLimit(1) } .padding(.horizontal, SodaSpacing.s6) .padding(.vertical, 2) .frame(height: 18) .background(Color.black) .clipShape(Capsule()) } } private extension CreatorChannelLiveResponse { func relativeStartedAtText(now: Date = Date()) -> String { DateParser.relativeTimeText(fromUTC: beginDateTimeUtc, fallback: beginDateTimeUtc, now: now) } var priceText: String { price > 0 ? price.comma() : I18n.LiveReservation.Item.free } } struct CreatorChannelCurrentLiveSection_Previews: PreviewProvider { static var previews: some View { CreatorChannelCurrentLiveSection( currentLive: CreatorChannelLiveResponse( liveId: 1, title: "라이브 제목", coverImageUrl: "https://picsum.photos/300/300", beginDateTimeUtc: "2026-07-01T00:30:00Z", price: 300, isAdult: true ) ) .background(Color.black) .previewLayout(.sizeThatFits) } }