Fix coast-to-coast trips and improve itinerary display
- Fix same-day different-city validation in C2C routes (no more impossible games like Detroit 7:30pm AND Milwaukee 8pm on the same day) - Cap C2C trips at 14 days max with 3 middle stops, prefer shortest routes - Add sport icon and name to game rows in trip itinerary - Add horizontal scroll to route dots in suggested trip cards - Allow swipe-to-dismiss on home sheet (trip planner still blocks) - Generate travel segments for suggested trips - Increase DAG route lookahead to 5 days for multi-day drives 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -120,7 +120,6 @@ struct HomeView: View {
|
||||
NavigationStack {
|
||||
TripDetailView(trip: suggestedTrip.trip, games: suggestedTrip.richGames)
|
||||
}
|
||||
.interactiveDismissDisabled()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,33 +79,45 @@ struct SuggestedTripCard: View {
|
||||
|
||||
private var routePreview: some View {
|
||||
let cities = suggestedTrip.trip.stops.map { $0.city }
|
||||
let displayCities: [String]
|
||||
let startCity = cities.first ?? ""
|
||||
let endCity = cities.last ?? ""
|
||||
|
||||
if cities.count <= 3 {
|
||||
displayCities = cities
|
||||
} else {
|
||||
displayCities = [cities.first ?? "", "...", cities.last ?? ""]
|
||||
}
|
||||
return VStack(alignment: .leading, spacing: Theme.Spacing.xs) {
|
||||
// Start → End display
|
||||
HStack(spacing: 6) {
|
||||
Text(startCity)
|
||||
.font(.system(size: Theme.FontSize.caption, weight: .semibold))
|
||||
.foregroundStyle(Theme.textPrimary(colorScheme))
|
||||
.lineLimit(1)
|
||||
|
||||
return VStack(alignment: .leading, spacing: 0) {
|
||||
ForEach(Array(displayCities.enumerated()), id: \.offset) { index, city in
|
||||
if index > 0 {
|
||||
// Connector
|
||||
HStack(spacing: 4) {
|
||||
Text("|")
|
||||
.font(.system(size: 10))
|
||||
Image(systemName: "chevron.down")
|
||||
.font(.system(size: 8))
|
||||
}
|
||||
.foregroundStyle(Theme.warmOrange.opacity(0.6))
|
||||
.padding(.leading, 4)
|
||||
}
|
||||
Image(systemName: "arrow.right")
|
||||
.font(.system(size: 10, weight: .semibold))
|
||||
.foregroundStyle(Theme.warmOrange)
|
||||
|
||||
Text(city)
|
||||
.font(.system(size: Theme.FontSize.caption, weight: index == 0 ? .semibold : .regular))
|
||||
.foregroundStyle(index == 0 ? Theme.textPrimary(colorScheme) : Theme.textSecondary(colorScheme))
|
||||
Text(endCity)
|
||||
.font(.system(size: Theme.FontSize.caption, weight: .semibold))
|
||||
.foregroundStyle(Theme.textPrimary(colorScheme))
|
||||
.lineLimit(1)
|
||||
}
|
||||
|
||||
// Scrollable stop dots
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack(spacing: 4) {
|
||||
ForEach(0..<cities.count, id: \.self) { index in
|
||||
Circle()
|
||||
.fill(index == 0 || index == cities.count - 1 ? Theme.warmOrange : Theme.routeGold.opacity(0.6))
|
||||
.frame(width: 6, height: 6)
|
||||
|
||||
if index < cities.count - 1 {
|
||||
Rectangle()
|
||||
.fill(Theme.routeGold.opacity(0.4))
|
||||
.frame(width: 8, height: 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, Theme.Spacing.xs)
|
||||
}
|
||||
.frame(height: 12)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user