Best Value: rename the remaining user-facing copy, hide the sheet section when off

Following the sort-segment rename, the rest of the user-facing "Worth the Drive"
copy moves to "Best Value".

- Settings: the toggle is now just "Best Value" (was "Enable Worth the Drive"),
  and the narrative footer opens "Best Value estimates fuel cost only, …".
- More info sheet: the section header is "Best Value" (was "Worth the drive?"),
  and the section itself is now conditional. `fuelSavings` is nil whenever the
  feature is off — `savingsLookup` returns nil when it is not configured — so
  the heading is never left dangling over an empty section while the feature is
  disabled.
- The unavailable text reads "Best Value unavailable: …".
- Comments and doc comments that named the sort were updated so they match the
  UI instead of contradicting it.

Deliberately unchanged: the enum's raw value stays `worthTheDrive`, so stored
sort preferences and widget configs keep decoding, and FuelSavingsStatus keeps
its verdict wording ("Worth the drive" / "Not worth the drive") — that describes
a station's verdict rather than the feature, and is not shown in the UI.

Verified on the simulator: with the feature OFF the more info sheet shows
Address / Distance / Directions and no heading at all; with it ON the sheet
shows the "Best Value" section; Settings reads "Fuel Savings" / "Best Value"
with no "Enable" anywhere. 172 tests, 0 failures.
This commit is contained in:
FuelBoard Contributor
2026-10-11 20:11:57 +01:00
parent 801f969644
commit d348157a45
7 changed files with 31 additions and 23 deletions
+2 -2
View File
@@ -340,7 +340,7 @@ struct ContentView: View {
private static var lastDriveLogLine: String?
/// One summary line per ranking pass (FB-DRIVE) so a device console shows
/// whether the Worth the Drive list is actually carrying savings for the
/// whether the Best Value list is actually carrying savings for the
/// whole pool — the regression was silent otherwise.
private func logWorthTheDriveSummary(_ ordered: [FuelStation],
baseline: FuelStation?,
@@ -1357,7 +1357,7 @@ struct StationRow: View {
VStack(alignment: .trailing, spacing: 2) {
if isTopResult {
// The badge always marks the CHEAPEST PUMP PRICE (never
// "best saving"), so in Worth the Drive order — where the
// "best saving"), so in Best Value order — where the
// top row is the best net saving — it may sit lower down
// the list, and says so. It sits ABOVE the price it
// annotates rather than beside the name, so it reads as
+1 -1
View File
@@ -142,7 +142,7 @@ struct FuelSavingsSummaryView: View {
}
}
case .unavailable(let reason):
Text(compact ? "Savings unavailable" : "Worth the Drive unavailable: \(reason)")
Text(compact ? "Savings unavailable" : "Best Value unavailable: \(reason)")
.font(compact ? .caption2 : .caption)
.foregroundStyle(.secondary)
case nil:
+3 -3
View File
@@ -150,13 +150,13 @@ struct SettingsView: View {
}
Section {
Toggle("Enable Worth the Drive", isOn: fuelSavingsEnabledBinding)
Toggle("Best Value", isOn: fuelSavingsEnabledBinding)
// The feature's own controls follow its toggle: switched
// off they grey out but stay on screen (same rule as the
// distance picker in Closest mode) and keep their values, so
// re-enabling restores exactly what was there. The sections
// that USE the feature — the in-list fill-up control and the
// Worth the Drive sort option — are gated on `isConfigured`,
// Best Value sort option — are gated on `isConfigured`,
// which already includes `enabled`, so they hide entirely.
Group {
HStack {
@@ -199,7 +199,7 @@ struct SettingsView: View {
} header: {
Text("Fuel Savings")
} footer: {
Text("Worth the Drive estimates fuel cost only, using UK imperial MPG, your typical purchase amount, fuel prices and Apple Maps road distances. Real-world average MPG is better than manufacturer figures; the fill-up amount is your usual purchase, not tank capacity.")
Text("Best Value estimates fuel cost only, using UK imperial MPG, your typical purchase amount, fuel prices and Apple Maps road distances. Real-world average MPG is better than manufacturer figures; the fill-up amount is your usual purchase, not tank capacity.")
}
Section {
+15 -9
View File
@@ -69,15 +69,21 @@ struct StationDetailView: View {
.background(Capsule().fill(Color.orange.opacity(0.14)))
}
}
Section {
FuelSavingsSummaryView(
availability: fuelSavings,
amount: fuelSavingsAmount,
baselineStationName: savingsBaselineStationName,
distanceUnit: distanceUnit
)
} header: {
Text("Worth the drive?")
// Only shown while Fuel Savings backs it. `fuelSavings` is nil
// when the feature is off — `savingsLookup` returns nil when it
// is not configured — so the heading cannot be left dangling
// over an empty section.
if let fuelSavings {
Section {
FuelSavingsSummaryView(
availability: fuelSavings,
amount: fuelSavingsAmount,
baselineStationName: savingsBaselineStationName,
distanceUnit: distanceUnit
)
} header: {
Text("Best Value")
}
}
Section {