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 { let messenger = use_context::(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::(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::::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::::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.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() )) ) } } } } }