klg-asutk-app/app/risks/page.tsx
Yuriy a7da43be0e apply recommendations: security, get_db, exceptions, eslint, api-client
- session: set_tenant use bound param (SQL injection fix)
- health: text('SELECT 1'), REDIS_URL from config
- deps: re-export get_db from session, use settings.ENABLE_DEV_AUTH (default False)
- routes: all get_db from app.api.deps; conftest overrides deps.get_db
- main: register exception handlers from app.api.exceptions
- next.config: enable ESLint and TypeScript checks
- .eslintrc: drop @typescript-eslint/recommended; fix no-console (logger, ws-client, regulations)
- backend/.env.example added
- frontend: export apiFetch; dashboard, profile, settings, risks use api-client
- docs/ANALYSIS_AND_RECOMMENDATIONS.md

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-14 21:48:58 +03:00

42 lines
2.2 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 { useState, useEffect } from 'react';
import { PageLayout, DataTable, StatusBadge, EmptyState } from '@/components/ui';
import { risksApi } from '@/lib/api/api-client';
export default function RisksPage() {
const [risks, setRisks] = useState([] as any[]);
const [loading, setLoading] = useState(true);
const [filter, setFilter] = useState('');
useEffect(() => {
setLoading(true);
risksApi.list(filter ? { severity: filter } : {}).then(d => { setRisks(d.items || []); setLoading(false); }).catch(() => setLoading(false));
}, [filter]);
return (
<>
{loading && <div className="fixed inset-0 bg-white/50 z-50 flex items-center justify-center"><div className="text-gray-500"> Загрузка...</div></div>}
<PageLayout title="⚠️ Управление рисками" subtitle="ICAO Annex 19; ВК РФ ст. 24.1; ICAO Doc 9859">
<div className="flex gap-2 mb-4">
{['', 'critical', 'high', 'medium', 'low'].map(s => (
<button key={s} onClick={() => setFilter(s)}
className={`px-3 py-1.5 rounded text-xs ${filter === s ? 'bg-blue-600 text-white' : 'bg-gray-100'}`}>{s || 'Все'}</button>
))}
</div>
{risks.length > 0 ? (
<DataTable columns={[
{ key: 'title', label: 'Риск' },
{ key: 'severity', label: 'Серьёзность', render: (v: string) => (
<StatusBadge status={v} colorMap={{ critical: 'bg-red-500', high: 'bg-orange-500', medium: 'bg-yellow-500', low: 'bg-green-500' }} />
)},
{ key: 'category', label: 'Категория' },
{ key: 'status', label: 'Статус', render: (v: string) => (
<StatusBadge status={v} colorMap={{ open: 'bg-red-500', mitigating: 'bg-yellow-500', resolved: 'bg-green-500', accepted: 'bg-gray-400' }}
labelMap={{ open: 'Открыт', mitigating: 'Меры', resolved: 'Устранён', accepted: 'Принят' }} />
)},
{ key: 'created_at', label: 'Дата', render: (v: string) => v ? new Date(v).toLocaleDateString('ru-RU') : '—' },
]} data={risks} />
) : <EmptyState message="Нет зарегистрированных рисков" />}
</PageLayout>
</>
);
}