import SwiftUI struct SettingsView: View { @State private var store = AppStore.shared @State private var session = SessionStore.shared var body: some View { VStack(alignment: .leading, spacing: 24) { VStack(alignment: .leading, spacing: 4) { Text("Settings") .font(.system(size: 28, weight: .bold)) .foregroundStyle(VelocityTheme.foreground) Text("Live runtime configuration") .font(.system(size: 12)) .foregroundStyle(VelocityTheme.mutedFg) } SettingsSection(title: "Connectivity") { SettingsRow( label: "Backend endpoint", value: session.endpointDisplay, icon: "server.rack", accentColor: VelocityTheme.accent ) Divider().background(VelocityTheme.borderSubtle) SettingsRow( label: "Dream Weaver endpoint", value: session.dreamWeaverEndpointDisplay, icon: "wand.and.stars", accentColor: session.dreamWeaverEndpointModeDescription == "Dedicated gateway" ? VelocityTheme.warning : VelocityTheme.mutedFg ) Divider().background(VelocityTheme.borderSubtle) SettingsRow( label: "Dream Weaver route mode", value: session.dreamWeaverEndpointModeDescription, icon: "point.3.connected.trianglepath.dotted", accentColor: session.dreamWeaverEndpointModeDescription == "Dedicated gateway" ? VelocityTheme.warning : VelocityTheme.success ) Divider().background(VelocityTheme.borderSubtle) SettingsRow( label: "Dream Weaver auth", value: session.dreamWeaverAuthenticationDescription, icon: "key.horizontal", accentColor: session.dreamWeaverAuthenticationDescription == "API key configured" ? VelocityTheme.success : VelocityTheme.mutedFg ) Divider().background(VelocityTheme.borderSubtle) SettingsRow( label: "Auth mode", value: session.authModeDescription, icon: "lock.shield", accentColor: session.isConfigured ? VelocityTheme.success : VelocityTheme.warning ) Divider().background(VelocityTheme.borderSubtle) SettingsRow( label: "Config source", value: session.configurationSourceDescription, icon: "externaldrive.badge.icloud", accentColor: session.isUsingStoredRuntimeConfiguration ? VelocityTheme.success : VelocityTheme.mutedFg ) Divider().background(VelocityTheme.borderSubtle) SettingsRow( label: "Last refresh", value: store.lastRefreshAt?.relativeShort ?? "No live fetch yet", icon: "arrow.clockwise", accentColor: VelocityTheme.mutedFg ) } SettingsSection(title: "Operator") { SettingsRow( label: "Identity", value: session.operatorIdentity, icon: "person.crop.circle", accentColor: VelocityTheme.accent ) Divider().background(VelocityTheme.borderSubtle) SettingsRow( label: "CRM contacts loaded", value: "\(store.contacts.count)", icon: "person.3", accentColor: VelocityTheme.success ) Divider().background(VelocityTheme.borderSubtle) SettingsRow( label: "Pending CRM tasks loaded", value: "\(store.tasks.count)", icon: "checklist", accentColor: VelocityTheme.warning ) Divider().background(VelocityTheme.borderSubtle) SettingsRow( label: "Property records loaded", value: "\(store.properties.count)", icon: "building.2", accentColor: VelocityTheme.warning ) } SettingsSection(title: "Production Readiness") { SettingsRow( label: "Canonical contacts", value: "\(store.contacts.count) loaded", icon: "person.text.rectangle", accentColor: store.contacts.isEmpty ? VelocityTheme.warning : VelocityTheme.success ) Divider().background(VelocityTheme.borderSubtle) SettingsRow( label: "Pipeline lanes", value: "\(store.kanbanColumns.reduce(0) { $0 + $1.count }) leads", icon: "square.grid.3x1.below.line.grid.1x2", accentColor: store.kanbanColumns.isEmpty ? VelocityTheme.warning : VelocityTheme.success ) Divider().background(VelocityTheme.borderSubtle) SettingsRow( label: "Deals", value: "\(store.opportunities.count) opportunities", icon: "target", accentColor: store.opportunities.isEmpty ? VelocityTheme.warning : VelocityTheme.success ) Divider().background(VelocityTheme.borderSubtle) SettingsRow( label: "Timeline events", value: "\(store.timelineEvents.count) hydrated", icon: "clock.arrow.circlepath", accentColor: store.timelineEvents.isEmpty ? VelocityTheme.warning : VelocityTheme.success ) Divider().background(VelocityTheme.borderSubtle) SettingsRow( label: "Last app error", value: store.errorMessage ?? "None", icon: "exclamationmark.triangle", accentColor: store.errorMessage == nil ? VelocityTheme.success : VelocityTheme.danger ) } SessionConfigurationPanel( title: "Session Configuration", subtitle: "Update the production endpoint, point Dream Weaver at a dedicated gateway when needed, or rotate operator credentials without rebuilding the app. Saving clears the cached token, re-runs a live refresh, and probes the Dream Weaver routes.", primaryActionTitle: "Save and refresh", allowsClearingStoredConfiguration: true ) SettingsSection(title: "Production Notes") { VStack(alignment: .leading, spacing: 8) { Text("This build avoids local demo data. Runtime session overrides are stored on-device so investor or operator installs no longer depend on committed build-time credentials.") .font(.system(size: 13)) .foregroundStyle(VelocityTheme.foreground) Text("\(SentinelScope.navigationTitle) remains the truthful iPad label for the current \(SentinelScope.productFamilyName) surface because visitor analytics stay disabled until a dedicated production feed exists; Communications, Calendar, Dashboard, Oracle pipeline, and inventory summaries are live-backed. Dream Weaver can now use a dedicated gateway with an optional per-gateway API key, and backend plus generation route health are still enforced and reported truthfully.") .font(.system(size: 12)) .foregroundStyle(VelocityTheme.mutedFg) } .padding(.horizontal, 16) .padding(.vertical, 14) } Spacer() } .padding(24) .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) .background(VelocityTheme.background) } } private struct SettingsSection: View { let title: String @ViewBuilder let content: Content var body: some View { VStack(alignment: .leading, spacing: 0) { Text(title.uppercased()) .font(.system(size: 10, weight: .semibold)) .tracking(1.2) .foregroundStyle(VelocityTheme.mutedFg) .padding(.bottom, 8) .padding(.horizontal, 4) VStack(spacing: 0) { content } .padding(.vertical, 4) .background( RoundedRectangle(cornerRadius: 14) .fill(Color(red: 0.031, green: 0.039, blue: 0.071)) .overlay( RoundedRectangle(cornerRadius: 14) .stroke(VelocityTheme.borderSubtle, lineWidth: 1) ) ) } } } private struct SettingsRow: View { let label: String let value: String let icon: String let accentColor: Color var body: some View { HStack(spacing: 14) { ZStack { RoundedRectangle(cornerRadius: 7) .fill(accentColor.opacity(0.12)) .frame(width: 30, height: 30) Image(systemName: icon) .font(.system(size: 13, weight: .medium)) .foregroundStyle(accentColor) } Text(label) .font(.system(size: 14)) .foregroundStyle(VelocityTheme.foreground) Spacer() Text(value) .font(.system(size: 13)) .foregroundStyle(VelocityTheme.mutedFg) .multilineTextAlignment(.trailing) } .padding(.horizontal, 16) .padding(.vertical, 12) } }