+ {/* Header */}
+
+
+
+ Editar Allocaciones
+
+
+ {portfolio?.name} - Perfil{' '}
+ {portfolio?.riskProfile === 'conservative'
+ ? 'Conservador'
+ : portfolio?.riskProfile === 'moderate'
+ ? 'Moderado'
+ : 'Agresivo'}
+
+
+
+ {/* Total indicator */}
+
+
+ {!isValid && }
+
+ Total: {totalPercent.toFixed(1)}%
+
+
+ {!isValid && (
+
+ {totalPercent < 100
+ ? `Faltan ${(100 - totalPercent).toFixed(1)}%`
+ : `Sobran ${(totalPercent - 100).toFixed(1)}%`}
+
+ )}
+
+
+ {/* Allocations list */}
+
+
+
Distribución
+
+
+
+
+ {allocations.map((alloc, index) => {
+ const assetInfo = AVAILABLE_ASSETS.find((a) => a.symbol === alloc.asset);
+ return (
+
+
+ {assetInfo?.icon ? (
+

+ ) : (
+
+ {alloc.asset.slice(0, 2)}
+
+ )}
+
+
+ {alloc.asset}
+
+
+ {assetInfo?.name || alloc.asset}
+
+
+
+
+
+ handlePercentChange(index, e.target.value)}
+ min="0"
+ max="100"
+ step="0.1"
+ className="w-20 px-3 py-2 bg-white dark:bg-gray-600 border border-gray-200 dark:border-gray-500 rounded-lg text-right text-gray-900 dark:text-white"
+ />
+ %
+
+
+
+
+ {/* Visual bar */}
+
+
+ );
+ })}
+
+
+ {/* Add asset button */}
+ {availableToAdd.length > 0 && (
+
+ )}
+
+
+ {/* Error Message */}
+ {error && (
+
+ )}
+
+ {/* Action buttons */}
+
+
+
+
+
+ {/* Add Asset Modal */}
+ {showAddModal && (
+
+
+
+
Agregar Activo
+
+
+
+ {availableToAdd.map((asset) => (
+
+ ))}
+
+
+
+
+
+
+
+ )}
+
+ );
+}
diff --git a/src/modules/portfolio/pages/PortfolioDashboard.tsx b/src/modules/portfolio/pages/PortfolioDashboard.tsx
index 94015d5..df89c73 100644
--- a/src/modules/portfolio/pages/PortfolioDashboard.tsx
+++ b/src/modules/portfolio/pages/PortfolioDashboard.tsx
@@ -29,6 +29,7 @@ import { AllocationChart } from '../components/AllocationChart';
import { AllocationTable } from '../components/AllocationTable';
import { RebalanceCard } from '../components/RebalanceCard';
import { GoalCard } from '../components/GoalCard';
+import { PerformanceChart } from '../components/PerformanceChart';
// ============================================================================
// Subcomponents
@@ -289,6 +290,11 @@ export default function PortfolioDashboard() {
/>
+ {/* Performance Chart */}
+
{/* Left: Allocation Chart & Table */}
diff --git a/src/services/portfolio.service.ts b/src/services/portfolio.service.ts
index f09ad38..1f9f318 100644
--- a/src/services/portfolio.service.ts
+++ b/src/services/portfolio.service.ts
@@ -193,6 +193,62 @@ export async function getPortfolioStats(portfolioId: string): Promise
{
+ const response = await fetch(
+ `${API_URL}/api/v1/portfolio/${portfolioId}/performance?period=${period}`,
+ { credentials: 'include' }
+ );
+ if (!response.ok) throw new Error('Failed to fetch performance');
+ const data = await response.json();
+ return data.data || data;
+}
+
+/**
+ * Get detailed performance statistics
+ */
+export async function getPerformanceStats(portfolioId: string): Promise {
+ const response = await fetch(`${API_URL}/api/v1/portfolio/${portfolioId}/performance/stats`, {
+ credentials: 'include',
+ });
+ if (!response.ok) throw new Error('Failed to fetch performance stats');
+ const data = await response.json();
+ return data.data || data;
+}
+
// ============================================================================
// Goals API Functions
// ============================================================================