feat(gift): 받은 선물 상세를 추가한다
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
import SwiftUI
|
||||
|
||||
struct ReceivedGiftDetailContentView: View {
|
||||
let model: ReceivedGiftDetailDisplayModel
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: SodaSpacing.s32) {
|
||||
hero
|
||||
|
||||
if model.status == .undeliverable {
|
||||
undeliverableReason
|
||||
} else {
|
||||
if model.status != .canceled {
|
||||
GiftProgressView(progress: model.progress)
|
||||
}
|
||||
giftInfo
|
||||
recipientAddress
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
|
||||
private var hero: some View {
|
||||
VStack(alignment: .leading, spacing: SodaSpacing.s14) {
|
||||
if let statusLabel {
|
||||
Text(statusLabel)
|
||||
.appFont(.caption2)
|
||||
.foregroundColor(model.status == .undeliverable ? .red400 : .soda400)
|
||||
.padding(.horizontal, SodaSpacing.s8)
|
||||
.padding(.vertical, SodaSpacing.s4)
|
||||
.background(Color.gray900)
|
||||
.clipShape(RoundedRectangle(cornerRadius: SodaRadius.r4))
|
||||
}
|
||||
|
||||
Text(heroTitle)
|
||||
.appFont(.heading1)
|
||||
.foregroundColor(.white)
|
||||
.accessibilityAddTraits(.isHeader)
|
||||
|
||||
if model.status == .undeliverable {
|
||||
Text("보내주신 선물은 소다라이브 선물 정책에 따라 크리에이터에게 전달할 수 없는 품목으로 확인되었습니다.")
|
||||
.appFont(.body6)
|
||||
.foregroundColor(.gray500)
|
||||
}
|
||||
}
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
|
||||
private var statusLabel: String? {
|
||||
switch model.status {
|
||||
case .trackingRegistered: return "배송지 입력 완료"
|
||||
case .delivered: return "전달 완료"
|
||||
case .undeliverable: return "전달 불가"
|
||||
case .received, .arrivedAtMailbox, .inspectionCompleted, .canceled: return nil
|
||||
}
|
||||
}
|
||||
|
||||
private var heroTitle: String {
|
||||
switch model.status {
|
||||
case .trackingRegistered: return "배송지 입력이 완료되었어요"
|
||||
case .delivered: return "선물을 전달받았어요"
|
||||
case .undeliverable: return "전달할 수 없는 품목입니다"
|
||||
case .received, .arrivedAtMailbox, .inspectionCompleted, .canceled: return model.statusName
|
||||
}
|
||||
}
|
||||
|
||||
private var giftInfo: some View {
|
||||
GiftInfoSectionView(title: "선물 정보") {
|
||||
if let nickname = model.senderNickname {
|
||||
GiftInfoRow(title: "보낸 사람", value: nickname)
|
||||
}
|
||||
GiftInfoRow(title: "선물 사이즈", value: model.sizeName)
|
||||
GiftInfoRow(title: "카테고리", value: model.categoryName)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var recipientAddress: some View {
|
||||
if let address = model.recipientAddress {
|
||||
GiftInfoSectionView(title: "받는 주소") {
|
||||
GiftInfoRow(title: "이름", value: address.name)
|
||||
GiftInfoRow(title: "휴대폰 번호", value: address.phoneNumber)
|
||||
GiftInfoRow(title: "주소", value: address.address)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var undeliverableReason: some View {
|
||||
GiftInfoSectionView(title: "사유") {
|
||||
if let reason = model.undeliverableReason?.trimmingCharacters(in: .whitespacesAndNewlines),
|
||||
!reason.isEmpty {
|
||||
Text(reason)
|
||||
.appFont(.body6)
|
||||
.foregroundColor(.white)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
Divider()
|
||||
.overlay(Color.gray800)
|
||||
.accessibilityHidden(true)
|
||||
}
|
||||
|
||||
Text("해당 선물은 정책에 따라 폐기되며 반송되지 않습니다.")
|
||||
.appFont(.body6)
|
||||
.foregroundColor(.red400)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ReceivedGiftDetailActionBar: View {
|
||||
let onPolicy: () -> Void
|
||||
@State private var isNavigating = false
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: SodaSpacing.s8) {
|
||||
Button {
|
||||
guard !isNavigating else { return }
|
||||
isNavigating = true
|
||||
AppState.shared.setAppStep(step: GiftConstants.inquiryStep)
|
||||
} label: {
|
||||
secondaryLabel("문의하기", isEnabled: !isNavigating)
|
||||
}
|
||||
.disabled(isNavigating)
|
||||
|
||||
Button {
|
||||
onPolicy()
|
||||
} label: {
|
||||
secondaryLabel("선물 정책 확인")
|
||||
}
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.padding(.horizontal, SodaSpacing.s14)
|
||||
.padding(.vertical, SodaSpacing.s12)
|
||||
.frame(maxWidth: .infinity)
|
||||
.background(Color.black)
|
||||
.onAppear {
|
||||
isNavigating = false
|
||||
}
|
||||
}
|
||||
|
||||
private func secondaryLabel(_ title: String, isEnabled: Bool = true) -> some View {
|
||||
Text(title)
|
||||
.appFont(.body2)
|
||||
.foregroundColor(isEnabled ? .white : .gray500)
|
||||
.multilineTextAlignment(.center)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.padding(.horizontal, SodaSpacing.s16)
|
||||
.padding(.vertical, SodaSpacing.s12)
|
||||
.frame(maxWidth: .infinity, minHeight: SodaSpacing.s48)
|
||||
.background(Color.gray900)
|
||||
.clipShape(RoundedRectangle(cornerRadius: SodaRadius.r8))
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user