import SwiftUI import SwiftData import EventKit struct SettingsView: View { @Environment(\.modelContext) private var context @Query private var allSettings: [AppSettings] @StateObject private var viewModel = SettingsViewModel() @State private var showResetAllDataAlert = false private var settings: AppSettings? { allSettings.first } var body: some View { ZStack { Color.mealMoodBackground.ignoresSafeArea() if let settings = settings { settingsContent(settings: settings) } } .navigationTitle("settings_title") .navigationBarTitleDisplayMode(.inline) .toolbarBackground(Color.mealMoodBackground, for: .navigationBar) .toolbarBackground(.visible, for: .navigationBar) .environment(\.isEnabled, true) .toast(isShowing: $viewModel.showToast, message: viewModel.toastMessage) } @ViewBuilder private func settingsContent(settings: AppSettings) -> some View { List { // Planning section Section { Picker("settings_meal_windows", selection: Binding( get: { settings.mealWindowsEnum }, set: { settings.mealWindowsEnum = $0 } )) { Text("meal_windows_dinner_only").tag(MealWindows.dinnerOnly) Text("meal_windows_lunch_only").tag(MealWindows.lunchOnly) Text("meal_windows_both").tag(MealWindows.both) } Toggle("settings_include_weekends", isOn: Binding( get: { settings.includeWeekends }, set: { settings.includeWeekends = $0 } )) .tint(.mealMoodCoral) } header: { Label("settings_planning", systemImage: "fork.knife") } .listRowBackground(Color.mealMoodSurface) // Calendar section Section { Toggle("settings_icloud_sync", isOn: Binding( get: { settings.iCloudSyncEnabledResolved }, set: { settings.iCloudSyncEnabledResolved = $0 } )) .tint(.mealMoodCoral) Toggle("settings_sync", isOn: Binding( get: { settings.syncEnabled }, set: { newValue in if newValue { Task { let granted = await viewModel.requestCalendarAccess() if granted { let hasCalendar = viewModel.ensureValidCalendarSelection(settings: settings) settings.syncEnabled = hasCalendar } } } else { settings.syncEnabled = false } } )) .tint(.mealMoodCoral) if settings.syncEnabled { Picker("settings_sync_mode", selection: Binding( get: { settings.syncModeEnum }, set: { settings.syncModeEnum = $0 } )) { ForEach(CalendarSyncMode.allCases, id: \.self) { mode in Text(LocalizedStringKey(mode.localizedKey)).tag(mode) } } if !viewModel.availableCalendars.isEmpty { Picker("calendar_select", selection: Binding( get: { settings.calendarId }, set: { settings.calendarId = $0 } )) { Text("calendar_select").tag(nil as String?) ForEach(viewModel.availableCalendars, id: \.calendarIdentifier) { cal in Text(cal.title).tag(cal.calendarIdentifier as String?) } } } DatePicker("settings_lunch_time", selection: Binding( get: { settings.lunchTime }, set: { settings.lunchTime = $0 } ), displayedComponents: .hourAndMinute) DatePicker("settings_dinner_time", selection: Binding( get: { settings.dinnerTime }, set: { settings.dinnerTime = $0 } ), displayedComponents: .hourAndMinute) Picker("settings_event_duration", selection: Binding( get: { settings.eventDuration }, set: { settings.eventDuration = $0 } )) { Text("duration_30").tag(30) Text("duration_60").tag(60) Text("duration_90").tag(90) Text("duration_120").tag(120) } TextField("settings_event_prefix", text: Binding( get: { settings.eventPrefix }, set: { settings.eventPrefix = $0 } )) Picker("settings_reminder", selection: Binding( get: { settings.reminderMinutesBefore }, set: { settings.reminderMinutesBefore = $0 } )) { Text("settings_reminder_none").tag(nil as Int?) Text("reminder_30").tag(30 as Int?) Text("reminder_60").tag(60 as Int?) Text("reminder_120").tag(120 as Int?) } } } header: { Label("settings_calendar", systemImage: "calendar") } .listRowBackground(Color.mealMoodSurface) // Tags section Section { NavigationLink(destination: TagListView()) { Text("settings_manage_tags") } } header: { Label("settings_tags", systemImage: "tag") } .listRowBackground(Color.mealMoodSurface) // Language section Section { Picker("settings_language", selection: Binding( get: { settings.languageEnum }, set: { settings.languageEnum = $0 } )) { ForEach(AppLanguage.allCases, id: \.self) { lang in Text(lang.displayName).tag(lang) } } } header: { Label("settings_language", systemImage: "globe") } .listRowBackground(Color.mealMoodSurface) // Premium section Section { HStack { Text("settings_premium_status") Spacer() Text(settings.isPremium ? "Premium" : "Free") .foregroundColor(.mealMoodTextSecondary) } NavigationLink(destination: PremiumView(settings: settings)) { Text("settings_remove_ads") } } header: { Label("settings_premium", systemImage: "star") } .listRowBackground(Color.mealMoodSurface) Section { Button { ReviewPromptService.shared.requestFromSettings() } label: { Label("settings_rate_app", systemImage: "star.bubble") } Link(destination: URL(string: "https://mealmood.app")!) { Label("settings_website", systemImage: "safari") } Link(destination: URL(string: "mailto:support@mealmood.app")!) { Label("settings_support", systemImage: "envelope") } HStack { Text("settings_app_version") Spacer() Text(viewModel.appVersion) .foregroundColor(.mealMoodTextSecondary) } HStack { Text("settings_app_build") Spacer() Text(viewModel.appBuild) .foregroundColor(.mealMoodTextSecondary) } } header: { Label("settings_about", systemImage: "info.circle") } .listRowBackground(Color.mealMoodSurface) Section { Button(role: .destructive) { showResetAllDataAlert = true } label: { Label("settings_reset_all_data", systemImage: "trash") } } header: { Label("settings_danger_zone", systemImage: "exclamationmark.triangle") } .listRowBackground(Color.mealMoodSurface) } .scrollContentBackground(.hidden) .listStyle(.insetGrouped) .foregroundColor(.mealMoodTextPrimary) .tint(.mealMoodCoral) .onAppear { if settings.syncEnabled { let hasCalendar = viewModel.ensureValidCalendarSelection(settings: settings) settings.syncEnabled = hasCalendar } } .alert("calendar_permission_title", isPresented: $viewModel.showCalendarPermissionAlert) { Button("calendar_permission_settings") { viewModel.openSystemSettings() } Button("reset_cancel", role: .cancel) {} } message: { Text("calendar_permission_message") } .alert("settings_reset_all_data_title", isPresented: $showResetAllDataAlert) { Button("reset_cancel", role: .cancel) {} Button("settings_reset_all_data_confirm", role: .destructive) { viewModel.resetAllData(context: context) } } message: { Text("settings_reset_all_data_message") } } }