import SwiftUI struct OnboardingView: View { @Binding var onboardingCompleted: Bool @State private var currentPage = 0 @State private var selectedCurrency = Locale.current.currency?.identifier ?? "EUR" @State private var useSampleData = true @AppStorage("calmModeEnabled") private var calmModeEnabled = true @AppStorage("cloudSyncEnabled") private var cloudSyncEnabled = false @State private var showingImportSheet = false @State private var showingAddSource = false private let pages: [OnboardingPage] = [ OnboardingPage( icon: "chart.pie.fill", title: "Long-Term Tracking", description: "A calm, offline-first portfolio tracker for investors who update monthly.", color: .appPrimary ), OnboardingPage( icon: "calendar.circle.fill", title: "Monthly Check-ins", description: "Build a deliberate habit. Update sources, log contributions, and add a short note.", color: .positiveGreen ), OnboardingPage( icon: "bell.badge.fill", title: "Gentle Reminders", description: "Get a monthly nudge to review your portfolio without realtime noise.", color: .appWarning ), OnboardingPage( icon: "leaf.fill", title: "Calm Mode", description: "Hide short-term swings and focus on contributions and long-term growth.", color: .appSecondary ) ] var body: some View { VStack { // Pages TabView(selection: $currentPage) { ForEach(0.. Void let onAddSource: () -> Void var body: some View { VStack(spacing: 24) { Spacer() VStack(spacing: 12) { Image("BrandMark") .resizable() .scaledToFit() .frame(width: 72, height: 72) Text("Quick Start") .font(.title.weight(.bold)) Text("Pick your currency and start with sample data or import your own.") .font(.subheadline) .foregroundColor(.secondary) .multilineTextAlignment(.center) .padding(.horizontal, 30) } VStack(spacing: 12) { HStack { Text("Currency") Spacer() Picker("Currency", selection: $selectedCurrency) { ForEach(CurrencyPicker.commonCodes, id: \.self) { code in Text(code).tag(code) } } .pickerStyle(.menu) } .padding() .background(Color.gray.opacity(0.1)) .cornerRadius(12) Toggle("Load sample portfolio", isOn: $useSampleData) .padding() .background(Color.gray.opacity(0.1)) .cornerRadius(12) Toggle("Enable Calm Mode (recommended)", isOn: $calmModeEnabled) .padding() .background(Color.gray.opacity(0.1)) .cornerRadius(12) Toggle("Sync with iCloud (optional)", isOn: $cloudSyncEnabled) .padding() .background(Color.gray.opacity(0.1)) .cornerRadius(12) if cloudSyncEnabled { Text("iCloud sync starts after you restart the app.") .font(.caption) .foregroundColor(.secondary) .frame(maxWidth: .infinity, alignment: .leading) } HStack(spacing: 12) { Button { onImport() } label: { Label("Import", systemImage: "square.and.arrow.down") .frame(maxWidth: .infinity) } .padding() .background(Color.appPrimary.opacity(0.1)) .cornerRadius(12) Button { onAddSource() } label: { Label("Add Source", systemImage: "plus") .frame(maxWidth: .infinity) } .padding() .background(Color.appSecondary.opacity(0.1)) .cornerRadius(12) } } .padding(.horizontal, 24) Spacer() Spacer() } } } // MARK: - First Launch Welcome struct WelcomeView: View { @Binding var showWelcome: Bool let userName: String? @AppStorage("cloudSyncEnabled") private var cloudSyncEnabled = false var body: some View { VStack(spacing: 24) { Spacer() Image(systemName: "hand.wave.fill") .font(.system(size: 60)) .foregroundColor(.appPrimary) VStack(spacing: 8) { if let name = userName { Text("Welcome back, \(name)!") .font(.title.weight(.bold)) } else { Text("Welcome!") .font(.title.weight(.bold)) } Text(cloudSyncEnabled ? "Your investment data has been synced from iCloud." : "Your investment data stays on this device.") .font(.subheadline) .foregroundColor(.secondary) .multilineTextAlignment(.center) } Spacer() Button { withAnimation { showWelcome = false } } label: { Text("Continue") .font(.headline) .foregroundColor(.white) .frame(maxWidth: .infinity) .padding() .background(Color.appPrimary) .cornerRadius(AppConstants.UI.cornerRadius) } .padding(.horizontal, 24) .padding(.bottom, 40) } .background(Color(.systemBackground)) } } #Preview { OnboardingView(onboardingCompleted: .constant(false)) .environmentObject(AccountStore(iapService: IAPService())) }