Untitled

 avatar
unknown
rust
a year ago
2.5 kB
7
Indexable
use std::cell::RefCell;

use leptos::prelude::*;

#[derive(Debug, Default, Clone)]
pub struct Task {
    pub id: u32,
    pub name: ArcRwSignal<String>,
    pub some_big_nonreactive_data: String,
}

impl Task {
    pub fn new(id: u32, name: &str) -> Self {
        Self {
            id,
            name: ArcRwSignal::new(name.into()),
            ..Default::default()
        }
    }

    pub fn change_name(&self, name: &str) {
        self.name.set(name.into());
    }

    pub fn change_data(&mut self, data: &str) {
        self.some_big_nonreactive_data = data.into();
    }
}

#[derive(Debug, Default, Clone)]
pub struct Container {
    pub id: u32,
    pub name: RwSignal<String>,
    pub tasks: RwSignal<Vec<Task>>,
    task_ids: RefCell<Vec<u32>>,
}

impl Container {
    pub fn new(id: u32, name: &str) -> Self {
        Container {
            id,
            name: RwSignal::new(name.into()),
            ..Default::default()
        }
    }

    pub fn change_name(&self, name: &str) {
        self.name.set(name.into());
    }

    pub fn insert_task(&self, position: usize, task: Task) -> bool {
        if self.task_ids.borrow().contains(&task.id) {
            return false;
        }
        let position = position.min(self.task_count());
        self.task_ids.borrow_mut().insert(position, task.id);
        self.tasks.write().insert(position, task);
        true
    }

    pub fn add_task(&self, task: Task) -> bool {
        self.insert_task(0, task)
    }

    pub fn task_count(&self) -> usize {
        self.task_ids.borrow().len()
    }
}

#[component]
pub fn Task(task: Task) -> impl IntoView {
    view! {
        <div class="task">
            <div class="header">"#" {task.id}</div>
            <div class="name">{task.name}</div>
        </div>
    }
}

#[component]
pub fn Container(container: Container) -> impl IntoView {
    let container1 = container.clone();

    let add_task = move |_| {
        container1.add_task(Task::new(1 /* there was a counter */, ""));
    };

    let tasks = move || container.tasks.get();

    view! {
        <div class="stage">
            <div class="header">
                <button on:click=add_task class="add">
                    +
                </button>
                {container.name}
            </div>
            <div class="tasks">
                <For each=tasks key=|task| task.id let:task>
                    <Task task/>
                </For>
            </div>
        </div>
    }
}
Editor is loading...
Leave a Comment