diff options
author | Joris | 2021-05-20 09:43:02 +0200 |
---|---|---|
committer | Joris | 2021-05-20 09:43:02 +0200 |
commit | f9e7e819a0a673befb11b24404efeb9d6644bceb (patch) | |
tree | 07fdcc252964382568236647e74709980dc479d4 /src/view/form.ts | |
parent | cde24cbf3fbc418af3c98d82e47dcd5df71e5b26 (diff) |
Provide named exercices
Diffstat (limited to 'src/view/form.ts')
-rw-r--r-- | src/view/form.ts | 178 |
1 files changed, 151 insertions, 27 deletions
diff --git a/src/view/form.ts b/src/view/form.ts index b0d5827..a5e7253 100644 --- a/src/view/form.ts +++ b/src/view/form.ts @@ -3,25 +3,6 @@ import h from 'h' import * as Router from 'router' import * as Duration from 'duration' -function labelledInput( - labelValue: string, - min: number, - value: number, - update: (n: number) => void -): Element { - return h('label', - { className: 'g-Form__Label', - oninput: (e: Event) => { - if (e.target !== null) { - const target = e.target as HTMLInputElement - update(parseInt(target.value) || 0) - } - } - }, - labelValue, - h('input', { className: 'g-Form__Input', type: 'number', min, value })) -} - export function view(config: Config.Config, showPage: (route: Router.Route) => void) { const duration = document.createTextNode(Duration.prettyPrint(Config.getDuration(config))) const wd = () => duration.textContent = Duration.prettyPrint(Config.getDuration(config)) @@ -36,13 +17,156 @@ export function view(config: Config.Config, showPage: (route: Router.Route) => v history.pushState({}, '', Router.toString(timerRoute)) showPage(timerRoute) }}, - labelledInput('Warm Up', 0, config.warmup, n => { config.warmup = n; wd()}), - labelledInput('Tabatas', 1, config.tabatas, n => { config.tabatas = n; wd()}), - labelledInput('Prepare', 0, config.prepare, n => { config.prepare = n; wd()}), - labelledInput('Cycles', 1, config.cycles, n => { config.cycles = n; wd()}), - labelledInput('Work', 5, config.work, n => { config.work = n; wd()}), - labelledInput('Rest', 5, config.rest, n => { config.rest = n; wd()}), - h('div', { className: 'g-Form__Duration' }, 'Duration:', h('div', {}, duration)), - h('button', { className: 'g-Form__Start' }, 'start')) + h('section', + { className: 'g-Form__Section' }, + numberInput('Warm Up', 0, config.warmup, n => { config.warmup = n; wd()}) + ), + h('section', + { className: 'g-Form__Section' }, + h('h1', { className: 'g-Form__Title' }, 'Tabatas'), + h('div', + { className: 'g-Form__Line' }, + numberInput('Preparation', 0, config.prepare, n => { config.prepare = n; wd()}), + operator('+'), + numberInput('Cycles', 1, config.cycles, n => { config.cycles = n; wd()}), + operator('× ('), + numberInput('Work', 5, config.work, n => { config.work = n; wd()}), + operator('+'), + numberInput('Rest', 5, config.rest, n => { config.rest = n; wd()}), + operator(')') + ), + tabatasSection( + config.tabatas, + (str: string) => { config.tabatas.push(str); wd() }, + (index: number, str: string) => { config.tabatas[index] = str; wd() }, + (index: number) => { config.tabatas.splice(index, 1); wd() } + ) + ), + h('section', + { className: 'g-Form__Section' }, + h('h1', { className: 'g-Title' }, 'Duration'), + h('div', { className: 'g-Form__Duration' }, duration) + ), + h('button', { className: 'g-Button' }, 'Start') + ) + ) +} + +function operator(str: string): Element { + return h('span', { className: 'g-Form__Operator' }, str) +} + +function tabatasSection( + init: string[], + onAdd: (str: string) => void, + onUpdate: (index: number, str: string) => void, + onRemove: (inedx: number) => void +) { + const tabatas = h('ol', { className: 'g-List' }) + let counter = init.length + let removedIndexes: number[] = [] + let adjustIndex = (index: number) => index - removedIndexes.filter(i => i < index).length + + init.forEach((initStr, index) => { + const { tabata } = tabataInput( + initStr, + (str: string) => onUpdate(adjustIndex(index), str), + () => { + onRemove(adjustIndex(index)) + tabatas.removeChild(tabata) + removedIndexes.push(index) + } + ) + tabatas.appendChild(tabata) + }) + + return h('div', + { className: 'g-Form__Tabatas' }, + tabatas, + h('input', + { type: 'button', + value: 'Add', + className: 'g-Button', + onclick: (e: Event) => { + let index = counter++ + const txt = `Exercise ${adjustIndex(index) + 1}` + onAdd(txt) + let { tabata, textInput } = tabataInput( + txt, + (str: string) => onUpdate(adjustIndex(index), str), + () => { + onRemove(adjustIndex(index)) + tabatas.removeChild(tabata) + removedIndexes.push(index) + } + ) + tabatas.appendChild(tabata) + textInput.select() + } + } + ) + ) +} + +interface TabataInput { + tabata: Element, + textInput: HTMLInputElement, +} + +function tabataInput( + init: string, + onUpdate: (str: string) => void, + onRemove: () => void +): TabataInput { + const textInput = h('input', + { value: init, + className: 'g-Input', + required: 'required', + oninput: (e: Event) => { + if (e.target !== null) { + const target = e.target as HTMLInputElement + onUpdate(target.value.trim()) + } + } + } + ) as HTMLInputElement + + const tabata = h('li', + { className: 'g-Form__Tabata'}, + textInput, + h('input', + { type: 'button', + value: 'Remove', + className: 'g-Button', + onclick: (e: Event) => onRemove() + } + ) ) + + return { tabata, textInput } +} + +function numberInput( + labelValue: string, + min: number, + value: number, + update: (n: number) => void +): Element { + return h('label', + { className: 'g-Form__Label', + oninput: (e: Event) => { + if (e.target !== null) { + const target = e.target as HTMLInputElement + update(parseInt(target.value) || 0) + } + } + }, + labelValue, + h('input', + { className: 'g-Input', + type: 'number', + required: 'required', + min, + value + })) } |