trading-platform-frontend-v2/src/modules/predictions/components/StatsOverview.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

153 lines
6.3 KiB
TypeScript

/**
* Prediction Stats Overview Component - STC Theme (Gold/Black)
*/
import { FC } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Progress } from '@/components/ui/progress';
import type { PredictionStats } from '../types';
interface StatsOverviewProps {
stats: PredictionStats;
}
export const StatsOverview: FC<StatsOverviewProps> = ({ stats }) => {
return (
<div className="space-y-6">
{/* Main Stats */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
<Card className="bg-primary-800 border-primary-700">
<CardContent className="p-4">
<p className="text-gray-400 text-sm">Total Predictions</p>
<p className="text-3xl font-bold text-gold">{stats.totalPredictions}</p>
</CardContent>
</Card>
<Card className="bg-primary-800 border-primary-700">
<CardContent className="p-4">
<p className="text-gray-400 text-sm">Win Rate</p>
<p className={`text-3xl font-bold ${stats.winRate >= 50 ? 'text-green-400' : 'text-red-400'}`}>
{stats.winRate.toFixed(1)}%
</p>
</CardContent>
</Card>
<Card className="bg-primary-800 border-primary-700">
<CardContent className="p-4">
<p className="text-gray-400 text-sm">Avg P&L</p>
<p className={`text-3xl font-bold ${stats.averagePnlPercent >= 0 ? 'text-green-400' : 'text-red-400'}`}>
{stats.averagePnlPercent >= 0 ? '+' : ''}{stats.averagePnlPercent.toFixed(2)}%
</p>
</CardContent>
</Card>
<Card className="bg-primary-800 border-primary-700">
<CardContent className="p-4">
<p className="text-gray-400 text-sm">Win/Loss</p>
<p className="text-3xl font-bold">
<span className="text-green-400">{stats.winCount}</span>
<span className="text-gray-500">/</span>
<span className="text-red-400">{stats.lossCount}</span>
</p>
</CardContent>
</Card>
</div>
{/* Breakdown */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{/* By Type */}
<Card className="bg-primary-800 border-primary-700">
<CardHeader>
<CardTitle className="text-white">By Model Type</CardTitle>
</CardHeader>
<CardContent className="space-y-3">
{stats.byType.map((item) => (
<div key={item.predictionType} className="flex items-center justify-between">
<div className="flex items-center gap-3">
<span className="text-gray-300">{item.predictionType}</span>
<span className="text-gray-500 text-sm">({item.total})</span>
</div>
<div className="flex items-center gap-3">
<Progress
value={item.winRate}
className="w-24 h-2 bg-primary-700"
indicatorClassName={item.winRate >= 50 ? 'bg-green-500' : 'bg-red-500'}
/>
<span className={`text-sm font-medium w-12 text-right ${
item.winRate >= 50 ? 'text-green-400' : 'text-red-400'
}`}>
{item.winRate.toFixed(0)}%
</span>
</div>
</div>
))}
</CardContent>
</Card>
{/* By Asset Class */}
<Card className="bg-primary-800 border-primary-700">
<CardHeader>
<CardTitle className="text-white">By Asset Class</CardTitle>
</CardHeader>
<CardContent className="space-y-3">
{stats.byAssetClass.map((item) => (
<div key={item.assetClass} className="flex items-center justify-between">
<div className="flex items-center gap-3">
<span className="text-gray-300">{item.assetClass}</span>
<span className="text-gray-500 text-sm">({item.total})</span>
</div>
<div className="flex items-center gap-3">
<Progress
value={item.winRate}
className="w-24 h-2 bg-primary-700"
indicatorClassName={item.winRate >= 50 ? 'bg-green-500' : 'bg-red-500'}
/>
<span className={`text-sm font-medium w-12 text-right ${
item.winRate >= 50 ? 'text-green-400' : 'text-red-400'
}`}>
{item.winRate.toFixed(0)}%
</span>
</div>
</div>
))}
</CardContent>
</Card>
</div>
{/* Outcome Distribution */}
<Card className="bg-primary-800 border-primary-700">
<CardHeader>
<CardTitle className="text-white">Outcome Distribution</CardTitle>
</CardHeader>
<CardContent>
<div className="flex items-center gap-1 h-8">
<div
className="bg-green-500 h-full rounded-l transition-all"
style={{ width: `${(stats.winCount / stats.totalPredictions) * 100}%` }}
title={`Wins: ${stats.winCount}`}
/>
<div
className="bg-yellow-500 h-full transition-all"
style={{ width: `${(stats.partialCount / stats.totalPredictions) * 100}%` }}
title={`Partial: ${stats.partialCount}`}
/>
<div
className="bg-red-500 h-full transition-all"
style={{ width: `${(stats.lossCount / stats.totalPredictions) * 100}%` }}
title={`Losses: ${stats.lossCount}`}
/>
<div
className="bg-gray-600 h-full rounded-r transition-all"
style={{ width: `${(stats.expiredCount / stats.totalPredictions) * 100}%` }}
title={`Expired: ${stats.expiredCount}`}
/>
</div>
<div className="flex justify-between text-sm mt-2">
<span className="text-green-400">Wins: {stats.winCount}</span>
<span className="text-yellow-400">Partial: {stats.partialCount}</span>
<span className="text-red-400">Losses: {stats.lossCount}</span>
<span className="text-gray-400">Expired: {stats.expiredCount}</span>
</div>
</CardContent>
</Card>
</div>
);
};