feat(gift): 선물함 목록 컴포넌트를 추가한다

This commit is contained in:
Yu Sung
2026-10-08 12:32:46 +09:00
parent 9ee23677af
commit 104e6d93ad
3 changed files with 161 additions and 0 deletions
@@ -0,0 +1,100 @@
import SwiftUI
struct GiftBoxCardView: View {
let model: GiftListCardDisplayModel
let onTap: () -> Void
var body: some View {
Button(action: onTap) {
VStack(alignment: .leading, spacing: SodaSpacing.s14) {
HStack(alignment: .top, spacing: SodaSpacing.s8) {
DownsampledKFImage(
url: profileURL,
size: CGSize(width: SodaSpacing.s20, height: SodaSpacing.s20)
)
.background(Color.gray800)
.clipShape(Circle())
.accessibilityHidden(true)
Text(model.counterpartNickname)
.appFont(.caption3)
.foregroundColor(.white)
.fixedSize(horizontal: false, vertical: true)
.frame(maxWidth: .infinity, alignment: .leading)
if let dateText {
Text(dateText)
.appFont(.caption3)
.foregroundColor(.gray500)
.multilineTextAlignment(.trailing)
.fixedSize(horizontal: false, vertical: true)
}
}
.frame(minHeight: SodaSpacing.s20)
HStack(spacing: SodaSpacing.s12) {
VStack(alignment: .leading, spacing: SodaSpacing.s4) {
Text(model.statusDisplay.title)
.appFont(.body4)
.foregroundColor(.white)
if let subtitle {
Text(subtitle)
.appFont(.caption3)
.foregroundColor(.gray400)
}
}
.fixedSize(horizontal: false, vertical: true)
.frame(maxWidth: .infinity, alignment: .leading)
Image("ic_chevron_right")
.resizable()
.renderingMode(.template)
.scaledToFit()
.foregroundColor(.white)
.frame(width: SodaSpacing.s20, height: SodaSpacing.s20)
.accessibilityHidden(true)
}
.frame(minHeight: 39)
}
.multilineTextAlignment(.leading)
.padding(SodaSpacing.s14)
.frame(maxWidth: .infinity, minHeight: 101, alignment: .topLeading)
.background(Color.gray900)
.clipShape(RoundedRectangle(cornerRadius: SodaRadius.r14))
.contentShape(RoundedRectangle(cornerRadius: SodaRadius.r14))
}
.buttonStyle(.plain)
.accessibilityElement(children: .ignore)
.accessibilityLabel(accessibilityText)
.accessibilityAddTraits(.isButton)
.padding(.horizontal, SodaSpacing.s14)
}
private var profileURL: URL? {
guard let text = model.counterpartProfileImageUrl,
!text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty,
let url = URL(string: text),
let scheme = url.scheme?.lowercased(),
["https", "http"].contains(scheme),
let host = url.host, !host.isEmpty else { return nil }
return url
}
private var dateText: String? {
model.createdDateText.map { "\($0) 신청" }
}
private var subtitle: String? {
model.direction == .sent
? "\(model.sizeName) · \(model.categoryName)"
: model.statusDisplay.subtitle
}
private var accessibilityText: String {
[model.counterpartNickname, dateText, model.statusDisplay.title, subtitle,
model.direction == .received ? "\(model.sizeName) · \(model.categoryName)" : nil]
.compactMap { $0 }
.joined(separator: ", ")
}
}