- FuelType labels: 'Unleaded (E10)'/'Premium (E5)' -> 'Unleaded'/'Premium' - New DistanceUnit (miles/km) preference; all app + widget distances, radii and alert text convert/display in the chosen unit - Settings tab (4th tab): segmented miles/km picker, 'Show introduction' replay button (onboarding moved out of Alerts tab), StoreKit tip £4.99 - ProximityMonitor + widget notifications use the chosen unit - Tests: label expectations updated, DistanceUnit conversion + format tests
71 lines
3.1 KiB
Swift
71 lines
3.1 KiB
Swift
import SwiftUI
|
||
|
||
/// Alerts tab — enables the cheapest-station proximity alerts and shows what's
|
||
/// being monitored.
|
||
struct AlertsView: View {
|
||
@Binding var enabled: Bool
|
||
@Binding var radius: Double // stored in km (monitor + storage)
|
||
let distanceUnit: DistanceUnit
|
||
let monitoredCount: Int
|
||
let lastAlert: String?
|
||
|
||
/// The radius slider works in the user's chosen unit; the stored value
|
||
/// stays km so ProximityMonitor and persistence never change.
|
||
private var radiusInUnit: Double { distanceUnit.fromKM(radius) }
|
||
|
||
var body: some View {
|
||
NavigationStack {
|
||
List {
|
||
Section {
|
||
Toggle("Cheapest-station alerts", isOn: $enabled)
|
||
} footer: {
|
||
Text("When you approach a station that is the cheapest within the radius, FuelBoard sends a notification — even with the app closed.")
|
||
}
|
||
|
||
if enabled {
|
||
Section("Trigger radius") {
|
||
VStack(alignment: .leading, spacing: 8) {
|
||
HStack {
|
||
Text("Radius")
|
||
Spacer()
|
||
Text(String(format: "%.1f %@", radiusInUnit, distanceUnit.shortName))
|
||
.foregroundStyle(.secondary)
|
||
.monospacedDigit()
|
||
}
|
||
// 1–10 in the user's unit; convert back to km on change.
|
||
Slider(value: Binding(
|
||
get: { radiusInUnit },
|
||
set: { radius = distanceUnit.toKM($0) }
|
||
), in: 1...10, step: distanceUnit == .kilometers ? 1 : 0.5)
|
||
}
|
||
}
|
||
|
||
Section("Monitoring") {
|
||
if monitoredCount == 0 {
|
||
Text("No stations monitored yet — open the Stations tab to load prices first.")
|
||
.font(.caption)
|
||
.foregroundStyle(.secondary)
|
||
} else {
|
||
LabeledContent("Geofenced stations", value: "\(monitoredCount)")
|
||
Text("Your favourites get priority, then the closest stations fill the rest (18 max, iOS region limit).")
|
||
.font(.caption)
|
||
.foregroundStyle(.secondary)
|
||
Text("Alerts are checked against the cheapest station within the trigger radius for the selected fuel. Each station alerts at most once per hour.")
|
||
.font(.caption)
|
||
.foregroundStyle(.secondary)
|
||
}
|
||
}
|
||
|
||
if let lastAlert {
|
||
Section("Last alert") {
|
||
Label(lastAlert, systemImage: "bell.badge.fill")
|
||
.font(.footnote)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.navigationTitle("Alerts")
|
||
}
|
||
}
|
||
}
|