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.

89 lines
2.6 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 Action
  13. case object Init extends Action
  14. case class Add(content: String) extends Action
  15. case class Edit(id: Int, content: String) extends Action
  16. case class Delete(id: Int) extends Action
  17. private case class InternalAdd(content: String) extends Action
  18. private case object End extends Action
  19. case class State(todos: Vector[Todo], counter: Int)
  20. def reducer(logger: Logger[Task])(
  21. state: State,
  22. action: Action
  23. ): (State, Option[Task[Action]]) =
  24. action match {
  25. case Init => (state, None)
  26. case Add(content) =>
  27. val nextAction = Some(for {
  28. // _ <- logger.debug(s"Received $content")
  29. res <- Task.pure(InternalAdd(content))
  30. } yield res)
  31. (state, nextAction)
  32. case Edit(_id, content) =>
  33. val condition: Todo => Boolean = _.id == _id
  34. val nextState = state
  35. .modify(_.todos.eachWhere(condition))
  36. .using(_.copy(content = content))
  37. (nextState, None)
  38. case Delete(id) =>
  39. (state.copy(state.todos.filterNot(_.id == id)), None)
  40. case InternalAdd(content) =>
  41. val nextState = state.copy(
  42. todos = state.todos :+ Todo(state.counter, content),
  43. counter = state.counter + 1
  44. )
  45. (nextState, Some(logger.debug(s"Received $content") >> Task.pure(End)))
  46. case End => (state, None)
  47. }
  48. def apply(logger: Logger[Task]) =
  49. Task.deferAction(implicit s =>
  50. for {
  51. logMware <- actionLoggerMiddleware[Action, State](logger, "TodoStore")
  52. store <-
  53. Store
  54. .createL[Action, State](
  55. Init,
  56. State(Vector.empty[Todo], 0),
  57. Reducer.withOptionalEffects(reducer(logger) _),
  58. Seq(
  59. // actionLoggerMiddleware(logger, "TodoStore2")
  60. logMware
  61. )
  62. )
  63. } yield (store)
  64. )
  65. }
  66. // Task.deferAction(implicit s =>
  67. // Store
  68. // .createJsonL[Action, State](
  69. // Init,
  70. // State(Vector.empty[Todo], 0),
  71. // Reducer.withOptionalEffects(reducer(logger) _),
  72. // "TodoStore",
  73. // logger
  74. // // Seq(
  75. // // actionLoggerMiddleware(logger, "TodoStore")
  76. // // // actionLoggerMiddleware(logger, "TodoStore2")
  77. // // )
  78. // )
  79. // )