master merged

This commit is contained in:
Daniel Arantes Loverde
2026-06-03 14:52:27 -03:00
parent 980a106661
commit f51319b486
112 changed files with 1051 additions and 1139 deletions

View File

@@ -1,6 +1,7 @@
import SwiftUI
struct OrdersView: View {
@Environment(\.dismiss) var dismiss
@State var isLoading = false
@State var errorMessage: String? = nil
@State var orders: [AppOrderSummary] = []
@@ -12,6 +13,8 @@ struct OrdersView: View {
var body: some View {
ScrollView(showsIndicators: false) {
VStack(alignment: .leading, spacing: 14) {
screenHeader(title: "Meus Pedidos", onBack: { dismiss() })
if isLoading {
ProgressView()
.frame(maxWidth: .infinity)
@@ -35,11 +38,12 @@ struct OrdersView: View {
}
}
.padding(.horizontal, 20)
.padding(.top, 18)
.padding(.bottom, UIDevice.bottomNotch + 18)
}
.background(AppColors.backgroundLight)
.navigationTitle("Meus Pedidos")
.appInlineNavigationTitle()
.navigationBarBackButtonHidden(true)
.appHiddenNavigationBar()
.task {
await loadOrdersIfNeeded()
await refreshStoreRatings()
@@ -59,6 +63,28 @@ struct OrdersView: View {
}
}
private func screenHeader(title: String, onBack: @escaping () -> Void) -> some View {
ZStack {
Text(title)
.font(AppTypography.heading2)
.foregroundStyle(AppColors.textPrimary)
HStack {
Button(action: onBack) {
Image(systemName: "chevron.left")
.font(.system(size: 24, weight: .semibold))
.foregroundStyle(AppColors.textPrimary)
.frame(width: 52, height: 52)
.background(AppColors.surface)
.clipShape(Circle())
.shadow(color: .black.opacity(0.06), radius: 8, y: 2)
}
.buttonStyle(.plain)
Spacer()
}
}
}
private func orderCard(_ order: AppOrderSummary) -> some View {
let status = orderVisualStatus(for: order)
let detailsRoute = OrderRouteContext(
@@ -81,7 +107,6 @@ struct OrdersView: View {
AsyncStoreImage(imageURL: resolvedMediaURL(order.storeLogoURL))
.frame(width: 80, height: 80)
.clipShape(RoundedRectangle(cornerRadius: 20, style: .continuous))
.background(AppColors.brandSoft, in: RoundedRectangle(cornerRadius: 20, style: .continuous))
VStack(alignment: .leading, spacing: 5) {
@@ -663,58 +688,57 @@ struct OrderEntryDestinationView: View {
func resolveRoute() async {
defer { isResolvingRoute = false }
if routeIntent == .tracking {
return
}
let order = await fetchOrderForRouting()
guard let order else { return }
if routeIntent == .details {
orderDetails = order
return
}
if shouldOpenOrderDetails(for: order) {
// For both .tracking and .auto: show payment screen if payment is still pending.
// Timeline only shows once payment is confirmed or method is off-app.
if shouldOpenPaymentScreen(for: order) {
let normalizedMethod = normalizePaymentMethod(order)
if normalizedMethod.contains("PIX") {
let pixFromPayment = order.payment?.pix
let pixFromPayload = order.paymentPayload
let copyPaste = (pixFromPayment?.copyPaste?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false)
? pixFromPayment?.copyPaste
: pixFromPayload?.copyPaste
let qrCodeImage = (pixFromPayment?.qrCodeImage?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false)
? pixFromPayment?.qrCodeImage
: pixFromPayload?.qrCodeImage
let expirationDate = (pixFromPayment?.expirationDate?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false)
? pixFromPayment?.expirationDate
: pixFromPayload?.expirationDate
pixContext = PixPaymentContext(
id: order.id,
orderId: order.id,
shortId: order.shortId ?? initialShortId,
copyPaste: copyPaste?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false
? (copyPaste ?? "")
: "Código PIX indisponível no momento. Aguarde e tente novamente.",
qrCodeImageBase64: qrCodeImage,
expirationDate: expirationDate
)
return
}
if normalizedMethod == "CREDIT_CARD" || normalizedMethod == "DEBIT_CARD" {
cardContext = CardPaymentContext(
orderId: order.id,
shortId: order.shortId ?? initialShortId,
total: order.total ?? fallbackTotal ?? 0
)
return
}
}
// For .auto only: route terminal/canceled orders to details instead of timeline.
if routeIntent == .auto && shouldOpenOrderDetails(for: order) {
orderDetails = order
return
}
guard shouldOpenPaymentScreen(for: order) else { return }
let normalizedMethod = normalizePaymentMethod(order)
if normalizedMethod.contains("PIX") {
let pixFromPayment = order.payment?.pix
let pixFromPayload = order.paymentPayload
let copyPaste = (pixFromPayment?.copyPaste?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false)
? pixFromPayment?.copyPaste
: pixFromPayload?.copyPaste
let qrCodeImage = (pixFromPayment?.qrCodeImage?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false)
? pixFromPayment?.qrCodeImage
: pixFromPayload?.qrCodeImage
let expirationDate = (pixFromPayment?.expirationDate?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false)
? pixFromPayment?.expirationDate
: pixFromPayload?.expirationDate
pixContext = PixPaymentContext(
id: order.id,
orderId: order.id,
shortId: order.shortId ?? initialShortId,
copyPaste: copyPaste?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false
? (copyPaste ?? "")
: "Código PIX indisponível no momento. Aguarde e tente novamente.",
qrCodeImageBase64: qrCodeImage,
expirationDate: expirationDate
)
return
}
if normalizedMethod == "CREDIT_CARD" || normalizedMethod == "DEBIT_CARD" {
cardContext = CardPaymentContext(
orderId: order.id,
shortId: order.shortId ?? initialShortId,
total: order.total ?? fallbackTotal ?? 0
)
return
}
// .tracking (and .auto fallthrough) nil states body renders OrderTrackingView
}
@MainActor