diff --git a/Cargo.toml b/Cargo.toml
index b315c7c..4912a35 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -31,4 +31,7 @@ gloo-storage = "0.2"
gloo-net = "0.4"
wasm-bindgen-futures = "0.4"
serde = { version = "1.0", features = ["derive"] }
-chrono = { version = "0.4", features = ["serde", "wasmbind"] }
\ No newline at end of file
+serde_json = "1.0" # Added for JSON serialization/deserialization
+chrono = { version = "0.4", features = ["serde", "wasmbind"] }
+pulldown-cmark = "0.9"
+html-escape = "0.2"
\ No newline at end of file
diff --git a/index.scss b/index.scss
index aab6577..fcb0a6b 100644
--- a/index.scss
+++ b/index.scss
@@ -2,6 +2,7 @@
@import 'styles/modal.scss';
@import 'styles/comments.scss';
@import 'styles/forms.scss';
+@import 'styles/markdown.scss';
// CSS Custom Properties for theming
:root {
diff --git a/src/app.rs b/src/app.rs
index 18b3bc0..7081482 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -5,6 +5,7 @@ use gloo_storage::{LocalStorage, Storage};
use serde::{Deserialize, Serialize};
use crate::home::HomePage;
use crate::kanban::KanbanBoard;
+use crate::edit_card_page::EditCardPage;
#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize)]
enum Theme {
@@ -22,11 +23,17 @@ impl Theme {
}
#[derive(Clone, Routable, PartialEq)]
-enum Route {
+pub enum Route {
#[at("/")]
Home,
#[at("/kanban")]
Kanban,
+ #[at("/edit/:card_id")]
+ EditCard { card_id: String },
+ #[at("/edit?documentid=:document_id")]
+ EditByDocumentId { document_id: String },
+ #[at("/edit?content=:content")]
+ EditByContent { content: String },
#[not_found]
#[at("/404")]
NotFound,
@@ -36,6 +43,13 @@ fn switch(routes: Route) -> Html {
match routes {
Route::Home => html! {
{"Card not found, redirecting..."}
}; + } + + let on_title_change = { + let card = card.clone(); + Callback::from(move |e: Event| { + let input: HtmlInputElement = e.target_unchecked_into(); + let mut updated_card = (*card).clone(); + updated_card.title = input.value(); + card.set(updated_card); + }) + }; + + let on_description_change = { + let card = card.clone(); + Callback::from(move |value: String| { + let mut updated_card = (*card).clone(); + updated_card.description = value; + card.set(updated_card); + }) + }; + + let on_priority_change = { + let card = card.clone(); + Callback::from(move |e: Event| { + let select: HtmlSelectElement = e.target_unchecked_into(); + let mut updated_card = (*card).clone(); + updated_card.priority = select.value(); + card.set(updated_card); + }) + }; + + let on_assignee_change = { + let card = card.clone(); + Callback::from(move |e: Event| { + let input: HtmlInputElement = e.target_unchecked_into(); + let mut updated_card = (*card).clone(); + updated_card.assignee = input.value(); + card.set(updated_card); + }) + }; + + let on_due_date_change = { + let card = card.clone(); + Callback::from(move |date: String| { + let mut updated_card = (*card).clone(); + updated_card.due_date = date; + card.set(updated_card); + }) + }; + + let on_add_comment = { + let card = card.clone(); + Callback::from(move |content: String| { + let mut updated_card = (*card).clone(); + let new_comment = Comment { + id: format!("comment-{}", Utc::now().timestamp_millis()), + author: "Current User".to_string(), // In a real app, this would be the logged-in user + content, + timestamp: Utc::now().to_rfc3339(), + }; + updated_card.comments_list.push(new_comment); + updated_card.comments = updated_card.comments_list.len() as u32; + card.set(updated_card); + }) + }; + + let on_delete_comment = { + let card = card.clone(); + Callback::from(move |comment_id: String| { + let mut updated_card = (*card).clone(); + updated_card.comments_list.retain(|c| c.id != comment_id); + updated_card.comments = updated_card.comments_list.len() as u32; + card.set(updated_card); + }) + }; + + let on_tags_change = { + let card = card.clone(); + Callback::from(move |e: Event| { + let input: HtmlInputElement = e.target_unchecked_into(); + let mut updated_card = (*card).clone(); + updated_card.tags = input.value() + .split(',') + .map(|s| s.trim().to_string()) + .filter(|s| !s.is_empty()) + .collect(); + card.set(updated_card); + }) + }; + + let on_save_click = { + let card = card.clone(); + let kanban_data = kanban_data.clone(); + let navigator = navigator.clone(); + Callback::from(move |_| { + let mut new_data = (*kanban_data).clone(); + let updated_card = (*card).clone(); + + // Find and update the card in the data + for column in &mut new_data.columns { + if let Some(card_index) = column.cards.iter().position(|c| c.id == updated_card.id) { + column.cards[card_index] = updated_card.clone(); + break; + } + } + + // Save updated data to local storage + LocalStorage::set("kanban_data", serde_json::to_string(&new_data).unwrap()).unwrap(); + kanban_data.set(new_data); // Update state + navigator.push(&Route::Kanban); // Navigate back to kanban board + }) + }; + + let on_cancel_click = { + let navigator = navigator.clone(); + Callback::from(move |_| { + navigator.push(&Route::Kanban); // Navigate back to kanban board without saving + }) + }; + + let tags_string = card.tags.join(", "); + + html! { +{&card.description}
+