diff --git a/quotesdb/src/bin/ui/pages/quote.rs b/quotesdb/src/bin/ui/pages/quote.rs index b3fd968..349c066 100644 --- a/quotesdb/src/bin/ui/pages/quote.rs +++ b/quotesdb/src/bin/ui/pages/quote.rs @@ -57,6 +57,20 @@ pub fn quote_page(props: &QuotePageProps) -> Html { let edit_tags = use_state(String::new); let navigator = use_navigator().unwrap(); + let new_auth: UseStateHandle> = use_state(|| None); + + // Show a one-time auth code notice if this quote was just created. + { + let id = id.clone(); + let new_auth = new_auth.clone(); + use_effect_with(id.clone(), move |id| { + if storage::take_new_quote(id) { + if let Some(auth_code) = storage::get_auth_code(id) { + new_auth.set(Some(auth_code)); + } + } + }); + } // Fetch the quote on mount (and re-fetch when id changes) { @@ -237,6 +251,16 @@ pub fn quote_page(props: &QuotePageProps) -> Html { } else if let Some(q) = (*quote).clone() { + if let Some(auth) = (*new_auth).clone() { +
+

{ "Quote submitted! Save your auth code — you'll need it to edit or delete this quote." }

+
+ { "Auth Code: " } + { auth } +
+
+ } + if let Some(action_err) = (*action_error).clone() { } diff --git a/quotesdb/src/bin/ui/pages/submit.rs b/quotesdb/src/bin/ui/pages/submit.rs index 922ad17..3084f8f 100644 --- a/quotesdb/src/bin/ui/pages/submit.rs +++ b/quotesdb/src/bin/ui/pages/submit.rs @@ -14,9 +14,8 @@ use yew_router::prelude::*; /// Submit page component. /// /// Provides a form for creating a new quote with fields for text, author, -/// source, date, tags, and an optional custom auth code. On success, displays -/// the returned auth code prominently so the user can save it, and stores it -/// in session storage for immediate use. +/// source, date, tags, and an optional custom auth code. On success, navigates +/// directly to the quote detail page and stores the auth code in session storage. #[function_component(SubmitPage)] pub fn submit_page() -> Html { let text = use_state(String::new); @@ -27,8 +26,8 @@ pub fn submit_page() -> Html { let custom_auth = use_state(String::new); let submitting = use_state(|| false); let error: UseStateHandle> = use_state(|| None); - let success: UseStateHandle> = use_state(|| None); // (quote_id, auth_code) let turnstile_token: UseStateHandle> = use_state(|| None); + let navigator = use_navigator().unwrap(); // Register the Turnstile callback in the global window object. { @@ -57,7 +56,7 @@ pub fn submit_page() -> Html { let custom_auth = custom_auth.clone(); let submitting = submitting.clone(); let error = error.clone(); - let success = success.clone(); + let navigator = navigator.clone(); let turnstile_token = turnstile_token.clone(); Callback::from(move |e: SubmitEvent| { e.prevent_default(); @@ -114,12 +113,13 @@ pub fn submit_page() -> Html { let submitting = submitting.clone(); let error = error.clone(); - let success = success.clone(); + let navigator = navigator.clone(); spawn_local(async move { match api::create_quote(&input).await { Ok(resp) => { storage::set_auth_code(&resp.quote.id, &resp.auth_code); - success.set(Some((resp.quote.id, resp.auth_code))); + storage::mark_new_quote(&resp.quote.id); + navigator.push(&Route::QuoteDetail { id: resp.quote.id }); submitting.set(false); } Err(ApiError::Server { status, message }) => { @@ -135,30 +135,6 @@ pub fn submit_page() -> Html { }) }; - if let Some((quote_id, auth_code)) = (*success).clone() { - return html! { -
-

{ "Quote Submitted!" }

-

{ "Your quote has been added. Save your auth code below — you'll need it to edit or delete this quote." }

-
- { "Auth Code: " } - { &auth_code } -
-
- - to={Route::QuoteDetail { id: quote_id.clone() }} - classes="btn btn--primary" - > - { "View your quote" } - > - to={Route::Browse} classes="btn"> - { "Browse all quotes" } - > -
-
- }; - } - html! {

{ "Submit a Quote" }

diff --git a/quotesdb/src/bin/ui/storage.rs b/quotesdb/src/bin/ui/storage.rs index 138b029..f12dd3d 100644 --- a/quotesdb/src/bin/ui/storage.rs +++ b/quotesdb/src/bin/ui/storage.rs @@ -52,3 +52,39 @@ pub fn clear_auth_code(quote_id: &str) { let _ = storage.remove_item(&format!("auth_code_{quote_id}")); } } + +/// Mark a quote as newly created so the quote detail page can show a one-time auth code notice. +/// +/// Sets `new_quote_{quote_id}` in `sessionStorage`. +/// +/// # Arguments +/// - `quote_id` — The quote's unique ID. +pub fn mark_new_quote(quote_id: &str) { + if let Some(storage) = web_sys::window() + .and_then(|w| w.session_storage().ok()) + .flatten() + { + let _ = storage.set_item(&format!("new_quote_{quote_id}"), "1"); + } +} + +/// Check whether this quote was just created and consume the marker. +/// +/// Returns `true` and removes the `new_quote_{quote_id}` key if it was present. +/// This is a one-shot read — a second call for the same ID always returns `false`. +/// +/// # Arguments +/// - `quote_id` — The quote's unique ID. +pub fn take_new_quote(quote_id: &str) -> bool { + if let Some(storage) = web_sys::window() + .and_then(|w| w.session_storage().ok()) + .flatten() + { + let key = format!("new_quote_{quote_id}"); + if storage.get_item(&key).ok().flatten().is_some() { + let _ = storage.remove_item(&key); + return true; + } + } + false +}