|
|
import { Fragment, useState, useRef } from "react";
|
|
|
import { Dialog, Disclosure, Menu, Transition } from "@headlessui/react";
|
|
|
import { XMarkIcon } from "@heroicons/react/24/outline";
|
|
|
import {
|
|
|
ChevronUpIcon,
|
|
|
ChevronDownIcon,
|
|
|
FunnelIcon,
|
|
|
MinusIcon,
|
|
|
PlusIcon,
|
|
|
} from "@heroicons/react/20/solid";
|
|
|
|
|
|
import Map, { Layer, Source, Popup, ScaleControl } from "react-map-gl";
|
|
|
import mapstyle from "./points.json";
|
|
|
|
|
|
mapstyle.sources.remap.url = import.meta.env.MODE === "development" ? "http://localhost:8080/capabilities/remap.json" : mapstyle.sources.remap.url
|
|
|
|
|
|
const MAPBOX_TOKEN =
|
|
|
"pk.eyJ1IjoiZ2hlcm1hbnQiLCJhIjoiY2wzbHR0YW1sMXB0YjNkcXd5NWpqaWpybiJ9.jyLcIcB7NLbtZzGYIJZWWg";
|
|
|
|
|
|
const paintedLayers = mapstyle.layers.reduce((acc, cur) => ({ ...acc, [cur.id]: cur }), {})
|
|
|
const pointsColors = mapstyle.layers.find(layer => layer.id == "Объекты").paint["circle-color"].slice(2, -1).reduce((acc, cur, i, source) => (i % 2 == 0 ? [...acc, { name: cur, color: source[i + 1] }] : acc), [])
|
|
|
const pointsSizes = mapstyle.layers.find(layer => layer.id == "Объекты").paint["circle-radius"].slice(3).reduce((acc, cur, i, source) => (i % 2 == 0 ? [...acc, { value: cur, size: source[i + 1] }] : acc), [])
|
|
|
|
|
|
const initialFilters = [
|
|
|
{
|
|
|
id: "id_tech",
|
|
|
name: "ВИЭ-технология",
|
|
|
options: [
|
|
|
{
|
|
|
"value": 1,
|
|
|
"label": "СЭС",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": 2,
|
|
|
"label": "ВЭС",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": 3,
|
|
|
"label": "мГЭС",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": 4,
|
|
|
"label": "БиоЭС (биомасса)",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": 5,
|
|
|
"label": "БиоЭС (биогаз)",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": 6,
|
|
|
"label": "БиоЭС (свалочный газ)",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": 8,
|
|
|
"label": "ПЭС",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": 9,
|
|
|
"label": "ГеоЭС",
|
|
|
"checked": true
|
|
|
}
|
|
|
]
|
|
|
},
|
|
|
{
|
|
|
"id": "region_name",
|
|
|
"name": "Регион размещения",
|
|
|
"options": [
|
|
|
{
|
|
|
"value": "Республика Адыгея ",
|
|
|
"label": "Республика Адыгея ",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Республика Алтай",
|
|
|
"label": "Республика Алтай",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Республика Башкортостан",
|
|
|
"label": "Республика Башкортостан",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Республика Бурятия",
|
|
|
"label": "Республика Бурятия",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Республика Дагестан",
|
|
|
"label": "Республика Дагестан",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Республика Ингушетия",
|
|
|
"label": "Республика Ингушетия",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Кабардино-Балкарская Республика",
|
|
|
"label": "Кабардино-Балкарская Республика",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Республика Калмыкия",
|
|
|
"label": "Республика Калмыкия",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Карачаево-Черкесская Республика",
|
|
|
"label": "Карачаево-Черкесская Республика",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Республика Карелия",
|
|
|
"label": "Республика Карелия",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Республика Коми",
|
|
|
"label": "Республика Коми",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Республика Крым",
|
|
|
"label": "Республика Крым",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Республика Марий Эл",
|
|
|
"label": "Республика Марий Эл",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Республика Мордовия",
|
|
|
"label": "Республика Мордовия",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Республика Саха (Якутия)",
|
|
|
"label": "Республика Саха (Якутия)",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Республика Северная Осетия – Алания",
|
|
|
"label": "Республика Северная Осетия – Алания",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Республика Татарстан ",
|
|
|
"label": "Республика Татарстан ",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Республика Тыва",
|
|
|
"label": "Республика Тыва",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Удмуртская Республика",
|
|
|
"label": "Удмуртская Республика",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Республика Хакасия",
|
|
|
"label": "Республика Хакасия",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Чеченская Республика",
|
|
|
"label": "Чеченская Республика",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Чувашская Республика",
|
|
|
"label": "Чувашская Республика",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Алтайский край",
|
|
|
"label": "Алтайский край",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Забайкальский край",
|
|
|
"label": "Забайкальский край",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Камчатский край",
|
|
|
"label": "Камчатский край",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Краснодарский край",
|
|
|
"label": "Краснодарский край",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Красноярский край",
|
|
|
"label": "Красноярский край",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Пермский край",
|
|
|
"label": "Пермский край",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Приморский край",
|
|
|
"label": "Приморский край",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Ставропольский край",
|
|
|
"label": "Ставропольский край",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Хабаровский край",
|
|
|
"label": "Хабаровский край",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Амурская область",
|
|
|
"label": "Амурская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Архангельская область",
|
|
|
"label": "Архангельская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Астраханская область",
|
|
|
"label": "Астраханская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Белгородская область",
|
|
|
"label": "Белгородская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Брянская область",
|
|
|
"label": "Брянская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Владимирская область",
|
|
|
"label": "Владимирская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Волгоградская область",
|
|
|
"label": "Волгоградская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Вологодская область",
|
|
|
"label": "Вологодская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Воронежская область",
|
|
|
"label": "Воронежская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Ивановская область",
|
|
|
"label": "Ивановская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Иркутская область",
|
|
|
"label": "Иркутская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Калининградская область",
|
|
|
"label": "Калининградская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Калужская область",
|
|
|
"label": "Калужская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Кемеровская область",
|
|
|
"label": "Кемеровская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Кировская область",
|
|
|
"label": "Кировская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Костромская область",
|
|
|
"label": "Костромская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Курганская область",
|
|
|
"label": "Курганская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Курская область",
|
|
|
"label": "Курская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Ленинградская область",
|
|
|
"label": "Ленинградская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Липецкая область",
|
|
|
"label": "Липецкая область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Магаданская область",
|
|
|
"label": "Магаданская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Московская область",
|
|
|
"label": "Московская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Мурманская область",
|
|
|
"label": "Мурманская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Нижегородская область",
|
|
|
"label": "Нижегородская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Новгородская область",
|
|
|
"label": "Новгородская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Новосибирская область",
|
|
|
"label": "Новосибирская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Омская область",
|
|
|
"label": "Омская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Оренбургская область",
|
|
|
"label": "Оренбургская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Орловская область",
|
|
|
"label": "Орловская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Пензенская область",
|
|
|
"label": "Пензенская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Псковская область",
|
|
|
"label": "Псковская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Ростовская область",
|
|
|
"label": "Ростовская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Рязанская область",
|
|
|
"label": "Рязанская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Самарская область",
|
|
|
"label": "Самарская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Саратовская область",
|
|
|
"label": "Саратовская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Сахалинская область",
|
|
|
"label": "Сахалинская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Свердловская область",
|
|
|
"label": "Свердловская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Смоленская область",
|
|
|
"label": "Смоленская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Тамбовская область",
|
|
|
"label": "Тамбовская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Тверская область",
|
|
|
"label": "Тверская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Томская область",
|
|
|
"label": "Томская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Тульская область",
|
|
|
"label": "Тульская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Тюменская область",
|
|
|
"label": "Тюменская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Ульяновская область",
|
|
|
"label": "Ульяновская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Челябинская область",
|
|
|
"label": "Челябинская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Ярославская область",
|
|
|
"label": "Ярославская область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Город Москва",
|
|
|
"label": "Город Москва",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Город Санкт-Петербург",
|
|
|
"label": "Город Санкт-Петербург",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Город Севастополь",
|
|
|
"label": "Город Севастополь",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Еврейская автономная область",
|
|
|
"label": "Еврейская автономная область",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Ненецкий автономный округ",
|
|
|
"label": "Ненецкий автономный округ",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Ханты-Мансийский автономный округ – Югра",
|
|
|
"label": "Ханты-Мансийский автономный округ – Югра",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Чукотский автономный округ",
|
|
|
"label": "Чукотский автономный округ",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Ямало-Ненецкий автономный округ",
|
|
|
"label": "Ямало-Ненецкий автономный округ",
|
|
|
"checked": true
|
|
|
}
|
|
|
]
|
|
|
},
|
|
|
{
|
|
|
"id": "id_support",
|
|
|
"name": "Форма поддержки",
|
|
|
"options": [
|
|
|
{
|
|
|
"value": 1,
|
|
|
"label": "ДПМ ВИЭ 1.0 (оптовый рынок)",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": 2,
|
|
|
"label": "ДПМ ВИЭ 2.0 (оптовый рынок)",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": 3,
|
|
|
"label": "Розничный рынок (с поддержкой)",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": 4,
|
|
|
"label": "Розничный рынок (без поддержки)",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": 5,
|
|
|
"label": "Оптовый рынок (без поддержки)",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": 6,
|
|
|
"label": "Собственная генерация промышленности",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": 7,
|
|
|
"label": "ВИЭ в изолированнных энергосистемах",
|
|
|
"checked": true
|
|
|
}
|
|
|
]
|
|
|
},
|
|
|
{
|
|
|
"id": "main_company_for_site",
|
|
|
"name": "Компания-владелец",
|
|
|
"options": [
|
|
|
{
|
|
|
"value": "ООО \"Вершина Девелопмент\"",
|
|
|
"label": "ООО \"Вершина Девелопмент\"",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "АО \"НоваВинд\"",
|
|
|
"label": "АО \"НоваВинд\"",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "ООО \"Ветропарки ФРВ\"",
|
|
|
"label": "ООО \"Ветропарки ФРВ\"",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "ПАО \"ТГК-1\"",
|
|
|
"label": "ПАО \"ТГК-1\"",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "ООО \"Солар Системс\"",
|
|
|
"label": "ООО \"Солар Системс\"",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "ГК \"Хевел\"",
|
|
|
"label": "ГК \"Хевел\"",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "ПАО \"ЭЛ5-Энерго\"",
|
|
|
"label": "ПАО \"ЭЛ5-Энерго\"",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "ПАО \"Форвард Энерго\"",
|
|
|
"label": "ПАО \"Форвард Энерго\"",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "Другие",
|
|
|
"label": "Другие",
|
|
|
"checked": true
|
|
|
}
|
|
|
]
|
|
|
},
|
|
|
{
|
|
|
"id": "year_commissioning_filter",
|
|
|
"name": "Год ввода в эксплуатацию",
|
|
|
"options": [
|
|
|
{
|
|
|
"value": "1905-2009",
|
|
|
"label": "1905-2009",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "2010",
|
|
|
"label": "2010",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "2011",
|
|
|
"label": "2011",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "2012",
|
|
|
"label": "2012",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "2013",
|
|
|
"label": "2013",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "2014",
|
|
|
"label": "2014",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "2015",
|
|
|
"label": "2015",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "2016",
|
|
|
"label": "2016",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "2017",
|
|
|
"label": "2017",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "2018",
|
|
|
"label": "2018",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "2019",
|
|
|
"label": "2019",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "2020",
|
|
|
"label": "2020",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "2021",
|
|
|
"label": "2021",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "2022",
|
|
|
"label": "2022",
|
|
|
"checked": true
|
|
|
},
|
|
|
{
|
|
|
"value": "2023",
|
|
|
"label": "2023",
|
|
|
"checked": true
|
|
|
}
|
|
|
]
|
|
|
}
|
|
|
]
|
|
|
|
|
|
export default function Points({ mapOptions, onMapOptionClick }) {
|
|
|
const mapRef = useRef(null);
|
|
|
|
|
|
const [open, setOpen] = useState(false)
|
|
|
|
|
|
const [mobileFiltersOpen, setMobileFiltersOpen] = useState(false);
|
|
|
|
|
|
const [popupInfo, setPopupInfo] = useState(null);
|
|
|
|
|
|
const [filters, setFilters] = useState(initialFilters);
|
|
|
|
|
|
const generatePopup = (info) => {
|
|
|
console.log(info)
|
|
|
return (
|
|
|
<div>
|
|
|
<img src={`/photos/${info.id_rreda_parc}.jpg`} className="mb-4 rounded" />
|
|
|
|
|
|
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
|
|
|
<tbody>
|
|
|
{info.power_fact_parc_mw != null &&
|
|
|
<tr className="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
|
|
|
<th scope="row" className="px-2 py-4 font-medium text-gray-900 dark:text-white">
|
|
|
Установленная мощность
|
|
|
</th>
|
|
|
<td className="px-2 py-4">
|
|
|
{info.power_fact_parc_mw.toFixed(2).replace(".", ",")} МВт
|
|
|
</td>
|
|
|
</tr>
|
|
|
}
|
|
|
{info.year_commissioning &&
|
|
|
<tr className="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
|
|
|
<th scope="row" className="px-2 py-4 font-medium text-gray-900 dark:text-white">
|
|
|
Год ввода в эксплуатацию
|
|
|
</th>
|
|
|
<td className="px-2 py-4">
|
|
|
{info.year_commissioning}
|
|
|
</td>
|
|
|
</tr>
|
|
|
}
|
|
|
{info.year_qualification &&
|
|
|
<tr className="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
|
|
|
<th scope="row" className="px-2 py-4 font-medium text-gray-900 dark:text-white">
|
|
|
Год квалификации
|
|
|
</th>
|
|
|
<td className="px-2 py-4">
|
|
|
{info.year_qualification}
|
|
|
</td>
|
|
|
</tr>
|
|
|
}
|
|
|
{info.support_name &&
|
|
|
<tr className="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
|
|
|
<th scope="row" className="px-2 py-4 font-medium text-gray-900 dark:text-white">
|
|
|
Механизм поддержки
|
|
|
</th>
|
|
|
<td className="px-2 py-4">
|
|
|
{info.support_name}
|
|
|
</td>
|
|
|
</tr>
|
|
|
}
|
|
|
{info.region_name &&
|
|
|
<tr className="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
|
|
|
<th scope="row" className="px-2 py-4 font-medium text-gray-900 dark:text-white">
|
|
|
Регион размещения
|
|
|
</th>
|
|
|
<td className="px-2 py-4">
|
|
|
{info.region_name}
|
|
|
</td>
|
|
|
</tr>
|
|
|
}
|
|
|
{info.residence_area &&
|
|
|
<tr className="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
|
|
|
<th scope="row" className="px-2 py-4 font-medium text-gray-900 dark:text-white">
|
|
|
Район размещения
|
|
|
</th>
|
|
|
<td className="px-2 py-4">
|
|
|
{[info.residence_area, info.settlement, info.natural_object].filter(item => item).join(", ")}
|
|
|
</td>
|
|
|
</tr>
|
|
|
}
|
|
|
{info.main_owner_company &&
|
|
|
<tr className="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
|
|
|
<th scope="row" className="px-2 py-4 font-medium text-gray-900 dark:text-white">
|
|
|
Владелец объекта
|
|
|
</th>
|
|
|
<td className="px-2 py-4">
|
|
|
{info.current_owner_name && info.main_owner_company != info.current_owner_name ? `${info.current_owner_name} (${info.main_owner_company})` : info.main_owner_company}
|
|
|
</td>
|
|
|
</tr>
|
|
|
}
|
|
|
</tbody>
|
|
|
</table>
|
|
|
|
|
|
{Boolean(info.rreda_member) && info.company_link_rreda && <p className="text-sm mt-4 text-gray-600">Ссылка на компанию: <a href={info.company_link_rreda} target="_blank" className="text-indigo-800">{info.company_link_rreda}</a></p>}
|
|
|
{info.date_actualization && <p className="text-sm mt-1 text-gray-600">Дата актуализации: {info.date_actualization}</p>}
|
|
|
</div>
|
|
|
)
|
|
|
}
|
|
|
|
|
|
const clearAllOptions = (event) => {
|
|
|
event.preventDefault()
|
|
|
const newStateFilters = filters.map((filter) =>
|
|
|
filter.id == event.target.value
|
|
|
? {
|
|
|
...filter,
|
|
|
options: filter.options.map((option) => {
|
|
|
const newoption = { ...option, checked: false }
|
|
|
return (newoption)
|
|
|
})
|
|
|
}
|
|
|
: filter
|
|
|
)
|
|
|
setFilters(newStateFilters);
|
|
|
}
|
|
|
|
|
|
const addAllOptions = (event) => {
|
|
|
event.preventDefault();
|
|
|
const newStateFilters = filters.map((filter) =>
|
|
|
filter.id == event.target.value
|
|
|
? {
|
|
|
...filter,
|
|
|
options: filter.options.map((option) => {
|
|
|
const newoption = { ...option, checked: true }
|
|
|
return (newoption)
|
|
|
})
|
|
|
}
|
|
|
: filter
|
|
|
)
|
|
|
setFilters(newStateFilters);
|
|
|
}
|
|
|
|
|
|
const handleFilterToggle = function (event) {
|
|
|
const newStateFilters = filters.map((filter) =>
|
|
|
filter.id == event.target.name
|
|
|
? {
|
|
|
...filter,
|
|
|
options: filter.options.map((option) =>
|
|
|
option.value == event.target.defaultValue
|
|
|
? { ...option, checked: !option.checked }
|
|
|
: option
|
|
|
),
|
|
|
}
|
|
|
: filter
|
|
|
);
|
|
|
setFilters(newStateFilters);
|
|
|
};
|
|
|
|
|
|
const applyFilters = (filtersObj) => {
|
|
|
const checkedFilters = ["all", ...filtersObj.map((propertyFilter) => [
|
|
|
"in",
|
|
|
["get", propertyFilter.id],
|
|
|
["literal", propertyFilter.options.filter(option => option.checked).map(option => option.value)],
|
|
|
])]
|
|
|
return checkedFilters
|
|
|
};
|
|
|
|
|
|
const handleClick = (event) => {
|
|
|
setOpen(false)
|
|
|
setPopupInfo(null)
|
|
|
if (event.features[0]) {
|
|
|
console.log(event.features[0].geometry)
|
|
|
// event.originalEvent.stopPropagation();
|
|
|
setPopupInfo({
|
|
|
lon: event.features[0].geometry.coordinates[0],
|
|
|
lat: event.features[0].geometry.coordinates[1],
|
|
|
...event.features[0].properties
|
|
|
})
|
|
|
setOpen(true)
|
|
|
}
|
|
|
};
|
|
|
|
|
|
const handleMouseEnter = (event) => {
|
|
|
const feature = event.features[0];
|
|
|
if (!feature) return;
|
|
|
|
|
|
mapRef.current.getCanvas().style.cursor = "pointer";
|
|
|
};
|
|
|
|
|
|
const handleMouseLeave = (event) => {
|
|
|
const feature = event.features[0];
|
|
|
if (!feature) {
|
|
|
return;
|
|
|
}
|
|
|
mapRef.current.getCanvas().style.cursor = "";
|
|
|
};
|
|
|
|
|
|
return (
|
|
|
<div className="bg-white">
|
|
|
<div>
|
|
|
<main className="mx-auto px-4 sm:px-6 lg:px-8">
|
|
|
<div className="flex items-baseline justify-between border-b border-gray-200 pt-24 pb-6">
|
|
|
<h1 className="text-4xl font-bold tracking-tight text-gray-900">
|
|
|
Объекты ВИЭ-генерации в регионах России
|
|
|
</h1>
|
|
|
<div className="flex items-center">
|
|
|
<Menu as="div" className="relative inline-block text-left">
|
|
|
<Menu.Button className="hidden group inline-flex justify-center text-sm font-medium text-gray-700 hover:text-gray-900">
|
|
|
{mapOptions.find((option) => option.current).name}
|
|
|
<ChevronDownIcon
|
|
|
className="-mr-1 ml-1 h-5 w-5 flex-shrink-0 text-gray-400 group-hover:text-gray-500"
|
|
|
aria-hidden="true"
|
|
|
/>
|
|
|
</Menu.Button>
|
|
|
|
|
|
<Transition
|
|
|
as={Fragment}
|
|
|
enter="transition ease-out duration-100"
|
|
|
enterFrom="transform opacity-0 scale-95"
|
|
|
enterTo="transform opacity-100 scale-100"
|
|
|
leave="transition ease-in duration-75"
|
|
|
leaveFrom="transform opacity-100 scale-100"
|
|
|
leaveTo="transform opacity-0 scale-95"
|
|
|
show={true}
|
|
|
>
|
|
|
<Menu.Items className="absolute right-0 z-10 mt-2 w-40 origin-top-right rounded-md bg-white shadow-2xl ring-1 ring-black ring-opacity-5 focus:outline-none">
|
|
|
<div className="py-1">
|
|
|
{mapOptions.map((option) => (
|
|
|
<Menu.Item key={option.name}>
|
|
|
<a
|
|
|
href="#"
|
|
|
className={option.current ? 'font-medium text-gray-900 block px-4 py-2 text-sm' : 'text-gray-500 block px-4 py-2 text-sm'}
|
|
|
onClick={onMapOptionClick}
|
|
|
>
|
|
|
{option.name}
|
|
|
</a>
|
|
|
</Menu.Item>
|
|
|
))}
|
|
|
</div>
|
|
|
</Menu.Items>
|
|
|
</Transition>
|
|
|
</Menu>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<section aria-labelledby="products-heading" className="pt-6 pb-24">
|
|
|
<div className="grid grid-cols-1 gap-x-8 gap-y-10 md:grid-cols-4">
|
|
|
|
|
|
<form className="hidden md:block h-[65vh] px-1 py-1 overflow-y-scroll">
|
|
|
{/* Layers */}
|
|
|
<ul
|
|
|
role="list"
|
|
|
className="space-y-4 border-b border-gray-200 pb-6 text-sm font-medium text-gray-900"
|
|
|
>
|
|
|
{mapstyle.layers.map((layer) => (
|
|
|
<div key={layer.id} className="flex items-center">
|
|
|
<input
|
|
|
id={layer.id}
|
|
|
name={layer.id}
|
|
|
defaultValue={layer.id}
|
|
|
type="checkbox"
|
|
|
defaultChecked={true}
|
|
|
className="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
|
|
|
onChange={(event) => {
|
|
|
mapRef.current
|
|
|
.getMap()
|
|
|
.setLayoutProperty(
|
|
|
event.target.id,
|
|
|
"visibility",
|
|
|
event.target.checked ? "visible" : "none"
|
|
|
);
|
|
|
}}
|
|
|
/>
|
|
|
<label
|
|
|
htmlFor={layer.id}
|
|
|
className="ml-3 text-sm text-gray-600"
|
|
|
>
|
|
|
{layer.id}
|
|
|
</label>
|
|
|
</div>
|
|
|
))}
|
|
|
</ul>
|
|
|
|
|
|
{/* Legend */}
|
|
|
<Disclosure as="div" className="border-b border-gray-200 py-6">
|
|
|
{({ open }) => (
|
|
|
<>
|
|
|
<h3 className="-my-3 flow-root">
|
|
|
<Disclosure.Button className="flex w-full items-center justify-between bg-white py-3 text-sm text-gray-400 hover:text-gray-500">
|
|
|
<span className="font-medium text-gray-900">
|
|
|
Легенда
|
|
|
</span>
|
|
|
<span className="ml-6 flex items-center">
|
|
|
{open ? (
|
|
|
<ChevronUpIcon
|
|
|
className="h-5 w-5"
|
|
|
aria-hidden="true"
|
|
|
/>
|
|
|
) : (
|
|
|
<ChevronDownIcon
|
|
|
className="h-5 w-5"
|
|
|
aria-hidden="true"
|
|
|
/>
|
|
|
)}
|
|
|
</span>
|
|
|
</Disclosure.Button>
|
|
|
</h3>
|
|
|
<Disclosure.Panel className="pt-6">
|
|
|
<div className="space-y-4">
|
|
|
<p className="text-sm">Установленная мощность</p>
|
|
|
<div className="flex items-center"><span className="text-sm text-gray-600">{pointsSizes[0].value}</span><div className={"ml-3 rounded-full border-2 border-gray-400"} style={{ width: pointsSizes[0].size, height: pointsSizes[0].size }}></div><div className={`ml-5 rounded-full border-2 border-gray-400`} style={{ width: pointsSizes[1].size, height: pointsSizes[1].size }}></div><span className="ml-3 text-sm text-gray-600">{pointsSizes[1].value} МВт</span></div>
|
|
|
<p className="text-sm">ВИЭ-технология</p>
|
|
|
{pointsColors.map(e => <div key={e.name} className="flex items-center"><div className={"w-3 h-3 rounded-full"} style={{ backgroundColor: e.color }}></div><p className="ml-2 text-sm text-gray-600">{e.name}</p></div>)}
|
|
|
</div>
|
|
|
<div className="mt-4 space-y-4 text-xs text-gray-600">
|
|
|
<p >СЭС – солнечные электростанции</p>
|
|
|
<p>ВЭС – ветроэлектростанции</p>
|
|
|
<p>мГЭС – малые гидроэлектростанции</p>
|
|
|
<p>БиоЭС (биомасса) – биоэлектростанции на основе биомассы</p>
|
|
|
<p>БиоЭС (биогаз) – биоэлектростанции на основе биогаза</p>
|
|
|
<p>БиоЭС (свалочный газ) – биоэлектростанции на основе свалочного газа</p>
|
|
|
<p>ГеоЭС – геотермальные электростанции</p>
|
|
|
<p>ПЭС – приливные электростанции</p>
|
|
|
|
|
|
</div>
|
|
|
</Disclosure.Panel>
|
|
|
</>
|
|
|
)}
|
|
|
</Disclosure>
|
|
|
|
|
|
{/* Filters */}
|
|
|
{filters.map((section) => (
|
|
|
<Disclosure
|
|
|
as="div"
|
|
|
key={section.id}
|
|
|
className="border-b border-gray-200 py-6"
|
|
|
>
|
|
|
{({ open }) => (
|
|
|
<>
|
|
|
<h3 className="-my-3 flow-root">
|
|
|
<Disclosure.Button className="flex w-full items-center justify-between bg-white py-3 text-sm text-gray-400 hover:text-gray-500">
|
|
|
<span className="font-medium text-gray-900">
|
|
|
{section.name}
|
|
|
</span>
|
|
|
<span className="ml-6 flex items-center">
|
|
|
{open ? (
|
|
|
<ChevronUpIcon
|
|
|
className="h-5 w-5"
|
|
|
aria-hidden="true"
|
|
|
/>
|
|
|
) : (
|
|
|
<ChevronDownIcon
|
|
|
className="h-5 w-5"
|
|
|
aria-hidden="true"
|
|
|
/>
|
|
|
)}
|
|
|
</span>
|
|
|
</Disclosure.Button>
|
|
|
</h3>
|
|
|
<Disclosure.Panel className="pt-4">
|
|
|
<button value={section.id} onClick={addAllOptions} className="text-sm pb-3 text-gray-500">Добавить все</button>
|
|
|
<span className="text-sm pb-3 text-gray-500"> / </span>
|
|
|
<button value={section.id} onClick={clearAllOptions} className="text-sm pb-3 text-gray-500">Убрать все</button>
|
|
|
<div className="space-y-4">
|
|
|
{section.options.map((option, optionIdx) => (
|
|
|
<div
|
|
|
key={option.value}
|
|
|
className="flex items-center"
|
|
|
>
|
|
|
<input
|
|
|
id={`filter-${section.id}-${optionIdx}`}
|
|
|
name={`${section.id}`}
|
|
|
defaultValue={option.value}
|
|
|
type="checkbox"
|
|
|
checked={option.checked}
|
|
|
className="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
|
|
|
onChange={handleFilterToggle}
|
|
|
/>
|
|
|
<label
|
|
|
htmlFor={`filter-${section.id}-${optionIdx}`}
|
|
|
className="ml-3 text-sm text-gray-600"
|
|
|
>
|
|
|
{option.label}
|
|
|
</label>
|
|
|
{pointsColors.find(color => color.name == option.label) && <div className={"w-3 h-3 rounded-full ml-2"} style={{ backgroundColor: pointsColors.find(color => color.name == option.label).color }}></div>}
|
|
|
</div>
|
|
|
))}
|
|
|
</div>
|
|
|
</Disclosure.Panel>
|
|
|
</>
|
|
|
)}
|
|
|
</Disclosure>
|
|
|
))}
|
|
|
|
|
|
{/* Metadata */}
|
|
|
<Disclosure as="div" className="border-b border-gray-200 py-6">
|
|
|
{({ open }) => (
|
|
|
<>
|
|
|
<h3 className="-my-3 flow-root">
|
|
|
<Disclosure.Button className="flex w-full items-center justify-between bg-white py-3 text-sm text-gray-400 hover:text-gray-500">
|
|
|
<span className="font-medium text-gray-900">
|
|
|
Метаданные
|
|
|
</span>
|
|
|
<span className="ml-6 flex items-center">
|
|
|
{open ? (
|
|
|
<ChevronUpIcon
|
|
|
className="h-5 w-5"
|
|
|
aria-hidden="true"
|
|
|
/>
|
|
|
) : (
|
|
|
<ChevronDownIcon
|
|
|
className="h-5 w-5"
|
|
|
aria-hidden="true"
|
|
|
/>
|
|
|
)}
|
|
|
</span>
|
|
|
</Disclosure.Button>
|
|
|
</h3>
|
|
|
<Disclosure.Panel className="pt-6">
|
|
|
<div className="space-y-4">
|
|
|
<p className="text-sm">
|
|
|
© Ассоциация развития возобновляемой энергетики
|
|
|
</p>
|
|
|
</div>
|
|
|
</Disclosure.Panel>
|
|
|
</>
|
|
|
)}
|
|
|
</Disclosure>
|
|
|
</form>
|
|
|
|
|
|
{/* Map itself */}
|
|
|
<div className="md:col-span-3">
|
|
|
<div className="h-[65vh]">
|
|
|
<Map
|
|
|
initialViewState={{
|
|
|
latitude: mapstyle.center[0],
|
|
|
longitude: mapstyle.center[1],
|
|
|
zoom: mapstyle.zoom,
|
|
|
}}
|
|
|
minZoom={mapstyle.minZoom}
|
|
|
ref={mapRef}
|
|
|
mapboxAccessToken={MAPBOX_TOKEN}
|
|
|
interactiveLayerIds={["Объекты"]}
|
|
|
onClick={handleClick}
|
|
|
onMouseEnter={handleMouseEnter}
|
|
|
onMouseLeave={handleMouseLeave}
|
|
|
>
|
|
|
|
|
|
{open && <Popup
|
|
|
longitude={popupInfo.lon}
|
|
|
latitude={popupInfo.lat}
|
|
|
closeButton={false}
|
|
|
>
|
|
|
<h3>{popupInfo.res_name_parc}</h3>
|
|
|
{popupInfo.region_name}
|
|
|
</Popup>}
|
|
|
<ScaleControl />
|
|
|
<Source
|
|
|
id="basemap"
|
|
|
tileSize={512}
|
|
|
{...mapstyle.sources.basemap}
|
|
|
>
|
|
|
<Layer {...paintedLayers["Подложка"]} />
|
|
|
</Source>
|
|
|
<Source
|
|
|
id="remap"
|
|
|
{...mapstyle.sources.remap}
|
|
|
>
|
|
|
<Layer {...paintedLayers["Границы"]} />
|
|
|
<Layer {...paintedLayers["Объекты"]} filter={applyFilters(filters)} />
|
|
|
</Source>
|
|
|
</Map>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</section>
|
|
|
</main>
|
|
|
<Transition.Root show={open} as={Fragment}>
|
|
|
<Dialog as="div" className="relative z-10" onClose={setOpen}>
|
|
|
<Transition.Child
|
|
|
as={Fragment}
|
|
|
enter="ease-in-out duration-500"
|
|
|
enterFrom="opacity-0"
|
|
|
enterTo="opacity-100"
|
|
|
leave="ease-in-out duration-500"
|
|
|
leaveFrom="opacity-100"
|
|
|
leaveTo="opacity-0"
|
|
|
>
|
|
|
<div className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
|
|
|
</Transition.Child>
|
|
|
|
|
|
<div className="fixed inset-0 overflow-hidden">
|
|
|
<div className="absolute inset-0 overflow-hidden">
|
|
|
<div className="pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-10">
|
|
|
<Transition.Child
|
|
|
as={Fragment}
|
|
|
enter="transform transition ease-in-out duration-500 sm:duration-700"
|
|
|
enterFrom="translate-x-full"
|
|
|
enterTo="translate-x-0"
|
|
|
leave="transform transition ease-in-out duration-500 sm:duration-700"
|
|
|
leaveFrom="translate-x-0"
|
|
|
leaveTo="translate-x-full"
|
|
|
>
|
|
|
<Dialog.Panel className="pointer-events-auto relative w-screen max-w-md">
|
|
|
<Transition.Child
|
|
|
as={Fragment}
|
|
|
enter="ease-in-out duration-500"
|
|
|
enterFrom="opacity-0"
|
|
|
enterTo="opacity-100"
|
|
|
leave="ease-in-out duration-500"
|
|
|
leaveFrom="opacity-100"
|
|
|
leaveTo="opacity-0"
|
|
|
>
|
|
|
<div className="absolute top-0 left-0 -ml-8 flex pt-4 pr-2 sm:-ml-10 sm:pr-4">
|
|
|
<button
|
|
|
type="button"
|
|
|
className="rounded-md text-gray-300 hover:text-white focus:outline-none focus:ring-2 focus:ring-white"
|
|
|
onClick={() => setOpen(false)}
|
|
|
>
|
|
|
<span className="sr-only">Close panel</span>
|
|
|
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
|
|
|
</button>
|
|
|
</div>
|
|
|
</Transition.Child>
|
|
|
<div className="flex h-full flex-col overflow-y-scroll bg-white py-6 shadow-xl">
|
|
|
<div className="px-4 sm:px-6">
|
|
|
<Dialog.Title className="text-lg font-medium text-gray-900">{popupInfo && popupInfo.res_name_parc}</Dialog.Title>
|
|
|
</div>
|
|
|
<div className="relative mt-6 flex-1 px-4 sm:px-6">
|
|
|
{/* Replace with your content */}
|
|
|
{popupInfo && generatePopup(popupInfo)}
|
|
|
{/* /End replace */}
|
|
|
</div>
|
|
|
</div>
|
|
|
</Dialog.Panel>
|
|
|
</Transition.Child>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</Dialog>
|
|
|
</Transition.Root>
|
|
|
</div>
|
|
|
</div>
|
|
|
);
|
|
|
}
|