watch/src/app.rs

100 lines
2.6 KiB
Rust
Raw Normal View History

2024-09-02 18:34:30 +00:00
use crate::error_template::{AppError, ErrorTemplate};
use leptos::*;
use leptos_meta::*;
use leptos_router::*;
2024-09-02 21:43:49 +00:00
use serde::{Deserialize, Serialize};
#[cfg(feature = "ssr")]
use sqlx::FromRow;
use uuid::Uuid;
2024-09-02 18:34:30 +00:00
#[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 <head>
// id=leptos means cargo-leptos will hot-reload this stylesheet
<Stylesheet id="leptos" href="/pkg/watch.css"/>
<Link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
crossorigin="anonymous"
/>
// sets the document title
2024-09-02 21:43:49 +00:00
<Title text="Watch"/>
2024-09-02 18:34:30 +00:00
// 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>
}
}
2024-09-02 21:43:49 +00:00
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "ssr", derive(FromRow))]
struct Series {
id: Uuid,
name: String,
}
2024-09-02 18:34:30 +00:00
#[server]
pub async fn get_all() -> Result<Vec<String>, ServerFnError> {
2024-09-02 21:43:49 +00:00
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);
}
2024-09-02 18:34:30 +00:00
2024-09-02 21:43:49 +00:00
Ok(found)
2024-09-02 18:34:30 +00:00
}
/// Renders the home page of your application.
#[component]
fn HomePage() -> impl IntoView {
// Creates a reactive value to update the button
2024-09-02 21:43:49 +00:00
let load = create_resource(|| (), |_| async move { get_all().await });
2024-09-02 18:34:30 +00:00
view! {
2024-09-02 21:43:49 +00:00
<h1>"What We're Watching"</h1>
<div class="card">
<Suspense fallback=|| view!{ <div>"Loading..."</div> }>
<ul>
{load().map(format_series)}
</ul>
</Suspense>
</div>
2024-09-02 18:34:30 +00:00
}
}
2024-09-02 21:43:49 +00:00
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<_>>()
}