diff --git a/src/components/bottom_panel.rs b/src/components/bottom_panel.rs index c90d542..51edb4d 100644 --- a/src/components/bottom_panel.rs +++ b/src/components/bottom_panel.rs @@ -2,6 +2,7 @@ use dioxus::prelude::*; use crate::components::navigation::Navigation; use crate::components::project_form::ProjectForm; use crate::components::task_form::TaskForm; +use crate::models::project::Project; use crate::route::Route; #[component] @@ -11,9 +12,11 @@ pub(crate) fn BottomPanel(display_form: Signal) -> Element { let mut expanded = use_signal(|| display_form()); let navigation_expanded = use_signal(|| false); let current_route = use_route(); + + let mut project_being_edited = use_context::>>(); - use_effect(use_reactive(&display_form, move |creating_task| { - if creating_task() { + use_effect(use_reactive(&display_form, move |display_form| { + if display_form() { expanded.set(true); } else { spawn(async move { @@ -39,8 +42,10 @@ pub(crate) fn BottomPanel(display_form: Signal) -> Element { match current_route { Route::ProjectsPage => rsx! { ProjectForm { + project: project_being_edited(), on_successful_submit: move |_| { display_form.set(false); + project_being_edited.set(None); } } }, diff --git a/src/components/create_task_button.rs b/src/components/create_task_button.rs deleted file mode 100644 index 25d69a2..0000000 --- a/src/components/create_task_button.rs +++ /dev/null @@ -1,16 +0,0 @@ -use dioxus::prelude::*; - -#[component] -pub(crate) fn CreateButton(creating: Signal) -> Element { - rsx! { - button { - class: "m-4 py-3 px-5 self-end text-center bg-zinc-300/50 rounded-xl border-t-zinc-200 border-t backdrop-blur drop-shadow-[0_-5px_10px_rgba(0,0,0,0.2)] text-2xl text-zinc-200", - onclick: move |_| { - creating.set(!creating()); - }, - i { - class: format!("min-w-6 fa-solid {}", if creating() { "fa-xmark" } else { "fa-plus" }), - } - } - } -} diff --git a/src/components/form_open_button.rs b/src/components/form_open_button.rs new file mode 100644 index 0000000..c4935f0 --- /dev/null +++ b/src/components/form_open_button.rs @@ -0,0 +1,22 @@ +use dioxus::prelude::*; +use crate::models::project::Project; + +#[component] +pub(crate) fn FormOpenButton(opened: Signal) -> Element { + let mut project_being_edited = use_context::>>(); + + rsx! { + button { + class: "m-4 py-3 px-5 self-end text-center bg-zinc-300/50 rounded-xl border-t-zinc-200 border-t backdrop-blur drop-shadow-[0_-5px_10px_rgba(0,0,0,0.2)] text-2xl text-zinc-200", + onclick: move |_| { + if opened() { + project_being_edited.set(None); + } + opened.set(!opened()); + }, + i { + class: format!("min-w-6 fa-solid {}", if opened() { "fa-xmark" } else { "fa-plus" }), + } + } + } +} diff --git a/src/components/layout.rs b/src/components/layout.rs index ed89b5f..1e67361 100644 --- a/src/components/layout.rs +++ b/src/components/layout.rs @@ -3,18 +3,26 @@ use crate::route::Route; use dioxus::core_macro::rsx; use dioxus::dioxus_core::Element; use dioxus::prelude::*; -use crate::components::create_task_button::CreateButton; +use crate::components::form_open_button::FormOpenButton; use crate::components::sticky_bottom::StickyBottom; +use crate::models::project::Project; #[component] pub(crate) fn Layout() -> Element { - let display_form = use_signal(|| false); + let mut display_form = use_signal(|| false); + let project_being_edited = use_context_provider::>>( + || Signal::new(None) + ); + + use_effect(move || { + display_form.set(project_being_edited().is_some()); + }); rsx! { Outlet:: {} StickyBottom { - CreateButton { - creating: display_form, + FormOpenButton { + opened: display_form, } BottomPanel { display_form: display_form, diff --git a/src/components/mod.rs b/src/components/mod.rs index bd961d8..3dde58e 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -5,7 +5,7 @@ pub(crate) mod task_form; pub(crate) mod task_list; pub(crate) mod pages; pub(crate) mod navigation; -pub(crate) mod create_task_button; +pub(crate) mod form_open_button; pub(crate) mod bottom_panel; pub(crate) mod sticky_bottom; pub(crate) mod category_input; diff --git a/src/components/pages/projects_page.rs b/src/components/pages/projects_page.rs index fd7f34e..5b18b05 100644 --- a/src/components/pages/projects_page.rs +++ b/src/components/pages/projects_page.rs @@ -1,22 +1,32 @@ use dioxus::prelude::*; use dioxus_query::prelude::QueryResult; +use crate::models::project::Project; use crate::query::projects::use_projects_query; use crate::query::QueryValue; #[component] pub(crate) fn ProjectsPage() -> Element { let projects_query = use_projects_query(); - + let mut project_being_edited = use_context::>>(); + rsx! { match projects_query.result().value() { QueryResult::Ok(QueryValue::Projects(projects)) | QueryResult::Loading(Some(QueryValue::Projects(projects))) => rsx! { div { class: "flex flex-col", - for project in projects { + for project in projects.clone() { div { key: "{project.id()}", - class: "px-8 py-4", + class: format!( + "px-8 py-4 select-none {}", + if project_being_edited().map(|p| p.id()) == Some(project.id()) { + "bg-zinc-700" + } else { "" } + ), + onclick: move |_| { + project_being_edited.set(Some(project.clone())); + }, {project.title()} } } diff --git a/src/components/project_form.rs b/src/components/project_form.rs index fc7ad2f..5efb58b 100644 --- a/src/components/project_form.rs +++ b/src/components/project_form.rs @@ -1,5 +1,5 @@ -use crate::models::project::NewProject; -use crate::server::projects::create_project; +use crate::models::project::{NewProject, Project}; +use crate::server::projects::{create_project, edit_project}; use dioxus::core_macro::{component, rsx}; use dioxus::dioxus_core::Element; use dioxus::prelude::*; @@ -7,17 +7,28 @@ use dioxus_query::prelude::use_query_client; use crate::query::{QueryErrors, QueryKey, QueryValue}; #[component] -pub(crate) fn ProjectForm(on_successful_submit: EventHandler<()>) -> Element { +pub(crate) fn ProjectForm(project: Option, on_successful_submit: EventHandler<()>) + -> Element { let query_client = use_query_client::(); + let project_for_submit = project.clone(); + rsx! { form { onsubmit: move |event| { + let project_clone = project_for_submit.clone(); async move { let new_project = NewProject::new( event.values().get("title").unwrap().as_value() ); - let _ = create_project(new_project).await; + match project_clone { + Some(project) => { + let _ = edit_project(project.id(), new_project).await; + } + None => { + let _ = create_project(new_project).await; + } + } query_client.invalidate_queries(&[ QueryKey::Projects ]); @@ -35,9 +46,10 @@ pub(crate) fn ProjectForm(on_successful_submit: EventHandler<()>) -> Element { } } input { - r#type: "text", name: "title", required: true, + initial_value: project.map(|project| project.title().to_owned()), + r#type: "text", class: "py-2 px-3 grow bg-zinc-800/50 rounded-lg", id: "input_title" }