1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
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'
}
}
|