[cart-checkout] Match selected address by coordinates before label, not after
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.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user