refactor(web): Overview usage reuses WalletStatsCard (same as 模型与余额)

The wallet page already renders Current Balance / Total Usage / API Requests
from /api/user/self. Reuse that exact component (WalletStatsCard) on the
Overview instead of a hand-written block — DRY, identical numbers
($160.47 / $39.53 / 521 for the current user).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-03 11:08:45 +08:00
co-authored by Claude Opus 4.8
parent 42883dac63
commit 0eb754b1e1
@@ -3,32 +3,30 @@ import { useQuery } from '@tanstack/react-query'
import { Link } from '@tanstack/react-router'
import { useTranslation } from 'react-i18next'
import {
Activity,
AlertTriangle,
ArrowUpRight,
Building2,
CheckCircle2,
CircleDashed,
Coins,
PlayCircle,
Rocket,
ScrollText,
Wallet,
} from 'lucide-react'
import { api } from '@/lib/api'
import { formatQuota } from '@/lib/format'
import { cn } from '@/lib/utils'
import { Button } from '@/components/ui/button'
import {
listAgentDeployments,
type AgentDeployment,
} from '@/features/agent-console/api'
import { WalletStatsCard } from '@/features/wallet/components/wallet-stats-card'
import type { UserWalletData } from '@/features/wallet/types'
// Current user's own lifetime usage (NOT the admin-global aggregate).
type SelfUsage = { quota?: number; used_quota?: number; request_count?: number }
async function getSelfUsage(): Promise<SelfUsage> {
const res = await api.get<{ data?: SelfUsage }>('/api/user/self')
return res.data?.data ?? {}
// Current user's OWN balance/usage (NOT the admin-global aggregate) — same
// source the 模型与余额 page uses.
async function getSelfUsage(): Promise<UserWalletData> {
const res = await api.get<{ data?: UserWalletData }>('/api/user/self')
return res.data?.data ?? ({} as UserWalletData)
}
type StatusKey = 'running' | 'success' | 'failed' | 'pending'
@@ -162,7 +160,6 @@ export function CockpitView() {
refetchInterval: 60_000,
retry: false,
})
const self = selfQuery.data ?? {}
const stats = useMemo(() => {
const list: AgentDeployment[] = deploymentsQuery.data ?? []
@@ -238,29 +235,10 @@ export function CockpitView() {
<p className='text-muted-foreground mb-2 text-[11px] font-semibold tracking-[0.16em] uppercase'>
{t('Usage & cost')}
</p>
<div className='grid grid-cols-2 gap-3 lg:grid-cols-3'>
<StatCard
label={t('Used')}
value={formatQuota(self.used_quota ?? 0)}
hint={t('Your total spend so far')}
icon={Coins}
tone='primary'
<WalletStatsCard
user={selfQuery.data ?? null}
loading={selfQuery.isLoading}
/>
<StatCard
label={t('Remaining quota')}
value={formatQuota(self.quota ?? 0)}
hint={t('Balance available')}
icon={Wallet}
tone='success'
/>
<StatCard
label={t('Requests')}
value={String(self.request_count ?? 0)}
hint={t('Your total requests')}
icon={Activity}
tone='warn'
/>
</div>
</div>
{/* Tier 2: Stream */}