'use client' import React, { useState } from 'react' interface DetectorsDataType { detectors: Record } interface FloorNavigationProps { objectId?: string detectorsData: DetectorsDataType onDetectorMenuClick: (detector: DetectorType) => void onClose?: () => void is3DReady?: boolean } interface DetectorType { detector_id: number name: string serial_number: string object: string status: string checked: boolean type: string location: string floor: number notifications: Array<{ id: number type: string message: string timestamp: string acknowledged: boolean priority: string }> } const FloorNavigation: React.FC = ({ objectId, detectorsData, onDetectorMenuClick, onClose, is3DReady = true }) => { const [expandedFloors, setExpandedFloors] = useState>(new Set()) const [searchTerm, setSearchTerm] = useState('') // конвертация детекторов в array и фильтруем по objectId и тексту запроса const detectorsArray = Object.values(detectorsData.detectors) as DetectorType[] let filteredDetectors = objectId ? detectorsArray.filter(detector => detector.object === objectId) : detectorsArray // Фильтр-поиск if (searchTerm) { filteredDetectors = filteredDetectors.filter(detector => detector.name.toLowerCase().includes(searchTerm.toLowerCase()) || detector.location.toLowerCase().includes(searchTerm.toLowerCase()) ) } // Группиовка детекторов по этажам const detectorsByFloor = filteredDetectors.reduce((acc, detector) => { const floor = detector.floor if (!acc[floor]) { acc[floor] = [] } acc[floor].push(detector) return acc }, {} as Record) // Сортировка этажей const sortedFloors = Object.keys(detectorsByFloor) .map(Number) .sort((a, b) => a - b) const toggleFloor = (floor: number) => { const newExpanded = new Set(expandedFloors) if (newExpanded.has(floor)) { newExpanded.delete(floor) } else { newExpanded.add(floor) } setExpandedFloors(newExpanded) } const getStatusColor = (status: string) => { switch (status) { case '#b3261e': return 'bg-red-500' case '#fd7c22': return 'bg-orange-500' case '#00ff00': return 'bg-green-500' default: return 'bg-gray-500' } } const getStatusText = (status: string) => { switch (status) { case '#b3261e': return 'Критический' case '#fd7c22': return 'Предупреждение' case '#00ff00': return 'Норма' default: return 'Неизвестно' } } const handleDetectorMenuClick = (detector: DetectorType) => { // Проверяем валидность данных детектора перед передачей if (!detector || !detector.detector_id || !detector.serial_number) { console.warn('[FloorNavigation] Invalid detector data, skipping menu click:', detector) return } onDetectorMenuClick(detector) } return (

Навигация по этажам

{onClose && ( )}
setSearchTerm(e.target.value)} className="w-full bg-[rgb(27,30,40)] text-white placeholder-gray-400 px-4 py-2 rounded-lg border border-gray-600 focus:border-blue-500 focus:outline-none" />
{sortedFloors.map(floor => { const floorDetectors = detectorsByFloor[floor] const isExpanded = expandedFloors.has(floor) return (
{/* суб-меню с детекторами */} {isExpanded && (
{floorDetectors.map(detector => (
{detector.name}
{detector.location}
{getStatusText(detector.status)} {detector.checked && ( )}
))}
)}
) })}
) } export default FloorNavigation