From 3ca53db260bbf7a51b504722856022e8ccf148ee Mon Sep 17 00:00:00 2001 From: Daan Vanoverloop Date: Mon, 5 Sep 2022 16:48:55 +0200 Subject: [PATCH] Stuff --- web/dist/index.html | 6 ++-- web/src/components/button.rs | 1 + web/src/components/event.rs | 65 ++++++++++++++++++++++++++++++++++++ web/src/components/mod.rs | 29 +++++++++++++--- web/src/main.rs | 4 +-- web/src/pages/events.rs | 30 +++++++++++++++++ web/src/pages/mod.rs | 2 ++ web/src/pages/users.rs | 48 ++++++++++++++++++++++---- web/src/util.rs | 25 ++++---------- 9 files changed, 176 insertions(+), 34 deletions(-) create mode 100644 web/src/components/event.rs create mode 100644 web/src/pages/events.rs diff --git a/web/dist/index.html b/web/dist/index.html index 3b2d162..2b5ef4d 100644 --- a/web/dist/index.html +++ b/web/dist/index.html @@ -4,9 +4,9 @@ Yew App - - + + - \ No newline at end of file + \ No newline at end of file diff --git a/web/src/components/button.rs b/web/src/components/button.rs index 3eae9c7..be952f3 100644 --- a/web/src/components/button.rs +++ b/web/src/components/button.rs @@ -45,6 +45,7 @@ pub struct Props { #[function_component(Button)] pub fn button(props: &Props) -> Html { let mut icon_class = Classes::from("mdi"); + icon_class.push("text-lg"); if !props.icon.is_empty() { icon_class.push(&props.icon); diff --git a/web/src/components/event.rs b/web/src/components/event.rs new file mode 100644 index 0000000..bf913f4 --- /dev/null +++ b/web/src/components/event.rs @@ -0,0 +1,65 @@ +use lan_party_core::event::*; +use yew::prelude::*; + +#[derive(Debug, Clone, Properties, PartialEq)] +pub struct BlockProps { + children: Children, +} + +#[function_component(Block)] +pub fn block(props: &BlockProps) -> Html { + html! { +
+ {for props.children.iter()} +
+ } +} + +pub trait RenderEvent { + fn view(&self) -> Html; +} + +impl RenderEvent for String { + fn view(&self) -> Html { + html! { self } + } +} + +impl RenderEvent for bool { + fn view(&self) -> Html { + html! { + + } + } +} + +impl RenderEvent for Vec { + fn view(&self) -> Html { + html! { + self.iter().map(|x| x.view()).collect::() + } + } +} + +impl RenderEvent for &[T] { + fn view(&self) -> Html { + html! { + self.iter().map(|x| x.view()).collect::() + } + } +} + +impl RenderEvent for lan_party_core::event::Event { + fn view(&self) -> Html { + html! { + + { "Name: " } + { self.name.view() }
+ { "Description: " } + { self.description.view() }
+ { "Concluded: " } + { self.concluded.view() }
+
+ } + } +} diff --git a/web/src/components/mod.rs b/web/src/components/mod.rs index 4be5f03..1a66f87 100644 --- a/web/src/components/mod.rs +++ b/web/src/components/mod.rs @@ -1,9 +1,11 @@ mod button; +mod event; mod table; pub use button::Button; +pub use event::RenderEvent; pub use table::Table; -use yew::{function_component, html, Children, Html, Properties}; +use yew::{function_component, html, Children, Properties}; use wasm_bindgen::{JsCast, UnwrapThrowExt}; use web_sys::{Event, HtmlInputElement, InputEvent}; @@ -13,27 +15,31 @@ use yew::prelude::*; pub struct InputProps { pub value: String, pub onchange: Callback, + pub class: Classes, } fn get_value_from_input_event(e: InputEvent) -> String { let event: Event = e.dyn_into().unwrap_throw(); let event_target = event.target().unwrap_throw(); let target: HtmlInputElement = event_target.dyn_into().unwrap_throw(); - web_sys::console::log_1(&target.value().into()); target.value() } /// Controlled Text Input Component #[function_component(TextInput)] pub fn text_input(props: &InputProps) -> Html { - let InputProps { value, onchange } = props.clone(); + let InputProps { + value, + onchange, + class, + } = props.clone(); let oninput = Callback::from(move |input_event: InputEvent| { onchange.emit(get_value_from_input_event(input_event)); }); html! { - + } } @@ -47,3 +53,18 @@ pub struct PageProps { pub fn page(props: &PageProps) -> Html { html! {
{ for props.children.iter() }
} } + +#[function_component(Loading)] +pub fn loading() -> Html { + html! { + + + + + } +} diff --git a/web/src/main.rs b/web/src/main.rs index 02fdd03..4a5b4aa 100644 --- a/web/src/main.rs +++ b/web/src/main.rs @@ -2,7 +2,7 @@ mod components; mod pages; pub mod util; -use pages::UsersPage; +use pages::{EventsPage, UsersPage}; use yew::prelude::*; use yew_router::prelude::*; @@ -59,7 +59,7 @@ fn switch(routes: &Route) -> Html { Route::Users => html! { }, - Route::Events => html! {

{ "Events" }

}, + Route::Events => html! { }, } } diff --git a/web/src/pages/events.rs b/web/src/pages/events.rs new file mode 100644 index 0000000..9373e02 --- /dev/null +++ b/web/src/pages/events.rs @@ -0,0 +1,30 @@ +use crate::components::{Page, RenderEvent}; +use yew::prelude::*; +use yew_hooks::*; + +use crate::{clone, util::api_request}; + +#[function_component(EventsPage)] +pub fn events_page() -> Html { + let events: UseAsyncHandle, _> = use_async(async move { + api_request::<_, Vec>("GET", "/event", Option::<()>::None) + .await + .map(|inner| inner.unwrap()) + .map_err(|_| "failed to load users") + }); + + clone!(events; use_effect_with_deps(move |_| { + if events.data.is_none() { + events.run(); + } + || () + }, ())); + + html! { + + { if let Some(events) = &events.data { + events.view() + } else { html! {} }} + + } +} diff --git a/web/src/pages/mod.rs b/web/src/pages/mod.rs index 97bd228..098c525 100644 --- a/web/src/pages/mod.rs +++ b/web/src/pages/mod.rs @@ -1,3 +1,5 @@ +mod events; mod users; +pub use events::EventsPage; pub use users::UsersPage; diff --git a/web/src/pages/users.rs b/web/src/pages/users.rs index 8a8db17..43ad946 100644 --- a/web/src/pages/users.rs +++ b/web/src/pages/users.rs @@ -1,9 +1,9 @@ use crate::{ clone, clone_cb, - components::{Button, Page, Table, TextInput}, - util::{api_request, AutoCopy}, + components::{Button, Loading, Page, Table, TextInput}, + util::api_request, }; -use lan_party_core::{user::User, PartyError}; +use lan_party_core::user::User; use wasm_bindgen_futures::spawn_local; use yew::prelude::*; use yew_hooks::*; @@ -12,6 +12,7 @@ use yew_hooks::*; pub fn users_page() -> Html { let headers = vec!["Username".into(), "Score".into(), "".into()]; + let new_username = use_state(|| String::new()); let score_edit: UseStateHandle> = use_state(|| Option::None); let current_score = use_state(|| String::new()); let users: UseAsyncHandle, _> = use_async(async move { @@ -28,8 +29,6 @@ pub fn users_page() -> Html { || () }, ())); - let onchange = clone_cb!(current_score; move |value| current_score.set(value)); - let oncheck = clone_cb!(score_edit, current_score, users; move |_| { clone!(score_edit, users, current_score; { spawn_local(async move { @@ -68,6 +67,19 @@ pub fn users_page() -> Html { }); }); + let onadd = clone_cb!(new_username, users; move |_| { + clone!(new_username, users; { + spawn_local(async move { + if let Some(users_inner) = &users.data { + let user = api_request::("POST", "/user", Some((*new_username).clone())).await.unwrap(); + let mut cloned = users_inner.clone(); + cloned.push(user.unwrap()); + users.update(cloned); + } + }); + }); + }); + html! { @@ -80,7 +92,8 @@ pub fn users_page() -> Html { <> @@ -100,7 +113,28 @@ pub fn users_page() -> Html { }).collect::()} - } else { html! { "Loading..." }}} + } else { + html! { +
+ +
+ } + }} + + + + +
+ + + + +
} diff --git a/web/src/util.rs b/web/src/util.rs index 5beb1d7..91957dc 100644 --- a/web/src/util.rs +++ b/web/src/util.rs @@ -8,23 +8,6 @@ use wasm_bindgen_futures::JsFuture; use web_sys::{Headers, Request, RequestInit, RequestMode, Response}; use yew::html::IntoPropValue; -#[derive(Clone, Copy)] -pub struct AutoCopy(pub T); - -impl Deref for AutoCopy { - type Target = T; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl + Clone> IntoPropValue for AutoCopy { - fn into_prop_value(self) -> T { - self.0.into_prop_value() - } -} - #[derive(Error, Debug, Clone)] pub enum JsError { #[error("javascript error: {0}")] @@ -60,8 +43,14 @@ pub async fn api_request Deserialize<'a>>( if let Some(body) = body { let value = JsValue::from_serde(&body)?; - req_opts.body(Some(&value)); + req_opts.body( + js_sys::JSON::stringify(&value) + .ok() + .map(JsValue::from) + .as_ref(), + ); } + web_sys::console::log_1(&JsValue::from("here")); let request = Request::new_with_str_and_init( &format!("http://localhost:8000/api/{}", endpoint),