import { useState, useMemo } from 'react'; import { IconServer, IconWorld, IconBuildingSkyscraper, IconNetwork, IconChevronDown, IconChevronRight, IconX, IconSearch, IconFilter, IconDatabase } from '@tabler/icons-react'; // Преобразование кода страны в emoji-флаг function countryToFlag(isoCode) { if (!isoCode) return ''; const codeMap = { 'SWE': 'SE', 'RUS': 'RU', 'USA': 'US', 'GER': 'DE', 'FIN': 'FI', 'NLD': 'NL' }; const code = codeMap[isoCode?.toUpperCase()] || isoCode?.toUpperCase(); if (!code || code.length !== 2) return isoCode; return code .replace(/./g, char => String.fromCodePoint(127397 + char.charCodeAt()) ); } export default function ServerSidebar({ servers = [], filters = {}, onFiltersChange, onSearch, searchTerm = '', onReset }) { const [expandedSections, setExpandedSections] = useState({ country: true, provider: true, type: true, tunnel: false }); // Подсчёт серверов по категориям const stats = useMemo(() => { const byCountry = {}; const byProvider = {}; const byType = {}; const byTunnel = {}; servers.forEach(srv => { byCountry[srv.country] = (byCountry[srv.country] || 0) + 1; byProvider[srv.provider] = (byProvider[srv.provider] || 0) + 1; byType[srv.type] = (byType[srv.type] || 0) + 1; byTunnel[srv.tunnel] = (byTunnel[srv.tunnel] || 0) + 1; }); return { byCountry, byProvider, byType, byTunnel }; }, [servers]); const toggleSection = (section) => { setExpandedSections(prev => ({ ...prev, [section]: !prev[section] })); }; const handleFilterClick = (category, value) => { const currentValue = filters[category]; const newValue = currentValue === value ? '' : value; onFiltersChange({ ...filters, [category]: newValue }); }; const activeFiltersCount = Object.values(filters).filter(Boolean).length + (searchTerm ? 1 : 0); const typeLabels = { 'jumphost': 'Jumphost', 'exit': 'Выходная нода' }; return (
{/* Заголовок */}
Фильтры {activeFiltersCount > 0 && ( {activeFiltersCount} )}
{activeFiltersCount > 0 && ( )}
{/* Поиск */}
onSearch(e.target.value)} style={{ background: 'rgba(0,0,0,0.02)', border: '1px solid rgba(0,0,0,0.06)', borderRadius: '8px', fontSize: '0.85rem' }} />
{/* Скроллируемый контент */}
{/* Секция: Страны */}
toggleSection('country')} style={{ background: 'rgba(0,0,0,0.02)', borderBottom: '1px solid rgba(0,0,0,0.04)' }} >
Страны
{expandedSections.country ? : }
{expandedSections.country && (
{Object.entries(stats.byCountry) .sort((a, b) => b[1] - a[1]) .map(([country, count]) => ( ))}
)}
{/* Секция: Провайдеры */}
toggleSection('provider')} style={{ background: 'rgba(0,0,0,0.02)', borderBottom: '1px solid rgba(0,0,0,0.04)' }} >
Провайдеры
{expandedSections.provider ? : }
{expandedSections.provider && (
{Object.entries(stats.byProvider) .sort((a, b) => b[1] - a[1]) .map(([provider, count]) => ( ))}
)}
{/* Секция: Типы */}
toggleSection('type')} style={{ background: 'rgba(0,0,0,0.02)', borderBottom: '1px solid rgba(0,0,0,0.04)' }} >
Тип сервера
{expandedSections.type ? : }
{expandedSections.type && (
{Object.entries(stats.byType) .sort((a, b) => b[1] - a[1]) .map(([type, count]) => ( ))}
)}
{/* Секция: Туннели */}
toggleSection('tunnel')} style={{ background: 'rgba(0,0,0,0.02)', borderBottom: '1px solid rgba(0,0,0,0.04)' }} >
Туннель
{expandedSections.tunnel ? : }
{expandedSections.tunnel && (
{Object.entries(stats.byTunnel) .sort((a, b) => b[1] - a[1]) .map(([tunnel, count]) => ( ))}
)}
{/* Статистика внизу */}
Статистика
Всего серверов {servers.length}
Выходных нод {stats.byType['exit'] || 0}
Jumphosts {stats.byType['jumphost'] || 0}
); }