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.

52 lines
1.4 KiB

  1. package nova.monadic_sfx.ui.components.todo
  2. import com.softwaremill.quicklens._
  3. import io.circe.generic.JsonCodec
  4. import io.odin.Logger
  5. import monix.bio.Task
  6. import nova.monadic_sfx.util.reactive.Middlewares.actionLoggerMiddleware
  7. import nova.monadic_sfx.util.reactive.Reducer
  8. import nova.monadic_sfx.util.reactive.Store
  9. case class Todo(id: Int, content: String)
  10. object TodoListStore {
  11. @JsonCodec
  12. sealed trait Command
  13. case object Init extends Command
  14. case class Add(content: String) extends Command
  15. case class Edit(id: Int, content: String) extends Command
  16. case class Delete(id: Int) extends Command
  17. case class State(todos: Vector[Todo], counter: Int)
  18. def reducer(
  19. state: State,
  20. action: Command
  21. ) =
  22. action match {
  23. case Init => state
  24. case Add(content) =>
  25. state.copy(
  26. todos = state.todos :+ Todo(state.counter, content),
  27. counter = state.counter + 1
  28. )
  29. case Edit(_id, content) =>
  30. val condition: Todo => Boolean = _.id == _id
  31. state
  32. .modify(_.todos.eachWhere(condition))
  33. .using(_.copy(content = content))
  34. case Delete(id) =>
  35. state.copy(state.todos.filterNot(_.id == id))
  36. }
  37. def apply(logger: Logger[Task]) =
  38. Store
  39. .createL[Command, State](
  40. Init,
  41. State(Vector.empty[Todo], 0),
  42. Reducer(reducer _),
  43. Seq(actionLoggerMiddleware(logger))
  44. )
  45. }