+ {/* ── Page Header ─────────────────────────────────────────────────── */}
+
+
+
+
Pensiones
+
+ Seguimiento de aportes, rendimientos y proyecciones
+
+
+
+
+ {/* ── Section 1: Fund Overview Cards ──────────────────────────────── */}
+
+
+
+ Fondos
+
+
+ {FUND_KEYS.map((key) => {
+ const fund = FUNDS[key];
+ return (
+
+
+
+
+
+ {fund.name}
+
+
+ {fund.isDividend ? 'Dividendos' : 'Interés'}
+
+
+
+ {fund.fullName}
+
+
+
+
+
+ Balance actual
+
+
+ {formatCRC(fund.startBalance)}
+
+
+
+
+
+
+
+ Aporte mensual
+
+ {formatCRC(fund.monthlyContribution)}
+
+
+
+ Tasa anual
+ {fund.annualRate}%
+
+
+
+
+
+ {fund.withdrawalRule}
+
+
+
+ );
+ })}
+
+
+
+ {/* ── Section 2: Growth Chart ──────────────────────────────────────── */}
+
+
+
+ Evolución del Balance (Abr 2025 — Mar 2026)
+
+
+
+
+ {FUND_KEYS.map((key) => {
+ const fund = FUNDS[key];
+ const active = visibleFunds.has(key);
+ return (
+
+ );
+ })}
+
+
+
+
+
+
+ `${(v / 1_000_000).toFixed(1)}M`}
+ tick={{ fontSize: 11, fill: 'var(--muted-foreground)' }}
+ axisLine={false}
+ tickLine={false}
+ width={52}
+ />
+ } />
+
+
+
+
+
+
+ {/* ── Section 3: ROI Summary ───────────────────────────────────────── */}
+
+
+
+ Rendimiento — Últimos 12 meses
+
+
+ {FUND_KEYS.map((key) => {
+ const fund = FUNDS[key];
+ const earned = roiEarned[key];
+ return (
+
+
+
+
+ {fund.name}
+
+
+ {fund.isDividend ? `Dividendos ${fund.annualRate}%` : `${fund.annualRate}% anual`}
+
+
+ +{formatCRC(earned)}
+
+ en rendimientos
+
+
+ );
+ })}
+
+
+
+ {/* ── Section 4: Projections ───────────────────────────────────────── */}
+
+
+
+ Proyecciones
+
+
+ Basado en edad actual de {CURRENT_AGE} años. Edita los campos para simular escenarios.
+
+
+ {FUND_KEYS.map((key) => {
+ const fund = FUNDS[key];
+ const proj = projections[key];
+ const projected = calcProjection(
+ fund.startBalance,
+ proj.contribution,
+ proj.rate,
+ proj.targetAge,
+ fund.isDividend,
+ );
+ const years = Math.max(0, proj.targetAge - CURRENT_AGE);
+ return (
+
+
+
+ {fund.name}
+
+
+
+
+
+
+
+
+
+ Valor en {years} {years === 1 ? 'año' : 'años'}
+
+
+ {formatCRC(Math.round(projected))}
+
+
+
+
+ );
+ })}
+
+
+
+ {/* ── Section 5: PDF Upload ────────────────────────────────────────── */}
+
+
+
+ Estados de Cuenta
+
+
+
+ {/* Drop zone */}
+ fileInputRef.current?.click()}
+ role="button"
+ tabIndex={0}
+ onKeyDown={(e) => e.key === 'Enter' && fileInputRef.current?.click()}
+ aria-label="Seleccionar archivos PDF"
+ className={[
+ 'border-2 border-dashed rounded-lg p-8',
+ 'flex flex-col items-center justify-center gap-3',
+ 'cursor-pointer transition-colors select-none',
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
+ isDragging
+ ? 'border-primary bg-primary/5'
+ : 'border-border hover:border-primary/50 hover:bg-muted/30',
+ ].join(' ')}
+ >
+
+
+
+ {isDragging
+ ? 'Suelta los archivos aquí'
+ : 'Arrastra PDFs aquí o toca para seleccionar'}
+
+
+ Solo archivos PDF · Múltiples archivos soportados
+
+
+
+
+ handleFiles(e.target.files)}
+ />
+
+ {/* File list */}
+ {uploadedFiles.length > 0 && (
+
+
+ {uploadedFiles.length}{' '}
+ {uploadedFiles.length === 1 ? 'archivo en cola' : 'archivos en cola'}
+
+
+ {uploadedFiles.map((file, i) => (
+
+
+
+
+
{file.name}
+
{formatFileSize(file.size)}
+
+
+
+
+ ))}
+
+
+ )}
+
+ {/* Submit with "Próximamente" tooltip */}
+
+
+
+ Próximamente
+
+
+
+
+
+
+ );
+}