diff options
Diffstat (limited to 'frontend/ts/src/pages/map/markerForm.ts')
-rw-r--r-- | frontend/ts/src/pages/map/markerForm.ts | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/frontend/ts/src/pages/map/markerForm.ts b/frontend/ts/src/pages/map/markerForm.ts new file mode 100644 index 0000000..f04a008 --- /dev/null +++ b/frontend/ts/src/pages/map/markerForm.ts @@ -0,0 +1,172 @@ +import { h, Html, Rx } from 'lib/rx' +import * as rx from 'lib/rx' +import * as request from 'request' +import * as modal from 'ui/modal' +import * as layout from 'ui/layout' +import * as markerModel from 'models/marker' +import * as form from 'lib/form' +import * as icons from 'lib/icons' +import * as L from 'lib/loadable' + +interface MarkerFormParams { + lat: number + lng: number + marker?: markerModel.Marker + colors: Array<string> + label: string + req: (body: string) => Promise<markerModel.Marker> + onSuccess: (m: markerModel.Marker) => void + onClose: () => void + lastUserAdded?: markerModel.Marker + onDeleteMarker?: () => void +} + +export function view({ lat, lng, marker, colors, label, req, onSuccess, onClose, lastUserAdded, onDeleteMarker }: MarkerFormParams): Html { + const initName = marker?.name || '' + const initDescription = marker?.description || '' + const initColor = marker?.color || lastUserAdded?.color || (colors.length > 0 ? colors[0] : '#3584e4') + const initIcon = marker?.icon || '' + const initRadius = marker?.radius || 0 + + const isCreation = marker === undefined + + const iconValues: { [key: string]: string } = {} + Object.keys(icons.values).forEach(key => iconValues[key] = icons.values[key].name) + + return modal.view({ + header: marker == undefined ? 'Nouveau marqueur' : 'Modification du marqueur', + body: rx.withState7<string, string, string, string, number, L.Loadable<void>, L.Loadable<void>>( + [initName, initDescription, initColor, initIcon, initRadius, L.init, L.init], + (nameVar, descriptionVar, colorVar, iconVar, radiusVar, updateReqVar, deleteReqVar) => + h('form', + { + onsubmit: rx.map5([nameVar, descriptionVar, colorVar, iconVar, radiusVar], (name, description, color, icon, radius) => + (event: Event) => { + event.preventDefault() + updateReqVar.update(_ => L.loading) + const payload = { lat, lng, color, name, description, icon, radius } + + req(JSON.stringify(payload)) + .then((m: markerModel.Marker) => { + updateReqVar.update(_ => L.loaded(undefined)) + onSuccess(m) + }) + .catch(({ message }) => updateReqVar.update(_ => L.failure(message))) + } + ) + }, + form.input({ + label: 'Nom', + select: isCreation, + initValue: initName, + onUpdate: value => { + nameVar.update(_ => value) + updateReqVar.update(_ => L.init) + deleteReqVar.update(_ => L.init) + } + }), + form.textarea({ + label: 'Description', + initValue: initDescription, + onUpdate: value => { + descriptionVar.update(_ => value) + updateReqVar.update(_ => L.init) + deleteReqVar.update(_ => L.init) + } + }), + colorSection({ + colorRx: colorVar, + colors, + onUpdateColor: color => { + colorVar.update(_ => color) + updateReqVar.update(_ => L.init) + deleteReqVar.update(_ => L.init) + } + }), + layout.columns([ + form.select({ + label: 'IcĂ´ne', + initValue: initIcon, + values: iconValues, + onUpdate: value => { + iconVar.update(_ => value) + updateReqVar.update(_ => L.init) + deleteReqVar.update(_ => L.init) + } + }), + form.input({ + type: 'number', + label: 'Radius', + initValue: initRadius.toString(), + onUpdate: value => { + radiusVar.update(_ => parseInt(value) || 0) + updateReqVar.update(_ => L.init) + deleteReqVar.update(_ => L.init) + } + }) + ]), + form.error(updateReqVar), + form.error(deleteReqVar), + form.submit({ + label, + className: 'g-Button--FullWidth', + requestVar: updateReqVar, + disabled: deleteReqVar.map(l => l != L.init) + }), + marker !== undefined && onDeleteMarker !== undefined && form.button({ + style: 'margin-top: 1rem', + label: 'Supprimer', + className: 'g-Button--FullWidth g-Button--Danger', + requestVar: deleteReqVar, + disabled: updateReqVar.map(l => l != L.init), + onClick: () => { + deleteReqVar.update(_ => L.loading) + request + .del_(`/api/markers/${marker.id}`) + .then(_ => onDeleteMarker()) + .catch(({ message }) => updateReqVar.update(_ => L.failure(message))) + } + }) + ) + ), + onClose: onClose + }) +} + +interface ColorSectionParams { + colorRx: Rx<string>, + colors: Array<string>, + onUpdateColor: (color: string) => void, +} + +function colorSection({ colorRx, colors, onUpdateColor }: ColorSectionParams): Html { + return h('label', + { className: 'g-Label' }, + 'Couleur', + h('div', + { className: 'g-ColorLine' }, + h('input', + { + type: 'color', + className: 'g-Input', + oninput: (event: Event) => onUpdateColor((event.target as HTMLInputElement).value), + value: colorRx + } + ), + h('div', + { className: 'g-ColorButtons' }, + colors.map(c => + h('input', + { + type: 'button', + className: 'g-ColorButton', + style: `background-color: ${c}`, + onclick: (event: Event) => onUpdateColor(c) + } + ) + ) + ) + ) + ) + +} |