import SwiftUI /// Alerts tab — enables the cheapest-station proximity alerts and shows what's /// being monitored. The fuel being monitored is chosen HERE, independently of /// the Stations-tab selection: users can browse any fuel without re-targeting /// their alerts (and vice versa). The Live Activity section also lives here — /// it mirrors this page's shape (toggle + fuel + distance) so the two /// "notify me while driving" surfaces sit together. struct AlertsView: View { @Binding var enabled: Bool @Binding var radius: Double // stored in km (monitor + storage) @Binding var fuel: FuelType // the fuel alerts monitor for /// Whether the "cheapest nearby" Live Activity is shown on the Lock Screen /// / Dynamic Island. Tracks its OWN fuel + radius (below) — independent of /// the Stations tab. @Binding var liveActivityEnabled: Bool /// Fuel the Live Activity tracks (independent of the Stations tab). @Binding var liveActivityFuel: FuelType /// Search radius (miles, 5/10/15) the Live Activity uses. @Binding var liveActivityRadiusMiles: Int let distanceUnit: DistanceUnit let monitoredCount: Int let lastAlert: String? /// The radius picker works in the user's chosen unit; the stored value /// stays km so ProximityMonitor and persistence never change. Options are /// snapped to the nearest picker value so any stored radius still selects. private var radiusOption: Binding { Binding( get: { let inUnit = distanceUnit.fromKM(radius) return FuelStore.alertRadiusOptions .min(by: { abs(Double($0) - inUnit) < abs(Double($1) - inUnit) }) ?? 3 }, set: { value in radius = distanceUnit.toKM(Double(value)) } ) } var body: some View { NavigationStack { List { Section { Toggle("Cheapest-station alerts", isOn: $enabled) Picker("Fuel", selection: $fuel) { ForEach(FuelType.allCases) { fuel in Text(fuel.displayName).tag(fuel) } } Picker("Radius", selection: radiusOption) { ForEach(FuelStore.alertRadiusOptions, id: \.self) { value in Text("\(value) \(distanceUnit.label)").tag(value) } } } header: { Text("Cheapest-station alerts") } footer: { Text("When you approach a station that is the cheapest within the radius, FuelBoard sends a notification — even with the app closed. Alerts watch for the cheapest \(fuel.displayName.lowercased()) station within the radius.") } if enabled { 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 for \(fuel.displayName.lowercased()) get priority, then the closest stations selling that fuel 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 fuel chosen above. 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) } } } Section { Toggle("Live Activity", isOn: $liveActivityEnabled) Picker("Fuel", selection: $liveActivityFuel) { ForEach(FuelType.allCases) { fuel in Text(fuel.displayName).tag(fuel) } } Picker("Distance", selection: $liveActivityRadiusMiles) { ForEach(FuelStore.stationRadiusOptions, id: \.self) { miles in Text("\(miles) \(distanceUnit.label)").tag(miles) } } } header: { Text("Live Activity") } footer: { Text("Shows the cheapest station for the fuel and distance you pick here on the Lock Screen and Dynamic Island — independent of the Stations tab. Updates as you drive; tap to open directions. Live Activities can be disabled in System Settings → Live Activities.") } } .navigationTitle("Alerts") } } }