/** * Регулятор — Минтранс, ФАВТ, Ространснадзор * Доступ: favt_inspector или admin. * Показывает ТОЛЬКО агрегированные данные согласно: * - ВК РФ ст. 8, 24.1, 28, 33, 36, 37, 67, 68 * - ФАП-246, ФАП-285, ФГИС РЭВС * - ICAO Annex 6, 7, 8, 19; Doc 9734, 9760, 9859 * - EASA Part-M, Part-CAMO, Part-145, Part-ARO * * Разработчик: АО «REFLY» */ 'use client'; import { useState, useEffect, useCallback } from 'react'; import { PageLayout, DataTable, StatusBadge, EmptyState } from '@/components/ui'; import { useAuth } from '@/lib/auth-context'; import { useI18n } from '@/hooks/useI18n'; type Tab = 'overview' | 'aircraft' | 'certifications' | 'safety' | 'audits' | 'personnel'; interface OverviewData { aircraft: { total: number; airworthy: number; in_maintenance: number; grounded: number; decommissioned: number }; organizations: { total: number }; certification: { total_applications: number; pending: number; approved: number; rejected: number }; safety: { total_risks: number; critical: number; high: number; unresolved: number }; audits_last_30d: number; legal_basis: string[]; } const TABS: { id: Tab; label: string; icon: string }[] = [ { id: 'overview', label: 'Сводка', icon: '📊' }, { id: 'aircraft', label: 'Реестр ВС', icon: '✈️' }, { id: 'certifications', label: 'Сертификация', icon: '📋' }, { id: 'safety', label: 'Безопасность', icon: '🛡️' }, { id: 'audits', label: 'Аудиты', icon: '🔍' }, { id: 'personnel' as Tab, label: 'Персонал ПЛГ', icon: '🎓' }, ]; function AccessDenied() { return (
🔒

Доступ ограничен

Панель доступна уполномоченным сотрудникам Минтранса, ФАВТ и Ространснадзора.

Основание: ВК РФ ст. 8 — Федеральные правила использования воздушного пространства. Для получения доступа обратитесь к администратору системы.

); } function StatCard({ label, value, sub, color = 'primary' }: { label: string; value: number; sub?: string; color?: string }) { const colors: Record = { primary: 'bg-blue-50 text-blue-700 border-blue-200', green: 'bg-green-50 text-green-700 border-green-200', yellow: 'bg-yellow-50 text-yellow-700 border-yellow-200', red: 'bg-red-50 text-red-700 border-red-200', gray: 'bg-gray-50 text-gray-700 border-gray-200', }; return (
{value}
{label}
{sub &&
{sub}
}
); } function LegalBasisBadge({ items }: { items: string[] }) { return (
📜 Правовые основания ({items.length})
); } export default function RegulatorPanel() { const { user } = useAuth(); const [tab, setTab] = useState('overview'); const [overview, setOverview] = useState(null); const [aircraftData, setAircraftData] = useState(null); const [certData, setCertData] = useState(null); const [safetyData, setSafetyData] = useState(null); const [auditData, setAuditData] = useState(null); const [personnelData, setPersonnelData] = useState(null); const [loading, setLoading] = useState(false); const [days, setDays] = useState(90); const [agency, setAgency] = useState<'mintrans' | 'favt' | 'rostransnadzor'>('favt'); const DEMO_OVERVIEW: OverviewData = { aircraft: { total: 142, airworthy: 118, in_maintenance: 12, grounded: 8, decommissioned: 4 }, organizations: { total: 28 }, certification: { total_applications: 15, pending: 3, approved: 10, rejected: 2 }, safety: { total_risks: 45, critical: 2, high: 8, unresolved: 5 }, audits_last_30d: 7, legal_basis: ['ВК РФ ст. 8, 24.1, 28, 33, 36, 37', 'ФАП-246, ФАП-148', 'ICAO Annex 6/8/19'], }; // Access control: only favt_inspector or admin const hasAccess = user?.role === 'favt_inspector' || user?.role === 'admin'; const fetchData = useCallback(async (endpoint: string) => { try { const res = await fetch(`/api/v1/regulator/${endpoint}`); if (!res.ok) throw new Error(`HTTP ${res.status}`); return await res.json(); } catch (e) { console.error(`Regulator API error:`, e); return null; } }, []); useEffect(() => { if (!hasAccess) return; setLoading(true); fetchData('overview').then(d => { setOverview(d || DEMO_OVERVIEW); setLoading(false); }); }, [hasAccess, fetchData]); useEffect(() => { if (!hasAccess) return; if (tab === 'aircraft' && !aircraftData) fetchData('aircraft-register').then(setAircraftData); if (tab === 'certifications' && !certData) fetchData('certifications').then(setCertData); if (tab === 'safety' && !safetyData) fetchData(`safety-indicators?days=${days}`).then(setSafetyData); if (tab === 'audits' && !auditData) fetchData(`audits?days=${days}`).then(setAuditData); if (tab === 'personnel' && !personnelData) fetchData('personnel-summary').then(setPersonnelData); }, [tab, hasAccess, days, fetchData, aircraftData, certData, safetyData, auditData]); if (!hasAccess) return ; const handlePdfExport = async () => { try { const res = await fetch('/api/v1/regulator/report/pdf'); if (!res.ok) throw new Error('PDF generation failed'); const blob = await res.blob(); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `favt_report_${new Date().toISOString().slice(0, 10)}.pdf`; a.click(); URL.revokeObjectURL(url); } catch (e) { console.error(e); } }; const handleExport = async () => { const data = await fetchData('report'); if (data) { const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `favt_report_${new Date().toISOString().slice(0, 10)}.json`; a.click(); URL.revokeObjectURL(url); } }; return ( } > {/* Disclaimer */}
⚠️ Ограниченный доступ. Данные предоставляются в агрегированном виде согласно ВК РФ (60-ФЗ), ФАП-21/128/145/147/148/149/246, ФЗ-488, ICAO Annex 6/8/19, EASA Part-M/CAMO/145/ARO, Поручение Президента Пр-1379, ТЗ АСУ ТК. Персональные данные и коммерческая тайна не раскрываются.
{/* Ведомства */}
{(['mintrans', 'favt', 'rostransnadzor'] as const).map(a => ( ))}
{/* Tabs */}
{TABS.map(t => ( ))}
{loading && !overview ? (
⏳ Загрузка данных...
) : ( <> {/* === OVERVIEW TAB === */} {tab === 'overview' && overview && (
{/* Aircraft section — ВК РФ ст. 33, ICAO Annex 7 */}

✈️ Состояние парка ВС (ВК РФ ст. 33; ICAO Annex 7, 8)

{/* Certification — ФАП-246, ICAO Annex 6 */}

📋 Сертификация эксплуатантов (ФАП-246; ICAO Annex 6)

{/* Safety — ВК РФ ст. 24.1, ICAO Annex 19 */}

🛡️ Показатели безопасности (ГПБП; ICAO Annex 19; Doc 9859)

{/* Audits + Orgs */}

🔍 Надзорная деятельность (ВК РФ ст. 28; ICAO Doc 9734)

)} {/* === AIRCRAFT REGISTER TAB === */} {tab === 'aircraft' && (

Данные аналогичны ФГИС РЭВС (приказ Росавиации № 180-П от 09.03.2017)

{aircraftData?.items?.length ? ( ( )}, { key: 'organization', label: 'Эксплуатант' }, { key: 'cert_expiry', label: 'СЛГ до', render: (v: string) => v ? new Date(v).toLocaleDateString('ru-RU') : '—' }, ]} data={aircraftData.items} /> ) : }
)} {/* === CERTIFICATIONS TAB === */} {tab === 'certifications' && (

Процедуры подтверждения соответствия по ФАП-246

{certData?.items?.length ? ( v?.slice(0, 8) }, { key: 'type', label: 'Тип' }, { key: 'status', label: 'Статус', render: (v: string) => ( )}, { key: 'organization', label: 'Организация' }, { key: 'submitted_at', label: 'Дата подачи', render: (v: string) => v ? new Date(v).toLocaleDateString('ru-RU') : '—' }, ]} data={certData.items} /> ) : }
)} {/* === SAFETY TAB === */} {tab === 'safety' && (
Период: {[30, 90, 180, 365].map(d => ( ))}
{safetyData ? ( <> {/* Severity distribution */}

Распределение рисков по степени серьёзности

{Object.entries(safetyData.severity_distribution || {}).map(([sev, cnt]) => ( ))}
{/* Monthly trend */} {safetyData.monthly_trend?.length > 0 && (

Динамика рисков по месяцам

{safetyData.monthly_trend.map((m: any, i: number) => { const maxC = Math.max(...safetyData.monthly_trend.map((t: any) => t.count), 1); return (
{m.count}
{m.month ? new Date(m.month).toLocaleDateString('ru-RU', { month: 'short' }) : '?'}
); })}
)}
⚠️
{safetyData.critical_unresolved}
Критических неустранённых рисков
) :
Загрузка...
}
)} {/* === AUDITS TAB === */} {tab === 'audits' && (

Результаты инспекционного контроля (ВК РФ ст. 28)

{auditData?.items?.length ? ( v?.slice(0, 8) }, { key: 'type', label: 'Тип проверки' }, { key: 'status', label: 'Результат', render: (v: string) => ( )}, { key: 'aircraft_reg', label: 'Рег. знак ВС' }, { key: 'conducted_at', label: 'Дата', render: (v: string) => v ? new Date(v).toLocaleDateString('ru-RU') : '—' }, ]} data={auditData.items} /> ) : }
)} )} {/* === PERSONNEL PLG TAB === */} {tab === 'personnel' && (

Агрегированные данные о персонале ПЛГ (ВК РФ ст. 52-54; ФАП-147; ICAO Annex 1)

{personnelData ? ( <>
{personnelData.total_specialists}
Всего специалистов
{personnelData.compliant}
Квалификация в порядке
{personnelData.non_compliant}
Нарушения
{personnelData.compliance_rate}%
Compliance rate
{Object.keys(personnelData.by_category || {}).length > 0 && (

Распределение по категориям (EASA Part-66 / ФАП-147)

{Object.entries(personnelData.by_category).map(([cat, cnt]) => (
{cnt as number}
Кат. {cat}
))}
)}
Персональные данные (ФИО, табельные номера) не раскрываются (ФЗ-152)
) :
Загрузка...
}
)} {/* Footer */}
Данные предоставлены из АСУ ТК КЛГ согласно ТЗ (утв. 24.07.2022) и Поручению Президента Пр-1379. Агрегированные показатели — коммерческая тайна и ПДн не раскрываются.
Система соответствует требованиям ФЗ-152 «О персональных данных» и ФЗ-149 «Об информации».
© {new Date().getFullYear()} АО «REFLY» — Разработчик АСУ ТК
); }