From 2063603f32623b685bdba1c7a39fa28f7370f35a Mon Sep 17 00:00:00 2001 From: Yu Sung Date: Sat, 4 Jul 2026 22:44:57 +0900 Subject: [PATCH] =?UTF-8?q?refactor(creator):=20=ED=9B=84=EC=9B=90=20?= =?UTF-8?q?=EC=B9=B4=EB=93=9C=EB=A5=BC=20=EB=B6=84=EB=A6=AC=ED=95=9C?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CreatorChannelDonationCard.swift | 111 ++++++++++++++++++ .../CreatorChannelDonationSection.swift | 93 --------------- 2 files changed, 111 insertions(+), 93 deletions(-) create mode 100644 SodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationCard.swift diff --git a/SodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationCard.swift b/SodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationCard.swift new file mode 100644 index 00000000..35f6a8a9 --- /dev/null +++ b/SodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationCard.swift @@ -0,0 +1,111 @@ +import SwiftUI + +struct CreatorChannelDonationCard: View { + let donation: CreatorChannelDonationResponse + + var body: some View { + VStack(alignment: .leading, spacing: SodaSpacing.s14) { + header + + Text(donation.messageText) + .appFont(size: 16, weight: .regular) + .foregroundColor(.white) + .lineLimit(2) + .truncationMode(.tail) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.horizontal, SodaSpacing.s14) + } + .padding(.bottom, SodaSpacing.s14) + .frame(maxWidth: .infinity, alignment: .leading) + .background(Color.gray900) + .clipShape(RoundedRectangle(cornerRadius: SodaSpacing.s14, style: .continuous)) + } + + private var header: some View { + HStack(alignment: .center, spacing: SodaSpacing.s8) { + DownsampledKFImage( + url: URL(string: donation.profileImageUrl), + size: CGSize(width: 42, height: 42) + ) + .background(Color.white.opacity(0.6)) + .clipShape(Circle()) + + VStack(alignment: .leading, spacing: 2) { + Text(donation.nickname) + .appFont(size: 14, weight: .medium) + .foregroundColor(.black) + .lineLimit(1) + .truncationMode(.tail) + + Text(donation.relativeTimeText()) + .appFont(size: 14, weight: .regular) + .foregroundColor(Color.gray700) + .lineLimit(1) + } + .frame(maxWidth: .infinity, alignment: .leading) + + canBadge + } + .padding(SodaSpacing.s14) + .background(donation.tierColor) + } + + private var canBadge: some View { + HStack(spacing: 2) { + Image("ic_bar_cash") + .resizable() + .scaledToFit() + .frame(width: 18, height: 18) + + Text("\(donation.can)캔") + .appFont(size: 14, weight: .regular) + .foregroundColor(.white) + .lineLimit(1) + } + .padding(.horizontal, SodaSpacing.s6) + .padding(.vertical, SodaSpacing.s4) + .background(Color.gray900) + .clipShape(Capsule()) + } +} + +extension CreatorChannelDonationResponse { + var messageText: String { + let trimmedMessage = message.trimmingCharacters(in: .whitespacesAndNewlines) + return trimmedMessage.isEmpty ? "\(can)캔을 후원하였습니다" : trimmedMessage + } + + func relativeTimeText(now: Date = Date()) -> String { + DateParser.relativeTimeText(fromUTC: createdAtUtc, fallback: createdAtUtc, now: now) + } + + var tierColor: Color { + switch can { + case 1...50: + return Color(hex: "E2E2E2") + case 51...100: + return Color(hex: "73EE01") + case 101...500: + return Color(hex: "00EAFF") + default: + return Color(hex: "FF4C3C") + } + } +} + +struct CreatorChannelDonationCard_Previews: PreviewProvider { + static var previews: some View { + CreatorChannelDonationCard( + donation: CreatorChannelDonationResponse( + nickname: "팬 이름 501", + profileImageUrl: "https://picsum.photos/120/120?4", + can: 501, + message: "501캔 이상 후원 컬러를 확인하는 Preview 샘플입니다.", + createdAtUtc: "2026-07-03T03:41:00Z" + ) + ) + .padding(SodaSpacing.s14) + .background(Color.black) + .previewLayout(.sizeThatFits) + } +} diff --git a/SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelDonationSection.swift b/SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelDonationSection.swift index 9eb1f7af..80ec1b5f 100644 --- a/SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelDonationSection.swift +++ b/SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelDonationSection.swift @@ -110,99 +110,6 @@ private struct CreatorChannelDonationEmptyCard: View { } } -private struct CreatorChannelDonationCard: View { - let donation: CreatorChannelDonationResponse - - var body: some View { - VStack(alignment: .leading, spacing: SodaSpacing.s14) { - header - - Text(donation.messageText) - .appFont(size: 16, weight: .regular) - .foregroundColor(.white) - .lineLimit(2) - .truncationMode(.tail) - .frame(maxWidth: .infinity, alignment: .leading) - .padding(.horizontal, SodaSpacing.s14) - } - .padding(.bottom, SodaSpacing.s14) - .frame(maxWidth: .infinity, alignment: .leading) - .background(Color.gray900) - .clipShape(RoundedRectangle(cornerRadius: SodaSpacing.s14, style: .continuous)) - } - - private var header: some View { - HStack(alignment: .center, spacing: SodaSpacing.s8) { - DownsampledKFImage( - url: URL(string: donation.profileImageUrl), - size: CGSize(width: 42, height: 42) - ) - .background(Color.white.opacity(0.6)) - .clipShape(Circle()) - - VStack(alignment: .leading, spacing: 2) { - Text(donation.nickname) - .appFont(size: 14, weight: .medium) - .foregroundColor(.black) - .lineLimit(1) - .truncationMode(.tail) - - Text(donation.relativeTimeText()) - .appFont(size: 14, weight: .regular) - .foregroundColor(Color.gray700) - .lineLimit(1) - } - .frame(maxWidth: .infinity, alignment: .leading) - - canBadge - } - .padding(SodaSpacing.s14) - .background(donation.tierColor) - } - - private var canBadge: some View { - HStack(spacing: 2) { - Image("ic_bar_cash") - .resizable() - .scaledToFit() - .frame(width: 18, height: 18) - - Text("\(donation.can)캔") - .appFont(size: 14, weight: .regular) - .foregroundColor(.white) - .lineLimit(1) - } - .padding(.horizontal, SodaSpacing.s6) - .padding(.vertical, SodaSpacing.s4) - .background(Color.gray900) - .clipShape(Capsule()) - } -} - -private extension CreatorChannelDonationResponse { - var messageText: String { - let trimmedMessage = message.trimmingCharacters(in: .whitespacesAndNewlines) - return trimmedMessage.isEmpty ? "\(can)캔을 후원하였습니다" : trimmedMessage - } - - func relativeTimeText(now: Date = Date()) -> String { - DateParser.relativeTimeText(fromUTC: createdAtUtc, fallback: createdAtUtc, now: now) - } - - var tierColor: Color { - switch can { - case 1...50: - return Color(hex: "E2E2E2") - case 51...100: - return Color(hex: "73EE01") - case 101...500: - return Color(hex: "00EAFF") - default: - return Color(hex: "FF4C3C") - } - } -} - struct CreatorChannelDonationSection_Previews: PreviewProvider { static var previews: some View { VStack(spacing: SodaSpacing.s20) {