app: Implement disconnection & leaving an household
This commit is contained in:
parent
a90b87e849
commit
68fa303a38
3 changed files with 127 additions and 3 deletions
|
|
@ -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)]
|
#[derive(Properties, PartialEq)]
|
||||||
pub struct TitledModalProps {
|
pub struct TitledModalProps {
|
||||||
pub id: AttrValue,
|
pub id: AttrValue,
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,12 @@ const API_ROUTE: &str = match option_env!("REGALADE_API_SERVER_BASE") {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
macro_rules! api {
|
macro_rules! api {
|
||||||
($($arg:tt)*) => {
|
($($arg:tt)*) => {{
|
||||||
|
use $crate::API_ROUTE;
|
||||||
&format!("{API_ROUTE}/api/{}", format_args!($($arg)*))
|
&format!("{API_ROUTE}/api/{}", format_args!($($arg)*))
|
||||||
};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Routable, Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Routable, Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
use crate::{RegaladeGlobalState, Route};
|
use gloo_storage::{LocalStorage, Storage};
|
||||||
|
use uuid::Uuid;
|
||||||
use yew::prelude::*;
|
use yew::prelude::*;
|
||||||
use yew_router::prelude::*;
|
use yew_router::prelude::*;
|
||||||
|
|
||||||
|
use crate::{api, bootstrap::ConfirmDangerModal, RegaladeGlobalState, Route};
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
struct MenuEntry {
|
struct MenuEntry {
|
||||||
icon: &'static str,
|
icon: &'static str,
|
||||||
|
|
@ -16,9 +19,54 @@ struct SidebarProps {
|
||||||
children: Children,
|
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]
|
#[function_component]
|
||||||
fn Sidebar(props: &SidebarProps) -> Html {
|
fn Sidebar(props: &SidebarProps) -> Html {
|
||||||
let global_state = use_state(RegaladeGlobalState::get);
|
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! {
|
html! {
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
|
|
@ -105,7 +153,35 @@ fn Sidebar(props: &SidebarProps) -> Html {
|
||||||
{format!("{} ({})", global_state.household.name, global_state.token.name)}
|
{format!("{} ({})", global_state.household.name, global_state.token.name)}
|
||||||
</strong>
|
</strong>
|
||||||
</a>
|
</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">
|
<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 />
|
<hr />
|
||||||
<li>
|
<li>
|
||||||
<Link<Route>
|
<Link<Route>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue