parent
958726e783
commit
057a9416b5
@ -0,0 +1,82 @@
|
||||
import { AutoComplete, Input } from "antd";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { SearchOutlined } from "@ant-design/icons";
|
||||
import { api } from "../../api";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useMap } from "react-map-gl";
|
||||
import parse from "wellknown";
|
||||
|
||||
function useDebounce(value, delay) {
|
||||
const [debouncedValue, setDebouncedValue] = useState(value);
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => setDebouncedValue(value), delay || 500);
|
||||
return () => {
|
||||
clearTimeout(timer);
|
||||
};
|
||||
}, [value, delay]);
|
||||
|
||||
return debouncedValue;
|
||||
}
|
||||
|
||||
export const AddressSearch = () => {
|
||||
const { map } = useMap();
|
||||
const [value, setValue] = useState("");
|
||||
const debouncedValue = useDebounce(value);
|
||||
|
||||
const { data } = useQuery(["address", debouncedValue], async () => {
|
||||
const result = await api.get(
|
||||
`/api/placement_points/search_address?page_size=100&address=${debouncedValue}`
|
||||
);
|
||||
|
||||
return result.data;
|
||||
});
|
||||
|
||||
const options = useMemo(() => {
|
||||
if (!data) return [];
|
||||
|
||||
return data.results.map((item) => ({
|
||||
label: item.address,
|
||||
value: `${item.address}$${item.location_id}`,
|
||||
item: item,
|
||||
}));
|
||||
}, [data]);
|
||||
|
||||
const handleChange = (value) => {
|
||||
if (!value) {
|
||||
setValue(value);
|
||||
} else {
|
||||
setValue(value.split("$")[0]);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSelect = (_value, option) => {
|
||||
const geometry = parse(option.item.geometry);
|
||||
map.flyTo({
|
||||
center: [geometry.coordinates[0], geometry.coordinates[1]],
|
||||
zoom: 15,
|
||||
speed: 5,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="absolute top-[20px] left-[360px]">
|
||||
<AutoComplete
|
||||
options={options}
|
||||
style={{
|
||||
width: 300,
|
||||
}}
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
onSelect={handleSelect}
|
||||
allowClear={true}
|
||||
onClear={() => setValue("")}
|
||||
>
|
||||
<Input
|
||||
prefix={<SearchOutlined />}
|
||||
placeholder="Введите адрес точки"
|
||||
className="text-ellipsis"
|
||||
/>
|
||||
</AutoComplete>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,36 @@
|
||||
import { Radio } from "antd";
|
||||
import { MODES } from "../../config";
|
||||
import { useMode } from "../../stores/useMode";
|
||||
|
||||
const modeOptions = [
|
||||
{
|
||||
label: "ЛКР",
|
||||
value: MODES.INITIAL,
|
||||
},
|
||||
{
|
||||
label: "ЛВР",
|
||||
value: MODES.APPROVE,
|
||||
},
|
||||
{
|
||||
label: "РП",
|
||||
value: MODES.WORKING,
|
||||
},
|
||||
];
|
||||
|
||||
export const Header = () => {
|
||||
const { mode, setMode } = useMode();
|
||||
|
||||
const handleModeChange = ({ target: { value } }) => setMode(value);
|
||||
|
||||
return (
|
||||
<div className="mb-4">
|
||||
<Radio.Group
|
||||
options={modeOptions}
|
||||
onChange={handleModeChange}
|
||||
value={mode}
|
||||
optionType="button"
|
||||
buttonStyle="solid"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,15 @@
|
||||
import { create } from "zustand";
|
||||
import { immer } from "zustand/middleware/immer";
|
||||
import { MODES } from "../config";
|
||||
|
||||
const store = (set) => ({
|
||||
mode: MODES.INITIAL,
|
||||
|
||||
setMode: (mode) => {
|
||||
set((state) => {
|
||||
state.mode = mode;
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export const useMode = create(immer(store));
|
||||
Loading…
Reference in new issue