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(', '))
)
}