app: Implement disconnection & leaving an household

This commit is contained in:
traxys 2023-05-29 17:24:34 +02:00
parent a90b87e849
commit 68fa303a38
3 changed files with 127 additions and 3 deletions

View file

@ -58,6 +58,52 @@ pub fn Modal(props: &ModalProps) -> Html {
}
}
#[derive(Properties, PartialEq)]
pub struct ConfirmDangerModalProps {
pub id: AttrValue,
#[prop_or(true)]
pub fade: bool,
#[prop_or_default]
pub centered: bool,
pub title: AttrValue,
pub on_confirm: Callback<()>,
pub children: Children,
}
#[function_component]
pub fn ConfirmDangerModal(
ConfirmDangerModalProps {
id,
fade,
centered,
title,
children,
on_confirm,
}: &ConfirmDangerModalProps,
) -> Html {
let on_confirm = on_confirm.clone();
html! {
<TitledModal {id} {fade} {centered} {title}>
<ModalBody>
{ for children.iter() }
</ModalBody>
<ModalFooter>
<button type="button" class={classes!("btn", "btn-secondary")} data-bs-dismiss="modal">
{"Cancel"}
</button>
<button
type="button"
class={classes!("btn", "btn-danger")}
data-bs-dismiss="modal"
onclick={Callback::from(move |_| on_confirm.emit(()))}
>
{"Confirm"}
</button>
</ModalFooter>
</TitledModal>
}
}
#[derive(Properties, PartialEq)]
pub struct TitledModalProps {
pub id: AttrValue,

View file

@ -25,10 +25,12 @@ const API_ROUTE: &str = match option_env!("REGALADE_API_SERVER_BASE") {
Some(v) => v,
};
#[macro_export]
macro_rules! api {
($($arg:tt)*) => {
($($arg:tt)*) => {{
use $crate::API_ROUTE;
&format!("{API_ROUTE}/api/{}", format_args!($($arg)*))
};
}};
}
#[derive(Routable, Debug, Clone, Copy, PartialEq, Eq)]

View file

@ -1,7 +1,10 @@
use crate::{RegaladeGlobalState, Route};
use gloo_storage::{LocalStorage, Storage};
use uuid::Uuid;
use yew::prelude::*;
use yew_router::prelude::*;
use crate::{api, bootstrap::ConfirmDangerModal, RegaladeGlobalState, Route};
#[derive(PartialEq)]
struct MenuEntry {
icon: &'static str,
@ -16,9 +19,54 @@ struct SidebarProps {
children: Children,
}
async fn do_leave(token: String, household: Uuid) -> anyhow::Result<()> {
let rsp = gloo_net::http::Request::delete(api!("household/{household}"))
.header("Authorization", &format!("Bearer {token}"))
.send()
.await?;
if !rsp.ok() {
let body = rsp.body();
match body {
None => anyhow::bail!("Could not leave: {rsp:?}"),
Some(s) => anyhow::bail!("Could not leave: {}", s.to_string()),
}
}
LocalStorage::delete("household");
Ok(())
}
#[function_component]
fn Sidebar(props: &SidebarProps) -> Html {
let global_state = use_state(RegaladeGlobalState::get);
let navigator = use_navigator().unwrap();
let token = global_state.token.token.clone();
let household = global_state.household.id;
let nav = navigator.clone();
let leave_household = Callback::from(move |()| {
let token = token.clone();
let nav = nav.clone();
wasm_bindgen_futures::spawn_local(async move {
match do_leave(token, household).await {
Err(e) => {
log::error!("Could not leave household: {e:?}");
}
Ok(_) => {
nav.push(&Route::HouseholdSelect);
}
}
})
});
let logout = Callback::from(move |_| {
LocalStorage::delete("token");
LocalStorage::delete("household");
navigator.push(&Route::HouseholdSelect);
});
html! {
<div class="container-fluid">
@ -105,7 +153,35 @@ fn Sidebar(props: &SidebarProps) -> Html {
{format!("{} ({})", global_state.household.name, global_state.token.name)}
</strong>
</a>
<ConfirmDangerModal
id="leaveModal"
title="Leaving Household"
centered={true}
on_confirm={leave_household}
>
{format!("Are you sure you want to leave the household '{}' ?", global_state.household.name)}
</ConfirmDangerModal>
<ul class="dropdown-menu">
<li>
<a
class="dropdown-item"
href="#"
onclick={logout}
>
{"Logout"}
</a>
</li>
<hr />
<li>
<a
class="dropdown-item"
href="#"
data-bs-toggle="modal"
data-bs-target="#leaveModal"
>
{"Leave Household"}
</a>
</li>
<hr />
<li>
<Link<Route>