aboutsummaryrefslogtreecommitdiff
path: root/src/view/form.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/form.ts')
-rw-r--r--src/view/form.ts178
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
+ }))
}