aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.ts132
1 files changed, 106 insertions, 26 deletions
diff --git a/src/main.ts b/src/main.ts
index 7033690..0a3fd30 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,4 +1,6 @@
-import { h, withVar, mount } from 'lib/rx'
+import { h, withVar, mount, Rx } from 'lib/rx'
+
+// Model
interface Book {
title: string
@@ -6,43 +8,121 @@ interface Book {
authorsSort: string
genres: Array<string>
date: string
- read: boolean
+ read: ReadStatus,
cover: string
}
+type ReadStatus = 'Read' | 'Unread' | 'Reading' | 'Stopped'
+
+const readStatuses: Array<ReadStatus> = ['Read', 'Unread', 'Reading', 'Stopped' ]
+
+// Books
+
// @ts-ignore
-const sortedBooks: Array<Book> = (books as Array<Book>).sort((a, b) =>
+const sortedBookLibrary: Array<Book> = (bookLibrary as Array<Book>).sort((a, b) =>
a.authorsSort == b.authorsSort
? a.date > b.date
: a.authorsSort > b.authorsSort)
-enum Filter {
- All,
- Read,
- Unread
+// Filters
+
+interface Filters {
+ read?: ReadStatus
}
-const view = withVar(Filter.All, (filter, updateFilter) => [
- h('aside',
- { className: 'g-Aside' },
- h('select',
- { name: 'filter',
- id: 'filter',
- onchange: (event: Event) => updateFilter(_ => (event.target as HTMLSelectElement).value as any)
- },
- h('option', { value: Filter.All }, 'Tous les livres'),
- h('option', { value: Filter.Read }, 'Livres lus'),
- h('option', { value: Filter.Unread }, 'Livres non lus')
+// View
+
+const view = withVar<Filters>({}, (filters, updateFilters) => {
+ const filtredBooks = filters.map(f =>
+ sortedBookLibrary.filter(book =>
+ f.read === undefined || book.read === f.read
)
- ),
- h('main',
- { className: 'g-Main' },
- filter.map(f =>
- sortedBooks
- .filter(b => f == Filter.All || b.read == (f == Filter.Read))
- .map(book => h('img', { className: 'g-Book', src: book.cover }))
+ )
+
+ 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)