From f7064928239827d312db62580f5707a303fc9656 Mon Sep 17 00:00:00 2001 From: Daniel Arantes Loverde Date: Fri, 10 Jul 2026 10:49:18 -0300 Subject: [PATCH] [cart-checkout] Match selected address by coordinates before label, not after MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CustomerAddress.id is genuinely optional (Services/ApiModels.swift:46) — some address book entries have no id. AddressesView.selectAddress sets appState.address.selectedId = address.id directly with no fallback, so picking one of those addresses leaves selectedId nil. The matching cascade in both CartView and CheckoutView+Logic then skipped straight to a label match, which silently collides whenever two addresses share an empty or duplicate label (common for unnamed entries), and finally fell back to addresses.first — always redisplaying whatever's first in the list regardless of what was tapped, with no error surfaced anywhere. Coordinates are set immediately and reliably at selection time and are far less likely to collide than a label. Checkout already had a lat/lng fallback but ordered after the weak label match; promoted it ahead of label matching in both files, and added the same fallback to Cart, which didn't have one at all. --- Sources/PediFoods/Views/Main/CartView.swift | 15 +++++++++++ .../Views/Main/CheckoutView+Logic.swift | 25 ++++++++++++------- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/Sources/PediFoods/Views/Main/CartView.swift b/Sources/PediFoods/Views/Main/CartView.swift index 4ba0420..d104ae3 100644 --- a/Sources/PediFoods/Views/Main/CartView.swift +++ b/Sources/PediFoods/Views/Main/CartView.swift @@ -296,6 +296,21 @@ struct CartView: View { selectedCustomerAddress = nil } + // id can be nil for some address book entries — lat/lng is set + // immediately and reliably at selection time (AddressesView. + // selectAddress), so it's a stronger signal than the label match + // below, which silently collides whenever two addresses share an + // empty/duplicate label. Without this, an id-less address falls + // through to addresses.first and never actually "changes". + if selectedCustomerAddress == nil, + let lat = appState.address.latitude, let lng = appState.address.longitude { + selectedCustomerAddress = addresses.first { address in + guard let addrLat = address.latLong?.first, + let addrLng = address.latLong?.dropFirst().first else { return false } + return abs(addrLat - lat) < 0.00001 && abs(addrLng - lng) < 0.00001 + } + } + if selectedCustomerAddress == nil { let display = appState.address.display .trimmingCharacters(in: .whitespacesAndNewlines) diff --git a/Sources/PediFoods/Views/Main/CheckoutView+Logic.swift b/Sources/PediFoods/Views/Main/CheckoutView+Logic.swift index 2d67163..035c256 100644 --- a/Sources/PediFoods/Views/Main/CheckoutView+Logic.swift +++ b/Sources/PediFoods/Views/Main/CheckoutView+Logic.swift @@ -92,6 +92,22 @@ extension CheckoutView { selectedCustomerAddress = nil } + // id can be nil for some address book entries — lat/lng is set + // immediately and reliably at selection time (AddressesView. + // selectAddress), so it's a stronger signal than the label match + // below, which silently collides whenever two addresses share an + // empty/duplicate label. Without this ordered first, an id-less + // address falls through to addresses.first and never actually + // "changes" even though delivery to it is allowed. + if selectedCustomerAddress == nil, + let lat = appState.address.latitude, let lng = appState.address.longitude { + selectedCustomerAddress = addresses.first { address in + guard let addrLat = address.latLong?.first, + let addrLng = address.latLong?.dropFirst().first else { return false } + return abs(addrLat - lat) < 0.00001 && abs(addrLng - lng) < 0.00001 + } + } + if selectedCustomerAddress == nil { let display = appState.address.display .trimmingCharacters(in: .whitespacesAndNewlines) @@ -103,15 +119,6 @@ extension CheckoutView { } } - if selectedCustomerAddress == nil, - let lat = appState.address.latitude, let lng = appState.address.longitude { - selectedCustomerAddress = addresses.first { address in - guard let addrLat = address.latLong?.first, - let addrLng = address.latLong?.dropFirst().first else { return false } - return abs(addrLat - lat) < 0.00001 && abs(addrLng - lng) < 0.00001 - } - } - if selectedCustomerAddress == nil { selectedCustomerAddress = addresses.first }