Best Value: candidate-priced fills, key copy, detail total

This commit is contained in:
FuelBoard Contributor
2026-10-14 10:43:12 +01:00
parent 2ed9cbf4e8
commit 3c424ab397
9 changed files with 218 additions and 80 deletions
+37 -7
View File
@@ -566,10 +566,34 @@ struct ContentView: View {
func source(_ basis: FuelSavingsDistanceBasis) -> String {
basis == .roadRoute ? "road route" : "straight-line estimate"
}
let price = station.prices[selectedFuel].map { String(format: "%.1fp/L", $0) } ?? "—"
let baselinePrice = baseline?.prices[selectedFuel].map { String(format: "%.1fp/L", $0) } ?? "—"
func amount(_ value: FuelSavingsFillAmount) -> String {
switch value.unit {
case .pounds: return String(format: "£%.2f", value.value)
case .litres: return String(format: "%.2f L", value.value)
}
}
func rawMoney(_ value: Double?) -> String {
value.map { String(format: "£%.6f", $0) } ?? "—"
}
let candidatePriceValue = station.prices[selectedFuel]
let baselinePriceValue = baseline?.prices[selectedFuel]
let price = candidatePriceValue.map { String(format: "%.1fp/L", $0) } ?? "—"
let baselinePrice = baselinePriceValue.map { String(format: "%.1fp/L", $0) } ?? "—"
let priceDifference = candidatePriceValue.flatMap { candidate in
baselinePriceValue.map { String(format: "%+.1fp/L", $0 - candidate) }
} ?? "—"
let litresBasis = sessionFuelSavingsAmount.unit == .pounds ? "candidate price" : "fixed litres"
let rows: [(String, String)] = [
("Station", "\(station.name) (\(station.id))"),
("Settings default fill-up", amount(fuelSavingsSettings.preferredAmount)),
("Effective/session fill-up", amount(sessionFuelSavingsAmount)),
("Fill-up unit", sessionFuelSavingsAmount.unit.displayName),
("MPG", String(format: "%.1f UK MPG", fuelSavingsSettings.mpg)),
("Candidate price", price),
("Baseline price", baselinePrice),
("Price difference", priceDifference),
("Candidate litres", result.map { String(format: "%.6f L · %@", $0.fillLitres, litresBasis) } ?? "—"),
("Gross saving raw", rawMoney(result?.grossSavingGBP)),
("Displayed distance", "\(distanceUnit.format(stationDistance.displayDistanceKM)) · \(source(stationDistance.displaySource))"),
("Outward road", meters(stationDistance.outwardMeters)),
("Return road", stationDistance.hasMeasuredReturn ? meters(stationDistance.returnMeters) : "inferred or unavailable"),
@@ -581,12 +605,11 @@ struct ContentView: View {
("Station journey", miles(journey?.miles)),
("Baseline journey", miles(baselineJourney?.miles)),
("Additional journey", miles(result?.extraDistanceMiles)),
("Additional fuel used", result.map { String(format: "%.6f L", $0.extraFuelLitres) } ?? "—"),
("Confidence", result?.journeyConfidence.rawValue ?? "estimated"),
("Fuel price", price),
("Baseline price", baselinePrice),
("Gross saving", result.map { FuelSavingsFormat.money($0.grossSavingGBP) } ?? "—"),
("Travel cost", result.map { FuelSavingsFormat.money($0.extraDrivingCostGBP) } ?? "—"),
("Net saving", result.map { FuelSavingsFormat.money($0.netSavingGBP) } ?? "—")
("Travel cost raw", rawMoney(result?.extraDrivingCostGBP)),
("Net saving raw", rawMoney(result?.netSavingGBP)),
("Displayed net saving", result?.headline() ?? "—")
]
return FuelSavingsJourneyDiagnostics(rows: rows)
#else
@@ -1104,6 +1127,13 @@ struct ContentView: View {
ensureBestValueAlertModeIsAvailable()
updateAlertMonitor()
}
.onChange(of: sessionFuelSavingsAmount) { _, _ in
// This remains a session-only override: do not write it to FuelStore.
// Any active Best Value alert/Live Activity must nevertheless use
// the same effective amount as rows, details, favourites and sorting.
updateAlertMonitor()
updateLiveActivity()
}
.onChange(of: scenePhase) { _, newPhase in
if newPhase == .active {
// Never start location tracking while onboarding is on screen —