Linked backend data to detectors' meshes.

This commit is contained in:
iv_vuytsik
2025-10-20 11:02:34 +03:00
parent aeda917001
commit 66e2bab683
15 changed files with 546 additions and 156 deletions

View File

@@ -15,55 +15,39 @@ const Dashboard: React.FC = () => {
const objectId = currentObject?.id
const objectTitle = currentObject?.title
const [detectorsArray, setDetectorsArray] = useState<any[]>([])
const [dashboardAlerts, setDashboardAlerts] = useState<any[]>([])
const [chartData, setChartData] = useState<{ timestamp: string; value: number }[]>([])
useEffect(() => {
const loadDetectors = async () => {
const loadDashboard = async () => {
try {
const res = await fetch('/api/get-detectors', { cache: 'no-store' })
const res = await fetch('/api/get-dashboard', { cache: 'no-store' })
if (!res.ok) return
const payload = await res.json()
console.log('[Dashboard] GET /api/get-detectors', { status: res.status, payload })
const detectorsData = payload?.data?.detectors ?? {}
const arr = Object.values(detectorsData).filter(
(detector: any) => (objectId ? detector.object === objectId : true)
)
setDetectorsArray(arr as any[])
console.log('[Dashboard] GET /api/get-dashboard', { status: res.status, payload })
const tableData = payload?.data?.table_data ?? []
const arr = (Array.isArray(tableData) ? tableData : [])
.filter((a: any) => (objectTitle ? a.object === objectTitle : true))
setDashboardAlerts(arr as any[])
const cd = Array.isArray(payload?.data?.chart_data) ? payload.data.chart_data : []
setChartData(cd as any[])
} catch (e) {
console.error('Failed to load detectors:', e)
console.error('Failed to load dashboard:', e)
}
}
loadDetectors()
}, [objectId])
loadDashboard()
}, [objectTitle])
const handleBackClick = () => {
router.push('/objects')
}
interface DetectorData {
detector_id: number
name: string
object: string
status: string
type: string
location: string
floor: number
checked?: boolean
notifications: Array<{
id: number
type: string
message: string
timestamp: string
acknowledged: boolean
priority: string
}>
}
// Статусы
const statusCounts = detectorsArray.reduce((acc: { critical: number; warning: number; normal: number }, detector: DetectorData) => {
if (detector.status === '#b3261e') acc.critical++
else if (detector.status === '#fd7c22') acc.warning++
else if (detector.status === '#00ff00') acc.normal++
const statusCounts = dashboardAlerts.reduce((acc: { critical: number; warning: number; normal: number }, a: any) => {
if (a.severity === 'critical') acc.critical++
else if (a.severity === 'warning') acc.warning++
else acc.normal++
return acc
}, { critical: 0, warning: 0, normal: 0 })
@@ -139,14 +123,14 @@ const Dashboard: React.FC = () => {
title="Показатель"
subtitle="За последние 6 месяцев"
>
<AreaChart />
<AreaChart data={chartData} />
</ChartCard>
<ChartCard
title="Статистика"
subtitle="Данные за период"
>
<BarChart />
<BarChart data={chartData?.map((d: any) => ({ value: d.value }))} />
</ChartCard>
</div>
</div>
@@ -174,36 +158,26 @@ const Dashboard: React.FC = () => {
<thead>
<tr className="border-b border-gray-700">
<th className="text-left text-white font-medium py-3">Детектор</th>
<th className="text-left text-white font-medium py-3">Статус</th>
<th className="text-left text-white font-medium py-3">Местоположение</th>
<th className="text-left text-white font-medium py-3">Проверен</th>
<th className="text-left text-white font-medium py-3">Сообщение</th>
<th className="text-left text-white font-medium py-3">Серьезность</th>
<th className="text-left text-white font-medium py-3">Дата</th>
<th className="text-left text-white font-medium py-3">Решен</th>
</tr>
</thead>
<tbody>
{detectorsArray.map((detector: DetectorData) => (
<tr key={detector.detector_id} className="border-b border-gray-800">
<td className="py-3 text-white text-sm">{detector.name}</td>
{dashboardAlerts.map((alert: any) => (
<tr key={alert.id} className="border-b border-gray-800">
<td className="py-3 text-white text-sm">{alert.name}</td>
<td className="py-3 text-gray-300 text-sm">{alert.message}</td>
<td className="py-3">
<div className="flex items-center gap-2">
<div
className={`w-3 h-3 rounded-full`}
style={{ backgroundColor: detector.status }}
></div>
<span className="text-sm text-gray-300">
{detector.status === '#b3261e' ? 'Критическое' :
detector.status === '#fd7c22' ? 'Предупреждение' : 'Норма'}
</span>
</div>
<span className={`text-sm ${alert.severity === 'critical' ? 'text-red-500' : alert.severity === 'warning' ? 'text-orange-500' : 'text-green-500'}`}>
{alert.severity === 'critical' ? 'Критическое' : alert.severity === 'warning' ? 'Предупреждение' : 'Норма'}
</span>
</td>
<td className="py-3 text-gray-400 text-sm">{detector.location}</td>
<td className="py-3 text-gray-400 text-sm">{new Date(alert.created_at).toLocaleString()}</td>
<td className="py-3">
{detector.checked ? (
<div className="flex items-center gap-1">
<svg className="w-4 h-4 text-green-500" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
</svg>
<span className="text-sm text-green-500">Да</span>
</div>
{alert.resolved ? (
<span className="text-sm text-green-500">Да</span>
) : (
<span className="text-sm text-gray-500">Нет</span>
)}
@@ -217,7 +191,7 @@ const Dashboard: React.FC = () => {
{/* Статы */}
<div className="mt-6 grid grid-cols-4 gap-4">
<div className="text-center">
<div className="text-2xl font-bold text-white">{detectorsArray.length}</div>
<div className="text-2xl font-bold text-white">{dashboardAlerts.length}</div>
<div className="text-sm text-gray-400">Всего</div>
</div>
<div className="text-center">