'use client' import React from 'react' import { useRouter } from 'next/navigation' import useNavigationStore from '@/app/store/navigationStore' interface DetectorType { detector_id: number name: string serial_number: string object: string status: string checked: boolean type: string detector_type: string location: string floor: number notifications: Array<{ id: number type: string message: string timestamp: string acknowledged: boolean priority: string }> } interface DetectorMenuProps { detector: DetectorType isOpen: boolean onClose: () => void getStatusText: (status: string) => string compact?: boolean anchor?: { left: number; top: number } | null } // Главный компонент меню детектора // Показывает детальную информацию о датчике с возможностью навигации к отчетам и истории const DetectorMenu: React.FC = ({ detector, isOpen, onClose, getStatusText, compact = false, anchor = null }) => { const router = useRouter() const { setSelectedDetector, currentObject } = useNavigationStore() if (!isOpen) return null // Определение последней временной метки из уведомлений детектора const latestTimestamp = (() => { const list = detector.notifications ?? [] if (!Array.isArray(list) || list.length === 0) return null const dates = list.map(n => new Date(n.timestamp)).filter(d => !isNaN(d.getTime())) if (dates.length === 0) return null dates.sort((a, b) => b.getTime() - a.getTime()) return dates[0] })() const formattedTimestamp = latestTimestamp ? latestTimestamp.toLocaleString('ru-RU', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }) : 'Нет данных' // Определение типа детектора и его отображаемого названия const rawDetectorTypeCode = (detector.detector_type || '').toUpperCase() const deriveCodeFromType = (): string => { const t = (detector.type || '').toLowerCase() if (!t) return '' if (t.includes('инклинометр')) return 'GA' if (t.includes('тензометр')) return 'PE' if (t.includes('гидроуров')) return 'GLE' return '' } const effectiveDetectorTypeCode = rawDetectorTypeCode || deriveCodeFromType() // Карта соответствия кодов типов детекторов их русским названиям const detectorTypeLabelMap: Record = { GA: 'Инклинометр', PE: 'Тензометр', GLE: 'Гидроуровень', } const displayDetectorTypeLabel = detectorTypeLabelMap[effectiveDetectorTypeCode] || '—' // Обработчик клика по кнопке "Отчет" - навигация на страницу отчетов с выбранным детектором const handleReportsClick = () => { const currentUrl = new URL(window.location.href) const objectId = currentUrl.searchParams.get('objectId') || currentObject.id const objectTitle = currentUrl.searchParams.get('objectTitle') || currentObject.title const detectorData = { ...detector, notifications: detector.notifications || [] } setSelectedDetector(detectorData) let reportsUrl = '/reports' const params = new URLSearchParams() if (objectId) params.set('objectId', objectId) if (objectTitle) params.set('objectTitle', objectTitle) if (params.toString()) { reportsUrl += `?${params.toString()}` } router.push(reportsUrl) } // Обработчик клика по кнопке "История" - навигация на страницу истории тревог с выбранным детектором const handleHistoryClick = () => { const currentUrl = new URL(window.location.href) const objectId = currentUrl.searchParams.get('objectId') || currentObject.id const objectTitle = currentUrl.searchParams.get('objectTitle') || currentObject.title const detectorData = { ...detector, notifications: detector.notifications || [] } setSelectedDetector(detectorData) let alertsUrl = '/alerts' const params = new URLSearchParams() if (objectId) params.set('objectId', objectId) if (objectTitle) params.set('objectTitle', objectTitle) if (params.toString()) { alertsUrl += `?${params.toString()}` } router.push(alertsUrl) } // Компонент секции деталей детектора // Отображает информацию о датчике в компактном или полном формате const DetailsSection: React.FC<{ compact?: boolean }> = ({ compact = false }) => (
{compact ? ( // Компактный режим: 4 строки по 2 колонки с основной информацией <> {/* Строка 1: Маркировка и тип детектора */}
Маркировка по проекту
{detector.name}
Тип детектора
{displayDetectorTypeLabel}
{/* Строка 2: Местоположение и статус */}
Местоположение
{detector.location}
Статус
{getStatusText(detector.status)}
{/* Строка 3: Временная метка и этаж */}
Временная метка
{formattedTimestamp}
Этаж
{detector.floor}
{/* Строка 4: Серийный номер */}
Серийный номер
{detector.serial_number}
) : ( // Полный режим: 3 строки по 2 колонки с рамками между элементами <> {/* Строка 1: Маркировка по проекту и тип детектора */}
Маркировка по проекту
{detector.name}
Тип детектора
{displayDetectorTypeLabel}
{/* Строка 2: Местоположение и статус */}
Местоположение
{detector.location}
Статус
{getStatusText(detector.status)}
{/* Строка 3: Временная метка и серийный номер */}
Временная метка
{formattedTimestamp}
Серийный номер
{detector.serial_number}
)}
) // Компактный режим с якорной позицией (всплывающее окно) // Используется для отображения информации при наведении на детектор в списке if (compact && anchor) { return (
{detector.name}
) } // Полный режим боковой панели (основной режим) // Отображается как правая панель с полной информацией о детекторе return (
{/* Заголовок с названием детектора */}

{detector.name}

{/* Кнопки действий: Отчет и История */}
{/* Секция с детальной информацией о детекторе */} {/* Кнопка закрытия панели */}
) } export default DetectorMenu