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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
import { h, withVar, mount, Rx } from 'lib/rx'
// Model
interface Book {
title: string
authors: Array<string>
authorsSort: string
genres: Array<string>
date: string
read: ReadStatus,
cover: string
}
type ReadStatus = 'Read' | 'Unread' | 'Reading' | 'Stopped'
const readStatuses: Array<ReadStatus> = ['Read', 'Unread', 'Reading', 'Stopped' ]
// Books
// @ts-ignore
const sortedBookLibrary: Array<Book> = (bookLibrary as Array<Book>).sort((a, b) =>
a.authorsSort == b.authorsSort
? a.date > b.date
: a.authorsSort > b.authorsSort)
// Filters
interface Filters {
read?: ReadStatus
}
// View
const view = withVar<Filters>({}, (filters, updateFilters) => {
const filtredBooks = filters.map(f =>
sortedBookLibrary.filter(book =>
f.read === undefined || book.read === f.read
)
)
return [
h('aside', viewFilters({ filtredBooks, filters, updateFilters })),
h('main',
h('header', filtredBooks.map(fb => `${fb.length} livres`)),
h('div',
{ className: 'g-Books' },
filtredBooks.map(fb =>
fb.map(book => h('img', { className: 'g-Book', src: book.cover }))
)
)
)
]
})
// Filters view
interface ViewFiltersParams {
filtredBooks: Rx<Array<Book>>
filters: Rx<Filters>
updateFilters: (f: (filters: Filters) => Filters) => void
}
function viewFilters({ filtredBooks, filters, updateFilters }: ViewFiltersParams) {
return h('ul',
{},
h('li', [
h('div', { className: 'g-FilterTitle' }, 'Lecture'),
readFilter({
filtredBooks,
readStatus: filters.map(fs => fs.read),
update: (status?: ReadStatus) => updateFilters(fs => {
fs.read = status
return fs
})
})
])
)
}
interface ReadFilterParams {
filtredBooks: Rx<Array<Book>>
readStatus: Rx<ReadStatus | undefined>
update: (status?: ReadStatus) => void
}
function readFilter({ filtredBooks, readStatus, update }: ReadFilterParams) {
return h('ul',
{ className: 'g-Filters' },
readStatus.map(currentStatus => {
if (currentStatus !== undefined) {
return h('li',
{ className: 'g-Filter g-Filter--Selected' },
h('button',
{ onclick: () => update(undefined) },
readStatusLabel(currentStatus)
)
)
} else {
return readStatuses.map(status => {
const count = filtredBooks.map(xs => xs.filter(b => b.read === status).length)
return h('li',
{ className: 'g-Filter g-Filter--Unselected' },
h('button',
{ onclick: () => update(status) },
count.map(c => `${readStatusLabel(status)} (${c})`)
)
)
})
}
})
)
}
function readStatusLabel(status: ReadStatus): string {
if (status === 'Read') {
return 'lus'
} else if (status === 'Unread') {
return 'non lus'
} else if (status === 'Reading') {
return 'en cours'
} else {
return 'arrêtés'
}
}
mount(view)
|