mentorenwahl/frontend/src/layouts/main.rs

117 lines
3.7 KiB
Rust

use graphql_client::reqwest::post_graphql;
use yew::prelude::*;
use yew_agent::{Dispatched, Dispatcher};
use yew_router::prelude::*;
use crate::agents;
use crate::components;
use crate::graphql;
use crate::routes;
pub enum Msg {
LogOutClicked,
LogOut(Option<Vec<String>>),
}
#[derive(Properties, PartialEq)]
pub struct MainProps {
pub token: Option<String>,
pub logged_in: bool,
#[prop_or_default]
pub children: Children,
}
pub struct Main {
logged_in: bool,
logged_in_event_bus: Dispatcher<agents::logged_in::EventBus>,
errors: Option<Vec<String>>,
}
impl Component for Main {
type Message = Msg;
type Properties = MainProps;
fn create(ctx: &Context<Self>) -> Self {
Self {
logged_in: ctx.props().logged_in,
logged_in_event_bus: agents::logged_in::EventBus::dispatcher(),
errors: None,
}
}
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
Msg::LogOutClicked => {
let client = graphql::client(ctx.props().token.as_ref()).unwrap();
ctx.link().send_future(async move {
let response = post_graphql::<graphql::mutations::logout::Logout, _>(
&client,
graphql::URL.as_str(),
graphql::mutations::logout::logout::Variables,
)
.await
.unwrap();
Msg::LogOut(components::graphql_errors::convert(response.errors))
});
false
}
Msg::LogOut(errors) => {
if self.errors.is_none() {
self.logged_in_event_bus
.send(agents::logged_in::Request::LoggedIn(false));
false
} else {
self.errors = errors;
true
}
}
}
}
fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<>
<components::logged_in_handler::LoggedInHandler logged_in={self.logged_in} />
<div id="wrapper">
<nav>
<ul>
<li>
<Link<routes::Route> to={routes::Route::Home}>
<button>{ "Home" }</button>
</Link<routes::Route>>
</li>
<li>
<Link<routes::Route> to={routes::Route::Settings}>
<button>{ "Settings" }</button>
</Link<routes::Route>>
</li>
<li>
if self.logged_in {
<button onclick={ctx.link().callback(move |_| Msg::LogOutClicked)}>{ "Logout" }</button>
} else {
<Link<routes::Route> to={routes::Route::Login}>
<button>{ "Login" }</button>
</Link<routes::Route>>
}
</li>
</ul>
<components::graphql_errors::GraphQLErrors errors={self.errors.clone()} />
</nav>
<hr />
<main>
{ for ctx.props().children.iter() }
</main>
</div>
<components::footer::Footer />
</>
}
}
}