import SwiftUI struct SettingsView: View { @EnvironmentObject var iapService: IAPService @StateObject private var viewModel: SettingsViewModel init() { _viewModel = StateObject(wrappedValue: SettingsViewModel(iapService: IAPService())) } var body: some View { NavigationStack { List { // Premium Section premiumSection // Notifications Section notificationsSection // Data Section dataSection // About Section aboutSection // Danger Zone dangerZoneSection } .navigationTitle("Settings") .sheet(isPresented: $viewModel.showingPaywall) { PaywallView() } .sheet(isPresented: $viewModel.showingExportOptions) { ExportOptionsSheet(viewModel: viewModel) } .confirmationDialog( "Reset All Data", isPresented: $viewModel.showingResetConfirmation, titleVisibility: .visible ) { Button("Reset Everything", role: .destructive) { viewModel.resetAllData() } } message: { Text("This will permanently delete all your investment data. This action cannot be undone.") } .alert("Success", isPresented: .constant(viewModel.successMessage != nil)) { Button("OK") { viewModel.successMessage = nil } } message: { Text(viewModel.successMessage ?? "") } .alert("Error", isPresented: .constant(viewModel.errorMessage != nil)) { Button("OK") { viewModel.errorMessage = nil } } message: { Text(viewModel.errorMessage ?? "") } } } // MARK: - Premium Section private var premiumSection: some View { Section { if viewModel.isPremium { HStack { ZStack { Circle() .fill(Color.yellow.opacity(0.2)) .frame(width: 44, height: 44) Image(systemName: "crown.fill") .foregroundStyle( LinearGradient( colors: [.yellow, .orange], startPoint: .topLeading, endPoint: .bottomTrailing ) ) } VStack(alignment: .leading, spacing: 2) { Text("Premium Active") .font(.headline) if viewModel.isFamilyShared { Text("Family Sharing") .font(.caption) .foregroundColor(.secondary) } } Spacer() Image(systemName: "checkmark.seal.fill") .foregroundColor(.positiveGreen) } } else { Button { viewModel.upgradeToPremium() } label: { HStack { ZStack { Circle() .fill(Color.appPrimary.opacity(0.1)) .frame(width: 44, height: 44) Image(systemName: "crown.fill") .foregroundColor(.appPrimary) } VStack(alignment: .leading, spacing: 2) { Text("Upgrade to Premium") .font(.headline) .foregroundColor(.primary) Text("Unlock all features for €4.69") .font(.caption) .foregroundColor(.secondary) } Spacer() Image(systemName: "chevron.right") .foregroundColor(.secondary) } } Button { Task { await viewModel.restorePurchases() } } label: { Text("Restore Purchases") } } } header: { Text("Subscription") } footer: { if !viewModel.isPremium { Text("Free: \(viewModel.sourceLimitText) • \(viewModel.historyLimitText)") } } } // MARK: - Notifications Section private var notificationsSection: some View { Section { HStack { Text("Notifications") Spacer() Text(viewModel.notificationsEnabled ? "Enabled" : "Disabled") .foregroundColor(.secondary) } .contentShape(Rectangle()) .onTapGesture { if !viewModel.notificationsEnabled { Task { await viewModel.requestNotificationPermission() } } else { viewModel.openSystemSettings() } } if viewModel.notificationsEnabled { DatePicker( "Default Reminder Time", selection: $viewModel.defaultNotificationTime, displayedComponents: .hourAndMinute ) .onChange(of: viewModel.defaultNotificationTime) { _, newTime in viewModel.updateNotificationTime(newTime) } } } header: { Text("Notifications") } footer: { Text("Set when you'd like to receive investment update reminders.") } } // MARK: - Data Section private var dataSection: some View { Section { Button { if viewModel.canExport { viewModel.showingExportOptions = true } else { viewModel.showingPaywall = true } } label: { HStack { Label("Export Data", systemImage: "square.and.arrow.up") Spacer() if !viewModel.canExport { Image(systemName: "lock.fill") .font(.caption) .foregroundColor(.appWarning) } } } HStack { Text("Total Sources") Spacer() Text("\(viewModel.totalSources)") .foregroundColor(.secondary) } HStack { Text("Total Snapshots") Spacer() Text("\(viewModel.totalSnapshots)") .foregroundColor(.secondary) } HStack { Text("Storage Used") Spacer() Text(viewModel.storageUsedText) .foregroundColor(.secondary) } } header: { Text("Data") } } // MARK: - About Section private var aboutSection: some View { Section { HStack { Text("Version") Spacer() Text(viewModel.appVersion) .foregroundColor(.secondary) } Link(destination: URL(string: AppConstants.URLs.privacyPolicy)!) { HStack { Text("Privacy Policy") Spacer() Image(systemName: "arrow.up.right") .font(.caption) .foregroundColor(.secondary) } } Link(destination: URL(string: AppConstants.URLs.termsOfService)!) { HStack { Text("Terms of Service") Spacer() Image(systemName: "arrow.up.right") .font(.caption) .foregroundColor(.secondary) } } Link(destination: URL(string: AppConstants.URLs.support)!) { HStack { Text("Support") Spacer() Image(systemName: "arrow.up.right") .font(.caption) .foregroundColor(.secondary) } } Button { requestAppReview() } label: { HStack { Text("Rate App") Spacer() Image(systemName: "star.fill") .foregroundColor(.yellow) } } } header: { Text("About") } } // MARK: - Danger Zone Section private var dangerZoneSection: some View { Section { Button(role: .destructive) { viewModel.showingResetConfirmation = true } label: { HStack { Image(systemName: "trash") Text("Reset All Data") } } } header: { Text("Danger Zone") } footer: { Text("This will permanently delete all your investment sources, snapshots, and settings.") } } // MARK: - Helpers private func requestAppReview() { guard let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return } import StoreKit SKStoreReviewController.requestReview(in: scene) } } // MARK: - Export Options Sheet struct ExportOptionsSheet: View { @Environment(\.dismiss) private var dismiss @ObservedObject var viewModel: SettingsViewModel var body: some View { NavigationStack { List { Section { Button { viewModel.exportData(format: .csv) dismiss() } label: { HStack { Image(systemName: "tablecells") .foregroundColor(.positiveGreen) .frame(width: 30) VStack(alignment: .leading) { Text("CSV") .font(.headline) Text("Compatible with Excel, Google Sheets") .font(.caption) .foregroundColor(.secondary) } } } Button { viewModel.exportData(format: .json) dismiss() } label: { HStack { Image(systemName: "doc.text") .foregroundColor(.appPrimary) .frame(width: 30) VStack(alignment: .leading) { Text("JSON") .font(.headline) Text("Full data structure for backup") .font(.caption) .foregroundColor(.secondary) } } } } header: { Text("Select Format") } } .navigationTitle("Export Data") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button("Cancel") { dismiss() } } } } .presentationDetents([.medium]) } } #Preview { SettingsView() .environmentObject(IAPService()) }