feat: rewrite bootstrap, fix CloudKit sync, update canonical data, and UI fixes
- Rewrite BootstrapService: remove all legacy code paths (JSONStadium, JSONGame, bootstrapStadiumsLegacy, bootstrapGamesLegacy, venue aliases, createDefaultLeagueStructure), require canonical JSON files only - Add clearCanonicalData() to handle partial bootstrap recovery (prevents duplicate key crashes from interrupted first-launch) - Fix nullable stadium_canonical_id in games (4 MLS games have null) - Fix CKModels: logoUrl case, conference/division field keys - Fix CanonicalSyncService: sync conferenceCanonicalId/divisionCanonicalId - Add sports_canonical.json and DemoMode.swift - Delete legacy stadiums.json and games.json - Update all canonical resource JSON files with latest data - Fix TripWizardView horizontal scrolling with GeometryReader constraint - Update RegionMapSelector, TripDetailView, TripOptionsView UI improvements - Add DateRangePicker, PlanningModeStep, SportsStep enhancements - Update UI tests and marketing-videos config Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@ import UniformTypeIdentifiers
|
||||
struct TripDetailView: View {
|
||||
@Environment(\.modelContext) private var modelContext
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
@Environment(\.isDemoMode) private var isDemoMode
|
||||
|
||||
let trip: Trip
|
||||
private let providedGames: [String: RichGame]?
|
||||
@@ -33,6 +34,7 @@ struct TripDetailView: View {
|
||||
@State private var isLoadingRoutes = false
|
||||
@State private var loadedGames: [String: RichGame] = [:]
|
||||
@State private var isLoadingGames = false
|
||||
@State private var hasAppliedDemoSelection = false
|
||||
|
||||
// Itinerary items state
|
||||
@State private var itineraryItems: [ItineraryItem] = []
|
||||
@@ -113,7 +115,18 @@ struct TripDetailView: View {
|
||||
} message: {
|
||||
Text("This trip has \(multiRouteChunks.flatMap { $0 }.count) stops, which exceeds Apple Maps' limit of 16. Open the route in parts?")
|
||||
}
|
||||
.onAppear { checkIfSaved() }
|
||||
.onAppear {
|
||||
checkIfSaved()
|
||||
// Demo mode: auto-favorite the trip
|
||||
if isDemoMode && !hasAppliedDemoSelection && !isSaved {
|
||||
hasAppliedDemoSelection = true
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + DemoConfig.selectionDelay + 0.5) {
|
||||
if !isSaved {
|
||||
saveTrip()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.task {
|
||||
await loadGamesIfNeeded()
|
||||
if allowCustomItems {
|
||||
@@ -348,6 +361,7 @@ struct TripDetailView: View {
|
||||
.clipShape(Circle())
|
||||
.shadow(color: .black.opacity(0.2), radius: 4, y: 2)
|
||||
}
|
||||
.accessibilityIdentifier("tripDetail.favoriteButton")
|
||||
.padding(.top, 12)
|
||||
.padding(.trailing, 12)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user