Redesign the More info sheet

The sheet leads with the station name and address inside the card, above the map, then a two-column facts row (fuel price on the left, distance and return on the right, split by a hairline) and the two station actions divided the same way. The Best Value block becomes a tinted card: verdict badge, the two figures the estimate is made of, the working and the total. "How Best Value works" moves to its own row below it, using the shared HowBestValueRow the Key sheet already shows.

Presentation only: every figure still comes from the shared sources (FuelStore.priceText, stationDistanceDisplay, FuelSavingsResult), so the sheet cannot disagree with the listing row, the widget or the Live Activity, and no calculation, ranking or freshness rule changed.

StationDistanceDisplay.returnLabel(unit:) and FuelSavingsFormat.extraTravelDistanceLabel(...) are split out of their caption forms so a surface printing the return or extra-travel figure on its own line takes it from the same place, confidence marker included; their existing output is unchanged, pinned by tests. FuelSavingsSummaryView is deleted - the sheet's card supersedes it and nothing referenced it.

DEBUG-only QA hooks: -qaConfigureSavings configures a Fuel Savings plan (the Best Value card and the Worth the Drive sort are gated on it), -qaDetailBottom scrolls to that card (defaultScrollAnchor is a no-op on a List) and -qaCopyPostcode holds the copied confirmation long enough to screenshot.
This commit is contained in:
FuelBoard Contributor
2026-10-16 14:51:36 +01:00
parent ff8a1e18d0
commit 05c76f21a9
9 changed files with 519 additions and 299 deletions
+23 -2
View File
@@ -31,8 +31,8 @@ struct ContentView: View {
@State private var distanceUnit: DistanceUnit = FuelStore.loadDistanceUnit()
@State private var priceDisplayStyle: PriceDisplayStyle = ContentView.qaPriceStyleOverride(default: FuelStore.loadPriceDisplayStyle())
@State private var stationTapAction: StationTapAction = FuelStore.loadStationTapAction()
@State private var fuelSavingsSettings: FuelSavingsSettings = FuelStore.loadFuelSavingsSettings()
@State private var sessionFuelSavingsAmount: FuelSavingsFillAmount = FuelStore.loadFuelSavingsSettings().preferredAmount
@State private var fuelSavingsSettings: FuelSavingsSettings = ContentView.qaSavingsSettingsOverride(default: FuelStore.loadFuelSavingsSettings())
@State private var sessionFuelSavingsAmount: FuelSavingsFillAmount = ContentView.qaSavingsSettingsOverride(default: FuelStore.loadFuelSavingsSettings()).preferredAmount
@State private var favourites: [FavouriteEntry] = FuelStore.loadFavourites()
@State private var alertsEnabled: Bool = FuelStore.loadAlertsEnabled()
@State private var alertsRadius: Double = FuelStore.loadAlertsRadius()
@@ -175,6 +175,27 @@ struct ContentView: View {
)
}
/// QA hook: `-qaConfigureSavings` configures the Fuel Savings feature for the
/// session (the sheet's Best Value card, the Worth the Drive sort and the
/// Key sheet's Best Value row are ALL gated on `settings.isConfigured`), so
/// they can be screenshotted without walking Settings. It writes through the
/// store exactly as the Settings screen does and returns what it wrote, so
/// the app runs on the same stored values — not a stubbed, parallel one.
static func qaSavingsSettingsOverride(default value: FuelSavingsSettings) -> FuelSavingsSettings {
#if DEBUG
guard ProcessInfo.processInfo.arguments.contains("-qaConfigureSavings") else { return value }
let seeded = FuelSavingsSettings(
enabled: true,
mpg: value.mpg,
preferredAmount: FuelSavingsFillAmount(value: 60, unit: .pounds)
)
FuelStore.saveFuelSavingsSettings(seeded)
return seeded
#else
return value
#endif
}
private func installLocationUpdateHook() {
locationManager.onLocationUpdate = {
self.updateAlertMonitor()