diff --git a/packages/api/src/lib.rs b/packages/api/src/lib.rs index 8c9b029..402c1be 100644 --- a/packages/api/src/lib.rs +++ b/packages/api/src/lib.rs @@ -113,3 +113,8 @@ pub async fn toggle_pin_note(id: String) -> Result<(), ServerFnError> { Err(ServerFnError::new("Note not found".to_string())) } } + +#[post("/api/echo")] +pub async fn echo(message: String) -> Result { + Ok(format!("Echo: {}", message)) +} diff --git a/packages/ui/src/lib.rs b/packages/ui/src/lib.rs index b9a396b..b8acc20 100644 --- a/packages/ui/src/lib.rs +++ b/packages/ui/src/lib.rs @@ -1,7 +1,10 @@ -//! This crate contains all shared UI for the workspace. +//! This is the UI package for the braindump application. mod hero; pub use hero::Hero; mod navbar; pub use navbar::Navbar; + +mod echo; +pub use echo::Echo; diff --git a/packages/web/src/braindump.rs b/packages/web/src/braindump.rs index fce817c..0726f9f 100644 --- a/packages/web/src/braindump.rs +++ b/packages/web/src/braindump.rs @@ -13,6 +13,17 @@ fn BraindumpLayout() -> Element { let notes = use_resource(|| async move { api::list_notes().await.unwrap_or_default() }); + + let refresh_notes = { + let mut notes_ref = notes.clone(); + move || { + spawn(async move { + if let Ok(new_notes) = api::list_notes().await { + notes_ref.set(Some(new_notes)); + } + }); + } + }; let mut selected_note_id = use_signal(|| None::); let search_query = use_signal(|| String::new()); @@ -40,6 +51,11 @@ fn BraindumpLayout() -> Element { on_go_back: move |_| { selected_note_id.set(None); }, + on_save: refresh_notes, + on_delete: move |_| { + selected_note_id.set(None); + refresh_notes(); + }, } }, None => rsx! { @@ -52,6 +68,7 @@ fn BraindumpLayout() -> Element { vec![] ).await { selected_note_id.set(Some(id)); + refresh_notes(); } }); } @@ -158,7 +175,6 @@ fn SidebarContent( div { class: "tags-section", div { class: "tags-label", "Tags" } div { class: "tags-list", - // Tag filtering placeholder button { class: "tag", "Work" } button { class: "tag", "Personal" } button { class: "tag", "Ideas" } @@ -243,10 +259,16 @@ fn EmptyState(on_new_note: EventHandler) -> Element { } #[component] -fn NoteEditor(note_id: String, on_go_back: EventHandler) -> Element { - let note_id_clone_for_resource = note_id.clone(); +fn NoteEditor( + note_id: String, + on_go_back: Callback, + on_save: Callback<()>, + on_delete: Callback<()>, +) -> Element { + let mut note_id_signal = use_signal(|| note_id.clone()); + let note = use_resource(move || { - let id = note_id_clone_for_resource.clone(); + let id = note_id_signal().clone(); async move { api::get_note(id).await.ok() } @@ -257,6 +279,10 @@ fn NoteEditor(note_id: String, on_go_back: EventHandler) -> Element let mut tags = use_signal(|| String::new()); let mut is_pinned = use_signal(|| false); + use_effect(move || { + note_id_signal.set(note_id.clone()); + }); + use_effect(move || { let note_val = note.read_unchecked(); if let Some(Some(n)) = note_val.as_ref() { @@ -267,9 +293,8 @@ fn NoteEditor(note_id: String, on_go_back: EventHandler) -> Element } }); - let note_id_for_save = note_id.clone(); let save_note = move |_: MouseEvent| { - let id = note_id_for_save.clone(); + let id = note_id_signal().clone(); let title_val = title(); let content_val = content(); let tags_input = tags(); @@ -282,24 +307,25 @@ fn NoteEditor(note_id: String, on_go_back: EventHandler) -> Element spawn(async move { let _ = api::update_note(id, title_val, content_val, tags_list, pinned).await; + on_save(()); }); }; - let note_id_for_delete = note_id.clone(); let delete_note = move |_: MouseEvent| { - let id = note_id_for_delete.clone(); + let id = note_id_signal().clone(); spawn(async move { let _ = api::delete_note(id).await; + on_delete(()); }); }; - let note_id_for_toggle = note_id.clone(); let toggle_pin = move |_: MouseEvent| { - let id = note_id_for_toggle.clone(); + let id = note_id_signal().clone(); let current_pin = is_pinned(); spawn(async move { let _ = api::toggle_pin_note(id).await; is_pinned.set(!current_pin); + on_save(()); }); }; @@ -308,7 +334,7 @@ fn NoteEditor(note_id: String, on_go_back: EventHandler) -> Element div { class: "editor-header", button { class: "back-button", - onclick: move |evt| on_go_back.call(evt), + onclick: on_go_back, "← Back" } div { class: "editor-actions",