use graphql_client::reqwest::post_graphql; use web_sys::HtmlInputElement; use yew::prelude::*; use yew_router::prelude::*; use yew_side_effect::title::Title; use crate::components; use crate::cookies; use crate::graphql; use crate::layouts; use crate::routes; #[derive(Properties, PartialEq)] pub struct LoginProps { pub token: Option, pub logged_in: bool, } pub enum Msg { Submit, Login(Option>), } pub struct Login { username: NodeRef, password: NodeRef, fetching: bool, errors: Option>, } impl Component for Login { type Message = Msg; type Properties = LoginProps; fn create(_ctx: &Context) -> Self { Self { username: NodeRef::default(), password: NodeRef::default(), fetching: false, errors: None, } } fn update(&mut self, ctx: &Context, msg: Self::Message) -> bool { match msg { Msg::Submit => { if let (Some(username), Some(password)) = ( self.username.cast::().map(|x| x.value()), self.password.cast::().map(|x| x.value()), ) { if !username.is_empty() && !password.is_empty() { self.fetching = true; ctx.link().send_future(async { let response = post_graphql::( &graphql::client(None).unwrap(), graphql::URL.as_str(), graphql::mutations::login::login::Variables { username, password }, ) .await .unwrap(); if response.errors.is_some() { cookies::logout_clear(); } else { let data = response.data.unwrap().login.unwrap(); wasm_cookies::set( cookies::TOKEN, &data.token, &wasm_cookies::CookieOptions::default(), ); if data.user.admin { wasm_cookies::set( cookies::ADMIN, "1", &wasm_cookies::CookieOptions::default(), ); } else { wasm_cookies::delete(cookies::ADMIN); } } Msg::Login(graphql::convert(response.errors)) }); true } else { false } } else { false } } Msg::Login(errors) => { self.fetching = false; self.errors = errors; if self.errors.is_none() { ctx.link().history().unwrap().push(routes::Route::Home); false } else { true } } } } fn view(&self, ctx: &Context) -> Html { if ctx.props().logged_in { ctx.link().history().unwrap().push(routes::Route::Home); } html! { <> <layouts::main::Main token={ctx.props().token.to_owned()} logged_in={false}> <div class={classes!("columns")}> <div class={classes!("column", "is-one-third", "mx-auto")}> <form onsubmit={ctx.link().callback(|e: FocusEvent| { e.prevent_default(); Msg::Submit })} class={classes!("box")}> <div class={classes!("field")}> <p class={classes!("control", "has-icons-left")}> <input ref={self.username.clone()} class={classes!("input")} type="username" placeholder="Benutzername" /> <span class={classes!("icon", "is-small", "is-left")}> <i class={classes!("fas", "fa-envelope")} /> </span> </p> </div> <div class={classes!("field")}> <p class={classes!("control", "has-icons-left")}> <input ref={self.password.clone()} class={classes!("input")} type="password" placeholder="Passwort" /> <span class={classes!("icon", "is-small", "is-left")}> <i class={classes!("fas", "fa-lock")} /> </span> </p> </div> <div class={classes!("field")}> <p class="control"> <button class={classes!( "button", "is-fullwidth", "is-success", if self.fetching { Some("is-loading") } else { None } )} type="submit" > <span class={classes!("icon", "is-small")}> <i class={classes!("fas", "fa-right-to-bracket")} /> </span> <span>{ "Login" }</span> </button> </p> </div> <components::graphql_errors::GraphQLErrors errors={self.errors.clone()} /> </form> </div> </div> </layouts::main::Main> </> } } }