// // SettingsViewModel.swift // SportsTime // import Foundation import SwiftUI @MainActor @Observable final class SettingsViewModel { // MARK: - User Preferences (persisted via UserDefaults) var selectedSports: Set { didSet { savePreferences() } } var maxDrivingHoursPerDay: Int { didSet { savePreferences() } } var preferredGameTime: PreferredGameTime { didSet { savePreferences() } } var includePlayoffGames: Bool { didSet { savePreferences() } } var notificationsEnabled: Bool { didSet { savePreferences() } } // MARK: - Sync State private(set) var isSyncing = false private(set) var lastSyncDate: Date? private(set) var syncError: String? // MARK: - App Info let appVersion: String let buildNumber: String // MARK: - Initialization init() { // Load from UserDefaults using local variables first let defaults = UserDefaults.standard // Selected sports if let sportStrings = defaults.stringArray(forKey: "selectedSports") { self.selectedSports = Set(sportStrings.compactMap { Sport(rawValue: $0) }) } else { self.selectedSports = Set(Sport.supported) } // Travel preferences - use local variable to avoid self access before init complete let savedDrivingHours = defaults.integer(forKey: "maxDrivingHoursPerDay") self.maxDrivingHoursPerDay = savedDrivingHours == 0 ? 8 : savedDrivingHours if let timeRaw = defaults.string(forKey: "preferredGameTime"), let time = PreferredGameTime(rawValue: timeRaw) { self.preferredGameTime = time } else { self.preferredGameTime = .evening } self.includePlayoffGames = defaults.object(forKey: "includePlayoffGames") as? Bool ?? true self.notificationsEnabled = defaults.object(forKey: "notificationsEnabled") as? Bool ?? true // Last sync self.lastSyncDate = defaults.object(forKey: "lastSyncDate") as? Date // App info self.appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "1.0.0" self.buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "1" } // MARK: - Actions func syncSchedules() async { isSyncing = true syncError = nil do { // Trigger data reload from provider await AppDataProvider.shared.loadInitialData() lastSyncDate = Date() UserDefaults.standard.set(lastSyncDate, forKey: "lastSyncDate") } catch { syncError = error.localizedDescription } isSyncing = false } func toggleSport(_ sport: Sport) { if selectedSports.contains(sport) { // Don't allow removing all sports guard selectedSports.count > 1 else { return } selectedSports.remove(sport) } else { selectedSports.insert(sport) } } func resetToDefaults() { selectedSports = Set(Sport.supported) maxDrivingHoursPerDay = 8 preferredGameTime = .evening includePlayoffGames = true notificationsEnabled = true } // MARK: - Persistence private func savePreferences() { let defaults = UserDefaults.standard defaults.set(selectedSports.map(\.rawValue), forKey: "selectedSports") defaults.set(maxDrivingHoursPerDay, forKey: "maxDrivingHoursPerDay") defaults.set(preferredGameTime.rawValue, forKey: "preferredGameTime") defaults.set(includePlayoffGames, forKey: "includePlayoffGames") defaults.set(notificationsEnabled, forKey: "notificationsEnabled") } } // MARK: - Supporting Types enum PreferredGameTime: String, CaseIterable, Identifiable { case any = "any" case afternoon = "afternoon" case evening = "evening" var id: String { rawValue } var displayName: String { switch self { case .any: return "Any Time" case .afternoon: return "Afternoon" case .evening: return "Evening" } } var description: String { switch self { case .any: return "No preference" case .afternoon: return "1 PM - 5 PM" case .evening: return "6 PM - 10 PM" } } }