diff --git a/FuelBoard/ContentView.swift b/FuelBoard/ContentView.swift index 73229b5..4741c88 100644 --- a/FuelBoard/ContentView.swift +++ b/FuelBoard/ContentView.swift @@ -1032,6 +1032,12 @@ struct StationRow: View { .background(Capsule().fill(.blue.opacity(0.15))) .foregroundStyle(.blue) } + ForEach(StationNotice.notices(for: station)) { notice in + Image(systemName: notice.symbolName) + .font(.caption2.weight(.semibold)) + .foregroundStyle(.secondary) + .accessibilityLabel(notice.title) + } } Text("\(station.address), \(station.postcode)") .font(.caption) diff --git a/FuelBoard/StationDetailView.swift b/FuelBoard/StationDetailView.swift index 2d0512d..d375273 100644 --- a/FuelBoard/StationDetailView.swift +++ b/FuelBoard/StationDetailView.swift @@ -45,6 +45,14 @@ struct StationDetailView: View { LabeledContent("Distance", value: distanceUnit.format(km)) .monospacedDigit() } + ForEach(StationNotice.notices(for: station)) { notice in + Label(notice.title, systemImage: notice.symbolName) + .font(.subheadline.weight(.semibold)) + .foregroundStyle(.orange) + .padding(.horizontal, 10) + .padding(.vertical, 6) + .background(Capsule().fill(Color.orange.opacity(0.14))) + } } Section { Button { diff --git a/FuelBoard/StationNotice.swift b/FuelBoard/StationNotice.swift new file mode 100644 index 0000000..8c8a1cd --- /dev/null +++ b/FuelBoard/StationNotice.swift @@ -0,0 +1,41 @@ +import Foundation + +/// Presentation-only notices derived from existing station metadata. +/// +/// These do not alter `FuelStation`, persistence, filtering, sorting, or +/// navigation. They are intentionally small and reusable so additional +/// informational station notices can be added later from the UI layer. +enum StationNotice: Identifiable, Equatable { + case membershipRequired + + var id: String { + switch self { + case .membershipRequired: return "membershipRequired" + } + } + + var title: String { + switch self { + case .membershipRequired: return "Membership required" + } + } + + var symbolName: String { + switch self { + case .membershipRequired: return "creditcard.fill" + } + } + + static func notices(for station: FuelStation) -> [StationNotice] { + isCostco(station) ? [.membershipRequired] : [] + } + + static func isCostco(_ station: FuelStation) -> Bool { + containsCostcoToken(station.brand) || containsCostcoToken(station.name) + } + + private static func containsCostcoToken(_ value: String) -> Bool { + let tokens = value.uppercased().split { !$0.isLetter && !$0.isNumber } + return tokens.contains("COSTCO") + } +} diff --git a/FuelBoard/en.lproj/Localizable.strings b/FuelBoard/en.lproj/Localizable.strings index 73a9c89..9939a52 100644 --- a/FuelBoard/en.lproj/Localizable.strings +++ b/FuelBoard/en.lproj/Localizable.strings @@ -148,6 +148,7 @@ "Done" = "Done"; "Directions" = "Directions"; "Report issue" = "Report issue"; +"Membership required" = "Membership required"; "Report an error?" = "Report an error?"; "Cancel" = "Cancel"; "Report" = "Report";