import { h, withVar, mount, Html, Rx } from 'lib/rx' import * as Book from 'book' import * as Modal from 'view/components/modal' export function view(books: Rx>): Html { return h('div', { className: 'g-Books' }, withVar(undefined, (focusBook, updateFocusBook) => [ books.map(bs => [ focusBook.map(book => { if (book !== undefined) { let onKeyup = keyupHandler({ books: bs, book, onUpdate: (book: Book.Book) => updateFocusBook(_ => book) }) return bookDetailModal({ book, onClose: () => updateFocusBook(_ => undefined), onmount: () => addEventListener('keyup', onKeyup), onunmount: () => removeEventListener('keyup', onKeyup) }) } }), bs.map(book => viewBook({ book, onSelect: (book) => updateFocusBook(_ => book) })) ]) ]) ) } interface KeyupHandlerParams { books: Array book: Book.Book onUpdate: (book: Book.Book) => void } function keyupHandler({ books, book, onUpdate }: KeyupHandlerParams): ((e: KeyboardEvent) => void) { return (e: KeyboardEvent) => { if (e.key === 'ArrowLeft') { const indexedBooks = books.map((b, i) => ({ b, i })) const focus = indexedBooks.find(({ b }) => b == book) if (focus !== undefined && focus.i > 0) { onUpdate(books[focus.i - 1]) } } else if (e.key === 'ArrowRight') { const indexedBooks = books.map((b, i) => ({ b, i })) const focus = indexedBooks.find(({ b }) => b == book) if (focus !== undefined && focus.i < books.length - 1) { onUpdate(books[focus.i + 1]) } } } } interface ViewBookParams { book: Book.Book onSelect: (book: Book.Book) => void } function viewBook({ book, onSelect }: ViewBookParams): Html { return h('button', { className: 'g-Book' }, h('img', { src: book.cover, alt: book.title, className: 'g-Book__Image', onclick: () => onSelect(book) } ) ) } interface BookDetailModalParams { book: Book.Book onClose: () => void onmount: () => void onunmount: () => void } function bookDetailModal({ book, onClose, onmount, onunmount }: BookDetailModalParams): Html { return Modal.view({ header: h('div', h('div', { className: 'g-BookDetail__Title' }, `${book.title}, ${book.date}`), book.subtitle && h('div', { className: 'g-BookDetail__Subtitle' }, book.subtitle) ), body: h('div', { className: 'g-BookDetail' }, h('img', { src: book.cover }), h('div', h('dl', metadata('Auteur', book.authors), metadata('Genre', book.genres) ), book.summary && book.summary .split('\n') .map(str => str.trim()) .filter(str => str != '') .map(str => h('p', str)) ) ), onClose, onmount, onunmount }) } function metadata(term: string, descriptions: Array): Html { return h('div', h('dt', term, descriptions.length > 1 && 's', ' :'), h('dd', ' ', descriptions.join(', ')) ) }