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
+3 -8
View File
@@ -21,8 +21,6 @@ struct StationDetailView: View {
var selectedFuel: FuelType = FuelStore.loadSelectedFuel()
var fuelSavings: FuelSavingsAvailability? = nil
var fuelSavingsAmount: FuelSavingsFillAmount = FuelSavingsSettings.defaultPreferredAmount
var savingsPriceConfidence: FuelPriceFreshness.ComparisonConfidence = .ineligible
var savingsPriceWarning: String? = nil
var savingsBaselineStationName: String? = nil
var journeyDiagnostics: FuelSavingsJourneyDiagnostics? = nil
/// Whether this station is starred for the fuel currently being viewed, and
@@ -62,11 +60,11 @@ struct StationDetailView: View {
}
private var priceFreshness: FuelPriceFreshness.Assessment {
FuelPriceFreshness.assessment(for: station, fuel: selectedFuel)
FuelPriceFreshness.assessment(for: station)
}
/// The selected grade's current price, when present. Kept separate from
/// the freshness label so a stale price remains visible rather than being
/// the price-age row so an old price remains visible rather than being
/// silently hidden.
private var selectedFuelPriceText: String {
guard let price = station.prices[selectedFuel] else { return "—" }
@@ -215,8 +213,7 @@ struct StationDetailView: View {
}
LabeledContent("\(selectedFuel.displayName) price", value: selectedFuelPriceText)
.monospacedDigit()
LabeledContent("Price updated", value: priceFreshness.updateAgeLabel)
.monospacedDigit()
StationPriceAgeView(assessment: priceFreshness)
ForEach(StationNotice.notices(for: station)) { notice in
Label(notice.title, systemImage: notice.symbolName)
.font(.subheadline.weight(.semibold))
@@ -257,8 +254,6 @@ struct StationDetailView: View {
FuelSavingsSummaryView(
availability: fuelSavings,
amount: fuelSavingsAmount,
priceConfidence: savingsPriceConfidence,
priceWarning: savingsPriceWarning,
baselineStationName: savingsBaselineStationName,
distanceUnit: distanceUnit,
showInfoAction: { showBestValueInfo = true }