use crate::*;
pub(crate) fn use_todo_list() -> UseTodoList {
UseTodoList::new(
use_signal(|| {
let mut items: Vec<String> = Vec::with_capacity(1000);
for index in 1..=1000 {
items.push(format!("Item {}", index));
}
items
}),
use_signal(String::new),
use_signal(String::new),
)
}
pub(crate) fn validate_todo_new_item(state: UseTodoList) {
let new_item_value: String = state.get_new_item().get();
if new_item_value.trim().is_empty() {
state
.get_add_error()
.set("Please enter an item name.".to_string());
} else if new_item_value.trim().len() > 50 {
state
.get_add_error()
.set("Item name is too long (max 50 chars).".to_string());
} else {
state.get_add_error().set(String::new());
}
}
pub(crate) fn todo_list_on_input_new_item(state: UseTodoList) -> Option<Rc<dyn Fn(Event)>> {
Some(Rc::new(move |event: Event| {
if let Some(target) = event.target()
&& let Ok(input) = target.clone().dyn_into::<HtmlInputElement>()
{
state.get_new_item().set(input.value());
}
validate_todo_new_item(state);
}))
}
pub(crate) fn todo_list_on_add(state: UseTodoList) -> Option<Rc<dyn Fn(Event)>> {
Some(Rc::new(move |_event: Event| {
validate_todo_new_item(state);
let add_error_value: String = state.get_add_error().get();
if add_error_value.is_empty() {
let text: String = state.get_new_item().get();
let mut current: Vec<String> = state.get_items().get();
current.push(text.trim().to_string());
state.get_items().set(current);
state.get_new_item().set(String::new());
}
}))
}
pub(crate) fn todo_list_on_remove(
items: Signal<Vec<String>>,
index: usize,
) -> Option<Rc<dyn Fn(Event)>> {
Some(Rc::new(move |_event: Event| {
let mut current: Vec<String> = items.get();
if index < current.len() {
current.remove(index);
items.set(current);
}
}))
}