diff --git a/FuelBoard/FavouritesView.swift b/FuelBoard/FavouritesView.swift index 6c4abd6..b9f7d92 100644 --- a/FuelBoard/FavouritesView.swift +++ b/FuelBoard/FavouritesView.swift @@ -48,6 +48,14 @@ struct FavouritesView: View { /// Trends sheet (price history chart) presentation state. @State private var showTrends = false + /// The Key (legend) sheet — the same sheet the Stations tab presents, opened + /// from the info button beside Edit. + @State private var showKey = false + /// The Key sheet's two nested sheets, owned here because its rows set them + /// (same arrangement as StationsView, so the QA hooks behave identically). + @State private var showBestValueInfo = false + @State private var showImportantInformation = false + /// Station picked for the More-info sheet (tap action = showDetails). @State private var detailStation: FuelStation? @@ -206,8 +214,8 @@ struct FavouritesView: View { } .navigationTitle(String(localized: "Favourites", comment: "Favourites tab title")) .toolbar { - if !favourites.isEmpty { - ToolbarItemGroup(placement: .topBarTrailing) { + ToolbarItemGroup(placement: .topBarTrailing) { + if !favourites.isEmpty { Button { showTrends = true } label: { @@ -216,8 +224,25 @@ struct FavouritesView: View { } EditButton() } + // Same button and same slot as the Stations tab: last in the + // group, so it sits to the right of Edit. Shown even with no + // favourites — the legend explains the prices and labels, which + // matter before anything is starred. + Button { + showKey = true + } label: { + Image(systemName: "info.circle") + } + .accessibilityLabel(String(localized: "Key", comment: "Key button accessibility label")) } } + .sheet(isPresented: $showKey) { + KeySheetView( + fuelTint: activeFuel.tintColor, + showBestValueInfo: $showBestValueInfo, + showImportantInformation: $showImportantInformation + ) + } .sheet(isPresented: $showTrends) { TrendsView( favourites: favourites, diff --git a/FuelBoard/StationsView.swift b/FuelBoard/StationsView.swift index cc87de8..f7ca052 100644 --- a/FuelBoard/StationsView.swift +++ b/FuelBoard/StationsView.swift @@ -1,6 +1,94 @@ import SwiftUI import WidgetKit +/// The "Key" legend: price ratings, savings capsules, station labels, the +/// favourite glyph, then the two deeper explanations. One sheet for both list +/// tabs — Stations opens it from the info button in the navigation bar, +/// Favourites from the button beside Edit — so the legend cannot drift between +/// them. +/// +/// Dismisses through the environment rather than the presenting view's state, and +/// takes the two nested-sheet flags as bindings, so each tab keeps owning its own +/// QA launch-argument hooks. +struct KeySheetView: View { + /// The selected fuel's colour. `KeyStationLabelIndicator` draws its pump badge + /// in it, so the legend matches the rows the reader is looking at. + let fuelTint: Color + @Binding var showBestValueInfo: Bool + @Binding var showImportantInformation: Bool + + @Environment(\.dismiss) private var dismiss + + var body: some View { + NavigationStack { + List { + Section { + KeySheetDescriptionRow(item: KeySheetContent.priceRatings[0]) { + KeyPriceRatingIndicator(item: KeySheetContent.priceRatings[0], color: .green) + } + KeySheetDescriptionRow(item: KeySheetContent.priceRatings[1]) { + KeyPriceRatingIndicator(item: KeySheetContent.priceRatings[1], color: .orange) + } + KeySheetDescriptionRow(item: KeySheetContent.priceRatings[2]) { + KeyPriceRatingIndicator(item: KeySheetContent.priceRatings[2], color: .red) + } + } header: { + Text("Price ratings") + } + + Section { + ForEach(KeySheetContent.savings, id: \.label) { item in + KeySheetDescriptionRow(item: item) { + KeySavingsCapsule(label: item.label) + } + } + } header: { + Text("Savings") + } + + Section { + ForEach(KeySheetContent.stationLabels, id: \.label) { item in + KeySheetDescriptionRow(item: item) { + KeyStationLabelIndicator(label: item.label, fuelColor: fuelTint) + } + } + } header: { + Text("Station labels") + } + + Section { + KeySheetDescriptionRow(item: KeySheetContent.favourite) { + FavouriteStarGlyph(isFavourite: true) + } + } header: { + Text("Favourites") + } + + Section { + HowBestValueRow { showBestValueInfo = true } + } + + Section { + ImportantInformationRow { showImportantInformation = true } + } + } + .navigationTitle("Key") + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .confirmationAction) { + Button("Done") { dismiss() } + } + } + // Nested sheet: the Key sheet stays behind the explanation. + .sheet(isPresented: $showBestValueInfo) { HowBestValueSheet() } + // Nested sheet: the Key sheet stays behind the disclaimer. + .importantInformationSheet(isPresented: $showImportantInformation) + } + .presentationDetents([.fraction(0.6), .large]) + .presentationBackground(Color(UIColor.systemGroupedBackground)) + } +} + /// Stations tab — the main list with fuel picker, distance filter, sort, pagination. struct StationsView: View { let stations: [FuelStation] @@ -296,73 +384,15 @@ struct StationsView: View { ) } + /// The legend sheet, shared with the Favourites tab. Only the fuel differs: + /// its colour tints the station-label row, so the legend matches the rows the + /// reader is actually looking at. private var keySheet: some View { - NavigationStack { - List { - Section { - KeySheetDescriptionRow(item: KeySheetContent.priceRatings[0]) { - KeyPriceRatingIndicator(item: KeySheetContent.priceRatings[0], color: .green) - } - KeySheetDescriptionRow(item: KeySheetContent.priceRatings[1]) { - KeyPriceRatingIndicator(item: KeySheetContent.priceRatings[1], color: .orange) - } - KeySheetDescriptionRow(item: KeySheetContent.priceRatings[2]) { - KeyPriceRatingIndicator(item: KeySheetContent.priceRatings[2], color: .red) - } - } header: { - Text("Price ratings") - } - - Section { - ForEach(KeySheetContent.savings, id: \.label) { item in - KeySheetDescriptionRow(item: item) { - KeySavingsCapsule(label: item.label) - } - } - } header: { - Text("Savings") - } - - Section { - ForEach(KeySheetContent.stationLabels, id: \.label) { item in - KeySheetDescriptionRow(item: item) { - KeyStationLabelIndicator(label: item.label, fuelColor: selectedFuel.tintColor) - } - } - } header: { - Text("Station labels") - } - - Section { - KeySheetDescriptionRow(item: KeySheetContent.favourite) { - FavouriteStarGlyph(isFavourite: true) - } - } header: { - Text("Favourites") - } - - Section { - HowBestValueRow { showBestValueInfo = true } - } - - Section { - ImportantInformationRow { showImportantInformation = true } - } - } - .navigationTitle("Key") - .navigationBarTitleDisplayMode(.inline) - .toolbar { - ToolbarItem(placement: .confirmationAction) { - Button("Done") { showKey = false } - } - } - // Nested sheet: the Key sheet stays behind the explanation. - .sheet(isPresented: $showBestValueInfo) { HowBestValueSheet() } - // Nested sheet: the Key sheet stays behind the disclaimer. - .importantInformationSheet(isPresented: $showImportantInformation) - } - .presentationDetents([.fraction(0.6), .large]) - .presentationBackground(Color(UIColor.systemGroupedBackground)) + KeySheetView( + fuelTint: selectedFuel.tintColor, + showBestValueInfo: $showBestValueInfo, + showImportantInformation: $showImportantInformation + ) } private func stationRow(_ station: FuelStation) -> some View {