Retire the Best Value proximity alert option; move Key sheet copy into a tested model

- Alerts: drop the alert-type picker and the Best Value alert path, so
  proximity alerts always follow the cheapest station. A stored `bestValue`
  selection now falls back to cheapest when loaded.
- Key sheet: the price-rating, savings, station-label and favourite wording
  comes from `KeySheetContent` in Shared/FuelSavings.swift — a Foundation-only
  model with tests that pin the exact meaning of each indicator — and the
  sheet is built from that model rather than inline strings.
- BACKLOG: record the plan to restore Best Value proximity alerts behind one
  shared evaluator (user-location baseline, a single disclosed qualification
  rule, and real/Test alert parity).
- Bump CURRENT_PROJECT_VERSION to 29.
This commit is contained in:
FuelBoard Contributor
2026-10-18 17:16:12 +01:00
parent c331f3d663
commit 6cbb083208
11 changed files with 355 additions and 225 deletions
+36
View File
@@ -309,6 +309,42 @@ struct FuelSavingsRankedStation: Equatable {
let pricePencePerLitre: Double
}
/// The user-facing copy shown by the Stations tab's Key sheet. Keeping the
/// descriptions in one Foundation-only model lets tests pin the exact meaning of
/// each visual indicator without coupling the wording to SwiftUI layout.
enum KeySheetContent {
struct Item: Equatable {
let label: String
let description: String
}
static let priceRatings = [
Item(label: "Good price", description: "Within 1.5p/L of the cheapest."),
Item(label: "Okay", description: "More than 1.5p/L, up to 4p/L above the cheapest."),
Item(label: "Pricey", description: "More than 4p/L above the cheapest.")
]
static let savings = [
Item(label: "Saves", description: "You’ll save money compared with your closest station, including travel costs."),
Item(label: "Break even", description: "The saving or extra cost is negligible."),
Item(label: "Costs more", description: "Filling up here costs more than at your closest station, including travel.")
]
static let stationLabels = [
Item(label: "BEST VALUE", description: "Meets your minimum saving after travel costs."),
Item(label: "CHEAPEST", description: "The lowest fuel price per litre within your selected range."),
Item(label: "CLOSEST", description: "The nearest station by journey distance."),
Item(label: "TOP", description: "The cheapest station in your Favourites for the selected fuel.")
]
static let favourite = Item(
label: "Favourites",
description: "Star a station to save it to your Favourites."
)
static let helpTitle = "How does Best Value work?"
}
/// Which recommendation badge a station listing row shows, if any.
///
/// Presentation only — no new rules: the BEST VALUE qualification reuses the
+5 -3
View File
@@ -701,10 +701,12 @@ struct FuelStore {
}
static func loadAlertsMode() -> AlertMode {
if let raw = loadString(service: alertsModeKey), let mode = AlertMode(rawValue: raw) {
return mode
guard let raw = loadString(service: alertsModeKey),
let mode = AlertMode(rawValue: raw),
mode == .cheapest else {
return .cheapest
}
return .cheapest
return mode
}
static func saveAlertsMode(_ mode: AlertMode) {