// // SuggestedTripCard.swift // SportsTime // // Card component for displaying a suggested trip in the carousel. // import SwiftUI struct SuggestedTripCard: View { let suggestedTrip: SuggestedTrip @Environment(\.colorScheme) private var colorScheme var body: some View { VStack(alignment: .leading, spacing: Theme.Spacing.sm) { // Header: Region badge + Sport icons HStack { // Region badge Text(suggestedTrip.region.shortName) .font(.system(size: Theme.FontSize.micro, weight: .semibold)) .foregroundStyle(.white) .padding(.horizontal, Theme.Spacing.xs) .padding(.vertical, 4) .background(regionColor) .clipShape(Capsule()) Spacer() // Sport icons HStack(spacing: 4) { ForEach(suggestedTrip.displaySports, id: \.self) { sport in Image(systemName: sport.iconName) .font(.system(size: 12)) .foregroundStyle(sport.themeColor) } } } // Route preview (vertical) routePreview Spacer() // Stats row - inline compact display HStack(spacing: 6) { Label { Text(suggestedTrip.trip.totalGames == 1 ? "1 game" : "\(suggestedTrip.trip.totalGames) games") } icon: { Image(systemName: "sportscourt") } Text("•") .foregroundStyle(Theme.textMuted(colorScheme).opacity(0.5)) Label { Text(suggestedTrip.trip.stops.count == 1 ? "1 city" : "\(suggestedTrip.trip.stops.count) cities") } icon: { Image(systemName: "mappin") } } .font(.system(size: 11)) .foregroundStyle(Theme.textSecondary(colorScheme)) // Date range Text(suggestedTrip.trip.formattedDateRange) .font(.system(size: Theme.FontSize.micro)) .foregroundStyle(Theme.textMuted(colorScheme)) } .padding(Theme.Spacing.md) .frame(width: 200, height: 160) .background(Theme.cardBackground(colorScheme)) .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.large)) .overlay { RoundedRectangle(cornerRadius: Theme.CornerRadius.large) .stroke(Theme.surfaceGlow(colorScheme), lineWidth: 1) } .shadow(color: Theme.cardShadow(colorScheme), radius: 8, y: 4) } private var routePreview: some View { let cities = suggestedTrip.trip.stops.map { $0.city } let displayCities: [String] if cities.count <= 3 { displayCities = cities } else { displayCities = [cities.first ?? "", "...", cities.last ?? ""] } 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) } Text(city) .font(.system(size: Theme.FontSize.caption, weight: index == 0 ? .semibold : .regular)) .foregroundStyle(index == 0 ? Theme.textPrimary(colorScheme) : Theme.textSecondary(colorScheme)) .lineLimit(1) } } } private var regionColor: Color { switch suggestedTrip.region { case .east: return .blue case .central: return .green case .west: return .orange case .crossCountry: return .purple } } } #Preview { let trip = Trip( name: "Test Trip", preferences: TripPreferences(), stops: [ TripStop(stopNumber: 1, city: "New York", state: "NY", coordinate: nil, arrivalDate: Date(), departureDate: Date(), games: [], isRestDay: false), TripStop(stopNumber: 2, city: "Boston", state: "MA", coordinate: nil, arrivalDate: Date(), departureDate: Date(), games: [], isRestDay: false), TripStop(stopNumber: 3, city: "Philadelphia", state: "PA", coordinate: nil, arrivalDate: Date(), departureDate: Date(), games: [], isRestDay: false) ], totalGames: 5 ) let suggestedTrip = SuggestedTrip( id: UUID(), region: .east, isSingleSport: false, trip: trip, richGames: [:], sports: [.mlb, .nba] ) SuggestedTripCard(suggestedTrip: suggestedTrip) .padding() }