Files
FamilyMealPlanner/MealMood/Views/Onboarding/CalendarStepView.swift
T

157 lines
6.6 KiB
Swift

import SwiftUI
import EventKit
struct CalendarStepView: View {
@Binding var iCloudSyncEnabled: Bool
@Binding var syncEnabled: Bool
@Binding var selectedCalendarId: String?
@Binding var lunchTime: Date
@Binding var dinnerTime: Date
var onEnableICloud: () -> Void
var onNext: () -> Void
var onSkip: () -> Void
@State private var availableCalendars: [EKCalendar] = []
@State private var showPermissionAlert = false
var body: some View {
ScrollView {
VStack(spacing: 24) {
Text("calendar_title")
.font(.mealMoodH1)
.foregroundColor(.mealMoodTextPrimary)
.multilineTextAlignment(.leading)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal, 24)
.padding(.top, 12)
VStack(spacing: 16) {
// iCloud sync toggle
HStack {
Text("settings_icloud_sync")
.font(.mealMoodBody)
.foregroundColor(.mealMoodTextPrimary)
Spacer()
Toggle("", isOn: $iCloudSyncEnabled)
.tint(.mealMoodCoral)
.labelsHidden()
.onChange(of: iCloudSyncEnabled) { _, newValue in
if newValue {
onEnableICloud()
}
}
}
.padding(16)
.background(Color.mealMoodSurface)
.cornerRadius(14)
.overlay(
RoundedRectangle(cornerRadius: 14)
.stroke(Color(hex: "#F0F0F0"), lineWidth: 1)
)
// Sync toggle
HStack {
Text("calendar_sync")
.font(.mealMoodBody)
.foregroundColor(.mealMoodTextPrimary)
Spacer()
Toggle("", isOn: $syncEnabled)
.tint(.mealMoodCoral)
.labelsHidden()
.onChange(of: syncEnabled) { _, newValue in
if newValue {
Task {
let granted = await CalendarService.shared.requestAccess()
if granted {
availableCalendars = CalendarService.shared.availableCalendars()
} else {
syncEnabled = false
showPermissionAlert = true
}
}
}
}
}
.padding(16)
.background(Color.mealMoodSurface)
.cornerRadius(14)
.overlay(
RoundedRectangle(cornerRadius: 14)
.stroke(Color(hex: "#F0F0F0"), lineWidth: 1)
)
if syncEnabled {
// Calendar picker
if !availableCalendars.isEmpty {
VStack(alignment: .leading, spacing: 8) {
Text("calendar_select")
.font(.mealMoodSmall)
.foregroundColor(.mealMoodTextSecondary)
Picker("calendar_select", selection: $selectedCalendarId) {
Text("calendar_select").tag(nil as String?)
ForEach(availableCalendars, id: \.calendarIdentifier) { cal in
Text(cal.title).tag(cal.calendarIdentifier as String?)
}
}
.pickerStyle(.menu)
.padding(12)
.background(Color.mealMoodSurface)
.cornerRadius(12)
.overlay(
RoundedRectangle(cornerRadius: 12)
.stroke(Color(hex: "#F0F0F0"), lineWidth: 1)
)
}
}
// Time pickers
VStack(spacing: 12) {
DatePicker("calendar_lunch_time", selection: $lunchTime, displayedComponents: .hourAndMinute)
.font(.mealMoodBody)
DatePicker("calendar_dinner_time", selection: $dinnerTime, displayedComponents: .hourAndMinute)
.font(.mealMoodBody)
}
.padding(16)
.background(Color.mealMoodSurface)
.cornerRadius(14)
.overlay(
RoundedRectangle(cornerRadius: 14)
.stroke(Color(hex: "#F0F0F0"), lineWidth: 1)
)
}
}
.padding(.horizontal, 24)
Text("calendar_optional")
.font(.mealMoodSmall)
.foregroundColor(.mealMoodTextSecondary)
Spacer(minLength: 40)
HStack(spacing: 12) {
SecondaryButton(title: String(localized: "onboarding_skip"), action: {
syncEnabled = false
onSkip()
})
PrimaryButton(title: String(localized: "onboarding_continue"), action: onNext)
}
.padding(.horizontal, 24)
.padding(.bottom, 40)
}
}
.alert("calendar_permission_title", isPresented: $showPermissionAlert) {
Button("calendar_permission_settings") {
if let url = URL(string: UIApplication.openSettingsURLString) {
UIApplication.shared.open(url)
}
}
Button("reset_cancel", role: .cancel) {}
} message: {
Text("calendar_permission_message")
}
}
}