|
|
|
|
@ -1,34 +1,25 @@
|
|
|
|
|
import { Popup } from "react-map-gl";
|
|
|
|
|
import { Button, Col, Row } from "antd";
|
|
|
|
|
import { twMerge } from "tailwind-merge";
|
|
|
|
|
import { TYPE_MAPPER } from "../config";
|
|
|
|
|
import { usePointSelection } from "../stores/usePointSelection";
|
|
|
|
|
import { useState } from "react";
|
|
|
|
|
|
|
|
|
|
const pointConfig = [
|
|
|
|
|
const popupConfig = [
|
|
|
|
|
{
|
|
|
|
|
field: "name",
|
|
|
|
|
name: "Название",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
field: "category",
|
|
|
|
|
name: "Тип",
|
|
|
|
|
formatter: (value) => TYPE_MAPPER[value],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Востребованность, у.е.",
|
|
|
|
|
formatter: (value) => Math.round(value),
|
|
|
|
|
field: "prediction_current",
|
|
|
|
|
name: "Прогнозный трафик",
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
export const MapPopup = ({ feature, lat, lng, onClose }) => {
|
|
|
|
|
const { include, selection, exclude } = usePointSelection();
|
|
|
|
|
|
|
|
|
|
const isSelected = selection.included.has(feature.properties.id);
|
|
|
|
|
|
|
|
|
|
const handleSelect = () =>
|
|
|
|
|
isSelected
|
|
|
|
|
? exclude(feature.properties.id)
|
|
|
|
|
: include(feature.properties.id);
|
|
|
|
|
|
|
|
|
|
const PopupWrapper = ({ lat, lng, onClose, children }) => {
|
|
|
|
|
return (
|
|
|
|
|
<Popup
|
|
|
|
|
longitude={lng}
|
|
|
|
|
@ -37,14 +28,38 @@ export const MapPopup = ({ feature, lat, lng, onClose }) => {
|
|
|
|
|
onClose={onClose}
|
|
|
|
|
closeOnClick={false}
|
|
|
|
|
>
|
|
|
|
|
{children}
|
|
|
|
|
</Popup>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const SingleFeaturePopup = ({ feature, onSelect }) => {
|
|
|
|
|
const { include, selection, exclude } = usePointSelection();
|
|
|
|
|
const doesMatchFilter = feature.layer.id === "match-points";
|
|
|
|
|
|
|
|
|
|
const isSelected =
|
|
|
|
|
(doesMatchFilter || selection.included.has(feature.properties.id)) &&
|
|
|
|
|
!selection.excluded.has(feature.properties.id);
|
|
|
|
|
|
|
|
|
|
const handleSelect = () => {
|
|
|
|
|
if (isSelected) {
|
|
|
|
|
exclude(feature.properties.id);
|
|
|
|
|
} else {
|
|
|
|
|
include(feature.properties.id);
|
|
|
|
|
}
|
|
|
|
|
onSelect();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<div>
|
|
|
|
|
{Object.entries(feature.properties).map(([key, value]) => {
|
|
|
|
|
{popupConfig.map(({ field, name }) => {
|
|
|
|
|
return (
|
|
|
|
|
<Row className={twMerge("p-1")} key={key}>
|
|
|
|
|
<Row className={twMerge("p-1")} key={field}>
|
|
|
|
|
<Col className={"font-semibold"} span={15}>
|
|
|
|
|
{key}
|
|
|
|
|
{name}
|
|
|
|
|
</Col>
|
|
|
|
|
<Col span={9}>{value}</Col>
|
|
|
|
|
<Col span={9}>{feature.properties[field]}</Col>
|
|
|
|
|
</Row>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
@ -52,6 +67,56 @@ export const MapPopup = ({ feature, lat, lng, onClose }) => {
|
|
|
|
|
<Button type="text" className="mt-2 mx-auto" block onClick={handleSelect}>
|
|
|
|
|
{isSelected ? "Исключить из выборки" : "Добавить в выборку"}
|
|
|
|
|
</Button>
|
|
|
|
|
</Popup>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const MultipleFeaturesPopup = ({ features, onSelect }) => {
|
|
|
|
|
return (
|
|
|
|
|
<div className="space-y-2 p-1">
|
|
|
|
|
{features.map((feature) => {
|
|
|
|
|
return (
|
|
|
|
|
<Button
|
|
|
|
|
type={feature.layer.id === "match-points" ? "primary" : "text"}
|
|
|
|
|
className="flex items-center gap-x-1"
|
|
|
|
|
block
|
|
|
|
|
onClick={() => onSelect(feature)}
|
|
|
|
|
key={feature.properties.id}
|
|
|
|
|
>
|
|
|
|
|
<span>{feature.properties.id}</span>
|
|
|
|
|
<span>{feature.properties.category}</span>
|
|
|
|
|
</Button>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const MapPopup = ({ features, lat, lng, onClose }) => {
|
|
|
|
|
const [selectedFeature, setSelectedFeature] = useState(null);
|
|
|
|
|
|
|
|
|
|
const getContent = () => {
|
|
|
|
|
if (features.length === 1) {
|
|
|
|
|
return <SingleFeaturePopup feature={features[0]} onSelect={onClose} />;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (selectedFeature) {
|
|
|
|
|
return (
|
|
|
|
|
<SingleFeaturePopup feature={selectedFeature} onSelect={onClose} />
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<MultipleFeaturesPopup
|
|
|
|
|
features={features}
|
|
|
|
|
onSelect={setSelectedFeature}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<PopupWrapper lat={lat} lng={lng} onClose={onClose}>
|
|
|
|
|
{getContent()}
|
|
|
|
|
</PopupWrapper>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|