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
52 lines
1.4 KiB
package nova.monadic_sfx.ui.components.todo
|
|
|
|
import com.softwaremill.quicklens._
|
|
import io.circe.generic.JsonCodec
|
|
import io.odin.Logger
|
|
import monix.bio.Task
|
|
import nova.monadic_sfx.util.reactive.Middlewares.actionLoggerMiddleware
|
|
import nova.monadic_sfx.util.reactive.Reducer
|
|
import nova.monadic_sfx.util.reactive.Store
|
|
|
|
case class Todo(id: Int, content: String)
|
|
|
|
object TodoListStore {
|
|
|
|
@JsonCodec
|
|
sealed trait Command
|
|
case object Init extends Command
|
|
case class Add(content: String) extends Command
|
|
case class Edit(id: Int, content: String) extends Command
|
|
case class Delete(id: Int) extends Command
|
|
|
|
case class State(todos: Vector[Todo], counter: Int)
|
|
|
|
def reducer(
|
|
state: State,
|
|
action: Command
|
|
) =
|
|
action match {
|
|
case Init => state
|
|
case Add(content) =>
|
|
state.copy(
|
|
todos = state.todos :+ Todo(state.counter, content),
|
|
counter = state.counter + 1
|
|
)
|
|
case Edit(_id, content) =>
|
|
val condition: Todo => Boolean = _.id == _id
|
|
state
|
|
.modify(_.todos.eachWhere(condition))
|
|
.using(_.copy(content = content))
|
|
case Delete(id) =>
|
|
state.copy(state.todos.filterNot(_.id == id))
|
|
}
|
|
|
|
def apply(logger: Logger[Task]) =
|
|
Store
|
|
.createL[Command, State](
|
|
Init,
|
|
State(Vector.empty[Todo], 0),
|
|
Reducer(reducer _),
|
|
Seq(actionLoggerMiddleware(logger))
|
|
)
|
|
}
|