diff --git a/src/Map/MapComponent.jsx b/src/Map/MapComponent.jsx
index 8a7c8a3..d9b3030 100644
--- a/src/Map/MapComponent.jsx
+++ b/src/Map/MapComponent.jsx
@@ -9,11 +9,13 @@ import { SignOut } from "../SignOut";
import debounce from "lodash.debounce";
import { Table } from "../modules/Table/Table";
import { usePopup } from "../stores/usePopup";
+import { useClickedPoint } from "../stores/useClickedPoint";
export const MapComponent = () => {
const mapRef = useRef(null);
const mapContainerRef = useRef(null);
const { popup, setPopup } = usePopup();
+ const { setClickedPoint } = useClickedPoint();
const handleClick = (event) => {
if (!event.features) {
@@ -94,7 +96,10 @@ export const MapComponent = () => {
lat={popup.coordinates[1]}
lng={popup.coordinates[0]}
features={popup.features}
- onClose={() => setPopup(null)}
+ onClose={() => {
+ setPopup(null);
+ setClickedPoint(null);
+ }}
/>
)}
diff --git a/src/Map/Popup.jsx b/src/Map/Popup.jsx
index 4fff60f..00f053a 100644
--- a/src/Map/Popup.jsx
+++ b/src/Map/Popup.jsx
@@ -2,24 +2,95 @@ import { Popup } from "react-map-gl";
import { Button, Col, Row } from "antd";
import { twMerge } from "tailwind-merge";
import { usePointSelection } from "../stores/usePointSelection";
-import { useState } from "react";
+import { useEffect, useState } from "react";
+import { CATEGORIES } from "../config";
+import { useQuery } from "@tanstack/react-query";
+import { api } from "../api";
+import { useClickedPoint } from "../stores/useClickedPoint";
const popupConfig = [
{
+ name: "Id",
field: "id",
- name: "id",
},
{
- field: "name",
+ name: "Адрес",
+ field: "address",
+ },
+ {
+ name: "Район",
+ field: "rayon_id",
+ },
+ {
+ name: "Округ",
+ field: "okrug_id",
+ },
+ {
name: "Название",
+ field: "name",
},
{
+ name: "Категория",
field: "category",
- name: "Тип",
},
{
+ name: "Статус",
+ field: "status",
+ },
+ {
+ name: "Прогнозный трафик",
field: "prediction_current",
+ },
+];
+
+const residentialPointConfig = [
+ {
+ name: "Id",
+ field: "id",
+ },
+ {
+ name: "Адрес",
+ field: "address",
+ },
+ {
+ name: "Район",
+ field: "rayon_id",
+ },
+ {
+ name: "Округ",
+ field: "okrug_id",
+ },
+ {
+ name: "Название",
+ field: "name",
+ },
+ {
+ name: "Категория",
+ field: "category",
+ },
+ {
+ name: "Статус",
+ field: "status",
+ },
+ {
name: "Прогнозный трафик",
+ field: "prediction_current",
+ },
+ {
+ name: "Кол-во квартир",
+ field: "flat_cnt",
+ },
+ {
+ name: "Год постройки",
+ field: "year_bld",
+ },
+ {
+ name: "Кол-во этажей",
+ field: "levels",
+ },
+ {
+ name: "Материал стен",
+ field: "mat_nes",
},
];
@@ -28,9 +99,9 @@ const PopupWrapper = ({ lat, lng, onClose, children }) => {
{children}
@@ -39,17 +110,44 @@ const PopupWrapper = ({ lat, lng, onClose, children }) => {
const SingleFeaturePopup = ({ feature, onSelect }) => {
const { include, selection, exclude } = usePointSelection();
+ const { setClickedPoint } = useClickedPoint();
const doesMatchFilter = feature.layer.id === "match-points";
+ const featureId = feature.properties.id;
+ const locationId = feature.properties.location_id;
+
+ const { data } = useQuery(["clicked-point", locationId], async () => {
+ const params = new URLSearchParams({
+ "location_ids[]": [locationId],
+ });
+
+ const { data } = await api.get(
+ `/api/placement_points?${params.toString()}`
+ );
+
+ return data;
+ });
+
+ useEffect(() => {
+ if (!data) {
+ return;
+ }
+
+ setClickedPoint(data.results[0]);
+ }, [data]);
+
+ const isResidential = feature.properties.category === CATEGORIES.residential;
+
+ const config = isResidential ? residentialPointConfig : popupConfig;
const isSelected =
- (doesMatchFilter || selection.included.has(feature.properties.id)) &&
- !selection.excluded.has(feature.properties.id);
+ (doesMatchFilter || selection.included.has(featureId)) &&
+ !selection.excluded.has(featureId);
const handleSelect = () => {
if (isSelected) {
- exclude(feature.properties.id);
+ exclude(featureId);
} else {
- include(feature.properties.id);
+ include(featureId);
}
onSelect();
};
@@ -57,13 +155,13 @@ const SingleFeaturePopup = ({ feature, onSelect }) => {
return (
<>
- {popupConfig.map(({ field, name }) => {
+ {config.map(({ field, name }) => {
return (
-
+
{name}
- {feature.properties[field]}
+ {feature.properties[field]}
);
})}
diff --git a/src/config.js b/src/config.js
index 0a276e3..f3d2637 100644
--- a/src/config.js
+++ b/src/config.js
@@ -1,20 +1,15 @@
-export const factorsNameMapper = {
- people: "Численность населения в 2021 г.",
- people2025: "Численность населения в 2025 г. (прогноз)",
- stops_ot: "Остановки общественного транспорта",
- routes_ot: "Маршруты общетвенного транспорта",
- in_metro: "Входы в ближайшее метро в месяц",
- out_metro: "Выходы из ближайшего метро в месяц",
- tc: "Тогровые центры",
- empls: "Рабочие места",
- walkers: "Трафик населения",
- schools: "Школы и детские сады",
- parking: "Парковочные места",
- pvz: "Пункты выдачи заказов",
- gov_place: "Рекомендованные пункты размещения постаматов",
- bike_park: "Городская аренда велосипедов, шт.",
- products: "Продовольственные магазины",
- nonprod: "Непродовольственные магазины",
- service: "Пункты оказания бытовых услуг",
- vuz: "ВУЗы и техникумы",
+export const STATUSES = {
+ toWork: "К рассмотрению",
+ approve: "Согласование-установка",
+ working: "Работает",
+};
+
+export const CATEGORIES = {
+ kiosk: "Городской киоск",
+ mfc: "МФЦ",
+ library: "Библиотека",
+ sport: "Спортивный объект",
+ retail: "Ритейл",
+ residential: "Подъезд жилого дома",
+ culture: "Дом культуры/Клуб",
};
diff --git a/src/index.css b/src/index.css
index 008640b..86bbc70 100644
--- a/src/index.css
+++ b/src/index.css
@@ -21,6 +21,11 @@
@apply border-t-grey-light;
}
+.mapboxgl-popup-anchor-top .mapboxgl-popup-tip,
+.maplibregl-popup-anchor-top .maplibregl-popup-tip {
+ @apply border-b-grey-light;
+}
+
.ant-popover-inner {
@apply bg-white-background rounded-xl max-h-[calc(100vh-100px)] overflow-y-auto;
}
diff --git a/src/modules/Sidebar/ObjectTypesSelect.jsx b/src/modules/Sidebar/ObjectTypesSelect.jsx
index 2e48c51..bc08ffd 100644
--- a/src/modules/Sidebar/ObjectTypesSelect.jsx
+++ b/src/modules/Sidebar/ObjectTypesSelect.jsx
@@ -3,22 +3,7 @@ import { twMerge } from "tailwind-merge";
import { Title } from "../../components/Title";
import { useFilters } from "../../stores/useFilters";
import { useHasManualEdits } from "../../stores/usePointSelection";
-
-//kiosk - городские киоски
-// mfc - многофункциональные центры предоставления государственных и муниципальных услуг
-// library - библиотеки
-// dk - дома культуры и клубы
-// sport - спортивные объекты
-
-const types = [
- "Городской киоск",
- "МФЦ",
- "Библиотека",
- "Спортивный объект",
- "Ритейл",
- "Подъезд жилого дома",
- "Дом культуры/Клуб",
-];
+import { CATEGORIES } from "../../config";
const SelectItem = ({ name, isActive, onClick, disabled }) => {
return (
@@ -48,7 +33,7 @@ export const ObjectTypesSelect = () => {
return (
-
+
{filters.categories.length !== 0 && (
- {types.map((type) => (
+ {Object.entries(CATEGORIES).map(([key, value]) => (
handleClick(type)}
+ key={key}
+ name={value}
+ isActive={filters.categories.includes(value)}
+ onClick={() => handleClick(value)}
disabled={hasManualEdits}
/>
))}
diff --git a/src/modules/Sidebar/PredictionSlider.jsx b/src/modules/Sidebar/PredictionSlider.jsx
index f5da42d..44cc5c9 100644
--- a/src/modules/Sidebar/PredictionSlider.jsx
+++ b/src/modules/Sidebar/PredictionSlider.jsx
@@ -8,11 +8,15 @@ import { useHasManualEdits } from "../../stores/usePointSelection";
export const PredictionSlider = () => {
const { filters, setPrediction } = useFilters();
const hasManualEdits = useHasManualEdits();
- const { data } = useQuery(["max-min"], async () => {
- const { data } = await api.get(`/api/placement_points/filters`);
-
- return data;
- });
+ const { data } = useQuery(
+ ["max-min"],
+ async () => {
+ const { data } = await api.get(`/api/placement_points/filters`);
+
+ return data;
+ },
+ { enabled: false }
+ );
const handleAfterChange = (range) => setPrediction(range);
@@ -29,7 +33,7 @@ export const PredictionSlider = () => {
return (
{
const getRegions = async () => {
setLoading(true);
try {
- const response = await api.get(
- "https://postnet-dev.selftech.ru/api/ao_and_rayons"
- );
+ const response = await api.get("/api/ao_and_rayons");
setData(response.data);
} catch (err) {
console.error(err);
diff --git a/src/modules/Sidebar/Sidebar.jsx b/src/modules/Sidebar/Sidebar.jsx
index 59820b9..7d657ae 100644
--- a/src/modules/Sidebar/Sidebar.jsx
+++ b/src/modules/Sidebar/Sidebar.jsx
@@ -10,6 +10,7 @@ import {
useHasManualEdits,
usePointSelection,
} from "../../stores/usePointSelection";
+import { TakeToWorkButton } from "./TakeToWorkButton";
function download(filename, data) {
const downloadLink = window.document.createElement("a");
@@ -83,7 +84,7 @@ export const Sidebar = () => {
};
return (
-
+
@@ -100,9 +101,7 @@ export const Sidebar = () => {
>
Экспорт данных
-
+
{hasManualEdits ? (