fix: standardize trip name display with arrow separators app-wide

- Add `displayName` computed property to Trip model that always
  generates city list with " → " separator for consistent display
- Replace all `trip.name` usages with `trip.displayName` in UI files
- Update SuggestedTripsGenerator to use " → " separator
- Update PDFGenerator to use displayName for PDF titles

This ensures all trip names display consistently regardless of when
the trip was created or how the name was originally stored.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-01-14 11:36:13 -06:00
parent 2ad458bffd
commit 1e26cfebc8
30 changed files with 60 additions and 59 deletions

View File

@@ -70,6 +70,13 @@ struct Trip: Identifiable, Codable, Hashable {
return stop.city
}
}
/// Display name generated from cities - always uses " " separator for consistency
var displayName: String {
let cityList = cities
return cityList.isEmpty ? name : cityList.joined(separator: "")
}
var uniqueSports: Set<Sport> { preferences.sports }
var startDate: Date { stops.first?.arrivalDate ?? preferences.startDate }
var endDate: Date { stops.last?.departureDate ?? preferences.endDate }

View File

@@ -584,7 +584,7 @@ final class SuggestedTripsGenerator {
if cities.count <= 1 {
return cities.first ?? "Road Trip"
}
return cities.joined(separator: " - ")
return cities.joined(separator: " ")
}
// MARK: - Corridor Trip Building

View File

@@ -103,7 +103,7 @@ final class PDFGenerator {
.foregroundColor: UIColor.black
]
let titleRect = CGRect(x: margin, y: y, width: contentWidth, height: 50)
(trip.name as NSString).draw(in: titleRect, withAttributes: titleAttributes)
(trip.displayName as NSString).draw(in: titleRect, withAttributes: titleAttributes)
y += 55
// Date range

View File

@@ -329,7 +329,7 @@ struct SavedTripCard: View {
}
VStack(alignment: .leading, spacing: 4) {
Text(trip.name)
Text(trip.displayName)
.font(.body)
.foregroundStyle(Theme.textPrimary(colorScheme))
@@ -653,7 +653,7 @@ struct SavedTripListRow: View {
.frame(width: 20)
VStack(alignment: .leading, spacing: Theme.Spacing.xs) {
Text(trip.name)
Text(trip.displayName)
.font(.headline)
.foregroundStyle(Theme.textPrimary(colorScheme))

View File

@@ -215,7 +215,7 @@ struct HomeContent_Airbnb: View {
VStack(alignment: .leading, spacing: 4) {
HStack {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 14, weight: .medium))
.foregroundStyle(textPrimary)
.lineLimit(1)
@@ -302,7 +302,7 @@ struct HomeContent_Airbnb: View {
)
VStack(alignment: .leading, spacing: 6) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 15, weight: .medium))
.foregroundStyle(textPrimary)
.lineLimit(1)

View File

@@ -154,7 +154,7 @@ struct HomeContent_AppleMaps: View {
}
VStack(alignment: .leading, spacing: 3) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 16))
.foregroundStyle(textPrimary)
.lineLimit(1)
@@ -239,7 +239,7 @@ struct HomeContent_AppleMaps: View {
}
VStack(alignment: .leading, spacing: 4) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 14, weight: .medium))
.foregroundStyle(textPrimary)
.lineLimit(2)

View File

@@ -347,7 +347,7 @@ struct HomeContent_ArtDeco: View {
}
VStack(alignment: .leading, spacing: 6) {
Text(trip.name.uppercased())
Text(trip.displayName.uppercased())
.font(.system(size: 14, weight: .bold))
.tracking(1)
.foregroundStyle(textPrimary)
@@ -430,7 +430,7 @@ struct HomeContent_ArtDeco: View {
decoDiamond
.foregroundStyle(decoTeal)
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 14, weight: .medium))
.foregroundStyle(textPrimary)

View File

@@ -169,7 +169,7 @@ struct HomeContent_Brutalist: View {
VStack(alignment: .leading, spacing: 8) {
HStack(alignment: .top) {
VStack(alignment: .leading, spacing: 4) {
Text(trip.name.uppercased())
Text(trip.displayName.uppercased())
.font(.system(.headline, design: .monospaced).bold())
.foregroundStyle(textColor)
@@ -227,7 +227,7 @@ struct HomeContent_Brutalist: View {
TripDetailView(trip: trip)
} label: {
HStack {
Text(trip.name.uppercased())
Text(trip.displayName.uppercased())
.font(.system(.subheadline, design: .monospaced))
.foregroundStyle(textColor)

View File

@@ -240,7 +240,7 @@ struct HomeContent_CarrotWeather: View {
)
VStack(alignment: .leading, spacing: 3) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 15, weight: .medium))
.foregroundStyle(textPrimary)
.lineLimit(1)
@@ -323,7 +323,7 @@ struct HomeContent_CarrotWeather: View {
.padding(.vertical, 12)
VStack(alignment: .leading, spacing: 4) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 13, weight: .medium))
.foregroundStyle(textPrimary)
.lineLimit(2)

View File

@@ -231,7 +231,7 @@ struct HomeContent_Classic: View {
}
VStack(alignment: .leading, spacing: 4) {
Text(trip.name)
Text(trip.displayName)
.font(.body)
.foregroundStyle(Theme.textPrimary(colorScheme))

View File

@@ -306,7 +306,7 @@ struct HomeContent_DarkIndustrial: View {
.background(warningYellow)
VStack(alignment: .leading, spacing: 6) {
Text(trip.name.uppercased())
Text(trip.displayName.uppercased())
.font(.system(size: 13, weight: .bold, design: .monospaced))
.foregroundStyle(textPrimary)
.lineLimit(1)
@@ -383,7 +383,7 @@ struct HomeContent_DarkIndustrial: View {
.fill(steelGray.opacity(0.5))
.frame(width: 3, height: 32)
Text(trip.name.uppercased())
Text(trip.displayName.uppercased())
.font(.system(size: 12, weight: .medium, design: .monospaced))
.foregroundStyle(textPrimary)

View File

@@ -207,7 +207,7 @@ struct HomeContent_Fantastical: View {
.frame(width: 4, height: 44)
VStack(alignment: .leading, spacing: 3) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 15, weight: .medium))
.foregroundStyle(textPrimary)
.lineLimit(1)
@@ -297,7 +297,7 @@ struct HomeContent_Fantastical: View {
)
VStack(alignment: .leading, spacing: 4) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 15, weight: .medium))
.foregroundStyle(textPrimary)
.lineLimit(1)

View File

@@ -221,7 +221,7 @@ struct HomeContent_Flighty: View {
}
VStack(alignment: .leading, spacing: 8) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 16, weight: .semibold))
.foregroundStyle(textPrimary)
.lineLimit(1)
@@ -310,7 +310,7 @@ struct HomeContent_Flighty: View {
}
VStack(alignment: .leading, spacing: 3) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 15, weight: .medium))
.foregroundStyle(textPrimary)
.lineLimit(1)

View File

@@ -224,7 +224,7 @@ struct HomeContent_Glassmorphism: View {
}
}
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 16, weight: .semibold, design: .rounded))
.foregroundStyle(colorScheme == .dark ? .white : Color(white: 0.15))
.lineLimit(2)
@@ -306,7 +306,7 @@ struct HomeContent_Glassmorphism: View {
}
VStack(alignment: .leading, spacing: 4) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 15, weight: .medium, design: .rounded))
.foregroundStyle(colorScheme == .dark ? .white : Color(white: 0.15))

View File

@@ -227,7 +227,7 @@ struct HomeContent_LuxuryEditorial: View {
}
// Title
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 18, weight: .regular, design: .serif))
.foregroundStyle(textPrimary)
.lineLimit(2)
@@ -293,7 +293,7 @@ struct HomeContent_LuxuryEditorial: View {
.frame(width: 20)
VStack(alignment: .leading, spacing: 4) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 16, weight: .regular, design: .serif))
.foregroundStyle(textPrimary)

View File

@@ -324,7 +324,7 @@ struct HomeContent_MaximalistChaos: View {
}
VStack(alignment: .leading, spacing: 6) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 16, weight: .bold, design: .rounded))
.foregroundStyle(colorScheme == .dark ? .white : .black)
.lineLimit(1)
@@ -402,7 +402,7 @@ struct HomeContent_MaximalistChaos: View {
.fill(accentColor)
.frame(width: 6)
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 14, weight: .semibold, design: .rounded))
.foregroundStyle(colorScheme == .dark ? .white : .black)

View File

@@ -230,7 +230,7 @@ struct HomeContent_NeoBrutalist: View {
.frame(width: 8)
VStack(alignment: .leading, spacing: 6) {
Text(trip.name.uppercased())
Text(trip.displayName.uppercased())
.font(.system(size: 14, weight: .black))
.foregroundStyle(textColor)
.lineLimit(1)
@@ -297,7 +297,7 @@ struct HomeContent_NeoBrutalist: View {
.fill(electricBlue)
.frame(width: 4)
Text(trip.name.uppercased())
Text(trip.displayName.uppercased())
.font(.system(size: 13, weight: .bold))
.foregroundStyle(textColor)

View File

@@ -194,7 +194,7 @@ struct HomeContent_NikeRunClub: View {
}
VStack(alignment: .leading, spacing: 4) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 16, weight: .semibold))
.foregroundStyle(textPrimary)
.lineLimit(1)
@@ -278,7 +278,7 @@ struct HomeContent_NikeRunClub: View {
}
VStack(alignment: .leading, spacing: 4) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 14, weight: .semibold))
.foregroundStyle(textPrimary)
.lineLimit(1)

View File

@@ -195,7 +195,7 @@ struct HomeContent_Organic: View {
}
VStack(alignment: .leading, spacing: 6) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 16, weight: .semibold, design: .rounded))
.foregroundStyle(textPrimary)
.lineLimit(1)
@@ -269,7 +269,7 @@ struct HomeContent_Organic: View {
.frame(width: 24, height: 24)
VStack(alignment: .leading, spacing: 2) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 15, weight: .medium, design: .rounded))
.foregroundStyle(textPrimary)

View File

@@ -240,7 +240,7 @@ struct HomeContent_Playful: View {
}
VStack(alignment: .leading, spacing: 6) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 16, weight: .semibold, design: .rounded))
.foregroundStyle(colorScheme == .dark ? .white : Color(white: 0.15))
.lineLimit(1)
@@ -321,7 +321,7 @@ struct HomeContent_Playful: View {
)
VStack(alignment: .leading, spacing: 4) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 15, weight: .medium, design: .rounded))
.foregroundStyle(colorScheme == .dark ? .white : Color(white: 0.15))

View File

@@ -237,7 +237,7 @@ struct HomeContent_RetroFuturism: View {
.shadow(color: trip.uniqueSports.first?.themeColor.opacity(0.5) ?? neonCyan.opacity(0.5), radius: 10)
VStack(alignment: .leading, spacing: 4) {
Text(trip.name.uppercased())
Text(trip.displayName.uppercased())
.font(.system(size: 14, weight: .bold, design: .rounded))
.foregroundStyle(chrome)
@@ -306,7 +306,7 @@ struct HomeContent_RetroFuturism: View {
TripDetailView(trip: trip)
} label: {
HStack {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 13, weight: .medium, design: .rounded))
.foregroundStyle(chrome.opacity(0.8))

View File

@@ -197,7 +197,7 @@ struct HomeContent_SeatGeek: View {
Spacer()
}
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 15, weight: .semibold))
.foregroundStyle(textPrimary)
.lineLimit(2)
@@ -286,7 +286,7 @@ struct HomeContent_SeatGeek: View {
}
VStack(alignment: .leading, spacing: 4) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 15, weight: .semibold))
.foregroundStyle(textPrimary)
.lineLimit(1)

View File

@@ -260,7 +260,7 @@ struct HomeContent_SoftPastel: View {
)
VStack(alignment: .leading, spacing: 6) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 16, weight: .medium, design: .rounded))
.foregroundStyle(textPrimary)
.lineLimit(1)
@@ -333,7 +333,7 @@ struct HomeContent_SoftPastel: View {
.frame(width: 12, height: 12)
VStack(alignment: .leading, spacing: 4) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 15, weight: .medium, design: .rounded))
.foregroundStyle(textPrimary)

View File

@@ -144,7 +144,7 @@ struct HomeContent_Spotify: View {
.shadow(color: Color.black.opacity(0.4), radius: 8, y: 4)
VStack(alignment: .leading, spacing: 4) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 14, weight: .semibold))
.foregroundStyle(textPrimary)
.lineLimit(1)
@@ -213,7 +213,7 @@ struct HomeContent_Spotify: View {
.shadow(color: Color.black.opacity(0.4), radius: 8, y: 4)
VStack(alignment: .leading, spacing: 4) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 14, weight: .semibold))
.foregroundStyle(textPrimary)
.lineLimit(2)

View File

@@ -236,7 +236,7 @@ struct HomeContent_Strava: View {
)
VStack(alignment: .leading, spacing: 2) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 15, weight: .semibold))
.foregroundStyle(textPrimary)
.lineLimit(1)
@@ -351,7 +351,7 @@ struct HomeContent_Strava: View {
}
VStack(alignment: .leading, spacing: 4) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 13, weight: .semibold))
.foregroundStyle(textPrimary)
.lineLimit(1)

View File

@@ -228,7 +228,7 @@ struct HomeContent_SwissModernist: View {
.frame(width: 24)
// Trip name
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 15, weight: .medium))
.foregroundStyle(textPrimary)
.lineLimit(1)
@@ -314,7 +314,7 @@ struct HomeContent_SwissModernist: View {
.frame(width: 24)
VStack(alignment: .leading, spacing: 4) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 15, weight: .medium))
.foregroundStyle(textPrimary)

View File

@@ -188,7 +188,7 @@ struct HomeContent_Things3: View {
.frame(width: 22, height: 22)
VStack(alignment: .leading, spacing: 4) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 17))
.foregroundStyle(textPrimary)
.lineLimit(1)
@@ -279,7 +279,7 @@ struct HomeContent_Things3: View {
)
VStack(alignment: .leading, spacing: 3) {
Text(trip.name)
Text(trip.displayName)
.font(.system(size: 17))
.foregroundStyle(textPrimary)
.lineLimit(1)

View File

@@ -101,7 +101,7 @@ private struct TripSelectionRow: View {
Button(action: onTap) {
HStack {
VStack(alignment: .leading, spacing: 4) {
Text(trip.name)
Text(trip.displayName)
.font(.headline)
.foregroundStyle(.primary)

View File

@@ -274,7 +274,7 @@ struct PollDetailView: View {
let rank = results.tripScores.firstIndex { $0.tripIndex == item.tripIndex }! + 1
ResultRow(
rank: rank,
tripName: trip.name,
tripName: trip.displayName,
score: item.score,
percentage: results.scorePercentage(for: item.tripIndex),
isLeader: rank == 1 && item.score > 0
@@ -420,7 +420,7 @@ private struct TripPreviewCard: View {
.background(Theme.warmOrange)
.clipShape(Capsule())
Text(trip.name)
Text(trip.displayName)
.font(.headline)
.foregroundStyle(.primary)
}
@@ -441,12 +441,6 @@ private struct TripPreviewCard: View {
}
.font(.caption)
.foregroundStyle(.secondary)
// Show cities
Text(trip.stops.map { $0.city }.joined(separator: ""))
.font(.caption)
.foregroundStyle(.secondary)
.lineLimit(2)
}
Image(systemName: "chevron.right")

View File

@@ -138,7 +138,7 @@ private struct RankingRow: View {
.clipShape(Circle())
VStack(alignment: .leading, spacing: 2) {
Text(trip.name)
Text(trip.displayName)
.font(.headline)
Text(tripSummary)