fix: show -- instead of 0 when account data fetch fails on dashboard

Replace zero-value fallback with undefined, pass accountFailed prop to
distinguish load failure from initial loading skeleton.
This commit is contained in:
Dean
2026-03-27 20:57:39 +08:00
committed by shinchan-zhai
parent 4a483eaca6
commit d6e3088998
2 changed files with 22 additions and 16 deletions

View File

@@ -322,10 +322,7 @@ function App() {
const selectedTrader = traders?.find((t) => t.trader_id === selectedTraderId) const selectedTrader = traders?.find((t) => t.trader_id === selectedTraderId)
// When polling has permanently failed, provide zero-value data instead of keeping skeleton const effectiveAccount = account
const effectiveAccount = (accountPollOff && !account)
? { total_equity: 0, available_balance: 0, total_pnl: 0, total_pnl_pct: 0, position_count: 0, margin_used: 0, margin_used_pct: 0 } as AccountInfo
: account
const effectivePositions = (positionsPollOff && !positions) ? [] as Position[] : positions const effectivePositions = (positionsPollOff && !positions) ? [] as Position[] : positions
const effectiveDecisions = (decisionsPollOff && !decisions) ? [] as DecisionRecord[] : decisions const effectiveDecisions = (decisionsPollOff && !decisions) ? [] as DecisionRecord[] : decisions
@@ -545,6 +542,7 @@ function App() {
selectedTrader={selectedTrader} selectedTrader={selectedTrader}
status={status} status={status}
account={effectiveAccount} account={effectiveAccount}
accountFailed={accountPollOff}
positions={effectivePositions} positions={effectivePositions}
decisions={effectiveDecisions} decisions={effectiveDecisions}
decisionsLimit={decisionsLimit} decisionsLimit={decisionsLimit}

View File

@@ -103,6 +103,7 @@ interface TraderDashboardPageProps {
onNavigateToTraders: () => void onNavigateToTraders: () => void
status?: SystemStatus status?: SystemStatus
account?: AccountInfo account?: AccountInfo
accountFailed?: boolean
positions?: Position[] positions?: Position[]
decisions?: DecisionRecord[] decisions?: DecisionRecord[]
decisionsLimit: number decisionsLimit: number
@@ -117,6 +118,7 @@ export function TraderDashboardPage({
selectedTrader, selectedTrader,
status, status,
account, account,
accountFailed,
positions, positions,
decisions, decisions,
decisionsLimit, decisionsLimit,
@@ -488,6 +490,12 @@ export function TraderDashboardPage({
<span>EQ::{account.total_equity?.toFixed(2)}</span> <span>EQ::{account.total_equity?.toFixed(2)}</span>
<span>PNL::{account.total_pnl?.toFixed(2)}</span> <span>PNL::{account.total_pnl?.toFixed(2)}</span>
</div> </div>
) : accountFailed ? (
<div className="flex gap-4">
<span>LAST_UPDATE::--</span>
<span>EQ::--</span>
<span>PNL::--</span>
</div>
) : ( ) : (
<div className="flex gap-4"> <div className="flex gap-4">
<span className="inline-block w-32 h-3 rounded bg-white/5 animate-pulse" /> <span className="inline-block w-32 h-3 rounded bg-white/5 animate-pulse" />
@@ -501,37 +509,37 @@ export function TraderDashboardPage({
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-8"> <div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-8">
<StatCard <StatCard
title={t('totalEquity', language)} title={t('totalEquity', language)}
value={`${account?.total_equity?.toFixed(2) || '0.00'}`} value={accountFailed && !account ? '--' : `${account?.total_equity?.toFixed(2) ?? '--'}`}
unit="USDT" unit="USDT"
change={account?.total_pnl_pct || 0} change={account ? (account.total_pnl_pct || 0) : undefined}
positive={(account?.total_pnl ?? 0) > 0} positive={(account?.total_pnl ?? 0) > 0}
icon="💰" icon="💰"
loading={!account} loading={!account && !accountFailed}
/> />
<StatCard <StatCard
title={t('availableBalance', language)} title={t('availableBalance', language)}
value={`${account?.available_balance?.toFixed(2) || '0.00'}`} value={accountFailed && !account ? '--' : `${account?.available_balance?.toFixed(2) ?? '--'}`}
unit="USDT" unit="USDT"
subtitle={`${account?.available_balance && account?.total_equity ? ((account.available_balance / account.total_equity) * 100).toFixed(1) : '0.0'}% ${t('free', language)}`} subtitle={accountFailed && !account ? '--' : `${account?.available_balance && account?.total_equity ? ((account.available_balance / account.total_equity) * 100).toFixed(1) : '--'}% ${t('free', language)}`}
icon="💳" icon="💳"
loading={!account} loading={!account && !accountFailed}
/> />
<StatCard <StatCard
title={t('totalPnL', language)} title={t('totalPnL', language)}
value={`${account?.total_pnl !== undefined && account.total_pnl >= 0 ? '+' : ''}${account?.total_pnl?.toFixed(2) || '0.00'}`} value={accountFailed && !account ? '--' : `${account?.total_pnl !== undefined && account.total_pnl >= 0 ? '+' : ''}${account?.total_pnl?.toFixed(2) ?? '--'}`}
unit="USDT" unit="USDT"
change={account?.total_pnl_pct || 0} change={account ? (account.total_pnl_pct || 0) : undefined}
positive={(account?.total_pnl ?? 0) >= 0} positive={(account?.total_pnl ?? 0) >= 0}
icon="📈" icon="📈"
loading={!account} loading={!account && !accountFailed}
/> />
<StatCard <StatCard
title={t('positions', language)} title={t('positions', language)}
value={`${account?.position_count || 0}`} value={accountFailed && !account ? '--' : `${account?.position_count ?? '--'}`}
unit="ACTIVE" unit="ACTIVE"
subtitle={`${t('margin', language)}: ${account?.margin_used_pct?.toFixed(1) || '0.0'}%`} subtitle={accountFailed && !account ? `${t('margin', language)}: --` : `${t('margin', language)}: ${account?.margin_used_pct?.toFixed(1) ?? '--'}%`}
icon="📊" icon="📊"
loading={!account} loading={!account && !accountFailed}
/> />
</div> </div>