172 lines
4.5 KiB
TypeScript
172 lines
4.5 KiB
TypeScript
import { Coordinate } from 'ol/coordinate';
|
|
import { Component, createEffect, createSignal } from 'solid-js';
|
|
import { useNavigate } from '@solidjs/router';
|
|
|
|
import SearchIcon from '@suid/icons-material/Search';
|
|
import { useI18n } from '@solid-primitives/i18n';
|
|
import proj4 from 'proj4';
|
|
|
|
import style from './Finder.module.css';
|
|
import { Box, Button, IconButton, TextField } from '@suid/material';
|
|
import Dialog from '../dialog';
|
|
import { getMap, getState } from '../map';
|
|
import { Overlay } from 'ol';
|
|
import { fromLonLat } from 'ol/proj';
|
|
import WptEditDialog from '../wpt/WptEditDialog';
|
|
|
|
const [popup, setPopup] = createSignal<Overlay>();
|
|
const [open, setOpen] = createSignal(false);
|
|
let popupElement: HTMLElement;
|
|
|
|
export const findLocation = (
|
|
navigate: (url: string) => void,
|
|
coordinate: Coordinate
|
|
) => {
|
|
setOpen(false);
|
|
if (popup() === undefined) {
|
|
setPopup(
|
|
new Overlay({
|
|
element: popupElement,
|
|
positioning: 'center-center',
|
|
})
|
|
);
|
|
}
|
|
console.log({
|
|
caller: 'Finder / submitHandler / popup',
|
|
coordinate,
|
|
popup: popup(),
|
|
popupElement,
|
|
});
|
|
popup().setMap(getMap());
|
|
popup().setPosition(fromLonLat(coordinate));
|
|
getMap()?.addOverlay(popup());
|
|
|
|
navigate(
|
|
`/map/${getState().provider}/${coordinate[0]}/${coordinate[1]}/16/${
|
|
getState().rotation
|
|
}`
|
|
);
|
|
};
|
|
|
|
interface Props {}
|
|
|
|
const Finder: Component<Props> = (props) => {
|
|
const [searchString, setSearchString] = createSignal('');
|
|
const [popupContent, setPopupContent] = createSignal(<></>);
|
|
const [t, { add, locale, dict }] = useI18n();
|
|
const [coordinate, setCoordinate] = createSignal<Coordinate>();
|
|
const searchStringChangeHandler = (event: any) => {
|
|
setSearchString(event.target.value);
|
|
};
|
|
const navigate = useNavigate();
|
|
|
|
const popupCloseHandler = () => {
|
|
popup()?.setMap(null);
|
|
};
|
|
|
|
const submitHandler = () => {
|
|
const latLonRegExp = /(-?[0-9]+.[0-9]+)\s*,\s*(-?[0-9]+.[0-9]+)/;
|
|
const latLonMatch = searchString().match(latLonRegExp);
|
|
|
|
if (!!latLonMatch) {
|
|
setCoordinate([+latLonMatch[2], +latLonMatch[1]]);
|
|
setPopupContent(<>{latLonMatch[0]}</>);
|
|
console.log({
|
|
caller: 'Finder / submitHandler',
|
|
searchString: searchString(),
|
|
latLonMatch,
|
|
coordinate: coordinate(),
|
|
});
|
|
} else {
|
|
const utmRegExp = /([0-6]?[0-9])\s*([C-X])\s*([0-9]+)\s*([0-9]+)/;
|
|
const utmMatch = searchString().match(utmRegExp);
|
|
if (!!utmMatch) {
|
|
const utm = `+proj=utm +zone=${utmMatch[1]}`;
|
|
setCoordinate(proj4(utm, 'EPSG:4326', [+utmMatch[3], +utmMatch[4]]));
|
|
setPopupContent(
|
|
<>{`${coordinate()[0]}, ${coordinate()[1]} (UTM ${utmMatch[0]})`}</>
|
|
);
|
|
}
|
|
console.log({
|
|
caller: 'Finder / submitHandler',
|
|
searchString: searchString(),
|
|
utmMatch,
|
|
coordinate: coordinate(),
|
|
});
|
|
}
|
|
|
|
if (!!coordinate()) {
|
|
findLocation(navigate, coordinate());
|
|
}
|
|
};
|
|
|
|
const [openCreateWptDialog, setOpenCreateWptDialog] = createSignal(false);
|
|
|
|
const createWptCloseHandler = () => {
|
|
setOpenCreateWptDialog(false);
|
|
popupCloseHandler();
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<div class={style.control}>
|
|
<IconButton
|
|
onClick={() => {
|
|
setOpen(true);
|
|
}}
|
|
>
|
|
<SearchIcon />
|
|
</IconButton>
|
|
</div>
|
|
<Dialog
|
|
closeHandler={() => {
|
|
setOpen(false);
|
|
}}
|
|
open={open()}
|
|
title={t('search')}
|
|
>
|
|
<Box
|
|
component='form'
|
|
sx={{
|
|
width: '100%',
|
|
'& .MuiTextField-root': { m: 1, width: '100%' },
|
|
paddingTop: '5px',
|
|
}}
|
|
noValidate
|
|
autoComplete='off'
|
|
onSubmit={submitHandler}
|
|
method='dialog'
|
|
>
|
|
<TextField onChange={searchStringChangeHandler} />
|
|
</Box>
|
|
</Dialog>
|
|
<div class={style.ol_popup} ref={popupElement}>
|
|
<a
|
|
href='#'
|
|
onclick={popupCloseHandler}
|
|
class={style.ol_popup_closer}
|
|
></a>
|
|
<div>
|
|
<div>{popupContent()}</div>
|
|
<div>
|
|
<Button
|
|
onClick={() => {
|
|
setOpenCreateWptDialog(true);
|
|
}}
|
|
>
|
|
New waypoint
|
|
</Button>
|
|
</div>
|
|
<WptEditDialog
|
|
open={openCreateWptDialog}
|
|
closeHandler={createWptCloseHandler}
|
|
coordinate={coordinate}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default Finder;
|