// // PlanSettingsView.swift // Bible-Week // // Configurações do Plano de 180 Dias: lembrete diário (horário, som), // pausar/continuar e reiniciar. // import SwiftUI import UserNotifications struct PlanSettingsView: View { @Bindable var plan: ReadingPlanState @Environment(\.dismiss) private var dismiss @State private var authorizationStatus: UNAuthorizationStatus = .notDetermined @State private var showRestartConfirmation = false var body: some View { NavigationStack { Form { remindersSection planSection } .navigationTitle("Plano de Leitura") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .confirmationAction) { Button("OK") { dismiss() } } } .task { authorizationStatus = await ReadingReminderService.authorizationStatus() } .confirmationDialog( "Reiniciar o plano do dia 1? Seu progresso atual será apagado, mas a preferência de lembrete será mantida.", isPresented: $showRestartConfirmation, titleVisibility: .visible ) { Button("Reiniciar plano", role: .destructive) { plan.restart() Task { await ReadingReminderService.refresh(for: plan) } } } } } // MARK: - Lembretes @ViewBuilder private var remindersSection: some View { Section("Lembretes") { if authorizationStatus == .denied { VStack(alignment: .leading, spacing: 8) { Text("Notificações desativadas") .font(.headline) Text("Para receber lembretes de leitura, habilite as notificações nos Ajustes do iPhone.") .font(.caption) .foregroundStyle(.secondary) Button("Abrir Ajustes") { openNotificationSettings() } } .padding(.vertical, 4) } else { Toggle("Lembrete diário", isOn: reminderEnabledBinding) if plan.reminderEnabled { DatePicker( "Horário", selection: reminderTimeBinding, displayedComponents: .hourAndMinute ) Toggle("Som", isOn: soundEnabledBinding) } } } .accessibilityElement(children: .contain) } /// Ligar pede autorização se necessário; desligar cancela o agendamento. private var reminderEnabledBinding: Binding { Binding { plan.reminderEnabled } set: { newValue in if newValue { Task { let status = await ReadingReminderService.authorizationStatus() var granted = status == .authorized || status == .provisional if status == .notDetermined { granted = (try? await ReadingReminderService.requestAuthorization()) ?? false } if granted { plan.reminderEnabled = true await ReadingReminderService.refresh(for: plan) } else { plan.reminderEnabled = false authorizationStatus = .denied } } } else { plan.reminderEnabled = false ReadingReminderService.cancelDailyReminder() } } } /// Alterar o horário substitui o agendamento anterior (mesmo identificador, /// nunca duplica) e persiste o novo valor. private var reminderTimeBinding: Binding { Binding { Calendar.current.date( bySettingHour: plan.reminderHour, minute: plan.reminderMinute, second: 0, of: .now ) ?? .now } set: { newValue in let components = Calendar.current.dateComponents([.hour, .minute], from: newValue) plan.reminderHour = components.hour ?? 20 plan.reminderMinute = components.minute ?? 0 Task { await ReadingReminderService.refresh(for: plan) } } } private var soundEnabledBinding: Binding { Binding { plan.reminderSoundEnabled } set: { newValue in plan.reminderSoundEnabled = newValue Task { await ReadingReminderService.refresh(for: plan) } } } // MARK: - Plano private var planSection: some View { Section("Plano") { LabeledContent("Progresso", value: "\(plan.completedDaysCount) de \(PlanSchedule.totalDays) dias") Button(plan.isPaused ? "Continuar plano" : "Pausar plano") { plan.isPaused.toggle() // Pausar remove o agendamento sem apagar a preferência; // continuar restaura automaticamente o horário salvo. Task { await ReadingReminderService.refresh(for: plan) } } Button("Reiniciar plano", role: .destructive) { showRestartConfirmation = true } } } }