// // TripWizardViewModel.swift // SportsTime // // ViewModel for progressive-reveal trip wizard. // import Foundation import SwiftUI @Observable final class TripWizardViewModel { // MARK: - Planning Mode var planningMode: PlanningMode? = nil { didSet { if oldValue != nil && oldValue != planningMode { resetDownstreamFromPlanningMode() } } } // MARK: - Sports Selection var selectedSports: Set = [] // MARK: - Dates var startDate: Date = Date() var endDate: Date = Date().addingTimeInterval(86400 * 7) var hasSetDates: Bool = false // MARK: - Regions var selectedRegions: Set = [] // MARK: - Route Preferences var routePreference: RoutePreference = .balanced var hasSetRoutePreference: Bool = false // MARK: - Repeat Cities var allowRepeatCities: Bool = false var hasSetRepeatCities: Bool = false // MARK: - Must Stops var mustStopLocations: [LocationInput] = [] // MARK: - Planning State var isPlanning: Bool = false // MARK: - Sport Availability var sportAvailability: [Sport: Bool] = [:] var isLoadingSportAvailability: Bool = false // MARK: - Reveal State (computed) var isPlanningModeStepVisible: Bool { true } var isDatesStepVisible: Bool { planningMode != nil } var isSportsStepVisible: Bool { isDatesStepVisible && hasSetDates } var isRegionsStepVisible: Bool { isSportsStepVisible && !selectedSports.isEmpty } var isRoutePreferenceStepVisible: Bool { isRegionsStepVisible && !selectedRegions.isEmpty } var isRepeatCitiesStepVisible: Bool { isRoutePreferenceStepVisible && hasSetRoutePreference } var isMustStopsStepVisible: Bool { isRepeatCitiesStepVisible && hasSetRepeatCities } var isReviewStepVisible: Bool { isMustStopsStepVisible } /// Combined state for animation tracking var revealState: Int { var state = 0 if isSportsStepVisible { state += 1 } if isDatesStepVisible { state += 2 } if isRegionsStepVisible { state += 4 } if isRoutePreferenceStepVisible { state += 8 } if isRepeatCitiesStepVisible { state += 16 } if isMustStopsStepVisible { state += 32 } if isReviewStepVisible { state += 64 } return state } // MARK: - Sport Availability func canSelectSport(_ sport: Sport) -> Bool { sportAvailability[sport] ?? true // Default to available if not checked } func fetchSportAvailability() async { guard hasSetDates else { return } isLoadingSportAvailability = true defer { isLoadingSportAvailability = false } var availability: [Sport: Bool] = [:] for sport in Sport.supported { do { let games = try await AppDataProvider.shared.filterGames( sports: [sport], startDate: startDate, endDate: endDate ) availability[sport] = !games.isEmpty } catch { availability[sport] = true // Default to available on error } } await MainActor.run { self.sportAvailability = availability } } // MARK: - Reset Logic private func resetDownstreamFromPlanningMode() { selectedSports = [] hasSetDates = false selectedRegions = [] hasSetRoutePreference = false hasSetRepeatCities = false mustStopLocations = [] } }