|
| 1 | +'use client'; |
| 2 | + |
| 3 | +import React from 'react'; |
| 4 | +import { Cpu } from 'lucide-react'; |
| 5 | +import { SystemStatsType } from '@/redux/types/monitor'; |
| 6 | +import { TypographySmall, TypographyMuted } from '@/components/ui/typography'; |
| 7 | +import { BarChartComponent } from '@/components/ui/bar-chart-component'; |
| 8 | +import { SystemMetricCard } from './system-metric-card'; |
| 9 | +import { useSystemMetric } from '../../hooks/use-system-metric'; |
| 10 | +import { createCPUChartData, createCPUChartConfig, formatPercentage } from '../utils/utils'; |
| 11 | +import { DEFAULT_METRICS, CHART_COLORS } from '../utils/constants'; |
| 12 | +import { CPUUsageCardSkeletonContent } from './skeletons/cpu-usage'; |
| 13 | + |
| 14 | +interface CPUUsageCardProps { |
| 15 | + systemStats: SystemStatsType | null; |
| 16 | +} |
| 17 | + |
| 18 | +interface CPUUsageHeaderProps { |
| 19 | + overallUsage: number; |
| 20 | + label: string; |
| 21 | +} |
| 22 | + |
| 23 | +interface CPUUsageChartProps { |
| 24 | + chartData: ReturnType<typeof createCPUChartData>; |
| 25 | + chartConfig: ReturnType<typeof createCPUChartConfig>; |
| 26 | + yAxisLabel: string; |
| 27 | + xAxisLabel: string; |
| 28 | +} |
| 29 | + |
| 30 | +interface TopCoresListProps { |
| 31 | + cores: Array<{ core_id: number; usage: number }>; |
| 32 | +} |
| 33 | + |
| 34 | +interface CoreItemProps { |
| 35 | + coreId: number; |
| 36 | + usage: number; |
| 37 | + color: string; |
| 38 | +} |
| 39 | + |
| 40 | +const CPU_COLORS = [ |
| 41 | + CHART_COLORS.blue, |
| 42 | + CHART_COLORS.green, |
| 43 | + CHART_COLORS.orange, |
| 44 | + CHART_COLORS.purple, |
| 45 | + CHART_COLORS.red, |
| 46 | + CHART_COLORS.yellow, |
| 47 | +]; |
| 48 | + |
| 49 | +const CPUUsageHeader: React.FC<CPUUsageHeaderProps> = ({ overallUsage, label }) => { |
| 50 | + return ( |
| 51 | + <div className="text-center"> |
| 52 | + <TypographyMuted className="text-xs">{label}</TypographyMuted> |
| 53 | + <div className="text-3xl font-bold text-primary mt-1"> |
| 54 | + {formatPercentage(overallUsage)}% |
| 55 | + </div> |
| 56 | + </div> |
| 57 | + ); |
| 58 | +}; |
| 59 | + |
| 60 | +const CPUUsageChart: React.FC<CPUUsageChartProps> = ({ |
| 61 | + chartData, |
| 62 | + chartConfig, |
| 63 | + yAxisLabel, |
| 64 | + xAxisLabel, |
| 65 | +}) => { |
| 66 | + return ( |
| 67 | + <div> |
| 68 | + <BarChartComponent |
| 69 | + data={chartData} |
| 70 | + chartConfig={chartConfig} |
| 71 | + height="h-[180px]" |
| 72 | + yAxisLabel={yAxisLabel} |
| 73 | + xAxisLabel={xAxisLabel} |
| 74 | + showAxisLabels={true} |
| 75 | + /> |
| 76 | + </div> |
| 77 | + ); |
| 78 | +}; |
| 79 | + |
| 80 | +const CoreItem: React.FC<CoreItemProps> = ({ coreId, usage, color }) => { |
| 81 | + return ( |
| 82 | + <div className="flex flex-col items-center gap-1"> |
| 83 | + <div className="flex items-center gap-1"> |
| 84 | + <div className="h-2 w-2 rounded-full" style={{ backgroundColor: color }} /> |
| 85 | + <TypographyMuted className="text-xs">Core {coreId}</TypographyMuted> |
| 86 | + </div> |
| 87 | + <TypographySmall className="text-sm font-bold"> |
| 88 | + {formatPercentage(usage)}% |
| 89 | + </TypographySmall> |
| 90 | + </div> |
| 91 | + ); |
| 92 | +}; |
| 93 | + |
| 94 | +const TopCoresList: React.FC<TopCoresListProps> = ({ cores }) => { |
| 95 | + return ( |
| 96 | + <div className="grid grid-cols-3 gap-2 text-center"> |
| 97 | + {cores.map((core) => { |
| 98 | + const color = CPU_COLORS[core.core_id % CPU_COLORS.length]; |
| 99 | + return ( |
| 100 | + <CoreItem |
| 101 | + key={core.core_id} |
| 102 | + coreId={core.core_id} |
| 103 | + usage={core.usage} |
| 104 | + color={color} |
| 105 | + /> |
| 106 | + ); |
| 107 | + })} |
| 108 | + </div> |
| 109 | + ); |
| 110 | +}; |
| 111 | + |
| 112 | +const CPUUsageCard: React.FC<CPUUsageCardProps> = ({ systemStats }) => { |
| 113 | + const { data: cpu, isLoading, t } = useSystemMetric({ |
| 114 | + systemStats, |
| 115 | + extractData: (stats) => stats.cpu, |
| 116 | + defaultData: DEFAULT_METRICS.cpu, |
| 117 | + }); |
| 118 | + |
| 119 | + const perCoreData = cpu.per_core; |
| 120 | + const chartData = createCPUChartData(perCoreData); |
| 121 | + const chartConfig = createCPUChartConfig(perCoreData.length); |
| 122 | + const topCores = [...perCoreData].sort((a, b) => b.usage - a.usage).slice(0, 3); |
| 123 | + |
| 124 | + return ( |
| 125 | + <SystemMetricCard |
| 126 | + title={t('dashboard.cpu.title')} |
| 127 | + icon={Cpu} |
| 128 | + isLoading={isLoading} |
| 129 | + skeletonContent={<CPUUsageCardSkeletonContent />} |
| 130 | + > |
| 131 | + <div className="space-y-4"> |
| 132 | + <CPUUsageHeader |
| 133 | + overallUsage={cpu.overall} |
| 134 | + label={t('dashboard.cpu.overall')} |
| 135 | + /> |
| 136 | + |
| 137 | + <CPUUsageChart |
| 138 | + chartData={chartData} |
| 139 | + chartConfig={chartConfig} |
| 140 | + yAxisLabel={t('dashboard.cpu.usage')} |
| 141 | + xAxisLabel={t('dashboard.cpu.cores')} |
| 142 | + /> |
| 143 | + |
| 144 | + <TopCoresList cores={topCores} /> |
| 145 | + </div> |
| 146 | + </SystemMetricCard> |
| 147 | + ); |
| 148 | +}; |
| 149 | + |
| 150 | +export default CPUUsageCard; |
0 commit comments