From 232e53d8a7f8c642a3ea5d1d6f07f5267623d6a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A0=ED=98=84=EC=95=84?= Date: Wed, 29 Oct 2025 15:14:37 +0900 Subject: [PATCH 1/5] =?UTF-8?q?[FEAT]=20=EC=A3=BC=EB=AC=B8=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=B0=8F=20=EC=98=81?= =?UTF-8?q?=EC=88=98=EC=A6=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- StockMate/.DS_Store | Bin 6148 -> 6148 bytes .../feature/orders/ui/OrderDetailView.swift | 107 ++++++--- .../app/feature/orders/ui/ReceiptView.swift | 214 ++++++++++++------ 3 files changed, 213 insertions(+), 108 deletions(-) diff --git a/StockMate/.DS_Store b/StockMate/.DS_Store index 8b131bc6d6be2f3fa147df58dc1424275991ebff..9b2b289a6cc938aeb964150a839318a8b9520a06 100644 GIT binary patch delta 70 zcmZoMXffCj%gW4>X)`&2)r{j&>B_Ag;l~|;9G%IhSh(Bd!1Fbq!4&n;j80cL}Z Ng`XHVvvd6A2LNgN7oq?F diff --git a/StockMate/StockMate/app/feature/orders/ui/OrderDetailView.swift b/StockMate/StockMate/app/feature/orders/ui/OrderDetailView.swift index 1d8054e..3fd73db 100644 --- a/StockMate/StockMate/app/feature/orders/ui/OrderDetailView.swift +++ b/StockMate/StockMate/app/feature/orders/ui/OrderDetailView.swift @@ -21,15 +21,16 @@ struct OrderDetailView: View { VStack(spacing: 16) { // ✅ 주문 정보 - VStack(alignment: .leading, spacing: 8) { + VStack(alignment: .leading, spacing: 6) { Text(formatDate(order.createdAt)) .font(.system(size: 15, weight: .semibold)) - Text("주문번호: \(order.orderNumber)") - .font(.system(size: 14)) - .foregroundColor(.gray) + .padding(.bottom, 4) + + infoRow("주문번호", order.orderNumber) HStack { - Text("상태:") - .font(.system(size: 14, weight: .semibold)) + Text("상태") + .font(.system(size: 14)) + Spacer() Text(statusText(order.orderStatus)) .font(.system(size: 13, weight: .semibold)) .padding(.horizontal, 10) @@ -37,14 +38,15 @@ struct OrderDetailView: View { .background(statusBdColor(order.orderStatus)) .foregroundColor(statusColor(order.orderStatus)) .cornerRadius(12) + .padding(.leading,4) } + } .frame(maxWidth: .infinity, alignment: .leading) // ✅ 이거 추가 .padding(.all, 20) .background(Color.white) .cornerRadius(16) .shadow(color: .black.opacity(0.05), radius: 3, y: 2) -// .padding(.horizontal, 20) // ✅ 배송 정보 @@ -52,22 +54,29 @@ struct OrderDetailView: View { Text("배송정보") .font(.system(size: 15, weight: .semibold)) .padding(.bottom, 4) - Text(order.userInfo?.owner ?? "-") - Text(order.userInfo?.address ?? "-") - if !(order.etc ?? "").isEmpty { - Text(order.etc ?? "") - } - if let email = order.userInfo?.email { - Text(email) - .foregroundColor(.gray) - } + + infoRow("주문자명", order.userInfo?.owner ?? "-") + infoRow("주소", order.userInfo?.address ?? "-") + // ✅ 운송장정보 안전 처리 + let trackingText: String = { + if let carrier = order.carrier, + let trackingNo = order.trackingNumber, + !carrier.isEmpty, + !trackingNo.isEmpty { + return "\(carrier): \(trackingNo)" + } + return "-" + }() + infoRow("운송장번호", trackingText) + + infoRow("요청사항", order.etc ?? "") } .frame(maxWidth: .infinity, alignment: .leading) // ✅ 여기도 추가 .padding(.all, 20) .background(Color.white) .cornerRadius(16) .shadow(color: .black.opacity(0.05), radius: 3, y: 2) -// .padding(.horizontal, 20) + // ✅ 주문 상품 OrderSectionCard { @@ -138,7 +147,8 @@ struct OrderDetailView: View { // ✅ 하단 버튼 HStack(spacing: 12) { // 왼쪽: 영수증 확인 - Button(action: {}) { + // 왼쪽: 영수증 확인 + NavigationLink(destination: ReceiptView(orderId: order.id)) { Text("영수증 확인") .font(.system(size: 15, weight: .semibold)) .foregroundColor(Color.Primary) @@ -152,24 +162,55 @@ struct OrderDetailView: View { .cornerRadius(10) } - // 오른쪽: 주문 취소 - Button(action: { - // 주문취소 처리 - Task { - await orderViewModel.cancelOrder(orderId: orderId) + + // 오른쪽 버튼: 주문 상태에 따라 변경 + if order.orderStatus == "ORDER_COMPLETED" { + // 주문 완료 → "주문취소" 버튼 + Button(action: { + Task { + await orderViewModel.cancelOrder(orderId: orderId) + } + }) { + Text("주문 취소") + .font(.system(size: 15, weight: .semibold)) + .frame(maxWidth: .infinity) + .frame(height: 48) + .background(Color(hex: "#1D4ED8")) + .foregroundColor(.white) + .cornerRadius(10) } - - }) { - Text("주문 취소") - .font(.system(size: 15, weight: .semibold)) - .frame(maxWidth: .infinity) - .frame(height: 48) - .background(Color(hex: "#1D4ED8")) - .foregroundColor(.white) - .cornerRadius(10) + + } else if order.orderStatus == "ORDER_COMPLETED" { + // 배송 완료 → "입고 하기" 버튼 + Button(action: { + // TODO: 입고 처리 버튼 + }) { + Text("입고 처리") + .font(.system(size: 15, weight: .semibold)) + .frame(maxWidth: .infinity) + .frame(height: 48) + .background(Color(hex: "#1D4ED8")) + .foregroundColor(.white) + .cornerRadius(10) + } + + } else { + // 👉 나머지 상태 → "재주문하기" 버튼 + Button(action: { + // TODO: 평가 액션 처리 + }) { + Text("재주문하기") + .font(.system(size: 15, weight: .semibold)) + .frame(maxWidth: .infinity) + .frame(height: 48) + .background(Color(hex: "#1D4ED8")) + .foregroundColor(.white) + .cornerRadius(10) + } + } } - .padding(.top, 10) + .padding(.top, 5) } .padding(.horizontal, 20) // ✅ 전체 섹션 동일 여백 diff --git a/StockMate/StockMate/app/feature/orders/ui/ReceiptView.swift b/StockMate/StockMate/app/feature/orders/ui/ReceiptView.swift index 59aec01..9e690f1 100644 --- a/StockMate/StockMate/app/feature/orders/ui/ReceiptView.swift +++ b/StockMate/StockMate/app/feature/orders/ui/ReceiptView.swift @@ -7,70 +7,106 @@ import SwiftUI import PDFKit +import UIKit enum PDFType { case a4 case receipt80mm } -// TODO: API 연결 후 주문 상세 페이지와 연결 + struct ReceiptView: View { + let orderId: Int + @StateObject private var detailViewModel = OrderDetailViewModel() - @State var paymentType = "예치금" - @State var approvalNumber = "202510300743" - @State var date = "2025/10/30 07:43:54" - @State var orderNumber = "SMO-2" - @State var itemName = "배터리-트랜스미터" - @State var quantity = 1 - @State var price = 5273 - @State var sellerName = "박시영" - @State var businessNumber = "888777776666" - @State var phone = "010-2596-2352" - @State var address = "서울특별시 성동구 동일로 259 3층" - - var vat: Int { Int(Double(price) * 0.1) } - var total: Int { price + vat } + @State var sellerName = "홍길동" + @State var businessNumber = "215-87-12345" // 형식만 맞춘 랜덤번호 + @State var phone = "02-567-8901" + @State var address = "서울특별시 금천구 가산동 459-9" + var body: some View { ScrollView { - VStack(alignment: .leading) { - receiptContent - - HStack { - pdfButton(type: .a4, title: "A4 PDF") - pdfButton(type: .receipt80mm, title: "영수증 PDF") + if detailViewModel.isLoading { + ProgressView() + .frame(maxWidth: .infinity, maxHeight: .infinity) + } else if let order = detailViewModel.order { + VStack(alignment: .leading) { + receiptContent(order: order) + + Button { + generatePDF(type: .receipt80mm, order: order) + } label: { + Text("영수증 PDF 저장") + .frame(maxWidth: .infinity) + .padding() + .background(Color.blue) + .foregroundColor(.white) + .cornerRadius(8) + } + .padding(.horizontal) + .padding(.bottom) + } - .padding(.horizontal) - .padding(.bottom) + .background(Color.white) + .cornerRadius(12) + .padding() } - .background(Color.white) - .cornerRadius(12) - .padding() } .background(Color.Light) .navigationTitle("영수증") .navigationBarTitleDisplayMode(.inline) + .task { + await detailViewModel.fetchOrderDetail(orderId: orderId) + } } - - private var receiptContent: some View { - VStack(alignment: .leading, spacing: 16) { + + private func receiptContent(order: OrderResponseItem) -> some View { + let total = order.totalPrice + let vat = Int(Double(total) * 10 / 110) // 부가세액 + let supplyPrice = total - vat // 공급가액 + + return VStack(alignment: .leading, spacing: 16) { section("결제 정보") { Divider() - row("거래종류", paymentType) - row("승인번호", approvalNumber) - row("거래일시", date) + if order.paymentType == "DEPOSIT" { + row("거래종류", "예치금") + } else { + row("결제수단", "신용카드") + } + row("승인번호", formattedApprovalNumber(order.createdAt)) + row("거래일시", formattedDate(order.createdAt)) + } .padding(4) .padding(.top,5) section("구매정보") { Divider() - row("주문번호", orderNumber) - row("상품명", "\(itemName), \(quantity)개") - row("공급가액", "\(price)원") - row("부가세액", "\(vat)원") - row("합계금액", "\(total)원", highlight: true) + VStack(spacing: 8){ + row("주문번호", order.orderNumber) + VStack{ + // 상품명 라벨과 첫 번째 상품 같은 라인 + if let first = order.orderItems.first { + HStack { + Text("상품명") + Spacer() + Text("\(first.partDetail.korName) \(first.amount)개") + } + } + // 나머지는 label 없이 아래에 + ForEach(order.orderItems.dropFirst(), id: \.partId) { item in + HStack { + Spacer() // label 영역만큼 들여쓰기 효과 + Text("\(item.partDetail.korName) \(item.amount)개") + } + } + } + row("공급가액", "\(formatPrice(supplyPrice))원") + row("부가세액", "\(formatPrice(vat))원") + row("합계금액", "\(formatPrice(total))원", highlight: true) + } } .padding(4) .padding(.top) @@ -104,7 +140,7 @@ struct ReceiptView: View { .multilineTextAlignment(.leading) .frame(maxWidth: .infinity, alignment: .leading) .lineSpacing(4) - .padding(.leading, 2) // ✅ 총알 뒤 문장 들여쓰기 추가 + .padding(.leading, 2) // 문장 들여쓰기 추가 } .padding() @@ -129,54 +165,82 @@ struct ReceiptView: View { } } - private func pdfButton(type: PDFType, title: String) -> some View { - Button(action: { - generatePDF(type: type) - }) { - Text(title) - .frame(maxWidth: .infinity) - .padding() - .background(Color.blue) - .foregroundColor(.white) - .cornerRadius(8) - } - } - - private func generatePDF(type: PDFType) { - let content = receiptContent - let renderer = ImageRenderer(content: content) + private func generatePDF(type: PDFType, order: OrderResponseItem) { + let view = receiptContent(order: order) // ✅ 실제 View 생성 + let renderer = ImageRenderer(content: view) let width: CGFloat - let height: CGFloat = 2000 - switch type { case .a4: width = 595.2 // A4 width in pt case .receipt80mm: width = 226.77 // 80mm in pt } renderer.scale = UIScreen.main.scale + + // ✅ cgImage 기반 안전 처리 + if let cgImage = renderer.cgImage { + let uiImage = UIImage(cgImage: cgImage) + let pdfDoc = PDFDocument() + if let pdfPage = PDFPage(image: uiImage) { + pdfDoc.insert(pdfPage, at: 0) + } + + // ✅ 주문번호 기반 파일명 + let fileName = "receipt_\(order.orderNumber).pdf" + let tempURL = FileManager.default.temporaryDirectory.appendingPathComponent(fileName) + + if pdfDoc.write(to: tempURL) { + let av = UIActivityViewController(activityItems: [tempURL], applicationActivities: nil) + + if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, + let rootVC = windowScene.windows.first?.rootViewController { + av.popoverPresentationController?.sourceView = rootVC.view + rootVC.present(av, animated: true) + } + } + } + + } +} - if let image = renderer.uiImage { - let pdfDoc = PDFDocument() - let pdfPage = PDFPage(image: image) - pdfDoc.insert(pdfPage!, at: 0) - - let tempURL = FileManager.default.temporaryDirectory.appendingPathComponent("receipt.pdf") - if pdfDoc.write(to: tempURL) { - let av = UIActivityViewController(activityItems: [tempURL], applicationActivities: nil) - if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, - let rootVC = windowScene.windows.first?.rootViewController { - rootVC.present(av, animated: true) - } -// let av = UIActivityViewController(activityItems: [tempURL], applicationActivities: nil) -// UIApplication.shared.windows.first?.rootViewController?.present(av, animated: true) - } - } +//struct ReceiptView_Previews: PreviewProvider { +// static var previews: some View { +// ReceiptView() +// } +//} + +func formattedDate(_ timestamp: String) -> String { + let inputFormatter = DateFormatter() + inputFormatter.locale = Locale(identifier: "ko_KR") + inputFormatter.timeZone = TimeZone(abbreviation: "UTC") + inputFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS" + + guard let date = inputFormatter.date(from: timestamp) else { + return timestamp } + + let outputFormatter = DateFormatter() + outputFormatter.locale = Locale(identifier: "ko_KR") + outputFormatter.timeZone = TimeZone.current + outputFormatter.dateFormat = "yyyy/MM/dd HH:mm:ss" + + return outputFormatter.string(from: date) } -struct ReceiptView_Previews: PreviewProvider { - static var previews: some View { - ReceiptView() +func formattedApprovalNumber(_ timestamp: String) -> String { + let inputFormatter = DateFormatter() + inputFormatter.locale = Locale(identifier: "ko_KR") + inputFormatter.timeZone = TimeZone(abbreviation: "UTC") + inputFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS" + + guard let date = inputFormatter.date(from: timestamp) else { + return timestamp } + + let outputFormatter = DateFormatter() + outputFormatter.locale = Locale(identifier: "ko_KR") + outputFormatter.timeZone = TimeZone.current + outputFormatter.dateFormat = "yyyyMMddHHmm" // ✅ 승인번호 포맷 + + return outputFormatter.string(from: date) } From 4405f9b673f5ee80c4224fce9bbc7375a03ed1f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A0=ED=98=84=EC=95=84?= Date: Thu, 30 Oct 2025 16:01:43 +0900 Subject: [PATCH 2/5] =?UTF-8?q?[FEAT]=20=EC=A3=BC=EB=AC=B8=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=98=88=EC=B9=98?= =?UTF-8?q?=EA=B8=88=20=EC=B6=A9=EC=A0=84=20API=20=EC=97=B0=EB=8F=99,?= =?UTF-8?q?=EB=B0=B0=EC=86=A1=EC=A0=95=EB=B3=B4=20UI=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=20=EB=B0=8F=20=EB=B0=B0=EC=86=A1=EC=83=81=ED=83=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- StockMate/StockMate/ContentView.swift | 50 ++++++-- .../feature/cart/ui/DeliveryStatusView.swift | 106 ++++++++++++++++ .../feature/orders/ui/OrderDetailView.swift | 58 ++++++++- .../app/feature/orders/ui/OrderInfoView.swift | 100 +++++++++++---- .../app/feature/payment/data/PaymentApi.swift | 40 ++++++ .../payment/data/PaymentRepositoryImpl.swift | 48 ++++++++ .../domain/PaymentRepositoryProtocol.swift | 14 +++ .../payment/ui/DepositChargeView.swift | 115 ++++++++++++++++++ .../payment/viewmodel/DepositViewModel.swift | 46 +++++++ .../check.imageset/Contents.json | 21 ++++ .../Assets.xcassets/check.imageset/check.svg | 8 ++ .../deposit_background.imageset/Contents.json | 23 ++++ .../deposit_background@1x.png | Bin 0 -> 3184 bytes .../deposit_background@2x.png | Bin 0 -> 6499 bytes .../deposit_background@3x.png | Bin 0 -> 10386 bytes .../dottedline.imageset/Contents.json | 21 ++++ .../dottedline.imageset/dottedline.svg | 6 + .../hourglass.imageset/Contents.json | 21 ++++ .../hourglass.imageset/hourglass.svg | 8 ++ .../pindrop.imageset/Contents.json | 21 ++++ .../pindrop.imageset/pindrop.svg | 9 ++ .../rocket.imageset/Contents.json | 21 ++++ .../rocket.imageset/rocket.svg | 8 ++ .../uploadprogress.imageset/Contents.json | 21 ++++ .../uploadprogress.svg | 8 ++ StockMate/StockMate/resources/Color.swift | 2 + 26 files changed, 735 insertions(+), 40 deletions(-) create mode 100644 StockMate/StockMate/app/feature/cart/ui/DeliveryStatusView.swift create mode 100644 StockMate/StockMate/app/feature/payment/data/PaymentApi.swift create mode 100644 StockMate/StockMate/app/feature/payment/data/PaymentRepositoryImpl.swift create mode 100644 StockMate/StockMate/app/feature/payment/domain/PaymentRepositoryProtocol.swift create mode 100644 StockMate/StockMate/app/feature/payment/ui/DepositChargeView.swift create mode 100644 StockMate/StockMate/app/feature/payment/viewmodel/DepositViewModel.swift create mode 100644 StockMate/StockMate/resources/Assets.xcassets/check.imageset/Contents.json create mode 100644 StockMate/StockMate/resources/Assets.xcassets/check.imageset/check.svg create mode 100644 StockMate/StockMate/resources/Assets.xcassets/deposit_background.imageset/Contents.json create mode 100644 StockMate/StockMate/resources/Assets.xcassets/deposit_background.imageset/deposit_background@1x.png create mode 100644 StockMate/StockMate/resources/Assets.xcassets/deposit_background.imageset/deposit_background@2x.png create mode 100644 StockMate/StockMate/resources/Assets.xcassets/deposit_background.imageset/deposit_background@3x.png create mode 100644 StockMate/StockMate/resources/Assets.xcassets/dottedline.imageset/Contents.json create mode 100644 StockMate/StockMate/resources/Assets.xcassets/dottedline.imageset/dottedline.svg create mode 100644 StockMate/StockMate/resources/Assets.xcassets/hourglass.imageset/Contents.json create mode 100644 StockMate/StockMate/resources/Assets.xcassets/hourglass.imageset/hourglass.svg create mode 100644 StockMate/StockMate/resources/Assets.xcassets/pindrop.imageset/Contents.json create mode 100644 StockMate/StockMate/resources/Assets.xcassets/pindrop.imageset/pindrop.svg create mode 100644 StockMate/StockMate/resources/Assets.xcassets/rocket.imageset/Contents.json create mode 100644 StockMate/StockMate/resources/Assets.xcassets/rocket.imageset/rocket.svg create mode 100644 StockMate/StockMate/resources/Assets.xcassets/uploadprogress.imageset/Contents.json create mode 100644 StockMate/StockMate/resources/Assets.xcassets/uploadprogress.imageset/uploadprogress.svg diff --git a/StockMate/StockMate/ContentView.swift b/StockMate/StockMate/ContentView.swift index d576e34..ccb290e 100644 --- a/StockMate/StockMate/ContentView.swift +++ b/StockMate/StockMate/ContentView.swift @@ -6,28 +6,52 @@ // import SwiftUI +// +//struct DottedLine: View { +// var body: some View { +// Rectangle() +// .fill(Color.clear) +// .frame(height: 1) +// .overlay( +// Rectangle() +// .stroke(style: StrokeStyle(lineWidth: 1, dash: [3])) // <- 점선 패턴 +// .foregroundColor(.gray) +// ) +// } +//} struct ContentView: View { var body: some View { VStack { - Image(systemName: "globe") - .imageScale(.large) - .foregroundStyle(.tint) - Text("임시 화면") + Text("위쪽") +// DottedLine() + Text("아래쪽") } .padding() - HStack(spacing: 20) { - Image(systemName: "gearshape") - .font(.system(size: 40)) - .foregroundColor(.blue) - - Image(systemName: "lightbulb") - .font(.system(size: 40)) - .foregroundColor(.cyan) - } } } +//struct ContentView: View { +// var body: some View { +// VStack { +// Image(systemName: "globe") +// .imageScale(.large) +// .foregroundStyle(.tint) +// Text("임시 화면") +// } +// .padding() +// HStack(spacing: 20) { +// Image(systemName: "gearshape") +// .font(.system(size: 40)) +// .foregroundColor(.blue) +// +// Image(systemName: "lightbulb") +// .font(.system(size: 40)) +// .foregroundColor(.cyan) +// } +// } +//} + #Preview { ContentView() } diff --git a/StockMate/StockMate/app/feature/cart/ui/DeliveryStatusView.swift b/StockMate/StockMate/app/feature/cart/ui/DeliveryStatusView.swift new file mode 100644 index 0000000..2825687 --- /dev/null +++ b/StockMate/StockMate/app/feature/cart/ui/DeliveryStatusView.swift @@ -0,0 +1,106 @@ +// +// DeliveryStatusView.swift +// StockMate +// +// Created by Admin on 10/30/25. +// + +import SwiftUI + +struct DeliveryStep { + let title: String + let iconName: String // Asset 이름 +} + + +struct DeliveryStatusView: View { + let steps: [DeliveryStep] = [ + DeliveryStep(title: "결제완료", iconName: "check"), + DeliveryStep(title: "승인대기중", iconName: "hourglass"), + DeliveryStep(title: "상품준비중", iconName: "uploadprogress"), + DeliveryStep(title: "배송중", iconName: "rocket"), + DeliveryStep(title: "배송완료", iconName: "pindrop") + ] + + let currentStep: Int + + var body: some View { + GeometryReader { geo in + HStack(alignment: .center, spacing: 0) { + ForEach(0.. String { switch status { - case "ORDER_COMPLETED": return "주문 완료" + case "ORDER_COMPLETED": return "주문 완료" // + case "PAY_COMPLETED": return "결제 완료" + case "PENDING_APPROVAL": return "승인 대기" // + case "FAILED": return "결제 실패" case "PENDING_SHIPPING": return "출고 대기" - case "REJECTED": return "출고 반려" - case "SHIPPING": return "배송 중" + case "SHIPPING": return "배송중" + case "PENDING_RECEIVING": return "입고 대기" + case "REJECTED": return "주문 반려" case "DELIVERED": return "배송 완료" case "RECEIVED": return "입고 완료" + case "REFUNDED": return "환불 완료" + case "REFUND_REJECTED": return "환불 반려" case "CANCELLED": return "주문 취소" default: return "알 수 없음" } @@ -262,12 +275,18 @@ struct OrderDetailView: View { func statusColor(_ status: String) -> Color { switch status { case "ORDER_COMPLETED": return .StatusGreen + case "PAY_COMPLETED": return .StatusGreen + case "PENDING_APPROVAL": return .Warning + case "FAILED": return .Danger case "PENDING_SHIPPING": return .InvUse - case "REJECTED": return .Danger case "SHIPPING": return .Transfer + case "PENDING_RECEIVING": return .Secondary + case "REJECTED": return .Danger case "DELIVERED": return .Secondary case "RECEIVED": return .StatusPurple - case "CANCELLED": return .gray + case "REFUNDED": return .Gray + case "REFUND_REJECTED": return .Gray + case "CANCELLED": return .Gray default: return .gray.opacity(0.6) } } @@ -275,11 +294,17 @@ struct OrderDetailView: View { func statusBdColor(_ status: String) -> Color { switch status { case "ORDER_COMPLETED": return .StatusGreenBg + case "PAY_COMPLETED": return .StatusGreenBg + case "PENDING_APPROVAL": return .WarningBg + case "FAILED": return .DangerBg case "PENDING_SHIPPING": return .InvUseBg - case "REJECTED": return .DangerBg case "SHIPPING": return .TransferBg + case "PENDING_RECEIVING": return .LightBlue04 + case "REJECTED": return .DangerBg case "DELIVERED": return .LightBlue04 case "RECEIVED": return .StatusPurpleBg + case "REFUNDED": return Color(hex: "#EEEEEF") + case "REFUND_REJECTED": return Color(hex: "#EEEEEF") case "CANCELLED": return Color(hex: "#EEEEEF") default: return .gray.opacity(0.6) } @@ -319,3 +344,24 @@ func formatDateOrDash(_ isoDate: String?) -> String { guard comps.count == 3 else { return "-" } return "\(comps[0])년 \(comps[1])월 \(comps[2])일" } + +func deliveryStep(for status: String) -> Int { + //6 -> 전체 회색 + //4 -> 전체 파란색 + switch status { + case "ORDER_COMPLETED": return 0 // 주문 완료 + case "PAY_COMPLETED": return 0 // 결제 완료 + case "PENDING_APPROVAL": return 1 // 승인 대기 + case "FAILED": return 6 // 결제 실패 + case "PENDING_SHIPPING": return 2 // 출고 대기 + case "SHIPPING": return 3 // 배송중 + case "PENDING_RECEIVING": return 4 // 입고 대기 + case "REJECTED": return 6 // 승인 반려 + case "DELIVERED": return 4 // 배송 완료 + case "RECEIVED": return 4 // 입고 완료 + case "REFUNDED": return 6 // 환불 완료 + case "REFUND_REJECTED": return 6 // 환불 반려 + case "CANCELLED": return 6 // 주문 취소 + default: return 6 + } +} diff --git a/StockMate/StockMate/app/feature/orders/ui/OrderInfoView.swift b/StockMate/StockMate/app/feature/orders/ui/OrderInfoView.swift index b167671..701c358 100644 --- a/StockMate/StockMate/app/feature/orders/ui/OrderInfoView.swift +++ b/StockMate/StockMate/app/feature/orders/ui/OrderInfoView.swift @@ -20,6 +20,7 @@ enum ShippingDateOption { struct OrderInfoView: View { @ObservedObject var cartViewModel: CartViewModel @StateObject var orderViewModel = OrderViewModel() + @StateObject private var depositViewModel = DepositViewModel() @State private var paymentType: PaymentType = .deposit @State private var shippingDateOption: ShippingDateOption = .today @@ -74,7 +75,10 @@ struct OrderInfoView: View { .background(Color.Light) .navigationTitle("주문/결제") .navigationBarTitleDisplayMode(.inline) - .task { await cartViewModel.fetchCart() } + .task { + await cartViewModel.fetchCart() + await depositViewModel.fetchDepositAmount() + } .edgesIgnoringSafeArea(.bottom) .onChange(of: orderViewModel.isOrderSuccess) { success in if success { @@ -84,7 +88,16 @@ struct OrderInfoView: View { } } } + // ✅ 충전 bottom sheet 연결 + .sheet(isPresented: $depositViewModel.showChargeSheet) { + DepositChargeView(viewModel: depositViewModel) + .presentationDetents([.fraction(0.80)]) // 시트 높이 85% +// .presentationDragIndicator(.visible) + } + } + + } // MARK: - UI 구성 View @@ -164,35 +177,80 @@ extension OrderInfoView { .cornerRadius(16) } } - private var paymentSection: some View { - VStack(alignment: .leading) { - Text("결제 수단") - .font(.headline) - .padding(.leading, 5) + ZStack { + // 배경 이미지 적용 + Image("deposit_background") // ← 에셋에 넣은 이미지 이름 + .resizable() + .scaledToFill() + .frame(height: 185) + .clipped() + .cornerRadius(16.39) - VStack(alignment: .leading, spacing: 5) { - HStack{ - RadioButtonRow(title: "예치금 (잔액 ₩1,200,000)", selected: paymentType == .deposit) { - paymentType = .deposit + VStack(alignment: .leading, spacing: 12) { + VStack (alignment: .leading, spacing: 13){ + HStack { + Text("사용 가능 예치금") + .font(.system(size: 17, weight: .bold)) + .padding(.leading, 5) + .padding(.top, 25) + .foregroundColor(Color.white) } - Spacer() - } - .frame(height: 35) - HStack{ - RadioButtonRow(title: "직접 결제", selected: paymentType == .card) { - paymentType = .card + + HStack { + // 예치금 금액 표시 + if depositViewModel.isLoading { + ProgressView() + .tint(.white) + } else { + Text("₩\(formatPrice(depositViewModel.balance))") + .font(.system(size: 26, weight: .bold)) + .foregroundColor(Color.white) + } + + // Text("₩\(cartViewModel.depositBalance?.formatted() ?? "0")") + // .font(.system(size: 22, weight: .bold)) } + } + + Spacer() + + HStack { Spacer() + Button { + depositViewModel.showChargeSheet = true // <-- $ 없이 할당 + } label: { + Text("충전") + .foregroundColor(Color.Primary) + .font(.system(size: 14, weight: .bold)) + .padding(.vertical, 6) + .padding(.horizontal, 14) + .background(Color.white) + .cornerRadius(20) + } + .padding(.trailing, 5) + +// Button { +// depositViewModel.showChargeSheet = true +// } label: { +// Text("충전") +// .foregroundColor(Color.Primary) +// .font(.system(size: 14, weight: .bold)) +// .padding(.vertical, 6) +// .padding(.horizontal, 14) +// .background(Color.white) +// .cornerRadius(20) +// } +// .padding(.trailing, 5) } - .frame(height: 35) + .padding(.bottom, 25) } - .padding() - .frame(maxWidth: .infinity) - .background(Color.white) - .cornerRadius(16) + .frame(height: 185) + .padding(20) } + .frame(maxWidth: .infinity) } + private var shippingDateSection: some View { VStack(alignment: .leading) { diff --git a/StockMate/StockMate/app/feature/payment/data/PaymentApi.swift b/StockMate/StockMate/app/feature/payment/data/PaymentApi.swift new file mode 100644 index 0000000..53346c3 --- /dev/null +++ b/StockMate/StockMate/app/feature/payment/data/PaymentApi.swift @@ -0,0 +1,40 @@ +// +// PaymentApi.swift +// StockMate +// +// Created by Admin on 10/29/25. +// + + +import Foundation +import Alamofire + + +struct PaymentAmount: Decodable { + let id: Int + let balance: Int + let userId: Int +} + + +enum PaymentApi { + // 예치금 조회 + static func getPaymentAmount() -> DataRequest { + let url = ApiClient.baseURL + "api/v1/payment/amount" + return ApiClient.shared.request(url, method: .get) + } + + // 예치금 충전 + static func chargeDeposit(amount: Int) -> DataRequest { + let url = ApiClient.baseURL + "api/v1/payment/charge" + let params: [String: Any] = [ + "amount": amount + ] + return ApiClient.shared.request( + url, + method: .post, + parameters: params, + encoding: URLEncoding.queryString + ) + } +} diff --git a/StockMate/StockMate/app/feature/payment/data/PaymentRepositoryImpl.swift b/StockMate/StockMate/app/feature/payment/data/PaymentRepositoryImpl.swift new file mode 100644 index 0000000..625b887 --- /dev/null +++ b/StockMate/StockMate/app/feature/payment/data/PaymentRepositoryImpl.swift @@ -0,0 +1,48 @@ +// +// PaymentRepositoryImpl.swift +// StockMate +// +// Created by Admin on 10/29/25. +// + + +import Foundation +import Alamofire + + +final class PaymentRepositoryImpl: PaymentRepositoryProtocol { + + func fetchDepositAmount() async -> AppResult { + let request = PaymentApi.getPaymentAmount() + let result = await safeApi(request, decodeTo: ApiResponse.self) + + switch result { + case .success(let response): + if let data = response.data { + return .success(data) + } else { + return .failure(.init( + code: response.status, + message: response.message, + underlying: nil + )) + } + + case .failure(let error): + return .failure(error) + } + } + + func chargeDeposit(amount: Int) async -> AppResult { + let request = PaymentApi.chargeDeposit(amount: amount) + let result = await safeApi(request, decodeTo: ApiResponse.self) + + switch result { + case .success(let response): + return .success(response.data ?? response.message) + + case .failure(let error): + return .failure(error) + } + } +} diff --git a/StockMate/StockMate/app/feature/payment/domain/PaymentRepositoryProtocol.swift b/StockMate/StockMate/app/feature/payment/domain/PaymentRepositoryProtocol.swift new file mode 100644 index 0000000..150ab26 --- /dev/null +++ b/StockMate/StockMate/app/feature/payment/domain/PaymentRepositoryProtocol.swift @@ -0,0 +1,14 @@ +// +// PaymentRepositoryProtocol.swift +// StockMate +// +// Created by Admin on 10/29/25. +// + +import Foundation +import Alamofire + +protocol PaymentRepositoryProtocol { + func fetchDepositAmount() async -> AppResult + func chargeDeposit(amount: Int) async -> AppResult +} diff --git a/StockMate/StockMate/app/feature/payment/ui/DepositChargeView.swift b/StockMate/StockMate/app/feature/payment/ui/DepositChargeView.swift new file mode 100644 index 0000000..77987f5 --- /dev/null +++ b/StockMate/StockMate/app/feature/payment/ui/DepositChargeView.swift @@ -0,0 +1,115 @@ +import SwiftUI + +struct DepositChargeView: View { + @Environment(\.dismiss) private var dismiss + @ObservedObject var viewModel: DepositViewModel + @State private var amountText: String = "" + @State private var isCharging: Bool = false + + let keypad: [[String]] = [ + ["1","2","3"], + ["4","5","6"], + ["7","8","9"], + ["00","0","⌫"] + ] + + private var formattedNumberString: String { + if let value = Int(amountText) { + return value.formatted(.number) + } + return "0" + } + + private var formattedAmount: String { + return formattedNumberString + "원" + } + + func buttonAction(_ val: String) { + if val == "⌫" { + if !amountText.isEmpty { amountText.removeLast() } + } else { + amountText.append(val) + } + } + + var body: some View { + VStack(spacing: 20) { + + // Title + Text("예치금 충전") + .font(.system(size: 20, weight: .semibold)) + .padding(.top, 35) + + // 금액 + Text(formattedAmount) + .font(.system(size: 38, weight: .bold)) + .padding(.top, 35) + + // 아래 작은 라벨 +// Text("\(formattedNumberString)원") +// .font(.system(size: 15)) +// .foregroundColor(.textGray1) +// .padding(.horizontal, 10) +// .padding(.vertical, 4) +// .background(Color.white.opacity(0.9)) +// .cornerRadius(12) + + Spacer().frame(height: 80) + + // 키패드 + LazyVGrid(columns: Array(repeating: GridItem(.flexible(), spacing: 0), count: 3), + spacing: 1) { + ForEach(keypad.flatMap { $0 }, id: \.self) { key in + Button { + buttonAction(key) + } label: { + Text(key) + .font(.system(size: 20)) + .frame(width: 50, height: 45) + .foregroundColor(Color.black) +// .background(Color.red.opacity(0.5)) + .padding(.horizontal, 4) + .background(Color.white) + } + } + } + .padding(.horizontal,16) + .padding(.top, 28) + + + // 충전 버튼 + Button { + Task { + guard let amount = Int(amountText), amount > 0 else { return } + isCharging = true + let success = await viewModel.chargeDeposit(amount: amount) + isCharging = false + if success { + viewModel.showChargeSheet = false + dismiss() + } + } + } label: { + if isCharging { + ProgressView() + .tint(.white) + .frame(height: 56) + .frame(maxWidth: .infinity) + } else { + Text("충전") + .font(.system(size: 18, weight: .bold)) + .foregroundColor(.white) + .frame(height: 59) + .frame(maxWidth: .infinity) + } + } + .background(Color.Primary) + .cornerRadius(28) + .padding(.top, 28) + .padding(.horizontal, 10) + } + .padding(.horizontal, 20) +// .padding(.top, 20) + .background(Color.white) + } +} diff --git a/StockMate/StockMate/app/feature/payment/viewmodel/DepositViewModel.swift b/StockMate/StockMate/app/feature/payment/viewmodel/DepositViewModel.swift new file mode 100644 index 0000000..27d6009 --- /dev/null +++ b/StockMate/StockMate/app/feature/payment/viewmodel/DepositViewModel.swift @@ -0,0 +1,46 @@ +// +// PaymentViewModel.swift +// StockMate +// +// Created by Admin on 10/29/25. +// + +import Foundation + +@MainActor +final class DepositViewModel: ObservableObject { + private let repository: PaymentRepositoryProtocol = PaymentRepositoryImpl() + + @Published var balance: Int = 0 + @Published var isLoading: Bool = false + @Published var showChargeSheet: Bool = false + + /// ✅ 예치금 조회 + func fetchDepositAmount() async { + isLoading = true + + let result = await repository.fetchDepositAmount() + + isLoading = false + + switch result { + case .success(let data): + self.balance = data.balance + case .failure(let error): + print("❌ 예치금 조회 실패:", error.message) + } + } + + /// ✅ 예치금 충전 + func chargeDeposit(amount: Int) async -> Bool { + let result = await repository.chargeDeposit(amount: amount) + switch result { + case .success(_): + await fetchDepositAmount() + return true + case .failure(let error): + print("❌ 충전 실패:", error.message) + return false + } + } +} diff --git a/StockMate/StockMate/resources/Assets.xcassets/check.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/check.imageset/Contents.json new file mode 100644 index 0000000..17203cc --- /dev/null +++ b/StockMate/StockMate/resources/Assets.xcassets/check.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "check.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/StockMate/StockMate/resources/Assets.xcassets/check.imageset/check.svg b/StockMate/StockMate/resources/Assets.xcassets/check.imageset/check.svg new file mode 100644 index 0000000..8bdc85f --- /dev/null +++ b/StockMate/StockMate/resources/Assets.xcassets/check.imageset/check.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/StockMate/StockMate/resources/Assets.xcassets/deposit_background.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/deposit_background.imageset/Contents.json new file mode 100644 index 0000000..7c4374c --- /dev/null +++ b/StockMate/StockMate/resources/Assets.xcassets/deposit_background.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "deposit_background@1x.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "deposit_background@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "deposit_background@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/StockMate/StockMate/resources/Assets.xcassets/deposit_background.imageset/deposit_background@1x.png b/StockMate/StockMate/resources/Assets.xcassets/deposit_background.imageset/deposit_background@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..b988925e9908e624cb8ec64cfc26bfdc0234a1f7 GIT binary patch literal 3184 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 al1N-gzcYW=1NfT=u(5JDRC9ou^nU<3qIA6g literal 0 HcmV?d00001 diff --git a/StockMate/StockMate/resources/Assets.xcassets/deposit_background.imageset/deposit_background@3x.png b/StockMate/StockMate/resources/Assets.xcassets/deposit_background.imageset/deposit_background@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..84218d3225a008f947b7d4f122a5683c69dc628e GIT binary patch literal 10386 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%0ABU9Fo%ljc6 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 literal 0 HcmV?d00001 diff --git a/StockMate/StockMate/resources/Assets.xcassets/dottedline.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/dottedline.imageset/Contents.json new file mode 100644 index 0000000..ab174a4 --- /dev/null +++ b/StockMate/StockMate/resources/Assets.xcassets/dottedline.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "dottedline.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/StockMate/StockMate/resources/Assets.xcassets/dottedline.imageset/dottedline.svg b/StockMate/StockMate/resources/Assets.xcassets/dottedline.imageset/dottedline.svg new file mode 100644 index 0000000..5f4b4b2 --- /dev/null +++ b/StockMate/StockMate/resources/Assets.xcassets/dottedline.imageset/dottedline.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/StockMate/StockMate/resources/Assets.xcassets/hourglass.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/hourglass.imageset/Contents.json new file mode 100644 index 0000000..9e19804 --- /dev/null +++ b/StockMate/StockMate/resources/Assets.xcassets/hourglass.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "hourglass.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/StockMate/StockMate/resources/Assets.xcassets/hourglass.imageset/hourglass.svg b/StockMate/StockMate/resources/Assets.xcassets/hourglass.imageset/hourglass.svg new file mode 100644 index 0000000..f229793 --- /dev/null +++ b/StockMate/StockMate/resources/Assets.xcassets/hourglass.imageset/hourglass.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/StockMate/StockMate/resources/Assets.xcassets/pindrop.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/pindrop.imageset/Contents.json new file mode 100644 index 0000000..b922f9e --- /dev/null +++ b/StockMate/StockMate/resources/Assets.xcassets/pindrop.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "pindrop.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/StockMate/StockMate/resources/Assets.xcassets/pindrop.imageset/pindrop.svg b/StockMate/StockMate/resources/Assets.xcassets/pindrop.imageset/pindrop.svg new file mode 100644 index 0000000..f9cfacb --- /dev/null +++ b/StockMate/StockMate/resources/Assets.xcassets/pindrop.imageset/pindrop.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/StockMate/StockMate/resources/Assets.xcassets/rocket.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/rocket.imageset/Contents.json new file mode 100644 index 0000000..288431e --- /dev/null +++ b/StockMate/StockMate/resources/Assets.xcassets/rocket.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "rocket.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/StockMate/StockMate/resources/Assets.xcassets/rocket.imageset/rocket.svg b/StockMate/StockMate/resources/Assets.xcassets/rocket.imageset/rocket.svg new file mode 100644 index 0000000..b63f40e --- /dev/null +++ b/StockMate/StockMate/resources/Assets.xcassets/rocket.imageset/rocket.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/StockMate/StockMate/resources/Assets.xcassets/uploadprogress.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/uploadprogress.imageset/Contents.json new file mode 100644 index 0000000..e776e0e --- /dev/null +++ b/StockMate/StockMate/resources/Assets.xcassets/uploadprogress.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "uploadprogress.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/StockMate/StockMate/resources/Assets.xcassets/uploadprogress.imageset/uploadprogress.svg b/StockMate/StockMate/resources/Assets.xcassets/uploadprogress.imageset/uploadprogress.svg new file mode 100644 index 0000000..3e65143 --- /dev/null +++ b/StockMate/StockMate/resources/Assets.xcassets/uploadprogress.imageset/uploadprogress.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/StockMate/StockMate/resources/Color.swift b/StockMate/StockMate/resources/Color.swift index f927e60..94172ee 100644 --- a/StockMate/StockMate/resources/Color.swift +++ b/StockMate/StockMate/resources/Color.swift @@ -95,6 +95,8 @@ extension Color { static let Hstatus5Bg = Color(hex: "#ECEEF0") + static let Grayline = Color(hex: "#ECECED") + static let Grayline2 = Color(hex: "#DDDDDD") // 투명도 포함 예시 static let boxBgWhite = Color(hex: "#40FFFFFF") // 투명도 포함 From e01f5cc45b863c288f757bb38823720da2520758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A0=ED=98=84=EC=95=84?= Date: Thu, 30 Oct 2025 16:18:54 +0900 Subject: [PATCH 3/5] =?UTF-8?q?[CHORE]=20svg=20=ED=8C=8C=EC=9D=BC=20single?= =?UTF-8?q?=20scale=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Assets.xcassets/chair.imageset/Contents.json | 11 +---------- .../Assets.xcassets/check.imageset/Contents.json | 11 +---------- .../Assets.xcassets/cog.imageset/Contents.json | 11 +---------- .../Assets.xcassets/dottedline.imageset/Contents.json | 11 +---------- .../Assets.xcassets/hourglass.imageset/Contents.json | 11 +---------- .../Assets.xcassets/lightbulb.imageset/Contents.json | 11 +---------- .../Assets.xcassets/location.imageset/Contents.json | 11 +---------- .../notification.imageset/Contents.json | 11 +---------- .../Assets.xcassets/package.imageset/Contents.json | 11 +---------- .../Assets.xcassets/pindrop.imageset/Contents.json | 11 +---------- .../Assets.xcassets/rocket.imageset/Contents.json | 11 +---------- .../Assets.xcassets/spanner.imageset/Contents.json | 11 +---------- .../Assets.xcassets/tabHome.imageset/Contents.json | 11 +---------- .../tabInventory.imageset/Contents.json | 11 +---------- .../Assets.xcassets/tabPackage.imageset/Contents.json | 11 +---------- .../Assets.xcassets/tabProfile.imageset/Contents.json | 11 +---------- .../uploadprogress.imageset/Contents.json | 11 +---------- 17 files changed, 17 insertions(+), 170 deletions(-) diff --git a/StockMate/StockMate/resources/Assets.xcassets/chair.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/chair.imageset/Contents.json index ad1d744..052b5da 100644 --- a/StockMate/StockMate/resources/Assets.xcassets/chair.imageset/Contents.json +++ b/StockMate/StockMate/resources/Assets.xcassets/chair.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "filename" : "chair.svg", - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "idiom" : "universal" } ], "info" : { diff --git a/StockMate/StockMate/resources/Assets.xcassets/check.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/check.imageset/Contents.json index 17203cc..b09981a 100644 --- a/StockMate/StockMate/resources/Assets.xcassets/check.imageset/Contents.json +++ b/StockMate/StockMate/resources/Assets.xcassets/check.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "filename" : "check.svg", - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "idiom" : "universal" } ], "info" : { diff --git a/StockMate/StockMate/resources/Assets.xcassets/cog.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/cog.imageset/Contents.json index 7124035..bd8698d 100644 --- a/StockMate/StockMate/resources/Assets.xcassets/cog.imageset/Contents.json +++ b/StockMate/StockMate/resources/Assets.xcassets/cog.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "filename" : "cog.svg", - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "idiom" : "universal" } ], "info" : { diff --git a/StockMate/StockMate/resources/Assets.xcassets/dottedline.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/dottedline.imageset/Contents.json index ab174a4..3551fde 100644 --- a/StockMate/StockMate/resources/Assets.xcassets/dottedline.imageset/Contents.json +++ b/StockMate/StockMate/resources/Assets.xcassets/dottedline.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "filename" : "dottedline.svg", - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "idiom" : "universal" } ], "info" : { diff --git a/StockMate/StockMate/resources/Assets.xcassets/hourglass.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/hourglass.imageset/Contents.json index 9e19804..900b128 100644 --- a/StockMate/StockMate/resources/Assets.xcassets/hourglass.imageset/Contents.json +++ b/StockMate/StockMate/resources/Assets.xcassets/hourglass.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "filename" : "hourglass.svg", - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "idiom" : "universal" } ], "info" : { diff --git a/StockMate/StockMate/resources/Assets.xcassets/lightbulb.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/lightbulb.imageset/Contents.json index beab311..e82017e 100644 --- a/StockMate/StockMate/resources/Assets.xcassets/lightbulb.imageset/Contents.json +++ b/StockMate/StockMate/resources/Assets.xcassets/lightbulb.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "filename" : "lightbulb.svg", - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "idiom" : "universal" } ], "info" : { diff --git a/StockMate/StockMate/resources/Assets.xcassets/location.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/location.imageset/Contents.json index 306ca5c..be50dad 100644 --- a/StockMate/StockMate/resources/Assets.xcassets/location.imageset/Contents.json +++ b/StockMate/StockMate/resources/Assets.xcassets/location.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "filename" : "location.svg", - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "idiom" : "universal" } ], "info" : { diff --git a/StockMate/StockMate/resources/Assets.xcassets/notification.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/notification.imageset/Contents.json index acfc443..5dabea1 100644 --- a/StockMate/StockMate/resources/Assets.xcassets/notification.imageset/Contents.json +++ b/StockMate/StockMate/resources/Assets.xcassets/notification.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "filename" : "notification.svg", - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "idiom" : "universal" } ], "info" : { diff --git a/StockMate/StockMate/resources/Assets.xcassets/package.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/package.imageset/Contents.json index e7f4c71..f289ed5 100644 --- a/StockMate/StockMate/resources/Assets.xcassets/package.imageset/Contents.json +++ b/StockMate/StockMate/resources/Assets.xcassets/package.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "filename" : "package.svg", - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "idiom" : "universal" } ], "info" : { diff --git a/StockMate/StockMate/resources/Assets.xcassets/pindrop.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/pindrop.imageset/Contents.json index b922f9e..01ce80a 100644 --- a/StockMate/StockMate/resources/Assets.xcassets/pindrop.imageset/Contents.json +++ b/StockMate/StockMate/resources/Assets.xcassets/pindrop.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "filename" : "pindrop.svg", - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "idiom" : "universal" } ], "info" : { diff --git a/StockMate/StockMate/resources/Assets.xcassets/rocket.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/rocket.imageset/Contents.json index 288431e..a61a5d8 100644 --- a/StockMate/StockMate/resources/Assets.xcassets/rocket.imageset/Contents.json +++ b/StockMate/StockMate/resources/Assets.xcassets/rocket.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "filename" : "rocket.svg", - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "idiom" : "universal" } ], "info" : { diff --git a/StockMate/StockMate/resources/Assets.xcassets/spanner.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/spanner.imageset/Contents.json index 36cb254..7fcd63e 100644 --- a/StockMate/StockMate/resources/Assets.xcassets/spanner.imageset/Contents.json +++ b/StockMate/StockMate/resources/Assets.xcassets/spanner.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "filename" : "spanner.svg", - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "idiom" : "universal" } ], "info" : { diff --git a/StockMate/StockMate/resources/Assets.xcassets/tabHome.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/tabHome.imageset/Contents.json index e847277..a1b0717 100644 --- a/StockMate/StockMate/resources/Assets.xcassets/tabHome.imageset/Contents.json +++ b/StockMate/StockMate/resources/Assets.xcassets/tabHome.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "filename" : "tabHome.svg", - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "idiom" : "universal" } ], "info" : { diff --git a/StockMate/StockMate/resources/Assets.xcassets/tabInventory.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/tabInventory.imageset/Contents.json index 3421138..53286b8 100644 --- a/StockMate/StockMate/resources/Assets.xcassets/tabInventory.imageset/Contents.json +++ b/StockMate/StockMate/resources/Assets.xcassets/tabInventory.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "filename" : "tabInventory.svg", - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "idiom" : "universal" } ], "info" : { diff --git a/StockMate/StockMate/resources/Assets.xcassets/tabPackage.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/tabPackage.imageset/Contents.json index c6df33b..d90fcd3 100644 --- a/StockMate/StockMate/resources/Assets.xcassets/tabPackage.imageset/Contents.json +++ b/StockMate/StockMate/resources/Assets.xcassets/tabPackage.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "filename" : "tabPackage.svg", - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "idiom" : "universal" } ], "info" : { diff --git a/StockMate/StockMate/resources/Assets.xcassets/tabProfile.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/tabProfile.imageset/Contents.json index 9bea2a3..25e0b53 100644 --- a/StockMate/StockMate/resources/Assets.xcassets/tabProfile.imageset/Contents.json +++ b/StockMate/StockMate/resources/Assets.xcassets/tabProfile.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "filename" : "tabProfile.svg", - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "idiom" : "universal" } ], "info" : { diff --git a/StockMate/StockMate/resources/Assets.xcassets/uploadprogress.imageset/Contents.json b/StockMate/StockMate/resources/Assets.xcassets/uploadprogress.imageset/Contents.json index e776e0e..a1bff87 100644 --- a/StockMate/StockMate/resources/Assets.xcassets/uploadprogress.imageset/Contents.json +++ b/StockMate/StockMate/resources/Assets.xcassets/uploadprogress.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "filename" : "uploadprogress.svg", - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "idiom" : "universal" } ], "info" : { From 23e2adf24e3f78e45997f7cb8cf3c98376841dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A0=ED=98=84=EC=95=84?= Date: Fri, 31 Oct 2025 10:22:42 +0900 Subject: [PATCH 4/5] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- StockMate/StockMate/ContentView.swift | 50 ++----- .../feature/orders/ui/OrderDetailView.swift | 138 +++++++++--------- .../app/feature/orders/ui/OrderInfoView.swift | 13 -- .../app/feature/orders/ui/OrderListView.swift | 39 ----- .../payment/ui/DepositChargeView.swift | 2 + 5 files changed, 86 insertions(+), 156 deletions(-) diff --git a/StockMate/StockMate/ContentView.swift b/StockMate/StockMate/ContentView.swift index ccb290e..d576e34 100644 --- a/StockMate/StockMate/ContentView.swift +++ b/StockMate/StockMate/ContentView.swift @@ -6,52 +6,28 @@ // import SwiftUI -// -//struct DottedLine: View { -// var body: some View { -// Rectangle() -// .fill(Color.clear) -// .frame(height: 1) -// .overlay( -// Rectangle() -// .stroke(style: StrokeStyle(lineWidth: 1, dash: [3])) // <- 점선 패턴 -// .foregroundColor(.gray) -// ) -// } -//} struct ContentView: View { var body: some View { VStack { - Text("위쪽") -// DottedLine() - Text("아래쪽") + Image(systemName: "globe") + .imageScale(.large) + .foregroundStyle(.tint) + Text("임시 화면") } .padding() + HStack(spacing: 20) { + Image(systemName: "gearshape") + .font(.system(size: 40)) + .foregroundColor(.blue) + + Image(systemName: "lightbulb") + .font(.system(size: 40)) + .foregroundColor(.cyan) + } } } -//struct ContentView: View { -// var body: some View { -// VStack { -// Image(systemName: "globe") -// .imageScale(.large) -// .foregroundStyle(.tint) -// Text("임시 화면") -// } -// .padding() -// HStack(spacing: 20) { -// Image(systemName: "gearshape") -// .font(.system(size: 40)) -// .foregroundColor(.blue) -// -// Image(systemName: "lightbulb") -// .font(.system(size: 40)) -// .foregroundColor(.cyan) -// } -// } -//} - #Preview { ContentView() } diff --git a/StockMate/StockMate/app/feature/orders/ui/OrderDetailView.swift b/StockMate/StockMate/app/feature/orders/ui/OrderDetailView.swift index c47aec8..c701163 100644 --- a/StockMate/StockMate/app/feature/orders/ui/OrderDetailView.swift +++ b/StockMate/StockMate/app/feature/orders/ui/OrderDetailView.swift @@ -153,7 +153,6 @@ struct OrderDetailView: View { // ✅ 하단 버튼 HStack(spacing: 12) { - // 왼쪽: 영수증 확인 // 왼쪽: 영수증 확인 NavigationLink(destination: ReceiptView(orderId: order.id)) { Text("영수증 확인") @@ -171,8 +170,10 @@ struct OrderDetailView: View { // 오른쪽 버튼: 주문 상태에 따라 변경 - if order.orderStatus == "ORDER_COMPLETED" { - // 주문 완료 → "주문취소" 버튼 + if order.orderStatus == "ORDER_COMPLETED" || + order.orderStatus == "PAY_COMPLETED" || + order.orderStatus == "PENDING_APPROVAL" { + // "주문취소" → 주문완료/결제완료/승인대기 Button(action: { Task { await orderViewModel.cancelOrder(orderId: orderId) @@ -187,8 +188,9 @@ struct OrderDetailView: View { .cornerRadius(10) } - } else if order.orderStatus == "ORDER_COMPLETED" { - // 배송 완료 → "입고 하기" 버튼 + } else if order.orderStatus == "PENDING_RECEIVING" || + order.orderStatus == "DELIVERED" { + // "입고 하기" → 입고대기/배송완료 Button(action: { // TODO: 입고 처리 버튼 }) { @@ -247,68 +249,7 @@ struct OrderDetailView: View { .font(.system(size: 14)) } - func formatDate(_ isoDate: String) -> String { - let comps = isoDate.split(separator: "T").first?.split(separator: "-") ?? [] - guard comps.count == 3 else { return isoDate } - return "\(comps[0])년 \(comps[1])월 \(comps[2])일" - } - - func statusText(_ status: String) -> String { - switch status { - case "ORDER_COMPLETED": return "주문 완료" // - case "PAY_COMPLETED": return "결제 완료" - case "PENDING_APPROVAL": return "승인 대기" // - case "FAILED": return "결제 실패" - case "PENDING_SHIPPING": return "출고 대기" - case "SHIPPING": return "배송중" - case "PENDING_RECEIVING": return "입고 대기" - case "REJECTED": return "주문 반려" - case "DELIVERED": return "배송 완료" - case "RECEIVED": return "입고 완료" - case "REFUNDED": return "환불 완료" - case "REFUND_REJECTED": return "환불 반려" - case "CANCELLED": return "주문 취소" - default: return "알 수 없음" - } - } - - func statusColor(_ status: String) -> Color { - switch status { - case "ORDER_COMPLETED": return .StatusGreen - case "PAY_COMPLETED": return .StatusGreen - case "PENDING_APPROVAL": return .Warning - case "FAILED": return .Danger - case "PENDING_SHIPPING": return .InvUse - case "SHIPPING": return .Transfer - case "PENDING_RECEIVING": return .Secondary - case "REJECTED": return .Danger - case "DELIVERED": return .Secondary - case "RECEIVED": return .StatusPurple - case "REFUNDED": return .Gray - case "REFUND_REJECTED": return .Gray - case "CANCELLED": return .Gray - default: return .gray.opacity(0.6) - } - } - - func statusBdColor(_ status: String) -> Color { - switch status { - case "ORDER_COMPLETED": return .StatusGreenBg - case "PAY_COMPLETED": return .StatusGreenBg - case "PENDING_APPROVAL": return .WarningBg - case "FAILED": return .DangerBg - case "PENDING_SHIPPING": return .InvUseBg - case "SHIPPING": return .TransferBg - case "PENDING_RECEIVING": return .LightBlue04 - case "REJECTED": return .DangerBg - case "DELIVERED": return .LightBlue04 - case "RECEIVED": return .StatusPurpleBg - case "REFUNDED": return Color(hex: "#EEEEEF") - case "REFUND_REJECTED": return Color(hex: "#EEEEEF") - case "CANCELLED": return Color(hex: "#EEEEEF") - default: return .gray.opacity(0.6) - } - } + } // ✅ 카드 레이아웃 통일용 @@ -365,3 +306,66 @@ func deliveryStep(for status: String) -> Int { default: return 6 } } + +func formatDate(_ isoDate: String) -> String { + let comps = isoDate.split(separator: "T").first?.split(separator: "-") ?? [] + guard comps.count == 3 else { return isoDate } + return "\(comps[0])년 \(comps[1])월 \(comps[2])일" +} + +func statusText(_ status: String) -> String { + switch status { + case "ORDER_COMPLETED": return "주문 완료" // 주문 완료 + case "PAY_COMPLETED": return "결제 완료" // 결제 완료 + case "PENDING_APPROVAL": return "승인 대기" // 승인대기 + case "FAILED": return "결제 실패" // 결제 실패 + case "PENDING_SHIPPING": return "출고 대기" // 출고 대기 + case "SHIPPING": return "배송중" // 배송중 + case "PENDING_RECEIVING": return "배송 완료" // 입고대기 + case "REJECTED": return "승인 반려" // 이론상 출고 반려 + case "DELIVERED": return "배송 완료" // 배송 완료 + case "RECEIVED": return "입고 완료" // 입고 완료 + case "REFUNDED": return "환불 완료" // 환불 완료 + case "REFUND_REJECTED": return "환불 반려" // 환불 반려 + case "CANCELLED": return "주문 취소" // 주문 취소 + default: return "알 수 없음" + } +} + +func statusColor(_ status: String) -> Color { + switch status { + case "ORDER_COMPLETED": return .StatusGreen + case "PAY_COMPLETED": return .StatusGreen + case "PENDING_APPROVAL": return .Warning + case "FAILED": return .Danger + case "PENDING_SHIPPING": return .InvUse + case "SHIPPING": return .Transfer + case "PENDING_RECEIVING": return .Secondary + case "REJECTED": return .Danger + case "DELIVERED": return .Secondary + case "RECEIVED": return .StatusPurple + case "REFUNDED": return .Gray + case "REFUND_REJECTED": return .Gray + case "CANCELLED": return .Gray + default: return .gray.opacity(0.6) + } +} + +func statusBdColor(_ status: String) -> Color { + switch status { + case "ORDER_COMPLETED": return .StatusGreenBg + case "PAY_COMPLETED": return .StatusGreenBg + case "PENDING_APPROVAL": return .WarningBg + case "FAILED": return .DangerBg + case "PENDING_SHIPPING": return .InvUseBg + case "SHIPPING": return .TransferBg + case "PENDING_RECEIVING": return .LightBlue04 + case "REJECTED": return .DangerBg + case "DELIVERED": return .LightBlue04 + case "RECEIVED": return .StatusPurpleBg + case "REFUNDED": return Color(hex: "#EEEEEF") + case "REFUND_REJECTED": return Color(hex: "#EEEEEF") + case "CANCELLED": return Color(hex: "#EEEEEF") + default: return .gray.opacity(0.6) + } +} diff --git a/StockMate/StockMate/app/feature/orders/ui/OrderInfoView.swift b/StockMate/StockMate/app/feature/orders/ui/OrderInfoView.swift index 701c358..f32ac74 100644 --- a/StockMate/StockMate/app/feature/orders/ui/OrderInfoView.swift +++ b/StockMate/StockMate/app/feature/orders/ui/OrderInfoView.swift @@ -229,19 +229,6 @@ extension OrderInfoView { .cornerRadius(20) } .padding(.trailing, 5) - -// Button { -// depositViewModel.showChargeSheet = true -// } label: { -// Text("충전") -// .foregroundColor(Color.Primary) -// .font(.system(size: 14, weight: .bold)) -// .padding(.vertical, 6) -// .padding(.horizontal, 14) -// .background(Color.white) -// .cornerRadius(20) -// } -// .padding(.trailing, 5) } .padding(.bottom, 25) } diff --git a/StockMate/StockMate/app/feature/orders/ui/OrderListView.swift b/StockMate/StockMate/app/feature/orders/ui/OrderListView.swift index 0dc04a5..a6e9aa5 100644 --- a/StockMate/StockMate/app/feature/orders/ui/OrderListView.swift +++ b/StockMate/StockMate/app/feature/orders/ui/OrderListView.swift @@ -155,43 +155,4 @@ struct OrderListCardView: View { .shadow(color: .black.opacity(0.05), radius: 4, x: 0, y: 2) .padding(.horizontal) } - - func statusText(_ status: String) -> String { - switch status { - case "ORDER_COMPLETED": return "주문 완료" - case "PENDING_SHIPPING": return "출고 대기" - case "REJECTED": return "출고 반려" - case "SHIPPING": return "배송 중" - case "DELIVERED": return "배송 완료" - case "RECEIVED": return "입고 완료" - case "CANCELLED": return "주문 취소" - default: return "알 수 없음" - } - } - - func statusColor(_ status: String) -> Color { - switch status { - case "ORDER_COMPLETED": return .StatusGreen - case "PENDING_SHIPPING": return .InvUse - case "REJECTED": return .Danger - case "SHIPPING": return .Transfer - case "DELIVERED": return .Secondary - case "RECEIVED": return .StatusPurple - case "CANCELLED": return .gray - default: return .gray.opacity(0.6) - } - } - - func statusBdColor(_ status: String) -> Color { - switch status { - case "ORDER_COMPLETED": return .StatusGreenBg - case "PENDING_SHIPPING": return .InvUseBg - case "REJECTED": return .DangerBg - case "SHIPPING": return .TransferBg - case "DELIVERED": return .LightBlue04 - case "RECEIVED": return .StatusPurpleBg - case "CANCELLED": return Color(hex: "#EEEEEF") - default: return .gray.opacity(0.6) - } - } } diff --git a/StockMate/StockMate/app/feature/payment/ui/DepositChargeView.swift b/StockMate/StockMate/app/feature/payment/ui/DepositChargeView.swift index 77987f5..538412f 100644 --- a/StockMate/StockMate/app/feature/payment/ui/DepositChargeView.swift +++ b/StockMate/StockMate/app/feature/payment/ui/DepositChargeView.swift @@ -79,6 +79,7 @@ struct DepositChargeView: View { // 충전 버튼 Button { + guard !isCharging else { return } Task { guard let amount = Int(amountText), amount > 0 else { return } isCharging = true @@ -107,6 +108,7 @@ struct DepositChargeView: View { .cornerRadius(28) .padding(.top, 28) .padding(.horizontal, 10) + .disabled(isCharging) } .padding(.horizontal, 20) // .padding(.top, 20) From 259efb0655ffe0af710227bbd70295fb95512421 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A0=ED=98=84=EC=95=84?= Date: Fri, 31 Oct 2025 11:27:12 +0900 Subject: [PATCH 5/5] =?UTF-8?q?[REFAC]=20=EC=A3=BC=EB=AC=B8=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=ED=99=94=EB=A9=B4=20=EB=B0=B0=EC=B9=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/orders/ui/OrderDetailView.swift | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/StockMate/StockMate/app/feature/orders/ui/OrderDetailView.swift b/StockMate/StockMate/app/feature/orders/ui/OrderDetailView.swift index c701163..a963578 100644 --- a/StockMate/StockMate/app/feature/orders/ui/OrderDetailView.swift +++ b/StockMate/StockMate/app/feature/orders/ui/OrderDetailView.swift @@ -25,27 +25,35 @@ struct OrderDetailView: View { } .frame(maxWidth: .infinity, alignment: .center) - - // ✅ 주문 정보 + VStack(alignment: .leading, spacing: 6) { Text(formatDate(order.createdAt)) .font(.system(size: 15, weight: .semibold)) .padding(.bottom, 4) - infoRow("주문번호", order.orderNumber) - - HStack { - Text("상태") - .font(.system(size: 14)) - Spacer() - Text(statusText(order.orderStatus)) - .font(.system(size: 13, weight: .semibold)) - .padding(.horizontal, 10) - .padding(.vertical, 6) - .background(statusBdColor(order.orderStatus)) - .foregroundColor(statusColor(order.orderStatus)) - .cornerRadius(12) - .padding(.leading,4) + // ✅ 주문 정보 + HStack(alignment: .top, spacing: 6){ + VStack(alignment: .leading){ + Text("주문번호") + .font(.system(size: 14)) + .padding(.bottom, 4) + + Text("상태") + .font(.system(size: 14)) + } + + VStack(alignment: .leading){ + Text(order.orderNumber) + .font(.system(size: 14)) + + Text(statusText(order.orderStatus)) + .font(.system(size: 13, weight: .semibold)) + .padding(.horizontal, 10) + .padding(.vertical, 6) + .background(statusBdColor(order.orderStatus)) + .foregroundColor(statusColor(order.orderStatus)) + .cornerRadius(12) + }.padding(.leading) } }