|
|
import { Empty, TreeSelect } from "antd";
|
|
|
import { Title } from "../../components/Title";
|
|
|
import { useRegion } from "../../stores/useRegion";
|
|
|
import { useEffect, useMemo, useState } from "react";
|
|
|
import { useMap } from "react-map-gl";
|
|
|
import getBbox from "@turf/bbox";
|
|
|
import { polygon as getPolygon } from "@turf/helpers";
|
|
|
import { useRegionGeometry } from "../../stores/useRegionGeometry";
|
|
|
import { api } from "../../api";
|
|
|
|
|
|
const { TreeNode } = TreeSelect;
|
|
|
|
|
|
const normalizeRegions = (rawRegions) => {
|
|
|
if (!rawRegions) return {};
|
|
|
|
|
|
return rawRegions.reduce((acc, raw) => {
|
|
|
acc[`ao-${raw.id}`] = raw;
|
|
|
if (raw.children) {
|
|
|
raw.children.forEach((child) => {
|
|
|
acc[`rayon-${child.id}`] = child;
|
|
|
});
|
|
|
}
|
|
|
return acc;
|
|
|
}, {});
|
|
|
};
|
|
|
|
|
|
export const RegionSelect = () => {
|
|
|
const { current: map } = useMap();
|
|
|
const { region, setRegion } = useRegion();
|
|
|
const { setRegionGeometry } = useRegionGeometry();
|
|
|
const [data, setData] = useState([]);
|
|
|
const normalizedData = useMemo(() => normalizeRegions(data), [data]);
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
|
|
useEffect(() => {
|
|
|
const getRegions = async () => {
|
|
|
setLoading(true);
|
|
|
try {
|
|
|
const response = await api.get(
|
|
|
"https://postamates.spatiality.website/api/ao_and_rayons"
|
|
|
);
|
|
|
setData(response.data);
|
|
|
} catch (err) {
|
|
|
console.error(err);
|
|
|
} finally {
|
|
|
setLoading(false);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
getRegions();
|
|
|
}, []);
|
|
|
|
|
|
const onChange = (value) => {
|
|
|
if (!value) return;
|
|
|
|
|
|
const selectedRegion = normalizedData[value];
|
|
|
|
|
|
const polygon = getPolygon(selectedRegion.geometry[0]);
|
|
|
const bbox = getBbox(polygon);
|
|
|
|
|
|
setRegionGeometry(polygon);
|
|
|
setRegion(value);
|
|
|
|
|
|
map.fitBounds(
|
|
|
[
|
|
|
[bbox[0], bbox[1]], // southwestern corner of the bounds
|
|
|
[bbox[2], bbox[3]], // northeastern corner of the bounds
|
|
|
],
|
|
|
{
|
|
|
padding: 20,
|
|
|
}
|
|
|
);
|
|
|
};
|
|
|
|
|
|
const handleClear = () => {
|
|
|
setRegion(null);
|
|
|
setRegionGeometry(null);
|
|
|
};
|
|
|
|
|
|
return (
|
|
|
<div>
|
|
|
<Title text={"АО / район"} />
|
|
|
<TreeSelect
|
|
|
showSearch
|
|
|
style={{ width: "100%" }}
|
|
|
value={region}
|
|
|
dropdownStyle={{ maxHeight: 400, overflow: "auto" }}
|
|
|
placeholder="Выберите АО или район"
|
|
|
allowClear
|
|
|
treeDefaultExpandAll={false}
|
|
|
onChange={onChange}
|
|
|
loading={loading}
|
|
|
treeNodeFilterProp="title"
|
|
|
onClear={handleClear}
|
|
|
notFoundContent={
|
|
|
<Empty
|
|
|
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
|
|
description={"Не найдено"}
|
|
|
/>
|
|
|
}
|
|
|
>
|
|
|
{data?.map((parent) => {
|
|
|
return (
|
|
|
<TreeNode
|
|
|
key={`ao-${parent.id}`}
|
|
|
value={`ao-${parent.id}`}
|
|
|
title={parent.name}
|
|
|
>
|
|
|
{parent.children?.map((child) => (
|
|
|
<TreeNode
|
|
|
key={`rayon-${child.id}`}
|
|
|
value={`rayon-${child.id}`}
|
|
|
title={child.name}
|
|
|
/>
|
|
|
))}
|
|
|
</TreeNode>
|
|
|
);
|
|
|
})}
|
|
|
</TreeSelect>
|
|
|
</div>
|
|
|
);
|
|
|
};
|