Update FuelBoard onboarding copy, title formatting, key sheet card wrapping, and best-value button placement
This commit is contained in:
@@ -78,6 +78,7 @@ struct FuelSavingsSummaryView: View {
|
||||
/// Sizes the "extra return travel" caption in the user's own unit (the
|
||||
/// stored figure is miles) — used by both the row banner and the detail sheet.
|
||||
var distanceUnit: DistanceUnit = .miles
|
||||
var showInfoAction: (() -> Void)? = nil
|
||||
|
||||
var body: some View {
|
||||
switch availability {
|
||||
@@ -166,6 +167,22 @@ struct FuelSavingsSummaryView: View {
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
if let showInfoAction {
|
||||
Rectangle()
|
||||
.fill(Color(.separator))
|
||||
.frame(height: 0.5)
|
||||
.padding(.vertical, 4)
|
||||
Button(action: showInfoAction) {
|
||||
HStack(spacing: 8) {
|
||||
Text("How Best Value works")
|
||||
Spacer(minLength: 8)
|
||||
Image(systemName: "chevron.forward")
|
||||
.font(.footnote.weight(.semibold))
|
||||
.foregroundStyle(.tertiary)
|
||||
}
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
}
|
||||
}
|
||||
case .unavailable(let reason):
|
||||
|
||||
@@ -108,10 +108,10 @@ struct OnboardingView: View {
|
||||
.frame(width: 96, height: 96)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 21, style: .continuous))
|
||||
}
|
||||
.padding(.bottom, 28)
|
||||
.padding(.bottom, 16)
|
||||
|
||||
Text(String(localized: "Welcome to FuelBoard", comment: "Onboarding welcome title"))
|
||||
.font(.largeTitle.bold())
|
||||
Text(String(localized: "Welcome to\nFuelBoard", comment: "Onboarding welcome title"))
|
||||
.font(.title.bold())
|
||||
.multilineTextAlignment(.center)
|
||||
|
||||
Text(String(localized: "The cheapest petrol, diesel and premium fuel near you — from the official UK Fuel Finder data.", comment: "Onboarding welcome subtitle"))
|
||||
@@ -121,12 +121,13 @@ struct OnboardingView: View {
|
||||
.padding(.horizontal, 32)
|
||||
.padding(.top, 12)
|
||||
|
||||
featureRow(icon: "globe.europe.africa.fill", text: String(localized: "UK-wide prices — 8,000+ stations, updated twice a day", comment: "Onboarding feature row"))
|
||||
featureRow(icon: "scope", text: String(localized: "Cheapest within your chosen radius, or closest station first", comment: "Onboarding feature row"))
|
||||
featureRow(icon: "star.fill", text: String(localized: "Favourites with instant price comparison", comment: "Onboarding feature row"))
|
||||
featureRow(icon: "chart.bar.fill", text: String(localized: "Green/amber/red rating vs the best nearby price", comment: "Onboarding feature row"))
|
||||
featureRow(icon: "square.grid.2x2.fill", text: String(localized: "Home-screen widget showing the cheapest nearby", comment: "Onboarding feature row"))
|
||||
featureRow(icon: "bell.fill", text: String(localized: "Alerts when you approach the cheapest station", comment: "Onboarding feature row"))
|
||||
featureRow(icon: "map.fill", title: String(localized: "Compare fuel prices near you", comment: "Onboarding feature row title"), subtitle: String(localized: "Over 8,000 stations across Great Britain, with prices updated daily.", comment: "Onboarding feature row subtitle"))
|
||||
|
||||
featureRow(icon: "chart.line.uptrend.xyaxis", title: String(localized: "See how much you could save", comment: "Onboarding feature row title"), subtitle: String(localized: "Compare fill-up costs and potential savings at different stations.", comment: "Onboarding feature row subtitle"))
|
||||
|
||||
featureRow(icon: "car.fill", title: String(localized: "Know if it's worth the drive", comment: "Onboarding feature row title"), subtitle: String(localized: "Factor in your journey and fuel costs to find the best value.", comment: "Onboarding feature row subtitle"))
|
||||
|
||||
featureRow(icon: "star.fill", title: String(localized: "Keep your favourites close", comment: "Onboarding feature row title"), subtitle: String(localized: "Save stations and quickly compare their latest prices.", comment: "Onboarding feature row subtitle"))
|
||||
|
||||
Spacer()
|
||||
}
|
||||
@@ -298,18 +299,23 @@ struct OnboardingView: View {
|
||||
OnboardingPrimaryButton(title: title, action: action)
|
||||
}
|
||||
|
||||
private func featureRow(icon: String, text: String) -> some View {
|
||||
HStack(spacing: 12) {
|
||||
private func featureRow(icon: String, title: String, subtitle: String) -> some View {
|
||||
HStack(alignment: .top, spacing: 12) {
|
||||
Image(systemName: icon)
|
||||
.font(.system(size: 20, weight: .semibold))
|
||||
.foregroundStyle(Color.accentColor)
|
||||
.frame(width: 32)
|
||||
Text(text)
|
||||
.font(.subheadline)
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(title)
|
||||
.font(.subheadline.bold())
|
||||
Text(subtitle)
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
.padding(.horizontal, 36)
|
||||
.padding(.vertical, 10)
|
||||
.padding(.vertical, 8)
|
||||
}
|
||||
|
||||
private func permissionStatusLabel(granted: Bool, denied: Bool, deniedText: String) -> some View {
|
||||
|
||||
@@ -238,18 +238,12 @@ struct StationDetailView: View {
|
||||
availability: fuelSavings,
|
||||
amount: fuelSavingsAmount,
|
||||
baselineStationName: savingsBaselineStationName,
|
||||
distanceUnit: distanceUnit
|
||||
distanceUnit: distanceUnit,
|
||||
showInfoAction: { showBestValueInfo = true }
|
||||
)
|
||||
} header: {
|
||||
Text("Best Value")
|
||||
}
|
||||
|
||||
// The explanation lives in its own sheet now, opened from this
|
||||
// row. The row sits INSIDE the `if let` so it carries the same
|
||||
// gate as the card above: no card, no row.
|
||||
Section {
|
||||
HowBestValueRow { showBestValueInfo = true }
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
@@ -267,14 +267,14 @@ struct StationsView: View {
|
||||
keyCard(
|
||||
icon: "checkmark.circle.fill", color: .green,
|
||||
title: "Good price", blurb: "Within 1.5p of the cheapest",
|
||||
threshold: "≤1.5p")
|
||||
threshold: "0–1.5p")
|
||||
keyCard(
|
||||
icon: "equal.circle.fill", color: .orange,
|
||||
title: "Okay", blurb: "Within 4p of the cheapest",
|
||||
threshold: "≤4p")
|
||||
title: "Okay", blurb: "More than 1.5p, up to 4p above the cheapest",
|
||||
threshold: ">1.5–4p")
|
||||
keyCard(
|
||||
icon: "exclamationmark.circle.fill", color: .red,
|
||||
title: "Pricey", blurb: "More than 4p over the cheapest",
|
||||
title: "Pricey", blurb: "More than 4p above the cheapest",
|
||||
threshold: ">4p")
|
||||
Rectangle()
|
||||
.fill(Color(.separator))
|
||||
@@ -306,10 +306,11 @@ struct StationsView: View {
|
||||
.padding(.horizontal, 14)
|
||||
.padding(.vertical, 12)
|
||||
.keyCardFill(color: .yellow)
|
||||
Text("Colours match each station's rating on the list")
|
||||
Text("Price differences are shown in pence per litre (p/litre). Colours match each station's rating on the list.")
|
||||
.font(.footnote)
|
||||
.foregroundStyle(.secondary)
|
||||
.frame(maxWidth: .infinity)
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
.multilineTextAlignment(.center)
|
||||
.padding(.top, 4)
|
||||
}
|
||||
.listRowBackground(Color.clear)
|
||||
@@ -377,6 +378,7 @@ struct StationsView: View {
|
||||
Text(LocalizedStringKey(blurb))
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
Spacer(minLength: 8)
|
||||
HStack(spacing: 6) {
|
||||
|
||||
@@ -26,15 +26,15 @@
|
||||
"Good price" = "Good price";
|
||||
"Within 1.5p of the cheapest" = "Within 1.5p of the cheapest";
|
||||
"Okay" = "Okay";
|
||||
"Within 4p of the cheapest" = "Within 4p of the cheapest";
|
||||
"More than 1.5p, up to 4p above the cheapest" = "More than 1.5p, up to 4p above the cheapest";
|
||||
"Pricey" = "Pricey";
|
||||
"More than 4p over the cheapest" = "More than 4p over the cheapest";
|
||||
"More than 4p above the cheapest" = "More than 4p above the cheapest";
|
||||
"Top result for the current sort" = "Top result for the current sort";
|
||||
"Star a station to add it to Favourites" = "Star a station to add it to Favourites";
|
||||
/* Star button in the More info sheet heading (accessibility labels) */
|
||||
"Add to favourites" = "Add to favourites";
|
||||
"Remove from favourites" = "Remove from favourites";
|
||||
"Colours match each station's rating on the list" = "Colours match each station's rating on the list";
|
||||
"Price differences are shown in pence per litre (p/litre). Colours match each station's rating on the list." = "Price differences are shown in pence per litre (p/litre). Colours match each station's rating on the list.";
|
||||
"How Best Value works" = "How Best Value works";
|
||||
"Best Value compares each station with the closest one. It works out what you could save at the pump, then takes off the fuel used for the extra return journey." = "Best Value compares each station with the closest one. It works out what you could save at the pump, then takes off the fuel used for the extra return journey.";
|
||||
"Your fill-up amount and MPG are used to show whether you could save overall." = "Your fill-up amount and MPG are used to show whether you could save overall.";
|
||||
|
||||
Reference in New Issue
Block a user