a8a9ad64f3
- Imports de CoreData que faltaban (MemberImportVisibility) en AccountsView, ImportDataView, ChartsContainerView y AddSourceView. - Aislamiento MainActor: IsolatedDefaultValues en el target de la app, LinearGradient @MainActor, WatchSyncMessage nonisolated, closures de ReviewPromptService/MonthlyCheckInStore/AppIntents. - Warnings de valores sin usar (SnapshotGapDetector, DashboardLayoutStore, OnboardingView, GoalEditorView, CoreDataStack, SettingsViewModel). - foregroundColor→foregroundStyle, cornerRadius→clipShape, navigationBarLeading/Trailing→topBarLeading/Trailing, Task.sleep(nanoseconds:)→sleep(for:), NavigationLink(isActive:)→ navigationDestination(isPresented:). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F1u4K16xy7eQVtgsYNZ9Vn
67 lines
2.5 KiB
Swift
67 lines
2.5 KiB
Swift
import SwiftUI
|
|
|
|
// Calm 2.0: one insight at a time instead of a chip carousel — a quiet,
|
|
// glanceable line under the check-in zone. Tap to cycle through the rest.
|
|
struct InsightsRow: View {
|
|
let insights: [PortfolioInsight]
|
|
@State private var index = 0
|
|
|
|
private var current: PortfolioInsight? {
|
|
guard !insights.isEmpty else { return nil }
|
|
return insights[index % insights.count]
|
|
}
|
|
|
|
var body: some View {
|
|
if let insight = current {
|
|
Button {
|
|
withAnimation(.snappy) {
|
|
index = (index + 1) % insights.count
|
|
}
|
|
} label: {
|
|
HStack(spacing: 12) {
|
|
Image(systemName: insight.systemImage)
|
|
.font(.subheadline.weight(.semibold))
|
|
.foregroundStyle(insight.accentColor)
|
|
.frame(width: 30, height: 30)
|
|
.background(insight.accentColor.opacity(0.12))
|
|
.clipShape(Circle())
|
|
|
|
VStack(alignment: .leading, spacing: 1) {
|
|
Text(insight.title)
|
|
.font(.caption)
|
|
.foregroundStyle(.secondary)
|
|
Text(insight.value)
|
|
.font(.subheadline.weight(.semibold))
|
|
.foregroundStyle(.primary)
|
|
.lineLimit(2)
|
|
if let detail = insight.detail {
|
|
Text(detail)
|
|
.font(.caption2)
|
|
.foregroundStyle(.secondary)
|
|
.lineLimit(1)
|
|
}
|
|
}
|
|
|
|
Spacer()
|
|
|
|
if insights.count > 1 {
|
|
HStack(spacing: 4) {
|
|
ForEach(insights.indices, id: \.self) { i in
|
|
Circle()
|
|
.fill(i == index % insights.count ? Color.secondary : Color.secondary.opacity(0.25))
|
|
.frame(width: 5, height: 5)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.padding(14)
|
|
.background(Color(.secondarySystemGroupedBackground))
|
|
.clipShape(RoundedRectangle(cornerRadius: AppConstants.UI.cornerRadius))
|
|
}
|
|
.buttonStyle(.plain)
|
|
.id(insight.id)
|
|
.transition(.opacity)
|
|
}
|
|
}
|
|
}
|