fix(dashboard): handle nested API response shapes for trades and system-health

Backend wraps data in extra layer:
  system-health   → {code:0, data:{services:[...]}}
  realtime-trades → {code:0, data:{items:[...], total:N}}

HttpClient strips outer data but leaves inner object.
Fix: type as {services/items} and access nested arrays.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-03-06 11:34:49 -08:00
parent 45a69491d7
commit 5d9e1f7d06
1 changed files with 6 additions and 4 deletions

View File

@ -46,8 +46,10 @@ const loadingBox: React.CSSProperties = {
export const DashboardPage: React.FC = () => { export const DashboardPage: React.FC = () => {
const { data: statsData, isLoading: statsLoading, error: statsError } = useApi<DashboardStats>('/api/v1/admin/dashboard/stats'); const { data: statsData, isLoading: statsLoading, error: statsError } = useApi<DashboardStats>('/api/v1/admin/dashboard/stats');
const { data: tradesData, isLoading: tradesLoading } = useApi<RealtimeTrade[]>('/api/v1/admin/dashboard/realtime-trades'); const { data: tradesResp, isLoading: tradesLoading } = useApi<{ items: RealtimeTrade[]; total: number }>('/api/v1/admin/dashboard/realtime-trades');
const { data: healthData, isLoading: healthLoading } = useApi<ServiceHealth[]>('/api/v1/admin/dashboard/system-health'); const { data: healthResp, isLoading: healthLoading } = useApi<{ services: ServiceHealth[] }>('/api/v1/admin/dashboard/system-health');
const tradesData = tradesResp?.items ?? [];
const healthData = healthResp?.services ?? [];
const formatNumber = (n: number) => n?.toLocaleString() ?? '-'; const formatNumber = (n: number) => n?.toLocaleString() ?? '-';
const formatCurrency = (n: number) => `$${n?.toLocaleString() ?? '0'}`; const formatCurrency = (n: number) => `$${n?.toLocaleString() ?? '0'}`;
@ -185,7 +187,7 @@ export const DashboardPage: React.FC = () => {
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{(tradesData ?? []).map((row, i) => ( {tradesData.map((row, i) => (
<tr key={i} style={{ borderBottom: '1px solid var(--color-border-light)' }}> <tr key={i} style={{ borderBottom: '1px solid var(--color-border-light)' }}>
<td style={{ font: 'var(--text-body-sm)', color: 'var(--color-text-tertiary)', padding: '10px 12px' }}>{row.time}</td> <td style={{ font: 'var(--text-body-sm)', color: 'var(--color-text-tertiary)', padding: '10px 12px' }}>{row.time}</td>
<td style={{ font: 'var(--text-label-sm)', padding: '10px 12px' }}>{row.type}</td> <td style={{ font: 'var(--text-label-sm)', padding: '10px 12px' }}>{row.type}</td>
@ -219,7 +221,7 @@ export const DashboardPage: React.FC = () => {
<div style={{ font: 'var(--text-h3)', marginBottom: 16 }}>{t('dashboard_system_health')}</div> <div style={{ font: 'var(--text-h3)', marginBottom: 16 }}>{t('dashboard_system_health')}</div>
{healthLoading ? ( {healthLoading ? (
<div style={loadingBox}>Loading...</div> <div style={loadingBox}>Loading...</div>
) : (healthData ?? []).map(service => ( ) : healthData.map(service => (
<div key={service.name} style={{ <div key={service.name} style={{
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',