feat(gift): 선물함 목록 컴포넌트를 추가한다
This commit is contained in:
@@ -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: ", ")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import SwiftUI
|
||||
|
||||
struct GiftBoxEmptyView: View {
|
||||
let onFeedback: () -> Void
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: SodaSpacing.s20) {
|
||||
Text("전달 예정인 선물이 없어요")
|
||||
.appFont(.heading1)
|
||||
.foregroundColor(.white)
|
||||
|
||||
Text("베타 기간에는 팬이 선물을 보내는 기능만 제공돼요.\n더 다양해진 선물 기능으로 곧 다시 만나요!")
|
||||
.appFont(.body3)
|
||||
.foregroundColor(.gray500)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
|
||||
Button(action: onFeedback) {
|
||||
Text("의견 남기기")
|
||||
.appFont(.body2)
|
||||
.foregroundColor(.white)
|
||||
.padding(SodaSpacing.s12)
|
||||
.background(Color.gray800)
|
||||
.clipShape(Capsule())
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
.multilineTextAlignment(.center)
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(SodaSpacing.s14)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import SwiftUI
|
||||
|
||||
struct GiftBoxInfoBannerView: View {
|
||||
let direction: GiftDirection
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: SodaSpacing.s8) {
|
||||
HStack(spacing: SodaSpacing.s6) {
|
||||
Image(systemName: "info.circle")
|
||||
.accessibilityHidden(true)
|
||||
Text(direction == .received ? "배송지 입력 기간 안내" : "사서함을 통해 안전하게 전달됩니다")
|
||||
.appFont(.body4)
|
||||
}
|
||||
.foregroundColor(.white)
|
||||
|
||||
Text(direction == .received
|
||||
? "알림을 받은 날부터 7일 이내에 배송지를 입력해 주세요. 기한 내 입력하지 않으면 선물이 반송됩니다."
|
||||
: "크리에이터 및 팬의 주소는 공개되지 않습니다. 선물은 소다라이브 사서함에 도착한 뒤 크리에이터에게 전달됩니다.")
|
||||
.appFont(.caption3)
|
||||
.foregroundColor(.gray500)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
.padding(SodaSpacing.s14)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.background(Color.gray900)
|
||||
.clipShape(RoundedRectangle(cornerRadius: SodaRadius.r14))
|
||||
.accessibilityElement(children: .combine)
|
||||
.padding(.horizontal, SodaSpacing.s14)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user