dyomedea/src/components/wpt/WptEditDialog.tsx

296 lines
7.7 KiB
TypeScript

import {
Box,
Button,
FormControl,
InputLabel,
NativeSelect,
Stack,
TextField,
} from '@suid/material';
import { Component, createEffect, createSignal, Show } from 'solid-js';
import { useI18n } from '@solid-primitives/i18n';
import Dialog from '../dialog';
import {
cachedSignalValue,
peekCachedSignal,
} from '../../workers/cached-signals';
import dispatch from '../../workers/dispatcher-main';
import { emptyWpt } from '../../db/wpt';
import GpxChooser from '../gpx-chooser';
import { currentGpxId } from '../gpx-dialog';
import { emptyGpx } from '../../db/gpx';
import getUri from '../../lib/ids';
import { Coordinate } from 'ol/coordinate';
export enum Category {
NOTE = 'note',
POI = 'poi',
PICTURE = 'picture',
UNKNOWN = '',
}
export enum SubCategory {
ACCOMMODATION = 'accommodation',
UNKNOWN = '',
}
interface Props {
wptId?: string;
coordinate?: () => Coordinate | undefined;
open: () => boolean;
closeHandler?: () => void;
initialWpt: () => Wpt;
imageUrl?: string | undefined;
}
const WptEditDialog: Component<Props> = (props) => {
const {
wptId,
closeHandler,
open,
coordinate,
initialWpt = () => emptyWpt,
imageUrl,
} = props;
const [t, { add, locale, dict }] = useI18n();
const wpt = !!wptId
? peekCachedSignal({ id: wptId, method: 'getWpt' })
: initialWpt;
const [gpxId, setGpxId] = !wptId
? createSignal<string>(currentGpxId())
: [() => '', () => {}];
createEffect(() => {
setGpxId(currentGpxId());
});
const [editedWpt, setEditedWpt] = createSignal<Wpt>();
createEffect(() => {
console.log({
caller: 'WptEditDialog / createEffect',
wptId,
gpxId: gpxId(),
wpt: wpt(),
});
const newWpt = editedWpt() || wpt();
if (!!coordinate && !!coordinate()) {
newWpt.$.lon = coordinate()[0];
newWpt.$.lat = coordinate()[1];
}
console.log({
caller: 'WptEditDialog / createEffect',
wptId,
gpxId: gpxId(),
wpt: wpt(),
newWpt,
});
setEditedWpt(newWpt);
});
const _closeHandler = () => {
if (!!closeHandler) {
closeHandler();
}
};
const saveHandler = async () => {
console.log({
caller: 'WptEditDialog / saveHandler',
wptId,
editedWpt: editedWpt(),
});
let newWptId = wptId;
if (!newWptId) {
if (gpxId() === 'new') {
const id = (await dispatch({
action: 'putGpx',
params: {
id: 'new',
gpx: emptyGpx,
},
})) as string;
setGpxId(id);
}
const gpx = await cachedSignalValue({ method: 'getGpx', id: gpxId() });
const gpxIdObj = getUri('gpx', gpxId());
const lastWptId = gpx.wpt?.at(-1);
const lastWptIdObj = !!lastWptId
? getUri('wpt', lastWptId)
: {
gpx: gpxIdObj.gpx,
wpt: -1,
};
newWptId = getUri('wpt', { ...lastWptIdObj, wpt: lastWptIdObj.wpt + 1 });
}
console.log({
caller: 'WptEditDialog / saveHandler',
wptId,
editedWpt: editedWpt(),
newWptId,
});
dispatch({
action: 'putWpt',
params: { id: newWptId, wpt: editedWpt() },
});
setEditedWpt(undefined);
_closeHandler();
};
const getTitle = () => {
if (wpt()?.name) {
return `${wpt()?.name} (${t('wpt')})`;
}
return t('wpt');
};
// <TextField
// label={t('sym')}
// defaultValue={wpt()?.sym}
// onChange={(event: any, value: string) => {
// setEditedWpt({ ...editedWpt(), sym: value });
// }}
// />
// <TextField
// label={t('minZoom')}
// defaultValue={wpt()?.extensions?.['dyo:minZoom']?.toString()}
// onChange={(event: any, value: string) => {
// const extensions = {
// ...editedWpt()?.extensions,
// 'dyo:minZoom': parseFloat(value),
// };
// setEditedWpt({ ...editedWpt(), extensions });
// }}
// />
return (
<Dialog
open={open() && !!wpt()}
title={getTitle()}
closeHandler={_closeHandler}
>
<Show when={!wptId}>
<GpxChooser gpxId={gpxId} setGpxId={setGpxId} />
</Show>
<Box
component='form'
sx={{
width: '100%',
'& .MuiTextField-root': { m: 1, width: '100%' },
paddingTop: '5px',
}}
noValidate
autoComplete='off'
>
<div>
<TextField
required
label={t('name')}
defaultValue={wpt()?.name}
onChange={(event: any, value: string) => {
setEditedWpt({ ...editedWpt(), name: value });
}}
/>
<FormControl>
<InputLabel variant='normal' htmlFor='category'>
Type
</InputLabel>
<NativeSelect
inputProps={{
name: 'category',
id: 'category',
}}
onChange={(event: any, value: string) => {
setEditedWpt({
...editedWpt(),
extensions: { ...editedWpt().extensions, category: value },
});
}}
>
<option
value={Category.POI}
selected={editedWpt()?.extensions?.category === Category.POI}
>
Point d'intérêt
</option>
<option
value={Category.NOTE}
selected={editedWpt()?.extensions?.category === Category.NOTE}
>
Note
</option>
<option
value={Category.PICTURE}
selected={
editedWpt()?.extensions?.category === Category.PICTURE
}
>
Picture
</option>
<option
value={undefined}
selected={!editedWpt()?.extensions?.category}
>
Autre
</option>
</NativeSelect>
</FormControl>
<TextField
label={t('gpxDesc')}
type='text'
rows={5}
multiline={true}
value={editedWpt()?.desc || ''}
onChange={(event: any) => {
setEditedWpt({ ...editedWpt(), desc: event.target.value });
}}
InputProps={{ inputComponent: 'textarea' }}
/>
<TextField
label='Début'
type='datetime-local'
value={(editedWpt()?.extensions?.startTime || '').replace('Z', '')}
onChange={(event: any) => {
setEditedWpt({
...editedWpt(),
extensions: {
...editedWpt().extensions,
startTime: new Date(event.target.value).toISOString(),
},
});
}}
/>
<TextField
label='Fin'
type='datetime-local'
value={(editedWpt()?.extensions?.endTime || '').replace('Z', '')}
onChange={(event: any) => {
setEditedWpt({
...editedWpt(),
extensions: {
...editedWpt().extensions,
endTime: new Date(event.target.value).toISOString(),
},
});
}}
/>
<Stack spacing={2} direction='row' sx={{ marginTop: '20px' }}>
<Button variant='outlined' color='secondary' onClick={closeHandler}>
{t('cancel')}
</Button>
<Button variant='contained' color='success' onClick={saveHandler}>
{t('save')}
</Button>
</Stack>
</div>
</Box>
</Dialog>
);
};
export default WptEditDialog;