@@ -12,14 +12,16 @@ import { ProxyInfo } from '@/lib/pb/common'
12
12
import { Button } from '../ui/button'
13
13
import { CheckCircle2 , CircleX , RefreshCcw } from "lucide-react"
14
14
import { useTranslation } from 'react-i18next' ;
15
+ import TrafficStatsCard from './stats-item'
16
+ import { Separator } from '@radix-ui/react-separator'
17
+ import { formatBytes } from '@/lib/utils'
15
18
16
19
export interface ClientStatsCardProps {
17
20
clientID ?: string
18
21
}
19
22
export const ClientStatsCard : React . FC < ClientStatsCardProps > = ( { clientID : defaultClientID } : ClientStatsCardProps = { } ) => {
20
23
const { t } = useTranslation ( ) ;
21
24
const [ clientID , setClientID ] = useState < string | undefined > ( )
22
- const [ proxyName , setProxyName ] = useState < string | undefined > ( )
23
25
const [ status , setStatus ] = useState < "loading" | "success" | "error" | undefined > ( )
24
26
const [ timeoutId , setTimeoutId ] = useState < NodeJS . Timeout | null > ( null ) ;
25
27
@@ -69,11 +71,6 @@ export const ClientStatsCard: React.FC<ClientStatsCardProps> = ({ clientID: defa
69
71
return Array . from ( mergedMap . values ( ) ) ;
70
72
} ;
71
73
72
- function removeDuplicateCharacters ( input : string ) : string {
73
- const uniqueChars = new Set ( input ) ;
74
- return Array . from ( uniqueChars ) . join ( '' ) ;
75
- }
76
-
77
74
return (
78
75
< Card className = "w-full" >
79
76
< CardHeader >
@@ -88,18 +85,16 @@ export const ClientStatsCard: React.FC<ClientStatsCardProps> = ({ clientID: defa
88
85
< Label > { t ( 'client.stats.label' ) } </ Label >
89
86
< ClientSelector clientID = { clientID } setClientID = { handleClientChange } onOpenChange = { ( ) => {
90
87
refetchClientStats ( )
91
- setProxyName ( undefined )
92
88
} } />
93
89
< Label > { t ( 'proxy.stats.label' ) } </ Label >
94
- < ProxySelector
95
- // @ts -ignore
96
- proxyNames = { Array . from ( new Set ( clientStatsList ?. proxyInfos . map ( ( proxyInfo ) => proxyInfo . name ) . filter ( ( value ) => value !== undefined ) ) ) || [ ] }
97
- proxyName = { proxyName }
98
- setProxyname = { setProxyName } />
99
- < div className = "w-full grid gap-4 grid-cols-1" >
90
+ < div className = "w-full grid gap-2 grid-cols-1 overflow-x-auto" >
100
91
{ clientStatsList && clientStatsList . proxyInfos . length > 0 &&
101
- < ProxyStatusCard
102
- proxyInfo = { mergeProxyInfos ( clientStatsList . proxyInfos ) . find ( ( proxyInfo ) => proxyInfo . name === proxyName ) } /> }
92
+ clientStatsList . proxyInfos . map ( ( proxyInfo ) => {
93
+ return (
94
+ < ProxyStatusCard key = { proxyInfo . name } proxyInfo = { proxyInfo } />
95
+ )
96
+ } )
97
+ }
103
98
</ div >
104
99
</ CardContent >
105
100
< CardFooter >
@@ -135,21 +130,23 @@ const ProxyStatusCard: React.FC<{ proxyInfo: ProxyInfo | undefined }> = ({ proxy
135
130
}
136
131
137
132
return (
138
- < div key = { proxyInfo . name } className = "flex flex-col space-y-4 " >
133
+ < Card key = { proxyInfo . name } className = "flex flex-row gap-2 p-4 w-full min-w-[900px] shadow-none justify-between " >
139
134
< Label > { t ( 'proxy.stats.tunnel_traffic' , { name : proxyInfo . name } ) } </ Label >
140
- < ProxyTrafficOverview proxyInfo = { proxyInfo } />
141
- < div className = 'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4' >
142
- < ProxyTrafficPieChart
143
- title = { t ( 'proxy.stats.today_traffic_title' ) }
144
- chartLabel = { t ( 'proxy.stats.today_traffic_total' ) }
145
- trafficIn = { proxyInfo . todayTrafficIn || BigInt ( 0 ) }
146
- trafficOut = { proxyInfo . todayTrafficOut || BigInt ( 0 ) } />
147
- < ProxyTrafficPieChart
148
- title = { t ( 'proxy.stats.history_traffic_title' ) }
149
- chartLabel = { t ( 'proxy.stats.history_traffic_total' ) }
150
- trafficIn = { proxyInfo . historyTrafficIn || BigInt ( 0 ) }
151
- trafficOut = { proxyInfo . historyTrafficOut || BigInt ( 0 ) } />
152
- </ div >
153
- </ div >
135
+ < Separator orientation = "vertical" />
136
+ < ProxyTrafficField label = { t ( 'traffic.today.total' ) } value = { formatBytes ( Number ( proxyInfo . todayTrafficOut || BigInt ( 0 ) ) ) } />
137
+ < ProxyTrafficField label = { t ( 'traffic.today.inbound' ) } value = { formatBytes ( Number ( proxyInfo . todayTrafficIn || BigInt ( 0 ) ) ) } />
138
+ < ProxyTrafficField label = { t ( 'traffic.today.outbound' ) } value = { formatBytes ( Number ( proxyInfo . todayTrafficOut || BigInt ( 0 ) ) ) } />
139
+ < Separator orientation = "vertical" />
140
+ < ProxyTrafficField label = { t ( 'traffic.history.total' ) } value = { formatBytes ( Number ( proxyInfo . historyTrafficOut || BigInt ( 0 ) ) ) } />
141
+ < ProxyTrafficField label = { t ( 'traffic.history.inbound' ) } value = { formatBytes ( Number ( proxyInfo . historyTrafficIn || BigInt ( 0 ) ) ) } />
142
+ < ProxyTrafficField label = { t ( 'traffic.history.outbound' ) } value = { formatBytes ( Number ( proxyInfo . historyTrafficOut || BigInt ( 0 ) ) ) } />
143
+ </ Card >
154
144
) ;
145
+ }
146
+
147
+ const ProxyTrafficField = ( { label, value } : { label : string , value : string } ) => {
148
+ return < div className = "flex w-fit flex-col" >
149
+ < p className = "text-xs text-muted-foreground text-nowrap" > { label } </ p >
150
+ < div className = "flex items-center text-xs font-semibold text-nowrap" > { value } </ div >
151
+ </ div >
155
152
}
0 commit comments