Files
Sportstime/SportsTime/Features/Settings/ViewModels/SettingsViewModel.swift
Trey t f5e509a9ae Add region-based filtering and route length diversity
- Add RegionMapSelector UI for geographic trip filtering (East/Central/West)
- Add RouteFilters module for allowRepeatCities preference
- Improve GameDAGRouter to preserve route length diversity
  - Routes now grouped by city count before scoring
  - Ensures 2-city trips appear alongside longer trips
  - Increased beam width and max options for better coverage
- Add TripOptionsView filters (max cities slider, pace filter)
- Remove TravelStyle section from trip creation (replaced by region selector)
- Clean up debug logging from DataProvider and ScenarioAPlanner

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 15:18:37 -06:00

107 lines
2.8 KiB
Swift

//
// SettingsViewModel.swift
// SportsTime
//
import Foundation
import SwiftUI
@MainActor
@Observable
final class SettingsViewModel {
// MARK: - User Preferences (persisted via UserDefaults)
var selectedTheme: AppTheme {
didSet {
ThemeManager.shared.currentTheme = selectedTheme
}
}
var selectedSports: Set<Sport> {
didSet { savePreferences() }
}
var maxDrivingHoursPerDay: Int {
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
// Theme
self.selectedTheme = ThemeManager.shared.currentTheme
// 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
let savedDrivingHours = defaults.integer(forKey: "maxDrivingHoursPerDay")
self.maxDrivingHoursPerDay = savedDrivingHours == 0 ? 8 : savedDrivingHours
// 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
// Trigger data reload from provider
await AppDataProvider.shared.loadInitialData()
lastSyncDate = Date()
UserDefaults.standard.set(lastSyncDate, forKey: "lastSyncDate")
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() {
selectedTheme = .teal
selectedSports = Set(Sport.supported)
maxDrivingHoursPerDay = 8
}
// MARK: - Persistence
private func savePreferences() {
let defaults = UserDefaults.standard
defaults.set(selectedSports.map(\.rawValue), forKey: "selectedSports")
defaults.set(maxDrivingHoursPerDay, forKey: "maxDrivingHoursPerDay")
}
}