diff options
author | Joris | 2017-01-22 21:17:17 +0100 |
---|---|---|
committer | Joris | 2017-01-22 21:17:17 +0100 |
commit | 049e6078fc8b47100820ac35508afd23813ea9fe (patch) | |
tree | 958a1a7110507c0da3715f36e7e3565e225d6a25 /src/main/scala/reading/component/index | |
parent | e8c4affa73f3e556981267ae4236561ece158ca1 (diff) | |
download | reading-049e6078fc8b47100820ac35508afd23813ea9fe.tar.gz reading-049e6078fc8b47100820ac35508afd23813ea9fe.tar.bz2 reading-049e6078fc8b47100820ac35508afd23813ea9fe.zip |
Adapt applicatio to mobiles
Diffstat (limited to 'src/main/scala/reading/component/index')
13 files changed, 396 insertions, 183 deletions
diff --git a/src/main/scala/reading/component/index/BookDetail.scala b/src/main/scala/reading/component/index/BookDetail.scala index 6a9d83a..80280ac 100644 --- a/src/main/scala/reading/component/index/BookDetail.scala +++ b/src/main/scala/reading/component/index/BookDetail.scala @@ -15,7 +15,8 @@ object BookDetail { img( BookStyle.cover, - src := s"cover/${book.title}.jpg" + src := s"cover/${book.title}.jpg", + alt := book.title ), div( diff --git a/src/main/scala/reading/component/index/Books.scala b/src/main/scala/reading/component/index/Books.scala index 5d7c92e..b75a5b0 100644 --- a/src/main/scala/reading/component/index/Books.scala +++ b/src/main/scala/reading/component/index/Books.scala @@ -30,6 +30,7 @@ object Books { img( BooksStyle.cover, src := s"cover/${book.title}.jpg", + alt := book.title, RxAttr(onclick, Rx(() => focus() = Some(book))) ) ) diff --git a/src/main/scala/reading/component/index/Filters.scala b/src/main/scala/reading/component/index/Filters.scala deleted file mode 100644 index 569bd86..0000000 --- a/src/main/scala/reading/component/index/Filters.scala +++ /dev/null @@ -1,41 +0,0 @@ -package reading.component.index - -import rx._ -import Ctx.Owner.Unsafe._ - -import scalatags.JsDom.all._ -import scalacss.Defaults._ -import scalacss.ScalatagsCss._ - -import reading.component.index.style.{ Filters => FiltersStyle } -import reading.component.widget.Cross -import reading.component.style.Col -import reading.models.Filter -import reading.Route -import reading.utils.{ RxTag, RxAttr } - -object Filters { - def apply(filters: Var[Seq[Filter]]): Frag = - RxTag { implicit context => - if (filters().isEmpty) - span("") - else - div( - FiltersStyle.render, - FiltersStyle.filters, - - filters().sortBy(_.name).map { filter => - div( - FiltersStyle.filter, - RxAttr(onclick, Rx(() => { - val newFilters = Filter.remove(filters(), filter) - filters() = newFilters - Route.push(Route.Books(newFilters)) - })), - span(FiltersStyle.name, filter.name.capitalize), - Cross(15.px, Col.black) - ) - } - ) - } -} diff --git a/src/main/scala/reading/component/index/FiltersMenu.scala b/src/main/scala/reading/component/index/FiltersMenu.scala deleted file mode 100644 index f3f9ca2..0000000 --- a/src/main/scala/reading/component/index/FiltersMenu.scala +++ /dev/null @@ -1,72 +0,0 @@ -package reading.component.index - -import rx._ -import Ctx.Owner.Unsafe._ - -import scalatags.JsDom.all._ -import scalacss.Defaults._ -import scalacss.ScalatagsCss._ - -import reading.component.index.style.{ FiltersMenu => FiltersMenuStyle } -import reading.models._ -import reading.utils.{ RxTag, RxAttr } -import reading.Route - -object FiltersMenu { - def apply(books: Rx[Seq[Book]], filters: Var[Seq[Filter]]): Frag = - RxTag { implicit context => - div( - FiltersMenuStyle.render, - FiltersMenuStyle.groups, - filters().find(_.kind == FilterKind.Grade) match { - case None => - group(books, filters, "Classe", Grade.values.map(Filter.apply(_))) - case Some(grade) => - group(books, filters, "Programme", Program.values.map(Filter.apply(_))) - }, - group(books, filters, "Theme", Theme.values.map(Filter.apply(_))), - group(books, filters, "Genre", Genre.values.map(Filter.apply(_))), - group(books, filters, "Niveau", Level.values.map(Filter.apply(_))), - group(books, filters, "Période", Period.values.map(Filter.apply(_))) - ) - } - - def group( - books: Rx[Seq[Book]], - filters: Var[Seq[Filter]], - name: String, - groupFilters: Seq[Filter] - )( - implicit - context: Ctx.Data - ): Frag = { - val filtersWithCount = Rx { - groupFilters - .filter(filter => !Filter.contains(filters(), filter)) - .map(filter => (filter, Book.filter(books(), Seq(filter)).length)) - .filter(_._2 > 0) - } - - if (filtersWithCount().isEmpty) - span("") - else - div( - FiltersMenuStyle.group, - div(FiltersMenuStyle.groupTitle, name), - div( - filtersWithCount().map { - case (filter, count) => - button( - FiltersMenuStyle.filter, - RxAttr(onclick, Rx(() => { - val newFilters = filter +: filters() - filters() = newFilters - Route.push(Route.Books(newFilters)) - })), - span(s"${filter.name.capitalize} ($count)") - ) - } - ) - ) - } -} diff --git a/src/main/scala/reading/component/index/Header.scala b/src/main/scala/reading/component/index/Header.scala new file mode 100644 index 0000000..7e29b4c --- /dev/null +++ b/src/main/scala/reading/component/index/Header.scala @@ -0,0 +1,76 @@ +package reading.component.index + +import org.scalajs.dom + +import rx._ +import Ctx.Owner.Unsafe._ + +import scalatags.JsDom.all._ +import scalacss.Defaults._ +import scalacss.ScalatagsCss._ + +import reading.component.index.style.{ Header => HeaderStyle } +import reading.component.widget.Cross +import reading.component.style.{ Color => C } +import reading.models.Filter +import reading.Route +import reading.utils.{ RxTag, RxAttr } + +object Header { + def apply(filters: Var[Seq[Filter]], showFiltersMenu: Var[Boolean], booksCount: Rx[Int]): Frag = { + val filtersCount: Rx[Int] = Rx(filters().length) + + div( + HeaderStyle.render, + HeaderStyle.header, + + RxTag { implicit context => + div( + div( + HeaderStyle.showFiltersMenu, + RxAttr(onclick, Rx(() => { + showFiltersMenu() = true + dom.document.body.style.overflowY = "hidden" + })), + "Filtrer", + if (filtersCount() > 0) span(HeaderStyle.filtersCount, filtersCount()) else span("") + ), + + if (filters().isEmpty) + span("") + else + div( + HeaderStyle.filters, + + div( + HeaderStyle.clear, + RxAttr(onclick, Rx(() => updateFilters(filters, Nil))), + "Effacer les filtres" + ), + + filters().sortBy(_.name).map { filter => + div( + HeaderStyle.filter, + RxAttr(onclick, Rx(() => updateFilters(filters, Filter.remove(filters(), filter)))), + span(HeaderStyle.name, filter.name.capitalize), + Cross(15.px, C.black.value) + ) + } + ) + ) + }, + + RxTag { implicit context => + div( + HeaderStyle.booksCount, + span(s"${booksCount()} livre${if (booksCount() > 1) "s" else ""}") + ) + } + ) + } + + private def updateFilters(filters: Var[Seq[Filter]], newFilters: Seq[Filter]): Unit = { + filters() = newFilters + Route.push(Route.Books(newFilters)) + } +} diff --git a/src/main/scala/reading/component/index/Menu.scala b/src/main/scala/reading/component/index/Menu.scala new file mode 100644 index 0000000..5ffbd25 --- /dev/null +++ b/src/main/scala/reading/component/index/Menu.scala @@ -0,0 +1,104 @@ +package reading.component.index + +import org.scalajs.dom + +import rx._ +import Ctx.Owner.Unsafe._ + +import scalatags.JsDom.all._ +import scalacss.Defaults._ +import scalacss.ScalatagsCss._ + +import reading.component.index.style.{ Menu => MenuStyle } +import reading.models._ +import reading.utils.{ RxTag, RxAttr } +import reading.Route + +object Menu { + def apply(books: Rx[Seq[Book]], filters: Var[Seq[Filter]], showFiltersMenu: Var[Boolean]): Frag = + RxTag { implicit context => + div( + MenuStyle.render, + if (showFiltersMenu()) MenuStyle.show else "", + MenuStyle.menu, + + header(showFiltersMenu, filters().length), + + filters().find(_.kind == FilterKind.Grade) match { + case None => group(books, filters, "Classe", Grade.values.map(Filter.apply(_))) + case Some(grade) => group(books, filters, grade.name, Program.values.map(Filter.apply(_)), Some(grade)) + }, + group(books, filters, "Theme", Theme.values.map(Filter.apply(_))), + group(books, filters, "Genre", Genre.values.map(Filter.apply(_))), + group(books, filters, "Niveau", Level.values.map(Filter.apply(_))), + group(books, filters, "Période", Period.values.map(Filter.apply(_))) + ) + } + + def header(showFiltersMenu: Var[Boolean], count: Int): HtmlTag = + div( + MenuStyle.header, + span( + MenuStyle.close, + RxAttr(onclick, Rx(() => { + showFiltersMenu() = false + dom.document.body.style.overflowY = "scroll" + })) + ), + "Filtrer", + if (count > 0) span(MenuStyle.count, count) else span("") + ) + + def group( + books: Rx[Seq[Book]], + filters: Var[Seq[Filter]], + name: String, + groupFilters: Seq[Filter], + parentFilter: Option[Filter] = None + )( + implicit + context: Ctx.Data + ): Frag = { + val filtersWithCount = Rx { + groupFilters + .map(filter => (filter, Book.filter(books(), Seq(filter)).length)) + .filter(_._2 > 0) + } + + if (filtersWithCount().isEmpty) + span("") + else + div( + MenuStyle.filterGroup, + div( + MenuStyle.filterTitle, + parentFilter.map(filter => + RxAttr(onclick, Rx(() => updateFilters(filters, Filter.remove(filters(), filter))))).getOrElse(""), + if (parentFilter.isDefined) MenuStyle.activeFilter else "", + name + ), + div( + filtersWithCount().map { + case (filter, count) => { + val isActive = Filter.contains(filters(), filter) + + button( + MenuStyle.filter, + if (isActive) MenuStyle.activeFilter else "", + RxAttr(onclick, Rx(() => updateFilters( + filters, + if (isActive) Filter.remove(filters(), filter) else filter +: filters() + ))), + span(s"${filter.name.capitalize} ($count)") + ) + } + } + ) + ) + } + + private def updateFilters(filters: Var[Seq[Filter]], newFilters: Seq[Filter]): Unit = { + filters() = newFilters + Route.push(Route.Books(newFilters)) + } +} diff --git a/src/main/scala/reading/component/index/style/BookDetail.scala b/src/main/scala/reading/component/index/style/BookDetail.scala index e54c964..6e79113 100644 --- a/src/main/scala/reading/component/index/style/BookDetail.scala +++ b/src/main/scala/reading/component/index/style/BookDetail.scala @@ -2,7 +2,8 @@ package reading.component.index.style import scalacss.Defaults._ -import reading.component.style.Col +import reading.Media +import reading.component.style.{ Color => C } object BookDetail extends StyleSheet.Inline { import dsl._ @@ -12,7 +13,7 @@ object BookDetail extends StyleSheet.Inline { fontSize(18.px), fontWeight.bold, marginBottom(20.px), - color(Col.congoBrown) + color(C.congoBrown.value) ) val author = style( @@ -20,12 +21,15 @@ object BookDetail extends StyleSheet.Inline { ) val detail = style( - display.flex + display.flex, + flexWrap.wrap, + justifyContent.center ) val cover = style( height(300.px), - marginRight(30.px) + marginRight(30.px), + Media.mobile(marginBottom(30.px)) ) val item = style( diff --git a/src/main/scala/reading/component/index/style/Books.scala b/src/main/scala/reading/component/index/style/Books.scala index 34a7a83..79aea1a 100644 --- a/src/main/scala/reading/component/index/style/Books.scala +++ b/src/main/scala/reading/component/index/style/Books.scala @@ -2,22 +2,27 @@ package reading.component.index.style import scalacss.Defaults._ +import reading.Media + object Books extends StyleSheet.Inline { import dsl._ val books = style( display.flex, - flexWrap.wrap + flexWrap.wrap, + justifyContent.center ) val book = style( - width(250.px), + Media.desktop(width(250.px)), + Media.mobile(width(150.px)), paddingBottom(60.px), textAlign.center ) val cover = style( - height(250.px), + Media.desktop(height(250.px)), + Media.mobile(height(150.px)), cursor.pointer ) } diff --git a/src/main/scala/reading/component/index/style/Count.scala b/src/main/scala/reading/component/index/style/Count.scala new file mode 100644 index 0000000..cc1eb80 --- /dev/null +++ b/src/main/scala/reading/component/index/style/Count.scala @@ -0,0 +1,20 @@ +package reading.component.index.style + +import scalacss.Defaults._ + +import reading.component.style.{ Color => C } + +object Count extends StyleSheet.Inline { + import dsl._ + + val count = style( + display.flex, + alignItems.center, + justifyContent.center, + backgroundColor(C.stiletto.value), + width(25.px), + height(25.px), + borderRadius(50.%%), + marginLeft(20.px) + ) +} diff --git a/src/main/scala/reading/component/index/style/Filters.scala b/src/main/scala/reading/component/index/style/Filters.scala deleted file mode 100644 index c324965..0000000 --- a/src/main/scala/reading/component/index/style/Filters.scala +++ /dev/null @@ -1,34 +0,0 @@ -package reading.component.index.style - -import scalacss.Defaults._ - -import reading.component.style.Col - -object Filters extends StyleSheet.Inline { - import dsl._ - - val filters = style( - marginBottom(50.px), - display.flex - ) - - val filter = style( - display.flex, - alignItems.center, - padding(15.px), - marginRight(20.px), - borderRadius(2.px), - &.hover(cursor.pointer), - border(1.px, solid, Col.alto), - fontSize(18.px) - ) - - val name = style( - marginRight(10.px) - ) - - val cross = style( - width(15.px), - height(15.px) - ) -} diff --git a/src/main/scala/reading/component/index/style/FiltersMenu.scala b/src/main/scala/reading/component/index/style/FiltersMenu.scala deleted file mode 100644 index 3fcc363..0000000 --- a/src/main/scala/reading/component/index/style/FiltersMenu.scala +++ /dev/null @@ -1,28 +0,0 @@ -package reading.component.index.style - -import scalacss.Defaults._ - -import reading.component.style.Col - -object FiltersMenu extends StyleSheet.Inline { - import dsl._ - - val groups = style( - width(280.px) - ) - - val group = style( - marginBottom(30.px) - ) - - val groupTitle = style( - color(Col.congoBrown), - fontWeight.bold, - textTransform.uppercase, - padding(10.px, 30.px, 15.px) - ) - - val filter = style( - padding(10.px, 30.px) - ) -} diff --git a/src/main/scala/reading/component/index/style/Header.scala b/src/main/scala/reading/component/index/style/Header.scala new file mode 100644 index 0000000..643dd8e --- /dev/null +++ b/src/main/scala/reading/component/index/style/Header.scala @@ -0,0 +1,80 @@ +package reading.component.index.style + +import scalacss.Defaults._ + +import reading.Media +import reading.component.style.{ Color => C } + +object Header extends StyleSheet.Inline { + import dsl._ + + val header = style( + Media.desktop(margin(40.px)), + Media.mobile(margin(30.px)) + ) + + val showFiltersMenu = style( + Media.desktop(display.none), + Media.mobile( + display.flex, + justifyContent.center, + alignItems.center, + width(100.%%), + backgroundColor(C.englishWalnut.value), + color(C.white.value), + border(1.px, solid, C.congoBrown.value), + borderRadius(4.px), + marginBottom(20.px), + padding(10.px, 0.px), + cursor.pointer + ) + ) + + val filtersCount = style( + Count.count + ) + + val filters = style( + display.flex, + marginBottom(30.px), + Media.mobile(display.none) + ) + + private val box = style( + display.flex, + alignItems.center, + padding(15.px), + marginRight(20.px), + borderRadius(2.px), + border(1.px, solid, C.gray.lighten(80).value), + fontSize(18.px), + &.hover(cursor.pointer) + ) + + val clear = style( + box, + backgroundColor(C.mickado.value), + color(C.white.value), + &.hover(backgroundColor(C.mickado.lighten(20).value)) + ) + + val filter = style( + box, + &.hover(borderColor(C.gray.lighten(50).value)) + ) + + val name = style( + marginRight(10.px) + ) + + val cross = style( + width(15.px), + height(15.px) + ) + + val booksCount = style( + fontSize(20.px), + color(C.gray.value), + Media.mobile(textAlign.center) + ) +} diff --git a/src/main/scala/reading/component/index/style/Menu.scala b/src/main/scala/reading/component/index/style/Menu.scala new file mode 100644 index 0000000..38620e8 --- /dev/null +++ b/src/main/scala/reading/component/index/style/Menu.scala @@ -0,0 +1,97 @@ +package reading.component.index.style + +import scalacss.Defaults._ + +import reading.Media +import reading.component.style.{ Color => C } + +object Menu extends StyleSheet.Inline { + import dsl._ + + val menu = style( + Media.mobile(display.none), + backgroundColor(C.englishWalnut.value), + color(C.white.value), + width(280.px), + height(100.%%), + boxShadow := "4px 0px 6px -1px rgba(0, 0, 0, 0.2)" + ) + + val header = style( + display.flex, + alignItems.center, + justifyContent.center, + position.relative, + height(60.px), + backgroundColor(C.englishWalnut.darken(20).value), + color(C.white.value), + textTransform.uppercase, + fontWeight.bold, + letterSpacing(1.px), + marginBottom(20.px), + Media.mobile(boxShadow := "0px 3px 5px -1px rgba(0, 0, 0, 0.2)") + ) + + val close = style( + Media.desktop(display.none), + Media.mobile( + position.absolute, + top(0.px), + left(0.px), + width(100.%%), + height(100.%%), + cursor.pointer + ) + ) + + val count = style( + Count.count + ) + + val show = style( + Media.mobile( + display.block, + position.fixed, + top(0.px), + left(0.px), + width(100.%%), + height(100.%%), + zIndex(1), + overflowY.scroll, + backgroundColor(C.white.value), + color(C.black.value) + ) + ) + + val filterGroup = style() + + private val filterCommon = style( + display.flex, + alignItems.center, + width(100.%%), + padding(5.px, 30.px), + textAlign.left + ) + + val filterTitle = style( + filterCommon, + minHeight(50.px), + fontWeight.bold, + textTransform.uppercase, + letterSpacing(1.px), + marginBottom(10.px) + ) + + val filter = style( + filterCommon, + marginLeft(10.px), + minHeight(40.px), + color.inherit, + &.lastChild(marginBottom(30.px)) + ) + + val activeFilter = style( + color(C.stiletto.value), + cursor.pointer + ) +} |