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:
alexandrev-tibco
2026-07-03 10:17:10 +02:00
parent d0a51d0162
commit db844d5e80
19 changed files with 557 additions and 230 deletions
@@ -433,3 +433,16 @@
"paywall_trial_format" = "%d %@ gratis";
"chart_history_locked" = "%d weitere Monate Verlauf — mit Premium freischalten";
"chart_group_overview" = "Überblick";
"chart_group_analyze" = "Analyse";
"chart_group_risk" = "Risiko";
"chart_group_forecast" = "Prognose";
"kpi_total_value" = "Gesamtwert";
"kpi_period_return" = "Zeitraum-Rendite";
"kpi_cagr" = "CAGR";
"kpi_volatility" = "Volatilität";
"kpi_max_drawdown" = "Max. Drawdown";
"chart_zoom_in" = "Vergrößern";
"chart_zoom_out" = "Verkleinern";
"chart_zoom_reset" = "Zoom zurücksetzen";
@@ -441,3 +441,16 @@
"paywall_trial_format" = "%d %@ free";
"chart_history_locked" = "%d more months of history — unlock with Premium";
"chart_group_overview" = "Overview";
"chart_group_analyze" = "Analyze";
"chart_group_risk" = "Risk";
"chart_group_forecast" = "Forecast";
"kpi_total_value" = "Total Value";
"kpi_period_return" = "Period Return";
"kpi_cagr" = "CAGR";
"kpi_volatility" = "Volatility";
"kpi_max_drawdown" = "Max Drawdown";
"chart_zoom_in" = "Zoom in";
"chart_zoom_out" = "Zoom out";
"chart_zoom_reset" = "Reset zoom";
@@ -385,3 +385,16 @@
"paywall_trial_format" = "%d %@ gratis";
"chart_history_locked" = "%d meses más de historial — desbloquéalos con Premium";
"chart_group_overview" = "Resumen";
"chart_group_analyze" = "Análisis";
"chart_group_risk" = "Riesgo";
"chart_group_forecast" = "Previsión";
"kpi_total_value" = "Valor total";
"kpi_period_return" = "Retorno periodo";
"kpi_cagr" = "CAGR";
"kpi_volatility" = "Volatilidad";
"kpi_max_drawdown" = "Caída máx.";
"chart_zoom_in" = "Acercar";
"chart_zoom_out" = "Alejar";
"chart_zoom_reset" = "Restablecer zoom";
@@ -433,3 +433,16 @@
"paywall_trial_format" = "%d %@ gratuits";
"chart_history_locked" = "%d mois d'historique en plus — débloquez avec Premium";
"chart_group_overview" = "Aperçu";
"chart_group_analyze" = "Analyse";
"chart_group_risk" = "Risque";
"chart_group_forecast" = "Prévision";
"kpi_total_value" = "Valeur totale";
"kpi_period_return" = "Rendement période";
"kpi_cagr" = "TCAC";
"kpi_volatility" = "Volatilité";
"kpi_max_drawdown" = "Baisse max.";
"chart_zoom_in" = "Zoom avant";
"chart_zoom_out" = "Zoom arrière";
"chart_zoom_reset" = "Réinitialiser le zoom";
@@ -433,3 +433,16 @@
"paywall_trial_format" = "%d %@ gratis";
"chart_history_locked" = "%d mesi di storico in più — sblocca con Premium";
"chart_group_overview" = "Panoramica";
"chart_group_analyze" = "Analisi";
"chart_group_risk" = "Rischio";
"chart_group_forecast" = "Previsione";
"kpi_total_value" = "Valore totale";
"kpi_period_return" = "Rendimento periodo";
"kpi_cagr" = "CAGR";
"kpi_volatility" = "Volatilità";
"kpi_max_drawdown" = "Drawdown max";
"chart_zoom_in" = "Ingrandisci";
"chart_zoom_out" = "Riduci";
"chart_zoom_reset" = "Reimposta zoom";
@@ -433,3 +433,16 @@
"paywall_trial_format" = "%d%@無料";
"chart_history_locked" = "さらに%dか月分の履歴 — プレミアムで解除";
"chart_group_overview" = "概要";
"chart_group_analyze" = "分析";
"chart_group_risk" = "リスク";
"chart_group_forecast" = "予測";
"kpi_total_value" = "合計金額";
"kpi_period_return" = "期間リターン";
"kpi_cagr" = "CAGR";
"kpi_volatility" = "ボラティリティ";
"kpi_max_drawdown" = "最大下落率";
"chart_zoom_in" = "拡大";
"chart_zoom_out" = "縮小";
"chart_zoom_reset" = "ズームをリセット";
@@ -433,3 +433,16 @@
"paywall_trial_format" = "%d %@ grátis";
"chart_history_locked" = "%d meses a mais de histórico — desbloqueie com o Premium";
"chart_group_overview" = "Visão geral";
"chart_group_analyze" = "Análise";
"chart_group_risk" = "Risco";
"chart_group_forecast" = "Previsão";
"kpi_total_value" = "Valor total";
"kpi_period_return" = "Retorno período";
"kpi_cagr" = "CAGR";
"kpi_volatility" = "Volatilidade";
"kpi_max_drawdown" = "Queda máx.";
"chart_zoom_in" = "Ampliar";
"chart_zoom_out" = "Reduzir";
"chart_zoom_reset" = "Redefinir zoom";