import Foundation import Observation enum AppLanguage: String, CaseIterable, Identifiable { case system case english case korean var id: String { rawValue } var displayName: String { switch self { case .system: return String(localized: "settings.language.system") case .english: return "English" case .korean: return "한국어" } } } enum FirstWeekday: Int, CaseIterable, Identifiable { case sunday = 1 case monday = 2 var id: Int { rawValue } var displayName: String { switch self { case .sunday: return String(localized: "settings.firstWeekday.sunday") case .monday: return String(localized: "settings.firstWeekday.monday") } } } @MainActor @Observable final class SettingsViewModel { private static let languageKey = "settings.language" private static let firstWeekdayKey = "settings.firstWeekday" private static let dayStartMinutesKey = "settings.dayStartMinutes" static let defaultDayStartMinutes = 4 * 60 // 04:00 AM var language: AppLanguage { didSet { UserDefaults.standard.set(language.rawValue, forKey: Self.languageKey) } } var firstWeekday: FirstWeekday { didSet { UserDefaults.standard.set(firstWeekday.rawValue, forKey: Self.firstWeekdayKey) } } /// Minutes since midnight marking when a "day" starts for goal/log purposes. var dayStartMinutes: Int { didSet { UserDefaults.standard.set(dayStartMinutes, forKey: Self.dayStartMinutesKey) } } var dayStartDate: Date { get { Calendar.current.date(bySettingHour: dayStartMinutes / 60, minute: dayStartMinutes % 60, second: 0, of: .now) ?? .now } set { let comps = Calendar.current.dateComponents([.hour, .minute], from: newValue) dayStartMinutes = (comps.hour ?? 0) * 60 + (comps.minute ?? 0) } } init() { let defaults = UserDefaults.standard language = AppLanguage(rawValue: defaults.string(forKey: Self.languageKey) ?? "") ?? .system firstWeekday = FirstWeekday(rawValue: defaults.integer(forKey: Self.firstWeekdayKey)) ?? .sunday if let storedMinutes = defaults.object(forKey: Self.dayStartMinutesKey) as? Int { dayStartMinutes = storedMinutes } else { dayStartMinutes = Self.defaultDayStartMinutes } } }