Files
aerbim-ht-monitor/frontend/components/dashboard/DetectorChart.tsx

138 lines
3.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client'
import React from 'react'
interface DetectorDataPoint {
value: number
label?: string
timestamp?: string
status?: string
}
interface DetectorChartProps {
className?: string
data?: DetectorDataPoint[]
type?: 'line' | 'bar'
}
const DetectorChart: React.FC<DetectorChartProps> = ({
className = '',
data,
type = 'line'
}) => {
if (type === 'bar') {
const defaultBarData = [
{ value: 85, label: 'Янв' },
{ value: 70, label: 'Фев' },
{ value: 90, label: 'Мар' },
{ value: 65, label: 'Апр' },
{ value: 80, label: 'Май' },
{ value: 95, label: 'Июн' }
]
const barData = (Array.isArray(data) && data.length > 0)
? data.slice(0, 6).map((d, i) => ({
value: d.value || 0,
label: d.label || defaultBarData[i]?.label || `${i + 1}`
}))
: defaultBarData
return (
<div className={`w-full h-full ${className}`}>
<svg className="w-full h-full" viewBox="0 0 400 200">
<g>
{barData.map((bar, index) => {
const barWidth = 50
const barSpacing = 15
const x = index * (barWidth + barSpacing) + 20
const barHeight = (bar.value / 100) * 150
const y = 160 - barHeight
return (
<g key={index}>
<rect
x={x}
y={y}
width={barWidth}
height={barHeight}
fill="rgb(42, 157, 144)"
rx="4"
ry="4"
/>
<text
x={x + barWidth / 2}
y={180}
textAnchor="middle"
fill="#71717a"
fontSize="12"
>
{bar.label}
</text>
</g>
)
})}
</g>
</svg>
</div>
)
}
// Line chart implementation
const defaultLineData = [
{ value: 150 },
{ value: 120 },
{ value: 100 },
{ value: 80 },
{ value: 90 },
{ value: 70 },
{ value: 60 }
]
const lineData = (Array.isArray(data) && data.length > 0)
? data.slice(0, 7)
: defaultLineData
const maxVal = Math.max(...lineData.map(d => d.value || 0), 1)
const width = 400
const height = 200
const padding = 20
const plotHeight = height - 40
const stepX = lineData.length > 1 ? (width - 2 * padding) / (lineData.length - 1) : 0
const points = lineData.map((d, i) => {
const x = padding + i * stepX
const y = height - padding - ((d.value || 0) / maxVal) * plotHeight
return { x, y }
})
const linePath = points.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x},${p.y}`).join(' ')
const areaPath = `${linePath} L${width - padding},${height - padding} L${padding},${height - padding} Z`
return (
<div className={`w-full h-full ${className}`}>
<svg className="w-full h-full" viewBox={`0 0 ${width} ${height}`}>
<defs>
<linearGradient id="detectorGradient" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor="rgb(231, 110, 80)" stopOpacity="0.3" />
<stop offset="100%" stopColor="rgb(231, 110, 80)" stopOpacity="0" />
</linearGradient>
</defs>
<path
d={areaPath}
fill="url(#detectorGradient)"
/>
<path
d={linePath}
stroke="rgb(231, 110, 80)"
strokeWidth="2"
fill="none"
/>
{points.map((p, i) => (
<circle key={i} cx={p.x} cy={p.y} r="3" fill="rgb(231, 110, 80)" />
))}
</svg>
</div>
)
}
export default DetectorChart