diff --git a/src/components/MlGeoCoding/MlGeoCoding.json b/src/components/MlGeoCoding/MlGeoCoding.json new file mode 100644 index 000000000..e47c15ae1 --- /dev/null +++ b/src/components/MlGeoCoding/MlGeoCoding.json @@ -0,0 +1,14 @@ +{ + "name": "MlGeoCoding", + "title": "", + "description": "", + "i18n": { + "de": { + "title": "", + "description": "" + } + }, + "tags": [], + "category": "", + "type": "component" +} diff --git a/src/components/MlGeoCoding/MlGeoCoding.stories.tsx b/src/components/MlGeoCoding/MlGeoCoding.stories.tsx new file mode 100644 index 000000000..59d74e6a4 --- /dev/null +++ b/src/components/MlGeoCoding/MlGeoCoding.stories.tsx @@ -0,0 +1,86 @@ +import React, { useEffect, useState } from 'react'; + +import MlGeoCoding from './MlGeoCoding'; + +import mapContextDecorator from '../../decorators/MapContextDecorator'; + +const storyoptions = { + title: 'MapComponents/MlGeoCoding', + component: MlGeoCoding, + argTypes: {}, + decorators: mapContextDecorator, + parameters: { docs: { source: { type: 'code' } } }, +}; + +export default storyoptions; +interface TemplateProps { + mapId: string; + label: string; +} + +const Template = (args: TemplateProps) => { + interface AutoCompleteOptionType { + title: string; + lat: number; + lng: number; + id: string | number; + } + + interface AddressType { + railway: string; + boundingbox: string[]; + class: string; + display_name: string; + importance: number; + lat: string; + licence: string; + lon: string; + name: string; + osm_id: number; + osm_type: string; + place_id: number; + place_rank: number; + type: string; + } + + const [searchValue, setSearchValue] = useState(''); + + const [autoCompleteOptionArr, setAutoCompleteOptionArr] = useState([ + + ]); + + useEffect(() => { + const apiUrl = `https://nominatim.openstreetmap.org/search?format=json&q=${searchValue},&limit=7`; + + searchValue && + fetch(apiUrl) + .then((res) => res.json()) + .then((res: AddressType[]) => { + console.log(res[0]); + const optionsResArr = res.map((el) => ({ + title: el.display_name, + lng: parseInt(el.lon), + lat: parseInt(el.lat), + id: el.place_id, + })); + setAutoCompleteOptionArr(optionsResArr); + }) + .catch((err) => console.error(err)); + }, [searchValue]); + + return ( + + ); +}; + +export const ExampleConfig = Template.bind({}); +ExampleConfig.parameters = {}; +ExampleConfig.args = { + mapId: 'map_1', + label: 'Search', +}; diff --git a/src/components/MlGeoCoding/MlGeoCoding.tsx b/src/components/MlGeoCoding/MlGeoCoding.tsx new file mode 100644 index 000000000..38c68e430 --- /dev/null +++ b/src/components/MlGeoCoding/MlGeoCoding.tsx @@ -0,0 +1,148 @@ +import React, { useEffect, useState } from 'react'; +import { + SxProps, + Theme, + ListItemText, + ListItem, + List, + ListItemButton, + Box, + InputLabel, + FormControl, + InputAdornment, + OutlinedInput, +} from '@mui/material'; +import SearchIcon from '@mui/icons-material/Search'; +import MlMarker from '../MlMarker/MlMarker'; +import useMap from '../../hooks/useMap'; + +// import +interface AddressType { + title: string; + lat: number; + long: number; + id: string | number; +} + +const inputStyle: SxProps = { + my: 1, + background: 'white', + borderRadius: '4px', +}; + +interface Point { + lng: number; + lat: number; +} + +export interface MlGeoCodingProp { + mapId: string; + label: string; + autoCompleteOptionArr: AddressType[]; + handleChangeVal: (newValue: string) => void; +} + +const MlGeoCoding = (props: MlGeoCodingProp) => { + const [selectedPoints, setSelectedPoints] = useState({ lng: 0, lat: 0 }); + const [listShowed, setListShowed] = useState(false); + const [loading, setLoading] = useState(false); + const [searchValue, setSearchValue] = useState(''); + + const handleChangeOutSideVal = (event: React.ChangeEvent) => { + setLoading(true); + setSearchValue(event.target.value); + props.handleChangeVal(event.target.value); + }; + + useEffect(() => { + if (props.autoCompleteOptionArr.length < 1) return; + setListShowed(true); + setLoading(false); + }, [props.autoCompleteOptionArr]); + + const mapHook = useMap({ + mapId: props.mapId, + }); + + const handleListItemClick = (points: Point, title: string) => { + setSelectedPoints(points); + setSearchValue(title); + + mapHook?.map?.map?.flyTo({ + center: [points.lng, points.lat], + zoom: 9, + speed: 1.75, + curve: 1, + }); + }; + + return ( + <> + setListShowed(false)} + > + + {props.label} + + + + } + /> + + + {listShowed === true ? ( + + {loading ? ( + + + + ) : props.autoCompleteOptionArr.length > 1 ? ( + props.autoCompleteOptionArr.map((el: AddressType) => ( + + handleListItemClick( + { + lng: el.long || 0, + lat: el.lat || 0, + }, + el?.title + ) + } + > + + + )) + ) : ( + + + + )} + + ) : null} + + + {(selectedPoints.lat || selectedPoints.lng) && ( + + )} + + ); +}; + +MlGeoCoding.defaultProps = { + mapId: 'map_1', + label: 'Search', +}; + +export default MlGeoCoding;