Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a1ef0bd59 | ||
|
|
551a40ddf0 | ||
|
|
3c83c9b518 |
+23
-10
@@ -981,6 +981,21 @@ struct StationRow: View {
|
|||||||
return String(format: "%+.1fp", delta)
|
return String(format: "%+.1fp", delta)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func handleTap() {
|
||||||
|
switch tapAction {
|
||||||
|
case .openMap:
|
||||||
|
if let url = station.mapsDirectionsURL {
|
||||||
|
UIApplication.shared.open(url)
|
||||||
|
}
|
||||||
|
case .showDetails:
|
||||||
|
showDetails()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func showDetails() {
|
||||||
|
onShowDetails(station)
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack(spacing: 12) {
|
HStack(spacing: 12) {
|
||||||
// LEFT — round brand logo (or generic fuel pump fallback)
|
// LEFT — round brand logo (or generic fuel pump fallback)
|
||||||
@@ -1017,6 +1032,12 @@ struct StationRow: View {
|
|||||||
.background(Capsule().fill(.blue.opacity(0.15)))
|
.background(Capsule().fill(.blue.opacity(0.15)))
|
||||||
.foregroundStyle(.blue)
|
.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)")
|
Text("\(station.address), \(station.postcode)")
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
@@ -1059,16 +1080,8 @@ struct StationRow: View {
|
|||||||
.buttonStyle(.borderless)
|
.buttonStyle(.borderless)
|
||||||
}
|
}
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
.onTapGesture {
|
.onTapGesture(perform: handleTap)
|
||||||
switch tapAction {
|
.onLongPressGesture(perform: showDetails)
|
||||||
case .openMap:
|
|
||||||
if let url = station.mapsDirectionsURL {
|
|
||||||
UIApplication.shared.open(url)
|
|
||||||
}
|
|
||||||
case .showDetails:
|
|
||||||
onShowDetails(station)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,14 @@ struct StationDetailView: View {
|
|||||||
LabeledContent("Distance", value: distanceUnit.format(km))
|
LabeledContent("Distance", value: distanceUnit.format(km))
|
||||||
.monospacedDigit()
|
.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 {
|
Section {
|
||||||
Button {
|
Button {
|
||||||
@@ -65,7 +73,7 @@ struct StationDetailView: View {
|
|||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
.alert("Report an error?", isPresented: $showingReportIssueConfirmation) {
|
.alert("Report an error?", isPresented: $showingReportIssueConfirmation) {
|
||||||
Button("Cancel", role: .cancel) { }
|
Button("Cancel", role: .cancel) { }
|
||||||
Button("Open GOV.UK") {
|
Button("Report") {
|
||||||
UIApplication.shared.open(reportIssueURL)
|
UIApplication.shared.open(reportIssueURL)
|
||||||
}
|
}
|
||||||
} message: {
|
} message: {
|
||||||
|
|||||||
@@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -148,9 +148,10 @@
|
|||||||
"Done" = "Done";
|
"Done" = "Done";
|
||||||
"Directions" = "Directions";
|
"Directions" = "Directions";
|
||||||
"Report issue" = "Report issue";
|
"Report issue" = "Report issue";
|
||||||
|
"Membership required" = "Membership required";
|
||||||
"Report an error?" = "Report an error?";
|
"Report an error?" = "Report an error?";
|
||||||
"Cancel" = "Cancel";
|
"Cancel" = "Cancel";
|
||||||
"Open GOV.UK" = "Open GOV.UK";
|
"Report" = "Report";
|
||||||
"Are you sure you want to report an error in fuel prices or forecourt details? This will open in your chosen browser." = "Are you sure you want to report an error in fuel prices or forecourt details? This will open in your chosen browser.";
|
"Are you sure you want to report an error in fuel prices or forecourt details? This will open in your chosen browser." = "Are you sure you want to report an error in fuel prices or forecourt details? This will open in your chosen browser.";
|
||||||
|
|
||||||
/* Station row */
|
/* Station row */
|
||||||
|
|||||||
Reference in New Issue
Block a user