summaryrefslogtreecommitdiff
path: root/webapp/src/components
diff options
context:
space:
mode:
authorKjetil Orbekk <kj@orbekk.com>2022-11-13 16:07:27 -0500
committerKjetil Orbekk <kj@orbekk.com>2022-11-13 16:07:27 -0500
commitd4650a3160d52d289686fb59efbf8f0a436b71eb (patch)
tree0b38d0143824a3a7cab83e189fe1a2302f9685a7 /webapp/src/components
parent0012c25c9ab94754f3d6396e91dc3ae63d19ac9c (diff)
Add create/leave table options
Diffstat (limited to 'webapp/src/components')
-rw-r--r--webapp/src/components/app_context_provider.rs141
-rw-r--r--webapp/src/components/error_info.rs4
-rw-r--r--webapp/src/components/table.rs21
3 files changed, 129 insertions, 37 deletions
diff --git a/webapp/src/components/app_context_provider.rs b/webapp/src/components/app_context_provider.rs
index 4cf233b..19e7611 100644
--- a/webapp/src/components/app_context_provider.rs
+++ b/webapp/src/components/app_context_provider.rs
@@ -1,17 +1,89 @@
+use crate::routing::Route;
use gloo_net::http::Request;
+use log::info;
use protocol::UserInfo;
-use std::rc::Rc;
+use uuid::Uuid;
+use std::{future::Future, rc::Rc};
+use wasm_bindgen_futures::spawn_local;
use yew::prelude::*;
+use yew_router::prelude::*;
#[derive(Properties, Clone, PartialEq, Debug)]
pub struct ErrorInfoProperties {
pub message: String,
}
-#[derive(Clone, Debug, PartialEq, Default)]
+#[derive(Clone, PartialEq)]
+pub struct AppState {
+ user: UseStateHandle<Option<UserInfo>>,
+ error: UseStateHandle<Option<ErrorInfoProperties>>,
+}
+
+#[derive(Clone, PartialEq)]
pub struct AppContext {
- pub error: Option<ErrorInfoProperties>,
- pub user: Option<UserInfo>,
+ state: AppState,
+ history: AnyHistory,
+}
+
+impl AppContext {
+ fn spawn_async<F>(&self, f: F)
+ where
+ F: Future<Output = Result<(), anyhow::Error>> + 'static,
+ {
+ let error = self.state.error.clone();
+ spawn_local(async move {
+ if let Err(err) = f.await {
+ error.set(Some(ErrorInfoProperties {
+ message: format!("Some error occured: {:?}", err),
+ }));
+ }
+ });
+ }
+
+ pub fn user(&self) -> Option<&UserInfo> {
+ self.state.user.as_ref()
+ }
+
+ pub fn error(&self) -> Option<&ErrorInfoProperties> {
+ self.state.error.as_ref()
+ }
+
+ pub fn create_table(&self) {
+ let user = self.state.user.clone();
+ let history = self.history.clone();
+ self.spawn_async(async move {
+ let response = Request::post("/api/table").send().await?;
+ let table_id: Uuid = response.json().await?;
+ info!("Created table {table_id}");
+ if let Some(user_info) = user.as_ref() {
+ user.set(Some(UserInfo {
+ table: Some(protocol::Table { id: table_id }),
+ ..(user_info.clone())
+ }));
+ }
+ history.push(Route::Home);
+ Ok(())
+ });
+ }
+
+ pub fn leave_table(&self) {
+ let user = self.state.user.clone();
+ let history = self.history.clone();
+ self.spawn_async(async move {
+ let response = Request::delete("/api/table").send().await?;
+ if !response.ok() {
+ anyhow::bail!("error while leaving table");
+ }
+ if let Some(user_info) = user.as_ref() {
+ user.set(Some(UserInfo {
+ table: None,
+ ..(user_info.clone())
+ }));
+ }
+ history.push(Route::Home);
+ Ok(())
+ });
+ }
}
#[derive(Properties, Clone, PartialEq)]
@@ -32,30 +104,30 @@ async fn initialize_user_info() -> Result<UserInfo, anyhow::Error> {
Ok(user_info)
}
+pub fn use_app_context() -> AppContext {
+ let state : AppState = use_context::<AppState>().unwrap();
+ let history = use_history().unwrap();
+
+ AppContext { state: state, history }
+}
+
#[function_component(AppContextProvider)]
pub fn app_context_provider(props: &Props) -> Html {
- let context: UseStateHandle<Option<Rc<AppContext>>> = use_state(|| None);
+ let user: UseStateHandle<Option<UserInfo>> = use_state(|| None);
+ let error: UseStateHandle<Option<ErrorInfoProperties>> = use_state(|| None);
{
- let context = context.clone();
+ let user = user.clone();
+ let error = error.clone();
use_effect_with_deps(
move |_| {
- wasm_bindgen_futures::spawn_local(async move {
- let previous_context: AppContext = context
- .as_ref()
- .map_or(Default::default(), |c| (**c).clone());
- context.set(Some(Rc::new(match initialize_user_info().await {
- Ok(user_info) => AppContext {
- user: Some(user_info),
- ..previous_context
- },
- Err(e) => AppContext {
- error: Some(ErrorInfoProperties {
- message: format!("Could not contact server"),
- }),
- ..previous_context
- },
- })));
+ spawn_local(async move {
+ match initialize_user_info().await {
+ Ok(user_info) => user.set(Some(user_info)),
+ Err(e) => error.set(Some(ErrorInfoProperties {
+ message: format!("Could not contact server"),
+ })),
+ };
});
|| ()
},
@@ -63,14 +135,23 @@ pub fn app_context_provider(props: &Props) -> Html {
);
}
- match &*context {
- None => html! {
- <p>{ "Loading app..." }</p>
- },
- Some(context) => html! {
- <ContextProvider<Rc<AppContext>> {context}>
+ if user.is_none() && error.is_none() {
+ return html! {
+ <p>{ "Loading app..." }</p>
+ };
+ }
+
+ info!("Recomputing state");
+ info!("User is {:?}", *user);
+
+ let state = AppState {
+ user,
+ error,
+ };
+
+ html! {
+ <ContextProvider<AppState> context={state}>
{ for props.children.iter() }
- </ContextProvider<Rc<AppContext>>>
- },
+ </ContextProvider<AppState>>
}
}
diff --git a/webapp/src/components/error_info.rs b/webapp/src/components/error_info.rs
index 4ec5ba9..cb5a9c1 100644
--- a/webapp/src/components/error_info.rs
+++ b/webapp/src/components/error_info.rs
@@ -9,9 +9,9 @@ pub fn error_info(props: &ErrorInfoProperties) -> Html {
html! {
<div class="error-box">
<p>
- { format!("Error: {}. ", props.message) }
+ { format!("Error: {}. ", props.message) }
<button onclick={reload}>{ "Reload" }</button>
- </p>
+ </p>
</div>
}
}
diff --git a/webapp/src/components/table.rs b/webapp/src/components/table.rs
index 8e8b5c8..829441e 100644
--- a/webapp/src/components/table.rs
+++ b/webapp/src/components/table.rs
@@ -1,15 +1,26 @@
use yew::prelude::*;
+use yew_router::prelude::*;
+
+use crate::use_app_context;
#[function_component(Table)]
pub fn table(props: &TableProps) -> Html {
- // let leave_table = {
- // Callback::from(move |_| {
- // });
- // };
+ let ctx = use_app_context();
+ let history = use_history().unwrap();
+
+ let leave_table = {
+ let ctx = ctx.clone();
+ Callback::from(move |_| {
+ ctx.leave_table();
+ })
+ };
html! {
<>
- <p>{ format!("This is table {}", props.table.id) }</p>
+ <p>{ format!("This is table {}", props.table.id) }</p>
+ <button onclick={leave_table}>
+ { "Leave table" }
+ </button>
</>
}
}