/
zemars
/
it-dashboard
Обзор
Документация
Войти
/
zemars
/
it-dashboard
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
develop
frontend/src/components/TrendLineChart/TrendLineChart.jsx
80 строк
3 KB
Дмитрий
fix(docs): актуализировать risk_log и docstring init_db
26 май 2026, 22:07
26 май 2026, 22:07
9981d43
Код
Авторство
О чём код?
// Автор: Максим Учайкин — линейный график "Динамика тикетов". // Двойная Y-ось: количество тикетов и % нарушений. // Переключатель день/неделя — снаружи (родитель управляет). import { CartesianGrid, Legend, Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis, } from 'recharts' export default function TrendLineChart({ data, loading, groupBy, onGroupByChange }) { return ( <div className="card"> <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}> <h3 className="section-title" style={{ margin: 0 }}>Динамика тикетов</h3> <div style={{ display: 'flex', gap: 6 }}> <button className={`btn btn-secondary ${groupBy === 'day' ? '' : 'btn-ghost'}`} style={{ padding: '4px 10px', fontSize: 12 }} onClick={() => onGroupByChange('day')} type="button" > По дням </button> <button className={`btn btn-secondary ${groupBy === 'week' ? '' : 'btn-ghost'}`} style={{ padding: '4px 10px', fontSize: 12 }} onClick={() => onGroupByChange('week')} type="button" > По неделям </button> </div> </div> {loading || !data ? ( <div className="empty-state">Загрузка…</div> ) : data.length === 0 ? ( <div className="empty-state">Нет данных за выбранный период</div> ) : ( <div style={{ width: '100%', height: 280 }}> <ResponsiveContainer> <LineChart data={data} margin={{ top: 10, right: 30, left: 0, bottom: 0 }}> <CartesianGrid strokeDasharray="3 3" stroke="#e3e8f0" /> <XAxis dataKey="period" stroke="#6b7385" tick={{ fontSize: 11 }} /> <YAxis yAxisId="left" stroke="#3b82f6" /> <YAxis yAxisId="right" orientation="right" stroke="#dc2626" tickFormatter={(v) => `${(v * 100).toFixed(0)}%`} /> <Tooltip formatter={(value, name) => { if (name === 'breach_rate') return [`${(Number(value) * 100).toFixed(1)}%`, '% нарушений SLA'] if (name === 'ticket_count') return [Number(value), 'Количество тикетов'] return [value, name] }} /> <Legend wrapperStyle={{ fontSize: 13 }} formatter={(value) => { if (value === 'ticket_count') return 'Количество тикетов' if (value === 'breach_rate') return '% нарушений SLA' return value }} /> <Line yAxisId="left" type="monotone" dataKey="ticket_count" stroke="#3b82f6" strokeWidth={2} dot={false} /> <Line yAxisId="right" type="monotone" dataKey="breach_rate" stroke="#dc2626" strokeWidth={2} dot={false} /> </LineChart> </ResponsiveContainer> </div> )} </div> ) }