use crate::error_template::{AppError, ErrorTemplate}; use leptos::*; use leptos_meta::*; use leptos_router::*; use serde::{Deserialize, Serialize}; #[cfg(feature = "ssr")] use sqlx::FromRow; use uuid::Uuid; #[component] pub fn App() -> impl IntoView { // Provides context that manages stylesheets, titles, meta tags, etc. provide_meta_context(); view! { // injects a stylesheet into the document // id=leptos means cargo-leptos will hot-reload this stylesheet // sets the document title // content for this welcome page <Router fallback=|| { let mut outside_errors = Errors::default(); outside_errors.insert_with_default_key(AppError::NotFound); view! { <ErrorTemplate outside_errors/> } .into_view() }> <main class="container"> <Routes> <Route path="" view=HomePage/> </Routes> </main> </Router> } } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[cfg_attr(feature = "ssr", derive(FromRow))] struct Series { id: Uuid, name: String, } #[server] pub async fn get_all() -> Result<Vec<String>, ServerFnError> { use sqlx::{Pool, Postgres}; use tokio_stream::StreamExt; let pool: Pool<Postgres> = expect_context(); let mut r = sqlx::query_as::<_, Series>("select * from series;").fetch(&pool); let mut found = Vec::new(); while let Some(series) = r.try_next().await? { found.push(series.name); } Ok(found) } /// Renders the home page of your application. #[component] fn HomePage() -> impl IntoView { // Creates a reactive value to update the button let load = create_resource(|| (), |_| async move { get_all().await }); view! { <h1>"What We're Watching"</h1> <div class="card"> <Suspense fallback=|| view!{ <div>"Loading..."</div> }> <ul> {load().map(format_series)} </ul> </Suspense> </div> } } fn format_series(data: Result<Vec<String>, ServerFnError>) -> Vec<impl IntoView> { data.unwrap_or_default() .into_iter() .map(|d| { view! { <li>{d}</li> } }) .collect::<Vec<_>>() }