187 lines
7.2 KiB
Rust
187 lines
7.2 KiB
Rust
use anyhow::anyhow;
|
|
use lan_party_core::{
|
|
components::Block,
|
|
edit::IntoEdit,
|
|
event::{Event, EventOutcome, EventSpec, EventUpdate},
|
|
view::IntoView,
|
|
};
|
|
use log::debug;
|
|
use reqwasm::http::Method;
|
|
use sycamore::{futures::spawn_local_scoped, prelude::*};
|
|
|
|
use crate::{
|
|
components::{messages::Messenger, Button, Modal, Table},
|
|
state::Events,
|
|
util::api_request,
|
|
};
|
|
|
|
pub enum Msg {
|
|
Reload,
|
|
Add(EventSpec),
|
|
Update(String, EventUpdate),
|
|
Delete(String),
|
|
Stop(String),
|
|
ViewOutcome(String),
|
|
}
|
|
|
|
#[component]
|
|
pub fn EventsPage<'a, G: Html>(cx: Scope<'a>) -> View<G> {
|
|
let messenger = use_context::<Messenger>(cx);
|
|
|
|
let event_spec = create_signal(cx, EventSpec::default());
|
|
let event_update = create_signal(cx, EventUpdate::default());
|
|
let event_update_name = create_signal(cx, String::new());
|
|
|
|
let current_event = create_signal(cx, String::new());
|
|
let show_outcome = create_signal(cx, false);
|
|
let event_outcome = create_signal(cx, EventOutcome::default());
|
|
|
|
let events = use_context::<Events>(cx);
|
|
|
|
let dispatch = move |msg: Msg| {
|
|
spawn_local_scoped(cx, async move {
|
|
match msg {
|
|
Msg::Add(event_spec) => {
|
|
let name = event_spec.name.clone();
|
|
messenger.add_result(
|
|
events.add(event_spec).await,
|
|
Some(format!("Created a new event with name \"{}\"", name)),
|
|
Some("Error when adding an event"),
|
|
);
|
|
}
|
|
Msg::Reload => messenger.add_result(
|
|
events.load().await,
|
|
Option::<String>::None,
|
|
Some("Failed to load events"),
|
|
),
|
|
Msg::Update(event_update_name, event_update) => {
|
|
messenger.add_result(
|
|
events.update_event(&event_update_name, event_update).await,
|
|
Some(format!("Updated event with name \"{}\"", event_update_name)),
|
|
Some("Error when updating event"),
|
|
);
|
|
}
|
|
Msg::Delete(event_name) => {
|
|
messenger.add_result(
|
|
events.delete(&event_name).await,
|
|
Some(format!("Deleted event with name \"{}\"", event_name)),
|
|
Some("Error when deleting event"),
|
|
);
|
|
}
|
|
Msg::ViewOutcome(event_name) => {
|
|
show_outcome.set(true);
|
|
current_event.set(event_name.clone());
|
|
let res = api_request::<(), EventOutcome>(
|
|
Method::GET,
|
|
&format!("/event/{}/outcome", event_name),
|
|
None,
|
|
)
|
|
.await
|
|
.and_then(|inner| inner.ok_or(anyhow!("missing body")));
|
|
|
|
if let Ok(outcome) = res {
|
|
debug!("{:#?}", outcome);
|
|
event_outcome.set(outcome);
|
|
} else {
|
|
debug!("oh no");
|
|
messenger.add_result(
|
|
res,
|
|
Option::<String>::None,
|
|
Some("Failed to load outcome"),
|
|
)
|
|
}
|
|
}
|
|
_ => {}
|
|
}
|
|
});
|
|
};
|
|
|
|
dispatch(Msg::Reload);
|
|
|
|
let outcome_points = create_memo(cx, || {
|
|
let cloned = event_outcome.get().as_ref().clone();
|
|
let mut vec = cloned.points.into_iter().collect::<Vec<_>>();
|
|
vec.sort_by_key(|(_, s)| -*s);
|
|
vec
|
|
});
|
|
|
|
view! { cx,
|
|
Modal(open=show_outcome, title="Event outcome".into()) {
|
|
Table(headers=vec!["Username".into(), "Score".into()]) {
|
|
Indexed(
|
|
iterable=&outcome_points,
|
|
view=move |cx, (k, v)| {
|
|
view! { cx,
|
|
tr {
|
|
td { (k.clone()) }
|
|
td { (v.clone()) }
|
|
}
|
|
}
|
|
}
|
|
)
|
|
}
|
|
Button(text="Reload".into(), icon="mdi-refresh".into(), onclick=move |_| dispatch(Msg::ViewOutcome(current_event.get().as_ref().clone())))
|
|
}
|
|
div(class="events-cols") {
|
|
div {
|
|
Block(title="Events".into()) {
|
|
Button(text="Reload".into(), icon="mdi-refresh".into(), onclick=move |_| dispatch(Msg::Reload))
|
|
Indexed(
|
|
iterable=&events.get(),
|
|
view=move |cx, event| {
|
|
let event = create_ref(cx, event);
|
|
view! { cx,
|
|
Block(title=event.name.clone()) {
|
|
(event.description)
|
|
br()
|
|
span(class="event-action") {
|
|
Button(text="Delete".into(), icon="mdi-delete".into(), onclick=move |_| dispatch(Msg::Delete(event.name.clone())))
|
|
}
|
|
span(class="event-action") {
|
|
Button(text="View outcome".into(), onclick=move |_| dispatch(Msg::ViewOutcome(event.name.clone())))
|
|
}
|
|
span(class="event-action") {
|
|
Button(text="Finish".into(), onclick=move |_| dispatch(Msg::Stop(event.name.clone())))
|
|
}
|
|
br()
|
|
(event.event_type.view(cx))
|
|
}
|
|
br()
|
|
}
|
|
},
|
|
)
|
|
}
|
|
}
|
|
div(class="events-right") {
|
|
Block(title="Create new event".into()) {
|
|
(event_spec.edit(cx))
|
|
Button(icon="mdi-check".into(), onclick=move |_| dispatch(Msg::Add(event_spec.get().as_ref().clone())))
|
|
}
|
|
br()
|
|
Block(title="Update an event".into()) {
|
|
label { "Event name" }
|
|
select(bind:value=event_update_name) {
|
|
Indexed(
|
|
iterable=&events.get(),
|
|
view=move |cx, event| {
|
|
let event = create_ref(cx, event);
|
|
view! { cx,
|
|
option(value=event.name) { (event.name) }
|
|
}
|
|
},
|
|
)
|
|
}
|
|
(event_update.edit(cx))
|
|
Button(
|
|
icon="mdi-check".into(),
|
|
onclick=move |_| dispatch(Msg::Update(
|
|
event_update_name.get().as_ref().clone(),
|
|
event_update.get().as_ref().clone()
|
|
))
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|