Refactor usage panes to extract shared formatters and tables

Extract duplicated formatting utilities to a shared helper module. Move
the large, inline recent sessions tables into dedicated sub-components to
reduce duplication and simplify the parent pane components.
This commit is contained in:
Jinjing
2026-06-11 17:02:25 -07:00
parent 1735fda8ad
commit 4cffc3dde7
3 changed files with 9 additions and 316 deletions
@@ -25,8 +25,10 @@ import {
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/tooltip'
import { ClaudeUsageDailyChart } from './ClaudeUsageDailyChart'
import { ClaudeUsageLoadingState } from './ClaudeUsageLoadingState'
import { ClaudeUsageRecentSessionsTable } from './ClaudeUsageRecentSessionsTable'
import { ShareUsageButton } from './ShareUsageButton'
import { StatCard } from './StatCard'
import { formatCost, formatTokens, formatUpdatedAt } from './usage-formatters'
import { translate } from '@/i18n/i18n'
const RANGE_OPTIONS: ClaudeUsageRange[] = ['7d', '30d', '90d', 'all']
@@ -47,43 +49,6 @@ const RANGE_LABELS: Record<ClaudeUsageRange, string> = {
all: 'All time'
}
function formatTokens(value: number): string {
if (value >= 1_000_000) {
return `${(value / 1_000_000).toFixed(1)}M`
}
if (value >= 1_000) {
return `${(value / 1_000).toFixed(1)}k`
}
return value.toLocaleString()
}
function formatCost(value: number | null): string {
if (value === null) {
return 'n/a'
}
return value < 0.01 ? `$${value.toFixed(4)}` : `$${value.toFixed(2)}`
}
function formatUpdatedAt(timestamp: number | null): string {
if (!timestamp) {
return 'Not scanned yet'
}
return `Updated ${new Date(timestamp).toLocaleString()}`
}
function formatSessionTime(timestamp: string): string {
const parsed = new Date(timestamp)
if (Number.isNaN(parsed.getTime())) {
return timestamp
}
return parsed.toLocaleString(undefined, {
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: '2-digit'
})
}
export function ClaudeUsagePane(): React.JSX.Element {
const scanState = useAppStore((state) => state.claudeUsageScanState)
const summary = useAppStore((state) => state.claudeUsageSummary)
@@ -412,72 +377,7 @@ export function ClaudeUsagePane(): React.JSX.Element {
</section>
</div>
<section className="rounded-lg border border-border/60 bg-card/40 p-4">
<div className="mb-3">
<h4 className="text-sm font-semibold text-foreground">
{translate('auto.components.stats.ClaudeUsagePane.7e76c84153', 'Recent sessions')}
</h4>
<p className="text-xs text-muted-foreground">
{translate('auto.components.stats.ClaudeUsagePane.abfc4a4943', 'Cache reuse rate:')}{' '}
{summary?.cacheReuseRate !== null && summary?.cacheReuseRate !== undefined
? `${Math.round(summary.cacheReuseRate * 100)}%`
: translate('auto.components.stats.ClaudeUsagePane.7765a4c3e1', 'n/a')}
</p>
</div>
<div className="overflow-x-auto">
<table className="min-w-full text-sm">
<thead>
<tr className="border-b border-border/60 text-left text-xs text-muted-foreground">
<th className="px-2 py-2 font-medium">
{translate('auto.components.stats.ClaudeUsagePane.01476891c7', 'Last active')}
</th>
<th className="px-2 py-2 font-medium">
{translate('auto.components.stats.ClaudeUsagePane.c17bed0416', 'Project')}
</th>
<th className="px-2 py-2 font-medium">
{translate('auto.components.stats.ClaudeUsagePane.1afc25eb06', 'Model')}
</th>
<th className="px-2 py-2 font-medium">
{translate('auto.components.stats.ClaudeUsagePane.0f03975d59', 'Turns')}
</th>
<th className="px-2 py-2 font-medium">
{translate('auto.components.stats.ClaudeUsagePane.faf3444859', 'Input')}
</th>
<th className="px-2 py-2 font-medium">
{translate('auto.components.stats.ClaudeUsagePane.a8b7487ff7', 'Output')}
</th>
<th className="px-2 py-2 font-medium">
{translate('auto.components.stats.ClaudeUsagePane.21ea00bfa8', 'Cache')}
</th>
</tr>
</thead>
<tbody>
{recentSessions.map((row) => (
<tr key={row.sessionId} className="border-b border-border/40 last:border-b-0">
<td className="px-2 py-2 text-muted-foreground">
{formatSessionTime(row.lastActiveAt)}
</td>
<td className="px-2 py-2 text-foreground">{row.projectLabel}</td>
<td className="px-2 py-2 text-muted-foreground">
{row.model ??
translate('auto.components.stats.ClaudeUsagePane.cfe2282ffa', 'Unknown')}
</td>
<td className="px-2 py-2 text-muted-foreground">{row.turns}</td>
<td className="px-2 py-2 text-muted-foreground">
{formatTokens(row.inputTokens)}
</td>
<td className="px-2 py-2 text-muted-foreground">
{formatTokens(row.outputTokens)}
</td>
<td className="px-2 py-2 text-muted-foreground">
{formatTokens(row.cacheReadTokens + row.cacheWriteTokens)}
</td>
</tr>
))}
</tbody>
</table>
</div>
</section>
<ClaudeUsageRecentSessionsTable recentSessions={recentSessions} summary={summary} />
</>
)}
</div>
@@ -24,8 +24,10 @@ import {
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/tooltip'
import { ClaudeUsageLoadingState } from './ClaudeUsageLoadingState'
import { CodexUsageDailyChart } from './CodexUsageDailyChart'
import { CodexUsageRecentSessionsTable } from './CodexUsageRecentSessionsTable'
import { ShareUsageButton } from './ShareUsageButton'
import { StatCard } from './StatCard'
import { formatCost, formatTokens, formatUpdatedAt } from './usage-formatters'
import { translate } from '@/i18n/i18n'
const RANGE_OPTIONS: CodexUsageRange[] = ['7d', '30d', '90d', 'all']
@@ -46,43 +48,6 @@ const RANGE_LABELS: Record<CodexUsageRange, string> = {
all: 'All time'
}
function formatTokens(value: number): string {
if (value >= 1_000_000) {
return `${(value / 1_000_000).toFixed(1)}M`
}
if (value >= 1_000) {
return `${(value / 1_000).toFixed(1)}k`
}
return value.toLocaleString()
}
function formatCost(value: number | null): string {
if (value === null) {
return 'n/a'
}
return value < 0.01 ? `$${value.toFixed(4)}` : `$${value.toFixed(2)}`
}
function formatUpdatedAt(timestamp: number | null): string {
if (!timestamp) {
return 'Not scanned yet'
}
return `Updated ${new Date(timestamp).toLocaleString()}`
}
function formatSessionTime(timestamp: string): string {
const parsed = new Date(timestamp)
if (Number.isNaN(parsed.getTime())) {
return timestamp
}
return parsed.toLocaleString(undefined, {
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: '2-digit'
})
}
export function CodexUsagePane(): React.JSX.Element {
const scanState = useAppStore((state) => state.codexUsageScanState)
const summary = useAppStore((state) => state.codexUsageSummary)
@@ -396,73 +361,7 @@ export function CodexUsagePane(): React.JSX.Element {
</section>
</div>
<section className="rounded-lg border border-border/60 bg-card/40 p-4">
<div className="mb-3">
<h4 className="text-sm font-semibold text-foreground">
{translate('auto.components.stats.CodexUsagePane.0cb0983c07', 'Recent sessions')}
</h4>
<p className="text-xs text-muted-foreground">
{translate(
'auto.components.stats.CodexUsagePane.0bd8655475',
'Most recent local Codex sessions in this scope.'
)}
</p>
</div>
<div className="overflow-x-auto">
<table className="min-w-full text-sm">
<thead>
<tr className="border-b border-border/60 text-left text-xs text-muted-foreground">
<th className="px-2 py-2 font-medium">
{translate('auto.components.stats.CodexUsagePane.0c36b100be', 'Last active')}
</th>
<th className="px-2 py-2 font-medium">
{translate('auto.components.stats.CodexUsagePane.1a65900aea', 'Project')}
</th>
<th className="px-2 py-2 font-medium">
{translate('auto.components.stats.CodexUsagePane.c2478bcc3c', 'Model')}
</th>
<th className="px-2 py-2 font-medium">
{translate('auto.components.stats.CodexUsagePane.bd0822ca47', 'Events')}
</th>
<th className="px-2 py-2 font-medium">
{translate('auto.components.stats.CodexUsagePane.3acc582214', 'Input')}
</th>
<th className="px-2 py-2 font-medium">
{translate('auto.components.stats.CodexUsagePane.bbd20344b8', 'Output')}
</th>
<th className="px-2 py-2 font-medium">
{translate('auto.components.stats.CodexUsagePane.e0b988599d', 'Total')}
</th>
</tr>
</thead>
<tbody>
{recentSessions.map((row) => (
<tr key={row.sessionId} className="border-b border-border/40 last:border-b-0">
<td className="px-2 py-2 text-muted-foreground">
{formatSessionTime(row.lastActiveAt)}
</td>
<td className="px-2 py-2 text-foreground">{row.projectLabel}</td>
<td className="px-2 py-2 text-muted-foreground">
{row.model ??
translate('auto.components.stats.CodexUsagePane.bf6cf2d4dd', 'Unknown')}
{row.hasInferredPricing ? ' *' : ''}
</td>
<td className="px-2 py-2 text-muted-foreground">{row.events}</td>
<td className="px-2 py-2 text-muted-foreground">
{formatTokens(row.inputTokens)}
</td>
<td className="px-2 py-2 text-muted-foreground">
{formatTokens(row.outputTokens)}
</td>
<td className="px-2 py-2 text-muted-foreground">
{formatTokens(row.totalTokens)}
</td>
</tr>
))}
</tbody>
</table>
</div>
</section>
<CodexUsageRecentSessionsTable recentSessions={recentSessions} />
</>
)}
</div>
@@ -27,7 +27,9 @@ import {
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/tooltip'
import { ClaudeUsageLoadingState } from './ClaudeUsageLoadingState'
import { CodexUsageDailyChart } from './CodexUsageDailyChart'
import { OpenCodeUsageRecentSessionsTable } from './OpenCodeUsageRecentSessionsTable'
import { StatCard } from './StatCard'
import { formatCost, formatTokens, formatUpdatedAt } from './usage-formatters'
import { translate } from '@/i18n/i18n'
const RANGE_OPTIONS: OpenCodeUsageRange[] = ['7d', '30d', '90d', 'all']
@@ -51,43 +53,6 @@ const RANGE_LABELS: Record<OpenCodeUsageRange, string> = {
all: 'All time'
}
function formatTokens(value: number): string {
if (value >= 1_000_000) {
return `${(value / 1_000_000).toFixed(1)}M`
}
if (value >= 1_000) {
return `${(value / 1_000).toFixed(1)}k`
}
return value.toLocaleString()
}
function formatCost(value: number | null): string {
if (value === null) {
return 'n/a'
}
return value < 0.01 ? `$${value.toFixed(4)}` : `$${value.toFixed(2)}`
}
function formatUpdatedAt(timestamp: number | null): string {
if (!timestamp) {
return 'Not scanned yet'
}
return `Updated ${new Date(timestamp).toLocaleString()}`
}
function formatSessionTime(timestamp: string): string {
const parsed = new Date(timestamp)
if (Number.isNaN(parsed.getTime())) {
return timestamp
}
return parsed.toLocaleString(undefined, {
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: '2-digit'
})
}
export function OpenCodeUsagePane(): React.JSX.Element {
const scanState = useAppStore((state) => state.openCodeUsageScanState)
const summary = useAppStore((state) => state.openCodeUsageSummary)
@@ -422,78 +387,7 @@ export function OpenCodeUsagePane(): React.JSX.Element {
</section>
</div>
<section className="rounded-lg border border-border/60 bg-card/40 p-4">
<div className="mb-3">
<h4 className="text-sm font-semibold text-foreground">
{translate('auto.components.stats.OpenCodeUsagePane.4799177b1c', 'Recent sessions')}
</h4>
<p className="text-xs text-muted-foreground">
{translate(
'auto.components.stats.OpenCodeUsagePane.81817a641a',
'Most recent local OpenCode sessions in this scope.'
)}
</p>
</div>
<div className="overflow-x-auto">
<table className="min-w-full text-sm">
<thead>
<tr className="border-b border-border/60 text-left text-xs text-muted-foreground">
<th className="px-2 py-2 font-medium">
{translate(
'auto.components.stats.OpenCodeUsagePane.d97bdf6e27',
'Last active'
)}
</th>
<th className="px-2 py-2 font-medium">
{translate('auto.components.stats.OpenCodeUsagePane.a4738de041', 'Project')}
</th>
<th className="px-2 py-2 font-medium">
{translate('auto.components.stats.OpenCodeUsagePane.08c78441b7', 'Model')}
</th>
<th className="px-2 py-2 font-medium">
{translate('auto.components.stats.OpenCodeUsagePane.d416f5cf92', 'Events')}
</th>
<th className="px-2 py-2 font-medium">
{translate('auto.components.stats.OpenCodeUsagePane.0f2f266c9d', 'Input')}
</th>
<th className="px-2 py-2 font-medium">
{translate('auto.components.stats.OpenCodeUsagePane.dfc4513657', 'Output')}
</th>
<th className="px-2 py-2 font-medium">
{translate('auto.components.stats.OpenCodeUsagePane.349f7c3f5c', 'Total')}
</th>
</tr>
</thead>
<tbody>
{recentSessions.map((row) => (
<tr key={row.sessionId} className="border-b border-border/40 last:border-b-0">
<td className="px-2 py-2 text-muted-foreground">
{formatSessionTime(row.lastActiveAt)}
</td>
<td className="px-2 py-2 text-foreground">{row.projectLabel}</td>
<td className="px-2 py-2 text-muted-foreground">
{row.model ??
translate(
'auto.components.stats.OpenCodeUsagePane.362231082f',
'Unknown'
)}
</td>
<td className="px-2 py-2 text-muted-foreground">{row.events}</td>
<td className="px-2 py-2 text-muted-foreground">
{formatTokens(row.inputTokens)}
</td>
<td className="px-2 py-2 text-muted-foreground">
{formatTokens(row.outputTokens)}
</td>
<td className="px-2 py-2 text-muted-foreground">
{formatTokens(row.totalTokens)}
</td>
</tr>
))}
</tbody>
</table>
</div>
</section>
<OpenCodeUsageRecentSessionsTable recentSessions={recentSessions} />
</>
)}
</div>