From d62ac1b26556b8e5ab0e6d09019f14df728eb030 Mon Sep 17 00:00:00 2001 From: FuelBoard Contributor Date: Tue, 11 Aug 2026 19:38:08 +0100 Subject: [PATCH] Distance filter below fuel type under Distance heading; list paginated 10 rows with Show more --- FuelBoard/StationsView.swift | 59 ++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/FuelBoard/StationsView.swift b/FuelBoard/StationsView.swift index c4cfadc..8caca6b 100644 --- a/FuelBoard/StationsView.swift +++ b/FuelBoard/StationsView.swift @@ -1,7 +1,7 @@ import SwiftUI import WidgetKit -/// Stations tab — the main list with fuel picker, sort, station count limit. +/// Stations tab — the main list with fuel picker, distance filter, sort, pagination. struct StationsView: View { let stations: [FuelStation] let totalCount: Int @@ -15,6 +15,13 @@ struct StationsView: View { var onToggleFavourite: (FuelStation) -> Void = { _ in } var onRefresh: () async -> Void = {} + /// Pagination: one page = 10 rows, reset whenever the underlying list + /// changes (new fetch, fuel/sort/radius switch). RAG/TOP/deltas still come + /// from the whole radius pool via `cheapestPrice` — paging never changes + /// which station is "best". + @State private var pageSize = 10 + @State private var visibleCount = 10 + var body: some View { NavigationStack { List { @@ -43,6 +50,22 @@ struct StationsView: View { } } + Section("Distance") { + Picker("Distance", selection: $stationLimit) { + ForEach(FuelStore.stationRadiusOptions, id: \.self) { miles in + Text("\(miles) miles").tag(miles) + } + } + .pickerStyle(.segmented) + .onChange(of: stationLimit) { _, newValue in + FuelStore.saveStationLimit(newValue) + } + .padding(.vertical, 2) + Text("\(totalCount) stations within \(stationLimit) miles") + .font(.caption2) + .foregroundStyle(.secondary) + } + Section("Stations") { Picker("Sort by", selection: $sortMode) { ForEach(SortMode.allCases) { mode in @@ -64,7 +87,7 @@ struct StationsView: View { Text("No \(selectedFuel.displayName) stations found.") .foregroundStyle(.secondary) } else { - ForEach(Array(stations.enumerated()), id: \.element.id) { index, station in + ForEach(Array(stations.prefix(visibleCount).enumerated()), id: \.element.id) { index, station in StationRow( station: station, fuel: selectedFuel, @@ -75,23 +98,23 @@ struct StationsView: View { onToggleFavourite: { onToggleFavourite(station) } ) } - } - if !stations.isEmpty { - Divider() - Picker("Within", selection: $stationLimit) { - ForEach(FuelStore.stationRadiusOptions, id: \.self) { miles in - Text("\(miles) miles").tag(miles) + if visibleCount < stations.count { + Button { + visibleCount += pageSize + } label: { + HStack { + Spacer() + Text("Show \(min(pageSize, stations.count - visibleCount)) more (\(stations.count - visibleCount) remaining)") + Spacer() + } } + } else { + Text("All \(stations.count) stations shown") + .font(.caption2) + .foregroundStyle(.secondary) + .frame(maxWidth: .infinity) } - .pickerStyle(.segmented) - .onChange(of: stationLimit) { _, newValue in - FuelStore.saveStationLimit(newValue) - } - .padding(.vertical, 2) - Text("\(totalCount) stations within \(stationLimit) miles") - .font(.caption2) - .foregroundStyle(.secondary) } } @@ -134,6 +157,10 @@ struct StationsView: View { // Manual override for the twice-a-day cache policy. await onRefresh() } + .onChange(of: stations) { _, _ in + // New fetch or filter switch → back to the first page. + visibleCount = pageSize + } .navigationTitle("FuelBoard") } }