use redux_rs::{Selector, Store};
#[derive(Default, Debug)]
struct State {
todos: Vec<Todo>,
visibility_filter: VisibilityFilter,
}
#[derive(Debug)]
struct Todo {
text: String,
completed: bool,
}
#[derive(Debug)]
enum VisibilityFilter {
ShowAll,
ShowCompleted,
}
impl Default for VisibilityFilter {
fn default() -> Self {
VisibilityFilter::ShowCompleted
}
}
enum Action {
AddTodo { text: String },
ToggleTodo { index: usize },
SetVisibilityFilter { filter: VisibilityFilter },
}
fn reducer(mut state: State, action: Action) -> State {
match action {
Action::AddTodo { text } => State {
todos: {
state.todos.push(Todo { text, completed: false });
state.todos
},
..state
},
Action::ToggleTodo { index } => State {
todos: {
if let Some(todo) = state.todos.get_mut(index) {
todo.completed = !todo.completed;
}
state.todos
},
..state
},
Action::SetVisibilityFilter { filter } => State {
visibility_filter: filter,
..state
},
}
}
struct SelectNumberCompletedTodos;
impl Selector<State> for SelectNumberCompletedTodos {
type Result = usize;
fn select(&self, state: &State) -> Self::Result {
state.todos.iter().filter(|t| t.completed).count()
}
}
#[tokio::main]
async fn main() {
let store = Store::new(reducer);
store.subscribe(|state: &State| println!("New state: {:?}", state)).await;
println!("Number of completed tasks: {}", store.select(SelectNumberCompletedTodos).await);
store
.dispatch(Action::AddTodo {
text: "Go to swimming pool".to_string(),
})
.await;
println!("Number of completed tasks: {}", store.select(SelectNumberCompletedTodos).await);
store.dispatch(Action::ToggleTodo { index: 0 }).await;
println!("Number of completed tasks: {}", store.select(SelectNumberCompletedTodos).await);
store
.dispatch(Action::SetVisibilityFilter {
filter: VisibilityFilter::ShowAll,
})
.await;
}