feat(payment): implement change payment method (PATCH /payment-method)

- ChangePaymentMethodPayload + ChangePaymentMethodResult models
- ApiService.changePaymentMethod()
- PixPaymentContext gains storeId + order data for payment switch
- PaymentPixView: Trocar button opens ChangePaymentSheet with 3 options
- ChangePaymentSheet: Novo PIX (new QR), Cartão (saved or new), Pagar na Entrega
- ChangePaymentCardSheet + ChangePaymentNewCardView with same card masks/validation
- OrdersView/OrderEntryDestinationView: threaded appState binding
This commit is contained in:
Daniel Arantes Loverde
2026-06-03 18:49:07 -03:00
parent 9525c19b6b
commit ee8745553e
6 changed files with 487 additions and 21 deletions

View File

@@ -1,6 +1,7 @@
import SwiftUI
struct OrdersView: View {
@Binding var appState: AppState
@Environment(\.dismiss) var dismiss
@State var isLoading = false
@State var errorMessage: String? = nil
@@ -58,7 +59,8 @@ struct OrdersView: View {
initialShortId: context.shortId,
fallbackPaymentMethod: context.paymentMethod,
fallbackTotal: context.total,
routeIntent: context.intent
routeIntent: context.intent,
appState: $appState
)
}
}
@@ -629,6 +631,7 @@ struct OrderEntryDestinationView: View {
let fallbackPaymentMethod: String?
let fallbackTotal: Double?
let routeIntent: OrderRouteIntent
@Binding var appState: AppState
@State var isResolvingRoute = true
@State var didResolve = false
@@ -650,6 +653,7 @@ struct OrderEntryDestinationView: View {
} else if let pixContext {
PaymentPixView(
context: pixContext,
appState: $appState,
onPaymentConfirmed: {
orderTrackingContext = OrderTrackingContext(orderId: pixContext.orderId, shortId: pixContext.shortId)
},
@@ -701,15 +705,25 @@ struct OrderEntryDestinationView: View {
let expirationDate = (pixFromPayment?.expirationDate?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false)
? pixFromPayment?.expirationDate
: pixFromPayload?.expirationDate
let storeId = order.storeId ?? ""
pixContext = PixPaymentContext(
id: order.id,
orderId: order.id,
shortId: order.shortId ?? initialShortId,
storeId: storeId,
copyPaste: copyPaste?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false
? (copyPaste ?? "")
: "Código PIX indisponível no momento. Aguarde e tente novamente.",
qrCodeImageBase64: qrCodeImage,
expirationDate: expirationDate
expirationDate: expirationDate,
total: order.total ?? 0,
profileName: "",
profileEmail: "",
profilePhone: "",
addressZip: nil,
addressNumber: nil,
deliveryType: order.deliveryType ?? "DELIVERY",
itemsJSON: "[]"
)
return
}