import h from 'lib/h' import * as Format from 'lib/format' import * as Dom from 'lib/dom' import * as Function from 'lib/function' import * as Food from 'food' import * as Sort from 'view/sort' export function view(): Element { const maxGlycemicLoad: number = Math.max(...Food.all.map(Food.glycemicLoad)) const aliments = h('div', { className: 'g-Aliments' }, ...Food.all.sort((a1, a2) => Sort.aliments(a1, a2, Sort.init)).map(aliment => line(aliment, maxGlycemicLoad)) ) return h('div', { className: 'g-Page' }, header( (search: string, sort: Sort.Sort) => { const lines = Food .search(search) .sort((a1, a2) => Sort.aliments(a1, a2, sort)) .map(aliment => line(aliment, maxGlycemicLoad)) Dom.replaceChildren(aliments, ...lines) } ), aliments ) } function header( onUpdateTable: (search: string, sort: Sort.Sort) => void ): Element { let search = '' let sort = Sort.init const alimentHeader = h('button', { className: 'g-Header--Sorted' }, 'Aliment') const glycemicIndexHeader = h('button', {}, 'Index glycémique') const carbohydratesHeader = h('button', {}, 'Glucides pour 100 g') const glycemicLoadHeader = h('button', {}, 'Charge glycémique') const onSort = (field: Sort.Field) => () => { sort = Sort.toggle(sort, field) onUpdateTable(search, sort) alimentHeader.className = field === Sort.Field.Name ? 'g-Header--Sorted' : '' glycemicIndexHeader.className = field === Sort.Field.GlycemicIndex ? 'g-Header--Sorted' : '' carbohydratesHeader.className = field === Sort.Field.Carbohydrates ? 'g-Header--Sorted' : '' glycemicLoadHeader.className = field === Sort.Field.GlycemicLoad ? 'g-Header--Sorted' : '' } alimentHeader.addEventListener('click', onSort(Sort.Field.Name)) glycemicIndexHeader.addEventListener('click', onSort(Sort.Field.GlycemicIndex)) carbohydratesHeader.addEventListener('click', onSort(Sort.Field.Carbohydrates)) glycemicLoadHeader.addEventListener('click', onSort(Sort.Field.GlycemicLoad)) return h('header', { className: 'g-Header' }, h('div', { className: 'g-Title g-Line' }, alimentHeader, glycemicIndexHeader, carbohydratesHeader, glycemicLoadHeader, ), h('input', { className: 'g-Search g-Line', placeholder: 'Rechercher…', oninput: Function.debounce((e: Event) => { search = (e.target as HTMLInputElement).value onUpdateTable(search, sort) }) } ) ) } function line(aliment: Food.Aliment, maxGlycemicLoad: number): Element { return h('div', { className: 'g-Aliment g-Line' }, h('div', {}, aliment.name), h('div', { className: 'g-Number' }, aliment.glycemicIndex), h('div', { className: 'g-Number' }, `${Math.round(aliment.carbohydrates)} g`), h('div', { className: 'g-Number' }, formatGlycemicLoad(aliment, maxGlycemicLoad)) ) } function formatGlycemicLoad(aliment: Food.Aliment, maxGlycemicLoad: number): Element { const glycemicLoad = Food.glycemicLoad(aliment) return h('div', { className: `number ${glycemicLoadNumberClass(glycemicLoad)}` }, Format.decimal(glycemicLoad) ) } function glycemicLoadNumberClass(index: number): string { if (index < 8) { return 'g-Number--Low' } else if (index < 20) { return 'g-Number--Middle' } else { return 'g-Number--High' } }