add: movie input, refactor things, and fix vscode config

This commit is contained in:
2025-05-03 22:28:19 -07:00
parent 88b0d26b36
commit a68ffc4bb7
8 changed files with 119 additions and 24 deletions

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"rust-analyzer.cargo.features": ["ssr"]
}

View File

@@ -15,6 +15,7 @@ leptos_axum = { version = "0.7.0", optional = true }
leptos_meta = { version = "0.7.0" }
tokio = { version = "1", features = ["rt-multi-thread"], optional = true }
wasm-bindgen = { version = "=0.2.100", optional = true }
serde = { version = "1.0.219", features = ["derive"] }
[features]
hydrate = [

View File

@@ -1,9 +1,12 @@
use leptos::{prelude::*, task::spawn_local};
use leptos::prelude::*;
use leptos_meta::{provide_meta_context, MetaTags, Stylesheet, Title};
use leptos_router::{
components::{Route, Router, Routes},
StaticSegment,
};
use movies::Movies;
mod movies;
pub fn shell(options: LeptosOptions) -> impl IntoView {
view! {
@@ -25,21 +28,18 @@ pub fn shell(options: LeptosOptions) -> impl IntoView {
#[server]
pub async fn load_counter() -> Result<usize, ServerFnError> {
use tokio::sync::Mutex;
use std::sync::Arc;
let data = use_context::<Arc<Mutex<usize>>>().unwrap();
let mut data = data.lock().await;
use crate::common::Context;
let data = use_context::<Context>().unwrap();
let data = data.counter.lock().await;
Ok(*data)
}
#[server]
pub async fn increment_counter() -> Result<usize, ServerFnError> {
use tokio::sync::Mutex;
use std::sync::Arc;
let data = use_context::<Arc<Mutex<usize>>>().unwrap();
let mut data = data.lock().await;
use crate::common::Context;
let data = use_context::<Context>().unwrap();
let mut data = data.counter.lock().await;
*data += 1;
println!("Counter {}", *data);
Ok(*data)
}
@@ -72,27 +72,24 @@ pub fn App() -> impl IntoView {
fn HomePage() -> impl IntoView {
let increment_counter = ServerAction::<IncrementCounter>::new();
let counts = Resource::new(
move || {
(
increment_counter.version().get(),
)
},
move |_| load_counter()
move || (increment_counter.version().get(),),
move |_| load_counter(),
);
let existing_counter = move || {
Suspend::new(async move {
let count = counts.await;
view! { {count} }
view! { {count} }
})
};
let onclick = move |ev| {
increment_counter.dispatch(IncrementCounter{});
let onclick = move |_| {
increment_counter.dispatch(IncrementCounter {});
};
view! {
<h1>"Welcome to Leptos!"</h1>
<h1>"Welcome to Wiseau movie picker"</h1>
<Movies></Movies>
<button on:click=onclick>"Click Me: "
<Transition fallback=move || view! { <p>"Loading..."</p> }>
{existing_counter}

52
src/app/movies.rs Normal file
View File

@@ -0,0 +1,52 @@
use leptos::prelude::*;
use crate::model::Movie;
#[server]
pub async fn load_movies() -> Result<Vec<Movie>, ServerFnError> {
use crate::common::Context;
let data = use_context::<Context>().unwrap();
let movies = data.movies.lock().await.clone();
Ok(movies)
}
#[server]
pub async fn add_movie(name: String) -> Result<(), ServerFnError> {
use crate::common::Context;
let data = use_context::<Context>().unwrap();
let mut data = data.movies.lock().await;
data.push(Movie::new(&name));
Ok(())
}
/// Renders the home page of your application.
#[component]
pub fn Movies() -> impl IntoView {
let add_movie = ServerMultiAction::<AddMovie>::new();
let movies_resource =
Resource::new(move || (add_movie.version().get(),), move |_| load_movies());
let movies = move || {
Suspend::new(async move {
let movies = movies_resource.await.unwrap();
view! {
<ul>
{movies.into_iter().map(move |movie| {
view! {
<li>{movie.name}</li>
}
}).collect::<Vec<_>>()}
</ul>
}
})
};
view! {
<h2>"Movies"</h2>
<MultiActionForm action=add_movie>
<label>"Add a movie" <input type="text" name="name"/></label>
<input type="submit" value="Add"/>
</MultiActionForm>
<Transition fallback=move || view! { <p>"Loading..."</p> }>
{movies}
</Transition>
}
}

23
src/common.rs Normal file
View File

@@ -0,0 +1,23 @@
use std::sync::Arc;
use tokio::sync::Mutex;
use crate::model::Movie;
#[derive(Clone)]
pub struct Context {
pub counter: Arc<Mutex<usize>>,
pub movies: Arc<Mutex<Vec<Movie>>>,
}
impl Context {
pub fn new() -> Self {
let movies = vec![
Movie::new("Hackers"),
Movie::new("Princess Bridge"),
];
Self {
counter: Arc::new(Mutex::new(0)),
movies: Arc::new(Mutex::new(movies)),
}
}
}

View File

@@ -1,4 +1,7 @@
pub mod app;
pub mod model;
#[cfg(feature = "ssr")]
pub mod common;
#[cfg(feature = "hydrate")]
#[wasm_bindgen::prelude::wasm_bindgen]

View File

@@ -1,8 +1,8 @@
use wiseau::common;
//#[cfg(feature = "ssr")]
#[tokio::main]
async fn main() {
use std::sync::Arc;
use tokio::sync::Mutex;
use axum::Router;
use leptos::logging::log;
use leptos::prelude::*;
@@ -15,13 +15,13 @@ async fn main() {
// Generate the list of routes in your Leptos App
let routes = generate_route_list(App);
let counter: Arc<Mutex<usize>> = Arc::new(Mutex::new(0));
let context = common::Context::new();
let app = Router::new()
.leptos_routes_with_context(
&leptos_options,
routes,
move || provide_context(counter.clone()),
move || provide_context(context.clone()),
{
let leptos_options = leptos_options.clone();
move || shell(leptos_options.clone())

16
src/model.rs Normal file
View File

@@ -0,0 +1,16 @@
use serde::{Deserialize, Serialize};
#[derive(Clone, Serialize, Deserialize)]
pub struct Movie {
pub name: String,
pub imdb_url: String,
}
impl Movie {
pub fn new(name: &str) -> Self {
Self {
name: name.to_string(),
imdb_url: String::new(),
}
}
}