Rediseño Charts iPad, zoom en gráficas, eliminación de Focus Mode y fixes de rendimiento
Charts iPad (rediseño): - Fila de KPIs sobre el chart: Total Value, Period Return, CAGR, Volatility y Max Drawdown del rango activo (nuevo ChartsViewModel.portfolioMetrics, calculado sobre los TOTALES MENSUALES AGREGADOS — pasar snapshots multi-source crudos a calculateMetrics producía KPIs absurdos) - Sidebar (248pt) con tiles de chart type en grid 2 col agrupados por sección: Overview / Analyze / Risk / Forecast, con candado premium y accesibilidad - Selector de periodo como Picker segmentado nativo en la cabecera del chart (fuera del sidebar); título + descripción del chart visibles - Eliminado sheet de paywall duplicado del layout iPad Zoom (todas las series temporales): - Nuevo ChartZoom.swift: pinch + botones +/- y reset (HIG: el gesto nunca es el único camino), chartScrollableAxes + chartXVisibleDomain al hacer zoom - Integrado en Evolution, Contributions, Rolling 12M, Cashflow, Drawdown y Volatility Focus Mode eliminado (todo siempre disponible): - Fuera el toggle de Dashboard/Charts/Settings/Onboarding y los 6 @AppStorage - Todos los chart types siempre visibles; variantes completas en SourceDetail/SourceList - Home: Total Portfolio Value muestra SIEMPRE el cambio desde el último check-in - PeriodReturnsCard siempre visible Rendimiento y bugs (de la auditoría): - El cache de snapshots ya no se invalida al cambiar solo de chart type/rango/breakdown - calculateAnnualizedGrowth y el forecast a 12 meses ahora componen (la aproximación lineal sobreestimaba con historiales cortos) - Drawdown sin force unwrap; simulador: rama muerta reemplazada por preservación real de las asignaciones simuladas del usuario - UITest de captura de Charts con manejo del alert de notificaciones 12 strings nuevas localizadas en los 7 idiomas. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015qUZrBusG82T37R7PeokqJ
This commit is contained in:
@@ -3,6 +3,7 @@ import Charts
|
||||
|
||||
struct DrawdownChart: View {
|
||||
let data: [(date: Date, drawdown: Double)]
|
||||
@State private var zoom = ChartZoomModel()
|
||||
|
||||
var maxDrawdown: Double {
|
||||
abs(data.map { $0.drawdown }.min() ?? 0)
|
||||
@@ -74,6 +75,7 @@ struct DrawdownChart: View {
|
||||
}
|
||||
.chartYScale(domain: (data.map { $0.drawdown }.min() ?? -50)...0)
|
||||
.frame(height: 250)
|
||||
.zoomableTimeSeries(dates: data.map(\.date), zoom: $zoom)
|
||||
|
||||
// Statistics
|
||||
HStack(spacing: 20) {
|
||||
@@ -164,6 +166,7 @@ struct DrawdownStatView: View {
|
||||
|
||||
struct VolatilityChartView: View {
|
||||
let data: [(date: Date, volatility: Double)]
|
||||
@State private var zoom = ChartZoomModel()
|
||||
|
||||
var currentVolatility: Double {
|
||||
data.last?.volatility ?? 0
|
||||
@@ -236,6 +239,7 @@ struct VolatilityChartView: View {
|
||||
}
|
||||
}
|
||||
.frame(height: 250)
|
||||
.zoomableTimeSeries(dates: data.map(\.date), zoom: $zoom)
|
||||
|
||||
ChartStatsRow(stats: [
|
||||
ChartStat(label: "Current", value: String(format: "%.1f%%", currentVolatility), color: volatilityColor(currentVolatility)),
|
||||
|
||||
Reference in New Issue
Block a user