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",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-logger",
|
||||
"web-sys",
|
||||
"yew",
|
||||
"yew-agent",
|
||||
"yew-router",
|
||||
|
@ -140,7 +140,7 @@ async fn ws_handler(
|
||||
} else {
|
||||
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))
|
||||
}
|
||||
|
@ -16,3 +16,5 @@ reqwasm = "0.5.0"
|
||||
yew-agent = "0.2.0"
|
||||
serde.workspace = true
|
||||
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::prelude::*;
|
||||
use yew_router::prelude::*;
|
||||
|
||||
|
||||
#[function_component(Admin)]
|
||||
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 admin;
|
||||
pub mod create_achievement;
|
||||
pub mod root;
|
||||
|
@ -5,6 +5,7 @@ use std::rc::Rc;
|
||||
use yew::prelude::*;
|
||||
use yew_agent::Bridge;
|
||||
use yew_agent::Bridged;
|
||||
use yew_router::scope_ext::RouterScopeExt;
|
||||
|
||||
pub struct Root {
|
||||
wss: WebsocketService,
|
||||
@ -48,6 +49,13 @@ impl Component for Root {
|
||||
}
|
||||
|
||||
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 {
|
||||
return html! {
|
||||
<p>{"loading..."}</p>
|
||||
@ -66,15 +74,15 @@ impl Component for Root {
|
||||
.collect::<Html>();
|
||||
|
||||
html! {
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="twelve columns" style="margin-top: 25%">
|
||||
<>
|
||||
<h4>{"Achievements"}</h4>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
{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 handle_input(&mut self, msg: Self::Input, id: HandlerId) {
|
||||
fn handle_input(&mut self, msg: Self::Input, _id: HandlerId) {
|
||||
match msg {
|
||||
EventBusInput::EventBusMsg(s) => {
|
||||
for sub in &self.subscribers {
|
||||
|
@ -1,4 +1,5 @@
|
||||
use components::admin::Admin;
|
||||
use components::create_achievement::CreateAchievementComponent;
|
||||
use components::root::Root;
|
||||
use std::rc::Rc;
|
||||
use yew::prelude::*;
|
||||
@ -16,6 +17,8 @@ enum Route {
|
||||
Root,
|
||||
#[at("/chat")]
|
||||
Admin,
|
||||
#[at("/create-achievement")]
|
||||
CreateAchievement,
|
||||
#[not_found]
|
||||
#[at("/404")]
|
||||
NotFound,
|
||||
@ -25,6 +28,7 @@ fn switch(selected_route: Route) -> Html {
|
||||
match selected_route {
|
||||
Route::Root => html! {<Root />},
|
||||
Route::Admin => html! {<Admin/>},
|
||||
Route::CreateAchievement => html! {<CreateAchievementComponent/>},
|
||||
Route::NotFound => html! {<h1>{"404 not found"}</h1>},
|
||||
}
|
||||
}
|
||||
@ -42,7 +46,7 @@ pub fn App() -> Html {
|
||||
html! {
|
||||
<ContextProvider<AppState> context={(*ctx).clone()}>
|
||||
<BrowserRouter>
|
||||
<div class="flex w-screen h-screen">
|
||||
<div class="container" style="margin-top: 5%; margin-bottom: 25%">
|
||||
<Switch<Route> render={switch}/>
|
||||
</div>
|
||||
</BrowserRouter>
|
||||
|
Loading…
x
Reference in New Issue
Block a user