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.
67 lines
1.8 KiB
67 lines
1.8 KiB
package nova.monadic_sfx.ui.components.todo
|
|
|
|
import nova.monadic_sfx.util.reactive.Store
|
|
import nova.monadic_sfx.util.reactive.Reducer
|
|
import nova.monadic_sfx.util.reactive.Middlewares.actionLoggerMiddleware
|
|
import io.odin.Logger
|
|
import monix.bio.Task
|
|
import io.odin._
|
|
import io.odin.syntax._
|
|
import io.circe.generic.JsonCodec
|
|
import com.softwaremill.quicklens._
|
|
|
|
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) =>
|
|
state
|
|
.modify(_.todos.eachWhere(_.id == id))
|
|
.using(_.copy(content = content))
|
|
case Delete(id) =>
|
|
state.copy(state.todos.filterNot(_.id == id))
|
|
}
|
|
|
|
def updateTodo(id: Int, content: String, todos: Vector[Todo]) =
|
|
todos.view.zipWithIndex
|
|
.find {
|
|
case (todo, index) => todo.id == id
|
|
}
|
|
.map {
|
|
case (todo, index) => todo.copy(content = content) -> index
|
|
}
|
|
.map {
|
|
case (todo, index) => todos.updated(index, todo)
|
|
}
|
|
|
|
val middlewareLogger = consoleLogger[Task]().withAsync()
|
|
|
|
def apply(logger: Logger[Task]) =
|
|
Store
|
|
.createL[Command, State](
|
|
Init,
|
|
State(Vector.empty[Todo], 0),
|
|
Reducer(reducer _),
|
|
Seq(actionLoggerMiddleware(logger))
|
|
)
|
|
}
|