aboutsummaryrefslogtreecommitdiff
path: root/src/main.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.ts')
-rw-r--r--src/main.ts156
1 files changed, 39 insertions, 117 deletions
diff --git a/src/main.ts b/src/main.ts
index 0a3fd30..21bf215 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,128 +1,50 @@
-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
+import { h, withVar, mount } from 'lib/rx'
+import * as Search from 'lib/search'
+import * as Functions from 'lib/functions'
+import * as I18n from 'lib/i18n'
+import * as Filters from 'view/filters'
+import * as Book from 'book'
// @ts-ignore
-const sortedBookLibrary: Array<Book> = (bookLibrary as Array<Book>).sort((a, b) =>
+const sortedBookLibrary: Array<Book> = (bookLibrary as Array<Book.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 }))
- )
+mount(withVar<Filters.Model>({}, (filters, updateFilters) =>
+ withVar('', (search, updateSearch) => {
+ const filteredBooks = filters.flatMap(f => search.map(s =>
+ sortedBookLibrary.filter(book =>
+ (f.read === undefined || book.read === f.read)
+ && (s === '' || matchSearch(book, s))
)
- )
- ]
-})
-
-// 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)
+ ))
+
+ return [
+ h('aside', Filters.view({ filteredBooks, filters, updateFilters })),
+ h('main',
+ h('header',
+ h('input',
+ { className: 'g-Search',
+ oninput: Functions.debounce(
+ (event: Event) => updateSearch(_ => (event.target as HTMLInputElement).value),
+ 500
+ )
+ }
+ ),
+ filteredBooks.map(fb => I18n.unit(fb.length, 'livre', 'livres'))
+ ),
+ h('div',
+ { className: 'g-Books' },
+ filteredBooks.map(fb =>
+ fb.map(book => h('img', { className: 'g-Book', src: book.cover }))
)
)
- } 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'
- }
+function matchSearch(book: Book.Book, search: string): boolean {
+ return Search.match(search, book.title, book.subtitle, ...book.authors)
}
-
-mount(view)