Favourites are fuel-scoped: starring pins the station for one fuel only
Fixing the bug where favouriting an Unleaded entry also created a Diesel favourite. Favourites are now [FavouriteEntry] = (station, fuel) pairs: - Starring a row pins it only for the fuel being viewed - Favourites tabs show only fuels that actually have favourites - Geofence monitor gives priority slots only to favourites matching the monitored fuel - Tests updated + new fuel-scoping test (31/31 passing)
This commit is contained in:
@@ -3,20 +3,21 @@ import SwiftUI
|
||||
/// Favourites tab — starred stations, split by fuel type. Each fuel type
|
||||
/// with at least one favourite appears as its own tab; that tab's favourites
|
||||
/// are ranked cheapest-first for that fuel, with the cheapest called out.
|
||||
/// Favourites are fuel-scoped entries — starring a station only pins it for
|
||||
/// the fuel you were viewing, so an Unleaded favourite never shows as Diesel.
|
||||
struct FavouritesView: View {
|
||||
let favourites: [FuelStation]
|
||||
let favourites: [FavouriteEntry]
|
||||
/// The app's currently selected fuel — used only as the initial tab.
|
||||
let selectedFuel: FuelType
|
||||
let location: Coordinate?
|
||||
let distanceUnit: DistanceUnit
|
||||
let favouriteIDs: Set<String>
|
||||
var onToggleFavourite: (FuelStation) -> Void = { _ in }
|
||||
var onToggleFavourite: (FuelStation, FuelType) -> Void = { _, _ in }
|
||||
|
||||
/// Fuel types that currently have at least one favourite selling them —
|
||||
/// these are the only tabs shown.
|
||||
/// Fuel types that currently have at least one favourite — these are the
|
||||
/// only tabs shown (a fuel with no favourites gets no tab).
|
||||
private var availableFuels: [FuelType] {
|
||||
FuelType.allCases.filter { fuel in
|
||||
favourites.contains { $0.prices[fuel] != nil }
|
||||
favourites.contains { $0.fuel == fuel }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,9 +29,9 @@ struct FavouritesView: View {
|
||||
availableFuels.contains(fuel) ? fuel : (availableFuels.first ?? .e10)
|
||||
}
|
||||
|
||||
/// Favourites that sell the active fuel, cheapest first (distance tiebreak).
|
||||
/// Stations favourited for the active fuel, cheapest first (distance tiebreak).
|
||||
private var ranked: [FuelStation] {
|
||||
let available = favourites.filter { $0.prices[activeFuel] != nil }
|
||||
let available = favourites.filter { $0.fuel == activeFuel }.map(\.station)
|
||||
return available.sorted { lhs, rhs in
|
||||
let lPrice = lhs.prices[activeFuel]!
|
||||
let rPrice = rhs.prices[activeFuel]!
|
||||
@@ -41,20 +42,23 @@ struct FavouritesView: View {
|
||||
}
|
||||
}
|
||||
|
||||
/// IDs favourited for the active fuel — the star state on each row.
|
||||
private var activeFuelFavouriteIDs: Set<String> {
|
||||
Set(favourites.filter { $0.fuel == activeFuel }.map(\.station.id))
|
||||
}
|
||||
|
||||
private var cheapest: FuelStation? { ranked.first }
|
||||
private var cheapestPrice: Double? { cheapest?.prices[activeFuel] }
|
||||
|
||||
init(favourites: [FuelStation],
|
||||
init(favourites: [FavouriteEntry],
|
||||
selectedFuel: FuelType,
|
||||
location: Coordinate?,
|
||||
distanceUnit: DistanceUnit,
|
||||
favouriteIDs: Set<String>,
|
||||
onToggleFavourite: @escaping (FuelStation) -> Void = { _ in }) {
|
||||
onToggleFavourite: @escaping (FuelStation, FuelType) -> Void = { _, _ in }) {
|
||||
self.favourites = favourites
|
||||
self.selectedFuel = selectedFuel
|
||||
self.location = location
|
||||
self.distanceUnit = distanceUnit
|
||||
self.favouriteIDs = favouriteIDs
|
||||
self.onToggleFavourite = onToggleFavourite
|
||||
_fuel = State(initialValue: selectedFuel)
|
||||
}
|
||||
@@ -70,7 +74,7 @@ struct FavouritesView: View {
|
||||
.foregroundStyle(.secondary)
|
||||
Text("No favourites yet")
|
||||
.font(.headline)
|
||||
Text("Tap the star on any station in the Stations tab to pin it here, ranked by which is cheapest.")
|
||||
Text("Tap the star on any station in the Stations tab to pin it here, ranked by which is cheapest for that fuel.")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.multilineTextAlignment(.center)
|
||||
@@ -108,8 +112,8 @@ struct FavouritesView: View {
|
||||
distanceUnit: distanceUnit,
|
||||
baselinePrice: cheapestPrice,
|
||||
isTopResult: index == 0,
|
||||
isFavourite: favouriteIDs.contains(station.id),
|
||||
onToggleFavourite: { onToggleFavourite(station) }
|
||||
isFavourite: activeFuelFavouriteIDs.contains(station.id),
|
||||
onToggleFavourite: { onToggleFavourite(station, activeFuel) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user