diff options
author | Joris | 2023-02-12 13:05:25 +0100 |
---|---|---|
committer | Joris | 2023-02-12 13:05:25 +0100 |
commit | 25ecb1cb75b7b5b584ad223e12d74c3e3ee7da89 (patch) | |
tree | 54118b78bd783812725a6a6cd43f3b4d47ffe006 /src/view/filters.ts | |
parent | 31acb6e43c07066e9a5ba404ea6c59201937c05a (diff) |
Add textual search on title, subtitle and authors
Diffstat (limited to 'src/view/filters.ts')
-rw-r--r-- | src/view/filters.ts | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/view/filters.ts b/src/view/filters.ts new file mode 100644 index 0000000..9ce277b --- /dev/null +++ b/src/view/filters.ts @@ -0,0 +1,90 @@ +import { h, Rx } from 'lib/rx' +import * as Book from 'book' +import * as I18n from 'lib/i18n' + +// Model + +export interface Model { + read?: Book.ReadStatus +} + +const init: Model = {} + +// View + +interface ViewFiltersParams { + filteredBooks: Rx<Array<Book.Book>> + filters: Rx<Model> + updateFilters: (f: (filters: Model) => Model) => void +} + +export function view({ filteredBooks, filters, updateFilters }: ViewFiltersParams) { + return h('ul', + h('li', [ + h('div', { className: 'g-FilterTitle' }, 'Lecture'), + readFilter({ + filteredBooks, + readStatus: filters.map(fs => fs.read), + update: (status?: Book.ReadStatus) => updateFilters(fs => { + fs.read = status + return fs + }) + }) + ]) + ) +} + +interface ReadFilterParams { + filteredBooks: Rx<Array<Book.Book>> + readStatus: Rx<Book.ReadStatus | undefined> + update: (status?: Book.ReadStatus) => void +} + +function readFilter({ filteredBooks, 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) }, + filteredBooks.map(xs => unit(xs.length, readStatusLabels(currentStatus))) + ) + ) + } else { + return Book.readStatuses.map(status => + filteredBooks.map(xs => { + const count = xs.filter(b => b.read === status).length + + return count !== 0 + ? h('li', + { className: 'g-Filter g-Filter--Unselected' }, + h('button', + { onclick: () => update(status) }, + unit(count, readStatusLabels(status)) + ) + ) + : undefined + }) + ) + } + }) + ) +} + +function unit(n: number, labels: Array<string>): string { + return I18n.unit(n, labels[0], labels[1], (n, str) => `${str} (${n})`) +} + +function readStatusLabels(status: Book.ReadStatus): Array<string> { + if (status === 'Read') { + return ['lu', 'lus'] + } else if (status === 'Unread') { + return ['non lu', 'non lus'] + } else if (status === 'Reading') { + return ['en cours', 'en cours'] + } else { + return ['arrêté', 'arrêtés'] + } +} |