@@ -8,24 +8,19 @@ import { useTranslations } from 'next-intl';
88import { formatCount , formatMoney } from '@/lib/utils' ;
99import dayjs from 'dayjs' ;
1010import { AnimatedNumber } from '@/components/common/AnimatedNumber' ;
11- import { Tabs , TabsList , TabsTrigger , TabsContents , TabsContent } from '@/components/animate-ui/components/animate/tabs' ;
12- import { useToolbarViewOptionsStore , type ChartMetricType } from '@/components/modules/toolbar/view-options-store' ;
13-
14- const PERIODS = [ '1' , '7' , '30' ] as const ;
15- const METRIC_TYPES : ChartMetricType [ ] = [ 'cost' , 'count' , 'tokens' ] ;
11+ import { Tabs , TabsList , TabsTrigger } from '@/components/animate-ui/components/animate/tabs' ;
12+ import { useHomeViewStore , type ChartMetricType , type ChartPeriod } from '@/components/modules/home/store' ;
1613
1714export function StatsChart ( ) {
15+ const PERIODS : readonly ChartPeriod [ ] = [ '1' , '7' , '30' ] ;
1816 const { data : statsDaily } = useStatsDaily ( ) ;
1917 const { data : statsHourly } = useStatsHourly ( ) ;
2018 const t = useTranslations ( 'home.chart' ) ;
21-
22- const chartMetricType = useToolbarViewOptionsStore ( ( state ) => state . chartMetricType ) ;
23- const setChartMetricType = useToolbarViewOptionsStore ( ( state ) => state . setChartMetricType ) ;
24- const period = useToolbarViewOptionsStore ( ( state ) => {
25- if ( ! state . chartPeriod ) return '1' ;
26- return state . chartPeriod ;
27- } ) ;
28- const setChartPeriod = useToolbarViewOptionsStore ( ( state ) => state . setChartPeriod ) ;
19+
20+ const chartMetricType = useHomeViewStore ( ( state ) => state . chartMetricType ) ;
21+ const setChartMetricType = useHomeViewStore ( ( state ) => state . setChartMetricType ) ;
22+ const period = useHomeViewStore ( ( state ) => state . chartPeriod ) ;
23+ const setChartPeriod = useHomeViewStore ( ( state ) => state . setChartPeriod ) ;
2924
3025 const sortedDaily = useMemo ( ( ) => {
3126 if ( ! statsDaily ) return [ ] ;
@@ -42,51 +37,49 @@ export function StatsChart() {
4237 if ( ! statsHourly ) return [ ] ;
4338 return statsHourly . map ( ( stat ) => ( {
4439 date : `${ stat . hour } :00` ,
45- [ dataKey ] : chartMetricType === 'cost'
46- ? stat . total_cost . raw
40+ [ dataKey ] : chartMetricType === 'cost'
41+ ? stat . total_cost . raw
4742 : chartMetricType === 'count'
48- ? stat . request_count . raw
49- : ( stat . input_token . raw + stat . output_token . raw ) ,
43+ ? stat . request_count . raw
44+ : ( stat . input_token . raw + stat . output_token . raw ) ,
5045 } ) ) ;
5146 } else {
52- const days = parseInt ( period ) ;
47+ const days = Number ( period ) ;
5348 return sortedDaily . slice ( - days ) . map ( ( stat ) => ( {
5449 date : dayjs ( stat . date ) . format ( 'MM/DD' ) ,
5550 [ dataKey ] : chartMetricType === 'cost'
5651 ? stat . total_cost . raw
5752 : chartMetricType === 'count'
58- ? ( stat . request_success . raw + stat . request_failed . raw )
59- : ( stat . input_token . raw + stat . output_token . raw ) ,
53+ ? ( stat . request_success . raw + stat . request_failed . raw )
54+ : ( stat . input_token . raw + stat . output_token . raw ) ,
6055 } ) ) ;
6156 }
6257 } , [ sortedDaily , statsHourly , period , chartMetricType ] ) ;
6358
6459 const totals = useMemo ( ( ) => {
6560 if ( period === '1' ) {
66- if ( ! statsHourly ) return { primary : 0 , requests : 0 , cost : 0 , tokens : 0 } ;
61+ if ( ! statsHourly ) return { requests : 0 , cost : 0 , tokens : 0 } ;
6762 const requests = statsHourly . reduce ( ( acc , stat ) => acc + stat . request_count . raw , 0 ) ;
6863 const cost = statsHourly . reduce ( ( acc , stat ) => acc + stat . total_cost . raw , 0 ) ;
6964 const tokens = statsHourly . reduce ( ( acc , stat ) => acc + stat . input_token . raw + stat . output_token . raw , 0 ) ;
7065 return {
71- primary : chartMetricType === 'cost' ? cost : chartMetricType === 'count' ? requests : tokens ,
7266 requests,
7367 cost,
7468 tokens,
7569 } ;
7670 } else {
77- const days = parseInt ( period ) ;
71+ const days = Number ( period ) ;
7872 const recentStats = sortedDaily . slice ( - days ) ;
7973 const requests = recentStats . reduce ( ( acc , stat ) => acc + stat . request_success . raw + stat . request_failed . raw , 0 ) ;
8074 const cost = recentStats . reduce ( ( acc , stat ) => acc + stat . total_cost . raw , 0 ) ;
8175 const tokens = recentStats . reduce ( ( acc , stat ) => acc + stat . input_token . raw + stat . output_token . raw , 0 ) ;
8276 return {
83- primary : chartMetricType === 'cost' ? cost : chartMetricType === 'count' ? requests : tokens ,
8477 requests,
8578 cost,
8679 tokens,
8780 } ;
8881 }
89- } , [ sortedDaily , statsHourly , period , chartMetricType ] ) ;
82+ } , [ sortedDaily , statsHourly , period ] ) ;
9083
9184 const chartConfig = useMemo ( ( ) => {
9285 const dataKey = getChartDataKey ( chartMetricType ) ;
@@ -100,7 +93,7 @@ export function StatsChart() {
10093 } ;
10194 } , [ chartMetricType , t ] ) ;
10295
103- const getPeriodLabel = ( p : typeof period ) => {
96+ const getPeriodLabel = ( p : ChartPeriod ) => {
10497 const labels = {
10598 '1' : t ( 'period.today' ) ,
10699 '7' : t ( 'period.last7Days' ) ,
@@ -109,26 +102,13 @@ export function StatsChart() {
109102 return labels [ p ] ;
110103 } ;
111104
112- const getMetricLabel = ( type : ChartMetricType ) => {
113- const labels = {
114- 'cost' : t ( 'metricType.cost' ) ,
115- 'count' : t ( 'metricType.count' ) ,
116- 'tokens' : t ( 'metricType.tokens' ) ,
117- } ;
118- return labels [ type ] ;
119- } ;
120105
121106 const handlePeriodClick = ( ) => {
122- const currentIndex = PERIODS . indexOf ( period as typeof PERIODS [ number ] ) ;
107+ const currentIndex = PERIODS . indexOf ( period ) ;
123108 const nextIndex = ( currentIndex + 1 ) % PERIODS . length ;
124109 setChartPeriod ( PERIODS [ nextIndex ] ) ;
125110 } ;
126111
127- const getMetricValue = ( type : ChartMetricType ) => {
128- if ( type === 'cost' ) return formatMoney ( totals . cost ) ;
129- if ( type === 'count' ) return formatCount ( totals . requests ) ;
130- return formatCount ( totals . tokens ) ;
131- } ;
132112
133113 const getChartStroke = ( type : ChartMetricType ) => {
134114 if ( type === 'cost' ) return 'var(--chart-1)' ;
@@ -144,8 +124,7 @@ export function StatsChart() {
144124
145125 return (
146126 < div className = "rounded-3xl bg-card border-card-border border pt-4 pb-0 text-card-foreground custom-shadow" >
147- < div className = "px-4 pb-2 space-y-4" >
148- { /* 第一行:标题 + 类型选择 */ }
127+ < div className = "px-4 pb-2 space-y-2" >
149128 < div className = "flex justify-between items-center" >
150129 < h3 className = "font-semibold text-base" > { t ( 'title' ) } </ h3 >
151130 < Tabs value = { chartMetricType } onValueChange = { ( value ) => setChartMetricType ( value as ChartMetricType ) } >
@@ -156,7 +135,7 @@ export function StatsChart() {
156135 </ TabsList >
157136 </ Tabs >
158137 </ div >
159-
138+
160139 { /* 第二行:汇总统计 + 周期选择 */ }
161140 < div className = "flex justify-between items-start" >
162141 < div className = "flex gap-2 text-sm" >
@@ -190,7 +169,7 @@ export function StatsChart() {
190169 >
191170 < div >
192171 < div className = "text-xs text-muted-foreground" > { t ( 'timePeriod' ) } </ div >
193- < div className = "text-base font-semibold" > { getPeriodLabel ( period as typeof PERIODS [ number ] ) } </ div >
172+ < div className = "text-base font-semibold" > { getPeriodLabel ( period ) } </ div >
194173 </ div >
195174 </ div >
196175 </ div >
@@ -228,11 +207,11 @@ export function StatsChart() {
228207 } }
229208 />
230209 < ChartTooltip cursor = { false } content = { < ChartTooltipContent indicator = "line" /> } />
231- < Area
232- type = "monotone"
233- dataKey = { getChartDataKey ( chartMetricType ) }
234- stroke = { getChartStroke ( chartMetricType ) }
235- fill = { getChartFill ( chartMetricType ) }
210+ < Area
211+ type = "monotone"
212+ dataKey = { getChartDataKey ( chartMetricType ) }
213+ stroke = { getChartStroke ( chartMetricType ) }
214+ fill = { getChartFill ( chartMetricType ) }
236215 />
237216 </ AreaChart >
238217 </ ChartContainer >
0 commit comments