Files
InvestmentTrackerApp/PortfolioJournal/Models/PortfolioInsight.swift
T
alexandrev-tibco 6887d05b01 1.6.0 #6+#7: proyección/ETA de objetivos + insights inteligentes
Goal ETA (#6): GoalProjection engine (CAGR mensual robusto de la evolución +
aportaciones, proyecta mes a mes → fecha estimada, estado ahead/on-track/behind/
unreachable, sparkline). GoalsView muestra 'Projected: <mes>', chip de ritmo con color,
fallback 'Add contributions to reach this'. GoalsViewModel.projection(for:) cacheado.

Insights (#7): InsightsEngine rule-based on-device (sin red/AI). Reglas: allocation vs
target, riesgo de concentración, mejor/peor categoría, diversificación, racha, YTD,
ganancias, forecast, proximidad a milestone. Priorizados por tono, top 4. PortfolioInsight
gana detail + tone. Surface en el Dashboard.

Localización: 19 claves nuevas en los 7 idiomas.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L2p3gUZRNWW388rWFRjiU7
2026-07-25 12:22:12 +02:00

48 lines
1.1 KiB
Swift

import SwiftUI
/// Tone / severity of an insight, used to pick an accent color and to
/// prioritize which insights are surfaced first.
enum InsightTone {
case positive
case neutral
case attention
/// Higher priority insights are shown first when capping the list.
var priority: Int {
switch self {
case .attention: return 2
case .positive: return 1
case .neutral: return 0
}
}
}
struct PortfolioInsight: Identifiable {
let id: String
let systemImage: String
let title: String
let value: String
let accentColor: Color
/// Optional supporting line shown under the value in the richer card.
let detail: String?
let tone: InsightTone
init(
id: String,
systemImage: String,
title: String,
value: String,
accentColor: Color,
detail: String? = nil,
tone: InsightTone = .neutral
) {
self.id = id
self.systemImage = systemImage
self.title = title
self.value = value
self.accentColor = accentColor
self.detail = detail
self.tone = tone
}
}