feat: set timed reveals
This commit is contained in:
parent
17faadf7cd
commit
35d53d82c6
103
Cargo.lock
generated
103
Cargo.lock
generated
@ -2,6 +2,21 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.3.2"
|
||||
@ -132,6 +147,7 @@ name = "backend"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"chrono",
|
||||
"clap",
|
||||
"common",
|
||||
"futures-util",
|
||||
@ -219,6 +235,22 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"time",
|
||||
"wasm-bindgen",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.3.3"
|
||||
@ -271,6 +303,7 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||
name = "common"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"uuid",
|
||||
@ -286,6 +319,12 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.6"
|
||||
@ -355,6 +394,7 @@ dependencies = [
|
||||
name = "frontend"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"common",
|
||||
"futures",
|
||||
"log",
|
||||
@ -362,6 +402,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"uuid",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-logger",
|
||||
@ -479,7 +520,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasi",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
@ -803,6 +844,29 @@ dependencies = [
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.3.0"
|
||||
@ -939,7 +1003,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
@ -953,6 +1017,15 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.15.0"
|
||||
@ -1389,6 +1462,17 @@ dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi 0.10.0+wasi-snapshot-preview1",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.6.0"
|
||||
@ -1700,6 +1784,12 @@ dependencies = [
|
||||
"try-lock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
@ -1817,6 +1907,15 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
|
@ -9,4 +9,10 @@ edition = "2021"
|
||||
[workspace.dependencies]
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
common = { path = "crates/common" }
|
||||
uuid = { vserion = "1.3", features = ["serde", "v4", "js"] }
|
||||
uuid = { vserion = "1.3", features = ["serde", "v4"] }
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
thiserror = "1"
|
||||
serde_json = "1"
|
||||
log = "0.4"
|
||||
futures = "0.3"
|
||||
futures-util = "0.3"
|
||||
|
@ -6,16 +6,17 @@ edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
serde.workspace = true
|
||||
uuid.workspace = true
|
||||
common.workspace = true
|
||||
thiserror.workspace = true
|
||||
axum = { version = "0.6", features = ["ws", "headers"] }
|
||||
serde_json = "1"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = "0.3"
|
||||
common.workspace = true
|
||||
thiserror = "1.0.40"
|
||||
tower = "0.4.13"
|
||||
uuid.workspace = true
|
||||
tower-http = { version = "0.4.0", features = ["fs", "trace", "cors"] }
|
||||
tokio-stream = { version = "0.1.14", features = ["sync"] }
|
||||
clap = { version = "4.3.3", features = ["derive"] }
|
||||
futures-util = "0.3.28"
|
||||
tower = "0.4"
|
||||
tower-http = { version = "0.4", features = ["fs", "trace", "cors"] }
|
||||
chrono.workspace = true
|
||||
tokio-stream = { version = "0.1", features = ["sync"] }
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
futures-util.workspace = true
|
||||
serde_json.workspace = true
|
||||
|
@ -20,6 +20,7 @@ use common::DeleteMilestone;
|
||||
use common::Milestone;
|
||||
use common::RestResponse;
|
||||
use common::ToggleAchievement;
|
||||
use common::UpdateAchievementTimeOfReveal;
|
||||
use futures_util::SinkExt;
|
||||
use futures_util::StreamExt;
|
||||
use serde::Deserialize;
|
||||
@ -133,6 +134,10 @@ async fn main() {
|
||||
.route("/api/v1/toggle", post(toggle_achievement))
|
||||
.route("/api/v1/create-milestone", post(create_milestone))
|
||||
.route("/api/v1/delete-milestone", post(delete_milestone))
|
||||
.route(
|
||||
"/api/v1/update-time-of-reveal",
|
||||
post(update_achievement_time_of_reveal),
|
||||
)
|
||||
.route("/api/ws", get(ws_handler))
|
||||
.layer(
|
||||
ServiceBuilder::new()
|
||||
@ -245,10 +250,12 @@ async fn create_achievement(
|
||||
Json(create_achievement): Json<CreateAchievement>,
|
||||
) -> Response<()> {
|
||||
tracing::debug!("Creating achievement: {create_achievement:?}.");
|
||||
let CreateAchievement { goal, time_of_reveal } = create_achievement;
|
||||
let achievement = Achievement {
|
||||
goal: create_achievement.goal,
|
||||
goal,
|
||||
completed: false,
|
||||
uuid: uuid::Uuid::new_v4(),
|
||||
time_of_reveal,
|
||||
};
|
||||
let mut lock = app_state.write().await;
|
||||
lock.app_state.state.achievements.push(achievement);
|
||||
@ -326,6 +333,27 @@ async fn toggle_achievement(
|
||||
Ok((StatusCode::OK, Json(Ok(()))))
|
||||
}
|
||||
|
||||
async fn update_achievement_time_of_reveal(
|
||||
Extension(app_state): Extension<SharedState>,
|
||||
Json(update): Json<UpdateAchievementTimeOfReveal>,
|
||||
) -> Response<()> {
|
||||
tracing::debug!("Updating achievement time of reveal: {update:?}.");
|
||||
let mut lock = app_state.write().await;
|
||||
if let Some(achievement) = lock
|
||||
.app_state
|
||||
.state
|
||||
.achievements
|
||||
.iter_mut()
|
||||
.find(|x| x.uuid == update.uuid)
|
||||
{
|
||||
achievement.time_of_reveal = update.time_of_reveal;
|
||||
lock.watcher_tx
|
||||
.send(lock.app_state.state.clone())
|
||||
.expect("watch channel is closed, every receiver was dropped.");
|
||||
}
|
||||
Ok((StatusCode::OK, Json(Ok(()))))
|
||||
}
|
||||
|
||||
async fn delete_achievement(
|
||||
Extension(app_state): Extension<SharedState>,
|
||||
Json(delete_achievement): Json<DeleteAchievement>,
|
||||
|
@ -6,5 +6,6 @@ edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
serde.workspace = true
|
||||
thiserror = "1"
|
||||
thiserror.workspace = true
|
||||
uuid.workspace = true
|
||||
chrono.workspace = true
|
||||
|
@ -48,11 +48,13 @@ pub struct Achievement {
|
||||
pub goal: String,
|
||||
pub completed: bool,
|
||||
pub uuid: uuid::Uuid,
|
||||
pub time_of_reveal: Option<chrono::NaiveTime>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct CreateAchievement {
|
||||
pub goal: String,
|
||||
pub time_of_reveal: Option<chrono::NaiveTime>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]
|
||||
@ -60,6 +62,12 @@ pub struct ToggleAchievement {
|
||||
pub uuid: uuid::Uuid,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct UpdateAchievementTimeOfReveal {
|
||||
pub uuid: uuid::Uuid,
|
||||
pub time_of_reveal: Option<chrono::NaiveTime>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Serialize, Clone, Deserialize)]
|
||||
pub struct DeleteAchievement {
|
||||
pub uuid: uuid::Uuid,
|
||||
|
@ -5,17 +5,19 @@ authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.19"
|
||||
wasm-logger = "0.2.0"
|
||||
log.workspace = true
|
||||
wasm-logger = "0.2"
|
||||
yew = { version = "0.20", features = ["csr"] }
|
||||
yew-router = "0.17.0"
|
||||
yew-router = "0.17"
|
||||
common.workspace = true
|
||||
futures = "0.3.28"
|
||||
wasm-bindgen-futures = "0.4.36"
|
||||
reqwasm = "0.5.0"
|
||||
yew-agent = "0.2.0"
|
||||
futures.workspace = true
|
||||
wasm-bindgen-futures = "0.4"
|
||||
reqwasm = "0.5"
|
||||
chrono.workspace = true
|
||||
yew-agent = "0.2"
|
||||
serde.workspace = true
|
||||
serde_json = "1.0.96"
|
||||
web-sys = "0.3.63"
|
||||
wasm-bindgen = "0.2.86"
|
||||
thiserror = "1.0.40"
|
||||
serde_json.workspace = true
|
||||
web-sys = "0.3"
|
||||
wasm-bindgen = "0.2"
|
||||
thiserror.workspace = true
|
||||
uuid = { workspace = true, features = ["js"] }
|
||||
|
@ -23,6 +23,7 @@ pub fn AchievementComponent(props: &Props) -> Html {
|
||||
goal,
|
||||
completed,
|
||||
uuid,
|
||||
time_of_reveal: _,
|
||||
} = &props.achievement;
|
||||
|
||||
let uuid = *uuid;
|
||||
|
130
crates/frontend/src/components/achievement_reveal_time.rs
Normal file
130
crates/frontend/src/components/achievement_reveal_time.rs
Normal file
@ -0,0 +1,130 @@
|
||||
use crate::services::confirm::ConfirmService;
|
||||
use crate::services::rest::RestService;
|
||||
use common::Achievement;
|
||||
use common::DeleteAchievement;
|
||||
use common::ToggleAchievement;
|
||||
use common::UpdateAchievementTimeOfReveal;
|
||||
use std::ops::Deref;
|
||||
use wasm_bindgen::JsCast;
|
||||
use wasm_bindgen_futures::spawn_local;
|
||||
use yew::classes;
|
||||
use yew::function_component;
|
||||
use yew::html;
|
||||
use yew::use_state;
|
||||
use yew::Callback;
|
||||
use yew::Html;
|
||||
use yew::Properties;
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props {
|
||||
pub achievement: Achievement,
|
||||
pub number: usize,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
pub fn AchievementRevealTime(props: &Props) -> Html {
|
||||
let achievement = &props.achievement;
|
||||
let uuid = achievement.uuid;
|
||||
|
||||
let time_of_reveal: Option<String> = achievement
|
||||
.time_of_reveal
|
||||
.map(|naive_time| naive_time.format("%H:%M").to_string());
|
||||
|
||||
let timed_reveal_enabled = use_state(|| time_of_reveal.is_some());
|
||||
let input_time = use_state(|| time_of_reveal.clone().unwrap_or("".to_string()));
|
||||
let awaiting_response = use_state(|| false);
|
||||
|
||||
let onsubmit = {
|
||||
let awaiting_response = awaiting_response.clone();
|
||||
let timed_reveal_enabled = timed_reveal_enabled.clone();
|
||||
let input_time = input_time.clone();
|
||||
Callback::from(move |e: web_sys::SubmitEvent| {
|
||||
e.prevent_default();
|
||||
|
||||
let new_time_of_reveal = if *timed_reveal_enabled {
|
||||
if let Ok(naive_time) = chrono::NaiveTime::parse_from_str(&input_time, "%H:%M") {
|
||||
Some(naive_time)
|
||||
} else {
|
||||
// TODO: show UI error
|
||||
log::debug!("Could not parse time: {}", *input_time);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let payload = UpdateAchievementTimeOfReveal {
|
||||
time_of_reveal: new_time_of_reveal,
|
||||
uuid,
|
||||
};
|
||||
awaiting_response.set(true);
|
||||
let awaiting_response = awaiting_response.clone();
|
||||
spawn_local(async move {
|
||||
let res = RestService::update_time_of_reveal(payload).await;
|
||||
awaiting_response.set(false);
|
||||
});
|
||||
})
|
||||
};
|
||||
|
||||
let oninput_time = {
|
||||
let input_time = input_time.clone();
|
||||
Callback::from(move |e: web_sys::InputEvent| {
|
||||
let Some(input) = e
|
||||
.target()
|
||||
.and_then(|t| t.dyn_into::<web_sys::HtmlInputElement>().ok()) else { unreachable!() };
|
||||
log::debug!("{:?}", input.value());
|
||||
input_time.set(input.value());
|
||||
})
|
||||
};
|
||||
|
||||
let oninput_timed_reveal_checkbox = {
|
||||
let timed_reveal_enabled = timed_reveal_enabled.clone();
|
||||
Callback::from(move |e: web_sys::InputEvent| {
|
||||
let Some(input) = e
|
||||
.target()
|
||||
.and_then(|t| t.dyn_into::<web_sys::HtmlInputElement>().ok()) else { unreachable!() };
|
||||
timed_reveal_enabled.set(input.checked());
|
||||
})
|
||||
};
|
||||
|
||||
let new_value: Option<&str> = timed_reveal_enabled.then_some(&**input_time);
|
||||
let show_submit_button: bool = time_of_reveal.as_deref() != new_value;
|
||||
|
||||
html! {
|
||||
<form {onsubmit}>
|
||||
|
||||
<div class="row flex">
|
||||
// Achievement number
|
||||
<div class="flex-intrinsic-size">
|
||||
<p>{format!("{}.", props.number)}</p>
|
||||
</div>
|
||||
|
||||
// Achievement text
|
||||
<div class="flex-grow">
|
||||
<p>{&achievement.goal}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
// Enable timed reveal checkbox
|
||||
<label class="row">
|
||||
<input oninput={oninput_timed_reveal_checkbox} checked={*timed_reveal_enabled} type="checkbox" />
|
||||
<span class="label-body">{"Timed reveal"}</span>
|
||||
</label>
|
||||
|
||||
{ if *timed_reveal_enabled { html! {
|
||||
// Time input
|
||||
<div>
|
||||
<label for="revealTimeInput">{"Reveal time"}</label>
|
||||
<input oninput={oninput_time} value={(*input_time).clone()} type="time" id="revealTimeInput" />
|
||||
</div>
|
||||
}} else { html! {}}}
|
||||
|
||||
// Submit button
|
||||
{ if show_submit_button { html! {
|
||||
<input class="button-primary" type="submit" value="Submit" disabled={ *awaiting_response } />
|
||||
}} else { html! {}}}
|
||||
|
||||
<hr />
|
||||
</form>
|
||||
}
|
||||
}
|
32
crates/frontend/src/components/achievement_reveal_times.rs
Normal file
32
crates/frontend/src/components/achievement_reveal_times.rs
Normal file
@ -0,0 +1,32 @@
|
||||
use crate::components::achievement_reveal_time::AchievementRevealTime;
|
||||
use yew::functional::*;
|
||||
use yew::prelude::*;
|
||||
use yew_router::prelude::*;
|
||||
|
||||
#[function_component]
|
||||
pub fn AchievementRevealTimes() -> Html {
|
||||
let nav = use_navigator().expect("cannot get navigator");
|
||||
let app_state = use_context::<crate::AppState>().expect("no app state ctx found");
|
||||
|
||||
let achievements = app_state
|
||||
.state
|
||||
.achievements
|
||||
.iter()
|
||||
.cloned()
|
||||
.enumerate()
|
||||
.map(|(idx, a)| (idx + 1, a))
|
||||
.map(|(n, a)| {
|
||||
html! {
|
||||
<AchievementRevealTime number={n} achievement={a} />
|
||||
}
|
||||
})
|
||||
.collect::<Html>();
|
||||
|
||||
html! {
|
||||
<>
|
||||
<h1>{"Achievement Timed Reveals"}</h1>
|
||||
<hr />
|
||||
{achievements}
|
||||
</>
|
||||
}
|
||||
}
|
@ -51,6 +51,7 @@ impl Component for CreateAchievementComponent {
|
||||
log::info!("Creating achievement");
|
||||
let payload = CreateAchievement {
|
||||
goal: self.input_value.clone(),
|
||||
time_of_reveal: None,
|
||||
};
|
||||
let link = ctx.link().clone();
|
||||
spawn_local(async move {
|
||||
|
@ -1,4 +1,6 @@
|
||||
pub mod achievement;
|
||||
pub mod achievement_reveal_time;
|
||||
pub mod achievement_reveal_times;
|
||||
pub mod admin;
|
||||
pub mod create_achievement;
|
||||
pub mod create_milestone;
|
||||
|
@ -2,6 +2,7 @@ use crate::components::error::error_component::ErrorComponent;
|
||||
use crate::components::error::error_provider::ErrorProvider;
|
||||
use crate::event_bus::EventBus;
|
||||
use crate::services::websocket::WebsocketService;
|
||||
use components::achievement_reveal_times::AchievementRevealTimes;
|
||||
use components::admin::Admin;
|
||||
use components::create_achievement::CreateAchievementComponent;
|
||||
use components::create_milestone::CreateMilestoneComponent;
|
||||
@ -27,6 +28,8 @@ enum Route {
|
||||
CreateAchievement,
|
||||
#[at("/create-milestone")]
|
||||
CreateMilestone,
|
||||
#[at("/reveal-times")]
|
||||
RevealTimes,
|
||||
#[not_found]
|
||||
#[at("/404")]
|
||||
NotFound,
|
||||
@ -39,6 +42,7 @@ fn switch(selected_route: Route) -> Html {
|
||||
Route::CreateAchievement => html! {<CreateAchievementComponent/>},
|
||||
Route::CreateMilestone => html! {<CreateMilestoneComponent/>},
|
||||
Route::NotFound => html! {<h1>{"404 not found"}</h1>},
|
||||
Route::RevealTimes => html! {<AchievementRevealTimes/>},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ use common::DeleteAchievement;
|
||||
use common::DeleteMilestone;
|
||||
use common::RestResponse;
|
||||
use common::ToggleAchievement;
|
||||
use common::UpdateAchievementTimeOfReveal;
|
||||
use reqwasm::http::Request;
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::Serialize;
|
||||
@ -67,4 +68,10 @@ impl RestService {
|
||||
pub async fn delete_milestone(payload: DeleteMilestone) -> Result<(), RestServiceError> {
|
||||
Self::post_json(payload, "/api/v1/delete-milestone").await
|
||||
}
|
||||
|
||||
pub async fn update_time_of_reveal(
|
||||
payload: UpdateAchievementTimeOfReveal,
|
||||
) -> Result<(), RestServiceError> {
|
||||
Self::post_json(payload, "/api/v1/update-time-of-reveal").await
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user