From 810cc2c0065245eb162073d8e957be1f0d57ba8b Mon Sep 17 00:00:00 2001 From: FuelBoard Contributor Date: Tue, 11 Aug 2026 17:54:04 +0100 Subject: [PATCH] =?UTF-8?q?Show=20full=20fetch=20in=20list=20(count=20pick?= =?UTF-8?q?er=20respected);=20radius=20scope=20only=20for=20cheapest/RAG?= =?UTF-8?q?=20reference;=20row=20=3D=20logo=20|=20name/address/distance=20?= =?UTF-8?q?|=20=C2=A3price=20+=20delta=20|=20star?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FuelBoard/ContentView.swift | 68 ++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/FuelBoard/ContentView.swift b/FuelBoard/ContentView.swift index 4de059b..eb79eb1 100644 --- a/FuelBoard/ContentView.swift +++ b/FuelBoard/ContentView.swift @@ -21,10 +21,11 @@ struct ContentView: View { @State private var locationManager = LocationManager() @StateObject private var monitor = ProximityMonitor() - /// Stations within the alert trigger radius of the current location, used - /// as the pool for "cheapest" (RAG reference, TOP, sorting). Falls back to - /// the full fetch when location is unknown or the radius pool is empty - /// (rural areas) so the list is never blank. + /// Stations within the alert trigger radius of the current location — used + /// ONLY as the "cheapest" reference (RAG, TOP, deltas), so the cheapest + /// label matches what alerts would flag. The list itself shows the full + /// fetch so the count picker works. Falls back to the full fetch when + /// location is unknown or the radius pool is empty. private var radiusScopedStations: [FuelStation] { guard let location else { return stations } let within = stations.filter { @@ -42,7 +43,9 @@ struct ContentView: View { } private var sortedStations: [FuelStation] { - let available = radiusScopedStations.filter { $0.prices[selectedFuel] != nil } + // Full fetch pool — NOT radius-scoped, so the results count picker + // (10/25/50/75/100) is respected. + let available = stations.filter { $0.prices[selectedFuel] != nil } switch sortMode { case .closest: guard let location else { return available.sorted { $0.prices[selectedFuel]! < $1.prices[selectedFuel]! } } @@ -224,7 +227,7 @@ struct StationRow: View { var body: some View { HStack(spacing: 12) { - // Round brand logo (or generic fuel pump fallback) + // LEFT — round brand logo (or generic fuel pump fallback) Group { if let asset = station.brandImageName { Image(asset) @@ -243,10 +246,9 @@ struct StationRow: View { .overlay(Circle().stroke(Color.primary.opacity(0.08), lineWidth: 1)) .shadow(color: .black.opacity(0.08), radius: 2, y: 1) - // Name at natural width (does NOT fill the row — truncates); - // price + details stay on the row below, right-aligned. - VStack(alignment: .leading, spacing: 3) { - HStack(alignment: .firstTextBaseline, spacing: 6) { + // MIDDLE — name, full address, distance + VStack(alignment: .leading, spacing: 2) { + HStack(spacing: 6) { Text(station.name) .font(.headline) .lineLimit(1) @@ -259,37 +261,41 @@ struct StationRow: View { .background(Capsule().fill(.blue.opacity(0.15))) .foregroundStyle(.blue) } - Spacer(minLength: 6) } - - HStack(spacing: 5) { - Text("\(station.address), \(station.postcode)") - .font(.caption) + Text("\(station.address), \(station.postcode)") + .font(.caption) + .foregroundStyle(.secondary) + .lineLimit(1) + .truncationMode(.tail) + if let location { + Text(String(format: "%.1f km", station.distanceKM(to: location.lat, lng2: location.lng))) + .font(.caption2) .foregroundStyle(.secondary) - .lineLimit(1) - Spacer(minLength: 8) - if let location { - Text(String(format: "%.1f km", station.distanceKM(to: location.lat, lng2: location.lng))) - .font(.caption2) - .foregroundStyle(.secondary) - .monospacedDigit() - } - if let price = station.prices[fuel] { + .monospacedDigit() + } + } + .frame(maxWidth: .infinity, alignment: .leading) + + // RIGHT — price in £ (no p) + difference vs cheapest + VStack(alignment: .trailing, spacing: 2) { + if let price = station.prices[fuel] { + HStack(spacing: 5) { Circle() .fill(ragColor) - .frame(width: 10, height: 10) - Text(String(format: "%.1fp", price)) + .frame(width: 8, height: 8) + Text(String(format: "£%.3f", price / 100)) .font(.title3.bold()) .monospacedDigit() - if let deltaText { - Text(deltaText) - .font(.caption2.bold()) - .foregroundStyle(ragColor) - } + } + if let deltaText { + Text(deltaText) + .font(.caption2.bold()) + .foregroundStyle(ragColor) } } } + // FAR RIGHT — favourite star Button { onToggleFavourite() } label: {