You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
3.0 KiB
105 lines
3.0 KiB
package wow.doge.http4sdemo.dto
|
|
|
|
import java.time.LocalDateTime
|
|
|
|
import cats.syntax.either._
|
|
import enumeratum.EnumEntry
|
|
import enumeratum._
|
|
import io.circe.generic.semiauto._
|
|
import io.scalaland.chimney.dsl._
|
|
import org.http4s.ParseFailure
|
|
import org.http4s.QueryParamDecoder
|
|
import org.http4s.dsl.impl.QueryParamDecoderMatcher
|
|
import slick.jdbc.JdbcProfile
|
|
import wow.doge.http4sdemo.slickcodegen.Tables
|
|
|
|
final case class Book(
|
|
bookId: Int,
|
|
bookTitle: String,
|
|
isbn: String,
|
|
authorId: Int,
|
|
createdAt: LocalDateTime
|
|
)
|
|
object Book {
|
|
def tupled = (apply _).tupled
|
|
implicit val codec = deriveCodec[Book]
|
|
def fromBooksRow(row: Tables.BooksRow) = row.transformInto[Book]
|
|
def fromBooksTableFn(implicit profile: JdbcProfile) = {
|
|
import profile.api._
|
|
(b: Tables.Books) =>
|
|
(b.bookId, b.bookTitle, b.isbn, b.authorId, b.createdAt).mapTo[Book]
|
|
}
|
|
def fromBooksTable(implicit profile: JdbcProfile) =
|
|
Tables.Books.map(fromBooksTableFn)
|
|
|
|
}
|
|
|
|
final case class NewBook(bookTitle: String, isbn: String, authorId: Int)
|
|
object NewBook {
|
|
def tupled = (apply _).tupled
|
|
implicit val decoder = deriveDecoder[NewBook]
|
|
def fromBooksTable(implicit profile: JdbcProfile) = {
|
|
import profile.api._
|
|
|
|
Tables.Books.map(b => (b.bookTitle, b.isbn, b.authorId).mapTo[NewBook])
|
|
}
|
|
}
|
|
|
|
final case class BookUpdate(title: Option[String], authorId: Option[Int]) {
|
|
import com.softwaremill.quicklens._
|
|
def update(row: Tables.BooksRow): Tables.BooksRow =
|
|
row
|
|
.modify(_.bookTitle)
|
|
.setToIfDefined(title)
|
|
.modify(_.authorId)
|
|
.setToIfDefined(authorId)
|
|
}
|
|
object BookUpdate {
|
|
implicit val codec = deriveCodec[BookUpdate]
|
|
}
|
|
|
|
final case class Author(authorId: Int, authorName: String)
|
|
object Author {
|
|
def tupled = (apply _).tupled
|
|
implicit val codec = deriveCodec[Author]
|
|
def fromAuthorsRow(row: Tables.AuthorsRow) = row.transformInto[Author]
|
|
def fromAuthorsTableFn(implicit profile: JdbcProfile) = {
|
|
import profile.api._
|
|
(a: Tables.Authors) => (a.authorId, a.authorName).mapTo[Author]
|
|
}
|
|
}
|
|
|
|
final case class NewAuthor(name: String)
|
|
object NewAuthor {
|
|
// def fromAuthorsTable(implicit profile: JdbcProfile) = {
|
|
// import profile.api._
|
|
|
|
// Tables.Authors.map(a => (a.authorName).mapTo[NewAuthor])
|
|
// }
|
|
}
|
|
|
|
final case class BookWithAuthor(
|
|
id: Int,
|
|
title: String,
|
|
isbn: String,
|
|
author: Author,
|
|
createdAt: LocalDateTime
|
|
)
|
|
object BookWithAuthor {
|
|
def tupled = (apply _).tupled
|
|
implicit val codec = deriveCodec[BookWithAuthor]
|
|
}
|
|
|
|
sealed trait BookSearchMode extends EnumEntry
|
|
object BookSearchMode extends Enum[BookSearchMode] {
|
|
val values = findValues
|
|
case object BookTitle extends BookSearchMode
|
|
case object AuthorName extends BookSearchMode
|
|
|
|
implicit val yearQueryParamDecoder: QueryParamDecoder[BookSearchMode] =
|
|
QueryParamDecoder[String].emap(s =>
|
|
withNameEither(s).leftMap(e => ParseFailure(e.getMessage, e.getMessage))
|
|
)
|
|
object Matcher extends QueryParamDecoderMatcher[BookSearchMode]("mode")
|
|
|
|
}
|