aboutsummaryrefslogtreecommitdiff
path: root/src/main.ts
blob: 0a3fd30f9f93d7de5ae165feb42ce50237953121 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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

// @ts-ignore
const sortedBookLibrary: Array<Book> = (bookLibrary as Array<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 }))
        )
      )
    )
  ]
})

// 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)