//! Submit page — new quote submission form. use crate::api::{self, ApiError}; use crate::components::error::ErrorDisplay; use crate::storage; use crate::Route; use quotesdb::CreateQuoteInput; use wasm_bindgen_futures::spawn_local; use web_sys::HtmlInputElement; use yew::prelude::*; 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. #[function_component(SubmitPage)] pub fn submit_page() -> Html { let text = use_state(String::new); let author = use_state(String::new); let source = use_state(String::new); let date = use_state(String::new); let tags = use_state(String::new); 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 onsubmit = { let text = text.clone(); let author = author.clone(); let source = source.clone(); let date = date.clone(); let tags = tags.clone(); let custom_auth = custom_auth.clone(); let submitting = submitting.clone(); let error = error.clone(); let success = success.clone(); Callback::from(move |e: SubmitEvent| { e.prevent_default(); if *submitting { return; } let text_val = (*text).clone(); let author_val = (*author).clone(); let source_val = (*source).clone(); let date_val = (*date).clone(); let tags_val = (*tags).clone(); let auth_val = (*custom_auth).clone(); if text_val.is_empty() { error.set(Some("Quote text is required.".to_string())); return; } let parsed_tags: Vec = tags_val .split(',') .map(|t| t.trim().to_string()) .filter(|t| !t.is_empty()) .collect(); let input = CreateQuoteInput { text: text_val, author: if author_val.is_empty() { "Anonymous".to_string() } else { author_val }, source: if source_val.is_empty() { None } else { Some(source_val) }, date: if date_val.is_empty() { None } else { Some(date_val) }, tags: parsed_tags, auth_code: if auth_val.is_empty() { None } else { Some(auth_val) }, }; submitting.set(true); error.set(None); let submitting = submitting.clone(); let error = error.clone(); let success = success.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))); submitting.set(false); } Err(ApiError::Server { status, message }) => { error.set(Some(format!("Error {status}: {message}"))); submitting.set(false); } Err(e) => { error.set(Some(e.to_string())); submitting.set(false); } } }); }) }; 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" }

if let Some(err) = (*error).clone() { }