// // HomeView.swift // SportsTime // import SwiftUI import SwiftData struct HomeView: View { @Environment(\.modelContext) private var modelContext @Query(sort: \SavedTrip.updatedAt, order: .reverse) private var savedTrips: [SavedTrip] @State private var showNewTrip = false @State private var selectedTab = 0 var body: some View { TabView(selection: $selectedTab) { // Home Tab NavigationStack { ScrollView { VStack(spacing: 24) { // Hero Card heroCard // Quick Actions quickActions // Saved Trips if !savedTrips.isEmpty { savedTripsSection } // Featured / Tips tipsSection } .padding() } .navigationTitle("Sport Travel Planner") .toolbar { ToolbarItem(placement: .primaryAction) { Button { showNewTrip = true } label: { Image(systemName: "plus") } } } } .tabItem { Label("Home", systemImage: "house.fill") } .tag(0) // Schedule Tab NavigationStack { ScheduleListView() } .tabItem { Label("Schedule", systemImage: "calendar") } .tag(1) // My Trips Tab NavigationStack { SavedTripsListView(trips: savedTrips) } .tabItem { Label("My Trips", systemImage: "suitcase.fill") } .tag(2) // Settings Tab NavigationStack { SettingsView() } .tabItem { Label("Settings", systemImage: "gear") } .tag(3) } .sheet(isPresented: $showNewTrip) { TripCreationView() } } // MARK: - Hero Card private var heroCard: some View { VStack(alignment: .leading, spacing: 12) { Text("Plan Your Ultimate Sports Road Trip") .font(.title2) .fontWeight(.bold) Text("Visit multiple stadiums, catch live games, and create unforgettable memories.") .font(.subheadline) .foregroundStyle(.secondary) Button { showNewTrip = true } label: { Text("Start Planning") .fontWeight(.semibold) .frame(maxWidth: .infinity) .padding() .background(Color.blue) .foregroundStyle(.white) .clipShape(RoundedRectangle(cornerRadius: 12)) } } .padding() .background( LinearGradient( colors: [.blue.opacity(0.1), .green.opacity(0.1)], startPoint: .topLeading, endPoint: .bottomTrailing ) ) .clipShape(RoundedRectangle(cornerRadius: 16)) } // MARK: - Quick Actions private var quickActions: some View { VStack(alignment: .leading, spacing: 12) { Text("Quick Start") .font(.headline) HStack(spacing: 12) { ForEach(Sport.supported) { sport in QuickSportButton(sport: sport) { // Start trip with this sport pre-selected showNewTrip = true } } } } } // MARK: - Saved Trips private var savedTripsSection: some View { VStack(alignment: .leading, spacing: 12) { HStack { Text("Recent Trips") .font(.headline) Spacer() Button("See All") { selectedTab = 2 } .font(.subheadline) } ForEach(savedTrips.prefix(3)) { savedTrip in if let trip = savedTrip.trip { SavedTripCard(trip: trip) } } } } // MARK: - Tips private var tipsSection: some View { VStack(alignment: .leading, spacing: 12) { Text("Planning Tips") .font(.headline) VStack(spacing: 8) { TipRow(icon: "calendar.badge.clock", title: "Check schedules early", subtitle: "Game times can change, sync often") TipRow(icon: "car.fill", title: "Plan rest days", subtitle: "Don't overdo the driving") TipRow(icon: "star.fill", title: "Mark must-sees", subtitle: "Ensure your favorite matchups are included") } .padding() .background(Color(.secondarySystemBackground)) .clipShape(RoundedRectangle(cornerRadius: 12)) } } } // MARK: - Supporting Views struct QuickSportButton: View { let sport: Sport let action: () -> Void var body: some View { Button(action: action) { VStack(spacing: 8) { Image(systemName: sport.iconName) .font(.title) Text(sport.rawValue) .font(.caption) .fontWeight(.medium) } .frame(maxWidth: .infinity) .padding(.vertical, 16) .background(Color(.secondarySystemBackground)) .clipShape(RoundedRectangle(cornerRadius: 12)) } .buttonStyle(.plain) } } struct SavedTripCard: View { let trip: Trip var body: some View { NavigationLink { TripDetailView(trip: trip, games: [:]) } label: { HStack { VStack(alignment: .leading, spacing: 4) { Text(trip.name) .font(.subheadline) .fontWeight(.semibold) Text(trip.formattedDateRange) .font(.caption) .foregroundStyle(.secondary) HStack(spacing: 8) { Label("\(trip.stops.count) cities", systemImage: "mappin") Label("\(trip.totalGames) games", systemImage: "sportscourt") } .font(.caption2) .foregroundStyle(.secondary) } Spacer() Image(systemName: "chevron.right") .foregroundStyle(.secondary) } .padding() .background(Color(.secondarySystemBackground)) .clipShape(RoundedRectangle(cornerRadius: 12)) } .buttonStyle(.plain) } } struct TipRow: View { let icon: String let title: String let subtitle: String var body: some View { HStack(spacing: 12) { Image(systemName: icon) .font(.title3) .foregroundStyle(.blue) .frame(width: 30) VStack(alignment: .leading, spacing: 2) { Text(title) .font(.subheadline) .fontWeight(.medium) Text(subtitle) .font(.caption) .foregroundStyle(.secondary) } Spacer() } } } // MARK: - Saved Trips List View struct SavedTripsListView: View { let trips: [SavedTrip] var body: some View { List { if trips.isEmpty { ContentUnavailableView( "No Saved Trips", systemImage: "suitcase", description: Text("Your planned trips will appear here") ) } else { ForEach(trips) { savedTrip in if let trip = savedTrip.trip { NavigationLink { TripDetailView(trip: trip, games: [:]) } label: { VStack(alignment: .leading) { Text(trip.name) .font(.headline) Text(trip.formattedDateRange) .font(.caption) .foregroundStyle(.secondary) } } } } } } .navigationTitle("My Trips") } } #Preview { HomeView() .modelContainer(for: SavedTrip.self, inMemory: true) }