Set up some callbacks to handle the login page state

This commit is contained in:
Savanni D'Gerinel 2025-02-18 23:18:23 -05:00
parent 1c4894df9a
commit 5e4fd97aca
3 changed files with 76 additions and 12 deletions

View File

@ -6,6 +6,9 @@ edition = "2021"
[dependencies] [dependencies]
gloo-net = "0.6.0" gloo-net = "0.6.0"
serde = { version = "1.0.217", features = ["derive"] } serde = { version = "1.0.217", features = ["derive"] }
serde-wasm-bindgen = "0.6.5"
serde_json = "1.0.138"
wasm-bindgen-futures = "0.4.50" wasm-bindgen-futures = "0.4.50"
web-sys = "0.3.77"
yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] } yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] }

View File

@ -1,5 +1,12 @@
use gloo_net::http::Request; use gloo_net::http::{Request, Response};
use serde::Deserialize; use serde::{Deserialize, Serialize};
use wasm_bindgen_futures::wasm_bindgen::{self, JsValue};
#[derive(Serialize)]
struct AuthRequest {
username: String,
password: String,
}
#[derive(Deserialize)] #[derive(Deserialize)]
enum AuthResponse { enum AuthResponse {
@ -12,6 +19,7 @@ struct SessionId(String);
enum ClientError { enum ClientError {
Unauthorized, Unauthorized,
Err(u16),
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -28,12 +36,29 @@ trait Client {
async fn list_users(session_id: SessionId) -> Result<Vec<UserInfo>, ClientError>; async fn list_users(session_id: SessionId) -> Result<Vec<UserInfo>, ClientError>;
} }
pub struct Connection;
impl Connection {
pub fn new() -> Self { Self }
}
impl Client for Connection { impl Client for Connection {
async fn auth(username: String, password: String) -> Result<AuthResponse, ClientError> { async fn auth(username: String, password: String) -> Result<AuthResponse, ClientError> {
let request = Request::post("http://localhost:8001") let response: Response = Request::post("http://localhost:8001")
.body().unwrap(); .body(serde_wasm_bindgen::to_value(&AuthRequest{ username, password }).unwrap())
.unwrap()
.send()
.await
.unwrap();
if response.ok() {
Ok(serde_json::from_slice(&response.binary().await.unwrap()).unwrap())
} else {
Err(ClientError::Err(response.status()))
}
} }
async fn list_users(session_id: SessionId) -> Result<Vec<UserInfo>, ClientError> { async fn list_users(session_id: SessionId) -> Result<Vec<UserInfo>, ClientError> {
todo!()
} }
} }

View File

@ -1,5 +1,6 @@
use std::rc::Rc; use std::rc::Rc;
use web_sys::HtmlInputElement;
use yew::prelude::*; use yew::prelude::*;
mod client; mod client;
@ -36,23 +37,57 @@ impl Reducible for AuthInfo {
#[derive(Properties, PartialEq)] #[derive(Properties, PartialEq)]
struct LoginProps { struct LoginProps {
on_click: Callback<()>, on_login: Callback<(String, String)>,
} }
#[function_component] #[function_component]
fn Login(LoginProps { on_click }: &LoginProps) -> Html { fn Login(LoginProps { on_login }: &LoginProps) -> Html {
let username_node_ref = use_node_ref();
let password_node_ref = use_node_ref();
let username = use_state(|| "".to_owned());
let password = use_state(|| "".to_owned());
let on_click = { let on_click = {
let on_click = on_click.clone(); let on_login = on_login.clone();
Callback::from(move |_| on_click.emit(())) let username = username.clone();
let password = password.clone();
Callback::from(move |_| on_login.emit((username.to_string(), password.to_string())))
}; };
let on_username_changed = {
let username = username.clone();
let username_node_ref = username_node_ref.clone();
Callback::from(move |_| {
let input = username_node_ref.cast::<HtmlInputElement>().unwrap();
println!("username changed: {}", input.value());
username.set(input.value());
})
};
let on_password_changed = {
let password = password.clone();
let password_node_ref = password_node_ref.clone();
Callback::from(move |_| {
let input = password_node_ref.cast::<HtmlInputElement>().unwrap();
println!("password changed: {}", input.value());
password.set(input.value());
})
};
html! { html! {
<div class="login-form"> <div class="login-form">
<div class="card"> <div class="card">
<h1>{"Welcome to Visions VTT"}</h1> <h1>{"Welcome to Visions VTT"}</h1>
<input type="text" name="username" placeholder="username" /> <input ref={username_node_ref} type="text" name="username" placeholder="username" onchange={on_username_changed} />
<input type="password" name="password" placeholder="password" /> <input ref={password_node_ref} type="password" name="password" placeholder="password" onchange={on_password_changed} />
<button onclick={on_click}>{"Login"}</button> <button onclick={on_click}>{"Login"}</button>
</div> </div>
<div class="card">
<p>{(*username).clone()}</p>
<p>{(*password).clone()}</p>
</div>
</div> </div>
} }
} }
@ -60,16 +95,17 @@ fn Login(LoginProps { on_click }: &LoginProps) -> Html {
#[function_component] #[function_component]
fn App() -> Html { fn App() -> Html {
let auth_info = use_reducer(AuthInfo::default); let auth_info = use_reducer(AuthInfo::default);
let client = Connection::new();
let on_login = { let on_login = {
let auth_info = auth_info.clone(); let auth_info = auth_info.clone();
Callback::from(move |_| auth_info.dispatch(AuthAction::Auth("abcdefg".into()))) Callback::from(move |(username, password)| auth_info.dispatch(AuthAction::Auth(username)))
}; };
if auth_info.session_id.is_some() { if auth_info.session_id.is_some() {
html! { <p>{ "this is just a thing" }</p> } html! { <p>{ "this is just a thing" }</p> }
} else { } else {
html! { <Login on_click={on_login.clone()} /> } html! { <Login on_login={on_login.clone()} /> }
} }
} }