create achievements
This commit is contained in:
parent
e12d616436
commit
ddd039fead
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -234,8 +234,10 @@ dependencies = [
|
|||||||
"reqwasm",
|
"reqwasm",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
"wasm-logger",
|
"wasm-logger",
|
||||||
|
"web-sys",
|
||||||
"yew",
|
"yew",
|
||||||
"yew-agent",
|
"yew-agent",
|
||||||
"yew-router",
|
"yew-router",
|
||||||
|
@ -140,7 +140,7 @@ async fn ws_handler(
|
|||||||
} else {
|
} else {
|
||||||
String::from("Unknown browser")
|
String::from("Unknown browser")
|
||||||
};
|
};
|
||||||
tracing::debug!("{user_agent} connected websocket.");
|
tracing::debug!("New ws connection from: {user_agent}.");
|
||||||
|
|
||||||
ws.on_upgrade(move |socket| handle_socket(socket, state_watch_rx))
|
ws.on_upgrade(move |socket| handle_socket(socket, state_watch_rx))
|
||||||
}
|
}
|
||||||
|
@ -16,3 +16,5 @@ reqwasm = "0.5.0"
|
|||||||
yew-agent = "0.2.0"
|
yew-agent = "0.2.0"
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_json = "1.0.96"
|
serde_json = "1.0.96"
|
||||||
|
web-sys = "0.3.63"
|
||||||
|
wasm-bindgen = "0.2.86"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::Route;
|
|
||||||
use yew::functional::*;
|
use yew::functional::*;
|
||||||
use yew::prelude::*;
|
use yew::prelude::*;
|
||||||
use yew_router::prelude::*;
|
|
||||||
|
|
||||||
#[function_component(Admin)]
|
#[function_component(Admin)]
|
||||||
pub fn admin() -> Html {
|
pub fn admin() -> Html {
|
||||||
|
139
crates/frontend/src/components/create_achievement.rs
Normal file
139
crates/frontend/src/components/create_achievement.rs
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
use common::CreateAchievement;
|
||||||
|
use reqwasm::http::Request;
|
||||||
|
use wasm_bindgen::JsCast;
|
||||||
|
use wasm_bindgen_futures::spawn_local;
|
||||||
|
use yew::html;
|
||||||
|
use yew::Callback;
|
||||||
|
use yew::Component;
|
||||||
|
use yew::Html;
|
||||||
|
use yew_router::scope_ext::RouterScopeExt;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Msg {
|
||||||
|
Submit,
|
||||||
|
Reset,
|
||||||
|
UpdateInput(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct CreateAchievementComponent {
|
||||||
|
input_value: String,
|
||||||
|
submitted: bool,
|
||||||
|
}
|
||||||
|
impl Component for CreateAchievementComponent {
|
||||||
|
type Message = Msg;
|
||||||
|
type Properties = ();
|
||||||
|
|
||||||
|
fn create(_ctx: &yew::Context<Self>) -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, _ctx: &yew::Context<Self>, msg: Self::Message) -> bool {
|
||||||
|
match msg {
|
||||||
|
Msg::Reset => {
|
||||||
|
self.input_value.clear();
|
||||||
|
self.submitted = false;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
Msg::Submit => {
|
||||||
|
log::info!("button click, creating achievement");
|
||||||
|
|
||||||
|
let payload = CreateAchievement {
|
||||||
|
goal: self.input_value.clone(),
|
||||||
|
};
|
||||||
|
let payload = serde_json::to_string(&payload).unwrap();
|
||||||
|
|
||||||
|
spawn_local(async move {
|
||||||
|
let req = Request::post("http://127.0.0.1:4000/create")
|
||||||
|
.header("Content-Type", "application/json")
|
||||||
|
.body(payload);
|
||||||
|
let res = req.send().await;
|
||||||
|
match res {
|
||||||
|
Ok(response) => {
|
||||||
|
dbg!(response);
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
log::error!("Request failed: {err:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
self.submitted = true;
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
Msg::UpdateInput(value) => {
|
||||||
|
self.input_value = value;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view(&self, ctx: &yew::Context<Self>) -> Html {
|
||||||
|
let link = ctx.link().clone();
|
||||||
|
let nav = ctx.link().navigator().unwrap();
|
||||||
|
|
||||||
|
if self.submitted {
|
||||||
|
let onclick_go_back = Callback::from(move |_: web_sys::MouseEvent| {
|
||||||
|
nav.push(&crate::Route::Root);
|
||||||
|
});
|
||||||
|
|
||||||
|
let onclick_add_another = link.callback(|_: web_sys::MouseEvent| Msg::Reset);
|
||||||
|
|
||||||
|
html! {
|
||||||
|
<>
|
||||||
|
<div class="row" style="margin-top: 15%">
|
||||||
|
<div class="twelve columns">
|
||||||
|
<h4>{"Submitted!"}</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="six columns">
|
||||||
|
<button onclick={onclick_go_back} class="button">{"Go back"}</button>
|
||||||
|
</div>
|
||||||
|
<div class="six columns">
|
||||||
|
<button onclick={onclick_add_another} class="button">{"Add another"}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let onclick_go_back = Callback::from(move |_: web_sys::MouseEvent| {
|
||||||
|
nav.push(&crate::Route::Root);
|
||||||
|
});
|
||||||
|
|
||||||
|
let onsubmit = link.callback(|e: web_sys::SubmitEvent| {
|
||||||
|
e.prevent_default();
|
||||||
|
Msg::Submit
|
||||||
|
});
|
||||||
|
|
||||||
|
let oninput = link.callback(|e: web_sys::InputEvent| {
|
||||||
|
let Some(input) = e
|
||||||
|
.target()
|
||||||
|
.and_then(|t| t.dyn_into::<web_sys::HtmlInputElement>().ok()) else { unreachable!() };
|
||||||
|
Msg::UpdateInput(input.value())
|
||||||
|
});
|
||||||
|
|
||||||
|
let input_value = self.input_value.clone();
|
||||||
|
|
||||||
|
html! {
|
||||||
|
<>
|
||||||
|
<div class="row">
|
||||||
|
<button onclick={onclick_go_back} class="button">{"Back"}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form {onsubmit} >
|
||||||
|
<hr />
|
||||||
|
<div class="row">
|
||||||
|
<div class="twelve columns">
|
||||||
|
<label for="achievementInput">{"New achievement"}</label>
|
||||||
|
<input {oninput} value={input_value} class="u-full-width" type="text" id="achievementInput" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input class="button-primary" type="submit" value="Submit" />
|
||||||
|
</form>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
pub mod achievement;
|
pub mod achievement;
|
||||||
pub mod admin;
|
pub mod admin;
|
||||||
|
pub mod create_achievement;
|
||||||
pub mod root;
|
pub mod root;
|
||||||
|
@ -5,6 +5,7 @@ use std::rc::Rc;
|
|||||||
use yew::prelude::*;
|
use yew::prelude::*;
|
||||||
use yew_agent::Bridge;
|
use yew_agent::Bridge;
|
||||||
use yew_agent::Bridged;
|
use yew_agent::Bridged;
|
||||||
|
use yew_router::scope_ext::RouterScopeExt;
|
||||||
|
|
||||||
pub struct Root {
|
pub struct Root {
|
||||||
wss: WebsocketService,
|
wss: WebsocketService,
|
||||||
@ -48,6 +49,13 @@ impl Component for Root {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self, ctx: &Context<Self>) -> Html {
|
fn view(&self, ctx: &Context<Self>) -> Html {
|
||||||
|
let link = ctx.link().clone();
|
||||||
|
let nav = ctx.link().navigator().unwrap();
|
||||||
|
|
||||||
|
let onclick_create_achievement = Callback::from(move |_: web_sys::MouseEvent| {
|
||||||
|
nav.push(&crate::Route::CreateAchievement);
|
||||||
|
});
|
||||||
|
|
||||||
let Some(state) = &self.state else {
|
let Some(state) = &self.state else {
|
||||||
return html! {
|
return html! {
|
||||||
<p>{"loading..."}</p>
|
<p>{"loading..."}</p>
|
||||||
@ -66,15 +74,15 @@ impl Component for Root {
|
|||||||
.collect::<Html>();
|
.collect::<Html>();
|
||||||
|
|
||||||
html! {
|
html! {
|
||||||
<div class="container">
|
<>
|
||||||
<div class="row">
|
<h4>{"Achievements"}</h4>
|
||||||
<div class="twelve columns" style="margin-top: 25%">
|
<hr />
|
||||||
<h4>{"Achievements"}</h4>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{achievements}
|
{achievements}
|
||||||
</div>
|
|
||||||
|
<hr />
|
||||||
|
<button onclick={onclick_create_achievement} class="button-primary">{"Create new achievement"}</button>
|
||||||
|
</>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ impl yew_agent::Worker for EventBus {
|
|||||||
|
|
||||||
fn update(&mut self, _msg: Self::Message) {}
|
fn update(&mut self, _msg: Self::Message) {}
|
||||||
|
|
||||||
fn handle_input(&mut self, msg: Self::Input, id: HandlerId) {
|
fn handle_input(&mut self, msg: Self::Input, _id: HandlerId) {
|
||||||
match msg {
|
match msg {
|
||||||
EventBusInput::EventBusMsg(s) => {
|
EventBusInput::EventBusMsg(s) => {
|
||||||
for sub in &self.subscribers {
|
for sub in &self.subscribers {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use components::admin::Admin;
|
use components::admin::Admin;
|
||||||
|
use components::create_achievement::CreateAchievementComponent;
|
||||||
use components::root::Root;
|
use components::root::Root;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use yew::prelude::*;
|
use yew::prelude::*;
|
||||||
@ -16,6 +17,8 @@ enum Route {
|
|||||||
Root,
|
Root,
|
||||||
#[at("/chat")]
|
#[at("/chat")]
|
||||||
Admin,
|
Admin,
|
||||||
|
#[at("/create-achievement")]
|
||||||
|
CreateAchievement,
|
||||||
#[not_found]
|
#[not_found]
|
||||||
#[at("/404")]
|
#[at("/404")]
|
||||||
NotFound,
|
NotFound,
|
||||||
@ -25,6 +28,7 @@ fn switch(selected_route: Route) -> Html {
|
|||||||
match selected_route {
|
match selected_route {
|
||||||
Route::Root => html! {<Root />},
|
Route::Root => html! {<Root />},
|
||||||
Route::Admin => html! {<Admin/>},
|
Route::Admin => html! {<Admin/>},
|
||||||
|
Route::CreateAchievement => html! {<CreateAchievementComponent/>},
|
||||||
Route::NotFound => html! {<h1>{"404 not found"}</h1>},
|
Route::NotFound => html! {<h1>{"404 not found"}</h1>},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -42,7 +46,7 @@ pub fn App() -> Html {
|
|||||||
html! {
|
html! {
|
||||||
<ContextProvider<AppState> context={(*ctx).clone()}>
|
<ContextProvider<AppState> context={(*ctx).clone()}>
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<div class="flex w-screen h-screen">
|
<div class="container" style="margin-top: 5%; margin-bottom: 25%">
|
||||||
<Switch<Route> render={switch}/>
|
<Switch<Route> render={switch}/>
|
||||||
</div>
|
</div>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user