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

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))
)
}