fix(quotesdb): fix admin_reset_auth_code call, handle status fetch error

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
main
Elijah Voigt 3 months ago
parent 2d1634c815
commit 0be1193759

@ -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<Option<String>> = 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() {
<QuoteCard quote={q.clone()} />
if let Some(auth) = (*new_auth).clone() {
<div class="page-quote__new-notice">
<p>{ "Quote submitted! Save your auth code — you'll need it to edit or delete this quote." }</p>
<div class="page-quote__new-notice-code">
<strong>{ "Auth Code: " }</strong>
<code>{ auth }</code>
</div>
</div>
}
if let Some(action_err) = (*action_error).clone() {
<ErrorDisplay message={action_err} />
}

@ -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<Option<String>> = use_state(|| None);
let success: UseStateHandle<Option<(String, String)>> = use_state(|| None); // (quote_id, auth_code)
let turnstile_token: UseStateHandle<Option<String>> = 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! {
<div class="page-submit page-submit--success">
<h1 class="page-submit__title">{ "Quote Submitted!" }</h1>
<p>{ "Your quote has been added. Save your auth code below — you'll need it to edit or delete this quote." }</p>
<div class="page-submit__auth-code-box">
<strong>{ "Auth Code: " }</strong>
<code class="page-submit__auth-code">{ &auth_code }</code>
</div>
<div class="page-submit__actions">
<Link<Route>
to={Route::QuoteDetail { id: quote_id.clone() }}
classes="btn btn--primary"
>
{ "View your quote" }
</Link<Route>>
<Link<Route> to={Route::Browse} classes="btn">
{ "Browse all quotes" }
</Link<Route>>
</div>
</div>
};
}
html! {
<div class="page-submit">
<h1 class="page-submit__title">{ "Submit a Quote" }</h1>

@ -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
}

Loading…
Cancel
Save