Update front and fix back

This commit is contained in:
2025-08-14 20:17:13 +07:00
parent 4a45d6c970
commit 8d37b04d3f
9 changed files with 419 additions and 130 deletions

View File

@@ -4577,6 +4577,19 @@ export interface PlatformSummaryViewModel {
totalPlatformPnL?: number;
totalPlatformVolume?: number;
totalPlatformVolumeLast24h?: number;
totalOpenInterest?: number;
totalPositionCount?: number;
agentsChange24h?: number;
strategiesChange24h?: number;
pnLChange24h?: number;
volumeChange24h?: number;
openInterestChange24h?: number;
positionCountChange24h?: number;
volumeByAsset?: { [key: string]: number; } | null;
positionCountByAsset?: { [key: string]: number; } | null;
positionCountByDirection?: { [key: string]: number; } | null;
lastUpdated?: Date;
last24HourSnapshot?: Date;
}
export interface PaginatedAgentIndexResponse {

View File

@@ -967,6 +967,19 @@ export interface PlatformSummaryViewModel {
totalPlatformPnL?: number;
totalPlatformVolume?: number;
totalPlatformVolumeLast24h?: number;
totalOpenInterest?: number;
totalPositionCount?: number;
agentsChange24h?: number;
strategiesChange24h?: number;
pnLChange24h?: number;
volumeChange24h?: number;
openInterestChange24h?: number;
positionCountChange24h?: number;
volumeByAsset?: { [key: string]: number; } | null;
positionCountByAsset?: { [key: string]: number; } | null;
positionCountByDirection?: { [key: string]: number; } | null;
lastUpdated?: Date;
last24HourSnapshot?: Date;
}
export interface PaginatedAgentIndexResponse {

View File

@@ -85,6 +85,12 @@ function PlatformSummary({ index }: { index: number }) {
)
}
const formatPercentageChange = (current: number, change: number) => {
if (current === 0) return '0%'
const percentage = (change / (current - change)) * 100
return `${percentage >= 0 ? '+' : ''}${percentage.toFixed(1)}%`
}
if (isLoading) {
return (
<div className="flex justify-center items-center min-h-96">
@@ -121,8 +127,11 @@ function PlatformSummary({ index }: { index: number }) {
<div className="text-3xl font-bold text-white mb-1">
{formatCurrency(platformData?.totalPlatformVolume || 0)}
</div>
<div className="text-green-500">
+{formatCurrency(platformData?.totalPlatformVolumeLast24h || 0)} Today
<div className={`text-sm ${(platformData?.volumeChange24h || 0) >= 0 ? 'text-green-500' : 'text-red-500'}`}>
{(platformData?.volumeChange24h || 0) >= 0 ? '+' : ''}{formatCurrency(platformData?.volumeChange24h || 0)} Today
<span className="ml-2 text-gray-400">
({formatPercentageChange(platformData?.totalPlatformVolume || 0, platformData?.volumeChange24h || 0)})
</span>
</div>
{/* Simple chart placeholder - you can replace with actual chart */}
<div className="mt-4 h-16 flex items-end">
@@ -230,19 +239,25 @@ function PlatformSummary({ index }: { index: number }) {
</div>
{/* Platform Summary Stats */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
<div className="bg-base-200 rounded-lg p-6">
<h3 className="text-lg font-semibold text-gray-400 mb-2">Total Agents</h3>
<div className="text-3xl font-bold text-white">
<div className="text-3xl font-bold text-white mb-1">
{formatNumber(platformData?.totalAgents || 0)}
</div>
<div className={`text-sm ${(platformData?.agentsChange24h || 0) >= 0 ? 'text-green-500' : 'text-red-500'}`}>
{formatChangeIndicator(platformData?.agentsChange24h || 0)}
</div>
</div>
<div className="bg-base-200 rounded-lg p-6">
<h3 className="text-lg font-semibold text-gray-400 mb-2">Active Strategies</h3>
<div className="text-3xl font-bold text-white">
<div className="text-3xl font-bold text-white mb-1">
{formatNumber(platformData?.totalActiveStrategies || 0)}
</div>
<div className={`text-sm ${(platformData?.strategiesChange24h || 0) >= 0 ? 'text-green-500' : 'text-red-500'}`}>
{formatChangeIndicator(platformData?.strategiesChange24h || 0)}
</div>
</div>
<div className="bg-base-200 rounded-lg p-6">
@@ -250,6 +265,131 @@ function PlatformSummary({ index }: { index: number }) {
<div className={`text-3xl font-bold ${(platformData?.totalPlatformPnL || 0) >= 0 ? 'text-green-500' : 'text-red-500'}`}>
{(platformData?.totalPlatformPnL || 0) >= 0 ? '+' : ''}{formatCurrency(platformData?.totalPlatformPnL || 0)}
</div>
<div className={`text-sm ${(platformData?.pnLChange24h || 0) >= 0 ? 'text-green-500' : 'text-red-500'}`}>
{(platformData?.pnLChange24h || 0) >= 0 ? '+' : ''}{formatCurrency(platformData?.pnLChange24h || 0)} Today
</div>
</div>
<div className="bg-base-200 rounded-lg p-6">
<h3 className="text-lg font-semibold text-gray-400 mb-2">Open Interest</h3>
<div className="text-3xl font-bold text-white mb-1">
{formatCurrency(platformData?.totalOpenInterest || 0)}
</div>
<div className={`text-sm ${(platformData?.openInterestChange24h || 0) >= 0 ? 'text-green-500' : 'text-red-500'}`}>
{(platformData?.openInterestChange24h || 0) >= 0 ? '+' : ''}{formatCurrency(platformData?.openInterestChange24h || 0)} Today
</div>
</div>
</div>
{/* Position Metrics */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
<div className="bg-base-200 rounded-lg p-6">
<h3 className="text-lg font-semibold text-gray-400 mb-2">Total Positions</h3>
<div className="text-3xl font-bold text-white mb-1">
{formatNumber(platformData?.totalPositionCount || 0)}
</div>
<div className={`text-sm ${(platformData?.positionCountChange24h || 0) >= 0 ? 'text-green-500' : 'text-red-500'}`}>
{formatChangeIndicator(platformData?.positionCountChange24h || 0)}
</div>
</div>
<div className="bg-base-200 rounded-lg p-6">
<h3 className="text-lg font-semibold text-gray-400 mb-2">Long Positions</h3>
<div className="text-3xl font-bold text-green-400 mb-1">
{formatNumber(platformData?.positionCountByDirection?.Long || 0)}
</div>
<div className="text-sm text-gray-400">
{platformData?.totalPositionCount ?
((platformData.positionCountByDirection?.Long || 0) / platformData.totalPositionCount * 100).toFixed(1) : 0}% of total
</div>
</div>
<div className="bg-base-200 rounded-lg p-6">
<h3 className="text-lg font-semibold text-gray-400 mb-2">Short Positions</h3>
<div className="text-3xl font-bold text-red-400 mb-1">
{formatNumber(platformData?.positionCountByDirection?.Short || 0)}
</div>
<div className="text-sm text-gray-400">
{platformData?.totalPositionCount ?
((platformData.positionCountByDirection?.Short || 0) / platformData.totalPositionCount * 100).toFixed(1) : 0}% of total
</div>
</div>
</div>
{/* Volume and Positions by Asset */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
{/* Volume by Asset */}
<div className="bg-base-200 rounded-lg p-6">
<h3 className="text-lg font-semibold text-gray-400 mb-4">Volume by Asset</h3>
<div className="space-y-3 max-h-80 overflow-y-auto">
{platformData?.volumeByAsset && Object.keys(platformData.volumeByAsset).length > 0 ? (
Object.entries(platformData.volumeByAsset)
.sort(([,a], [,b]) => b - a)
.slice(0, 10)
.map(([asset, volume]) => (
<div key={asset} className="flex items-center justify-between">
<div className="flex items-center gap-2">
<div className="w-8 h-8 bg-blue-500 rounded-full flex items-center justify-center">
<span className="text-xs font-bold text-white">
{asset.substring(0, 2)}
</span>
</div>
<span className="text-white font-medium">{asset}</span>
</div>
<div className="text-right">
<div className="text-white font-semibold">
{formatCurrency(volume)}
</div>
</div>
</div>
))
) : (
<div className="text-gray-500 text-sm">No volume data available</div>
)}
</div>
</div>
{/* Positions by Asset */}
<div className="bg-base-200 rounded-lg p-6">
<h3 className="text-lg font-semibold text-gray-400 mb-4">Positions by Asset</h3>
<div className="space-y-3 max-h-80 overflow-y-auto">
{platformData?.positionCountByAsset && Object.keys(platformData.positionCountByAsset).length > 0 ? (
Object.entries(platformData.positionCountByAsset)
.sort(([,a], [,b]) => b - a)
.slice(0, 10)
.map(([asset, count]) => (
<div key={asset} className="flex items-center justify-between">
<div className="flex items-center gap-2">
<div className="w-8 h-8 bg-purple-500 rounded-full flex items-center justify-center">
<span className="text-xs font-bold text-white">
{asset.substring(0, 2)}
</span>
</div>
<span className="text-white font-medium">{asset}</span>
</div>
<div className="text-right">
<div className="text-white font-semibold">
{formatNumber(count)} positions
</div>
<div className="text-xs text-gray-400">
{platformData?.totalPositionCount ?
(count / platformData.totalPositionCount * 100).toFixed(1) : 0}% of total
</div>
</div>
</div>
))
) : (
<div className="text-gray-500 text-sm">No position data available</div>
)}
</div>
</div>
</div>
{/* Data Freshness Indicator */}
<div className="bg-base-200 rounded-lg p-4">
<div className="flex items-center justify-between text-sm text-gray-400">
<span>Last updated: {platformData?.lastUpdated ? new Date(platformData.lastUpdated).toLocaleString() : 'Unknown'}</span>
<span>24h snapshot: {platformData?.last24HourSnapshot ? new Date(platformData.last24HourSnapshot).toLocaleString() : 'Unknown'}</span>
</div>
</div>
</div>