Make station price age informational only

The relay's price_updated is the maximum price_last_updated across the grades it maps, so it cannot vouch for the selected grade: stop using it to score, gate or warn about Best Value.

- FuelPriceFreshness is now station-level and display-only: one age per station, fresh/outdated/unknown/invalid, "May be outdated" past 30 days, with future-tolerance and non-finite guards.
- Best Value restores the closest-station-selling-the-selected-fuel baseline and its savings ranking; eligibility gating, eligible-first sorting and the unavailable banner are gone.
- Price age appears in the More info sheet only - no listing-row warnings, no extra banners.
- Copy reverted from "closest eligible station" to "closest station"; stale price-confidence strings removed, "May be outdated" added.
- Dormant per-grade timestamp plumbing removed, and regression tests added for every fuel type, missing/invalid/future stamps and the bundled offline dump.
This commit is contained in:
FuelBoard Contributor
2026-10-16 09:48:01 +01:00
parent 5900a81473
commit e960ef85c6
19 changed files with 530 additions and 732 deletions
-11
View File
@@ -20,8 +20,6 @@ struct StationsView: View {
@Binding var fuelSavingsAmount: FuelSavingsFillAmount
var savingsForStation: (FuelStation) -> FuelSavingsAvailability? = { _ in nil }
var journeyDiagnosticsForStation: (FuelStation) -> FuelSavingsJourneyDiagnostics? = { _ in nil }
var savingsPriceConfidenceForStation: (FuelStation) -> FuelPriceFreshness.ComparisonConfidence
var savingsPriceWarningForStation: (FuelStation) -> String?
var onToggleFavourite: (FuelStation, FuelType) -> Void = { _, _ in }
var onRefresh: () async -> Void = {}
@@ -123,11 +121,6 @@ struct StationsView: View {
// for a switched-off feature.
if sortMode == .worthTheDrive && fuelSavingsSettings.isConfigured {
FuelSavingsAdjustmentView(amount: $fuelSavingsAmount)
if !stations.isEmpty && stations.allSatisfy({ savingsPriceConfidenceForStation($0) == .ineligible }) {
Text("Best Value unavailable: no eligible price comparison. Stations and prices remain visible below.")
.font(.caption)
.foregroundStyle(.orange)
}
}
if isLoading && stations.isEmpty {
@@ -264,8 +257,6 @@ struct StationsView: View {
selectedFuel: selectedFuel,
fuelSavings: savingsForStation(station),
fuelSavingsAmount: fuelSavingsAmount,
savingsPriceConfidence: savingsPriceConfidenceForStation(station),
savingsPriceWarning: savingsPriceWarningForStation(station),
journeyDiagnostics: journeyDiagnosticsForStation(station),
isFavourite: favouriteIDs.contains(station.id),
onToggleFavourite: { onToggleFavourite(station, selectedFuel) }
@@ -369,8 +360,6 @@ struct StationsView: View {
tapAction: stationTapAction,
fuelSavings: savingsForStation(station),
fuelSavingsAmount: fuelSavingsAmount,
savingsPriceConfidence: savingsPriceConfidenceForStation(station),
savingsPriceWarning: savingsPriceWarningForStation(station),
onToggleFavourite: { onToggleFavourite(station, selectedFuel) },
onShowDetails: { detailStation = $0 }
)