import SwiftUI struct CreatorChannelCommunityGridItem: View { let post: CreatorChannelCommunityPostItem let isOwnPost: Bool let onTapPurchase: () -> Void var body: some View { GeometryReader { proxy in ZStack { if isPaidLocked { Button(action: onTapPurchase) { Color.gray400 .overlay(paidPriceOverlay) } .buttonStyle(.plain) } else if let imageUrl = post.imageUrl, !imageUrl.isEmpty { DownsampledKFImage(url: URL(string: imageUrl), size: CGSize(width: proxy.size.width, height: proxy.size.width)) .frame(width: proxy.size.width, height: proxy.size.width) .aspectRatio(1, contentMode: .fill) .clipped() } else { Color.gray900 Text(fallbackText) .appFont(size: 12, weight: .medium) .foregroundColor(.white) .multilineTextAlignment(.center) .lineLimit(3) .padding(SodaSpacing.s8) } } .frame(width: proxy.size.width, height: proxy.size.width) .clipped() .overlay(alignment: .topTrailing) { if post.isPinned { Image("ic_pin") .resizable() .scaledToFit() .frame(width: 18, height: 18) .padding(6) .shadow(color: .black.opacity(0.45), radius: 2, x: 0, y: 1) .allowsHitTesting(false) } } } .aspectRatio(1, contentMode: .fit) } private var paidPriceOverlay: some View { VStack(spacing: SodaSpacing.s4) { Image("ic_new_community_lock") .resizable() .renderingMode(.template) .foregroundColor(.white) .frame(width: 24, height: 24) HStack(spacing: SodaSpacing.s6) { Image("ic_bar_cash") .resizable() .frame(width: 20, height: 20) Text("\(post.price)") .appFont(size: 16, weight: .medium) .foregroundColor(.black) } .padding(SodaSpacing.s8) .background(Color.white) .clipShape(Capsule()) } } private var isPaidLocked: Bool { post.price > 0 && post.existOrdered == false && isOwnPost == false } private var fallbackText: String { let content = post.content.trimmingCharacters(in: .whitespacesAndNewlines) guard !content.isEmpty else { return "-" } return String(content.prefix(18)) } }