feat: added a session struct to communicate with the api and added it as context

This commit is contained in:
antifallobst 2023-09-30 22:12:57 +02:00
parent 63beba63c8
commit 8c756a4eb6
Signed by: antifallobst
GPG Key ID: 2B4F402172791BAF
8 changed files with 87 additions and 30 deletions

7
Cargo.lock generated
View File

@ -17,6 +17,12 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "anyhow"
version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]]
name = "anymap2"
version = "0.13.0"
@ -121,6 +127,7 @@ dependencies = [
name = "frontend"
version = "0.1.0"
dependencies = [
"anyhow",
"gloo 0.10.0",
"wasm-bindgen",
"web-sys",

View File

@ -11,3 +11,4 @@ yew-router = "0.17.0"
web-sys = { version = "0.3.64", features = ["HtmlInputElement"] }
wasm-bindgen = "0.2.87"
gloo = "0.10.0"
anyhow = "1.0.75"

34
src/backend/mod.rs Normal file
View File

@ -0,0 +1,34 @@
use anyhow::Result;
#[derive(Clone, PartialEq)]
pub struct Session {
base_url: String,
auth_token: Option<String>,
}
impl Default for Session {
fn default() -> Self {
Self {
base_url: "https://api.nerdcult.net".to_owned(),
auth_token: None,
}
}
}
impl Session {
pub fn new(base_url: String) -> Self {
Self {
base_url,
auth_token: None,
}
}
pub fn login(&mut self, username: &str, password: &str) -> Result<()> {
gloo::console::log!("Login: ", username, " || ", password);
Ok(())
}
pub fn is_authenticated(&self) -> bool {
self.auth_token.is_some()
}
}

View File

@ -1,10 +1,10 @@
mod backend;
mod content;
mod state;
mod topbar;
use backend::Session;
use content::{error, home::Home};
use state::State;
use std::rc::Rc;
use std::ops::Deref;
use topbar::TopBar;
use yew::prelude::*;
use yew_router::prelude::*;
@ -34,19 +34,37 @@ fn switch(routes: Route) -> Html {
}
}
#[derive(Clone, PartialEq)]
pub struct Callbacks {
pub sign_in_callback: Callback<(String, String)>,
}
#[function_component]
fn App() -> Html {
let state = use_memo(|_| State::default(), ());
let state = use_state(Session::default);
let cloned_state = state.clone();
let callbacks = use_state(move || Callbacks {
sign_in_callback: Callback::from(move |data: (String, String)| {
let mut new_state = cloned_state.deref().clone();
new_state
.login(data.0.as_str(), data.1.as_str())
.expect("Login failed");
cloned_state.set(new_state);
}),
});
html! {
<ContextProvider<Rc<State>> context={state}>
<TopBar/>
<main>
<BrowserRouter>
<Switch<Route> render={switch} />
</BrowserRouter>
</main>
</ContextProvider<Rc<State>>>
<ContextProvider<Session> context={state.deref().clone()}>
<ContextProvider<Callbacks> context={callbacks.deref().clone()}>
<TopBar/>
<main>
<BrowserRouter>
<Switch<Route> render={switch} />
</BrowserRouter>
</main>
</ContextProvider<Callbacks>>
</ContextProvider<Session>>
}
}

View File

@ -1,10 +0,0 @@
#[derive(Clone, PartialEq)]
pub struct State {
pub auth_token: Option<String>,
}
impl Default for State {
fn default() -> Self {
Self { auth_token: None }
}
}

View File

@ -2,6 +2,7 @@ mod signin;
mod signup;
use crate::topbar::Tab;
use crate::Callbacks;
use signin::SignIn;
use signup::SignUp;
use std::rc::Rc;
@ -49,6 +50,7 @@ impl Reducible for State {
#[function_component]
pub fn TopBar() -> Html {
let state = use_reducer(State::default);
let callbacks = use_context::<Callbacks>().expect("Callbacks context not available!");
let sign_in_onclick = {
let state = state.clone();
@ -75,7 +77,7 @@ pub fn TopBar() -> Html {
</ul>
if state.sign_in {
<SignIn/>
<SignIn callback={callbacks.sign_in_callback}/>
}
if state.sign_up {

View File

@ -9,8 +9,13 @@ struct Data {
pub password: String,
}
#[derive(Properties, PartialEq)]
pub struct Props {
pub callback: Callback<(String, String)>,
}
#[function_component]
pub fn SignIn() -> Html {
pub fn SignIn(props: &Props) -> Html {
let state = use_state(|| Data::default());
let cloned_state = state.clone();
@ -40,12 +45,13 @@ pub fn SignIn() -> Html {
});
let cloned_state = state.clone();
let callback = props.callback.clone();
let onsubmit = Callback::from(move |event: SubmitEvent| {
event.prevent_default();
let data = cloned_state.deref().clone();
gloo::console::log!("username: ", data.username);
gloo::console::log!("password: ", data.password);
callback.emit((data.username, data.password));
});
html! {

View File

@ -1,8 +1,7 @@
mod guest;
mod user;
use crate::state::State;
use std::rc::Rc;
use crate::backend::Session;
use yew::prelude::*;
#[derive(Properties, PartialEq)]
@ -27,10 +26,10 @@ fn Tab(props: &TabProps) -> Html {
#[function_component]
pub fn TopBar() -> Html {
let ctx = use_context::<Rc<State>>().expect("No context found!");
let session = use_context::<Session>().unwrap_or_default();
html! {
if ctx.auth_token.is_some() {
if session.is_authenticated() {
<user::TopBar/>
} else {
<guest::TopBar/>