lan-party-backend/web/src/pages/events.rs

204 lines
6.4 KiB
Rust

use lan_party_core::{
components::Block,
edit::IntoEdit,
event::{Event, EventSpec, EventUpdate},
view::IntoView,
};
use log::debug;
use reqwasm::http::Method;
use sycamore::{futures::spawn_local_scoped, prelude::*};
use crate::{
components::{messages::Messenger, Button},
util::api_request,
};
#[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 events: &'a Signal<Vec<Event>> = create_signal(cx, Vec::<Event>::new());
let update_events = move || async move {
events.set(
api_request::<_, Vec<Event>>(Method::GET, "/event", Option::<()>::None)
.await
.map(|inner| inner.unwrap())
.unwrap(),
);
};
spawn_local_scoped(cx, update_events());
let onadd = move |_| {
spawn_local_scoped(cx, async move {
let new_event = api_request::<EventSpec, Event>(
Method::POST,
"/event",
Some((*event_spec).get().as_ref().clone()),
)
.await;
if let Ok(Some(new_event)) = new_event {
messenger.info(
"Added new event",
format!(
"Successfully created a new event with name \"{}\"",
new_event.name
),
);
events.modify().push(new_event);
} else {
messenger.info("Error when adding an event", "Unable to create a new event");
}
});
};
let onupdate = move |_| {
spawn_local_scoped(cx, async move {
let res = api_request::<EventUpdate, ()>(
Method::POST,
&format!("/event/{}", event_update_name),
Some((*event_update).get().as_ref().clone()),
)
.await;
if let Ok(_) = res {
update_events().await;
messenger.info(
"Updated event",
format!(
"Successfully updated event with name \"{}\"",
event_update_name
),
);
} else {
messenger.info(
"Error when updating event",
format!("Unable to update event with name \"{}\"", event_update_name),
);
}
});
};
let onviewoutcome = move |event_name: String| {
move |_| {
let event_name = event_name.clone();
spawn_local_scoped(cx, async move {});
}
};
let onstop = move |event_name: String| {
move |_| {
let event_name = event_name.clone();
spawn_local_scoped(cx, async move {});
}
};
let ondelete = move |event_name: String| {
move |_| {
let event_name = event_name.clone();
spawn_local_scoped(cx, async move {
let res =
api_request::<(), ()>(Method::DELETE, &format!("/event/{}", event_name), None)
.await;
if let Ok(_) = res {
update_events().await;
messenger.info(
"Removed event",
format!("Successfully removed event with name \"{}\"", event_name),
);
} else {
messenger.info(
"Error when removing event",
format!("Unable to remove event with name \"{}\"", event_name),
);
}
});
}
};
view! { cx,
div(class="events-cols") {
div {
Block(title="Events".into()) {
Indexed(
iterable=&events,
view=move |cx, event| {
let event = create_ref(cx, event);
view! { cx,
//(event.view(cx))
EventView(event=event, ondelete=ondelete(event.name.clone()), onviewoutcome=onviewoutcome(event.name.clone()), onstop=onstop(event.name.clone()))
br()
}
},
)
}
}
div(class="events-right") {
Block(title="Create new event".into()) {
(event_spec.edit(cx))
Button(icon="mdi-check".into(), onclick=onadd)
}
br()
Block(title="Update an event".into()) {
label { "Event name" }
select(bind:value=event_update_name) {
Indexed(
iterable=&events,
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=onupdate)
}
}
}
}
}
#[derive(Prop)]
struct EventViewProps<'a, F1, F2, F3>
where
F1: FnMut(web_sys::Event),
F2: FnMut(web_sys::Event),
F3: FnMut(web_sys::Event),
{
pub event: &'a Event,
pub ondelete: F1,
pub onviewoutcome: F2,
pub onstop: F3,
}
#[component]
fn EventView<'a, G, F1, F2, F3>(cx: Scope<'a>, props: EventViewProps<'a, F1, F2, F3>) -> View<G>
where
F1: FnMut(web_sys::Event) + 'a,
F2: FnMut(web_sys::Event) + 'a,
F3: FnMut(web_sys::Event) + 'a,
G: Html,
{
view! { cx,
Block(title=props.event.name.clone()) {
(props.event.description)
br()
Button(text="Delete".into(), icon="mdi-delete".into(), onclick=props.ondelete)
Button(text="View outcome".into(), onclick=props.onviewoutcome)
Button(text="Finish".into(), onclick=props.onstop)
br()
(props.event.event_type.view(cx))
}
}
}