package reading.component.index import rx._ import scalacss.Defaults._ import scalacss.ScalatagsCss._ import scalatags.JsDom.all._ import reading.component.index.style.{ BookDetail => BookStyle } import reading.component.widget.AnimateMethod import reading.models.{ Filter, Book, Program, Grade, Theme, GroupedTheme } import reading.Route import reading.utils.RxUtils._ object BookDetail { val componentId = s"books-detail" def apply( filters: Var[Set[Filter]], detail: Var[Option[Book]], search: Var[String], book: Book, parentId: String, onClose: => Unit )( implicit ctx: Ctx.Owner ): Frag = { val titleParts = if (book.parts > 1) s", ${book.parts} volumes" else "" val grades = book.programs.map(Grade.from(_)).distinct.sorted AnimateMethod.fadeIn(componentId, AnimateMethod.fadeOut(Books.componentId)) div( BookStyle.render, BookStyle.detailParent, id := componentId, div( BookStyle.detail, img( BookStyle.cover, src := s"cover/${book.title}.jpg", alt := s"${book.title}, ${book.author}" ), div( BookStyle.presentation, div(BookStyle.title, s"${book.title}$titleParts"), div(BookStyle.author, book.author), p(BookStyle.summary, raw(book.summary)), dl( BookStyle.definitions, grades.map { grade => val programs = book.programs.filter(p => Grade.from(p) == grade).sorted val pp = grade.prettyPrint val programFilters = programs.map { program => (Filter(program), filters.map(addProgram(_, program))) } definition(filters, detail, search, pp, pp, programFilters, p => s"« $p »") }, if (book.themes.nonEmpty) { val themeFilters = book.themes.sorted.map { theme => (Filter(theme), filters.map(addTheme(_, theme))) } definition(filters, detail, search, "thème", "thèmes", themeFilters) }, if (book.genres.nonEmpty) { val bookFilters = book.genres.sorted.map(Filter(_)).map(b => (b, filters.map(_ + b))) definition(filters, detail, search, "genre", "genres", bookFilters) }, { val levelFilters = Seq(Filter(book.level)).map(b => (b, filters.map(_ + b))) definition(filters, detail, search, "niveau", "niveaux", levelFilters) } ), a( BookStyle.close, onclick := (() => onClose), href := Rx(Route.url(Route.Books(filters()))), "Fermer" ) ) ) ) } private def definition( filters: Var[Set[Filter]], detail: Var[Option[Book]], search: Var[String], term: String, pluralTerm: String, definitionFilters: Seq[(Filter, Rx[Set[Filter]])], format: String => String = _.capitalize )( implicit ctx: Ctx.Owner ): Seq[Frag] = { val sTerm = if (definitionFilters.length > 1) pluralTerm else term Seq( dt(BookStyle.definitionTerm, s"${sTerm.capitalize} :"), dd( BookStyle.definitionDescription, definitionFilters.map { case (filter, newFilters) => a( BookStyle.definitionFilter, href := Rx(Route.url(Route.Books(newFilters()))), onclick := (() => FilterUtils.set(filters, detail, search, newFilters.now)), format(filter.name) ) } ) ) } private def addProgram(filters: Set[Filter], program: Program): Set[Filter] = { val grade = Grade.from(program) val otherGrades = Grade.values.filter(_ != grade).map(Filter(_)) val otherPrograms = Program.values.filter(Grade.from(_) != grade).map(Filter(_)) filters -- otherGrades -- otherPrograms + Filter(grade) + Filter(program) } private def addTheme(filters: Set[Filter], theme: Theme): Set[Filter] = { val groupedTheme = GroupedTheme.from(theme) val otherGroupedThemes = GroupedTheme.values.filter(_ != groupedTheme).map(Filter(_)) val otherThemes = Theme.values.filter(GroupedTheme.from(_) != groupedTheme).map(Filter(_)) filters -- otherGroupedThemes -- otherThemes + Filter(groupedTheme) + Filter(theme) } }