Update plateform summary

This commit is contained in:
2025-08-14 18:59:37 +07:00
parent cfb04e9dc9
commit 345d76e06f
6 changed files with 272 additions and 25 deletions

View File

@@ -1980,10 +1980,8 @@ export class DataClient extends AuthorizedApiBase {
return Promise.resolve<UserStrategyDetailsViewModel>(null as any);
}
data_GetPlatformSummary(timeFilter: string | null | undefined): Promise<PlatformSummaryViewModel> {
let url_ = this.baseUrl + "/Data/GetPlatformSummary?";
if (timeFilter !== undefined && timeFilter !== null)
url_ += "timeFilter=" + encodeURIComponent("" + timeFilter) + "&";
data_GetPlatformSummary(): Promise<PlatformSummaryViewModel> {
let url_ = this.baseUrl + "/Data/GetPlatformSummary";
url_ = url_.replace(/[?&]$/, "");
let options_: RequestInit = {
@@ -4579,7 +4577,6 @@ export interface PlatformSummaryViewModel {
totalPlatformPnL?: number;
totalPlatformVolume?: number;
totalPlatformVolumeLast24h?: number;
timeFilter?: string | null;
}
export interface PaginatedAgentIndexResponse {

View File

@@ -967,7 +967,6 @@ export interface PlatformSummaryViewModel {
totalPlatformPnL?: number;
totalPlatformVolume?: number;
totalPlatformVolumeLast24h?: number;
timeFilter?: string | null;
}
export interface PaginatedAgentIndexResponse {

View File

@@ -9,6 +9,7 @@ import BestAgents from './analytics/bestAgents'
import AgentSearch from './agentSearch'
import AgentIndex from './agentIndex'
import AgentStrategy from './agentStrategy'
import PlatformSummary from './platformSummary'
const tabs: ITabsType = [
{
@@ -41,6 +42,11 @@ const tabs: ITabsType = [
index: 6,
label: 'Agent Strategy',
},
{
Component: PlatformSummary,
index: 7,
label: 'Platform Summary',
},
]
const Dashboard: React.FC = () => {

View File

@@ -0,0 +1,259 @@
import React, {useEffect, useState} from 'react'
import useApiUrlStore from '../../app/store/apiStore'
import {
DataClient,
type PlatformSummaryViewModel,
type StrategiesStatisticsViewModel,
type TopStrategiesViewModel
} from '../../generated/ManagingApi'
function PlatformSummary({ index }: { index: number }) {
const { apiUrl } = useApiUrlStore()
const [platformData, setPlatformData] = useState<PlatformSummaryViewModel | null>(null)
const [strategiesStats, setStrategiesStats] = useState<StrategiesStatisticsViewModel | null>(null)
const [topStrategies, setTopStrategies] = useState<TopStrategiesViewModel | null>(null)
const [isLoading, setIsLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
const fetchPlatformData = async () => {
setIsLoading(true)
setError(null)
try {
const client = new DataClient({}, apiUrl)
// Fetch all platform data in parallel
const [platform, strategies, top] = await Promise.all([
client.data_GetPlatformSummary(),
client.data_GetStrategiesStatistics(),
client.data_GetTopStrategies()
])
setPlatformData(platform)
setStrategiesStats(strategies)
setTopStrategies(top)
} catch (err) {
setError('Failed to fetch platform data')
console.error('Error fetching platform data:', err)
} finally {
setIsLoading(false)
}
}
useEffect(() => {
fetchPlatformData()
// Set up refresh interval (every 30 seconds)
const interval = setInterval(fetchPlatformData, 30000)
return () => clearInterval(interval)
}, [apiUrl])
const formatCurrency = (value: number) => {
if (value >= 1000000) {
return `$${(value / 1000000).toFixed(1)}M`
} else if (value >= 1000) {
return `$${(value / 1000).toFixed(1)}K`
}
return `$${value.toFixed(0)}`
}
const formatNumber = (value: number) => {
if (value >= 1000) {
return value.toLocaleString()
}
return value.toString()
}
const formatChangeIndicator = (change: number) => {
if (change > 0) {
return (
<span className="text-green-500">
+{change} Today
</span>
)
} else if (change < 0) {
return (
<span className="text-red-500">
{change} Today
</span>
)
}
return (
<span className="text-gray-500">
No change
</span>
)
}
if (isLoading) {
return (
<div className="flex justify-center items-center min-h-96">
<div className="loading loading-spinner loading-lg"></div>
</div>
)
}
if (error) {
return (
<div className="alert alert-error">
<span>{error}</span>
</div>
)
}
return (
<div className="p-6 bg-base-100 min-h-screen">
{/* Header */}
<div className="mb-8">
<h1 className="text-4xl font-bold text-white mb-2">
{formatNumber(strategiesStats?.totalStrategiesRunning || 0)} Strategies Deployed
</h1>
<div className="text-lg">
{strategiesStats && formatChangeIndicator(strategiesStats.changeInLast24Hours || 0)}
</div>
</div>
{/* Main Stats Grid */}
<div className="grid grid-cols-1 lg:grid-cols-4 gap-6 mb-8">
{/* Total Volume Traded */}
<div className="bg-base-200 rounded-lg p-6">
<h3 className="text-lg font-semibold text-gray-400 mb-2">Total Volume Traded</h3>
<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>
{/* Simple chart placeholder - you can replace with actual chart */}
<div className="mt-4 h-16 flex items-end">
<div className="w-full h-8 bg-green-500 rounded opacity-20"></div>
</div>
</div>
{/* Top 3 Most Profitable */}
<div className="bg-base-200 rounded-lg p-6">
<div className="flex items-center gap-2 mb-4">
<span className="text-2xl">🤑</span>
<h3 className="text-lg font-semibold text-gray-400">Top 3 Most Profitable</h3>
</div>
<div className="space-y-3">
{topStrategies?.topStrategies?.slice(0, 3).map((strategy, index) => (
<div key={index} className="flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="w-8 h-8 bg-blue-500 rounded-full flex items-center justify-center">
<span className="text-xs font-bold text-white">
{strategy.strategyName?.charAt(0) || 'S'}
</span>
</div>
<div>
<div className="text-sm text-white font-medium">
{strategy.strategyName || '[Strategy Name]'}
</div>
<div className="text-xs text-gray-400">📧</div>
</div>
</div>
<div className={`text-sm font-bold ${strategy.pnL && strategy.pnL >= 0 ? 'text-green-500' : 'text-red-500'}`}>
{strategy.pnL && strategy.pnL >= 0 ? '+' : ''}{formatCurrency(strategy.pnL || 0)}
</div>
</div>
)) || (
<div className="text-gray-500 text-sm">No profitable strategies found</div>
)}
</div>
</div>
{/* Top 3 Rising (placeholder - using same data for now) */}
<div className="bg-base-200 rounded-lg p-6">
<div className="flex items-center gap-2 mb-4">
<span className="text-2xl">📈</span>
<h3 className="text-lg font-semibold text-gray-400">Top 3 Rising</h3>
</div>
<div className="space-y-3">
{topStrategies?.topStrategies?.slice(0, 3).map((strategy, index) => (
<div key={index} className="flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="w-8 h-8 bg-blue-500 rounded-full flex items-center justify-center">
<span className="text-xs font-bold text-white">
{strategy.strategyName?.charAt(0) || 'S'}
</span>
</div>
<div>
<div className="text-sm text-white font-medium">
{strategy.strategyName || '[Strategy Name]'}
</div>
<div className="text-xs text-gray-400">📧</div>
</div>
</div>
<div className="flex items-center gap-1">
<span className="text-red-500">🔴</span>
<span className="text-sm text-white">1,200</span>
</div>
</div>
)) || (
<div className="text-gray-500 text-sm">No rising strategies found</div>
)}
</div>
</div>
{/* Top 3 Strategies */}
<div className="bg-base-200 rounded-lg p-6">
<div className="flex items-center gap-2 mb-4">
<span className="text-2xl"></span>
<h3 className="text-lg font-semibold text-gray-400">Top 3 Strategies</h3>
</div>
<div className="space-y-3">
{topStrategies?.topStrategies?.slice(0, 3).map((strategy, index) => {
// Calculate a mock percentage for display
const percentage = Math.abs((strategy.pnL || 0) / 100 * 10).toFixed(0)
return (
<div key={index} className="flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="w-8 h-8 bg-yellow-500 rounded-full flex items-center justify-center">
<span className="text-xs font-bold text-black"></span>
</div>
<div>
<div className="text-sm text-white font-medium">
{strategy.strategyName || '[Strategy Name]'}
</div>
</div>
</div>
<div className="text-green-500 text-sm font-bold">
+{percentage}%
</div>
</div>
)
}) || (
<div className="text-gray-500 text-sm">No strategies found</div>
)}
</div>
</div>
</div>
{/* Platform Summary Stats */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<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">
{formatNumber(platformData?.totalAgents || 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">
{formatNumber(platformData?.totalActiveStrategies || 0)}
</div>
</div>
<div className="bg-base-200 rounded-lg p-6">
<h3 className="text-lg font-semibold text-gray-400 mb-2">Total Platform PnL</h3>
<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>
</div>
</div>
)
}
export default PlatformSummary