trading-platform-frontend-v2/src/modules/investment/pages/InvestmentPage.tsx
rckrdmrd 737303d177 Migración desde trading-platform/apps/frontend - Estándar multi-repo v2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 08:32:49 -06:00

192 lines
7.1 KiB
TypeScript

/**
* Investment Page - STC Theme (Gold/Black)
*/
import { FC, useState } from 'react';
import { useAgents, useAllocations, useInvestmentSummary } from '../hooks/useInvestment';
import { AgentCard, AllocationCard, AllocationModal } from '../components';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Skeleton } from '@/components/ui/skeleton';
import type { AgentConfig, AllocationWithAgent, AgentType } from '../types';
export const InvestmentPage: FC = () => {
const [showModal, setShowModal] = useState(false);
const [selectedAgent, setSelectedAgent] = useState<AgentConfig | null>(null);
const [selectedAllocation, setSelectedAllocation] = useState<AllocationWithAgent | null>(null);
const { data: agents, isLoading: agentsLoading } = useAgents();
const { data: allocations, isLoading: allocationsLoading } = useAllocations();
const { data: summary } = useInvestmentSummary();
const handleAllocate = (agentType: AgentType) => {
const agent = agents?.find((a) => a.agentType === agentType);
const existingAllocation = allocations?.find(
(a) => a.agentType === agentType && a.status === 'active'
);
setSelectedAgent(agent || null);
setSelectedAllocation(existingAllocation || null);
setShowModal(true);
};
const handleManageAllocation = (allocation: AllocationWithAgent) => {
const agent = agents?.find((a) => a.agentType === allocation.agentType);
setSelectedAgent(agent || null);
setSelectedAllocation(allocation);
setShowModal(true);
};
const handleCloseModal = () => {
setShowModal(false);
setSelectedAgent(null);
setSelectedAllocation(null);
};
// Get allocation value by agent type
const getAllocationValue = (agentType: AgentType) => {
const allocation = allocations?.find(
(a) => a.agentType === agentType && a.status === 'active'
);
return allocation?.currentValue || 0;
};
if (agentsLoading || allocationsLoading) {
return (
<div className="min-h-screen bg-background p-6">
<div className="max-w-6xl mx-auto">
<div className="space-y-6">
<Skeleton className="h-32 w-full bg-primary-800" />
<div className="grid grid-cols-3 gap-6">
{[1, 2, 3].map((i) => (
<Skeleton key={i} className="h-96 w-full bg-primary-800" />
))}
</div>
</div>
</div>
</div>
);
}
const activeAllocations = allocations?.filter((a) => a.status === 'active') || [];
return (
<div className="min-h-screen bg-background p-6">
<div className="max-w-6xl mx-auto space-y-8">
{/* Header */}
<div>
<h1 className="text-3xl font-bold text-white">
Investment <span className="text-gold">Agents</span>
</h1>
<p className="text-gray-400 mt-1">
Allocate funds to AI-powered trading agents
</p>
</div>
{/* Portfolio Summary */}
{summary && (summary.totalAllocated > 0 || activeAllocations.length > 0) && (
<div className="bg-gradient-to-r from-gold/20 to-primary-700/50 rounded-xl border border-gold/30 p-6">
<h2 className="text-lg font-semibold text-white mb-4">Your Portfolio</h2>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
<div>
<p className="text-gray-400 text-sm">Total Allocated</p>
<p className="text-2xl font-bold text-white">
${summary.totalAllocated.toLocaleString()}
</p>
</div>
<div>
<p className="text-gray-400 text-sm">Current Value</p>
<p className="text-2xl font-bold text-gold">
${summary.currentValue.toLocaleString()}
</p>
</div>
<div>
<p className="text-gray-400 text-sm">Total P&L</p>
<p className={`text-2xl font-bold ${summary.totalPnl >= 0 ? 'text-green-400' : 'text-red-400'}`}>
{summary.totalPnl >= 0 ? '+' : ''}${summary.totalPnl.toFixed(2)}
</p>
</div>
<div>
<p className="text-gray-400 text-sm">Return</p>
<p className={`text-2xl font-bold ${summary.totalPnlPercent >= 0 ? 'text-green-400' : 'text-red-400'}`}>
{summary.totalPnlPercent >= 0 ? '+' : ''}{summary.totalPnlPercent.toFixed(2)}%
</p>
</div>
</div>
</div>
)}
{/* Agent Cards */}
<div>
<h2 className="text-xl font-semibold text-gold mb-4">Available Agents</h2>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{agents?.map((agent) => (
<AgentCard
key={agent.id}
agent={agent}
userAllocationValue={getAllocationValue(agent.agentType)}
onAllocate={handleAllocate}
/>
))}
</div>
</div>
{/* Active Allocations */}
{activeAllocations.length > 0 && (
<div>
<h2 className="text-xl font-semibold text-gold mb-4">Your Allocations</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{activeAllocations.map((allocation) => (
<AllocationCard
key={allocation.id}
allocation={allocation}
onManage={handleManageAllocation}
/>
))}
</div>
</div>
)}
{/* Info Section */}
<Card className="bg-primary-800 border-primary-700">
<CardHeader>
<CardTitle className="text-white">How It Works</CardTitle>
</CardHeader>
<CardContent>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<div className="text-center">
<div className="text-4xl mb-3">1</div>
<h4 className="text-gold font-medium mb-1">Choose an Agent</h4>
<p className="text-gray-400 text-sm">
Select based on your risk tolerance and return expectations
</p>
</div>
<div className="text-center">
<div className="text-4xl mb-3">2</div>
<h4 className="text-gold font-medium mb-1">Allocate Funds</h4>
<p className="text-gray-400 text-sm">
Transfer credits from your wallet to the agent
</p>
</div>
<div className="text-center">
<div className="text-4xl mb-3">3</div>
<h4 className="text-gold font-medium mb-1">Earn Returns</h4>
<p className="text-gray-400 text-sm">
Profits are distributed monthly after fees
</p>
</div>
</div>
</CardContent>
</Card>
</div>
{/* Allocation Modal */}
<AllocationModal
isOpen={showModal}
onClose={handleCloseModal}
agent={selectedAgent}
existingAllocation={selectedAllocation}
/>
</div>
);
};